简体   繁体   中英

How to validate graphql schema with fragmented documents

i was thinking it would be cool to support schema validation at the unit test level so we could be aware of breaking changes to queries when we upgrade our api

i'd like to set up the test so that it supports auto-discovery of any new *.graphql files but in doing so, the jest process thinks the current working directory is in __tests__ so when i evaluate the graphql document manually with the loader, relative fragments in queries like this fail:

#import "./fragments/FullUserData.graphql"

query User(
  $zid: String!
) {
  user {
    userData: get(
      zid: $zid
    ) {
      ...FullUserData
    }
  }
}

failure message:

Error: Cannot find module './fragments/FullUserData.graphql' from 'schemaValidation-test.js'"

if i move fragments folder into the __tests__ dir, the test gets happy. any ideas on what I can do to trick the evaluation to process the fragment as if I was relative to the fragment directory?

__tests__/
  - schemaValidation-test.js
queries/
  - someQuery.graphql
  - fragments/someFragment.graphql

i tried process.chdir() to the queries dir from within jest but no dice

here is the validator:

// __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([])
    })
  }
})

How can I tell the loader I am in a different directory relative to the fragment?

I figured this out. The key was to use require instead of 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([])
    })
  })
})

here is 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"
  ]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM