Проблема: я хотел бы протестировать запрос GraphQL, который находится в файле .graphql, например:
#import '../../fragments/Widget.graphql'
query WidgetFragment($id: ID) {
readWidgetFragment(id: $id) {
...Widget
}
}
Чтобы создать схему GraphQL с имитируемыми преобразователями и данными, я использую makeExecutableSchema и addMockFunctionsToSchema из графические инструменты.
Насколько я понимаю, чтобы запустить запрос изнутри шутливого теста, мне нужно использовать функцию graphql() из graphql-js.
Эта функция требует запроса как нить, поэтому я попробовал два разных способа, но ни один из них не сработал:
.graphql как обычный текстовый файл, давая мне необработанную строку (используя jest-raw-loader в моей конфигурации jest).
Это дает мне: Failed: Errors in query: Unknown fragment "Widget"., когда я запускаю запрос..graphql в объект query с помощью jest-transform-graphql. Я считаю, что это должен быть правильный подход, потому что он должен правильно разрешает любые импортированные фрагменты. Однако для выполнения запроса мне нужно передать query.loc.source.body в graphql, что приводит к тому же сообщению об ошибке, что и вариант 1.

Вы можете использовать это:
import { print } from 'graphql/language/printer'
import query from './query.gql'
...
print(query)
Используйте первоначальный подход с анализом его как необработанного текста, за исключением:
#import и передав их себе и добавив результат в строковую переменнуюgraphql().Да, это довольно соленый огурец. Даже при правильной работе импорта (> = v2.1.0 для jest-transform-graphql они добавляются к объекту query.definitions, что полностью игнорируется при вызове graphql с document.loc.source.body в качестве аргумента запроса.
На стороне сервера graphql (function graphqlImpl) будет реконструировать объект document с помощью parse(source), но у него будет нулевое знание определений импортированных фрагментов ...
Насколько я могу судить, лучше всего поставить метку фрагментов в источник запроса перед его отправкой на сервер. Вам нужно будет явно найти все строки, начинающиеся с #import, и заменить их фактическим текстовым содержимым импортируемого файла graphql.
Ниже представлена функция, которую я использую. (Не проверено на рекурсивные фрагменты)
// Async wrapper around dynamic `import` function
import { importQuery } from "./queries";
const importAndReplace = async (fileToImport, sourceDocument, line) => {
const doc = await importQuery(fileToImport);
const targetDocument = (await sourceDocument).replace(line, doc.loc.source.body);
return targetDocument;
};
// Inspired by `graphql-tag/loader`
// Uses promises because of async function `importQuery` used
export default async graphqlOperation => {
const { body } = graphqlOperation.loc.source;
const lines = body.split(/\r\n|\r|\n/);
const bodyWithInlineImports = await lines.reduce(
async (accumulator, line) => {
await accumulator;
const lineSplit = line.slice(1).split(" ");
return line[0] === "#" && lineSplit[0] === "import"
? importAndReplace(lineSplit[1].replace(/"/g, ""), accumulator, line)
: Promise.resolve(accumulator);
},
Promise.resolve(body)
);
return bodyWithInlineImports;
};