Reputation: 35884
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?
Upvotes: 0
Views: 1523
Reputation: 35884
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"
]
}
Upvotes: 1