无法自定义graphql枚举的值

时间:2019-10-15 12:25:27

标签: graphql graphql-js apollo-server

我看了这个问题:How to use or resolve enum types with graphql-tools?

而且,此文档:https://www.apollographql.com/docs/graphql-tools/scalars/#internal-values

现在,我要自定义graphql enum的值。

typeDefs.ts

import { gql } from 'apollo-server';

export const typeDefs = gql`
  enum Device {
    UNKNOWN
    DESKTOP
    HIGH_END_MOBILE
    TABLET
    CONNECTED_TV
  }

  type CampaignPerformanceReport {
    campaignNme: String!
    campaignId: ID!
    device: Device
  }

  type Query {
    campaignPerformanceReports: [CampaignPerformanceReport]!
  }
`;

resolvers.ts

import { IResolvers } from 'graphql-tools';
import { IAppContext } from './appContext';

export const resolvers: IResolvers = {
  Device: {
    UNKNOWN: 'Other',
    DESKTOP: 'Computers',
    HIGH_END_MOBILE: 'Mobile devices with full browsers',
    TABLET: 'Tablets with full browsers',
    CONNECTED_TV: 'Devices streaming video content to TV screens',
  },
  Query: {
    async campaignPerformanceReports(_, __, { db }: IAppContext) {
      return db.campaignPerformanceReports;
    },
  },
};

如您所见,我在解析器中自定义了Device枚举的值。

db.ts:带有数据的虚假数据库

enum Device {
  UNKNOWN = 'Other',
  DESKTOP = 'Computers',
  HIGH_END_MOBILE = 'Mobile devices with full browsers',
  TABLET = 'Tablets with full browsers',
  CONNECTED_TV = 'Devices streaming video content to TV screens',
}

export const db = {
  campaignPerformanceReports: [
    {
      campaignId: 1,
      campaignNme: 'test',
      device: Device.DESKTOP,
    },
  ],
};

我还为此进行了集成测试:

 test.only('should query campaign performance reports correctly with executable graphql schema', async () => {
      const schema = makeExecutableSchema({ typeDefs, resolvers });
      console.log(printSchema(schema));
      const server: ApolloServerBase = new ApolloServer({ schema, context: { db } });
      const { query }: ApolloServerTestClient = createTestClient(server);
      const res: GraphQLResponse = await query({ query: Q.campaignPerformanceReports });
      expect(res).toMatchInlineSnapshot(`
        Object {
          "data": Object {
            "campaignPerformanceReports": Array [
              Object {
                "campaignId": "1",
                "campaignNme": "test",
                "device": "DESKTOP",
              },
            ],
          },
          "errors": undefined,
          "extensions": undefined,
          "http": Object {
            "headers": Headers {
              Symbol(map): Object {},
            },
          },
        }
      `);
    });

如您所见,快照测试的结果。 device字段的值仍为“ DESKTOP” ,我希望该值应为“计算机”

依赖版本:

"apollo-server": "^2.9.3",
"apollo-server-express": "^2.9.3",
"graphql": "^14.5.4",

最小存储库:https://github.com/mrdulin/apollo-graphql-tutorial/tree/master/src/custom-scalar-and-enum

1 个答案:

答案 0 :(得分:2)

您为GraphQL枚举指定的内部值就是-内部。 documentation中对此进行了说明:

  

这些根本不会更改公共API ,但是它们确实允许您在解析程序中使用该值而不是架构值

如果将枚举值DESKTOP映射到内部值Computers,则只会影响解析程序的行为。具体来说:

  • 如果字段采用类型为Device的参数,并且该参数传递的值为DESKTOP,则实际传递给解析器函数的值为Computers
  • 如果字段本身具有设备类型,并且我们想在解析器内部返回DESKTOP,则需要返回Computers

例如,一个如下所示的模式:

type Query {
  someQuery(device: Device!): Device!
}

如果您指定内部值,我们的解析器将像这样工作:

function (parent, args) {
  console.log(args.device) // "DESKTOP"
  return 'DESKTOP'
}

如果执行指定内部值,则解析器如下所示:

function (parent, args) {
  console.log(args.device) // "Computers"
  return 'Computers'
}

解析器是唯一受每个枚举值的内部值影响的对象。 不更改的内容:

  • 如何在响应中序列化枚举值。枚举值总是被序列化为枚举值名称的字符串。
  • 枚举值如何以文字形式写入文档中。例如,如果查询上述相同字段,我们将始终写为:{ someQuery(device: DESKTOP) }
  • 枚举值如何作为变量提供。类型为Device的变量将始终写为"DESKTOP"

注意:尽管该问题专门针对Apollo Server,但以上内容也适用于普通GraphQL.js。例如,这个枚举

const DeviceEnum = new GraphQLEnumType({
  name: 'Device',
  values: {
    UNKNOWN: { value: 'Other' },
    DESKTOP: { value: 'Computers' },
    HIGH_END_MOBILE: { value: 'Mobile devices with full browsers' },
    TABLET: { value: 'Tablets with full browsers' },
    CONNECTED_TV: { value: 'Devices streaming video content to TV screens' },
  }
})

仍然会如上所述。