Не может пользовательское значение перечисления graphql - PullRequest
0 голосов
/ 15 октября 2019

Я посмотрел этот вопрос: Как использовать или разрешать перечислимые типы с помощью GraphQl-инструментов?

И, этот документ: 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 Ответ

1 голос
/ 15 октября 2019

Внутренние значения, которые вы указываете для перечисления GraphQL, только внутренние. Это указано в документации :

Они вообще не изменяют общедоступный API , но позволяют использовать это значение вместозначение схемы в ваших резольверах

Если вы сопоставите значение enum 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,вышеизложенное относится и к vanilla 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' },
  }
})

будет по-прежнему вести себя так, как описано выше.

...