如何使用碎片化文档验证 graphql 模式
Posted
技术标签:
【中文标题】如何使用碎片化文档验证 graphql 模式【英文标题】:How to validate graphql schema with fragmented documents 【发布时间】:2020-05-09 05:59:43 【问题描述】:我认为在单元测试级别支持架构验证会很酷,这样我们就可以在升级 api 时意识到对查询的重大更改
我想设置测试,以便它支持自动发现任何新的 *.graphql
文件,但这样做,开玩笑的过程认为当前工作目录在 __tests__
所以当我评估 graphql使用加载器手动记录文档,这样的查询中的相关片段失败:
#import "./fragments/FullUserData.graphql"
query User(
$zid: String!
)
user
userData: get(
zid: $zid
)
...FullUserData
失败信息:
Error: Cannot find module './fragments/FullUserData.graphql' from 'schemaValidation-test.js'"
如果我将 Fragments 文件夹移动到 __tests__
目录中,则测试会很顺利。
关于我可以做些什么来欺骗评估以处理片段的任何想法,就好像我是相对于片段目录一样?
__tests__/
- schemaValidation-test.js
queries/
- someQuery.graphql
- fragments/someFragment.graphql
我在 jest 中尝试了 process.chdir()
到查询目录,但没有骰子
这里是验证器:
// __tests__/schemaValidation-test.js
import glob from 'glob'
import validate from 'graphql/validation'
import loader from 'graphql-tag/loader'
import schema from 'api/lib/app/graphql/schema'
import path from 'path'
import fs from 'fs'
const gqlDir = path.join(__dirname, '..')
const queryDir = path.join(gqlDir, 'queries', 'shared')
const pattern = `$queryDir/!(fragments)*.graphql`
const getGraphqlFiles = () => glob.sync(pattern)
describe('api schema', () =>
const files = getGraphqlFiles()
for(var file of files)
const buffer = fs.readFileSync(file)
let document = (buffer || "").toString()
try
document = eval(loader.call(
cacheable: () => () ,
document
))
catch (e)
fail(`could not parse $file, $e`)
it(`$file passes validation`, () =>
const errors = validate(
schema,
document,
)
expect(errors).toEqual([])
)
)
如何告诉加载器我在相对于片段不同的目录中?
【问题讨论】:
FWIW,graphql-tag
明确声明它不应该用于测试。您应该改用jest-transform-graphql
,如here 所述。
值得一提的是上面的代码只会验证你的模式。如果您真的对识别重大更改感兴趣,您应该对架构进行快照,然后使用核心库中的 findBreakingChanges 实用程序。
是的,这就是我的直接目标。我会看看你推荐的图书馆。丹尼尔,我也在用变压器。只是不适用于这个例子,我想支持自动发现添加到 repo 的 *.graphql 文件
这个库不能满足我的需求,它看起来好像比较了 2 个模式。我只能访问 API 公开的单一模式。
另外,在这种情况下,我正在积极使用 graphql-tag 来支持片段。除非您知道另一种加载 graphql 扩展和相关片段的方法
【参考方案1】:
我想通了。关键是使用require
而不是fs.readFileSync
import glob from 'glob'
import validate from 'graphql/validation'
import schema from 'api/lib/app/graphql/schema'
import path from 'path'
const gqlDir = path.join(__dirname, '..')
const queryDir = path.join(gqlDir, 'queries', 'shared')
const pattern = `$queryDir/!(fragments)*.graphql`
const getGraphqlFiles = () => glob.sync(pattern)
describe('rent-js-api schema', () =>
const files = getGraphqlFiles()
files.forEach(file =>
/* eslint-disable import/no-dynamic-require */
const document = require(file)
it(`$file passes validation`, () =>
const errors = validate(
schema,
document,
)
expect(errors).toEqual([])
)
)
)
这里是 jest.config.json
"setupFiles": [
"<rootDir>/test/jest/shim.js",
"<rootDir>/test/jest/setup.js"
],
"moduleDirectories": ["node_modules", "src", "test/jest", "test"],
"collectCoverage": false,
"testMatch": ["**/*-test.js"],
"collectCoverageFrom": [
"**/src/**/*.js,ts,jsx,tsx",
"!**/src/**/*-test.js",
"!**/index.ts,js",
"!**/src/**/const.ts,js",
"!**/ui/theme/**",
"!**/src/**/*.d.ts,tsx",
"!**/node_modules/**",
"!**/src/ui/*/themes/**"
],
"coverageDirectory": "./coverage",
"moduleNameMapper":
"\\.(css|scss)$": "<rootDir>/test/jest/noop-styles",
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/test/jest/noop-binary",
"^.+\\.html$": "<rootDir>/test/jest/htmlLoader"
,
"moduleFileExtensions": [
"graphql",
"js",
"json",
"ts",
"tsx"
],
"transform":
"^.+\\.jsx?$": "babel-jest",
"^.+\\.tsx?$": "babel-jest",
"^.+\\.graphql$": "jest-transform-graphql"
,
"testPathIgnorePatterns": [
"<rootDir>/node_modules/",
"^.*__tests__/__helpers__.*"
],
"snapshotSerializers": [
"enzyme-to-json/serializer",
"jest-serializer-html"
]
【讨论】:
以上是关于如何使用碎片化文档验证 graphql 模式的主要内容,如果未能解决你的问题,请参考以下文章
GraphQL 的 GitHub API 身份验证:如果需要身份验证,我如何公开发布我的应用程序?