5

问题:我想测试一个存在于.graphql如下文件中的 GraphQL 查询:

#import '../../fragments/Widget.graphql'

query WidgetFragment($id: ID) {
    readWidgetFragment(id: $id) {
        ...Widget
    }
}

要使用模拟解析器和数据创建 GraphQL 模式,我使用 makeExecutableSchemaand addMockFunctionsToSchemafrom graphql-tools

要从一个笑话测试中运行查询,我的理解是我需要使用graphql()来自graphql-js的函数。

这个函数需要将查询作为字符串,所以我尝试了两种不同的方法,但它们都不起作用:

  • 将文件解析.graphql为普通文本文件,给我原始字符串(在我的 jest 配置中使用jest-raw-loader)。这给了我:Failed: Errors in query: Unknown fragment "Widget".当我运行查询时。
  • 使用jest-transform-graphql.graphql文件解析为对象。我相信这应该是正确的方法,因为它应该正确解析任何导入的片段。但是,要执行查询,我需要传递给,这会导致与选项 1 相同的错误消息。queryquery.loc.source.bodygraphql
4

3 回答 3

3

你可以使用这个:

import { print } from 'graphql/language/printer'

import query from './query.gql'

...

print(query)
于 2018-12-19T17:31:55.113 回答
0

是的,这真是个泡菜。即使导入正常工作(> = v2.1.0 for jest-transform-graphql,它们也会被添加到对象中,这在使用查询参数query.definitions调用时完全回避。graphqldocument.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;
};

于 2019-09-06T07:36:38.720 回答
0

使用初始方法将其解析为原始文本,除了:

  1. 使用带有路径参数的递归函数(假设您可以嵌套片段)
  2. 它使用正则表达式将所有导入预先提取到数组中(也许使用更好的模式:))
  3. 将文件的其余部分附加到字符串变量
  4. 然后循环导入,解析#imports 并将它们传递给自身并将结果附加到字符串变量
  5. 最后将结果返回给主函数,然后将其传递给graphql()
于 2019-09-05T07:42:14.350 回答