From 7d2fbd41f8f9720e8a9cdb53c675da5a90d681f1 Mon Sep 17 00:00:00 2001 From: PrettierCI Date: Wed, 7 Mar 2018 17:56:48 +0000 Subject: [PATCH] Sync with Prettier --- CONTRIBUTING.md | 7 +- README.md | 17 +- package.json | 25 +- resources/mocha-bootload.js | 10 +- resources/watch.js | 154 +- src/README.md | 3 +- src/__tests__/starWarsData.js | 70 +- src/__tests__/starWarsIntrospection-test.js | 182 +- src/__tests__/starWarsQuery-test.js | 154 +- src/__tests__/starWarsSchema.js | 99 +- src/__tests__/starWarsValidation-test.js | 33 +- src/error/GraphQLError.js | 79 +- src/error/README.md | 3 +- src/error/formatError.js | 7 +- src/error/index.js | 8 +- src/error/locatedError.js | 9 +- src/error/syntaxError.js | 32 +- src/execution/README.md | 7 +- src/execution/__tests__/abstract-test.js | 180 +- src/execution/__tests__/directives-test.js | 141 +- src/execution/__tests__/executor-test.js | 497 +++-- src/execution/__tests__/lists-test.js | 681 +++--- src/execution/__tests__/mutations-test.js | 65 +- src/execution/__tests__/nonnull-test.js | 484 +++-- src/execution/__tests__/resolve-test.js | 54 +- src/execution/__tests__/schema-test.js | 124 +- .../__tests__/union-interface-test.js | 176 +- src/execution/__tests__/variables-test.js | 248 ++- src/execution/execute.js | 371 ++-- src/execution/index.js | 2 +- src/execution/values.js | 49 +- src/graphql.js | 25 +- src/index.js | 57 +- src/jsutils/README.md | 3 +- src/jsutils/keyMap.js | 2 +- src/jsutils/keyValMap.js | 2 +- src/language/README.md | 3 +- src/language/__tests__/kitchen-sink.graphql | 12 +- src/language/__tests__/lexer-test.js | 432 ++-- src/language/__tests__/parser-test.js | 382 ++-- src/language/__tests__/printer-test.js | 75 +- .../__tests__/schema-kitchen-sink.graphql | 7 +- src/language/__tests__/schema-parser-test.js | 333 ++- src/language/__tests__/schema-printer-test.js | 44 +- src/language/__tests__/visitor-test.js | 1887 +++++++++-------- src/language/ast.js | 494 +++-- src/language/index.js | 14 +- src/language/kinds.js | 72 +- src/language/lexer.js | 298 ++- src/language/location.js | 8 +- src/language/parser.js | 233 +- src/language/printer.js | 104 +- src/language/source.js | 2 +- src/language/visitor.js | 98 +- src/type/README.md | 3 +- src/type/__tests__/definition-test.js | 237 +-- src/type/__tests__/enumType-test.js | 157 +- src/type/__tests__/introspection-test.js | 785 ++++--- src/type/__tests__/serialization-test.js | 166 +- src/type/__tests__/validation-test.js | 1525 +++++++------ src/type/definition.js | 418 ++-- src/type/directives.js | 65 +- src/type/index.js | 12 +- src/type/introspection.js | 259 +-- src/type/scalars.js | 51 +- src/type/schema.js | 100 +- src/utilities/README.md | 3 +- src/utilities/TypeInfo.js | 61 +- src/utilities/__tests__/astFromValue-test.js | 272 +-- .../__tests__/buildASTSchema-test.js | 161 +- .../__tests__/buildClientSchema-test.js | 451 ++-- src/utilities/__tests__/concatAST-test.js | 22 +- src/utilities/__tests__/extendSchema-test.js | 209 +- .../__tests__/getOperationAST-test.js | 44 +- src/utilities/__tests__/schemaPrinter-test.js | 309 ++- .../__tests__/typeComparators-test.js | 93 +- src/utilities/assertValidName.js | 3 +- src/utilities/astFromValue.js | 44 +- src/utilities/buildASTSchema.js | 103 +- src/utilities/buildClientSchema.js | 147 +- src/utilities/concatAST.js | 7 +- src/utilities/extendSchema.js | 134 +- src/utilities/getOperationAST.js | 5 +- src/utilities/index.js | 30 +- src/utilities/introspectionQuery.js | 159 +- src/utilities/isValidJSValue.js | 43 +- src/utilities/isValidLiteralValue.js | 43 +- src/utilities/schemaPrinter.js | 100 +- src/utilities/typeComparators.js | 46 +- src/utilities/typeFromAST.js | 19 +- src/utilities/valueFromAST.js | 37 +- src/validation/README.md | 7 +- .../__tests__/ArgumentsOfCorrectType-test.js | 790 ++++--- .../DefaultValuesOfCorrectType-test.js | 130 +- .../__tests__/FieldsOnCorrectType-test.js | 218 +- .../FragmentsOnCompositeTypes-test.js | 107 +- .../__tests__/KnownArgumentNames-test.js | 136 +- .../__tests__/KnownDirectives-test.js | 92 +- .../__tests__/KnownFragmentNames-test.js | 42 +- .../__tests__/KnownTypeNames-test.js | 55 +- .../__tests__/LoneAnonymousOperation-test.js | 88 +- .../__tests__/NoFragmentCycles-test.js | 308 ++- .../__tests__/NoUndefinedVariables-test.js | 215 +- .../__tests__/NoUnusedFragments-test.js | 72 +- .../__tests__/NoUnusedVariables-test.js | 144 +- .../OverlappingFieldsCanBeMerged-test.js | 740 ++++--- .../__tests__/PossibleFragmentSpreads-test.js | 226 +- .../ProvidedNonNullArguments-test.js | 203 +- src/validation/__tests__/ScalarLeafs-test.js | 100 +- .../__tests__/UniqueArgumentNames-test.js | 146 +- .../__tests__/UniqueFragmentNames-test.js | 84 +- .../__tests__/UniqueInputFieldNames-test.js | 76 +- .../__tests__/UniqueOperationNames-test.js | 105 +- .../__tests__/UniqueVariableNames-test.js | 44 +- .../__tests__/VariablesAreInputTypes-test.js | 52 +- .../VariablesInAllowedPosition-test.js | 263 ++- src/validation/__tests__/harness.js | 174 +- src/validation/__tests__/validation-test.js | 42 +- src/validation/index.js | 4 +- .../rules/ArgumentsOfCorrectType.js | 37 +- .../rules/DefaultValuesOfCorrectType.js | 53 +- src/validation/rules/FieldsOnCorrectType.js | 36 +- .../rules/FragmentsOnCompositeTypes.js | 43 +- src/validation/rules/KnownArgumentNames.js | 50 +- src/validation/rules/KnownDirectives.js | 59 +- src/validation/rules/KnownFragmentNames.js | 12 +- src/validation/rules/KnownTypeNames.js | 9 +- .../rules/LoneAnonymousOperation.js | 11 +- src/validation/rules/NoFragmentCycles.js | 24 +- src/validation/rules/NoUndefinedVariables.js | 27 +- src/validation/rules/NoUnusedFragments.js | 20 +- src/validation/rules/NoUnusedVariables.js | 20 +- .../rules/OverlappingFieldsCanBeMerged.js | 140 +- .../rules/PossibleFragmentSpreads.js | 59 +- .../rules/ProvidedNonNullArguments.js | 59 +- src/validation/rules/ScalarLeafs.js | 31 +- src/validation/rules/UniqueArgumentNames.js | 15 +- src/validation/rules/UniqueFragmentNames.js | 15 +- src/validation/rules/UniqueInputFieldNames.js | 15 +- src/validation/rules/UniqueOperationNames.js | 17 +- src/validation/rules/UniqueVariableNames.js | 17 +- .../rules/VariablesAreInputTypes.js | 23 +- .../rules/VariablesInAllowedPosition.js | 35 +- src/validation/specifiedRules.js | 54 +- src/validation/validate.js | 66 +- 145 files changed, 10764 insertions(+), 9727 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 74c72e3529..5a0fdfdbc9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,4 @@ -Contributing to graphql-js -========================== +# Contributing to graphql-js We want to make contributing to this project as easy and transparent as possible. Hopefully this document makes the process for contributing clear and @@ -80,12 +79,12 @@ This will watch the file system run any relevant lint, tests, and type checks au ## Release on NPM -*Only core contributors may release to NPM.* +_Only core contributors may release to NPM._ To release a new version on NPM, first ensure all tests pass with `npm test`, then use `npm version patch|minor|major` in order to increment the version in package.json and tag and commit a release. Then `git push && git push --tags` -this change so Travis CI can deploy to NPM. *Do not run `npm publish` directly.* +this change so Travis CI can deploy to NPM. _Do not run `npm publish` directly._ Once published, add [release notes](https://github.com/graphql/graphql-js/tags). Use [semver](http://semver.org/) to determine which version part to increment. diff --git a/README.md b/README.md index 1cd8377c3c..a9682a9a5c 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,7 @@ For discussion, join [#graphql on Discord](http://join.reactiflux.com/). ## Technical Preview Contents -This technical preview contains a [draft specification for GraphQL] -(https://github.com/facebook/graphql) and a reference implementation in +This technical preview contains a [draft specification for GraphQL](https://github.com/facebook/graphql) and a reference implementation in JavaScript that implements that draft, GraphQL.js. The reference implementation provides base libraries in JavaScript that would @@ -71,16 +70,16 @@ import { GraphQLSchema, GraphQLObjectType, GraphQLString -} from 'graphql'; +} from "graphql"; var schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'RootQueryType', + name: "RootQueryType", fields: { hello: { type: GraphQLString, resolve() { - return 'world'; + return "world"; } } } @@ -96,16 +95,14 @@ level [tests](src/__tests__) directory. Then, serve the result of a query against that type schema. ```js -var query = '{ hello }'; +var query = "{ hello }"; graphql(schema, query).then(result => { - // Prints // { // data: { hello: "world" } // } console.log(result); - }); ``` @@ -114,10 +111,9 @@ first ensure the query is syntactically and semantically valid before executing it, reporting errors otherwise. ```js -var query = '{ boyhowdy }'; +var query = "{ boyhowdy }"; graphql(schema, query).then(result => { - // Prints // { // errors: [ @@ -126,7 +122,6 @@ graphql(schema, query).then(result => { // ] // } console.log(result); - }); ``` diff --git a/package.json b/package.json index c8d24cee72..a8b19bef8a 100644 --- a/package.json +++ b/package.json @@ -18,12 +18,11 @@ "url": "http://github.com/graphql/graphql-js.git" }, "options": { - "mocha": "--require ./resources/mocha-bootload --check-leaks --full-trace src/**/__tests__/**/*-test.js" + "mocha": + "--require ./resources/mocha-bootload --check-leaks --full-trace src/**/__tests__/**/*-test.js" }, "babel": { - "presets": [ - "es2015" - ], + "presets": ["es2015"], "plugins": [ "syntax-async-functions", "transform-class-properties", @@ -35,15 +34,21 @@ }, "scripts": { "test": "npm run lint && npm run check && npm run testonly", - "testonly": "babel-node ./node_modules/.bin/_mocha $npm_package_options_mocha", - "t": "babel-node ./node_modules/.bin/_mocha --require ./resources/mocha-bootload", + "testonly": + "babel-node ./node_modules/.bin/_mocha $npm_package_options_mocha", + "t": + "babel-node ./node_modules/.bin/_mocha --require ./resources/mocha-bootload", "lint": "eslint src", "check": "flow check", - "check-cover": "for file in {src/*.js,src/**/*.js}; do echo $file; flow coverage $file; done", - "build": "babel src --ignore __tests__ --out-dir dist/ && cp package.json dist/", + "check-cover": + "for file in {src/*.js,src/**/*.js}; do echo $file; flow coverage $file; done", + "build": + "babel src --ignore __tests__ --out-dir dist/ && cp package.json dist/", "watch": "babel-node ./resources/watch.js", - "cover": "babel-node ./node_modules/.bin/isparta cover --root src --report html _mocha -- $npm_package_options_mocha", - "cover:lcov": "babel-node ./node_modules/.bin/isparta cover --root src --report lcovonly _mocha -- $npm_package_options_mocha", + "cover": + "babel-node ./node_modules/.bin/isparta cover --root src --report html _mocha -- $npm_package_options_mocha", + "cover:lcov": + "babel-node ./node_modules/.bin/isparta cover --root src --report lcovonly _mocha -- $npm_package_options_mocha", "preversion": ". ./resources/checkgit.sh && npm test", "prepublish": ". ./resources/prepublish.sh" }, diff --git a/resources/mocha-bootload.js b/resources/mocha-bootload.js index 03cfe05104..8879cc7fb7 100644 --- a/resources/mocha-bootload.js +++ b/resources/mocha-bootload.js @@ -7,12 +7,12 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -var chai = require('chai'); +var chai = require("chai"); -var chaiSubset = require('chai-subset'); +var chaiSubset = require("chai-subset"); chai.use(chaiSubset); -process.on('unhandledRejection', function (error) { - console.error('Unhandled Promise Rejection:'); - console.error(error && error.stack || error); +process.on("unhandledRejection", function(error) { + console.error("Unhandled Promise Rejection:"); + console.error((error && error.stack) || error); }); diff --git a/resources/watch.js b/resources/watch.js index a5bc789fc4..4671cda51a 100644 --- a/resources/watch.js +++ b/resources/watch.js @@ -7,47 +7,46 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import sane from 'sane'; -import { resolve as resolvePath } from 'path'; -import { spawn } from 'child_process'; -import flowBinPath from 'flow-bin'; +import sane from "sane"; +import { resolve as resolvePath } from "path"; +import { spawn } from "child_process"; +import flowBinPath from "flow-bin"; - -process.env.PATH += ':./node_modules/.bin'; +process.env.PATH += ":./node_modules/.bin"; var cmd = resolvePath(__dirname); -var srcDir = resolvePath(cmd, '../src'); +var srcDir = resolvePath(cmd, "../src"); function exec(command, options) { return new Promise((resolve, reject) => { var child = spawn(command, options, { cmd: cmd, env: process.env, - stdio: 'inherit' + stdio: "inherit" }); - child.on('exit', code => { + child.on("exit", code => { if (code === 0) { resolve(true); } else { - reject(new Error('Error code: ' + code)); + reject(new Error("Error code: " + code)); } }); }); } -var flowServer = spawn(flowBinPath, ['server'], { +var flowServer = spawn(flowBinPath, ["server"], { cmd: cmd, env: process.env }); -var watcher = sane(srcDir, { glob: ['**/*.js', '**/*.graphql'] }) - .on('ready', startWatch) - .on('add', changeFile) - .on('delete', deleteFile) - .on('change', changeFile); +var watcher = sane(srcDir, { glob: ["**/*.js", "**/*.graphql"] }) + .on("ready", startWatch) + .on("add", changeFile) + .on("delete", deleteFile) + .on("change", changeFile); -process.on('SIGINT', () => { - console.log(CLEARLINE + yellow(invert('stopped watching'))); +process.on("SIGINT", () => { + console.log(CLEARLINE + yellow(invert("stopped watching"))); watcher.close(); flowServer.kill(); process.exit(); @@ -59,7 +58,7 @@ var toCheck = {}; var timeout; function startWatch() { - process.stdout.write(CLEARSCREEN + green(invert('watching...'))); + process.stdout.write(CLEARSCREEN + green(invert("watching..."))); } function changeFile(filepath, root, stat) { @@ -95,18 +94,21 @@ function guardedCheck() { } function checkFiles(filepaths) { - console.log('\u001b[2J'); + console.log("\u001b[2J"); return parseFiles(filepaths) .then(() => runTests(filepaths)) - .then(testSuccess => lintFiles(filepaths) - .then(lintSuccess => typecheckStatus() - .then(typecheckSuccess => - testSuccess && lintSuccess && typecheckSuccess))) + .then(testSuccess => + lintFiles(filepaths).then(lintSuccess => + typecheckStatus().then( + typecheckSuccess => testSuccess && lintSuccess && typecheckSuccess + ) + ) + ) .catch(() => false) .then(success => { process.stdout.write( - '\n' + (success ? '' : '\x07') + green(invert('watching...')) + "\n" + (success ? "" : "\x07") + green(invert("watching...")) ); }); } @@ -114,54 +116,68 @@ function checkFiles(filepaths) { // Checking steps function parseFiles(filepaths) { - console.log('Checking Syntax'); - - return Promise.all(filepaths.map(filepath => { - if (isJS(filepath) && !isTest(filepath)) { - return exec('babel', [ - '--optional', 'runtime', - '--out-file', '/dev/null', - srcPath(filepath) - ]); - } - })); + console.log("Checking Syntax"); + + return Promise.all( + filepaths.map(filepath => { + if (isJS(filepath) && !isTest(filepath)) { + return exec("babel", [ + "--optional", + "runtime", + "--out-file", + "/dev/null", + srcPath(filepath) + ]); + } + }) + ); } function runTests(filepaths) { - console.log('\nRunning Tests'); - - return exec('babel-node', [ - './node_modules/.bin/_mocha', - '--reporter', 'progress', - '--require', './resources/mocha-bootload', - ].concat( - allTests(filepaths) ? - filepaths.map(srcPath) : - ['src/**/__tests__/**/*-test.js'] - )).catch(() => false); + console.log("\nRunning Tests"); + + return exec( + "babel-node", + [ + "./node_modules/.bin/_mocha", + "--reporter", + "progress", + "--require", + "./resources/mocha-bootload" + ].concat( + allTests(filepaths) + ? filepaths.map(srcPath) + : ["src/**/__tests__/**/*-test.js"] + ) + ).catch(() => false); } function lintFiles(filepaths) { - console.log('Linting Code\n'); - - return filepaths.reduce((prev, filepath) => prev.then(prevSuccess => { - if (isJS(filepath)) { - process.stdout.write(' ' + filepath + ' ...'); - return exec('eslint', [srcPath(filepath)]) - .catch(() => false) - .then(success => { - console.log(CLEARLINE + ' ' + (success ? CHECK : X) - + ' ' + filepath); - return prevSuccess && success; - }); - } - return prevSuccess; - }), Promise.resolve(true)); + console.log("Linting Code\n"); + + return filepaths.reduce( + (prev, filepath) => + prev.then(prevSuccess => { + if (isJS(filepath)) { + process.stdout.write(" " + filepath + " ..."); + return exec("eslint", [srcPath(filepath)]) + .catch(() => false) + .then(success => { + console.log( + CLEARLINE + " " + (success ? CHECK : X) + " " + filepath + ); + return prevSuccess && success; + }); + } + return prevSuccess; + }), + Promise.resolve(true) + ); } function typecheckStatus() { - console.log('\nType Checking\n'); - return exec(flowBinPath, ['status']).catch(() => false); + console.log("\nType Checking\n"); + return exec(flowBinPath, ["status"]).catch(() => false); } // Filepath @@ -173,7 +189,7 @@ function srcPath(filepath) { // Predicates function isJS(filepath) { - return filepath.indexOf('.js') === filepath.length - 3; + return filepath.indexOf(".js") === filepath.length - 3; } function allTests(filepaths) { @@ -188,10 +204,10 @@ function isTest(filepath) { // Print helpers -var CLEARSCREEN = '\u001b[2J'; -var CLEARLINE = '\r\x1B[K'; -var CHECK = green('\u2713'); -var X = red('\u2718'); +var CLEARSCREEN = "\u001b[2J"; +var CLEARLINE = "\r\x1B[K"; +var CHECK = green("\u2713"); +var X = red("\u2718"); function invert(str) { return `\u001b[7m ${str} \u001b[27m`; diff --git a/src/README.md b/src/README.md index ba7b7cd5b3..62b8a7bf9b 100644 --- a/src/README.md +++ b/src/README.md @@ -1,5 +1,4 @@ -GraphQL JS ----------- +## GraphQL JS The primary `graphql` module includes everything you need to define a GraphQL schema and fulfill GraphQL requests. diff --git a/src/__tests__/starWarsData.js b/src/__tests__/starWarsData.js index 7bda5c039c..cc2425eccf 100644 --- a/src/__tests__/starWarsData.js +++ b/src/__tests__/starWarsData.js @@ -14,41 +14,41 @@ */ const luke = { - id: '1000', - name: 'Luke Skywalker', - friends: [ '1002', '1003', '2000', '2001' ], - appearsIn: [ 4, 5, 6 ], - homePlanet: 'Tatooine', + id: "1000", + name: "Luke Skywalker", + friends: ["1002", "1003", "2000", "2001"], + appearsIn: [4, 5, 6], + homePlanet: "Tatooine" }; const vader = { - id: '1001', - name: 'Darth Vader', - friends: [ '1004' ], - appearsIn: [ 4, 5, 6 ], - homePlanet: 'Tatooine', + id: "1001", + name: "Darth Vader", + friends: ["1004"], + appearsIn: [4, 5, 6], + homePlanet: "Tatooine" }; const han = { - id: '1002', - name: 'Han Solo', - friends: [ '1000', '1003', '2001' ], - appearsIn: [ 4, 5, 6 ], + id: "1002", + name: "Han Solo", + friends: ["1000", "1003", "2001"], + appearsIn: [4, 5, 6] }; const leia = { - id: '1003', - name: 'Leia Organa', - friends: [ '1000', '1002', '2000', '2001' ], - appearsIn: [ 4, 5, 6 ], - homePlanet: 'Alderaan', + id: "1003", + name: "Leia Organa", + friends: ["1000", "1002", "2000", "2001"], + appearsIn: [4, 5, 6], + homePlanet: "Alderaan" }; const tarkin = { - id: '1004', - name: 'Wilhuff Tarkin', - friends: [ '1001' ], - appearsIn: [ 4 ], + id: "1004", + name: "Wilhuff Tarkin", + friends: ["1001"], + appearsIn: [4] }; const humanData = { @@ -56,28 +56,28 @@ const humanData = { 1001: vader, 1002: han, 1003: leia, - 1004: tarkin, + 1004: tarkin }; const threepio = { - id: '2000', - name: 'C-3PO', - friends: [ '1000', '1002', '1003', '2001' ], - appearsIn: [ 4, 5, 6 ], - primaryFunction: 'Protocol', + id: "2000", + name: "C-3PO", + friends: ["1000", "1002", "1003", "2001"], + appearsIn: [4, 5, 6], + primaryFunction: "Protocol" }; const artoo = { - id: '2001', - name: 'R2-D2', - friends: [ '1000', '1002', '1003' ], - appearsIn: [ 4, 5, 6 ], - primaryFunction: 'Astromech', + id: "2001", + name: "R2-D2", + friends: ["1000", "1002", "1003"], + appearsIn: [4, 5, 6], + primaryFunction: "Astromech" }; const droidData = { 2000: threepio, - 2001: artoo, + 2001: artoo }; /** diff --git a/src/__tests__/starWarsIntrospection-test.js b/src/__tests__/starWarsIntrospection-test.js index 6646825e34..2d4a369977 100644 --- a/src/__tests__/starWarsIntrospection-test.js +++ b/src/__tests__/starWarsIntrospection-test.js @@ -7,17 +7,17 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { StarWarsSchema } from './starWarsSchema.js'; -import { graphql } from '../graphql'; +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { StarWarsSchema } from "./starWarsSchema.js"; +import { graphql } from "../graphql"; // 80+ char lines are useful in describe/it, so ignore in this file. /* eslint-disable max-len */ -describe('Star Wars Introspection Tests', () => { - describe('Basic Introspection', () => { - it('Allows querying the schema for types', async () => { +describe("Star Wars Introspection Tests", () => { + describe("Basic Introspection", () => { + it("Allows querying the schema for types", async () => { const query = ` query IntrospectionTypeQuery { __schema { @@ -31,49 +31,49 @@ describe('Star Wars Introspection Tests', () => { __schema: { types: [ { - name: 'Query' + name: "Query" }, { - name: 'Episode' + name: "Episode" }, { - name: 'Character' + name: "Character" }, { - name: 'String' + name: "String" }, { - name: 'Human' + name: "Human" }, { - name: 'Droid' + name: "Droid" }, { - name: '__Schema' + name: "__Schema" }, { - name: '__Type' + name: "__Type" }, { - name: '__TypeKind' + name: "__TypeKind" }, { - name: 'Boolean' + name: "Boolean" }, { - name: '__Field' + name: "__Field" }, { - name: '__InputValue' + name: "__InputValue" }, { - name: '__EnumValue' + name: "__EnumValue" }, { - name: '__Directive' + name: "__Directive" }, { - name: '__DirectiveLocation' + name: "__DirectiveLocation" } ] } @@ -82,7 +82,7 @@ describe('Star Wars Introspection Tests', () => { expect(result).to.deep.equal({ data: expected }); }); - it('Allows querying the schema for query type', async () => { + it("Allows querying the schema for query type", async () => { const query = ` query IntrospectionQueryTypeQuery { __schema { @@ -95,15 +95,15 @@ describe('Star Wars Introspection Tests', () => { const expected = { __schema: { queryType: { - name: 'Query' - }, + name: "Query" + } } }; const result = await graphql(StarWarsSchema, query); expect(result).to.deep.equal({ data: expected }); }); - it('Allows querying the schema for a specific type', async () => { + it("Allows querying the schema for a specific type", async () => { const query = ` query IntrospectionDroidTypeQuery { __type(name: "Droid") { @@ -113,14 +113,14 @@ describe('Star Wars Introspection Tests', () => { `; const expected = { __type: { - name: 'Droid' + name: "Droid" } }; const result = await graphql(StarWarsSchema, query); expect(result).to.deep.equal({ data: expected }); }); - it('Allows querying the schema for an object kind', async () => { + it("Allows querying the schema for an object kind", async () => { const query = ` query IntrospectionDroidKindQuery { __type(name: "Droid") { @@ -131,15 +131,15 @@ describe('Star Wars Introspection Tests', () => { `; const expected = { __type: { - name: 'Droid', - kind: 'OBJECT' + name: "Droid", + kind: "OBJECT" } }; const result = await graphql(StarWarsSchema, query); expect(result).to.deep.equal({ data: expected }); }); - it('Allows querying the schema for an interface kind', async () => { + it("Allows querying the schema for an interface kind", async () => { const query = ` query IntrospectionCharacterKindQuery { __type(name: "Character") { @@ -150,15 +150,15 @@ describe('Star Wars Introspection Tests', () => { `; const expected = { __type: { - name: 'Character', - kind: 'INTERFACE' + name: "Character", + kind: "INTERFACE" } }; const result = await graphql(StarWarsSchema, query); expect(result).to.deep.equal({ data: expected }); }); - it('Allows querying the schema for object fields', async () => { + it("Allows querying the schema for object fields", async () => { const query = ` query IntrospectionDroidFieldsQuery { __type(name: "Droid") { @@ -175,41 +175,41 @@ describe('Star Wars Introspection Tests', () => { `; const expected = { __type: { - name: 'Droid', + name: "Droid", fields: [ { - name: 'id', + name: "id", type: { name: null, - kind: 'NON_NULL' + kind: "NON_NULL" } }, { - name: 'name', + name: "name", type: { - name: 'String', - kind: 'SCALAR' + name: "String", + kind: "SCALAR" } }, { - name: 'friends', + name: "friends", type: { name: null, - kind: 'LIST' + kind: "LIST" } }, { - name: 'appearsIn', + name: "appearsIn", type: { name: null, - kind: 'LIST' + kind: "LIST" } }, { - name: 'primaryFunction', + name: "primaryFunction", type: { - name: 'String', - kind: 'SCALAR' + name: "String", + kind: "SCALAR" } } ] @@ -220,7 +220,7 @@ describe('Star Wars Introspection Tests', () => { expect(result).to.deep.equal({ data: expected }); }); - it('Allows querying the schema for nested object fields', async () => { + it("Allows querying the schema for nested object fields", async () => { const query = ` query IntrospectionDroidNestedFieldsQuery { __type(name: "Droid") { @@ -241,54 +241,54 @@ describe('Star Wars Introspection Tests', () => { `; const expected = { __type: { - name: 'Droid', + name: "Droid", fields: [ { - name: 'id', + name: "id", type: { name: null, - kind: 'NON_NULL', + kind: "NON_NULL", ofType: { - name: 'String', - kind: 'SCALAR' + name: "String", + kind: "SCALAR" } } }, { - name: 'name', + name: "name", type: { - name: 'String', - kind: 'SCALAR', + name: "String", + kind: "SCALAR", ofType: null } }, { - name: 'friends', + name: "friends", type: { name: null, - kind: 'LIST', + kind: "LIST", ofType: { - name: 'Character', - kind: 'INTERFACE' + name: "Character", + kind: "INTERFACE" } } }, { - name: 'appearsIn', + name: "appearsIn", type: { name: null, - kind: 'LIST', + kind: "LIST", ofType: { - name: 'Episode', - kind: 'ENUM' + name: "Episode", + kind: "ENUM" } } }, { - name: 'primaryFunction', + name: "primaryFunction", type: { - name: 'String', - kind: 'SCALAR', + name: "String", + kind: "SCALAR", ofType: null } } @@ -299,7 +299,7 @@ describe('Star Wars Introspection Tests', () => { expect(result).to.deep.equal({ data: expected }); }); - it('Allows querying the schema for field args', async () => { + it("Allows querying the schema for field args", async () => { const query = ` query IntrospectionQueryTypeQuery { __schema { @@ -329,34 +329,35 @@ describe('Star Wars Introspection Tests', () => { queryType: { fields: [ { - name: 'hero', + name: "hero", args: [ { defaultValue: null, - description: 'If omitted, returns the hero of the whole ' + - 'saga. If provided, returns the hero of ' + - 'that particular episode.', - name: 'episode', + description: + "If omitted, returns the hero of the whole " + + "saga. If provided, returns the hero of " + + "that particular episode.", + name: "episode", type: { - kind: 'ENUM', - name: 'Episode', + kind: "ENUM", + name: "Episode", ofType: null } } ] }, { - name: 'human', + name: "human", args: [ { - name: 'id', - description: 'id of the human', + name: "id", + description: "id of the human", type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'SCALAR', - name: 'String' + kind: "SCALAR", + name: "String" } }, defaultValue: null @@ -364,17 +365,17 @@ describe('Star Wars Introspection Tests', () => { ] }, { - name: 'droid', + name: "droid", args: [ { - name: 'id', - description: 'id of the droid', + name: "id", + description: "id of the droid", type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'SCALAR', - name: 'String' + kind: "SCALAR", + name: "String" } }, defaultValue: null @@ -386,12 +387,11 @@ describe('Star Wars Introspection Tests', () => { } }; - const result = await graphql(StarWarsSchema, query); expect(result).to.deep.equal({ data: expected }); }); - it('Allows querying the schema for documentation', async () => { + it("Allows querying the schema for documentation", async () => { const query = ` query IntrospectionDroidDescriptionQuery { __type(name: "Droid") { @@ -402,8 +402,8 @@ describe('Star Wars Introspection Tests', () => { `; const expected = { __type: { - name: 'Droid', - description: 'A mechanical creature in the Star Wars universe.' + name: "Droid", + description: "A mechanical creature in the Star Wars universe." } }; const result = await graphql(StarWarsSchema, query); diff --git a/src/__tests__/starWarsQuery-test.js b/src/__tests__/starWarsQuery-test.js index 180e12b3af..73cd0fcf34 100644 --- a/src/__tests__/starWarsQuery-test.js +++ b/src/__tests__/starWarsQuery-test.js @@ -7,17 +7,17 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { StarWarsSchema } from './starWarsSchema.js'; -import { graphql } from '../graphql'; +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { StarWarsSchema } from "./starWarsSchema.js"; +import { graphql } from "../graphql"; // 80+ char lines are useful in describe/it, so ignore in this file. /* eslint-disable max-len */ -describe('Star Wars Query Tests', () => { - describe('Basic Queries', () => { - it('Correctly identifies R2-D2 as the hero of the Star Wars Saga', async () => { +describe("Star Wars Query Tests", () => { + describe("Basic Queries", () => { + it("Correctly identifies R2-D2 as the hero of the Star Wars Saga", async () => { const query = ` query HeroNameQuery { hero { @@ -27,14 +27,14 @@ describe('Star Wars Query Tests', () => { `; const expected = { hero: { - name: 'R2-D2' + name: "R2-D2" } }; const result = await graphql(StarWarsSchema, query); expect(result).to.deep.equal({ data: expected }); }); - it('Allows us to query for the ID and friends of R2-D2', async () => { + it("Allows us to query for the ID and friends of R2-D2", async () => { const query = ` query HeroNameAndFriendsQuery { hero { @@ -48,18 +48,18 @@ describe('Star Wars Query Tests', () => { `; const expected = { hero: { - id: '2001', - name: 'R2-D2', + id: "2001", + name: "R2-D2", friends: [ { - name: 'Luke Skywalker', + name: "Luke Skywalker" }, { - name: 'Han Solo', + name: "Han Solo" }, { - name: 'Leia Organa', - }, + name: "Leia Organa" + } ] } }; @@ -68,8 +68,8 @@ describe('Star Wars Query Tests', () => { }); }); - describe('Nested Queries', () => { - it('Allows us to query for the friends of friends of R2-D2', async () => { + describe("Nested Queries", () => { + it("Allows us to query for the friends of friends of R2-D2", async () => { const query = ` query NestedQuery { hero { @@ -86,59 +86,59 @@ describe('Star Wars Query Tests', () => { `; const expected = { hero: { - name: 'R2-D2', + name: "R2-D2", friends: [ { - name: 'Luke Skywalker', - appearsIn: [ 'NEWHOPE', 'EMPIRE', 'JEDI' ], + name: "Luke Skywalker", + appearsIn: ["NEWHOPE", "EMPIRE", "JEDI"], friends: [ { - name: 'Han Solo', + name: "Han Solo" }, { - name: 'Leia Organa', + name: "Leia Organa" }, { - name: 'C-3PO', + name: "C-3PO" }, { - name: 'R2-D2', - }, + name: "R2-D2" + } ] }, { - name: 'Han Solo', - appearsIn: [ 'NEWHOPE', 'EMPIRE', 'JEDI' ], + name: "Han Solo", + appearsIn: ["NEWHOPE", "EMPIRE", "JEDI"], friends: [ { - name: 'Luke Skywalker', + name: "Luke Skywalker" }, { - name: 'Leia Organa', + name: "Leia Organa" }, { - name: 'R2-D2', - }, + name: "R2-D2" + } ] }, { - name: 'Leia Organa', - appearsIn: [ 'NEWHOPE', 'EMPIRE', 'JEDI' ], + name: "Leia Organa", + appearsIn: ["NEWHOPE", "EMPIRE", "JEDI"], friends: [ { - name: 'Luke Skywalker', + name: "Luke Skywalker" }, { - name: 'Han Solo', + name: "Han Solo" }, { - name: 'C-3PO', + name: "C-3PO" }, { - name: 'R2-D2', - }, + name: "R2-D2" + } ] - }, + } ] } }; @@ -147,8 +147,8 @@ describe('Star Wars Query Tests', () => { }); }); - describe('Using IDs and query parameters to refetch objects', () => { - it('Allows us to query for Luke Skywalker directly, using his ID', async () => { + describe("Using IDs and query parameters to refetch objects", () => { + it("Allows us to query for Luke Skywalker directly, using his ID", async () => { const query = ` query FetchLukeQuery { human(id: "1000") { @@ -158,14 +158,14 @@ describe('Star Wars Query Tests', () => { `; const expected = { human: { - name: 'Luke Skywalker' + name: "Luke Skywalker" } }; const result = await graphql(StarWarsSchema, query); expect(result).to.deep.equal({ data: expected }); }); - it('Allows us to create a generic query, then use it to fetch Luke Skywalker using his ID', async () => { + it("Allows us to create a generic query, then use it to fetch Luke Skywalker using his ID", async () => { const query = ` query FetchSomeIDQuery($someId: String!) { human(id: $someId) { @@ -174,18 +174,18 @@ describe('Star Wars Query Tests', () => { } `; const params = { - someId: '1000' + someId: "1000" }; const expected = { human: { - name: 'Luke Skywalker' + name: "Luke Skywalker" } }; const result = await graphql(StarWarsSchema, query, null, null, params); expect(result).to.deep.equal({ data: expected }); }); - it('Allows us to create a generic query, then use it to fetch Han Solo using his ID', async () => { + it("Allows us to create a generic query, then use it to fetch Han Solo using his ID", async () => { const query = ` query FetchSomeIDQuery($someId: String!) { human(id: $someId) { @@ -194,18 +194,18 @@ describe('Star Wars Query Tests', () => { } `; const params = { - someId: '1002' + someId: "1002" }; const expected = { human: { - name: 'Han Solo' + name: "Han Solo" } }; const result = await graphql(StarWarsSchema, query, null, null, params); expect(result).to.deep.equal({ data: expected }); }); - it('Allows us to create a generic query, then pass an invalid ID to get null back', async () => { + it("Allows us to create a generic query, then pass an invalid ID to get null back", async () => { const query = ` query humanQuery($id: String!) { human(id: $id) { @@ -214,7 +214,7 @@ describe('Star Wars Query Tests', () => { } `; const params = { - id: 'not a valid id' + id: "not a valid id" }; const expected = { human: null @@ -224,8 +224,8 @@ describe('Star Wars Query Tests', () => { }); }); - describe('Using aliases to change the key in the response', () => { - it('Allows us to query for Luke, changing his key with an alias', async () => { + describe("Using aliases to change the key in the response", () => { + it("Allows us to query for Luke, changing his key with an alias", async () => { const query = ` query FetchLukeAliased { luke: human(id: "1000") { @@ -235,14 +235,14 @@ describe('Star Wars Query Tests', () => { `; const expected = { luke: { - name: 'Luke Skywalker' - }, + name: "Luke Skywalker" + } }; const result = await graphql(StarWarsSchema, query); expect(result).to.deep.equal({ data: expected }); }); - it('Allows us to query for both Luke and Leia, using two root fields and an alias', async () => { + it("Allows us to query for both Luke and Leia, using two root fields and an alias", async () => { const query = ` query FetchLukeAndLeiaAliased { luke: human(id: "1000") { @@ -255,10 +255,10 @@ describe('Star Wars Query Tests', () => { `; const expected = { luke: { - name: 'Luke Skywalker' + name: "Luke Skywalker" }, leia: { - name: 'Leia Organa' + name: "Leia Organa" } }; const result = await graphql(StarWarsSchema, query); @@ -266,8 +266,8 @@ describe('Star Wars Query Tests', () => { }); }); - describe('Uses fragments to express more complex queries', () => { - it('Allows us to query using duplicated content', async () => { + describe("Uses fragments to express more complex queries", () => { + it("Allows us to query using duplicated content", async () => { const query = ` query DuplicateFields { luke: human(id: "1000") { @@ -282,19 +282,19 @@ describe('Star Wars Query Tests', () => { `; const expected = { luke: { - name: 'Luke Skywalker', - homePlanet: 'Tatooine' + name: "Luke Skywalker", + homePlanet: "Tatooine" }, leia: { - name: 'Leia Organa', - homePlanet: 'Alderaan' + name: "Leia Organa", + homePlanet: "Alderaan" } }; const result = await graphql(StarWarsSchema, query); expect(result).to.deep.equal({ data: expected }); }); - it('Allows us to use a fragment to avoid duplicating content', async () => { + it("Allows us to use a fragment to avoid duplicating content", async () => { const query = ` query UseFragment { luke: human(id: "1000") { @@ -312,12 +312,12 @@ describe('Star Wars Query Tests', () => { `; const expected = { luke: { - name: 'Luke Skywalker', - homePlanet: 'Tatooine' + name: "Luke Skywalker", + homePlanet: "Tatooine" }, leia: { - name: 'Leia Organa', - homePlanet: 'Alderaan' + name: "Leia Organa", + homePlanet: "Alderaan" } }; const result = await graphql(StarWarsSchema, query); @@ -325,8 +325,8 @@ describe('Star Wars Query Tests', () => { }); }); - describe('Using __typename to find the type of an object', () => { - it('Allows us to verify that R2-D2 is a droid', async () => { + describe("Using __typename to find the type of an object", () => { + it("Allows us to verify that R2-D2 is a droid", async () => { const query = ` query CheckTypeOfR2 { hero { @@ -337,15 +337,15 @@ describe('Star Wars Query Tests', () => { `; const expected = { hero: { - __typename: 'Droid', - name: 'R2-D2' - }, + __typename: "Droid", + name: "R2-D2" + } }; const result = await graphql(StarWarsSchema, query); expect(result).to.deep.equal({ data: expected }); }); - it('Allows us to verify that Luke is a human', async () => { + it("Allows us to verify that Luke is a human", async () => { const query = ` query CheckTypeOfLuke { hero(episode: EMPIRE) { @@ -356,9 +356,9 @@ describe('Star Wars Query Tests', () => { `; const expected = { hero: { - __typename: 'Human', - name: 'Luke Skywalker' - }, + __typename: "Human", + name: "Luke Skywalker" + } }; const result = await graphql(StarWarsSchema, query); expect(result).to.deep.equal({ data: expected }); diff --git a/src/__tests__/starWarsSchema.js b/src/__tests__/starWarsSchema.js index e315986a66..b47273cd73 100644 --- a/src/__tests__/starWarsSchema.js +++ b/src/__tests__/starWarsSchema.js @@ -14,10 +14,10 @@ import { GraphQLList, GraphQLNonNull, GraphQLSchema, - GraphQLString, -} from '../type'; + GraphQLString +} from "../type"; -import { getFriends, getHero, getHuman, getDroid } from './starWarsData.js'; +import { getFriends, getHero, getHuman, getDroid } from "./starWarsData.js"; /** * This is designed to be an end-to-end test, demonstrating @@ -75,21 +75,21 @@ import { getFriends, getHero, getHuman, getDroid } from './starWarsData.js'; * enum Episode { NEWHOPE, EMPIRE, JEDI } */ const episodeEnum = new GraphQLEnumType({ - name: 'Episode', - description: 'One of the films in the Star Wars Trilogy', + name: "Episode", + description: "One of the films in the Star Wars Trilogy", values: { NEWHOPE: { value: 4, - description: 'Released in 1977.', + description: "Released in 1977." }, EMPIRE: { value: 5, - description: 'Released in 1980.', + description: "Released in 1980." }, JEDI: { value: 6, - description: 'Released in 1983.', - }, + description: "Released in 1983." + } } }); @@ -105,26 +105,26 @@ const episodeEnum = new GraphQLEnumType({ * } */ const characterInterface = new GraphQLInterfaceType({ - name: 'Character', - description: 'A character in the Star Wars Trilogy', + name: "Character", + description: "A character in the Star Wars Trilogy", fields: () => ({ id: { type: new GraphQLNonNull(GraphQLString), - description: 'The id of the character.', + description: "The id of the character." }, name: { type: GraphQLString, - description: 'The name of the character.', + description: "The name of the character." }, friends: { type: new GraphQLList(characterInterface), - description: 'The friends of the character, or an empty list if they ' + - 'have none.', + description: + "The friends of the character, or an empty list if they " + "have none." }, appearsIn: { type: new GraphQLList(episodeEnum), - description: 'Which movies they appear in.', - }, + description: "Which movies they appear in." + } }), resolveType: character => { return getHuman(character.id) ? humanType : droidType; @@ -143,33 +143,33 @@ const characterInterface = new GraphQLInterfaceType({ * } */ const humanType = new GraphQLObjectType({ - name: 'Human', - description: 'A humanoid creature in the Star Wars universe.', + name: "Human", + description: "A humanoid creature in the Star Wars universe.", fields: () => ({ id: { type: new GraphQLNonNull(GraphQLString), - description: 'The id of the human.', + description: "The id of the human." }, name: { type: GraphQLString, - description: 'The name of the human.', + description: "The name of the human." }, friends: { type: new GraphQLList(characterInterface), - description: 'The friends of the human, or an empty list if they ' + - 'have none.', - resolve: human => getFriends(human), + description: + "The friends of the human, or an empty list if they " + "have none.", + resolve: human => getFriends(human) }, appearsIn: { type: new GraphQLList(episodeEnum), - description: 'Which movies they appear in.', + description: "Which movies they appear in." }, homePlanet: { type: GraphQLString, - description: 'The home planet of the human, or null if unknown.', - }, + description: "The home planet of the human, or null if unknown." + } }), - interfaces: [ characterInterface ] + interfaces: [characterInterface] }); /** @@ -185,33 +185,33 @@ const humanType = new GraphQLObjectType({ * } */ const droidType = new GraphQLObjectType({ - name: 'Droid', - description: 'A mechanical creature in the Star Wars universe.', + name: "Droid", + description: "A mechanical creature in the Star Wars universe.", fields: () => ({ id: { type: new GraphQLNonNull(GraphQLString), - description: 'The id of the droid.', + description: "The id of the droid." }, name: { type: GraphQLString, - description: 'The name of the droid.', + description: "The name of the droid." }, friends: { type: new GraphQLList(characterInterface), - description: 'The friends of the droid, or an empty list if they ' + - 'have none.', - resolve: droid => getFriends(droid), + description: + "The friends of the droid, or an empty list if they " + "have none.", + resolve: droid => getFriends(droid) }, appearsIn: { type: new GraphQLList(episodeEnum), - description: 'Which movies they appear in.', + description: "Which movies they appear in." }, primaryFunction: { type: GraphQLString, - description: 'The primary function of the droid.', - }, + description: "The primary function of the droid." + } }), - interfaces: [ characterInterface ] + interfaces: [characterInterface] }); /** @@ -229,39 +229,40 @@ const droidType = new GraphQLObjectType({ * */ const queryType = new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: () => ({ hero: { type: characterInterface, args: { episode: { - description: 'If omitted, returns the hero of the whole saga. If ' + - 'provided, returns the hero of that particular episode.', + description: + "If omitted, returns the hero of the whole saga. If " + + "provided, returns the hero of that particular episode.", type: episodeEnum } }, - resolve: (root, { episode }) => getHero(episode), + resolve: (root, { episode }) => getHero(episode) }, human: { type: humanType, args: { id: { - description: 'id of the human', + description: "id of the human", type: new GraphQLNonNull(GraphQLString) } }, - resolve: (root, { id }) => getHuman(id), + resolve: (root, { id }) => getHuman(id) }, droid: { type: droidType, args: { id: { - description: 'id of the droid', + description: "id of the droid", type: new GraphQLNonNull(GraphQLString) } }, - resolve: (root, { id }) => getDroid(id), - }, + resolve: (root, { id }) => getDroid(id) + } }) }); @@ -271,5 +272,5 @@ const queryType = new GraphQLObjectType({ */ export const StarWarsSchema = new GraphQLSchema({ query: queryType, - types: [ humanType, droidType ] + types: [humanType, droidType] }); diff --git a/src/__tests__/starWarsValidation-test.js b/src/__tests__/starWarsValidation-test.js index 45f3eddb98..14441172c4 100644 --- a/src/__tests__/starWarsValidation-test.js +++ b/src/__tests__/starWarsValidation-test.js @@ -7,26 +7,25 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { StarWarsSchema } from './starWarsSchema.js'; -import { Source } from '../language/source'; -import { parse } from '../language/parser'; -import { validate } from '../validation/validate'; - +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { StarWarsSchema } from "./starWarsSchema.js"; +import { Source } from "../language/source"; +import { parse } from "../language/parser"; +import { validate } from "../validation/validate"; /** * Helper function to test a query and the expected response. */ function validationErrors(query) { - const source = new Source(query, 'StarWars.graphql'); + const source = new Source(query, "StarWars.graphql"); const ast = parse(source); return validate(StarWarsSchema, ast); } -describe('Star Wars Validation Tests', () => { - describe('Basic Queries', () => { - it('Validates a complex but valid query', () => { +describe("Star Wars Validation Tests", () => { + describe("Basic Queries", () => { + it("Validates a complex but valid query", () => { const query = ` query NestedQueryWithFragment { hero { @@ -48,7 +47,7 @@ describe('Star Wars Validation Tests', () => { return expect(validationErrors(query)).to.be.empty; }); - it('Notes that non-existent fields are invalid', () => { + it("Notes that non-existent fields are invalid", () => { const query = ` query HeroSpaceshipQuery { hero { @@ -59,7 +58,7 @@ describe('Star Wars Validation Tests', () => { return expect(validationErrors(query)).to.not.be.empty; }); - it('Requires fields on objects', () => { + it("Requires fields on objects", () => { const query = ` query HeroNoFieldsQuery { hero @@ -68,7 +67,7 @@ describe('Star Wars Validation Tests', () => { return expect(validationErrors(query)).to.not.be.empty; }); - it('Disallows fields on scalars', () => { + it("Disallows fields on scalars", () => { const query = ` query HeroFieldsOnScalarQuery { hero { @@ -81,7 +80,7 @@ describe('Star Wars Validation Tests', () => { return expect(validationErrors(query)).to.not.be.empty; }); - it('Disallows object fields on interfaces', () => { + it("Disallows object fields on interfaces", () => { const query = ` query DroidFieldOnCharacter { hero { @@ -93,7 +92,7 @@ describe('Star Wars Validation Tests', () => { return expect(validationErrors(query)).to.not.be.empty; }); - it('Allows object fields in fragments', () => { + it("Allows object fields in fragments", () => { const query = ` query DroidFieldInFragment { hero { @@ -109,7 +108,7 @@ describe('Star Wars Validation Tests', () => { return expect(validationErrors(query)).to.be.empty; }); - it('Allows object fields in inline fragments', () => { + it("Allows object fields in inline fragments", () => { const query = ` query DroidFieldInFragment { hero { diff --git a/src/error/GraphQLError.js b/src/error/GraphQLError.js index 08fc5b883d..a1bde98e82 100644 --- a/src/error/GraphQLError.js +++ b/src/error/GraphQLError.js @@ -8,10 +8,9 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { getLocation } from '../language'; -import type { Node } from '../language/ast'; -import type { Source } from '../language/source'; - +import { getLocation } from "../language"; +import type { Node } from "../language/ast"; +import type { Source } from "../language/source"; export class GraphQLError extends Error { message: string; @@ -25,7 +24,7 @@ export class GraphQLError extends Error { constructor( message: string, // A flow bug keeps us from declaring nodes as an array of Node - nodes?: Array, + nodes?: Array, stack?: ?string, source?: Source, positions?: Array @@ -33,42 +32,54 @@ export class GraphQLError extends Error { super(message); this.message = message; - Object.defineProperty(this, 'stack', { value: stack || message }); - Object.defineProperty(this, 'nodes', { value: nodes }); + Object.defineProperty(this, "stack", { value: stack || message }); + Object.defineProperty(this, "nodes", { value: nodes }); // Note: flow does not yet know about Object.defineProperty with `get`. - Object.defineProperty(this, 'source', ({ - get() { - if (source) { - return source; - } - if (nodes && nodes.length > 0) { - const node = nodes[0]; - return node && node.loc && node.loc.source; + Object.defineProperty( + this, + "source", + ({ + get() { + if (source) { + return source; + } + if (nodes && nodes.length > 0) { + const node = nodes[0]; + return node && node.loc && node.loc.source; + } } - } - }: any)); + }: any) + ); - Object.defineProperty(this, 'positions', ({ - get() { - if (positions) { - return positions; - } - if (nodes) { - const nodePositions = nodes.map(node => node.loc && node.loc.start); - if (nodePositions.some(p => p)) { - return nodePositions; + Object.defineProperty( + this, + "positions", + ({ + get() { + if (positions) { + return positions; + } + if (nodes) { + const nodePositions = nodes.map(node => node.loc && node.loc.start); + if (nodePositions.some(p => p)) { + return nodePositions; + } } } - } - }: any)); + }: any) + ); - Object.defineProperty(this, 'locations', ({ - get() { - if (this.positions && this.source) { - return this.positions.map(pos => getLocation(this.source, pos)); + Object.defineProperty( + this, + "locations", + ({ + get() { + if (this.positions && this.source) { + return this.positions.map(pos => getLocation(this.source, pos)); + } } - } - }: any)); + }: any) + ); } } diff --git a/src/error/README.md b/src/error/README.md index 9f4460676d..3898d77780 100644 --- a/src/error/README.md +++ b/src/error/README.md @@ -1,5 +1,4 @@ -GraphQL Errors --------------- +## GraphQL Errors The `graphql/error` module is responsible for creating and formating GraphQL errors. diff --git a/src/error/formatError.js b/src/error/formatError.js index 320afcf60f..9e7354e4e7 100644 --- a/src/error/formatError.js +++ b/src/error/formatError.js @@ -8,16 +8,15 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import invariant from '../jsutils/invariant'; -import type { GraphQLError } from './GraphQLError'; - +import invariant from "../jsutils/invariant"; +import type { GraphQLError } from "./GraphQLError"; /** * Given a GraphQLError, format it according to the rules described by the * Response Format, Errors section of the GraphQL Specification. */ export function formatError(error: GraphQLError): GraphQLFormattedError { - invariant(error, 'Received null or undefined error.'); + invariant(error, "Received null or undefined error."); return { message: error.message, locations: error.locations diff --git a/src/error/index.js b/src/error/index.js index 3419e8ea3e..3270d57de0 100644 --- a/src/error/index.js +++ b/src/error/index.js @@ -8,7 +8,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -export { GraphQLError } from './GraphQLError'; -export { syntaxError } from './syntaxError'; -export { locatedError } from './locatedError'; -export { formatError } from './formatError'; +export { GraphQLError } from "./GraphQLError"; +export { syntaxError } from "./syntaxError"; +export { locatedError } from "./locatedError"; +export { formatError } from "./formatError"; diff --git a/src/error/locatedError.js b/src/error/locatedError.js index 6bab9071ac..da7af10011 100644 --- a/src/error/locatedError.js +++ b/src/error/locatedError.js @@ -8,8 +8,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { GraphQLError } from './GraphQLError'; - +import { GraphQLError } from "./GraphQLError"; /** * Given an arbitrary Error, presumably thrown while attempting to execute a @@ -20,9 +19,9 @@ export function locatedError( originalError: ?Error, nodes: Array ): GraphQLError { - const message = originalError ? - originalError.message || String(originalError) : - 'An unknown error occurred.'; + const message = originalError + ? originalError.message || String(originalError) + : "An unknown error occurred."; const stack = originalError ? originalError.stack : null; const error = new GraphQLError(message, nodes, stack); error.originalError = originalError; diff --git a/src/error/syntaxError.js b/src/error/syntaxError.js index bfa129b8f1..79f661b924 100644 --- a/src/error/syntaxError.js +++ b/src/error/syntaxError.js @@ -8,9 +8,9 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { getLocation } from '../language/location'; -import type { Source } from '../language/source'; -import { GraphQLError } from './GraphQLError'; +import { getLocation } from "../language/location"; +import type { Source } from "../language/source"; +import { GraphQLError } from "./GraphQLError"; /** * Produces a GraphQLError representing a syntax error, containing useful @@ -24,11 +24,13 @@ export function syntaxError( const location = getLocation(source, position); const error = new GraphQLError( `Syntax Error ${source.name} (${location.line}:${location.column}) ` + - description + '\n\n' + highlightSourceAtLocation(source, location), + description + + "\n\n" + + highlightSourceAtLocation(source, location), undefined, undefined, source, - [ position ] + [position] ); return error; } @@ -45,15 +47,21 @@ function highlightSourceAtLocation(source, location) { const padLen = nextLineNum.length; const lines = source.body.split(/\r\n|[\n\r]/g); return ( - (line >= 2 ? - lpad(padLen, prevLineNum) + ': ' + lines[line - 2] + '\n' : '') + - lpad(padLen, lineNum) + ': ' + lines[line - 1] + '\n' + - Array(2 + padLen + location.column).join(' ') + '^\n' + - (line < lines.length ? - lpad(padLen, nextLineNum) + ': ' + lines[line] + '\n' : '') + (line >= 2 + ? lpad(padLen, prevLineNum) + ": " + lines[line - 2] + "\n" + : "") + + lpad(padLen, lineNum) + + ": " + + lines[line - 1] + + "\n" + + Array(2 + padLen + location.column).join(" ") + + "^\n" + + (line < lines.length + ? lpad(padLen, nextLineNum) + ": " + lines[line] + "\n" + : "") ); } function lpad(len, str) { - return Array(len - str.length + 1).join(' ') + str; + return Array(len - str.length + 1).join(" ") + str; } diff --git a/src/execution/README.md b/src/execution/README.md index 7b875646ee..55ed0cb5e6 100644 --- a/src/execution/README.md +++ b/src/execution/README.md @@ -1,10 +1,9 @@ -GraphQL Execution ------------------ +## GraphQL Execution The `graphql/execution` module is responsible for the execution phase of fulfilling a GraphQL request. ```js -import { execute } from 'graphql/execution'; // ES6 -var GraphQLExecution = require('graphql/execution'); // CommonJS +import { execute } from "graphql/execution"; // ES6 +var GraphQLExecution = require("graphql/execution"); // CommonJS ``` diff --git a/src/execution/__tests__/abstract-test.js b/src/execution/__tests__/abstract-test.js index e839a580f2..0d07e5700d 100644 --- a/src/execution/__tests__/abstract-test.js +++ b/src/execution/__tests__/abstract-test.js @@ -7,8 +7,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; +import { expect } from "chai"; +import { describe, it } from "mocha"; import { graphql, GraphQLSchema, @@ -17,9 +17,8 @@ import { GraphQLUnionType, GraphQLList, GraphQLString, - GraphQLBoolean, -} from '../../'; - + GraphQLBoolean +} from "../../"; class Dog { constructor(name, woofs) { @@ -41,49 +40,48 @@ class Human { } } -describe('Execute: Handles execution of abstract types', () => { - - it('isTypeOf used to resolve runtime type for Interface', async () => { +describe("Execute: Handles execution of abstract types", () => { + it("isTypeOf used to resolve runtime type for Interface", async () => { const PetType = new GraphQLInterfaceType({ - name: 'Pet', + name: "Pet", fields: { name: { type: GraphQLString } } }); const DogType = new GraphQLObjectType({ - name: 'Dog', - interfaces: [ PetType ], + name: "Dog", + interfaces: [PetType], isTypeOf: obj => obj instanceof Dog, fields: { name: { type: GraphQLString }, - woofs: { type: GraphQLBoolean }, + woofs: { type: GraphQLBoolean } } }); const CatType = new GraphQLObjectType({ - name: 'Cat', - interfaces: [ PetType ], + name: "Cat", + interfaces: [PetType], isTypeOf: obj => obj instanceof Cat, fields: { name: { type: GraphQLString }, - meows: { type: GraphQLBoolean }, + meows: { type: GraphQLBoolean } } }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { pets: { type: new GraphQLList(PetType), resolve() { - return [ new Dog('Odie', true), new Cat('Garfield', false) ]; + return [new Dog("Odie", true), new Cat("Garfield", false)]; } } } }), - types: [ CatType, DogType ] + types: [CatType, DogType] }); const query = `{ @@ -103,45 +101,51 @@ describe('Execute: Handles execution of abstract types', () => { expect(result).to.deep.equal({ data: { pets: [ - { name: 'Odie', - woofs: true }, - { name: 'Garfield', - meows: false } ] } + { + name: "Odie", + woofs: true + }, + { + name: "Garfield", + meows: false + } + ] + } }); }); - it('isTypeOf used to resolve runtime type for Union', async () => { + it("isTypeOf used to resolve runtime type for Union", async () => { const DogType = new GraphQLObjectType({ - name: 'Dog', + name: "Dog", isTypeOf: obj => obj instanceof Dog, fields: { name: { type: GraphQLString }, - woofs: { type: GraphQLBoolean }, + woofs: { type: GraphQLBoolean } } }); const CatType = new GraphQLObjectType({ - name: 'Cat', + name: "Cat", isTypeOf: obj => obj instanceof Cat, fields: { name: { type: GraphQLString }, - meows: { type: GraphQLBoolean }, + meows: { type: GraphQLBoolean } } }); const PetType = new GraphQLUnionType({ - name: 'Pet', - types: [ DogType, CatType ] + name: "Pet", + types: [DogType, CatType] }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { pets: { type: new GraphQLList(PetType), resolve() { - return [ new Dog('Odie', true), new Cat('Garfield', false) ]; + return [new Dog("Odie", true), new Cat("Garfield", false)]; } } } @@ -166,21 +170,28 @@ describe('Execute: Handles execution of abstract types', () => { expect(result).to.deep.equal({ data: { pets: [ - { name: 'Odie', - woofs: true }, - { name: 'Garfield', - meows: false } ] } + { + name: "Odie", + woofs: true + }, + { + name: "Garfield", + meows: false + } + ] + } }); }); - it('resolveType on Interface yields useful error', async () => { + it("resolveType on Interface yields useful error", async () => { const PetType = new GraphQLInterfaceType({ - name: 'Pet', + name: "Pet", resolveType(obj) { - return obj instanceof Dog ? DogType : - obj instanceof Cat ? CatType : - obj instanceof Human ? HumanType : - null; + return obj instanceof Dog + ? DogType + : obj instanceof Cat + ? CatType + : obj instanceof Human ? HumanType : null; }, fields: { name: { type: GraphQLString } @@ -188,47 +199,47 @@ describe('Execute: Handles execution of abstract types', () => { }); const HumanType = new GraphQLObjectType({ - name: 'Human', + name: "Human", fields: { - name: { type: GraphQLString }, + name: { type: GraphQLString } } }); const DogType = new GraphQLObjectType({ - name: 'Dog', - interfaces: [ PetType ], + name: "Dog", + interfaces: [PetType], fields: { name: { type: GraphQLString }, - woofs: { type: GraphQLBoolean }, + woofs: { type: GraphQLBoolean } } }); const CatType = new GraphQLObjectType({ - name: 'Cat', - interfaces: [ PetType ], + name: "Cat", + interfaces: [PetType], fields: { name: { type: GraphQLString }, - meows: { type: GraphQLBoolean }, + meows: { type: GraphQLBoolean } } }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { pets: { type: new GraphQLList(PetType), resolve() { return [ - new Dog('Odie', true), - new Cat('Garfield', false), - new Human('Jon') + new Dog("Odie", true), + new Cat("Garfield", false), + new Human("Jon") ]; } } } }), - types: [ CatType, DogType ] + types: [CatType, DogType] }); const query = `{ @@ -248,10 +259,14 @@ describe('Execute: Handles execution of abstract types', () => { expect(result).to.deep.equal({ data: { pets: [ - { name: 'Odie', - woofs: true }, - { name: 'Garfield', - meows: false }, + { + name: "Odie", + woofs: true + }, + { + name: "Garfield", + meows: false + }, null ] }, @@ -263,53 +278,53 @@ describe('Execute: Handles execution of abstract types', () => { }); }); - it('resolveType on Union yields useful error', async () => { + it("resolveType on Union yields useful error", async () => { const HumanType = new GraphQLObjectType({ - name: 'Human', + name: "Human", fields: { - name: { type: GraphQLString }, + name: { type: GraphQLString } } }); const DogType = new GraphQLObjectType({ - name: 'Dog', + name: "Dog", fields: { name: { type: GraphQLString }, - woofs: { type: GraphQLBoolean }, + woofs: { type: GraphQLBoolean } } }); const CatType = new GraphQLObjectType({ - name: 'Cat', + name: "Cat", fields: { name: { type: GraphQLString }, - meows: { type: GraphQLBoolean }, + meows: { type: GraphQLBoolean } } }); const PetType = new GraphQLUnionType({ - name: 'Pet', + name: "Pet", resolveType(obj) { - return obj instanceof Dog ? DogType : - obj instanceof Cat ? CatType : - obj instanceof Human ? HumanType : - null; + return obj instanceof Dog + ? DogType + : obj instanceof Cat + ? CatType + : obj instanceof Human ? HumanType : null; }, - types: [ DogType, CatType ] + types: [DogType, CatType] }); - const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { pets: { type: new GraphQLList(PetType), resolve() { return [ - new Dog('Odie', true), - new Cat('Garfield', false), - new Human('Jon') + new Dog("Odie", true), + new Cat("Garfield", false), + new Human("Jon") ]; } } @@ -335,10 +350,14 @@ describe('Execute: Handles execution of abstract types', () => { expect(result).to.deep.equal({ data: { pets: [ - { name: 'Odie', - woofs: true }, - { name: 'Garfield', - meows: false }, + { + name: "Odie", + woofs: true + }, + { + name: "Garfield", + meows: false + }, null ] }, @@ -349,5 +368,4 @@ describe('Execute: Handles execution of abstract types', () => { ] }); }); - }); diff --git a/src/execution/__tests__/directives-test.js b/src/execution/__tests__/directives-test.js index 814147c858..72b5c547bc 100644 --- a/src/execution/__tests__/directives-test.js +++ b/src/execution/__tests__/directives-test.js @@ -7,83 +7,80 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { execute } from '../execute'; -import { describe, it } from 'mocha'; -import { parse } from '../../language'; -import { - GraphQLSchema, - GraphQLObjectType, - GraphQLString, -} from '../../type'; - +import { expect } from "chai"; +import { execute } from "../execute"; +import { describe, it } from "mocha"; +import { parse } from "../../language"; +import { GraphQLSchema, GraphQLObjectType, GraphQLString } from "../../type"; const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'TestType', + name: "TestType", fields: { a: { type: GraphQLString }, - b: { type: GraphQLString }, + b: { type: GraphQLString } } - }), + }) }); const data = { - a() { return 'a'; }, - b() { return 'b'; } + a() { + return "a"; + }, + b() { + return "b"; + } }; async function executeTestQuery(doc) { return await execute(schema, parse(doc), data); } -describe('Execute: handles directives', () => { - describe('works without directives', () => { - it('basic query works', async () => { - expect( - await executeTestQuery('{ a, b }') - ).to.deep.equal({ - data: { a: 'a', b: 'b' } +describe("Execute: handles directives", () => { + describe("works without directives", () => { + it("basic query works", async () => { + expect(await executeTestQuery("{ a, b }")).to.deep.equal({ + data: { a: "a", b: "b" } }); }); }); - describe('works on scalars', () => { - it('if true includes scalar', async () => { + describe("works on scalars", () => { + it("if true includes scalar", async () => { return expect( - await executeTestQuery('{ a, b @include(if: true) }') + await executeTestQuery("{ a, b @include(if: true) }") ).to.deep.equal({ - data: { a: 'a', b: 'b' } + data: { a: "a", b: "b" } }); }); - it('if false omits on scalar', async () => { + it("if false omits on scalar", async () => { return expect( - await executeTestQuery('{ a, b @include(if: false) }') + await executeTestQuery("{ a, b @include(if: false) }") ).to.deep.equal({ - data: { a: 'a' } + data: { a: "a" } }); }); - it('unless false includes scalar', async () => { + it("unless false includes scalar", async () => { return expect( - await executeTestQuery('{ a, b @skip(if: false) }') + await executeTestQuery("{ a, b @skip(if: false) }") ).to.deep.equal({ - data: { a: 'a', b: 'b' } + data: { a: "a", b: "b" } }); }); - it('unless true omits scalar', async () => { + it("unless true omits scalar", async () => { return expect( - await executeTestQuery('{ a, b @skip(if: true) }') + await executeTestQuery("{ a, b @skip(if: true) }") ).to.deep.equal({ - data: { a: 'a' } + data: { a: "a" } }); }); }); - describe('works on fragment spreads', () => { - it('if false omits fragment spread', async () => { + describe("works on fragment spreads", () => { + it("if false omits fragment spread", async () => { const q = ` query Q { a @@ -94,11 +91,11 @@ describe('Execute: handles directives', () => { } `; return expect(await executeTestQuery(q)).to.deep.equal({ - data: { a: 'a' } + data: { a: "a" } }); }); - it('if true includes fragment spread', async () => { + it("if true includes fragment spread", async () => { const q = ` query Q { a @@ -109,11 +106,11 @@ describe('Execute: handles directives', () => { } `; return expect(await executeTestQuery(q)).to.deep.equal({ - data: { a: 'a', b: 'b' } + data: { a: "a", b: "b" } }); }); - it('unless false includes fragment spread', async () => { + it("unless false includes fragment spread", async () => { const q = ` query Q { a @@ -124,11 +121,11 @@ describe('Execute: handles directives', () => { } `; return expect(await executeTestQuery(q)).to.deep.equal({ - data: { a: 'a', b: 'b' } + data: { a: "a", b: "b" } }); }); - it('unless true omits fragment spread', async () => { + it("unless true omits fragment spread", async () => { const q = ` query Q { a @@ -139,13 +136,13 @@ describe('Execute: handles directives', () => { } `; return expect(await executeTestQuery(q)).to.deep.equal({ - data: { a: 'a' } + data: { a: "a" } }); }); }); - describe('works on inline fragment', () => { - it('if false omits inline fragment', async () => { + describe("works on inline fragment", () => { + it("if false omits inline fragment", async () => { const q = ` query Q { a @@ -158,11 +155,11 @@ describe('Execute: handles directives', () => { } `; return expect(await executeTestQuery(q)).to.deep.equal({ - data: { a: 'a' } + data: { a: "a" } }); }); - it('if true includes inline fragment', async () => { + it("if true includes inline fragment", async () => { const q = ` query Q { a @@ -175,10 +172,10 @@ describe('Execute: handles directives', () => { } `; return expect(await executeTestQuery(q)).to.deep.equal({ - data: { a: 'a', b: 'b' } + data: { a: "a", b: "b" } }); }); - it('unless false includes inline fragment', async () => { + it("unless false includes inline fragment", async () => { const q = ` query Q { a @@ -191,10 +188,10 @@ describe('Execute: handles directives', () => { } `; return expect(await executeTestQuery(q)).to.deep.equal({ - data: { a: 'a', b: 'b' } + data: { a: "a", b: "b" } }); }); - it('unless true includes inline fragment', async () => { + it("unless true includes inline fragment", async () => { const q = ` query Q { a @@ -207,13 +204,13 @@ describe('Execute: handles directives', () => { } `; return expect(await executeTestQuery(q)).to.deep.equal({ - data: { a: 'a' } + data: { a: "a" } }); }); }); - describe('works on anonymous inline fragment', () => { - it('if false omits anonymous inline fragment', async () => { + describe("works on anonymous inline fragment", () => { + it("if false omits anonymous inline fragment", async () => { const q = ` query Q { a @@ -223,11 +220,11 @@ describe('Execute: handles directives', () => { } `; return expect(await executeTestQuery(q)).to.deep.equal({ - data: { a: 'a' } + data: { a: "a" } }); }); - it('if true includes anonymous inline fragment', async () => { + it("if true includes anonymous inline fragment", async () => { const q = ` query Q { a @@ -237,10 +234,10 @@ describe('Execute: handles directives', () => { } `; return expect(await executeTestQuery(q)).to.deep.equal({ - data: { a: 'a', b: 'b' } + data: { a: "a", b: "b" } }); }); - it('unless false includes anonymous inline fragment', async () => { + it("unless false includes anonymous inline fragment", async () => { const q = ` query Q { a @@ -250,10 +247,10 @@ describe('Execute: handles directives', () => { } `; return expect(await executeTestQuery(q)).to.deep.equal({ - data: { a: 'a', b: 'b' } + data: { a: "a", b: "b" } }); }); - it('unless true includes anonymous inline fragment', async () => { + it("unless true includes anonymous inline fragment", async () => { const q = ` query Q { a @@ -263,33 +260,33 @@ describe('Execute: handles directives', () => { } `; return expect(await executeTestQuery(q)).to.deep.equal({ - data: { a: 'a' } + data: { a: "a" } }); }); }); - describe('works with skip and include directives', () => { - it('include and no skip', async () => { + describe("works with skip and include directives", () => { + it("include and no skip", async () => { return expect( - await executeTestQuery('{ a, b @include(if: true) @skip(if: false) }') + await executeTestQuery("{ a, b @include(if: true) @skip(if: false) }") ).to.deep.equal({ - data: { a: 'a', b: 'b' } + data: { a: "a", b: "b" } }); }); - it('include and skip', async () => { + it("include and skip", async () => { return expect( - await executeTestQuery('{ a, b @include(if: true) @skip(if: true) }') + await executeTestQuery("{ a, b @include(if: true) @skip(if: true) }") ).to.deep.equal({ - data: { a: 'a' } + data: { a: "a" } }); }); - it('no include or skip', async () => { + it("no include or skip", async () => { return expect( - await executeTestQuery('{ a, b @include(if: false) @skip(if: false) }') + await executeTestQuery("{ a, b @include(if: false) @skip(if: false) }") ).to.deep.equal({ - data: { a: 'a' } + data: { a: "a" } }); }); }); diff --git a/src/execution/__tests__/executor-test.js b/src/execution/__tests__/executor-test.js index e46d57ac0b..07df591dd9 100644 --- a/src/execution/__tests__/executor-test.js +++ b/src/execution/__tests__/executor-test.js @@ -7,41 +7,63 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { execute } from '../execute'; -import { formatError } from '../../error'; -import { parse } from '../../language'; +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { execute } from "../execute"; +import { formatError } from "../../error"; +import { parse } from "../../language"; import { GraphQLSchema, GraphQLObjectType, GraphQLList, GraphQLBoolean, GraphQLInt, - GraphQLString, -} from '../../type'; + GraphQLString +} from "../../type"; -describe('Execute: Handles basic execution tasks', () => { - it('executes arbitrary code', async () => { +describe("Execute: Handles basic execution tasks", () => { + it("executes arbitrary code", async () => { const data = { - a() { return 'Apple'; }, - b() { return 'Banana'; }, - c() { return 'Cookie'; }, - d() { return 'Donut'; }, - e() { return 'Egg'; }, - f: 'Fish', + a() { + return "Apple"; + }, + b() { + return "Banana"; + }, + c() { + return "Cookie"; + }, + d() { + return "Donut"; + }, + e() { + return "Egg"; + }, + f: "Fish", pic(size) { - return 'Pic of size: ' + (size || 50); + return "Pic of size: " + (size || 50); + }, + deep() { + return deepData; }, - deep() { return deepData; }, - promise() { return promiseData(); } + promise() { + return promiseData(); + } }; const deepData = { - a() { return 'Already Been Done'; }, - b() { return 'Boring'; }, - c() { return [ 'Contrived', undefined, 'Confusing' ]; }, - deeper() { return [ data, null, data ]; } + a() { + return "Already Been Done"; + }, + b() { + return "Boring"; + }, + c() { + return ["Contrived", undefined, "Confusing"]; + }, + deeper() { + return [data, null, data]; + } }; function promiseData() { @@ -85,26 +107,29 @@ describe('Execute: Handles basic execution tasks', () => { const ast = parse(doc); const expected = { data: { - a: 'Apple', - b: 'Banana', - x: 'Cookie', - d: 'Donut', - e: 'Egg', - f: 'Fish', - pic: 'Pic of size: 100', - promise: { a: 'Apple' }, + a: "Apple", + b: "Banana", + x: "Cookie", + d: "Donut", + e: "Egg", + f: "Fish", + pic: "Pic of size: 100", + promise: { a: "Apple" }, deep: { - a: 'Already Been Done', - b: 'Boring', - c: [ 'Contrived', null, 'Confusing' ], + a: "Already Been Done", + b: "Boring", + c: ["Contrived", null, "Confusing"], deeper: [ - { a: 'Apple', b: 'Banana' }, + { a: "Apple", b: "Banana" }, null, - { a: 'Apple', b: 'Banana' } ] } } + { a: "Apple", b: "Banana" } + ] + } + } }; const DataType = new GraphQLObjectType({ - name: 'DataType', + name: "DataType", fields: () => ({ a: { type: GraphQLString }, b: { type: GraphQLString }, @@ -118,17 +143,17 @@ describe('Execute: Handles basic execution tasks', () => { resolve: (obj, { size }) => obj.pic(size) }, deep: { type: DeepDataType }, - promise: { type: DataType }, + promise: { type: DataType } }) }); const DeepDataType = new GraphQLObjectType({ - name: 'DeepDataType', + name: "DeepDataType", fields: { a: { type: GraphQLString }, b: { type: GraphQLString }, c: { type: new GraphQLList(GraphQLString) }, - deeper: { type: new GraphQLList(DataType) }, + deeper: { type: new GraphQLList(DataType) } } }); @@ -137,11 +162,11 @@ describe('Execute: Handles basic execution tasks', () => { }); expect( - await execute(schema, ast, data, null, { size: 100 }, 'Example') + await execute(schema, ast, data, null, { size: 100 }, "Example") ).to.deep.equal(expected); }); - it('merges parallel fragments', async () => { + it("merges parallel fragments", async () => { const ast = parse(` { a, ...FragOne, ...FragTwo } @@ -157,44 +182,45 @@ describe('Execute: Handles basic execution tasks', () => { `); const Type = new GraphQLObjectType({ - name: 'Type', + name: "Type", fields: () => ({ - a: { type: GraphQLString, resolve: () => 'Apple' }, - b: { type: GraphQLString, resolve: () => 'Banana' }, - c: { type: GraphQLString, resolve: () => 'Cherry' }, - deep: { type: Type, resolve: () => ({}) }, + a: { type: GraphQLString, resolve: () => "Apple" }, + b: { type: GraphQLString, resolve: () => "Banana" }, + c: { type: GraphQLString, resolve: () => "Cherry" }, + deep: { type: Type, resolve: () => ({}) } }) }); const schema = new GraphQLSchema({ query: Type }); - expect( - await execute(schema, ast) - ).to.deep.equal({ + expect(await execute(schema, ast)).to.deep.equal({ data: { - a: 'Apple', - b: 'Banana', - c: 'Cherry', + a: "Apple", + b: "Banana", + c: "Cherry", deep: { - b: 'Banana', - c: 'Cherry', + b: "Banana", + c: "Cherry", deeper: { - b: 'Banana', - c: 'Cherry' } } } + b: "Banana", + c: "Cherry" + } + } + } }); }); - it('threads root value context correctly', async () => { - const doc = 'query Example { a }'; + it("threads root value context correctly", async () => { + const doc = "query Example { a }"; const data = { - contextThing: 'thing', + contextThing: "thing" }; let resolvedRootValue; const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Type', + name: "Type", fields: { a: { type: GraphQLString, @@ -208,10 +234,10 @@ describe('Execute: Handles basic execution tasks', () => { await execute(schema, parse(doc), data); - expect(resolvedRootValue.contextThing).to.equal('thing'); + expect(resolvedRootValue.contextThing).to.equal("thing"); }); - it('correctly threads arguments', async () => { + it("correctly threads arguments", async () => { const doc = ` query Example { b(numArg: 123, stringArg: "foo") @@ -222,7 +248,7 @@ describe('Execute: Handles basic execution tasks', () => { const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Type', + name: "Type", fields: { b: { args: { @@ -241,10 +267,10 @@ describe('Execute: Handles basic execution tasks', () => { await execute(schema, parse(doc)); expect(resolvedArgs.numArg).to.equal(123); - expect(resolvedArgs.stringArg).to.equal('foo'); + expect(resolvedArgs.stringArg).to.equal("foo"); }); - it('nulls out error subtrees', async () => { + it("nulls out error subtrees", async () => { const doc = `{ sync syncError @@ -262,62 +288,62 @@ describe('Execute: Handles basic execution tasks', () => { const data = { sync() { - return 'sync'; + return "sync"; }, syncError() { - throw new Error('Error getting syncError'); + throw new Error("Error getting syncError"); }, syncRawError() { /* eslint-disable */ - throw 'Error getting syncRawError'; + throw "Error getting syncRawError"; /* eslint-enable */ }, syncReturnError() { - return new Error('Error getting syncReturnError'); + return new Error("Error getting syncReturnError"); }, syncReturnErrorList() { return [ - 'sync0', - new Error('Error getting syncReturnErrorList1'), - 'sync2', - new Error('Error getting syncReturnErrorList3') + "sync0", + new Error("Error getting syncReturnErrorList1"), + "sync2", + new Error("Error getting syncReturnErrorList3") ]; }, async() { - return new Promise(resolve => resolve('async')); + return new Promise(resolve => resolve("async")); }, asyncReject() { return new Promise((_, reject) => - reject(new Error('Error getting asyncReject')) + reject(new Error("Error getting asyncReject")) ); }, asyncRawReject() { - return Promise.reject('Error getting asyncRawReject'); + return Promise.reject("Error getting asyncRawReject"); }, asyncEmptyReject() { return Promise.reject(); }, asyncError() { return new Promise(() => { - throw new Error('Error getting asyncError'); + throw new Error("Error getting asyncError"); }); }, asyncRawError() { return new Promise(() => { /* eslint-disable */ - throw 'Error getting asyncRawError'; + throw "Error getting asyncRawError"; /* eslint-enable */ }); }, asyncReturnError() { - return Promise.resolve(new Error('Error getting asyncReturnError')); - }, + return Promise.resolve(new Error("Error getting asyncReturnError")); + } }; const ast = parse(doc); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Type', + name: "Type", fields: { sync: { type: GraphQLString }, syncError: { type: GraphQLString }, @@ -330,7 +356,7 @@ describe('Execute: Handles basic execution tasks', () => { asyncEmptyReject: { type: GraphQLString }, asyncError: { type: GraphQLString }, asyncRawError: { type: GraphQLString }, - asyncReturnError: { type: GraphQLString }, + asyncReturnError: { type: GraphQLString } } }) }); @@ -338,235 +364,255 @@ describe('Execute: Handles basic execution tasks', () => { const result = await execute(schema, ast, data); expect(result.data).to.deep.equal({ - sync: 'sync', + sync: "sync", syncError: null, syncRawError: null, syncReturnError: null, - syncReturnErrorList: [ 'sync0', null, 'sync2', null ], - async: 'async', + syncReturnErrorList: ["sync0", null, "sync2", null], + async: "async", asyncReject: null, asyncRawReject: null, asyncEmptyReject: null, asyncError: null, asyncRawError: null, - asyncReturnError: null, + asyncReturnError: null }); expect(result.errors && result.errors.map(formatError)).to.deep.equal([ - { message: 'Error getting syncError', - locations: [ { line: 3, column: 7 } ] }, - { message: 'Error getting syncRawError', - locations: [ { line: 4, column: 7 } ] }, - { message: 'Error getting syncReturnError', - locations: [ { line: 5, column: 7 } ] }, - { message: 'Error getting syncReturnErrorList1', - locations: [ { line: 6, column: 7 } ] }, - { message: 'Error getting syncReturnErrorList3', - locations: [ { line: 6, column: 7 } ] }, - { message: 'Error getting asyncReturnError', - locations: [ { line: 13, column: 7 } ] }, - { message: 'Error getting asyncReject', - locations: [ { line: 8, column: 7 } ] }, - { message: 'Error getting asyncRawReject', - locations: [ { line: 9, column: 7 } ] }, - { message: 'An unknown error occurred.', - locations: [ { line: 10, column: 7 } ] }, - { message: 'Error getting asyncError', - locations: [ { line: 11, column: 7 } ] }, - { message: 'Error getting asyncRawError', - locations: [ { line: 12, column: 7 } ] }, + { + message: "Error getting syncError", + locations: [{ line: 3, column: 7 }] + }, + { + message: "Error getting syncRawError", + locations: [{ line: 4, column: 7 }] + }, + { + message: "Error getting syncReturnError", + locations: [{ line: 5, column: 7 }] + }, + { + message: "Error getting syncReturnErrorList1", + locations: [{ line: 6, column: 7 }] + }, + { + message: "Error getting syncReturnErrorList3", + locations: [{ line: 6, column: 7 }] + }, + { + message: "Error getting asyncReturnError", + locations: [{ line: 13, column: 7 }] + }, + { + message: "Error getting asyncReject", + locations: [{ line: 8, column: 7 }] + }, + { + message: "Error getting asyncRawReject", + locations: [{ line: 9, column: 7 }] + }, + { + message: "An unknown error occurred.", + locations: [{ line: 10, column: 7 }] + }, + { + message: "Error getting asyncError", + locations: [{ line: 11, column: 7 }] + }, + { + message: "Error getting asyncRawError", + locations: [{ line: 12, column: 7 }] + } ]); }); - it('uses the inline operation if no operation name is provided', async () => { - const doc = '{ a }'; - const data = { a: 'b' }; + it("uses the inline operation if no operation name is provided", async () => { + const doc = "{ a }"; + const data = { a: "b" }; const ast = parse(doc); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Type', + name: "Type", fields: { - a: { type: GraphQLString }, + a: { type: GraphQLString } } }) }); const result = await execute(schema, ast, data); - expect(result).to.deep.equal({ data: { a: 'b' } }); + expect(result).to.deep.equal({ data: { a: "b" } }); }); - it('uses the only operation if no operation name is provided', async () => { - const doc = 'query Example { a }'; - const data = { a: 'b' }; + it("uses the only operation if no operation name is provided", async () => { + const doc = "query Example { a }"; + const data = { a: "b" }; const ast = parse(doc); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Type', + name: "Type", fields: { - a: { type: GraphQLString }, + a: { type: GraphQLString } } }) }); const result = await execute(schema, ast, data); - expect(result).to.deep.equal({ data: { a: 'b' } }); + expect(result).to.deep.equal({ data: { a: "b" } }); }); - it('uses the named operation if operation name is provided', async () => { - const doc = 'query Example { first: a } query OtherExample { second: a }'; - const data = { a: 'b' }; + it("uses the named operation if operation name is provided", async () => { + const doc = "query Example { first: a } query OtherExample { second: a }"; + const data = { a: "b" }; const ast = parse(doc); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Type', + name: "Type", fields: { - a: { type: GraphQLString }, + a: { type: GraphQLString } } }) }); - const result = await execute(schema, ast, data, null, null, 'OtherExample'); + const result = await execute(schema, ast, data, null, null, "OtherExample"); - expect(result).to.deep.equal({ data: { second: 'b' } }); + expect(result).to.deep.equal({ data: { second: "b" } }); }); - it('throws if no operation is provided', () => { - const doc = 'fragment Example on Type { a }'; - const data = { a: 'b' }; + it("throws if no operation is provided", () => { + const doc = "fragment Example on Type { a }"; + const data = { a: "b" }; const ast = parse(doc); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Type', + name: "Type", fields: { - a: { type: GraphQLString }, + a: { type: GraphQLString } } }) }); expect(() => execute(schema, ast, data)).to.throw( - 'Must provide an operation.' + "Must provide an operation." ); }); - it('throws if no operation name is provided with multiple operations', () => { - const doc = 'query Example { a } query OtherExample { a }'; - const data = { a: 'b' }; + it("throws if no operation name is provided with multiple operations", () => { + const doc = "query Example { a } query OtherExample { a }"; + const data = { a: "b" }; const ast = parse(doc); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Type', + name: "Type", fields: { - a: { type: GraphQLString }, + a: { type: GraphQLString } } }) }); expect(() => execute(schema, ast, data)).to.throw( - 'Must provide operation name if query contains multiple operations.' + "Must provide operation name if query contains multiple operations." ); }); - it('throws if unknown operation name is provided', () => { - const doc = 'query Example { a } query OtherExample { a }'; - const data = { a: 'b' }; + it("throws if unknown operation name is provided", () => { + const doc = "query Example { a } query OtherExample { a }"; + const data = { a: "b" }; const ast = parse(doc); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Type', + name: "Type", fields: { - a: { type: GraphQLString }, + a: { type: GraphQLString } } }) }); expect(() => - execute(schema, ast, data, null, null, 'UnknownExample') - ).to.throw( - 'Unknown operation named "UnknownExample".' - ); + execute(schema, ast, data, null, null, "UnknownExample") + ).to.throw('Unknown operation named "UnknownExample".'); }); - it('uses the query schema for queries', async () => { - const doc = 'query Q { a } mutation M { c } subscription S { a }'; - const data = { a: 'b', c: 'd' }; + it("uses the query schema for queries", async () => { + const doc = "query Q { a } mutation M { c } subscription S { a }"; + const data = { a: "b", c: "d" }; const ast = parse(doc); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Q', + name: "Q", fields: { - a: { type: GraphQLString }, + a: { type: GraphQLString } } }), mutation: new GraphQLObjectType({ - name: 'M', + name: "M", fields: { - c: { type: GraphQLString }, + c: { type: GraphQLString } } }), subscription: new GraphQLObjectType({ - name: 'S', + name: "S", fields: { - a: { type: GraphQLString }, + a: { type: GraphQLString } } }) }); - const queryResult = await execute(schema, ast, data, null, {}, 'Q'); + const queryResult = await execute(schema, ast, data, null, {}, "Q"); - expect(queryResult).to.deep.equal({ data: { a: 'b' } }); + expect(queryResult).to.deep.equal({ data: { a: "b" } }); }); - it('uses the mutation schema for mutations', async () => { - const doc = 'query Q { a } mutation M { c }'; - const data = { a: 'b', c: 'd' }; + it("uses the mutation schema for mutations", async () => { + const doc = "query Q { a } mutation M { c }"; + const data = { a: "b", c: "d" }; const ast = parse(doc); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Q', + name: "Q", fields: { - a: { type: GraphQLString }, + a: { type: GraphQLString } } }), mutation: new GraphQLObjectType({ - name: 'M', + name: "M", fields: { - c: { type: GraphQLString }, + c: { type: GraphQLString } } }) }); - const mutationResult = await execute(schema, ast, data, null, {}, 'M'); + const mutationResult = await execute(schema, ast, data, null, {}, "M"); - expect(mutationResult).to.deep.equal({ data: { c: 'd' } }); + expect(mutationResult).to.deep.equal({ data: { c: "d" } }); }); - it('uses the subscription schema for subscriptions', async () => { - const doc = 'query Q { a } subscription S { a }'; - const data = { a: 'b', c: 'd' }; + it("uses the subscription schema for subscriptions", async () => { + const doc = "query Q { a } subscription S { a }"; + const data = { a: "b", c: "d" }; const ast = parse(doc); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Q', + name: "Q", fields: { - a: { type: GraphQLString }, + a: { type: GraphQLString } } }), subscription: new GraphQLObjectType({ - name: 'S', + name: "S", fields: { - a: { type: GraphQLString }, + a: { type: GraphQLString } } }) }); - const subscriptionResult = await execute(schema, ast, data, null, {}, 'S'); + const subscriptionResult = await execute(schema, ast, data, null, {}, "S"); - expect(subscriptionResult).to.deep.equal({ data: { a: 'b' } }); + expect(subscriptionResult).to.deep.equal({ data: { a: "b" } }); }); - it('correct field ordering despite execution order', async () => { + it("correct field ordering despite execution order", async () => { const doc = `{ a, b, @@ -577,32 +623,32 @@ describe('Execute: Handles basic execution tasks', () => { const data = { a() { - return 'a'; + return "a"; }, b() { - return new Promise(resolve => resolve('b')); + return new Promise(resolve => resolve("b")); }, c() { - return 'c'; + return "c"; }, d() { - return new Promise(resolve => resolve('d')); + return new Promise(resolve => resolve("d")); }, e() { - return 'e'; - }, + return "e"; + } }; const ast = parse(doc); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Type', + name: "Type", fields: { a: { type: GraphQLString }, b: { type: GraphQLString }, c: { type: GraphQLString }, d: { type: GraphQLString }, - e: { type: GraphQLString }, + e: { type: GraphQLString } } }) }); @@ -611,18 +657,18 @@ describe('Execute: Handles basic execution tasks', () => { expect(result).to.deep.equal({ data: { - a: 'a', - b: 'b', - c: 'c', - d: 'd', - e: 'e', + a: "a", + b: "b", + c: "c", + d: "d", + e: "e" } }); - expect(Object.keys(result.data)).to.deep.equal([ 'a', 'b', 'c', 'd', 'e' ]); + expect(Object.keys(result.data)).to.deep.equal(["a", "b", "c", "d", "e"]); }); - it('Avoids recursion', async () => { + it("Avoids recursion", async () => { const doc = ` query Q { a @@ -635,54 +681,53 @@ describe('Execute: Handles basic execution tasks', () => { ...Frag } `; - const data = { a: 'b' }; + const data = { a: "b" }; const ast = parse(doc); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Type', + name: "Type", fields: { - a: { type: GraphQLString }, + a: { type: GraphQLString } } - }), + }) }); - const queryResult = await execute(schema, ast, data, null, {}, 'Q'); + const queryResult = await execute(schema, ast, data, null, {}, "Q"); - expect(queryResult).to.deep.equal({ data: { a: 'b' } }); + expect(queryResult).to.deep.equal({ data: { a: "b" } }); }); - it('does not include illegal fields in output', async () => { + it("does not include illegal fields in output", async () => { const doc = `mutation M { thisIsIllegalDontIncludeMe }`; const ast = parse(doc); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Q', + name: "Q", fields: { - a: { type: GraphQLString }, + a: { type: GraphQLString } } }), mutation: new GraphQLObjectType({ - name: 'M', + name: "M", fields: { - c: { type: GraphQLString }, + c: { type: GraphQLString } } - }), + }) }); const mutationResult = await execute(schema, ast); expect(mutationResult).to.deep.equal({ - data: { - } + data: {} }); }); - it('does not include arguments that were not set', async () => { + it("does not include arguments that were not set", async () => { const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Type', + name: "Type", fields: { field: { type: GraphQLString, @@ -692,14 +737,14 @@ describe('Execute: Handles basic execution tasks', () => { b: { type: GraphQLBoolean }, c: { type: GraphQLBoolean }, d: { type: GraphQLInt }, - e: { type: GraphQLInt }, - }, + e: { type: GraphQLInt } + } } } }) }); - const query = parse('{ field(a: true, c: false, e: 0) }'); + const query = parse("{ field(a: true, c: false, e: 0) }"); const result = await execute(schema, query); expect(result).to.deep.equal({ @@ -709,7 +754,7 @@ describe('Execute: Handles basic execution tasks', () => { }); }); - it('fails when an isTypeOf check is not met', async () => { + it("fails when an isTypeOf check is not met", async () => { class Special { constructor(value) { this.value = value; @@ -723,7 +768,7 @@ describe('Execute: Handles basic execution tasks', () => { } const SpecialType = new GraphQLObjectType({ - name: 'SpecialType', + name: "SpecialType", isTypeOf(obj) { return obj instanceof Special; }, @@ -734,7 +779,7 @@ describe('Execute: Handles basic execution tasks', () => { const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { specials: { type: new GraphQLList(SpecialType), @@ -744,27 +789,26 @@ describe('Execute: Handles basic execution tasks', () => { }) }); - const query = parse('{ specials { value } }'); + const query = parse("{ specials { value } }"); const value = { - specials: [ new Special('foo'), new NotSpecial('bar') ] + specials: [new Special("foo"), new NotSpecial("bar")] }; const result = await execute(schema, query, value); expect(result.data).to.deep.equal({ - specials: [ - { value: 'foo' }, - null - ] + specials: [{ value: "foo" }, null] }); expect(result.errors).to.have.lengthOf(1); expect(result.errors).to.containSubset([ - { message: + { + message: 'Expected value of type "SpecialType" but got: [object Object].', - locations: [ { line: 1, column: 3 } ] } + locations: [{ line: 1, column: 3 }] + } ]); }); - it('fails to execute a query containing a type definition', async () => { + it("fails to execute a query containing a type definition", async () => { const query = parse(` { foo } @@ -773,7 +817,7 @@ describe('Execute: Handles basic execution tasks', () => { const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { foo: { type: GraphQLString } } @@ -789,9 +833,8 @@ describe('Execute: Handles basic execution tasks', () => { expect(caughtError).to.deep.equal( new Error( - 'GraphQL cannot execute a request containing a ObjectTypeDefinition.' + "GraphQL cannot execute a request containing a ObjectTypeDefinition." ) ); }); - }); diff --git a/src/execution/__tests__/lists-test.js b/src/execution/__tests__/lists-test.js index 31c6a364ee..c6c91a22bd 100644 --- a/src/execution/__tests__/lists-test.js +++ b/src/execution/__tests__/lists-test.js @@ -10,18 +10,18 @@ // 80+ char lines are useful in describe/it, so ignore in this file. /* eslint-disable max-len */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { formatError } from '../../error'; -import { execute } from '../execute'; -import { parse } from '../../language'; +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { formatError } from "../../error"; +import { execute } from "../execute"; +import { parse } from "../../language"; import { GraphQLSchema, GraphQLObjectType, GraphQLInt, GraphQLList, GraphQLNonNull -} from '../../type'; +} from "../../type"; // resolved() is shorthand for Promise.resolve() const resolved = Promise.resolve.bind(Promise); @@ -40,16 +40,16 @@ function check(testType, testData, expected) { const data = { test: testData }; const dataType = new GraphQLObjectType({ - name: 'DataType', + name: "DataType", fields: () => ({ test: { type: testType }, - nest: { type: dataType, resolve: () => data }, + nest: { type: dataType, resolve: () => data } }) }); const schema = new GraphQLSchema({ query: dataType }); - const ast = parse('{ nest { test } }'); + const ast = parse("{ nest { test } }"); const response = await execute(schema, ast, data); @@ -67,349 +67,426 @@ function check(testType, testData, expected) { }; } -describe('Execute: Handles list nullability', () => { - - describe('[T]', () => { +describe("Execute: Handles list nullability", () => { + describe("[T]", () => { const type = new GraphQLList(GraphQLInt); - describe('Array', () => { - - it('Contains values', check(type, - [ 1, 2 ], - { data: { nest: { test: [ 1, 2 ] } } } - )); + describe("Array", () => { + it( + "Contains values", + check(type, [1, 2], { data: { nest: { test: [1, 2] } } }) + ); - it('Contains null', check(type, - [ 1, null, 2 ], - { data: { nest: { test: [ 1, null, 2 ] } } } - )); - - it('Returns null', check(type, - null, - { data: { nest: { test: null } } } - )); + it( + "Contains null", + check(type, [1, null, 2], { data: { nest: { test: [1, null, 2] } } }) + ); + it("Returns null", check(type, null, { data: { nest: { test: null } } })); }); - describe('Promise>', () => { - - it('Contains values', check(type, - resolved([ 1, 2 ]), - { data: { nest: { test: [ 1, 2 ] } } } - )); - - it('Contains null', check(type, - resolved([ 1, null, 2 ]), - { data: { nest: { test: [ 1, null, 2 ] } } } - )); - - - it('Returns null', check(type, - resolved(null), - { data: { nest: { test: null } } } - )); - - it('Rejected', check(type, - () => rejected(new Error('bad')), - { data: { nest: { test: null } }, + describe("Promise>", () => { + it( + "Contains values", + check(type, resolved([1, 2]), { data: { nest: { test: [1, 2] } } }) + ); + + it( + "Contains null", + check(type, resolved([1, null, 2]), { + data: { nest: { test: [1, null, 2] } } + }) + ); + + it( + "Returns null", + check(type, resolved(null), { data: { nest: { test: null } } }) + ); + + it( + "Rejected", + check(type, () => rejected(new Error("bad")), { + data: { nest: { test: null } }, errors: [ - { message: 'bad', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - + { + message: "bad", + locations: [{ line: 1, column: 10 }] + } + ] + }) + ); }); - describe('Array>', () => { - - it('Contains values', check(type, - [ resolved(1), resolved(2) ], - { data: { nest: { test: [ 1, 2 ] } } } - )); - - it('Contains null', check(type, - [ resolved(1), resolved(null), resolved(2) ], - { data: { nest: { test: [ 1, null, 2 ] } } } - )); - - it('Contains reject', check(type, - () => [ resolved(1), rejected(new Error('bad')), resolved(2) ], - { data: { nest: { test: [ 1, null, 2 ] } }, - errors: [ - { message: 'bad', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - + describe("Array>", () => { + it( + "Contains values", + check(type, [resolved(1), resolved(2)], { + data: { nest: { test: [1, 2] } } + }) + ); + + it( + "Contains null", + check(type, [resolved(1), resolved(null), resolved(2)], { + data: { nest: { test: [1, null, 2] } } + }) + ); + + it( + "Contains reject", + check( + type, + () => [resolved(1), rejected(new Error("bad")), resolved(2)], + { + data: { nest: { test: [1, null, 2] } }, + errors: [ + { + message: "bad", + locations: [{ line: 1, column: 10 }] + } + ] + } + ) + ); }); - }); - describe('[T]!', () => { + describe("[T]!", () => { const type = new GraphQLNonNull(new GraphQLList(GraphQLInt)); - describe('Array', () => { - - it('Contains values', check(type, - [ 1, 2 ], - { data: { nest: { test: [ 1, 2 ] } } } - )); - - it('Contains null', check(type, - [ 1, null, 2 ], - { data: { nest: { test: [ 1, null, 2 ] } } } - )); - - it('Returns null', check(type, - null, - { data: { nest: null }, + describe("Array", () => { + it( + "Contains values", + check(type, [1, 2], { data: { nest: { test: [1, 2] } } }) + ); + + it( + "Contains null", + check(type, [1, null, 2], { data: { nest: { test: [1, null, 2] } } }) + ); + + it( + "Returns null", + check(type, null, { + data: { nest: null }, errors: [ - { message: 'Cannot return null for non-nullable field DataType.test.', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - + { + message: + "Cannot return null for non-nullable field DataType.test.", + locations: [{ line: 1, column: 10 }] + } + ] + }) + ); }); - describe('Promise>', () => { - - it('Contains values', check(type, - resolved([ 1, 2 ]), - { data: { nest: { test: [ 1, 2 ] } } } - )); - - it('Contains null', check(type, - resolved([ 1, null, 2 ]), - { data: { nest: { test: [ 1, null, 2 ] } } } - )); - - it('Returns null', check(type, - resolved(null), - { data: { nest: null }, + describe("Promise>", () => { + it( + "Contains values", + check(type, resolved([1, 2]), { data: { nest: { test: [1, 2] } } }) + ); + + it( + "Contains null", + check(type, resolved([1, null, 2]), { + data: { nest: { test: [1, null, 2] } } + }) + ); + + it( + "Returns null", + check(type, resolved(null), { + data: { nest: null }, errors: [ - { message: 'Cannot return null for non-nullable field DataType.test.', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - - it('Rejected', check(type, - () => rejected(new Error('bad')), - { data: { nest: null }, + { + message: + "Cannot return null for non-nullable field DataType.test.", + locations: [{ line: 1, column: 10 }] + } + ] + }) + ); + + it( + "Rejected", + check(type, () => rejected(new Error("bad")), { + data: { nest: null }, errors: [ - { message: 'bad', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - + { + message: "bad", + locations: [{ line: 1, column: 10 }] + } + ] + }) + ); }); - describe('Array>', () => { - - it('Contains values', check(type, - [ resolved(1), resolved(2) ], - { data: { nest: { test: [ 1, 2 ] } } } - )); - - it('Contains null', check(type, - [ resolved(1), resolved(null), resolved(2) ], - { data: { nest: { test: [ 1, null, 2 ] } } } - )); - - it('Contains reject', check(type, - () => [ resolved(1), rejected(new Error('bad')), resolved(2) ], - { data: { nest: { test: [ 1, null, 2 ] } }, - errors: [ - { message: 'bad', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - + describe("Array>", () => { + it( + "Contains values", + check(type, [resolved(1), resolved(2)], { + data: { nest: { test: [1, 2] } } + }) + ); + + it( + "Contains null", + check(type, [resolved(1), resolved(null), resolved(2)], { + data: { nest: { test: [1, null, 2] } } + }) + ); + + it( + "Contains reject", + check( + type, + () => [resolved(1), rejected(new Error("bad")), resolved(2)], + { + data: { nest: { test: [1, null, 2] } }, + errors: [ + { + message: "bad", + locations: [{ line: 1, column: 10 }] + } + ] + } + ) + ); }); - }); - describe('[T!]', () => { + describe("[T!]", () => { const type = new GraphQLList(new GraphQLNonNull(GraphQLInt)); - describe('Array', () => { - - it('Contains values', check(type, - [ 1, 2 ], - { data: { nest: { test: [ 1, 2 ] } } } - )); + describe("Array", () => { + it( + "Contains values", + check(type, [1, 2], { data: { nest: { test: [1, 2] } } }) + ); - it('Contains null', check(type, - [ 1, null, 2 ], - { data: { nest: { test: null } }, + it( + "Contains null", + check(type, [1, null, 2], { + data: { nest: { test: null } }, errors: [ - { message: 'Cannot return null for non-nullable field DataType.test.', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - - it('Returns null', check(type, - null, - { data: { nest: { test: null } } } - )); - + { + message: + "Cannot return null for non-nullable field DataType.test.", + locations: [{ line: 1, column: 10 }] + } + ] + }) + ); + + it("Returns null", check(type, null, { data: { nest: { test: null } } })); }); - describe('Promise>', () => { - - it('Contains values', check(type, - resolved([ 1, 2 ]), - { data: { nest: { test: [ 1, 2 ] } } } - )); + describe("Promise>", () => { + it( + "Contains values", + check(type, resolved([1, 2]), { data: { nest: { test: [1, 2] } } }) + ); - it('Contains null', check(type, - resolved([ 1, null, 2 ]), - { data: { nest: { test: null } }, + it( + "Contains null", + check(type, resolved([1, null, 2]), { + data: { nest: { test: null } }, errors: [ - { message: 'Cannot return null for non-nullable field DataType.test.', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - - it('Returns null', check(type, - resolved(null), - { data: { nest: { test: null } } } - )); - - it('Rejected', check(type, - () => rejected(new Error('bad')), - { data: { nest: { test: null } }, + { + message: + "Cannot return null for non-nullable field DataType.test.", + locations: [{ line: 1, column: 10 }] + } + ] + }) + ); + + it( + "Returns null", + check(type, resolved(null), { data: { nest: { test: null } } }) + ); + + it( + "Rejected", + check(type, () => rejected(new Error("bad")), { + data: { nest: { test: null } }, errors: [ - { message: 'bad', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - + { + message: "bad", + locations: [{ line: 1, column: 10 }] + } + ] + }) + ); }); - describe('Array>', () => { - - it('Contains values', check(type, - [ resolved(1), resolved(2) ], - { data: { nest: { test: [ 1, 2 ] } } } - )); - - it('Contains null', check(type, - [ resolved(1), resolved(null), resolved(2) ], - { data: { nest: { test: null } }, + describe("Array>", () => { + it( + "Contains values", + check(type, [resolved(1), resolved(2)], { + data: { nest: { test: [1, 2] } } + }) + ); + + it( + "Contains null", + check(type, [resolved(1), resolved(null), resolved(2)], { + data: { nest: { test: null } }, errors: [ - { message: 'Cannot return null for non-nullable field DataType.test.', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - - it('Contains reject', check(type, - () => [ resolved(1), rejected(new Error('bad')), resolved(2) ], - { data: { nest: { test: null } }, - errors: [ - { message: 'bad', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - + { + message: + "Cannot return null for non-nullable field DataType.test.", + locations: [{ line: 1, column: 10 }] + } + ] + }) + ); + + it( + "Contains reject", + check( + type, + () => [resolved(1), rejected(new Error("bad")), resolved(2)], + { + data: { nest: { test: null } }, + errors: [ + { + message: "bad", + locations: [{ line: 1, column: 10 }] + } + ] + } + ) + ); }); - }); - describe('[T!]!', () => { - const type = - new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(GraphQLInt))); - - describe('Array', () => { - - it('Contains values', check(type, - [ 1, 2 ], - { data: { nest: { test: [ 1, 2 ] } } } - )); - - - it('Contains null', check(type, - [ 1, null, 2 ], - { data: { nest: null }, + describe("[T!]!", () => { + const type = new GraphQLNonNull( + new GraphQLList(new GraphQLNonNull(GraphQLInt)) + ); + + describe("Array", () => { + it( + "Contains values", + check(type, [1, 2], { data: { nest: { test: [1, 2] } } }) + ); + + it( + "Contains null", + check(type, [1, null, 2], { + data: { nest: null }, errors: [ - { message: 'Cannot return null for non-nullable field DataType.test.', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - - it('Returns null', check(type, - null, - { data: { nest: null }, + { + message: + "Cannot return null for non-nullable field DataType.test.", + locations: [{ line: 1, column: 10 }] + } + ] + }) + ); + + it( + "Returns null", + check(type, null, { + data: { nest: null }, errors: [ - { message: 'Cannot return null for non-nullable field DataType.test.', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - + { + message: + "Cannot return null for non-nullable field DataType.test.", + locations: [{ line: 1, column: 10 }] + } + ] + }) + ); }); - describe('Promise>', () => { - - it('Contains values', check(type, - resolved([ 1, 2 ]), - { data: { nest: { test: [ 1, 2 ] } } } - )); + describe("Promise>", () => { + it( + "Contains values", + check(type, resolved([1, 2]), { data: { nest: { test: [1, 2] } } }) + ); - it('Contains null', check(type, - resolved([ 1, null, 2 ]), - { data: { nest: null }, + it( + "Contains null", + check(type, resolved([1, null, 2]), { + data: { nest: null }, errors: [ - { message: 'Cannot return null for non-nullable field DataType.test.', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - - it('Returns null', check(type, - resolved(null), - { data: { nest: null }, + { + message: + "Cannot return null for non-nullable field DataType.test.", + locations: [{ line: 1, column: 10 }] + } + ] + }) + ); + + it( + "Returns null", + check(type, resolved(null), { + data: { nest: null }, errors: [ - { message: 'Cannot return null for non-nullable field DataType.test.', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - - it('Rejected', check(type, - () => rejected(new Error('bad')), - { data: { nest: null }, + { + message: + "Cannot return null for non-nullable field DataType.test.", + locations: [{ line: 1, column: 10 }] + } + ] + }) + ); + + it( + "Rejected", + check(type, () => rejected(new Error("bad")), { + data: { nest: null }, errors: [ - { message: 'bad', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - + { + message: "bad", + locations: [{ line: 1, column: 10 }] + } + ] + }) + ); }); - describe('Array>', () => { - - it('Contains values', check(type, - [ resolved(1), resolved(2) ], - { data: { nest: { test: [ 1, 2 ] } } } - )); - - it('Contains null', check(type, - [ resolved(1), resolved(null), resolved(2) ], - { data: { nest: null }, - errors: [ - { message: 'Cannot return null for non-nullable field DataType.test.', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - - it('Contains reject', check(type, - () => [ resolved(1), rejected(new Error('bad')), resolved(2) ], - { data: { nest: null }, + describe("Array>", () => { + it( + "Contains values", + check(type, [resolved(1), resolved(2)], { + data: { nest: { test: [1, 2] } } + }) + ); + + it( + "Contains null", + check(type, [resolved(1), resolved(null), resolved(2)], { + data: { nest: null }, errors: [ - { message: 'bad', - locations: [ { line: 1, column: 10 } ] } - ] } - )); - + { + message: + "Cannot return null for non-nullable field DataType.test.", + locations: [{ line: 1, column: 10 }] + } + ] + }) + ); + + it( + "Contains reject", + check( + type, + () => [resolved(1), rejected(new Error("bad")), resolved(2)], + { + data: { nest: null }, + errors: [ + { + message: "bad", + locations: [{ line: 1, column: 10 }] + } + ] + } + ) + ); }); - }); - }); diff --git a/src/execution/__tests__/mutations-test.js b/src/execution/__tests__/mutations-test.js index 7632d9a880..9c875212e0 100644 --- a/src/execution/__tests__/mutations-test.js +++ b/src/execution/__tests__/mutations-test.js @@ -10,15 +10,11 @@ // 80+ char lines are useful in describe/it, so ignore in this file. /* eslint-disable max-len */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { execute } from '../execute'; -import { parse } from '../../language'; -import { - GraphQLSchema, - GraphQLObjectType, - GraphQLInt, -} from '../../type'; +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { execute } from "../execute"; +import { parse } from "../../language"; +import { GraphQLSchema, GraphQLObjectType, GraphQLInt } from "../../type"; class NumberHolder { theNumber: number; @@ -49,13 +45,13 @@ class Root { } failToChangeTheNumber(): Object { - throw new Error('Cannot change the number'); + throw new Error("Cannot change the number"); } promiseAndFailToChangeTheNumber(): Promise { return new Promise((resolve, reject) => { process.nextTick(() => { - reject(new Error('Cannot change the number')); + reject(new Error("Cannot change the number")); }); }); } @@ -63,55 +59,54 @@ class Root { const numberHolderType = new GraphQLObjectType({ fields: { - theNumber: { type: GraphQLInt }, + theNumber: { type: GraphQLInt } }, - name: 'NumberHolder', + name: "NumberHolder" }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ fields: { - numberHolder: { type: numberHolderType }, + numberHolder: { type: numberHolderType } }, - name: 'Query', + name: "Query" }), mutation: new GraphQLObjectType({ fields: { immediatelyChangeTheNumber: { type: numberHolderType, args: { newNumber: { type: GraphQLInt } }, - resolve: (function (obj, { newNumber }) { + resolve: (function(obj, { newNumber }) { return obj.immediatelyChangeTheNumber(newNumber); - }:any) + }: any) }, promiseToChangeTheNumber: { type: numberHolderType, args: { newNumber: { type: GraphQLInt } }, - resolve: (function (obj, { newNumber }) { + resolve: (function(obj, { newNumber }) { return obj.promiseToChangeTheNumber(newNumber); - }:any) + }: any) }, failToChangeTheNumber: { type: numberHolderType, args: { newNumber: { type: GraphQLInt } }, - resolve: (function (obj, { newNumber }) { + resolve: (function(obj, { newNumber }) { return obj.failToChangeTheNumber(newNumber); - }:any) + }: any) }, promiseAndFailToChangeTheNumber: { type: numberHolderType, args: { newNumber: { type: GraphQLInt } }, - resolve: (function (obj, { newNumber }) { + resolve: (function(obj, { newNumber }) { return obj.promiseAndFailToChangeTheNumber(newNumber); - }:any) + }: any) } }, - name: 'Mutation', + name: "Mutation" }) }); -describe('Execute: Handles mutation execution ordering', () => { - - it('evaluates mutations serially', async () => { +describe("Execute: Handles mutation execution ordering", () => { + it("evaluates mutations serially", async () => { const doc = `mutation M { first: immediatelyChangeTheNumber(newNumber: 1) { theNumber @@ -153,7 +148,7 @@ describe('Execute: Handles mutation execution ordering', () => { }); }); - it('evaluates mutations correctly in the presense of a failed mutation', async () => { + it("evaluates mutations correctly in the presense of a failed mutation", async () => { const doc = `mutation M { first: immediatelyChangeTheNumber(newNumber: 1) { theNumber @@ -191,15 +186,19 @@ describe('Execute: Handles mutation execution ordering', () => { fifth: { theNumber: 5 }, - sixth: null, + sixth: null }); expect(result.errors).to.have.length(2); expect(result.errors).to.containSubset([ - { message: 'Cannot change the number', - locations: [ { line: 8, column: 7 } ] }, - { message: 'Cannot change the number', - locations: [ { line: 17, column: 7 } ] } + { + message: "Cannot change the number", + locations: [{ line: 8, column: 7 }] + }, + { + message: "Cannot change the number", + locations: [{ line: 17, column: 7 }] + } ]); }); }); diff --git a/src/execution/__tests__/nonnull-test.js b/src/execution/__tests__/nonnull-test.js index 2f286d1244..3f8b8898be 100644 --- a/src/execution/__tests__/nonnull-test.js +++ b/src/execution/__tests__/nonnull-test.js @@ -10,38 +10,38 @@ // 80+ char lines are useful in describe/it, so ignore in this file. /* eslint-disable max-len */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { execute } from '../execute'; -import { parse } from '../../language'; +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { execute } from "../execute"; +import { parse } from "../../language"; import { GraphQLSchema, GraphQLObjectType, GraphQLString, GraphQLNonNull -} from '../../type'; +} from "../../type"; -const syncError = new Error('sync'); -const nonNullSyncError = new Error('nonNullSync'); -const promiseError = new Error('promise'); -const nonNullPromiseError = new Error('nonNullPromise'); +const syncError = new Error("sync"); +const nonNullSyncError = new Error("nonNullSync"); +const promiseError = new Error("promise"); +const nonNullPromiseError = new Error("nonNullPromise"); const throwingData = { - sync() { throw syncError; }, - nonNullSync() { throw nonNullSyncError; }, + sync() { + throw syncError; + }, + nonNullSync() { + throw nonNullSyncError; + }, promise() { - return new Promise( - () => { - throw promiseError; - } - ); + return new Promise(() => { + throw promiseError; + }); }, nonNullPromise() { - return new Promise( - () => { - throw nonNullPromiseError; - } - ); + return new Promise(() => { + throw nonNullPromiseError; + }); }, nest() { return throwingData; @@ -50,37 +50,33 @@ const throwingData = { return throwingData; }, promiseNest() { - return new Promise( - resolve => { - resolve(throwingData); - } - ); + return new Promise(resolve => { + resolve(throwingData); + }); }, nonNullPromiseNest() { - return new Promise( - resolve => { - resolve(throwingData); - } - ); - }, + return new Promise(resolve => { + resolve(throwingData); + }); + } }; const nullingData = { - sync() { return null; }, - nonNullSync() { return null; }, + sync() { + return null; + }, + nonNullSync() { + return null; + }, promise() { - return new Promise( - resolve => { - resolve(null); - } - ); + return new Promise(resolve => { + resolve(null); + }); }, nonNullPromise() { - return new Promise( - resolve => { - resolve(null); - } - ); + return new Promise(resolve => { + resolve(null); + }); }, nest() { return nullingData; @@ -89,23 +85,19 @@ const nullingData = { return nullingData; }, promiseNest() { - return new Promise( - resolve => { - resolve(nullingData); - } - ); + return new Promise(resolve => { + resolve(nullingData); + }); }, nonNullPromiseNest() { - return new Promise( - resolve => { - resolve(nullingData); - } - ); - }, + return new Promise(resolve => { + resolve(nullingData); + }); + } }; const dataType = new GraphQLObjectType({ - name: 'DataType', + name: "DataType", fields: () => ({ sync: { type: GraphQLString }, nonNullSync: { type: new GraphQLNonNull(GraphQLString) }, @@ -114,16 +106,15 @@ const dataType = new GraphQLObjectType({ nest: { type: dataType }, nonNullNest: { type: new GraphQLNonNull(dataType) }, promiseNest: { type: dataType }, - nonNullPromiseNest: { type: new GraphQLNonNull(dataType) }, + nonNullPromiseNest: { type: new GraphQLNonNull(dataType) } }) }); const schema = new GraphQLSchema({ query: dataType }); -describe('Execute: handles non-nullable types', () => { - - it('nulls a nullable field that throws synchronously', async () => { +describe("Execute: handles non-nullable types", () => { + it("nulls a nullable field that throws synchronously", async () => { const doc = ` query Q { sync @@ -134,20 +125,22 @@ describe('Execute: handles non-nullable types', () => { const expected = { data: { - sync: null, + sync: null }, errors: [ - { message: syncError.message, - locations: [ { line: 3, column: 9 } ] } + { + message: syncError.message, + locations: [{ line: 3, column: 9 }] + } ] }; - return expect( - await execute(schema, ast, throwingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, throwingData)).to.containSubset( + expected + ); }); - it('nulls a nullable field that throws in a promise', async () => { + it("nulls a nullable field that throws in a promise", async () => { const doc = ` query Q { promise @@ -158,20 +151,22 @@ describe('Execute: handles non-nullable types', () => { const expected = { data: { - promise: null, + promise: null }, errors: [ - { message: promiseError.message, - locations: [ { line: 3, column: 9 } ] } + { + message: promiseError.message, + locations: [{ line: 3, column: 9 }] + } ] }; - return expect( - await execute(schema, ast, throwingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, throwingData)).to.containSubset( + expected + ); }); - it('nulls a synchronously returned object that contains a non-nullable field that throws synchronously', async () => { + it("nulls a synchronously returned object that contains a non-nullable field that throws synchronously", async () => { const doc = ` query Q { nest { @@ -187,17 +182,19 @@ describe('Execute: handles non-nullable types', () => { nest: null }, errors: [ - { message: nonNullSyncError.message, - locations: [ { line: 4, column: 11 } ] } + { + message: nonNullSyncError.message, + locations: [{ line: 4, column: 11 }] + } ] }; - return expect( - await execute(schema, ast, throwingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, throwingData)).to.containSubset( + expected + ); }); - it('nulls a synchronously returned object that contains a non-nullable field that throws in a promise', async () => { + it("nulls a synchronously returned object that contains a non-nullable field that throws in a promise", async () => { const doc = ` query Q { nest { @@ -213,17 +210,19 @@ describe('Execute: handles non-nullable types', () => { nest: null }, errors: [ - { message: nonNullPromiseError.message, - locations: [ { line: 4, column: 11 } ] } + { + message: nonNullPromiseError.message, + locations: [{ line: 4, column: 11 }] + } ] }; - return expect( - await execute(schema, ast, throwingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, throwingData)).to.containSubset( + expected + ); }); - it('nulls an object returned in a promise that contains a non-nullable field that throws synchronously', async () => { + it("nulls an object returned in a promise that contains a non-nullable field that throws synchronously", async () => { const doc = ` query Q { promiseNest { @@ -239,17 +238,19 @@ describe('Execute: handles non-nullable types', () => { promiseNest: null }, errors: [ - { message: nonNullSyncError.message, - locations: [ { line: 4, column: 11 } ] } + { + message: nonNullSyncError.message, + locations: [{ line: 4, column: 11 }] + } ] }; - return expect( - await execute(schema, ast, throwingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, throwingData)).to.containSubset( + expected + ); }); - it('nulls an object returned in a promise that contains a non-nullable field that throws in a promise', async () => { + it("nulls an object returned in a promise that contains a non-nullable field that throws in a promise", async () => { const doc = ` query Q { promiseNest { @@ -265,17 +266,19 @@ describe('Execute: handles non-nullable types', () => { promiseNest: null }, errors: [ - { message: nonNullPromiseError.message, - locations: [ { line: 4, column: 11 } ] } + { + message: nonNullPromiseError.message, + locations: [{ line: 4, column: 11 }] + } ] }; - return expect( - await execute(schema, ast, throwingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, throwingData)).to.containSubset( + expected + ); }); - it('nulls a complex tree of nullable fields that throw', async () => { + it("nulls a complex tree of nullable fields that throw", async () => { const doc = ` query Q { nest { @@ -314,11 +317,11 @@ describe('Execute: handles non-nullable types', () => { promise: null, nest: { sync: null, - promise: null, + promise: null }, promiseNest: { sync: null, - promise: null, + promise: null } }, promiseNest: { @@ -326,48 +329,72 @@ describe('Execute: handles non-nullable types', () => { promise: null, nest: { sync: null, - promise: null, + promise: null }, promiseNest: { sync: null, - promise: null, + promise: null } } }, errors: [ - { message: syncError.message, - locations: [ { line: 4, column: 11 } ] }, - { message: syncError.message, - locations: [ { line: 7, column: 13 } ] }, - { message: syncError.message, - locations: [ { line: 11, column: 13 } ] }, - { message: syncError.message, - locations: [ { line: 16, column: 11 } ] }, - { message: syncError.message, - locations: [ { line: 19, column: 13 } ] }, - { message: syncError.message, - locations: [ { line: 23, column: 13 } ] }, - { message: promiseError.message, - locations: [ { line: 5, column: 11 } ] }, - { message: promiseError.message, - locations: [ { line: 8, column: 13 } ] }, - { message: promiseError.message, - locations: [ { line: 12, column: 13 } ] }, - { message: promiseError.message, - locations: [ { line: 17, column: 11 } ] }, - { message: promiseError.message, - locations: [ { line: 20, column: 13 } ] }, - { message: promiseError.message, - locations: [ { line: 24, column: 13 } ] }, + { + message: syncError.message, + locations: [{ line: 4, column: 11 }] + }, + { + message: syncError.message, + locations: [{ line: 7, column: 13 }] + }, + { + message: syncError.message, + locations: [{ line: 11, column: 13 }] + }, + { + message: syncError.message, + locations: [{ line: 16, column: 11 }] + }, + { + message: syncError.message, + locations: [{ line: 19, column: 13 }] + }, + { + message: syncError.message, + locations: [{ line: 23, column: 13 }] + }, + { + message: promiseError.message, + locations: [{ line: 5, column: 11 }] + }, + { + message: promiseError.message, + locations: [{ line: 8, column: 13 }] + }, + { + message: promiseError.message, + locations: [{ line: 12, column: 13 }] + }, + { + message: promiseError.message, + locations: [{ line: 17, column: 11 }] + }, + { + message: promiseError.message, + locations: [{ line: 20, column: 13 }] + }, + { + message: promiseError.message, + locations: [{ line: 24, column: 13 }] + } ] }; - return expect( - await execute(schema, ast, throwingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, throwingData)).to.containSubset( + expected + ); }); - it('nulls the first nullable object after a field throws in a long chain of fields that are non-null', async () => { + it("nulls the first nullable object after a field throws in a long chain of fields that are non-null", async () => { const doc = ` query Q { nest { @@ -427,24 +454,31 @@ describe('Execute: handles non-nullable types', () => { anotherPromiseNest: null }, errors: [ - { message: nonNullSyncError.message, - locations: [ { line: 8, column: 19 } ] }, - { message: nonNullSyncError.message, - locations: [ { line: 19, column: 19 } ] }, - { message: nonNullPromiseError.message, - locations: [ { line: 30, column: 19 } ] }, - { message: nonNullPromiseError.message, - locations: [ { line: 41, column: 19 } ] } + { + message: nonNullSyncError.message, + locations: [{ line: 8, column: 19 }] + }, + { + message: nonNullSyncError.message, + locations: [{ line: 19, column: 19 }] + }, + { + message: nonNullPromiseError.message, + locations: [{ line: 30, column: 19 }] + }, + { + message: nonNullPromiseError.message, + locations: [{ line: 41, column: 19 }] + } ] }; - return expect( - await execute(schema, ast, throwingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, throwingData)).to.containSubset( + expected + ); }); - - it('nulls a nullable field that synchronously returns null', async () => { + it("nulls a nullable field that synchronously returns null", async () => { const doc = ` query Q { sync @@ -455,16 +489,16 @@ describe('Execute: handles non-nullable types', () => { const expected = { data: { - sync: null, + sync: null } }; - return expect( - await execute(schema, ast, nullingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, nullingData)).to.containSubset( + expected + ); }); - it('nulls a nullable field that returns null in a promise', async () => { + it("nulls a nullable field that returns null in a promise", async () => { const doc = ` query Q { promise @@ -475,16 +509,16 @@ describe('Execute: handles non-nullable types', () => { const expected = { data: { - promise: null, + promise: null } }; - return expect( - await execute(schema, ast, nullingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, nullingData)).to.containSubset( + expected + ); }); - it('nulls a synchronously returned object that contains a non-nullable field that returns null synchronously', async () => { + it("nulls a synchronously returned object that contains a non-nullable field that returns null synchronously", async () => { const doc = ` query Q { nest { @@ -500,17 +534,20 @@ describe('Execute: handles non-nullable types', () => { nest: null }, errors: [ - { message: 'Cannot return null for non-nullable field DataType.nonNullSync.', - locations: [ { line: 4, column: 11 } ] } + { + message: + "Cannot return null for non-nullable field DataType.nonNullSync.", + locations: [{ line: 4, column: 11 }] + } ] }; - return expect( - await execute(schema, ast, nullingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, nullingData)).to.containSubset( + expected + ); }); - it('nulls a synchronously returned object that contains a non-nullable field that returns null in a promise', async () => { + it("nulls a synchronously returned object that contains a non-nullable field that returns null in a promise", async () => { const doc = ` query Q { nest { @@ -526,17 +563,20 @@ describe('Execute: handles non-nullable types', () => { nest: null }, errors: [ - { message: 'Cannot return null for non-nullable field DataType.nonNullPromise.', - locations: [ { line: 4, column: 11 } ] } + { + message: + "Cannot return null for non-nullable field DataType.nonNullPromise.", + locations: [{ line: 4, column: 11 }] + } ] }; - return expect( - await execute(schema, ast, nullingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, nullingData)).to.containSubset( + expected + ); }); - it('nulls an object returned in a promise that contains a non-nullable field that returns null synchronously', async () => { + it("nulls an object returned in a promise that contains a non-nullable field that returns null synchronously", async () => { const doc = ` query Q { promiseNest { @@ -552,17 +592,20 @@ describe('Execute: handles non-nullable types', () => { promiseNest: null }, errors: [ - { message: 'Cannot return null for non-nullable field DataType.nonNullSync.', - locations: [ { line: 4, column: 11 } ] } + { + message: + "Cannot return null for non-nullable field DataType.nonNullSync.", + locations: [{ line: 4, column: 11 }] + } ] }; - return expect( - await execute(schema, ast, nullingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, nullingData)).to.containSubset( + expected + ); }); - it('nulls an object returned in a promise that contains a non-nullable field that returns null ina a promise', async () => { + it("nulls an object returned in a promise that contains a non-nullable field that returns null ina a promise", async () => { const doc = ` query Q { promiseNest { @@ -578,17 +621,20 @@ describe('Execute: handles non-nullable types', () => { promiseNest: null }, errors: [ - { message: 'Cannot return null for non-nullable field DataType.nonNullPromise.', - locations: [ { line: 4, column: 11 } ] } + { + message: + "Cannot return null for non-nullable field DataType.nonNullPromise.", + locations: [{ line: 4, column: 11 }] + } ] }; - return expect( - await execute(schema, ast, nullingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, nullingData)).to.containSubset( + expected + ); }); - it('nulls a complex tree of nullable fields that return null', async () => { + it("nulls a complex tree of nullable fields that return null", async () => { const doc = ` query Q { nest { @@ -627,11 +673,11 @@ describe('Execute: handles non-nullable types', () => { promise: null, nest: { sync: null, - promise: null, + promise: null }, promiseNest: { sync: null, - promise: null, + promise: null } }, promiseNest: { @@ -639,22 +685,22 @@ describe('Execute: handles non-nullable types', () => { promise: null, nest: { sync: null, - promise: null, + promise: null }, promiseNest: { sync: null, - promise: null, + promise: null } } } }; - return expect( - await execute(schema, ast, nullingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, nullingData)).to.containSubset( + expected + ); }); - it('nulls the first nullable object after a field returns null in a long chain of fields that are non-null', async () => { + it("nulls the first nullable object after a field returns null in a long chain of fields that are non-null", async () => { const doc = ` query Q { nest { @@ -714,23 +760,35 @@ describe('Execute: handles non-nullable types', () => { anotherPromiseNest: null }, errors: [ - { message: 'Cannot return null for non-nullable field DataType.nonNullSync.', - locations: [ { line: 8, column: 19 } ] }, - { message: 'Cannot return null for non-nullable field DataType.nonNullSync.', - locations: [ { line: 19, column: 19 } ] }, - { message: 'Cannot return null for non-nullable field DataType.nonNullPromise.', - locations: [ { line: 30, column: 19 } ] }, - { message: 'Cannot return null for non-nullable field DataType.nonNullPromise.', - locations: [ { line: 41, column: 19 } ] } + { + message: + "Cannot return null for non-nullable field DataType.nonNullSync.", + locations: [{ line: 8, column: 19 }] + }, + { + message: + "Cannot return null for non-nullable field DataType.nonNullSync.", + locations: [{ line: 19, column: 19 }] + }, + { + message: + "Cannot return null for non-nullable field DataType.nonNullPromise.", + locations: [{ line: 30, column: 19 }] + }, + { + message: + "Cannot return null for non-nullable field DataType.nonNullPromise.", + locations: [{ line: 41, column: 19 }] + } ] }; - return expect( - await execute(schema, ast, nullingData) - ).to.containSubset(expected); + return expect(await execute(schema, ast, nullingData)).to.containSubset( + expected + ); }); - it('nulls the top level if sync non-nullable field throws', async () => { + it("nulls the top level if sync non-nullable field throws", async () => { const doc = ` query Q { nonNullSync } `; @@ -738,8 +796,10 @@ describe('Execute: handles non-nullable types', () => { const expected = { data: null, errors: [ - { message: nonNullSyncError.message, - locations: [ { line: 2, column: 17 } ] } + { + message: nonNullSyncError.message, + locations: [{ line: 2, column: 17 }] + } ] }; @@ -748,7 +808,7 @@ describe('Execute: handles non-nullable types', () => { ).to.containSubset(expected); }); - it('nulls the top level if async non-nullable field errors', async () => { + it("nulls the top level if async non-nullable field errors", async () => { const doc = ` query Q { nonNullPromise } `; @@ -756,8 +816,10 @@ describe('Execute: handles non-nullable types', () => { const expected = { data: null, errors: [ - { message: nonNullPromiseError.message, - locations: [ { line: 2, column: 17 } ] } + { + message: nonNullPromiseError.message, + locations: [{ line: 2, column: 17 }] + } ] }; @@ -766,7 +828,7 @@ describe('Execute: handles non-nullable types', () => { ).to.containSubset(expected); }); - it('nulls the top level if sync non-nullable field returns null', async () => { + it("nulls the top level if sync non-nullable field returns null", async () => { const doc = ` query Q { nonNullSync } `; @@ -774,8 +836,11 @@ describe('Execute: handles non-nullable types', () => { const expected = { data: null, errors: [ - { message: 'Cannot return null for non-nullable field DataType.nonNullSync.', - locations: [ { line: 2, column: 17 } ] } + { + message: + "Cannot return null for non-nullable field DataType.nonNullSync.", + locations: [{ line: 2, column: 17 }] + } ] }; @@ -784,7 +849,7 @@ describe('Execute: handles non-nullable types', () => { ).to.containSubset(expected); }); - it('nulls the top level if async non-nullable field resolves null', async () => { + it("nulls the top level if async non-nullable field resolves null", async () => { const doc = ` query Q { nonNullPromise } `; @@ -792,8 +857,11 @@ describe('Execute: handles non-nullable types', () => { const expected = { data: null, errors: [ - { message: 'Cannot return null for non-nullable field DataType.nonNullPromise.', - locations: [ { line: 2, column: 17 } ] } + { + message: + "Cannot return null for non-nullable field DataType.nonNullPromise.", + locations: [{ line: 2, column: 17 }] + } ] }; diff --git a/src/execution/__tests__/resolve-test.js b/src/execution/__tests__/resolve-test.js index 896b0b8919..da3f3eacd7 100644 --- a/src/execution/__tests__/resolve-test.js +++ b/src/execution/__tests__/resolve-test.js @@ -7,23 +7,22 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; +import { expect } from "chai"; +import { describe, it } from "mocha"; import { graphql, GraphQLSchema, GraphQLObjectType, GraphQLString, - GraphQLInt, -} from '../../'; - -describe('Execute: resolve function', () => { + GraphQLInt +} from "../../"; +describe("Execute: resolve function", () => { function testSchema(testField) { return new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { test: testField } @@ -31,71 +30,63 @@ describe('Execute: resolve function', () => { }); } - it('default function accesses properties', async () => { + it("default function accesses properties", async () => { const schema = testSchema({ type: GraphQLString }); const source = { - test: 'testValue' + test: "testValue" }; - expect( - await graphql(schema, '{ test }', source) - ).to.deep.equal({ + expect(await graphql(schema, "{ test }", source)).to.deep.equal({ data: { - test: 'testValue' + test: "testValue" } }); }); - it('default function calls methods', async () => { + it("default function calls methods", async () => { const schema = testSchema({ type: GraphQLString }); const source = { - _secret: 'secretValue', + _secret: "secretValue", test() { return this._secret; } }; - expect( - await graphql(schema, '{ test }', source) - ).to.deep.equal({ + expect(await graphql(schema, "{ test }", source)).to.deep.equal({ data: { - test: 'secretValue' + test: "secretValue" } }); }); - it('uses provided resolve function', async () => { + it("uses provided resolve function", async () => { const schema = testSchema({ type: GraphQLString, args: { aStr: { type: GraphQLString }, - aInt: { type: GraphQLInt }, + aInt: { type: GraphQLInt } }, resolve(source, args) { - return JSON.stringify([ source, args ]); + return JSON.stringify([source, args]); } }); - expect( - await graphql(schema, '{ test }') - ).to.deep.equal({ + expect(await graphql(schema, "{ test }")).to.deep.equal({ data: { - test: '[null,{}]' + test: "[null,{}]" } }); - expect( - await graphql(schema, '{ test }', 'Source!') - ).to.deep.equal({ + expect(await graphql(schema, "{ test }", "Source!")).to.deep.equal({ data: { test: '["Source!",{}]' } }); expect( - await graphql(schema, '{ test(aStr: "String!") }', 'Source!') + await graphql(schema, '{ test(aStr: "String!") }', "Source!") ).to.deep.equal({ data: { test: '["Source!",{"aStr":"String!"}]' @@ -103,12 +94,11 @@ describe('Execute: resolve function', () => { }); expect( - await graphql(schema, '{ test(aInt: -123, aStr: "String!") }', 'Source!') + await graphql(schema, '{ test(aInt: -123, aStr: "String!") }', "Source!") ).to.deep.equal({ data: { test: '["Source!",{"aStr":"String!","aInt":-123}]' } }); }); - }); diff --git a/src/execution/__tests__/schema-test.js b/src/execution/__tests__/schema-test.js index f831a16808..64bff25cb1 100644 --- a/src/execution/__tests__/schema-test.js +++ b/src/execution/__tests__/schema-test.js @@ -7,11 +7,11 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; +import { expect } from "chai"; +import { describe, it } from "mocha"; -import { execute } from '../execute'; -import { parse } from '../../language'; +import { execute } from "../execute"; +import { parse } from "../../language"; import { GraphQLSchema, GraphQLObjectType, @@ -20,24 +20,22 @@ import { GraphQLInt, GraphQLString, GraphQLBoolean, - GraphQLID, -} from '../../type'; - - -describe('Execute: Handles execution with a complex schema', () => { - it('executes using a schema', async () => { + GraphQLID +} from "../../type"; +describe("Execute: Handles execution with a complex schema", () => { + it("executes using a schema", async () => { const BlogImage = new GraphQLObjectType({ - name: 'Image', + name: "Image", fields: { url: { type: GraphQLString }, width: { type: GraphQLInt }, - height: { type: GraphQLInt }, + height: { type: GraphQLInt } } }); const BlogAuthor = new GraphQLObjectType({ - name: 'Author', + name: "Author", fields: () => ({ id: { type: GraphQLString }, name: { type: GraphQLString }, @@ -51,7 +49,7 @@ describe('Execute: Handles execution with a complex schema', () => { }); const BlogArticle = new GraphQLObjectType({ - name: 'Article', + name: "Article", fields: { id: { type: new GraphQLNonNull(GraphQLString) }, isPublished: { type: GraphQLBoolean }, @@ -63,7 +61,7 @@ describe('Execute: Handles execution with a complex schema', () => { }); const BlogQuery = new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { article: { type: BlogArticle, @@ -95,18 +93,18 @@ describe('Execute: Handles execution with a complex schema', () => { function article(id) { return { id, - isPublished: 'true', + isPublished: "true", author: johnSmith, - title: 'My Article ' + id, - body: 'This is a post', - hidden: 'This data is not exposed in the schema', - keywords: [ 'foo', 'bar', 1, true, null ] + title: "My Article " + id, + body: "This is a post", + hidden: "This data is not exposed in the schema", + keywords: ["foo", "bar", 1, true, null] }; } const johnSmith = { id: 123, - name: 'John Smith', + name: "John Smith", pic: (width, height) => getPic(123, width, height), recentArticle: article(1) }; @@ -155,51 +153,69 @@ describe('Execute: Handles execution with a complex schema', () => { // Note: this is intentionally not validating to ensure appropriate // behavior occurs when executing an invalid query. - return expect( - await execute(BlogSchema, parse(request)) - ).to.deep.equal({ + return expect(await execute(BlogSchema, parse(request))).to.deep.equal({ data: { feed: [ - { id: '1', - title: 'My Article 1' }, - { id: '2', - title: 'My Article 2' }, - { id: '3', - title: 'My Article 3' }, - { id: '4', - title: 'My Article 4' }, - { id: '5', - title: 'My Article 5' }, - { id: '6', - title: 'My Article 6' }, - { id: '7', - title: 'My Article 7' }, - { id: '8', - title: 'My Article 8' }, - { id: '9', - title: 'My Article 9' }, - { id: '10', - title: 'My Article 10' } + { + id: "1", + title: "My Article 1" + }, + { + id: "2", + title: "My Article 2" + }, + { + id: "3", + title: "My Article 3" + }, + { + id: "4", + title: "My Article 4" + }, + { + id: "5", + title: "My Article 5" + }, + { + id: "6", + title: "My Article 6" + }, + { + id: "7", + title: "My Article 7" + }, + { + id: "8", + title: "My Article 8" + }, + { + id: "9", + title: "My Article 9" + }, + { + id: "10", + title: "My Article 10" + } ], article: { - id: '1', + id: "1", isPublished: true, - title: 'My Article 1', - body: 'This is a post', + title: "My Article 1", + body: "This is a post", author: { - id: '123', - name: 'John Smith', + id: "123", + name: "John Smith", pic: { - url: 'cdn://123', + url: "cdn://123", width: 640, height: 480 }, recentArticle: { - id: '1', + id: "1", isPublished: true, - title: 'My Article 1', - body: 'This is a post', - keywords: [ 'foo', 'bar', '1', 'true', null ] + title: "My Article 1", + body: "This is a post", + keywords: ["foo", "bar", "1", "true", null] } } } diff --git a/src/execution/__tests__/union-interface-test.js b/src/execution/__tests__/union-interface-test.js index 5797ca07f5..8b10cd02f6 100644 --- a/src/execution/__tests__/union-interface-test.js +++ b/src/execution/__tests__/union-interface-test.js @@ -7,11 +7,11 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; +import { expect } from "chai"; +import { describe, it } from "mocha"; -import { execute } from '../execute'; -import { parse } from '../../language'; +import { execute } from "../execute"; +import { parse } from "../../language"; import { GraphQLSchema, GraphQLObjectType, @@ -20,8 +20,7 @@ import { GraphQLList, GraphQLString, GraphQLBoolean -} from '../../type'; - +} from "../../type"; class Dog { constructor(name, barks) { @@ -46,15 +45,15 @@ class Person { } const NamedType = new GraphQLInterfaceType({ - name: 'Named', + name: "Named", fields: { name: { type: GraphQLString } } }); const DogType = new GraphQLObjectType({ - name: 'Dog', - interfaces: [ NamedType ], + name: "Dog", + interfaces: [NamedType], fields: { name: { type: GraphQLString }, barks: { type: GraphQLBoolean } @@ -63,8 +62,8 @@ const DogType = new GraphQLObjectType({ }); const CatType = new GraphQLObjectType({ - name: 'Cat', - interfaces: [ NamedType ], + name: "Cat", + interfaces: [NamedType], fields: { name: { type: GraphQLString }, meows: { type: GraphQLBoolean } @@ -73,8 +72,8 @@ const CatType = new GraphQLObjectType({ }); const PetType = new GraphQLUnionType({ - name: 'Pet', - types: [ DogType, CatType ], + name: "Pet", + types: [DogType, CatType], resolveType(value) { if (value instanceof Dog) { return DogType; @@ -86,29 +85,28 @@ const PetType = new GraphQLUnionType({ }); const PersonType = new GraphQLObjectType({ - name: 'Person', - interfaces: [ NamedType ], + name: "Person", + interfaces: [NamedType], fields: { name: { type: GraphQLString }, pets: { type: new GraphQLList(PetType) }, - friends: { type: new GraphQLList(NamedType) }, + friends: { type: new GraphQLList(NamedType) } }, isTypeOf: value => value instanceof Person }); const schema = new GraphQLSchema({ query: PersonType, - types: [ PetType ] + types: [PetType] }); -const garfield = new Cat('Garfield', false); -const odie = new Dog('Odie', true); -const liz = new Person('Liz'); -const john = new Person('John', [ garfield, odie ], [ liz, odie ]); - -describe('Execute: Union and intersection types', () => { +const garfield = new Cat("Garfield", false); +const odie = new Dog("Odie", true); +const liz = new Person("Liz"); +const john = new Person("John", [garfield, odie], [liz, odie]); - it('can introspect on union and intersection types', async () => { +describe("Execute: Union and intersection types", () => { + it("can introspect on union and intersection types", async () => { const ast = parse(` { Named: __type(name: "Named") { @@ -132,34 +130,23 @@ describe('Execute: Union and intersection types', () => { } `); - return expect( - await execute(schema, ast) - ).to.deep.equal({ + return expect(await execute(schema, ast)).to.deep.equal({ data: { Named: { - kind: 'INTERFACE', - name: 'Named', - fields: [ - { name: 'name' } - ], + kind: "INTERFACE", + name: "Named", + fields: [{ name: "name" }], interfaces: null, - possibleTypes: [ - { name: 'Person' }, - { name: 'Dog' }, - { name: 'Cat' }, - ], + possibleTypes: [{ name: "Person" }, { name: "Dog" }, { name: "Cat" }], enumValues: null, inputFields: null }, Pet: { - kind: 'UNION', - name: 'Pet', + kind: "UNION", + name: "Pet", fields: null, interfaces: null, - possibleTypes: [ - { name: 'Dog' }, - { name: 'Cat' } - ], + possibleTypes: [{ name: "Dog" }, { name: "Cat" }], enumValues: null, inputFields: null } @@ -167,8 +154,7 @@ describe('Execute: Union and intersection types', () => { }); }); - it('executes using union types', async () => { - + it("executes using union types", async () => { // NOTE: This is an *invalid* query, but it should be an *executable* query. const ast = parse(` { @@ -183,22 +169,19 @@ describe('Execute: Union and intersection types', () => { } `); - return expect( - await execute(schema, ast, john) - ).to.deep.equal({ + return expect(await execute(schema, ast, john)).to.deep.equal({ data: { - __typename: 'Person', - name: 'John', + __typename: "Person", + name: "John", pets: [ - { __typename: 'Cat', name: 'Garfield', meows: false }, - { __typename: 'Dog', name: 'Odie', barks: true } + { __typename: "Cat", name: "Garfield", meows: false }, + { __typename: "Dog", name: "Odie", barks: true } ] } }); }); - it('executes union types with inline fragments', async () => { - + it("executes union types with inline fragments", async () => { // This is the valid version of the query in the above test. const ast = parse(` { @@ -218,22 +201,19 @@ describe('Execute: Union and intersection types', () => { } `); - return expect( - await execute(schema, ast, john) - ).to.deep.equal({ + return expect(await execute(schema, ast, john)).to.deep.equal({ data: { - __typename: 'Person', - name: 'John', + __typename: "Person", + name: "John", pets: [ - { __typename: 'Cat', name: 'Garfield', meows: false }, - { __typename: 'Dog', name: 'Odie', barks: true } + { __typename: "Cat", name: "Garfield", meows: false }, + { __typename: "Dog", name: "Odie", barks: true } ] } }); }); - it('executes using interface types', async () => { - + it("executes using interface types", async () => { // NOTE: This is an *invalid* query, but it should be an *executable* query. const ast = parse(` { @@ -248,22 +228,19 @@ describe('Execute: Union and intersection types', () => { } `); - return expect( - await execute(schema, ast, john) - ).to.deep.equal({ + return expect(await execute(schema, ast, john)).to.deep.equal({ data: { - __typename: 'Person', - name: 'John', + __typename: "Person", + name: "John", friends: [ - { __typename: 'Person', name: 'Liz' }, - { __typename: 'Dog', name: 'Odie', barks: true } + { __typename: "Person", name: "Liz" }, + { __typename: "Dog", name: "Odie", barks: true } ] } }); }); - it('executes union types with inline fragments', async () => { - + it("executes union types with inline fragments", async () => { // This is the valid version of the query in the above test. const ast = parse(` { @@ -282,22 +259,19 @@ describe('Execute: Union and intersection types', () => { } `); - return expect( - await execute(schema, ast, john) - ).to.deep.equal({ + return expect(await execute(schema, ast, john)).to.deep.equal({ data: { - __typename: 'Person', - name: 'John', + __typename: "Person", + name: "John", friends: [ - { __typename: 'Person', name: 'Liz' }, - { __typename: 'Dog', name: 'Odie', barks: true } + { __typename: "Person", name: "Liz" }, + { __typename: "Dog", name: "Odie", barks: true } ] } }); }); - it('allows fragment conditions to be abstract types', async () => { - + it("allows fragment conditions to be abstract types", async () => { const ast = parse(` { __typename @@ -330,31 +304,29 @@ describe('Execute: Union and intersection types', () => { } `); - return expect( - await execute(schema, ast, john) - ).to.deep.equal({ + return expect(await execute(schema, ast, john)).to.deep.equal({ data: { - __typename: 'Person', - name: 'John', + __typename: "Person", + name: "John", pets: [ - { __typename: 'Cat', name: 'Garfield', meows: false }, - { __typename: 'Dog', name: 'Odie', barks: true } + { __typename: "Cat", name: "Garfield", meows: false }, + { __typename: "Dog", name: "Odie", barks: true } ], friends: [ - { __typename: 'Person', name: 'Liz' }, - { __typename: 'Dog', name: 'Odie', barks: true } + { __typename: "Person", name: "Liz" }, + { __typename: "Dog", name: "Odie", barks: true } ] } }); }); - it('gets execution info in resolver', async () => { + it("gets execution info in resolver", async () => { let encounteredContext; let encounteredSchema; let encounteredRootValue; const NamedType2 = new GraphQLInterfaceType({ - name: 'Named', + name: "Named", fields: { name: { type: GraphQLString } }, @@ -367,28 +339,26 @@ describe('Execute: Union and intersection types', () => { }); const PersonType2 = new GraphQLObjectType({ - name: 'Person', - interfaces: [ NamedType2 ], + name: "Person", + interfaces: [NamedType2], fields: { name: { type: GraphQLString }, - friends: { type: new GraphQLList(NamedType2) }, - }, + friends: { type: new GraphQLList(NamedType2) } + } }); const schema2 = new GraphQLSchema({ query: PersonType2 }); - const john2 = new Person('John', [], [ liz ]); + const john2 = new Person("John", [], [liz]); - const context = { authToken: '123abc' }; + const context = { authToken: "123abc" }; - const ast = parse('{ name, friends { name } }'); + const ast = parse("{ name, friends { name } }"); - expect( - await execute(schema2, ast, john2, context) - ).to.deep.equal({ - data: { name: 'John', friends: [ { name: 'Liz' } ] } + expect(await execute(schema2, ast, john2, context)).to.deep.equal({ + data: { name: "John", friends: [{ name: "Liz" }] } }); expect(encounteredContext).to.equal(context); diff --git a/src/execution/__tests__/variables-test.js b/src/execution/__tests__/variables-test.js index 01b649766a..7ba63f5c9d 100644 --- a/src/execution/__tests__/variables-test.js +++ b/src/execution/__tests__/variables-test.js @@ -10,10 +10,10 @@ // 80+ char lines are useful in describe/it, so ignore in this file. /* eslint-disable max-len */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { execute } from '../execute'; -import { parse } from '../../language'; +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { execute } from "../execute"; +import { parse } from "../../language"; import { GraphQLSchema, GraphQLObjectType, @@ -22,50 +22,50 @@ import { GraphQLString, GraphQLNonNull, GraphQLScalarType -} from '../../type'; +} from "../../type"; const TestComplexScalar = new GraphQLScalarType({ - name: 'ComplexScalar', + name: "ComplexScalar", serialize(value) { - if (value === 'DeserializedValue') { - return 'SerializedValue'; + if (value === "DeserializedValue") { + return "SerializedValue"; } return null; }, parseValue(value) { - if (value === 'SerializedValue') { - return 'DeserializedValue'; + if (value === "SerializedValue") { + return "DeserializedValue"; } return null; }, parseLiteral(ast) { - if (ast.value === 'SerializedValue') { - return 'DeserializedValue'; + if (ast.value === "SerializedValue") { + return "DeserializedValue"; } return null; - }, + } }); const TestInputObject = new GraphQLInputObjectType({ - name: 'TestInputObject', + name: "TestInputObject", fields: { a: { type: GraphQLString }, b: { type: new GraphQLList(GraphQLString) }, c: { type: new GraphQLNonNull(GraphQLString) }, - d: { type: TestComplexScalar }, + d: { type: TestComplexScalar } } }); const TestNestedInputObject = new GraphQLInputObjectType({ - name: 'TestNestedInputObject', + name: "TestNestedInputObject", fields: { na: { type: new GraphQLNonNull(TestInputObject) }, - nb: { type: new GraphQLNonNull(GraphQLString) }, - }, + nb: { type: new GraphQLNonNull(GraphQLString) } + } }); const TestType = new GraphQLObjectType({ - name: 'TestType', + name: "TestType", fields: { fieldWithObjectInput: { type: GraphQLString, @@ -84,14 +84,15 @@ const TestType = new GraphQLObjectType({ }, fieldWithDefaultArgumentValue: { type: GraphQLString, - args: { input: { type: GraphQLString, defaultValue: 'Hello World' } }, + args: { input: { type: GraphQLString, defaultValue: "Hello World" } }, resolve: (_, { input }) => input && JSON.stringify(input) }, fieldWithNestedInputObject: { type: GraphQLString, args: { input: { - type: TestNestedInputObject, defaultValue: 'Hello World' + type: TestNestedInputObject, + defaultValue: "Hello World" } }, resolve: (_, { input }) => input && JSON.stringify(input) @@ -103,33 +104,38 @@ const TestType = new GraphQLObjectType({ }, nnList: { type: GraphQLString, - args: { input: { type: new GraphQLNonNull(new GraphQLList(GraphQLString)) } }, + args: { + input: { type: new GraphQLNonNull(new GraphQLList(GraphQLString)) } + }, resolve: (_, { input }) => input && JSON.stringify(input) }, listNN: { type: GraphQLString, - args: { input: { type: new GraphQLList(new GraphQLNonNull(GraphQLString)) } }, + args: { + input: { type: new GraphQLList(new GraphQLNonNull(GraphQLString)) } + }, resolve: (_, { input }) => input && JSON.stringify(input) }, nnListNN: { type: GraphQLString, - args: { input: { type: - new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(GraphQLString))) - } }, + args: { + input: { + type: new GraphQLNonNull( + new GraphQLList(new GraphQLNonNull(GraphQLString)) + ) + } + }, resolve: (_, { input }) => input && JSON.stringify(input) - }, + } } }); const schema = new GraphQLSchema({ query: TestType }); -describe('Execute: Handles inputs', () => { - - describe('Handles objects and nullability', () => { - - describe('using inline structs', () => { - - it('executes with complex input', async () => { +describe("Execute: Handles inputs", () => { + describe("Handles objects and nullability", () => { + describe("using inline structs", () => { + it("executes with complex input", async () => { const doc = ` { fieldWithObjectInput(input: {a: "foo", b: ["bar"], c: "baz"}) @@ -144,7 +150,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('properly parses single value to list', async () => { + it("properly parses single value to list", async () => { const doc = ` { fieldWithObjectInput(input: {a: "foo", b: "bar", c: "baz"}) @@ -159,7 +165,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('does not use incorrect value', async () => { + it("does not use incorrect value", async () => { const doc = ` { fieldWithObjectInput(input: ["foo", "bar", "baz"]) @@ -176,7 +182,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('properly runs parseLiteral on complex scalar types', async () => { + it("properly runs parseLiteral on complex scalar types", async () => { const doc = ` { fieldWithObjectInput(input: {a: "foo", d: "SerializedValue"}) @@ -186,15 +192,13 @@ describe('Execute: Handles inputs', () => { return expect(await execute(schema, ast)).to.deep.equal({ data: { - fieldWithObjectInput: '{"a":"foo","d":"DeserializedValue"}', + fieldWithObjectInput: '{"a":"foo","d":"DeserializedValue"}' } }); }); - }); - describe('using variables', () => { - + describe("using variables", () => { const doc = ` query q($input: TestInputObject) { fieldWithObjectInput(input: $input) @@ -202,8 +206,8 @@ describe('Execute: Handles inputs', () => { `; const ast = parse(doc); - it('executes with complex input', async () => { - const params = { input: { a: 'foo', b: [ 'bar' ], c: 'baz' } }; + it("executes with complex input", async () => { + const params = { input: { a: "foo", b: ["bar"], c: "baz" } }; const result = await execute(schema, ast, null, null, params); return expect(result).to.deep.equal({ @@ -213,7 +217,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('uses default value when not provided', async () => { + it("uses default value when not provided", async () => { const withDefaultsAST = parse(` query q($input: TestInputObject = {a: "foo", b: ["bar"], c: "baz"}) { fieldWithObjectInput(input: $input) @@ -229,8 +233,8 @@ describe('Execute: Handles inputs', () => { }); }); - it('properly parses single value to list', async () => { - const params = { input: { a: 'foo', b: 'bar', c: 'baz' } }; + it("properly parses single value to list", async () => { + const params = { input: { a: "foo", b: "bar", c: "baz" } }; const result = await execute(schema, ast, null, null, params); return expect(result).to.deep.equal({ @@ -240,8 +244,8 @@ describe('Execute: Handles inputs', () => { }); }); - it('executes with complex scalar input', async () => { - const params = { input: { c: 'foo', d: 'SerializedValue' } }; + it("executes with complex scalar input", async () => { + const params = { input: { c: "foo", d: "SerializedValue" } }; const result = await execute(schema, ast, null, null, params); return expect(result).to.deep.equal({ @@ -251,8 +255,8 @@ describe('Execute: Handles inputs', () => { }); }); - it('errors on null for nested non-null', async () => { - const params = { input: { a: 'foo', b: 'bar', c: null } }; + it("errors on null for nested non-null", async () => { + const params = { input: { a: "foo", b: "bar", c: null } }; let caughtError; try { @@ -262,7 +266,7 @@ describe('Execute: Handles inputs', () => { } expect(caughtError).to.containSubset({ - locations: [ { line: 2, column: 17 } ], + locations: [{ line: 2, column: 17 }], message: 'Variable "$input" got invalid value ' + '{"a":"foo","b":"bar","c":null}.' + @@ -270,8 +274,8 @@ describe('Execute: Handles inputs', () => { }); }); - it('errors on incorrect type', async () => { - const params = { input: 'foo bar' }; + it("errors on incorrect type", async () => { + const params = { input: "foo bar" }; let caughtError; try { @@ -281,15 +285,15 @@ describe('Execute: Handles inputs', () => { } expect(caughtError).to.containSubset({ - locations: [ { line: 2, column: 17 } ], + locations: [{ line: 2, column: 17 }], message: 'Variable "$input" got invalid value "foo bar".' + '\nExpected "TestInputObject", found not an object.' }); }); - it('errors on omission of nested non-null', async () => { - const params = { input: { a: 'foo', b: 'bar' } }; + it("errors on omission of nested non-null", async () => { + const params = { input: { a: "foo", b: "bar" } }; let caughtError; try { @@ -299,21 +303,21 @@ describe('Execute: Handles inputs', () => { } expect(caughtError).to.containSubset({ - locations: [ { line: 2, column: 17 } ], + locations: [{ line: 2, column: 17 }], message: 'Variable "$input" got invalid value {"a":"foo","b":"bar"}.' + '\nIn field "c": Expected "String!", found null.' }); }); - it('errors on deep nested errors and with many errors', async () => { + it("errors on deep nested errors and with many errors", async () => { const nestedDoc = ` query q($input: TestNestedInputObject) { fieldWithNestedObjectInput(input: $input) } `; const nestedAst = parse(nestedDoc); - const params = { input: { na: { a: 'foo' } } }; + const params = { input: { na: { a: "foo" } } }; let caughtError; try { @@ -323,18 +327,17 @@ describe('Execute: Handles inputs', () => { } expect(caughtError).to.containSubset({ - locations: [ { line: 2, column: 19 } ], + locations: [{ line: 2, column: 19 }], message: 'Variable "$input" got invalid value {"na":{"a":"foo"}}.' + '\nIn field "na": In field "c": Expected "String!", found null.' + '\nIn field "nb": Expected "String!", found null.' }); - }); - it('errors on addition of unknown input field', async () => { + it("errors on addition of unknown input field", async () => { const params = { - input: { a: 'foo', b: 'bar', c: 'baz', extra: 'dog' } + input: { a: "foo", b: "bar", c: "baz", extra: "dog" } }; let caughtError; @@ -345,19 +348,18 @@ describe('Execute: Handles inputs', () => { } expect(caughtError).to.containSubset({ - locations: [ { line: 2, column: 17 } ], + locations: [{ line: 2, column: 17 }], message: 'Variable "$input" got invalid value ' + - '{"a":"foo","b":"bar","c":"baz","extra":"dog"}.' + - '\nIn field \"extra\": Unknown field.' + '{"a":"foo","b":"bar","c":"baz","extra":"dog"}.' + + '\nIn field "extra": Unknown field.' }); }); - }); }); - describe('Handles nullable scalars', () => { - it('allows nullable inputs to be omitted', async () => { + describe("Handles nullable scalars", () => { + it("allows nullable inputs to be omitted", async () => { const doc = ` { fieldWithNullableStringInput @@ -372,7 +374,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('allows nullable inputs to be omitted in a variable', async () => { + it("allows nullable inputs to be omitted in a variable", async () => { const doc = ` query SetsNullable($value: String) { fieldWithNullableStringInput(input: $value) @@ -387,7 +389,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('allows nullable inputs to be omitted in an unlisted variable', async () => { + it("allows nullable inputs to be omitted in an unlisted variable", async () => { const doc = ` query SetsNullable { fieldWithNullableStringInput(input: $value) @@ -402,7 +404,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('allows nullable inputs to be set to null in a variable', async () => { + it("allows nullable inputs to be set to null in a variable", async () => { const doc = ` query SetsNullable($value: String) { fieldWithNullableStringInput(input: $value) @@ -419,7 +421,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('allows nullable inputs to be set to a value in a variable', async () => { + it("allows nullable inputs to be set to a value in a variable", async () => { const doc = ` query SetsNullable($value: String) { fieldWithNullableStringInput(input: $value) @@ -428,7 +430,7 @@ describe('Execute: Handles inputs', () => { const ast = parse(doc); return expect( - await execute(schema, ast, null, null, { value: 'a' }) + await execute(schema, ast, null, null, { value: "a" }) ).to.deep.equal({ data: { fieldWithNullableStringInput: '"a"' @@ -436,7 +438,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('allows nullable inputs to be set to a value directly', async () => { + it("allows nullable inputs to be set to a value directly", async () => { const doc = ` { fieldWithNullableStringInput(input: "a") @@ -452,8 +454,8 @@ describe('Execute: Handles inputs', () => { }); }); - describe('Handles non-nullable scalars', () => { - it('does not allow non-nullable inputs to be omitted in a variable', async () => { + describe("Handles non-nullable scalars", () => { + it("does not allow non-nullable inputs to be omitted in a variable", async () => { const doc = ` query SetsNonNullable($value: String!) { fieldWithNonNullableStringInput(input: $value) @@ -468,13 +470,13 @@ describe('Execute: Handles inputs', () => { } expect(caughtError).to.containSubset({ - locations: [ { line: 2, column: 31 } ], + locations: [{ line: 2, column: 31 }], message: 'Variable "$value" of required type "String!" was not provided.' }); }); - it('does not allow non-nullable inputs to be set to null in a variable', async () => { + it("does not allow non-nullable inputs to be set to null in a variable", async () => { const doc = ` query SetsNonNullable($value: String!) { fieldWithNonNullableStringInput(input: $value) @@ -490,13 +492,13 @@ describe('Execute: Handles inputs', () => { } expect(caughtError).to.containSubset({ - locations: [ { line: 2, column: 31 } ], + locations: [{ line: 2, column: 31 }], message: 'Variable "$value" of required type "String!" was not provided.' }); }); - it('allows non-nullable inputs to be set to a value in a variable', async () => { + it("allows non-nullable inputs to be set to a value in a variable", async () => { const doc = ` query SetsNonNullable($value: String!) { fieldWithNonNullableStringInput(input: $value) @@ -505,7 +507,7 @@ describe('Execute: Handles inputs', () => { const ast = parse(doc); return expect( - await execute(schema, ast, null, null, { value: 'a' }) + await execute(schema, ast, null, null, { value: "a" }) ).to.deep.equal({ data: { fieldWithNonNullableStringInput: '"a"' @@ -513,7 +515,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('allows non-nullable inputs to be set to a value directly', async () => { + it("allows non-nullable inputs to be set to a value directly", async () => { const doc = ` { fieldWithNonNullableStringInput(input: "a") @@ -528,7 +530,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('passes along null for non-nullable inputs if explcitly set in the query', async () => { + it("passes along null for non-nullable inputs if explcitly set in the query", async () => { const doc = ` { fieldWithNonNullableStringInput @@ -544,8 +546,8 @@ describe('Execute: Handles inputs', () => { }); }); - describe('Handles lists and nullability', () => { - it('allows lists to be null', async () => { + describe("Handles lists and nullability", () => { + it("allows lists to be null", async () => { const doc = ` query q($input: [String]) { list(input: $input) @@ -562,7 +564,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('allows lists to contain values', async () => { + it("allows lists to contain values", async () => { const doc = ` query q($input: [String]) { list(input: $input) @@ -571,7 +573,7 @@ describe('Execute: Handles inputs', () => { const ast = parse(doc); return expect( - await execute(schema, ast, null, null, { input: [ 'A' ] }) + await execute(schema, ast, null, null, { input: ["A"] }) ).to.deep.equal({ data: { list: '["A"]' @@ -579,7 +581,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('allows lists to contain null', async () => { + it("allows lists to contain null", async () => { const doc = ` query q($input: [String]) { list(input: $input) @@ -588,7 +590,7 @@ describe('Execute: Handles inputs', () => { const ast = parse(doc); return expect( - await execute(schema, ast, null, null, { input: [ 'A', null, 'B' ] }) + await execute(schema, ast, null, null, { input: ["A", null, "B"] }) ).to.deep.equal({ data: { list: '["A",null,"B"]' @@ -596,7 +598,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('does not allow non-null lists to be null', async () => { + it("does not allow non-null lists to be null", async () => { const doc = ` query q($input: [String]!) { nnList(input: $input) @@ -612,13 +614,13 @@ describe('Execute: Handles inputs', () => { } expect(caughtError).to.containSubset({ - locations: [ { line: 2, column: 17 } ], + locations: [{ line: 2, column: 17 }], message: 'Variable "$input" of required type "[String]!" was not provided.' }); }); - it('allows non-null lists to contain values', async () => { + it("allows non-null lists to contain values", async () => { const doc = ` query q($input: [String]!) { nnList(input: $input) @@ -627,7 +629,7 @@ describe('Execute: Handles inputs', () => { const ast = parse(doc); return expect( - await execute(schema, ast, null, null, { input: [ 'A' ] }) + await execute(schema, ast, null, null, { input: ["A"] }) ).to.deep.equal({ data: { nnList: '["A"]' @@ -635,7 +637,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('allows non-null lists to contain null', async () => { + it("allows non-null lists to contain null", async () => { const doc = ` query q($input: [String]!) { nnList(input: $input) @@ -644,7 +646,7 @@ describe('Execute: Handles inputs', () => { const ast = parse(doc); return expect( - await execute(schema, ast, null, null, { input: [ 'A', null, 'B' ] }) + await execute(schema, ast, null, null, { input: ["A", null, "B"] }) ).to.deep.equal({ data: { nnList: '["A",null,"B"]' @@ -652,7 +654,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('allows lists of non-nulls to be null', async () => { + it("allows lists of non-nulls to be null", async () => { const doc = ` query q($input: [String!]) { listNN(input: $input) @@ -669,7 +671,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('allows lists of non-nulls to contain values', async () => { + it("allows lists of non-nulls to contain values", async () => { const doc = ` query q($input: [String!]) { listNN(input: $input) @@ -678,7 +680,7 @@ describe('Execute: Handles inputs', () => { const ast = parse(doc); return expect( - await execute(schema, ast, null, null, { input: [ 'A' ] }) + await execute(schema, ast, null, null, { input: ["A"] }) ).to.deep.equal({ data: { listNN: '["A"]' @@ -686,14 +688,14 @@ describe('Execute: Handles inputs', () => { }); }); - it('does not allow lists of non-nulls to contain null', async () => { + it("does not allow lists of non-nulls to contain null", async () => { const doc = ` query q($input: [String!]) { listNN(input: $input) } `; const ast = parse(doc); - const vars = { input: [ 'A', null, 'B' ] }; + const vars = { input: ["A", null, "B"] }; let caughtError; try { @@ -703,14 +705,14 @@ describe('Execute: Handles inputs', () => { } expect(caughtError).to.containSubset({ - locations: [ { line: 2, column: 17 } ], + locations: [{ line: 2, column: 17 }], message: 'Variable "$input" got invalid value ["A",null,"B"].' + '\nIn element #1: Expected "String!", found null.' }); }); - it('does not allow non-null lists of non-nulls to be null', async () => { + it("does not allow non-null lists of non-nulls to be null", async () => { const doc = ` query q($input: [String!]!) { nnListNN(input: $input) @@ -726,13 +728,13 @@ describe('Execute: Handles inputs', () => { } expect(caughtError).to.containSubset({ - locations: [ { line: 2, column: 17 } ], + locations: [{ line: 2, column: 17 }], message: 'Variable "$input" of required type "[String!]!" was not provided.' }); }); - it('allows non-null lists of non-nulls to contain values', async () => { + it("allows non-null lists of non-nulls to contain values", async () => { const doc = ` query q($input: [String!]!) { nnListNN(input: $input) @@ -741,7 +743,7 @@ describe('Execute: Handles inputs', () => { const ast = parse(doc); return expect( - await execute(schema, ast, null, null, { input: [ 'A' ] }) + await execute(schema, ast, null, null, { input: ["A"] }) ).to.deep.equal({ data: { nnListNN: '["A"]' @@ -749,14 +751,14 @@ describe('Execute: Handles inputs', () => { }); }); - it('does not allow non-null lists of non-nulls to contain null', async () => { + it("does not allow non-null lists of non-nulls to contain null", async () => { const doc = ` query q($input: [String!]!) { nnListNN(input: $input) } `; const ast = parse(doc); - const vars = { input: [ 'A', null, 'B' ] }; + const vars = { input: ["A", null, "B"] }; let caughtError; try { @@ -766,21 +768,21 @@ describe('Execute: Handles inputs', () => { } expect(caughtError).to.containSubset({ - locations: [ { line: 2, column: 17 } ], + locations: [{ line: 2, column: 17 }], message: 'Variable "$input" got invalid value ["A",null,"B"].' + '\nIn element #1: Expected "String!", found null.' }); }); - it('does not allow invalid types to be used as values', async () => { + it("does not allow invalid types to be used as values", async () => { const doc = ` query q($input: TestType!) { fieldWithObjectInput(input: $input) } `; const ast = parse(doc); - const vars = { input: { list: [ 'A', 'B' ] } }; + const vars = { input: { list: ["A", "B"] } }; let caughtError; try { @@ -790,21 +792,21 @@ describe('Execute: Handles inputs', () => { } expect(caughtError).to.containSubset({ - locations: [ { line: 2, column: 17 } ], + locations: [{ line: 2, column: 17 }], message: 'Variable "$input" expected value of type "TestType!" which cannot ' + - 'be used as an input type.' + "be used as an input type." }); }); - it('does not allow unknown types to be used as values', async () => { + it("does not allow unknown types to be used as values", async () => { const doc = ` query q($input: UnknownType!) { fieldWithObjectInput(input: $input) } `; const ast = parse(doc); - const vars = { input: 'whoknows' }; + const vars = { input: "whoknows" }; let caughtError; try { @@ -814,18 +816,16 @@ describe('Execute: Handles inputs', () => { } expect(caughtError).to.containSubset({ - locations: [ { line: 2, column: 17 } ], + locations: [{ line: 2, column: 17 }], message: 'Variable "$input" expected value of type "UnknownType!" which ' + - 'cannot be used as an input type.' + "cannot be used as an input type." }); }); - }); - describe('Execute: Uses argument default values', () => { - - it('when no argument provided', async () => { + describe("Execute: Uses argument default values", () => { + it("when no argument provided", async () => { const ast = parse(`{ fieldWithDefaultArgumentValue }`); @@ -837,7 +837,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('when nullable variable provided', async () => { + it("when nullable variable provided", async () => { const ast = parse(`query optionalVariable($optional: String) { fieldWithDefaultArgumentValue(input: $optional) }`); @@ -849,7 +849,7 @@ describe('Execute: Handles inputs', () => { }); }); - it('when argument provided cannot be parsed', async () => { + it("when argument provided cannot be parsed", async () => { const ast = parse(`{ fieldWithDefaultArgumentValue(input: WRONG_TYPE) }`); @@ -860,7 +860,5 @@ describe('Execute: Handles inputs', () => { } }); }); - }); - }); diff --git a/src/execution/execute.js b/src/execution/execute.js index 29e9de0e97..168d3f447a 100644 --- a/src/execution/execute.js +++ b/src/execution/execute.js @@ -8,13 +8,13 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { GraphQLError, locatedError } from '../error'; -import find from '../jsutils/find'; -import invariant from '../jsutils/invariant'; -import isNullish from '../jsutils/isNullish'; -import { typeFromAST } from '../utilities/typeFromAST'; -import { Kind } from '../language'; -import { getVariableValues, getArgumentValues } from './values'; +import { GraphQLError, locatedError } from "../error"; +import find from "../jsutils/find"; +import invariant from "../jsutils/invariant"; +import isNullish from "../jsutils/isNullish"; +import { typeFromAST } from "../utilities/typeFromAST"; +import { Kind } from "../language"; +import { getVariableValues, getArgumentValues } from "./values"; import { GraphQLScalarType, GraphQLObjectType, @@ -24,25 +24,25 @@ import { GraphQLInterfaceType, GraphQLUnionType, isAbstractType -} from '../type/definition'; +} from "../type/definition"; import type { GraphQLType, GraphQLLeafType, GraphQLAbstractType, GraphQLFieldDefinition, GraphQLFieldResolveFn, - GraphQLResolveInfo, -} from '../type/definition'; -import { GraphQLSchema } from '../type/schema'; + GraphQLResolveInfo +} from "../type/definition"; +import { GraphQLSchema } from "../type/schema"; import { SchemaMetaFieldDef, TypeMetaFieldDef, TypeNameMetaFieldDef -} from '../type/introspection'; +} from "../type/introspection"; import { GraphQLIncludeDirective, GraphQLSkipDirective -} from '../type/directives'; +} from "../type/directives"; import type { Directive, Document, @@ -51,8 +51,7 @@ import type { Field, InlineFragment, FragmentDefinition -} from '../language/ast'; - +} from "../language/ast"; /** * Terminology @@ -81,14 +80,14 @@ import type { * and the fragments defined in the query document */ type ExecutionContext = { - schema: GraphQLSchema; - fragments: {[key: string]: FragmentDefinition}; - rootValue: mixed; - contextValue: mixed; - operation: OperationDefinition; - variableValues: {[key: string]: mixed}; - errors: Array; -} + schema: GraphQLSchema, + fragments: { [key: string]: FragmentDefinition }, + rootValue: mixed, + contextValue: mixed, + operation: OperationDefinition, + variableValues: { [key: string]: mixed }, + errors: Array +}; /** * The result of execution. `data` is the result of executing the @@ -96,9 +95,9 @@ type ExecutionContext = { * non-empty array if an error occurred. */ type ExecutionResult = { - data: ?Object; - errors?: Array; -} + data: ?Object, + errors?: Array +}; /** * Implements the "Evaluating requests" section of the GraphQL specification. @@ -113,14 +112,14 @@ export function execute( documentAST: Document, rootValue?: mixed, contextValue?: mixed, - variableValues?: ?{[key: string]: mixed}, + variableValues?: ?{ [key: string]: mixed }, operationName?: ?string ): Promise { - invariant(schema, 'Must provide schema'); + invariant(schema, "Must provide schema"); invariant( schema instanceof GraphQLSchema, - 'Schema must be an instance of GraphQLSchema. Also ensure that there are ' + - 'not multiple versions of GraphQL installed in your node_modules directory.' + "Schema must be an instance of GraphQLSchema. Also ensure that there are " + + "not multiple versions of GraphQL installed in your node_modules directory." ); // If a valid context cannot be created due to incorrect arguments, @@ -143,18 +142,20 @@ export function execute( // resolved Promise. return new Promise(resolve => { resolve(executeOperation(context, context.operation, rootValue)); - }).catch(error => { - // Errors from sub-fields of a NonNull type may propagate to the top level, - // at which point we still log the error and null the parent field, which - // in this case is the entire response. - context.errors.push(error); - return null; - }).then(data => { - if (!context.errors.length) { - return { data }; - } - return { data, errors: context.errors }; - }); + }) + .catch(error => { + // Errors from sub-fields of a NonNull type may propagate to the top level, + // at which point we still log the error and null the parent field, which + // in this case is the entire response. + context.errors.push(error); + return null; + }) + .then(data => { + if (!context.errors.length) { + return { data }; + } + return { data, errors: context.errors }; + }); } /** @@ -168,39 +169,42 @@ function buildExecutionContext( documentAST: Document, rootValue: mixed, contextValue: mixed, - rawVariableValues: ?{[key: string]: mixed}, + rawVariableValues: ?{ [key: string]: mixed }, operationName: ?string ): ExecutionContext { const errors: Array = []; let operation: ?OperationDefinition; - const fragments: {[name: string]: FragmentDefinition} = Object.create(null); + const fragments: { [name: string]: FragmentDefinition } = Object.create(null); documentAST.definitions.forEach(definition => { switch (definition.kind) { case Kind.OPERATION_DEFINITION: if (!operationName && operation) { throw new GraphQLError( - 'Must provide operation name if query contains multiple operations.' + "Must provide operation name if query contains multiple operations." ); } - if (!operationName || - definition.name && definition.name.value === operationName) { + if ( + !operationName || + (definition.name && definition.name.value === operationName) + ) { operation = definition; } break; case Kind.FRAGMENT_DEFINITION: fragments[definition.name.value] = definition; break; - default: throw new GraphQLError( - `GraphQL cannot execute a request containing a ${definition.kind}.`, - definition - ); + default: + throw new GraphQLError( + `GraphQL cannot execute a request containing a ${definition.kind}.`, + definition + ); } }); if (!operation) { if (operationName) { throw new GraphQLError(`Unknown operation named "${operationName}".`); } else { - throw new GraphQLError('Must provide an operation.'); + throw new GraphQLError("Must provide an operation."); } } const variableValues = getVariableValues( @@ -237,7 +241,7 @@ function executeOperation( Object.create(null) ); - if (operation.operation === 'mutation') { + if (operation.operation === "mutation") { return executeFieldsSerially(exeContext, type, rootValue, fields); } return executeFields(exeContext, type, rootValue, fields); @@ -251,30 +255,28 @@ function getOperationRootType( operation: OperationDefinition ): GraphQLObjectType { switch (operation.operation) { - case 'query': + case "query": return schema.getQueryType(); - case 'mutation': + case "mutation": const mutationType = schema.getMutationType(); if (!mutationType) { - throw new GraphQLError( - 'Schema is not configured for mutations', - [ operation ] - ); + throw new GraphQLError("Schema is not configured for mutations", [ + operation + ]); } return mutationType; - case 'subscription': + case "subscription": const subscriptionType = schema.getSubscriptionType(); if (!subscriptionType) { - throw new GraphQLError( - 'Schema is not configured for subscriptions', - [ operation ] - ); + throw new GraphQLError("Schema is not configured for subscriptions", [ + operation + ]); } return subscriptionType; default: throw new GraphQLError( - 'Can only execute queries, mutations and subscriptions', - [ operation ] + "Can only execute queries, mutations and subscriptions", + [operation] ); } } @@ -287,29 +289,30 @@ function executeFieldsSerially( exeContext: ExecutionContext, parentType: GraphQLObjectType, sourceValue: mixed, - fields: {[key: string]: Array} + fields: { [key: string]: Array } ): Promise { return Object.keys(fields).reduce( - (prevPromise, responseName) => prevPromise.then(results => { - const fieldASTs = fields[responseName]; - const result = resolveField( - exeContext, - parentType, - sourceValue, - fieldASTs - ); - if (result === undefined) { - return results; - } - if (isThenable(result)) { - return ((result: any): Promise).then(resolvedResult => { - results[responseName] = resolvedResult; + (prevPromise, responseName) => + prevPromise.then(results => { + const fieldASTs = fields[responseName]; + const result = resolveField( + exeContext, + parentType, + sourceValue, + fieldASTs + ); + if (result === undefined) { return results; - }); - } - results[responseName] = result; - return results; - }), + } + if (isThenable(result)) { + return ((result: any): Promise).then(resolvedResult => { + results[responseName] = resolvedResult; + return results; + }); + } + results[responseName] = result; + return results; + }), Promise.resolve({}) ); } @@ -322,30 +325,22 @@ function executeFields( exeContext: ExecutionContext, parentType: GraphQLObjectType, sourceValue: mixed, - fields: {[key: string]: Array} + fields: { [key: string]: Array } ): Object { let containsPromise = false; - const finalResults = Object.keys(fields).reduce( - (results, responseName) => { - const fieldASTs = fields[responseName]; - const result = resolveField( - exeContext, - parentType, - sourceValue, - fieldASTs - ); - if (result === undefined) { - return results; - } - results[responseName] = result; - if (isThenable(result)) { - containsPromise = true; - } + const finalResults = Object.keys(fields).reduce((results, responseName) => { + const fieldASTs = fields[responseName]; + const result = resolveField(exeContext, parentType, sourceValue, fieldASTs); + if (result === undefined) { return results; - }, - Object.create(null) - ); + } + results[responseName] = result; + if (isThenable(result)) { + containsPromise = true; + } + return results; + }, Object.create(null)); // If there are no promises, we can just return the object if (!containsPromise) { @@ -371,9 +366,9 @@ function collectFields( exeContext: ExecutionContext, runtimeType: GraphQLObjectType, selectionSet: SelectionSet, - fields: {[key: string]: Array}, - visitedFragmentNames: {[key: string]: boolean} -): {[key: string]: Array} { + fields: { [key: string]: Array }, + visitedFragmentNames: { [key: string]: boolean } +): { [key: string]: Array } { for (let i = 0; i < selectionSet.selections.length; i++) { const selection = selectionSet.selections[i]; switch (selection.kind) { @@ -388,8 +383,10 @@ function collectFields( fields[name].push(selection); break; case Kind.INLINE_FRAGMENT: - if (!shouldIncludeNode(exeContext, selection.directives) || - !doesFragmentConditionMatch(exeContext, selection, runtimeType)) { + if ( + !shouldIncludeNode(exeContext, selection.directives) || + !doesFragmentConditionMatch(exeContext, selection, runtimeType) + ) { continue; } collectFields( @@ -402,14 +399,18 @@ function collectFields( break; case Kind.FRAGMENT_SPREAD: const fragName = selection.name.value; - if (visitedFragmentNames[fragName] || - !shouldIncludeNode(exeContext, selection.directives)) { + if ( + visitedFragmentNames[fragName] || + !shouldIncludeNode(exeContext, selection.directives) + ) { continue; } visitedFragmentNames[fragName] = true; const fragment = exeContext.fragments[fragName]; - if (!fragment || - !doesFragmentConditionMatch(exeContext, fragment, runtimeType)) { + if ( + !fragment || + !doesFragmentConditionMatch(exeContext, fragment, runtimeType) + ) { continue; } collectFields( @@ -433,10 +434,12 @@ function shouldIncludeNode( exeContext: ExecutionContext, directives: ?Array ): boolean { - const skipAST = directives && find( - directives, - directive => directive.name.value === GraphQLSkipDirective.name - ); + const skipAST = + directives && + find( + directives, + directive => directive.name.value === GraphQLSkipDirective.name + ); if (skipAST) { const { if: skipIf } = getArgumentValues( GraphQLSkipDirective.args, @@ -448,10 +451,12 @@ function shouldIncludeNode( } } - const includeAST = directives && find( - directives, - directive => directive.name.value === GraphQLIncludeDirective.name - ); + const includeAST = + directives && + find( + directives, + directive => directive.name.value === GraphQLIncludeDirective.name + ); if (includeAST) { const { if: includeIf } = getArgumentValues( GraphQLIncludeDirective.args, @@ -496,13 +501,13 @@ function doesFragmentConditionMatch( * This is akin to bluebird's `Promise.props`, but implemented only using * `Promise.all` so it will work with any implementation of ES6 promises. */ -function promiseForObject( - object: {[key: string]: Promise} -): Promise<{[key: string]: T}> { +function promiseForObject(object: { + [key: string]: Promise +}): Promise<{ [key: string]: T }> { const keys = Object.keys(object); const valuesAndPromises = keys.map(name => object[name]); - return Promise.all(valuesAndPromises).then( - values => values.reduce((resolvedObject, value, i) => { + return Promise.all(valuesAndPromises).then(values => + values.reduce((resolvedObject, value, i) => { resolvedObject[keys[i]] = value; return resolvedObject; }, Object.create(null)) @@ -564,7 +569,7 @@ function resolveField( fragments: exeContext.fragments, rootValue: exeContext.rootValue, operation: exeContext.operation, - variableValues: exeContext.variableValues, + variableValues: exeContext.variableValues }; // Get the resolve function, regardless of if its result is normal @@ -674,13 +679,8 @@ function completeValue( if (isThenable(result)) { return ((result: any): Promise).then( // Once resolved to a value, complete that value. - resolved => completeValue( - exeContext, - returnType, - fieldASTs, - info, - resolved - ), + resolved => + completeValue(exeContext, returnType, fieldASTs, info, resolved), // If rejected, create a located error, and continue to reject. error => Promise.reject(locatedError(error, fieldASTs)) ); @@ -703,8 +703,9 @@ function completeValue( ); if (completed === null) { throw new GraphQLError( - `Cannot return null for non-nullable field ${ - info.parentType}.${info.fieldName}.`, + `Cannot return null for non-nullable field ${info.parentType}.${ + info.fieldName + }.`, fieldASTs ); } @@ -723,15 +724,19 @@ function completeValue( // If field type is a leaf type, Scalar or Enum, serialize to a valid value, // returning null if serialization is not possible. - if (returnType instanceof GraphQLScalarType || - returnType instanceof GraphQLEnumType) { + if ( + returnType instanceof GraphQLScalarType || + returnType instanceof GraphQLEnumType + ) { return completeLeafValue(returnType, result); } // If field type is an abstract type, Interface or Union, determine the // runtime Object type and complete for that type. - if (returnType instanceof GraphQLInterfaceType || - returnType instanceof GraphQLUnionType) { + if ( + returnType instanceof GraphQLInterfaceType || + returnType instanceof GraphQLUnionType + ) { return completeAbstractValue( exeContext, returnType, @@ -743,20 +748,11 @@ function completeValue( // If field type is Object, execute and complete all sub-selections. if (returnType instanceof GraphQLObjectType) { - return completeObjectValue( - exeContext, - returnType, - fieldASTs, - info, - result - ); + return completeObjectValue(exeContext, returnType, fieldASTs, info, result); } // Not reachable. All possible output types have been considered. - invariant( - false, - `Cannot complete value of unexpected type "${returnType}".` - ); + invariant(false, `Cannot complete value of unexpected type "${returnType}".`); } /** @@ -773,7 +769,8 @@ function completeListValue( invariant( Array.isArray(result), `User Error: expected iterable, but did not find one for field ${ - info.parentType}.${info.fieldName}.` + info.parentType + }.${info.fieldName}.` ); // This is specified as a simple map, however we're optimizing the path @@ -781,8 +778,13 @@ function completeListValue( const itemType = returnType.ofType; let containsPromise = false; const completedResults = result.map(item => { - const completedItem = - completeValueCatchingError(exeContext, itemType, fieldASTs, info, item); + const completedItem = completeValueCatchingError( + exeContext, + itemType, + fieldASTs, + info, + item + ); if (!containsPromise && isThenable(completedItem)) { containsPromise = true; } @@ -796,11 +798,8 @@ function completeListValue( * Complete a Scalar or Enum by serializing to a valid value, returning * null if serialization is not possible. */ -function completeLeafValue( - returnType: GraphQLLeafType, - result: mixed -): mixed { - invariant(returnType.serialize, 'Missing serialize method on type'); +function completeLeafValue(returnType: GraphQLLeafType, result: mixed): mixed { + invariant(returnType.serialize, "Missing serialize method on type"); const serializedResult = returnType.serialize(result); return isNullish(serializedResult) ? null : serializedResult; } @@ -816,15 +815,17 @@ function completeAbstractValue( info: GraphQLResolveInfo, result: mixed ): mixed { - const runtimeType = returnType.resolveType ? - returnType.resolveType(result, exeContext.contextValue, info) : - defaultResolveTypeFn(result, exeContext.contextValue, info, returnType); + const runtimeType = returnType.resolveType + ? returnType.resolveType(result, exeContext.contextValue, info) + : defaultResolveTypeFn(result, exeContext.contextValue, info, returnType); if (!(runtimeType instanceof GraphQLObjectType)) { throw new GraphQLError( `Abstract type ${returnType} must resolve to an Object type at runtime ` + - `for field ${info.parentType}.${info.fieldName} with value "${result}",` + - `received "${runtimeType}".`, + `for field ${info.parentType}.${ + info.fieldName + } with value "${result}",` + + `received "${runtimeType}".`, fieldASTs ); } @@ -832,18 +833,12 @@ function completeAbstractValue( if (!exeContext.schema.isPossibleType(returnType, runtimeType)) { throw new GraphQLError( `Runtime Object type "${runtimeType}" is not a possible type ` + - `for "${returnType}".`, + `for "${returnType}".`, fieldASTs ); } - return completeObjectValue( - exeContext, - runtimeType, - fieldASTs, - info, - result - ); + return completeObjectValue(exeContext, runtimeType, fieldASTs, info, result); } /** @@ -859,8 +854,10 @@ function completeObjectValue( // If there is an isTypeOf predicate function, call it with the // current result. If isTypeOf returns false, then raise an error rather // than continuing execution. - if (returnType.isTypeOf && - !returnType.isTypeOf(result, exeContext.contextValue, info)) { + if ( + returnType.isTypeOf && + !returnType.isTypeOf(result, exeContext.contextValue, info) + ) { throw new GraphQLError( `Expected value of type "${returnType}" but got: ${result}.`, fieldASTs @@ -914,9 +911,9 @@ function defaultResolveTypeFn( */ function defaultResolveFn(source: any, args, context, { fieldName }) { // ensure source is a value for which property access is acceptable. - if (typeof source === 'object' || typeof source === 'function') { + if (typeof source === "object" || typeof source === "function") { const property = source[fieldName]; - return typeof property === 'function' ? source[fieldName]() : property; + return typeof property === "function" ? source[fieldName]() : property; } } @@ -925,9 +922,11 @@ function defaultResolveFn(source: any, args, context, { fieldName }) { * function. */ function isThenable(value: mixed): boolean { - return typeof value === 'object' && + return ( + typeof value === "object" && value !== null && - typeof value.then === 'function'; + typeof value.then === "function" + ); } /** @@ -944,11 +943,15 @@ function getFieldDef( parentType: GraphQLObjectType, fieldName: string ): ?GraphQLFieldDefinition { - if (fieldName === SchemaMetaFieldDef.name && - schema.getQueryType() === parentType) { + if ( + fieldName === SchemaMetaFieldDef.name && + schema.getQueryType() === parentType + ) { return SchemaMetaFieldDef; - } else if (fieldName === TypeMetaFieldDef.name && - schema.getQueryType() === parentType) { + } else if ( + fieldName === TypeMetaFieldDef.name && + schema.getQueryType() === parentType + ) { return TypeMetaFieldDef; } else if (fieldName === TypeNameMetaFieldDef.name) { return TypeNameMetaFieldDef; diff --git a/src/execution/index.js b/src/execution/index.js index b1158009ef..56b728062b 100644 --- a/src/execution/index.js +++ b/src/execution/index.js @@ -7,4 +7,4 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -export { execute } from './execute'; +export { execute } from "./execute"; diff --git a/src/execution/values.js b/src/execution/values.js index 4447d13dc6..28944e9a85 100644 --- a/src/execution/values.js +++ b/src/execution/values.js @@ -8,26 +8,25 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { GraphQLError } from '../error'; -import invariant from '../jsutils/invariant'; -import isNullish from '../jsutils/isNullish'; -import keyMap from '../jsutils/keyMap'; -import { typeFromAST } from '../utilities/typeFromAST'; -import { valueFromAST } from '../utilities/valueFromAST'; -import { isValidJSValue } from '../utilities/isValidJSValue'; -import { print } from '../language/printer'; +import { GraphQLError } from "../error"; +import invariant from "../jsutils/invariant"; +import isNullish from "../jsutils/isNullish"; +import keyMap from "../jsutils/keyMap"; +import { typeFromAST } from "../utilities/typeFromAST"; +import { valueFromAST } from "../utilities/valueFromAST"; +import { isValidJSValue } from "../utilities/isValidJSValue"; +import { print } from "../language/printer"; import { isInputType, GraphQLScalarType, GraphQLEnumType, GraphQLInputObjectType, GraphQLList, - GraphQLNonNull, -} from '../type/definition'; -import type { GraphQLInputType, GraphQLArgument } from '../type/definition'; -import type { GraphQLSchema } from '../type/schema'; -import type { Argument, VariableDefinition } from '../language/ast'; - + GraphQLNonNull +} from "../type/definition"; +import type { GraphQLInputType, GraphQLArgument } from "../type/definition"; +import type { GraphQLSchema } from "../type/schema"; +import type { Argument, VariableDefinition } from "../language/ast"; /** * Prepares an object map of variableValues of the correct type based on the @@ -46,7 +45,6 @@ export function getVariableValues( }, {}); } - /** * Prepares an object map of argument values given a list of argument * definitions and list of argument AST nodes. @@ -74,7 +72,6 @@ export function getArgumentValues( }, {}); } - /** * Given a variable definition, and any value of input, return a value which * adheres to the variable definition, or throw an error. @@ -89,8 +86,8 @@ function getVariableValue( if (!type || !isInputType(type)) { throw new GraphQLError( `Variable "$${variable.name.value}" expected value of type ` + - `"${print(definitionAST.type)}" which cannot be used as an input type.`, - [ definitionAST ] + `"${print(definitionAST.type)}" which cannot be used as an input type.`, + [definitionAST] ); } const inputType = ((type: any): GraphQLInputType); @@ -107,15 +104,15 @@ function getVariableValue( if (isNullish(input)) { throw new GraphQLError( `Variable "$${variable.name.value}" of required type ` + - `"${print(definitionAST.type)}" was not provided.`, - [ definitionAST ] + `"${print(definitionAST.type)}" was not provided.`, + [definitionAST] ); } - const message = errors ? '\n' + errors.join('\n') : ''; + const message = errors ? "\n" + errors.join("\n") : ""; throw new GraphQLError( `Variable "$${variable.name.value}" got invalid value ` + - `${JSON.stringify(input)}.${message}`, - [ definitionAST ] + `${JSON.stringify(input)}.${message}`, + [definitionAST] ); } @@ -142,11 +139,11 @@ function coerceValue(type: GraphQLInputType, value: mixed): mixed { if (Array.isArray(_value)) { return _value.map(item => coerceValue(itemType, item)); } - return [ coerceValue(itemType, _value) ]; + return [coerceValue(itemType, _value)]; } if (type instanceof GraphQLInputObjectType) { - if (typeof _value !== 'object' || _value === null) { + if (typeof _value !== "object" || _value === null) { return null; } const fields = type.getFields(); @@ -165,7 +162,7 @@ function coerceValue(type: GraphQLInputType, value: mixed): mixed { invariant( type instanceof GraphQLScalarType || type instanceof GraphQLEnumType, - 'Must be input type' + "Must be input type" ); const parsed = type.parseValue(_value); diff --git a/src/graphql.js b/src/graphql.js index 4e4a764c73..c647247c9b 100644 --- a/src/graphql.js +++ b/src/graphql.js @@ -8,13 +8,12 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { Source } from './language/source'; -import { parse } from './language/parser'; -import { validate } from './validation/validate'; -import { execute } from './execution/execute'; -import type { GraphQLError } from './error/GraphQLError'; -import type { GraphQLSchema } from './type/schema'; - +import { Source } from "./language/source"; +import { parse } from "./language/parser"; +import { validate } from "./validation/validate"; +import { execute } from "./execution/execute"; +import type { GraphQLError } from "./error/GraphQLError"; +import type { GraphQLSchema } from "./type/schema"; /** * This is the primary entry point function for fulfilling GraphQL operations @@ -45,11 +44,11 @@ export function graphql( requestString: string, rootValue?: mixed, contextValue?: mixed, - variableValues?: ?{[key: string]: mixed}, + variableValues?: ?{ [key: string]: mixed }, operationName?: ?string ): Promise { return new Promise(resolve => { - const source = new Source(requestString || '', 'GraphQL request'); + const source = new Source(requestString || "", "GraphQL request"); const documentAST = parse(source); const validationErrors = validate(schema, documentAST); if (validationErrors.length > 0) { @@ -67,7 +66,7 @@ export function graphql( ); } }).catch(error => { - return { errors: [ error ] }; + return { errors: [error] }; }); } @@ -78,6 +77,6 @@ export function graphql( * `errors` is included when any errors occurred as a non-empty array. */ type GraphQLResult = { - data?: ?Object; - errors?: Array; -} + data?: ?Object, + errors?: Array +}; diff --git a/src/index.js b/src/index.js index 949eaae073..4715c75350 100644 --- a/src/index.js +++ b/src/index.js @@ -33,15 +33,11 @@ */ // The primary entry point into fulfilling a GraphQL request. -export { - graphql -} from './graphql'; - +export { graphql } from "./graphql"; // Create and operate on GraphQL type definitions and schema. export { GraphQLSchema, - // Definitions GraphQLScalarType, GraphQLObjectType, @@ -51,14 +47,12 @@ export { GraphQLInputObjectType, GraphQLList, GraphQLNonNull, - // Scalars GraphQLInt, GraphQLFloat, GraphQLString, GraphQLBoolean, GraphQLID, - // Predicates isType, isInputType, @@ -66,102 +60,71 @@ export { isLeafType, isCompositeType, isAbstractType, - // Un-modifiers getNullableType, - getNamedType, -} from './type'; - + getNamedType +} from "./type"; // Parse and operate on GraphQL language source files. export { Source, getLocation, - // Parse parse, parseValue, - // Print print, - // Visit visit, visitInParallel, visitWithTypeInfo, Kind, - BREAK, -} from './language'; - + BREAK +} from "./language"; // Execute GraphQL queries. -export { - execute, -} from './execution'; - +export { execute } from "./execution"; // Validate GraphQL queries. -export { - validate, - specifiedRules, -} from './validation'; - +export { validate, specifiedRules } from "./validation"; // Create and format GraphQL errors. -export { - GraphQLError, - formatError, -} from './error'; - +export { GraphQLError, formatError } from "./error"; // Utilities for operating on GraphQL type schema and parsed sources. export { // The GraphQL query recommended for a full schema introspection. introspectionQuery, - // Gets the target Operation from a Document getOperationAST, - // Build a GraphQLSchema from an introspection result. buildClientSchema, - // Build a GraphQLSchema from a parsed GraphQL Schema language AST. buildASTSchema, - // Extends an existing GraphQLSchema from a parsed GraphQL Schema // language AST. extendSchema, - // Print a GraphQLSchema to GraphQL Schema language. printSchema, - // Create a GraphQLType from a GraphQL language AST. typeFromAST, - // Create a JavaScript value from a GraphQL language AST. valueFromAST, - // Create a GraphQL language AST from a JavaScript value. astFromValue, - // A helper to use within recursive-descent visitors which need to be aware of // the GraphQL type system. TypeInfo, - // Determine if JavaScript values adhere to a GraphQL type. isValidJSValue, - // Determine if AST values adhere to a GraphQL type. isValidLiteralValue, - // Concatenates multiple AST together. concatAST, - // Comparators for types isEqualType, isTypeSubTypeOf, doTypesOverlap, - // Asserts a string is a valid GraphQL name. - assertValidName, -} from './utilities'; + assertValidName +} from "./utilities"; diff --git a/src/jsutils/README.md b/src/jsutils/README.md index 8c1e5f97d3..9eb96485e1 100644 --- a/src/jsutils/README.md +++ b/src/jsutils/README.md @@ -1,5 +1,4 @@ -JavaScript Utils ----------------- +## JavaScript Utils This directory contains dependency-free JavaScript utility functions used throughout the codebase. diff --git a/src/jsutils/keyMap.js b/src/jsutils/keyMap.js index 5afd5b18b8..4b47d7bfc5 100644 --- a/src/jsutils/keyMap.js +++ b/src/jsutils/keyMap.js @@ -34,6 +34,6 @@ export default function keyMap( list: Array, keyFn: (item: T) => string -): {[key: string]: T} { +): { [key: string]: T } { return list.reduce((map, item) => ((map[keyFn(item)] = item), map), {}); } diff --git a/src/jsutils/keyValMap.js b/src/jsutils/keyValMap.js index 60ca478a80..ea922f2eb7 100644 --- a/src/jsutils/keyValMap.js +++ b/src/jsutils/keyValMap.js @@ -29,7 +29,7 @@ export default function keyValMap( list: Array, keyFn: (item: T) => string, valFn: (item: T) => V -): {[key: string]: V} { +): { [key: string]: V } { return list.reduce( (map, item) => ((map[keyFn(item)] = valFn(item)), map), {} diff --git a/src/language/README.md b/src/language/README.md index d5043f482c..68cc9fd4a7 100644 --- a/src/language/README.md +++ b/src/language/README.md @@ -1,5 +1,4 @@ -GraphQL Language ----------------- +## GraphQL Language The `graphql/language` module is responsible for parsing and operating on the GraphQL language. diff --git a/src/language/__tests__/kitchen-sink.graphql b/src/language/__tests__/kitchen-sink.graphql index 0e04e2e42d..093c63f7ab 100644 --- a/src/language/__tests__/kitchen-sink.graphql +++ b/src/language/__tests__/kitchen-sink.graphql @@ -7,12 +7,12 @@ query queryName($foo: ComplexType, $site: Site = MOBILE) { whoever123is: node(id: [123, 456]) { - id , + id ... on User @defer { field2 { - id , - alias: field1(first:10, after:$foo,) @include(if: $foo) { - id, + id + alias: field1(first: 10, after: $foo) @include(if: $foo) { + id ...frag } } @@ -48,10 +48,10 @@ subscription StoryLikeSubscription($input: StoryLikeSubscribeInput) { } fragment frag on Friend { - foo(size: $size, bar: $b, obj: {key: "value"}) + foo(size: $size, bar: $b, obj: { key: "value" }) } { - unnamed(truthy: true, falsey: false), + unnamed(truthy: true, falsey: false) query } diff --git a/src/language/__tests__/lexer-test.js b/src/language/__tests__/lexer-test.js index 040e6bdf57..f1ae2f375f 100644 --- a/src/language/__tests__/lexer-test.js +++ b/src/language/__tests__/lexer-test.js @@ -7,10 +7,10 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { Source } from '../source'; -import { lex, TokenKind } from '../lexer'; +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { Source } from "../source"; +import { lex, TokenKind } from "../lexer"; function lexOne(str) { return lex(new Source(str))(); @@ -20,30 +20,25 @@ function lexErr(str) { return lex(new Source(str)); } -describe('Lexer', () => { - - it('disallows uncommon control characters', () => { - - expect(lexErr('\u0007') - ).to.throw( +describe("Lexer", () => { + it("disallows uncommon control characters", () => { + expect(lexErr("\u0007")).to.throw( 'Syntax Error GraphQL (1:1) Invalid character "\\u0007"' ); - }); - it('accepts BOM header', () => { - expect(lexOne('\uFEFF foo') - ).to.deep.equal({ + it("accepts BOM header", () => { + expect(lexOne("\uFEFF foo")).to.deep.equal({ kind: TokenKind.NAME, start: 2, end: 5, - value: 'foo' + value: "foo" }); }); - it('skips whitespace', () => { - - expect(lexOne(` + it("skips whitespace", () => { + expect( + lexOne(` foo @@ -53,10 +48,11 @@ describe('Lexer', () => { kind: TokenKind.NAME, start: 6, end: 9, - value: 'foo' + value: "foo" }); - expect(lexOne(` + expect( + lexOne(` #comment foo#comment `) @@ -64,21 +60,20 @@ describe('Lexer', () => { kind: TokenKind.NAME, start: 18, end: 21, - value: 'foo' + value: "foo" }); - expect(lexOne(',,,foo,,,')).to.deep.equal({ + expect(lexOne(",,,foo,,,")).to.deep.equal({ kind: TokenKind.NAME, start: 3, end: 6, - value: 'foo' + value: "foo" }); - }); - it('errors respect whitespace', () => { - - expect(lexErr(` + it("errors respect whitespace", () => { + expect( + lexErr(` ? @@ -86,499 +81,388 @@ describe('Lexer', () => { `) ).to.throw( 'Syntax Error GraphQL (3:5) Unexpected character "?".\n' + - '\n' + - '2: \n' + - '3: ?\n' + - ' ^\n' + - '4: \n' + "\n" + + "2: \n" + + "3: ?\n" + + " ^\n" + + "4: \n" ); - }); - it('lexes strings', () => { - - expect( - lexOne('"simple"') - ).to.deep.equal({ + it("lexes strings", () => { + expect(lexOne('"simple"')).to.deep.equal({ kind: TokenKind.STRING, start: 0, end: 8, - value: 'simple' + value: "simple" }); - expect( - lexOne('" white space "') - ).to.deep.equal({ + expect(lexOne('" white space "')).to.deep.equal({ kind: TokenKind.STRING, start: 0, end: 15, - value: ' white space ' + value: " white space " }); - expect( - lexOne('"quote \\""') - ).to.deep.equal({ + expect(lexOne('"quote \\""')).to.deep.equal({ kind: TokenKind.STRING, start: 0, end: 10, value: 'quote "' }); - expect( - lexOne('"escaped \\n\\r\\b\\t\\f"') - ).to.deep.equal({ + expect(lexOne('"escaped \\n\\r\\b\\t\\f"')).to.deep.equal({ kind: TokenKind.STRING, start: 0, end: 20, - value: 'escaped \n\r\b\t\f' + value: "escaped \n\r\b\t\f" }); - expect( - lexOne('"slashes \\\\ \\/"') - ).to.deep.equal({ + expect(lexOne('"slashes \\\\ \\/"')).to.deep.equal({ kind: TokenKind.STRING, start: 0, end: 15, - value: 'slashes \\ \/' + value: "slashes \\ /" }); - expect( - lexOne('"unicode \\u1234\\u5678\\u90AB\\uCDEF"') - ).to.deep.equal({ + expect(lexOne('"unicode \\u1234\\u5678\\u90AB\\uCDEF"')).to.deep.equal({ kind: TokenKind.STRING, start: 0, end: 34, - value: 'unicode \u1234\u5678\u90AB\uCDEF' + value: "unicode \u1234\u5678\u90AB\uCDEF" }); - }); - it('lex reports useful string errors', () => { - - expect( - lexErr('"') - ).to.throw('Syntax Error GraphQL (1:2) Unterminated string'); + it("lex reports useful string errors", () => { + expect(lexErr('"')).to.throw( + "Syntax Error GraphQL (1:2) Unterminated string" + ); - expect( - lexErr('"no end quote') - ).to.throw('Syntax Error GraphQL (1:14) Unterminated string'); + expect(lexErr('"no end quote')).to.throw( + "Syntax Error GraphQL (1:14) Unterminated string" + ); - expect( - lexErr('"contains unescaped \u0007 control char"') - ).to.throw( + expect(lexErr('"contains unescaped \u0007 control char"')).to.throw( 'Syntax Error GraphQL (1:21) Invalid character within String: "\\u0007".' ); - expect( - lexErr('"null-byte is not \u0000 end of file"') - ).to.throw( + expect(lexErr('"null-byte is not \u0000 end of file"')).to.throw( 'Syntax Error GraphQL (1:19) Invalid character within String: "\\u0000".' ); - expect( - lexErr('"multi\nline"') - ).to.throw('Syntax Error GraphQL (1:7) Unterminated string'); + expect(lexErr('"multi\nline"')).to.throw( + "Syntax Error GraphQL (1:7) Unterminated string" + ); - expect( - lexErr('"multi\rline"') - ).to.throw('Syntax Error GraphQL (1:7) Unterminated string'); + expect(lexErr('"multi\rline"')).to.throw( + "Syntax Error GraphQL (1:7) Unterminated string" + ); - expect( - lexErr('"bad \\z esc"') - ).to.throw( - 'Syntax Error GraphQL (1:7) Invalid character escape sequence: \\z.' + expect(lexErr('"bad \\z esc"')).to.throw( + "Syntax Error GraphQL (1:7) Invalid character escape sequence: \\z." ); - expect( - lexErr('"bad \\x esc"') - ).to.throw( - 'Syntax Error GraphQL (1:7) Invalid character escape sequence: \\x.' + expect(lexErr('"bad \\x esc"')).to.throw( + "Syntax Error GraphQL (1:7) Invalid character escape sequence: \\x." ); - expect( - lexErr('"bad \\u1 esc"') - ).to.throw( - 'Syntax Error GraphQL (1:7) Invalid character escape sequence: \\u1 es.' + expect(lexErr('"bad \\u1 esc"')).to.throw( + "Syntax Error GraphQL (1:7) Invalid character escape sequence: \\u1 es." ); - expect( - lexErr('"bad \\u0XX1 esc"') - ).to.throw( - 'Syntax Error GraphQL (1:7) Invalid character escape sequence: \\u0XX1.' + expect(lexErr('"bad \\u0XX1 esc"')).to.throw( + "Syntax Error GraphQL (1:7) Invalid character escape sequence: \\u0XX1." ); - expect( - lexErr('"bad \\uXXXX esc"') - ).to.throw( - 'Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uXXXX.' + expect(lexErr('"bad \\uXXXX esc"')).to.throw( + "Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uXXXX." ); - expect( - lexErr('"bad \\uFXXX esc"') - ).to.throw( - 'Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uFXXX.' + expect(lexErr('"bad \\uFXXX esc"')).to.throw( + "Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uFXXX." ); - expect( - lexErr('"bad \\uXXXF esc"') - ).to.throw( - 'Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uXXXF.' + expect(lexErr('"bad \\uXXXF esc"')).to.throw( + "Syntax Error GraphQL (1:7) Invalid character escape sequence: \\uXXXF." ); }); - it('lexes numbers', () => { - - expect( - lexOne('4') - ).to.deep.equal({ + it("lexes numbers", () => { + expect(lexOne("4")).to.deep.equal({ kind: TokenKind.INT, start: 0, end: 1, - value: '4' + value: "4" }); - expect( - lexOne('4.123') - ).to.deep.equal({ + expect(lexOne("4.123")).to.deep.equal({ kind: TokenKind.FLOAT, start: 0, end: 5, - value: '4.123' + value: "4.123" }); - expect( - lexOne('-4') - ).to.deep.equal({ + expect(lexOne("-4")).to.deep.equal({ kind: TokenKind.INT, start: 0, end: 2, - value: '-4' + value: "-4" }); - expect( - lexOne('9') - ).to.deep.equal({ + expect(lexOne("9")).to.deep.equal({ kind: TokenKind.INT, start: 0, end: 1, - value: '9' + value: "9" }); - expect( - lexOne('0') - ).to.deep.equal({ + expect(lexOne("0")).to.deep.equal({ kind: TokenKind.INT, start: 0, end: 1, - value: '0' + value: "0" }); - expect( - lexOne('-4.123') - ).to.deep.equal({ + expect(lexOne("-4.123")).to.deep.equal({ kind: TokenKind.FLOAT, start: 0, end: 6, - value: '-4.123' + value: "-4.123" }); - expect( - lexOne('0.123') - ).to.deep.equal({ + expect(lexOne("0.123")).to.deep.equal({ kind: TokenKind.FLOAT, start: 0, end: 5, - value: '0.123' + value: "0.123" }); - expect( - lexOne('123e4') - ).to.deep.equal({ + expect(lexOne("123e4")).to.deep.equal({ kind: TokenKind.FLOAT, start: 0, end: 5, - value: '123e4' + value: "123e4" }); - expect( - lexOne('123E4') - ).to.deep.equal({ + expect(lexOne("123E4")).to.deep.equal({ kind: TokenKind.FLOAT, start: 0, end: 5, - value: '123E4' + value: "123E4" }); - expect( - lexOne('123e-4') - ).to.deep.equal({ + expect(lexOne("123e-4")).to.deep.equal({ kind: TokenKind.FLOAT, start: 0, end: 6, - value: '123e-4' + value: "123e-4" }); - expect( - lexOne('123e+4') - ).to.deep.equal({ + expect(lexOne("123e+4")).to.deep.equal({ kind: TokenKind.FLOAT, start: 0, end: 6, - value: '123e+4' + value: "123e+4" }); - expect( - lexOne('-1.123e4') - ).to.deep.equal({ + expect(lexOne("-1.123e4")).to.deep.equal({ kind: TokenKind.FLOAT, start: 0, end: 8, - value: '-1.123e4' + value: "-1.123e4" }); - expect( - lexOne('-1.123E4') - ).to.deep.equal({ + expect(lexOne("-1.123E4")).to.deep.equal({ kind: TokenKind.FLOAT, start: 0, end: 8, - value: '-1.123E4' + value: "-1.123E4" }); - expect( - lexOne('-1.123e-4') - ).to.deep.equal({ + expect(lexOne("-1.123e-4")).to.deep.equal({ kind: TokenKind.FLOAT, start: 0, end: 9, - value: '-1.123e-4' + value: "-1.123e-4" }); - expect( - lexOne('-1.123e+4') - ).to.deep.equal({ + expect(lexOne("-1.123e+4")).to.deep.equal({ kind: TokenKind.FLOAT, start: 0, end: 9, - value: '-1.123e+4' + value: "-1.123e+4" }); - expect( - lexOne('-1.123e4567') - ).to.deep.equal({ + expect(lexOne("-1.123e4567")).to.deep.equal({ kind: TokenKind.FLOAT, start: 0, end: 11, - value: '-1.123e4567' + value: "-1.123e4567" }); - }); - it('lex reports useful number errors', () => { - - expect( - lexErr('00') - ).to.throw( - 'Syntax Error GraphQL (1:2) Invalid number, ' + - 'unexpected digit after 0: "0".' + it("lex reports useful number errors", () => { + expect(lexErr("00")).to.throw( + "Syntax Error GraphQL (1:2) Invalid number, " + + 'unexpected digit after 0: "0".' ); - expect( - lexErr('+1') - ).to.throw('Syntax Error GraphQL (1:1) Unexpected character "+"'); + expect(lexErr("+1")).to.throw( + 'Syntax Error GraphQL (1:1) Unexpected character "+"' + ); - expect( - lexErr('1.') - ).to.throw( - 'Syntax Error GraphQL (1:3) Invalid number, ' + - 'expected digit but got: .' + expect(lexErr("1.")).to.throw( + "Syntax Error GraphQL (1:3) Invalid number, " + + "expected digit but got: ." ); - expect( - lexErr('.123') - ).to.throw('Syntax Error GraphQL (1:1) Unexpected character "."'); + expect(lexErr(".123")).to.throw( + 'Syntax Error GraphQL (1:1) Unexpected character "."' + ); - expect( - lexErr('1.A') - ).to.throw( - 'Syntax Error GraphQL (1:3) Invalid number, ' + - 'expected digit but got: "A".' + expect(lexErr("1.A")).to.throw( + "Syntax Error GraphQL (1:3) Invalid number, " + + 'expected digit but got: "A".' ); - expect( - lexErr('-A') - ).to.throw( - 'Syntax Error GraphQL (1:2) Invalid number, ' + - 'expected digit but got: "A".' + expect(lexErr("-A")).to.throw( + "Syntax Error GraphQL (1:2) Invalid number, " + + 'expected digit but got: "A".' ); - expect( - lexErr('1.0e') - ).to.throw( - 'Syntax Error GraphQL (1:5) Invalid number, ' + - 'expected digit but got: .'); + expect(lexErr("1.0e")).to.throw( + "Syntax Error GraphQL (1:5) Invalid number, " + + "expected digit but got: ." + ); - expect( - lexErr('1.0eA') - ).to.throw( - 'Syntax Error GraphQL (1:5) Invalid number, ' + - 'expected digit but got: "A".' + expect(lexErr("1.0eA")).to.throw( + "Syntax Error GraphQL (1:5) Invalid number, " + + 'expected digit but got: "A".' ); }); - it('lexes punctuation', () => { - - expect( - lexOne('!') - ).to.deep.equal({ + it("lexes punctuation", () => { + expect(lexOne("!")).to.deep.equal({ kind: TokenKind.BANG, start: 0, end: 1, value: undefined }); - expect( - lexOne('$') - ).to.deep.equal({ + expect(lexOne("$")).to.deep.equal({ kind: TokenKind.DOLLAR, start: 0, end: 1, value: undefined }); - expect( - lexOne('(') - ).to.deep.equal({ + expect(lexOne("(")).to.deep.equal({ kind: TokenKind.PAREN_L, start: 0, end: 1, value: undefined }); - expect( - lexOne(')') - ).to.deep.equal({ + expect(lexOne(")")).to.deep.equal({ kind: TokenKind.PAREN_R, start: 0, end: 1, value: undefined }); - expect( - lexOne('...') - ).to.deep.equal({ + expect(lexOne("...")).to.deep.equal({ kind: TokenKind.SPREAD, start: 0, end: 3, value: undefined }); - expect( - lexOne(':') - ).to.deep.equal({ + expect(lexOne(":")).to.deep.equal({ kind: TokenKind.COLON, start: 0, end: 1, value: undefined }); - expect( - lexOne('=') - ).to.deep.equal({ + expect(lexOne("=")).to.deep.equal({ kind: TokenKind.EQUALS, start: 0, end: 1, value: undefined }); - expect( - lexOne('@') - ).to.deep.equal({ + expect(lexOne("@")).to.deep.equal({ kind: TokenKind.AT, start: 0, end: 1, value: undefined }); - expect( - lexOne('[') - ).to.deep.equal({ + expect(lexOne("[")).to.deep.equal({ kind: TokenKind.BRACKET_L, start: 0, end: 1, value: undefined }); - expect( - lexOne(']') - ).to.deep.equal({ + expect(lexOne("]")).to.deep.equal({ kind: TokenKind.BRACKET_R, start: 0, end: 1, value: undefined }); - expect( - lexOne('{') - ).to.deep.equal({ + expect(lexOne("{")).to.deep.equal({ kind: TokenKind.BRACE_L, start: 0, end: 1, value: undefined }); - expect( - lexOne('|') - ).to.deep.equal({ + expect(lexOne("|")).to.deep.equal({ kind: TokenKind.PIPE, start: 0, end: 1, value: undefined }); - expect( - lexOne('}') - ).to.deep.equal({ + expect(lexOne("}")).to.deep.equal({ kind: TokenKind.BRACE_R, start: 0, end: 1, value: undefined }); - }); - it('lex reports useful unknown character error', () => { - - expect( - lexErr('..') - ).to.throw('Syntax Error GraphQL (1:1) Unexpected character "."'); + it("lex reports useful unknown character error", () => { + expect(lexErr("..")).to.throw( + 'Syntax Error GraphQL (1:1) Unexpected character "."' + ); - expect( - lexErr('?') - ).to.throw('Syntax Error GraphQL (1:1) Unexpected character "?"'); + expect(lexErr("?")).to.throw( + 'Syntax Error GraphQL (1:1) Unexpected character "?"' + ); - expect( - lexErr('\u203B') - ).to.throw('Syntax Error GraphQL (1:1) Unexpected character "\\u203B"'); + expect(lexErr("\u203B")).to.throw( + 'Syntax Error GraphQL (1:1) Unexpected character "\\u203B"' + ); - expect( - lexErr('\u200b') - ).to.throw('Syntax Error GraphQL (1:1) Unexpected character "\\u200B"'); + expect(lexErr("\u200b")).to.throw( + 'Syntax Error GraphQL (1:1) Unexpected character "\\u200B"' + ); }); - it('lex reports useful information for dashes in names', () => { - const q = 'a-b'; + it("lex reports useful information for dashes in names", () => { + const q = "a-b"; const lexer = lex(new Source(q)); const firstToken = lexer(); expect(firstToken).to.deep.equal({ kind: TokenKind.NAME, start: 0, end: 1, - value: 'a' + value: "a" }); - expect( - () => lexer() - ).to.throw( + expect(() => lexer()).to.throw( 'Syntax Error GraphQL (1:3) Invalid number, expected digit but got: "b".' ); }); diff --git a/src/language/__tests__/parser-test.js b/src/language/__tests__/parser-test.js index 7d7e968f87..1b227213b7 100644 --- a/src/language/__tests__/parser-test.js +++ b/src/language/__tests__/parser-test.js @@ -7,49 +7,55 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import * as Kind from '../kinds'; -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { parse } from '../parser'; -import { Source } from '../source'; -import { readFileSync } from 'fs'; -import { join } from 'path'; +import * as Kind from "../kinds"; +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { parse } from "../parser"; +import { Source } from "../source"; +import { readFileSync } from "fs"; +import { join } from "path"; -describe('Parser', () => { - - it('accepts option to not include source', () => { - expect(parse('{ field }', { noSource: true })).to.deep.equal({ - kind: 'Document', +describe("Parser", () => { + it("accepts option to not include source", () => { + expect(parse("{ field }", { noSource: true })).to.deep.equal({ + kind: "Document", loc: { start: 0, end: 9 }, - definitions: - [ { kind: 'OperationDefinition', - loc: { start: 0, end: 9 }, - operation: 'query', - name: null, - variableDefinitions: null, - directives: [], - selectionSet: { - kind: 'SelectionSet', - loc: { start: 0, end: 9 }, - selections: - [ { kind: 'Field', + definitions: [ + { + kind: "OperationDefinition", + loc: { start: 0, end: 9 }, + operation: "query", + name: null, + variableDefinitions: null, + directives: [], + selectionSet: { + kind: "SelectionSet", + loc: { start: 0, end: 9 }, + selections: [ + { + kind: "Field", + loc: { start: 2, end: 7 }, + alias: null, + name: { + kind: "Name", loc: { start: 2, end: 7 }, - alias: null, - name: - { kind: 'Name', - loc: { start: 2, end: 7 }, - value: 'field' }, - arguments: [], - directives: [], - selectionSet: null } ] } } ] + value: "field" + }, + arguments: [], + directives: [], + selectionSet: null + } + ] + } + } + ] }); }); - it('parse provides useful errors', () => { - + it("parse provides useful errors", () => { let caughtError; try { - parse('{'); + parse("{"); } catch (error) { caughtError = error; } @@ -62,70 +68,68 @@ describe('Parser', () => { ` ); - expect(caughtError.positions).to.deep.equal([ 1 ]); + expect(caughtError.positions).to.deep.equal([1]); - expect(caughtError.locations).to.deep.equal([ - { line: 1, column: 2 } - ]); + expect(caughtError.locations).to.deep.equal([{ line: 1, column: 2 }]); - expect( - () => parse( -`{ ...MissingOn } + expect(() => + parse( + `{ ...MissingOn } fragment MissingOn Type -`) +` + ) ).to.throw('Syntax Error GraphQL (2:20) Expected "on", found Name "Type"'); - expect( - () => parse('{ field: {} }') - ).to.throw('Syntax Error GraphQL (1:10) Expected Name, found {'); - - expect( - () => parse('notanoperation Foo { field }') - ).to.throw('Syntax Error GraphQL (1:1) Unexpected Name "notanoperation"'); + expect(() => parse("{ field: {} }")).to.throw( + "Syntax Error GraphQL (1:10) Expected Name, found {" + ); - expect( - () => parse('...') - ).to.throw('Syntax Error GraphQL (1:1) Unexpected ...'); + expect(() => parse("notanoperation Foo { field }")).to.throw( + 'Syntax Error GraphQL (1:1) Unexpected Name "notanoperation"' + ); + expect(() => parse("...")).to.throw( + "Syntax Error GraphQL (1:1) Unexpected ..." + ); }); - it('parse provides useful error when using source', () => { - expect( - () => parse(new Source('query', 'MyQuery.graphql')) - ).to.throw('Syntax Error MyQuery.graphql (1:6) Expected {, found EOF'); + it("parse provides useful error when using source", () => { + expect(() => parse(new Source("query", "MyQuery.graphql"))).to.throw( + "Syntax Error MyQuery.graphql (1:6) Expected {, found EOF" + ); }); - it('parses variable inline values', () => { - expect( - () => parse('{ field(complex: { a: { b: [ $var ] } }) }') + it("parses variable inline values", () => { + expect(() => + parse("{ field(complex: { a: { b: [ $var ] } }) }") ).to.not.throw(); }); - it('parses constant default values', () => { - expect( - () => parse('query Foo($x: Complex = { a: { b: [ $var ] } }) { field }') - ).to.throw('Syntax Error GraphQL (1:37) Unexpected $'); + it("parses constant default values", () => { + expect(() => + parse("query Foo($x: Complex = { a: { b: [ $var ] } }) { field }") + ).to.throw("Syntax Error GraphQL (1:37) Unexpected $"); }); it('does not accept fragments named "on"', () => { - expect( - () => parse('fragment on on on { on }') - ).to.throw('Syntax Error GraphQL (1:10) Unexpected Name "on"'); + expect(() => parse("fragment on on on { on }")).to.throw( + 'Syntax Error GraphQL (1:10) Unexpected Name "on"' + ); }); it('does not accept fragments spread of "on"', () => { - expect( - () => parse('{ ...on }') - ).to.throw('Syntax Error GraphQL (1:9) Expected Name, found }'); + expect(() => parse("{ ...on }")).to.throw( + "Syntax Error GraphQL (1:9) Expected Name, found }" + ); }); - it('does not allow null as value', async () => { - expect( - () => parse('{ fieldWithNullableStringInput(input: null) }') + it("does not allow null as value", async () => { + expect(() => + parse("{ fieldWithNullableStringInput(input: null) }") ).to.throw('Syntax Error GraphQL (1:39) Unexpected Name "null"'); }); - it('parses multi-byte characters', async () => { + it("parses multi-byte characters", async () => { // Note: \u0A0A could be naively interpretted as two line-feed chars. expect( parse(` @@ -133,45 +137,50 @@ fragment MissingOn Type { field(arg: "Has a \u0A0A multi-byte character.") } `) ).to.containSubset({ - definitions: [ { - selectionSet: { - selections: [ { - arguments: [ { - value: { - kind: Kind.STRING, - value: 'Has a \u0A0A multi-byte character.' + definitions: [ + { + selectionSet: { + selections: [ + { + arguments: [ + { + value: { + kind: Kind.STRING, + value: "Has a \u0A0A multi-byte character." + } + } + ] } - } ] - } ] + ] + } } - } ] + ] }); }); - const kitchenSink = readFileSync( - join(__dirname, '/kitchen-sink.graphql'), - { encoding: 'utf8' } - ); + const kitchenSink = readFileSync(join(__dirname, "/kitchen-sink.graphql"), { + encoding: "utf8" + }); - it('parses kitchen sink', () => { + it("parses kitchen sink", () => { expect(() => parse(kitchenSink)).to.not.throw(); }); - it('allows non-keywords anywhere a Name is allowed', () => { + it("allows non-keywords anywhere a Name is allowed", () => { const nonKeywords = [ - 'on', - 'fragment', - 'query', - 'mutation', - 'subscription', - 'true', - 'false' + "on", + "fragment", + "query", + "mutation", + "subscription", + "true", + "false" ]; nonKeywords.forEach(keyword => { let fragmentName = keyword; // You can't define or reference a fragment named `on`. - if (keyword === 'on') { - fragmentName = 'a'; + if (keyword === "on") { + fragmentName = "a"; } expect(() => { parse(`query ${keyword} { @@ -180,46 +189,52 @@ fragment MissingOn Type } fragment ${fragmentName} on Type { ${keyword}(${keyword}: $${keyword}) @${keyword}(${keyword}: ${keyword}) -}` - ); +}`); }).to.not.throw(); }); }); - it('parses anonymous mutation operations', () => { - expect(() => parse(` + it("parses anonymous mutation operations", () => { + expect(() => + parse(` mutation { mutationField } - `)).to.not.throw(); + `) + ).to.not.throw(); }); - it('parses anonymous subscription operations', () => { - expect(() => parse(` + it("parses anonymous subscription operations", () => { + expect(() => + parse(` subscription { subscriptionField } - `)).to.not.throw(); + `) + ).to.not.throw(); }); - it('parses named mutation operations', () => { - expect(() => parse(` + it("parses named mutation operations", () => { + expect(() => + parse(` mutation Foo { mutationField } - `)).to.not.throw(); + `) + ).to.not.throw(); }); - it('parses named subscription operations', () => { - expect(() => parse(` + it("parses named subscription operations", () => { + expect(() => + parse(` subscription Foo { subscriptionField } - `)).to.not.throw(); + `) + ).to.not.throw(); }); - it('parse creates ast', () => { - + it("parse creates ast", () => { const source = new Source(`{ node(id: 4) { id, @@ -229,63 +244,84 @@ fragment ${fragmentName} on Type { `); const result = parse(source); - expect(result).to.deep.equal( - { kind: Kind.DOCUMENT, - loc: { start: 0, end: 41, source }, - definitions: - [ { kind: Kind.OPERATION_DEFINITION, - loc: { start: 0, end: 40, source }, - operation: 'query', - name: null, - variableDefinitions: null, - directives: [], - selectionSet: - { kind: Kind.SELECTION_SET, - loc: { start: 0, end: 40, source }, - selections: - [ { kind: Kind.FIELD, - loc: { start: 4, end: 38, source }, - alias: null, - name: - { kind: Kind.NAME, - loc: { start: 4, end: 8, source }, - value: 'node' }, - arguments: - [ { kind: Kind.ARGUMENT, - name: - { kind: Kind.NAME, - loc: { start: 9, end: 11, source }, - value: 'id' }, - value: - { kind: Kind.INT, - loc: { start: 13, end: 14, source }, - value: '4' }, - loc: { start: 9, end: 14, source } } ], - directives: [], - selectionSet: - { kind: Kind.SELECTION_SET, - loc: { start: 16, end: 38, source }, - selections: - [ { kind: Kind.FIELD, - loc: { start: 22, end: 24, source }, - alias: null, - name: - { kind: Kind.NAME, - loc: { start: 22, end: 24, source }, - value: 'id' }, - arguments: [], - directives: [], - selectionSet: null }, - { kind: Kind.FIELD, - loc: { start: 30, end: 34, source }, - alias: null, - name: - { kind: Kind.NAME, - loc: { start: 30, end: 34, source }, - value: 'name' }, - arguments: [], - directives: [], - selectionSet: null } ] } } ] } } ] } - ); + expect(result).to.deep.equal({ + kind: Kind.DOCUMENT, + loc: { start: 0, end: 41, source }, + definitions: [ + { + kind: Kind.OPERATION_DEFINITION, + loc: { start: 0, end: 40, source }, + operation: "query", + name: null, + variableDefinitions: null, + directives: [], + selectionSet: { + kind: Kind.SELECTION_SET, + loc: { start: 0, end: 40, source }, + selections: [ + { + kind: Kind.FIELD, + loc: { start: 4, end: 38, source }, + alias: null, + name: { + kind: Kind.NAME, + loc: { start: 4, end: 8, source }, + value: "node" + }, + arguments: [ + { + kind: Kind.ARGUMENT, + name: { + kind: Kind.NAME, + loc: { start: 9, end: 11, source }, + value: "id" + }, + value: { + kind: Kind.INT, + loc: { start: 13, end: 14, source }, + value: "4" + }, + loc: { start: 9, end: 14, source } + } + ], + directives: [], + selectionSet: { + kind: Kind.SELECTION_SET, + loc: { start: 16, end: 38, source }, + selections: [ + { + kind: Kind.FIELD, + loc: { start: 22, end: 24, source }, + alias: null, + name: { + kind: Kind.NAME, + loc: { start: 22, end: 24, source }, + value: "id" + }, + arguments: [], + directives: [], + selectionSet: null + }, + { + kind: Kind.FIELD, + loc: { start: 30, end: 34, source }, + alias: null, + name: { + kind: Kind.NAME, + loc: { start: 30, end: 34, source }, + value: "name" + }, + arguments: [], + directives: [], + selectionSet: null + } + ] + } + } + ] + } + } + ] + }); }); }); diff --git a/src/language/__tests__/printer-test.js b/src/language/__tests__/printer-test.js index 2f8a416618..58c3a047aa 100644 --- a/src/language/__tests__/printer-test.js +++ b/src/language/__tests__/printer-test.js @@ -7,85 +7,86 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { parse } from '../parser'; -import { readFileSync } from 'fs'; -import { print } from '../printer'; -import { join } from 'path'; - -describe('Printer', () => { - it('does not alter ast', () => { +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { parse } from "../parser"; +import { readFileSync } from "fs"; +import { print } from "../printer"; +import { join } from "path"; + +describe("Printer", () => { + it("does not alter ast", () => { const ast = parse(kitchenSink); const astCopy = JSON.parse(JSON.stringify(ast)); print(ast); expect(ast).to.deep.equal(astCopy); }); - it('prints minimal ast', () => { - const ast = { kind: 'Field', name: { kind: 'Name', value: 'foo' } }; - expect(print(ast)).to.equal('foo'); + it("prints minimal ast", () => { + const ast = { kind: "Field", name: { kind: "Name", value: "foo" } }; + expect(print(ast)).to.equal("foo"); }); - it('produces helpful error messages', () => { - const badAst1 = { random: 'Data' }; + it("produces helpful error messages", () => { + const badAst1 = { random: "Data" }; expect(() => print(badAst1)).to.throw( 'Invalid AST Node: {"random":"Data"}' ); }); - it('correctly prints non-query operations without name', () => { - const queryAstShorthanded = parse('query { id, name }'); + it("correctly prints non-query operations without name", () => { + const queryAstShorthanded = parse("query { id, name }"); expect(print(queryAstShorthanded)).to.equal( -`{ + `{ id name } -`); +` + ); - const mutationAst = parse('mutation { id, name }'); + const mutationAst = parse("mutation { id, name }"); expect(print(mutationAst)).to.equal( -`mutation { + `mutation { id name } -`); +` + ); const queryAstWithArtifacts = parse( - 'query ($foo: TestType) @testDirective { id, name }' + "query ($foo: TestType) @testDirective { id, name }" ); expect(print(queryAstWithArtifacts)).to.equal( -`query ($foo: TestType) @testDirective { + `query ($foo: TestType) @testDirective { id name } -`); +` + ); const mutationAstWithArtifacts = parse( - 'mutation ($foo: TestType) @testDirective { id, name }' + "mutation ($foo: TestType) @testDirective { id, name }" ); expect(print(mutationAstWithArtifacts)).to.equal( -`mutation ($foo: TestType) @testDirective { + `mutation ($foo: TestType) @testDirective { id name } -`); +` + ); }); + const kitchenSink = readFileSync(join(__dirname, "/kitchen-sink.graphql"), { + encoding: "utf8" + }); - const kitchenSink = readFileSync( - join(__dirname, '/kitchen-sink.graphql'), - { encoding: 'utf8' } - ); - - it('prints kitchen sink', () => { - + it("prints kitchen sink", () => { const ast = parse(kitchenSink); const printed = print(ast); expect(printed).to.equal( - `query queryName($foo: ComplexType, $site: Site = MOBILE) { + `query queryName($foo: ComplexType, $site: Site = MOBILE) { whoever123is: node(id: [123, 456]) { id ... on User @defer { @@ -135,7 +136,7 @@ fragment frag on Friend { unnamed(truthy: true, falsey: false) query } -`); - +` + ); }); }); diff --git a/src/language/__tests__/schema-kitchen-sink.graphql b/src/language/__tests__/schema-kitchen-sink.graphql index e623ec4052..67eabfb169 100644 --- a/src/language/__tests__/schema-kitchen-sink.graphql +++ b/src/language/__tests__/schema-kitchen-sink.graphql @@ -16,7 +16,7 @@ type Foo implements Bar { three(argument: InputType, other: String): Int four(argument: String = "string"): String five(argument: [String] = ["string", "string"]): String - six(argument: InputType = {key: "value"}): Type + six(argument: InputType = { key: "value" }): Type } interface Bar { @@ -44,7 +44,4 @@ extend type Foo { directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT -directive @include(if: Boolean!) - on FIELD - | FRAGMENT_SPREAD - | INLINE_FRAGMENT +directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT diff --git a/src/language/__tests__/schema-parser-test.js b/src/language/__tests__/schema-parser-test.js index dea11e574b..e2c2408d8e 100644 --- a/src/language/__tests__/schema-parser-test.js +++ b/src/language/__tests__/schema-parser-test.js @@ -7,9 +7,9 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { parse } from '../parser'; +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { parse } from "../parser"; function createLocFn(body) { return (start, end) => ({ @@ -17,8 +17,8 @@ function createLocFn(body) { end, source: { body, - name: 'GraphQL', - }, + name: "GraphQL" + } }); } @@ -28,17 +28,17 @@ function printJson(obj) { function typeNode(name, loc) { return { - kind: 'NamedType', + kind: "NamedType", name: nameNode(name, loc), - loc, + loc }; } function nameNode(name, loc) { return { - kind: 'Name', + kind: "Name", value: name, - loc, + loc }; } @@ -48,34 +48,34 @@ function fieldNode(name, type, loc) { function fieldNodeWithArgs(name, type, args, loc) { return { - kind: 'FieldDefinition', + kind: "FieldDefinition", name, arguments: args, type, - loc, + loc }; } function enumValueNode(name, loc) { return { - kind: 'EnumValueDefinition', + kind: "EnumValueDefinition", name: nameNode(name, loc), - loc, + loc }; } function inputValueNode(name, type, defaultValue, loc) { return { - kind: 'InputValueDefinition', + kind: "InputValueDefinition", name, type, defaultValue, - loc, + loc }; } -describe('Schema Parser', () => { - it('Simple type', () => { +describe("Schema Parser", () => { + it("Simple type", () => { const body = ` type Hello { world: String @@ -83,28 +83,28 @@ type Hello { const doc = parse(body); const loc = createLocFn(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'ObjectTypeDefinition', - name: nameNode('Hello', loc(6, 11)), + kind: "ObjectTypeDefinition", + name: nameNode("Hello", loc(6, 11)), interfaces: [], fields: [ fieldNode( - nameNode('world', loc(16, 21)), - typeNode('String', loc(23, 29)), + nameNode("world", loc(16, 21)), + typeNode("String", loc(23, 29)), loc(16, 29) ) ], - loc: loc(1, 31), + loc: loc(1, 31) } ], - loc: loc(1, 31), + loc: loc(1, 31) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Simple extension', () => { + it("Simple extension", () => { const body = ` extend type Hello { world: String @@ -112,24 +112,24 @@ extend type Hello { const doc = parse(body); const loc = createLocFn(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'TypeExtensionDefinition', + kind: "TypeExtensionDefinition", definition: { - kind: 'ObjectTypeDefinition', - name: nameNode('Hello', loc(13, 18)), + kind: "ObjectTypeDefinition", + name: nameNode("Hello", loc(13, 18)), interfaces: [], fields: [ fieldNode( - nameNode('world', loc(23, 28)), - typeNode('String', loc(30, 36)), + nameNode("world", loc(23, 28)), + typeNode("String", loc(30, 36)), loc(23, 36) ) ], - loc: loc(8, 38), + loc: loc(8, 38) }, - loc: loc(1, 38), + loc: loc(1, 38) } ], loc: loc(1, 38) @@ -137,7 +137,7 @@ extend type Hello { expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Simple non-null type', () => { + it("Simple non-null type", () => { const body = ` type Hello { world: String! @@ -145,117 +145,116 @@ type Hello { const loc = createLocFn(body); const doc = parse(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'ObjectTypeDefinition', - name: nameNode('Hello', loc(6, 11)), + kind: "ObjectTypeDefinition", + name: nameNode("Hello", loc(6, 11)), interfaces: [], fields: [ fieldNode( - nameNode('world', loc(16, 21)), + nameNode("world", loc(16, 21)), { - kind: 'NonNullType', - type: typeNode('String', loc(23, 29)), - loc: loc(23, 30), + kind: "NonNullType", + type: typeNode("String", loc(23, 29)), + loc: loc(23, 30) }, loc(16, 30) ) ], - loc: loc(1, 32), + loc: loc(1, 32) } ], - loc: loc(1, 32), + loc: loc(1, 32) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - - it('Simple type inheriting interface', () => { - const body = 'type Hello implements World { }'; + it("Simple type inheriting interface", () => { + const body = "type Hello implements World { }"; const loc = createLocFn(body); const doc = parse(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'ObjectTypeDefinition', - name: nameNode('Hello', loc(5, 10)), - interfaces: [ typeNode('World', loc(22, 27)) ], + kind: "ObjectTypeDefinition", + name: nameNode("Hello", loc(5, 10)), + interfaces: [typeNode("World", loc(22, 27))], fields: [], - loc: loc(0, 31), + loc: loc(0, 31) } ], - loc: loc(0, 31), + loc: loc(0, 31) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Simple type inheriting multiple interfaces', () => { - const body = 'type Hello implements Wo, rld { }'; + it("Simple type inheriting multiple interfaces", () => { + const body = "type Hello implements Wo, rld { }"; const loc = createLocFn(body); const doc = parse(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'ObjectTypeDefinition', - name: nameNode('Hello', loc(5, 10)), + kind: "ObjectTypeDefinition", + name: nameNode("Hello", loc(5, 10)), interfaces: [ - typeNode('Wo', loc(22, 24)), - typeNode('rld', loc(26, 29)) + typeNode("Wo", loc(22, 24)), + typeNode("rld", loc(26, 29)) ], fields: [], - loc: loc(0, 33), + loc: loc(0, 33) } ], - loc: loc(0, 33), + loc: loc(0, 33) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Single value enum', () => { - const body = 'enum Hello { WORLD }'; + it("Single value enum", () => { + const body = "enum Hello { WORLD }"; const loc = createLocFn(body); const doc = parse(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'EnumTypeDefinition', - name: nameNode('Hello', loc(5, 10)), - values: [ enumValueNode('WORLD', loc(13, 18)) ], - loc: loc(0, 20), + kind: "EnumTypeDefinition", + name: nameNode("Hello", loc(5, 10)), + values: [enumValueNode("WORLD", loc(13, 18))], + loc: loc(0, 20) } ], - loc: loc(0, 20), + loc: loc(0, 20) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Double value enum', () => { - const body = 'enum Hello { WO, RLD }'; + it("Double value enum", () => { + const body = "enum Hello { WO, RLD }"; const loc = createLocFn(body); const doc = parse(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'EnumTypeDefinition', - name: nameNode('Hello', loc(5, 10)), + kind: "EnumTypeDefinition", + name: nameNode("Hello", loc(5, 10)), values: [ - enumValueNode('WO', loc(13, 15)), - enumValueNode('RLD', loc(17, 20)), + enumValueNode("WO", loc(13, 15)), + enumValueNode("RLD", loc(17, 20)) ], - loc: loc(0, 22), + loc: loc(0, 22) } ], - loc: loc(0, 22), + loc: loc(0, 22) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Simple interface', () => { + it("Simple interface", () => { const body = ` interface Hello { world: String @@ -263,27 +262,27 @@ interface Hello { const doc = parse(body); const loc = createLocFn(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'InterfaceTypeDefinition', - name: nameNode('Hello', loc(11, 16)), + kind: "InterfaceTypeDefinition", + name: nameNode("Hello", loc(11, 16)), fields: [ fieldNode( - nameNode('world', loc(21, 26)), - typeNode('String', loc(28, 34)), + nameNode("world", loc(21, 26)), + typeNode("String", loc(28, 34)), loc(21, 34) ) ], - loc: loc(1, 36), + loc: loc(1, 36) } ], - loc: loc(1, 36), + loc: loc(1, 36) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Simple field with arg', () => { + it("Simple field with arg", () => { const body = ` type Hello { world(flag: Boolean): String @@ -291,20 +290,20 @@ type Hello { const doc = parse(body); const loc = createLocFn(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'ObjectTypeDefinition', - name: nameNode('Hello', loc(6, 11)), + kind: "ObjectTypeDefinition", + name: nameNode("Hello", loc(6, 11)), interfaces: [], fields: [ fieldNodeWithArgs( - nameNode('world', loc(16, 21)), - typeNode('String', loc(38, 44)), + nameNode("world", loc(16, 21)), + typeNode("String", loc(38, 44)), [ inputValueNode( - nameNode('flag', loc(22, 26)), - typeNode('Boolean', loc(28, 35)), + nameNode("flag", loc(22, 26)), + typeNode("Boolean", loc(28, 35)), null, loc(22, 35) ) @@ -312,15 +311,15 @@ type Hello { loc(16, 44) ) ], - loc: loc(1, 46), + loc: loc(1, 46) } ], - loc: loc(1, 46), + loc: loc(1, 46) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Simple field with arg with default value', () => { + it("Simple field with arg with default value", () => { const body = ` type Hello { world(flag: Boolean = true): String @@ -328,24 +327,24 @@ type Hello { const doc = parse(body); const loc = createLocFn(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'ObjectTypeDefinition', - name: nameNode('Hello', loc(6, 11)), + kind: "ObjectTypeDefinition", + name: nameNode("Hello", loc(6, 11)), interfaces: [], fields: [ fieldNodeWithArgs( - nameNode('world', loc(16, 21)), - typeNode('String', loc(45, 51)), + nameNode("world", loc(16, 21)), + typeNode("String", loc(45, 51)), [ inputValueNode( - nameNode('flag', loc(22, 26)), - typeNode('Boolean', loc(28, 35)), + nameNode("flag", loc(22, 26)), + typeNode("Boolean", loc(28, 35)), { - kind: 'BooleanValue', + kind: "BooleanValue", value: true, - loc: loc(38, 42), + loc: loc(38, 42) }, loc(22, 42) ) @@ -353,15 +352,15 @@ type Hello { loc(16, 51) ) ], - loc: loc(1, 53), + loc: loc(1, 53) } ], - loc: loc(1, 53), + loc: loc(1, 53) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Simple field with list arg', () => { + it("Simple field with list arg", () => { const body = ` type Hello { world(things: [String]): String @@ -369,22 +368,22 @@ type Hello { const doc = parse(body); const loc = createLocFn(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'ObjectTypeDefinition', - name: nameNode('Hello', loc(6, 11)), + kind: "ObjectTypeDefinition", + name: nameNode("Hello", loc(6, 11)), interfaces: [], fields: [ fieldNodeWithArgs( - nameNode('world', loc(16, 21)), - typeNode('String', loc(41, 47)), + nameNode("world", loc(16, 21)), + typeNode("String", loc(41, 47)), [ inputValueNode( - nameNode('things', loc(22, 28)), + nameNode("things", loc(22, 28)), { - kind: 'ListType', - type: typeNode('String', loc(31, 37)), + kind: "ListType", + type: typeNode("String", loc(31, 37)), loc: loc(30, 38) }, null, @@ -394,15 +393,15 @@ type Hello { loc(16, 47) ) ], - loc: loc(1, 49), + loc: loc(1, 49) } ], - loc: loc(1, 49), + loc: loc(1, 49) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Simple field with two args', () => { + it("Simple field with two args", () => { const body = ` type Hello { world(argOne: Boolean, argTwo: Int): String @@ -410,101 +409,98 @@ type Hello { const doc = parse(body); const loc = createLocFn(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'ObjectTypeDefinition', - name: nameNode('Hello', loc(6, 11)), + kind: "ObjectTypeDefinition", + name: nameNode("Hello", loc(6, 11)), interfaces: [], fields: [ fieldNodeWithArgs( - nameNode('world', loc(16, 21)), - typeNode('String', loc(53, 59)), + nameNode("world", loc(16, 21)), + typeNode("String", loc(53, 59)), [ inputValueNode( - nameNode('argOne', loc(22, 28)), - typeNode('Boolean', loc(30, 37)), + nameNode("argOne", loc(22, 28)), + typeNode("Boolean", loc(30, 37)), null, loc(22, 37) ), inputValueNode( - nameNode('argTwo', loc(39, 45)), - typeNode('Int', loc(47, 50)), + nameNode("argTwo", loc(39, 45)), + typeNode("Int", loc(47, 50)), null, loc(39, 50) - ), + ) ], loc(16, 59) ) ], - loc: loc(1, 61), + loc: loc(1, 61) } ], - loc: loc(1, 61), + loc: loc(1, 61) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Simple union', () => { - const body = 'union Hello = World'; + it("Simple union", () => { + const body = "union Hello = World"; const doc = parse(body); const loc = createLocFn(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'UnionTypeDefinition', - name: nameNode('Hello', loc(6, 11)), - types: [ typeNode('World', loc(14, 19)) ], - loc: loc(0, 19), + kind: "UnionTypeDefinition", + name: nameNode("Hello", loc(6, 11)), + types: [typeNode("World", loc(14, 19))], + loc: loc(0, 19) } ], - loc: loc(0, 19), + loc: loc(0, 19) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Union with two types', () => { - const body = 'union Hello = Wo | Rld'; + it("Union with two types", () => { + const body = "union Hello = Wo | Rld"; const doc = parse(body); const loc = createLocFn(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'UnionTypeDefinition', - name: nameNode('Hello', loc(6, 11)), - types: [ - typeNode('Wo', loc(14, 16)), - typeNode('Rld', loc(19, 22)), - ], - loc: loc(0, 22), + kind: "UnionTypeDefinition", + name: nameNode("Hello", loc(6, 11)), + types: [typeNode("Wo", loc(14, 16)), typeNode("Rld", loc(19, 22))], + loc: loc(0, 22) } ], - loc: loc(0, 22), + loc: loc(0, 22) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Scalar', () => { - const body = 'scalar Hello'; + it("Scalar", () => { + const body = "scalar Hello"; const doc = parse(body); const loc = createLocFn(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'ScalarTypeDefinition', - name: nameNode('Hello', loc(7, 12)), - loc: loc(0, 12), + kind: "ScalarTypeDefinition", + name: nameNode("Hello", loc(7, 12)), + loc: loc(0, 12) } ], - loc: loc(0, 12), + loc: loc(0, 12) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Simple input object', () => { + it("Simple input object", () => { const body = ` input Hello { world: String @@ -512,33 +508,32 @@ input Hello { const doc = parse(body); const loc = createLocFn(body); const expected = { - kind: 'Document', + kind: "Document", definitions: [ { - kind: 'InputObjectTypeDefinition', - name: nameNode('Hello', loc(7, 12)), + kind: "InputObjectTypeDefinition", + name: nameNode("Hello", loc(7, 12)), fields: [ inputValueNode( - nameNode('world', loc(17, 22)), - typeNode('String', loc(24, 30)), + nameNode("world", loc(17, 22)), + typeNode("String", loc(24, 30)), null, loc(17, 30) ) ], - loc: loc(1, 32), + loc: loc(1, 32) } ], - loc: loc(1, 32), + loc: loc(1, 32) }; expect(printJson(doc)).to.equal(printJson(expected)); }); - it('Simple input object with args should fail', () => { + it("Simple input object with args should fail", () => { const body = ` input Hello { world(foo: Int): String }`; - expect(() => parse(body)).to.throw('Error'); + expect(() => parse(body)).to.throw("Error"); }); - }); diff --git a/src/language/__tests__/schema-printer-test.js b/src/language/__tests__/schema-printer-test.js index 80b417071c..d984450fcf 100644 --- a/src/language/__tests__/schema-printer-test.js +++ b/src/language/__tests__/schema-printer-test.js @@ -7,51 +7,49 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { readFileSync } from 'fs'; -import { join } from 'path'; -import { parse } from '../parser'; -import { print } from '../printer'; - -describe('Printer', () => { - - it('prints minimal ast', () => { +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { readFileSync } from "fs"; +import { join } from "path"; +import { parse } from "../parser"; +import { print } from "../printer"; + +describe("Printer", () => { + it("prints minimal ast", () => { const ast = { - kind: 'ScalarTypeDefinition', - name: { kind: 'Name', value: 'foo' } + kind: "ScalarTypeDefinition", + name: { kind: "Name", value: "foo" } }; - expect(print(ast)).to.equal('scalar foo'); + expect(print(ast)).to.equal("scalar foo"); }); - it('produces helpful error messages', () => { - const badAst1 = { random: 'Data' }; + it("produces helpful error messages", () => { + const badAst1 = { random: "Data" }; expect(() => print(badAst1)).to.throw( 'Invalid AST Node: {"random":"Data"}' ); }); const kitchenSink = readFileSync( - join(__dirname, '/schema-kitchen-sink.graphql'), - { encoding: 'utf8' } + join(__dirname, "/schema-kitchen-sink.graphql"), + { encoding: "utf8" } ); - it('does not alter ast', () => { + it("does not alter ast", () => { const ast = parse(kitchenSink); const astCopy = JSON.parse(JSON.stringify(ast)); print(ast); expect(ast).to.deep.equal(astCopy); }); - it('prints kitchen sink', () => { - + it("prints kitchen sink", () => { const ast = parse(kitchenSink); const printed = print(ast); /* eslint-disable max-len */ expect(printed).to.equal( -`schema { + `schema { query: QueryType mutation: MutationType } @@ -91,7 +89,7 @@ extend type Foo { directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT -`); - +` + ); }); }); diff --git a/src/language/__tests__/visitor-test.js b/src/language/__tests__/visitor-test.js index 3c3b6ca0ad..691f84929f 100644 --- a/src/language/__tests__/visitor-test.js +++ b/src/language/__tests__/visitor-test.js @@ -7,23 +7,20 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { parse } from '../parser'; -import { print } from '../printer'; -import { readFileSync } from 'fs'; -import { visit, visitInParallel, visitWithTypeInfo, BREAK } from '../visitor'; -import { join } from 'path'; -import { TypeInfo } from '../../utilities/TypeInfo'; -import { testSchema } from '../../validation/__tests__/harness'; -import { getNamedType, isCompositeType } from '../../type'; - - -describe('Visitor', () => { - - it('allows editing a node both on enter and on leave', () => { - - const ast = parse('{ a, b, c { a, b, c } }', { noLocation: true }); +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { parse } from "../parser"; +import { print } from "../printer"; +import { readFileSync } from "fs"; +import { visit, visitInParallel, visitWithTypeInfo, BREAK } from "../visitor"; +import { join } from "path"; +import { TypeInfo } from "../../utilities/TypeInfo"; +import { testSchema } from "../../validation/__tests__/harness"; +import { getNamedType, isCompositeType } from "../../type"; + +describe("Visitor", () => { + it("allows editing a node both on enter and on leave", () => { + const ast = parse("{ a, b, c { a, b, c } }", { noLocation: true }); let selectionSet; @@ -34,17 +31,17 @@ describe('Visitor', () => { return { ...node, selectionSet: { - kind: 'SelectionSet', + kind: "SelectionSet", selections: [] }, - didEnter: true, + didEnter: true }; }, leave(node) { return { ...node, selectionSet, - didLeave: true, + didLeave: true }; } } @@ -62,9 +59,8 @@ describe('Visitor', () => { }); }); - it('allows editing the root node on enter and on leave', () => { - - const ast = parse('{ a, b, c { a, b, c } }', { noLocation: true }); + it("allows editing the root node on enter and on leave", () => { + const ast = parse("{ a, b, c { a, b, c } }", { noLocation: true }); const { definitions } = ast; @@ -74,14 +70,14 @@ describe('Visitor', () => { return { ...node, definitions: [], - didEnter: true, + didEnter: true }; }, leave(node) { return { ...node, definitions, - didLeave: true, + didLeave: true }; } } @@ -94,63 +90,62 @@ describe('Visitor', () => { }); }); - it('allows for editing on enter', () => { - - const ast = parse('{ a, b, c { a, b, c } }', { noLocation: true }); + it("allows for editing on enter", () => { + const ast = parse("{ a, b, c { a, b, c } }", { noLocation: true }); const editedAst = visit(ast, { enter(node) { - if (node.kind === 'Field' && node.name.value === 'b') { + if (node.kind === "Field" && node.name.value === "b") { return null; } } }); expect(ast).to.deep.equal( - parse('{ a, b, c { a, b, c } }', { noLocation: true }) + parse("{ a, b, c { a, b, c } }", { noLocation: true }) ); expect(editedAst).to.deep.equal( - parse('{ a, c { a, c } }', { noLocation: true }) + parse("{ a, c { a, c } }", { noLocation: true }) ); }); - it('allows for editing on leave', () => { - - const ast = parse('{ a, b, c { a, b, c } }', { noLocation: true }); + it("allows for editing on leave", () => { + const ast = parse("{ a, b, c { a, b, c } }", { noLocation: true }); const editedAst = visit(ast, { leave(node) { - if (node.kind === 'Field' && node.name.value === 'b') { + if (node.kind === "Field" && node.name.value === "b") { return null; } } }); expect(ast).to.deep.equal( - parse('{ a, b, c { a, b, c } }', { noLocation: true }) + parse("{ a, b, c { a, b, c } }", { noLocation: true }) ); expect(editedAst).to.deep.equal( - parse('{ a, c { a, c } }', { noLocation: true }) + parse("{ a, c { a, c } }", { noLocation: true }) ); }); - it('visits edited node', () => { - - const addedField = - { kind: 'Field', - name: - { kind: 'Name', - value: '__typename' } }; + it("visits edited node", () => { + const addedField = { + kind: "Field", + name: { + kind: "Name", + value: "__typename" + } + }; let didVisitAddedField; - const ast = parse('{ a { x } }'); + const ast = parse("{ a { x } }"); visit(ast, { enter(node) { - if (node.kind === 'Field' && node.name.value === 'a') { + if (node.kind === "Field" && node.name.value === "a") { return { - kind: 'Field', - selectionSet: [ addedField ].concat(node.selectionSet) + kind: "Field", + selectionSet: [addedField].concat(node.selectionSet) }; } if (node === addedField) { @@ -162,1088 +157,1110 @@ describe('Visitor', () => { expect(didVisitAddedField).to.equal(true); }); - it('allows skipping a sub-tree', () => { - + it("allows skipping a sub-tree", () => { const visited = []; - const ast = parse('{ a, b { x }, c }'); + const ast = parse("{ a, b { x }, c }"); visit(ast, { enter(node) { - visited.push([ 'enter', node.kind, node.value ]); - if (node.kind === 'Field' && node.name.value === 'b') { + visited.push(["enter", node.kind, node.value]); + if (node.kind === "Field" && node.name.value === "b") { return false; } }, leave(node) { - visited.push([ 'leave', node.kind, node.value ]); + visited.push(["leave", node.kind, node.value]); } }); expect(visited).to.deep.equal([ - [ 'enter', 'Document', undefined ], - [ 'enter', 'OperationDefinition', undefined ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'a' ], - [ 'leave', 'Name', 'a' ], - [ 'leave', 'Field', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'c' ], - [ 'leave', 'Name', 'c' ], - [ 'leave', 'Field', undefined ], - [ 'leave', 'SelectionSet', undefined ], - [ 'leave', 'OperationDefinition', undefined ], - [ 'leave', 'Document', undefined ], + ["enter", "Document", undefined], + ["enter", "OperationDefinition", undefined], + ["enter", "SelectionSet", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", undefined], + ["enter", "Field", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "c"], + ["leave", "Name", "c"], + ["leave", "Field", undefined], + ["leave", "SelectionSet", undefined], + ["leave", "OperationDefinition", undefined], + ["leave", "Document", undefined] ]); }); - it('allows early exit while visiting', () => { - + it("allows early exit while visiting", () => { const visited = []; - const ast = parse('{ a, b { x }, c }'); + const ast = parse("{ a, b { x }, c }"); visit(ast, { enter(node) { - visited.push([ 'enter', node.kind, node.value ]); - if (node.kind === 'Name' && node.value === 'x') { + visited.push(["enter", node.kind, node.value]); + if (node.kind === "Name" && node.value === "x") { return BREAK; } }, leave(node) { - visited.push([ 'leave', node.kind, node.value ]); + visited.push(["leave", node.kind, node.value]); } }); expect(visited).to.deep.equal([ - [ 'enter', 'Document', undefined ], - [ 'enter', 'OperationDefinition', undefined ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'a' ], - [ 'leave', 'Name', 'a' ], - [ 'leave', 'Field', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'b' ], - [ 'leave', 'Name', 'b' ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'x' ] + ["enter", "Document", undefined], + ["enter", "OperationDefinition", undefined], + ["enter", "SelectionSet", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "b"], + ["leave", "Name", "b"], + ["enter", "SelectionSet", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "x"] ]); }); - it('allows early exit while leaving', () => { - + it("allows early exit while leaving", () => { const visited = []; - const ast = parse('{ a, b { x }, c }'); + const ast = parse("{ a, b { x }, c }"); visit(ast, { enter(node) { - visited.push([ 'enter', node.kind, node.value ]); + visited.push(["enter", node.kind, node.value]); }, leave(node) { - visited.push([ 'leave', node.kind, node.value ]); - if (node.kind === 'Name' && node.value === 'x') { + visited.push(["leave", node.kind, node.value]); + if (node.kind === "Name" && node.value === "x") { return BREAK; } } }); expect(visited).to.deep.equal([ - [ 'enter', 'Document', undefined ], - [ 'enter', 'OperationDefinition', undefined ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'a' ], - [ 'leave', 'Name', 'a' ], - [ 'leave', 'Field', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'b' ], - [ 'leave', 'Name', 'b' ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'x' ], - [ 'leave', 'Name', 'x' ] + ["enter", "Document", undefined], + ["enter", "OperationDefinition", undefined], + ["enter", "SelectionSet", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "b"], + ["leave", "Name", "b"], + ["enter", "SelectionSet", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "x"], + ["leave", "Name", "x"] ]); }); - it('allows a named functions visitor API', () => { - + it("allows a named functions visitor API", () => { const visited = []; - const ast = parse('{ a, b { x }, c }'); + const ast = parse("{ a, b { x }, c }"); visit(ast, { Name(node) { - visited.push([ 'enter', node.kind, node.value ]); + visited.push(["enter", node.kind, node.value]); }, SelectionSet: { enter(node) { - visited.push([ 'enter', node.kind, node.value ]); + visited.push(["enter", node.kind, node.value]); }, leave(node) { - visited.push([ 'leave', node.kind, node.value ]); + visited.push(["leave", node.kind, node.value]); } } }); expect(visited).to.deep.equal([ - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Name', 'a' ], - [ 'enter', 'Name', 'b' ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Name', 'x' ], - [ 'leave', 'SelectionSet', undefined ], - [ 'enter', 'Name', 'c' ], - [ 'leave', 'SelectionSet', undefined ], + ["enter", "SelectionSet", undefined], + ["enter", "Name", "a"], + ["enter", "Name", "b"], + ["enter", "SelectionSet", undefined], + ["enter", "Name", "x"], + ["leave", "SelectionSet", undefined], + ["enter", "Name", "c"], + ["leave", "SelectionSet", undefined] ]); }); + const kitchenSink = readFileSync(join(__dirname, "/kitchen-sink.graphql"), { + encoding: "utf8" + }); - const kitchenSink = readFileSync( - join(__dirname, '/kitchen-sink.graphql'), - { encoding: 'utf8' } - ); - - it('visits kitchen sink', () => { - + it("visits kitchen sink", () => { const ast = parse(kitchenSink); const visited = []; visit(ast, { enter(node, key, parent) { - visited.push([ 'enter', node.kind, key, parent && parent.kind ]); + visited.push(["enter", node.kind, key, parent && parent.kind]); }, leave(node, key, parent) { - visited.push([ 'leave', node.kind, key, parent && parent.kind ]); + visited.push(["leave", node.kind, key, parent && parent.kind]); } }); expect(visited).to.deep.equal([ - [ 'enter', 'Document', undefined, undefined ], - [ 'enter', 'OperationDefinition', 0, undefined ], - [ 'enter', 'Name', 'name', 'OperationDefinition' ], - [ 'leave', 'Name', 'name', 'OperationDefinition' ], - [ 'enter', 'VariableDefinition', 0, undefined ], - [ 'enter', 'Variable', 'variable', 'VariableDefinition' ], - [ 'enter', 'Name', 'name', 'Variable' ], - [ 'leave', 'Name', 'name', 'Variable' ], - [ 'leave', 'Variable', 'variable', 'VariableDefinition' ], - [ 'enter', 'NamedType', 'type', 'VariableDefinition' ], - [ 'enter', 'Name', 'name', 'NamedType' ], - [ 'leave', 'Name', 'name', 'NamedType' ], - [ 'leave', 'NamedType', 'type', 'VariableDefinition' ], - [ 'leave', 'VariableDefinition', 0, undefined ], - [ 'enter', 'VariableDefinition', 1, undefined ], - [ 'enter', 'Variable', 'variable', 'VariableDefinition' ], - [ 'enter', 'Name', 'name', 'Variable' ], - [ 'leave', 'Name', 'name', 'Variable' ], - [ 'leave', 'Variable', 'variable', 'VariableDefinition' ], - [ 'enter', 'NamedType', 'type', 'VariableDefinition' ], - [ 'enter', 'Name', 'name', 'NamedType' ], - [ 'leave', 'Name', 'name', 'NamedType' ], - [ 'leave', 'NamedType', 'type', 'VariableDefinition' ], - [ 'enter', 'EnumValue', 'defaultValue', 'VariableDefinition' ], - [ 'leave', 'EnumValue', 'defaultValue', 'VariableDefinition' ], - [ 'leave', 'VariableDefinition', 1, undefined ], - [ 'enter', 'SelectionSet', 'selectionSet', 'OperationDefinition' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'alias', 'Field' ], - [ 'leave', 'Name', 'alias', 'Field' ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'enter', 'Argument', 0, undefined ], - [ 'enter', 'Name', 'name', 'Argument' ], - [ 'leave', 'Name', 'name', 'Argument' ], - [ 'enter', 'ListValue', 'value', 'Argument' ], - [ 'enter', 'IntValue', 0, undefined ], - [ 'leave', 'IntValue', 0, undefined ], - [ 'enter', 'IntValue', 1, undefined ], - [ 'leave', 'IntValue', 1, undefined ], - [ 'leave', 'ListValue', 'value', 'Argument' ], - [ 'leave', 'Argument', 0, undefined ], - [ 'enter', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'enter', 'InlineFragment', 1, undefined ], - [ 'enter', 'NamedType', 'typeCondition', 'InlineFragment' ], - [ 'enter', 'Name', 'name', 'NamedType' ], - [ 'leave', 'Name', 'name', 'NamedType' ], - [ 'leave', 'NamedType', 'typeCondition', 'InlineFragment' ], - [ 'enter', 'Directive', 0, undefined ], - [ 'enter', 'Name', 'name', 'Directive' ], - [ 'leave', 'Name', 'name', 'Directive' ], - [ 'leave', 'Directive', 0, undefined ], - [ 'enter', 'SelectionSet', 'selectionSet', 'InlineFragment' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'enter', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'enter', 'Field', 1, undefined ], - [ 'enter', 'Name', 'alias', 'Field' ], - [ 'leave', 'Name', 'alias', 'Field' ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'enter', 'Argument', 0, undefined ], - [ 'enter', 'Name', 'name', 'Argument' ], - [ 'leave', 'Name', 'name', 'Argument' ], - [ 'enter', 'IntValue', 'value', 'Argument' ], - [ 'leave', 'IntValue', 'value', 'Argument' ], - [ 'leave', 'Argument', 0, undefined ], - [ 'enter', 'Argument', 1, undefined ], - [ 'enter', 'Name', 'name', 'Argument' ], - [ 'leave', 'Name', 'name', 'Argument' ], - [ 'enter', 'Variable', 'value', 'Argument' ], - [ 'enter', 'Name', 'name', 'Variable' ], - [ 'leave', 'Name', 'name', 'Variable' ], - [ 'leave', 'Variable', 'value', 'Argument' ], - [ 'leave', 'Argument', 1, undefined ], - [ 'enter', 'Directive', 0, undefined ], - [ 'enter', 'Name', 'name', 'Directive' ], - [ 'leave', 'Name', 'name', 'Directive' ], - [ 'enter', 'Argument', 0, undefined ], - [ 'enter', 'Name', 'name', 'Argument' ], - [ 'leave', 'Name', 'name', 'Argument' ], - [ 'enter', 'Variable', 'value', 'Argument' ], - [ 'enter', 'Name', 'name', 'Variable' ], - [ 'leave', 'Name', 'name', 'Variable' ], - [ 'leave', 'Variable', 'value', 'Argument' ], - [ 'leave', 'Argument', 0, undefined ], - [ 'leave', 'Directive', 0, undefined ], - [ 'enter', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'enter', 'FragmentSpread', 1, undefined ], - [ 'enter', 'Name', 'name', 'FragmentSpread' ], - [ 'leave', 'Name', 'name', 'FragmentSpread' ], - [ 'leave', 'FragmentSpread', 1, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'leave', 'Field', 1, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'InlineFragment' ], - [ 'leave', 'InlineFragment', 1, undefined ], - [ 'enter', 'InlineFragment', 2, undefined ], - [ 'enter', 'Directive', 0, undefined ], - [ 'enter', 'Name', 'name', 'Directive' ], - [ 'leave', 'Name', 'name', 'Directive' ], - [ 'enter', 'Argument', 0, undefined ], - [ 'enter', 'Name', 'name', 'Argument' ], - [ 'leave', 'Name', 'name', 'Argument' ], - [ 'enter', 'Variable', 'value', 'Argument' ], - [ 'enter', 'Name', 'name', 'Variable' ], - [ 'leave', 'Name', 'name', 'Variable' ], - [ 'leave', 'Variable', 'value', 'Argument' ], - [ 'leave', 'Argument', 0, undefined ], - [ 'leave', 'Directive', 0, undefined ], - [ 'enter', 'SelectionSet', 'selectionSet', 'InlineFragment' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'InlineFragment' ], - [ 'leave', 'InlineFragment', 2, undefined ], - [ 'enter', 'InlineFragment', 3, undefined ], - [ 'enter', 'SelectionSet', 'selectionSet', 'InlineFragment' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'InlineFragment' ], - [ 'leave', 'InlineFragment', 3, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'OperationDefinition' ], - [ 'leave', 'OperationDefinition', 0, undefined ], - [ 'enter', 'OperationDefinition', 1, undefined ], - [ 'enter', 'Name', 'name', 'OperationDefinition' ], - [ 'leave', 'Name', 'name', 'OperationDefinition' ], - [ 'enter', 'SelectionSet', 'selectionSet', 'OperationDefinition' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'enter', 'Argument', 0, undefined ], - [ 'enter', 'Name', 'name', 'Argument' ], - [ 'leave', 'Name', 'name', 'Argument' ], - [ 'enter', 'IntValue', 'value', 'Argument' ], - [ 'leave', 'IntValue', 'value', 'Argument' ], - [ 'leave', 'Argument', 0, undefined ], - [ 'enter', 'Directive', 0, undefined ], - [ 'enter', 'Name', 'name', 'Directive' ], - [ 'leave', 'Name', 'name', 'Directive' ], - [ 'leave', 'Directive', 0, undefined ], - [ 'enter', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'enter', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'OperationDefinition' ], - [ 'leave', 'OperationDefinition', 1, undefined ], - [ 'enter', 'OperationDefinition', 2, undefined ], - [ 'enter', 'Name', 'name', 'OperationDefinition' ], - [ 'leave', 'Name', 'name', 'OperationDefinition' ], - [ 'enter', 'VariableDefinition', 0, undefined ], - [ 'enter', 'Variable', 'variable', 'VariableDefinition' ], - [ 'enter', 'Name', 'name', 'Variable' ], - [ 'leave', 'Name', 'name', 'Variable' ], - [ 'leave', 'Variable', 'variable', 'VariableDefinition' ], - [ 'enter', 'NamedType', 'type', 'VariableDefinition' ], - [ 'enter', 'Name', 'name', 'NamedType' ], - [ 'leave', 'Name', 'name', 'NamedType' ], - [ 'leave', 'NamedType', 'type', 'VariableDefinition' ], - [ 'leave', 'VariableDefinition', 0, undefined ], - [ 'enter', 'SelectionSet', 'selectionSet', 'OperationDefinition' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'enter', 'Argument', 0, undefined ], - [ 'enter', 'Name', 'name', 'Argument' ], - [ 'leave', 'Name', 'name', 'Argument' ], - [ 'enter', 'Variable', 'value', 'Argument' ], - [ 'enter', 'Name', 'name', 'Variable' ], - [ 'leave', 'Name', 'name', 'Variable' ], - [ 'leave', 'Variable', 'value', 'Argument' ], - [ 'leave', 'Argument', 0, undefined ], - [ 'enter', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'enter', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'enter', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'enter', 'Field', 1, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'enter', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'leave', 'Field', 1, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'Field' ], - [ 'leave', 'Field', 0, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'OperationDefinition' ], - [ 'leave', 'OperationDefinition', 2, undefined ], - [ 'enter', 'FragmentDefinition', 3, undefined ], - [ 'enter', 'Name', 'name', 'FragmentDefinition' ], - [ 'leave', 'Name', 'name', 'FragmentDefinition' ], - [ 'enter', 'NamedType', 'typeCondition', 'FragmentDefinition' ], - [ 'enter', 'Name', 'name', 'NamedType' ], - [ 'leave', 'Name', 'name', 'NamedType' ], - [ 'leave', 'NamedType', 'typeCondition', 'FragmentDefinition' ], - [ 'enter', 'SelectionSet', 'selectionSet', 'FragmentDefinition' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'enter', 'Argument', 0, undefined ], - [ 'enter', 'Name', 'name', 'Argument' ], - [ 'leave', 'Name', 'name', 'Argument' ], - [ 'enter', 'Variable', 'value', 'Argument' ], - [ 'enter', 'Name', 'name', 'Variable' ], - [ 'leave', 'Name', 'name', 'Variable' ], - [ 'leave', 'Variable', 'value', 'Argument' ], - [ 'leave', 'Argument', 0, undefined ], - [ 'enter', 'Argument', 1, undefined ], - [ 'enter', 'Name', 'name', 'Argument' ], - [ 'leave', 'Name', 'name', 'Argument' ], - [ 'enter', 'Variable', 'value', 'Argument' ], - [ 'enter', 'Name', 'name', 'Variable' ], - [ 'leave', 'Name', 'name', 'Variable' ], - [ 'leave', 'Variable', 'value', 'Argument' ], - [ 'leave', 'Argument', 1, undefined ], - [ 'enter', 'Argument', 2, undefined ], - [ 'enter', 'Name', 'name', 'Argument' ], - [ 'leave', 'Name', 'name', 'Argument' ], - [ 'enter', 'ObjectValue', 'value', 'Argument' ], - [ 'enter', 'ObjectField', 0, undefined ], - [ 'enter', 'Name', 'name', 'ObjectField' ], - [ 'leave', 'Name', 'name', 'ObjectField' ], - [ 'enter', 'StringValue', 'value', 'ObjectField' ], - [ 'leave', 'StringValue', 'value', 'ObjectField' ], - [ 'leave', 'ObjectField', 0, undefined ], - [ 'leave', 'ObjectValue', 'value', 'Argument' ], - [ 'leave', 'Argument', 2, undefined ], - [ 'leave', 'Field', 0, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'FragmentDefinition' ], - [ 'leave', 'FragmentDefinition', 3, undefined ], - [ 'enter', 'OperationDefinition', 4, undefined ], - [ 'enter', 'SelectionSet', 'selectionSet', 'OperationDefinition' ], - [ 'enter', 'Field', 0, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'enter', 'Argument', 0, undefined ], - [ 'enter', 'Name', 'name', 'Argument' ], - [ 'leave', 'Name', 'name', 'Argument' ], - [ 'enter', 'BooleanValue', 'value', 'Argument' ], - [ 'leave', 'BooleanValue', 'value', 'Argument' ], - [ 'leave', 'Argument', 0, undefined ], - [ 'enter', 'Argument', 1, undefined ], - [ 'enter', 'Name', 'name', 'Argument' ], - [ 'leave', 'Name', 'name', 'Argument' ], - [ 'enter', 'BooleanValue', 'value', 'Argument' ], - [ 'leave', 'BooleanValue', 'value', 'Argument' ], - [ 'leave', 'Argument', 1, undefined ], - [ 'leave', 'Field', 0, undefined ], - [ 'enter', 'Field', 1, undefined ], - [ 'enter', 'Name', 'name', 'Field' ], - [ 'leave', 'Name', 'name', 'Field' ], - [ 'leave', 'Field', 1, undefined ], - [ 'leave', 'SelectionSet', 'selectionSet', 'OperationDefinition' ], - [ 'leave', 'OperationDefinition', 4, undefined ], - [ 'leave', 'Document', undefined, undefined ] ]); + ["enter", "Document", undefined, undefined], + ["enter", "OperationDefinition", 0, undefined], + ["enter", "Name", "name", "OperationDefinition"], + ["leave", "Name", "name", "OperationDefinition"], + ["enter", "VariableDefinition", 0, undefined], + ["enter", "Variable", "variable", "VariableDefinition"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "variable", "VariableDefinition"], + ["enter", "NamedType", "type", "VariableDefinition"], + ["enter", "Name", "name", "NamedType"], + ["leave", "Name", "name", "NamedType"], + ["leave", "NamedType", "type", "VariableDefinition"], + ["leave", "VariableDefinition", 0, undefined], + ["enter", "VariableDefinition", 1, undefined], + ["enter", "Variable", "variable", "VariableDefinition"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "variable", "VariableDefinition"], + ["enter", "NamedType", "type", "VariableDefinition"], + ["enter", "Name", "name", "NamedType"], + ["leave", "Name", "name", "NamedType"], + ["leave", "NamedType", "type", "VariableDefinition"], + ["enter", "EnumValue", "defaultValue", "VariableDefinition"], + ["leave", "EnumValue", "defaultValue", "VariableDefinition"], + ["leave", "VariableDefinition", 1, undefined], + ["enter", "SelectionSet", "selectionSet", "OperationDefinition"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "alias", "Field"], + ["leave", "Name", "alias", "Field"], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "Argument", 0, undefined], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "ListValue", "value", "Argument"], + ["enter", "IntValue", 0, undefined], + ["leave", "IntValue", 0, undefined], + ["enter", "IntValue", 1, undefined], + ["leave", "IntValue", 1, undefined], + ["leave", "ListValue", "value", "Argument"], + ["leave", "Argument", 0, undefined], + ["enter", "SelectionSet", "selectionSet", "Field"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, undefined], + ["enter", "InlineFragment", 1, undefined], + ["enter", "NamedType", "typeCondition", "InlineFragment"], + ["enter", "Name", "name", "NamedType"], + ["leave", "Name", "name", "NamedType"], + ["leave", "NamedType", "typeCondition", "InlineFragment"], + ["enter", "Directive", 0, undefined], + ["enter", "Name", "name", "Directive"], + ["leave", "Name", "name", "Directive"], + ["leave", "Directive", 0, undefined], + ["enter", "SelectionSet", "selectionSet", "InlineFragment"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "SelectionSet", "selectionSet", "Field"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, undefined], + ["enter", "Field", 1, undefined], + ["enter", "Name", "alias", "Field"], + ["leave", "Name", "alias", "Field"], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "Argument", 0, undefined], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "IntValue", "value", "Argument"], + ["leave", "IntValue", "value", "Argument"], + ["leave", "Argument", 0, undefined], + ["enter", "Argument", 1, undefined], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "Variable", "value", "Argument"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "value", "Argument"], + ["leave", "Argument", 1, undefined], + ["enter", "Directive", 0, undefined], + ["enter", "Name", "name", "Directive"], + ["leave", "Name", "name", "Directive"], + ["enter", "Argument", 0, undefined], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "Variable", "value", "Argument"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "value", "Argument"], + ["leave", "Argument", 0, undefined], + ["leave", "Directive", 0, undefined], + ["enter", "SelectionSet", "selectionSet", "Field"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, undefined], + ["enter", "FragmentSpread", 1, undefined], + ["enter", "Name", "name", "FragmentSpread"], + ["leave", "Name", "name", "FragmentSpread"], + ["leave", "FragmentSpread", 1, undefined], + ["leave", "SelectionSet", "selectionSet", "Field"], + ["leave", "Field", 1, undefined], + ["leave", "SelectionSet", "selectionSet", "Field"], + ["leave", "Field", 0, undefined], + ["leave", "SelectionSet", "selectionSet", "InlineFragment"], + ["leave", "InlineFragment", 1, undefined], + ["enter", "InlineFragment", 2, undefined], + ["enter", "Directive", 0, undefined], + ["enter", "Name", "name", "Directive"], + ["leave", "Name", "name", "Directive"], + ["enter", "Argument", 0, undefined], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "Variable", "value", "Argument"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "value", "Argument"], + ["leave", "Argument", 0, undefined], + ["leave", "Directive", 0, undefined], + ["enter", "SelectionSet", "selectionSet", "InlineFragment"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, undefined], + ["leave", "SelectionSet", "selectionSet", "InlineFragment"], + ["leave", "InlineFragment", 2, undefined], + ["enter", "InlineFragment", 3, undefined], + ["enter", "SelectionSet", "selectionSet", "InlineFragment"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, undefined], + ["leave", "SelectionSet", "selectionSet", "InlineFragment"], + ["leave", "InlineFragment", 3, undefined], + ["leave", "SelectionSet", "selectionSet", "Field"], + ["leave", "Field", 0, undefined], + ["leave", "SelectionSet", "selectionSet", "OperationDefinition"], + ["leave", "OperationDefinition", 0, undefined], + ["enter", "OperationDefinition", 1, undefined], + ["enter", "Name", "name", "OperationDefinition"], + ["leave", "Name", "name", "OperationDefinition"], + ["enter", "SelectionSet", "selectionSet", "OperationDefinition"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "Argument", 0, undefined], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "IntValue", "value", "Argument"], + ["leave", "IntValue", "value", "Argument"], + ["leave", "Argument", 0, undefined], + ["enter", "Directive", 0, undefined], + ["enter", "Name", "name", "Directive"], + ["leave", "Name", "name", "Directive"], + ["leave", "Directive", 0, undefined], + ["enter", "SelectionSet", "selectionSet", "Field"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "SelectionSet", "selectionSet", "Field"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, undefined], + ["leave", "SelectionSet", "selectionSet", "Field"], + ["leave", "Field", 0, undefined], + ["leave", "SelectionSet", "selectionSet", "Field"], + ["leave", "Field", 0, undefined], + ["leave", "SelectionSet", "selectionSet", "OperationDefinition"], + ["leave", "OperationDefinition", 1, undefined], + ["enter", "OperationDefinition", 2, undefined], + ["enter", "Name", "name", "OperationDefinition"], + ["leave", "Name", "name", "OperationDefinition"], + ["enter", "VariableDefinition", 0, undefined], + ["enter", "Variable", "variable", "VariableDefinition"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "variable", "VariableDefinition"], + ["enter", "NamedType", "type", "VariableDefinition"], + ["enter", "Name", "name", "NamedType"], + ["leave", "Name", "name", "NamedType"], + ["leave", "NamedType", "type", "VariableDefinition"], + ["leave", "VariableDefinition", 0, undefined], + ["enter", "SelectionSet", "selectionSet", "OperationDefinition"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "Argument", 0, undefined], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "Variable", "value", "Argument"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "value", "Argument"], + ["leave", "Argument", 0, undefined], + ["enter", "SelectionSet", "selectionSet", "Field"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "SelectionSet", "selectionSet", "Field"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "SelectionSet", "selectionSet", "Field"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, undefined], + ["leave", "SelectionSet", "selectionSet", "Field"], + ["leave", "Field", 0, undefined], + ["enter", "Field", 1, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "SelectionSet", "selectionSet", "Field"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 0, undefined], + ["leave", "SelectionSet", "selectionSet", "Field"], + ["leave", "Field", 1, undefined], + ["leave", "SelectionSet", "selectionSet", "Field"], + ["leave", "Field", 0, undefined], + ["leave", "SelectionSet", "selectionSet", "Field"], + ["leave", "Field", 0, undefined], + ["leave", "SelectionSet", "selectionSet", "OperationDefinition"], + ["leave", "OperationDefinition", 2, undefined], + ["enter", "FragmentDefinition", 3, undefined], + ["enter", "Name", "name", "FragmentDefinition"], + ["leave", "Name", "name", "FragmentDefinition"], + ["enter", "NamedType", "typeCondition", "FragmentDefinition"], + ["enter", "Name", "name", "NamedType"], + ["leave", "Name", "name", "NamedType"], + ["leave", "NamedType", "typeCondition", "FragmentDefinition"], + ["enter", "SelectionSet", "selectionSet", "FragmentDefinition"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "Argument", 0, undefined], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "Variable", "value", "Argument"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "value", "Argument"], + ["leave", "Argument", 0, undefined], + ["enter", "Argument", 1, undefined], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "Variable", "value", "Argument"], + ["enter", "Name", "name", "Variable"], + ["leave", "Name", "name", "Variable"], + ["leave", "Variable", "value", "Argument"], + ["leave", "Argument", 1, undefined], + ["enter", "Argument", 2, undefined], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "ObjectValue", "value", "Argument"], + ["enter", "ObjectField", 0, undefined], + ["enter", "Name", "name", "ObjectField"], + ["leave", "Name", "name", "ObjectField"], + ["enter", "StringValue", "value", "ObjectField"], + ["leave", "StringValue", "value", "ObjectField"], + ["leave", "ObjectField", 0, undefined], + ["leave", "ObjectValue", "value", "Argument"], + ["leave", "Argument", 2, undefined], + ["leave", "Field", 0, undefined], + ["leave", "SelectionSet", "selectionSet", "FragmentDefinition"], + ["leave", "FragmentDefinition", 3, undefined], + ["enter", "OperationDefinition", 4, undefined], + ["enter", "SelectionSet", "selectionSet", "OperationDefinition"], + ["enter", "Field", 0, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["enter", "Argument", 0, undefined], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "BooleanValue", "value", "Argument"], + ["leave", "BooleanValue", "value", "Argument"], + ["leave", "Argument", 0, undefined], + ["enter", "Argument", 1, undefined], + ["enter", "Name", "name", "Argument"], + ["leave", "Name", "name", "Argument"], + ["enter", "BooleanValue", "value", "Argument"], + ["leave", "BooleanValue", "value", "Argument"], + ["leave", "Argument", 1, undefined], + ["leave", "Field", 0, undefined], + ["enter", "Field", 1, undefined], + ["enter", "Name", "name", "Field"], + ["leave", "Name", "name", "Field"], + ["leave", "Field", 1, undefined], + ["leave", "SelectionSet", "selectionSet", "OperationDefinition"], + ["leave", "OperationDefinition", 4, undefined], + ["leave", "Document", undefined, undefined] + ]); }); - describe('visitInParallel', () => { - + describe("visitInParallel", () => { // Note: nearly identical to the above test of the same test but // using visitInParallel. - it('allows skipping a sub-tree', () => { - + it("allows skipping a sub-tree", () => { const visited = []; - const ast = parse('{ a, b { x }, c }'); - visit(ast, visitInParallel([ { - enter(node) { - visited.push([ 'enter', node.kind, node.value ]); - if (node.kind === 'Field' && node.name.value === 'b') { - return false; - } - }, + const ast = parse("{ a, b { x }, c }"); + visit( + ast, + visitInParallel([ + { + enter(node) { + visited.push(["enter", node.kind, node.value]); + if (node.kind === "Field" && node.name.value === "b") { + return false; + } + }, - leave(node) { - visited.push([ 'leave', node.kind, node.value ]); - } - } ])); + leave(node) { + visited.push(["leave", node.kind, node.value]); + } + } + ]) + ); expect(visited).to.deep.equal([ - [ 'enter', 'Document', undefined ], - [ 'enter', 'OperationDefinition', undefined ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'a' ], - [ 'leave', 'Name', 'a' ], - [ 'leave', 'Field', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'c' ], - [ 'leave', 'Name', 'c' ], - [ 'leave', 'Field', undefined ], - [ 'leave', 'SelectionSet', undefined ], - [ 'leave', 'OperationDefinition', undefined ], - [ 'leave', 'Document', undefined ], + ["enter", "Document", undefined], + ["enter", "OperationDefinition", undefined], + ["enter", "SelectionSet", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", undefined], + ["enter", "Field", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "c"], + ["leave", "Name", "c"], + ["leave", "Field", undefined], + ["leave", "SelectionSet", undefined], + ["leave", "OperationDefinition", undefined], + ["leave", "Document", undefined] ]); }); - it('allows skipping different sub-trees', () => { + it("allows skipping different sub-trees", () => { const visited = []; - const ast = parse('{ a { x }, b { y} }'); - visit(ast, visitInParallel([ - { - enter(node) { - visited.push([ 'no-a', 'enter', node.kind, node.value ]); - if (node.kind === 'Field' && node.name.value === 'a') { - return false; + const ast = parse("{ a { x }, b { y} }"); + visit( + ast, + visitInParallel([ + { + enter(node) { + visited.push(["no-a", "enter", node.kind, node.value]); + if (node.kind === "Field" && node.name.value === "a") { + return false; + } + }, + leave(node) { + visited.push(["no-a", "leave", node.kind, node.value]); } }, - leave(node) { - visited.push([ 'no-a', 'leave', node.kind, node.value ]); - } - }, - { - enter(node) { - visited.push([ 'no-b', 'enter', node.kind, node.value ]); - if (node.kind === 'Field' && node.name.value === 'b') { - return false; + { + enter(node) { + visited.push(["no-b", "enter", node.kind, node.value]); + if (node.kind === "Field" && node.name.value === "b") { + return false; + } + }, + leave(node) { + visited.push(["no-b", "leave", node.kind, node.value]); } - }, - leave(node) { - visited.push([ 'no-b', 'leave', node.kind, node.value ]); } - } - ])); + ]) + ); expect(visited).to.deep.equal([ - [ 'no-a', 'enter', 'Document', undefined ], - [ 'no-b', 'enter', 'Document', undefined ], - [ 'no-a', 'enter', 'OperationDefinition', undefined ], - [ 'no-b', 'enter', 'OperationDefinition', undefined ], - [ 'no-a', 'enter', 'SelectionSet', undefined ], - [ 'no-b', 'enter', 'SelectionSet', undefined ], - [ 'no-a', 'enter', 'Field', undefined ], - [ 'no-b', 'enter', 'Field', undefined ], - [ 'no-b', 'enter', 'Name', 'a' ], - [ 'no-b', 'leave', 'Name', 'a' ], - [ 'no-b', 'enter', 'SelectionSet', undefined ], - [ 'no-b', 'enter', 'Field', undefined ], - [ 'no-b', 'enter', 'Name', 'x' ], - [ 'no-b', 'leave', 'Name', 'x' ], - [ 'no-b', 'leave', 'Field', undefined ], - [ 'no-b', 'leave', 'SelectionSet', undefined ], - [ 'no-b', 'leave', 'Field', undefined ], - [ 'no-a', 'enter', 'Field', undefined ], - [ 'no-b', 'enter', 'Field', undefined ], - [ 'no-a', 'enter', 'Name', 'b' ], - [ 'no-a', 'leave', 'Name', 'b' ], - [ 'no-a', 'enter', 'SelectionSet', undefined ], - [ 'no-a', 'enter', 'Field', undefined ], - [ 'no-a', 'enter', 'Name', 'y' ], - [ 'no-a', 'leave', 'Name', 'y' ], - [ 'no-a', 'leave', 'Field', undefined ], - [ 'no-a', 'leave', 'SelectionSet', undefined ], - [ 'no-a', 'leave', 'Field', undefined ], - [ 'no-a', 'leave', 'SelectionSet', undefined ], - [ 'no-b', 'leave', 'SelectionSet', undefined ], - [ 'no-a', 'leave', 'OperationDefinition', undefined ], - [ 'no-b', 'leave', 'OperationDefinition', undefined ], - [ 'no-a', 'leave', 'Document', undefined ], - [ 'no-b', 'leave', 'Document', undefined ], + ["no-a", "enter", "Document", undefined], + ["no-b", "enter", "Document", undefined], + ["no-a", "enter", "OperationDefinition", undefined], + ["no-b", "enter", "OperationDefinition", undefined], + ["no-a", "enter", "SelectionSet", undefined], + ["no-b", "enter", "SelectionSet", undefined], + ["no-a", "enter", "Field", undefined], + ["no-b", "enter", "Field", undefined], + ["no-b", "enter", "Name", "a"], + ["no-b", "leave", "Name", "a"], + ["no-b", "enter", "SelectionSet", undefined], + ["no-b", "enter", "Field", undefined], + ["no-b", "enter", "Name", "x"], + ["no-b", "leave", "Name", "x"], + ["no-b", "leave", "Field", undefined], + ["no-b", "leave", "SelectionSet", undefined], + ["no-b", "leave", "Field", undefined], + ["no-a", "enter", "Field", undefined], + ["no-b", "enter", "Field", undefined], + ["no-a", "enter", "Name", "b"], + ["no-a", "leave", "Name", "b"], + ["no-a", "enter", "SelectionSet", undefined], + ["no-a", "enter", "Field", undefined], + ["no-a", "enter", "Name", "y"], + ["no-a", "leave", "Name", "y"], + ["no-a", "leave", "Field", undefined], + ["no-a", "leave", "SelectionSet", undefined], + ["no-a", "leave", "Field", undefined], + ["no-a", "leave", "SelectionSet", undefined], + ["no-b", "leave", "SelectionSet", undefined], + ["no-a", "leave", "OperationDefinition", undefined], + ["no-b", "leave", "OperationDefinition", undefined], + ["no-a", "leave", "Document", undefined], + ["no-b", "leave", "Document", undefined] ]); }); // Note: nearly identical to the above test of the same test but // using visitInParallel. - it('allows early exit while visiting', () => { - + it("allows early exit while visiting", () => { const visited = []; - const ast = parse('{ a, b { x }, c }'); - visit(ast, visitInParallel([ { - enter(node) { - visited.push([ 'enter', node.kind, node.value ]); - if (node.kind === 'Name' && node.value === 'x') { - return BREAK; + const ast = parse("{ a, b { x }, c }"); + visit( + ast, + visitInParallel([ + { + enter(node) { + visited.push(["enter", node.kind, node.value]); + if (node.kind === "Name" && node.value === "x") { + return BREAK; + } + }, + leave(node) { + visited.push(["leave", node.kind, node.value]); + } } - }, - leave(node) { - visited.push([ 'leave', node.kind, node.value ]); - } - } ])); + ]) + ); expect(visited).to.deep.equal([ - [ 'enter', 'Document', undefined ], - [ 'enter', 'OperationDefinition', undefined ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'a' ], - [ 'leave', 'Name', 'a' ], - [ 'leave', 'Field', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'b' ], - [ 'leave', 'Name', 'b' ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'x' ] + ["enter", "Document", undefined], + ["enter", "OperationDefinition", undefined], + ["enter", "SelectionSet", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "b"], + ["leave", "Name", "b"], + ["enter", "SelectionSet", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "x"] ]); }); - it('allows early exit from different points', () => { - + it("allows early exit from different points", () => { const visited = []; - const ast = parse('{ a { y }, b { x } }'); - visit(ast, visitInParallel([ - { - enter(node) { - visited.push([ 'break-a', 'enter', node.kind, node.value ]); - if (node.kind === 'Name' && node.value === 'a') { - return BREAK; + const ast = parse("{ a { y }, b { x } }"); + visit( + ast, + visitInParallel([ + { + enter(node) { + visited.push(["break-a", "enter", node.kind, node.value]); + if (node.kind === "Name" && node.value === "a") { + return BREAK; + } + }, + leave(node) { + visited.push(["break-a", "leave", node.kind, node.value]); } }, - leave(node) { - visited.push([ 'break-a', 'leave', node.kind, node.value ]); - } - }, - { - enter(node) { - visited.push([ 'break-b', 'enter', node.kind, node.value ]); - if (node.kind === 'Name' && node.value === 'b') { - return BREAK; + { + enter(node) { + visited.push(["break-b", "enter", node.kind, node.value]); + if (node.kind === "Name" && node.value === "b") { + return BREAK; + } + }, + leave(node) { + visited.push(["break-b", "leave", node.kind, node.value]); } - }, - leave(node) { - visited.push([ 'break-b', 'leave', node.kind, node.value ]); } - }, - ])); + ]) + ); expect(visited).to.deep.equal([ - [ 'break-a', 'enter', 'Document', undefined ], - [ 'break-b', 'enter', 'Document', undefined ], - [ 'break-a', 'enter', 'OperationDefinition', undefined ], - [ 'break-b', 'enter', 'OperationDefinition', undefined ], - [ 'break-a', 'enter', 'SelectionSet', undefined ], - [ 'break-b', 'enter', 'SelectionSet', undefined ], - [ 'break-a', 'enter', 'Field', undefined ], - [ 'break-b', 'enter', 'Field', undefined ], - [ 'break-a', 'enter', 'Name', 'a' ], - [ 'break-b', 'enter', 'Name', 'a' ], - [ 'break-b', 'leave', 'Name', 'a' ], - [ 'break-b', 'enter', 'SelectionSet', undefined ], - [ 'break-b', 'enter', 'Field', undefined ], - [ 'break-b', 'enter', 'Name', 'y' ], - [ 'break-b', 'leave', 'Name', 'y' ], - [ 'break-b', 'leave', 'Field', undefined ], - [ 'break-b', 'leave', 'SelectionSet', undefined ], - [ 'break-b', 'leave', 'Field', undefined ], - [ 'break-b', 'enter', 'Field', undefined ], - [ 'break-b', 'enter', 'Name', 'b' ] + ["break-a", "enter", "Document", undefined], + ["break-b", "enter", "Document", undefined], + ["break-a", "enter", "OperationDefinition", undefined], + ["break-b", "enter", "OperationDefinition", undefined], + ["break-a", "enter", "SelectionSet", undefined], + ["break-b", "enter", "SelectionSet", undefined], + ["break-a", "enter", "Field", undefined], + ["break-b", "enter", "Field", undefined], + ["break-a", "enter", "Name", "a"], + ["break-b", "enter", "Name", "a"], + ["break-b", "leave", "Name", "a"], + ["break-b", "enter", "SelectionSet", undefined], + ["break-b", "enter", "Field", undefined], + ["break-b", "enter", "Name", "y"], + ["break-b", "leave", "Name", "y"], + ["break-b", "leave", "Field", undefined], + ["break-b", "leave", "SelectionSet", undefined], + ["break-b", "leave", "Field", undefined], + ["break-b", "enter", "Field", undefined], + ["break-b", "enter", "Name", "b"] ]); }); // Note: nearly identical to the above test of the same test but // using visitInParallel. - it('allows early exit while leaving', () => { - + it("allows early exit while leaving", () => { const visited = []; - const ast = parse('{ a, b { x }, c }'); - visit(ast, visitInParallel([ { - enter(node) { - visited.push([ 'enter', node.kind, node.value ]); - }, - leave(node) { - visited.push([ 'leave', node.kind, node.value ]); - if (node.kind === 'Name' && node.value === 'x') { - return BREAK; + const ast = parse("{ a, b { x }, c }"); + visit( + ast, + visitInParallel([ + { + enter(node) { + visited.push(["enter", node.kind, node.value]); + }, + leave(node) { + visited.push(["leave", node.kind, node.value]); + if (node.kind === "Name" && node.value === "x") { + return BREAK; + } + } } - } - } ])); + ]) + ); expect(visited).to.deep.equal([ - [ 'enter', 'Document', undefined ], - [ 'enter', 'OperationDefinition', undefined ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'a' ], - [ 'leave', 'Name', 'a' ], - [ 'leave', 'Field', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'b' ], - [ 'leave', 'Name', 'b' ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'x' ], - [ 'leave', 'Name', 'x' ] + ["enter", "Document", undefined], + ["enter", "OperationDefinition", undefined], + ["enter", "SelectionSet", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "b"], + ["leave", "Name", "b"], + ["enter", "SelectionSet", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "x"], + ["leave", "Name", "x"] ]); }); - it('allows early exit from leaving different points', () => { - + it("allows early exit from leaving different points", () => { const visited = []; - const ast = parse('{ a { y }, b { x } }'); - visit(ast, visitInParallel([ - { - enter(node) { - visited.push([ 'break-a', 'enter', node.kind, node.value ]); - }, - leave(node) { - visited.push([ 'break-a', 'leave', node.kind, node.value ]); - if (node.kind === 'Field' && node.name.value === 'a') { - return BREAK; + const ast = parse("{ a { y }, b { x } }"); + visit( + ast, + visitInParallel([ + { + enter(node) { + visited.push(["break-a", "enter", node.kind, node.value]); + }, + leave(node) { + visited.push(["break-a", "leave", node.kind, node.value]); + if (node.kind === "Field" && node.name.value === "a") { + return BREAK; + } } - } - }, - { - enter(node) { - visited.push([ 'break-b', 'enter', node.kind, node.value ]); }, - leave(node) { - visited.push([ 'break-b', 'leave', node.kind, node.value ]); - if (node.kind === 'Field' && node.name.value === 'b') { - return BREAK; + { + enter(node) { + visited.push(["break-b", "enter", node.kind, node.value]); + }, + leave(node) { + visited.push(["break-b", "leave", node.kind, node.value]); + if (node.kind === "Field" && node.name.value === "b") { + return BREAK; + } } } - }, - ])); + ]) + ); expect(visited).to.deep.equal([ - [ 'break-a', 'enter', 'Document', undefined ], - [ 'break-b', 'enter', 'Document', undefined ], - [ 'break-a', 'enter', 'OperationDefinition', undefined ], - [ 'break-b', 'enter', 'OperationDefinition', undefined ], - [ 'break-a', 'enter', 'SelectionSet', undefined ], - [ 'break-b', 'enter', 'SelectionSet', undefined ], - [ 'break-a', 'enter', 'Field', undefined ], - [ 'break-b', 'enter', 'Field', undefined ], - [ 'break-a', 'enter', 'Name', 'a' ], - [ 'break-b', 'enter', 'Name', 'a' ], - [ 'break-a', 'leave', 'Name', 'a' ], - [ 'break-b', 'leave', 'Name', 'a' ], - [ 'break-a', 'enter', 'SelectionSet', undefined ], - [ 'break-b', 'enter', 'SelectionSet', undefined ], - [ 'break-a', 'enter', 'Field', undefined ], - [ 'break-b', 'enter', 'Field', undefined ], - [ 'break-a', 'enter', 'Name', 'y' ], - [ 'break-b', 'enter', 'Name', 'y' ], - [ 'break-a', 'leave', 'Name', 'y' ], - [ 'break-b', 'leave', 'Name', 'y' ], - [ 'break-a', 'leave', 'Field', undefined ], - [ 'break-b', 'leave', 'Field', undefined ], - [ 'break-a', 'leave', 'SelectionSet', undefined ], - [ 'break-b', 'leave', 'SelectionSet', undefined ], - [ 'break-a', 'leave', 'Field', undefined ], - [ 'break-b', 'leave', 'Field', undefined ], - [ 'break-b', 'enter', 'Field', undefined ], - [ 'break-b', 'enter', 'Name', 'b' ], - [ 'break-b', 'leave', 'Name', 'b' ], - [ 'break-b', 'enter', 'SelectionSet', undefined ], - [ 'break-b', 'enter', 'Field', undefined ], - [ 'break-b', 'enter', 'Name', 'x' ], - [ 'break-b', 'leave', 'Name', 'x' ], - [ 'break-b', 'leave', 'Field', undefined ], - [ 'break-b', 'leave', 'SelectionSet', undefined ], - [ 'break-b', 'leave', 'Field', undefined ] + ["break-a", "enter", "Document", undefined], + ["break-b", "enter", "Document", undefined], + ["break-a", "enter", "OperationDefinition", undefined], + ["break-b", "enter", "OperationDefinition", undefined], + ["break-a", "enter", "SelectionSet", undefined], + ["break-b", "enter", "SelectionSet", undefined], + ["break-a", "enter", "Field", undefined], + ["break-b", "enter", "Field", undefined], + ["break-a", "enter", "Name", "a"], + ["break-b", "enter", "Name", "a"], + ["break-a", "leave", "Name", "a"], + ["break-b", "leave", "Name", "a"], + ["break-a", "enter", "SelectionSet", undefined], + ["break-b", "enter", "SelectionSet", undefined], + ["break-a", "enter", "Field", undefined], + ["break-b", "enter", "Field", undefined], + ["break-a", "enter", "Name", "y"], + ["break-b", "enter", "Name", "y"], + ["break-a", "leave", "Name", "y"], + ["break-b", "leave", "Name", "y"], + ["break-a", "leave", "Field", undefined], + ["break-b", "leave", "Field", undefined], + ["break-a", "leave", "SelectionSet", undefined], + ["break-b", "leave", "SelectionSet", undefined], + ["break-a", "leave", "Field", undefined], + ["break-b", "leave", "Field", undefined], + ["break-b", "enter", "Field", undefined], + ["break-b", "enter", "Name", "b"], + ["break-b", "leave", "Name", "b"], + ["break-b", "enter", "SelectionSet", undefined], + ["break-b", "enter", "Field", undefined], + ["break-b", "enter", "Name", "x"], + ["break-b", "leave", "Name", "x"], + ["break-b", "leave", "Field", undefined], + ["break-b", "leave", "SelectionSet", undefined], + ["break-b", "leave", "Field", undefined] ]); }); - it('allows for editing on enter', () => { + it("allows for editing on enter", () => { const visited = []; - const ast = parse('{ a, b, c { a, b, c } }', { noLocation: true }); - const editedAst = visit(ast, visitInParallel([ - { - enter(node) { - if (node.kind === 'Field' && node.name.value === 'b') { - return null; + const ast = parse("{ a, b, c { a, b, c } }", { noLocation: true }); + const editedAst = visit( + ast, + visitInParallel([ + { + enter(node) { + if (node.kind === "Field" && node.name.value === "b") { + return null; + } } - } - }, - { - enter(node) { - visited.push([ 'enter', node.kind, node.value ]); }, - leave(node) { - visited.push([ 'leave', node.kind, node.value ]); + { + enter(node) { + visited.push(["enter", node.kind, node.value]); + }, + leave(node) { + visited.push(["leave", node.kind, node.value]); + } } - }, - ])); + ]) + ); expect(ast).to.deep.equal( - parse('{ a, b, c { a, b, c } }', { noLocation: true }) + parse("{ a, b, c { a, b, c } }", { noLocation: true }) ); expect(editedAst).to.deep.equal( - parse('{ a, c { a, c } }', { noLocation: true }) + parse("{ a, c { a, c } }", { noLocation: true }) ); expect(visited).to.deep.equal([ - [ 'enter', 'Document', undefined ], - [ 'enter', 'OperationDefinition', undefined ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'a' ], - [ 'leave', 'Name', 'a' ], - [ 'leave', 'Field', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'c' ], - [ 'leave', 'Name', 'c' ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'a' ], - [ 'leave', 'Name', 'a' ], - [ 'leave', 'Field', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'c' ], - [ 'leave', 'Name', 'c' ], - [ 'leave', 'Field', undefined ], - [ 'leave', 'SelectionSet', undefined ], - [ 'leave', 'Field', undefined ], - [ 'leave', 'SelectionSet', undefined ], - [ 'leave', 'OperationDefinition', undefined ], - [ 'leave', 'Document', undefined ] + ["enter", "Document", undefined], + ["enter", "OperationDefinition", undefined], + ["enter", "SelectionSet", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "c"], + ["leave", "Name", "c"], + ["enter", "SelectionSet", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "c"], + ["leave", "Name", "c"], + ["leave", "Field", undefined], + ["leave", "SelectionSet", undefined], + ["leave", "Field", undefined], + ["leave", "SelectionSet", undefined], + ["leave", "OperationDefinition", undefined], + ["leave", "Document", undefined] ]); }); - it('allows for editing on leave', () => { + it("allows for editing on leave", () => { const visited = []; - const ast = parse('{ a, b, c { a, b, c } }', { noLocation: true }); - const editedAst = visit(ast, visitInParallel([ - { - leave(node) { - if (node.kind === 'Field' && node.name.value === 'b') { - return null; + const ast = parse("{ a, b, c { a, b, c } }", { noLocation: true }); + const editedAst = visit( + ast, + visitInParallel([ + { + leave(node) { + if (node.kind === "Field" && node.name.value === "b") { + return null; + } } - } - }, - { - enter(node) { - visited.push([ 'enter', node.kind, node.value ]); }, - leave(node) { - visited.push([ 'leave', node.kind, node.value ]); + { + enter(node) { + visited.push(["enter", node.kind, node.value]); + }, + leave(node) { + visited.push(["leave", node.kind, node.value]); + } } - }, - ])); + ]) + ); expect(ast).to.deep.equal( - parse('{ a, b, c { a, b, c } }', { noLocation: true }) + parse("{ a, b, c { a, b, c } }", { noLocation: true }) ); expect(editedAst).to.deep.equal( - parse('{ a, c { a, c } }', { noLocation: true }) + parse("{ a, c { a, c } }", { noLocation: true }) ); expect(visited).to.deep.equal([ - [ 'enter', 'Document', undefined ], - [ 'enter', 'OperationDefinition', undefined ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'a' ], - [ 'leave', 'Name', 'a' ], - [ 'leave', 'Field', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'b' ], - [ 'leave', 'Name', 'b' ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'c' ], - [ 'leave', 'Name', 'c' ], - [ 'enter', 'SelectionSet', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'a' ], - [ 'leave', 'Name', 'a' ], - [ 'leave', 'Field', undefined ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'b' ], - [ 'leave', 'Name', 'b' ], - [ 'enter', 'Field', undefined ], - [ 'enter', 'Name', 'c' ], - [ 'leave', 'Name', 'c' ], - [ 'leave', 'Field', undefined ], - [ 'leave', 'SelectionSet', undefined ], - [ 'leave', 'Field', undefined ], - [ 'leave', 'SelectionSet', undefined ], - [ 'leave', 'OperationDefinition', undefined ], - [ 'leave', 'Document', undefined ] + ["enter", "Document", undefined], + ["enter", "OperationDefinition", undefined], + ["enter", "SelectionSet", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "b"], + ["leave", "Name", "b"], + ["enter", "Field", undefined], + ["enter", "Name", "c"], + ["leave", "Name", "c"], + ["enter", "SelectionSet", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "a"], + ["leave", "Name", "a"], + ["leave", "Field", undefined], + ["enter", "Field", undefined], + ["enter", "Name", "b"], + ["leave", "Name", "b"], + ["enter", "Field", undefined], + ["enter", "Name", "c"], + ["leave", "Name", "c"], + ["leave", "Field", undefined], + ["leave", "SelectionSet", undefined], + ["leave", "Field", undefined], + ["leave", "SelectionSet", undefined], + ["leave", "OperationDefinition", undefined], + ["leave", "Document", undefined] ]); }); - }); - describe('visitWithTypeInfo', () => { - - it('maintains type info during visit', () => { + describe("visitWithTypeInfo", () => { + it("maintains type info during visit", () => { const visited = []; const typeInfo = new TypeInfo(testSchema); - const ast = parse('{ human(id: 4) { name, pets { name }, unknown } }'); - visit(ast, visitWithTypeInfo(typeInfo, { - enter(node) { - const parentType = typeInfo.getParentType(); - const type = typeInfo.getType(); - const inputType = typeInfo.getInputType(); - visited.push([ - 'enter', - node.kind, - node.kind === 'Name' ? node.value : null, - parentType ? String(parentType) : null, - type ? String(type) : null, - inputType ? String(inputType) : null - ]); - }, - leave(node) { - const parentType = typeInfo.getParentType(); - const type = typeInfo.getType(); - const inputType = typeInfo.getInputType(); - visited.push([ - 'leave', - node.kind, - node.kind === 'Name' ? node.value : null, - parentType ? String(parentType) : null, - type ? String(type) : null, - inputType ? String(inputType) : null - ]); - } - })); + const ast = parse("{ human(id: 4) { name, pets { name }, unknown } }"); + visit( + ast, + visitWithTypeInfo(typeInfo, { + enter(node) { + const parentType = typeInfo.getParentType(); + const type = typeInfo.getType(); + const inputType = typeInfo.getInputType(); + visited.push([ + "enter", + node.kind, + node.kind === "Name" ? node.value : null, + parentType ? String(parentType) : null, + type ? String(type) : null, + inputType ? String(inputType) : null + ]); + }, + leave(node) { + const parentType = typeInfo.getParentType(); + const type = typeInfo.getType(); + const inputType = typeInfo.getInputType(); + visited.push([ + "leave", + node.kind, + node.kind === "Name" ? node.value : null, + parentType ? String(parentType) : null, + type ? String(type) : null, + inputType ? String(inputType) : null + ]); + } + }) + ); expect(visited).to.deep.equal([ - [ 'enter', 'Document', null, null, null, null ], - [ 'enter', 'OperationDefinition', null, null, 'QueryRoot', null ], - [ 'enter', 'SelectionSet', null, 'QueryRoot', 'QueryRoot', null ], - [ 'enter', 'Field', null, 'QueryRoot', 'Human', null ], - [ 'enter', 'Name', 'human', 'QueryRoot', 'Human', null ], - [ 'leave', 'Name', 'human', 'QueryRoot', 'Human', null ], - [ 'enter', 'Argument', null, 'QueryRoot', 'Human', 'ID' ], - [ 'enter', 'Name', 'id', 'QueryRoot', 'Human', 'ID' ], - [ 'leave', 'Name', 'id', 'QueryRoot', 'Human', 'ID' ], - [ 'enter', 'IntValue', null, 'QueryRoot', 'Human', 'ID' ], - [ 'leave', 'IntValue', null, 'QueryRoot', 'Human', 'ID' ], - [ 'leave', 'Argument', null, 'QueryRoot', 'Human', 'ID' ], - [ 'enter', 'SelectionSet', null, 'Human', 'Human', null ], - [ 'enter', 'Field', null, 'Human', 'String', null ], - [ 'enter', 'Name', 'name', 'Human', 'String', null ], - [ 'leave', 'Name', 'name', 'Human', 'String', null ], - [ 'leave', 'Field', null, 'Human', 'String', null ], - [ 'enter', 'Field', null, 'Human', '[Pet]', null ], - [ 'enter', 'Name', 'pets', 'Human', '[Pet]', null ], - [ 'leave', 'Name', 'pets', 'Human', '[Pet]', null ], - [ 'enter', 'SelectionSet', null, 'Pet', '[Pet]', null ], - [ 'enter', 'Field', null, 'Pet', 'String', null ], - [ 'enter', 'Name', 'name', 'Pet', 'String', null ], - [ 'leave', 'Name', 'name', 'Pet', 'String', null ], - [ 'leave', 'Field', null, 'Pet', 'String', null ], - [ 'leave', 'SelectionSet', null, 'Pet', '[Pet]', null ], - [ 'leave', 'Field', null, 'Human', '[Pet]', null ], - [ 'enter', 'Field', null, 'Human', null, null ], - [ 'enter', 'Name', 'unknown', 'Human', null, null ], - [ 'leave', 'Name', 'unknown', 'Human', null, null ], - [ 'leave', 'Field', null, 'Human', null, null ], - [ 'leave', 'SelectionSet', null, 'Human', 'Human', null ], - [ 'leave', 'Field', null, 'QueryRoot', 'Human', null ], - [ 'leave', 'SelectionSet', null, 'QueryRoot', 'QueryRoot', null ], - [ 'leave', 'OperationDefinition', null, null, 'QueryRoot', null ], - [ 'leave', 'Document', null, null, null, null ] + ["enter", "Document", null, null, null, null], + ["enter", "OperationDefinition", null, null, "QueryRoot", null], + ["enter", "SelectionSet", null, "QueryRoot", "QueryRoot", null], + ["enter", "Field", null, "QueryRoot", "Human", null], + ["enter", "Name", "human", "QueryRoot", "Human", null], + ["leave", "Name", "human", "QueryRoot", "Human", null], + ["enter", "Argument", null, "QueryRoot", "Human", "ID"], + ["enter", "Name", "id", "QueryRoot", "Human", "ID"], + ["leave", "Name", "id", "QueryRoot", "Human", "ID"], + ["enter", "IntValue", null, "QueryRoot", "Human", "ID"], + ["leave", "IntValue", null, "QueryRoot", "Human", "ID"], + ["leave", "Argument", null, "QueryRoot", "Human", "ID"], + ["enter", "SelectionSet", null, "Human", "Human", null], + ["enter", "Field", null, "Human", "String", null], + ["enter", "Name", "name", "Human", "String", null], + ["leave", "Name", "name", "Human", "String", null], + ["leave", "Field", null, "Human", "String", null], + ["enter", "Field", null, "Human", "[Pet]", null], + ["enter", "Name", "pets", "Human", "[Pet]", null], + ["leave", "Name", "pets", "Human", "[Pet]", null], + ["enter", "SelectionSet", null, "Pet", "[Pet]", null], + ["enter", "Field", null, "Pet", "String", null], + ["enter", "Name", "name", "Pet", "String", null], + ["leave", "Name", "name", "Pet", "String", null], + ["leave", "Field", null, "Pet", "String", null], + ["leave", "SelectionSet", null, "Pet", "[Pet]", null], + ["leave", "Field", null, "Human", "[Pet]", null], + ["enter", "Field", null, "Human", null, null], + ["enter", "Name", "unknown", "Human", null, null], + ["leave", "Name", "unknown", "Human", null, null], + ["leave", "Field", null, "Human", null, null], + ["leave", "SelectionSet", null, "Human", "Human", null], + ["leave", "Field", null, "QueryRoot", "Human", null], + ["leave", "SelectionSet", null, "QueryRoot", "QueryRoot", null], + ["leave", "OperationDefinition", null, null, "QueryRoot", null], + ["leave", "Document", null, null, null, null] ]); }); - it('maintains type info during edit', () => { + it("maintains type info during edit", () => { const visited = []; const typeInfo = new TypeInfo(testSchema); - const ast = parse( - '{ human(id: 4) { name, pets }, alien }' - ); - const editedAst = visit(ast, visitWithTypeInfo(typeInfo, { - enter(node) { - const parentType = typeInfo.getParentType(); - const type = typeInfo.getType(); - const inputType = typeInfo.getInputType(); - visited.push([ - 'enter', - node.kind, - node.kind === 'Name' ? node.value : null, - parentType ? String(parentType) : null, - type ? String(type) : null, - inputType ? String(inputType) : null - ]); - - // Make a query valid by adding missing selection sets. - if ( - node.kind === 'Field' && - !node.selectionSet && - isCompositeType(getNamedType(type)) - ) { - return { - kind: 'Field', - alias: node.alias, - name: node.name, - arguments: node.arguments, - directives: node.directives, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: '__typename' } - } - ] - } - }; + const ast = parse("{ human(id: 4) { name, pets }, alien }"); + const editedAst = visit( + ast, + visitWithTypeInfo(typeInfo, { + enter(node) { + const parentType = typeInfo.getParentType(); + const type = typeInfo.getType(); + const inputType = typeInfo.getInputType(); + visited.push([ + "enter", + node.kind, + node.kind === "Name" ? node.value : null, + parentType ? String(parentType) : null, + type ? String(type) : null, + inputType ? String(inputType) : null + ]); + + // Make a query valid by adding missing selection sets. + if ( + node.kind === "Field" && + !node.selectionSet && + isCompositeType(getNamedType(type)) + ) { + return { + kind: "Field", + alias: node.alias, + name: node.name, + arguments: node.arguments, + directives: node.directives, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "__typename" } + } + ] + } + }; + } + }, + leave(node) { + const parentType = typeInfo.getParentType(); + const type = typeInfo.getType(); + const inputType = typeInfo.getInputType(); + visited.push([ + "leave", + node.kind, + node.kind === "Name" ? node.value : null, + parentType ? String(parentType) : null, + type ? String(type) : null, + inputType ? String(inputType) : null + ]); } - }, - leave(node) { - const parentType = typeInfo.getParentType(); - const type = typeInfo.getType(); - const inputType = typeInfo.getInputType(); - visited.push([ - 'leave', - node.kind, - node.kind === 'Name' ? node.value : null, - parentType ? String(parentType) : null, - type ? String(type) : null, - inputType ? String(inputType) : null - ]); - } - })); + }) + ); - expect(print(ast)).to.deep.equal(print(parse( - '{ human(id: 4) { name, pets }, alien }' - ))); + expect(print(ast)).to.deep.equal( + print(parse("{ human(id: 4) { name, pets }, alien }")) + ); - expect(print(editedAst)).to.deep.equal(print(parse( - '{ human(id: 4) { name, pets { __typename } }, alien { __typename } }' - ))); + expect(print(editedAst)).to.deep.equal( + print( + parse( + "{ human(id: 4) { name, pets { __typename } }, alien { __typename } }" + ) + ) + ); expect(visited).to.deep.equal([ - [ 'enter', 'Document', null, null, null, null ], - [ 'enter', 'OperationDefinition', null, null, 'QueryRoot', null ], - [ 'enter', 'SelectionSet', null, 'QueryRoot', 'QueryRoot', null ], - [ 'enter', 'Field', null, 'QueryRoot', 'Human', null ], - [ 'enter', 'Name', 'human', 'QueryRoot', 'Human', null ], - [ 'leave', 'Name', 'human', 'QueryRoot', 'Human', null ], - [ 'enter', 'Argument', null, 'QueryRoot', 'Human', 'ID' ], - [ 'enter', 'Name', 'id', 'QueryRoot', 'Human', 'ID' ], - [ 'leave', 'Name', 'id', 'QueryRoot', 'Human', 'ID' ], - [ 'enter', 'IntValue', null, 'QueryRoot', 'Human', 'ID' ], - [ 'leave', 'IntValue', null, 'QueryRoot', 'Human', 'ID' ], - [ 'leave', 'Argument', null, 'QueryRoot', 'Human', 'ID' ], - [ 'enter', 'SelectionSet', null, 'Human', 'Human', null ], - [ 'enter', 'Field', null, 'Human', 'String', null ], - [ 'enter', 'Name', 'name', 'Human', 'String', null ], - [ 'leave', 'Name', 'name', 'Human', 'String', null ], - [ 'leave', 'Field', null, 'Human', 'String', null ], - [ 'enter', 'Field', null, 'Human', '[Pet]', null ], - [ 'enter', 'Name', 'pets', 'Human', '[Pet]', null ], - [ 'leave', 'Name', 'pets', 'Human', '[Pet]', null ], - [ 'enter', 'SelectionSet', null, 'Pet', '[Pet]', null ], - [ 'enter', 'Field', null, 'Pet', 'String!', null ], - [ 'enter', 'Name', '__typename', 'Pet', 'String!', null ], - [ 'leave', 'Name', '__typename', 'Pet', 'String!', null ], - [ 'leave', 'Field', null, 'Pet', 'String!', null ], - [ 'leave', 'SelectionSet', null, 'Pet', '[Pet]', null ], - [ 'leave', 'Field', null, 'Human', '[Pet]', null ], - [ 'leave', 'SelectionSet', null, 'Human', 'Human', null ], - [ 'leave', 'Field', null, 'QueryRoot', 'Human', null ], - [ 'enter', 'Field', null, 'QueryRoot', 'Alien', null ], - [ 'enter', 'Name', 'alien', 'QueryRoot', 'Alien', null ], - [ 'leave', 'Name', 'alien', 'QueryRoot', 'Alien', null ], - [ 'enter', 'SelectionSet', null, 'Alien', 'Alien', null ], - [ 'enter', 'Field', null, 'Alien', 'String!', null ], - [ 'enter', 'Name', '__typename', 'Alien', 'String!', null ], - [ 'leave', 'Name', '__typename', 'Alien', 'String!', null ], - [ 'leave', 'Field', null, 'Alien', 'String!', null ], - [ 'leave', 'SelectionSet', null, 'Alien', 'Alien', null ], - [ 'leave', 'Field', null, 'QueryRoot', 'Alien', null ], - [ 'leave', 'SelectionSet', null, 'QueryRoot', 'QueryRoot', null ], - [ 'leave', 'OperationDefinition', null, null, 'QueryRoot', null ], - [ 'leave', 'Document', null, null, null, null ] + ["enter", "Document", null, null, null, null], + ["enter", "OperationDefinition", null, null, "QueryRoot", null], + ["enter", "SelectionSet", null, "QueryRoot", "QueryRoot", null], + ["enter", "Field", null, "QueryRoot", "Human", null], + ["enter", "Name", "human", "QueryRoot", "Human", null], + ["leave", "Name", "human", "QueryRoot", "Human", null], + ["enter", "Argument", null, "QueryRoot", "Human", "ID"], + ["enter", "Name", "id", "QueryRoot", "Human", "ID"], + ["leave", "Name", "id", "QueryRoot", "Human", "ID"], + ["enter", "IntValue", null, "QueryRoot", "Human", "ID"], + ["leave", "IntValue", null, "QueryRoot", "Human", "ID"], + ["leave", "Argument", null, "QueryRoot", "Human", "ID"], + ["enter", "SelectionSet", null, "Human", "Human", null], + ["enter", "Field", null, "Human", "String", null], + ["enter", "Name", "name", "Human", "String", null], + ["leave", "Name", "name", "Human", "String", null], + ["leave", "Field", null, "Human", "String", null], + ["enter", "Field", null, "Human", "[Pet]", null], + ["enter", "Name", "pets", "Human", "[Pet]", null], + ["leave", "Name", "pets", "Human", "[Pet]", null], + ["enter", "SelectionSet", null, "Pet", "[Pet]", null], + ["enter", "Field", null, "Pet", "String!", null], + ["enter", "Name", "__typename", "Pet", "String!", null], + ["leave", "Name", "__typename", "Pet", "String!", null], + ["leave", "Field", null, "Pet", "String!", null], + ["leave", "SelectionSet", null, "Pet", "[Pet]", null], + ["leave", "Field", null, "Human", "[Pet]", null], + ["leave", "SelectionSet", null, "Human", "Human", null], + ["leave", "Field", null, "QueryRoot", "Human", null], + ["enter", "Field", null, "QueryRoot", "Alien", null], + ["enter", "Name", "alien", "QueryRoot", "Alien", null], + ["leave", "Name", "alien", "QueryRoot", "Alien", null], + ["enter", "SelectionSet", null, "Alien", "Alien", null], + ["enter", "Field", null, "Alien", "String!", null], + ["enter", "Name", "__typename", "Alien", "String!", null], + ["leave", "Name", "__typename", "Alien", "String!", null], + ["leave", "Field", null, "Alien", "String!", null], + ["leave", "SelectionSet", null, "Alien", "Alien", null], + ["leave", "Field", null, "QueryRoot", "Alien", null], + ["leave", "SelectionSet", null, "QueryRoot", "QueryRoot", null], + ["leave", "OperationDefinition", null, null, "QueryRoot", null], + ["leave", "Document", null, null, null, null] ]); }); - }); - }); diff --git a/src/language/ast.js b/src/language/ast.js index feda211f40..3ea427c810 100644 --- a/src/language/ast.js +++ b/src/language/ast.js @@ -8,357 +8,353 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { Source } from './source'; - +import type { Source } from "./source"; /** * Contains a range of UTF-8 character offsets that identify * the region of the source from which the AST derived. */ export type Location = { - start: number; - end: number; + start: number, + end: number, source?: ?Source -} +}; /** * The list of all possible AST node types. */ -export type Node = Name - | Document - | OperationDefinition - | VariableDefinition - | Variable - | SelectionSet - | Field - | Argument - | FragmentSpread - | InlineFragment - | FragmentDefinition - | IntValue - | FloatValue - | StringValue - | BooleanValue - | EnumValue - | ListValue - | ObjectValue - | ObjectField - | Directive - | NamedType - | ListType - | NonNullType - | SchemaDefinition - | OperationTypeDefinition - | ScalarTypeDefinition - | ObjectTypeDefinition - | FieldDefinition - | InputValueDefinition - | InterfaceTypeDefinition - | UnionTypeDefinition - | EnumTypeDefinition - | EnumValueDefinition - | InputObjectTypeDefinition - | TypeExtensionDefinition - | DirectiveDefinition +export type Node = + | Name + | Document + | OperationDefinition + | VariableDefinition + | Variable + | SelectionSet + | Field + | Argument + | FragmentSpread + | InlineFragment + | FragmentDefinition + | IntValue + | FloatValue + | StringValue + | BooleanValue + | EnumValue + | ListValue + | ObjectValue + | ObjectField + | Directive + | NamedType + | ListType + | NonNullType + | SchemaDefinition + | OperationTypeDefinition + | ScalarTypeDefinition + | ObjectTypeDefinition + | FieldDefinition + | InputValueDefinition + | InterfaceTypeDefinition + | UnionTypeDefinition + | EnumTypeDefinition + | EnumValueDefinition + | InputObjectTypeDefinition + | TypeExtensionDefinition + | DirectiveDefinition; // Name export type Name = { - kind: 'Name'; - loc?: ?Location; - value: string; -} + kind: "Name", + loc?: ?Location, + value: string +}; // Document export type Document = { - kind: 'Document'; - loc?: ?Location; - definitions: Array; -} + kind: "Document", + loc?: ?Location, + definitions: Array +}; -export type Definition = OperationDefinition - | FragmentDefinition - | TypeSystemDefinition // experimental non-spec addition. +export type Definition = + | OperationDefinition + | FragmentDefinition + | TypeSystemDefinition; // experimental non-spec addition. export type OperationDefinition = { - kind: 'OperationDefinition'; - loc?: ?Location; - operation: OperationType; - name?: ?Name; - variableDefinitions?: ?Array; - directives?: ?Array; - selectionSet: SelectionSet; -} + kind: "OperationDefinition", + loc?: ?Location, + operation: OperationType, + name?: ?Name, + variableDefinitions?: ?Array, + directives?: ?Array, + selectionSet: SelectionSet +}; // Note: subscription is an experimental non-spec addition. -export type OperationType = 'query' | 'mutation' | 'subscription'; +export type OperationType = "query" | "mutation" | "subscription"; export type VariableDefinition = { - kind: 'VariableDefinition'; - loc?: ?Location; - variable: Variable; - type: Type; - defaultValue?: ?Value; -} + kind: "VariableDefinition", + loc?: ?Location, + variable: Variable, + type: Type, + defaultValue?: ?Value +}; export type Variable = { - kind: 'Variable'; - loc?: ?Location; - name: Name; -} + kind: "Variable", + loc?: ?Location, + name: Name +}; export type SelectionSet = { - kind: 'SelectionSet'; - loc?: ?Location; - selections: Array; -} + kind: "SelectionSet", + loc?: ?Location, + selections: Array +}; -export type Selection = Field - | FragmentSpread - | InlineFragment +export type Selection = Field | FragmentSpread | InlineFragment; export type Field = { - kind: 'Field'; - loc?: ?Location; - alias?: ?Name; - name: Name; - arguments?: ?Array; - directives?: ?Array; - selectionSet?: ?SelectionSet; -} + kind: "Field", + loc?: ?Location, + alias?: ?Name, + name: Name, + arguments?: ?Array, + directives?: ?Array, + selectionSet?: ?SelectionSet +}; export type Argument = { - kind: 'Argument'; - loc?: ?Location; - name: Name; - value: Value; -} - + kind: "Argument", + loc?: ?Location, + name: Name, + value: Value +}; // Fragments export type FragmentSpread = { - kind: 'FragmentSpread'; - loc?: ?Location; - name: Name; - directives?: ?Array; -} + kind: "FragmentSpread", + loc?: ?Location, + name: Name, + directives?: ?Array +}; export type InlineFragment = { - kind: 'InlineFragment'; - loc?: ?Location; - typeCondition?: ?NamedType; - directives?: ?Array; - selectionSet: SelectionSet; -} + kind: "InlineFragment", + loc?: ?Location, + typeCondition?: ?NamedType, + directives?: ?Array, + selectionSet: SelectionSet +}; export type FragmentDefinition = { - kind: 'FragmentDefinition'; - loc?: ?Location; - name: Name; - typeCondition: NamedType; - directives?: ?Array; - selectionSet: SelectionSet; -} - + kind: "FragmentDefinition", + loc?: ?Location, + name: Name, + typeCondition: NamedType, + directives?: ?Array, + selectionSet: SelectionSet +}; // Values -export type Value = Variable - | IntValue - | FloatValue - | StringValue - | BooleanValue - | EnumValue - | ListValue - | ObjectValue +export type Value = + | Variable + | IntValue + | FloatValue + | StringValue + | BooleanValue + | EnumValue + | ListValue + | ObjectValue; export type IntValue = { - kind: 'IntValue'; - loc?: ?Location; - value: string; -} + kind: "IntValue", + loc?: ?Location, + value: string +}; export type FloatValue = { - kind: 'FloatValue'; - loc?: ?Location; - value: string; -} + kind: "FloatValue", + loc?: ?Location, + value: string +}; export type StringValue = { - kind: 'StringValue'; - loc?: ?Location; - value: string; -} + kind: "StringValue", + loc?: ?Location, + value: string +}; export type BooleanValue = { - kind: 'BooleanValue'; - loc?: ?Location; - value: boolean; -} + kind: "BooleanValue", + loc?: ?Location, + value: boolean +}; export type EnumValue = { - kind: 'EnumValue'; - loc?: ?Location; - value: string; -} + kind: "EnumValue", + loc?: ?Location, + value: string +}; export type ListValue = { - kind: 'ListValue'; - loc?: ?Location; - values: Array; -} + kind: "ListValue", + loc?: ?Location, + values: Array +}; export type ObjectValue = { - kind: 'ObjectValue'; - loc?: ?Location; - fields: Array; -} + kind: "ObjectValue", + loc?: ?Location, + fields: Array +}; export type ObjectField = { - kind: 'ObjectField'; - loc?: ?Location; - name: Name; - value: Value; -} - + kind: "ObjectField", + loc?: ?Location, + name: Name, + value: Value +}; // Directives export type Directive = { - kind: 'Directive'; - loc?: ?Location; - name: Name; - arguments?: ?Array; -} - + kind: "Directive", + loc?: ?Location, + name: Name, + arguments?: ?Array +}; // Type Reference -export type Type = NamedType - | ListType - | NonNullType +export type Type = NamedType | ListType | NonNullType; export type NamedType = { - kind: 'NamedType'; - loc?: ?Location; - name: Name; + kind: "NamedType", + loc?: ?Location, + name: Name }; export type ListType = { - kind: 'ListType'; - loc?: ?Location; - type: Type; -} + kind: "ListType", + loc?: ?Location, + type: Type +}; export type NonNullType = { - kind: 'NonNullType'; - loc?: ?Location; - type: NamedType | ListType; -} + kind: "NonNullType", + loc?: ?Location, + type: NamedType | ListType +}; // Type System Definition -export type TypeSystemDefinition = SchemaDefinition - | TypeDefinition - | TypeExtensionDefinition - | DirectiveDefinition +export type TypeSystemDefinition = + | SchemaDefinition + | TypeDefinition + | TypeExtensionDefinition + | DirectiveDefinition; export type SchemaDefinition = { - kind: 'SchemaDefinition'; - loc?: ?Location; - operationTypes: Array; -} + kind: "SchemaDefinition", + loc?: ?Location, + operationTypes: Array +}; export type OperationTypeDefinition = { - kind: 'OperationTypeDefinition'; - loc?: ?Location; - operation: OperationType; - type: NamedType; -} - -export type TypeDefinition = ScalarTypeDefinition - | ObjectTypeDefinition - | InterfaceTypeDefinition - | UnionTypeDefinition - | EnumTypeDefinition - | InputObjectTypeDefinition + kind: "OperationTypeDefinition", + loc?: ?Location, + operation: OperationType, + type: NamedType +}; + +export type TypeDefinition = + | ScalarTypeDefinition + | ObjectTypeDefinition + | InterfaceTypeDefinition + | UnionTypeDefinition + | EnumTypeDefinition + | InputObjectTypeDefinition; export type ScalarTypeDefinition = { - kind: 'ScalarTypeDefinition'; - loc?: ?Location; - name: Name; -} + kind: "ScalarTypeDefinition", + loc?: ?Location, + name: Name +}; export type ObjectTypeDefinition = { - kind: 'ObjectTypeDefinition'; - loc?: ?Location; - name: Name; - interfaces?: ?Array; - fields: Array; -} + kind: "ObjectTypeDefinition", + loc?: ?Location, + name: Name, + interfaces?: ?Array, + fields: Array +}; export type FieldDefinition = { - kind: 'FieldDefinition'; - loc?: ?Location; - name: Name; - arguments: Array; - type: Type; -} + kind: "FieldDefinition", + loc?: ?Location, + name: Name, + arguments: Array, + type: Type +}; export type InputValueDefinition = { - kind: 'InputValueDefinition'; - loc?: ?Location; - name: Name; - type: Type; - defaultValue?: ?Value; -} + kind: "InputValueDefinition", + loc?: ?Location, + name: Name, + type: Type, + defaultValue?: ?Value +}; export type InterfaceTypeDefinition = { - kind: 'InterfaceTypeDefinition'; - loc?: ?Location; - name: Name; - fields: Array; -} + kind: "InterfaceTypeDefinition", + loc?: ?Location, + name: Name, + fields: Array +}; export type UnionTypeDefinition = { - kind: 'UnionTypeDefinition'; - loc?: ?Location; - name: Name; - types: Array; -} + kind: "UnionTypeDefinition", + loc?: ?Location, + name: Name, + types: Array +}; export type EnumTypeDefinition = { - kind: 'EnumTypeDefinition'; - loc?: ?Location; - name: Name; - values: Array; -} + kind: "EnumTypeDefinition", + loc?: ?Location, + name: Name, + values: Array +}; export type EnumValueDefinition = { - kind: 'EnumValueDefinition'; - loc?: ?Location; - name: Name; -} + kind: "EnumValueDefinition", + loc?: ?Location, + name: Name +}; export type InputObjectTypeDefinition = { - kind: 'InputObjectTypeDefinition'; - loc?: ?Location; - name: Name; - fields: Array; -} + kind: "InputObjectTypeDefinition", + loc?: ?Location, + name: Name, + fields: Array +}; export type TypeExtensionDefinition = { - kind: 'TypeExtensionDefinition'; - loc?: ?Location; - definition: ObjectTypeDefinition; -} + kind: "TypeExtensionDefinition", + loc?: ?Location, + definition: ObjectTypeDefinition +}; export type DirectiveDefinition = { - kind: 'DirectiveDefinition'; - loc?: ?Location; - name: Name; - arguments?: ?Array; - locations: Array; -} + kind: "DirectiveDefinition", + loc?: ?Location, + name: Name, + arguments?: ?Array, + locations: Array +}; diff --git a/src/language/index.js b/src/language/index.js index 2cda6ec294..14a80fdaad 100644 --- a/src/language/index.js +++ b/src/language/index.js @@ -7,11 +7,11 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -export { getLocation } from './location'; -import * as Kind from './kinds'; +export { getLocation } from "./location"; +import * as Kind from "./kinds"; export { Kind }; -export { lex } from './lexer'; -export { parse, parseValue } from './parser'; -export { print } from './printer'; -export { Source } from './source'; -export { visit, visitInParallel, visitWithTypeInfo, BREAK } from './visitor'; +export { lex } from "./lexer"; +export { parse, parseValue } from "./parser"; +export { print } from "./printer"; +export { Source } from "./source"; +export { visit, visitInParallel, visitWithTypeInfo, BREAK } from "./visitor"; diff --git a/src/language/kinds.js b/src/language/kinds.js index 372e2a51d7..5aa9f30f78 100644 --- a/src/language/kinds.js +++ b/src/language/kinds.js @@ -9,66 +9,66 @@ // Name -export const NAME = 'Name'; +export const NAME = "Name"; // Document -export const DOCUMENT = 'Document'; -export const OPERATION_DEFINITION = 'OperationDefinition'; -export const VARIABLE_DEFINITION = 'VariableDefinition'; -export const VARIABLE = 'Variable'; -export const SELECTION_SET = 'SelectionSet'; -export const FIELD = 'Field'; -export const ARGUMENT = 'Argument'; +export const DOCUMENT = "Document"; +export const OPERATION_DEFINITION = "OperationDefinition"; +export const VARIABLE_DEFINITION = "VariableDefinition"; +export const VARIABLE = "Variable"; +export const SELECTION_SET = "SelectionSet"; +export const FIELD = "Field"; +export const ARGUMENT = "Argument"; // Fragments -export const FRAGMENT_SPREAD = 'FragmentSpread'; -export const INLINE_FRAGMENT = 'InlineFragment'; -export const FRAGMENT_DEFINITION = 'FragmentDefinition'; +export const FRAGMENT_SPREAD = "FragmentSpread"; +export const INLINE_FRAGMENT = "InlineFragment"; +export const FRAGMENT_DEFINITION = "FragmentDefinition"; // Values -export const INT = 'IntValue'; -export const FLOAT = 'FloatValue'; -export const STRING = 'StringValue'; -export const BOOLEAN = 'BooleanValue'; -export const ENUM = 'EnumValue'; -export const LIST = 'ListValue'; -export const OBJECT = 'ObjectValue'; -export const OBJECT_FIELD = 'ObjectField'; +export const INT = "IntValue"; +export const FLOAT = "FloatValue"; +export const STRING = "StringValue"; +export const BOOLEAN = "BooleanValue"; +export const ENUM = "EnumValue"; +export const LIST = "ListValue"; +export const OBJECT = "ObjectValue"; +export const OBJECT_FIELD = "ObjectField"; // Directives -export const DIRECTIVE = 'Directive'; +export const DIRECTIVE = "Directive"; // Types -export const NAMED_TYPE = 'NamedType'; -export const LIST_TYPE = 'ListType'; -export const NON_NULL_TYPE = 'NonNullType'; +export const NAMED_TYPE = "NamedType"; +export const LIST_TYPE = "ListType"; +export const NON_NULL_TYPE = "NonNullType"; // Type System Definitions -export const SCHEMA_DEFINITION = 'SchemaDefinition'; -export const OPERATION_TYPE_DEFINITION = 'OperationTypeDefinition'; +export const SCHEMA_DEFINITION = "SchemaDefinition"; +export const OPERATION_TYPE_DEFINITION = "OperationTypeDefinition"; // Type Definitions -export const SCALAR_TYPE_DEFINITION = 'ScalarTypeDefinition'; -export const OBJECT_TYPE_DEFINITION = 'ObjectTypeDefinition'; -export const FIELD_DEFINITION = 'FieldDefinition'; -export const INPUT_VALUE_DEFINITION = 'InputValueDefinition'; -export const INTERFACE_TYPE_DEFINITION = 'InterfaceTypeDefinition'; -export const UNION_TYPE_DEFINITION = 'UnionTypeDefinition'; -export const ENUM_TYPE_DEFINITION = 'EnumTypeDefinition'; -export const ENUM_VALUE_DEFINITION = 'EnumValueDefinition'; -export const INPUT_OBJECT_TYPE_DEFINITION = 'InputObjectTypeDefinition'; +export const SCALAR_TYPE_DEFINITION = "ScalarTypeDefinition"; +export const OBJECT_TYPE_DEFINITION = "ObjectTypeDefinition"; +export const FIELD_DEFINITION = "FieldDefinition"; +export const INPUT_VALUE_DEFINITION = "InputValueDefinition"; +export const INTERFACE_TYPE_DEFINITION = "InterfaceTypeDefinition"; +export const UNION_TYPE_DEFINITION = "UnionTypeDefinition"; +export const ENUM_TYPE_DEFINITION = "EnumTypeDefinition"; +export const ENUM_VALUE_DEFINITION = "EnumValueDefinition"; +export const INPUT_OBJECT_TYPE_DEFINITION = "InputObjectTypeDefinition"; // Type Extensions -export const TYPE_EXTENSION_DEFINITION = 'TypeExtensionDefinition'; +export const TYPE_EXTENSION_DEFINITION = "TypeExtensionDefinition"; // Directive Definitions -export const DIRECTIVE_DEFINITION = 'DirectiveDefinition'; +export const DIRECTIVE_DEFINITION = "DirectiveDefinition"; diff --git a/src/language/lexer.js b/src/language/lexer.js index c3d783435e..6c1acc0d21 100644 --- a/src/language/lexer.js +++ b/src/language/lexer.js @@ -8,18 +8,18 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { Source } from './source'; -import { syntaxError } from '../error'; +import type { Source } from "./source"; +import { syntaxError } from "../error"; /** * A representation of a lexed Token. Value only appears for non-punctuation * tokens: NAME, INT, FLOAT, and STRING. */ export type Token = { - kind: number; - start: number; - end: number; - value: ?string; + kind: number, + start: number, + end: number, + value: ?string }; type Lexer = (resetPosition?: number) => Token; @@ -68,16 +68,16 @@ export const TokenKind = { NAME: 15, INT: 16, FLOAT: 17, - STRING: 18, + STRING: 18 }; /** * A helper function to describe a token as a string for debugging */ export function getTokenDesc(token: Token): string { - return token.value ? - `${getTokenKindDesc(token.kind)} "${token.value}"` : - getTokenKindDesc(token.kind); + return token.value + ? `${getTokenKindDesc(token.kind)} "${token.value}"` + : getTokenKindDesc(token.kind); } /** @@ -88,24 +88,24 @@ export function getTokenKindDesc(kind: number): string { } const tokenDescription = {}; -tokenDescription[TokenKind.EOF] = 'EOF'; -tokenDescription[TokenKind.BANG] = '!'; -tokenDescription[TokenKind.DOLLAR] = '$'; -tokenDescription[TokenKind.PAREN_L] = '('; -tokenDescription[TokenKind.PAREN_R] = ')'; -tokenDescription[TokenKind.SPREAD] = '...'; -tokenDescription[TokenKind.COLON] = ':'; -tokenDescription[TokenKind.EQUALS] = '='; -tokenDescription[TokenKind.AT] = '@'; -tokenDescription[TokenKind.BRACKET_L] = '['; -tokenDescription[TokenKind.BRACKET_R] = ']'; -tokenDescription[TokenKind.BRACE_L] = '{'; -tokenDescription[TokenKind.PIPE] = '|'; -tokenDescription[TokenKind.BRACE_R] = '}'; -tokenDescription[TokenKind.NAME] = 'Name'; -tokenDescription[TokenKind.INT] = 'Int'; -tokenDescription[TokenKind.FLOAT] = 'Float'; -tokenDescription[TokenKind.STRING] = 'String'; +tokenDescription[TokenKind.EOF] = "EOF"; +tokenDescription[TokenKind.BANG] = "!"; +tokenDescription[TokenKind.DOLLAR] = "$"; +tokenDescription[TokenKind.PAREN_L] = "("; +tokenDescription[TokenKind.PAREN_R] = ")"; +tokenDescription[TokenKind.SPREAD] = "..."; +tokenDescription[TokenKind.COLON] = ":"; +tokenDescription[TokenKind.EQUALS] = "="; +tokenDescription[TokenKind.AT] = "@"; +tokenDescription[TokenKind.BRACKET_L] = "["; +tokenDescription[TokenKind.BRACKET_R] = "]"; +tokenDescription[TokenKind.BRACE_L] = "{"; +tokenDescription[TokenKind.PIPE] = "|"; +tokenDescription[TokenKind.BRACE_R] = "}"; +tokenDescription[TokenKind.NAME] = "Name"; +tokenDescription[TokenKind.INT] = "Int"; +tokenDescription[TokenKind.FLOAT] = "Float"; +tokenDescription[TokenKind.STRING] = "String"; const charCodeAt = String.prototype.charCodeAt; const slice = String.prototype.slice; @@ -125,11 +125,13 @@ function makeToken( function printCharCode(code) { return ( // NaN/undefined represents access beyond the end of the file. - isNaN(code) ? '' : - // Trust JSON for ASCII. - code < 0x007F ? JSON.stringify(String.fromCharCode(code)) : - // Otherwise print the escaped form. - `"\\u${('00' + code.toString(16).toUpperCase()).slice(-4)}"` + isNaN(code) + ? "" + : // Trust JSON for ASCII. + code < 0x007f + ? JSON.stringify(String.fromCharCode(code)) + : // Otherwise print the escaped form. + `"\\u${("00" + code.toString(16).toUpperCase()).slice(-4)}"` ); } @@ -153,7 +155,7 @@ function readToken(source: Source, fromPosition: number): Token { const code = charCodeAt.call(body, position); // SourceCharacter - if (code < 0x0020 && code !== 0x0009 && code !== 0x000A && code !== 0x000D) { + if (code < 0x0020 && code !== 0x0009 && code !== 0x000a && code !== 0x000d) { throw syntaxError( source, position, @@ -163,57 +165,124 @@ function readToken(source: Source, fromPosition: number): Token { switch (code) { // ! - case 33: return makeToken(TokenKind.BANG, position, position + 1); + case 33: + return makeToken(TokenKind.BANG, position, position + 1); // $ - case 36: return makeToken(TokenKind.DOLLAR, position, position + 1); + case 36: + return makeToken(TokenKind.DOLLAR, position, position + 1); // ( - case 40: return makeToken(TokenKind.PAREN_L, position, position + 1); + case 40: + return makeToken(TokenKind.PAREN_L, position, position + 1); // ) - case 41: return makeToken(TokenKind.PAREN_R, position, position + 1); + case 41: + return makeToken(TokenKind.PAREN_R, position, position + 1); // . case 46: - if (charCodeAt.call(body, position + 1) === 46 && - charCodeAt.call(body, position + 2) === 46) { + if ( + charCodeAt.call(body, position + 1) === 46 && + charCodeAt.call(body, position + 2) === 46 + ) { return makeToken(TokenKind.SPREAD, position, position + 3); } break; // : - case 58: return makeToken(TokenKind.COLON, position, position + 1); + case 58: + return makeToken(TokenKind.COLON, position, position + 1); // = - case 61: return makeToken(TokenKind.EQUALS, position, position + 1); + case 61: + return makeToken(TokenKind.EQUALS, position, position + 1); // @ - case 64: return makeToken(TokenKind.AT, position, position + 1); + case 64: + return makeToken(TokenKind.AT, position, position + 1); // [ - case 91: return makeToken(TokenKind.BRACKET_L, position, position + 1); + case 91: + return makeToken(TokenKind.BRACKET_L, position, position + 1); // ] - case 93: return makeToken(TokenKind.BRACKET_R, position, position + 1); + case 93: + return makeToken(TokenKind.BRACKET_R, position, position + 1); // { - case 123: return makeToken(TokenKind.BRACE_L, position, position + 1); + case 123: + return makeToken(TokenKind.BRACE_L, position, position + 1); // | - case 124: return makeToken(TokenKind.PIPE, position, position + 1); + case 124: + return makeToken(TokenKind.PIPE, position, position + 1); // } - case 125: return makeToken(TokenKind.BRACE_R, position, position + 1); + case 125: + return makeToken(TokenKind.BRACE_R, position, position + 1); // A-Z - case 65: case 66: case 67: case 68: case 69: case 70: case 71: case 72: - case 73: case 74: case 75: case 76: case 77: case 78: case 79: case 80: - case 81: case 82: case 83: case 84: case 85: case 86: case 87: case 88: - case 89: case 90: + case 65: + case 66: + case 67: + case 68: + case 69: + case 70: + case 71: + case 72: + case 73: + case 74: + case 75: + case 76: + case 77: + case 78: + case 79: + case 80: + case 81: + case 82: + case 83: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 90: // _ case 95: // a-z - case 97: case 98: case 99: case 100: case 101: case 102: case 103: case 104: - case 105: case 106: case 107: case 108: case 109: case 110: case 111: - case 112: case 113: case 114: case 115: case 116: case 117: case 118: - case 119: case 120: case 121: case 122: + case 97: + case 98: + case 99: + case 100: + case 101: + case 102: + case 103: + case 104: + case 105: + case 106: + case 107: + case 108: + case 109: + case 110: + case 111: + case 112: + case 113: + case 114: + case 115: + case 116: + case 117: + case 118: + case 119: + case 120: + case 121: + case 122: return readName(source, position); // - case 45: // 0-9 - case 48: case 49: case 50: case 51: case 52: - case 53: case 54: case 55: case 56: case 57: + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: return readNumber(source, position, code); // " - case 34: return readString(source, position); + case 34: + return readString(source, position); } throw syntaxError( @@ -236,25 +305,28 @@ function positionAfterWhitespace(body: string, startPosition: number): number { // Skip Ignored if ( // BOM - code === 0xFEFF || + code === 0xfeff || // White Space code === 0x0009 || // tab code === 0x0020 || // space // Line Terminator - code === 0x000A || // new line - code === 0x000D || // carriage return + code === 0x000a || // new line + code === 0x000d || // carriage return // Comma - code === 0x002C + code === 0x002c ) { ++position; - // Skip comments - } else if (code === 35) { // # + // Skip comments + } else if (code === 35) { + // # ++position; while ( position < bodyLength && (code = charCodeAt.call(body, position)) !== null && // SourceCharacter but not LineTerminator - (code > 0x001F || code === 0x0009) && code !== 0x000A && code !== 0x000D + (code > 0x001f || code === 0x0009) && + code !== 0x000a && + code !== 0x000d ) { ++position; } @@ -278,11 +350,13 @@ function readNumber(source, start, firstCode) { let position = start; let isFloat = false; - if (code === 45) { // - + if (code === 45) { + // - code = charCodeAt.call(body, ++position); } - if (code === 48) { // 0 + if (code === 48) { + // 0 code = charCodeAt.call(body, ++position); if (code >= 48 && code <= 57) { throw syntaxError( @@ -296,7 +370,8 @@ function readNumber(source, start, firstCode) { code = charCodeAt.call(body, position); } - if (code === 46) { // . + if (code === 46) { + // . isFloat = true; code = charCodeAt.call(body, ++position); @@ -304,11 +379,13 @@ function readNumber(source, start, firstCode) { code = charCodeAt.call(body, position); } - if (code === 69 || code === 101) { // E e + if (code === 69 || code === 101) { + // E e isFloat = true; code = charCodeAt.call(body, ++position); - if (code === 43 || code === 45) { // + - + if (code === 43 || code === 45) { + // + - code = charCodeAt.call(body, ++position); } position = readDigits(source, position, code); @@ -329,7 +406,8 @@ function readDigits(source, start, firstCode) { const body = source.body; let position = start; let code = firstCode; - if (code >= 48 && code <= 57) { // 0 - 9 + if (code >= 48 && code <= 57) { + // 0 - 9 do { code = charCodeAt.call(body, ++position); } while (code >= 48 && code <= 57); // 0 - 9 @@ -352,13 +430,14 @@ function readString(source, start) { let position = start + 1; let chunkStart = position; let code = 0; - let value = ''; + let value = ""; while ( position < body.length && (code = charCodeAt.call(body, position)) !== null && // not LineTerminator - code !== 0x000A && code !== 0x000D && + code !== 0x000a && + code !== 0x000d && // not Quote (") code !== 34 ) { @@ -372,18 +451,35 @@ function readString(source, start) { } ++position; - if (code === 92) { // \ + if (code === 92) { + // \ value += slice.call(body, chunkStart, position - 1); code = charCodeAt.call(body, position); switch (code) { - case 34: value += '"'; break; - case 47: value += '\/'; break; - case 92: value += '\\'; break; - case 98: value += '\b'; break; - case 102: value += '\f'; break; - case 110: value += '\n'; break; - case 114: value += '\r'; break; - case 116: value += '\t'; break; + case 34: + value += '"'; + break; + case 47: + value += "/"; + break; + case 92: + value += "\\"; + break; + case 98: + value += "\b"; + break; + case 102: + value += "\f"; + break; + case 110: + value += "\n"; + break; + case 114: + value += "\r"; + break; + case 116: + value += "\t"; + break; case 117: // u const charCode = uniCharCode( charCodeAt.call(body, position + 1), @@ -395,8 +491,8 @@ function readString(source, start) { throw syntaxError( source, position, - 'Invalid character escape sequence: ' + - `\\u${body.slice(position + 1, position + 5)}.` + "Invalid character escape sequence: " + + `\\u${body.slice(position + 1, position + 5)}.` ); } value += String.fromCharCode(charCode); @@ -414,8 +510,9 @@ function readString(source, start) { } } - if (code !== 34) { // quote (") - throw syntaxError(source, position, 'Unterminated string.'); + if (code !== 34) { + // quote (") + throw syntaxError(source, position, "Unterminated string."); } value += slice.call(body, chunkStart, position); @@ -433,7 +530,9 @@ function readString(source, start) { * which means the result of ORing the char2hex() will also be negative. */ function uniCharCode(a, b, c, d) { - return char2hex(a) << 12 | char2hex(b) << 8 | char2hex(c) << 4 | char2hex(d); + return ( + (char2hex(a) << 12) | (char2hex(b) << 8) | (char2hex(c) << 4) | char2hex(d) + ); } /** @@ -445,12 +544,13 @@ function uniCharCode(a, b, c, d) { * Returns -1 on error. */ function char2hex(a) { - return ( - a >= 48 && a <= 57 ? a - 48 : // 0-9 - a >= 65 && a <= 70 ? a - 55 : // A-F - a >= 97 && a <= 102 ? a - 87 : // a-f - -1 - ); + return a >= 48 && a <= 57 + ? a - 48 // 0-9 + : a >= 65 && a <= 70 + ? a - 55 // A-F + : a >= 97 && a <= 102 + ? a - 87 // a-f + : -1; } /** @@ -466,12 +566,10 @@ function readName(source, position) { while ( end !== bodyLength && (code = charCodeAt.call(body, end)) !== null && - ( - code === 95 || // _ - code >= 48 && code <= 57 || // 0-9 - code >= 65 && code <= 90 || // A-Z - code >= 97 && code <= 122 // a-z - ) + (code === 95 || // _ + (code >= 48 && code <= 57) || // 0-9 + (code >= 65 && code <= 90) || // A-Z + (code >= 97 && code <= 122)) // a-z ) { ++end; } diff --git a/src/language/location.js b/src/language/location.js index 32f2da1d7f..230b7b627a 100644 --- a/src/language/location.js +++ b/src/language/location.js @@ -8,15 +8,15 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { Source } from './source'; +import type { Source } from "./source"; /** * Represents a location in a Source. */ type SourceLocation = { - line: number; - column: number; -} + line: number, + column: number +}; /** * Takes a Source and a UTF-8 character offset, and returns the corresponding diff --git a/src/language/parser.js b/src/language/parser.js index 95820afdc7..3f0f7b036a 100644 --- a/src/language/parser.js +++ b/src/language/parser.js @@ -8,14 +8,13 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { Source } from './source'; -import { syntaxError } from '../error'; -import { lex, TokenKind, getTokenKindDesc, getTokenDesc } from './lexer'; -import type { Token } from './lexer'; +import { Source } from "./source"; +import { syntaxError } from "../error"; +import { lex, TokenKind, getTokenKindDesc, getTokenDesc } from "./lexer"; +import type { Token } from "./lexer"; import type { Name, Variable, - Document, Definition, OperationDefinition, @@ -25,28 +24,21 @@ import type { Selection, Field, Argument, - FragmentSpread, InlineFragment, FragmentDefinition, - Value, ListValue, ObjectValue, ObjectField, - Directive, - Type, NamedType, ListType, NonNullType, - TypeSystemDefinition, - SchemaDefinition, OperationTypeDefinition, - ScalarTypeDefinition, ObjectTypeDefinition, FieldDefinition, @@ -56,27 +48,22 @@ import type { EnumTypeDefinition, EnumValueDefinition, InputObjectTypeDefinition, - TypeExtensionDefinition, - - DirectiveDefinition, -} from './ast'; + DirectiveDefinition +} from "./ast"; import { NAME, VARIABLE, - DOCUMENT, OPERATION_DEFINITION, VARIABLE_DEFINITION, SELECTION_SET, FIELD, ARGUMENT, - FRAGMENT_SPREAD, INLINE_FRAGMENT, FRAGMENT_DEFINITION, - INT, FLOAT, STRING, @@ -85,16 +72,12 @@ import { LIST, OBJECT, OBJECT_FIELD, - DIRECTIVE, - NAMED_TYPE, LIST_TYPE, NON_NULL_TYPE, - SCHEMA_DEFINITION, OPERATION_TYPE_DEFINITION, - SCALAR_TYPE_DEFINITION, OBJECT_TYPE_DEFINITION, FIELD_DEFINITION, @@ -104,12 +87,9 @@ import { ENUM_TYPE_DEFINITION, ENUM_VALUE_DEFINITION, INPUT_OBJECT_TYPE_DEFINITION, - TYPE_EXTENSION_DEFINITION, - - DIRECTIVE_DEFINITION, -} from './kinds'; - + DIRECTIVE_DEFINITION +} from "./kinds"; /** * Configuration options to control parser behavior @@ -127,8 +107,8 @@ export type ParseOptions = { * to the source that they were created from. This configuration flag * disables that behavior for performance or testing. */ - noSource?: boolean, -} + noSource?: boolean +}; /** * Given a GraphQL source, parses it into a Document. @@ -204,30 +184,32 @@ function parseDefinition(parser: Parser): Definition { if (peek(parser, TokenKind.NAME)) { switch (parser.token.value) { - case 'query': - case 'mutation': + case "query": + case "mutation": // Note: subscription is an experimental non-spec addition. - case 'subscription': return parseOperationDefinition(parser); + case "subscription": + return parseOperationDefinition(parser); - case 'fragment': return parseFragmentDefinition(parser); + case "fragment": + return parseFragmentDefinition(parser); // Note: the Type System IDL is an experimental non-spec addition. - case 'schema': - case 'scalar': - case 'type': - case 'interface': - case 'union': - case 'enum': - case 'input': - case 'extend': - case 'directive': return parseTypeSystemDefinition(parser); + case "schema": + case "scalar": + case "type": + case "interface": + case "union": + case "enum": + case "input": + case "extend": + case "directive": + return parseTypeSystemDefinition(parser); } } throw unexpected(parser); } - // Implements the parsing rules in the Operations section. /** @@ -240,7 +222,7 @@ function parseOperationDefinition(parser: Parser): OperationDefinition { if (peek(parser, TokenKind.BRACE_L)) { return { kind: OPERATION_DEFINITION, - operation: 'query', + operation: "query", name: null, variableDefinitions: null, directives: [], @@ -270,10 +252,13 @@ function parseOperationDefinition(parser: Parser): OperationDefinition { function parseOperationType(parser: Parser): OperationType { const operationToken = expect(parser, TokenKind.NAME); switch (operationToken.value) { - case 'query': return 'query'; - case 'mutation': return 'mutation'; + case "query": + return "query"; + case "mutation": + return "mutation"; // Note: subscription is an experimental non-spec addition. - case 'subscription': return 'subscription'; + case "subscription": + return "subscription"; } throw unexpected(parser, operationToken); @@ -283,14 +268,14 @@ function parseOperationType(parser: Parser): OperationType { * VariableDefinitions : ( VariableDefinition+ ) */ function parseVariableDefinitions(parser: Parser): Array { - return peek(parser, TokenKind.PAREN_L) ? - many( - parser, - TokenKind.PAREN_L, - parseVariableDefinition, - TokenKind.PAREN_R - ) : - []; + return peek(parser, TokenKind.PAREN_L) + ? many( + parser, + TokenKind.PAREN_L, + parseVariableDefinition, + TokenKind.PAREN_R + ) + : []; } /** @@ -302,8 +287,9 @@ function parseVariableDefinition(parser: Parser): VariableDefinition { kind: VARIABLE_DEFINITION, variable: parseVariable(parser), type: (expect(parser, TokenKind.COLON), parseType(parser)), - defaultValue: - skip(parser, TokenKind.EQUALS) ? parseValueLiteral(parser, true) : null, + defaultValue: skip(parser, TokenKind.EQUALS) + ? parseValueLiteral(parser, true) + : null, loc: loc(parser, start) }; } @@ -328,8 +314,12 @@ function parseSelectionSet(parser: Parser): SelectionSet { const start = parser.token.start; return { kind: SELECTION_SET, - selections: - many(parser, TokenKind.BRACE_L, parseSelection, TokenKind.BRACE_R), + selections: many( + parser, + TokenKind.BRACE_L, + parseSelection, + TokenKind.BRACE_R + ), loc: loc(parser, start) }; } @@ -341,9 +331,9 @@ function parseSelectionSet(parser: Parser): SelectionSet { * - InlineFragment */ function parseSelection(parser: Parser): Selection { - return peek(parser, TokenKind.SPREAD) ? - parseFragment(parser) : - parseField(parser); + return peek(parser, TokenKind.SPREAD) + ? parseFragment(parser) + : parseField(parser); } /** @@ -371,8 +361,9 @@ function parseField(parser: Parser): Field { name, arguments: parseArguments(parser), directives: parseDirectives(parser), - selectionSet: - peek(parser, TokenKind.BRACE_L) ? parseSelectionSet(parser) : null, + selectionSet: peek(parser, TokenKind.BRACE_L) + ? parseSelectionSet(parser) + : null, loc: loc(parser, start) }; } @@ -381,9 +372,9 @@ function parseField(parser: Parser): Field { * Arguments : ( Argument+ ) */ function parseArguments(parser: Parser): Array { - return peek(parser, TokenKind.PAREN_L) ? - many(parser, TokenKind.PAREN_L, parseArgument, TokenKind.PAREN_R) : - []; + return peek(parser, TokenKind.PAREN_L) + ? many(parser, TokenKind.PAREN_L, parseArgument, TokenKind.PAREN_R) + : []; } /** @@ -399,7 +390,6 @@ function parseArgument(parser: Parser): Argument { }; } - // Implements the parsing rules in the Fragments section. /** @@ -412,7 +402,7 @@ function parseArgument(parser: Parser): Argument { function parseFragment(parser: Parser): FragmentSpread | InlineFragment { const start = parser.token.start; expect(parser, TokenKind.SPREAD); - if (peek(parser, TokenKind.NAME) && parser.token.value !== 'on') { + if (peek(parser, TokenKind.NAME) && parser.token.value !== "on") { return { kind: FRAGMENT_SPREAD, name: parseFragmentName(parser), @@ -421,7 +411,7 @@ function parseFragment(parser: Parser): FragmentSpread | InlineFragment { }; } let typeCondition = null; - if (parser.token.value === 'on') { + if (parser.token.value === "on") { advance(parser); typeCondition = parseNamedType(parser); } @@ -442,11 +432,11 @@ function parseFragment(parser: Parser): FragmentSpread | InlineFragment { */ function parseFragmentDefinition(parser: Parser): FragmentDefinition { const start = parser.token.start; - expectKeyword(parser, 'fragment'); + expectKeyword(parser, "fragment"); return { kind: FRAGMENT_DEFINITION, name: parseFragmentName(parser), - typeCondition: (expectKeyword(parser, 'on'), parseNamedType(parser)), + typeCondition: (expectKeyword(parser, "on"), parseNamedType(parser)), directives: parseDirectives(parser), selectionSet: parseSelectionSet(parser), loc: loc(parser, start) @@ -457,13 +447,12 @@ function parseFragmentDefinition(parser: Parser): FragmentDefinition { * FragmentName : Name but not `on` */ function parseFragmentName(parser: Parser): Name { - if (parser.token.value === 'on') { + if (parser.token.value === "on") { throw unexpected(parser); } return parseName(parser); } - // Implements the parsing rules in the Values section. /** @@ -510,14 +499,14 @@ function parseValueLiteral(parser: Parser, isConst: boolean): Value { loc: loc(parser, token.start) }; case TokenKind.NAME: - if (token.value === 'true' || token.value === 'false') { + if (token.value === "true" || token.value === "false") { advance(parser); return { kind: BOOLEAN, - value: token.value === 'true', + value: token.value === "true", loc: loc(parser, token.start) }; - } else if (token.value !== 'null') { + } else if (token.value !== "null") { advance(parser); return { kind: ENUM, @@ -585,13 +574,12 @@ function parseObjectField(parser: Parser, isConst: boolean): ObjectField { return { kind: OBJECT_FIELD, name: parseName(parser), - value: - (expect(parser, TokenKind.COLON), parseValueLiteral(parser, isConst)), + value: (expect(parser, TokenKind.COLON), + parseValueLiteral(parser, isConst)), loc: loc(parser, start) }; } - // Implements the parsing rules in the Directives section. /** @@ -619,7 +607,6 @@ function parseDirective(parser: Parser): Directive { }; } - // Implements the parsing rules in the Types section. /** @@ -664,7 +651,6 @@ export function parseNamedType(parser: Parser): NamedType { }; } - // Implements the parsing rules in the Type Definition section. /** @@ -684,15 +670,24 @@ export function parseNamedType(parser: Parser): NamedType { function parseTypeSystemDefinition(parser: Parser): TypeSystemDefinition { if (peek(parser, TokenKind.NAME)) { switch (parser.token.value) { - case 'schema': return parseSchemaDefinition(parser); - case 'scalar': return parseScalarTypeDefinition(parser); - case 'type': return parseObjectTypeDefinition(parser); - case 'interface': return parseInterfaceTypeDefinition(parser); - case 'union': return parseUnionTypeDefinition(parser); - case 'enum': return parseEnumTypeDefinition(parser); - case 'input': return parseInputObjectTypeDefinition(parser); - case 'extend': return parseTypeExtensionDefinition(parser); - case 'directive': return parseDirectiveDefinition(parser); + case "schema": + return parseSchemaDefinition(parser); + case "scalar": + return parseScalarTypeDefinition(parser); + case "type": + return parseObjectTypeDefinition(parser); + case "interface": + return parseInterfaceTypeDefinition(parser); + case "union": + return parseUnionTypeDefinition(parser); + case "enum": + return parseEnumTypeDefinition(parser); + case "input": + return parseInputObjectTypeDefinition(parser); + case "extend": + return parseTypeExtensionDefinition(parser); + case "directive": + return parseDirectiveDefinition(parser); } } @@ -706,7 +701,7 @@ function parseTypeSystemDefinition(parser: Parser): TypeSystemDefinition { */ function parseSchemaDefinition(parser: Parser): SchemaDefinition { const start = parser.token.start; - expectKeyword(parser, 'schema'); + expectKeyword(parser, "schema"); const operationTypes = many( parser, TokenKind.BRACE_L, @@ -716,7 +711,7 @@ function parseSchemaDefinition(parser: Parser): SchemaDefinition { return { kind: SCHEMA_DEFINITION, operationTypes, - loc: loc(parser, start), + loc: loc(parser, start) }; } @@ -729,7 +724,7 @@ function parseOperationTypeDefinition(parser: Parser): OperationTypeDefinition { kind: OPERATION_TYPE_DEFINITION, operation, type, - loc: loc(parser, start), + loc: loc(parser, start) }; } @@ -738,12 +733,12 @@ function parseOperationTypeDefinition(parser: Parser): OperationTypeDefinition { */ function parseScalarTypeDefinition(parser: Parser): ScalarTypeDefinition { const start = parser.token.start; - expectKeyword(parser, 'scalar'); + expectKeyword(parser, "scalar"); const name = parseName(parser); return { kind: SCALAR_TYPE_DEFINITION, name, - loc: loc(parser, start), + loc: loc(parser, start) }; } @@ -752,7 +747,7 @@ function parseScalarTypeDefinition(parser: Parser): ScalarTypeDefinition { */ function parseObjectTypeDefinition(parser: Parser): ObjectTypeDefinition { const start = parser.token.start; - expectKeyword(parser, 'type'); + expectKeyword(parser, "type"); const name = parseName(parser); const interfaces = parseImplementsInterfaces(parser); const fields = any( @@ -766,7 +761,7 @@ function parseObjectTypeDefinition(parser: Parser): ObjectTypeDefinition { name, interfaces, fields, - loc: loc(parser, start), + loc: loc(parser, start) }; } @@ -775,7 +770,7 @@ function parseObjectTypeDefinition(parser: Parser): ObjectTypeDefinition { */ function parseImplementsInterfaces(parser: Parser): Array { const types = []; - if (parser.token.value === 'implements') { + if (parser.token.value === "implements") { advance(parser); do { types.push(parseNamedType(parser)); @@ -798,7 +793,7 @@ function parseFieldDefinition(parser: Parser): FieldDefinition { name, arguments: args, type, - loc: loc(parser, start), + loc: loc(parser, start) }; } @@ -829,7 +824,7 @@ function parseInputValueDef(parser: Parser): InputValueDefinition { name, type, defaultValue, - loc: loc(parser, start), + loc: loc(parser, start) }; } @@ -838,7 +833,7 @@ function parseInputValueDef(parser: Parser): InputValueDefinition { */ function parseInterfaceTypeDefinition(parser: Parser): InterfaceTypeDefinition { const start = parser.token.start; - expectKeyword(parser, 'interface'); + expectKeyword(parser, "interface"); const name = parseName(parser); const fields = any( parser, @@ -850,7 +845,7 @@ function parseInterfaceTypeDefinition(parser: Parser): InterfaceTypeDefinition { kind: INTERFACE_TYPE_DEFINITION, name, fields, - loc: loc(parser, start), + loc: loc(parser, start) }; } @@ -859,7 +854,7 @@ function parseInterfaceTypeDefinition(parser: Parser): InterfaceTypeDefinition { */ function parseUnionTypeDefinition(parser: Parser): UnionTypeDefinition { const start = parser.token.start; - expectKeyword(parser, 'union'); + expectKeyword(parser, "union"); const name = parseName(parser); expect(parser, TokenKind.EQUALS); const types = parseUnionMembers(parser); @@ -867,7 +862,7 @@ function parseUnionTypeDefinition(parser: Parser): UnionTypeDefinition { kind: UNION_TYPE_DEFINITION, name, types, - loc: loc(parser, start), + loc: loc(parser, start) }; } @@ -889,7 +884,7 @@ function parseUnionMembers(parser: Parser): Array { */ function parseEnumTypeDefinition(parser: Parser): EnumTypeDefinition { const start = parser.token.start; - expectKeyword(parser, 'enum'); + expectKeyword(parser, "enum"); const name = parseName(parser); const values = many( parser, @@ -901,7 +896,7 @@ function parseEnumTypeDefinition(parser: Parser): EnumTypeDefinition { kind: ENUM_TYPE_DEFINITION, name, values, - loc: loc(parser, start), + loc: loc(parser, start) }; } @@ -910,13 +905,13 @@ function parseEnumTypeDefinition(parser: Parser): EnumTypeDefinition { * * EnumValue : Name */ -function parseEnumValueDefinition(parser: Parser) : EnumValueDefinition { +function parseEnumValueDefinition(parser: Parser): EnumValueDefinition { const start = parser.token.start; const name = parseName(parser); return { kind: ENUM_VALUE_DEFINITION, name, - loc: loc(parser, start), + loc: loc(parser, start) }; } @@ -927,7 +922,7 @@ function parseInputObjectTypeDefinition( parser: Parser ): InputObjectTypeDefinition { const start = parser.token.start; - expectKeyword(parser, 'input'); + expectKeyword(parser, "input"); const name = parseName(parser); const fields = any( parser, @@ -939,7 +934,7 @@ function parseInputObjectTypeDefinition( kind: INPUT_OBJECT_TYPE_DEFINITION, name, fields, - loc: loc(parser, start), + loc: loc(parser, start) }; } @@ -948,12 +943,12 @@ function parseInputObjectTypeDefinition( */ function parseTypeExtensionDefinition(parser: Parser): TypeExtensionDefinition { const start = parser.token.start; - expectKeyword(parser, 'extend'); + expectKeyword(parser, "extend"); const definition = parseObjectTypeDefinition(parser); return { kind: TYPE_EXTENSION_DEFINITION, definition, - loc: loc(parser, start), + loc: loc(parser, start) }; } @@ -963,11 +958,11 @@ function parseTypeExtensionDefinition(parser: Parser): TypeExtensionDefinition { */ function parseDirectiveDefinition(parser: Parser): DirectiveDefinition { const start = parser.token.start; - expectKeyword(parser, 'directive'); + expectKeyword(parser, "directive"); expect(parser, TokenKind.AT); const name = parseName(parser); const args = parseArgumentDefs(parser); - expectKeyword(parser, 'on'); + expectKeyword(parser, "on"); const locations = parseDirectiveLocations(parser); return { kind: DIRECTIVE_DEFINITION, @@ -998,7 +993,7 @@ type Parser = { options: ParseOptions, prevEnd: number, token: Token, - _lexToken: () => Token, + _lexToken: () => Token }; /** @@ -1012,7 +1007,7 @@ function makeParser(source: Source, options: ParseOptions): Parser { source, options, prevEnd: 0, - token: _lexToken(), + token: _lexToken() }; } @@ -1139,7 +1134,7 @@ function many( closeKind: number ): Array { expect(parser, openKind); - const nodes = [ parseFn(parser) ]; + const nodes = [parseFn(parser)]; while (!skip(parser, closeKind)) { nodes.push(parseFn(parser)); } diff --git a/src/language/printer.js b/src/language/printer.js index 143f4fdaeb..e75632c464 100644 --- a/src/language/printer.js +++ b/src/language/printer.js @@ -7,7 +7,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { visit } from './visitor'; +import { visit } from "./visitor"; /** * Converts an AST into a string, using one set of reasonable @@ -19,55 +19,56 @@ export function print(ast) { const printDocASTReducer = { Name: node => node.value, - Variable: node => '$' + node.name, + Variable: node => "$" + node.name, // Document - Document: node => join(node.definitions, '\n\n') + '\n', + Document: node => join(node.definitions, "\n\n") + "\n", OperationDefinition(node) { const op = node.operation; const name = node.name; - const varDefs = wrap('(', join(node.variableDefinitions, ', '), ')'); - const directives = join(node.directives, ' '); + const varDefs = wrap("(", join(node.variableDefinitions, ", "), ")"); + const directives = join(node.directives, " "); const selectionSet = node.selectionSet; // Anonymous queries with no directives or variable definitions can use // the query short form. - return !name && !directives && !varDefs && op === 'query' ? - selectionSet : - join([ op, join([ name, varDefs ]), directives, selectionSet ], ' '); + return !name && !directives && !varDefs && op === "query" + ? selectionSet + : join([op, join([name, varDefs]), directives, selectionSet], " "); }, VariableDefinition: ({ variable, type, defaultValue }) => - variable + ': ' + type + wrap(' = ', defaultValue), + variable + ": " + type + wrap(" = ", defaultValue), SelectionSet: ({ selections }) => block(selections), Field: ({ alias, name, arguments: args, directives, selectionSet }) => - join([ - wrap('', alias, ': ') + name + wrap('(', join(args, ', '), ')'), - join(directives, ' '), - selectionSet - ], ' '), + join( + [ + wrap("", alias, ": ") + name + wrap("(", join(args, ", "), ")"), + join(directives, " "), + selectionSet + ], + " " + ), - Argument: ({ name, value }) => name + ': ' + value, + Argument: ({ name, value }) => name + ": " + value, // Fragments FragmentSpread: ({ name, directives }) => - '...' + name + wrap(' ', join(directives, ' ')), + "..." + name + wrap(" ", join(directives, " ")), InlineFragment: ({ typeCondition, directives, selectionSet }) => - join([ - '...', - wrap('on ', typeCondition), - join(directives, ' '), - selectionSet - ], ' '), + join( + ["...", wrap("on ", typeCondition), join(directives, " "), selectionSet], + " " + ), FragmentDefinition: ({ name, typeCondition, directives, selectionSet }) => `fragment ${name} on ${typeCondition} ` + - wrap('', join(directives, ' '), ' ') + + wrap("", join(directives, " "), " ") + selectionSet, // Value @@ -77,51 +78,49 @@ const printDocASTReducer = { StringValue: ({ value }) => JSON.stringify(value), BooleanValue: ({ value }) => JSON.stringify(value), EnumValue: ({ value }) => value, - ListValue: ({ values }) => '[' + join(values, ', ') + ']', - ObjectValue: ({ fields }) => '{' + join(fields, ', ') + '}', - ObjectField: ({ name, value }) => name + ': ' + value, + ListValue: ({ values }) => "[" + join(values, ", ") + "]", + ObjectValue: ({ fields }) => "{" + join(fields, ", ") + "}", + ObjectField: ({ name, value }) => name + ": " + value, // Directive Directive: ({ name, arguments: args }) => - '@' + name + wrap('(', join(args, ', '), ')'), + "@" + name + wrap("(", join(args, ", "), ")"), // Type NamedType: ({ name }) => name, - ListType: ({ type }) => '[' + type + ']', - NonNullType: ({ type }) => type + '!', + ListType: ({ type }) => "[" + type + "]", + NonNullType: ({ type }) => type + "!", // Type System Definitions - SchemaDefinition: ({ operationTypes }) => - 'schema ' + block(operationTypes), + SchemaDefinition: ({ operationTypes }) => "schema " + block(operationTypes), - OperationTypeDefinition: ({ operation, type }) => - operation + ': ' + type, + OperationTypeDefinition: ({ operation, type }) => operation + ": " + type, - ScalarTypeDefinition: ({ name }) => - `scalar ${name}`, + ScalarTypeDefinition: ({ name }) => `scalar ${name}`, ObjectTypeDefinition: ({ name, interfaces, fields }) => - 'type ' + name + ' ' + - wrap('implements ', join(interfaces, ', '), ' ') + + "type " + + name + + " " + + wrap("implements ", join(interfaces, ", "), " ") + block(fields), FieldDefinition: ({ name, arguments: args, type }) => - name + wrap('(', join(args, ', '), ')') + ': ' + type, + name + wrap("(", join(args, ", "), ")") + ": " + type, InputValueDefinition: ({ name, type, defaultValue }) => - name + ': ' + type + wrap(' = ', defaultValue), + name + ": " + type + wrap(" = ", defaultValue), InterfaceTypeDefinition: ({ name, fields }) => `interface ${name} ${block(fields)}`, UnionTypeDefinition: ({ name, types }) => - `union ${name} = ${join(types, ' | ')}`, + `union ${name} = ${join(types, " | ")}`, - EnumTypeDefinition: ({ name, values }) => - `enum ${name} ${block(values)}`, + EnumTypeDefinition: ({ name, values }) => `enum ${name} ${block(values)}`, EnumValueDefinition: ({ name }) => name, @@ -131,8 +130,11 @@ const printDocASTReducer = { TypeExtensionDefinition: ({ definition }) => `extend ${definition}`, DirectiveDefinition: ({ name, arguments: args, locations }) => - 'directive @' + name + wrap('(', join(args, ', '), ')') + - ' on ' + join(locations, ' | '), + "directive @" + + name + + wrap("(", join(args, ", "), ")") + + " on " + + join(locations, " | ") }; /** @@ -140,7 +142,7 @@ const printDocASTReducer = { * print all items together separated by separator if provided */ function join(maybeArray, separator) { - return maybeArray ? maybeArray.filter(x => x).join(separator || '') : ''; + return maybeArray ? maybeArray.filter(x => x).join(separator || "") : ""; } /** @@ -148,9 +150,9 @@ function join(maybeArray, separator) { * print each item on its own line, wrapped in an indented "{ }" block. */ function block(maybeArray) { - return length(maybeArray) ? - indent('{\n' + join(maybeArray, '\n')) + '\n}' : - ''; + return length(maybeArray) + ? indent("{\n" + join(maybeArray, "\n")) + "\n}" + : ""; } /** @@ -158,13 +160,11 @@ function block(maybeArray) { * print an empty string. */ function wrap(start, maybeString, end) { - return maybeString ? - start + maybeString + (end || '') : - ''; + return maybeString ? start + maybeString + (end || "") : ""; } function indent(maybeString) { - return maybeString && maybeString.replace(/\n/g, '\n '); + return maybeString && maybeString.replace(/\n/g, "\n "); } function length(maybeArray) { diff --git a/src/language/source.js b/src/language/source.js index a4af284636..3c39214c1f 100644 --- a/src/language/source.js +++ b/src/language/source.js @@ -20,6 +20,6 @@ export class Source { constructor(body: string, name?: string) { this.body = body; - this.name = name || 'GraphQL'; + this.name = name || "GraphQL"; } } diff --git a/src/language/visitor.js b/src/language/visitor.js index 34ae887b7e..29603659ad 100644 --- a/src/language/visitor.js +++ b/src/language/visitor.js @@ -10,50 +10,54 @@ export const QueryDocumentKeys = { Name: [], - Document: [ 'definitions' ], - OperationDefinition: - [ 'name', 'variableDefinitions', 'directives', 'selectionSet' ], - VariableDefinition: [ 'variable', 'type', 'defaultValue' ], - Variable: [ 'name' ], - SelectionSet: [ 'selections' ], - Field: [ 'alias', 'name', 'arguments', 'directives', 'selectionSet' ], - Argument: [ 'name', 'value' ], + Document: ["definitions"], + OperationDefinition: [ + "name", + "variableDefinitions", + "directives", + "selectionSet" + ], + VariableDefinition: ["variable", "type", "defaultValue"], + Variable: ["name"], + SelectionSet: ["selections"], + Field: ["alias", "name", "arguments", "directives", "selectionSet"], + Argument: ["name", "value"], - FragmentSpread: [ 'name', 'directives' ], - InlineFragment: [ 'typeCondition', 'directives', 'selectionSet' ], - FragmentDefinition: [ 'name', 'typeCondition', 'directives', 'selectionSet' ], + FragmentSpread: ["name", "directives"], + InlineFragment: ["typeCondition", "directives", "selectionSet"], + FragmentDefinition: ["name", "typeCondition", "directives", "selectionSet"], IntValue: [], FloatValue: [], StringValue: [], BooleanValue: [], EnumValue: [], - ListValue: [ 'values' ], - ObjectValue: [ 'fields' ], - ObjectField: [ 'name', 'value' ], + ListValue: ["values"], + ObjectValue: ["fields"], + ObjectField: ["name", "value"], - Directive: [ 'name', 'arguments' ], + Directive: ["name", "arguments"], - NamedType: [ 'name' ], - ListType: [ 'type' ], - NonNullType: [ 'type' ], + NamedType: ["name"], + ListType: ["type"], + NonNullType: ["type"], - SchemaDefinition: [ 'operationTypes' ], - OperationTypeDefinition: [ 'type' ], + SchemaDefinition: ["operationTypes"], + OperationTypeDefinition: ["type"], - ScalarTypeDefinition: [ 'name' ], - ObjectTypeDefinition: [ 'name', 'interfaces', 'fields' ], - FieldDefinition: [ 'name', 'arguments', 'type' ], - InputValueDefinition: [ 'name', 'type', 'defaultValue' ], - InterfaceTypeDefinition: [ 'name', 'fields' ], - UnionTypeDefinition: [ 'name', 'types' ], - EnumTypeDefinition: [ 'name', 'values' ], - EnumValueDefinition: [ 'name' ], - InputObjectTypeDefinition: [ 'name', 'fields' ], + ScalarTypeDefinition: ["name"], + ObjectTypeDefinition: ["name", "interfaces", "fields"], + FieldDefinition: ["name", "arguments", "type"], + InputValueDefinition: ["name", "type", "defaultValue"], + InterfaceTypeDefinition: ["name", "fields"], + UnionTypeDefinition: ["name", "types"], + EnumTypeDefinition: ["name", "values"], + EnumValueDefinition: ["name"], + InputObjectTypeDefinition: ["name", "fields"], - TypeExtensionDefinition: [ 'definition' ], + TypeExtensionDefinition: ["definition"], - DirectiveDefinition: [ 'name', 'arguments', 'locations' ], + DirectiveDefinition: ["name", "arguments", "locations"] }; export const BREAK = {}; @@ -149,7 +153,7 @@ export function visit(root, visitor, keyMap) { let stack; let inArray = Array.isArray(root); - let keys = [ root ]; + let keys = [root]; let index = -1; let edits = []; let parent; @@ -181,8 +185,8 @@ export function visit(root, visitor, keyMap) { } let editOffset = 0; for (let ii = 0; ii < edits.length; ii++) { - let [ editKey ] = edits[ii]; - const [ , editValue ] = edits[ii]; + let [editKey] = edits[ii]; + const [, editValue] = edits[ii]; if (inArray) { editKey -= editOffset; } @@ -200,7 +204,7 @@ export function visit(root, visitor, keyMap) { inArray = stack.inArray; stack = stack.prev; } else { - key = parent ? inArray ? index : keys[index] : undefined; + key = parent ? (inArray ? index : keys[index]) : undefined; node = parent ? parent[key] : newRoot; if (node === null || node === undefined) { continue; @@ -213,7 +217,7 @@ export function visit(root, visitor, keyMap) { let result; if (!Array.isArray(node)) { if (!isNode(node)) { - throw new Error('Invalid AST Node: ' + JSON.stringify(node)); + throw new Error("Invalid AST Node: " + JSON.stringify(node)); } const visitFn = getVisitFn(visitor, node.kind, isLeaving); if (visitFn) { @@ -229,7 +233,7 @@ export function visit(root, visitor, keyMap) { continue; } } else if (result !== undefined) { - edits.push([ key, result ]); + edits.push([key, result]); if (!isLeaving) { if (isNode(result)) { node = result; @@ -243,7 +247,7 @@ export function visit(root, visitor, keyMap) { } if (result === undefined && isEdited) { - edits.push([ key, node ]); + edits.push([key, node]); } if (!isLeaving) { @@ -267,10 +271,9 @@ export function visit(root, visitor, keyMap) { } function isNode(maybeNode) { - return maybeNode && typeof maybeNode.kind === 'string'; + return maybeNode && typeof maybeNode.kind === "string"; } - /** * Creates a new visitor instance which delegates to many visitors to run in * parallel. Each visitor will be visited for each node before moving on. @@ -318,7 +321,6 @@ export function visitInParallel(visitors) { }; } - /** * Creates a new visitor instance which maintains a provided TypeInfo instance * along with visiting visitor. @@ -351,7 +353,6 @@ export function visitWithTypeInfo(typeInfo, visitor) { }; } - /** * Given a visitor instance, if it is leaving or not, and a node kind, return * the function the visitor runtime should call. @@ -359,25 +360,26 @@ export function visitWithTypeInfo(typeInfo, visitor) { function getVisitFn(visitor, kind, isLeaving) { const kindVisitor = visitor[kind]; if (kindVisitor) { - if (!isLeaving && typeof kindVisitor === 'function') { + if (!isLeaving && typeof kindVisitor === "function") { // { Kind() {} } return kindVisitor; } - const kindSpecificVisitor = - isLeaving ? kindVisitor.leave : kindVisitor.enter; - if (typeof kindSpecificVisitor === 'function') { + const kindSpecificVisitor = isLeaving + ? kindVisitor.leave + : kindVisitor.enter; + if (typeof kindSpecificVisitor === "function") { // { Kind: { enter() {}, leave() {} } } return kindSpecificVisitor; } } else { const specificVisitor = isLeaving ? visitor.leave : visitor.enter; if (specificVisitor) { - if (typeof specificVisitor === 'function') { + if (typeof specificVisitor === "function") { // { enter() {}, leave() {} } return specificVisitor; } const specificKindVisitor = specificVisitor[kind]; - if (typeof specificKindVisitor === 'function') { + if (typeof specificKindVisitor === "function") { // { enter: { Kind() {} }, leave: { Kind() {} } } return specificKindVisitor; } diff --git a/src/type/README.md b/src/type/README.md index 9fd9e8a802..1c03491a3a 100644 --- a/src/type/README.md +++ b/src/type/README.md @@ -1,5 +1,4 @@ -GraphQL Type System -------------------- +## GraphQL Type System The `graphql/type` module is responsible for defining GraphQL types and schema. diff --git a/src/type/__tests__/definition-test.js b/src/type/__tests__/definition-test.js index 4e4ba43a45..707a86305e 100644 --- a/src/type/__tests__/definition-test.js +++ b/src/type/__tests__/definition-test.js @@ -19,24 +19,24 @@ import { GraphQLInt, GraphQLString, GraphQLBoolean -} from '../'; +} from "../"; -import { describe, it } from 'mocha'; -import { expect } from 'chai'; +import { describe, it } from "mocha"; +import { expect } from "chai"; -import { isInputType, isOutputType } from '../definition'; +import { isInputType, isOutputType } from "../definition"; const BlogImage = new GraphQLObjectType({ - name: 'Image', + name: "Image", fields: { url: { type: GraphQLString }, width: { type: GraphQLInt }, - height: { type: GraphQLInt }, + height: { type: GraphQLInt } } }); const BlogAuthor = new GraphQLObjectType({ - name: 'Author', + name: "Author", fields: () => ({ id: { type: GraphQLString }, name: { type: GraphQLString }, @@ -49,7 +49,7 @@ const BlogAuthor = new GraphQLObjectType({ }); const BlogArticle = new GraphQLObjectType({ - name: 'Article', + name: "Article", fields: { id: { type: GraphQLString }, isPublished: { type: GraphQLBoolean }, @@ -60,7 +60,7 @@ const BlogArticle = new GraphQLObjectType({ }); const BlogQuery = new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { article: { args: { id: { type: GraphQLString } }, @@ -73,16 +73,16 @@ const BlogQuery = new GraphQLObjectType({ }); const BlogMutation = new GraphQLObjectType({ - name: 'Mutation', + name: "Mutation", fields: { writeArticle: { type: BlogArticle - }, + } } }); const BlogSubscription = new GraphQLObjectType({ - name: 'Subscription', + name: "Subscription", fields: { articleSubscribe: { args: { id: { type: GraphQLString } }, @@ -92,54 +92,55 @@ const BlogSubscription = new GraphQLObjectType({ }); const ObjectType = new GraphQLObjectType({ - name: 'Object', + name: "Object", isTypeOf: () => true }); -const InterfaceType = new GraphQLInterfaceType({ name: 'Interface' }); -const UnionType = - new GraphQLUnionType({ name: 'Union', types: [ ObjectType ] }); -const EnumType = new GraphQLEnumType({ name: 'Enum', values: { foo: {} } }); -const InputObjectType = new GraphQLInputObjectType({ name: 'InputObject' }); - -describe('Type System: Example', () => { - it('defines a query only schema', () => { +const InterfaceType = new GraphQLInterfaceType({ name: "Interface" }); +const UnionType = new GraphQLUnionType({ name: "Union", types: [ObjectType] }); +const EnumType = new GraphQLEnumType({ name: "Enum", values: { foo: {} } }); +const InputObjectType = new GraphQLInputObjectType({ name: "InputObject" }); + +describe("Type System: Example", () => { + it("defines a query only schema", () => { const BlogSchema = new GraphQLSchema({ query: BlogQuery }); expect(BlogSchema.getQueryType()).to.equal(BlogQuery); - const articleField = BlogQuery.getFields()[('article' : string)]; + const articleField = BlogQuery.getFields()[("article": string)]; expect(articleField && articleField.type).to.equal(BlogArticle); - expect(articleField && articleField.type.name).to.equal('Article'); - expect(articleField && articleField.name).to.equal('article'); + expect(articleField && articleField.type.name).to.equal("Article"); + expect(articleField && articleField.name).to.equal("article"); const articleFieldType = articleField ? articleField.type : null; - const titleField = articleFieldType instanceof GraphQLObjectType && - articleFieldType.getFields()[('title': string)]; - expect(titleField && titleField.name).to.equal('title'); + const titleField = + articleFieldType instanceof GraphQLObjectType && + articleFieldType.getFields()[("title": string)]; + expect(titleField && titleField.name).to.equal("title"); expect(titleField && titleField.type).to.equal(GraphQLString); - expect(titleField && titleField.type.name).to.equal('String'); + expect(titleField && titleField.type.name).to.equal("String"); - const authorField = articleFieldType instanceof GraphQLObjectType && - articleFieldType.getFields()[('author': string)]; + const authorField = + articleFieldType instanceof GraphQLObjectType && + articleFieldType.getFields()[("author": string)]; const authorFieldType = authorField ? authorField.type : null; - const recentArticleField = authorFieldType instanceof GraphQLObjectType && - authorFieldType.getFields()[('recentArticle': string)]; + const recentArticleField = + authorFieldType instanceof GraphQLObjectType && + authorFieldType.getFields()[("recentArticle": string)]; expect(recentArticleField && recentArticleField.type).to.equal(BlogArticle); - const feedField = BlogQuery.getFields()[('feed' : string)]; - expect( - feedField && (feedField.type: GraphQLList).ofType - ).to.equal(BlogArticle); - expect(feedField && feedField.name).to.equal('feed'); - + const feedField = BlogQuery.getFields()[("feed": string)]; + expect(feedField && (feedField.type: GraphQLList).ofType).to.equal( + BlogArticle + ); + expect(feedField && feedField.name).to.equal("feed"); }); - it('defines a mutation schema', () => { + it("defines a mutation schema", () => { const BlogSchema = new GraphQLSchema({ query: BlogQuery, mutation: BlogMutation @@ -147,14 +148,13 @@ describe('Type System: Example', () => { expect(BlogSchema.getMutationType()).to.equal(BlogMutation); - const writeMutation = BlogMutation.getFields()[('writeArticle' : string)]; + const writeMutation = BlogMutation.getFields()[("writeArticle": string)]; expect(writeMutation && writeMutation.type).to.equal(BlogArticle); - expect(writeMutation && writeMutation.type.name).to.equal('Article'); - expect(writeMutation && writeMutation.name).to.equal('writeArticle'); - + expect(writeMutation && writeMutation.type.name).to.equal("Article"); + expect(writeMutation && writeMutation.name).to.equal("writeArticle"); }); - it('defines a subscription schema', () => { + it("defines a subscription schema", () => { const BlogSchema = new GraphQLSchema({ query: BlogQuery, subscription: BlogSubscription @@ -162,24 +162,23 @@ describe('Type System: Example', () => { expect(BlogSchema.getSubscriptionType()).to.equal(BlogSubscription); - const sub = BlogSubscription.getFields()[('articleSubscribe' : string)]; + const sub = BlogSubscription.getFields()[("articleSubscribe": string)]; expect(sub && sub.type).to.equal(BlogArticle); - expect(sub && sub.type.name).to.equal('Article'); - expect(sub && sub.name).to.equal('articleSubscribe'); - + expect(sub && sub.type.name).to.equal("Article"); + expect(sub && sub.name).to.equal("articleSubscribe"); }); - it('includes nested input objects in the map', () => { + it("includes nested input objects in the map", () => { const NestedInputObject = new GraphQLInputObjectType({ - name: 'NestedInputObject', + name: "NestedInputObject", fields: { value: { type: GraphQLString } } }); const SomeInputObject = new GraphQLInputObjectType({ - name: 'SomeInputObject', + name: "SomeInputObject", fields: { nested: { type: NestedInputObject } } }); const SomeMutation = new GraphQLObjectType({ - name: 'SomeMutation', + name: "SomeMutation", fields: { mutateSomething: { type: BlogArticle, @@ -188,7 +187,7 @@ describe('Type System: Example', () => { } }); const SomeSubscription = new GraphQLObjectType({ - name: 'SomeSubscription', + name: "SomeSubscription", fields: { subscribeToSomething: { type: BlogArticle, @@ -204,133 +203,125 @@ describe('Type System: Example', () => { expect(schema.getTypeMap().NestedInputObject).to.equal(NestedInputObject); }); - it('includes interfaces\' subtypes in the type map', () => { + it("includes interfaces' subtypes in the type map", () => { const SomeInterface = new GraphQLInterfaceType({ - name: 'SomeInterface', + name: "SomeInterface", fields: { f: { type: GraphQLInt } } }); const SomeSubtype = new GraphQLObjectType({ - name: 'SomeSubtype', + name: "SomeSubtype", fields: { f: { type: GraphQLInt } }, - interfaces: [ SomeInterface ], + interfaces: [SomeInterface], isTypeOf: () => true }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { iface: { type: SomeInterface } } }), - types: [ SomeSubtype ] + types: [SomeSubtype] }); expect(schema.getTypeMap().SomeSubtype).to.equal(SomeSubtype); }); - it('includes interfaces\' thunk subtypes in the type map', () => { + it("includes interfaces' thunk subtypes in the type map", () => { const SomeInterface = new GraphQLInterfaceType({ - name: 'SomeInterface', + name: "SomeInterface", fields: { f: { type: GraphQLInt } } }); const SomeSubtype = new GraphQLObjectType({ - name: 'SomeSubtype', + name: "SomeSubtype", fields: { f: { type: GraphQLInt } }, - interfaces: () => [ SomeInterface ], + interfaces: () => [SomeInterface], isTypeOf: () => true }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { iface: { type: SomeInterface } } }), - types: [ SomeSubtype ] + types: [SomeSubtype] }); expect(schema.getTypeMap().SomeSubtype).to.equal(SomeSubtype); }); - - it('stringifies simple types', () => { - - expect(String(GraphQLInt)).to.equal('Int'); - expect(String(BlogArticle)).to.equal('Article'); - expect(String(InterfaceType)).to.equal('Interface'); - expect(String(UnionType)).to.equal('Union'); - expect(String(EnumType)).to.equal('Enum'); - expect(String(InputObjectType)).to.equal('InputObject'); - expect( - String(new GraphQLNonNull(GraphQLInt)) - ).to.equal('Int!'); - expect( - String(new GraphQLList(GraphQLInt)) - ).to.equal('[Int]'); - expect( - String(new GraphQLNonNull(new GraphQLList(GraphQLInt))) - ).to.equal('[Int]!'); - expect( - String(new GraphQLList(new GraphQLNonNull(GraphQLInt))) - ).to.equal('[Int!]'); - expect( - String(new GraphQLList(new GraphQLList(GraphQLInt))) - ).to.equal('[[Int]]'); + it("stringifies simple types", () => { + expect(String(GraphQLInt)).to.equal("Int"); + expect(String(BlogArticle)).to.equal("Article"); + expect(String(InterfaceType)).to.equal("Interface"); + expect(String(UnionType)).to.equal("Union"); + expect(String(EnumType)).to.equal("Enum"); + expect(String(InputObjectType)).to.equal("InputObject"); + expect(String(new GraphQLNonNull(GraphQLInt))).to.equal("Int!"); + expect(String(new GraphQLList(GraphQLInt))).to.equal("[Int]"); + expect(String(new GraphQLNonNull(new GraphQLList(GraphQLInt)))).to.equal( + "[Int]!" + ); + expect(String(new GraphQLList(new GraphQLNonNull(GraphQLInt)))).to.equal( + "[Int!]" + ); + expect(String(new GraphQLList(new GraphQLList(GraphQLInt)))).to.equal( + "[[Int]]" + ); }); - it('identifies input types', () => { + it("identifies input types", () => { const expected = [ - [ GraphQLInt, true ], - [ ObjectType, false ], - [ InterfaceType, false ], - [ UnionType, false ], - [ EnumType, true ], - [ InputObjectType, true ] + [GraphQLInt, true], + [ObjectType, false], + [InterfaceType, false], + [UnionType, false], + [EnumType, true], + [InputObjectType, true] ]; - expected.forEach(([ type, answer ]) => { + expected.forEach(([type, answer]) => { expect(isInputType(type)).to.equal(answer); expect(isInputType(new GraphQLList(type))).to.equal(answer); expect(isInputType(new GraphQLNonNull(type))).to.equal(answer); }); }); - it('identifies output types', () => { + it("identifies output types", () => { const expected = [ - [ GraphQLInt, true ], - [ ObjectType, true ], - [ InterfaceType, true ], - [ UnionType, true ], - [ EnumType, true ], - [ InputObjectType, false ] + [GraphQLInt, true], + [ObjectType, true], + [InterfaceType, true], + [UnionType, true], + [EnumType, true], + [InputObjectType, false] ]; - expected.forEach(([ type, answer ]) => { + expected.forEach(([type, answer]) => { expect(isOutputType(type)).to.equal(answer); expect(isOutputType(new GraphQLList(type))).to.equal(answer); expect(isOutputType(new GraphQLNonNull(type))).to.equal(answer); }); }); - it('prohibits nesting NonNull inside NonNull', () => { - expect(() => - new GraphQLNonNull(new GraphQLNonNull(GraphQLInt)) - ).to.throw( - 'Can only create NonNull of a Nullable GraphQLType but got: Int!.' + it("prohibits nesting NonNull inside NonNull", () => { + expect(() => new GraphQLNonNull(new GraphQLNonNull(GraphQLInt))).to.throw( + "Can only create NonNull of a Nullable GraphQLType but got: Int!." ); }); - it('prohibits putting non-Object types in unions', () => { + it("prohibits putting non-Object types in unions", () => { const badUnionTypes = [ GraphQLInt, new GraphQLNonNull(GraphQLInt), @@ -341,18 +332,18 @@ describe('Type System: Example', () => { InputObjectType ]; badUnionTypes.forEach(x => { - expect(() => - new GraphQLUnionType({ name: 'BadUnion', types: [ x ] }) + expect( + () => new GraphQLUnionType({ name: "BadUnion", types: [x] }) ).to.throw( `BadUnion may only contain Object types, it cannot contain: ${x}.` ); }); }); - it('does not mutate passed field definitions', () => { + it("does not mutate passed field definitions", () => { const fields = { field1: { - type: GraphQLString, + type: GraphQLString }, field2: { type: GraphQLString, @@ -364,18 +355,18 @@ describe('Type System: Example', () => { } }; const testObject1 = new GraphQLObjectType({ - name: 'Test1', - fields, + name: "Test1", + fields }); const testObject2 = new GraphQLObjectType({ - name: 'Test2', - fields, + name: "Test2", + fields }); expect(testObject1.getFields()).to.deep.equal(testObject2.getFields()); expect(fields).to.deep.equal({ field1: { - type: GraphQLString, + type: GraphQLString }, field2: { type: GraphQLString, @@ -388,11 +379,11 @@ describe('Type System: Example', () => { }); const testInputObject1 = new GraphQLInputObjectType({ - name: 'Test1', + name: "Test1", fields }); const testInputObject2 = new GraphQLInputObjectType({ - name: 'Test2', + name: "Test2", fields }); @@ -401,7 +392,7 @@ describe('Type System: Example', () => { ); expect(fields).to.deep.equal({ field1: { - type: GraphQLString, + type: GraphQLString }, field2: { type: GraphQLString, diff --git a/src/type/__tests__/enumType-test.js b/src/type/__tests__/enumType-test.js index 7c55f514fc..8bd6959a43 100644 --- a/src/type/__tests__/enumType-test.js +++ b/src/type/__tests__/enumType-test.js @@ -7,50 +7,48 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expect } from 'chai'; +import { describe, it } from "mocha"; +import { expect } from "chai"; import { graphql, GraphQLSchema, GraphQLEnumType, GraphQLObjectType, GraphQLInt, - GraphQLString, -} from '../../'; - - -describe('Type System: Enum Values', () => { + GraphQLString +} from "../../"; +describe("Type System: Enum Values", () => { const ColorType = new GraphQLEnumType({ - name: 'Color', + name: "Color", values: { RED: { value: 0 }, GREEN: { value: 1 }, - BLUE: { value: 2 }, + BLUE: { value: 2 } } }); const QueryType = new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { colorEnum: { type: ColorType, args: { fromEnum: { type: ColorType }, fromInt: { type: GraphQLInt }, - fromString: { type: GraphQLString }, + fromString: { type: GraphQLString } }, resolve(value, { fromEnum, fromInt, fromString }) { - return fromInt !== undefined ? fromInt : - fromString !== undefined ? fromString : - fromEnum; + return fromInt !== undefined + ? fromInt + : fromString !== undefined ? fromString : fromEnum; } }, colorInt: { type: GraphQLInt, args: { fromEnum: { type: ColorType }, - fromInt: { type: GraphQLInt }, + fromInt: { type: GraphQLInt } }, resolve(value, { fromEnum, fromInt }) { return fromInt !== undefined ? fromInt : fromEnum; @@ -60,23 +58,27 @@ describe('Type System: Enum Values', () => { }); const MutationType = new GraphQLObjectType({ - name: 'Mutation', + name: "Mutation", fields: { favoriteEnum: { type: ColorType, args: { color: { type: ColorType } }, - resolve(value, { color }) { return color; } + resolve(value, { color }) { + return color; + } } } }); const SubscriptionType = new GraphQLObjectType({ - name: 'Subscription', + name: "Subscription", fields: { subscribeToEnum: { type: ColorType, args: { color: { type: ColorType } }, - resolve(value, { color }) { return color; } + resolve(value, { color }) { + return color; + } } } }); @@ -87,9 +89,9 @@ describe('Type System: Enum Values', () => { subscription: SubscriptionType }); - it('accepts enum literals as input', async () => { + it("accepts enum literals as input", async () => { expect( - await graphql(schema, '{ colorInt(fromEnum: GREEN) }') + await graphql(schema, "{ colorInt(fromEnum: GREEN) }") ).to.deep.equal({ data: { colorInt: 1 @@ -97,40 +99,38 @@ describe('Type System: Enum Values', () => { }); }); - it('enum may be output type', async () => { - expect( - await graphql(schema, '{ colorEnum(fromInt: 1) }') - ).to.deep.equal({ + it("enum may be output type", async () => { + expect(await graphql(schema, "{ colorEnum(fromInt: 1) }")).to.deep.equal({ data: { - colorEnum: 'GREEN' + colorEnum: "GREEN" } }); }); - it('enum may be both input and output type', async () => { + it("enum may be both input and output type", async () => { expect( - await graphql(schema, '{ colorEnum(fromEnum: GREEN) }') + await graphql(schema, "{ colorEnum(fromEnum: GREEN) }") ).to.deep.equal({ data: { - colorEnum: 'GREEN' + colorEnum: "GREEN" } }); }); - it('does not accept string literals', async () => { + it("does not accept string literals", async () => { expect( await graphql(schema, '{ colorEnum(fromEnum: "GREEN") }') ).to.deep.equal({ errors: [ new Error( 'Argument "fromEnum" has invalid value "GREEN".' + - '\nExpected type \"Color\", found "GREEN".' + '\nExpected type "Color", found "GREEN".' ) ] }); }); - it('does not accept incorrect internal value', async () => { + it("does not accept incorrect internal value", async () => { expect( await graphql(schema, '{ colorEnum(fromString: "GREEN") }') ).to.deep.equal({ @@ -140,85 +140,83 @@ describe('Type System: Enum Values', () => { }); }); - it('does not accept internal value in place of enum literal', async () => { - expect( - await graphql(schema, '{ colorEnum(fromEnum: 1) }') - ).to.deep.equal({ + it("does not accept internal value in place of enum literal", async () => { + expect(await graphql(schema, "{ colorEnum(fromEnum: 1) }")).to.deep.equal({ errors: [ new Error( 'Argument "fromEnum" has invalid value 1.' + - '\nExpected type "Color", found 1.' + '\nExpected type "Color", found 1.' ) ] }); }); - it('does not accept enum literal in place of int', async () => { + it("does not accept enum literal in place of int", async () => { expect( - await graphql(schema, '{ colorEnum(fromInt: GREEN) }') + await graphql(schema, "{ colorEnum(fromInt: GREEN) }") ).to.deep.equal({ errors: [ new Error( 'Argument "fromInt" has invalid value GREEN.' + - '\nExpected type "Int", found GREEN.' + '\nExpected type "Int", found GREEN.' ) ] }); }); - it('accepts JSON string as enum variable', async () => { + it("accepts JSON string as enum variable", async () => { expect( await graphql( schema, - 'query test($color: Color!) { colorEnum(fromEnum: $color) }', + "query test($color: Color!) { colorEnum(fromEnum: $color) }", null, null, - { color: 'BLUE' } + { color: "BLUE" } ) ).to.deep.equal({ data: { - colorEnum: 'BLUE' + colorEnum: "BLUE" } }); }); - it('accepts enum literals as input arguments to mutations', async () => { + it("accepts enum literals as input arguments to mutations", async () => { expect( await graphql( schema, - 'mutation x($color: Color!) { favoriteEnum(color: $color) }', + "mutation x($color: Color!) { favoriteEnum(color: $color) }", null, null, - { color: 'GREEN' } + { color: "GREEN" } ) ).to.deep.equal({ data: { - favoriteEnum: 'GREEN' + favoriteEnum: "GREEN" } }); }); - it('accepts enum literals as input arguments to subscriptions', async () => { + it("accepts enum literals as input arguments to subscriptions", async () => { expect( await graphql( schema, - 'subscription x($color: Color!) { subscribeToEnum(color: $color) }', + "subscription x($color: Color!) { subscribeToEnum(color: $color) }", null, null, - { color: 'GREEN' } + { color: "GREEN" } ) ).to.deep.equal({ data: { - subscribeToEnum: 'GREEN' + subscribeToEnum: "GREEN" } }); }); - it('does not accept internal value as enum variable', async () => { + it("does not accept internal value as enum variable", async () => { expect( await graphql( schema, - 'query test($color: Color!) { colorEnum(fromEnum: $color) }', + "query test($color: Color!) { colorEnum(fromEnum: $color) }", null, null, { color: 2 } @@ -226,37 +224,37 @@ describe('Type System: Enum Values', () => { ).to.deep.equal({ errors: [ new Error( - 'Variable "\$color" got invalid value 2.' + - '\nExpected type "Color", found 2.' + 'Variable "$color" got invalid value 2.' + + '\nExpected type "Color", found 2.' ) ] }); }); - it('does not accept string variables as enum input', async () => { + it("does not accept string variables as enum input", async () => { expect( await graphql( schema, - 'query test($color: String!) { colorEnum(fromEnum: $color) }', + "query test($color: String!) { colorEnum(fromEnum: $color) }", null, null, - { color: 'BLUE' } + { color: "BLUE" } ) ).to.deep.equal({ errors: [ new Error( 'Variable "$color" of type "String!" used in position ' + - 'expecting type "Color".' + 'expecting type "Color".' ) ] }); }); - it('does not accept internal value variable as enum input', async () => { + it("does not accept internal value variable as enum input", async () => { expect( await graphql( schema, - 'query test($color: Int!) { colorEnum(fromEnum: $color) }', + "query test($color: Int!) { colorEnum(fromEnum: $color) }", null, null, { color: 2 } @@ -265,32 +263,42 @@ describe('Type System: Enum Values', () => { errors: [ new Error( 'Variable "$color" of type "Int!" used in position ' + - 'expecting type "Color".' + 'expecting type "Color".' ) ] }); }); - it('enum value may have an internal value of 0', async () => { + it("enum value may have an internal value of 0", async () => { expect( - await graphql(schema, `{ - colorEnum(fromEnum: RED) - colorInt(fromEnum: RED) - }`) + await graphql( + schema, + ` + { + colorEnum(fromEnum: RED) + colorInt(fromEnum: RED) + } + ` + ) ).to.deep.equal({ data: { - colorEnum: 'RED', + colorEnum: "RED", colorInt: 0 } }); }); - it('enum inputs may be nullable', async () => { + it("enum inputs may be nullable", async () => { expect( - await graphql(schema, `{ - colorEnum - colorInt - }`) + await graphql( + schema, + ` + { + colorEnum + colorInt + } + ` + ) ).to.deep.equal({ data: { colorEnum: null, @@ -298,5 +306,4 @@ describe('Type System: Enum Values', () => { } }); }); - }); diff --git a/src/type/__tests__/introspection-test.js b/src/type/__tests__/introspection-test.js index 64aa6f7c4b..859a1d3454 100644 --- a/src/type/__tests__/introspection-test.js +++ b/src/type/__tests__/introspection-test.js @@ -7,12 +7,10 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; +import { expect } from "chai"; +import { describe, it } from "mocha"; -import { - missingFieldArgMessage -} from '../../validation/rules/ProvidedNonNullArguments'; +import { missingFieldArgMessage } from "../../validation/rules/ProvidedNonNullArguments"; import { graphql, GraphQLSchema, @@ -20,16 +18,16 @@ import { GraphQLList, GraphQLInputObjectType, GraphQLString, - GraphQLEnumType, -} from '../../'; + GraphQLEnumType +} from "../../"; -import { introspectionQuery } from '../../utilities/introspectionQuery'; +import { introspectionQuery } from "../../utilities/introspectionQuery"; -describe('Introspection', () => { - it('executes an introspection query', async () => { +describe("Introspection", () => { + it("executes an introspection query", async () => { const EmptySchema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'QueryRoot', + name: "QueryRoot", fields: { onlyField: { type: GraphQLString } } @@ -44,36 +42,36 @@ describe('Introspection', () => { mutationType: null, subscriptionType: null, queryType: { - name: 'QueryRoot', + name: "QueryRoot" }, types: [ { - kind: 'OBJECT', - name: 'QueryRoot', + kind: "OBJECT", + name: "QueryRoot", inputFields: null, interfaces: [], enumValues: null, - possibleTypes: null, + possibleTypes: null }, { - kind: 'OBJECT', - name: '__Schema', + kind: "OBJECT", + name: "__Schema", fields: [ { - name: 'types', + name: "types", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'LIST', + kind: "LIST", name: null, ofType: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'OBJECT', - name: '__Type' + kind: "OBJECT", + name: "__Type" } } } @@ -82,14 +80,14 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'queryType', + name: "queryType", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'OBJECT', - name: '__Type', + kind: "OBJECT", + name: "__Type", ofType: null } }, @@ -97,42 +95,42 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'mutationType', + name: "mutationType", args: [], type: { - kind: 'OBJECT', - name: '__Type', + kind: "OBJECT", + name: "__Type", ofType: null }, isDeprecated: false, deprecationReason: null }, { - name: 'subscriptionType', + name: "subscriptionType", args: [], type: { - kind: 'OBJECT', - name: '__Type', + kind: "OBJECT", + name: "__Type", ofType: null }, isDeprecated: false, deprecationReason: null }, { - name: 'directives', + name: "directives", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'LIST', + kind: "LIST", name: null, ofType: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'OBJECT', - name: '__Directive' + kind: "OBJECT", + name: "__Directive" } } } @@ -144,21 +142,21 @@ describe('Introspection', () => { inputFields: null, interfaces: [], enumValues: null, - possibleTypes: null, + possibleTypes: null }, { - kind: 'OBJECT', - name: '__Type', + kind: "OBJECT", + name: "__Type", fields: [ { - name: 'kind', + name: "kind", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'ENUM', - name: '__TypeKind', + kind: "ENUM", + name: "__TypeKind", ofType: null } }, @@ -166,49 +164,49 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'name', + name: "name", args: [], type: { - kind: 'SCALAR', - name: 'String', + kind: "SCALAR", + name: "String", ofType: null }, isDeprecated: false, deprecationReason: null }, { - name: 'description', + name: "description", args: [], type: { - kind: 'SCALAR', - name: 'String', + kind: "SCALAR", + name: "String", ofType: null }, isDeprecated: false, deprecationReason: null }, { - name: 'fields', + name: "fields", args: [ { - name: 'includeDeprecated', + name: "includeDeprecated", type: { - kind: 'SCALAR', - name: 'Boolean', + kind: "SCALAR", + name: "Boolean", ofType: null }, - defaultValue: 'false' + defaultValue: "false" } ], type: { - kind: 'LIST', + kind: "LIST", name: null, ofType: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'OBJECT', - name: '__Field', + kind: "OBJECT", + name: "__Field", ofType: null } } @@ -217,17 +215,17 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'interfaces', + name: "interfaces", args: [], type: { - kind: 'LIST', + kind: "LIST", name: null, ofType: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'OBJECT', - name: '__Type', + kind: "OBJECT", + name: "__Type", ofType: null } } @@ -236,17 +234,17 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'possibleTypes', + name: "possibleTypes", args: [], type: { - kind: 'LIST', + kind: "LIST", name: null, ofType: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'OBJECT', - name: '__Type', + kind: "OBJECT", + name: "__Type", ofType: null } } @@ -255,27 +253,27 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'enumValues', + name: "enumValues", args: [ { - name: 'includeDeprecated', + name: "includeDeprecated", type: { - kind: 'SCALAR', - name: 'Boolean', + kind: "SCALAR", + name: "Boolean", ofType: null }, - defaultValue: 'false' + defaultValue: "false" } ], type: { - kind: 'LIST', + kind: "LIST", name: null, ofType: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'OBJECT', - name: '__EnumValue', + kind: "OBJECT", + name: "__EnumValue", ofType: null } } @@ -284,17 +282,17 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'inputFields', + name: "inputFields", args: [], type: { - kind: 'LIST', + kind: "LIST", name: null, ofType: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'OBJECT', - name: '__InputValue', + kind: "OBJECT", + name: "__InputValue", ofType: null } } @@ -303,11 +301,11 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'ofType', + name: "ofType", args: [], type: { - kind: 'OBJECT', - name: '__Type', + kind: "OBJECT", + name: "__Type", ofType: null }, isDeprecated: false, @@ -317,89 +315,89 @@ describe('Introspection', () => { inputFields: null, interfaces: [], enumValues: null, - possibleTypes: null, + possibleTypes: null }, { - kind: 'ENUM', - name: '__TypeKind', + kind: "ENUM", + name: "__TypeKind", fields: null, inputFields: null, interfaces: null, enumValues: [ { - name: 'SCALAR', + name: "SCALAR", isDeprecated: false, deprecationReason: null }, { - name: 'OBJECT', + name: "OBJECT", isDeprecated: false, deprecationReason: null }, { - name: 'INTERFACE', + name: "INTERFACE", isDeprecated: false, deprecationReason: null }, { - name: 'UNION', + name: "UNION", isDeprecated: false, deprecationReason: null }, { - name: 'ENUM', + name: "ENUM", isDeprecated: false, deprecationReason: null }, { - name: 'INPUT_OBJECT', + name: "INPUT_OBJECT", isDeprecated: false, deprecationReason: null }, { - name: 'LIST', + name: "LIST", isDeprecated: false, deprecationReason: null }, { - name: 'NON_NULL', + name: "NON_NULL", isDeprecated: false, deprecationReason: null } ], - possibleTypes: null, + possibleTypes: null }, { - kind: 'SCALAR', - name: 'String', + kind: "SCALAR", + name: "String", fields: null, inputFields: null, interfaces: null, enumValues: null, - possibleTypes: null, + possibleTypes: null }, { - kind: 'SCALAR', - name: 'Boolean', + kind: "SCALAR", + name: "Boolean", fields: null, inputFields: null, interfaces: null, enumValues: null, - possibleTypes: null, + possibleTypes: null }, { - kind: 'OBJECT', - name: '__Field', + kind: "OBJECT", + name: "__Field", fields: [ { - name: 'name', + name: "name", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'SCALAR', - name: 'String', + kind: "SCALAR", + name: "String", ofType: null } }, @@ -407,31 +405,31 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'description', + name: "description", args: [], type: { - kind: 'SCALAR', - name: 'String', + kind: "SCALAR", + name: "String", ofType: null }, isDeprecated: false, deprecationReason: null }, { - name: 'args', + name: "args", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'LIST', + kind: "LIST", name: null, ofType: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'OBJECT', - name: '__InputValue' + kind: "OBJECT", + name: "__InputValue" } } } @@ -440,14 +438,14 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'type', + name: "type", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'OBJECT', - name: '__Type', + kind: "OBJECT", + name: "__Type", ofType: null } }, @@ -455,14 +453,14 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'isDeprecated', + name: "isDeprecated", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'SCALAR', - name: 'Boolean', + kind: "SCALAR", + name: "Boolean", ofType: null } }, @@ -470,11 +468,11 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'deprecationReason', + name: "deprecationReason", args: [], type: { - kind: 'SCALAR', - name: 'String', + kind: "SCALAR", + name: "String", ofType: null }, isDeprecated: false, @@ -484,21 +482,21 @@ describe('Introspection', () => { inputFields: null, interfaces: [], enumValues: null, - possibleTypes: null, + possibleTypes: null }, { - kind: 'OBJECT', - name: '__InputValue', + kind: "OBJECT", + name: "__InputValue", fields: [ { - name: 'name', + name: "name", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'SCALAR', - name: 'String', + kind: "SCALAR", + name: "String", ofType: null } }, @@ -506,25 +504,25 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'description', + name: "description", args: [], type: { - kind: 'SCALAR', - name: 'String', + kind: "SCALAR", + name: "String", ofType: null }, isDeprecated: false, deprecationReason: null }, { - name: 'type', + name: "type", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'OBJECT', - name: '__Type', + kind: "OBJECT", + name: "__Type", ofType: null } }, @@ -532,11 +530,11 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'defaultValue', + name: "defaultValue", args: [], type: { - kind: 'SCALAR', - name: 'String', + kind: "SCALAR", + name: "String", ofType: null }, isDeprecated: false, @@ -546,21 +544,21 @@ describe('Introspection', () => { inputFields: null, interfaces: [], enumValues: null, - possibleTypes: null, + possibleTypes: null }, { - kind: 'OBJECT', - name: '__EnumValue', + kind: "OBJECT", + name: "__EnumValue", fields: [ { - name: 'name', + name: "name", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'SCALAR', - name: 'String', + kind: "SCALAR", + name: "String", ofType: null } }, @@ -568,25 +566,25 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'description', + name: "description", args: [], type: { - kind: 'SCALAR', - name: 'String', + kind: "SCALAR", + name: "String", ofType: null }, isDeprecated: false, deprecationReason: null }, { - name: 'isDeprecated', + name: "isDeprecated", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'SCALAR', - name: 'Boolean', + kind: "SCALAR", + name: "Boolean", ofType: null } }, @@ -594,11 +592,11 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'deprecationReason', + name: "deprecationReason", args: [], type: { - kind: 'SCALAR', - name: 'String', + kind: "SCALAR", + name: "String", ofType: null }, isDeprecated: false, @@ -608,21 +606,21 @@ describe('Introspection', () => { inputFields: null, interfaces: [], enumValues: null, - possibleTypes: null, + possibleTypes: null }, { - kind: 'OBJECT', - name: '__Directive', + kind: "OBJECT", + name: "__Directive", fields: [ { - name: 'name', + name: "name", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'SCALAR', - name: 'String', + kind: "SCALAR", + name: "String", ofType: null } }, @@ -630,31 +628,31 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'description', + name: "description", args: [], type: { - kind: 'SCALAR', - name: 'String', + kind: "SCALAR", + name: "String", ofType: null }, isDeprecated: false, deprecationReason: null }, { - name: 'locations', + name: "locations", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'LIST', + kind: "LIST", name: null, ofType: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'ENUM', - name: '__DirectiveLocation' + kind: "ENUM", + name: "__DirectiveLocation" } } } @@ -663,20 +661,20 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'args', + name: "args", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'LIST', + kind: "LIST", name: null, ofType: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'OBJECT', - name: '__InputValue' + kind: "OBJECT", + name: "__InputValue" } } } @@ -685,133 +683,133 @@ describe('Introspection', () => { deprecationReason: null }, { - name: 'onOperation', + name: "onOperation", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'SCALAR', - name: 'Boolean', - ofType: null, - }, + kind: "SCALAR", + name: "Boolean", + ofType: null + } }, isDeprecated: true, - deprecationReason: 'Use `locations`.' + deprecationReason: "Use `locations`." }, { - name: 'onFragment', + name: "onFragment", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'SCALAR', - name: 'Boolean', - ofType: null, - }, + kind: "SCALAR", + name: "Boolean", + ofType: null + } }, isDeprecated: true, - deprecationReason: 'Use `locations`.' + deprecationReason: "Use `locations`." }, { - name: 'onField', + name: "onField", args: [], type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'SCALAR', - name: 'Boolean', - ofType: null, - }, + kind: "SCALAR", + name: "Boolean", + ofType: null + } }, isDeprecated: true, - deprecationReason: 'Use `locations`.' + deprecationReason: "Use `locations`." } ], inputFields: null, interfaces: [], enumValues: null, - possibleTypes: null, + possibleTypes: null }, { - kind: 'ENUM', - name: '__DirectiveLocation', + kind: "ENUM", + name: "__DirectiveLocation", fields: null, inputFields: null, interfaces: null, enumValues: [ { - name: 'QUERY', + name: "QUERY", isDeprecated: false }, { - name: 'MUTATION', + name: "MUTATION", isDeprecated: false }, { - name: 'SUBSCRIPTION', + name: "SUBSCRIPTION", isDeprecated: false }, { - name: 'FIELD', + name: "FIELD", isDeprecated: false }, { - name: 'FRAGMENT_DEFINITION', + name: "FRAGMENT_DEFINITION", isDeprecated: false }, { - name: 'FRAGMENT_SPREAD', + name: "FRAGMENT_SPREAD", isDeprecated: false }, { - name: 'INLINE_FRAGMENT', + name: "INLINE_FRAGMENT", isDeprecated: false - }, + } ], - possibleTypes: null, + possibleTypes: null } ], directives: [ { - name: 'include', - locations: [ 'FIELD', 'FRAGMENT_SPREAD', 'INLINE_FRAGMENT' ], + name: "include", + locations: ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], args: [ { defaultValue: null, - name: 'if', + name: "if", type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'SCALAR', - name: 'Boolean', + kind: "SCALAR", + name: "Boolean", ofType: null } } } - ], + ] }, { - name: 'skip', - locations: [ 'FIELD', 'FRAGMENT_SPREAD', 'INLINE_FRAGMENT' ], + name: "skip", + locations: ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], args: [ { defaultValue: null, - name: 'if', + name: "if", type: { - kind: 'NON_NULL', + kind: "NON_NULL", name: null, ofType: { - kind: 'SCALAR', - name: 'Boolean', + kind: "SCALAR", + name: "Boolean", ofType: null } } } - ], + ] } ] } @@ -819,18 +817,17 @@ describe('Introspection', () => { }); }); - it('introspects on input object', async () => { - + it("introspects on input object", async () => { const TestInputObject = new GraphQLInputObjectType({ - name: 'TestInputObject', + name: "TestInputObject", fields: { - a: { type: GraphQLString, defaultValue: 'foo' }, + a: { type: GraphQLString, defaultValue: "foo" }, b: { type: new GraphQLList(GraphQLString) } } }); const TestType = new GraphQLObjectType({ - name: 'TestType', + name: "TestType", fields: { field: { type: GraphQLString, @@ -874,39 +871,50 @@ describe('Introspection', () => { } `; - return expect( - await graphql(schema, request) - ).to.containSubset({ - data: - { __schema: - { types: - [ { kind: 'INPUT_OBJECT', - name: 'TestInputObject', - inputFields: - [ { name: 'a', - type: - { kind: 'SCALAR', - name: 'String', - ofType: null }, - defaultValue: '"foo"' }, - { name: 'b', - type: - { kind: 'LIST', - name: null, - ofType: - { kind: 'SCALAR', - name: 'String', - ofType: null } }, - defaultValue: null } ] } ] } } + return expect(await graphql(schema, request)).to.containSubset({ + data: { + __schema: { + types: [ + { + kind: "INPUT_OBJECT", + name: "TestInputObject", + inputFields: [ + { + name: "a", + type: { + kind: "SCALAR", + name: "String", + ofType: null + }, + defaultValue: '"foo"' + }, + { + name: "b", + type: { + kind: "LIST", + name: null, + ofType: { + kind: "SCALAR", + name: "String", + ofType: null + } + }, + defaultValue: null + } + ] + } + ] + } + } }); }); - it('supports the __type root field', async () => { + it("supports the __type root field", async () => { const TestType = new GraphQLObjectType({ - name: 'TestType', + name: "TestType", fields: { testField: { - type: GraphQLString, + type: GraphQLString } } }); @@ -920,28 +928,25 @@ describe('Introspection', () => { } `; - return expect( - await graphql(schema, request) - ).to.deep.equal({ + return expect(await graphql(schema, request)).to.deep.equal({ data: { __type: { - name: 'TestType' + name: "TestType" } } }); }); - it('identifies deprecated fields', async () => { - + it("identifies deprecated fields", async () => { const TestType = new GraphQLObjectType({ - name: 'TestType', + name: "TestType", fields: { nonDeprecated: { - type: GraphQLString, + type: GraphQLString }, deprecated: { type: GraphQLString, - deprecationReason: 'Removed in 1.0' + deprecationReason: "Removed in 1.0" } } }); @@ -960,22 +965,20 @@ describe('Introspection', () => { } `; - return expect( - await graphql(schema, request) - ).to.deep.equal({ + return expect(await graphql(schema, request)).to.deep.equal({ data: { __type: { - name: 'TestType', + name: "TestType", fields: [ { - name: 'nonDeprecated', + name: "nonDeprecated", isDeprecated: false, deprecationReason: null }, { - name: 'deprecated', + name: "deprecated", isDeprecated: true, - deprecationReason: 'Removed in 1.0' + deprecationReason: "Removed in 1.0" } ] } @@ -983,17 +986,16 @@ describe('Introspection', () => { }); }); - it('respects the includeDeprecated parameter for fields', async () => { - + it("respects the includeDeprecated parameter for fields", async () => { const TestType = new GraphQLObjectType({ - name: 'TestType', + name: "TestType", fields: { nonDeprecated: { - type: GraphQLString, + type: GraphQLString }, deprecated: { type: GraphQLString, - deprecationReason: 'Removed in 1.0' + deprecationReason: "Removed in 1.0" } } }); @@ -1016,52 +1018,49 @@ describe('Introspection', () => { } `; - return expect( - await graphql(schema, request) - ).to.deep.equal({ + return expect(await graphql(schema, request)).to.deep.equal({ data: { __type: { - name: 'TestType', + name: "TestType", trueFields: [ { - name: 'nonDeprecated', + name: "nonDeprecated" }, { - name: 'deprecated', + name: "deprecated" } ], falseFields: [ { - name: 'nonDeprecated', + name: "nonDeprecated" } ], omittedFields: [ { - name: 'nonDeprecated', + name: "nonDeprecated" } - ], + ] } } }); }); - it('identifies deprecated enum values', async () => { - + it("identifies deprecated enum values", async () => { const TestEnum = new GraphQLEnumType({ - name: 'TestEnum', + name: "TestEnum", values: { NONDEPRECATED: { value: 0 }, - DEPRECATED: { value: 1, deprecationReason: 'Removed in 1.0' }, + DEPRECATED: { value: 1, deprecationReason: "Removed in 1.0" }, ALSONONDEPRECATED: { value: 2 } } }); const TestType = new GraphQLObjectType({ - name: 'TestType', + name: "TestType", fields: { testEnum: { - type: TestEnum, - }, + type: TestEnum + } } }); @@ -1079,25 +1078,23 @@ describe('Introspection', () => { } `; - return expect( - await graphql(schema, request) - ).to.deep.equal({ + return expect(await graphql(schema, request)).to.deep.equal({ data: { __type: { - name: 'TestEnum', + name: "TestEnum", enumValues: [ { - name: 'NONDEPRECATED', + name: "NONDEPRECATED", isDeprecated: false, deprecationReason: null }, { - name: 'DEPRECATED', + name: "DEPRECATED", isDeprecated: true, - deprecationReason: 'Removed in 1.0' + deprecationReason: "Removed in 1.0" }, { - name: 'ALSONONDEPRECATED', + name: "ALSONONDEPRECATED", isDeprecated: false, deprecationReason: null } @@ -1107,23 +1104,22 @@ describe('Introspection', () => { }); }); - it('respects the includeDeprecated parameter for enum values', async () => { - + it("respects the includeDeprecated parameter for enum values", async () => { const TestEnum = new GraphQLEnumType({ - name: 'TestEnum', + name: "TestEnum", values: { NONDEPRECATED: { value: 0 }, - DEPRECATED: { value: 1, deprecationReason: 'Removed in 1.0' }, + DEPRECATED: { value: 1, deprecationReason: "Removed in 1.0" }, ALSONONDEPRECATED: { value: 2 } } }); const TestType = new GraphQLObjectType({ - name: 'TestType', + name: "TestType", fields: { testEnum: { - type: TestEnum, - }, + type: TestEnum + } } }); @@ -1145,50 +1141,48 @@ describe('Introspection', () => { } `; - return expect( - await graphql(schema, request) - ).to.deep.equal({ + return expect(await graphql(schema, request)).to.deep.equal({ data: { __type: { - name: 'TestEnum', + name: "TestEnum", trueValues: [ { - name: 'NONDEPRECATED', + name: "NONDEPRECATED" }, { - name: 'DEPRECATED', + name: "DEPRECATED" }, { - name: 'ALSONONDEPRECATED', + name: "ALSONONDEPRECATED" } ], falseValues: [ { - name: 'NONDEPRECATED', + name: "NONDEPRECATED" }, { - name: 'ALSONONDEPRECATED', + name: "ALSONONDEPRECATED" } ], omittedValues: [ { - name: 'NONDEPRECATED', + name: "NONDEPRECATED" }, { - name: 'ALSONONDEPRECATED', + name: "ALSONONDEPRECATED" } - ], + ] } } }); }); - it('fails as expected on the __type root field without an arg', async () => { + it("fails as expected on the __type root field without an arg", async () => { const TestType = new GraphQLObjectType({ - name: 'TestType', + name: "TestType", fields: { testField: { - type: GraphQLString, + type: GraphQLString } } }); @@ -1202,19 +1196,19 @@ describe('Introspection', () => { } `; - return expect( - await graphql(schema, request) - ).to.containSubset({ + return expect(await graphql(schema, request)).to.containSubset({ errors: [ - { message: missingFieldArgMessage('__type', 'name', 'String!'), - locations: [ { line: 3, column: 9 } ] } + { + message: missingFieldArgMessage("__type", "name", "String!"), + locations: [{ line: 3, column: 9 }] + } ] }); }); - it('exposes descriptions on types and fields', async () => { + it("exposes descriptions on types and fields", async () => { const QueryRoot = new GraphQLObjectType({ - name: 'QueryRoot', + name: "QueryRoot", fields: { onlyField: { type: GraphQLString } } @@ -1234,39 +1228,40 @@ describe('Introspection', () => { } `; - return expect( - await graphql(schema, request) - ).to.deep.equal({ + return expect(await graphql(schema, request)).to.deep.equal({ data: { schemaType: { - name: '__Schema', - description: 'A GraphQL Schema defines the capabilities of a ' + - 'GraphQL server. It exposes all available types and ' + - 'directives on the server, as well as the entry ' + - 'points for query, mutation, ' + - 'and subscription operations.', + name: "__Schema", + description: + "A GraphQL Schema defines the capabilities of a " + + "GraphQL server. It exposes all available types and " + + "directives on the server, as well as the entry " + + "points for query, mutation, " + + "and subscription operations.", fields: [ { - name: 'types', - description: 'A list of all types supported by this server.' + name: "types", + description: "A list of all types supported by this server." }, { - name: 'queryType', - description: 'The type that query operations will be rooted at.' + name: "queryType", + description: "The type that query operations will be rooted at." }, { - name: 'mutationType', - description: 'If this server supports mutation, the type that ' + - 'mutation operations will be rooted at.' + name: "mutationType", + description: + "If this server supports mutation, the type that " + + "mutation operations will be rooted at." }, { - name: 'subscriptionType', - description: 'If this server support subscription, the type ' + - 'that subscription operations will be rooted at.', + name: "subscriptionType", + description: + "If this server support subscription, the type " + + "that subscription operations will be rooted at." }, { - name: 'directives', - description: 'A list of all directives supported by this server.' + name: "directives", + description: "A list of all directives supported by this server." } ] } @@ -1274,9 +1269,9 @@ describe('Introspection', () => { }); }); - it('exposes descriptions on enums', async () => { + it("exposes descriptions on enums", async () => { const QueryRoot = new GraphQLObjectType({ - name: 'QueryRoot', + name: "QueryRoot", fields: { onlyField: { type: GraphQLString } } @@ -1296,58 +1291,62 @@ describe('Introspection', () => { } `; - return expect( - await graphql(schema, request) - ).to.deep.equal({ + return expect(await graphql(schema, request)).to.deep.equal({ data: { typeKindType: { - name: '__TypeKind', + name: "__TypeKind", description: - 'An enum describing what kind of type a given `__Type` is.', + "An enum describing what kind of type a given `__Type` is.", enumValues: [ { - description: 'Indicates this type is a scalar.', - name: 'SCALAR' + description: "Indicates this type is a scalar.", + name: "SCALAR" }, { - description: 'Indicates this type is an object. ' + - '`fields` and `interfaces` are valid fields.', - name: 'OBJECT' + description: + "Indicates this type is an object. " + + "`fields` and `interfaces` are valid fields.", + name: "OBJECT" }, { - description: 'Indicates this type is an interface. ' + - '`fields` and `possibleTypes` are valid fields.', - name: 'INTERFACE' + description: + "Indicates this type is an interface. " + + "`fields` and `possibleTypes` are valid fields.", + name: "INTERFACE" }, { - description: 'Indicates this type is a union. ' + - '`possibleTypes` is a valid field.', - name: 'UNION' + description: + "Indicates this type is a union. " + + "`possibleTypes` is a valid field.", + name: "UNION" }, { - description: 'Indicates this type is an enum. ' + - '`enumValues` is a valid field.', - name: 'ENUM' + description: + "Indicates this type is an enum. " + + "`enumValues` is a valid field.", + name: "ENUM" }, { - description: 'Indicates this type is an input object. ' + - '`inputFields` is a valid field.', - name: 'INPUT_OBJECT' + description: + "Indicates this type is an input object. " + + "`inputFields` is a valid field.", + name: "INPUT_OBJECT" }, { - description: 'Indicates this type is a list. ' + - '`ofType` is a valid field.', - name: 'LIST' + description: + "Indicates this type is a list. " + + "`ofType` is a valid field.", + name: "LIST" }, { - description: 'Indicates this type is a non-null. ' + - '`ofType` is a valid field.', - name: 'NON_NULL' + description: + "Indicates this type is a non-null. " + + "`ofType` is a valid field.", + name: "NON_NULL" } ] } } }); }); - }); diff --git a/src/type/__tests__/serialization-test.js b/src/type/__tests__/serialization-test.js index 4231d073b4..339ffe3f2f 100644 --- a/src/type/__tests__/serialization-test.js +++ b/src/type/__tests__/serialization-test.js @@ -7,138 +7,60 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { - GraphQLInt, - GraphQLFloat, - GraphQLString, - GraphQLBoolean -} from '../'; +import { GraphQLInt, GraphQLFloat, GraphQLString, GraphQLBoolean } from "../"; -import { describe, it } from 'mocha'; -import { expect } from 'chai'; +import { describe, it } from "mocha"; +import { expect } from "chai"; - -describe('Type System: Scalar coercion', () => { - it('serializes output int', () => { - expect( - GraphQLInt.serialize(1) - ).to.equal(1); - expect( - GraphQLInt.serialize(0) - ).to.equal(0); - expect( - GraphQLInt.serialize(-1) - ).to.equal(-1); - expect( - GraphQLInt.serialize(0.1) - ).to.equal(0); - expect( - GraphQLInt.serialize(1.1) - ).to.equal(1); - expect( - GraphQLInt.serialize(-1.1) - ).to.equal(-1); - expect( - GraphQLInt.serialize(1e5) - ).to.equal(100000); +describe("Type System: Scalar coercion", () => { + it("serializes output int", () => { + expect(GraphQLInt.serialize(1)).to.equal(1); + expect(GraphQLInt.serialize(0)).to.equal(0); + expect(GraphQLInt.serialize(-1)).to.equal(-1); + expect(GraphQLInt.serialize(0.1)).to.equal(0); + expect(GraphQLInt.serialize(1.1)).to.equal(1); + expect(GraphQLInt.serialize(-1.1)).to.equal(-1); + expect(GraphQLInt.serialize(1e5)).to.equal(100000); // Maybe a safe JavaScript int, but bigger than 2^32, so not // representable as a GraphQL Int - expect( - GraphQLInt.serialize(9876504321) - ).to.equal(null); - expect( - GraphQLInt.serialize(-9876504321) - ).to.equal(null); + expect(GraphQLInt.serialize(9876504321)).to.equal(null); + expect(GraphQLInt.serialize(-9876504321)).to.equal(null); // Too big to represent as an Int in JavaScript or GraphQL - expect( - GraphQLInt.serialize(1e100) - ).to.equal(null); - expect( - GraphQLInt.serialize(-1e100) - ).to.equal(null); - expect( - GraphQLInt.serialize('-1.1') - ).to.equal(-1); - expect( - GraphQLInt.serialize('one') - ).to.equal(null); - expect( - GraphQLInt.serialize(false) - ).to.equal(0); - expect( - GraphQLInt.serialize(true) - ).to.equal(1); + expect(GraphQLInt.serialize(1e100)).to.equal(null); + expect(GraphQLInt.serialize(-1e100)).to.equal(null); + expect(GraphQLInt.serialize("-1.1")).to.equal(-1); + expect(GraphQLInt.serialize("one")).to.equal(null); + expect(GraphQLInt.serialize(false)).to.equal(0); + expect(GraphQLInt.serialize(true)).to.equal(1); }); - it('serializes output float', () => { - expect( - GraphQLFloat.serialize(1) - ).to.equal(1.0); - expect( - GraphQLFloat.serialize(0) - ).to.equal(0.0); - expect( - GraphQLFloat.serialize(-1) - ).to.equal(-1.0); - expect( - GraphQLFloat.serialize(0.1) - ).to.equal(0.1); - expect( - GraphQLFloat.serialize(1.1) - ).to.equal(1.1); - expect( - GraphQLFloat.serialize(-1.1) - ).to.equal(-1.1); - expect( - GraphQLFloat.serialize('-1.1') - ).to.equal(-1.1); - expect( - GraphQLFloat.serialize('one') - ).to.equal(null); - expect( - GraphQLFloat.serialize(false) - ).to.equal(0.0); - expect( - GraphQLFloat.serialize(true) - ).to.equal(1.0); + it("serializes output float", () => { + expect(GraphQLFloat.serialize(1)).to.equal(1.0); + expect(GraphQLFloat.serialize(0)).to.equal(0.0); + expect(GraphQLFloat.serialize(-1)).to.equal(-1.0); + expect(GraphQLFloat.serialize(0.1)).to.equal(0.1); + expect(GraphQLFloat.serialize(1.1)).to.equal(1.1); + expect(GraphQLFloat.serialize(-1.1)).to.equal(-1.1); + expect(GraphQLFloat.serialize("-1.1")).to.equal(-1.1); + expect(GraphQLFloat.serialize("one")).to.equal(null); + expect(GraphQLFloat.serialize(false)).to.equal(0.0); + expect(GraphQLFloat.serialize(true)).to.equal(1.0); }); - it('serializes output strings', () => { - expect( - GraphQLString.serialize('string') - ).to.equal('string'); - expect( - GraphQLString.serialize(1) - ).to.equal('1'); - expect( - GraphQLString.serialize(-1.1) - ).to.equal('-1.1'); - expect( - GraphQLString.serialize(true) - ).to.equal('true'); - expect( - GraphQLString.serialize(false) - ).to.equal('false'); + it("serializes output strings", () => { + expect(GraphQLString.serialize("string")).to.equal("string"); + expect(GraphQLString.serialize(1)).to.equal("1"); + expect(GraphQLString.serialize(-1.1)).to.equal("-1.1"); + expect(GraphQLString.serialize(true)).to.equal("true"); + expect(GraphQLString.serialize(false)).to.equal("false"); }); - it('serializes output boolean', () => { - expect( - GraphQLBoolean.serialize('string') - ).to.equal(true); - expect( - GraphQLBoolean.serialize('') - ).to.equal(false); - expect( - GraphQLBoolean.serialize(1) - ).to.equal(true); - expect( - GraphQLBoolean.serialize(0) - ).to.equal(false); - expect( - GraphQLBoolean.serialize(true) - ).to.equal(true); - expect( - GraphQLBoolean.serialize(false) - ).to.equal(false); + it("serializes output boolean", () => { + expect(GraphQLBoolean.serialize("string")).to.equal(true); + expect(GraphQLBoolean.serialize("")).to.equal(false); + expect(GraphQLBoolean.serialize(1)).to.equal(true); + expect(GraphQLBoolean.serialize(0)).to.equal(false); + expect(GraphQLBoolean.serialize(true)).to.equal(true); + expect(GraphQLBoolean.serialize(false)).to.equal(false); }); }); diff --git a/src/type/__tests__/validation-test.js b/src/type/__tests__/validation-test.js index c73bed3999..ebe74ae06b 100644 --- a/src/type/__tests__/validation-test.js +++ b/src/type/__tests__/validation-test.js @@ -10,8 +10,8 @@ // 80+ char lines are useful in describe/it, so ignore in this file. /* eslint-disable max-len */ -import { describe, it } from 'mocha'; -import { expect } from 'chai'; +import { describe, it } from "mocha"; +import { expect } from "chai"; import { GraphQLSchema, GraphQLScalarType, @@ -22,51 +22,50 @@ import { GraphQLInputObjectType, GraphQLList, GraphQLNonNull, - GraphQLString, -} from '../../'; - + GraphQLString +} from "../../"; const SomeScalarType = new GraphQLScalarType({ - name: 'SomeScalar', + name: "SomeScalar", serialize() {}, parseValue() {}, parseLiteral() {} }); const SomeObjectType = new GraphQLObjectType({ - name: 'SomeObject', + name: "SomeObject", fields: { f: { type: GraphQLString } } }); const ObjectWithIsTypeOf = new GraphQLObjectType({ - name: 'ObjectWithIsTypeOf', + name: "ObjectWithIsTypeOf", isTypeOf: () => true, - fields: { f: { type: GraphQLString} } + fields: { f: { type: GraphQLString } } }); const SomeUnionType = new GraphQLUnionType({ - name: 'SomeUnion', + name: "SomeUnion", resolveType: () => null, - types: [ SomeObjectType ] + types: [SomeObjectType] }); const SomeInterfaceType = new GraphQLInterfaceType({ - name: 'SomeInterface', + name: "SomeInterface", resolveType: () => null, fields: { f: { type: GraphQLString } } }); const SomeEnumType = new GraphQLEnumType({ - name: 'SomeEnum', + name: "SomeEnum", values: { ONLY: {} } }); const SomeInputObjectType = new GraphQLInputObjectType({ - name: 'SomeInputObject', + name: "SomeInputObject", fields: { - val: { type: GraphQLString, defaultValue: 'hello' } + val: { type: GraphQLString, defaultValue: "hello" } } }); @@ -83,51 +82,48 @@ const outputTypes = withModifiers([ SomeEnumType, SomeObjectType, SomeUnionType, - SomeInterfaceType, + SomeInterfaceType ]); -const notOutputTypes = withModifiers([ - SomeInputObjectType, -]).concat(String); +const notOutputTypes = withModifiers([SomeInputObjectType]).concat(String); const inputTypes = withModifiers([ GraphQLString, SomeScalarType, SomeEnumType, - SomeInputObjectType, + SomeInputObjectType ]); const notInputTypes = withModifiers([ SomeObjectType, SomeUnionType, - SomeInterfaceType, + SomeInterfaceType ]).concat(String); function schemaWithFieldType(type) { return new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { f: { type } } }), - types: [ type ], + types: [type] }); } - -describe('Type System: A Schema must have Object root types', () => { - - it('accepts a Schema whose query type is an object type', () => { +describe("Type System: A Schema must have Object root types", () => { + it("accepts a Schema whose query type is an object type", () => { expect( - () => new GraphQLSchema({ - query: SomeObjectType - }) + () => + new GraphQLSchema({ + query: SomeObjectType + }) ).not.to.throw(); }); - it('accepts a Schema whose query and mutation types are object types', () => { + it("accepts a Schema whose query and mutation types are object types", () => { expect(() => { const MutationType = new GraphQLObjectType({ - name: 'Mutation', + name: "Mutation", fields: { edit: { type: GraphQLString } } }); @@ -138,10 +134,10 @@ describe('Type System: A Schema must have Object root types', () => { }).not.to.throw(); }); - it('accepts a Schema whose query and subscription types are object types', () => { + it("accepts a Schema whose query and subscription types are object types", () => { expect(() => { const SubscriptionType = new GraphQLObjectType({ - name: 'Subscription', + name: "Subscription", fields: { subscribe: { type: GraphQLString } } }); @@ -152,95 +148,92 @@ describe('Type System: A Schema must have Object root types', () => { }).not.to.throw(); }); - it('rejects a Schema without a query type', () => { - expect( - () => new GraphQLSchema({ }) - ).to.throw( - 'Schema query must be Object Type but got: undefined.' + it("rejects a Schema without a query type", () => { + expect(() => new GraphQLSchema({})).to.throw( + "Schema query must be Object Type but got: undefined." ); }); - it('rejects a Schema whose query type is an input type', () => { - expect( - () => new GraphQLSchema({ query: SomeInputObjectType }) - ).to.throw( - 'Schema query must be Object Type but got: SomeInputObject.' + it("rejects a Schema whose query type is an input type", () => { + expect(() => new GraphQLSchema({ query: SomeInputObjectType })).to.throw( + "Schema query must be Object Type but got: SomeInputObject." ); }); - it('rejects a Schema whose mutation type is an input type', () => { + it("rejects a Schema whose mutation type is an input type", () => { expect( - () => new GraphQLSchema({ - query: SomeObjectType, - mutation: SomeInputObjectType - }) + () => + new GraphQLSchema({ + query: SomeObjectType, + mutation: SomeInputObjectType + }) ).to.throw( - 'Schema mutation must be Object Type if provided but got: SomeInputObject.' + "Schema mutation must be Object Type if provided but got: SomeInputObject." ); }); - it('rejects a Schema whose subscription type is an input type', () => { + it("rejects a Schema whose subscription type is an input type", () => { expect( - () => new GraphQLSchema({ - query: SomeObjectType, - subscription: SomeInputObjectType - }) + () => + new GraphQLSchema({ + query: SomeObjectType, + subscription: SomeInputObjectType + }) ).to.throw( - 'Schema subscription must be Object Type if provided but got: SomeInputObject.' + "Schema subscription must be Object Type if provided but got: SomeInputObject." ); }); - it('rejects a Schema whose directives are incorrectly typed', () => { + it("rejects a Schema whose directives are incorrectly typed", () => { expect( - () => new GraphQLSchema({ - query: SomeObjectType, - directives: [ 'somedirective' ] - }) + () => + new GraphQLSchema({ + query: SomeObjectType, + directives: ["somedirective"] + }) ).to.throw( - 'Schema directives must be Array if provided but got: somedirective.' + "Schema directives must be Array if provided but got: somedirective." ); }); - }); -describe('Type System: A Schema must contain uniquely named types', () => { - - it('rejects a Schema which redefines a built-in type', () => { +describe("Type System: A Schema must contain uniquely named types", () => { + it("rejects a Schema which redefines a built-in type", () => { expect(() => { const FakeString = new GraphQLScalarType({ - name: 'String', - serialize: () => null, + name: "String", + serialize: () => null }); const QueryType = new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { normal: { type: GraphQLString }, - fake: { type: FakeString }, + fake: { type: FakeString } } }); return new GraphQLSchema({ query: QueryType }); }).to.throw( - 'Schema must contain unique named types but contains multiple types ' + - 'named "String".' + "Schema must contain unique named types but contains multiple types " + + 'named "String".' ); }); - it('rejects a Schema which defines an object type twice', () => { + it("rejects a Schema which defines an object type twice", () => { expect(() => { const A = new GraphQLObjectType({ - name: 'SameName', - fields: { f: { type: GraphQLString } }, + name: "SameName", + fields: { f: { type: GraphQLString } } }); const B = new GraphQLObjectType({ - name: 'SameName', - fields: { f: { type: GraphQLString } }, + name: "SameName", + fields: { f: { type: GraphQLString } } }); const QueryType = new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { a: { type: A }, b: { type: B } @@ -249,357 +242,368 @@ describe('Type System: A Schema must contain uniquely named types', () => { return new GraphQLSchema({ query: QueryType }); }).to.throw( - 'Schema must contain unique named types but contains multiple types ' + - 'named "SameName".' + "Schema must contain unique named types but contains multiple types " + + 'named "SameName".' ); }); - it('rejects a Schema which have same named objects implementing an interface', () => { + it("rejects a Schema which have same named objects implementing an interface", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, - fields: { f: { type: GraphQLString } }, + fields: { f: { type: GraphQLString } } }); const FirstBadObject = new GraphQLObjectType({ - name: 'BadObject', - interfaces: [ AnotherInterface ], - fields: { f: { type: GraphQLString } }, + name: "BadObject", + interfaces: [AnotherInterface], + fields: { f: { type: GraphQLString } } }); const SecondBadObject = new GraphQLObjectType({ - name: 'BadObject', - interfaces: [ AnotherInterface ], - fields: { f: { type: GraphQLString } }, + name: "BadObject", + interfaces: [AnotherInterface], + fields: { f: { type: GraphQLString } } }); const QueryType = new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { - iface: { type: AnotherInterface }, + iface: { type: AnotherInterface } } }); return new GraphQLSchema({ query: QueryType, - types: [ FirstBadObject, SecondBadObject ] + types: [FirstBadObject, SecondBadObject] }); }).to.throw( - 'Schema must contain unique named types but contains multiple types ' + - 'named "BadObject".' + "Schema must contain unique named types but contains multiple types " + + 'named "BadObject".' ); }); - }); -describe('Type System: Objects must have fields', () => { - - it('accepts an Object type with fields object', () => { - expect( - () => schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - fields: { - f: { type: GraphQLString } - } - })) +describe("Type System: Objects must have fields", () => { + it("accepts an Object type with fields object", () => { + expect(() => + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + fields: { + f: { type: GraphQLString } + } + }) + ) ).not.to.throw(); }); - it('accepts an Object type with a field function', () => { - expect( - () => schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - fields() { - return { - f: { type: GraphQLString } - }; - } - })) + it("accepts an Object type with a field function", () => { + expect(() => + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + fields() { + return { + f: { type: GraphQLString } + }; + } + }) + ) ).not.to.throw(); }); - it('rejects an Object type with missing fields', () => { - expect( - () => schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - })) + it("rejects an Object type with missing fields", () => { + expect(() => + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject" + }) + ) ).to.throw( - 'SomeObject fields must be an object with field names as keys or a ' + - 'function which returns such an object.' + "SomeObject fields must be an object with field names as keys or a " + + "function which returns such an object." ); }); - it('rejects an Object type with incorrectly named fields', () => { - expect( - () => schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - fields: { 'bad-name-with-dashes': { type: GraphQLString } } - })) + it("rejects an Object type with incorrectly named fields", () => { + expect(() => + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + fields: { "bad-name-with-dashes": { type: GraphQLString } } + }) + ) ).to.throw( 'Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "bad-name-with-dashes" does not.' ); }); - it('rejects an Object type with incorrectly typed fields', () => { - expect( - () => schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - fields: [ - { field: GraphQLString } - ] - })) + it("rejects an Object type with incorrectly typed fields", () => { + expect(() => + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + fields: [{ field: GraphQLString }] + }) + ) ).to.throw( - 'SomeObject fields must be an object with field names as keys or a ' + - 'function which returns such an object.' + "SomeObject fields must be an object with field names as keys or a " + + "function which returns such an object." ); }); - it('rejects an Object type with empty fields', () => { - expect( - () => schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - fields: {} - })) + it("rejects an Object type with empty fields", () => { + expect(() => + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + fields: {} + }) + ) ).to.throw( - 'SomeObject fields must be an object with field names as keys or a ' + - 'function which returns such an object.' + "SomeObject fields must be an object with field names as keys or a " + + "function which returns such an object." ); }); - it('rejects an Object type with a field function that returns nothing', () => { - expect( - () => schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - fields() { - return; - } - })) + it("rejects an Object type with a field function that returns nothing", () => { + expect(() => + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + fields() { + return; + } + }) + ) ).to.throw( - 'SomeObject fields must be an object with field names as keys or a ' + - 'function which returns such an object.' + "SomeObject fields must be an object with field names as keys or a " + + "function which returns such an object." ); }); - it('rejects an Object type with a field function that returns empty', () => { - expect( - () => schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - fields() { - return {}; - } - })) + it("rejects an Object type with a field function that returns empty", () => { + expect(() => + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + fields() { + return {}; + } + }) + ) ).to.throw( - 'SomeObject fields must be an object with field names as keys or a ' + - 'function which returns such an object.' + "SomeObject fields must be an object with field names as keys or a " + + "function which returns such an object." ); }); - }); +describe("Type System: Fields args must be properly named", () => { + it("accepts field args with valid names", () => { + expect(() => + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + fields: { + goodField: { + type: GraphQLString, + args: { + goodArg: { type: GraphQLString } + } + } + } + }) + ) + ).not.to.throw(); + }); -describe('Type System: Fields args must be properly named', () => { - - it('accepts field args with valid names', () => { - expect( - () => schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', + it("rejects field arg with invalid names", () => { + expect(() => { + const QueryType = new GraphQLObjectType({ + name: "SomeObject", fields: { - goodField: { + badField: { type: GraphQLString, args: { - goodArg: { type: GraphQLString } + "bad-name-with-dashes": { type: GraphQLString } } } } - })) - ).not.to.throw(); + }); + return new GraphQLSchema({ query: QueryType }); + }).to.throw( + 'Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "bad-name-with-dashes" does not.' + ); }); +}); - it('rejects field arg with invalid names', () => { - expect( - () => { - const QueryType = new GraphQLObjectType({ - name: 'SomeObject', +describe("Type System: Fields args must be objects", () => { + it("accepts an Object type with field args", () => { + expect(() => + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", fields: { - badField: { + goodField: { type: GraphQLString, args: { - 'bad-name-with-dashes': { type: GraphQLString } + goodArg: { type: GraphQLString } } } } - }); - return new GraphQLSchema({ query: QueryType }); - }).to.throw( - 'Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "bad-name-with-dashes" does not.' - ); - }); - -}); - - -describe('Type System: Fields args must be objects', () => { - - it('accepts an Object type with field args', () => { - expect( - () => schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - fields: { - goodField: { - type: GraphQLString, - args: { - goodArg: { type: GraphQLString } - } - } - } - })) + }) + ) ).not.to.throw(); }); - it('rejects an Object type with incorrectly typed field args', () => { - expect( - () => schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - fields: { - badField: { - type: GraphQLString, - args: [ - { badArg: GraphQLString } - ] + it("rejects an Object type with incorrectly typed field args", () => { + expect(() => + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + fields: { + badField: { + type: GraphQLString, + args: [{ badArg: GraphQLString }] + } } - } - })) + }) + ) ).to.throw( - 'SomeObject.badField args must be an object with argument names as keys.' + "SomeObject.badField args must be an object with argument names as keys." ); }); - }); - -describe('Type System: Object interfaces must be array', () => { - - it('accepts an Object type with array interfaces', () => { +describe("Type System: Object interfaces must be array", () => { + it("accepts an Object type with array interfaces", () => { expect(() => { const AnotherInterfaceType = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { f: { type: GraphQLString } } }); - schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - interfaces: [ AnotherInterfaceType ], - fields: { f: { type: GraphQLString } } - })); + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + interfaces: [AnotherInterfaceType], + fields: { f: { type: GraphQLString } } + }) + ); }).not.to.throw(); }); - it('accepts an Object type with interfaces as a function returning an array', () => { + it("accepts an Object type with interfaces as a function returning an array", () => { expect(() => { const AnotherInterfaceType = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { f: { type: GraphQLString } } }); - schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - interfaces() { - return [ AnotherInterfaceType ]; - }, - fields: { f: { type: GraphQLString } } - })); + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + interfaces() { + return [AnotherInterfaceType]; + }, + fields: { f: { type: GraphQLString } } + }) + ); }).not.to.throw(); }); - it('rejects an Object type with incorrectly typed interfaces', () => { - expect( - () => schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - interfaces: {}, - fields: { f: { type: GraphQLString } } - })) + it("rejects an Object type with incorrectly typed interfaces", () => { + expect(() => + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + interfaces: {}, + fields: { f: { type: GraphQLString } } + }) + ) ).to.throw( - 'SomeObject interfaces must be an Array or a function which returns an Array.' + "SomeObject interfaces must be an Array or a function which returns an Array." ); }); - it('rejects an Object type with interfaces as a function returning an incorrect type', () => { - expect( - () => schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - interfaces() { - return {}; - }, - fields: { f: { type: GraphQLString } } - })) + it("rejects an Object type with interfaces as a function returning an incorrect type", () => { + expect(() => + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + interfaces() { + return {}; + }, + fields: { f: { type: GraphQLString } } + }) + ) ).to.throw( - 'SomeObject interfaces must be an Array or a function which returns an Array.' + "SomeObject interfaces must be an Array or a function which returns an Array." ); }); }); - -describe('Type System: Union types must be array', () => { - - it('accepts a Union type with array types', () => { - expect( - () => schemaWithFieldType(new GraphQLUnionType({ - name: 'SomeUnion', - resolveType: () => null, - types: [ SomeObjectType ], - })) +describe("Type System: Union types must be array", () => { + it("accepts a Union type with array types", () => { + expect(() => + schemaWithFieldType( + new GraphQLUnionType({ + name: "SomeUnion", + resolveType: () => null, + types: [SomeObjectType] + }) + ) ).not.to.throw(); }); - it('rejects a Union type without types', () => { - expect( - () => schemaWithFieldType(new GraphQLUnionType({ - name: 'SomeUnion', - resolveType: () => null, - })) - ).to.throw( - 'Must provide Array of types for Union SomeUnion.' - ); + it("rejects a Union type without types", () => { + expect(() => + schemaWithFieldType( + new GraphQLUnionType({ + name: "SomeUnion", + resolveType: () => null + }) + ) + ).to.throw("Must provide Array of types for Union SomeUnion."); }); - it('rejects a Union type with empty types', () => { - expect( - () => schemaWithFieldType(new GraphQLUnionType({ - name: 'SomeUnion', - resolveType: () => null, - types: [] - })) - ).to.throw( - 'Must provide Array of types for Union SomeUnion.' - ); + it("rejects a Union type with empty types", () => { + expect(() => + schemaWithFieldType( + new GraphQLUnionType({ + name: "SomeUnion", + resolveType: () => null, + types: [] + }) + ) + ).to.throw("Must provide Array of types for Union SomeUnion."); }); - it('rejects a Union type with incorrectly typed types', () => { - expect( - () => schemaWithFieldType(new GraphQLUnionType({ - name: 'SomeUnion', - resolveType: () => null, - types: { - SomeObjectType - }, - })) - ).to.throw( - 'Must provide Array of types for Union SomeUnion.' - ); + it("rejects a Union type with incorrectly typed types", () => { + expect(() => + schemaWithFieldType( + new GraphQLUnionType({ + name: "SomeUnion", + resolveType: () => null, + types: { + SomeObjectType + } + }) + ) + ).to.throw("Must provide Array of types for Union SomeUnion."); }); - }); - -describe('Type System: Input Objects must have fields', () => { - +describe("Type System: Input Objects must have fields", () => { function schemaWithInputObject(inputObjectType) { return new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { f: { type: GraphQLString, @@ -612,453 +616,477 @@ describe('Type System: Input Objects must have fields', () => { }); } - it('accepts an Input Object type with fields', () => { - expect( - () => schemaWithInputObject(new GraphQLInputObjectType({ - name: 'SomeInputObject', - fields: { - f: { type: GraphQLString } - } - })) + it("accepts an Input Object type with fields", () => { + expect(() => + schemaWithInputObject( + new GraphQLInputObjectType({ + name: "SomeInputObject", + fields: { + f: { type: GraphQLString } + } + }) + ) ).not.to.throw(); }); - it('accepts an Input Object type with a field function', () => { - expect( - () => schemaWithInputObject(new GraphQLInputObjectType({ - name: 'SomeInputObject', - fields() { - return { - f: { type: GraphQLString } - }; - } - })) + it("accepts an Input Object type with a field function", () => { + expect(() => + schemaWithInputObject( + new GraphQLInputObjectType({ + name: "SomeInputObject", + fields() { + return { + f: { type: GraphQLString } + }; + } + }) + ) ).not.to.throw(); }); - it('rejects an Input Object type with missing fields', () => { - expect( - () => schemaWithInputObject(new GraphQLInputObjectType({ - name: 'SomeInputObject', - })) + it("rejects an Input Object type with missing fields", () => { + expect(() => + schemaWithInputObject( + new GraphQLInputObjectType({ + name: "SomeInputObject" + }) + ) ).to.throw( - 'SomeInputObject fields must be an object with field names as keys or a ' + - 'function which returns such an object.' + "SomeInputObject fields must be an object with field names as keys or a " + + "function which returns such an object." ); }); - it('rejects an Input Object type with incorrectly typed fields', () => { - expect( - () => schemaWithInputObject(new GraphQLInputObjectType({ - name: 'SomeInputObject', - fields: [ - { field: GraphQLString } - ] - })) + it("rejects an Input Object type with incorrectly typed fields", () => { + expect(() => + schemaWithInputObject( + new GraphQLInputObjectType({ + name: "SomeInputObject", + fields: [{ field: GraphQLString }] + }) + ) ).to.throw( - 'SomeInputObject fields must be an object with field names as keys or a ' + - 'function which returns such an object.' + "SomeInputObject fields must be an object with field names as keys or a " + + "function which returns such an object." ); }); - it('rejects an Input Object type with empty fields', () => { - expect( - () => schemaWithInputObject(new GraphQLInputObjectType({ - name: 'SomeInputObject', - fields: {} - })) + it("rejects an Input Object type with empty fields", () => { + expect(() => + schemaWithInputObject( + new GraphQLInputObjectType({ + name: "SomeInputObject", + fields: {} + }) + ) ).to.throw( - 'SomeInputObject fields must be an object with field names as keys or a ' + - 'function which returns such an object.' + "SomeInputObject fields must be an object with field names as keys or a " + + "function which returns such an object." ); }); - it('rejects an Input Object type with a field function that returns nothing', () => { - expect( - () => schemaWithInputObject(new GraphQLInputObjectType({ - name: 'SomeInputObject', - fields() { - return; - } - })) + it("rejects an Input Object type with a field function that returns nothing", () => { + expect(() => + schemaWithInputObject( + new GraphQLInputObjectType({ + name: "SomeInputObject", + fields() { + return; + } + }) + ) ).to.throw( - 'SomeInputObject fields must be an object with field names as keys or a ' + - 'function which returns such an object.' + "SomeInputObject fields must be an object with field names as keys or a " + + "function which returns such an object." ); }); - it('rejects an Input Object type with a field function that returns empty', () => { - expect( - () => schemaWithInputObject(new GraphQLInputObjectType({ - name: 'SomeInputObject', - fields() { - return {}; - } - })) + it("rejects an Input Object type with a field function that returns empty", () => { + expect(() => + schemaWithInputObject( + new GraphQLInputObjectType({ + name: "SomeInputObject", + fields() { + return {}; + } + }) + ) ).to.throw( - 'SomeInputObject fields must be an object with field names as keys or a ' + - 'function which returns such an object.' + "SomeInputObject fields must be an object with field names as keys or a " + + "function which returns such an object." ); }); - }); - -describe('Type System: Object types must be assertable', () => { - - it('accepts an Object type with an isTypeOf function', () => { +describe("Type System: Object types must be assertable", () => { + it("accepts an Object type with an isTypeOf function", () => { expect(() => { - schemaWithFieldType(new GraphQLObjectType({ - name: 'AnotherObject', - isTypeOf: () => true, - fields: { f: { type: GraphQLString } } - })); + schemaWithFieldType( + new GraphQLObjectType({ + name: "AnotherObject", + isTypeOf: () => true, + fields: { f: { type: GraphQLString } } + }) + ); }).not.to.throw(); }); - it('rejects an Object type with an incorrect type for isTypeOf', () => { + it("rejects an Object type with an incorrect type for isTypeOf", () => { expect(() => { - schemaWithFieldType(new GraphQLObjectType({ - name: 'AnotherObject', - isTypeOf: {}, - fields: { f: { type: GraphQLString } } - })); - }).to.throw( - 'AnotherObject must provide "isTypeOf" as a function.' - ); + schemaWithFieldType( + new GraphQLObjectType({ + name: "AnotherObject", + isTypeOf: {}, + fields: { f: { type: GraphQLString } } + }) + ); + }).to.throw('AnotherObject must provide "isTypeOf" as a function.'); }); - }); - -describe('Type System: Interface types must be resolvable', () => { - - it('accepts an Interface type defining resolveType', () => { +describe("Type System: Interface types must be resolvable", () => { + it("accepts an Interface type defining resolveType", () => { expect(() => { const AnotherInterfaceType = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { f: { type: GraphQLString } } }); - schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - interfaces: [ AnotherInterfaceType ], - fields: { f: { type: GraphQLString } } - })); + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + interfaces: [AnotherInterfaceType], + fields: { f: { type: GraphQLString } } + }) + ); }).not.to.throw(); }); - it('accepts an Interface with implementing type defining isTypeOf', () => { + it("accepts an Interface with implementing type defining isTypeOf", () => { expect(() => { const InterfaceTypeWithoutResolveType = new GraphQLInterfaceType({ - name: 'InterfaceTypeWithoutResolveType', + name: "InterfaceTypeWithoutResolveType", fields: { f: { type: GraphQLString } } }); - schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - isTypeOf: () => true, - interfaces: [ InterfaceTypeWithoutResolveType ], - fields: { f: { type: GraphQLString } } - })); + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + isTypeOf: () => true, + interfaces: [InterfaceTypeWithoutResolveType], + fields: { f: { type: GraphQLString } } + }) + ); }).not.to.throw(); }); - it('accepts an Interface type defining resolveType with implementing type defining isTypeOf', () => { + it("accepts an Interface type defining resolveType with implementing type defining isTypeOf", () => { expect(() => { const AnotherInterfaceType = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { f: { type: GraphQLString } } }); - schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - isTypeOf: () => true, - interfaces: [ AnotherInterfaceType ], - fields: { f: { type: GraphQLString } } - })); + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + isTypeOf: () => true, + interfaces: [AnotherInterfaceType], + fields: { f: { type: GraphQLString } } + }) + ); }).not.to.throw(); }); - it('rejects an Interface type with an incorrect type for resolveType', () => { - expect(() => - new GraphQLInterfaceType({ - name: 'AnotherInterface', - resolveType: {}, - fields: { f: { type: GraphQLString } } - }) - ).to.throw( - 'AnotherInterface must provide "resolveType" as a function.' - ); + it("rejects an Interface type with an incorrect type for resolveType", () => { + expect( + () => + new GraphQLInterfaceType({ + name: "AnotherInterface", + resolveType: {}, + fields: { f: { type: GraphQLString } } + }) + ).to.throw('AnotherInterface must provide "resolveType" as a function.'); }); - it('rejects an Interface type not defining resolveType with implementing type not defining isTypeOf', () => { + it("rejects an Interface type not defining resolveType with implementing type not defining isTypeOf", () => { expect(() => { const InterfaceTypeWithoutResolveType = new GraphQLInterfaceType({ - name: 'InterfaceTypeWithoutResolveType', + name: "InterfaceTypeWithoutResolveType", fields: { f: { type: GraphQLString } } }); - schemaWithFieldType(new GraphQLObjectType({ - name: 'SomeObject', - interfaces: [ InterfaceTypeWithoutResolveType ], - fields: { f: { type: GraphQLString } } - })); + schemaWithFieldType( + new GraphQLObjectType({ + name: "SomeObject", + interfaces: [InterfaceTypeWithoutResolveType], + fields: { f: { type: GraphQLString } } + }) + ); }).to.throw( - 'Interface Type InterfaceTypeWithoutResolveType does not provide a ' + - '"resolveType" function and implementing Type SomeObject does not ' + - 'provide a "isTypeOf" function. ' + - 'There is no way to resolve this implementing type during execution.' + "Interface Type InterfaceTypeWithoutResolveType does not provide a " + + '"resolveType" function and implementing Type SomeObject does not ' + + 'provide a "isTypeOf" function. ' + + "There is no way to resolve this implementing type during execution." ); }); - }); - -describe('Type System: Union types must be resolvable', () => { - - it('accepts a Union type defining resolveType', () => { +describe("Type System: Union types must be resolvable", () => { + it("accepts a Union type defining resolveType", () => { expect(() => - schemaWithFieldType(new GraphQLUnionType({ - name: 'SomeUnion', - resolveType: () => null, - types: [ SomeObjectType ], - })) + schemaWithFieldType( + new GraphQLUnionType({ + name: "SomeUnion", + resolveType: () => null, + types: [SomeObjectType] + }) + ) ).not.to.throw(); }); - it('accepts a Union of Object types defining isTypeOf', () => { + it("accepts a Union of Object types defining isTypeOf", () => { expect(() => - schemaWithFieldType(new GraphQLUnionType({ - name: 'SomeUnion', - types: [ ObjectWithIsTypeOf ], - })) + schemaWithFieldType( + new GraphQLUnionType({ + name: "SomeUnion", + types: [ObjectWithIsTypeOf] + }) + ) ).not.to.throw(); }); - it('accepts a Union type defining resolveType of Object types defining isTypeOf', () => { + it("accepts a Union type defining resolveType of Object types defining isTypeOf", () => { expect(() => - schemaWithFieldType(new GraphQLUnionType({ - name: 'SomeUnion', - resolveType: () => null, - types: [ ObjectWithIsTypeOf ], - })) + schemaWithFieldType( + new GraphQLUnionType({ + name: "SomeUnion", + resolveType: () => null, + types: [ObjectWithIsTypeOf] + }) + ) ).not.to.throw(); }); - it('rejects an Interface type with an incorrect type for resolveType', () => { + it("rejects an Interface type with an incorrect type for resolveType", () => { expect(() => - schemaWithFieldType(new GraphQLUnionType({ - name: 'SomeUnion', - resolveType: {}, - types: [ ObjectWithIsTypeOf ], - })) - ).to.throw( - 'SomeUnion must provide "resolveType" as a function.' - ); + schemaWithFieldType( + new GraphQLUnionType({ + name: "SomeUnion", + resolveType: {}, + types: [ObjectWithIsTypeOf] + }) + ) + ).to.throw('SomeUnion must provide "resolveType" as a function.'); }); - it('rejects a Union type not defining resolveType of Object types not defining isTypeOf', () => { + it("rejects a Union type not defining resolveType of Object types not defining isTypeOf", () => { expect(() => - schemaWithFieldType(new GraphQLUnionType({ - name: 'SomeUnion', - types: [ SomeObjectType ], - })) + schemaWithFieldType( + new GraphQLUnionType({ + name: "SomeUnion", + types: [SomeObjectType] + }) + ) ).to.throw( 'Union Type SomeUnion does not provide a "resolveType" function and ' + - 'possible Type SomeObject does not provide a "isTypeOf" function. ' + - 'There is no way to resolve this possible type during execution.' + 'possible Type SomeObject does not provide a "isTypeOf" function. ' + + "There is no way to resolve this possible type during execution." ); }); - }); - -describe('Type System: Scalar types must be serializable', () => { - - it('accepts a Scalar type defining serialize', () => { +describe("Type System: Scalar types must be serializable", () => { + it("accepts a Scalar type defining serialize", () => { expect(() => - schemaWithFieldType(new GraphQLScalarType({ - name: 'SomeScalar', - serialize: () => null, - })) + schemaWithFieldType( + new GraphQLScalarType({ + name: "SomeScalar", + serialize: () => null + }) + ) ).not.to.throw(); }); - it('rejects a Scalar type not defining serialize', () => { + it("rejects a Scalar type not defining serialize", () => { expect(() => - schemaWithFieldType(new GraphQLScalarType({ - name: 'SomeScalar', - })) + schemaWithFieldType( + new GraphQLScalarType({ + name: "SomeScalar" + }) + ) ).to.throw( 'SomeScalar must provide "serialize" function. If this custom Scalar ' + - 'is also used as an input type, ensure "parseValue" and "parseLiteral" ' + - 'functions are also provided.' + 'is also used as an input type, ensure "parseValue" and "parseLiteral" ' + + "functions are also provided." ); }); - it('rejects a Scalar type defining serialize with an incorrect type', () => { + it("rejects a Scalar type defining serialize with an incorrect type", () => { expect(() => - schemaWithFieldType(new GraphQLScalarType({ - name: 'SomeScalar', - serialize: {} - })) + schemaWithFieldType( + new GraphQLScalarType({ + name: "SomeScalar", + serialize: {} + }) + ) ).to.throw( 'SomeScalar must provide "serialize" function. If this custom Scalar ' + - 'is also used as an input type, ensure "parseValue" and "parseLiteral" ' + - 'functions are also provided.' + 'is also used as an input type, ensure "parseValue" and "parseLiteral" ' + + "functions are also provided." ); }); - it('accepts a Scalar type defining parseValue and parseLiteral', () => { + it("accepts a Scalar type defining parseValue and parseLiteral", () => { expect(() => - schemaWithFieldType(new GraphQLScalarType({ - name: 'SomeScalar', - serialize: () => null, - parseValue: () => null, - parseLiteral: () => null, - })) + schemaWithFieldType( + new GraphQLScalarType({ + name: "SomeScalar", + serialize: () => null, + parseValue: () => null, + parseLiteral: () => null + }) + ) ).not.to.throw(); }); - it('rejects a Scalar type defining parseValue but not parseLiteral', () => { + it("rejects a Scalar type defining parseValue but not parseLiteral", () => { expect(() => - schemaWithFieldType(new GraphQLScalarType({ - name: 'SomeScalar', - serialize: () => null, - parseValue: () => null, - })) + schemaWithFieldType( + new GraphQLScalarType({ + name: "SomeScalar", + serialize: () => null, + parseValue: () => null + }) + ) ).to.throw( 'SomeScalar must provide both "parseValue" and "parseLiteral" functions.' ); }); - it('rejects a Scalar type defining parseLiteral but not parseValue', () => { + it("rejects a Scalar type defining parseLiteral but not parseValue", () => { expect(() => - schemaWithFieldType(new GraphQLScalarType({ - name: 'SomeScalar', - serialize: () => null, - parseLiteral: () => null, - })) + schemaWithFieldType( + new GraphQLScalarType({ + name: "SomeScalar", + serialize: () => null, + parseLiteral: () => null + }) + ) ).to.throw( 'SomeScalar must provide both "parseValue" and "parseLiteral" functions.' ); }); - it('rejects a Scalar type defining parseValue and parseLiteral with an incorrect type', () => { + it("rejects a Scalar type defining parseValue and parseLiteral with an incorrect type", () => { expect(() => - schemaWithFieldType(new GraphQLScalarType({ - name: 'SomeScalar', - serialize: () => null, - parseValue: {}, - parseLiteral: {}, - })) + schemaWithFieldType( + new GraphQLScalarType({ + name: "SomeScalar", + serialize: () => null, + parseValue: {}, + parseLiteral: {} + }) + ) ).to.throw( 'SomeScalar must provide both "parseValue" and "parseLiteral" functions.' ); }); - }); - -describe('Type System: Enum types must be well defined', () => { - - it('accepts a well defined Enum type with empty value definition', () => { - expect(() => - new GraphQLEnumType({ - name: 'SomeEnum', - values: { - FOO: {}, - BAR: {}, - } - }) +describe("Type System: Enum types must be well defined", () => { + it("accepts a well defined Enum type with empty value definition", () => { + expect( + () => + new GraphQLEnumType({ + name: "SomeEnum", + values: { + FOO: {}, + BAR: {} + } + }) ).not.to.throw(); }); - it('accepts a well defined Enum type with internal value definition', () => { - expect(() => - new GraphQLEnumType({ - name: 'SomeEnum', - values: { - FOO: { value: 10 }, - BAR: { value: 20 }, - } - }) + it("accepts a well defined Enum type with internal value definition", () => { + expect( + () => + new GraphQLEnumType({ + name: "SomeEnum", + values: { + FOO: { value: 10 }, + BAR: { value: 20 } + } + }) ).not.to.throw(); }); - it('rejects an Enum type without values', () => { - expect(() => - new GraphQLEnumType({ - name: 'SomeEnum', - }) - ).to.throw( - 'SomeEnum values must be an object with value names as keys.' - ); + it("rejects an Enum type without values", () => { + expect( + () => + new GraphQLEnumType({ + name: "SomeEnum" + }) + ).to.throw("SomeEnum values must be an object with value names as keys."); }); - it('rejects an Enum type with empty values', () => { - expect(() => - new GraphQLEnumType({ - name: 'SomeEnum', - values: {} - }) - ).to.throw( - 'SomeEnum values must be an object with value names as keys.' - ); + it("rejects an Enum type with empty values", () => { + expect( + () => + new GraphQLEnumType({ + name: "SomeEnum", + values: {} + }) + ).to.throw("SomeEnum values must be an object with value names as keys."); }); - it('rejects an Enum type with incorrectly typed values', () => { - expect(() => - new GraphQLEnumType({ - name: 'SomeEnum', - values: [ - { FOO: 10 } - ] - }) - ).to.throw( - 'SomeEnum values must be an object with value names as keys.' - ); + it("rejects an Enum type with incorrectly typed values", () => { + expect( + () => + new GraphQLEnumType({ + name: "SomeEnum", + values: [{ FOO: 10 }] + }) + ).to.throw("SomeEnum values must be an object with value names as keys."); }); - it('rejects an Enum type with missing value definition', () => { - expect(() => - new GraphQLEnumType({ - name: 'SomeEnum', - values: { - FOO: null - } - }) + it("rejects an Enum type with missing value definition", () => { + expect( + () => + new GraphQLEnumType({ + name: "SomeEnum", + values: { + FOO: null + } + }) ).to.throw( 'SomeEnum.FOO must refer to an object with a "value" key representing ' + - 'an internal value but got: null.' + "an internal value but got: null." ); }); - it('rejects an Enum type with incorrectly typed value definition', () => { - expect(() => - new GraphQLEnumType({ - name: 'SomeEnum', - values: { - FOO: 10 - } - }) + it("rejects an Enum type with incorrectly typed value definition", () => { + expect( + () => + new GraphQLEnumType({ + name: "SomeEnum", + values: { + FOO: 10 + } + }) ).to.throw( 'SomeEnum.FOO must refer to an object with a "value" key representing ' + - 'an internal value but got: 10.' + "an internal value but got: 10." ); }); - }); - -describe('Type System: Object fields must have output types', () => { - +describe("Type System: Object fields must have output types", () => { function schemaWithObjectFieldOfType(fieldType) { const BadObjectType = new GraphQLObjectType({ - name: 'BadObject', + name: "BadObject", fields: { badField: { type: fieldType } } @@ -1066,7 +1094,7 @@ describe('Type System: Object fields must have output types', () => { return new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { f: { type: BadObjectType } } @@ -1080,9 +1108,9 @@ describe('Type System: Object fields must have output types', () => { }); }); - it('rejects an empty Object field type', () => { + it("rejects an empty Object field type", () => { expect(() => schemaWithObjectFieldOfType(undefined)).to.throw( - 'BadObject.badField field type must be Output Type but got: undefined.' + "BadObject.badField field type must be Output Type but got: undefined." ); }); @@ -1093,34 +1121,31 @@ describe('Type System: Object fields must have output types', () => { ); }); }); - }); - -describe('Type System: Objects can only implement interfaces', () => { - +describe("Type System: Objects can only implement interfaces", () => { function schemaWithObjectImplementingType(implementedType) { const BadObjectType = new GraphQLObjectType({ - name: 'BadObject', - interfaces: [ implementedType ], + name: "BadObject", + interfaces: [implementedType], fields: { f: { type: GraphQLString } } }); return new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { f: { type: BadObjectType } } }), - types: [ BadObjectType ] + types: [BadObjectType] }); } - it('accepts an Object implementing an Interface', () => { + it("accepts an Object implementing an Interface", () => { expect(() => { const AnotherInterfaceType = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { f: { type: GraphQLString } } }); @@ -1134,7 +1159,7 @@ describe('Type System: Objects can only implement interfaces', () => { SomeEnumType, SomeObjectType, SomeUnionType, - SomeInputObjectType, + SomeInputObjectType ]); notInterfaceTypes.forEach(type => { @@ -1144,22 +1169,19 @@ describe('Type System: Objects can only implement interfaces', () => { ); }); }); - }); - -describe('Type System: Unions must represent Object types', () => { - +describe("Type System: Unions must represent Object types", () => { function schemaWithUnionOfType(type) { const BadUnionType = new GraphQLUnionType({ - name: 'BadUnion', + name: "BadUnion", resolveType: () => null, - types: [ type ], + types: [type] }); return new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { f: { type: BadUnionType } } @@ -1167,10 +1189,8 @@ describe('Type System: Unions must represent Object types', () => { }); } - it('accepts a Union of an Object Type', () => { - expect(() => - schemaWithUnionOfType(SomeObjectType) - ).not.to.throw(); + it("accepts a Union of an Object Type", () => { + expect(() => schemaWithUnionOfType(SomeObjectType)).not.to.throw(); }); const notObjectTypes = withModifiers([ @@ -1178,7 +1198,7 @@ describe('Type System: Unions must represent Object types', () => { SomeEnumType, SomeInterfaceType, SomeUnionType, - SomeInputObjectType, + SomeInputObjectType ]); notObjectTypes.forEach(type => { @@ -1188,15 +1208,12 @@ describe('Type System: Unions must represent Object types', () => { ); }); }); - }); - -describe('Type System: Interface fields must have output types', () => { - +describe("Type System: Interface fields must have output types", () => { function schemaWithInterfaceFieldOfType(fieldType) { const BadInterfaceType = new GraphQLInterfaceType({ - name: 'BadInterface', + name: "BadInterface", fields: { badField: { type: fieldType } } @@ -1204,7 +1221,7 @@ describe('Type System: Interface fields must have output types', () => { return new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { f: { type: BadInterfaceType } } @@ -1218,9 +1235,9 @@ describe('Type System: Interface fields must have output types', () => { }); }); - it('rejects an empty Interface field type', () => { + it("rejects an empty Interface field type", () => { expect(() => schemaWithInterfaceFieldOfType(undefined)).to.throw( - 'BadInterface.badField field type must be Output Type but got: undefined.' + "BadInterface.badField field type must be Output Type but got: undefined." ); }); @@ -1231,15 +1248,12 @@ describe('Type System: Interface fields must have output types', () => { ); }); }); - }); - -describe('Type System: Field arguments must have input types', () => { - +describe("Type System: Field arguments must have input types", () => { function schemaWithArgOfType(argType) { const BadObjectType = new GraphQLObjectType({ - name: 'BadObject', + name: "BadObject", fields: { badField: { type: GraphQLString, @@ -1252,7 +1266,7 @@ describe('Type System: Field arguments must have input types', () => { return new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { f: { type: BadObjectType } } @@ -1266,9 +1280,9 @@ describe('Type System: Field arguments must have input types', () => { }); }); - it('rejects an empty field arg type', () => { + it("rejects an empty field arg type", () => { expect(() => schemaWithArgOfType(undefined)).to.throw( - 'BadObject.badField(badArg:) argument type must be Input Type but got: undefined.' + "BadObject.badField(badArg:) argument type must be Input Type but got: undefined." ); }); @@ -1279,15 +1293,12 @@ describe('Type System: Field arguments must have input types', () => { ); }); }); - }); - -describe('Type System: Input Object fields must have input types', () => { - +describe("Type System: Input Object fields must have input types", () => { function schemaWithInputFieldOfType(inputFieldType) { const BadInputObjectType = new GraphQLInputObjectType({ - name: 'BadInputObject', + name: "BadInputObject", fields: { badField: { type: inputFieldType } } @@ -1295,7 +1306,7 @@ describe('Type System: Input Object fields must have input types', () => { return new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { f: { type: GraphQLString, @@ -1314,9 +1325,9 @@ describe('Type System: Input Object fields must have input types', () => { }); }); - it('rejects an empty input field type', () => { + it("rejects an empty input field type", () => { expect(() => schemaWithInputFieldOfType(undefined)).to.throw( - 'BadInputObject.badField field type must be Input Type but got: undefined.' + "BadInputObject.badField field type must be Input Type but got: undefined." ); }); @@ -1327,12 +1338,9 @@ describe('Type System: Input Object fields must have input types', () => { ); }); }); - }); - -describe('Type System: List must accept GraphQL types', () => { - +describe("Type System: List must accept GraphQL types", () => { const types = withModifiers([ GraphQLString, SomeScalarType, @@ -1340,15 +1348,10 @@ describe('Type System: List must accept GraphQL types', () => { SomeUnionType, SomeInterfaceType, SomeEnumType, - SomeInputObjectType, + SomeInputObjectType ]); - const notTypes = [ - {}, - String, - undefined, - null, - ]; + const notTypes = [{}, String, undefined, null]; types.forEach(type => { it(`accepts an type as item type of list: ${type}`, () => { @@ -1363,12 +1366,9 @@ describe('Type System: List must accept GraphQL types', () => { ); }); }); - }); - -describe('Type System: NonNull must accept GraphQL types', () => { - +describe("Type System: NonNull must accept GraphQL types", () => { const nullableTypes = [ GraphQLString, SomeScalarType, @@ -1378,7 +1378,7 @@ describe('Type System: NonNull must accept GraphQL types', () => { SomeEnumType, SomeInputObjectType, new GraphQLList(GraphQLString), - new GraphQLList(new GraphQLNonNull(GraphQLString)), + new GraphQLList(new GraphQLNonNull(GraphQLString)) ]; const notNullableTypes = [ @@ -1386,7 +1386,7 @@ describe('Type System: NonNull must accept GraphQL types', () => { {}, String, undefined, - null, + null ]; nullableTypes.forEach(type => { @@ -1402,16 +1402,13 @@ describe('Type System: NonNull must accept GraphQL types', () => { ); }); }); - }); - -describe('Objects must adhere to Interface they implement', () => { - - it('accepts an Object which implements an Interface', () => { +describe("Objects must adhere to Interface they implement", () => { + it("accepts an Object which implements an Interface", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { @@ -1424,8 +1421,8 @@ describe('Objects must adhere to Interface they implement', () => { }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { field: { type: GraphQLString, @@ -1440,29 +1437,29 @@ describe('Objects must adhere to Interface they implement', () => { }).not.to.throw(); }); - it('accepts an Object which implements an Interface along with more fields', () => { + it("accepts an Object which implements an Interface along with more fields", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { type: GraphQLString, args: { - input: { type: GraphQLString }, + input: { type: GraphQLString } } } } }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { field: { type: GraphQLString, args: { - input: { type: GraphQLString }, + input: { type: GraphQLString } } }, anotherfield: { type: GraphQLString } @@ -1473,30 +1470,30 @@ describe('Objects must adhere to Interface they implement', () => { }).not.to.throw(); }); - it('accepts an Object which implements an Interface field along with additional optional arguments', () => { + it("accepts an Object which implements an Interface field along with additional optional arguments", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { type: GraphQLString, args: { - input: { type: GraphQLString }, + input: { type: GraphQLString } } } } }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { field: { type: GraphQLString, args: { input: { type: GraphQLString }, - anotherInput: { type: GraphQLString }, + anotherInput: { type: GraphQLString } } } } @@ -1506,30 +1503,30 @@ describe('Objects must adhere to Interface they implement', () => { }).not.to.throw(); }); - it('rejects an Object which implements an Interface field along with additional required arguments', () => { + it("rejects an Object which implements an Interface field along with additional required arguments", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { type: GraphQLString, args: { - input: { type: GraphQLString }, + input: { type: GraphQLString } } } } }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { field: { type: GraphQLString, args: { input: { type: GraphQLString }, - anotherInput: { type: new GraphQLNonNull(GraphQLString) }, + anotherInput: { type: new GraphQLNonNull(GraphQLString) } } } } @@ -1538,28 +1535,28 @@ describe('Objects must adhere to Interface they implement', () => { return schemaWithFieldType(AnotherObject); }).to.throw( 'AnotherObject.field(anotherInput:) is of required type "String!" but ' + - 'is not also provided by the interface AnotherInterface.field.' + "is not also provided by the interface AnotherInterface.field." ); }); - it('rejects an Object missing an Interface field', () => { + it("rejects an Object missing an Interface field", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { type: GraphQLString, args: { - input: { type: GraphQLString }, + input: { type: GraphQLString } } } } }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { anotherfield: { type: GraphQLString } } @@ -1568,14 +1565,14 @@ describe('Objects must adhere to Interface they implement', () => { return schemaWithFieldType(AnotherObject); }).to.throw( '"AnotherInterface" expects field "field" but ' + - '"AnotherObject" does not provide it.' + '"AnotherObject" does not provide it.' ); }); - it('rejects an Object with an incorrectly typed Interface field', () => { + it("rejects an Object with an incorrectly typed Interface field", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { type: GraphQLString } @@ -1583,8 +1580,8 @@ describe('Objects must adhere to Interface they implement', () => { }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { field: { type: SomeScalarType } } @@ -1593,28 +1590,28 @@ describe('Objects must adhere to Interface they implement', () => { return schemaWithFieldType(AnotherObject); }).to.throw( 'AnotherInterface.field expects type "String" but ' + - 'AnotherObject.field provides type "SomeScalar".' + 'AnotherObject.field provides type "SomeScalar".' ); }); - it('rejects an Object with a differently typed Interface field', () => { + it("rejects an Object with a differently typed Interface field", () => { expect(() => { const TypeA = new GraphQLObjectType({ - name: 'A', + name: "A", fields: { foo: { type: GraphQLString } } }); const TypeB = new GraphQLObjectType({ - name: 'B', + name: "B", fields: { foo: { type: GraphQLString } } }); const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { type: TypeA } @@ -1622,8 +1619,8 @@ describe('Objects must adhere to Interface they implement', () => { }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { field: { type: TypeB } } @@ -1632,14 +1629,14 @@ describe('Objects must adhere to Interface they implement', () => { return schemaWithFieldType(AnotherObject); }).to.throw( 'AnotherInterface.field expects type "A" but ' + - 'AnotherObject.field provides type "B".' + 'AnotherObject.field provides type "B".' ); }); - it('accepts an Object with a subtyped Interface field (interface)', () => { + it("accepts an Object with a subtyped Interface field (interface)", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: () => ({ field: { type: AnotherInterface } @@ -1647,8 +1644,8 @@ describe('Objects must adhere to Interface they implement', () => { }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: () => ({ field: { type: AnotherObject } }) @@ -1658,10 +1655,10 @@ describe('Objects must adhere to Interface they implement', () => { }).not.to.throw(); }); - it('accepts an Object with a subtyped Interface field (union)', () => { + it("accepts an Object with a subtyped Interface field (union)", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { type: SomeUnionType } @@ -1669,8 +1666,8 @@ describe('Objects must adhere to Interface they implement', () => { }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { field: { type: SomeObjectType } } @@ -1680,27 +1677,27 @@ describe('Objects must adhere to Interface they implement', () => { }).not.to.throw(); }); - it('rejects an Object missing an Interface argument', () => { + it("rejects an Object missing an Interface argument", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { type: GraphQLString, args: { - input: { type: GraphQLString }, + input: { type: GraphQLString } } } } }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { field: { - type: GraphQLString, + type: GraphQLString } } }); @@ -1708,33 +1705,33 @@ describe('Objects must adhere to Interface they implement', () => { return schemaWithFieldType(AnotherObject); }).to.throw( 'AnotherInterface.field expects argument "input" but ' + - 'AnotherObject.field does not provide it.' + "AnotherObject.field does not provide it." ); }); - it('rejects an Object with an incorrectly typed Interface argument', () => { + it("rejects an Object with an incorrectly typed Interface argument", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { type: GraphQLString, args: { - input: { type: GraphQLString }, + input: { type: GraphQLString } } } } }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { field: { type: GraphQLString, args: { - input: { type: SomeScalarType }, + input: { type: SomeScalarType } } } } @@ -1743,14 +1740,14 @@ describe('Objects must adhere to Interface they implement', () => { return schemaWithFieldType(AnotherObject); }).to.throw( 'AnotherInterface.field(input:) expects type "String" but ' + - 'AnotherObject.field(input:) provides type "SomeScalar".' + 'AnotherObject.field(input:) provides type "SomeScalar".' ); }); - it('accepts an Object with an equivalently modified Interface field type', () => { + it("accepts an Object with an equivalently modified Interface field type", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { type: new GraphQLNonNull(new GraphQLList(GraphQLString)) } @@ -1758,8 +1755,8 @@ describe('Objects must adhere to Interface they implement', () => { }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { field: { type: new GraphQLNonNull(new GraphQLList(GraphQLString)) } } @@ -1769,10 +1766,10 @@ describe('Objects must adhere to Interface they implement', () => { }).not.to.throw(); }); - it('rejects an Object with a non-list Interface field list type', () => { + it("rejects an Object with a non-list Interface field list type", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { type: new GraphQLList(GraphQLString) } @@ -1780,8 +1777,8 @@ describe('Objects must adhere to Interface they implement', () => { }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { field: { type: GraphQLString } } @@ -1790,14 +1787,14 @@ describe('Objects must adhere to Interface they implement', () => { return schemaWithFieldType(AnotherObject); }).to.throw( 'AnotherInterface.field expects type "[String]" but ' + - 'AnotherObject.field provides type "String".' + 'AnotherObject.field provides type "String".' ); }); - it('rejects an Object with a list Interface field non-list type', () => { + it("rejects an Object with a list Interface field non-list type", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { type: GraphQLString } @@ -1805,8 +1802,8 @@ describe('Objects must adhere to Interface they implement', () => { }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { field: { type: new GraphQLList(GraphQLString) } } @@ -1815,14 +1812,14 @@ describe('Objects must adhere to Interface they implement', () => { return schemaWithFieldType(AnotherObject); }).to.throw( 'AnotherInterface.field expects type "String" but ' + - 'AnotherObject.field provides type "[String]".' + 'AnotherObject.field provides type "[String]".' ); }); - it('accepts an Object with a subset non-null Interface field type', () => { + it("accepts an Object with a subset non-null Interface field type", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { type: GraphQLString } @@ -1830,8 +1827,8 @@ describe('Objects must adhere to Interface they implement', () => { }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { field: { type: new GraphQLNonNull(GraphQLString) } } @@ -1841,10 +1838,10 @@ describe('Objects must adhere to Interface they implement', () => { }).not.to.throw(); }); - it('rejects an Object with a superset nullable Interface field type', () => { + it("rejects an Object with a superset nullable Interface field type", () => { expect(() => { const AnotherInterface = new GraphQLInterfaceType({ - name: 'AnotherInterface', + name: "AnotherInterface", resolveType: () => null, fields: { field: { type: new GraphQLNonNull(GraphQLString) } @@ -1852,8 +1849,8 @@ describe('Objects must adhere to Interface they implement', () => { }); const AnotherObject = new GraphQLObjectType({ - name: 'AnotherObject', - interfaces: [ AnotherInterface ], + name: "AnotherObject", + interfaces: [AnotherInterface], fields: { field: { type: GraphQLString } } @@ -1862,14 +1859,14 @@ describe('Objects must adhere to Interface they implement', () => { return schemaWithFieldType(AnotherObject); }).to.throw( 'AnotherInterface.field expects type "String!" but ' + - 'AnotherObject.field provides type "String".' + 'AnotherObject.field provides type "String".' ); }); - it('does not allow isDeprecated without deprecationReason on field', () => { + it("does not allow isDeprecated without deprecationReason on field", () => { expect(() => { const OldObject = new GraphQLObjectType({ - name: 'OldObject', + name: "OldObject", fields: { field: { type: GraphQLString, @@ -1881,22 +1878,22 @@ describe('Objects must adhere to Interface they implement', () => { return schemaWithFieldType(OldObject); }).to.throw( 'OldObject.field should provide "deprecationReason" instead ' + - 'of "isDeprecated".' + 'of "isDeprecated".' ); }); - it('does not allow isDeprecated without deprecationReason on enum', () => { - expect(() => - new GraphQLEnumType({ - name: 'SomeEnum', - values: { - value: { isDeprecated: true } - } - }) + it("does not allow isDeprecated without deprecationReason on enum", () => { + expect( + () => + new GraphQLEnumType({ + name: "SomeEnum", + values: { + value: { isDeprecated: true } + } + }) ).to.throw( 'SomeEnum.value should provide "deprecationReason" instead ' + - 'of "isDeprecated".' + 'of "isDeprecated".' ); }); - }); diff --git a/src/type/definition.js b/src/type/definition.js index 70f0bf2a6e..4a47907c53 100644 --- a/src/type/definition.js +++ b/src/type/definition.js @@ -8,18 +8,17 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import invariant from '../jsutils/invariant'; -import isNullish from '../jsutils/isNullish'; -import { ENUM } from '../language/kinds'; -import { assertValidName } from '../utilities/assertValidName'; +import invariant from "../jsutils/invariant"; +import isNullish from "../jsutils/isNullish"; +import { ENUM } from "../language/kinds"; +import { assertValidName } from "../utilities/assertValidName"; import type { OperationDefinition, Field, FragmentDefinition, - Value, -} from '../language/ast'; -import type { GraphQLSchema } from './schema'; - + Value +} from "../language/ast"; +import type { GraphQLSchema } from "./schema"; // Predicates @@ -27,14 +26,14 @@ import type { GraphQLSchema } from './schema'; * These are all of the possible kinds of types. */ export type GraphQLType = - GraphQLScalarType | - GraphQLObjectType | - GraphQLInterfaceType | - GraphQLUnionType | - GraphQLEnumType | - GraphQLInputObjectType | - GraphQLList | - GraphQLNonNull; + | GraphQLScalarType + | GraphQLObjectType + | GraphQLInterfaceType + | GraphQLUnionType + | GraphQLEnumType + | GraphQLInputObjectType + | GraphQLList + | GraphQLNonNull; export function isType(type: mixed): boolean { return ( @@ -53,16 +52,16 @@ export function isType(type: mixed): boolean { * These types may be used as input types for arguments and directives. */ export type GraphQLInputType = - GraphQLScalarType | - GraphQLEnumType | - GraphQLInputObjectType | - GraphQLList | - GraphQLNonNull< - GraphQLScalarType | - GraphQLEnumType | - GraphQLInputObjectType | - GraphQLList - >; + | GraphQLScalarType + | GraphQLEnumType + | GraphQLInputObjectType + | GraphQLList + | GraphQLNonNull< + | GraphQLScalarType + | GraphQLEnumType + | GraphQLInputObjectType + | GraphQLList + >; export function isInputType(type: ?GraphQLType): boolean { const namedType = getNamedType(type); @@ -77,20 +76,20 @@ export function isInputType(type: ?GraphQLType): boolean { * These types may be used as output types as the result of fields. */ export type GraphQLOutputType = - GraphQLScalarType | - GraphQLObjectType | - GraphQLInterfaceType | - GraphQLUnionType | - GraphQLEnumType | - GraphQLList | - GraphQLNonNull< - GraphQLScalarType | - GraphQLObjectType | - GraphQLInterfaceType | - GraphQLUnionType | - GraphQLEnumType | - GraphQLList - >; + | GraphQLScalarType + | GraphQLObjectType + | GraphQLInterfaceType + | GraphQLUnionType + | GraphQLEnumType + | GraphQLList + | GraphQLNonNull< + | GraphQLScalarType + | GraphQLObjectType + | GraphQLInterfaceType + | GraphQLUnionType + | GraphQLEnumType + | GraphQLList + >; export function isOutputType(type: ?GraphQLType): boolean { const namedType = getNamedType(type); @@ -106,9 +105,7 @@ export function isOutputType(type: ?GraphQLType): boolean { /** * These types may describe types which may be leaf values. */ -export type GraphQLLeafType = - GraphQLScalarType | - GraphQLEnumType; +export type GraphQLLeafType = GraphQLScalarType | GraphQLEnumType; export function isLeafType(type: ?GraphQLType): boolean { const namedType = getNamedType(type); @@ -122,9 +119,9 @@ export function isLeafType(type: ?GraphQLType): boolean { * These types may describe the parent context of a selection set. */ export type GraphQLCompositeType = - GraphQLObjectType | - GraphQLInterfaceType | - GraphQLUnionType; + | GraphQLObjectType + | GraphQLInterfaceType + | GraphQLUnionType; export function isCompositeType(type: ?GraphQLType): boolean { return ( @@ -137,14 +134,11 @@ export function isCompositeType(type: ?GraphQLType): boolean { /** * These types may describe the parent context of a selection set. */ -export type GraphQLAbstractType = - GraphQLInterfaceType | - GraphQLUnionType; +export type GraphQLAbstractType = GraphQLInterfaceType | GraphQLUnionType; export function isAbstractType(type: ?GraphQLType): boolean { return ( - type instanceof GraphQLInterfaceType || - type instanceof GraphQLUnionType + type instanceof GraphQLInterfaceType || type instanceof GraphQLUnionType ); } @@ -152,13 +146,13 @@ export function isAbstractType(type: ?GraphQLType): boolean { * These types can all accept null as a value. */ export type GraphQLNullableType = - GraphQLScalarType | - GraphQLObjectType | - GraphQLInterfaceType | - GraphQLUnionType | - GraphQLEnumType | - GraphQLInputObjectType | - GraphQLList; + | GraphQLScalarType + | GraphQLObjectType + | GraphQLInterfaceType + | GraphQLUnionType + | GraphQLEnumType + | GraphQLInputObjectType + | GraphQLList; export function getNullableType(type: ?GraphQLType): ?GraphQLNullableType { return type instanceof GraphQLNonNull ? type.ofType : type; @@ -168,12 +162,12 @@ export function getNullableType(type: ?GraphQLType): ?GraphQLNullableType { * These named types do not include modifiers like List or NonNull. */ export type GraphQLNamedType = - GraphQLScalarType | - GraphQLObjectType | - GraphQLInterfaceType | - GraphQLUnionType | - GraphQLEnumType | - GraphQLInputObjectType; + | GraphQLScalarType + | GraphQLObjectType + | GraphQLInterfaceType + | GraphQLUnionType + | GraphQLEnumType + | GraphQLInputObjectType; export function getNamedType(type: ?GraphQLType): ?GraphQLNamedType { let unmodifiedType = type; @@ -186,7 +180,6 @@ export function getNamedType(type: ?GraphQLType): ?GraphQLNamedType { return unmodifiedType; } - /** * Scalar Type Definition * @@ -211,20 +204,20 @@ export class GraphQLScalarType { _scalarConfig: GraphQLScalarTypeConfig; constructor(config: GraphQLScalarTypeConfig) { - invariant(config.name, 'Type must be named.'); + invariant(config.name, "Type must be named."); assertValidName(config.name); this.name = config.name; this.description = config.description; invariant( - typeof config.serialize === 'function', + typeof config.serialize === "function", `${this} must provide "serialize" function. If this custom Scalar is ` + - 'also used as an input type, ensure "parseValue" and "parseLiteral" ' + - 'functions are also provided.' + 'also used as an input type, ensure "parseValue" and "parseLiteral" ' + + "functions are also provided." ); if (config.parseValue || config.parseLiteral) { invariant( - typeof config.parseValue === 'function' && - typeof config.parseLiteral === 'function', + typeof config.parseValue === "function" && + typeof config.parseLiteral === "function", `${this} must provide both "parseValue" and "parseLiteral" functions.` ); } @@ -252,14 +245,12 @@ export class GraphQLScalarType { } export type GraphQLScalarTypeConfig = { - name: string; - description?: ?string; - serialize: (value: mixed) => ?InternalType; - parseValue?: (value: mixed) => ?InternalType; - parseLiteral?: (valueAST: Value) => ?InternalType; -} - - + name: string, + description?: ?string, + serialize: (value: mixed) => ?InternalType, + parseValue?: (value: mixed) => ?InternalType, + parseLiteral?: (valueAST: Value) => ?InternalType +}; /** * Object Type Definition @@ -308,13 +299,13 @@ export class GraphQLObjectType { _interfaces: Array; constructor(config: GraphQLObjectTypeConfig) { - invariant(config.name, 'Type must be named.'); + invariant(config.name, "Type must be named."); assertValidName(config.name); this.name = config.name; this.description = config.description; if (config.isTypeOf) { invariant( - typeof config.isTypeOf === 'function', + typeof config.isTypeOf === "function", `${this} must provide "isTypeOf" as a function.` ); } @@ -323,14 +314,16 @@ export class GraphQLObjectType { } getFields(): GraphQLFieldDefinitionMap { - return this._fields || (this._fields = - defineFieldMap(this, this._typeConfig.fields) + return ( + this._fields || + (this._fields = defineFieldMap(this, this._typeConfig.fields)) ); } getInterfaces(): Array { - return this._interfaces || (this._interfaces = - defineInterfaces(this, this._typeConfig.interfaces) + return ( + this._interfaces || + (this._interfaces = defineInterfaces(this, this._typeConfig.interfaces)) ); } @@ -339,8 +332,8 @@ export class GraphQLObjectType { } } -function resolveMaybeThunk(thingOrThunk: T | () => T): T { - return typeof thingOrThunk === 'function' ? thingOrThunk() : thingOrThunk; +function resolveMaybeThunk(thingOrThunk: T | (() => T)): T { + return typeof thingOrThunk === "function" ? thingOrThunk() : thingOrThunk; } function defineInterfaces( @@ -359,15 +352,15 @@ function defineInterfaces( invariant( iface instanceof GraphQLInterfaceType, `${type} may only implement Interface types, it cannot ` + - `implement: ${iface}.` + `implement: ${iface}.` ); - if (typeof iface.resolveType !== 'function') { + if (typeof iface.resolveType !== "function") { invariant( - typeof type.isTypeOf === 'function', + typeof type.isTypeOf === "function", `Interface Type ${iface} does not provide a "resolveType" function ` + - `and implementing Type ${type} does not provide a "isTypeOf" ` + - 'function. There is no way to resolve this implementing type ' + - 'during execution.' + `and implementing Type ${type} does not provide a "isTypeOf" ` + + "function. There is no way to resolve this implementing type " + + "during execution." ); } }); @@ -382,14 +375,14 @@ function defineFieldMap( invariant( isPlainObj(fieldMap), `${type} fields must be an object with field names as keys or a ` + - 'function which returns such an object.' + "function which returns such an object." ); const fieldNames = Object.keys(fieldMap); invariant( fieldNames.length > 0, `${type} fields must be an object with field names as keys or a ` + - 'function which returns such an object.' + "function which returns such an object." ); const resultFieldMap = {}; @@ -400,14 +393,14 @@ function defineFieldMap( name: fieldName }; invariant( - !field.hasOwnProperty('isDeprecated'), + !field.hasOwnProperty("isDeprecated"), `${type}.${fieldName} should provide "deprecationReason" instead ` + - 'of "isDeprecated".' + 'of "isDeprecated".' ); invariant( isOutputType(field.type), `${type}.${fieldName} field type must be Output Type but ` + - `got: ${field.type}.` + `got: ${field.type}.` ); if (!field.args) { field.args = []; @@ -415,7 +408,7 @@ function defineFieldMap( invariant( isPlainObj(field.args), `${type}.${fieldName} args must be an object with argument names ` + - 'as keys.' + "as keys." ); field.args = Object.keys(field.args).map(argName => { assertValidName(argName); @@ -423,7 +416,7 @@ function defineFieldMap( invariant( isInputType(arg.type), `${type}.${fieldName}(${argName}:) argument type must be ` + - `Input Type but got: ${arg.type}.` + `Input Type but got: ${arg.type}.` ); return { name: argName, @@ -439,16 +432,16 @@ function defineFieldMap( } function isPlainObj(obj) { - return obj && typeof obj === 'object' && !Array.isArray(obj); + return obj && typeof obj === "object" && !Array.isArray(obj); } export type GraphQLObjectTypeConfig = { - name: string; - interfaces?: GraphQLInterfacesThunk | Array; - fields: GraphQLFieldConfigMapThunk | GraphQLFieldConfigMap; - isTypeOf?: GraphQLIsTypeOfFn; + name: string, + interfaces?: GraphQLInterfacesThunk | Array, + fields: GraphQLFieldConfigMapThunk | GraphQLFieldConfigMap, + isTypeOf?: GraphQLIsTypeOfFn, description?: ?string -} +}; type GraphQLInterfacesThunk = () => Array; @@ -458,20 +451,20 @@ export type GraphQLTypeResolveFn = ( value: mixed, context: mixed, info: GraphQLResolveInfo -) => ?GraphQLObjectType +) => ?GraphQLObjectType; export type GraphQLIsTypeOfFn = ( value: mixed, context: mixed, info: GraphQLResolveInfo -) => boolean +) => boolean; export type GraphQLFieldResolveFn = ( source: mixed, - args: {[argName: string]: mixed}, + args: { [argName: string]: mixed }, context: mixed, info: GraphQLResolveInfo -) => mixed +) => mixed; export type GraphQLResolveInfo = { fieldName: string, @@ -482,53 +475,51 @@ export type GraphQLResolveInfo = { fragments: { [fragmentName: string]: FragmentDefinition }, rootValue: mixed, operation: OperationDefinition, - variableValues: { [variableName: string]: mixed }, -} + variableValues: { [variableName: string]: mixed } +}; export type GraphQLFieldConfig = { - type: GraphQLOutputType; - args?: GraphQLFieldConfigArgumentMap; - resolve?: GraphQLFieldResolveFn; - deprecationReason?: ?string; - description?: ?string; -} + type: GraphQLOutputType, + args?: GraphQLFieldConfigArgumentMap, + resolve?: GraphQLFieldResolveFn, + deprecationReason?: ?string, + description?: ?string +}; export type GraphQLFieldConfigArgumentMap = { - [argName: string]: GraphQLArgumentConfig; + [argName: string]: GraphQLArgumentConfig }; export type GraphQLArgumentConfig = { - type: GraphQLInputType; - defaultValue?: mixed; - description?: ?string; -} + type: GraphQLInputType, + defaultValue?: mixed, + description?: ?string +}; export type GraphQLFieldConfigMap = { - [fieldName: string]: GraphQLFieldConfig; + [fieldName: string]: GraphQLFieldConfig }; export type GraphQLFieldDefinition = { - name: string; - description: ?string; - type: GraphQLOutputType; - args: Array; - resolve?: GraphQLFieldResolveFn; - deprecationReason?: ?string; -} + name: string, + description: ?string, + type: GraphQLOutputType, + args: Array, + resolve?: GraphQLFieldResolveFn, + deprecationReason?: ?string +}; export type GraphQLArgument = { - name: string; - type: GraphQLInputType; - defaultValue?: mixed; - description?: ?string; + name: string, + type: GraphQLInputType, + defaultValue?: mixed, + description?: ?string }; export type GraphQLFieldDefinitionMap = { - [fieldName: string]: GraphQLFieldDefinition; + [fieldName: string]: GraphQLFieldDefinition }; - - /** * Interface Type Definition * @@ -556,13 +547,13 @@ export class GraphQLInterfaceType { _fields: GraphQLFieldDefinitionMap; constructor(config: GraphQLInterfaceTypeConfig) { - invariant(config.name, 'Type must be named.'); + invariant(config.name, "Type must be named."); assertValidName(config.name); this.name = config.name; this.description = config.description; if (config.resolveType) { invariant( - typeof config.resolveType === 'function', + typeof config.resolveType === "function", `${this} must provide "resolveType" as a function.` ); } @@ -571,8 +562,10 @@ export class GraphQLInterfaceType { } getFields(): GraphQLFieldDefinitionMap { - return this._fields || - (this._fields = defineFieldMap(this, this._typeConfig.fields)); + return ( + this._fields || + (this._fields = defineFieldMap(this, this._typeConfig.fields)) + ); } toString(): string { @@ -592,8 +585,6 @@ export type GraphQLInterfaceTypeConfig = { description?: ?string }; - - /** * Union Type Definition * @@ -624,16 +615,16 @@ export class GraphQLUnionType { _typeConfig: GraphQLUnionTypeConfig; _types: Array; - _possibleTypeNames: {[typeName: string]: boolean}; + _possibleTypeNames: { [typeName: string]: boolean }; constructor(config: GraphQLUnionTypeConfig) { - invariant(config.name, 'Type must be named.'); + invariant(config.name, "Type must be named."); assertValidName(config.name); this.name = config.name; this.description = config.description; if (config.resolveType) { invariant( - typeof config.resolveType === 'function', + typeof config.resolveType === "function", `${this} must provide "resolveType" as a function.` ); } @@ -647,13 +638,13 @@ export class GraphQLUnionType { type instanceof GraphQLObjectType, `${this} may only contain Object types, it cannot contain: ${type}.` ); - if (typeof this.resolveType !== 'function') { + if (typeof this.resolveType !== "function") { invariant( - typeof type.isTypeOf === 'function', + typeof type.isTypeOf === "function", `Union Type ${this} does not provide a "resolveType" function ` + - `and possible Type ${type} does not provide a "isTypeOf" ` + - 'function. There is no way to resolve this possible type ' + - 'during execution.' + `and possible Type ${type} does not provide a "isTypeOf" ` + + "function. There is no way to resolve this possible type " + + "during execution." ); } }); @@ -678,12 +669,10 @@ export type GraphQLUnionTypeConfig = { * the default implementation will call `isTypeOf` on each implementing * Object type. */ - resolveType?: GraphQLTypeResolveFn; - description?: ?string; + resolveType?: GraphQLTypeResolveFn, + description?: ?string }; - - /** * Enum Type Definition * @@ -705,16 +694,16 @@ export type GraphQLUnionTypeConfig = { * Note: If a value is not provided in a definition, the name of the enum value * will be used as its internal value. */ -export class GraphQLEnumType/* */ { +export class GraphQLEnumType /* */ { name: string; description: ?string; - _enumConfig: GraphQLEnumTypeConfig/* */; - _values: Array */>; - _valueLookup: Map; + _enumConfig: GraphQLEnumTypeConfig /* */; + _values: Array */>; + _valueLookup: Map; _nameLookup: { [valueName: string]: GraphQLEnumValueDefinition }; - constructor(config: GraphQLEnumTypeConfig/* */) { + constructor(config: GraphQLEnumTypeConfig /* */) { this.name = config.name; assertValidName(config.name); this.description = config.description; @@ -722,17 +711,17 @@ export class GraphQLEnumType/* */ { this._enumConfig = config; } - getValues(): Array */> { + getValues(): Array */> { return this._values; } - serialize(value: any/* T */): ?string { + serialize(value: any /* T */): ?string { const enumValue = this._getValueLookup().get(value); return enumValue ? enumValue.name : null; } - parseValue(value: mixed): ?any/* T */ { - if (typeof value === 'string') { + parseValue(value: mixed): ?any /* T */ { + if (typeof value === "string") { const enumValue = this._getNameLookup()[value]; if (enumValue) { return enumValue.value; @@ -740,7 +729,7 @@ export class GraphQLEnumType/* */ { } } - parseLiteral(valueAST: Value): ?any/* T */ { + parseLiteral(valueAST: Value): ?any /* T */ { if (valueAST.kind === ENUM) { const enumValue = this._getNameLookup()[valueAST.value]; if (enumValue) { @@ -749,7 +738,7 @@ export class GraphQLEnumType/* */ { } } - _getValueLookup(): Map { + _getValueLookup(): Map { if (!this._valueLookup) { const lookup = new Map(); this.getValues().forEach(value => { @@ -778,8 +767,8 @@ export class GraphQLEnumType/* */ { function defineEnumValues( type: GraphQLEnumType, - valueMap: GraphQLEnumValueConfigMap/* */ -): Array */> { + valueMap: GraphQLEnumValueConfigMap /* */ +): Array */> { invariant( isPlainObj(valueMap), `${type} values must be an object with value names as keys.` @@ -795,46 +784,44 @@ function defineEnumValues( invariant( isPlainObj(value), `${type}.${valueName} must refer to an object with a "value" key ` + - `representing an internal value but got: ${value}.` + `representing an internal value but got: ${value}.` ); invariant( - !value.hasOwnProperty('isDeprecated'), + !value.hasOwnProperty("isDeprecated"), `${type}.${valueName} should provide "deprecationReason" instead ` + - 'of "isDeprecated".' + 'of "isDeprecated".' ); return { name: valueName, description: value.description, deprecationReason: value.deprecationReason, - value: isNullish(value.value) ? valueName : value.value, + value: isNullish(value.value) ? valueName : value.value }; }); } -export type GraphQLEnumTypeConfig/* */ = { - name: string; - values: GraphQLEnumValueConfigMap/* */; - description?: ?string; -} - -export type GraphQLEnumValueConfigMap/* */ = { - [valueName: string]: GraphQLEnumValueConfig/* */; +export type GraphQLEnumTypeConfig /* */ = { + name: string, + values: GraphQLEnumValueConfigMap /* */, + description?: ?string }; -export type GraphQLEnumValueConfig/* */ = { - value?: any/* T */; - deprecationReason?: ?string; - description?: ?string; -} - -export type GraphQLEnumValueDefinition/* */ = { - name: string; - description: ?string; - deprecationReason: ?string; - value: any/* T */; -} +export type GraphQLEnumValueConfigMap /* */ = { + [valueName: string]: GraphQLEnumValueConfig /* */ +}; +export type GraphQLEnumValueConfig /* */ = { + value?: any /* T */, + deprecationReason?: ?string, + description?: ?string +}; +export type GraphQLEnumValueDefinition /* */ = { + name: string, + description: ?string, + deprecationReason: ?string, + value: any /* T */ +}; /** * Input Object Type Definition @@ -864,7 +851,7 @@ export class GraphQLInputObjectType { _fields: InputObjectFieldMap; constructor(config: InputObjectConfig) { - invariant(config.name, 'Type must be named.'); + invariant(config.name, "Type must be named."); assertValidName(config.name); this.name = config.name; this.description = config.description; @@ -880,13 +867,13 @@ export class GraphQLInputObjectType { invariant( isPlainObj(fieldMap), `${this} fields must be an object with field names as keys or a ` + - 'function which returns such an object.' + "function which returns such an object." ); const fieldNames = Object.keys(fieldMap); invariant( fieldNames.length > 0, `${this} fields must be an object with field names as keys or a ` + - 'function which returns such an object.' + "function which returns such an object." ); const resultFieldMap = {}; fieldNames.forEach(fieldName => { @@ -898,7 +885,7 @@ export class GraphQLInputObjectType { invariant( isInputType(field.type), `${this}.${fieldName} field type must be Input Type but ` + - `got: ${field.type}.` + `got: ${field.type}.` ); resultFieldMap[fieldName] = field; }); @@ -911,36 +898,34 @@ export class GraphQLInputObjectType { } export type InputObjectConfig = { - name: string; - fields: InputObjectConfigFieldMapThunk | InputObjectConfigFieldMap; - description?: ?string; -} + name: string, + fields: InputObjectConfigFieldMapThunk | InputObjectConfigFieldMap, + description?: ?string +}; type InputObjectConfigFieldMapThunk = () => InputObjectConfigFieldMap; export type InputObjectFieldConfig = { - type: GraphQLInputType; - defaultValue?: mixed; - description?: ?string; -} + type: GraphQLInputType, + defaultValue?: mixed, + description?: ?string +}; export type InputObjectConfigFieldMap = { - [fieldName: string]: InputObjectFieldConfig; + [fieldName: string]: InputObjectFieldConfig }; export type InputObjectField = { - name: string; - type: GraphQLInputType; - defaultValue?: mixed; - description?: ?string; -} + name: string, + type: GraphQLInputType, + defaultValue?: mixed, + description?: ?string +}; export type InputObjectFieldMap = { - [fieldName: string]: InputObjectField; + [fieldName: string]: InputObjectField }; - - /** * List Modifier * @@ -971,11 +956,10 @@ export class GraphQLList { } toString(): string { - return '[' + String(this.ofType) + ']'; + return "[" + String(this.ofType) + "]"; } } - /** * Non-Null Modifier * @@ -1008,6 +992,6 @@ export class GraphQLNonNull { } toString(): string { - return this.ofType.toString() + '!'; + return this.ofType.toString() + "!"; } } diff --git a/src/type/directives.js b/src/type/directives.js index e93adb9674..4292a2b1b3 100644 --- a/src/type/directives.js +++ b/src/type/directives.js @@ -8,24 +8,23 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { isInputType, GraphQLNonNull } from './definition'; +import { isInputType, GraphQLNonNull } from "./definition"; import type { GraphQLFieldConfigArgumentMap, GraphQLArgument -} from './definition'; -import { GraphQLBoolean } from './scalars'; -import invariant from '../jsutils/invariant'; -import { assertValidName } from '../utilities/assertValidName'; - +} from "./definition"; +import { GraphQLBoolean } from "./scalars"; +import invariant from "../jsutils/invariant"; +import { assertValidName } from "../utilities/assertValidName"; export const DirectiveLocation = { - QUERY: 'QUERY', - MUTATION: 'MUTATION', - SUBSCRIPTION: 'SUBSCRIPTION', - FIELD: 'FIELD', - FRAGMENT_DEFINITION: 'FRAGMENT_DEFINITION', - FRAGMENT_SPREAD: 'FRAGMENT_SPREAD', - INLINE_FRAGMENT: 'INLINE_FRAGMENT', + QUERY: "QUERY", + MUTATION: "MUTATION", + SUBSCRIPTION: "SUBSCRIPTION", + FIELD: "FIELD", + FRAGMENT_DEFINITION: "FRAGMENT_DEFINITION", + FRAGMENT_SPREAD: "FRAGMENT_SPREAD", + INLINE_FRAGMENT: "INLINE_FRAGMENT" }; export type DirectiveLocationEnum = $Keys; // eslint-disable-line @@ -41,11 +40,11 @@ export class GraphQLDirective { args: Array; constructor(config: GraphQLDirectiveConfig) { - invariant(config.name, 'Directive must be named.'); + invariant(config.name, "Directive must be named."); assertValidName(config.name); invariant( Array.isArray(config.locations), - 'Must provide locations for directive.' + "Must provide locations for directive." ); this.name = config.name; this.description = config.description; @@ -65,7 +64,7 @@ export class GraphQLDirective { invariant( isInputType(arg.type), `@${config.name}(${argName}:) argument type must be ` + - `Input Type but got: ${arg.type}.` + `Input Type but got: ${arg.type}.` ); return { name: argName, @@ -79,50 +78,50 @@ export class GraphQLDirective { } type GraphQLDirectiveConfig = { - name: string; - description?: ?string; - locations: Array; - args?: ?GraphQLFieldConfigArgumentMap; -} + name: string, + description?: ?string, + locations: Array, + args?: ?GraphQLFieldConfigArgumentMap +}; /** * Used to conditionally include fields or fragments */ export const GraphQLIncludeDirective = new GraphQLDirective({ - name: 'include', + name: "include", description: - 'Directs the executor to include this field or fragment only when ' + - 'the `if` argument is true.', + "Directs the executor to include this field or fragment only when " + + "the `if` argument is true.", locations: [ DirectiveLocation.FIELD, DirectiveLocation.FRAGMENT_SPREAD, - DirectiveLocation.INLINE_FRAGMENT, + DirectiveLocation.INLINE_FRAGMENT ], args: { if: { type: new GraphQLNonNull(GraphQLBoolean), - description: 'Included when true.' + description: "Included when true." } - }, + } }); /** * Used to conditionally skip (exclude) fields or fragments */ export const GraphQLSkipDirective = new GraphQLDirective({ - name: 'skip', + name: "skip", description: - 'Directs the executor to skip this field or fragment when the `if` ' + - 'argument is true.', + "Directs the executor to skip this field or fragment when the `if` " + + "argument is true.", locations: [ DirectiveLocation.FIELD, DirectiveLocation.FRAGMENT_SPREAD, - DirectiveLocation.INLINE_FRAGMENT, + DirectiveLocation.INLINE_FRAGMENT ], args: { if: { type: new GraphQLNonNull(GraphQLBoolean), - description: 'Skipped when true.' + description: "Skipped when true." } - }, + } }); diff --git a/src/type/index.js b/src/type/index.js index 009b019601..54e465b4a7 100644 --- a/src/type/index.js +++ b/src/type/index.js @@ -9,7 +9,7 @@ */ // GraphQL Schema definition -export { GraphQLSchema } from './schema'; +export { GraphQLSchema } from "./schema"; export { // Predicates @@ -19,11 +19,9 @@ export { isLeafType, isCompositeType, isAbstractType, - // Un-modifiers getNullableType, getNamedType, - // Definitions GraphQLScalarType, GraphQLObjectType, @@ -32,8 +30,8 @@ export { GraphQLEnumType, GraphQLInputObjectType, GraphQLList, - GraphQLNonNull, -} from './definition'; + GraphQLNonNull +} from "./definition"; // Common built-in scalar instances. export { @@ -41,5 +39,5 @@ export { GraphQLFloat, GraphQLString, GraphQLBoolean, - GraphQLID, -} from './scalars'; + GraphQLID +} from "./scalars"; diff --git a/src/type/introspection.js b/src/type/introspection.js index d760dac70f..f98abd48ae 100644 --- a/src/type/introspection.js +++ b/src/type/introspection.js @@ -8,9 +8,9 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import isNullish from '../jsutils/isNullish'; -import { astFromValue } from '../utilities/astFromValue'; -import { print } from '../language/printer'; +import isNullish from "../jsutils/isNullish"; +import { astFromValue } from "../utilities/astFromValue"; +import { print } from "../language/printer"; import { GraphQLScalarType, GraphQLObjectType, @@ -19,22 +19,21 @@ import { GraphQLEnumType, GraphQLInputObjectType, GraphQLList, - GraphQLNonNull, -} from './definition'; -import { GraphQLString, GraphQLBoolean } from './scalars'; -import { DirectiveLocation } from './directives'; -import type { GraphQLFieldDefinition } from './definition'; - + GraphQLNonNull +} from "./definition"; +import { GraphQLString, GraphQLBoolean } from "./scalars"; +import { DirectiveLocation } from "./directives"; +import type { GraphQLFieldDefinition } from "./definition"; export const __Schema = new GraphQLObjectType({ - name: '__Schema', + name: "__Schema", description: - 'A GraphQL Schema defines the capabilities of a GraphQL server. It ' + - 'exposes all available types and directives on the server, as well as ' + - 'the entry points for query, mutation, and subscription operations.', + "A GraphQL Schema defines the capabilities of a GraphQL server. It " + + "exposes all available types and directives on the server, as well as " + + "the entry points for query, mutation, and subscription operations.", fields: () => ({ types: { - description: 'A list of all types supported by this server.', + description: "A list of all types supported by this server.", type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(__Type))), resolve(schema) { const typeMap = schema.getTypeMap(); @@ -42,57 +41,61 @@ export const __Schema = new GraphQLObjectType({ } }, queryType: { - description: 'The type that query operations will be rooted at.', + description: "The type that query operations will be rooted at.", type: new GraphQLNonNull(__Type), resolve: schema => schema.getQueryType() }, mutationType: { - description: 'If this server supports mutation, the type that ' + - 'mutation operations will be rooted at.', + description: + "If this server supports mutation, the type that " + + "mutation operations will be rooted at.", type: __Type, resolve: schema => schema.getMutationType() }, subscriptionType: { - description: 'If this server support subscription, the type that ' + - 'subscription operations will be rooted at.', + description: + "If this server support subscription, the type that " + + "subscription operations will be rooted at.", type: __Type, resolve: schema => schema.getSubscriptionType() }, directives: { - description: 'A list of all directives supported by this server.', - type: - new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(__Directive))), - resolve: schema => schema.getDirectives(), + description: "A list of all directives supported by this server.", + type: new GraphQLNonNull( + new GraphQLList(new GraphQLNonNull(__Directive)) + ), + resolve: schema => schema.getDirectives() } }) }); export const __Directive = new GraphQLObjectType({ - name: '__Directive', + name: "__Directive", description: - 'A Directive provides a way to describe alternate runtime execution and ' + - 'type validation behavior in a GraphQL document.' + - '\n\nIn some cases, you need to provide options to alter GraphQL’s ' + - 'execution behavior in ways field arguments will not suffice, such as ' + - 'conditionally including or skipping a field. Directives provide this by ' + - 'describing additional information to the executor.', + "A Directive provides a way to describe alternate runtime execution and " + + "type validation behavior in a GraphQL document." + + "\n\nIn some cases, you need to provide options to alter GraphQL’s " + + "execution behavior in ways field arguments will not suffice, such as " + + "conditionally including or skipping a field. Directives provide this by " + + "describing additional information to the executor.", fields: () => ({ name: { type: new GraphQLNonNull(GraphQLString) }, description: { type: GraphQLString }, locations: { - type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull( - __DirectiveLocation - ))) + type: new GraphQLNonNull( + new GraphQLList(new GraphQLNonNull(__DirectiveLocation)) + ) }, args: { - type: - new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(__InputValue))), + type: new GraphQLNonNull( + new GraphQLList(new GraphQLNonNull(__InputValue)) + ), resolve: directive => directive.args || [] }, // NOTE: the following three fields are deprecated and are no longer part // of the GraphQL specification. onOperation: { - deprecationReason: 'Use `locations`.', + deprecationReason: "Use `locations`.", type: new GraphQLNonNull(GraphQLBoolean), resolve: d => d.locations.indexOf(DirectiveLocation.QUERY) !== -1 || @@ -100,7 +103,7 @@ export const __Directive = new GraphQLObjectType({ d.locations.indexOf(DirectiveLocation.SUBSCRIPTION) !== -1 }, onFragment: { - deprecationReason: 'Use `locations`.', + deprecationReason: "Use `locations`.", type: new GraphQLNonNull(GraphQLBoolean), resolve: d => d.locations.indexOf(DirectiveLocation.FRAGMENT_SPREAD) !== -1 || @@ -108,61 +111,61 @@ export const __Directive = new GraphQLObjectType({ d.locations.indexOf(DirectiveLocation.FRAGMENT_DEFINITION) !== -1 }, onField: { - deprecationReason: 'Use `locations`.', + deprecationReason: "Use `locations`.", type: new GraphQLNonNull(GraphQLBoolean), resolve: d => d.locations.indexOf(DirectiveLocation.FIELD) !== -1 - }, - }), + } + }) }); export const __DirectiveLocation = new GraphQLEnumType({ - name: '__DirectiveLocation', + name: "__DirectiveLocation", description: - 'A Directive can be adjacent to many parts of the GraphQL language, a ' + - '__DirectiveLocation describes one such possible adjacencies.', + "A Directive can be adjacent to many parts of the GraphQL language, a " + + "__DirectiveLocation describes one such possible adjacencies.", values: { QUERY: { value: DirectiveLocation.QUERY, - description: 'Location adjacent to a query operation.' + description: "Location adjacent to a query operation." }, MUTATION: { value: DirectiveLocation.MUTATION, - description: 'Location adjacent to a mutation operation.' + description: "Location adjacent to a mutation operation." }, SUBSCRIPTION: { value: DirectiveLocation.SUBSCRIPTION, - description: 'Location adjacent to a subscription operation.' + description: "Location adjacent to a subscription operation." }, FIELD: { value: DirectiveLocation.FIELD, - description: 'Location adjacent to a field.' + description: "Location adjacent to a field." }, FRAGMENT_DEFINITION: { value: DirectiveLocation.FRAGMENT_DEFINITION, - description: 'Location adjacent to a fragment definition.' + description: "Location adjacent to a fragment definition." }, FRAGMENT_SPREAD: { value: DirectiveLocation.FRAGMENT_SPREAD, - description: 'Location adjacent to a fragment spread.' + description: "Location adjacent to a fragment spread." }, INLINE_FRAGMENT: { value: DirectiveLocation.INLINE_FRAGMENT, - description: 'Location adjacent to an inline fragment.' - }, + description: "Location adjacent to an inline fragment." + } } }); export const __Type = new GraphQLObjectType({ - name: '__Type', + name: "__Type", description: - 'The fundamental unit of any GraphQL Schema is the type. There are ' + - 'many kinds of types in GraphQL as represented by the `__TypeKind` enum.' + - '\n\nDepending on the kind of a type, certain fields describe ' + - 'information about that type. Scalar types provide no information ' + - 'beyond a name and description, while Enum types provide their values. ' + - 'Object and Interface types provide the fields they describe. Abstract ' + - 'types, Union and Interface, provide the Object types possible ' + - 'at runtime. List and NonNull types compose other types.', + "The fundamental unit of any GraphQL Schema is the type. There are " + + "many kinds of types in GraphQL as represented by the `__TypeKind` enum." + + "\n\nDepending on the kind of a type, certain fields describe " + + "information about that type. Scalar types provide no information " + + "beyond a name and description, while Enum types provide their values. " + + "Object and Interface types provide the fields they describe. Abstract " + + "types, Union and Interface, provide the Object types possible " + + "at runtime. List and NonNull types compose other types.", fields: () => ({ kind: { type: new GraphQLNonNull(__TypeKind), @@ -184,7 +187,7 @@ export const __Type = new GraphQLObjectType({ } else if (type instanceof GraphQLNonNull) { return TypeKind.NON_NULL; } - throw new Error('Unknown kind of type: ' + type); + throw new Error("Unknown kind of type: " + type); } }, name: { type: GraphQLString }, @@ -195,11 +198,14 @@ export const __Type = new GraphQLObjectType({ includeDeprecated: { type: GraphQLBoolean, defaultValue: false } }, resolve(type, { includeDeprecated }) { - if (type instanceof GraphQLObjectType || - type instanceof GraphQLInterfaceType) { + if ( + type instanceof GraphQLObjectType || + type instanceof GraphQLInterfaceType + ) { const fieldMap = type.getFields(); - let fields = - Object.keys(fieldMap).map(fieldName => fieldMap[fieldName]); + let fields = Object.keys(fieldMap).map( + fieldName => fieldMap[fieldName] + ); if (!includeDeprecated) { fields = fields.filter(field => !field.deprecationReason); } @@ -219,8 +225,10 @@ export const __Type = new GraphQLObjectType({ possibleTypes: { type: new GraphQLList(new GraphQLNonNull(__Type)), resolve(type, args, context, { schema }) { - if (type instanceof GraphQLInterfaceType || - type instanceof GraphQLUnionType) { + if ( + type instanceof GraphQLInterfaceType || + type instanceof GraphQLUnionType + ) { return schema.getPossibleTypes(type); } } @@ -254,35 +262,36 @@ export const __Type = new GraphQLObjectType({ }); export const __Field = new GraphQLObjectType({ - name: '__Field', + name: "__Field", description: - 'Object and Interface types are described by a list of Fields, each of ' + - 'which has a name, potentially a list of arguments, and a return type.', + "Object and Interface types are described by a list of Fields, each of " + + "which has a name, potentially a list of arguments, and a return type.", fields: () => ({ name: { type: new GraphQLNonNull(GraphQLString) }, description: { type: GraphQLString }, args: { - type: - new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(__InputValue))), + type: new GraphQLNonNull( + new GraphQLList(new GraphQLNonNull(__InputValue)) + ), resolve: field => field.args || [] }, type: { type: new GraphQLNonNull(__Type) }, isDeprecated: { type: new GraphQLNonNull(GraphQLBoolean), - resolve: field => !isNullish(field.deprecationReason), + resolve: field => !isNullish(field.deprecationReason) }, deprecationReason: { - type: GraphQLString, + type: GraphQLString } }) }); export const __InputValue = new GraphQLObjectType({ - name: '__InputValue', + name: "__InputValue", description: - 'Arguments provided to Fields or Directives and the input fields of an ' + - 'InputObject are represented as Input Values which describe their type ' + - 'and optionally a default value.', + "Arguments provided to Fields or Directives and the input fields of an " + + "InputObject are represented as Input Values which describe their type " + + "and optionally a default value.", fields: () => ({ name: { type: new GraphQLNonNull(GraphQLString) }, description: { type: GraphQLString }, @@ -290,88 +299,92 @@ export const __InputValue = new GraphQLObjectType({ defaultValue: { type: GraphQLString, description: - 'A GraphQL-formatted string representing the default value for this ' + - 'input value.', - resolve: inputVal => isNullish(inputVal.defaultValue) ? - null : - print(astFromValue(inputVal.defaultValue, inputVal)) + "A GraphQL-formatted string representing the default value for this " + + "input value.", + resolve: inputVal => + isNullish(inputVal.defaultValue) + ? null + : print(astFromValue(inputVal.defaultValue, inputVal)) } }) }); export const __EnumValue = new GraphQLObjectType({ - name: '__EnumValue', + name: "__EnumValue", description: - 'One possible value for a given Enum. Enum values are unique values, not ' + - 'a placeholder for a string or numeric value. However an Enum value is ' + - 'returned in a JSON response as a string.', + "One possible value for a given Enum. Enum values are unique values, not " + + "a placeholder for a string or numeric value. However an Enum value is " + + "returned in a JSON response as a string.", fields: () => ({ name: { type: new GraphQLNonNull(GraphQLString) }, description: { type: GraphQLString }, isDeprecated: { type: new GraphQLNonNull(GraphQLBoolean), - resolve: enumValue => !isNullish(enumValue.deprecationReason), + resolve: enumValue => !isNullish(enumValue.deprecationReason) }, deprecationReason: { - type: GraphQLString, + type: GraphQLString } }) }); export const TypeKind = { - SCALAR: 'SCALAR', - OBJECT: 'OBJECT', - INTERFACE: 'INTERFACE', - UNION: 'UNION', - ENUM: 'ENUM', - INPUT_OBJECT: 'INPUT_OBJECT', - LIST: 'LIST', - NON_NULL: 'NON_NULL', + SCALAR: "SCALAR", + OBJECT: "OBJECT", + INTERFACE: "INTERFACE", + UNION: "UNION", + ENUM: "ENUM", + INPUT_OBJECT: "INPUT_OBJECT", + LIST: "LIST", + NON_NULL: "NON_NULL" }; export const __TypeKind = new GraphQLEnumType({ - name: '__TypeKind', - description: 'An enum describing what kind of type a given `__Type` is.', + name: "__TypeKind", + description: "An enum describing what kind of type a given `__Type` is.", values: { SCALAR: { value: TypeKind.SCALAR, - description: 'Indicates this type is a scalar.' + description: "Indicates this type is a scalar." }, OBJECT: { value: TypeKind.OBJECT, - description: 'Indicates this type is an object. ' + - '`fields` and `interfaces` are valid fields.' + description: + "Indicates this type is an object. " + + "`fields` and `interfaces` are valid fields." }, INTERFACE: { value: TypeKind.INTERFACE, - description: 'Indicates this type is an interface. ' + - '`fields` and `possibleTypes` are valid fields.' + description: + "Indicates this type is an interface. " + + "`fields` and `possibleTypes` are valid fields." }, UNION: { value: TypeKind.UNION, - description: 'Indicates this type is a union. ' + - '`possibleTypes` is a valid field.' + description: + "Indicates this type is a union. " + "`possibleTypes` is a valid field." }, ENUM: { value: TypeKind.ENUM, - description: 'Indicates this type is an enum. ' + - '`enumValues` is a valid field.' + description: + "Indicates this type is an enum. " + "`enumValues` is a valid field." }, INPUT_OBJECT: { value: TypeKind.INPUT_OBJECT, - description: 'Indicates this type is an input object. ' + - '`inputFields` is a valid field.' + description: + "Indicates this type is an input object. " + + "`inputFields` is a valid field." }, LIST: { value: TypeKind.LIST, - description: 'Indicates this type is a list. ' + - '`ofType` is a valid field.' + description: + "Indicates this type is a list. " + "`ofType` is a valid field." }, NON_NULL: { value: TypeKind.NON_NULL, - description: 'Indicates this type is a non-null. ' + - '`ofType` is a valid field.' - }, + description: + "Indicates this type is a non-null. " + "`ofType` is a valid field." + } } }); @@ -381,28 +394,26 @@ export const __TypeKind = new GraphQLEnumType({ */ export const SchemaMetaFieldDef: GraphQLFieldDefinition = { - name: '__schema', + name: "__schema", type: new GraphQLNonNull(__Schema), - description: 'Access the current type schema of this server.', + description: "Access the current type schema of this server.", args: [], resolve: (source, args, context, { schema }) => schema }; export const TypeMetaFieldDef: GraphQLFieldDefinition = { - name: '__type', + name: "__type", type: __Type, - description: 'Request the type information of a single type.', - args: [ - { name: 'name', type: new GraphQLNonNull(GraphQLString) } - ], + description: "Request the type information of a single type.", + args: [{ name: "name", type: new GraphQLNonNull(GraphQLString) }], resolve: (source, { name }: { name: string }, context, { schema }) => schema.getType(name) }; export const TypeNameMetaFieldDef: GraphQLFieldDefinition = { - name: '__typename', + name: "__typename", type: new GraphQLNonNull(GraphQLString), - description: 'The name of the current Object type at runtime.', + description: "The name of the current Object type at runtime.", args: [], resolve: (source, args, context, { parentType }) => parentType.name }; diff --git a/src/type/scalars.js b/src/type/scalars.js index 8e25e3d42d..28b5f03182 100644 --- a/src/type/scalars.js +++ b/src/type/scalars.js @@ -8,8 +8,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { GraphQLScalarType } from './definition'; -import { Kind } from '../language'; +import { GraphQLScalarType } from "./definition"; +import { Kind } from "../language"; // As per the GraphQL Spec, Integers are only treated as valid when a valid // 32-bit signed integer, providing the broadest support across platforms. @@ -25,14 +25,13 @@ function coerceInt(value) { return (num < 0 ? Math.ceil : Math.floor)(num); } return null; - } export const GraphQLInt = new GraphQLScalarType({ - name: 'Int', + name: "Int", description: - 'The `Int` scalar type represents non-fractional signed whole numeric ' + - 'values. Int can represent values between -(2^31) and 2^31 - 1. ', + "The `Int` scalar type represents non-fractional signed whole numeric " + + "values. Int can represent values between -(2^31) and 2^31 - 1. ", serialize: coerceInt, parseValue: coerceInt, parseLiteral(ast) { @@ -52,26 +51,26 @@ function coerceFloat(value) { } export const GraphQLFloat = new GraphQLScalarType({ - name: 'Float', + name: "Float", description: - 'The `Float` scalar type represents signed double-precision fractional ' + - 'values as specified by ' + - '[IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ', + "The `Float` scalar type represents signed double-precision fractional " + + "values as specified by " + + "[IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ", serialize: coerceFloat, parseValue: coerceFloat, parseLiteral(ast) { - return ast.kind === Kind.FLOAT || ast.kind === Kind.INT ? - parseFloat(ast.value) : - null; + return ast.kind === Kind.FLOAT || ast.kind === Kind.INT + ? parseFloat(ast.value) + : null; } }); export const GraphQLString = new GraphQLScalarType({ - name: 'String', + name: "String", description: - 'The `String` scalar type represents textual data, represented as UTF-8 ' + - 'character sequences. The String type is most often used by GraphQL to ' + - 'represent free-form human-readable text.', + "The `String` scalar type represents textual data, represented as UTF-8 " + + "character sequences. The String type is most often used by GraphQL to " + + "represent free-form human-readable text.", serialize: String, parseValue: String, parseLiteral(ast) { @@ -80,8 +79,8 @@ export const GraphQLString = new GraphQLScalarType({ }); export const GraphQLBoolean = new GraphQLScalarType({ - name: 'Boolean', - description: 'The `Boolean` scalar type represents `true` or `false`.', + name: "Boolean", + description: "The `Boolean` scalar type represents `true` or `false`.", serialize: Boolean, parseValue: Boolean, parseLiteral(ast) { @@ -90,18 +89,16 @@ export const GraphQLBoolean = new GraphQLScalarType({ }); export const GraphQLID = new GraphQLScalarType({ - name: 'ID', + name: "ID", description: - 'The `ID` scalar type represents a unique identifier, often used to ' + - 'refetch an object or as key for a cache. The ID type appears in a JSON ' + - 'response as a String; however, it is not intended to be human-readable. ' + + "The `ID` scalar type represents a unique identifier, often used to " + + "refetch an object or as key for a cache. The ID type appears in a JSON " + + "response as a String; however, it is not intended to be human-readable. " + 'When expected as an input type, any string (such as `"4"`) or integer ' + - '(such as `4`) input value will be accepted as an ID.', + "(such as `4`) input value will be accepted as an ID.", serialize: String, parseValue: String, parseLiteral(ast) { - return ast.kind === Kind.STRING || ast.kind === Kind.INT ? - ast.value : - null; + return ast.kind === Kind.STRING || ast.kind === Kind.INT ? ast.value : null; } }); diff --git a/src/type/schema.js b/src/type/schema.js index ddbc3e8f16..b9314ddd82 100644 --- a/src/type/schema.js +++ b/src/type/schema.js @@ -15,18 +15,17 @@ import { GraphQLUnionType, GraphQLList, GraphQLNonNull -} from './definition'; -import type { GraphQLType, GraphQLAbstractType } from './definition'; +} from "./definition"; +import type { GraphQLType, GraphQLAbstractType } from "./definition"; import { GraphQLDirective, GraphQLIncludeDirective, GraphQLSkipDirective -} from './directives'; -import { __Schema } from './introspection'; -import find from '../jsutils/find'; -import invariant from '../jsutils/invariant'; -import { isEqualType, isTypeSubTypeOf } from '../utilities/typeComparators'; - +} from "./directives"; +import { __Schema } from "./introspection"; +import find from "../jsutils/find"; +import invariant from "../jsutils/invariant"; +import { isEqualType, isTypeSubTypeOf } from "../utilities/typeComparators"; /** * Schema Definition @@ -50,14 +49,12 @@ export class GraphQLSchema { _directives: Array; _typeMap: TypeMap; _implementations: { [interfaceName: string]: Array }; - _possibleTypeMap: - ?{ [abstractName: string]: { [possibleName: string]: boolean } }; + _possibleTypeMap: ?{ + [abstractName: string]: { [possibleName: string]: boolean } + }; constructor(config: GraphQLSchemaConfig) { - invariant( - typeof config === 'object', - 'Must provide configuration object.' - ); + invariant(typeof config === "object", "Must provide configuration object."); invariant( config.query instanceof GraphQLObjectType, @@ -68,14 +65,16 @@ export class GraphQLSchema { invariant( !config.mutation || config.mutation instanceof GraphQLObjectType, `Schema mutation must be Object Type if provided but got: ${ - config.mutation}.` + config.mutation + }.` ); this._mutationType = config.mutation; invariant( !config.subscription || config.subscription instanceof GraphQLObjectType, `Schema subscription must be Object Type if provided but got: ${ - config.subscription}.` + config.subscription + }.` ); this._subscriptionType = config.subscription; @@ -86,11 +85,13 @@ export class GraphQLSchema { invariant( !config.directives || - Array.isArray(config.directives) && config.directives.every( - directive => directive instanceof GraphQLDirective - ), + (Array.isArray(config.directives) && + config.directives.every( + directive => directive instanceof GraphQLDirective + )), `Schema directives must be Array if provided but got: ${ - config.directives}.` + config.directives + }.` ); // Provide `@include() and `@skip()` directives by default. this._directives = config.directives || [ @@ -126,7 +127,7 @@ export class GraphQLSchema { if (impls) { impls.push(type); } else { - this._implementations[iface.name] = [ type ]; + this._implementations[iface.name] = [type]; } }); } @@ -136,9 +137,9 @@ export class GraphQLSchema { Object.keys(this._typeMap).forEach(typeName => { const type = this._typeMap[typeName]; if (type instanceof GraphQLObjectType) { - type.getInterfaces().forEach( - iface => assertObjectImplementsInterface(this, type, iface) - ); + type + .getInterfaces() + .forEach(iface => assertObjectImplementsInterface(this, type, iface)); } }); } @@ -183,11 +184,12 @@ export class GraphQLSchema { } if (!possibleTypeMap[abstractType.name]) { - possibleTypeMap[abstractType.name] = - this.getPossibleTypes(abstractType).reduce( - (map, type) => ((map[type.name] = true), map), - Object.create(null) - ); + possibleTypeMap[abstractType.name] = this.getPossibleTypes( + abstractType + ).reduce( + (map, type) => ((map[type.name] = true), map), + Object.create(null) + ); } return Boolean(possibleTypeMap[abstractType.name][possibleType.name]); @@ -202,15 +204,15 @@ export class GraphQLSchema { } } -type TypeMap = { [typeName: string]: GraphQLType } +type TypeMap = { [typeName: string]: GraphQLType }; type GraphQLSchemaConfig = { - query: GraphQLObjectType; - mutation?: ?GraphQLObjectType; - subscription?: ?GraphQLObjectType; - types?: ?Array; - directives?: ?Array; -} + query: GraphQLObjectType, + mutation?: ?GraphQLObjectType, + subscription?: ?GraphQLObjectType, + types?: ?Array, + directives?: ?Array +}; function typeMapReducer(map: TypeMap, type: ?GraphQLType): TypeMap { if (!type) { @@ -222,8 +224,8 @@ function typeMapReducer(map: TypeMap, type: ?GraphQLType): TypeMap { if (map[type.name]) { invariant( map[type.name] === type, - 'Schema must contain unique named types but contains multiple ' + - `types named "${type}".` + "Schema must contain unique named types but contains multiple " + + `types named "${type}".` ); return map; } @@ -239,9 +241,11 @@ function typeMapReducer(map: TypeMap, type: ?GraphQLType): TypeMap { reducedMap = type.getInterfaces().reduce(typeMapReducer, reducedMap); } - if (type instanceof GraphQLObjectType || - type instanceof GraphQLInterfaceType || - type instanceof GraphQLInputObjectType) { + if ( + type instanceof GraphQLObjectType || + type instanceof GraphQLInterfaceType || + type instanceof GraphQLInputObjectType + ) { const fieldMap = type.getFields(); Object.keys(fieldMap).forEach(fieldName => { const field = fieldMap[fieldName]; @@ -274,7 +278,7 @@ function assertObjectImplementsInterface( invariant( objectField, `"${iface}" expects field "${fieldName}" but "${object}" does not ` + - 'provide it.' + "provide it." ); // Assert interface field type is satisfied by object field type, by being @@ -282,7 +286,7 @@ function assertObjectImplementsInterface( invariant( isTypeSubTypeOf(schema, objectField.type, ifaceField.type), `${iface}.${fieldName} expects type "${ifaceField.type}" but ` + - `${object}.${fieldName} provides type "${objectField.type}".` + `${object}.${fieldName} provides type "${objectField.type}".` ); // Assert each interface field arg is implemented. @@ -294,7 +298,7 @@ function assertObjectImplementsInterface( invariant( objectArg, `${iface}.${fieldName} expects argument "${argName}" but ` + - `${object}.${fieldName} does not provide it.` + `${object}.${fieldName} does not provide it.` ); // Assert interface field arg type matches object field arg type. @@ -302,8 +306,8 @@ function assertObjectImplementsInterface( invariant( isEqualType(ifaceArg.type, objectArg.type), `${iface}.${fieldName}(${argName}:) expects type "${ifaceArg.type}" ` + - `but ${object}.${fieldName}(${argName}:) provides ` + - `type "${objectArg.type}".` + `but ${object}.${fieldName}(${argName}:) provides ` + + `type "${objectArg.type}".` ); }); @@ -315,8 +319,8 @@ function assertObjectImplementsInterface( invariant( !(objectArg.type instanceof GraphQLNonNull), `${object}.${fieldName}(${argName}:) is of required type ` + - `"${objectArg.type}" but is not also provided by the ` + - `interface ${iface}.${fieldName}.` + `"${objectArg.type}" but is not also provided by the ` + + `interface ${iface}.${fieldName}.` ); } }); diff --git a/src/utilities/README.md b/src/utilities/README.md index a48dfce7da..0e626e2325 100644 --- a/src/utilities/README.md +++ b/src/utilities/README.md @@ -1,5 +1,4 @@ -GraphQL Utilities ------------------ +## GraphQL Utilities The `graphql/utilities` module contains common useful computations to use with the GraphQL language and type objects. diff --git a/src/utilities/TypeInfo.js b/src/utilities/TypeInfo.js index 8c4ff28952..10cc79f729 100644 --- a/src/utilities/TypeInfo.js +++ b/src/utilities/TypeInfo.js @@ -8,8 +8,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import * as Kind from '../language/kinds'; -import type { Field } from '../language/ast'; +import * as Kind from "../language/kinds"; +import type { Field } from "../language/ast"; import { isCompositeType, getNullableType, @@ -18,8 +18,8 @@ import { GraphQLInterfaceType, GraphQLUnionType, GraphQLInputObjectType, - GraphQLList, -} from '../type/definition'; + GraphQLList +} from "../type/definition"; import type { GraphQLType, GraphQLInputType, @@ -27,18 +27,17 @@ import type { GraphQLCompositeType, GraphQLFieldDefinition, GraphQLArgument -} from '../type/definition'; -import type { GraphQLDirective } from '../type/directives'; +} from "../type/definition"; +import type { GraphQLDirective } from "../type/directives"; import { SchemaMetaFieldDef, TypeMetaFieldDef, TypeNameMetaFieldDef -} from '../type/introspection'; -import type { GraphQLSchema } from '../type/schema'; -import type { Node } from '../language/ast'; -import { typeFromAST } from './typeFromAST'; -import find from '../jsutils/find'; - +} from "../type/introspection"; +import type { GraphQLSchema } from "../type/schema"; +import type { Node } from "../language/ast"; +import { typeFromAST } from "./typeFromAST"; +import find from "../jsutils/find"; /** * TypeInfo is a utility class which, given a GraphQL schema, can keep track @@ -105,7 +104,7 @@ export class TypeInfo { } // Flow does not yet handle this case. - enter(node: any/* Node */) { + enter(node: any /* Node */) { const schema = this._schema; switch (node.kind) { case Kind.SELECTION_SET: @@ -131,11 +130,11 @@ export class TypeInfo { break; case Kind.OPERATION_DEFINITION: let type; - if (node.operation === 'query') { + if (node.operation === "query") { type = schema.getQueryType(); - } else if (node.operation === 'mutation') { + } else if (node.operation === "mutation") { type = schema.getMutationType(); - } else if (node.operation === 'subscription') { + } else if (node.operation === "subscription") { type = schema.getSubscriptionType(); } this._typeStack.push(type); @@ -143,9 +142,9 @@ export class TypeInfo { case Kind.INLINE_FRAGMENT: case Kind.FRAGMENT_DEFINITION: const typeConditionAST = node.typeCondition; - const outputType = typeConditionAST ? - typeFromAST(schema, typeConditionAST) : - this.getType(); + const outputType = typeConditionAST + ? typeFromAST(schema, typeConditionAST) + : this.getType(); this._typeStack.push(((outputType: any): GraphQLOutputType)); break; case Kind.VARIABLE_DEFINITION: @@ -229,23 +228,27 @@ function getFieldDef( fieldAST: Field ): ?GraphQLFieldDefinition { const name = fieldAST.name.value; - if (name === SchemaMetaFieldDef.name && - schema.getQueryType() === parentType) { + if ( + name === SchemaMetaFieldDef.name && + schema.getQueryType() === parentType + ) { return SchemaMetaFieldDef; } - if (name === TypeMetaFieldDef.name && - schema.getQueryType() === parentType) { + if (name === TypeMetaFieldDef.name && schema.getQueryType() === parentType) { return TypeMetaFieldDef; } - if (name === TypeNameMetaFieldDef.name && - (parentType instanceof GraphQLObjectType || - parentType instanceof GraphQLInterfaceType || - parentType instanceof GraphQLUnionType) + if ( + name === TypeNameMetaFieldDef.name && + (parentType instanceof GraphQLObjectType || + parentType instanceof GraphQLInterfaceType || + parentType instanceof GraphQLUnionType) ) { return TypeNameMetaFieldDef; } - if (parentType instanceof GraphQLObjectType || - parentType instanceof GraphQLInterfaceType) { + if ( + parentType instanceof GraphQLObjectType || + parentType instanceof GraphQLInterfaceType + ) { return parentType.getFields()[name]; } } diff --git a/src/utilities/__tests__/astFromValue-test.js b/src/utilities/__tests__/astFromValue-test.js index 3316680da6..c8dcc34506 100644 --- a/src/utilities/__tests__/astFromValue-test.js +++ b/src/utilities/__tests__/astFromValue-test.js @@ -7,181 +7,203 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expect } from 'chai'; -import { astFromValue } from '../astFromValue'; +import { describe, it } from "mocha"; +import { expect } from "chai"; +import { astFromValue } from "../astFromValue"; import { GraphQLEnumType, GraphQLInputObjectType, GraphQLList, - GraphQLFloat, -} from '../../type'; - - -describe('astFromValue', () => { - - it('converts boolean values to ASTs', () => { - expect(astFromValue(true)).to.deep.equal( - { kind: 'BooleanValue', value: true } - ); + GraphQLFloat +} from "../../type"; + +describe("astFromValue", () => { + it("converts boolean values to ASTs", () => { + expect(astFromValue(true)).to.deep.equal({ + kind: "BooleanValue", + value: true + }); - expect(astFromValue(false)).to.deep.equal( - { kind: 'BooleanValue', value: false } - ); + expect(astFromValue(false)).to.deep.equal({ + kind: "BooleanValue", + value: false + }); }); - it('converts numeric values to ASTs', () => { - expect(astFromValue(123)).to.deep.equal( - { kind: 'IntValue', value: '123' } - ); + it("converts numeric values to ASTs", () => { + expect(astFromValue(123)).to.deep.equal({ kind: "IntValue", value: "123" }); - expect(astFromValue(123.0)).to.deep.equal( - { kind: 'IntValue', value: '123' } - ); + expect(astFromValue(123.0)).to.deep.equal({ + kind: "IntValue", + value: "123" + }); - expect(astFromValue(123.5)).to.deep.equal( - { kind: 'FloatValue', value: '123.5' } - ); + expect(astFromValue(123.5)).to.deep.equal({ + kind: "FloatValue", + value: "123.5" + }); - expect(astFromValue(1e4)).to.deep.equal( - { kind: 'IntValue', value: '10000' } - ); + expect(astFromValue(1e4)).to.deep.equal({ + kind: "IntValue", + value: "10000" + }); - expect(astFromValue(1e40)).to.deep.equal( - { kind: 'FloatValue', value: '1e+40' } - ); + expect(astFromValue(1e40)).to.deep.equal({ + kind: "FloatValue", + value: "1e+40" + }); }); - it('converts numeric values to Float ASTs', () => { - expect(astFromValue(123, GraphQLFloat)).to.deep.equal( - { kind: 'FloatValue', value: '123.0' } - ); + it("converts numeric values to Float ASTs", () => { + expect(astFromValue(123, GraphQLFloat)).to.deep.equal({ + kind: "FloatValue", + value: "123.0" + }); - expect(astFromValue(123.0, GraphQLFloat)).to.deep.equal( - { kind: 'FloatValue', value: '123.0' } - ); + expect(astFromValue(123.0, GraphQLFloat)).to.deep.equal({ + kind: "FloatValue", + value: "123.0" + }); - expect(astFromValue(123.5, GraphQLFloat)).to.deep.equal( - { kind: 'FloatValue', value: '123.5' } - ); + expect(astFromValue(123.5, GraphQLFloat)).to.deep.equal({ + kind: "FloatValue", + value: "123.5" + }); - expect(astFromValue(1e4, GraphQLFloat)).to.deep.equal( - { kind: 'FloatValue', value: '10000.0' } - ); + expect(astFromValue(1e4, GraphQLFloat)).to.deep.equal({ + kind: "FloatValue", + value: "10000.0" + }); - expect(astFromValue(1e40, GraphQLFloat)).to.deep.equal( - { kind: 'FloatValue', value: '1e+40' } - ); + expect(astFromValue(1e40, GraphQLFloat)).to.deep.equal({ + kind: "FloatValue", + value: "1e+40" + }); }); - it('converts string values to ASTs', () => { - expect(astFromValue('hello')).to.deep.equal( - { kind: 'StringValue', value: 'hello' } - ); + it("converts string values to ASTs", () => { + expect(astFromValue("hello")).to.deep.equal({ + kind: "StringValue", + value: "hello" + }); - expect(astFromValue('VALUE')).to.deep.equal( - { kind: 'StringValue', value: 'VALUE' } - ); + expect(astFromValue("VALUE")).to.deep.equal({ + kind: "StringValue", + value: "VALUE" + }); - expect(astFromValue('VA\nLUE')).to.deep.equal( - { kind: 'StringValue', value: 'VA\\nLUE' } - ); + expect(astFromValue("VA\nLUE")).to.deep.equal({ + kind: "StringValue", + value: "VA\\nLUE" + }); - expect(astFromValue('123')).to.deep.equal( - { kind: 'StringValue', value: '123' } - ); + expect(astFromValue("123")).to.deep.equal({ + kind: "StringValue", + value: "123" + }); }); const myEnum = new GraphQLEnumType({ - name: 'MyEnum', + name: "MyEnum", values: { HELLO: {}, - GOODBYE: {}, + GOODBYE: {} } }); - it('converts string values to Enum ASTs if possible', () => { - expect(astFromValue('hello', myEnum)).to.deep.equal( - { kind: 'EnumValue', value: 'hello' } - ); + it("converts string values to Enum ASTs if possible", () => { + expect(astFromValue("hello", myEnum)).to.deep.equal({ + kind: "EnumValue", + value: "hello" + }); - expect(astFromValue('HELLO', myEnum)).to.deep.equal( - { kind: 'EnumValue', value: 'HELLO' } - ); + expect(astFromValue("HELLO", myEnum)).to.deep.equal({ + kind: "EnumValue", + value: "HELLO" + }); - expect(astFromValue('VALUE', myEnum)).to.deep.equal( - { kind: 'EnumValue', value: 'VALUE' } - ); + expect(astFromValue("VALUE", myEnum)).to.deep.equal({ + kind: "EnumValue", + value: "VALUE" + }); - expect(astFromValue('VA\nLUE', myEnum)).to.deep.equal( - { kind: 'StringValue', value: 'VA\\nLUE' } - ); + expect(astFromValue("VA\nLUE", myEnum)).to.deep.equal({ + kind: "StringValue", + value: "VA\\nLUE" + }); - expect(astFromValue('123', myEnum)).to.deep.equal( - { kind: 'StringValue', value: '123' } - ); + expect(astFromValue("123", myEnum)).to.deep.equal({ + kind: "StringValue", + value: "123" + }); }); - it('converts array values to List ASTs', () => { - expect(astFromValue([ 'FOO', 'BAR' ])).to.deep.equal( - { kind: 'ListValue', - values: [ - { kind: 'StringValue', value: 'FOO' }, - { kind: 'StringValue', value: 'BAR' } ] } - ); + it("converts array values to List ASTs", () => { + expect(astFromValue(["FOO", "BAR"])).to.deep.equal({ + kind: "ListValue", + values: [ + { kind: "StringValue", value: "FOO" }, + { kind: "StringValue", value: "BAR" } + ] + }); - expect( - astFromValue([ 'FOO', 'BAR' ], - new GraphQLList(myEnum)) - ).to.deep.equal( - { kind: 'ListValue', + expect(astFromValue(["FOO", "BAR"], new GraphQLList(myEnum))).to.deep.equal( + { + kind: "ListValue", values: [ - { kind: 'EnumValue', value: 'FOO' }, - { kind: 'EnumValue', value: 'BAR' } ] } + { kind: "EnumValue", value: "FOO" }, + { kind: "EnumValue", value: "BAR" } + ] + } ); }); - it('converts list singletons', () => { - expect(astFromValue( - 'FOO', - new GraphQLList(myEnum) - )).to.deep.equal( - { kind: 'EnumValue', value: 'FOO' } - ); + it("converts list singletons", () => { + expect(astFromValue("FOO", new GraphQLList(myEnum))).to.deep.equal({ + kind: "EnumValue", + value: "FOO" + }); }); - it('converts input objects', () => { - expect(astFromValue({ foo: 3, bar: 'HELLO' })).to.deep.equal( - { kind: 'ObjectValue', - fields: [ - { kind: 'ObjectField', - name: { kind: 'Name', value: 'foo' }, - value: { kind: 'IntValue', value: '3' } }, - { kind: 'ObjectField', - name: { kind: 'Name', value: 'bar' }, - value: { kind: 'StringValue', value: 'HELLO' } } ] } - ); + it("converts input objects", () => { + expect(astFromValue({ foo: 3, bar: "HELLO" })).to.deep.equal({ + kind: "ObjectValue", + fields: [ + { + kind: "ObjectField", + name: { kind: "Name", value: "foo" }, + value: { kind: "IntValue", value: "3" } + }, + { + kind: "ObjectField", + name: { kind: "Name", value: "bar" }, + value: { kind: "StringValue", value: "HELLO" } + } + ] + }); const inputObj = new GraphQLInputObjectType({ - name: 'MyInputObj', + name: "MyInputObj", fields: { foo: { type: GraphQLFloat }, bar: { type: myEnum } } }); - expect(astFromValue( - { foo: 3, bar: 'HELLO' }, - inputObj - )).to.deep.equal( - { kind: 'ObjectValue', - fields: [ - { kind: 'ObjectField', - name: { kind: 'Name', value: 'foo' }, - value: { kind: 'FloatValue', value: '3.0' } }, - { kind: 'ObjectField', - name: { kind: 'Name', value: 'bar' }, - value: { kind: 'EnumValue', value: 'HELLO' } } ] } - ); + expect(astFromValue({ foo: 3, bar: "HELLO" }, inputObj)).to.deep.equal({ + kind: "ObjectValue", + fields: [ + { + kind: "ObjectField", + name: { kind: "Name", value: "foo" }, + value: { kind: "FloatValue", value: "3.0" } + }, + { + kind: "ObjectField", + name: { kind: "Name", value: "bar" }, + value: { kind: "EnumValue", value: "HELLO" } + } + ] + }); }); }); diff --git a/src/utilities/__tests__/buildASTSchema-test.js b/src/utilities/__tests__/buildASTSchema-test.js index ed8e259dc8..ae529270d9 100644 --- a/src/utilities/__tests__/buildASTSchema-test.js +++ b/src/utilities/__tests__/buildASTSchema-test.js @@ -7,11 +7,11 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { parse } from '../../language'; -import { printSchema } from '../schemaPrinter'; -import { buildASTSchema } from '../buildASTSchema'; +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { parse } from "../../language"; +import { printSchema } from "../schemaPrinter"; +import { buildASTSchema } from "../buildASTSchema"; /** * This function does a full cycle of going from a @@ -23,11 +23,11 @@ import { buildASTSchema } from '../buildASTSchema'; function cycleOutput(body) { const ast = parse(body); const schema = buildASTSchema(ast); - return '\n' + printSchema(schema); + return "\n" + printSchema(schema); } -describe('Schema Builder', () => { - it('Simple type', () => { +describe("Schema Builder", () => { + it("Simple type", () => { const body = ` schema { query: HelloScalars @@ -45,7 +45,7 @@ type HelloScalars { expect(output).to.equal(body); }); - it('With directives', () => { + it("With directives", () => { const body = ` schema { query: Hello @@ -61,7 +61,7 @@ type Hello { expect(output).to.equal(body); }); - it('Type modifiers', () => { + it("Type modifiers", () => { const body = ` schema { query: HelloScalars @@ -79,8 +79,7 @@ type HelloScalars { expect(output).to.equal(body); }); - - it('Recursive type', () => { + it("Recursive type", () => { const body = ` schema { query: Recurse @@ -95,7 +94,7 @@ type Recurse { expect(output).to.equal(body); }); - it('Two types circular', () => { + it("Two types circular", () => { const body = ` schema { query: TypeOne @@ -115,7 +114,7 @@ type TypeTwo { expect(output).to.equal(body); }); - it('Single argument field', () => { + it("Single argument field", () => { const body = ` schema { query: Hello @@ -133,7 +132,7 @@ type Hello { expect(output).to.equal(body); }); - it('Simple type with multiple arguments', () => { + it("Simple type with multiple arguments", () => { const body = ` schema { query: Hello @@ -143,11 +142,11 @@ type Hello { str(int: Int, bool: Boolean): String } `; - const output = cycleOutput(body, 'Hello'); + const output = cycleOutput(body, "Hello"); expect(output).to.equal(body); }); - it('Simple type with interface', () => { + it("Simple type with interface", () => { const body = ` schema { query: Hello @@ -161,11 +160,11 @@ interface WorldInterface { str: String } `; - const output = cycleOutput(body, 'Hello'); + const output = cycleOutput(body, "Hello"); expect(output).to.equal(body); }); - it('Simple output enum', () => { + it("Simple output enum", () => { const body = ` schema { query: OutputEnumRoot @@ -183,7 +182,7 @@ type OutputEnumRoot { expect(output).to.equal(body); }); - it('Simple input enum', () => { + it("Simple input enum", () => { const body = ` schema { query: InputEnumRoot @@ -201,7 +200,7 @@ type InputEnumRoot { expect(output).to.equal(body); }); - it('Multiple value enum', () => { + it("Multiple value enum", () => { const body = ` schema { query: OutputEnumRoot @@ -220,7 +219,7 @@ type OutputEnumRoot { expect(output).to.equal(body); }); - it('Simple Union', () => { + it("Simple Union", () => { const body = ` schema { query: Root @@ -240,7 +239,7 @@ type World { expect(output).to.equal(body); }); - it('Multiple Union', () => { + it("Multiple Union", () => { const body = ` schema { query: Root @@ -264,7 +263,7 @@ type WorldTwo { expect(output).to.equal(body); }); - it('Custom Scalar', () => { + it("Custom Scalar", () => { const body = ` schema { query: Root @@ -281,7 +280,7 @@ type Root { expect(output).to.equal(body); }); - it('Input Object', async() => { + it("Input Object", async () => { const body = ` schema { query: Root @@ -300,7 +299,7 @@ type Root { expect(output).to.equal(body); }); - it('Simple argument field with default', () => { + it("Simple argument field with default", () => { const body = ` schema { query: Hello @@ -314,7 +313,7 @@ type Hello { expect(output).to.equal(body); }); - it('Simple type with mutation', () => { + it("Simple type with mutation", () => { const body = ` schema { query: HelloScalars @@ -335,7 +334,7 @@ type Mutation { expect(output).to.equal(body); }); - it('Simple type with subscription', () => { + it("Simple type with subscription", () => { const body = ` schema { query: HelloScalars @@ -356,7 +355,7 @@ type Subscription { expect(output).to.equal(body); }); - it('Unreferenced type implementing referenced interface', () => { + it("Unreferenced type implementing referenced interface", () => { const body = ` schema { query: Query @@ -378,7 +377,7 @@ type Query { expect(output).to.equal(body); }); - it('Unreferenced type implementing referenced union', () => { + it("Unreferenced type implementing referenced union", () => { const body = ` schema { query: Query @@ -399,20 +398,20 @@ union Union = Concrete }); }); -describe('Failures', () => { - - it('Requires a schema definition', () => { +describe("Failures", () => { + it("Requires a schema definition", () => { const body = ` type Hello { bar: Bar } `; const doc = parse(body); - expect(() => buildASTSchema(doc)) - .to.throw('Must provide a schema definition.'); + expect(() => buildASTSchema(doc)).to.throw( + "Must provide a schema definition." + ); }); - it('Allows only a single schema definition', () => { + it("Allows only a single schema definition", () => { const body = ` schema { query: Hello @@ -427,11 +426,12 @@ type Hello { } `; const doc = parse(body); - expect(() => buildASTSchema(doc)) - .to.throw('Must provide only one schema definition.'); + expect(() => buildASTSchema(doc)).to.throw( + "Must provide only one schema definition." + ); }); - it('Requires a query type', () => { + it("Requires a query type", () => { const body = ` schema { mutation: Hello @@ -442,11 +442,12 @@ type Hello { } `; const doc = parse(body); - expect(() => buildASTSchema(doc)) - .to.throw('Must provide schema definition with query type.'); + expect(() => buildASTSchema(doc)).to.throw( + "Must provide schema definition with query type." + ); }); - it('Allows only a single query type', () => { + it("Allows only a single query type", () => { const body = ` schema { query: Hello @@ -462,11 +463,12 @@ type Yellow { } `; const doc = parse(body); - expect(() => buildASTSchema(doc)) - .to.throw('Must provide only one query type in schema.'); + expect(() => buildASTSchema(doc)).to.throw( + "Must provide only one query type in schema." + ); }); - it('Allows only a single mutation type', () => { + it("Allows only a single mutation type", () => { const body = ` schema { query: Hello @@ -483,11 +485,12 @@ type Yellow { } `; const doc = parse(body); - expect(() => buildASTSchema(doc)) - .to.throw('Must provide only one mutation type in schema.'); + expect(() => buildASTSchema(doc)).to.throw( + "Must provide only one mutation type in schema." + ); }); - it('Allows only a single subscription type', () => { + it("Allows only a single subscription type", () => { const body = ` schema { query: Hello @@ -504,11 +507,12 @@ type Yellow { } `; const doc = parse(body); - expect(() => buildASTSchema(doc)) - .to.throw('Must provide only one subscription type in schema.'); + expect(() => buildASTSchema(doc)).to.throw( + "Must provide only one subscription type in schema." + ); }); - it('Unknown type referenced', () => { + it("Unknown type referenced", () => { const body = ` schema { query: Hello @@ -519,11 +523,12 @@ type Hello { } `; const doc = parse(body); - expect(() => buildASTSchema(doc)) - .to.throw('Type "Bar" not found in document.'); + expect(() => buildASTSchema(doc)).to.throw( + 'Type "Bar" not found in document.' + ); }); - it('Unknown type in interface list', () => { + it("Unknown type in interface list", () => { const body = ` schema { query: Hello @@ -532,11 +537,12 @@ schema { type Hello implements Bar { } `; const doc = parse(body); - expect(() => buildASTSchema(doc)) - .to.throw('Type "Bar" not found in document.'); + expect(() => buildASTSchema(doc)).to.throw( + 'Type "Bar" not found in document.' + ); }); - it('Unknown type in union list', () => { + it("Unknown type in union list", () => { const body = ` schema { query: Hello @@ -546,11 +552,12 @@ union TestUnion = Bar type Hello { testUnion: TestUnion } `; const doc = parse(body); - expect(() => buildASTSchema(doc)) - .to.throw('Type "Bar" not found in document.'); + expect(() => buildASTSchema(doc)).to.throw( + 'Type "Bar" not found in document.' + ); }); - it('Unknown query type', () => { + it("Unknown query type", () => { const body = ` schema { query: Wat @@ -561,11 +568,12 @@ type Hello { } `; const doc = parse(body); - expect(() => buildASTSchema(doc)) - .to.throw('Specified query type "Wat" not found in document.'); + expect(() => buildASTSchema(doc)).to.throw( + 'Specified query type "Wat" not found in document.' + ); }); - it('Unknown mutation type', () => { + it("Unknown mutation type", () => { const body = ` schema { query: Hello @@ -577,11 +585,12 @@ type Hello { } `; const doc = parse(body); - expect(() => buildASTSchema(doc)) - .to.throw('Specified mutation type "Wat" not found in document.'); + expect(() => buildASTSchema(doc)).to.throw( + 'Specified mutation type "Wat" not found in document.' + ); }); - it('Unknown subscription type', () => { + it("Unknown subscription type", () => { const body = ` schema { query: Hello @@ -598,11 +607,12 @@ type Wat { } `; const doc = parse(body); - expect(() => buildASTSchema(doc)) - .to.throw('Specified subscription type "Awesome" not found in document.'); + expect(() => buildASTSchema(doc)).to.throw( + 'Specified subscription type "Awesome" not found in document.' + ); }); - it('Does not consider operation names', () => { + it("Does not consider operation names", () => { const body = ` schema { query: Foo @@ -611,11 +621,12 @@ schema { query Foo { field } `; const doc = parse(body); - expect(() => buildASTSchema(doc)) - .to.throw('Specified query type "Foo" not found in document.'); + expect(() => buildASTSchema(doc)).to.throw( + 'Specified query type "Foo" not found in document.' + ); }); - it('Does not consider fragment names', () => { + it("Does not consider fragment names", () => { const body = ` schema { query: Foo @@ -624,8 +635,8 @@ schema { fragment Foo on Type { field } `; const doc = parse(body); - expect(() => buildASTSchema(doc)) - .to.throw('Specified query type "Foo" not found in document.'); + expect(() => buildASTSchema(doc)).to.throw( + 'Specified query type "Foo" not found in document.' + ); }); - }); diff --git a/src/utilities/__tests__/buildClientSchema-test.js b/src/utilities/__tests__/buildClientSchema-test.js index b9ede38c61..2e70aeb177 100644 --- a/src/utilities/__tests__/buildClientSchema-test.js +++ b/src/utilities/__tests__/buildClientSchema-test.js @@ -7,10 +7,10 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expect } from 'chai'; -import { buildClientSchema } from '../buildClientSchema'; -import { introspectionQuery } from '../introspectionQuery'; +import { describe, it } from "mocha"; +import { expect } from "chai"; +import { buildClientSchema } from "../buildClientSchema"; +import { introspectionQuery } from "../introspectionQuery"; import { graphql, GraphQLSchema, @@ -26,10 +26,9 @@ import { GraphQLFloat, GraphQLString, GraphQLBoolean, - GraphQLID, -} from '../../'; -import { GraphQLDirective } from '../../type/directives'; - + GraphQLID +} from "../../"; +import { GraphQLDirective } from "../../type/directives"; // Test property: // Given a server's schema, a client may query that server with introspection, @@ -44,17 +43,16 @@ async function testSchema(serverSchema) { expect(secondIntrospection).to.deep.equal(initialIntrospection); } -describe('Type System: build schema from introspection', () => { - - it('builds a simple schema', async () => { +describe("Type System: build schema from introspection", () => { + it("builds a simple schema", async () => { const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Simple', - description: 'This is a simple type', + name: "Simple", + description: "This is a simple type", fields: { string: { type: GraphQLString, - description: 'This is a string field' + description: "This is a string field" } } }) @@ -63,25 +61,25 @@ describe('Type System: build schema from introspection', () => { await testSchema(schema); }); - it('builds a simple schema with both operation types', async () => { + it("builds a simple schema with both operation types", async () => { const queryType = new GraphQLObjectType({ - name: 'QueryType', - description: 'This is a simple query type', + name: "QueryType", + description: "This is a simple query type", fields: { string: { type: GraphQLString, - description: 'This is a string field' + description: "This is a string field" } } }); const mutationType = new GraphQLObjectType({ - name: 'MutationType', - description: 'This is a simple mutation type', + name: "MutationType", + description: "This is a simple mutation type", fields: { setString: { type: GraphQLString, - description: 'Set the string field', + description: "Set the string field", args: { value: { type: GraphQLString } } @@ -90,12 +88,12 @@ describe('Type System: build schema from introspection', () => { }); const subscriptionType = new GraphQLObjectType({ - name: 'SubscriptionType', - description: 'This is a simple subscription type', + name: "SubscriptionType", + description: "This is a simple subscription type", fields: { string: { type: GraphQLString, - description: 'This is a string field' + description: "This is a string field" } } }); @@ -109,21 +107,21 @@ describe('Type System: build schema from introspection', () => { await testSchema(schema); }); - it('uses built-in scalars when possible', async () => { + it("uses built-in scalars when possible", async () => { const customScalar = new GraphQLScalarType({ - name: 'CustomScalar', - serialize: () => null, + name: "CustomScalar", + serialize: () => null }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Scalars', + name: "Scalars", fields: { int: { type: GraphQLInt }, float: { type: GraphQLFloat }, string: { type: GraphQLString }, boolean: { type: GraphQLBoolean }, id: { type: GraphQLID }, - custom: { type: customScalar }, + custom: { type: customScalar } } }) }); @@ -134,19 +132,19 @@ describe('Type System: build schema from introspection', () => { const clientSchema = buildClientSchema(introspection.data); // Built-ins are used - expect(clientSchema.getType('Int')).to.equal(GraphQLInt); - expect(clientSchema.getType('Float')).to.equal(GraphQLFloat); - expect(clientSchema.getType('String')).to.equal(GraphQLString); - expect(clientSchema.getType('Boolean')).to.equal(GraphQLBoolean); - expect(clientSchema.getType('ID')).to.equal(GraphQLID); + expect(clientSchema.getType("Int")).to.equal(GraphQLInt); + expect(clientSchema.getType("Float")).to.equal(GraphQLFloat); + expect(clientSchema.getType("String")).to.equal(GraphQLString); + expect(clientSchema.getType("Boolean")).to.equal(GraphQLBoolean); + expect(clientSchema.getType("ID")).to.equal(GraphQLID); // Custom are built - expect(clientSchema.getType('CustomScalar')).not.to.equal(customScalar); + expect(clientSchema.getType("CustomScalar")).not.to.equal(customScalar); }); - it('builds a schema with a recursive type reference', async () => { + it("builds a schema with a recursive type reference", async () => { const recurType = new GraphQLObjectType({ - name: 'Recur', + name: "Recur", fields: () => ({ recur: { type: recurType } }) @@ -158,22 +156,22 @@ describe('Type System: build schema from introspection', () => { await testSchema(schema); }); - it('builds a schema with a circular type reference', async () => { + it("builds a schema with a circular type reference", async () => { const dogType = new GraphQLObjectType({ - name: 'Dog', + name: "Dog", fields: () => ({ bestFriend: { type: humanType } }) }); const humanType = new GraphQLObjectType({ - name: 'Human', + name: "Human", fields: () => ({ bestFriend: { type: dogType } }) }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Circular', + name: "Circular", fields: { dog: { type: dogType }, human: { type: humanType } @@ -184,65 +182,65 @@ describe('Type System: build schema from introspection', () => { await testSchema(schema); }); - it('builds a schema with an interface', async () => { + it("builds a schema with an interface", async () => { const friendlyType = new GraphQLInterfaceType({ - name: 'Friendly', + name: "Friendly", resolveType: () => null, fields: () => ({ bestFriend: { type: friendlyType, - description: 'The best friend of this friendly thing' + description: "The best friend of this friendly thing" } }) }); const dogType = new GraphQLObjectType({ - name: 'Dog', - interfaces: [ friendlyType ], + name: "Dog", + interfaces: [friendlyType], fields: () => ({ bestFriend: { type: friendlyType } }) }); const humanType = new GraphQLObjectType({ - name: 'Human', - interfaces: [ friendlyType ], + name: "Human", + interfaces: [friendlyType], fields: () => ({ bestFriend: { type: friendlyType } }) }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'WithInterface', + name: "WithInterface", fields: { friendly: { type: friendlyType } } }), - types: [ dogType, humanType ] + types: [dogType, humanType] }); await testSchema(schema); }); - it('builds a schema with an implicit interface', async () => { + it("builds a schema with an implicit interface", async () => { const friendlyType = new GraphQLInterfaceType({ - name: 'Friendly', + name: "Friendly", resolveType: () => null, fields: () => ({ bestFriend: { type: friendlyType, - description: 'The best friend of this friendly thing' + description: "The best friend of this friendly thing" } }) }); const dogType = new GraphQLObjectType({ - name: 'Dog', - interfaces: [ friendlyType ], + name: "Dog", + interfaces: [friendlyType], fields: () => ({ bestFriend: { type: dogType } }) }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'WithInterface', + name: "WithInterface", fields: { dog: { type: dogType } } @@ -252,27 +250,27 @@ describe('Type System: build schema from introspection', () => { await testSchema(schema); }); - it('builds a schema with a union', async () => { + it("builds a schema with a union", async () => { const dogType = new GraphQLObjectType({ - name: 'Dog', + name: "Dog", fields: () => ({ bestFriend: { type: friendlyType } }) }); const humanType = new GraphQLObjectType({ - name: 'Human', + name: "Human", fields: () => ({ bestFriend: { type: friendlyType } }) }); const friendlyType = new GraphQLUnionType({ - name: 'Friendly', + name: "Friendly", resolveType: () => null, - types: [ dogType, humanType ] + types: [dogType, humanType] }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'WithUnion', + name: "WithUnion", fields: { friendly: { type: friendlyType } } @@ -282,10 +280,10 @@ describe('Type System: build schema from introspection', () => { await testSchema(schema); }); - it('builds a schema with complex field values', async () => { + it("builds a schema with complex field values", async () => { const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'ComplexFields', + name: "ComplexFields", fields: { string: { type: GraphQLString }, listOfString: { type: new GraphQLList(GraphQLString) }, @@ -299,7 +297,7 @@ describe('Type System: build schema from introspection', () => { type: new GraphQLNonNull( new GraphQLList(new GraphQLNonNull(GraphQLString)) ) - }, + } } }) }); @@ -307,31 +305,31 @@ describe('Type System: build schema from introspection', () => { await testSchema(schema); }); - it('builds a schema with field arguments', async () => { + it("builds a schema with field arguments", async () => { const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'ArgFields', + name: "ArgFields", fields: { one: { - description: 'A field with a single arg', + description: "A field with a single arg", type: GraphQLString, args: { intArg: { - description: 'This is an int arg', + description: "This is an int arg", type: GraphQLInt } } }, two: { - description: 'A field with a two args', + description: "A field with a two args", type: GraphQLString, args: { listArg: { - description: 'This is an list of int arg', + description: "This is an list of int arg", type: new GraphQLList(GraphQLInt) }, requiredArg: { - description: 'This is a required arg', + description: "This is a required arg", type: new GraphQLNonNull(GraphQLBoolean) } } @@ -343,43 +341,43 @@ describe('Type System: build schema from introspection', () => { await testSchema(schema); }); - it('builds a schema with an enum', async () => { + it("builds a schema with an enum", async () => { const foodEnum = new GraphQLEnumType({ - name: 'Food', - description: 'Varieties of food stuffs', + name: "Food", + description: "Varieties of food stuffs", values: { VEGETABLES: { - description: 'Foods that are vegetables.', + description: "Foods that are vegetables.", value: 1 }, FRUITS: { - description: 'Foods that are fruits.', + description: "Foods that are fruits.", value: 2 }, OILS: { - description: 'Foods that are oils.', + description: "Foods that are oils.", value: 3 }, DAIRY: { - description: 'Foods that are dairy.', + description: "Foods that are dairy.", value: 4 }, MEAT: { - description: 'Foods that are meat.', + description: "Foods that are meat.", value: 5 } } }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'EnumFields', + name: "EnumFields", fields: { food: { - description: 'Repeats the arg you give it', + description: "Repeats the arg you give it", type: foodEnum, args: { kind: { - description: 'what kind of food?', + description: "what kind of food?", type: foodEnum } } @@ -392,7 +390,7 @@ describe('Type System: build schema from introspection', () => { const introspection = await graphql(schema, introspectionQuery); const clientSchema = buildClientSchema(introspection.data); - const clientFoodEnum = clientSchema.getType('Food'); + const clientFoodEnum = clientSchema.getType("Food"); // It's also an Enum type on the client. expect(clientFoodEnum).to.be.an.instanceOf(GraphQLEnumType); @@ -400,59 +398,69 @@ describe('Type System: build schema from introspection', () => { // Client types do not get server-only values, so `value` mirrors `name`, // rather than using the integers defined in the "server" schema. expect(clientFoodEnum.getValues()).to.deep.equal([ - { name: 'VEGETABLES', - value: 'VEGETABLES', - description: 'Foods that are vegetables.', - deprecationReason: null, }, - { name: 'FRUITS', - value: 'FRUITS', - description: 'Foods that are fruits.', - deprecationReason: null, }, - { name: 'OILS', - value: 'OILS', - description: 'Foods that are oils.', - deprecationReason: null, }, - { name: 'DAIRY', - value: 'DAIRY', - description: 'Foods that are dairy.', - deprecationReason: null, }, - { name: 'MEAT', - value: 'MEAT', - description: 'Foods that are meat.', - deprecationReason: null, }, + { + name: "VEGETABLES", + value: "VEGETABLES", + description: "Foods that are vegetables.", + deprecationReason: null + }, + { + name: "FRUITS", + value: "FRUITS", + description: "Foods that are fruits.", + deprecationReason: null + }, + { + name: "OILS", + value: "OILS", + description: "Foods that are oils.", + deprecationReason: null + }, + { + name: "DAIRY", + value: "DAIRY", + description: "Foods that are dairy.", + deprecationReason: null + }, + { + name: "MEAT", + value: "MEAT", + description: "Foods that are meat.", + deprecationReason: null + } ]); }); - it('builds a schema with an input object', async () => { + it("builds a schema with an input object", async () => { const addressType = new GraphQLInputObjectType({ - name: 'Address', - description: 'An input address', + name: "Address", + description: "An input address", fields: { street: { - description: 'What street is this address?', + description: "What street is this address?", type: new GraphQLNonNull(GraphQLString) }, city: { - description: 'The city the address is within?', + description: "The city the address is within?", type: new GraphQLNonNull(GraphQLString) }, country: { - description: 'The country (blank will assume USA).', + description: "The country (blank will assume USA).", type: GraphQLString, - defaultValue: 'USA' + defaultValue: "USA" } } }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'HasInputObjectFields', + name: "HasInputObjectFields", fields: { geocode: { - description: 'Get a geocode from an address', + description: "Get a geocode from an address", type: GraphQLString, args: { address: { - description: 'The address to lookup', + description: "The address to lookup", type: addressType } } @@ -464,19 +472,18 @@ describe('Type System: build schema from introspection', () => { await testSchema(schema); }); - - it('builds a schema with field arguments with default values', async () => { + it("builds a schema with field arguments with default values", async () => { const geoType = new GraphQLInputObjectType({ - name: 'Geo', + name: "Geo", fields: { lat: { type: GraphQLFloat }, - lon: { type: GraphQLFloat }, + lon: { type: GraphQLFloat } } }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'ArgFields', + name: "ArgFields", fields: { defaultInt: { type: GraphQLString, @@ -492,7 +499,7 @@ describe('Type System: build schema from introspection', () => { args: { listArg: { type: new GraphQLList(GraphQLInt), - defaultValue: [ 1, 2, 3 ] + defaultValue: [1, 2, 3] } } }, @@ -512,24 +519,23 @@ describe('Type System: build schema from introspection', () => { await testSchema(schema); }); - it('builds a schema with custom directives', async () => { - + it("builds a schema with custom directives", async () => { const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Simple', - description: 'This is a simple type', + name: "Simple", + description: "This is a simple type", fields: { string: { type: GraphQLString, - description: 'This is a string field' + description: "This is a string field" } } }), directives: [ new GraphQLDirective({ - name: 'customDirective', - description: 'This is a custom directive', - locations: [ 'FIELD' ], + name: "customDirective", + description: "This is a custom directive", + locations: ["FIELD"] }) ] }); @@ -537,30 +543,33 @@ describe('Type System: build schema from introspection', () => { await testSchema(schema); }); - it('builds a schema with legacy directives', async () => { - + it("builds a schema with legacy directives", async () => { const oldIntrospection = { __schema: { // Minimum required schema. queryType: { - name: 'Simple' + name: "Simple" }, - types: [ { - name: 'Simple', - kind: 'OBJECT', - fields: [ { - name: 'simple', - args: [], - type: { name: 'Simple' } - } ], - interfaces: [] - } ], + types: [ + { + name: "Simple", + kind: "OBJECT", + fields: [ + { + name: "simple", + args: [], + type: { name: "Simple" } + } + ], + interfaces: [] + } + ], // Test old directive introspection results. directives: [ - { name: 'Old1', args: [], onField: true }, - { name: 'Old2', args: [], onFragment: true }, - { name: 'Old3', args: [], onOperation: true }, - { name: 'Old4', args: [], onField: true, onFragment: true }, + { name: "Old1", args: [], onField: true }, + { name: "Old2", args: [], onFragment: true }, + { name: "Old3", args: [], onOperation: true }, + { name: "Old4", args: [], onField: true, onFragment: true } ] } }; @@ -570,34 +579,34 @@ describe('Type System: build schema from introspection', () => { __schema: { directives: [ { - name: 'Old1', + name: "Old1", args: [], - locations: [ 'FIELD' ] + locations: ["FIELD"] }, { - name: 'Old2', + name: "Old2", args: [], locations: [ - 'FRAGMENT_DEFINITION', - 'FRAGMENT_SPREAD', - 'INLINE_FRAGMENT' + "FRAGMENT_DEFINITION", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT" ] }, { - name: 'Old3', + name: "Old3", args: [], - locations: [ 'QUERY', 'MUTATION', 'SUBSCRIPTION' ] + locations: ["QUERY", "MUTATION", "SUBSCRIPTION"] }, { - name: 'Old4', + name: "Old4", args: [], locations: [ - 'FIELD', - 'FRAGMENT_DEFINITION', - 'FRAGMENT_SPREAD', - 'INLINE_FRAGMENT' + "FIELD", + "FRAGMENT_DEFINITION", + "FRAGMENT_SPREAD", + "INLINE_FRAGMENT" ] - }, + } ] } }; @@ -607,33 +616,32 @@ describe('Type System: build schema from introspection', () => { expect(secondIntrospection.data).to.containSubset(newIntrospection); }); - it('builds a schema aware of deprecation', async () => { - + it("builds a schema aware of deprecation", async () => { const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Simple', - description: 'This is a simple type', + name: "Simple", + description: "This is a simple type", fields: { shinyString: { type: GraphQLString, - description: 'This is a shiny string field' + description: "This is a shiny string field" }, deprecatedString: { type: GraphQLString, - description: 'This is a deprecated string field', - deprecationReason: 'Use shinyString', + description: "This is a deprecated string field", + deprecationReason: "Use shinyString" }, color: { type: new GraphQLEnumType({ - name: 'Color', + name: "Color", values: { - RED: { description: 'So rosy' }, - GREEN: { description: 'So grassy' }, - BLUE: { description: 'So calming' }, + RED: { description: "So rosy" }, + GREEN: { description: "So grassy" }, + BLUE: { description: "So calming" }, MAUVE: { - description: 'So sickening', - deprecationReason: 'No longer in fashion' - }, + description: "So sickening", + deprecationReason: "No longer in fashion" + } } }) } @@ -644,15 +652,15 @@ describe('Type System: build schema from introspection', () => { await testSchema(schema); }); - it('cannot use client schema for general execution', async () => { + it("cannot use client schema for general execution", async () => { const customScalar = new GraphQLScalarType({ - name: 'CustomScalar', - serialize: () => null, + name: "CustomScalar", + serialize: () => null }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { foo: { type: GraphQLString, @@ -670,104 +678,97 @@ describe('Type System: build schema from introspection', () => { const result = await graphql( clientSchema, - 'query NoNo($v: CustomScalar) { foo(custom1: 123, custom2: $v) }', - { foo: 'bar' }, + "query NoNo($v: CustomScalar) { foo(custom1: 123, custom2: $v) }", + { foo: "bar" }, null, - { v: 'baz' } + { v: "baz" } ); expect(result).to.containSubset({ data: { - foo: null, + foo: null }, errors: [ - { message: 'Client Schema cannot be used for execution.', - locations: [ { line: 1, column: 32 } ] } + { + message: "Client Schema cannot be used for execution.", + locations: [{ line: 1, column: 32 }] + } ] }); }); - describe('throws when given incomplete introspection', () => { - - it('throws when given empty types', () => { + describe("throws when given incomplete introspection", () => { + it("throws when given empty types", () => { const incompleteIntrospection = { __schema: { - queryType: { name: 'QueryType' }, + queryType: { name: "QueryType" }, types: [] } }; - expect( - () => buildClientSchema(incompleteIntrospection) - ).to.throw( - 'Invalid or incomplete schema, unknown type: QueryType. Ensure ' + - 'that a full introspection query is used in order to build a ' + - 'client schema.' + expect(() => buildClientSchema(incompleteIntrospection)).to.throw( + "Invalid or incomplete schema, unknown type: QueryType. Ensure " + + "that a full introspection query is used in order to build a " + + "client schema." ); }); - it('throws when missing kind', () => { + it("throws when missing kind", () => { const incompleteIntrospection = { __schema: { - queryType: { name: 'QueryType' }, - types: [ - { name: 'QueryType' } - ] + queryType: { name: "QueryType" }, + types: [{ name: "QueryType" }] } }; - expect( - () => buildClientSchema(incompleteIntrospection) - ).to.throw( - 'Invalid or incomplete schema, unknown kind: undefined. Ensure ' + - 'that a full introspection query is used in order to build a ' + - 'client schema.' + expect(() => buildClientSchema(incompleteIntrospection)).to.throw( + "Invalid or incomplete schema, unknown kind: undefined. Ensure " + + "that a full introspection query is used in order to build a " + + "client schema." ); }); - }); - describe('KP: very deep decorators are not supported', () => { - - it('fails on very deep lists', async () => { + describe("KP: very deep decorators are not supported", () => { + it("fails on very deep lists", async () => { const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { foo: { - type: new GraphQLList(new GraphQLList(new GraphQLList( - new GraphQLList(GraphQLString) - ))) + type: new GraphQLList( + new GraphQLList(new GraphQLList(new GraphQLList(GraphQLString))) + ) } } }) }); const introspection = await graphql(schema, introspectionQuery); - expect( - () => buildClientSchema(introspection.data) - ).to.throw('Decorated type deeper than introspection query.'); + expect(() => buildClientSchema(introspection.data)).to.throw( + "Decorated type deeper than introspection query." + ); }); - it('fails on a deep non-null', async () => { + it("fails on a deep non-null", async () => { const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: { foo: { - type: new GraphQLList(new GraphQLList(new GraphQLList( - new GraphQLNonNull(GraphQLString) - ))) + type: new GraphQLList( + new GraphQLList( + new GraphQLList(new GraphQLNonNull(GraphQLString)) + ) + ) } } }) }); const introspection = await graphql(schema, introspectionQuery); - expect( - () => buildClientSchema(introspection.data) - ).to.throw('Decorated type deeper than introspection query.'); + expect(() => buildClientSchema(introspection.data)).to.throw( + "Decorated type deeper than introspection query." + ); }); - }); - }); diff --git a/src/utilities/__tests__/concatAST-test.js b/src/utilities/__tests__/concatAST-test.js index 0e43e4f7a7..5ff886704e 100644 --- a/src/utilities/__tests__/concatAST-test.js +++ b/src/utilities/__tests__/concatAST-test.js @@ -7,15 +7,13 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expect } from 'chai'; -import { concatAST } from '../concatAST'; -import { Source, parse, print } from '../../language'; +import { describe, it } from "mocha"; +import { expect } from "chai"; +import { concatAST } from "../concatAST"; +import { Source, parse, print } from "../../language"; - -describe('concatAST', () => { - - it('concats two ASTs together', () => { +describe("concatAST", () => { + it("concats two ASTs together", () => { const sourceA = new Source(` { a, b, ...Frag } `); @@ -28,10 +26,10 @@ describe('concatAST', () => { const astA = parse(sourceA); const astB = parse(sourceB); - const astC = concatAST([ astA, astB ]); + const astC = concatAST([astA, astB]); expect(print(astC)).to.equal( -`{ + `{ a b ...Frag @@ -40,7 +38,7 @@ describe('concatAST', () => { fragment Frag on T { c } -`); +` + ); }); - }); diff --git a/src/utilities/__tests__/extendSchema-test.js b/src/utilities/__tests__/extendSchema-test.js index 385f410073..99e8745de7 100644 --- a/src/utilities/__tests__/extendSchema-test.js +++ b/src/utilities/__tests__/extendSchema-test.js @@ -7,12 +7,12 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expect } from 'chai'; -import { extendSchema } from '../extendSchema'; -import { execute } from '../../execution'; -import { parse } from '../../language'; -import { printSchema } from '../schemaPrinter'; +import { describe, it } from "mocha"; +import { expect } from "chai"; +import { extendSchema } from "../extendSchema"; +import { execute } from "../../execution"; +import { parse } from "../../language"; +import { printSchema } from "../schemaPrinter"; import { GraphQLSchema, GraphQLObjectType, @@ -22,64 +22,63 @@ import { GraphQLString, GraphQLEnumType, GraphQLNonNull, - GraphQLList, -} from '../../type'; - + GraphQLList +} from "../../type"; // Test schema. const SomeInterfaceType = new GraphQLInterfaceType({ - name: 'SomeInterface', + name: "SomeInterface", resolveType: () => FooType, fields: () => ({ name: { type: GraphQLString }, - some: { type: SomeInterfaceType }, + some: { type: SomeInterfaceType } }) }); const FooType = new GraphQLObjectType({ - name: 'Foo', - interfaces: [ SomeInterfaceType ], + name: "Foo", + interfaces: [SomeInterfaceType], fields: () => ({ name: { type: GraphQLString }, some: { type: SomeInterfaceType }, - tree: { type: new GraphQLNonNull(new GraphQLList(FooType)) }, + tree: { type: new GraphQLNonNull(new GraphQLList(FooType)) } }) }); const BarType = new GraphQLObjectType({ - name: 'Bar', - interfaces: [ SomeInterfaceType ], + name: "Bar", + interfaces: [SomeInterfaceType], fields: () => ({ name: { type: GraphQLString }, some: { type: SomeInterfaceType }, - foo: { type: FooType }, + foo: { type: FooType } }) }); const BizType = new GraphQLObjectType({ - name: 'Biz', + name: "Biz", fields: () => ({ - fizz: { type: GraphQLString }, + fizz: { type: GraphQLString } }) }); const SomeUnionType = new GraphQLUnionType({ - name: 'SomeUnion', + name: "SomeUnion", resolveType: () => FooType, - types: [ FooType, BizType ], + types: [FooType, BizType] }); const SomeEnumType = new GraphQLEnumType({ - name: 'SomeEnum', + name: "SomeEnum", values: { ONE: { value: 1 }, - TWO: { value: 2 }, + TWO: { value: 2 } } }); const testSchema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: () => ({ foo: { type: FooType }, someUnion: { type: SomeUnionType }, @@ -87,21 +86,20 @@ const testSchema = new GraphQLSchema({ someInterface: { args: { id: { type: new GraphQLNonNull(GraphQLID) } }, type: SomeInterfaceType - }, + } }) }), - types: [ FooType, BarType ] + types: [FooType, BarType] }); -describe('extendSchema', () => { - - it('returns the original schema when there are no type definitions', () => { - const ast = parse('{ field }'); +describe("extendSchema", () => { + it("returns the original schema when there are no type definitions", () => { + const ast = parse("{ field }"); const extendedSchema = extendSchema(testSchema, ast); expect(extendedSchema).to.equal(testSchema); }); - it('extends without altering original schema', () => { + it("extends without altering original schema", () => { const ast = parse(` extend type Query { newField: String @@ -111,27 +109,29 @@ describe('extendSchema', () => { const extendedSchema = extendSchema(testSchema, ast); expect(extendedSchema).to.not.equal(testSchema); expect(printSchema(testSchema)).to.equal(originalPrint); - expect(printSchema(extendedSchema)).to.contain('newField'); - expect(printSchema(testSchema)).to.not.contain('newField'); + expect(printSchema(extendedSchema)).to.contain("newField"); + expect(printSchema(testSchema)).to.not.contain("newField"); }); - it('cannot be used for execution', async () => { + it("cannot be used for execution", async () => { const ast = parse(` extend type Query { newField: String } `); const extendedSchema = extendSchema(testSchema, ast); - const clientQuery = parse('{ newField }'); + const clientQuery = parse("{ newField }"); const result = await execute(extendedSchema, clientQuery); expect(result.data.newField).to.equal(null); - expect(result.errors).to.containSubset([ { - message: 'Client Schema cannot be used for execution.' - } ]); + expect(result.errors).to.containSubset([ + { + message: "Client Schema cannot be used for execution." + } + ]); }); - it('extends objects by adding new fields', () => { + it("extends objects by adding new fields", () => { const ast = parse(` extend type Foo { newField: String @@ -142,7 +142,7 @@ describe('extendSchema', () => { expect(extendedSchema).to.not.equal(testSchema); expect(printSchema(testSchema)).to.equal(originalPrint); expect(printSchema(extendedSchema)).to.equal( -`schema { + `schema { query: Query } @@ -181,10 +181,11 @@ interface SomeInterface { } union SomeUnion = Foo | Biz -`); +` + ); }); - it('extends objects by adding new unused types', () => { + it("extends objects by adding new unused types", () => { const ast = parse(` type Unused { someField: String @@ -195,7 +196,7 @@ union SomeUnion = Foo | Biz expect(extendedSchema).to.not.equal(testSchema); expect(printSchema(testSchema)).to.equal(originalPrint); expect(printSchema(extendedSchema)).to.equal( -`schema { + `schema { query: Query } @@ -237,10 +238,11 @@ union SomeUnion = Foo | Biz type Unused { someField: String } -`); +` + ); }); - it('extends objects by adding new fields with arguments', () => { + it("extends objects by adding new fields with arguments", () => { const ast = parse(` extend type Foo { newField(arg1: String, arg2: NewInputObj!): String @@ -257,7 +259,7 @@ type Unused { expect(extendedSchema).to.not.equal(testSchema); expect(printSchema(testSchema)).to.equal(originalPrint); expect(printSchema(extendedSchema)).to.equal( -`schema { + `schema { query: Query } @@ -302,10 +304,11 @@ interface SomeInterface { } union SomeUnion = Foo | Biz -`); +` + ); }); - it('extends objects by adding new fields with existing types', () => { + it("extends objects by adding new fields with existing types", () => { const ast = parse(` extend type Foo { newField(arg1: SomeEnum!): SomeEnum @@ -316,7 +319,7 @@ union SomeUnion = Foo | Biz expect(extendedSchema).to.not.equal(testSchema); expect(printSchema(testSchema)).to.equal(originalPrint); expect(printSchema(extendedSchema)).to.equal( -`schema { + `schema { query: Query } @@ -355,10 +358,11 @@ interface SomeInterface { } union SomeUnion = Foo | Biz -`); +` + ); }); - it('extends objects by adding implemented interfaces', () => { + it("extends objects by adding implemented interfaces", () => { const ast = parse(` extend type Biz implements SomeInterface { name: String @@ -370,7 +374,7 @@ union SomeUnion = Foo | Biz expect(extendedSchema).to.not.equal(testSchema); expect(printSchema(testSchema)).to.equal(originalPrint); expect(printSchema(extendedSchema)).to.equal( -`schema { + `schema { query: Query } @@ -410,10 +414,11 @@ interface SomeInterface { } union SomeUnion = Foo | Biz -`); +` + ); }); - it('extends objects by including new types', () => { + it("extends objects by including new types", () => { const ast = parse(` extend type Foo { newObject: NewObject @@ -450,7 +455,7 @@ union SomeUnion = Foo | Biz expect(extendedSchema).to.not.equal(testSchema); expect(printSchema(testSchema)).to.equal(originalPrint); expect(printSchema(extendedSchema)).to.equal( -`schema { + `schema { query: Query } @@ -515,10 +520,11 @@ interface SomeInterface { } union SomeUnion = Foo | Biz -`); +` + ); }); - it('extends objects by adding implemented new interfaces', () => { + it("extends objects by adding implemented new interfaces", () => { const ast = parse(` extend type Foo implements NewInterface { baz: String @@ -533,7 +539,7 @@ union SomeUnion = Foo | Biz expect(extendedSchema).to.not.equal(testSchema); expect(printSchema(testSchema)).to.equal(originalPrint); expect(printSchema(extendedSchema)).to.equal( -`schema { + `schema { query: Query } @@ -576,10 +582,11 @@ interface SomeInterface { } union SomeUnion = Foo | Biz -`); +` + ); }); - it('extends objects multiple times', () => { + it("extends objects multiple times", () => { const ast = parse(` extend type Biz implements NewInterface { buzz: String @@ -605,7 +612,7 @@ union SomeUnion = Foo | Biz expect(extendedSchema).to.not.equal(testSchema); expect(printSchema(testSchema)).to.equal(originalPrint); expect(printSchema(extendedSchema)).to.equal( -`schema { + `schema { query: Query } @@ -652,29 +659,30 @@ interface SomeInterface { } union SomeUnion = Foo | Biz -`); +` + ); }); - it('may extend mutations and subscriptions', () => { + it("may extend mutations and subscriptions", () => { const mutationSchema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields: () => ({ - queryField: { type: GraphQLString }, + queryField: { type: GraphQLString } }) }), mutation: new GraphQLObjectType({ - name: 'Mutation', + name: "Mutation", fields: () => ({ - mutationField: { type: GraphQLString }, + mutationField: { type: GraphQLString } }) }), subscription: new GraphQLObjectType({ - name: 'Subscription', + name: "Subscription", fields: () => ({ - subscriptionField: { type: GraphQLString }, + subscriptionField: { type: GraphQLString } }) - }), + }) }); const ast = parse(` @@ -695,7 +703,7 @@ union SomeUnion = Foo | Biz expect(extendedSchema).to.not.equal(mutationSchema); expect(printSchema(mutationSchema)).to.equal(originalPrint); expect(printSchema(extendedSchema)).to.equal( -`schema { + `schema { query: Query mutation: Mutation subscription: Subscription @@ -715,106 +723,91 @@ type Subscription { subscriptionField: String newSubscriptionField: Int } -`); +` + ); }); - it('does not allow replacing an existing type', () => { + it("does not allow replacing an existing type", () => { const ast = parse(` type Bar { baz: String } `); - expect(() => - extendSchema(testSchema, ast) - ).to.throw( + expect(() => extendSchema(testSchema, ast)).to.throw( 'Type "Bar" already exists in the schema. It cannot also be defined ' + - 'in this type definition.' + "in this type definition." ); }); - it('does not allow replacing an existing field', () => { + it("does not allow replacing an existing field", () => { const ast = parse(` extend type Bar { foo: Foo } `); - expect(() => - extendSchema(testSchema, ast) - ).to.throw( + expect(() => extendSchema(testSchema, ast)).to.throw( 'Field "Bar.foo" already exists in the schema. It cannot also be ' + - 'defined in this type extension.' + "defined in this type extension." ); }); - it('does not allow implementing an existing interface', () => { + it("does not allow implementing an existing interface", () => { const ast = parse(` extend type Foo implements SomeInterface { otherField: String } `); - expect(() => - extendSchema(testSchema, ast) - ).to.throw( + expect(() => extendSchema(testSchema, ast)).to.throw( 'Type "Foo" already implements "SomeInterface". It cannot also be ' + - 'implemented in this type extension.' + "implemented in this type extension." ); }); - it('does not allow referencing an unknown type', () => { + it("does not allow referencing an unknown type", () => { const ast = parse(` extend type Bar { quix: Quix } `); - expect(() => - extendSchema(testSchema, ast) - ).to.throw( + expect(() => extendSchema(testSchema, ast)).to.throw( 'Unknown type: "Quix". Ensure that this type exists either in the ' + - 'original schema, or is added in a type definition.' + "original schema, or is added in a type definition." ); }); - it('does not allow extending an unknown type', () => { + it("does not allow extending an unknown type", () => { const ast = parse(` extend type UnknownType { baz: String } `); - expect(() => - extendSchema(testSchema, ast) - ).to.throw( + expect(() => extendSchema(testSchema, ast)).to.throw( 'Cannot extend type "UnknownType" because it does not exist in the ' + - 'existing schema.' + "existing schema." ); }); - describe('does not allow extending a non-object type', () => { - - it('not an interface', () => { + describe("does not allow extending a non-object type", () => { + it("not an interface", () => { const ast = parse(` extend type SomeInterface { baz: String } `); - expect(() => - extendSchema(testSchema, ast) - ).to.throw( + expect(() => extendSchema(testSchema, ast)).to.throw( 'Cannot extend non-object type "SomeInterface".' ); }); - it('not a scalar', () => { + it("not a scalar", () => { const ast = parse(` extend type String { baz: String } `); - expect(() => - extendSchema(testSchema, ast) - ).to.throw( + expect(() => extendSchema(testSchema, ast)).to.throw( 'Cannot extend non-object type "String".' ); }); - }); }); diff --git a/src/utilities/__tests__/getOperationAST-test.js b/src/utilities/__tests__/getOperationAST-test.js index a6d6589a1d..dba6166c18 100644 --- a/src/utilities/__tests__/getOperationAST-test.js +++ b/src/utilities/__tests__/getOperationAST-test.js @@ -7,34 +7,33 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { parse } from '../../language'; -import { getOperationAST } from '../getOperationAST'; +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { parse } from "../../language"; +import { getOperationAST } from "../getOperationAST"; -describe('getOperationAST', () => { - - it('Gets an operation from a simple document', () => { - const doc = parse('{ field }'); +describe("getOperationAST", () => { + it("Gets an operation from a simple document", () => { + const doc = parse("{ field }"); expect(getOperationAST(doc)).to.equal(doc.definitions[0]); }); - it('Gets an operation from a document with named op (mutation)', () => { - const doc = parse('mutation Test { field }'); + it("Gets an operation from a document with named op (mutation)", () => { + const doc = parse("mutation Test { field }"); expect(getOperationAST(doc)).to.equal(doc.definitions[0]); }); - it('Gets an operation from a document with named op (subscription)', () => { - const doc = parse('subscription Test { field }'); + it("Gets an operation from a document with named op (subscription)", () => { + const doc = parse("subscription Test { field }"); expect(getOperationAST(doc)).to.equal(doc.definitions[0]); }); - it('Does not get missing operation', () => { - const doc = parse('type Foo { field: String }'); + it("Does not get missing operation", () => { + const doc = parse("type Foo { field: String }"); expect(getOperationAST(doc)).to.equal(null); }); - it('Does not get ambiguous unnamed operation', () => { + it("Does not get ambiguous unnamed operation", () => { const doc = parse(` { field } mutation Test { field } @@ -42,7 +41,7 @@ describe('getOperationAST', () => { expect(getOperationAST(doc)).to.equal(null); }); - it('Does not get ambiguous named operation', () => { + it("Does not get ambiguous named operation", () => { const doc = parse(` query TestQ { field } mutation TestM { field } @@ -50,22 +49,21 @@ describe('getOperationAST', () => { expect(getOperationAST(doc)).to.equal(null); }); - it('Does not get misnamed operation', () => { + it("Does not get misnamed operation", () => { const doc = parse(` query TestQ { field } mutation TestM { field } subscription TestS { field }`); - expect(getOperationAST(doc, 'Unknown')).to.equal(null); + expect(getOperationAST(doc, "Unknown")).to.equal(null); }); - it('Gets named operation', () => { + it("Gets named operation", () => { const doc = parse(` query TestQ { field } mutation TestM { field } subscription TestS { field }`); - expect(getOperationAST(doc, 'TestQ')).to.equal(doc.definitions[0]); - expect(getOperationAST(doc, 'TestM')).to.equal(doc.definitions[1]); - expect(getOperationAST(doc, 'TestS')).to.equal(doc.definitions[2]); + expect(getOperationAST(doc, "TestQ")).to.equal(doc.definitions[0]); + expect(getOperationAST(doc, "TestM")).to.equal(doc.definitions[1]); + expect(getOperationAST(doc, "TestS")).to.equal(doc.definitions[2]); }); - }); diff --git a/src/utilities/__tests__/schemaPrinter-test.js b/src/utilities/__tests__/schemaPrinter-test.js index f9cb17c849..6797de8b22 100644 --- a/src/utilities/__tests__/schemaPrinter-test.js +++ b/src/utilities/__tests__/schemaPrinter-test.js @@ -7,9 +7,9 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expect } from 'chai'; -import { printSchema, printIntrospectionSchema } from '../schemaPrinter'; +import { describe, it } from "mocha"; +import { expect } from "chai"; +import { printSchema, printIntrospectionSchema } from "../schemaPrinter"; import { GraphQLSchema, GraphQLInputObjectType, @@ -22,18 +22,17 @@ import { GraphQLInt, GraphQLBoolean, GraphQLList, - GraphQLNonNull, -} from '../../'; - + GraphQLNonNull +} from "../../"; function printForTest(schema) { - return '\n' + printSchema(schema); + return "\n" + printSchema(schema); } function printSingleFieldSchema(fieldConfig) { const Root = new GraphQLObjectType({ - name: 'Root', - fields: { singleField: fieldConfig }, + name: "Root", + fields: { singleField: fieldConfig } }); return printForTest(new GraphQLSchema({ query: Root })); } @@ -46,8 +45,8 @@ function nonNull(type) { return new GraphQLNonNull(type); } -describe('Type System Printer', () => { - it('Prints String Field', () => { +describe("Type System Printer", () => { + it("Prints String Field", () => { const output = printSingleFieldSchema({ type: GraphQLString }); @@ -59,11 +58,10 @@ schema { type Root { singleField: String } -` - ); +`); }); - it('Prints [String] Field', () => { + it("Prints [String] Field", () => { const output = printSingleFieldSchema({ type: listOf(GraphQLString) }); @@ -75,11 +73,10 @@ schema { type Root { singleField: [String] } -` - ); +`); }); - it('Prints String! Field', () => { + it("Prints String! Field", () => { const output = printSingleFieldSchema({ type: nonNull(GraphQLString) }); @@ -91,11 +88,10 @@ schema { type Root { singleField: String! } -` - ); +`); }); - it('Prints [String]! Field', () => { + it("Prints [String]! Field", () => { const output = printSingleFieldSchema({ type: nonNull(listOf(GraphQLString)) }); @@ -107,11 +103,10 @@ schema { type Root { singleField: [String]! } -` - ); +`); }); - it('Prints [String!] Field', () => { + it("Prints [String!] Field", () => { const output = printSingleFieldSchema({ type: listOf(nonNull(GraphQLString)) }); @@ -123,11 +118,10 @@ schema { type Root { singleField: [String!] } -` - ); +`); }); - it('Prints [String!]! Field', () => { + it("Prints [String!]! Field", () => { const output = printSingleFieldSchema({ type: nonNull(listOf(nonNull(GraphQLString))) }); @@ -139,19 +133,18 @@ schema { type Root { singleField: [String!]! } -` - ); +`); }); - it('Print Object Field', () => { + it("Print Object Field", () => { const FooType = new GraphQLObjectType({ - name: 'Foo', + name: "Foo", fields: { str: { type: GraphQLString } } }); const Root = new GraphQLObjectType({ - name: 'Root', - fields: { foo: { type: FooType } }, + name: "Root", + fields: { foo: { type: FooType } } }); const Schema = new GraphQLSchema({ query: Root }); @@ -168,17 +161,14 @@ type Foo { type Root { foo: Foo } -` - ); +`); }); - it('Prints String Field With Int Arg', () => { - const output = printSingleFieldSchema( - { - type: GraphQLString, - args: { argOne: { type: GraphQLInt } }, - } - ); + it("Prints String Field With Int Arg", () => { + const output = printSingleFieldSchema({ + type: GraphQLString, + args: { argOne: { type: GraphQLInt } } + }); expect(output).to.equal(` schema { query: Root @@ -187,17 +177,14 @@ schema { type Root { singleField(argOne: Int): String } -` - ); +`); }); - it('Prints String Field With Int Arg With Default', () => { - const output = printSingleFieldSchema( - { - type: GraphQLString, - args: { argOne: { type: GraphQLInt, defaultValue: 2 } }, - } - ); + it("Prints String Field With Int Arg With Default", () => { + const output = printSingleFieldSchema({ + type: GraphQLString, + args: { argOne: { type: GraphQLInt, defaultValue: 2 } } + }); expect(output).to.equal(` schema { query: Root @@ -206,17 +193,14 @@ schema { type Root { singleField(argOne: Int = 2): String } -` - ); +`); }); - it('Prints String Field With Int! Arg', () => { - const output = printSingleFieldSchema( - { - type: GraphQLString, - args: { argOne: { type: nonNull(GraphQLInt) } }, - } - ); + it("Prints String Field With Int! Arg", () => { + const output = printSingleFieldSchema({ + type: GraphQLString, + args: { argOne: { type: nonNull(GraphQLInt) } } + }); expect(output).to.equal(` schema { query: Root @@ -225,20 +209,17 @@ schema { type Root { singleField(argOne: Int!): String } -` - ); +`); }); - it('Prints String Field With Multiple Args', () => { - const output = printSingleFieldSchema( - { - type: GraphQLString, - args: { - argOne: { type: GraphQLInt }, - argTwo: { type: GraphQLString }, - }, + it("Prints String Field With Multiple Args", () => { + const output = printSingleFieldSchema({ + type: GraphQLString, + args: { + argOne: { type: GraphQLInt }, + argTwo: { type: GraphQLString } } - ); + }); expect(output).to.equal(` schema { query: Root @@ -247,21 +228,18 @@ schema { type Root { singleField(argOne: Int, argTwo: String): String } -` - ); +`); }); - it('Prints String Field With Multiple Args, First is Default', () => { - const output = printSingleFieldSchema( - { - type: GraphQLString, - args: { - argOne: { type: GraphQLInt, defaultValue: 1 }, - argTwo: { type: GraphQLString }, - argThree: { type: GraphQLBoolean }, - }, + it("Prints String Field With Multiple Args, First is Default", () => { + const output = printSingleFieldSchema({ + type: GraphQLString, + args: { + argOne: { type: GraphQLInt, defaultValue: 1 }, + argTwo: { type: GraphQLString }, + argThree: { type: GraphQLBoolean } } - ); + }); expect(output).to.equal(` schema { query: Root @@ -270,21 +248,18 @@ schema { type Root { singleField(argOne: Int = 1, argTwo: String, argThree: Boolean): String } -` - ); +`); }); - it('Prints String Field With Multiple Args, Second is Default', () => { - const output = printSingleFieldSchema( - { - type: GraphQLString, - args: { - argOne: { type: GraphQLInt }, - argTwo: { type: GraphQLString, defaultValue: 'foo' }, - argThree: { type: GraphQLBoolean }, - }, + it("Prints String Field With Multiple Args, Second is Default", () => { + const output = printSingleFieldSchema({ + type: GraphQLString, + args: { + argOne: { type: GraphQLInt }, + argTwo: { type: GraphQLString, defaultValue: "foo" }, + argThree: { type: GraphQLBoolean } } - ); + }); expect(output).to.equal(` schema { query: Root @@ -293,21 +268,18 @@ schema { type Root { singleField(argOne: Int, argTwo: String = "foo", argThree: Boolean): String } -` - ); +`); }); - it('Prints String Field With Multiple Args, Last is Default', () => { - const output = printSingleFieldSchema( - { - type: GraphQLString, - args: { - argOne: { type: GraphQLInt }, - argTwo: { type: GraphQLString }, - argThree: { type: GraphQLBoolean, defaultValue: false }, - }, + it("Prints String Field With Multiple Args, Last is Default", () => { + const output = printSingleFieldSchema({ + type: GraphQLString, + args: { + argOne: { type: GraphQLInt }, + argTwo: { type: GraphQLString }, + argThree: { type: GraphQLBoolean, defaultValue: false } } - ); + }); expect(output).to.equal(` schema { query: Root @@ -316,31 +288,30 @@ schema { type Root { singleField(argOne: Int, argTwo: String, argThree: Boolean = false): String } -` - ); +`); }); - it('Print Interface', () => { + it("Print Interface", () => { const FooType = new GraphQLInterfaceType({ - name: 'Foo', + name: "Foo", resolveType: () => null, - fields: { str: { type: GraphQLString } }, + fields: { str: { type: GraphQLString } } }); const BarType = new GraphQLObjectType({ - name: 'Bar', + name: "Bar", fields: { str: { type: GraphQLString } }, - interfaces: [ FooType ], + interfaces: [FooType] }); const Root = new GraphQLObjectType({ - name: 'Root', - fields: { bar: { type: BarType } }, + name: "Root", + fields: { bar: { type: BarType } } }); const Schema = new GraphQLSchema({ query: Root, - types: [ BarType ] + types: [BarType] }); const output = printForTest(Schema); expect(output).to.equal(` @@ -359,40 +330,39 @@ interface Foo { type Root { bar: Bar } -` - ); +`); }); - it('Print Multiple Interface', () => { + it("Print Multiple Interface", () => { const FooType = new GraphQLInterfaceType({ - name: 'Foo', + name: "Foo", resolveType: () => null, - fields: { str: { type: GraphQLString } }, + fields: { str: { type: GraphQLString } } }); const BaazType = new GraphQLInterfaceType({ - name: 'Baaz', + name: "Baaz", resolveType: () => null, - fields: { int: { type: GraphQLInt } }, + fields: { int: { type: GraphQLInt } } }); const BarType = new GraphQLObjectType({ - name: 'Bar', + name: "Bar", fields: { str: { type: GraphQLString }, - int: { type: GraphQLInt }, + int: { type: GraphQLInt } }, - interfaces: [ FooType, BaazType ], + interfaces: [FooType, BaazType] }); const Root = new GraphQLObjectType({ - name: 'Root', - fields: { bar: { type: BarType } }, + name: "Root", + fields: { bar: { type: BarType } } }); const Schema = new GraphQLSchema({ query: Root, - types: [ BarType ] + types: [BarType] }); const output = printForTest(Schema); expect(output).to.equal(` @@ -416,43 +386,42 @@ interface Foo { type Root { bar: Bar } -` - ); +`); }); - it('Print Unions', () => { + it("Print Unions", () => { const FooType = new GraphQLObjectType({ - name: 'Foo', + name: "Foo", fields: { - bool: { type: GraphQLBoolean }, - }, + bool: { type: GraphQLBoolean } + } }); const BarType = new GraphQLObjectType({ - name: 'Bar', + name: "Bar", fields: { - str: { type: GraphQLString }, - }, + str: { type: GraphQLString } + } }); const SingleUnion = new GraphQLUnionType({ - name: 'SingleUnion', + name: "SingleUnion", resolveType: () => null, - types: [ FooType ], + types: [FooType] }); const MultipleUnion = new GraphQLUnionType({ - name: 'MultipleUnion', + name: "MultipleUnion", resolveType: () => null, - types: [ FooType, BarType ], + types: [FooType, BarType] }); const Root = new GraphQLObjectType({ - name: 'Root', + name: "Root", fields: { single: { type: SingleUnion }, - multiple: { type: MultipleUnion }, - }, + multiple: { type: MultipleUnion } + } }); const Schema = new GraphQLSchema({ query: Root }); @@ -478,26 +447,25 @@ type Root { } union SingleUnion = Foo -` - ); +`); }); - it('Print Input Type', () => { + it("Print Input Type", () => { const InputType = new GraphQLInputObjectType({ - name: 'InputType', + name: "InputType", fields: { - int: { type: GraphQLInt }, - }, + int: { type: GraphQLInt } + } }); const Root = new GraphQLObjectType({ - name: 'Root', + name: "Root", fields: { str: { type: GraphQLString, - args: { argOne: { type: InputType } }, - }, - }, + args: { argOne: { type: InputType } } + } + } }); const Schema = new GraphQLSchema({ query: Root }); @@ -517,19 +485,19 @@ type Root { `); }); - it('Custom Scalar', () => { + it("Custom Scalar", () => { const OddType = new GraphQLScalarType({ - name: 'Odd', + name: "Odd", serialize(value) { return value % 2 === 1 ? value : null; } }); const Root = new GraphQLObjectType({ - name: 'Root', + name: "Root", fields: { - odd: { type: OddType }, - }, + odd: { type: OddType } + } }); const Schema = new GraphQLSchema({ query: Root }); @@ -544,13 +512,12 @@ scalar Odd type Root { odd: Odd } -` - ); +`); }); - it('Enum', () => { + it("Enum", () => { const RGBType = new GraphQLEnumType({ - name: 'RGB', + name: "RGB", values: { RED: { value: 0 }, GREEN: { value: 1 }, @@ -559,10 +526,10 @@ type Root { }); const Root = new GraphQLObjectType({ - name: 'Root', + name: "Root", fields: { - rgb: { type: RGBType }, - }, + rgb: { type: RGBType } + } }); const Schema = new GraphQLSchema({ query: Root }); @@ -584,15 +551,15 @@ type Root { `); }); - it('Print Introspection Schema', () => { + it("Print Introspection Schema", () => { const Root = new GraphQLObjectType({ - name: 'Root', + name: "Root", fields: { onlyField: { type: GraphQLString } - }, + } }); const Schema = new GraphQLSchema({ query: Root }); - const output = '\n' + printIntrospectionSchema(Schema); + const output = "\n" + printIntrospectionSchema(Schema); const introspectionSchema = ` schema { query: Root diff --git a/src/utilities/__tests__/typeComparators-test.js b/src/utilities/__tests__/typeComparators-test.js index bbd86dbdb0..a3dc788e87 100644 --- a/src/utilities/__tests__/typeComparators-test.js +++ b/src/utilities/__tests__/typeComparators-test.js @@ -7,8 +7,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expect } from 'chai'; +import { describe, it } from "mocha"; +import { expect } from "chai"; import { GraphQLSchema, GraphQLString, @@ -18,36 +18,33 @@ import { GraphQLNonNull, GraphQLObjectType, GraphQLInterfaceType, - GraphQLUnionType, -} from '../../type'; -import { isEqualType, isTypeSubTypeOf } from '../typeComparators'; + GraphQLUnionType +} from "../../type"; +import { isEqualType, isTypeSubTypeOf } from "../typeComparators"; - -describe('typeComparators', () => { - - describe('isEqualType', () => { - - it('same reference are equal', () => { +describe("typeComparators", () => { + describe("isEqualType", () => { + it("same reference are equal", () => { expect(isEqualType(GraphQLString, GraphQLString)).to.equal(true); }); - it('int and float are not equal', () => { + it("int and float are not equal", () => { expect(isEqualType(GraphQLInt, GraphQLFloat)).to.equal(false); }); - it('lists of same type are equal', () => { + it("lists of same type are equal", () => { expect( isEqualType(new GraphQLList(GraphQLInt), new GraphQLList(GraphQLInt)) ).to.equal(true); }); - it('lists is not equal to item', () => { - expect( - isEqualType(new GraphQLList(GraphQLInt), GraphQLInt) - ).to.equal(false); + it("lists is not equal to item", () => { + expect(isEqualType(new GraphQLList(GraphQLInt), GraphQLInt)).to.equal( + false + ); }); - it('non-null of same type are equal', () => { + it("non-null of same type are equal", () => { expect( isEqualType( new GraphQLNonNull(GraphQLInt), @@ -56,103 +53,93 @@ describe('typeComparators', () => { ).to.equal(true); }); - it('non-null is not equal to nullable', () => { - expect( - isEqualType(new GraphQLNonNull(GraphQLInt), GraphQLInt) - ).to.equal(false); + it("non-null is not equal to nullable", () => { + expect(isEqualType(new GraphQLNonNull(GraphQLInt), GraphQLInt)).to.equal( + false + ); }); - }); - describe('isTypeSubTypeOf', () => { - + describe("isTypeSubTypeOf", () => { function testSchema(fields) { return new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'Query', + name: "Query", fields }) }); } - it('same reference is subtype', () => { + it("same reference is subtype", () => { const schema = testSchema({ field: { type: GraphQLString } }); - expect( - isTypeSubTypeOf(schema, GraphQLString, GraphQLString) - ).to.equal(true); + expect(isTypeSubTypeOf(schema, GraphQLString, GraphQLString)).to.equal( + true + ); }); - it('int is not subtype of float', () => { + it("int is not subtype of float", () => { const schema = testSchema({ field: { type: GraphQLString } }); - expect( - isTypeSubTypeOf(schema, GraphQLInt, GraphQLFloat) - ).to.equal(false); + expect(isTypeSubTypeOf(schema, GraphQLInt, GraphQLFloat)).to.equal(false); }); - it('non-null is subtype of nullable', () => { + it("non-null is subtype of nullable", () => { const schema = testSchema({ field: { type: GraphQLString } }); expect( isTypeSubTypeOf(schema, new GraphQLNonNull(GraphQLInt), GraphQLInt) ).to.equal(true); }); - it('nullable is not subtype of non-null', () => { + it("nullable is not subtype of non-null", () => { const schema = testSchema({ field: { type: GraphQLString } }); expect( isTypeSubTypeOf(schema, GraphQLInt, new GraphQLNonNull(GraphQLInt)) ).to.equal(false); }); - it('item is not subtype of list', () => { + it("item is not subtype of list", () => { const schema = testSchema({ field: { type: GraphQLString } }); expect( isTypeSubTypeOf(schema, GraphQLInt, new GraphQLList(GraphQLInt)) ).to.equal(false); }); - it('list is not subtype of item', () => { + it("list is not subtype of item", () => { const schema = testSchema({ field: { type: GraphQLString } }); expect( isTypeSubTypeOf(schema, new GraphQLList(GraphQLInt), GraphQLInt) ).to.equal(false); }); - it('member is subtype of union', () => { + it("member is subtype of union", () => { const member = new GraphQLObjectType({ - name: 'Object', + name: "Object", isTypeOf: () => true, fields: { field: { type: GraphQLString } } }); - const union = new GraphQLUnionType({ name: 'Union', types: [ member ] }); + const union = new GraphQLUnionType({ name: "Union", types: [member] }); const schema = testSchema({ field: { type: union } }); - expect( - isTypeSubTypeOf(schema, member, union) - ).to.equal(true); + expect(isTypeSubTypeOf(schema, member, union)).to.equal(true); }); - it('implementation is subtype of interface', () => { + it("implementation is subtype of interface", () => { const iface = new GraphQLInterfaceType({ - name: 'Interface', + name: "Interface", fields: { field: { type: GraphQLString } } }); const impl = new GraphQLObjectType({ - name: 'Object', + name: "Object", isTypeOf: () => true, - interfaces: [ iface ], + interfaces: [iface], fields: { field: { type: GraphQLString } } }); const schema = testSchema({ field: { type: impl } }); - expect( - isTypeSubTypeOf(schema, impl, iface) - ).to.equal(true); + expect(isTypeSubTypeOf(schema, impl, iface)).to.equal(true); }); - }); - }); diff --git a/src/utilities/assertValidName.js b/src/utilities/assertValidName.js index 8413767375..7c02500401 100644 --- a/src/utilities/assertValidName.js +++ b/src/utilities/assertValidName.js @@ -8,8 +8,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import invariant from '../jsutils/invariant'; - +import invariant from "../jsutils/invariant"; const NAME_RX = /^[_a-zA-Z][_a-zA-Z0-9]*$/; diff --git a/src/utilities/astFromValue.js b/src/utilities/astFromValue.js index 1293542693..50fa28fd0c 100644 --- a/src/utilities/astFromValue.js +++ b/src/utilities/astFromValue.js @@ -8,8 +8,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import invariant from '../jsutils/invariant'; -import isNullish from '../jsutils/isNullish'; +import invariant from "../jsutils/invariant"; +import isNullish from "../jsutils/isNullish"; import type { Value, IntValue, @@ -18,8 +18,8 @@ import type { BooleanValue, EnumValue, ListValue, - ObjectValue, -} from '../language/ast'; + ObjectValue +} from "../language/ast"; import { NAME, INT, @@ -29,17 +29,16 @@ import { ENUM, LIST, OBJECT, - OBJECT_FIELD, -} from '../language/kinds'; -import type { GraphQLType } from '../type/definition'; + OBJECT_FIELD +} from "../language/kinds"; +import type { GraphQLType } from "../type/definition"; import { GraphQLEnumType, GraphQLInputObjectType, GraphQLList, - GraphQLNonNull, -} from '../type/definition'; -import { GraphQLFloat } from '../type/scalars'; - + GraphQLNonNull +} from "../type/definition"; +import { GraphQLFloat } from "../type/scalars"; /** * Produces a GraphQL Value AST given a JavaScript value. @@ -56,10 +55,7 @@ import { GraphQLFloat } from '../type/scalars'; * | Number | Int / Float | * */ -export function astFromValue( - value: mixed, - type?: ?GraphQLType -): ?Value { +export function astFromValue(value: mixed, type?: ?GraphQLType): ?Value { // Ensure flow knows that we treat function params as const. const _value = value; @@ -81,7 +77,7 @@ export function astFromValue( kind: LIST, values: _value.map(item => { const itemValue = astFromValue(item, itemType); - invariant(itemValue, 'Could not create AST item.'); + invariant(itemValue, "Could not create AST item."); return itemValue; }) }: ListValue); @@ -92,19 +88,19 @@ export function astFromValue( return astFromValue(_value, type.ofType); } - if (typeof _value === 'boolean') { + if (typeof _value === "boolean") { return ({ kind: BOOLEAN, value: _value }: BooleanValue); } // JavaScript numbers can be Float or Int values. Use the GraphQLType to // differentiate if available, otherwise prefer Int if the value is a // valid Int. - if (typeof _value === 'number') { + if (typeof _value === "number") { const stringNum = String(_value); const isIntValue = /^[0-9]+$/.test(stringNum); if (isIntValue) { if (type === GraphQLFloat) { - return ({ kind: FLOAT, value: stringNum + '.0' }: FloatValue); + return ({ kind: FLOAT, value: stringNum + ".0" }: FloatValue); } return ({ kind: INT, value: stringNum }: IntValue); } @@ -113,9 +109,11 @@ export function astFromValue( // JavaScript strings can be Enum values or String values. Use the // GraphQLType to differentiate if possible. - if (typeof _value === 'string') { - if (type instanceof GraphQLEnumType && - /^[_a-zA-Z][_a-zA-Z0-9]*$/.test(_value)) { + if (typeof _value === "string") { + if ( + type instanceof GraphQLEnumType && + /^[_a-zA-Z][_a-zA-Z0-9]*$/.test(_value) + ) { return ({ kind: ENUM, value: _value }: EnumValue); } // Use JSON stringify, which uses the same string encoding as GraphQL, @@ -127,7 +125,7 @@ export function astFromValue( } // last remaining possible typeof - invariant(typeof _value === 'object' && _value !== null); + invariant(typeof _value === "object" && _value !== null); // Populate the fields of the input object by creating ASTs from each value // in the JavaScript object. diff --git a/src/utilities/buildASTSchema.js b/src/utilities/buildASTSchema.js index 5a1d04a5c5..cdcb136251 100644 --- a/src/utilities/buildASTSchema.js +++ b/src/utilities/buildASTSchema.js @@ -8,15 +8,12 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import invariant from '../jsutils/invariant'; -import keyMap from '../jsutils/keyMap'; -import keyValMap from '../jsutils/keyValMap'; -import { valueFromAST } from './valueFromAST'; +import invariant from "../jsutils/invariant"; +import keyMap from "../jsutils/keyMap"; +import keyValMap from "../jsutils/keyValMap"; +import { valueFromAST } from "./valueFromAST"; -import { - LIST_TYPE, - NON_NULL_TYPE, -} from '../language/kinds'; +import { LIST_TYPE, NON_NULL_TYPE } from "../language/kinds"; import { DOCUMENT, @@ -27,8 +24,8 @@ import { ENUM_TYPE_DEFINITION, UNION_TYPE_DEFINITION, INPUT_OBJECT_TYPE_DEFINITION, - DIRECTIVE_DEFINITION, -} from '../language/kinds'; + DIRECTIVE_DEFINITION +} from "../language/kinds"; import type { Document, @@ -43,8 +40,8 @@ import type { UnionTypeDefinition, EnumTypeDefinition, InputObjectTypeDefinition, - DirectiveDefinition, -} from '../language/ast'; + DirectiveDefinition +} from "../language/ast"; import { GraphQLSchema, @@ -60,10 +57,10 @@ import { GraphQLBoolean, GraphQLID, GraphQLList, - GraphQLNonNull, -} from '../type'; + GraphQLNonNull +} from "../type"; -import { GraphQLDirective } from '../type/directives'; +import { GraphQLDirective } from "../type/directives"; import { __Schema, @@ -73,19 +70,15 @@ import { __Field, __InputValue, __EnumValue, - __TypeKind, -} from '../type/introspection'; - -import type { - GraphQLType, - GraphQLNamedType -} from '../type/definition'; + __TypeKind +} from "../type/introspection"; +import type { GraphQLType, GraphQLNamedType } from "../type/definition"; type CompositeDefinition = - ObjectTypeDefinition | - InterfaceTypeDefinition | - UnionTypeDefinition; + | ObjectTypeDefinition + | InterfaceTypeDefinition + | UnionTypeDefinition; function buildWrappedType( innerType: GraphQLType, @@ -96,7 +89,7 @@ function buildWrappedType( } if (inputTypeAST.kind === NON_NULL_TYPE) { const wrappedType = buildWrappedType(innerType, inputTypeAST.type); - invariant(!(wrappedType instanceof GraphQLNonNull), 'No nesting nonnull.'); + invariant(!(wrappedType instanceof GraphQLNonNull), "No nesting nonnull."); return new GraphQLNonNull(wrappedType); } return innerType; @@ -120,7 +113,7 @@ function getNamedTypeAST(typeAST: Type): NamedType { */ export function buildASTSchema(ast: Document): GraphQLSchema { if (!ast || ast.kind !== DOCUMENT) { - throw new Error('Must provide a document ast.'); + throw new Error("Must provide a document ast."); } let schemaDef: ?SchemaDefinition; @@ -132,7 +125,7 @@ export function buildASTSchema(ast: Document): GraphQLSchema { switch (d.kind) { case SCHEMA_DEFINITION: if (schemaDef) { - throw new Error('Must provide only one schema definition.'); + throw new Error("Must provide only one schema definition."); } schemaDef = d; break; @@ -151,7 +144,7 @@ export function buildASTSchema(ast: Document): GraphQLSchema { } if (!schemaDef) { - throw new Error('Must provide a schema definition.'); + throw new Error("Must provide a schema definition."); } let queryTypeName; @@ -159,30 +152,32 @@ export function buildASTSchema(ast: Document): GraphQLSchema { let subscriptionTypeName; schemaDef.operationTypes.forEach(operationType => { const typeName = operationType.type.name.value; - if (operationType.operation === 'query') { + if (operationType.operation === "query") { if (queryTypeName) { - throw new Error('Must provide only one query type in schema.'); + throw new Error("Must provide only one query type in schema."); } queryTypeName = typeName; - } else if (operationType.operation === 'mutation') { + } else if (operationType.operation === "mutation") { if (mutationTypeName) { - throw new Error('Must provide only one mutation type in schema.'); + throw new Error("Must provide only one mutation type in schema."); } mutationTypeName = typeName; - } else if (operationType.operation === 'subscription') { + } else if (operationType.operation === "subscription") { if (subscriptionTypeName) { - throw new Error('Must provide only one subscription type in schema.'); + throw new Error("Must provide only one subscription type in schema."); } subscriptionTypeName = typeName; } }); if (!queryTypeName) { - throw new Error('Must provide schema definition with query type.'); + throw new Error("Must provide schema definition with query type."); } - const astMap: {[name: string]: TypeDefinition} = - keyMap(typeDefs, d => d.name.value); + const astMap: { [name: string]: TypeDefinition } = keyMap( + typeDefs, + d => d.name.value + ); if (!astMap[queryTypeName]) { throw new Error( @@ -198,8 +193,7 @@ export function buildASTSchema(ast: Document): GraphQLSchema { if (subscriptionTypeName && !astMap[subscriptionTypeName]) { throw new Error( - `Specified subscription type "${ - subscriptionTypeName}" not found in document.` + `Specified subscription type "${subscriptionTypeName}" not found in document.` ); } @@ -216,7 +210,7 @@ export function buildASTSchema(ast: Document): GraphQLSchema { __Field, __InputValue, __EnumValue, - __TypeKind, + __TypeKind }; const types = typeDefs.map(def => typeDefNamed(def.name.value)); @@ -226,17 +220,18 @@ export function buildASTSchema(ast: Document): GraphQLSchema { return new GraphQLSchema({ query: getObjectType(astMap[queryTypeName]), mutation: mutationTypeName ? getObjectType(astMap[mutationTypeName]) : null, - subscription: - subscriptionTypeName ? getObjectType(astMap[subscriptionTypeName]) : null, + subscription: subscriptionTypeName + ? getObjectType(astMap[subscriptionTypeName]) + : null, types, - directives, + directives }); function getDirective(directiveAST: DirectiveDefinition): GraphQLDirective { return new GraphQLDirective({ name: directiveAST.name.value, locations: directiveAST.locations.map(node => node.value), - args: makeInputValues(directiveAST.arguments), + args: makeInputValues(directiveAST.arguments) }); } @@ -244,7 +239,7 @@ export function buildASTSchema(ast: Document): GraphQLSchema { const type = typeDefNamed(typeAST.name.value); invariant( type instanceof GraphQLObjectType, - 'AST must provide object type.' + "AST must provide object type." ); return (type: any); } @@ -274,7 +269,7 @@ export function buildASTSchema(ast: Document): GraphQLSchema { function makeSchemaDef(def) { if (!def) { - throw new Error('def must be defined'); + throw new Error("def must be defined"); } switch (def.kind) { case OBJECT_TYPE_DEFINITION: @@ -299,7 +294,7 @@ export function buildASTSchema(ast: Document): GraphQLSchema { const config = { name: typeName, fields: () => makeFieldDefMap(def), - interfaces: () => makeImplementedInterfaces(def), + interfaces: () => makeImplementedInterfaces(def) }; return new GraphQLObjectType(config); } @@ -310,7 +305,7 @@ export function buildASTSchema(ast: Document): GraphQLSchema { field => field.name.value, field => ({ type: produceTypeDef(field.type), - args: makeInputValues(field.arguments), + args: makeInputValues(field.arguments) }) ); } @@ -335,7 +330,7 @@ export function buildASTSchema(ast: Document): GraphQLSchema { const config = { name: typeName, resolveType: () => null, - fields: () => makeFieldDefMap(def), + fields: () => makeFieldDefMap(def) }; return new GraphQLInterfaceType(config); } @@ -343,7 +338,7 @@ export function buildASTSchema(ast: Document): GraphQLSchema { function makeEnumDef(def: EnumTypeDefinition) { const enumType = new GraphQLEnumType({ name: def.name.value, - values: keyValMap(def.values, v => v.name.value, () => ({})), + values: keyValMap(def.values, v => v.name.value, () => ({})) }); return enumType; @@ -353,7 +348,7 @@ export function buildASTSchema(ast: Document): GraphQLSchema { return new GraphQLUnionType({ name: def.name.value, resolveType: () => null, - types: def.types.map(t => produceTypeDef(t)), + types: def.types.map(t => produceTypeDef(t)) }); } @@ -366,14 +361,14 @@ export function buildASTSchema(ast: Document): GraphQLSchema { // scalars to always fail validation. Returning false causes them to // always pass validation. parseValue: () => false, - parseLiteral: () => false, + parseLiteral: () => false }); } function makeInputObjectDef(def: InputObjectTypeDefinition) { return new GraphQLInputObjectType({ name: def.name.value, - fields: () => makeInputValues(def.fields), + fields: () => makeInputValues(def.fields) }); } } diff --git a/src/utilities/buildClientSchema.js b/src/utilities/buildClientSchema.js index 1161f1fea5..4a32a8f34d 100644 --- a/src/utilities/buildClientSchema.js +++ b/src/utilities/buildClientSchema.js @@ -8,12 +8,12 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import invariant from '../jsutils/invariant'; -import keyMap from '../jsutils/keyMap'; -import keyValMap from '../jsutils/keyValMap'; -import { valueFromAST } from './valueFromAST'; -import { parseValue } from '../language/parser'; -import { GraphQLSchema } from '../type/schema'; +import invariant from "../jsutils/invariant"; +import keyMap from "../jsutils/keyMap"; +import keyValMap from "../jsutils/keyValMap"; +import { valueFromAST } from "./valueFromAST"; +import { parseValue } from "../language/parser"; +import { GraphQLSchema } from "../type/schema"; import { isInputType, @@ -25,8 +25,8 @@ import { GraphQLEnumType, GraphQLInputObjectType, GraphQLList, - GraphQLNonNull, -} from '../type/definition'; + GraphQLNonNull +} from "../type/definition"; import { __Schema, @@ -36,8 +36,8 @@ import { __Field, __InputValue, __EnumValue, - __TypeKind, -} from '../type/introspection'; + __TypeKind +} from "../type/introspection"; import { GraphQLInt, @@ -45,18 +45,18 @@ import { GraphQLString, GraphQLBoolean, GraphQLID -} from '../type/scalars'; +} from "../type/scalars"; -import { DirectiveLocation, GraphQLDirective } from '../type/directives'; +import { DirectiveLocation, GraphQLDirective } from "../type/directives"; -import { TypeKind } from '../type/introspection'; +import { TypeKind } from "../type/introspection"; import type { GraphQLType, GraphQLInputType, GraphQLOutputType, - GraphQLNamedType, -} from '../type/definition'; + GraphQLNamedType +} from "../type/definition"; import type { IntrospectionQuery, @@ -69,9 +69,8 @@ import type { IntrospectionInputObjectType, IntrospectionTypeRef, IntrospectionListTypeRef, - IntrospectionNonNullTypeRef, -} from './introspectionQuery'; - + IntrospectionNonNullTypeRef +} from "./introspectionQuery"; /** * Build a GraphQLSchema for use by client tools. @@ -85,7 +84,6 @@ import type { export function buildClientSchema( introspection: IntrospectionQuery ): GraphQLSchema { - // Get the schema from the introspection result. const schemaIntrospection = introspection.__schema; @@ -111,7 +109,7 @@ export function buildClientSchema( __Field, __InputValue, __EnumValue, - __TypeKind, + __TypeKind }; // Given a type reference in introspection, return the GraphQLType instance. @@ -120,19 +118,19 @@ export function buildClientSchema( if (typeRef.kind === TypeKind.LIST) { const itemRef = ((typeRef: any): IntrospectionListTypeRef).ofType; if (!itemRef) { - throw new Error('Decorated type deeper than introspection query.'); + throw new Error("Decorated type deeper than introspection query."); } return new GraphQLList(getType(itemRef)); } if (typeRef.kind === TypeKind.NON_NULL) { const nullableRef = ((typeRef: any): IntrospectionNonNullTypeRef).ofType; if (!nullableRef) { - throw new Error('Decorated type deeper than introspection query.'); + throw new Error("Decorated type deeper than introspection query."); } const nullableType = getType(nullableRef); invariant( !(nullableType instanceof GraphQLNonNull), - 'No nesting nonnull.' + "No nesting nonnull." ); return new GraphQLNonNull(nullableType); } @@ -147,8 +145,8 @@ export function buildClientSchema( if (!typeIntrospection) { throw new Error( `Invalid or incomplete schema, unknown type: ${typeName}. Ensure ` + - 'that a full introspection query is used in order to build a ' + - 'client schema.' + "that a full introspection query is used in order to build a " + + "client schema." ); } const typeDef = buildType(typeIntrospection); @@ -160,7 +158,7 @@ export function buildClientSchema( const type = getType(typeRef); invariant( isInputType(type), - 'Introspection must provide input type for arguments.' + "Introspection must provide input type for arguments." ); return (type: any); } @@ -169,7 +167,7 @@ export function buildClientSchema( const type = getType(typeRef); invariant( isOutputType(type), - 'Introspection must provide output type for fields.' + "Introspection must provide output type for fields." ); return (type: any); } @@ -178,7 +176,7 @@ export function buildClientSchema( const type = getType(typeRef); invariant( type instanceof GraphQLObjectType, - 'Introspection must provide object type for possibleTypes.' + "Introspection must provide object type for possibleTypes." ); return (type: any); } @@ -189,12 +187,11 @@ export function buildClientSchema( const type = getType(typeRef); invariant( type instanceof GraphQLInterfaceType, - 'Introspection must provide interface type for interfaces.' + "Introspection must provide interface type for interfaces." ); return (type: any); } - // Given a type's introspection result, construct the correct // GraphQLType instance. function buildType(type: IntrospectionType): GraphQLNamedType { @@ -214,8 +211,8 @@ export function buildClientSchema( default: throw new Error( `Invalid or incomplete schema, unknown kind: ${type.kind}. Ensure ` + - 'that a full introspection query is used in order to build a ' + - 'client schema.' + "that a full introspection query is used in order to build a " + + "client schema." ); } } @@ -232,7 +229,7 @@ export function buildClientSchema( // scalars to always fail validation. Returning false causes them to // always pass validation. parseValue: () => false, - parseLiteral: () => false, + parseLiteral: () => false }); } @@ -243,7 +240,7 @@ export function buildClientSchema( name: objectIntrospection.name, description: objectIntrospection.description, interfaces: objectIntrospection.interfaces.map(getInterfaceType), - fields: () => buildFieldDefMap(objectIntrospection), + fields: () => buildFieldDefMap(objectIntrospection) }); } @@ -254,7 +251,7 @@ export function buildClientSchema( name: interfaceIntrospection.name, description: interfaceIntrospection.description, fields: () => buildFieldDefMap(interfaceIntrospection), - resolveType: cannotExecuteClientSchema, + resolveType: cannotExecuteClientSchema }); } @@ -265,7 +262,7 @@ export function buildClientSchema( name: unionIntrospection.name, description: unionIntrospection.description, types: unionIntrospection.possibleTypes.map(getObjectType), - resolveType: cannotExecuteClientSchema, + resolveType: cannotExecuteClientSchema }); } @@ -280,7 +277,7 @@ export function buildClientSchema( valueIntrospection => valueIntrospection.name, valueIntrospection => ({ description: valueIntrospection.description, - deprecationReason: valueIntrospection.deprecationReason, + deprecationReason: valueIntrospection.deprecationReason }) ) }); @@ -292,7 +289,7 @@ export function buildClientSchema( return new GraphQLInputObjectType({ name: inputObjectIntrospection.name, description: inputObjectIntrospection.description, - fields: () => buildInputValueDefMap(inputObjectIntrospection.inputFields), + fields: () => buildInputValueDefMap(inputObjectIntrospection.inputFields) }); } @@ -305,7 +302,7 @@ export function buildClientSchema( deprecationReason: fieldIntrospection.deprecationReason, type: getOutputType(fieldIntrospection.type), args: buildInputValueDefMap(fieldIntrospection.args), - resolve: cannotExecuteClientSchema, + resolve: cannotExecuteClientSchema }) ); } @@ -320,67 +317,69 @@ export function buildClientSchema( function buildInputValue(inputValueIntrospection) { const type = getInputType(inputValueIntrospection.type); - const defaultValue = inputValueIntrospection.defaultValue ? - valueFromAST(parseValue(inputValueIntrospection.defaultValue), type) : - null; + const defaultValue = inputValueIntrospection.defaultValue + ? valueFromAST(parseValue(inputValueIntrospection.defaultValue), type) + : null; return { name: inputValueIntrospection.name, description: inputValueIntrospection.description, type, - defaultValue, + defaultValue }; } function buildDirective(directiveIntrospection) { // Support deprecated `on****` fields for building `locations`, as this // is used by GraphiQL which may need to support outdated servers. - const locations = directiveIntrospection.locations ? - directiveIntrospection.locations.slice() : - [].concat( - !directiveIntrospection.onField ? [] : [ - DirectiveLocation.FIELD, - ], - !directiveIntrospection.onOperation ? [] : [ - DirectiveLocation.QUERY, - DirectiveLocation.MUTATION, - DirectiveLocation.SUBSCRIPTION, - ], - !directiveIntrospection.onFragment ? [] : [ - DirectiveLocation.FRAGMENT_DEFINITION, - DirectiveLocation.FRAGMENT_SPREAD, - DirectiveLocation.INLINE_FRAGMENT, - ] - ); + const locations = directiveIntrospection.locations + ? directiveIntrospection.locations.slice() + : [].concat( + !directiveIntrospection.onField ? [] : [DirectiveLocation.FIELD], + !directiveIntrospection.onOperation + ? [] + : [ + DirectiveLocation.QUERY, + DirectiveLocation.MUTATION, + DirectiveLocation.SUBSCRIPTION + ], + !directiveIntrospection.onFragment + ? [] + : [ + DirectiveLocation.FRAGMENT_DEFINITION, + DirectiveLocation.FRAGMENT_SPREAD, + DirectiveLocation.INLINE_FRAGMENT + ] + ); return new GraphQLDirective({ name: directiveIntrospection.name, description: directiveIntrospection.description, locations, - args: buildInputValueDefMap(directiveIntrospection.args), + args: buildInputValueDefMap(directiveIntrospection.args) }); } // Iterate through all types, getting the type definition for each, ensuring // that any type not directly referenced by a field will get created. - const types = schemaIntrospection.types.map( - typeIntrospection => getNamedType(typeIntrospection.name) + const types = schemaIntrospection.types.map(typeIntrospection => + getNamedType(typeIntrospection.name) ); // Get the root Query, Mutation, and Subscription types. const queryType = getObjectType(schemaIntrospection.queryType); - const mutationType = schemaIntrospection.mutationType ? - getObjectType(schemaIntrospection.mutationType) : - null; + const mutationType = schemaIntrospection.mutationType + ? getObjectType(schemaIntrospection.mutationType) + : null; - const subscriptionType = schemaIntrospection.subscriptionType ? - getObjectType(schemaIntrospection.subscriptionType) : - null; + const subscriptionType = schemaIntrospection.subscriptionType + ? getObjectType(schemaIntrospection.subscriptionType) + : null; // Get the directives supported by Introspection, assuming empty-set if // directives were not queried for. - const directives = schemaIntrospection.directives ? - schemaIntrospection.directives.map(buildDirective) : - []; + const directives = schemaIntrospection.directives + ? schemaIntrospection.directives.map(buildDirective) + : []; // Then produce and return a Schema with these types. return new GraphQLSchema({ @@ -388,10 +387,10 @@ export function buildClientSchema( mutation: mutationType, subscription: subscriptionType, types, - directives, + directives }); } function cannotExecuteClientSchema() { - throw new Error('Client Schema cannot be used for execution.'); + throw new Error("Client Schema cannot be used for execution."); } diff --git a/src/utilities/concatAST.js b/src/utilities/concatAST.js index 578761bded..1c137af75a 100644 --- a/src/utilities/concatAST.js +++ b/src/utilities/concatAST.js @@ -8,8 +8,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { Document } from '../language/ast'; - +import type { Document } from "../language/ast"; /** * Provided a collection of ASTs, presumably each from different files, @@ -25,7 +24,7 @@ export function concatAST(asts: Array): Document { } } return { - kind: 'Document', - definitions: batchDefinitions, + kind: "Document", + definitions: batchDefinitions }; } diff --git a/src/utilities/extendSchema.js b/src/utilities/extendSchema.js index 2a7f57a75d..0f77208937 100644 --- a/src/utilities/extendSchema.js +++ b/src/utilities/extendSchema.js @@ -8,12 +8,12 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import invariant from '../jsutils/invariant'; -import keyMap from '../jsutils/keyMap'; -import keyValMap from '../jsutils/keyValMap'; -import { valueFromAST } from './valueFromAST'; -import { GraphQLError } from '../error/GraphQLError'; -import { GraphQLSchema } from '../type/schema'; +import invariant from "../jsutils/invariant"; +import keyMap from "../jsutils/keyMap"; +import keyValMap from "../jsutils/keyValMap"; +import { valueFromAST } from "./valueFromAST"; +import { GraphQLError } from "../error/GraphQLError"; +import { GraphQLSchema } from "../type/schema"; import { GraphQLList, @@ -23,8 +23,8 @@ import { GraphQLUnionType, GraphQLScalarType, GraphQLEnumType, - GraphQLInputObjectType, -} from '../type/definition'; + GraphQLInputObjectType +} from "../type/definition"; import { __Schema, @@ -34,16 +34,16 @@ import { __Field, __InputValue, __EnumValue, - __TypeKind, -} from '../type/introspection'; + __TypeKind +} from "../type/introspection"; import { GraphQLString, GraphQLInt, GraphQLFloat, GraphQLBoolean, - GraphQLID, -} from '../type/scalars'; + GraphQLID +} from "../type/scalars"; import { DOCUMENT, @@ -55,13 +55,10 @@ import { UNION_TYPE_DEFINITION, SCALAR_TYPE_DEFINITION, INPUT_OBJECT_TYPE_DEFINITION, - TYPE_EXTENSION_DEFINITION, -} from '../language/kinds'; + TYPE_EXTENSION_DEFINITION +} from "../language/kinds"; -import type { - GraphQLType, - GraphQLNamedType, -} from '../type/definition'; +import type { GraphQLType, GraphQLNamedType } from "../type/definition"; import type { Document, @@ -74,9 +71,8 @@ import type { UnionTypeDefinition, ScalarTypeDefinition, EnumTypeDefinition, - InputObjectTypeDefinition, -} from '../language/ast'; - + InputObjectTypeDefinition +} from "../language/ast"; /** * Produces a new schema given an existing schema and a document which may @@ -96,12 +92,12 @@ export function extendSchema( ): GraphQLSchema { invariant( schema instanceof GraphQLSchema, - 'Must provide valid GraphQLSchema' + "Must provide valid GraphQLSchema" ); invariant( documentAST && documentAST.kind === DOCUMENT, - 'Must provide valid Document AST' + "Must provide valid Document AST" ); // Collect the type definitions and extensions found in the document. @@ -123,8 +119,8 @@ export function extendSchema( if (schema.getType(typeName)) { throw new GraphQLError( `Type "${typeName}" already exists in the schema. It cannot also ` + - 'be defined in this type definition.', - [ def ] + "be defined in this type definition.", + [def] ); } typeDefinitionMap[typeName] = def; @@ -137,21 +133,21 @@ export function extendSchema( if (!existingType) { throw new GraphQLError( `Cannot extend type "${extendedTypeName}" because it does not ` + - 'exist in the existing schema.', - [ def.definition ] + "exist in the existing schema.", + [def.definition] ); } if (!(existingType instanceof GraphQLObjectType)) { throw new GraphQLError( `Cannot extend non-object type "${extendedTypeName}".`, - [ def.definition ] + [def.definition] ); } let extensions = typeExtensionsMap[extendedTypeName]; if (extensions) { extensions.push(def); } else { - extensions = [ def ]; + extensions = [def]; } typeExtensionsMap[extendedTypeName] = extensions; break; @@ -160,8 +156,10 @@ export function extendSchema( // If this document contains no new types, then return the same unmodified // GraphQLSchema instance. - if (Object.keys(typeExtensionsMap).length === 0 && - Object.keys(typeDefinitionMap).length === 0) { + if ( + Object.keys(typeExtensionsMap).length === 0 && + Object.keys(typeDefinitionMap).length === 0 + ) { return schema; } @@ -182,21 +180,21 @@ export function extendSchema( __Field, __InputValue, __EnumValue, - __TypeKind, + __TypeKind }; // Get the root Query, Mutation, and Subscription types. const queryType = getTypeFromDef(schema.getQueryType()); const existingMutationType = schema.getMutationType(); - const mutationType = existingMutationType ? - getTypeFromDef(existingMutationType) : - null; + const mutationType = existingMutationType + ? getTypeFromDef(existingMutationType) + : null; const existingSubscriptionType = schema.getSubscriptionType(); - const subscriptionType = existingSubscriptionType ? - getTypeFromDef(existingSubscriptionType) : - null; + const subscriptionType = existingSubscriptionType + ? getTypeFromDef(existingSubscriptionType) + : null; // Iterate through all types, getting the type definition for each, ensuring // that any type not directly referenced by a field will get created. @@ -216,7 +214,7 @@ export function extendSchema( subscription: subscriptionType, types, // Copy directives. - directives: schema.getDirectives(), + directives: schema.getDirectives() }); // Below are functions used for producing this schema that have closed over @@ -224,7 +222,7 @@ export function extendSchema( function getTypeFromDef(typeDef: GraphQLNamedType): GraphQLNamedType { const type = _getNamedType(typeDef.name); - invariant(type, 'Invalid schema'); + invariant(type, "Invalid schema"); return type; } @@ -233,8 +231,8 @@ export function extendSchema( if (!type) { throw new GraphQLError( `Unknown type: "${astNode.name.value}". Ensure that this type exists ` + - 'either in the original schema, or is added in a type definition.', - [ astNode ] + "either in the original schema, or is added in a type definition.", + [astNode] ); } return type; @@ -283,7 +281,7 @@ export function extendSchema( name: type.name, description: type.description, interfaces: () => extendImplementedInterfaces(type), - fields: () => extendFieldMap(type), + fields: () => extendFieldMap(type) }); } @@ -294,7 +292,7 @@ export function extendSchema( name: type.name, description: type.description, fields: () => extendFieldMap(type), - resolveType: cannotExecuteClientSchema, + resolveType: cannotExecuteClientSchema }); } @@ -303,7 +301,7 @@ export function extendSchema( name: type.name, description: type.description, types: type.getTypes().map(getTypeFromDef), - resolveType: cannotExecuteClientSchema, + resolveType: cannotExecuteClientSchema }); } @@ -321,8 +319,8 @@ export function extendSchema( if (interfaces.some(def => def.name === interfaceName)) { throw new GraphQLError( `Type "${type.name}" already implements "${interfaceName}". ` + - 'It cannot also be implemented in this type extension.', - [ namedType ] + "It cannot also be implemented in this type extension.", + [namedType] ); } interfaces.push(getTypeFromAST(namedType)); @@ -343,7 +341,7 @@ export function extendSchema( deprecationReason: field.deprecationReason, type: extendFieldType(field.type), args: keyMap(field.args, arg => arg.name), - resolve: cannotExecuteClientSchema, + resolve: cannotExecuteClientSchema }; }); @@ -356,14 +354,14 @@ export function extendSchema( if (oldFieldMap[fieldName]) { throw new GraphQLError( `Field "${type.name}.${fieldName}" already exists in the ` + - 'schema. It cannot also be defined in this type extension.', - [ field ] + "schema. It cannot also be defined in this type extension.", + [field] ); } newFieldMap[fieldName] = { type: buildFieldType(field.type), args: buildInputValues(field.arguments), - resolve: cannotExecuteClientSchema, + resolve: cannotExecuteClientSchema }; }); }); @@ -384,12 +382,18 @@ export function extendSchema( function buildType(typeAST: TypeDefinition): GraphQLType { switch (typeAST.kind) { - case OBJECT_TYPE_DEFINITION: return buildObjectType(typeAST); - case INTERFACE_TYPE_DEFINITION: return buildInterfaceType(typeAST); - case UNION_TYPE_DEFINITION: return buildUnionType(typeAST); - case SCALAR_TYPE_DEFINITION: return buildScalarType(typeAST); - case ENUM_TYPE_DEFINITION: return buildEnumType(typeAST); - case INPUT_OBJECT_TYPE_DEFINITION: return buildInputObjectType(typeAST); + case OBJECT_TYPE_DEFINITION: + return buildObjectType(typeAST); + case INTERFACE_TYPE_DEFINITION: + return buildInterfaceType(typeAST); + case UNION_TYPE_DEFINITION: + return buildUnionType(typeAST); + case SCALAR_TYPE_DEFINITION: + return buildScalarType(typeAST); + case ENUM_TYPE_DEFINITION: + return buildEnumType(typeAST); + case INPUT_OBJECT_TYPE_DEFINITION: + return buildInputObjectType(typeAST); } } @@ -397,7 +401,7 @@ export function extendSchema( return new GraphQLObjectType({ name: typeAST.name.value, interfaces: () => buildImplementedInterfaces(typeAST), - fields: () => buildFieldMap(typeAST), + fields: () => buildFieldMap(typeAST) }); } @@ -405,7 +409,7 @@ export function extendSchema( return new GraphQLInterfaceType({ name: typeAST.name.value, fields: () => buildFieldMap(typeAST), - resolveType: cannotExecuteClientSchema, + resolveType: cannotExecuteClientSchema }); } @@ -413,7 +417,7 @@ export function extendSchema( return new GraphQLUnionType({ name: typeAST.name.value, types: typeAST.types.map(getTypeFromAST), - resolveType: cannotExecuteClientSchema, + resolveType: cannotExecuteClientSchema }); } @@ -426,21 +430,21 @@ export function extendSchema( // scalars to always fail validation. Returning false causes them to // always pass validation. parseValue: () => false, - parseLiteral: () => false, + parseLiteral: () => false }); } function buildEnumType(typeAST: EnumTypeDefinition) { return new GraphQLEnumType({ name: typeAST.name.value, - values: keyValMap(typeAST.values, v => v.name.value, () => ({})), + values: keyValMap(typeAST.values, v => v.name.value, () => ({})) }); } function buildInputObjectType(typeAST: InputObjectTypeDefinition) { return new GraphQLInputObjectType({ name: typeAST.name.value, - fields: () => buildInputValues(typeAST.fields), + fields: () => buildInputValues(typeAST.fields) }); } @@ -455,7 +459,7 @@ export function extendSchema( field => ({ type: buildFieldType(field.type), args: buildInputValues(field.arguments), - resolve: cannotExecuteClientSchema, + resolve: cannotExecuteClientSchema }) ); } @@ -486,5 +490,5 @@ export function extendSchema( } function cannotExecuteClientSchema() { - throw new Error('Client Schema cannot be used for execution.'); + throw new Error("Client Schema cannot be used for execution."); } diff --git a/src/utilities/getOperationAST.js b/src/utilities/getOperationAST.js index c7e38d598f..2aae80ab78 100644 --- a/src/utilities/getOperationAST.js +++ b/src/utilities/getOperationAST.js @@ -8,9 +8,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { OPERATION_DEFINITION } from '../language/kinds'; -import type { Document, OperationDefinition } from '../language/ast'; - +import { OPERATION_DEFINITION } from "../language/kinds"; +import type { Document, OperationDefinition } from "../language/ast"; /** * Returns an operation AST given a document AST and optionally an operation diff --git a/src/utilities/index.js b/src/utilities/index.js index 18129209c7..f2306497dc 100644 --- a/src/utilities/index.js +++ b/src/utilities/index.js @@ -9,51 +9,51 @@ */ // The GraphQL query recommended for a full schema introspection. -export { introspectionQuery } from './introspectionQuery'; +export { introspectionQuery } from "./introspectionQuery"; // Gets the target Operation from a Document -export { getOperationAST } from './getOperationAST'; +export { getOperationAST } from "./getOperationAST"; // Build a GraphQLSchema from an introspection result. -export { buildClientSchema } from './buildClientSchema'; +export { buildClientSchema } from "./buildClientSchema"; // Build a GraphQLSchema from a parsed GraphQL Schema language AST. -export { buildASTSchema } from './buildASTSchema'; +export { buildASTSchema } from "./buildASTSchema"; // Extends an existing GraphQLSchema from a parsed GraphQL Schema language AST. -export { extendSchema } from './extendSchema'; +export { extendSchema } from "./extendSchema"; // Print a GraphQLSchema to GraphQL Schema language. -export { printSchema, printIntrospectionSchema } from './schemaPrinter'; +export { printSchema, printIntrospectionSchema } from "./schemaPrinter"; // Create a GraphQLType from a GraphQL language AST. -export { typeFromAST } from './typeFromAST'; +export { typeFromAST } from "./typeFromAST"; // Create a JavaScript value from a GraphQL language AST. -export { valueFromAST } from './valueFromAST'; +export { valueFromAST } from "./valueFromAST"; // Create a GraphQL language AST from a JavaScript value. -export { astFromValue } from './astFromValue'; +export { astFromValue } from "./astFromValue"; // A helper to use within recursive-descent visitors which need to be aware of // the GraphQL type system. -export { TypeInfo } from './TypeInfo'; +export { TypeInfo } from "./TypeInfo"; // Determine if JavaScript values adhere to a GraphQL type. -export { isValidJSValue } from './isValidJSValue'; +export { isValidJSValue } from "./isValidJSValue"; // Determine if AST values adhere to a GraphQL type. -export { isValidLiteralValue } from './isValidLiteralValue'; +export { isValidLiteralValue } from "./isValidLiteralValue"; // Concatenates multiple AST together. -export { concatAST } from './concatAST'; +export { concatAST } from "./concatAST"; // Comparators for types export { isEqualType, isTypeSubTypeOf, doTypesOverlap -} from './typeComparators'; +} from "./typeComparators"; // Asserts that a string is a valid GraphQL name -export { assertValidName } from './assertValidName'; +export { assertValidName } from "./assertValidName"; diff --git a/src/utilities/introspectionQuery.js b/src/utilities/introspectionQuery.js index 73d548f1b7..303359954e 100644 --- a/src/utilities/introspectionQuery.js +++ b/src/utilities/introspectionQuery.js @@ -8,8 +8,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { DirectiveLocationEnum } from '../type/directives'; - +import type { DirectiveLocationEnum } from "../type/directives"; export const introspectionQuery = ` query IntrospectionQuery { @@ -91,113 +90,113 @@ export const introspectionQuery = ` export type IntrospectionQuery = { __schema: IntrospectionSchema -} +}; export type IntrospectionSchema = { - queryType: IntrospectionNamedTypeRef; - mutationType: ?IntrospectionNamedTypeRef; - subscriptionType: ?IntrospectionNamedTypeRef; - types: Array; - directives: Array; -} + queryType: IntrospectionNamedTypeRef, + mutationType: ?IntrospectionNamedTypeRef, + subscriptionType: ?IntrospectionNamedTypeRef, + types: Array, + directives: Array +}; export type IntrospectionType = - IntrospectionScalarType | - IntrospectionObjectType | - IntrospectionInterfaceType | - IntrospectionUnionType | - IntrospectionEnumType | - IntrospectionInputObjectType + | IntrospectionScalarType + | IntrospectionObjectType + | IntrospectionInterfaceType + | IntrospectionUnionType + | IntrospectionEnumType + | IntrospectionInputObjectType; export type IntrospectionScalarType = { - kind: 'SCALAR'; - name: string; - description: ?string; -} + kind: "SCALAR", + name: string, + description: ?string +}; export type IntrospectionObjectType = { - kind: 'OBJECT'; - name: string; - description: ?string; - fields: Array; - interfaces: Array; -} + kind: "OBJECT", + name: string, + description: ?string, + fields: Array, + interfaces: Array +}; export type IntrospectionInterfaceType = { - kind: 'INTERFACE'; - name: string; - description: ?string; - fields: Array; - possibleTypes: Array; -} + kind: "INTERFACE", + name: string, + description: ?string, + fields: Array, + possibleTypes: Array +}; export type IntrospectionUnionType = { - kind: 'UNION'; - name: string; - description: ?string; - possibleTypes: Array; -} + kind: "UNION", + name: string, + description: ?string, + possibleTypes: Array +}; export type IntrospectionEnumType = { - kind: 'ENUM'; - name: string; - description: ?string; - enumValues: Array; -} + kind: "ENUM", + name: string, + description: ?string, + enumValues: Array +}; export type IntrospectionInputObjectType = { - kind: 'INPUT_OBJECT'; - name: string; - description: ?string; - inputFields: Array; -} + kind: "INPUT_OBJECT", + name: string, + description: ?string, + inputFields: Array +}; export type IntrospectionTypeRef = - IntrospectionNamedTypeRef | - IntrospectionListTypeRef | - IntrospectionNonNullTypeRef + | IntrospectionNamedTypeRef + | IntrospectionListTypeRef + | IntrospectionNonNullTypeRef; export type IntrospectionNamedTypeRef = { - kind: string; - name: string; -} + kind: string, + name: string +}; export type IntrospectionListTypeRef = { - kind: 'LIST'; - ofType?: IntrospectionTypeRef; -} + kind: "LIST", + ofType?: IntrospectionTypeRef +}; export type IntrospectionNonNullTypeRef = { - kind: 'NON_NULL'; - ofType?: IntrospectionTypeRef; -} + kind: "NON_NULL", + ofType?: IntrospectionTypeRef +}; export type IntrospectionField = { - name: string; - description: ?string; - args: Array; - type: IntrospectionTypeRef; - isDeprecated: boolean; - deprecationReason: ?string; -} + name: string, + description: ?string, + args: Array, + type: IntrospectionTypeRef, + isDeprecated: boolean, + deprecationReason: ?string +}; export type IntrospectionInputValue = { - name: string; - description: ?string; - type: IntrospectionTypeRef; - defaultValue: ?string; -} + name: string, + description: ?string, + type: IntrospectionTypeRef, + defaultValue: ?string +}; export type IntrospectionEnumValue = { - name: string; - description: ?string; - isDeprecated: boolean; - deprecationReason: ?string; -} + name: string, + description: ?string, + isDeprecated: boolean, + deprecationReason: ?string +}; export type IntrospectionDirective = { - name: string; - description: ?string; - locations: Array; - args: Array; -} + name: string, + description: ?string, + locations: Array, + args: Array +}; diff --git a/src/utilities/isValidJSValue.js b/src/utilities/isValidJSValue.js index 7c04f5d5d8..c4cd78518f 100644 --- a/src/utilities/isValidJSValue.js +++ b/src/utilities/isValidJSValue.js @@ -8,17 +8,16 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import invariant from '../jsutils/invariant'; -import isNullish from '../jsutils/isNullish'; +import invariant from "../jsutils/invariant"; +import isNullish from "../jsutils/isNullish"; import { GraphQLScalarType, GraphQLEnumType, GraphQLInputObjectType, GraphQLList, - GraphQLNonNull, -} from '../type/definition'; -import type { GraphQLInputType } from '../type/definition'; - + GraphQLNonNull +} from "../type/definition"; +import type { GraphQLInputType } from "../type/definition"; /** * Given a JavaScript value and a GraphQL type, determine if the value will be @@ -30,9 +29,9 @@ export function isValidJSValue(value: mixed, type: GraphQLInputType): [string] { if (type instanceof GraphQLNonNull) { if (isNullish(value)) { if (type.ofType.name) { - return [ `Expected "${type.ofType.name}!", found null.` ]; + return [`Expected "${type.ofType.name}!", found null.`]; } - return [ 'Expected non-null value, found null.' ]; + return ["Expected non-null value, found null."]; } return isValidJSValue(value, type.ofType); } @@ -47,9 +46,9 @@ export function isValidJSValue(value: mixed, type: GraphQLInputType): [string] { if (Array.isArray(value)) { return value.reduce((acc, item, index) => { const errors = isValidJSValue(item, itemType); - return acc.concat(errors.map(error => - `In element #${index}: ${error}` - )); + return acc.concat( + errors.map(error => `In element #${index}: ${error}`) + ); }, []); } return isValidJSValue(value, itemType); @@ -57,8 +56,8 @@ export function isValidJSValue(value: mixed, type: GraphQLInputType): [string] { // Input objects check each defined field. if (type instanceof GraphQLInputObjectType) { - if (typeof value !== 'object' || value === null) { - return [ `Expected "${type.name}", found not an object.` ]; + if (typeof value !== "object" || value === null) { + return [`Expected "${type.name}", found not an object.`]; } const fields = type.getFields(); @@ -73,27 +72,27 @@ export function isValidJSValue(value: mixed, type: GraphQLInputType): [string] { // Ensure every defined field is valid. for (const fieldName of Object.keys(fields)) { - const newErrors = - isValidJSValue(value[fieldName], fields[fieldName].type); - errors.push(...(newErrors.map(error => - `In field "${fieldName}": ${error}` - ))); + const newErrors = isValidJSValue( + value[fieldName], + fields[fieldName].type + ); + errors.push( + ...newErrors.map(error => `In field "${fieldName}": ${error}`) + ); } return errors; } invariant( type instanceof GraphQLScalarType || type instanceof GraphQLEnumType, - 'Must be input type' + "Must be input type" ); // Scalar/Enum input checks to ensure the type can parse the value to // a non-null value. const parseResult = type.parseValue(value); if (isNullish(parseResult)) { - return [ - `Expected type "${type.name}", found ${JSON.stringify(value)}.` - ]; + return [`Expected type "${type.name}", found ${JSON.stringify(value)}.`]; } return []; diff --git a/src/utilities/isValidLiteralValue.js b/src/utilities/isValidLiteralValue.js index ea6e2397c0..05ec24f725 100644 --- a/src/utilities/isValidLiteralValue.js +++ b/src/utilities/isValidLiteralValue.js @@ -8,25 +8,20 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { print } from '../language/printer'; -import type { Value, ListValue, ObjectValue } from '../language/ast'; -import { - VARIABLE, - LIST, - OBJECT -} from '../language/kinds'; +import { print } from "../language/printer"; +import type { Value, ListValue, ObjectValue } from "../language/ast"; +import { VARIABLE, LIST, OBJECT } from "../language/kinds"; import { GraphQLScalarType, GraphQLEnumType, GraphQLInputObjectType, GraphQLList, GraphQLNonNull -} from '../type/definition'; -import type { GraphQLInputType } from '../type/definition'; -import invariant from '../jsutils/invariant'; -import keyMap from '../jsutils/keyMap'; -import isNullish from '../jsutils/isNullish'; - +} from "../type/definition"; +import type { GraphQLInputType } from "../type/definition"; +import invariant from "../jsutils/invariant"; +import keyMap from "../jsutils/keyMap"; +import isNullish from "../jsutils/isNullish"; /** * Utility for validators which determines if a value literal AST is valid given @@ -38,14 +33,14 @@ import isNullish from '../jsutils/isNullish'; export function isValidLiteralValue( type: GraphQLInputType, valueAST: Value -): [ string ] { +): [string] { // A value must be provided if the type is non-null. if (type instanceof GraphQLNonNull) { if (!valueAST) { if (type.ofType.name) { - return [ `Expected "${type.ofType.name}!", found null.` ]; + return [`Expected "${type.ofType.name}!", found null.`]; } - return [ 'Expected non-null value, found null.' ]; + return ["Expected non-null value, found null."]; } return isValidLiteralValue(type.ofType, valueAST); } @@ -66,9 +61,9 @@ export function isValidLiteralValue( if (valueAST.kind === LIST) { return (valueAST: ListValue).values.reduce((acc, itemAST, index) => { const errors = isValidLiteralValue(itemType, itemAST); - return acc.concat(errors.map(error => - `In element #${index}: ${error}` - )); + return acc.concat( + errors.map(error => `In element #${index}: ${error}`) + ); }, []); } return isValidLiteralValue(itemType, valueAST); @@ -77,7 +72,7 @@ export function isValidLiteralValue( // Input objects check each defined field and look for undefined fields. if (type instanceof GraphQLInputObjectType) { if (valueAST.kind !== OBJECT) { - return [ `Expected "${type.name}", found not an object.` ]; + return [`Expected "${type.name}", found not an object.`]; } const fields = type.getFields(); @@ -100,9 +95,7 @@ export function isValidLiteralValue( fields[fieldName].type, fieldASTMap[fieldName] && fieldASTMap[fieldName].value ); - errors.push(...(result.map(error => - `In field "${fieldName}": ${error}` - ))); + errors.push(...result.map(error => `In field "${fieldName}": ${error}`)); } return errors; @@ -110,14 +103,14 @@ export function isValidLiteralValue( invariant( type instanceof GraphQLScalarType || type instanceof GraphQLEnumType, - 'Must be input type' + "Must be input type" ); // Scalar/Enum input checks to ensure the type can parse the value to // a non-null value. const parseResult = type.parseLiteral(valueAST); if (isNullish(parseResult)) { - return [ `Expected type "${type.name}", found ${print(valueAST)}.` ]; + return [`Expected type "${type.name}", found ${print(valueAST)}.`]; } return []; diff --git a/src/utilities/schemaPrinter.js b/src/utilities/schemaPrinter.js index f977f9e4a8..5fa8a10138 100644 --- a/src/utilities/schemaPrinter.js +++ b/src/utilities/schemaPrinter.js @@ -8,21 +8,20 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import invariant from '../jsutils/invariant'; -import isNullish from '../jsutils/isNullish'; -import { astFromValue } from '../utilities/astFromValue'; -import { print } from '../language/printer'; -import type { GraphQLSchema } from '../type/schema'; -import type { GraphQLType } from '../type/definition'; +import invariant from "../jsutils/invariant"; +import isNullish from "../jsutils/isNullish"; +import { astFromValue } from "../utilities/astFromValue"; +import { print } from "../language/printer"; +import type { GraphQLSchema } from "../type/schema"; +import type { GraphQLType } from "../type/definition"; import { GraphQLScalarType, GraphQLObjectType, GraphQLInterfaceType, GraphQLUnionType, GraphQLEnumType, - GraphQLInputObjectType, -} from '../type/definition'; - + GraphQLInputObjectType +} from "../type/definition"; export function printSchema(schema: GraphQLSchema): string { return printFilteredSchema(schema, n => !isSpecDirective(n), isDefinedType); @@ -33,7 +32,7 @@ export function printIntrospectionSchema(schema: GraphQLSchema): string { } function isSpecDirective(directiveName: string): boolean { - return directiveName === 'skip' || directiveName === 'include'; + return directiveName === "skip" || directiveName === "include"; } function isDefinedType(typename: string): boolean { @@ -41,16 +40,16 @@ function isDefinedType(typename: string): boolean { } function isIntrospectionType(typename: string): boolean { - return typename.indexOf('__') === 0; + return typename.indexOf("__") === 0; } function isBuiltInScalar(typename: string): boolean { return ( - typename === 'String' || - typename === 'Boolean' || - typename === 'Int' || - typename === 'Float' || - typename === 'ID' + typename === "String" || + typename === "Boolean" || + typename === "Int" || + typename === "Float" || + typename === "ID" ); } @@ -59,17 +58,19 @@ function printFilteredSchema( directiveFilter: (type: string) => boolean, typeFilter: (type: string) => boolean ): string { - const directives = schema.getDirectives() + const directives = schema + .getDirectives() .filter(directive => directiveFilter(directive.name)); const typeMap = schema.getTypeMap(); const types = Object.keys(typeMap) .filter(typeFilter) .sort((name1, name2) => name1.localeCompare(name2)) .map(typeName => typeMap[typeName]); - return [ printSchemaDefinition(schema) ].concat( - directives.map(printDirective), - types.map(printType) - ).join('\n\n') + '\n'; + return ( + [printSchemaDefinition(schema)] + .concat(directives.map(printDirective), types.map(printType)) + .join("\n\n") + "\n" + ); } function printSchemaDefinition(schema: GraphQLSchema): string { @@ -90,7 +91,7 @@ function printSchemaDefinition(schema: GraphQLSchema): string { operationTypes.push(` subscription: ${subscriptionType}`); } - return `schema {\n${operationTypes.join('\n')}\n}`; + return `schema {\n${operationTypes.join("\n")}\n}`; } function printType(type: GraphQLType): string { @@ -115,51 +116,57 @@ function printScalar(type: GraphQLScalarType): string { function printObject(type: GraphQLObjectType): string { const interfaces = type.getInterfaces(); - const implementedInterfaces = interfaces.length ? - ' implements ' + interfaces.map(i => i.name).join(', ') : ''; - return `type ${type.name}${implementedInterfaces} {\n` + - printFields(type) + '\n' + - '}'; + const implementedInterfaces = interfaces.length + ? " implements " + interfaces.map(i => i.name).join(", ") + : ""; + return ( + `type ${type.name}${implementedInterfaces} {\n` + + printFields(type) + + "\n" + + "}" + ); } function printInterface(type: GraphQLInterfaceType): string { - return `interface ${type.name} {\n` + - printFields(type) + '\n' + - '}'; + return `interface ${type.name} {\n` + printFields(type) + "\n" + "}"; } function printUnion(type: GraphQLUnionType): string { - return `union ${type.name} = ${type.getTypes().join(' | ')}`; + return `union ${type.name} = ${type.getTypes().join(" | ")}`; } function printEnum(type: GraphQLEnumType): string { const values = type.getValues(); - return `enum ${type.name} {\n` + - values.map(v => ' ' + v.name).join('\n') + '\n' + - '}'; + return ( + `enum ${type.name} {\n` + + values.map(v => " " + v.name).join("\n") + + "\n" + + "}" + ); } function printInputObject(type: GraphQLInputObjectType): string { const fieldMap = type.getFields(); const fields = Object.keys(fieldMap).map(fieldName => fieldMap[fieldName]); - return `input ${type.name} {\n` + - fields.map(f => ' ' + printInputValue(f)).join('\n') + '\n' + - '}'; + return ( + `input ${type.name} {\n` + + fields.map(f => " " + printInputValue(f)).join("\n") + + "\n" + + "}" + ); } function printFields(type) { const fieldMap = type.getFields(); const fields = Object.keys(fieldMap).map(fieldName => fieldMap[fieldName]); - return fields.map( - f => ` ${f.name}${printArgs(f)}: ${f.type}` - ).join('\n'); + return fields.map(f => ` ${f.name}${printArgs(f)}: ${f.type}`).join("\n"); } function printArgs(fieldOrDirectives) { if (fieldOrDirectives.args.length === 0) { - return ''; + return ""; } - return '(' + fieldOrDirectives.args.map(printInputValue).join(', ') + ')'; + return "(" + fieldOrDirectives.args.map(printInputValue).join(", ") + ")"; } function printInputValue(arg) { @@ -171,6 +178,11 @@ function printInputValue(arg) { } function printDirective(directive) { - return 'directive @' + directive.name + printArgs(directive) + - ' on ' + directive.locations.join(' | '); + return ( + "directive @" + + directive.name + + printArgs(directive) + + " on " + + directive.locations.join(" | ") + ); } diff --git a/src/utilities/typeComparators.js b/src/utilities/typeComparators.js index bfd563ab57..69ed3e8367 100644 --- a/src/utilities/typeComparators.js +++ b/src/utilities/typeComparators.js @@ -14,17 +14,14 @@ import { GraphQLInterfaceType, GraphQLUnionType, GraphQLList, - GraphQLNonNull, -} from '../type/definition'; + GraphQLNonNull +} from "../type/definition"; import type { GraphQLType, GraphQLCompositeType, GraphQLAbstractType -} from '../type/definition'; -import type { - GraphQLSchema -} from '../type/schema'; - +} from "../type/definition"; +import type { GraphQLSchema } from "../type/schema"; /** * Provided two types, return true if the types are equal (invariant). @@ -87,12 +84,11 @@ export function isTypeSubTypeOf( // If superType type is an abstract type, maybeSubType type may be a currently // possible object type. - if (isAbstractType(superType) && - maybeSubType instanceof GraphQLObjectType && - schema.isPossibleType( - ((superType: any): GraphQLAbstractType), - maybeSubType - )) { + if ( + isAbstractType(superType) && + maybeSubType instanceof GraphQLObjectType && + schema.isPossibleType(((superType: any): GraphQLAbstractType), maybeSubType) + ) { return true; } @@ -122,22 +118,28 @@ export function doTypesOverlap( return true; } - if (typeA instanceof GraphQLInterfaceType || - typeA instanceof GraphQLUnionType) { - if (_typeB instanceof GraphQLInterfaceType || - _typeB instanceof GraphQLUnionType) { + if ( + typeA instanceof GraphQLInterfaceType || + typeA instanceof GraphQLUnionType + ) { + if ( + _typeB instanceof GraphQLInterfaceType || + _typeB instanceof GraphQLUnionType + ) { // If both types are abstract, then determine if there is any intersection // between possible concrete types of each. - return schema.getPossibleTypes(typeA).some( - type => schema.isPossibleType(_typeB, type) - ); + return schema + .getPossibleTypes(typeA) + .some(type => schema.isPossibleType(_typeB, type)); } // Determine if the latter type is a possible concrete type of the former. return schema.isPossibleType(typeA, _typeB); } - if (_typeB instanceof GraphQLInterfaceType || - _typeB instanceof GraphQLUnionType) { + if ( + _typeB instanceof GraphQLInterfaceType || + _typeB instanceof GraphQLUnionType + ) { // Determine if the former type is a possible concrete type of the latter. return schema.isPossibleType(_typeB, typeA); } diff --git a/src/utilities/typeFromAST.js b/src/utilities/typeFromAST.js index 768a37760c..1d0e083ae2 100644 --- a/src/utilities/typeFromAST.js +++ b/src/utilities/typeFromAST.js @@ -8,13 +8,12 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import invariant from '../jsutils/invariant'; -import { NAMED_TYPE, LIST_TYPE, NON_NULL_TYPE } from '../language/kinds'; -import type { Type } from '../language/ast'; -import { GraphQLList, GraphQLNonNull } from '../type/definition'; -import type { GraphQLType, GraphQLNullableType } from '../type/definition'; -import type { GraphQLSchema } from '../type/schema'; - +import invariant from "../jsutils/invariant"; +import { NAMED_TYPE, LIST_TYPE, NON_NULL_TYPE } from "../language/kinds"; +import type { Type } from "../language/ast"; +import { GraphQLList, GraphQLNonNull } from "../type/definition"; +import type { GraphQLType, GraphQLNullableType } from "../type/definition"; +import type { GraphQLSchema } from "../type/schema"; export function typeFromAST( schema: GraphQLSchema, @@ -27,10 +26,10 @@ export function typeFromAST( } if (inputTypeAST.kind === NON_NULL_TYPE) { innerType = typeFromAST(schema, inputTypeAST.type); - return innerType && new GraphQLNonNull( - ((innerType: any): GraphQLNullableType) + return ( + innerType && new GraphQLNonNull(((innerType: any): GraphQLNullableType)) ); } - invariant(inputTypeAST.kind === NAMED_TYPE, 'Must be a named type.'); + invariant(inputTypeAST.kind === NAMED_TYPE, "Must be a named type."); return schema.getType(inputTypeAST.name.value); } diff --git a/src/utilities/valueFromAST.js b/src/utilities/valueFromAST.js index 6e43407299..e8ba26b0d0 100644 --- a/src/utilities/valueFromAST.js +++ b/src/utilities/valueFromAST.js @@ -8,25 +8,19 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import keyMap from '../jsutils/keyMap'; -import invariant from '../jsutils/invariant'; -import isNullish from '../jsutils/isNullish'; -import * as Kind from '../language/kinds'; +import keyMap from "../jsutils/keyMap"; +import invariant from "../jsutils/invariant"; +import isNullish from "../jsutils/isNullish"; +import * as Kind from "../language/kinds"; import { GraphQLScalarType, GraphQLEnumType, GraphQLInputObjectType, GraphQLList, - GraphQLNonNull, -} from '../type/definition'; -import type { GraphQLInputType } from '../type/definition'; -import type { - Value, - Variable, - ListValue, - ObjectValue -} from '../language/ast'; - + GraphQLNonNull +} from "../type/definition"; +import type { GraphQLInputType } from "../type/definition"; +import type { Value, Variable, ListValue, ObjectValue } from "../language/ast"; /** * Produces a JavaScript value given a GraphQL Value AST. @@ -73,11 +67,11 @@ export function valueFromAST( if (type instanceof GraphQLList) { const itemType = type.ofType; if (valueAST.kind === Kind.LIST) { - return (valueAST: ListValue).values.map( - itemAST => valueFromAST(itemAST, itemType, variables) + return (valueAST: ListValue).values.map(itemAST => + valueFromAST(itemAST, itemType, variables) ); } - return [ valueFromAST(valueAST, itemType, variables) ]; + return [valueFromAST(valueAST, itemType, variables)]; } if (type instanceof GraphQLInputObjectType) { @@ -92,8 +86,11 @@ export function valueFromAST( return Object.keys(fields).reduce((obj, fieldName) => { const field = fields[fieldName]; const fieldAST = fieldASTs[fieldName]; - let fieldValue = - valueFromAST(fieldAST && fieldAST.value, field.type, variables); + let fieldValue = valueFromAST( + fieldAST && fieldAST.value, + field.type, + variables + ); if (isNullish(fieldValue)) { fieldValue = field.defaultValue; } @@ -106,7 +103,7 @@ export function valueFromAST( invariant( type instanceof GraphQLScalarType || type instanceof GraphQLEnumType, - 'Must be input type' + "Must be input type" ); const parsed = type.parseLiteral(valueAST); diff --git a/src/validation/README.md b/src/validation/README.md index ad4a486c58..4bf712b4c7 100644 --- a/src/validation/README.md +++ b/src/validation/README.md @@ -1,10 +1,9 @@ -GraphQL Validation ------------------- +## GraphQL Validation The `graphql/validation` module fulfills the Validation phase of fulfilling a GraphQL result. ```js -import { validate } from 'graphql/validation'; // ES6 -var GraphQLValidator = require('graphql/validation'); // CommonJS +import { validate } from "graphql/validation"; // ES6 +var GraphQLValidator = require("graphql/validation"); // CommonJS ``` diff --git a/src/validation/__tests__/ArgumentsOfCorrectType-test.js b/src/validation/__tests__/ArgumentsOfCorrectType-test.js index 036dc8d921..e0f523615b 100644 --- a/src/validation/__tests__/ArgumentsOfCorrectType-test.js +++ b/src/validation/__tests__/ArgumentsOfCorrectType-test.js @@ -7,692 +7,792 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { ArgumentsOfCorrectType, badValueMessage -} from '../rules/ArgumentsOfCorrectType'; - +} from "../rules/ArgumentsOfCorrectType"; function badValue(argName, typeName, value, line, column, errors) { let realErrors; if (!errors) { - realErrors = [ - `Expected type "${typeName}", found ${value}.` - ]; + realErrors = [`Expected type "${typeName}", found ${value}.`]; } else { realErrors = errors; } return { message: badValueMessage(argName, typeName, value, realErrors), - locations: [ { line, column } ], + locations: [{ line, column }] }; } - -describe('Validate: Argument values of correct type', () => { - - describe('Valid values', () => { - - it('Good int value', () => { - expectPassesRule(ArgumentsOfCorrectType, ` +describe("Validate: Argument values of correct type", () => { + describe("Valid values", () => { + it("Good int value", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { intArgField(intArg: 2) } } - `); + ` + ); }); - it('Good boolean value', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Good boolean value", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { booleanArgField(booleanArg: true) } } - `); + ` + ); }); - it('Good string value', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Good string value", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { stringArgField(stringArg: "foo") } } - `); + ` + ); }); - it('Good float value', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Good float value", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { floatArgField(floatArg: 1.1) } } - `); + ` + ); }); - it('Int into Float', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Int into Float", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { floatArgField(floatArg: 1) } } - `); + ` + ); }); - it('Int into ID', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Int into ID", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { idArgField(idArg: 1) } } - `); + ` + ); }); - it('String into ID', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("String into ID", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { idArgField(idArg: "someIdString") } } - `); + ` + ); }); - it('Good enum value', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Good enum value", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { dog { doesKnowCommand(dogCommand: SIT) } } - `); + ` + ); }); - }); - - describe('Invalid String values', () => { - - it('Int into String', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + describe("Invalid String values", () => { + it("Int into String", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { stringArgField(stringArg: 1) } } - `, [ - badValue('stringArg', 'String', '1', 4, 39) - ]); + `, + [badValue("stringArg", "String", "1", 4, 39)] + ); }); - it('Float into String', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Float into String", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { stringArgField(stringArg: 1.0) } } - `, [ - badValue('stringArg', 'String', '1.0', 4, 39) - ]); + `, + [badValue("stringArg", "String", "1.0", 4, 39)] + ); }); - it('Boolean into String', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Boolean into String", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { stringArgField(stringArg: true) } } - `, [ - badValue('stringArg', 'String', 'true', 4, 39) - ]); + `, + [badValue("stringArg", "String", "true", 4, 39)] + ); }); - it('Unquoted String into String', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Unquoted String into String", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { stringArgField(stringArg: BAR) } } - `, [ - badValue('stringArg', 'String', 'BAR', 4, 39) - ]); + `, + [badValue("stringArg", "String", "BAR", 4, 39)] + ); }); - }); - - describe('Invalid Int values', () => { - - it('String into Int', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + describe("Invalid Int values", () => { + it("String into Int", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { intArgField(intArg: "3") } } - `, [ - badValue('intArg', 'Int', '"3"', 4, 33) - ]); + `, + [badValue("intArg", "Int", '"3"', 4, 33)] + ); }); - it('Big Int into Int', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Big Int into Int", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { intArgField(intArg: 829384293849283498239482938) } } - `, [ - badValue('intArg', 'Int', '829384293849283498239482938', 4, 33) - ]); + `, + [badValue("intArg", "Int", "829384293849283498239482938", 4, 33)] + ); }); - it('Unquoted String into Int', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Unquoted String into Int", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { intArgField(intArg: FOO) } } - `, [ - badValue('intArg', 'Int', 'FOO', 4, 33) - ]); + `, + [badValue("intArg", "Int", "FOO", 4, 33)] + ); }); - it('Simple Float into Int', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Simple Float into Int", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { intArgField(intArg: 3.0) } } - `, [ - badValue('intArg', 'Int', '3.0', 4, 33) - ]); + `, + [badValue("intArg", "Int", "3.0", 4, 33)] + ); }); - it('Float into Int', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Float into Int", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { intArgField(intArg: 3.333) } } - `, [ - badValue('intArg', 'Int', '3.333', 4, 33) - ]); + `, + [badValue("intArg", "Int", "3.333", 4, 33)] + ); }); - }); - - describe('Invalid Float values', () => { - - it('String into Float', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + describe("Invalid Float values", () => { + it("String into Float", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { floatArgField(floatArg: "3.333") } } - `, [ - badValue('floatArg', 'Float', '"3.333"', 4, 37) - ]); + `, + [badValue("floatArg", "Float", '"3.333"', 4, 37)] + ); }); - it('Boolean into Float', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Boolean into Float", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { floatArgField(floatArg: true) } } - `, [ - badValue('floatArg', 'Float', 'true', 4, 37) - ]); + `, + [badValue("floatArg", "Float", "true", 4, 37)] + ); }); - it('Unquoted into Float', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Unquoted into Float", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { floatArgField(floatArg: FOO) } } - `, [ - badValue('floatArg', 'Float', 'FOO', 4, 37) - ]); + `, + [badValue("floatArg", "Float", "FOO", 4, 37)] + ); }); - }); - - describe('Invalid Boolean value', () => { - - it('Int into Boolean', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + describe("Invalid Boolean value", () => { + it("Int into Boolean", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { booleanArgField(booleanArg: 2) } } - `, [ - badValue('booleanArg', 'Boolean', '2', 4, 41) - ]); + `, + [badValue("booleanArg", "Boolean", "2", 4, 41)] + ); }); - it('Float into Boolean', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Float into Boolean", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { booleanArgField(booleanArg: 1.0) } } - `, [ - badValue('booleanArg', 'Boolean', '1.0', 4, 41) - ]); + `, + [badValue("booleanArg", "Boolean", "1.0", 4, 41)] + ); }); - it('String into Boolean', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("String into Boolean", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { booleanArgField(booleanArg: "true") } } - `, [ - badValue('booleanArg', 'Boolean', '"true"', 4, 41) - ]); + `, + [badValue("booleanArg", "Boolean", '"true"', 4, 41)] + ); }); - it('Unquoted into Boolean', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Unquoted into Boolean", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { booleanArgField(booleanArg: TRUE) } } - `, [ - badValue('booleanArg', 'Boolean', 'TRUE', 4, 41) - ]); + `, + [badValue("booleanArg", "Boolean", "TRUE", 4, 41)] + ); }); - }); - - describe('Invalid ID value', () => { - - it('Float into ID', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + describe("Invalid ID value", () => { + it("Float into ID", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { idArgField(idArg: 1.0) } } - `, [ - badValue('idArg', 'ID', '1.0', 4, 31) - ]); + `, + [badValue("idArg", "ID", "1.0", 4, 31)] + ); }); - it('Boolean into ID', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Boolean into ID", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { idArgField(idArg: true) } } - `, [ - badValue('idArg', 'ID', 'true', 4, 31) - ]); + `, + [badValue("idArg", "ID", "true", 4, 31)] + ); }); - it('Unquoted into ID', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Unquoted into ID", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { idArgField(idArg: SOMETHING) } } - `, [ - badValue('idArg', 'ID', 'SOMETHING', 4, 31) - ]); + `, + [badValue("idArg", "ID", "SOMETHING", 4, 31)] + ); }); - }); - - describe('Invalid Enum value', () => { - - it('Int into Enum', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + describe("Invalid Enum value", () => { + it("Int into Enum", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { dog { doesKnowCommand(dogCommand: 2) } } - `, [ - badValue('dogCommand', 'DogCommand', '2', 4, 41) - ]); + `, + [badValue("dogCommand", "DogCommand", "2", 4, 41)] + ); }); - it('Float into Enum', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Float into Enum", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { dog { doesKnowCommand(dogCommand: 1.0) } } - `, [ - badValue('dogCommand', 'DogCommand', '1.0', 4, 41) - ]); + `, + [badValue("dogCommand", "DogCommand", "1.0", 4, 41)] + ); }); - it('String into Enum', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("String into Enum", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { dog { doesKnowCommand(dogCommand: "SIT") } } - `, [ - badValue('dogCommand', 'DogCommand', '"SIT"', 4, 41) - ]); + `, + [badValue("dogCommand", "DogCommand", '"SIT"', 4, 41)] + ); }); - it('Boolean into Enum', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Boolean into Enum", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { dog { doesKnowCommand(dogCommand: true) } } - `, [ - badValue('dogCommand', 'DogCommand', 'true', 4, 41) - ]); + `, + [badValue("dogCommand", "DogCommand", "true", 4, 41)] + ); }); - it('Unknown Enum Value into Enum', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Unknown Enum Value into Enum", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { dog { doesKnowCommand(dogCommand: JUGGLE) } } - `, [ - badValue('dogCommand', 'DogCommand', 'JUGGLE', 4, 41) - ]); + `, + [badValue("dogCommand", "DogCommand", "JUGGLE", 4, 41)] + ); }); - it('Different case Enum Value into Enum', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Different case Enum Value into Enum", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { dog { doesKnowCommand(dogCommand: sit) } } - `, [ - badValue('dogCommand', 'DogCommand', 'sit', 4, 41) - ]); + `, + [badValue("dogCommand", "DogCommand", "sit", 4, 41)] + ); }); - }); - - describe('Valid List value', () => { - - it('Good list value', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + describe("Valid List value", () => { + it("Good list value", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { stringListArgField(stringListArg: ["one", "two"]) } } - `); + ` + ); }); - it('Empty list value', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Empty list value", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { stringListArgField(stringListArg: []) } } - `); + ` + ); }); - it('Single value into List', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Single value into List", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { stringListArgField(stringListArg: "one") } } - `); + ` + ); }); - }); - - describe('Invalid List value', () => { - - it('Incorrect item type', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + describe("Invalid List value", () => { + it("Incorrect item type", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { stringListArgField(stringListArg: ["one", 2]) } } - `, [ - badValue('stringListArg', '[String]', '["one", 2]', 4, 47, [ - 'In element #1: Expected type "String", found 2.' - ]), - ]); + `, + [ + badValue("stringListArg", "[String]", '["one", 2]', 4, 47, [ + 'In element #1: Expected type "String", found 2.' + ]) + ] + ); }); - it('Single value of incorrect type', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Single value of incorrect type", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { stringListArgField(stringListArg: 1) } } - `, [ - badValue('stringListArg', 'String', '1', 4, 47), - ]); + `, + [badValue("stringListArg", "String", "1", 4, 47)] + ); }); - }); - - describe('Valid non-nullable value', () => { - - it('Arg on optional arg', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + describe("Valid non-nullable value", () => { + it("Arg on optional arg", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { dog { isHousetrained(atOtherHomes: true) } } - `); + ` + ); }); - it('No Arg on optional arg', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("No Arg on optional arg", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { dog { isHousetrained } } - `); + ` + ); }); - it('Multiple args', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Multiple args", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { multipleReqs(req1: 1, req2: 2) } } - `); + ` + ); }); - it('Multiple args reverse order', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Multiple args reverse order", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { multipleReqs(req2: 2, req1: 1) } } - `); + ` + ); }); - it('No args on multiple optional', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("No args on multiple optional", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { multipleOpts } } - `); + ` + ); }); - it('One arg on multiple optional', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("One arg on multiple optional", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { multipleOpts(opt1: 1) } } - `); + ` + ); }); - it('Second arg on multiple optional', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Second arg on multiple optional", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { multipleOpts(opt2: 1) } } - `); + ` + ); }); - it('Multiple reqs on mixedList', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Multiple reqs on mixedList", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4) } } - `); + ` + ); }); - it('Multiple reqs and one opt on mixedList', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Multiple reqs and one opt on mixedList", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4, opt1: 5) } } - `); + ` + ); }); - it('All reqs and opts on mixedList', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("All reqs and opts on mixedList", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4, opt1: 5, opt2: 6) } } - `); + ` + ); }); - }); - - describe('Invalid non-nullable value', () => { - - it('Incorrect value type', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + describe("Invalid non-nullable value", () => { + it("Incorrect value type", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { multipleReqs(req2: "two", req1: "one") } } - `, [ - badValue('req2', 'Int', '"two"', 4, 32), - badValue('req1', 'Int', '"one"', 4, 45), - ]); + `, + [ + badValue("req2", "Int", '"two"', 4, 32), + badValue("req1", "Int", '"one"', 4, 45) + ] + ); }); - it('Incorrect value and missing argument', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Incorrect value and missing argument", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { multipleReqs(req1: "one") } } - `, [ - badValue('req1', 'Int', '"one"', 4, 32), - ]); + `, + [badValue("req1", "Int", '"one"', 4, 32)] + ); }); - }); - - describe('Valid input object value', () => { - - it('Optional arg, despite required field in type', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + describe("Valid input object value", () => { + it("Optional arg, despite required field in type", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { complexArgField } } - `); + ` + ); }); - it('Partial object, only required', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Partial object, only required", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { complexArgField(complexArg: { requiredField: true }) } } - `); + ` + ); }); - it('Partial object, required field can be falsey', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Partial object, required field can be falsey", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { complexArgField(complexArg: { requiredField: false }) } } - `); + ` + ); }); - it('Partial object, including required', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Partial object, including required", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { complexArgField(complexArg: { requiredField: true, intField: 4 }) } } - `); + ` + ); }); - it('Full object', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Full object", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { complexArgField(complexArg: { @@ -704,11 +804,14 @@ describe('Validate: Argument values of correct type', () => { }) } } - `); + ` + ); }); - it('Full object with fields in different order', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + it("Full object with fields in different order", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { complexArgField(complexArg: { @@ -720,30 +823,34 @@ describe('Validate: Argument values of correct type', () => { }) } } - `); + ` + ); }); - }); - - describe('Invalid input object value', () => { - - it('Partial object, missing required', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + describe("Invalid input object value", () => { + it("Partial object, missing required", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { complexArgField(complexArg: { intField: 4 }) } } - `, [ - badValue('complexArg', 'ComplexInput', '{intField: 4}', 4, 41, [ - 'In field "requiredField": Expected "Boolean!", found null.' - ]), - ]); + `, + [ + badValue("complexArg", "ComplexInput", "{intField: 4}", 4, 41, [ + 'In field "requiredField": Expected "Boolean!", found null.' + ]) + ] + ); }); - it('Partial object, invalid field type', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Partial object, invalid field type", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { complexArgField(complexArg: { @@ -752,21 +859,27 @@ describe('Validate: Argument values of correct type', () => { }) } } - `, [ - badValue( - 'complexArg', - 'ComplexInput', - '{stringListField: ["one", 2], requiredField: true}', - 4, - 41, - [ 'In field "stringListField": In element #1: ' + - 'Expected type "String", found 2.' ] - ), - ]); + `, + [ + badValue( + "complexArg", + "ComplexInput", + '{stringListField: ["one", 2], requiredField: true}', + 4, + 41, + [ + 'In field "stringListField": In element #1: ' + + 'Expected type "String", found 2.' + ] + ) + ] + ); }); - it('Partial object, unknown field arg', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("Partial object, unknown field arg", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { complicatedArgs { complexArgField(complexArg: { @@ -775,24 +888,26 @@ describe('Validate: Argument values of correct type', () => { }) } } - `, [ - badValue( - 'complexArg', - 'ComplexInput', - '{requiredField: true, unknownField: "value"}', - 4, - 41, - [ 'In field "unknownField": Unknown field.' ] - ), - ]); + `, + [ + badValue( + "complexArg", + "ComplexInput", + '{requiredField: true, unknownField: "value"}', + 4, + 41, + ['In field "unknownField": Unknown field.'] + ) + ] + ); }); - }); - describe('Directive arguments', () => { - - it('with directives of valid types', () => { - expectPassesRule(ArgumentsOfCorrectType, ` + describe("Directive arguments", () => { + it("with directives of valid types", () => { + expectPassesRule( + ArgumentsOfCorrectType, + ` { dog @include(if: true) { name @@ -801,22 +916,25 @@ describe('Validate: Argument values of correct type', () => { name } } - `); + ` + ); }); - it('with directive with incorrect types', () => { - expectFailsRule(ArgumentsOfCorrectType, ` + it("with directive with incorrect types", () => { + expectFailsRule( + ArgumentsOfCorrectType, + ` { dog @include(if: "yes") { name @skip(if: ENUM) } } - `, [ - badValue('if', 'Boolean', '"yes"', 3, 28), - badValue('if', 'Boolean', 'ENUM', 4, 28), - ]); + `, + [ + badValue("if", "Boolean", '"yes"', 3, 28), + badValue("if", "Boolean", "ENUM", 4, 28) + ] + ); }); - }); - }); diff --git a/src/validation/__tests__/DefaultValuesOfCorrectType-test.js b/src/validation/__tests__/DefaultValuesOfCorrectType-test.js index ecbe313ae6..3d4d1c0d27 100644 --- a/src/validation/__tests__/DefaultValuesOfCorrectType-test.js +++ b/src/validation/__tests__/DefaultValuesOfCorrectType-test.js @@ -7,57 +7,61 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { DefaultValuesOfCorrectType, defaultForNonNullArgMessage, - badValueForDefaultArgMessage, -} from '../rules/DefaultValuesOfCorrectType'; - + badValueForDefaultArgMessage +} from "../rules/DefaultValuesOfCorrectType"; function defaultForNonNullArg(varName, typeName, guessTypeName, line, column) { return { message: defaultForNonNullArgMessage(varName, typeName, guessTypeName), - locations: [ { line, column } ], + locations: [{ line, column }] }; } function badValue(varName, typeName, val, line, column, errors) { let realErrors; if (!errors) { - realErrors = [ - `Expected type "${typeName}", found ${val}.` - ]; + realErrors = [`Expected type "${typeName}", found ${val}.`]; } else { realErrors = errors; } return { message: badValueForDefaultArgMessage(varName, typeName, val, realErrors), - locations: [ { line, column } ], + locations: [{ line, column }] }; } -describe('Validate: Variable default values of correct type', () => { - - it('variables with no default values', () => { - expectPassesRule(DefaultValuesOfCorrectType, ` +describe("Validate: Variable default values of correct type", () => { + it("variables with no default values", () => { + expectPassesRule( + DefaultValuesOfCorrectType, + ` query NullableValues($a: Int, $b: String, $c: ComplexInput) { dog { name } } - `); + ` + ); }); - it('required variables without default values', () => { - expectPassesRule(DefaultValuesOfCorrectType, ` + it("required variables without default values", () => { + expectPassesRule( + DefaultValuesOfCorrectType, + ` query RequiredValues($a: Int!, $b: String!) { dog { name } } - `); + ` + ); }); - it('variables with valid default values', () => { - expectPassesRule(DefaultValuesOfCorrectType, ` + it("variables with valid default values", () => { + expectPassesRule( + DefaultValuesOfCorrectType, + ` query WithDefaultValues( $a: Int = 1, $b: String = "ok", @@ -65,22 +69,29 @@ describe('Validate: Variable default values of correct type', () => { ) { dog { name } } - `); + ` + ); }); - it('no required variables with default values', () => { - expectFailsRule(DefaultValuesOfCorrectType, ` + it("no required variables with default values", () => { + expectFailsRule( + DefaultValuesOfCorrectType, + ` query UnreachableDefaultValues($a: Int! = 3, $b: String! = "default") { dog { name } } - `, [ - defaultForNonNullArg('a', 'Int!', 'Int', 2, 49), - defaultForNonNullArg('b', 'String!', 'String', 2, 66) - ]); + `, + [ + defaultForNonNullArg("a", "Int!", "Int", 2, 49), + defaultForNonNullArg("b", "String!", "String", 2, 66) + ] + ); }); - it('variables with invalid default values', () => { - expectFailsRule(DefaultValuesOfCorrectType, ` + it("variables with invalid default values", () => { + expectFailsRule( + DefaultValuesOfCorrectType, + ` query InvalidDefaultValues( $a: Int = "one", $b: String = 4, @@ -88,41 +99,50 @@ describe('Validate: Variable default values of correct type', () => { ) { dog { name } } - `, [ - badValue('a', 'Int', '"one"', 3, 19, [ - 'Expected type "Int", found "one".' - ]), - badValue('b', 'String', '4', 4, 22, [ - 'Expected type "String", found 4.' - ]), - badValue('c', 'ComplexInput', '"notverycomplex"', 5, 28, [ - 'Expected "ComplexInput", found not an object.' - ]) - ]); + `, + [ + badValue("a", "Int", '"one"', 3, 19, [ + 'Expected type "Int", found "one".' + ]), + badValue("b", "String", "4", 4, 22, [ + 'Expected type "String", found 4.' + ]), + badValue("c", "ComplexInput", '"notverycomplex"', 5, 28, [ + 'Expected "ComplexInput", found not an object.' + ]) + ] + ); }); - it('complex variables missing required field', () => { - expectFailsRule(DefaultValuesOfCorrectType, ` + it("complex variables missing required field", () => { + expectFailsRule( + DefaultValuesOfCorrectType, + ` query MissingRequiredField($a: ComplexInput = {intField: 3}) { dog { name } } - `, [ - badValue('a', 'ComplexInput', '{intField: 3}', 2, 53, [ - 'In field "requiredField": Expected "Boolean!", found null.' - ]) - ]); + `, + [ + badValue("a", "ComplexInput", "{intField: 3}", 2, 53, [ + 'In field "requiredField": Expected "Boolean!", found null.' + ]) + ] + ); }); - it('list variables with invalid item', () => { - expectFailsRule(DefaultValuesOfCorrectType, ` + it("list variables with invalid item", () => { + expectFailsRule( + DefaultValuesOfCorrectType, + ` query InvalidItem($a: [String] = ["one", 2]) { dog { name } } - `, [ - badValue('a', '[String]', '["one", 2]', 2, 40, [ - 'In element #1: Expected type "String", found 2.' - ]) - ]); + `, + [ + badValue("a", "[String]", '["one", 2]', 2, 40, [ + 'In element #1: Expected type "String", found 2.' + ]) + ] + ); }); - }); diff --git a/src/validation/__tests__/FieldsOnCorrectType-test.js b/src/validation/__tests__/FieldsOnCorrectType-test.js index 496eece221..0a73543300 100644 --- a/src/validation/__tests__/FieldsOnCorrectType-test.js +++ b/src/validation/__tests__/FieldsOnCorrectType-test.js @@ -7,77 +7,95 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { expect } from "chai"; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { FieldsOnCorrectType, - undefinedFieldMessage, -} from '../rules/FieldsOnCorrectType'; - + undefinedFieldMessage +} from "../rules/FieldsOnCorrectType"; function undefinedField(field, type, suggestions, line, column) { return { message: undefinedFieldMessage(field, type, suggestions), - locations: [ { line, column } ], + locations: [{ line, column }] }; } -describe('Validate: Fields on correct type', () => { - - it('Object field selection', () => { - expectPassesRule(FieldsOnCorrectType, ` +describe("Validate: Fields on correct type", () => { + it("Object field selection", () => { + expectPassesRule( + FieldsOnCorrectType, + ` fragment objectFieldSelection on Dog { __typename name } - `); + ` + ); }); - it('Aliased object field selection', () => { - expectPassesRule(FieldsOnCorrectType, ` + it("Aliased object field selection", () => { + expectPassesRule( + FieldsOnCorrectType, + ` fragment aliasedObjectFieldSelection on Dog { tn : __typename otherName : name } - `); + ` + ); }); - it('Interface field selection', () => { - expectPassesRule(FieldsOnCorrectType, ` + it("Interface field selection", () => { + expectPassesRule( + FieldsOnCorrectType, + ` fragment interfaceFieldSelection on Pet { __typename name } - `); + ` + ); }); - it('Aliased interface field selection', () => { - expectPassesRule(FieldsOnCorrectType, ` + it("Aliased interface field selection", () => { + expectPassesRule( + FieldsOnCorrectType, + ` fragment interfaceFieldSelection on Pet { otherName : name } - `); + ` + ); }); - it('Lying alias selection', () => { - expectPassesRule(FieldsOnCorrectType, ` + it("Lying alias selection", () => { + expectPassesRule( + FieldsOnCorrectType, + ` fragment lyingAliasSelection on Dog { name : nickname } - `); + ` + ); }); - it('Ignores fields on unknown type', () => { - expectPassesRule(FieldsOnCorrectType, ` + it("Ignores fields on unknown type", () => { + expectPassesRule( + FieldsOnCorrectType, + ` fragment unknownSelection on UnknownType { unknownField } - `); + ` + ); }); - it('reports errors when type is known again', () => { - expectFailsRule(FieldsOnCorrectType, ` + it("reports errors when type is known again", () => { + expectFailsRule( + FieldsOnCorrectType, + ` fragment typeKnownAgain on Pet { unknown_pet_field { ... on Cat { @@ -85,116 +103,140 @@ describe('Validate: Fields on correct type', () => { } } }`, - [ undefinedField('unknown_pet_field', 'Pet', [], 3, 9), - undefinedField('unknown_cat_field', 'Cat', [], 5, 13) ] + [ + undefinedField("unknown_pet_field", "Pet", [], 3, 9), + undefinedField("unknown_cat_field", "Cat", [], 5, 13) + ] ); }); - it('Field not defined on fragment', () => { - expectFailsRule(FieldsOnCorrectType, ` + it("Field not defined on fragment", () => { + expectFailsRule( + FieldsOnCorrectType, + ` fragment fieldNotDefined on Dog { meowVolume }`, - [ undefinedField('meowVolume', 'Dog', [], 3, 9) ] + [undefinedField("meowVolume", "Dog", [], 3, 9)] ); }); - it('Ignores deeply unknown field', () => { - expectFailsRule(FieldsOnCorrectType, ` + it("Ignores deeply unknown field", () => { + expectFailsRule( + FieldsOnCorrectType, + ` fragment deepFieldNotDefined on Dog { unknown_field { deeper_unknown_field } }`, - [ undefinedField('unknown_field', 'Dog', [], 3, 9) ] + [undefinedField("unknown_field", "Dog", [], 3, 9)] ); }); - it('Sub-field not defined', () => { - expectFailsRule(FieldsOnCorrectType, ` + it("Sub-field not defined", () => { + expectFailsRule( + FieldsOnCorrectType, + ` fragment subFieldNotDefined on Human { pets { unknown_field } }`, - [ undefinedField('unknown_field', 'Pet', [], 4, 11) ] + [undefinedField("unknown_field", "Pet", [], 4, 11)] ); }); - it('Field not defined on inline fragment', () => { - expectFailsRule(FieldsOnCorrectType, ` + it("Field not defined on inline fragment", () => { + expectFailsRule( + FieldsOnCorrectType, + ` fragment fieldNotDefined on Pet { ... on Dog { meowVolume } }`, - [ undefinedField('meowVolume', 'Dog', [], 4, 11) ] + [undefinedField("meowVolume", "Dog", [], 4, 11)] ); }); - it('Aliased field target not defined', () => { - expectFailsRule(FieldsOnCorrectType, ` + it("Aliased field target not defined", () => { + expectFailsRule( + FieldsOnCorrectType, + ` fragment aliasedFieldTargetNotDefined on Dog { volume : mooVolume }`, - [ undefinedField('mooVolume', 'Dog', [], 3, 9) ] + [undefinedField("mooVolume", "Dog", [], 3, 9)] ); }); - it('Aliased lying field target not defined', () => { - expectFailsRule(FieldsOnCorrectType, ` + it("Aliased lying field target not defined", () => { + expectFailsRule( + FieldsOnCorrectType, + ` fragment aliasedLyingFieldTargetNotDefined on Dog { barkVolume : kawVolume }`, - [ undefinedField('kawVolume', 'Dog', [], 3, 9) ] + [undefinedField("kawVolume", "Dog", [], 3, 9)] ); }); - it('Not defined on interface', () => { - expectFailsRule(FieldsOnCorrectType, ` + it("Not defined on interface", () => { + expectFailsRule( + FieldsOnCorrectType, + ` fragment notDefinedOnInterface on Pet { tailLength }`, - [ undefinedField('tailLength', 'Pet', [], 3, 9) ] + [undefinedField("tailLength", "Pet", [], 3, 9)] ); }); - it('Defined on implementors but not on interface', () => { - expectFailsRule(FieldsOnCorrectType, ` + it("Defined on implementors but not on interface", () => { + expectFailsRule( + FieldsOnCorrectType, + ` fragment definedOnImplementorsButNotInterface on Pet { nickname }`, - [ undefinedField('nickname', 'Pet', [ 'Cat', 'Dog' ], 3, 9) ] + [undefinedField("nickname", "Pet", ["Cat", "Dog"], 3, 9)] ); }); - it('Meta field selection on union', () => { - expectPassesRule(FieldsOnCorrectType, ` + it("Meta field selection on union", () => { + expectPassesRule( + FieldsOnCorrectType, + ` fragment directFieldSelectionOnUnion on CatOrDog { __typename }` ); }); - it('Direct field selection on union', () => { - expectFailsRule(FieldsOnCorrectType, ` + it("Direct field selection on union", () => { + expectFailsRule( + FieldsOnCorrectType, + ` fragment directFieldSelectionOnUnion on CatOrDog { directField }`, - [ undefinedField('directField', 'CatOrDog', [], 3, 9) ] + [undefinedField("directField", "CatOrDog", [], 3, 9)] ); }); - it('Defined on implementors queried on union', () => { - expectFailsRule(FieldsOnCorrectType, ` + it("Defined on implementors queried on union", () => { + expectFailsRule( + FieldsOnCorrectType, + ` fragment definedOnImplementorsQueriedOnUnion on CatOrDog { name }`, [ undefinedField( - 'name', - 'CatOrDog', - [ 'Being', 'Pet', 'Canine', 'Cat', 'Dog' ], + "name", + "CatOrDog", + ["Being", "Pet", "Canine", "Cat", "Dog"], 3, 9 ) @@ -202,8 +244,10 @@ describe('Validate: Fields on correct type', () => { ); }); - it('valid field in inline fragment', () => { - expectPassesRule(FieldsOnCorrectType, ` + it("valid field in inline fragment", () => { + expectPassesRule( + FieldsOnCorrectType, + ` fragment objectFieldSelection on Pet { ... on Dog { name @@ -212,32 +256,34 @@ describe('Validate: Fields on correct type', () => { name } } - `); + ` + ); }); - describe('Fields on correct type error message', () => { - it('Works with no suggestions', () => { - expect( - undefinedFieldMessage('T', 'f', []) - ).to.equal('Cannot query field "T" on type "f".'); + describe("Fields on correct type error message", () => { + it("Works with no suggestions", () => { + expect(undefinedFieldMessage("T", "f", [])).to.equal( + 'Cannot query field "T" on type "f".' + ); }); - it('Works with no small numbers of suggestions', () => { - expect( - undefinedFieldMessage('T', 'f', [ 'A', 'B' ]) - ).to.equal('Cannot query field "T" on type "f". ' + - 'However, this field exists on "A", "B". ' + - 'Perhaps you meant to use an inline fragment?'); + it("Works with no small numbers of suggestions", () => { + expect(undefinedFieldMessage("T", "f", ["A", "B"])).to.equal( + 'Cannot query field "T" on type "f". ' + + 'However, this field exists on "A", "B". ' + + "Perhaps you meant to use an inline fragment?" + ); }); - it('Works with lots of suggestions', () => { + it("Works with lots of suggestions", () => { expect( - undefinedFieldMessage('T', 'f', [ 'A', 'B', 'C', 'D', 'E', 'F' ]) - ).to.equal('Cannot query field "T" on type "f". ' + - 'However, this field exists on "A", "B", "C", "D", "E", ' + - 'and 1 other types. ' + - 'Perhaps you meant to use an inline fragment?'); + undefinedFieldMessage("T", "f", ["A", "B", "C", "D", "E", "F"]) + ).to.equal( + 'Cannot query field "T" on type "f". ' + + 'However, this field exists on "A", "B", "C", "D", "E", ' + + "and 1 other types. " + + "Perhaps you meant to use an inline fragment?" + ); }); }); }); - diff --git a/src/validation/__tests__/FragmentsOnCompositeTypes-test.js b/src/validation/__tests__/FragmentsOnCompositeTypes-test.js index 05e894d74a..c0714b8f7c 100644 --- a/src/validation/__tests__/FragmentsOnCompositeTypes-test.js +++ b/src/validation/__tests__/FragmentsOnCompositeTypes-test.js @@ -7,102 +7,133 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { FragmentsOnCompositeTypes, inlineFragmentOnNonCompositeErrorMessage, - fragmentOnNonCompositeErrorMessage, -} from '../rules/FragmentsOnCompositeTypes'; + fragmentOnNonCompositeErrorMessage +} from "../rules/FragmentsOnCompositeTypes"; function error(fragName, typeName, line, column) { return { message: fragmentOnNonCompositeErrorMessage(fragName, typeName), - locations: [ { line, column } ], + locations: [{ line, column }] }; } -describe('Validate: Fragments on composite types', () => { - - it('object is valid fragment type', () => { - expectPassesRule(FragmentsOnCompositeTypes, ` +describe("Validate: Fragments on composite types", () => { + it("object is valid fragment type", () => { + expectPassesRule( + FragmentsOnCompositeTypes, + ` fragment validFragment on Dog { barks } - `); + ` + ); }); - it('interface is valid fragment type', () => { - expectPassesRule(FragmentsOnCompositeTypes, ` + it("interface is valid fragment type", () => { + expectPassesRule( + FragmentsOnCompositeTypes, + ` fragment validFragment on Pet { name } - `); + ` + ); }); - it('object is valid inline fragment type', () => { - expectPassesRule(FragmentsOnCompositeTypes, ` + it("object is valid inline fragment type", () => { + expectPassesRule( + FragmentsOnCompositeTypes, + ` fragment validFragment on Pet { ... on Dog { barks } } - `); + ` + ); }); - it('inline fragment without type is valid', () => { - expectPassesRule(FragmentsOnCompositeTypes, ` + it("inline fragment without type is valid", () => { + expectPassesRule( + FragmentsOnCompositeTypes, + ` fragment validFragment on Pet { ... { name } } - `); + ` + ); }); - it('union is valid fragment type', () => { - expectPassesRule(FragmentsOnCompositeTypes, ` + it("union is valid fragment type", () => { + expectPassesRule( + FragmentsOnCompositeTypes, + ` fragment validFragment on CatOrDog { __typename } - `); + ` + ); }); - it('scalar is invalid fragment type', () => { - expectFailsRule(FragmentsOnCompositeTypes, ` + it("scalar is invalid fragment type", () => { + expectFailsRule( + FragmentsOnCompositeTypes, + ` fragment scalarFragment on Boolean { bad } - `, [ error('scalarFragment', 'Boolean', 2, 34) ]); + `, + [error("scalarFragment", "Boolean", 2, 34)] + ); }); - it('enum is invalid fragment type', () => { - expectFailsRule(FragmentsOnCompositeTypes, ` + it("enum is invalid fragment type", () => { + expectFailsRule( + FragmentsOnCompositeTypes, + ` fragment scalarFragment on FurColor { bad } - `, [ error('scalarFragment', 'FurColor', 2, 34) ]); + `, + [error("scalarFragment", "FurColor", 2, 34)] + ); }); - it('input object is invalid fragment type', () => { - expectFailsRule(FragmentsOnCompositeTypes, ` + it("input object is invalid fragment type", () => { + expectFailsRule( + FragmentsOnCompositeTypes, + ` fragment inputFragment on ComplexInput { stringField } - `, [ error('inputFragment', 'ComplexInput', 2, 33) ]); + `, + [error("inputFragment", "ComplexInput", 2, 33)] + ); }); - it('scalar is invalid inline fragment type', () => { - expectFailsRule(FragmentsOnCompositeTypes, ` + it("scalar is invalid inline fragment type", () => { + expectFailsRule( + FragmentsOnCompositeTypes, + ` fragment invalidFragment on Pet { ... on String { barks } } - `, [ - { message: inlineFragmentOnNonCompositeErrorMessage('String'), - locations: [ { line: 3, column: 16 } ] } - ]); + `, + [ + { + message: inlineFragmentOnNonCompositeErrorMessage("String"), + locations: [{ line: 3, column: 16 }] + } + ] + ); }); - }); diff --git a/src/validation/__tests__/KnownArgumentNames-test.js b/src/validation/__tests__/KnownArgumentNames-test.js index bc9fec1ec9..9ec5db2cd3 100644 --- a/src/validation/__tests__/KnownArgumentNames-test.js +++ b/src/validation/__tests__/KnownArgumentNames-test.js @@ -7,73 +7,88 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { KnownArgumentNames, unknownArgMessage, - unknownDirectiveArgMessage, -} from '../rules/KnownArgumentNames'; - + unknownDirectiveArgMessage +} from "../rules/KnownArgumentNames"; function unknownArg(argName, fieldName, typeName, line, column) { return { message: unknownArgMessage(argName, fieldName, typeName), - locations: [ { line, column } ], + locations: [{ line, column }] }; } function unknownDirectiveArg(argName, directiveName, line, column) { return { message: unknownDirectiveArgMessage(argName, directiveName), - locations: [ { line, column } ], + locations: [{ line, column }] }; } -describe('Validate: Known argument names', () => { - - it('single arg is known', () => { - expectPassesRule(KnownArgumentNames, ` +describe("Validate: Known argument names", () => { + it("single arg is known", () => { + expectPassesRule( + KnownArgumentNames, + ` fragment argOnRequiredArg on Dog { doesKnowCommand(dogCommand: SIT) } - `); + ` + ); }); - it('multiple args are known', () => { - expectPassesRule(KnownArgumentNames, ` + it("multiple args are known", () => { + expectPassesRule( + KnownArgumentNames, + ` fragment multipleArgs on ComplicatedArgs { multipleReqs(req1: 1, req2: 2) } - `); + ` + ); }); - it('ignores args of unknown fields', () => { - expectPassesRule(KnownArgumentNames, ` + it("ignores args of unknown fields", () => { + expectPassesRule( + KnownArgumentNames, + ` fragment argOnUnknownField on Dog { unknownField(unknownArg: SIT) } - `); + ` + ); }); - it('multiple args in reverse order are known', () => { - expectPassesRule(KnownArgumentNames, ` + it("multiple args in reverse order are known", () => { + expectPassesRule( + KnownArgumentNames, + ` fragment multipleArgsReverseOrder on ComplicatedArgs { multipleReqs(req2: 2, req1: 1) } - `); + ` + ); }); - it('no args on optional arg', () => { - expectPassesRule(KnownArgumentNames, ` + it("no args on optional arg", () => { + expectPassesRule( + KnownArgumentNames, + ` fragment noArgOnOptionalArg on Dog { isHousetrained } - `); + ` + ); }); - it('args are known deeply', () => { - expectPassesRule(KnownArgumentNames, ` + it("args are known deeply", () => { + expectPassesRule( + KnownArgumentNames, + ` { dog { doesKnowCommand(dogCommand: SIT) @@ -86,50 +101,64 @@ describe('Validate: Known argument names', () => { } } } - `); + ` + ); }); - it('directive args are known', () => { - expectPassesRule(KnownArgumentNames, ` + it("directive args are known", () => { + expectPassesRule( + KnownArgumentNames, + ` { dog @skip(if: true) } - `); + ` + ); }); - it('undirective args are invalid', () => { - expectFailsRule(KnownArgumentNames, ` + it("undirective args are invalid", () => { + expectFailsRule( + KnownArgumentNames, + ` { dog @skip(unless: true) } - `, [ - unknownDirectiveArg('unless', 'skip', 3, 19), - ]); + `, + [unknownDirectiveArg("unless", "skip", 3, 19)] + ); }); - it('invalid arg name', () => { - expectFailsRule(KnownArgumentNames, ` + it("invalid arg name", () => { + expectFailsRule( + KnownArgumentNames, + ` fragment invalidArgName on Dog { doesKnowCommand(unknown: true) } - `, [ - unknownArg('unknown', 'doesKnowCommand', 'Dog', 3, 25), - ]); + `, + [unknownArg("unknown", "doesKnowCommand", "Dog", 3, 25)] + ); }); - it('unknown args amongst known args', () => { - expectFailsRule(KnownArgumentNames, ` + it("unknown args amongst known args", () => { + expectFailsRule( + KnownArgumentNames, + ` fragment oneGoodArgOneInvalidArg on Dog { doesKnowCommand(whoknows: 1, dogCommand: SIT, unknown: true) } - `, [ - unknownArg('whoknows', 'doesKnowCommand', 'Dog', 3, 25), - unknownArg('unknown', 'doesKnowCommand', 'Dog', 3, 55), - ]); + `, + [ + unknownArg("whoknows", "doesKnowCommand", "Dog", 3, 25), + unknownArg("unknown", "doesKnowCommand", "Dog", 3, 55) + ] + ); }); - it('unknown args deeply', () => { - expectFailsRule(KnownArgumentNames, ` + it("unknown args deeply", () => { + expectFailsRule( + KnownArgumentNames, + ` { dog { doesKnowCommand(unknown: true) @@ -142,10 +171,11 @@ describe('Validate: Known argument names', () => { } } } - `, [ - unknownArg('unknown', 'doesKnowCommand', 'Dog', 4, 27), - unknownArg('unknown', 'doesKnowCommand', 'Dog', 9, 31), - ]); + `, + [ + unknownArg("unknown", "doesKnowCommand", "Dog", 4, 27), + unknownArg("unknown", "doesKnowCommand", "Dog", 9, 31) + ] + ); }); - }); diff --git a/src/validation/__tests__/KnownDirectives-test.js b/src/validation/__tests__/KnownDirectives-test.js index e71f5f924b..6263c20f21 100644 --- a/src/validation/__tests__/KnownDirectives-test.js +++ b/src/validation/__tests__/KnownDirectives-test.js @@ -7,33 +7,33 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { KnownDirectives, unknownDirectiveMessage, - misplacedDirectiveMessage, -} from '../rules/KnownDirectives'; - + misplacedDirectiveMessage +} from "../rules/KnownDirectives"; function unknownDirective(directiveName, line, column) { return { message: unknownDirectiveMessage(directiveName), - locations: [ { line, column } ] + locations: [{ line, column }] }; } function misplacedDirective(directiveName, placement, line, column) { return { message: misplacedDirectiveMessage(directiveName, placement), - locations: [ { line, column } ] + locations: [{ line, column }] }; } -describe('Validate: Known directives', () => { - - it('with no directives', () => { - expectPassesRule(KnownDirectives, ` +describe("Validate: Known directives", () => { + it("with no directives", () => { + expectPassesRule( + KnownDirectives, + ` query Foo { name ...Frag @@ -42,11 +42,14 @@ describe('Validate: Known directives', () => { fragment Frag on Dog { name } - `); + ` + ); }); - it('with known directives', () => { - expectPassesRule(KnownDirectives, ` + it("with known directives", () => { + expectPassesRule( + KnownDirectives, + ` { dog @include(if: true) { name @@ -55,23 +58,28 @@ describe('Validate: Known directives', () => { name } } - `); + ` + ); }); - it('with unknown directive', () => { - expectFailsRule(KnownDirectives, ` + it("with unknown directive", () => { + expectFailsRule( + KnownDirectives, + ` { dog @unknown(directive: "value") { name } } - `, [ - unknownDirective('unknown', 3, 13) - ]); + `, + [unknownDirective("unknown", 3, 13)] + ); }); - it('with many unknown directives', () => { - expectFailsRule(KnownDirectives, ` + it("with many unknown directives", () => { + expectFailsRule( + KnownDirectives, + ` { dog @unknown(directive: "value") { name @@ -83,35 +91,43 @@ describe('Validate: Known directives', () => { } } } - `, [ - unknownDirective('unknown', 3, 13), - unknownDirective('unknown', 6, 15), - unknownDirective('unknown', 8, 16) - ]); + `, + [ + unknownDirective("unknown", 3, 13), + unknownDirective("unknown", 6, 15), + unknownDirective("unknown", 8, 16) + ] + ); }); - it('with well placed directives', () => { - expectPassesRule(KnownDirectives, ` + it("with well placed directives", () => { + expectPassesRule( + KnownDirectives, + ` query Foo { name @include(if: true) ...Frag @include(if: true) skippedField @skip(if: true) ...SkippedFrag @skip(if: true) } - `); + ` + ); }); - it('with misplaced directives', () => { - expectFailsRule(KnownDirectives, ` + it("with misplaced directives", () => { + expectFailsRule( + KnownDirectives, + ` query Foo @include(if: true) { name @operationOnly ...Frag @operationOnly } - `, [ - misplacedDirective('include', 'QUERY', 2, 17), - misplacedDirective('operationOnly', 'FIELD', 3, 14), - misplacedDirective('operationOnly', 'FRAGMENT_SPREAD', 4, 17), - ]); + `, + [ + misplacedDirective("include", "QUERY", 2, 17), + misplacedDirective("operationOnly", "FIELD", 3, 14), + misplacedDirective("operationOnly", "FRAGMENT_SPREAD", 4, 17) + ] + ); }); - }); diff --git a/src/validation/__tests__/KnownFragmentNames-test.js b/src/validation/__tests__/KnownFragmentNames-test.js index a05016f64f..4abf93d533 100644 --- a/src/validation/__tests__/KnownFragmentNames-test.js +++ b/src/validation/__tests__/KnownFragmentNames-test.js @@ -7,25 +7,25 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { KnownFragmentNames, - unknownFragmentMessage, -} from '../rules/KnownFragmentNames'; - + unknownFragmentMessage +} from "../rules/KnownFragmentNames"; function undefFrag(fragName, line, column) { return { message: unknownFragmentMessage(fragName), - locations: [ { line, column } ] + locations: [{ line, column }] }; } -describe('Validate: Known fragment names', () => { - - it('known fragment names are valid', () => { - expectPassesRule(KnownFragmentNames, ` +describe("Validate: Known fragment names", () => { + it("known fragment names are valid", () => { + expectPassesRule( + KnownFragmentNames, + ` { human(id: 4) { ...HumanFields1 @@ -47,11 +47,14 @@ describe('Validate: Known fragment names', () => { fragment HumanFields3 on Human { name } - `); + ` + ); }); - it('unknown fragment names are invalid', () => { - expectFailsRule(KnownFragmentNames, ` + it("unknown fragment names are invalid", () => { + expectFailsRule( + KnownFragmentNames, + ` { human(id: 4) { ...UnknownFragment1 @@ -64,11 +67,12 @@ describe('Validate: Known fragment names', () => { name ...UnknownFragment3 } - `, [ - undefFrag('UnknownFragment1', 4, 14), - undefFrag('UnknownFragment2', 6, 16), - undefFrag('UnknownFragment3', 12, 12) - ]); + `, + [ + undefFrag("UnknownFragment1", 4, 14), + undefFrag("UnknownFragment2", 6, 16), + undefFrag("UnknownFragment3", 12, 12) + ] + ); }); - }); diff --git a/src/validation/__tests__/KnownTypeNames-test.js b/src/validation/__tests__/KnownTypeNames-test.js index e158ad3acb..e9960e69b1 100644 --- a/src/validation/__tests__/KnownTypeNames-test.js +++ b/src/validation/__tests__/KnownTypeNames-test.js @@ -7,25 +7,22 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; -import { - KnownTypeNames, - unknownTypeMessage, -} from '../rules/KnownTypeNames'; - +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; +import { KnownTypeNames, unknownTypeMessage } from "../rules/KnownTypeNames"; function unknownType(typeName, line, column) { return { message: unknownTypeMessage(typeName), - locations: [ { line, column } ], + locations: [{ line, column }] }; } -describe('Validate: Known type names', () => { - - it('known type names are valid', () => { - expectPassesRule(KnownTypeNames, ` +describe("Validate: Known type names", () => { + it("known type names are valid", () => { + expectPassesRule( + KnownTypeNames, + ` query Foo($var: String, $required: [String!]!) { user(id: 4) { pets { ... on Pet { name }, ...PetFields, ... { name } } @@ -34,11 +31,14 @@ describe('Validate: Known type names', () => { fragment PetFields on Pet { name } - `); + ` + ); }); - it('unknown type names are invalid', () => { - expectFailsRule(KnownTypeNames, ` + it("unknown type names are invalid", () => { + expectFailsRule( + KnownTypeNames, + ` query Foo($var: JumbledUpLetters) { user(id: 4) { name @@ -48,15 +48,19 @@ describe('Validate: Known type names', () => { fragment PetFields on Peettt { name } - `, [ - unknownType('JumbledUpLetters', 2, 23), - unknownType('Badger', 5, 25), - unknownType('Peettt', 8, 29) - ]); + `, + [ + unknownType("JumbledUpLetters", 2, 23), + unknownType("Badger", 5, 25), + unknownType("Peettt", 8, 29) + ] + ); }); - it('ignores type definitions', () => { - expectFailsRule(KnownTypeNames, ` + it("ignores type definitions", () => { + expectFailsRule( + KnownTypeNames, + ` type NotInTheSchema { field: FooBar } @@ -72,9 +76,8 @@ describe('Validate: Known type names', () => { id } } - `, [ - unknownType('NotInTheSchema', 12, 23), - ]); + `, + [unknownType("NotInTheSchema", 12, 23)] + ); }); - }); diff --git a/src/validation/__tests__/LoneAnonymousOperation-test.js b/src/validation/__tests__/LoneAnonymousOperation-test.js index 9f66c721f0..7fe3832f11 100644 --- a/src/validation/__tests__/LoneAnonymousOperation-test.js +++ b/src/validation/__tests__/LoneAnonymousOperation-test.js @@ -7,41 +7,47 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { LoneAnonymousOperation, - anonOperationNotAloneMessage, -} from '../rules/LoneAnonymousOperation'; - + anonOperationNotAloneMessage +} from "../rules/LoneAnonymousOperation"; function anonNotAlone(line, column) { return { message: anonOperationNotAloneMessage(), - locations: [ { line, column } ], + locations: [{ line, column }] }; } -describe('Validate: Anonymous operation must be alone', () => { - - it('no operations', () => { - expectPassesRule(LoneAnonymousOperation, ` +describe("Validate: Anonymous operation must be alone", () => { + it("no operations", () => { + expectPassesRule( + LoneAnonymousOperation, + ` fragment fragA on Type { field } - `); + ` + ); }); - it('one anon operation', () => { - expectPassesRule(LoneAnonymousOperation, ` + it("one anon operation", () => { + expectPassesRule( + LoneAnonymousOperation, + ` { field } - `); + ` + ); }); - it('multiple named operations', () => { - expectPassesRule(LoneAnonymousOperation, ` + it("multiple named operations", () => { + expectPassesRule( + LoneAnonymousOperation, + ` query Foo { field } @@ -49,58 +55,66 @@ describe('Validate: Anonymous operation must be alone', () => { query Bar { field } - `); + ` + ); }); - it('anon operation with fragment', () => { - expectPassesRule(LoneAnonymousOperation, ` + it("anon operation with fragment", () => { + expectPassesRule( + LoneAnonymousOperation, + ` { ...Foo } fragment Foo on Type { field } - `); + ` + ); }); - it('multiple anon operations', () => { - expectFailsRule(LoneAnonymousOperation, ` + it("multiple anon operations", () => { + expectFailsRule( + LoneAnonymousOperation, + ` { fieldA } { fieldB } - `, [ - anonNotAlone(2, 7), - anonNotAlone(5, 7) - ]); + `, + [anonNotAlone(2, 7), anonNotAlone(5, 7)] + ); }); - it('anon operation with a mutation', () => { - expectFailsRule(LoneAnonymousOperation, ` + it("anon operation with a mutation", () => { + expectFailsRule( + LoneAnonymousOperation, + ` { fieldA } mutation Foo { fieldB } - `, [ - anonNotAlone(2, 7) - ]); + `, + [anonNotAlone(2, 7)] + ); }); - it('anon operation with a subscription', () => { - expectFailsRule(LoneAnonymousOperation, ` + it("anon operation with a subscription", () => { + expectFailsRule( + LoneAnonymousOperation, + ` { fieldA } subscription Foo { fieldB } - `, [ - anonNotAlone(2, 7) - ]); + `, + [anonNotAlone(2, 7)] + ); }); - }); diff --git a/src/validation/__tests__/NoFragmentCycles-test.js b/src/validation/__tests__/NoFragmentCycles-test.js index 13e80615d2..b62ef036cf 100644 --- a/src/validation/__tests__/NoFragmentCycles-test.js +++ b/src/validation/__tests__/NoFragmentCycles-test.js @@ -7,37 +7,46 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; -import { NoFragmentCycles, cycleErrorMessage } from '../rules/NoFragmentCycles'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; +import { NoFragmentCycles, cycleErrorMessage } from "../rules/NoFragmentCycles"; - -describe('Validate: No circular fragment spreads', () => { - - it('single reference is valid', () => { - expectPassesRule(NoFragmentCycles, ` +describe("Validate: No circular fragment spreads", () => { + it("single reference is valid", () => { + expectPassesRule( + NoFragmentCycles, + ` fragment fragA on Dog { ...fragB } fragment fragB on Dog { name } - `); + ` + ); }); - it('spreading twice is not circular', () => { - expectPassesRule(NoFragmentCycles, ` + it("spreading twice is not circular", () => { + expectPassesRule( + NoFragmentCycles, + ` fragment fragA on Dog { ...fragB, ...fragB } fragment fragB on Dog { name } - `); + ` + ); }); - it('spreading twice indirectly is not circular', () => { - expectPassesRule(NoFragmentCycles, ` + it("spreading twice indirectly is not circular", () => { + expectPassesRule( + NoFragmentCycles, + ` fragment fragA on Dog { ...fragB, ...fragC } fragment fragB on Dog { ...fragC } fragment fragC on Dog { name } - `); + ` + ); }); - it('double spread within abstract types', () => { - expectPassesRule(NoFragmentCycles, ` + it("double spread within abstract types", () => { + expectPassesRule( + NoFragmentCycles, + ` fragment nameFragment on Pet { ... on Dog { name } ... on Cat { name } @@ -47,71 +56,106 @@ describe('Validate: No circular fragment spreads', () => { ... on Dog { ...nameFragment } ... on Cat { ...nameFragment } } - `); + ` + ); }); - it('does not false positive on unknown fragment', () => { - expectPassesRule(NoFragmentCycles, ` + it("does not false positive on unknown fragment", () => { + expectPassesRule( + NoFragmentCycles, + ` fragment nameFragment on Pet { ...UnknownFragment } - `); + ` + ); }); - it('spreading recursively within field fails', () => { - expectFailsRule(NoFragmentCycles, ` + it("spreading recursively within field fails", () => { + expectFailsRule( + NoFragmentCycles, + ` fragment fragA on Human { relatives { ...fragA } }, - `, [ - { message: cycleErrorMessage('fragA', []), - locations: [ { line: 2, column: 45 } ] } - ]); + `, + [ + { + message: cycleErrorMessage("fragA", []), + locations: [{ line: 2, column: 45 }] + } + ] + ); }); - it('no spreading itself directly', () => { - expectFailsRule(NoFragmentCycles, ` + it("no spreading itself directly", () => { + expectFailsRule( + NoFragmentCycles, + ` fragment fragA on Dog { ...fragA } - `, [ - { message: cycleErrorMessage('fragA', []), - locations: [ { line: 2, column: 31 } ] } - ]); + `, + [ + { + message: cycleErrorMessage("fragA", []), + locations: [{ line: 2, column: 31 }] + } + ] + ); }); - it('no spreading itself directly within inline fragment', () => { - expectFailsRule(NoFragmentCycles, ` + it("no spreading itself directly within inline fragment", () => { + expectFailsRule( + NoFragmentCycles, + ` fragment fragA on Pet { ... on Dog { ...fragA } } - `, [ - { message: cycleErrorMessage('fragA', []), - locations: [ { line: 4, column: 11 } ] } - ]); + `, + [ + { + message: cycleErrorMessage("fragA", []), + locations: [{ line: 4, column: 11 }] + } + ] + ); }); - it('no spreading itself indirectly', () => { - expectFailsRule(NoFragmentCycles, ` + it("no spreading itself indirectly", () => { + expectFailsRule( + NoFragmentCycles, + ` fragment fragA on Dog { ...fragB } fragment fragB on Dog { ...fragA } - `, [ - { message: cycleErrorMessage('fragA', [ 'fragB' ]), - locations: [ { line: 2, column: 31 }, { line: 3, column: 31 } ] } - ]); + `, + [ + { + message: cycleErrorMessage("fragA", ["fragB"]), + locations: [{ line: 2, column: 31 }, { line: 3, column: 31 }] + } + ] + ); }); - it('no spreading itself indirectly reports opposite order', () => { - expectFailsRule(NoFragmentCycles, ` + it("no spreading itself indirectly reports opposite order", () => { + expectFailsRule( + NoFragmentCycles, + ` fragment fragB on Dog { ...fragA } fragment fragA on Dog { ...fragB } - `, [ - { message: cycleErrorMessage('fragB', [ 'fragA' ]), - locations: [ { line: 2, column: 31 }, { line: 3, column: 31 } ] } - ]); + `, + [ + { + message: cycleErrorMessage("fragB", ["fragA"]), + locations: [{ line: 2, column: 31 }, { line: 3, column: 31 }] + } + ] + ); }); - - it('no spreading itself indirectly within inline fragment', () => { - expectFailsRule(NoFragmentCycles, ` + it("no spreading itself indirectly within inline fragment", () => { + expectFailsRule( + NoFragmentCycles, + ` fragment fragA on Pet { ... on Dog { ...fragB @@ -122,14 +166,20 @@ describe('Validate: No circular fragment spreads', () => { ...fragA } } - `, [ - { message: cycleErrorMessage('fragA', [ 'fragB' ]), - locations: [ { line: 4, column: 11 }, { line: 9, column: 11 } ] } - ]); + `, + [ + { + message: cycleErrorMessage("fragA", ["fragB"]), + locations: [{ line: 4, column: 11 }, { line: 9, column: 11 }] + } + ] + ); }); - it('no spreading itself deeply', () => { - expectFailsRule(NoFragmentCycles, ` + it("no spreading itself deeply", () => { + expectFailsRule( + NoFragmentCycles, + ` fragment fragA on Dog { ...fragB } fragment fragB on Dog { ...fragC } fragment fragC on Dog { ...fragO } @@ -138,68 +188,110 @@ describe('Validate: No circular fragment spreads', () => { fragment fragZ on Dog { ...fragO } fragment fragO on Dog { ...fragP } fragment fragP on Dog { ...fragA, ...fragX } - `, [ - { message: - cycleErrorMessage('fragA', [ 'fragB', 'fragC', 'fragO', 'fragP' ]), - locations: [ - { line: 2, column: 31 }, - { line: 3, column: 31 }, - { line: 4, column: 31 }, - { line: 8, column: 31 }, - { line: 9, column: 31 } ] }, - { message: - cycleErrorMessage('fragO', [ 'fragP', 'fragX', 'fragY', 'fragZ' ]), - locations: [ - { line: 8, column: 31 }, - { line: 9, column: 41 }, - { line: 5, column: 31 }, - { line: 6, column: 31 }, - { line: 7, column: 31 } ] } - ]); + `, + [ + { + message: cycleErrorMessage("fragA", [ + "fragB", + "fragC", + "fragO", + "fragP" + ]), + locations: [ + { line: 2, column: 31 }, + { line: 3, column: 31 }, + { line: 4, column: 31 }, + { line: 8, column: 31 }, + { line: 9, column: 31 } + ] + }, + { + message: cycleErrorMessage("fragO", [ + "fragP", + "fragX", + "fragY", + "fragZ" + ]), + locations: [ + { line: 8, column: 31 }, + { line: 9, column: 41 }, + { line: 5, column: 31 }, + { line: 6, column: 31 }, + { line: 7, column: 31 } + ] + } + ] + ); }); - it('no spreading itself deeply two paths', () => { - expectFailsRule(NoFragmentCycles, ` + it("no spreading itself deeply two paths", () => { + expectFailsRule( + NoFragmentCycles, + ` fragment fragA on Dog { ...fragB, ...fragC } fragment fragB on Dog { ...fragA } fragment fragC on Dog { ...fragA } - `, [ - { message: cycleErrorMessage('fragA', [ 'fragB' ]), - locations: [ { line: 2, column: 31 }, { line: 3, column: 31 } ] }, - { message: cycleErrorMessage('fragA', [ 'fragC' ]), - locations: [ { line: 2, column: 41 }, { line: 4, column: 31 } ] } - ]); + `, + [ + { + message: cycleErrorMessage("fragA", ["fragB"]), + locations: [{ line: 2, column: 31 }, { line: 3, column: 31 }] + }, + { + message: cycleErrorMessage("fragA", ["fragC"]), + locations: [{ line: 2, column: 41 }, { line: 4, column: 31 }] + } + ] + ); }); - it('no spreading itself deeply two paths -- alt traverse order', () => { - expectFailsRule(NoFragmentCycles, ` + it("no spreading itself deeply two paths -- alt traverse order", () => { + expectFailsRule( + NoFragmentCycles, + ` fragment fragA on Dog { ...fragC } fragment fragB on Dog { ...fragC } fragment fragC on Dog { ...fragA, ...fragB } - `, [ - { message: cycleErrorMessage('fragA', [ 'fragC' ]), - locations: [ { line: 2, column: 31 }, { line: 4, column: 31 } ] }, - { message: cycleErrorMessage('fragC', [ 'fragB' ]), - locations: [ { line: 4, column: 41 }, { line: 3, column: 31 } ] } - ]); + `, + [ + { + message: cycleErrorMessage("fragA", ["fragC"]), + locations: [{ line: 2, column: 31 }, { line: 4, column: 31 }] + }, + { + message: cycleErrorMessage("fragC", ["fragB"]), + locations: [{ line: 4, column: 41 }, { line: 3, column: 31 }] + } + ] + ); }); - it('no spreading itself deeply and immediately', () => { - expectFailsRule(NoFragmentCycles, ` + it("no spreading itself deeply and immediately", () => { + expectFailsRule( + NoFragmentCycles, + ` fragment fragA on Dog { ...fragB } fragment fragB on Dog { ...fragB, ...fragC } fragment fragC on Dog { ...fragA, ...fragB } - `, [ - { message: cycleErrorMessage('fragB', []), - locations: [ { line: 3, column: 31 } ] }, - { message: cycleErrorMessage('fragA', [ 'fragB', 'fragC' ]), - locations: [ - { line: 2, column: 31 }, - { line: 3, column: 41 }, - { line: 4, column: 31 } ] }, - { message: cycleErrorMessage('fragB', [ 'fragC' ]), - locations: [ { line: 3, column: 41 }, { line: 4, column: 41 } ] } - ]); + `, + [ + { + message: cycleErrorMessage("fragB", []), + locations: [{ line: 3, column: 31 }] + }, + { + message: cycleErrorMessage("fragA", ["fragB", "fragC"]), + locations: [ + { line: 2, column: 31 }, + { line: 3, column: 41 }, + { line: 4, column: 31 } + ] + }, + { + message: cycleErrorMessage("fragB", ["fragC"]), + locations: [{ line: 3, column: 41 }, { line: 4, column: 41 }] + } + ] + ); }); - }); diff --git a/src/validation/__tests__/NoUndefinedVariables-test.js b/src/validation/__tests__/NoUndefinedVariables-test.js index 9ebf5a0594..822fa919d5 100644 --- a/src/validation/__tests__/NoUndefinedVariables-test.js +++ b/src/validation/__tests__/NoUndefinedVariables-test.js @@ -7,33 +7,36 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { NoUndefinedVariables, - undefinedVarMessage, -} from '../rules/NoUndefinedVariables'; - + undefinedVarMessage +} from "../rules/NoUndefinedVariables"; function undefVar(varName, l1, c1, opName, l2, c2) { return { message: undefinedVarMessage(varName, opName), - locations: [ { line: l1, column: c1 }, { line: l2, column: c2 } ], + locations: [{ line: l1, column: c1 }, { line: l2, column: c2 }] }; } -describe('Validate: No undefined variables', () => { - - it('all variables defined', () => { - expectPassesRule(NoUndefinedVariables, ` +describe("Validate: No undefined variables", () => { + it("all variables defined", () => { + expectPassesRule( + NoUndefinedVariables, + ` query Foo($a: String, $b: String, $c: String) { field(a: $a, b: $b, c: $c) } - `); + ` + ); }); - it('all variables deeply defined', () => { - expectPassesRule(NoUndefinedVariables, ` + it("all variables deeply defined", () => { + expectPassesRule( + NoUndefinedVariables, + ` query Foo($a: String, $b: String, $c: String) { field(a: $a) { field(b: $b) { @@ -41,11 +44,14 @@ describe('Validate: No undefined variables', () => { } } } - `); + ` + ); }); - it('all variables deeply in inline fragments defined', () => { - expectPassesRule(NoUndefinedVariables, ` + it("all variables deeply in inline fragments defined", () => { + expectPassesRule( + NoUndefinedVariables, + ` query Foo($a: String, $b: String, $c: String) { ... on Type { field(a: $a) { @@ -57,11 +63,14 @@ describe('Validate: No undefined variables', () => { } } } - `); + ` + ); }); - it('all variables in fragments deeply defined', () => { - expectPassesRule(NoUndefinedVariables, ` + it("all variables in fragments deeply defined", () => { + expectPassesRule( + NoUndefinedVariables, + ` query Foo($a: String, $b: String, $c: String) { ...FragA } @@ -78,11 +87,14 @@ describe('Validate: No undefined variables', () => { fragment FragC on Type { field(c: $c) } - `); + ` + ); }); - it('variable within single fragment defined in multiple operations', () => { - expectPassesRule(NoUndefinedVariables, ` + it("variable within single fragment defined in multiple operations", () => { + expectPassesRule( + NoUndefinedVariables, + ` query Foo($a: String) { ...FragA } @@ -92,11 +104,14 @@ describe('Validate: No undefined variables', () => { fragment FragA on Type { field(a: $a) } - `); + ` + ); }); - it('variable within fragments defined in operations', () => { - expectPassesRule(NoUndefinedVariables, ` + it("variable within fragments defined in operations", () => { + expectPassesRule( + NoUndefinedVariables, + ` query Foo($a: String) { ...FragA } @@ -109,11 +124,14 @@ describe('Validate: No undefined variables', () => { fragment FragB on Type { field(b: $b) } - `); + ` + ); }); - it('variable within recursive fragment defined', () => { - expectPassesRule(NoUndefinedVariables, ` + it("variable within recursive fragment defined", () => { + expectPassesRule( + NoUndefinedVariables, + ` query Foo($a: String) { ...FragA } @@ -122,55 +140,65 @@ describe('Validate: No undefined variables', () => { ...FragA } } - `); + ` + ); }); - it('variable not defined', () => { - expectFailsRule(NoUndefinedVariables, ` + it("variable not defined", () => { + expectFailsRule( + NoUndefinedVariables, + ` query Foo($a: String, $b: String, $c: String) { field(a: $a, b: $b, c: $c, d: $d) } - `, [ - undefVar('d', 3, 39, 'Foo', 2, 7) - ]); + `, + [undefVar("d", 3, 39, "Foo", 2, 7)] + ); }); - it('variable not defined by un-named query', () => { - expectFailsRule(NoUndefinedVariables, ` + it("variable not defined by un-named query", () => { + expectFailsRule( + NoUndefinedVariables, + ` { field(a: $a) } - `, [ - undefVar('a', 3, 18, '', 2, 7) - ]); + `, + [undefVar("a", 3, 18, "", 2, 7)] + ); }); - it('multiple variables not defined', () => { - expectFailsRule(NoUndefinedVariables, ` + it("multiple variables not defined", () => { + expectFailsRule( + NoUndefinedVariables, + ` query Foo($b: String) { field(a: $a, b: $b, c: $c) } - `, [ - undefVar('a', 3, 18, 'Foo', 2, 7), - undefVar('c', 3, 32, 'Foo', 2, 7) - ]); + `, + [undefVar("a", 3, 18, "Foo", 2, 7), undefVar("c", 3, 32, "Foo", 2, 7)] + ); }); - it('variable in fragment not defined by un-named query', () => { - expectFailsRule(NoUndefinedVariables, ` + it("variable in fragment not defined by un-named query", () => { + expectFailsRule( + NoUndefinedVariables, + ` { ...FragA } fragment FragA on Type { field(a: $a) } - `, [ - undefVar('a', 6, 18, '', 2, 7) - ]); + `, + [undefVar("a", 6, 18, "", 2, 7)] + ); }); - it('variable in fragment not defined by operation', () => { - expectFailsRule(NoUndefinedVariables, ` + it("variable in fragment not defined by operation", () => { + expectFailsRule( + NoUndefinedVariables, + ` query Foo($a: String, $b: String) { ...FragA } @@ -187,13 +215,15 @@ describe('Validate: No undefined variables', () => { fragment FragC on Type { field(c: $c) } - `, [ - undefVar('c', 16, 18, 'Foo', 2, 7) - ]); + `, + [undefVar("c", 16, 18, "Foo", 2, 7)] + ); }); - it('multiple variables in fragments not defined', () => { - expectFailsRule(NoUndefinedVariables, ` + it("multiple variables in fragments not defined", () => { + expectFailsRule( + NoUndefinedVariables, + ` query Foo($b: String) { ...FragA } @@ -210,14 +240,15 @@ describe('Validate: No undefined variables', () => { fragment FragC on Type { field(c: $c) } - `, [ - undefVar('a', 6, 18, 'Foo', 2, 7), - undefVar('c', 16, 18, 'Foo', 2, 7) - ]); + `, + [undefVar("a", 6, 18, "Foo", 2, 7), undefVar("c", 16, 18, "Foo", 2, 7)] + ); }); - it('single variable in fragment not defined by multiple operations', () => { - expectFailsRule(NoUndefinedVariables, ` + it("single variable in fragment not defined by multiple operations", () => { + expectFailsRule( + NoUndefinedVariables, + ` query Foo($a: String) { ...FragAB } @@ -227,14 +258,15 @@ describe('Validate: No undefined variables', () => { fragment FragAB on Type { field(a: $a, b: $b) } - `, [ - undefVar('b', 9, 25, 'Foo', 2, 7), - undefVar('b', 9, 25, 'Bar', 5, 7) - ]); + `, + [undefVar("b", 9, 25, "Foo", 2, 7), undefVar("b", 9, 25, "Bar", 5, 7)] + ); }); - it('variables in fragment not defined by multiple operations', () => { - expectFailsRule(NoUndefinedVariables, ` + it("variables in fragment not defined by multiple operations", () => { + expectFailsRule( + NoUndefinedVariables, + ` query Foo($b: String) { ...FragAB } @@ -244,14 +276,15 @@ describe('Validate: No undefined variables', () => { fragment FragAB on Type { field(a: $a, b: $b) } - `, [ - undefVar('a', 9, 18, 'Foo', 2, 7), - undefVar('b', 9, 25, 'Bar', 5, 7) - ]); + `, + [undefVar("a", 9, 18, "Foo", 2, 7), undefVar("b", 9, 25, "Bar", 5, 7)] + ); }); - it('variable in fragment used by other operation', () => { - expectFailsRule(NoUndefinedVariables, ` + it("variable in fragment used by other operation", () => { + expectFailsRule( + NoUndefinedVariables, + ` query Foo($b: String) { ...FragA } @@ -264,14 +297,15 @@ describe('Validate: No undefined variables', () => { fragment FragB on Type { field(b: $b) } - `, [ - undefVar('a', 9, 18, 'Foo', 2, 7), - undefVar('b', 12, 18, 'Bar', 5, 7) - ]); + `, + [undefVar("a", 9, 18, "Foo", 2, 7), undefVar("b", 12, 18, "Bar", 5, 7)] + ); }); - it('multiple undefined variables produce multiple errors', () => { - expectFailsRule(NoUndefinedVariables, ` + it("multiple undefined variables produce multiple errors", () => { + expectFailsRule( + NoUndefinedVariables, + ` query Foo($b: String) { ...FragAB } @@ -286,14 +320,15 @@ describe('Validate: No undefined variables', () => { fragment FragC on Type { field2(c: $c) } - `, [ - undefVar('a', 9, 19, 'Foo', 2, 7), - undefVar('a', 11, 19, 'Foo', 2, 7), - undefVar('c', 14, 19, 'Foo', 2, 7), - undefVar('b', 9, 26, 'Bar', 5, 7), - undefVar('b', 11, 26, 'Bar', 5, 7), - undefVar('c', 14, 19, 'Bar', 5, 7), - ]); + `, + [ + undefVar("a", 9, 19, "Foo", 2, 7), + undefVar("a", 11, 19, "Foo", 2, 7), + undefVar("c", 14, 19, "Foo", 2, 7), + undefVar("b", 9, 26, "Bar", 5, 7), + undefVar("b", 11, 26, "Bar", 5, 7), + undefVar("c", 14, 19, "Bar", 5, 7) + ] + ); }); - }); diff --git a/src/validation/__tests__/NoUnusedFragments-test.js b/src/validation/__tests__/NoUnusedFragments-test.js index 6e3717623a..05418ca199 100644 --- a/src/validation/__tests__/NoUnusedFragments-test.js +++ b/src/validation/__tests__/NoUnusedFragments-test.js @@ -7,25 +7,25 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { NoUnusedFragments, - unusedFragMessage, -} from '../rules/NoUnusedFragments'; - + unusedFragMessage +} from "../rules/NoUnusedFragments"; function unusedFrag(fragName, line, column) { return { message: unusedFragMessage(fragName), - locations: [ { line, column } ], + locations: [{ line, column }] }; } -describe('Validate: No unused fragments', () => { - - it('all fragment names are used', () => { - expectPassesRule(NoUnusedFragments, ` +describe("Validate: No unused fragments", () => { + it("all fragment names are used", () => { + expectPassesRule( + NoUnusedFragments, + ` { human(id: 4) { ...HumanFields1 @@ -44,12 +44,14 @@ describe('Validate: No unused fragments', () => { fragment HumanFields3 on Human { name } - `); + ` + ); }); - - it('all fragment names are used by multiple operations', () => { - expectPassesRule(NoUnusedFragments, ` + it("all fragment names are used by multiple operations", () => { + expectPassesRule( + NoUnusedFragments, + ` query Foo { human(id: 4) { ...HumanFields1 @@ -70,11 +72,14 @@ describe('Validate: No unused fragments', () => { fragment HumanFields3 on Human { name } - `); + ` + ); }); - it('contains unknown fragments', () => { - expectFailsRule(NoUnusedFragments, ` + it("contains unknown fragments", () => { + expectFailsRule( + NoUnusedFragments, + ` query Foo { human(id: 4) { ...HumanFields1 @@ -101,14 +106,15 @@ describe('Validate: No unused fragments', () => { fragment Unused2 on Human { name } - `, [ - unusedFrag('Unused1', 22, 7), - unusedFrag('Unused2', 25, 7), - ]); + `, + [unusedFrag("Unused1", 22, 7), unusedFrag("Unused2", 25, 7)] + ); }); - it('contains unknown fragments with ref cycle', () => { - expectFailsRule(NoUnusedFragments, ` + it("contains unknown fragments with ref cycle", () => { + expectFailsRule( + NoUnusedFragments, + ` query Foo { human(id: 4) { ...HumanFields1 @@ -137,14 +143,15 @@ describe('Validate: No unused fragments', () => { name ...Unused1 } - `, [ - unusedFrag('Unused1', 22, 7), - unusedFrag('Unused2', 26, 7), - ]); + `, + [unusedFrag("Unused1", 22, 7), unusedFrag("Unused2", 26, 7)] + ); }); - it('contains unknown and undef fragments', () => { - expectFailsRule(NoUnusedFragments, ` + it("contains unknown and undef fragments", () => { + expectFailsRule( + NoUnusedFragments, + ` query Foo { human(id: 4) { ...bar @@ -153,9 +160,8 @@ describe('Validate: No unused fragments', () => { fragment foo on Human { name } - `, [ - unusedFrag('foo', 7, 7), - ]); + `, + [unusedFrag("foo", 7, 7)] + ); }); - }); diff --git a/src/validation/__tests__/NoUnusedVariables-test.js b/src/validation/__tests__/NoUnusedVariables-test.js index 6690e5a9c7..890d26ce26 100644 --- a/src/validation/__tests__/NoUnusedVariables-test.js +++ b/src/validation/__tests__/NoUnusedVariables-test.js @@ -7,33 +7,36 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { NoUnusedVariables, - unusedVariableMessage, -} from '../rules/NoUnusedVariables'; - + unusedVariableMessage +} from "../rules/NoUnusedVariables"; function unusedVar(varName, opName, line, column) { return { message: unusedVariableMessage(varName, opName), - locations: [ { line, column } ], + locations: [{ line, column }] }; } -describe('Validate: No unused variables', () => { - - it('uses all variables', () => { - expectPassesRule(NoUnusedVariables, ` +describe("Validate: No unused variables", () => { + it("uses all variables", () => { + expectPassesRule( + NoUnusedVariables, + ` query ($a: String, $b: String, $c: String) { field(a: $a, b: $b, c: $c) } - `); + ` + ); }); - it('uses all variables deeply', () => { - expectPassesRule(NoUnusedVariables, ` + it("uses all variables deeply", () => { + expectPassesRule( + NoUnusedVariables, + ` query Foo($a: String, $b: String, $c: String) { field(a: $a) { field(b: $b) { @@ -41,11 +44,14 @@ describe('Validate: No unused variables', () => { } } } - `); + ` + ); }); - it('uses all variables deeply in inline fragments', () => { - expectPassesRule(NoUnusedVariables, ` + it("uses all variables deeply in inline fragments", () => { + expectPassesRule( + NoUnusedVariables, + ` query Foo($a: String, $b: String, $c: String) { ... on Type { field(a: $a) { @@ -57,11 +63,14 @@ describe('Validate: No unused variables', () => { } } } - `); + ` + ); }); - it('uses all variables in fragments', () => { - expectPassesRule(NoUnusedVariables, ` + it("uses all variables in fragments", () => { + expectPassesRule( + NoUnusedVariables, + ` query Foo($a: String, $b: String, $c: String) { ...FragA } @@ -78,11 +87,14 @@ describe('Validate: No unused variables', () => { fragment FragC on Type { field(c: $c) } - `); + ` + ); }); - it('variable used by fragment in multiple operations', () => { - expectPassesRule(NoUnusedVariables, ` + it("variable used by fragment in multiple operations", () => { + expectPassesRule( + NoUnusedVariables, + ` query Foo($a: String) { ...FragA } @@ -95,11 +107,14 @@ describe('Validate: No unused variables', () => { fragment FragB on Type { field(b: $b) } - `); + ` + ); }); - it('variable used by recursive fragment', () => { - expectPassesRule(NoUnusedVariables, ` + it("variable used by recursive fragment", () => { + expectPassesRule( + NoUnusedVariables, + ` query Foo($a: String) { ...FragA } @@ -108,32 +123,38 @@ describe('Validate: No unused variables', () => { ...FragA } } - `); + ` + ); }); - it('variable not used', () => { - expectFailsRule(NoUnusedVariables, ` + it("variable not used", () => { + expectFailsRule( + NoUnusedVariables, + ` query ($a: String, $b: String, $c: String) { field(a: $a, b: $b) } - `, [ - unusedVar('c', null, 2, 38) - ]); + `, + [unusedVar("c", null, 2, 38)] + ); }); - it('multiple variables not used', () => { - expectFailsRule(NoUnusedVariables, ` + it("multiple variables not used", () => { + expectFailsRule( + NoUnusedVariables, + ` query Foo($a: String, $b: String, $c: String) { field(b: $b) } - `, [ - unusedVar('a', 'Foo', 2, 17), - unusedVar('c', 'Foo', 2, 41) - ]); + `, + [unusedVar("a", "Foo", 2, 17), unusedVar("c", "Foo", 2, 41)] + ); }); - it('variable not used in fragments', () => { - expectFailsRule(NoUnusedVariables, ` + it("variable not used in fragments", () => { + expectFailsRule( + NoUnusedVariables, + ` query Foo($a: String, $b: String, $c: String) { ...FragA } @@ -150,13 +171,15 @@ describe('Validate: No unused variables', () => { fragment FragC on Type { field } - `, [ - unusedVar('c', 'Foo', 2, 41) - ]); + `, + [unusedVar("c", "Foo", 2, 41)] + ); }); - it('multiple variables not used', () => { - expectFailsRule(NoUnusedVariables, ` + it("multiple variables not used", () => { + expectFailsRule( + NoUnusedVariables, + ` query Foo($a: String, $b: String, $c: String) { ...FragA } @@ -173,14 +196,15 @@ describe('Validate: No unused variables', () => { fragment FragC on Type { field } - `, [ - unusedVar('a', 'Foo', 2, 17), - unusedVar('c', 'Foo', 2, 41) - ]); + `, + [unusedVar("a", "Foo", 2, 17), unusedVar("c", "Foo", 2, 41)] + ); }); - it('variable not used by unreferenced fragment', () => { - expectFailsRule(NoUnusedVariables, ` + it("variable not used by unreferenced fragment", () => { + expectFailsRule( + NoUnusedVariables, + ` query Foo($b: String) { ...FragA } @@ -190,13 +214,15 @@ describe('Validate: No unused variables', () => { fragment FragB on Type { field(b: $b) } - `, [ - unusedVar('b', 'Foo', 2, 17) - ]); + `, + [unusedVar("b", "Foo", 2, 17)] + ); }); - it('variable not used by fragment used by other operation', () => { - expectFailsRule(NoUnusedVariables, ` + it("variable not used by fragment used by other operation", () => { + expectFailsRule( + NoUnusedVariables, + ` query Foo($b: String) { ...FragA } @@ -209,10 +235,8 @@ describe('Validate: No unused variables', () => { fragment FragB on Type { field(b: $b) } - `, [ - unusedVar('b', 'Foo', 2, 17), - unusedVar('a', 'Bar', 5, 17) - ]); + `, + [unusedVar("b", "Foo", 2, 17), unusedVar("a", "Bar", 5, 17)] + ); }); - }); diff --git a/src/validation/__tests__/OverlappingFieldsCanBeMerged-test.js b/src/validation/__tests__/OverlappingFieldsCanBeMerged-test.js index 457a0dad05..adeac8aa7f 100644 --- a/src/validation/__tests__/OverlappingFieldsCanBeMerged-test.js +++ b/src/validation/__tests__/OverlappingFieldsCanBeMerged-test.js @@ -7,17 +7,17 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; +import { describe, it } from "mocha"; import { expectPassesRule, expectFailsRule, expectFailsRuleWithSchema, expectPassesRuleWithSchema -} from './harness'; +} from "./harness"; import { OverlappingFieldsCanBeMerged, - fieldsConflictMessage, -} from '../rules/OverlappingFieldsCanBeMerged'; + fieldsConflictMessage +} from "../rules/OverlappingFieldsCanBeMerged"; import { GraphQLSchema, GraphQLObjectType, @@ -26,97 +26,124 @@ import { GraphQLNonNull, GraphQLInt, GraphQLString, - GraphQLID, -} from '../../type'; - - -describe('Validate: Overlapping fields can be merged', () => { - - it('unique fields', () => { - expectPassesRule(OverlappingFieldsCanBeMerged, ` + GraphQLID +} from "../../type"; + +describe("Validate: Overlapping fields can be merged", () => { + it("unique fields", () => { + expectPassesRule( + OverlappingFieldsCanBeMerged, + ` fragment uniqueFields on Dog { name nickname } - `); + ` + ); }); - it('identical fields', () => { - expectPassesRule(OverlappingFieldsCanBeMerged, ` + it("identical fields", () => { + expectPassesRule( + OverlappingFieldsCanBeMerged, + ` fragment mergeIdenticalFields on Dog { name name } - `); + ` + ); }); - it('identical fields with identical args', () => { - expectPassesRule(OverlappingFieldsCanBeMerged, ` + it("identical fields with identical args", () => { + expectPassesRule( + OverlappingFieldsCanBeMerged, + ` fragment mergeIdenticalFieldsWithIdenticalArgs on Dog { doesKnowCommand(dogCommand: SIT) doesKnowCommand(dogCommand: SIT) } - `); + ` + ); }); - it('identical fields with identical directives', () => { - expectPassesRule(OverlappingFieldsCanBeMerged, ` + it("identical fields with identical directives", () => { + expectPassesRule( + OverlappingFieldsCanBeMerged, + ` fragment mergeSameFieldsWithSameDirectives on Dog { name @include(if: true) name @include(if: true) } - `); + ` + ); }); - it('different args with different aliases', () => { - expectPassesRule(OverlappingFieldsCanBeMerged, ` + it("different args with different aliases", () => { + expectPassesRule( + OverlappingFieldsCanBeMerged, + ` fragment differentArgsWithDifferentAliases on Dog { knowsSit: doesKnowCommand(dogCommand: SIT) knowsDown: doesKnowCommand(dogCommand: DOWN) } - `); + ` + ); }); - it('different directives with different aliases', () => { - expectPassesRule(OverlappingFieldsCanBeMerged, ` + it("different directives with different aliases", () => { + expectPassesRule( + OverlappingFieldsCanBeMerged, + ` fragment differentDirectivesWithDifferentAliases on Dog { nameIfTrue: name @include(if: true) nameIfFalse: name @include(if: false) } - `); + ` + ); }); - it('different skip/include directives accepted', () => { + it("different skip/include directives accepted", () => { // Note: Differing skip/include directives don't create an ambiguous return // value and are acceptable in conditions where differing runtime values // may have the same desired effect of including or skipping a field. - expectPassesRule(OverlappingFieldsCanBeMerged, ` + expectPassesRule( + OverlappingFieldsCanBeMerged, + ` fragment differentDirectivesWithDifferentAliases on Dog { name @include(if: true) name @include(if: false) } - `); + ` + ); }); - it('Same aliases with different field targets', () => { - expectFailsRule(OverlappingFieldsCanBeMerged, ` + it("Same aliases with different field targets", () => { + expectFailsRule( + OverlappingFieldsCanBeMerged, + ` fragment sameAliasesWithDifferentFieldTargets on Dog { fido: name fido: nickname } - `, [ - { message: fieldsConflictMessage( - 'fido', - 'name and nickname are different fields' - ), - locations: [ { line: 3, column: 9 }, { line: 4, column: 9 } ] }, - ]); + `, + [ + { + message: fieldsConflictMessage( + "fido", + "name and nickname are different fields" + ), + locations: [{ line: 3, column: 9 }, { line: 4, column: 9 }] + } + ] + ); }); - it('Same aliases allowed on non-overlapping fields', () => { + it("Same aliases allowed on non-overlapping fields", () => { // This is valid since no object can be both a "Dog" and a "Cat", thus // these fields can never overlap. - expectPassesRule(OverlappingFieldsCanBeMerged, ` + expectPassesRule( + OverlappingFieldsCanBeMerged, + ` fragment sameAliasesWithDifferentFieldTargets on Pet { ... on Dog { name @@ -125,73 +152,100 @@ describe('Validate: Overlapping fields can be merged', () => { name: nickname } } - `); + ` + ); }); - it('Alias masking direct field access', () => { - expectFailsRule(OverlappingFieldsCanBeMerged, ` + it("Alias masking direct field access", () => { + expectFailsRule( + OverlappingFieldsCanBeMerged, + ` fragment aliasMaskingDirectFieldAccess on Dog { name: nickname name } - `, [ - { message: fieldsConflictMessage( - 'name', - 'nickname and name are different fields' - ), - locations: [ { line: 3, column: 9 }, { line: 4, column: 9 } ] }, - ]); + `, + [ + { + message: fieldsConflictMessage( + "name", + "nickname and name are different fields" + ), + locations: [{ line: 3, column: 9 }, { line: 4, column: 9 }] + } + ] + ); }); - it('different args, second adds an argument', () => { - expectFailsRule(OverlappingFieldsCanBeMerged, ` + it("different args, second adds an argument", () => { + expectFailsRule( + OverlappingFieldsCanBeMerged, + ` fragment conflictingArgs on Dog { doesKnowCommand doesKnowCommand(dogCommand: HEEL) } - `, [ - { message: fieldsConflictMessage( - 'doesKnowCommand', - 'they have differing arguments' - ), - locations: [ { line: 3, column: 9 }, { line: 4, column: 9 } ] } - ]); + `, + [ + { + message: fieldsConflictMessage( + "doesKnowCommand", + "they have differing arguments" + ), + locations: [{ line: 3, column: 9 }, { line: 4, column: 9 }] + } + ] + ); }); - it('different args, second missing an argument', () => { - expectFailsRule(OverlappingFieldsCanBeMerged, ` + it("different args, second missing an argument", () => { + expectFailsRule( + OverlappingFieldsCanBeMerged, + ` fragment conflictingArgs on Dog { doesKnowCommand(dogCommand: SIT) doesKnowCommand } - `, [ - { message: fieldsConflictMessage( - 'doesKnowCommand', - 'they have differing arguments' - ), - locations: [ { line: 3, column: 9 }, { line: 4, column: 9 } ] } - ]); + `, + [ + { + message: fieldsConflictMessage( + "doesKnowCommand", + "they have differing arguments" + ), + locations: [{ line: 3, column: 9 }, { line: 4, column: 9 }] + } + ] + ); }); - it('conflicting args', () => { - expectFailsRule(OverlappingFieldsCanBeMerged, ` + it("conflicting args", () => { + expectFailsRule( + OverlappingFieldsCanBeMerged, + ` fragment conflictingArgs on Dog { doesKnowCommand(dogCommand: SIT) doesKnowCommand(dogCommand: HEEL) } - `, [ - { message: fieldsConflictMessage( - 'doesKnowCommand', - 'they have differing arguments' - ), - locations: [ { line: 3, column: 9 }, { line: 4, column: 9 } ] } - ]); + `, + [ + { + message: fieldsConflictMessage( + "doesKnowCommand", + "they have differing arguments" + ), + locations: [{ line: 3, column: 9 }, { line: 4, column: 9 }] + } + ] + ); }); - it('allows different args where no conflict is possible', () => { + it("allows different args where no conflict is possible", () => { // This is valid since no object can be both a "Dog" and a "Cat", thus // these fields can never overlap. - expectPassesRule(OverlappingFieldsCanBeMerged, ` + expectPassesRule( + OverlappingFieldsCanBeMerged, + ` fragment conflictingArgs on Pet { ... on Dog { name(surname: true) @@ -200,11 +254,14 @@ describe('Validate: Overlapping fields can be merged', () => { name } } - `); + ` + ); }); - it('encounters conflict in fragments', () => { - expectFailsRule(OverlappingFieldsCanBeMerged, ` + it("encounters conflict in fragments", () => { + expectFailsRule( + OverlappingFieldsCanBeMerged, + ` { ...A ...B @@ -215,14 +272,20 @@ describe('Validate: Overlapping fields can be merged', () => { fragment B on Type { x: b } - `, [ - { message: fieldsConflictMessage('x', 'a and b are different fields'), - locations: [ { line: 7, column: 9 }, { line: 10, column: 9 } ] } - ]); + `, + [ + { + message: fieldsConflictMessage("x", "a and b are different fields"), + locations: [{ line: 7, column: 9 }, { line: 10, column: 9 }] + } + ] + ); }); - it('reports each conflict once', () => { - expectFailsRule(OverlappingFieldsCanBeMerged, ` + it("reports each conflict once", () => { + expectFailsRule( + OverlappingFieldsCanBeMerged, + ` { f1 { ...A @@ -244,18 +307,28 @@ describe('Validate: Overlapping fields can be merged', () => { fragment B on Type { x: b } - `, [ - { message: fieldsConflictMessage('x', 'a and b are different fields'), - locations: [ { line: 18, column: 9 }, { line: 21, column: 9 } ] }, - { message: fieldsConflictMessage('x', 'a and c are different fields'), - locations: [ { line: 18, column: 9 }, { line: 14, column: 11 } ] }, - { message: fieldsConflictMessage('x', 'b and c are different fields'), - locations: [ { line: 21, column: 9 }, { line: 14, column: 11 } ] } - ]); + `, + [ + { + message: fieldsConflictMessage("x", "a and b are different fields"), + locations: [{ line: 18, column: 9 }, { line: 21, column: 9 }] + }, + { + message: fieldsConflictMessage("x", "a and c are different fields"), + locations: [{ line: 18, column: 9 }, { line: 14, column: 11 }] + }, + { + message: fieldsConflictMessage("x", "b and c are different fields"), + locations: [{ line: 21, column: 9 }, { line: 14, column: 11 }] + } + ] + ); }); - it('deep conflict', () => { - expectFailsRule(OverlappingFieldsCanBeMerged, ` + it("deep conflict", () => { + expectFailsRule( + OverlappingFieldsCanBeMerged, + ` { field { x: a @@ -264,20 +337,27 @@ describe('Validate: Overlapping fields can be merged', () => { x: b } } - `, [ - { message: fieldsConflictMessage( - 'field', [ [ 'x', 'a and b are different fields' ] ] - ), - locations: [ - { line: 3, column: 9 }, - { line: 4, column: 11 }, - { line: 6, column: 9 }, - { line: 7, column: 11 } ] }, - ]); + `, + [ + { + message: fieldsConflictMessage("field", [ + ["x", "a and b are different fields"] + ]), + locations: [ + { line: 3, column: 9 }, + { line: 4, column: 11 }, + { line: 6, column: 9 }, + { line: 7, column: 11 } + ] + } + ] + ); }); - it('deep conflict with multiple issues', () => { - expectFailsRule(OverlappingFieldsCanBeMerged, ` + it("deep conflict with multiple issues", () => { + expectFailsRule( + OverlappingFieldsCanBeMerged, + ` { field { x: a @@ -288,25 +368,30 @@ describe('Validate: Overlapping fields can be merged', () => { y: d } } - `, [ - { message: fieldsConflictMessage( - 'field', [ - [ 'x', 'a and b are different fields' ], - [ 'y', 'c and d are different fields' ] + `, + [ + { + message: fieldsConflictMessage("field", [ + ["x", "a and b are different fields"], + ["y", "c and d are different fields"] + ]), + locations: [ + { line: 3, column: 9 }, + { line: 4, column: 11 }, + { line: 5, column: 11 }, + { line: 7, column: 9 }, + { line: 8, column: 11 }, + { line: 9, column: 11 } ] - ), - locations: [ - { line: 3, column: 9 }, - { line: 4, column: 11 }, - { line: 5, column: 11 }, - { line: 7, column: 9 }, - { line: 8, column: 11 }, - { line: 9, column: 11 } ] }, - ]); + } + ] + ); }); - it('very deep conflict', () => { - expectFailsRule(OverlappingFieldsCanBeMerged, ` + it("very deep conflict", () => { + expectFailsRule( + OverlappingFieldsCanBeMerged, + ` { field { deepField { @@ -319,23 +404,29 @@ describe('Validate: Overlapping fields can be merged', () => { } } } - `, [ - { message: fieldsConflictMessage( - 'field', - [ [ 'deepField', [ [ 'x', 'a and b are different fields' ] ] ] ] - ), - locations: [ - { line: 3, column: 9 }, - { line: 4, column: 11 }, - { line: 5, column: 13 }, - { line: 8, column: 9 }, - { line: 9, column: 11 }, - { line: 10, column: 13 } ] }, - ]); + `, + [ + { + message: fieldsConflictMessage("field", [ + ["deepField", [["x", "a and b are different fields"]]] + ]), + locations: [ + { line: 3, column: 9 }, + { line: 4, column: 11 }, + { line: 5, column: 13 }, + { line: 8, column: 9 }, + { line: 9, column: 11 }, + { line: 10, column: 13 } + ] + } + ] + ); }); - it('reports deep conflict to nearest common ancestor', () => { - expectFailsRule(OverlappingFieldsCanBeMerged, ` + it("reports deep conflict to nearest common ancestor", () => { + expectFailsRule( + OverlappingFieldsCanBeMerged, + ` { field { deepField { @@ -351,22 +442,26 @@ describe('Validate: Overlapping fields can be merged', () => { } } } - `, [ - { message: fieldsConflictMessage( - 'deepField', [ [ 'x', 'a and b are different fields' ] ] - ), - locations: [ - { line: 4, column: 11 }, - { line: 5, column: 13 }, - { line: 7, column: 11 }, - { line: 8, column: 13 } ] }, - ]); + `, + [ + { + message: fieldsConflictMessage("deepField", [ + ["x", "a and b are different fields"] + ]), + locations: [ + { line: 4, column: 11 }, + { line: 5, column: 13 }, + { line: 7, column: 11 }, + { line: 8, column: 13 } + ] + } + ] + ); }); - describe('return types must be unambiguous', () => { - + describe("return types must be unambiguous", () => { const SomeBox = new GraphQLInterfaceType({ - name: 'SomeBox', + name: "SomeBox", resolveType: () => StringBox, fields: () => ({ deepBox: { type: SomeBox }, @@ -375,33 +470,33 @@ describe('Validate: Overlapping fields can be merged', () => { }); const StringBox = new GraphQLObjectType({ - name: 'StringBox', - interfaces: [ SomeBox ], + name: "StringBox", + interfaces: [SomeBox], fields: () => ({ scalar: { type: GraphQLString }, deepBox: { type: StringBox }, unrelatedField: { type: GraphQLString }, listStringBox: { type: new GraphQLList(StringBox) }, stringBox: { type: StringBox }, - intBox: { type: IntBox }, + intBox: { type: IntBox } }) }); const IntBox = new GraphQLObjectType({ - name: 'IntBox', - interfaces: [ SomeBox ], + name: "IntBox", + interfaces: [SomeBox], fields: () => ({ scalar: { type: GraphQLInt }, deepBox: { type: IntBox }, unrelatedField: { type: GraphQLString }, listStringBox: { type: new GraphQLList(StringBox) }, stringBox: { type: StringBox }, - intBox: { type: IntBox }, + intBox: { type: IntBox } }) }); const NonNullStringBox1 = new GraphQLInterfaceType({ - name: 'NonNullStringBox1', + name: "NonNullStringBox1", resolveType: () => StringBox, fields: { scalar: { type: new GraphQLNonNull(GraphQLString) } @@ -409,17 +504,17 @@ describe('Validate: Overlapping fields can be merged', () => { }); const NonNullStringBox1Impl = new GraphQLObjectType({ - name: 'NonNullStringBox1Impl', - interfaces: [ SomeBox, NonNullStringBox1 ], + name: "NonNullStringBox1Impl", + interfaces: [SomeBox, NonNullStringBox1], fields: { scalar: { type: new GraphQLNonNull(GraphQLString) }, unrelatedField: { type: GraphQLString }, - deepBox: { type: SomeBox }, + deepBox: { type: SomeBox } } }); const NonNullStringBox2 = new GraphQLInterfaceType({ - name: 'NonNullStringBox2', + name: "NonNullStringBox2", resolveType: () => StringBox, fields: { scalar: { type: new GraphQLNonNull(GraphQLString) } @@ -427,54 +522,59 @@ describe('Validate: Overlapping fields can be merged', () => { }); const NonNullStringBox2Impl = new GraphQLObjectType({ - name: 'NonNullStringBox2Impl', - interfaces: [ SomeBox, NonNullStringBox2 ], + name: "NonNullStringBox2Impl", + interfaces: [SomeBox, NonNullStringBox2], fields: { scalar: { type: new GraphQLNonNull(GraphQLString) }, unrelatedField: { type: GraphQLString }, - deepBox: { type: SomeBox }, + deepBox: { type: SomeBox } } }); const Connection = new GraphQLObjectType({ - name: 'Connection', + name: "Connection", fields: { edges: { - type: new GraphQLList(new GraphQLObjectType({ - name: 'Edge', - fields: { - node: { - type: new GraphQLObjectType({ - name: 'Node', - fields: { - id: { type: GraphQLID }, - name: { type: GraphQLString } - } - }) + type: new GraphQLList( + new GraphQLObjectType({ + name: "Edge", + fields: { + node: { + type: new GraphQLObjectType({ + name: "Node", + fields: { + id: { type: GraphQLID }, + name: { type: GraphQLString } + } + }) + } } - } - })) + }) + ) } } }); const schema = new GraphQLSchema({ query: new GraphQLObjectType({ - name: 'QueryRoot', + name: "QueryRoot", fields: () => ({ someBox: { type: SomeBox }, connection: { type: Connection } }) }), - types: [ IntBox, StringBox, NonNullStringBox1Impl, NonNullStringBox2Impl ] + types: [IntBox, StringBox, NonNullStringBox1Impl, NonNullStringBox2Impl] }); - it('conflicting return types which potentially overlap', () => { + it("conflicting return types which potentially overlap", () => { // This is invalid since an object could potentially be both the Object // type IntBox and the interface type NonNullStringBox1. While that // condition does not exist in the current schema, the schema could // expand in the future to allow this. Thus it is invalid. - expectFailsRuleWithSchema(schema, OverlappingFieldsCanBeMerged, ` + expectFailsRuleWithSchema( + schema, + OverlappingFieldsCanBeMerged, + ` { someBox { ...on IntBox { @@ -485,20 +585,27 @@ describe('Validate: Overlapping fields can be merged', () => { } } } - `, [ - { message: fieldsConflictMessage( - 'scalar', - 'they return conflicting types Int and String!' - ), - locations: [ { line: 5, column: 15 }, { line: 8, column: 15 } ] } - ]); + `, + [ + { + message: fieldsConflictMessage( + "scalar", + "they return conflicting types Int and String!" + ), + locations: [{ line: 5, column: 15 }, { line: 8, column: 15 }] + } + ] + ); }); - it('compatible return shapes on different return types', () => { + it("compatible return shapes on different return types", () => { // In this case `deepBox` returns `SomeBox` in the first usage, and // `StringBox` in the second usage. These return types are not the same! // however this is valid because the return *shapes* are compatible. - expectPassesRuleWithSchema(schema, OverlappingFieldsCanBeMerged, ` + expectPassesRuleWithSchema( + schema, + OverlappingFieldsCanBeMerged, + ` { someBox { ... on SomeBox { @@ -513,11 +620,15 @@ describe('Validate: Overlapping fields can be merged', () => { } } } - `); + ` + ); }); - it('disallows differing return types despite no overlap', () => { - expectFailsRuleWithSchema(schema, OverlappingFieldsCanBeMerged, ` + it("disallows differing return types despite no overlap", () => { + expectFailsRuleWithSchema( + schema, + OverlappingFieldsCanBeMerged, + ` { someBox { ... on IntBox { @@ -528,17 +639,24 @@ describe('Validate: Overlapping fields can be merged', () => { } } } - `, [ - { message: fieldsConflictMessage( - 'scalar', - 'they return conflicting types Int and String' - ), - locations: [ { line: 5, column: 15 }, { line: 8, column: 15 } ] } - ]); + `, + [ + { + message: fieldsConflictMessage( + "scalar", + "they return conflicting types Int and String" + ), + locations: [{ line: 5, column: 15 }, { line: 8, column: 15 }] + } + ] + ); }); - it('disallows differing return type nullability despite no overlap', () => { - expectFailsRuleWithSchema(schema, OverlappingFieldsCanBeMerged, ` + it("disallows differing return type nullability despite no overlap", () => { + expectFailsRuleWithSchema( + schema, + OverlappingFieldsCanBeMerged, + ` { someBox { ... on NonNullStringBox1 { @@ -549,17 +667,24 @@ describe('Validate: Overlapping fields can be merged', () => { } } } - `, [ - { message: fieldsConflictMessage( - 'scalar', - 'they return conflicting types String! and String' - ), - locations: [ { line: 5, column: 15 }, { line: 8, column: 15 } ] } - ]); + `, + [ + { + message: fieldsConflictMessage( + "scalar", + "they return conflicting types String! and String" + ), + locations: [{ line: 5, column: 15 }, { line: 8, column: 15 }] + } + ] + ); }); - it('disallows differing return type list despite no overlap', () => { - expectFailsRuleWithSchema(schema, OverlappingFieldsCanBeMerged, ` + it("disallows differing return type list despite no overlap", () => { + expectFailsRuleWithSchema( + schema, + OverlappingFieldsCanBeMerged, + ` { someBox { ... on IntBox { @@ -574,15 +699,22 @@ describe('Validate: Overlapping fields can be merged', () => { } } } - `, [ - { message: fieldsConflictMessage( - 'box', - 'they return conflicting types [StringBox] and StringBox' - ), - locations: [ { line: 5, column: 15 }, { line: 10, column: 15 } ] } - ]); + `, + [ + { + message: fieldsConflictMessage( + "box", + "they return conflicting types [StringBox] and StringBox" + ), + locations: [{ line: 5, column: 15 }, { line: 10, column: 15 }] + } + ] + ); - expectFailsRuleWithSchema(schema, OverlappingFieldsCanBeMerged, ` + expectFailsRuleWithSchema( + schema, + OverlappingFieldsCanBeMerged, + ` { someBox { ... on IntBox { @@ -597,17 +729,24 @@ describe('Validate: Overlapping fields can be merged', () => { } } } - `, [ - { message: fieldsConflictMessage( - 'box', - 'they return conflicting types StringBox and [StringBox]' - ), - locations: [ { line: 5, column: 15 }, { line: 10, column: 15 } ] } - ]); + `, + [ + { + message: fieldsConflictMessage( + "box", + "they return conflicting types StringBox and [StringBox]" + ), + locations: [{ line: 5, column: 15 }, { line: 10, column: 15 }] + } + ] + ); }); - it('disallows differing subfields', () => { - expectFailsRuleWithSchema(schema, OverlappingFieldsCanBeMerged, ` + it("disallows differing subfields", () => { + expectFailsRuleWithSchema( + schema, + OverlappingFieldsCanBeMerged, + ` { someBox { ... on IntBox { @@ -623,17 +762,24 @@ describe('Validate: Overlapping fields can be merged', () => { } } } - `, [ - { message: fieldsConflictMessage( - 'val', - 'scalar and unrelatedField are different fields' - ), - locations: [ { line: 6, column: 17 }, { line: 7, column: 17 } ] } - ]); + `, + [ + { + message: fieldsConflictMessage( + "val", + "scalar and unrelatedField are different fields" + ), + locations: [{ line: 6, column: 17 }, { line: 7, column: 17 }] + } + ] + ); }); - it('disallows differing deep return types despite no overlap', () => { - expectFailsRuleWithSchema(schema, OverlappingFieldsCanBeMerged, ` + it("disallows differing deep return types despite no overlap", () => { + expectFailsRuleWithSchema( + schema, + OverlappingFieldsCanBeMerged, + ` { someBox { ... on IntBox { @@ -648,21 +794,28 @@ describe('Validate: Overlapping fields can be merged', () => { } } } - `, [ - { message: fieldsConflictMessage( - 'box', - [ [ 'scalar', 'they return conflicting types String and Int' ] ] - ), - locations: [ - { line: 5, column: 15 }, - { line: 6, column: 17 }, - { line: 10, column: 15 }, - { line: 11, column: 17 } ] } - ]); + `, + [ + { + message: fieldsConflictMessage("box", [ + ["scalar", "they return conflicting types String and Int"] + ]), + locations: [ + { line: 5, column: 15 }, + { line: 6, column: 17 }, + { line: 10, column: 15 }, + { line: 11, column: 17 } + ] + } + ] + ); }); - it('allows non-conflicting overlaping types', () => { - expectPassesRuleWithSchema(schema, OverlappingFieldsCanBeMerged, ` + it("allows non-conflicting overlaping types", () => { + expectPassesRuleWithSchema( + schema, + OverlappingFieldsCanBeMerged, + ` { someBox { ... on IntBox { @@ -673,11 +826,15 @@ describe('Validate: Overlapping fields can be merged', () => { } } } - `); + ` + ); }); - it('same wrapped scalar return types', () => { - expectPassesRuleWithSchema(schema, OverlappingFieldsCanBeMerged, ` + it("same wrapped scalar return types", () => { + expectPassesRuleWithSchema( + schema, + OverlappingFieldsCanBeMerged, + ` { someBox { ...on NonNullStringBox1 { @@ -688,22 +845,30 @@ describe('Validate: Overlapping fields can be merged', () => { } } } - `); + ` + ); }); - it('allows inline typeless fragments', () => { - expectPassesRuleWithSchema(schema, OverlappingFieldsCanBeMerged, ` + it("allows inline typeless fragments", () => { + expectPassesRuleWithSchema( + schema, + OverlappingFieldsCanBeMerged, + ` { a ... { a } } - `); + ` + ); }); - it('compares deep types including list', () => { - expectFailsRuleWithSchema(schema, OverlappingFieldsCanBeMerged, ` + it("compares deep types including list", () => { + expectFailsRuleWithSchema( + schema, + OverlappingFieldsCanBeMerged, + ` { connection { ...edgeID @@ -722,24 +887,30 @@ describe('Validate: Overlapping fields can be merged', () => { } } } - `, [ - { message: fieldsConflictMessage( - 'edges', - [ [ 'node', [ [ 'id', 'id and name are different fields' ] ] ] ] - ), - locations: [ - { line: 14, column: 11 }, - { line: 15, column: 13 }, - { line: 16, column: 15 }, - { line: 5, column: 13 }, - { line: 6, column: 15 }, - { line: 7, column: 17 }, - ] } - ]); + `, + [ + { + message: fieldsConflictMessage("edges", [ + ["node", [["id", "id and name are different fields"]]] + ]), + locations: [ + { line: 14, column: 11 }, + { line: 15, column: 13 }, + { line: 16, column: 15 }, + { line: 5, column: 13 }, + { line: 6, column: 15 }, + { line: 7, column: 17 } + ] + } + ] + ); }); - it('ignores unknown types', () => { - expectPassesRuleWithSchema(schema, OverlappingFieldsCanBeMerged, ` + it("ignores unknown types", () => { + expectPassesRuleWithSchema( + schema, + OverlappingFieldsCanBeMerged, + ` { someBox { ...on UnknownType { @@ -750,9 +921,8 @@ describe('Validate: Overlapping fields can be merged', () => { } } } - `); + ` + ); }); - }); - }); diff --git a/src/validation/__tests__/PossibleFragmentSpreads-test.js b/src/validation/__tests__/PossibleFragmentSpreads-test.js index 2ae10608c1..529cca73d6 100644 --- a/src/validation/__tests__/PossibleFragmentSpreads-test.js +++ b/src/validation/__tests__/PossibleFragmentSpreads-test.js @@ -7,185 +7,259 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { PossibleFragmentSpreads, typeIncompatibleSpreadMessage, - typeIncompatibleAnonSpreadMessage, -} from '../rules/PossibleFragmentSpreads'; - + typeIncompatibleAnonSpreadMessage +} from "../rules/PossibleFragmentSpreads"; function error(fragName, parentType, fragType, line, column) { return { message: typeIncompatibleSpreadMessage(fragName, parentType, fragType), - locations: [ { line, column } ], + locations: [{ line, column }] }; } function errorAnon(parentType, fragType, line, column) { return { message: typeIncompatibleAnonSpreadMessage(parentType, fragType), - locations: [ { line, column } ], + locations: [{ line, column }] }; } -describe('Validate: Possible fragment spreads', () => { - - it('of the same object', () => { - expectPassesRule(PossibleFragmentSpreads, ` +describe("Validate: Possible fragment spreads", () => { + it("of the same object", () => { + expectPassesRule( + PossibleFragmentSpreads, + ` fragment objectWithinObject on Dog { ...dogFragment } fragment dogFragment on Dog { barkVolume } - `); + ` + ); }); - it('of the same object with inline fragment', () => { - expectPassesRule(PossibleFragmentSpreads, ` + it("of the same object with inline fragment", () => { + expectPassesRule( + PossibleFragmentSpreads, + ` fragment objectWithinObjectAnon on Dog { ... on Dog { barkVolume } } - `); + ` + ); }); - it('object into an implemented interface', () => { - expectPassesRule(PossibleFragmentSpreads, ` + it("object into an implemented interface", () => { + expectPassesRule( + PossibleFragmentSpreads, + ` fragment objectWithinInterface on Pet { ...dogFragment } fragment dogFragment on Dog { barkVolume } - `); + ` + ); }); - it('object into containing union', () => { - expectPassesRule(PossibleFragmentSpreads, ` + it("object into containing union", () => { + expectPassesRule( + PossibleFragmentSpreads, + ` fragment objectWithinUnion on CatOrDog { ...dogFragment } fragment dogFragment on Dog { barkVolume } - `); + ` + ); }); - it('union into contained object', () => { - expectPassesRule(PossibleFragmentSpreads, ` + it("union into contained object", () => { + expectPassesRule( + PossibleFragmentSpreads, + ` fragment unionWithinObject on Dog { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } - `); + ` + ); }); - it('union into overlapping interface', () => { - expectPassesRule(PossibleFragmentSpreads, ` + it("union into overlapping interface", () => { + expectPassesRule( + PossibleFragmentSpreads, + ` fragment unionWithinInterface on Pet { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } - `); + ` + ); }); - it('union into overlapping union', () => { - expectPassesRule(PossibleFragmentSpreads, ` + it("union into overlapping union", () => { + expectPassesRule( + PossibleFragmentSpreads, + ` fragment unionWithinUnion on DogOrHuman { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } - `); + ` + ); }); - it('interface into implemented object', () => { - expectPassesRule(PossibleFragmentSpreads, ` + it("interface into implemented object", () => { + expectPassesRule( + PossibleFragmentSpreads, + ` fragment interfaceWithinObject on Dog { ...petFragment } fragment petFragment on Pet { name } - `); + ` + ); }); - it('interface into overlapping interface', () => { - expectPassesRule(PossibleFragmentSpreads, ` + it("interface into overlapping interface", () => { + expectPassesRule( + PossibleFragmentSpreads, + ` fragment interfaceWithinInterface on Pet { ...beingFragment } fragment beingFragment on Being { name } - `); + ` + ); }); - it('interface into overlapping interface in inline fragment', () => { - expectPassesRule(PossibleFragmentSpreads, ` + it("interface into overlapping interface in inline fragment", () => { + expectPassesRule( + PossibleFragmentSpreads, + ` fragment interfaceWithinInterface on Pet { ... on Being { name } } - `); + ` + ); }); - it('interface into overlapping union', () => { - expectPassesRule(PossibleFragmentSpreads, ` + it("interface into overlapping union", () => { + expectPassesRule( + PossibleFragmentSpreads, + ` fragment interfaceWithinUnion on CatOrDog { ...petFragment } fragment petFragment on Pet { name } - `); + ` + ); }); - it('different object into object', () => { - expectFailsRule(PossibleFragmentSpreads, ` + it("different object into object", () => { + expectFailsRule( + PossibleFragmentSpreads, + ` fragment invalidObjectWithinObject on Cat { ...dogFragment } fragment dogFragment on Dog { barkVolume } - `, [ error('dogFragment', 'Cat', 'Dog', 2, 51) ]); + `, + [error("dogFragment", "Cat", "Dog", 2, 51)] + ); }); - it('different object into object in inline fragment', () => { - expectFailsRule(PossibleFragmentSpreads, ` + it("different object into object in inline fragment", () => { + expectFailsRule( + PossibleFragmentSpreads, + ` fragment invalidObjectWithinObjectAnon on Cat { ... on Dog { barkVolume } } - `, [ errorAnon('Cat', 'Dog', 3, 9) ]); + `, + [errorAnon("Cat", "Dog", 3, 9)] + ); }); - it('object into not implementing interface', () => { - expectFailsRule(PossibleFragmentSpreads, ` + it("object into not implementing interface", () => { + expectFailsRule( + PossibleFragmentSpreads, + ` fragment invalidObjectWithinInterface on Pet { ...humanFragment } fragment humanFragment on Human { pets { name } } - `, [ error('humanFragment', 'Pet', 'Human', 2, 54) ]); + `, + [error("humanFragment", "Pet", "Human", 2, 54)] + ); }); - it('object into not containing union', () => { - expectFailsRule(PossibleFragmentSpreads, ` + it("object into not containing union", () => { + expectFailsRule( + PossibleFragmentSpreads, + ` fragment invalidObjectWithinUnion on CatOrDog { ...humanFragment } fragment humanFragment on Human { pets { name } } - `, [ error('humanFragment', 'CatOrDog', 'Human', 2, 55) ]); + `, + [error("humanFragment", "CatOrDog", "Human", 2, 55)] + ); }); - it('union into not contained object', () => { - expectFailsRule(PossibleFragmentSpreads, ` + it("union into not contained object", () => { + expectFailsRule( + PossibleFragmentSpreads, + ` fragment invalidUnionWithinObject on Human { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } - `, [ error('catOrDogFragment', 'Human', 'CatOrDog', 2, 52) ]); + `, + [error("catOrDogFragment", "Human", "CatOrDog", 2, 52)] + ); }); - it('union into non overlapping interface', () => { - expectFailsRule(PossibleFragmentSpreads, ` + it("union into non overlapping interface", () => { + expectFailsRule( + PossibleFragmentSpreads, + ` fragment invalidUnionWithinInterface on Pet { ...humanOrAlienFragment } fragment humanOrAlienFragment on HumanOrAlien { __typename } - `, [ error('humanOrAlienFragment', 'Pet', 'HumanOrAlien', 2, 53) ]); + `, + [error("humanOrAlienFragment", "Pet", "HumanOrAlien", 2, 53)] + ); }); - it('union into non overlapping union', () => { - expectFailsRule(PossibleFragmentSpreads, ` + it("union into non overlapping union", () => { + expectFailsRule( + PossibleFragmentSpreads, + ` fragment invalidUnionWithinUnion on CatOrDog { ...humanOrAlienFragment } fragment humanOrAlienFragment on HumanOrAlien { __typename } - `, [ error('humanOrAlienFragment', 'CatOrDog', 'HumanOrAlien', 2, 54) ]); + `, + [error("humanOrAlienFragment", "CatOrDog", "HumanOrAlien", 2, 54)] + ); }); - it('interface into non implementing object', () => { - expectFailsRule(PossibleFragmentSpreads, ` + it("interface into non implementing object", () => { + expectFailsRule( + PossibleFragmentSpreads, + ` fragment invalidInterfaceWithinObject on Cat { ...intelligentFragment } fragment intelligentFragment on Intelligent { iq } - `, [ error('intelligentFragment', 'Cat', 'Intelligent', 2, 54) ]); + `, + [error("intelligentFragment", "Cat", "Intelligent", 2, 54)] + ); }); - it('interface into non overlapping interface', () => { - expectFailsRule(PossibleFragmentSpreads, ` + it("interface into non overlapping interface", () => { + expectFailsRule( + PossibleFragmentSpreads, + ` fragment invalidInterfaceWithinInterface on Pet { ...intelligentFragment } fragment intelligentFragment on Intelligent { iq } - `, [ error('intelligentFragment', 'Pet', 'Intelligent', 3, 9) ]); + `, + [error("intelligentFragment", "Pet", "Intelligent", 3, 9)] + ); }); - it('interface into non overlapping interface in inline fragment', () => { - expectFailsRule(PossibleFragmentSpreads, ` + it("interface into non overlapping interface in inline fragment", () => { + expectFailsRule( + PossibleFragmentSpreads, + ` fragment invalidInterfaceWithinInterfaceAnon on Pet { ...on Intelligent { iq } } - `, [ errorAnon('Pet', 'Intelligent', 3, 9) ]); + `, + [errorAnon("Pet", "Intelligent", 3, 9)] + ); }); - it('interface into non overlapping union', () => { - expectFailsRule(PossibleFragmentSpreads, ` + it("interface into non overlapping union", () => { + expectFailsRule( + PossibleFragmentSpreads, + ` fragment invalidInterfaceWithinUnion on HumanOrAlien { ...petFragment } fragment petFragment on Pet { name } - `, [ error('petFragment', 'HumanOrAlien', 'Pet', 2, 62) ]); + `, + [error("petFragment", "HumanOrAlien", "Pet", 2, 62)] + ); }); - }); diff --git a/src/validation/__tests__/ProvidedNonNullArguments-test.js b/src/validation/__tests__/ProvidedNonNullArguments-test.js index 8c4ed83f3b..df7c231b75 100644 --- a/src/validation/__tests__/ProvidedNonNullArguments-test.js +++ b/src/validation/__tests__/ProvidedNonNullArguments-test.js @@ -7,199 +7,237 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { ProvidedNonNullArguments, missingFieldArgMessage, - missingDirectiveArgMessage, -} from '../rules/ProvidedNonNullArguments'; - + missingDirectiveArgMessage +} from "../rules/ProvidedNonNullArguments"; function missingFieldArg(fieldName, argName, typeName, line, column) { return { message: missingFieldArgMessage(fieldName, argName, typeName), - locations: [ { line, column } ], + locations: [{ line, column }] }; } function missingDirectiveArg(directiveName, argName, typeName, line, column) { return { message: missingDirectiveArgMessage(directiveName, argName, typeName), - locations: [ { line, column } ], + locations: [{ line, column }] }; } -describe('Validate: Provided required arguments', () => { - - it('ignores unknown arguments', () => { - expectPassesRule(ProvidedNonNullArguments, ` +describe("Validate: Provided required arguments", () => { + it("ignores unknown arguments", () => { + expectPassesRule( + ProvidedNonNullArguments, + ` { dog { isHousetrained(unknownArgument: true) } } - `); + ` + ); }); - describe('Valid non-nullable value', () => { - - it('Arg on optional arg', () => { - expectPassesRule(ProvidedNonNullArguments, ` + describe("Valid non-nullable value", () => { + it("Arg on optional arg", () => { + expectPassesRule( + ProvidedNonNullArguments, + ` { dog { isHousetrained(atOtherHomes: true) } } - `); + ` + ); }); - it('No Arg on optional arg', () => { - expectPassesRule(ProvidedNonNullArguments, ` + it("No Arg on optional arg", () => { + expectPassesRule( + ProvidedNonNullArguments, + ` { dog { isHousetrained } } - `); + ` + ); }); - it('Multiple args', () => { - expectPassesRule(ProvidedNonNullArguments, ` + it("Multiple args", () => { + expectPassesRule( + ProvidedNonNullArguments, + ` { complicatedArgs { multipleReqs(req1: 1, req2: 2) } } - `); + ` + ); }); - it('Multiple args reverse order', () => { - expectPassesRule(ProvidedNonNullArguments, ` + it("Multiple args reverse order", () => { + expectPassesRule( + ProvidedNonNullArguments, + ` { complicatedArgs { multipleReqs(req2: 2, req1: 1) } } - `); + ` + ); }); - it('No args on multiple optional', () => { - expectPassesRule(ProvidedNonNullArguments, ` + it("No args on multiple optional", () => { + expectPassesRule( + ProvidedNonNullArguments, + ` { complicatedArgs { multipleOpts } } - `); + ` + ); }); - it('One arg on multiple optional', () => { - expectPassesRule(ProvidedNonNullArguments, ` + it("One arg on multiple optional", () => { + expectPassesRule( + ProvidedNonNullArguments, + ` { complicatedArgs { multipleOpts(opt1: 1) } } - `); + ` + ); }); - it('Second arg on multiple optional', () => { - expectPassesRule(ProvidedNonNullArguments, ` + it("Second arg on multiple optional", () => { + expectPassesRule( + ProvidedNonNullArguments, + ` { complicatedArgs { multipleOpts(opt2: 1) } } - `); + ` + ); }); - it('Multiple reqs on mixedList', () => { - expectPassesRule(ProvidedNonNullArguments, ` + it("Multiple reqs on mixedList", () => { + expectPassesRule( + ProvidedNonNullArguments, + ` { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4) } } - `); + ` + ); }); - it('Multiple reqs and one opt on mixedList', () => { - expectPassesRule(ProvidedNonNullArguments, ` + it("Multiple reqs and one opt on mixedList", () => { + expectPassesRule( + ProvidedNonNullArguments, + ` { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4, opt1: 5) } } - `); + ` + ); }); - it('All reqs and opts on mixedList', () => { - expectPassesRule(ProvidedNonNullArguments, ` + it("All reqs and opts on mixedList", () => { + expectPassesRule( + ProvidedNonNullArguments, + ` { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4, opt1: 5, opt2: 6) } } - `); + ` + ); }); - }); - - describe('Invalid non-nullable value', () => { - - it('Missing one non-nullable argument', () => { - expectFailsRule(ProvidedNonNullArguments, ` + describe("Invalid non-nullable value", () => { + it("Missing one non-nullable argument", () => { + expectFailsRule( + ProvidedNonNullArguments, + ` { complicatedArgs { multipleReqs(req2: 2) } } - `, [ - missingFieldArg('multipleReqs', 'req1', 'Int!', 4, 13) - ]); + `, + [missingFieldArg("multipleReqs", "req1", "Int!", 4, 13)] + ); }); - it('Missing multiple non-nullable arguments', () => { - expectFailsRule(ProvidedNonNullArguments, ` + it("Missing multiple non-nullable arguments", () => { + expectFailsRule( + ProvidedNonNullArguments, + ` { complicatedArgs { multipleReqs } } - `, [ - missingFieldArg('multipleReqs', 'req1', 'Int!', 4, 13), - missingFieldArg('multipleReqs', 'req2', 'Int!', 4, 13), - ]); + `, + [ + missingFieldArg("multipleReqs", "req1", "Int!", 4, 13), + missingFieldArg("multipleReqs", "req2", "Int!", 4, 13) + ] + ); }); - it('Incorrect value and missing argument', () => { - expectFailsRule(ProvidedNonNullArguments, ` + it("Incorrect value and missing argument", () => { + expectFailsRule( + ProvidedNonNullArguments, + ` { complicatedArgs { multipleReqs(req1: "one") } } - `, [ - missingFieldArg('multipleReqs', 'req2', 'Int!', 4, 13), - ]); + `, + [missingFieldArg("multipleReqs", "req2", "Int!", 4, 13)] + ); }); - }); - describe('Directive arguments', () => { - - it('ignores unknown directives', () => { - expectPassesRule(ProvidedNonNullArguments, ` + describe("Directive arguments", () => { + it("ignores unknown directives", () => { + expectPassesRule( + ProvidedNonNullArguments, + ` { dog @unknown } - `); + ` + ); }); - it('with directives of valid types', () => { - expectPassesRule(ProvidedNonNullArguments, ` + it("with directives of valid types", () => { + expectPassesRule( + ProvidedNonNullArguments, + ` { dog @include(if: true) { name @@ -208,22 +246,25 @@ describe('Validate: Provided required arguments', () => { name } } - `); + ` + ); }); - it('with directive with missing types', () => { - expectFailsRule(ProvidedNonNullArguments, ` + it("with directive with missing types", () => { + expectFailsRule( + ProvidedNonNullArguments, + ` { dog @include { name @skip } } - `, [ - missingDirectiveArg('include', 'if', 'Boolean!', 3, 15), - missingDirectiveArg('skip', 'if', 'Boolean!', 4, 18) - ]); + `, + [ + missingDirectiveArg("include", "if", "Boolean!", 3, 15), + missingDirectiveArg("skip", "if", "Boolean!", 4, 18) + ] + ); }); - }); - }); diff --git a/src/validation/__tests__/ScalarLeafs-test.js b/src/validation/__tests__/ScalarLeafs-test.js index e3fe768f75..351c2590e0 100644 --- a/src/validation/__tests__/ScalarLeafs-test.js +++ b/src/validation/__tests__/ScalarLeafs-test.js @@ -7,106 +7,132 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { ScalarLeafs, noSubselectionAllowedMessage, - requiredSubselectionMessage, -} from '../rules/ScalarLeafs'; - + requiredSubselectionMessage +} from "../rules/ScalarLeafs"; function noScalarSubselection(field, type, line, column) { return { message: noSubselectionAllowedMessage(field, type), - locations: [ { line, column } ], + locations: [{ line, column }] }; } function missingObjSubselection(field, type, line, column) { return { message: requiredSubselectionMessage(field, type), - locations: [ { line, column } ], + locations: [{ line, column }] }; } -describe('Validate: Scalar leafs', () => { - - it('valid scalar selection', () => { - expectPassesRule(ScalarLeafs, ` +describe("Validate: Scalar leafs", () => { + it("valid scalar selection", () => { + expectPassesRule( + ScalarLeafs, + ` fragment scalarSelection on Dog { barks } - `); + ` + ); }); - it('object type missing selection', () => { - expectFailsRule(ScalarLeafs, ` + it("object type missing selection", () => { + expectFailsRule( + ScalarLeafs, + ` query directQueryOnObjectWithoutSubFields { human } - `, [ missingObjSubselection('human', 'Human', 3, 9) ]); + `, + [missingObjSubselection("human", "Human", 3, 9)] + ); }); - it('interface type missing selection', () => { - expectFailsRule(ScalarLeafs, ` + it("interface type missing selection", () => { + expectFailsRule( + ScalarLeafs, + ` { human { pets } } - `, [ missingObjSubselection('pets', '[Pet]', 3, 17) ]); + `, + [missingObjSubselection("pets", "[Pet]", 3, 17)] + ); }); - it('valid scalar selection with args', () => { - expectPassesRule(ScalarLeafs, ` + it("valid scalar selection with args", () => { + expectPassesRule( + ScalarLeafs, + ` fragment scalarSelectionWithArgs on Dog { doesKnowCommand(dogCommand: SIT) } - `); + ` + ); }); - it('scalar selection not allowed on Boolean', () => { - expectFailsRule(ScalarLeafs, ` + it("scalar selection not allowed on Boolean", () => { + expectFailsRule( + ScalarLeafs, + ` fragment scalarSelectionsNotAllowedOnBoolean on Dog { barks { sinceWhen } } `, - [ noScalarSubselection('barks', 'Boolean', 3, 15) ] ); + [noScalarSubselection("barks", "Boolean", 3, 15)] + ); }); - it('scalar selection not allowed on Enum', () => { - expectFailsRule(ScalarLeafs, ` + it("scalar selection not allowed on Enum", () => { + expectFailsRule( + ScalarLeafs, + ` fragment scalarSelectionsNotAllowedOnEnum on Cat { furColor { inHexdec } } `, - [ noScalarSubselection('furColor', 'FurColor', 3, 18) ] ); + [noScalarSubselection("furColor", "FurColor", 3, 18)] + ); }); - it('scalar selection not allowed with args', () => { - expectFailsRule(ScalarLeafs, ` + it("scalar selection not allowed with args", () => { + expectFailsRule( + ScalarLeafs, + ` fragment scalarSelectionsNotAllowedWithArgs on Dog { doesKnowCommand(dogCommand: SIT) { sinceWhen } } `, - [ noScalarSubselection('doesKnowCommand', 'Boolean', 3, 42) ] ); + [noScalarSubselection("doesKnowCommand", "Boolean", 3, 42)] + ); }); - it('Scalar selection not allowed with directives', () => { - expectFailsRule(ScalarLeafs, ` + it("Scalar selection not allowed with directives", () => { + expectFailsRule( + ScalarLeafs, + ` fragment scalarSelectionsNotAllowedWithDirectives on Dog { name @include(if: true) { isAlsoHumanName } } `, - [ noScalarSubselection('name', 'String', 3, 33) ] ); + [noScalarSubselection("name", "String", 3, 33)] + ); }); - it('Scalar selection not allowed with directives and args', () => { - expectFailsRule(ScalarLeafs, ` + it("Scalar selection not allowed with directives and args", () => { + expectFailsRule( + ScalarLeafs, + ` fragment scalarSelectionsNotAllowedWithDirectivesAndArgs on Dog { doesKnowCommand(dogCommand: SIT) @include(if: true) { sinceWhen } } `, - [ noScalarSubselection('doesKnowCommand', 'Boolean', 3, 61) ] ); + [noScalarSubselection("doesKnowCommand", "Boolean", 3, 61)] + ); }); - }); diff --git a/src/validation/__tests__/UniqueArgumentNames-test.js b/src/validation/__tests__/UniqueArgumentNames-test.js index 1fb7e9a9f3..85954550ea 100644 --- a/src/validation/__tests__/UniqueArgumentNames-test.js +++ b/src/validation/__tests__/UniqueArgumentNames-test.js @@ -7,136 +7,166 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { UniqueArgumentNames, - duplicateArgMessage, -} from '../rules/UniqueArgumentNames'; - + duplicateArgMessage +} from "../rules/UniqueArgumentNames"; function duplicateArg(argName, l1, c1, l2, c2) { return { message: duplicateArgMessage(argName), - locations: [ { line: l1, column: c1 }, { line: l2, column: c2 } ], + locations: [{ line: l1, column: c1 }, { line: l2, column: c2 }] }; } -describe('Validate: Unique argument names', () => { - - it('no arguments on field', () => { - expectPassesRule(UniqueArgumentNames, ` +describe("Validate: Unique argument names", () => { + it("no arguments on field", () => { + expectPassesRule( + UniqueArgumentNames, + ` { field } - `); + ` + ); }); - it('no arguments on directive', () => { - expectPassesRule(UniqueArgumentNames, ` + it("no arguments on directive", () => { + expectPassesRule( + UniqueArgumentNames, + ` { field @directive } - `); + ` + ); }); - it('argument on field', () => { - expectPassesRule(UniqueArgumentNames, ` + it("argument on field", () => { + expectPassesRule( + UniqueArgumentNames, + ` { field(arg: "value") } - `); + ` + ); }); - it('argument on directive', () => { - expectPassesRule(UniqueArgumentNames, ` + it("argument on directive", () => { + expectPassesRule( + UniqueArgumentNames, + ` { field @directive(arg: "value") } - `); + ` + ); }); - it('same argument on two fields', () => { - expectPassesRule(UniqueArgumentNames, ` + it("same argument on two fields", () => { + expectPassesRule( + UniqueArgumentNames, + ` { one: field(arg: "value") two: field(arg: "value") } - `); + ` + ); }); - it('same argument on field and directive', () => { - expectPassesRule(UniqueArgumentNames, ` + it("same argument on field and directive", () => { + expectPassesRule( + UniqueArgumentNames, + ` { field(arg: "value") @directive(arg: "value") } - `); + ` + ); }); - it('same argument on two directives', () => { - expectPassesRule(UniqueArgumentNames, ` + it("same argument on two directives", () => { + expectPassesRule( + UniqueArgumentNames, + ` { field @directive1(arg: "value") @directive2(arg: "value") } - `); + ` + ); }); - it('multiple field arguments', () => { - expectPassesRule(UniqueArgumentNames, ` + it("multiple field arguments", () => { + expectPassesRule( + UniqueArgumentNames, + ` { field(arg1: "value", arg2: "value", arg3: "value") } - `); + ` + ); }); - it('multiple directive arguments', () => { - expectPassesRule(UniqueArgumentNames, ` + it("multiple directive arguments", () => { + expectPassesRule( + UniqueArgumentNames, + ` { field @directive(arg1: "value", arg2: "value", arg3: "value") } - `); + ` + ); }); - it('duplicate field arguments', () => { - expectFailsRule(UniqueArgumentNames, ` + it("duplicate field arguments", () => { + expectFailsRule( + UniqueArgumentNames, + ` { field(arg1: "value", arg1: "value") } - `, [ - duplicateArg('arg1', 3, 15, 3, 30) - ]); + `, + [duplicateArg("arg1", 3, 15, 3, 30)] + ); }); - it('many duplicate field arguments', () => { - expectFailsRule(UniqueArgumentNames, ` + it("many duplicate field arguments", () => { + expectFailsRule( + UniqueArgumentNames, + ` { field(arg1: "value", arg1: "value", arg1: "value") } - `, [ - duplicateArg('arg1', 3, 15, 3, 30), - duplicateArg('arg1', 3, 15, 3, 45) - ]); + `, + [duplicateArg("arg1", 3, 15, 3, 30), duplicateArg("arg1", 3, 15, 3, 45)] + ); }); - it('duplicate directive arguments', () => { - expectFailsRule(UniqueArgumentNames, ` + it("duplicate directive arguments", () => { + expectFailsRule( + UniqueArgumentNames, + ` { field @directive(arg1: "value", arg1: "value") } - `, [ - duplicateArg('arg1', 3, 26, 3, 41) - ]); + `, + [duplicateArg("arg1", 3, 26, 3, 41)] + ); }); - it('many duplicate directive arguments', () => { - expectFailsRule(UniqueArgumentNames, ` + it("many duplicate directive arguments", () => { + expectFailsRule( + UniqueArgumentNames, + ` { field @directive(arg1: "value", arg1: "value", arg1: "value") } - `, [ - duplicateArg('arg1', 3, 26, 3, 41), - duplicateArg('arg1', 3, 26, 3, 56) - ]); + `, + [duplicateArg("arg1", 3, 26, 3, 41), duplicateArg("arg1", 3, 26, 3, 56)] + ); }); - }); diff --git a/src/validation/__tests__/UniqueFragmentNames-test.js b/src/validation/__tests__/UniqueFragmentNames-test.js index bb22472b6c..4efc5c3160 100644 --- a/src/validation/__tests__/UniqueFragmentNames-test.js +++ b/src/validation/__tests__/UniqueFragmentNames-test.js @@ -7,33 +7,36 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { UniqueFragmentNames, - duplicateFragmentNameMessage, -} from '../rules/UniqueFragmentNames'; - + duplicateFragmentNameMessage +} from "../rules/UniqueFragmentNames"; function duplicateFrag(fragName, l1, c1, l2, c2) { return { message: duplicateFragmentNameMessage(fragName), - locations: [ { line: l1, column: c1 }, { line: l2, column: c2 } ], + locations: [{ line: l1, column: c1 }, { line: l2, column: c2 }] }; } -describe('Validate: Unique fragment names', () => { - - it('no fragments', () => { - expectPassesRule(UniqueFragmentNames, ` +describe("Validate: Unique fragment names", () => { + it("no fragments", () => { + expectPassesRule( + UniqueFragmentNames, + ` { field } - `); + ` + ); }); - it('one fragment', () => { - expectPassesRule(UniqueFragmentNames, ` + it("one fragment", () => { + expectPassesRule( + UniqueFragmentNames, + ` { ...fragA } @@ -41,11 +44,14 @@ describe('Validate: Unique fragment names', () => { fragment fragA on Type { field } - `); + ` + ); }); - it('many fragments', () => { - expectPassesRule(UniqueFragmentNames, ` + it("many fragments", () => { + expectPassesRule( + UniqueFragmentNames, + ` { ...fragA ...fragB @@ -60,11 +66,14 @@ describe('Validate: Unique fragment names', () => { fragment fragC on Type { fieldC } - `); + ` + ); }); - it('inline fragments are always unique', () => { - expectPassesRule(UniqueFragmentNames, ` + it("inline fragments are always unique", () => { + expectPassesRule( + UniqueFragmentNames, + ` { ...on Type { fieldA @@ -73,22 +82,28 @@ describe('Validate: Unique fragment names', () => { fieldB } } - `); + ` + ); }); - it('fragment and operation named the same', () => { - expectPassesRule(UniqueFragmentNames, ` + it("fragment and operation named the same", () => { + expectPassesRule( + UniqueFragmentNames, + ` query Foo { ...Foo } fragment Foo on Type { field } - `); + ` + ); }); - it('fragments named the same', () => { - expectFailsRule(UniqueFragmentNames, ` + it("fragments named the same", () => { + expectFailsRule( + UniqueFragmentNames, + ` { ...fragA } @@ -98,22 +113,23 @@ describe('Validate: Unique fragment names', () => { fragment fragA on Type { fieldB } - `, [ - duplicateFrag('fragA', 5, 16, 8, 16) - ]); + `, + [duplicateFrag("fragA", 5, 16, 8, 16)] + ); }); - it('fragments named the same without being referenced', () => { - expectFailsRule(UniqueFragmentNames, ` + it("fragments named the same without being referenced", () => { + expectFailsRule( + UniqueFragmentNames, + ` fragment fragA on Type { fieldA } fragment fragA on Type { fieldB } - `, [ - duplicateFrag('fragA', 2, 16, 5, 16) - ]); + `, + [duplicateFrag("fragA", 2, 16, 5, 16)] + ); }); - }); diff --git a/src/validation/__tests__/UniqueInputFieldNames-test.js b/src/validation/__tests__/UniqueInputFieldNames-test.js index 6ed4f535c0..e63f1fa277 100644 --- a/src/validation/__tests__/UniqueInputFieldNames-test.js +++ b/src/validation/__tests__/UniqueInputFieldNames-test.js @@ -7,49 +7,58 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { UniqueInputFieldNames, - duplicateInputFieldMessage, -} from '../rules/UniqueInputFieldNames'; - + duplicateInputFieldMessage +} from "../rules/UniqueInputFieldNames"; function duplicateField(name, l1, c1, l2, c2) { return { message: duplicateInputFieldMessage(name), - locations: [ { line: l1, column: c1 }, { line: l2, column: c2 } ], + locations: [{ line: l1, column: c1 }, { line: l2, column: c2 }] }; } -describe('Validate: Unique input field names', () => { - - it('input object with fields', () => { - expectPassesRule(UniqueInputFieldNames, ` +describe("Validate: Unique input field names", () => { + it("input object with fields", () => { + expectPassesRule( + UniqueInputFieldNames, + ` { field(arg: { f: true }) } - `); + ` + ); }); - it('same input object within two args', () => { - expectPassesRule(UniqueInputFieldNames, ` + it("same input object within two args", () => { + expectPassesRule( + UniqueInputFieldNames, + ` { field(arg1: { f: true }, arg2: { f: true }) } - `); + ` + ); }); - it('multiple input object fields', () => { - expectPassesRule(UniqueInputFieldNames, ` + it("multiple input object fields", () => { + expectPassesRule( + UniqueInputFieldNames, + ` { field(arg: { f1: "value", f2: "value", f3: "value" }) } - `); + ` + ); }); - it('allows for nested input objects with similar fields', () => { - expectPassesRule(UniqueInputFieldNames, ` + it("allows for nested input objects with similar fields", () => { + expectPassesRule( + UniqueInputFieldNames, + ` { field(arg: { deep: { @@ -61,28 +70,31 @@ describe('Validate: Unique input field names', () => { id: 1 }) } - `); + ` + ); }); - it('duplicate input object fields', () => { - expectFailsRule(UniqueInputFieldNames, ` + it("duplicate input object fields", () => { + expectFailsRule( + UniqueInputFieldNames, + ` { field(arg: { f1: "value", f1: "value" }) } - `, [ - duplicateField('f1', 3, 22, 3, 35) - ]); + `, + [duplicateField("f1", 3, 22, 3, 35)] + ); }); - it('many duplicate input object fields', () => { - expectFailsRule(UniqueInputFieldNames, ` + it("many duplicate input object fields", () => { + expectFailsRule( + UniqueInputFieldNames, + ` { field(arg: { f1: "value", f1: "value", f1: "value" }) } - `, [ - duplicateField('f1', 3, 22, 3, 35), - duplicateField('f1', 3, 22, 3, 48) - ]); + `, + [duplicateField("f1", 3, 22, 3, 35), duplicateField("f1", 3, 22, 3, 48)] + ); }); - }); diff --git a/src/validation/__tests__/UniqueOperationNames-test.js b/src/validation/__tests__/UniqueOperationNames-test.js index 6a9a1a1c9f..53d24cd5d9 100644 --- a/src/validation/__tests__/UniqueOperationNames-test.js +++ b/src/validation/__tests__/UniqueOperationNames-test.js @@ -7,49 +7,58 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { UniqueOperationNames, - duplicateOperationNameMessage, -} from '../rules/UniqueOperationNames'; - + duplicateOperationNameMessage +} from "../rules/UniqueOperationNames"; function duplicateOp(opName, l1, c1, l2, c2) { return { message: duplicateOperationNameMessage(opName), - locations: [ { line: l1, column: c1 }, { line: l2, column: c2 } ], + locations: [{ line: l1, column: c1 }, { line: l2, column: c2 }] }; } -describe('Validate: Unique operation names', () => { - - it('no operations', () => { - expectPassesRule(UniqueOperationNames, ` +describe("Validate: Unique operation names", () => { + it("no operations", () => { + expectPassesRule( + UniqueOperationNames, + ` fragment fragA on Type { field } - `); + ` + ); }); - it('one anon operation', () => { - expectPassesRule(UniqueOperationNames, ` + it("one anon operation", () => { + expectPassesRule( + UniqueOperationNames, + ` { field } - `); + ` + ); }); - it('one named operation', () => { - expectPassesRule(UniqueOperationNames, ` + it("one named operation", () => { + expectPassesRule( + UniqueOperationNames, + ` query Foo { field } - `); + ` + ); }); - it('multiple operations', () => { - expectPassesRule(UniqueOperationNames, ` + it("multiple operations", () => { + expectPassesRule( + UniqueOperationNames, + ` query Foo { field } @@ -57,11 +66,14 @@ describe('Validate: Unique operation names', () => { query Bar { field } - `); + ` + ); }); - it('multiple operations of different types', () => { - expectPassesRule(UniqueOperationNames, ` + it("multiple operations of different types", () => { + expectPassesRule( + UniqueOperationNames, + ` query Foo { field } @@ -73,57 +85,66 @@ describe('Validate: Unique operation names', () => { subscription Baz { field } - `); + ` + ); }); - it('fragment and operation named the same', () => { - expectPassesRule(UniqueOperationNames, ` + it("fragment and operation named the same", () => { + expectPassesRule( + UniqueOperationNames, + ` query Foo { ...Foo } fragment Foo on Type { field } - `); + ` + ); }); - it('multiple operations of same name', () => { - expectFailsRule(UniqueOperationNames, ` + it("multiple operations of same name", () => { + expectFailsRule( + UniqueOperationNames, + ` query Foo { fieldA } query Foo { fieldB } - `, [ - duplicateOp('Foo', 2, 13, 5, 13) - ]); + `, + [duplicateOp("Foo", 2, 13, 5, 13)] + ); }); - it('multiple ops of same name of different types (mutation)', () => { - expectFailsRule(UniqueOperationNames, ` + it("multiple ops of same name of different types (mutation)", () => { + expectFailsRule( + UniqueOperationNames, + ` query Foo { fieldA } mutation Foo { fieldB } - `, [ - duplicateOp('Foo', 2, 13, 5, 16) - ]); + `, + [duplicateOp("Foo", 2, 13, 5, 16)] + ); }); - it('multiple ops of same name of different types (subscription)', () => { - expectFailsRule(UniqueOperationNames, ` + it("multiple ops of same name of different types (subscription)", () => { + expectFailsRule( + UniqueOperationNames, + ` query Foo { fieldA } subscription Foo { fieldB } - `, [ - duplicateOp('Foo', 2, 13, 5, 20) - ]); + `, + [duplicateOp("Foo", 2, 13, 5, 20)] + ); }); - }); diff --git a/src/validation/__tests__/UniqueVariableNames-test.js b/src/validation/__tests__/UniqueVariableNames-test.js index f5b170b6c4..40d548b92e 100644 --- a/src/validation/__tests__/UniqueVariableNames-test.js +++ b/src/validation/__tests__/UniqueVariableNames-test.js @@ -7,41 +7,45 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { UniqueVariableNames, - duplicateVariableMessage, -} from '../rules/UniqueVariableNames'; - + duplicateVariableMessage +} from "../rules/UniqueVariableNames"; function duplicateVariable(name, l1, c1, l2, c2) { return { message: duplicateVariableMessage(name), - locations: [ { line: l1, column: c1 }, { line: l2, column: c2 } ], + locations: [{ line: l1, column: c1 }, { line: l2, column: c2 }] }; } -describe('Validate: Unique variable names', () => { - - it('unique variable names', () => { - expectPassesRule(UniqueVariableNames, ` +describe("Validate: Unique variable names", () => { + it("unique variable names", () => { + expectPassesRule( + UniqueVariableNames, + ` query A($x: Int, $y: String) { __typename } query B($x: String, $y: Int) { __typename } - `); + ` + ); }); - it('duplicate variable names', () => { - expectFailsRule(UniqueVariableNames, ` + it("duplicate variable names", () => { + expectFailsRule( + UniqueVariableNames, + ` query A($x: Int, $x: Int, $x: String) { __typename } query B($x: String, $x: Int) { __typename } query C($x: Int, $x: Int) { __typename } - `, [ - duplicateVariable('x', 2, 16, 2, 25), - duplicateVariable('x', 2, 16, 2, 34), - duplicateVariable('x', 3, 16, 3, 28), - duplicateVariable('x', 4, 16, 4, 25) - ]); + `, + [ + duplicateVariable("x", 2, 16, 2, 25), + duplicateVariable("x", 2, 16, 2, 34), + duplicateVariable("x", 3, 16, 3, 28), + duplicateVariable("x", 4, 16, 4, 25) + ] + ); }); - }); diff --git a/src/validation/__tests__/VariablesAreInputTypes-test.js b/src/validation/__tests__/VariablesAreInputTypes-test.js index a9acc99449..d81162963c 100644 --- a/src/validation/__tests__/VariablesAreInputTypes-test.js +++ b/src/validation/__tests__/VariablesAreInputTypes-test.js @@ -7,37 +7,47 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { VariablesAreInputTypes, - nonInputTypeOnVarMessage, -} from '../rules/VariablesAreInputTypes'; + nonInputTypeOnVarMessage +} from "../rules/VariablesAreInputTypes"; - -describe('Validate: Variables are input types', () => { - - it('input types are valid', () => { - expectPassesRule(VariablesAreInputTypes, ` +describe("Validate: Variables are input types", () => { + it("input types are valid", () => { + expectPassesRule( + VariablesAreInputTypes, + ` query Foo($a: String, $b: [Boolean!]!, $c: ComplexInput) { field(a: $a, b: $b, c: $c) } - `); + ` + ); }); - it('output types are invalid', () => { - expectFailsRule(VariablesAreInputTypes, ` + it("output types are invalid", () => { + expectFailsRule( + VariablesAreInputTypes, + ` query Foo($a: Dog, $b: [[CatOrDog!]]!, $c: Pet) { field(a: $a, b: $b, c: $c) } - `, [ - { locations: [ { line: 2, column: 21 } ], - message: nonInputTypeOnVarMessage('a', 'Dog') }, - { locations: [ { line: 2, column: 30 } ], - message: nonInputTypeOnVarMessage('b', '[[CatOrDog!]]!') }, - { locations: [ { line: 2, column: 50 } ], - message: nonInputTypeOnVarMessage('c', 'Pet') }, - ]); + `, + [ + { + locations: [{ line: 2, column: 21 }], + message: nonInputTypeOnVarMessage("a", "Dog") + }, + { + locations: [{ line: 2, column: 30 }], + message: nonInputTypeOnVarMessage("b", "[[CatOrDog!]]!") + }, + { + locations: [{ line: 2, column: 50 }], + message: nonInputTypeOnVarMessage("c", "Pet") + } + ] + ); }); - }); diff --git a/src/validation/__tests__/VariablesInAllowedPosition-test.js b/src/validation/__tests__/VariablesInAllowedPosition-test.js index d69047742d..620b2d7753 100644 --- a/src/validation/__tests__/VariablesInAllowedPosition-test.js +++ b/src/validation/__tests__/VariablesInAllowedPosition-test.js @@ -7,29 +7,32 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expectPassesRule, expectFailsRule } from './harness'; +import { describe, it } from "mocha"; +import { expectPassesRule, expectFailsRule } from "./harness"; import { VariablesInAllowedPosition, - badVarPosMessage, -} from '../rules/VariablesInAllowedPosition'; + badVarPosMessage +} from "../rules/VariablesInAllowedPosition"; - -describe('Validate: Variables are in allowed positions', () => { - - it('Boolean => Boolean', () => { - expectPassesRule(VariablesInAllowedPosition, ` +describe("Validate: Variables are in allowed positions", () => { + it("Boolean => Boolean", () => { + expectPassesRule( + VariablesInAllowedPosition, + ` query Query($booleanArg: Boolean) { complicatedArgs { booleanArgField(booleanArg: $booleanArg) } } - `); + ` + ); }); - it('Boolean => Boolean within fragment', () => { - expectPassesRule(VariablesInAllowedPosition, ` + it("Boolean => Boolean within fragment", () => { + expectPassesRule( + VariablesInAllowedPosition, + ` fragment booleanArgFrag on ComplicatedArgs { booleanArgField(booleanArg: $booleanArg) } @@ -39,9 +42,12 @@ describe('Validate: Variables are in allowed positions', () => { ...booleanArgFrag } } - `); + ` + ); - expectPassesRule(VariablesInAllowedPosition, ` + expectPassesRule( + VariablesInAllowedPosition, + ` query Query($booleanArg: Boolean) { complicatedArgs { @@ -51,22 +57,28 @@ describe('Validate: Variables are in allowed positions', () => { fragment booleanArgFrag on ComplicatedArgs { booleanArgField(booleanArg: $booleanArg) } - `); + ` + ); }); - it('Boolean! => Boolean', () => { - expectPassesRule(VariablesInAllowedPosition, ` + it("Boolean! => Boolean", () => { + expectPassesRule( + VariablesInAllowedPosition, + ` query Query($nonNullBooleanArg: Boolean!) { complicatedArgs { booleanArgField(booleanArg: $nonNullBooleanArg) } } - `); + ` + ); }); - it('Boolean! => Boolean within fragment', () => { - expectPassesRule(VariablesInAllowedPosition, ` + it("Boolean! => Boolean within fragment", () => { + expectPassesRule( + VariablesInAllowedPosition, + ` fragment booleanArgFrag on ComplicatedArgs { booleanArgField(booleanArg: $nonNullBooleanArg) } @@ -77,119 +89,155 @@ describe('Validate: Variables are in allowed positions', () => { ...booleanArgFrag } } - `); + ` + ); }); - it('Int => Int! with default', () => { - expectPassesRule(VariablesInAllowedPosition, ` + it("Int => Int! with default", () => { + expectPassesRule( + VariablesInAllowedPosition, + ` query Query($intArg: Int = 1) { complicatedArgs { nonNullIntArgField(nonNullIntArg: $intArg) } } - `); + ` + ); }); - it('[String] => [String]', () => { - expectPassesRule(VariablesInAllowedPosition, ` + it("[String] => [String]", () => { + expectPassesRule( + VariablesInAllowedPosition, + ` query Query($stringListVar: [String]) { complicatedArgs { stringListArgField(stringListArg: $stringListVar) } } - `); + ` + ); }); - it('[String!] => [String]', () => { - expectPassesRule(VariablesInAllowedPosition, ` + it("[String!] => [String]", () => { + expectPassesRule( + VariablesInAllowedPosition, + ` query Query($stringListVar: [String!]) { complicatedArgs { stringListArgField(stringListArg: $stringListVar) } } - `); + ` + ); }); - it('String => [String] in item position', () => { - expectPassesRule(VariablesInAllowedPosition, ` + it("String => [String] in item position", () => { + expectPassesRule( + VariablesInAllowedPosition, + ` query Query($stringVar: String) { complicatedArgs { stringListArgField(stringListArg: [$stringVar]) } } - `); + ` + ); }); - it('String! => [String] in item position', () => { - expectPassesRule(VariablesInAllowedPosition, ` + it("String! => [String] in item position", () => { + expectPassesRule( + VariablesInAllowedPosition, + ` query Query($stringVar: String!) { complicatedArgs { stringListArgField(stringListArg: [$stringVar]) } } - `); + ` + ); }); - it('ComplexInput => ComplexInput', () => { - expectPassesRule(VariablesInAllowedPosition, ` + it("ComplexInput => ComplexInput", () => { + expectPassesRule( + VariablesInAllowedPosition, + ` query Query($complexVar: ComplexInput) { complicatedArgs { complexArgField(complexArg: $complexVar) } } - `); + ` + ); }); - it('ComplexInput => ComplexInput in field position', () => { - expectPassesRule(VariablesInAllowedPosition, ` + it("ComplexInput => ComplexInput in field position", () => { + expectPassesRule( + VariablesInAllowedPosition, + ` query Query($boolVar: Boolean = false) { complicatedArgs { complexArgField(complexArg: {requiredArg: $boolVar}) } } - `); + ` + ); }); - it('Boolean! => Boolean! in directive', () => { - expectPassesRule(VariablesInAllowedPosition, ` + it("Boolean! => Boolean! in directive", () => { + expectPassesRule( + VariablesInAllowedPosition, + ` query Query($boolVar: Boolean!) { dog @include(if: $boolVar) } - `); + ` + ); }); - it('Boolean => Boolean! in directive with default', () => { - expectPassesRule(VariablesInAllowedPosition, ` + it("Boolean => Boolean! in directive with default", () => { + expectPassesRule( + VariablesInAllowedPosition, + ` query Query($boolVar: Boolean = false) { dog @include(if: $boolVar) } - `); + ` + ); }); - it('Int => Int!', () => { - expectFailsRule(VariablesInAllowedPosition, ` + it("Int => Int!", () => { + expectFailsRule( + VariablesInAllowedPosition, + ` query Query($intArg: Int) { complicatedArgs { nonNullIntArgField(nonNullIntArg: $intArg) } } - `, [ - { message: badVarPosMessage('intArg', 'Int', 'Int!'), - locations: [ { line: 2, column: 19 }, { line: 4, column: 45 } ] }, - ]); + `, + [ + { + message: badVarPosMessage("intArg", "Int", "Int!"), + locations: [{ line: 2, column: 19 }, { line: 4, column: 45 }] + } + ] + ); }); - it('Int => Int! within fragment', () => { - expectFailsRule(VariablesInAllowedPosition, ` + it("Int => Int! within fragment", () => { + expectFailsRule( + VariablesInAllowedPosition, + ` fragment nonNullIntArgFieldFrag on ComplicatedArgs { nonNullIntArgField(nonNullIntArg: $intArg) } @@ -199,14 +247,20 @@ describe('Validate: Variables are in allowed positions', () => { ...nonNullIntArgFieldFrag } } - `, [ - { message: badVarPosMessage('intArg', 'Int', 'Int!'), - locations: [ { line: 6, column: 19 }, { line: 3, column: 43 } ] } - ]); + `, + [ + { + message: badVarPosMessage("intArg", "Int", "Int!"), + locations: [{ line: 6, column: 19 }, { line: 3, column: 43 }] + } + ] + ); }); - it('Int => Int! within nested fragment', () => { - expectFailsRule(VariablesInAllowedPosition, ` + it("Int => Int! within nested fragment", () => { + expectFailsRule( + VariablesInAllowedPosition, + ` fragment outerFrag on ComplicatedArgs { ...nonNullIntArgFieldFrag } @@ -220,58 +274,85 @@ describe('Validate: Variables are in allowed positions', () => { ...outerFrag } } - `, [ - { message: badVarPosMessage('intArg', 'Int', 'Int!'), - locations: [ { line: 10, column: 19 }, { line: 7, column: 43 } ] } - ]); + `, + [ + { + message: badVarPosMessage("intArg", "Int", "Int!"), + locations: [{ line: 10, column: 19 }, { line: 7, column: 43 }] + } + ] + ); }); - it('String over Boolean', () => { - expectFailsRule(VariablesInAllowedPosition, ` + it("String over Boolean", () => { + expectFailsRule( + VariablesInAllowedPosition, + ` query Query($stringVar: String) { complicatedArgs { booleanArgField(booleanArg: $stringVar) } } - `, [ - { message: badVarPosMessage('stringVar', 'String', 'Boolean'), - locations: [ { line: 2, column: 19 }, { line: 4, column: 39 } ] } - ]); + `, + [ + { + message: badVarPosMessage("stringVar", "String", "Boolean"), + locations: [{ line: 2, column: 19 }, { line: 4, column: 39 }] + } + ] + ); }); - it('String => [String]', () => { - expectFailsRule(VariablesInAllowedPosition, ` + it("String => [String]", () => { + expectFailsRule( + VariablesInAllowedPosition, + ` query Query($stringVar: String) { complicatedArgs { stringListArgField(stringListArg: $stringVar) } } - `, [ - { message: badVarPosMessage('stringVar', 'String', '[String]'), - locations: [ { line: 2, column: 19 }, { line: 4, column: 45 } ] } - ]); + `, + [ + { + message: badVarPosMessage("stringVar", "String", "[String]"), + locations: [{ line: 2, column: 19 }, { line: 4, column: 45 }] + } + ] + ); }); - it('Boolean => Boolean! in directive', () => { - expectFailsRule(VariablesInAllowedPosition, ` + it("Boolean => Boolean! in directive", () => { + expectFailsRule( + VariablesInAllowedPosition, + ` query Query($boolVar: Boolean) { dog @include(if: $boolVar) } - `, [ - { message: badVarPosMessage('boolVar', 'Boolean', 'Boolean!'), - locations: [ { line: 2, column: 19 }, { line: 3, column: 26 } ] } - ]); + `, + [ + { + message: badVarPosMessage("boolVar", "Boolean", "Boolean!"), + locations: [{ line: 2, column: 19 }, { line: 3, column: 26 }] + } + ] + ); }); - it('String => Boolean! in directive', () => { - expectFailsRule(VariablesInAllowedPosition, ` + it("String => Boolean! in directive", () => { + expectFailsRule( + VariablesInAllowedPosition, + ` query Query($stringVar: String) { dog @include(if: $stringVar) } - `, [ - { message: badVarPosMessage('stringVar', 'String', 'Boolean!'), - locations: [ { line: 2, column: 19 }, { line: 3, column: 26 } ] } - ]); + `, + [ + { + message: badVarPosMessage("stringVar", "String", "Boolean!"), + locations: [{ line: 2, column: 19 }, { line: 3, column: 26 }] + } + ] + ); }); - }); diff --git a/src/validation/__tests__/harness.js b/src/validation/__tests__/harness.js index b9491e9b70..ca95a6d5dc 100644 --- a/src/validation/__tests__/harness.js +++ b/src/validation/__tests__/harness.js @@ -7,10 +7,10 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { expect } from 'chai'; -import { parse } from '../../language'; -import { formatError } from '../../error'; -import { validate } from '../validate'; +import { expect } from "chai"; +import { parse } from "../../language"; +import { formatError } from "../../error"; +import { validate } from "../validate"; import { GraphQLSchema, GraphQLObjectType, @@ -25,60 +25,59 @@ import { GraphQLString, GraphQLBoolean, GraphQLID -} from '../../type'; +} from "../../type"; import { GraphQLDirective, GraphQLIncludeDirective, - GraphQLSkipDirective, -} from '../../type/directives'; - + GraphQLSkipDirective +} from "../../type/directives"; const Being = new GraphQLInterfaceType({ - name: 'Being', + name: "Being", fields: () => ({ name: { type: GraphQLString, - args: { surname: { type: GraphQLBoolean } }, + args: { surname: { type: GraphQLBoolean } } } - }), + }) }); const Pet = new GraphQLInterfaceType({ - name: 'Pet', + name: "Pet", fields: () => ({ name: { type: GraphQLString, - args: { surname: { type: GraphQLBoolean } }, + args: { surname: { type: GraphQLBoolean } } } - }), + }) }); const Canine = new GraphQLInterfaceType({ - name: 'Canine', + name: "Canine", fields: () => ({ name: { type: GraphQLString, - args: { surname: { type: GraphQLBoolean } }, + args: { surname: { type: GraphQLBoolean } } } - }), + }) }); const DogCommand = new GraphQLEnumType({ - name: 'DogCommand', + name: "DogCommand", values: { SIT: { value: 0 }, HEEL: { value: 1 }, - DOWN: { value: 2 }, - }, + DOWN: { value: 2 } + } }); const Dog = new GraphQLObjectType({ - name: 'Dog', + name: "Dog", isTypeOf: () => true, fields: () => ({ name: { type: GraphQLString, - args: { surname: { type: GraphQLBoolean } }, + args: { surname: { type: GraphQLBoolean } } }, nickname: { type: GraphQLString }, barkVolume: { type: GraphQLInt }, @@ -86,184 +85,184 @@ const Dog = new GraphQLObjectType({ doesKnowCommand: { type: GraphQLBoolean, args: { - dogCommand: { type: DogCommand }, - }, + dogCommand: { type: DogCommand } + } }, isHousetrained: { type: GraphQLBoolean, args: { atOtherHomes: { type: GraphQLBoolean, - defaultValue: true, + defaultValue: true } - }, + } }, isAtLocation: { type: GraphQLBoolean, - args: { x: { type: GraphQLInt }, y: { type: GraphQLInt } }, - }, + args: { x: { type: GraphQLInt }, y: { type: GraphQLInt } } + } }), - interfaces: [ Being, Pet, Canine ], + interfaces: [Being, Pet, Canine] }); const Cat = new GraphQLObjectType({ - name: 'Cat', + name: "Cat", isTypeOf: () => true, fields: () => ({ name: { type: GraphQLString, - args: { surname: { type: GraphQLBoolean } }, + args: { surname: { type: GraphQLBoolean } } }, nickname: { type: GraphQLString }, meows: { type: GraphQLBoolean }, meowVolume: { type: GraphQLInt }, - furColor: { type: FurColor }, + furColor: { type: FurColor } }), - interfaces: [ Being, Pet ], + interfaces: [Being, Pet] }); const CatOrDog = new GraphQLUnionType({ - name: 'CatOrDog', - types: [ Dog, Cat ], + name: "CatOrDog", + types: [Dog, Cat], resolveType(/* value */) { // not used for validation } }); const Intelligent = new GraphQLInterfaceType({ - name: 'Intelligent', + name: "Intelligent", fields: { iq: { type: GraphQLInt } } }); const Human = new GraphQLObjectType({ - name: 'Human', + name: "Human", isTypeOf: () => true, - interfaces: [ Being, Intelligent ], + interfaces: [Being, Intelligent], fields: () => ({ name: { type: GraphQLString, - args: { surname: { type: GraphQLBoolean } }, + args: { surname: { type: GraphQLBoolean } } }, pets: { type: new GraphQLList(Pet) }, relatives: { type: new GraphQLList(Human) }, - iq: { type: GraphQLInt }, + iq: { type: GraphQLInt } }) }); const Alien = new GraphQLObjectType({ - name: 'Alien', + name: "Alien", isTypeOf: () => true, - interfaces: [ Being, Intelligent ], + interfaces: [Being, Intelligent], fields: { iq: { type: GraphQLInt }, name: { type: GraphQLString, - args: { surname: { type: GraphQLBoolean } }, + args: { surname: { type: GraphQLBoolean } } }, - numEyes: { type: GraphQLInt }, + numEyes: { type: GraphQLInt } } }); const DogOrHuman = new GraphQLUnionType({ - name: 'DogOrHuman', - types: [ Dog, Human ], + name: "DogOrHuman", + types: [Dog, Human], resolveType(/* value */) { // not used for validation } }); const HumanOrAlien = new GraphQLUnionType({ - name: 'HumanOrAlien', - types: [ Human, Alien ], + name: "HumanOrAlien", + types: [Human, Alien], resolveType(/* value */) { // not used for validation } }); const FurColor = new GraphQLEnumType({ - name: 'FurColor', + name: "FurColor", values: { BROWN: { value: 0 }, BLACK: { value: 1 }, TAN: { value: 2 }, - SPOTTED: { value: 3 }, - }, + SPOTTED: { value: 3 } + } }); const ComplexInput = new GraphQLInputObjectType({ - name: 'ComplexInput', + name: "ComplexInput", fields: { requiredField: { type: new GraphQLNonNull(GraphQLBoolean) }, intField: { type: GraphQLInt }, stringField: { type: GraphQLString }, booleanField: { type: GraphQLBoolean }, - stringListField: { type: new GraphQLList(GraphQLString) }, + stringListField: { type: new GraphQLList(GraphQLString) } } }); const ComplicatedArgs = new GraphQLObjectType({ - name: 'ComplicatedArgs', + name: "ComplicatedArgs", // TODO List // TODO Coercion // TODO NotNulls fields: () => ({ intArgField: { type: GraphQLString, - args: { intArg: { type: GraphQLInt } }, + args: { intArg: { type: GraphQLInt } } }, nonNullIntArgField: { type: GraphQLString, - args: { nonNullIntArg: { type: new GraphQLNonNull(GraphQLInt) } }, + args: { nonNullIntArg: { type: new GraphQLNonNull(GraphQLInt) } } }, stringArgField: { type: GraphQLString, - args: { stringArg: { type: GraphQLString } }, + args: { stringArg: { type: GraphQLString } } }, booleanArgField: { type: GraphQLString, - args: { booleanArg: { type: GraphQLBoolean } }, + args: { booleanArg: { type: GraphQLBoolean } } }, enumArgField: { type: GraphQLString, - args: { enumArg: { type: FurColor } }, + args: { enumArg: { type: FurColor } } }, floatArgField: { type: GraphQLString, - args: { floatArg: { type: GraphQLFloat } }, + args: { floatArg: { type: GraphQLFloat } } }, idArgField: { type: GraphQLString, - args: { idArg: { type: GraphQLID } }, + args: { idArg: { type: GraphQLID } } }, stringListArgField: { type: GraphQLString, - args: { stringListArg: { type: new GraphQLList(GraphQLString) } }, + args: { stringListArg: { type: new GraphQLList(GraphQLString) } } }, complexArgField: { type: GraphQLString, - args: { complexArg: { type: ComplexInput } }, + args: { complexArg: { type: ComplexInput } } }, multipleReqs: { type: GraphQLString, args: { req1: { type: new GraphQLNonNull(GraphQLInt) }, - req2: { type: new GraphQLNonNull(GraphQLInt) }, - }, + req2: { type: new GraphQLNonNull(GraphQLInt) } + } }, multipleOpts: { type: GraphQLString, args: { opt1: { type: GraphQLInt, - defaultValue: 0, + defaultValue: 0 }, opt2: { type: GraphQLInt, - defaultValue: 0, - }, - }, + defaultValue: 0 + } + } }, multipleOptAndReq: { type: GraphQLString, @@ -272,20 +271,19 @@ const ComplicatedArgs = new GraphQLObjectType({ req2: { type: new GraphQLNonNull(GraphQLInt) }, opt1: { type: GraphQLInt, - defaultValue: 0, + defaultValue: 0 }, opt2: { type: GraphQLInt, - defaultValue: 0, - }, - }, - }, - }), + defaultValue: 0 + } + } + } + }) }); - const QueryRoot = new GraphQLObjectType({ - name: 'QueryRoot', + name: "QueryRoot", fields: () => ({ human: { args: { id: { type: GraphQLID } }, @@ -298,46 +296,46 @@ const QueryRoot = new GraphQLObjectType({ catOrDog: { type: CatOrDog }, dogOrHuman: { type: DogOrHuman }, humanOrAlien: { type: HumanOrAlien }, - complicatedArgs: { type: ComplicatedArgs }, + complicatedArgs: { type: ComplicatedArgs } }) }); export const testSchema = new GraphQLSchema({ query: QueryRoot, - types: [ Cat, Dog, Human, Alien ], + types: [Cat, Dog, Human, Alien], directives: [ new GraphQLDirective({ - name: 'operationOnly', - locations: [ 'QUERY' ], + name: "operationOnly", + locations: ["QUERY"] }), GraphQLIncludeDirective, - GraphQLSkipDirective, + GraphQLSkipDirective ] }); function expectValid(schema, rules, queryString) { const errors = validate(schema, parse(queryString), rules); - expect(errors).to.deep.equal([], 'Should validate'); + expect(errors).to.deep.equal([], "Should validate"); } function expectInvalid(schema, rules, queryString, expectedErrors) { const errors = validate(schema, parse(queryString), rules); - expect(errors).to.have.length.of.at.least(1, 'Should not validate'); + expect(errors).to.have.length.of.at.least(1, "Should not validate"); expect(errors.map(formatError)).to.deep.equal(expectedErrors); } export function expectPassesRule(rule, queryString) { - return expectValid(testSchema, [ rule ], queryString); + return expectValid(testSchema, [rule], queryString); } export function expectFailsRule(rule, queryString, errors) { - return expectInvalid(testSchema, [ rule ], queryString, errors); + return expectInvalid(testSchema, [rule], queryString, errors); } export function expectPassesRuleWithSchema(schema, rule, queryString, errors) { - return expectValid(schema, [ rule ], queryString, errors); + return expectValid(schema, [rule], queryString, errors); } export function expectFailsRuleWithSchema(schema, rule, queryString, errors) { - return expectInvalid(schema, [ rule ], queryString, errors); + return expectInvalid(schema, [rule], queryString, errors); } diff --git a/src/validation/__tests__/validation-test.js b/src/validation/__tests__/validation-test.js index 2a280257f8..ef4dfd70c1 100644 --- a/src/validation/__tests__/validation-test.js +++ b/src/validation/__tests__/validation-test.js @@ -7,24 +7,24 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import { describe, it } from 'mocha'; -import { expect } from 'chai'; -import { testSchema } from './harness'; -import { validate, specifiedRules } from '../'; -import { visitUsingRules } from '../validate'; -import { parse } from '../../language'; -import { TypeInfo } from '../../utilities/TypeInfo'; - +import { describe, it } from "mocha"; +import { expect } from "chai"; +import { testSchema } from "./harness"; +import { validate, specifiedRules } from "../"; +import { visitUsingRules } from "../validate"; +import { parse } from "../../language"; +import { TypeInfo } from "../../utilities/TypeInfo"; function expectValid(schema, queryString) { const errors = validate(schema, parse(queryString)); - expect(errors).to.deep.equal([], 'Should validate'); + expect(errors).to.deep.equal([], "Should validate"); } -describe('Validate: Supports full validation', () => { - - it('validates queries', () => { - expectValid(testSchema, ` +describe("Validate: Supports full validation", () => { + it("validates queries", () => { + expectValid( + testSchema, + ` query { catOrDog { ... on Cat { @@ -35,12 +35,12 @@ describe('Validate: Supports full validation', () => { } } } - `); + ` + ); }); // NOTE: experimental - it('validates using a custom TypeInfo', () => { - + it("validates using a custom TypeInfo", () => { // This TypeInfo will never return a valid field. const typeInfo = new TypeInfo(testSchema, () => null); @@ -57,18 +57,12 @@ describe('Validate: Supports full validation', () => { } `); - const errors = visitUsingRules( - testSchema, - typeInfo, - ast, - specifiedRules - ); + const errors = visitUsingRules(testSchema, typeInfo, ast, specifiedRules); expect(errors).to.deep.equal([ new Error('Cannot query field "catOrDog" on type "QueryRoot".'), new Error('Cannot query field "furColor" on type "Cat".'), - new Error('Cannot query field "isHousetrained" on type "Dog".'), + new Error('Cannot query field "isHousetrained" on type "Dog".') ]); }); - }); diff --git a/src/validation/index.js b/src/validation/index.js index 231bd8208c..a3070b0d6a 100644 --- a/src/validation/index.js +++ b/src/validation/index.js @@ -7,5 +7,5 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -export { validate } from './validate'; -export { specifiedRules } from './specifiedRules'; +export { validate } from "./validate"; +export { specifiedRules } from "./specifiedRules"; diff --git a/src/validation/rules/ArgumentsOfCorrectType.js b/src/validation/rules/ArgumentsOfCorrectType.js index 32d626534e..d303a04a3a 100644 --- a/src/validation/rules/ArgumentsOfCorrectType.js +++ b/src/validation/rules/ArgumentsOfCorrectType.js @@ -8,12 +8,11 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import { print } from '../../language/printer'; -import { isValidLiteralValue } from '../../utilities/isValidLiteralValue'; -import type { GraphQLType } from '../../type/definition'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import { print } from "../../language/printer"; +import { isValidLiteralValue } from "../../utilities/isValidLiteralValue"; +import type { GraphQLType } from "../../type/definition"; export function badValueMessage( argName: string, @@ -21,10 +20,8 @@ export function badValueMessage( value: string, verboseErrors?: [string] ): string { - const message = verboseErrors ? '\n' + verboseErrors.join('\n') : ''; - return ( - `Argument "${argName}" has invalid value ${value}.${message}` - ); + const message = verboseErrors ? "\n" + verboseErrors.join("\n") : ""; + return `Argument "${argName}" has invalid value ${value}.${message}`; } /** @@ -40,15 +37,17 @@ export function ArgumentsOfCorrectType(context: ValidationContext): any { if (argDef) { const errors = isValidLiteralValue(argDef.type, argAST.value); if (errors && errors.length > 0) { - context.reportError(new GraphQLError( - badValueMessage( - argAST.name.value, - argDef.type, - print(argAST.value), - errors - ), - [ argAST.value ] - )); + context.reportError( + new GraphQLError( + badValueMessage( + argAST.name.value, + argDef.type, + print(argAST.value), + errors + ), + [argAST.value] + ) + ); } } return false; diff --git a/src/validation/rules/DefaultValuesOfCorrectType.js b/src/validation/rules/DefaultValuesOfCorrectType.js index 8ca795a0ec..3c81c10490 100644 --- a/src/validation/rules/DefaultValuesOfCorrectType.js +++ b/src/validation/rules/DefaultValuesOfCorrectType.js @@ -8,21 +8,22 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import { print } from '../../language/printer'; -import { GraphQLNonNull } from '../../type/definition'; -import { isValidLiteralValue } from '../../utilities/isValidLiteralValue'; -import type { GraphQLType } from '../../type/definition'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import { print } from "../../language/printer"; +import { GraphQLNonNull } from "../../type/definition"; +import { isValidLiteralValue } from "../../utilities/isValidLiteralValue"; +import type { GraphQLType } from "../../type/definition"; export function defaultForNonNullArgMessage( varName: string, type: GraphQLType, guessType: GraphQLType ): string { - return `Variable "$${varName}" of type "${type}" is required and will not ` + - `use the default value. Perhaps you meant to use type "${guessType}".`; + return ( + `Variable "$${varName}" of type "${type}" is required and will not ` + + `use the default value. Perhaps you meant to use type "${guessType}".` + ); } export function badValueForDefaultArgMessage( @@ -31,7 +32,7 @@ export function badValueForDefaultArgMessage( value: string, verboseErrors?: [string] ): string { - const message = verboseErrors ? '\n' + verboseErrors.join('\n') : ''; + const message = verboseErrors ? "\n" + verboseErrors.join("\n") : ""; return `Variable "$${varName}" has invalid default value ${value}.${message}`; } @@ -48,28 +49,32 @@ export function DefaultValuesOfCorrectType(context: ValidationContext): any { const defaultValue = varDefAST.defaultValue; const type = context.getInputType(); if (type instanceof GraphQLNonNull && defaultValue) { - context.reportError(new GraphQLError( - defaultForNonNullArgMessage(name, type, type.ofType), - [ defaultValue ] - )); + context.reportError( + new GraphQLError( + defaultForNonNullArgMessage(name, type, type.ofType), + [defaultValue] + ) + ); } if (type && defaultValue) { const errors = isValidLiteralValue(type, defaultValue); if (errors && errors.length > 0) { - context.reportError(new GraphQLError( - badValueForDefaultArgMessage( - name, - type, - print(defaultValue), - errors - ), - [ defaultValue ] - )); + context.reportError( + new GraphQLError( + badValueForDefaultArgMessage( + name, + type, + print(defaultValue), + errors + ), + [defaultValue] + ) + ); } } return false; }, SelectionSet: () => false, - FragmentDefinition: () => false, + FragmentDefinition: () => false }; } diff --git a/src/validation/rules/FieldsOnCorrectType.js b/src/validation/rules/FieldsOnCorrectType.js index f2962afa68..66293bed1a 100644 --- a/src/validation/rules/FieldsOnCorrectType.js +++ b/src/validation/rules/FieldsOnCorrectType.js @@ -8,13 +8,12 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import type { Field } from '../../language/ast'; -import type { GraphQLSchema } from '../../type/schema'; -import type { GraphQLAbstractType } from '../../type/definition'; -import { isAbstractType } from '../../type/definition'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import type { Field } from "../../language/ast"; +import type { GraphQLSchema } from "../../type/schema"; +import type { GraphQLAbstractType } from "../../type/definition"; +import { isAbstractType } from "../../type/definition"; export function undefinedFieldMessage( fieldName: string, @@ -27,12 +26,12 @@ export function undefinedFieldMessage( let suggestions = suggestedTypes .slice(0, MAX_LENGTH) .map(t => `"${t}"`) - .join(', '); + .join(", "); if (suggestedTypes.length > MAX_LENGTH) { suggestions += `, and ${suggestedTypes.length - MAX_LENGTH} other types`; } message += ` However, this field exists on ${suggestions}.`; - message += ' Perhaps you meant to use an inline fragment?'; + message += " Perhaps you meant to use an inline fragment?"; } return message; } @@ -63,10 +62,12 @@ export function FieldsOnCorrectType(context: ValidationContext): any { getImplementationsIncludingField(schema, type, node.name.value) ); } - context.reportError(new GraphQLError( - undefinedFieldMessage(node.name.value, type.name, suggestedTypes), - [ node ] - )); + context.reportError( + new GraphQLError( + undefinedFieldMessage(node.name.value, type.name, suggestedTypes), + [node] + ) + ); } } } @@ -81,7 +82,8 @@ function getImplementationsIncludingField( type: GraphQLAbstractType, fieldName: string ): Array { - return schema.getPossibleTypes(type) + return schema + .getPossibleTypes(type) .filter(t => t.getFields()[fieldName] !== undefined) .map(t => t.name) .sort(); @@ -110,7 +112,7 @@ function getSiblingInterfacesIncludingField( }); return acc; }, {}); - return Object.keys(suggestedInterfaces) - .sort((a,b) => suggestedInterfaces[b] - suggestedInterfaces[a]); + return Object.keys(suggestedInterfaces).sort( + (a, b) => suggestedInterfaces[b] - suggestedInterfaces[a] + ); } - diff --git a/src/validation/rules/FragmentsOnCompositeTypes.js b/src/validation/rules/FragmentsOnCompositeTypes.js index f2b87a9321..df612cc52a 100644 --- a/src/validation/rules/FragmentsOnCompositeTypes.js +++ b/src/validation/rules/FragmentsOnCompositeTypes.js @@ -8,12 +8,11 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import { print } from '../../language/printer'; -import { isCompositeType } from '../../type/definition'; -import type { GraphQLType } from '../../type/definition'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import { print } from "../../language/printer"; +import { isCompositeType } from "../../type/definition"; +import type { GraphQLType } from "../../type/definition"; export function inlineFragmentOnNonCompositeErrorMessage( type: GraphQLType @@ -25,8 +24,10 @@ export function fragmentOnNonCompositeErrorMessage( fragName: string, type: GraphQLType ): string { - return `Fragment "${fragName}" cannot condition on non composite ` + - `type "${type}".`; + return ( + `Fragment "${fragName}" cannot condition on non composite ` + + `type "${type}".` + ); } /** @@ -41,22 +42,26 @@ export function FragmentsOnCompositeTypes(context: ValidationContext): any { InlineFragment(node) { const type = context.getType(); if (node.typeCondition && type && !isCompositeType(type)) { - context.reportError(new GraphQLError( - inlineFragmentOnNonCompositeErrorMessage(print(node.typeCondition)), - [ node.typeCondition ] - )); + context.reportError( + new GraphQLError( + inlineFragmentOnNonCompositeErrorMessage(print(node.typeCondition)), + [node.typeCondition] + ) + ); } }, FragmentDefinition(node) { const type = context.getType(); if (type && !isCompositeType(type)) { - context.reportError(new GraphQLError( - fragmentOnNonCompositeErrorMessage( - node.name.value, - print(node.typeCondition) - ), - [ node.typeCondition ] - )); + context.reportError( + new GraphQLError( + fragmentOnNonCompositeErrorMessage( + node.name.value, + print(node.typeCondition) + ), + [node.typeCondition] + ) + ); } } }; diff --git a/src/validation/rules/KnownArgumentNames.js b/src/validation/rules/KnownArgumentNames.js index e389d65371..c8ad9c15d2 100644 --- a/src/validation/rules/KnownArgumentNames.js +++ b/src/validation/rules/KnownArgumentNames.js @@ -8,24 +8,22 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import find from '../../jsutils/find'; -import invariant from '../../jsutils/invariant'; -import { - FIELD, - DIRECTIVE -} from '../../language/kinds'; -import type { GraphQLType } from '../../type/definition'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import find from "../../jsutils/find"; +import invariant from "../../jsutils/invariant"; +import { FIELD, DIRECTIVE } from "../../language/kinds"; +import type { GraphQLType } from "../../type/definition"; export function unknownArgMessage( argName: string, fieldName: string, type: GraphQLType ): string { - return `Unknown argument "${argName}" on field "${fieldName}" of ` + - `type "${type}".`; + return ( + `Unknown argument "${argName}" on field "${fieldName}" of ` + + `type "${type}".` + ); } export function unknownDirectiveArgMessage( @@ -55,14 +53,16 @@ export function KnownArgumentNames(context: ValidationContext): any { if (!fieldArgDef) { const parentType = context.getParentType(); invariant(parentType); - context.reportError(new GraphQLError( - unknownArgMessage( - node.name.value, - fieldDef.name, - parentType.name - ), - [ node ] - )); + context.reportError( + new GraphQLError( + unknownArgMessage( + node.name.value, + fieldDef.name, + parentType.name + ), + [node] + ) + ); } } } else if (argumentOf.kind === DIRECTIVE) { @@ -73,10 +73,12 @@ export function KnownArgumentNames(context: ValidationContext): any { arg => arg.name === node.name.value ); if (!directiveArgDef) { - context.reportError(new GraphQLError( - unknownDirectiveArgMessage(node.name.value, directive.name), - [ node ] - )); + context.reportError( + new GraphQLError( + unknownDirectiveArgMessage(node.name.value, directive.name), + [node] + ) + ); } } } diff --git a/src/validation/rules/KnownDirectives.js b/src/validation/rules/KnownDirectives.js index 5ed6383868..ddd91d43d7 100644 --- a/src/validation/rules/KnownDirectives.js +++ b/src/validation/rules/KnownDirectives.js @@ -8,18 +8,17 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import find from '../../jsutils/find'; +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import find from "../../jsutils/find"; import { OPERATION_DEFINITION, FIELD, FRAGMENT_SPREAD, INLINE_FRAGMENT, FRAGMENT_DEFINITION -} from '../../language/kinds'; -import { DirectiveLocation } from '../../type/directives'; - +} from "../../language/kinds"; +import { DirectiveLocation } from "../../type/directives"; export function unknownDirectiveMessage(directiveName: string): string { return `Unknown directive "${directiveName}".`; @@ -46,24 +45,27 @@ export function KnownDirectives(context: ValidationContext): any { def => def.name === node.name.value ); if (!directiveDef) { - context.reportError(new GraphQLError( - unknownDirectiveMessage(node.name.value), - [ node ] - )); + context.reportError( + new GraphQLError(unknownDirectiveMessage(node.name.value), [node]) + ); return; } const appliedTo = ancestors[ancestors.length - 1]; const candidateLocation = getLocationForAppliedNode(appliedTo); if (!candidateLocation) { - context.reportError(new GraphQLError( - misplacedDirectiveMessage(node.name.value, node.type), - [ node ] - )); + context.reportError( + new GraphQLError( + misplacedDirectiveMessage(node.name.value, node.type), + [node] + ) + ); } else if (directiveDef.locations.indexOf(candidateLocation) === -1) { - context.reportError(new GraphQLError( - misplacedDirectiveMessage(node.name.value, candidateLocation), - [ node ] - )); + context.reportError( + new GraphQLError( + misplacedDirectiveMessage(node.name.value, candidateLocation), + [node] + ) + ); } } }; @@ -73,14 +75,21 @@ function getLocationForAppliedNode(appliedTo) { switch (appliedTo.kind) { case OPERATION_DEFINITION: switch (appliedTo.operation) { - case 'query': return DirectiveLocation.QUERY; - case 'mutation': return DirectiveLocation.MUTATION; - case 'subscription': return DirectiveLocation.SUBSCRIPTION; + case "query": + return DirectiveLocation.QUERY; + case "mutation": + return DirectiveLocation.MUTATION; + case "subscription": + return DirectiveLocation.SUBSCRIPTION; } break; - case FIELD: return DirectiveLocation.FIELD; - case FRAGMENT_SPREAD: return DirectiveLocation.FRAGMENT_SPREAD; - case INLINE_FRAGMENT: return DirectiveLocation.INLINE_FRAGMENT; - case FRAGMENT_DEFINITION: return DirectiveLocation.FRAGMENT_DEFINITION; + case FIELD: + return DirectiveLocation.FIELD; + case FRAGMENT_SPREAD: + return DirectiveLocation.FRAGMENT_SPREAD; + case INLINE_FRAGMENT: + return DirectiveLocation.INLINE_FRAGMENT; + case FRAGMENT_DEFINITION: + return DirectiveLocation.FRAGMENT_DEFINITION; } } diff --git a/src/validation/rules/KnownFragmentNames.js b/src/validation/rules/KnownFragmentNames.js index d725fa620a..1e3303d46b 100644 --- a/src/validation/rules/KnownFragmentNames.js +++ b/src/validation/rules/KnownFragmentNames.js @@ -8,9 +8,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; export function unknownFragmentMessage(fragName: string): string { return `Unknown fragment "${fragName}".`; @@ -28,10 +27,9 @@ export function KnownFragmentNames(context: ValidationContext): any { const fragmentName = node.name.value; const fragment = context.getFragment(fragmentName); if (!fragment) { - context.reportError(new GraphQLError( - unknownFragmentMessage(fragmentName), - [ node.name ] - )); + context.reportError( + new GraphQLError(unknownFragmentMessage(fragmentName), [node.name]) + ); } } }; diff --git a/src/validation/rules/KnownTypeNames.js b/src/validation/rules/KnownTypeNames.js index 6ab367c3d9..f5af2431d7 100644 --- a/src/validation/rules/KnownTypeNames.js +++ b/src/validation/rules/KnownTypeNames.js @@ -8,10 +8,9 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import type { GraphQLType } from '../../type/definition'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import type { GraphQLType } from "../../type/definition"; export function unknownTypeMessage(type: GraphQLType): string { return `Unknown type "${type}".`; @@ -37,7 +36,7 @@ export function KnownTypeNames(context: ValidationContext): any { const type = context.getSchema().getType(typeName); if (!type) { context.reportError( - new GraphQLError(unknownTypeMessage(typeName), [ node ]) + new GraphQLError(unknownTypeMessage(typeName), [node]) ); } } diff --git a/src/validation/rules/LoneAnonymousOperation.js b/src/validation/rules/LoneAnonymousOperation.js index 33e05fd622..69e3163de5 100644 --- a/src/validation/rules/LoneAnonymousOperation.js +++ b/src/validation/rules/LoneAnonymousOperation.js @@ -8,13 +8,12 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import { OPERATION_DEFINITION } from '../../language/kinds'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import { OPERATION_DEFINITION } from "../../language/kinds"; export function anonOperationNotAloneMessage(): string { - return 'This anonymous operation must be the only defined operation.'; + return "This anonymous operation must be the only defined operation."; } /** @@ -34,7 +33,7 @@ export function LoneAnonymousOperation(context: ValidationContext): any { OperationDefinition(node) { if (!node.name && operationCount > 1) { context.reportError( - new GraphQLError(anonOperationNotAloneMessage(), [ node ]) + new GraphQLError(anonOperationNotAloneMessage(), [node]) ); } } diff --git a/src/validation/rules/NoFragmentCycles.js b/src/validation/rules/NoFragmentCycles.js index c939925bfa..540160ba1c 100644 --- a/src/validation/rules/NoFragmentCycles.js +++ b/src/validation/rules/NoFragmentCycles.js @@ -8,16 +8,15 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import type { FragmentDefinition } from '../../language/ast'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import type { FragmentDefinition } from "../../language/ast"; export function cycleErrorMessage( fragName: string, spreadNames: Array ): string { - const via = spreadNames.length ? ' via ' + spreadNames.join(', ') : ''; + const via = spreadNames.length ? " via " + spreadNames.join(", ") : ""; return `Cannot spread fragment "${fragName}" within itself${via}.`; } @@ -39,7 +38,7 @@ export function NoFragmentCycles(context: ValidationContext): any { detectCycleRecursive(node); } return false; - }, + } }; // This does a straight-forward DFS to find cycles. @@ -72,13 +71,12 @@ export function NoFragmentCycles(context: ValidationContext): any { spreadPath.pop(); } else { const cyclePath = spreadPath.slice(cycleIndex); - context.reportError(new GraphQLError( - cycleErrorMessage( - spreadName, - cyclePath.map(s => s.name.value) - ), - cyclePath.concat(spreadNode) - )); + context.reportError( + new GraphQLError( + cycleErrorMessage(spreadName, cyclePath.map(s => s.name.value)), + cyclePath.concat(spreadNode) + ) + ); } } diff --git a/src/validation/rules/NoUndefinedVariables.js b/src/validation/rules/NoUndefinedVariables.js index 353e253130..91eccc67de 100644 --- a/src/validation/rules/NoUndefinedVariables.js +++ b/src/validation/rules/NoUndefinedVariables.js @@ -8,14 +8,13 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; export function undefinedVarMessage(varName: string, opName: ?string): string { - return opName ? - `Variable "$${varName}" is not defined by operation "${opName}".` : - `Variable "$${varName}" is not defined.`; + return opName + ? `Variable "$${varName}" is not defined by operation "${opName}".` + : `Variable "$${varName}" is not defined.`; } /** @@ -38,13 +37,15 @@ export function NoUndefinedVariables(context: ValidationContext): any { usages.forEach(({ node }) => { const varName = node.name.value; if (variableNameDefined[varName] !== true) { - context.reportError(new GraphQLError( - undefinedVarMessage( - varName, - operation.name && operation.name.value - ), - [ node, operation ] - )); + context.reportError( + new GraphQLError( + undefinedVarMessage( + varName, + operation.name && operation.name.value + ), + [node, operation] + ) + ); } }); } diff --git a/src/validation/rules/NoUnusedFragments.js b/src/validation/rules/NoUnusedFragments.js index ce965f4f00..098c5d88d0 100644 --- a/src/validation/rules/NoUnusedFragments.js +++ b/src/validation/rules/NoUnusedFragments.js @@ -8,9 +8,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; export function unusedFragMessage(fragName: string): string { return `Fragment "${fragName}" is never used.`; @@ -39,18 +38,19 @@ export function NoUnusedFragments(context: ValidationContext): any { leave() { const fragmentNameUsed = Object.create(null); operationDefs.forEach(operation => { - context.getRecursivelyReferencedFragments(operation).forEach( - fragment => { fragmentNameUsed[fragment.name.value] = true; } - ); + context + .getRecursivelyReferencedFragments(operation) + .forEach(fragment => { + fragmentNameUsed[fragment.name.value] = true; + }); }); fragmentDefs.forEach(fragmentDef => { const fragName = fragmentDef.name.value; if (fragmentNameUsed[fragName] !== true) { - context.reportError(new GraphQLError( - unusedFragMessage(fragName), - [ fragmentDef ] - )); + context.reportError( + new GraphQLError(unusedFragMessage(fragName), [fragmentDef]) + ); } }); } diff --git a/src/validation/rules/NoUnusedVariables.js b/src/validation/rules/NoUnusedVariables.js index 1a2066c588..bdcdfbf457 100644 --- a/src/validation/rules/NoUnusedVariables.js +++ b/src/validation/rules/NoUnusedVariables.js @@ -8,17 +8,16 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; export function unusedVariableMessage( varName: string, opName: ?string ): string { - return opName ? - `Variable "$${varName}" is never used in operation "${opName}".` : - `Variable "$${varName}" is never used.`; + return opName + ? `Variable "$${varName}" is never used in operation "${opName}".` + : `Variable "$${varName}" is never used.`; } /** @@ -47,10 +46,11 @@ export function NoUnusedVariables(context: ValidationContext): any { variableDefs.forEach(variableDef => { const variableName = variableDef.variable.name.value; if (variableNameUsed[variableName] !== true) { - context.reportError(new GraphQLError( - unusedVariableMessage(variableName, opName), - [ variableDef ] - )); + context.reportError( + new GraphQLError(unusedVariableMessage(variableName, opName), [ + variableDef + ]) + ); } }); } diff --git a/src/validation/rules/OverlappingFieldsCanBeMerged.js b/src/validation/rules/OverlappingFieldsCanBeMerged.js index 2c2c8edcab..dbb280a70f 100644 --- a/src/validation/rules/OverlappingFieldsCanBeMerged.js +++ b/src/validation/rules/OverlappingFieldsCanBeMerged.js @@ -8,32 +8,27 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import find from '../../jsutils/find'; -import type { - SelectionSet, - Field, - Argument, -} from '../../language/ast'; -import { FIELD, INLINE_FRAGMENT, FRAGMENT_SPREAD } from '../../language/kinds'; -import { print } from '../../language/printer'; +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import find from "../../jsutils/find"; +import type { SelectionSet, Field, Argument } from "../../language/ast"; +import { FIELD, INLINE_FRAGMENT, FRAGMENT_SPREAD } from "../../language/kinds"; +import { print } from "../../language/printer"; import { getNamedType, isLeafType, GraphQLList, GraphQLNonNull, GraphQLObjectType, - GraphQLInterfaceType, -} from '../../type/definition'; + GraphQLInterfaceType +} from "../../type/definition"; import type { GraphQLNamedType, GraphQLOutputType, GraphQLCompositeType, GraphQLFieldDefinition -} from '../../type/definition'; -import { typeFromAST } from '../../utilities/typeFromAST'; - +} from "../../type/definition"; +import { typeFromAST } from "../../utilities/typeFromAST"; export function fieldsConflictMessage( responseName: string, @@ -44,9 +39,14 @@ export function fieldsConflictMessage( function reasonMessage(reason: ConflictReasonMessage): string { if (Array.isArray(reason)) { - return reason.map(([ responseName, subreason ]) => - `subfields "${responseName}" conflict because ${reasonMessage(subreason)}` - ).join(' and '); + return reason + .map( + ([responseName, subreason]) => + `subfields "${responseName}" conflict because ${reasonMessage( + subreason + )}` + ) + .join(" and "); } return reason; } @@ -93,8 +93,8 @@ export function OverlappingFieldsCanBeMerged(context: ValidationContext): any { field1: AstAndDef, field2: AstAndDef ): ?Conflict { - const [ parentType1, ast1, def1 ] = field1; - const [ parentType2, ast2, def2 ] = field2; + const [parentType1, ast1, def1] = field1; + const [parentType2, ast2, def2] = field2; // Not a pair. if (ast1 === ast2) { @@ -129,9 +129,9 @@ export function OverlappingFieldsCanBeMerged(context: ValidationContext): any { // thus may not safely diverge. const fieldsAreMutuallyExclusive = parentFieldsAreMutuallyExclusive || - parentType1 !== parentType2 && - parentType1 instanceof GraphQLObjectType && - parentType2 instanceof GraphQLObjectType; + (parentType1 !== parentType2 && + parentType1 instanceof GraphQLObjectType && + parentType2 instanceof GraphQLObjectType); if (!fieldsAreMutuallyExclusive) { // Two aliases must refer to the same field. @@ -139,27 +139,27 @@ export function OverlappingFieldsCanBeMerged(context: ValidationContext): any { const name2 = ast2.name.value; if (name1 !== name2) { return [ - [ responseName, `${name1} and ${name2} are different fields` ], - [ ast1 ], - [ ast2 ] + [responseName, `${name1} and ${name2} are different fields`], + [ast1], + [ast2] ]; } // Two field calls must have the same arguments. if (!sameArguments(ast1.arguments || [], ast2.arguments || [])) { return [ - [ responseName, 'they have differing arguments' ], - [ ast1 ], - [ ast2 ] + [responseName, "they have differing arguments"], + [ast1], + [ast2] ]; } } if (type1 && type2 && doTypesConflict(type1, type2)) { return [ - [ responseName, `they return conflicting types ${type1} and ${type2}` ], - [ ast1 ], - [ ast2 ] + [responseName, `they return conflicting types ${type1} and ${type2}`], + [ast1], + [ast2] ]; } @@ -205,14 +205,14 @@ export function OverlappingFieldsCanBeMerged(context: ValidationContext): any { ): ?Conflict { if (conflicts.length > 0) { return [ - [ responseName, conflicts.map(([ reason ]) => reason) ], + [responseName, conflicts.map(([reason]) => reason)], conflicts.reduce( - (allFields, [ , fields1 ]) => allFields.concat(fields1), - [ ast1 ] + (allFields, [, fields1]) => allFields.concat(fields1), + [ast1] ), conflicts.reduce( - (allFields, [ , , fields2 ]) => allFields.concat(fields2), - [ ast2 ] + (allFields, [, , fields2]) => allFields.concat(fields2), + [ast2] ) ]; } @@ -230,25 +230,26 @@ export function OverlappingFieldsCanBeMerged(context: ValidationContext): any { selectionSet ); const conflicts = findConflicts(false, fieldMap); - conflicts.forEach( - ([ [ responseName, reason ], fields1, fields2 ]) => - context.reportError(new GraphQLError( + conflicts.forEach(([[responseName, reason], fields1, fields2]) => + context.reportError( + new GraphQLError( fieldsConflictMessage(responseName, reason), fields1.concat(fields2) - )) + ) + ) ); } } }; } -type Conflict = [ ConflictReason, Array, Array ]; +type Conflict = [ConflictReason, Array, Array]; // Field name and reason. -type ConflictReason = [ string, ConflictReasonMessage ]; +type ConflictReason = [string, ConflictReasonMessage]; // Reason is a string, or a nested list of conflicts. type ConflictReasonMessage = string | Array; // Tuple defining an AST in a context -type AstAndDef = [ GraphQLCompositeType, Field, ?GraphQLFieldDefinition ]; +type AstAndDef = [GraphQLCompositeType, Field, ?GraphQLFieldDefinition]; // Map of array of those. type AstAndDefCollection = { [key: string]: Array }; @@ -283,24 +284,24 @@ function doTypesConflict( type2: GraphQLOutputType ): boolean { if (type1 instanceof GraphQLList) { - return type2 instanceof GraphQLList ? - doTypesConflict(type1.ofType, type2.ofType) : - true; + return type2 instanceof GraphQLList + ? doTypesConflict(type1.ofType, type2.ofType) + : true; } if (type2 instanceof GraphQLList) { - return type1 instanceof GraphQLList ? - doTypesConflict(type1.ofType, type2.ofType) : - true; + return type1 instanceof GraphQLList + ? doTypesConflict(type1.ofType, type2.ofType) + : true; } if (type1 instanceof GraphQLNonNull) { - return type2 instanceof GraphQLNonNull ? - doTypesConflict(type1.ofType, type2.ofType) : - true; + return type2 instanceof GraphQLNonNull + ? doTypesConflict(type1.ofType, type2.ofType) + : true; } if (type2 instanceof GraphQLNonNull) { - return type1 instanceof GraphQLNonNull ? - doTypesConflict(type1.ofType, type2.ofType) : - true; + return type1 instanceof GraphQLNonNull + ? doTypesConflict(type1.ofType, type2.ofType) + : true; } if (isLeafType(type1) || isLeafType(type2)) { return type1 !== type2; @@ -320,7 +321,7 @@ function collectFieldASTsAndDefs( context: ValidationContext, parentType: ?GraphQLNamedType, selectionSet: SelectionSet, - visitedFragmentNames?: {[key: string]: boolean}, + visitedFragmentNames?: { [key: string]: boolean }, astAndDefs?: AstAndDefCollection ): AstAndDefCollection { const _visitedFragmentNames = visitedFragmentNames || {}; @@ -331,22 +332,25 @@ function collectFieldASTsAndDefs( case FIELD: const fieldName = selection.name.value; let fieldDef; - if (parentType instanceof GraphQLObjectType || - parentType instanceof GraphQLInterfaceType) { + if ( + parentType instanceof GraphQLObjectType || + parentType instanceof GraphQLInterfaceType + ) { fieldDef = parentType.getFields()[fieldName]; } - const responseName = - selection.alias ? selection.alias.value : fieldName; + const responseName = selection.alias + ? selection.alias.value + : fieldName; if (!_astAndDefs[responseName]) { _astAndDefs[responseName] = []; } - _astAndDefs[responseName].push([ parentType, selection, fieldDef ]); + _astAndDefs[responseName].push([parentType, selection, fieldDef]); break; case INLINE_FRAGMENT: const typeCondition = selection.typeCondition; - const inlineFragmentType = typeCondition ? - typeFromAST(context.getSchema(), selection.typeCondition) : - parentType; + const inlineFragmentType = typeCondition + ? typeFromAST(context.getSchema(), selection.typeCondition) + : parentType; _astAndDefs = collectFieldASTsAndDefs( context, ((inlineFragmentType: any): GraphQLNamedType), @@ -365,8 +369,10 @@ function collectFieldASTsAndDefs( if (!fragment) { continue; } - const fragmentType = - typeFromAST(context.getSchema(), fragment.typeCondition); + const fragmentType = typeFromAST( + context.getSchema(), + fragment.typeCondition + ); _astAndDefs = collectFieldASTsAndDefs( context, ((fragmentType: any): GraphQLNamedType), diff --git a/src/validation/rules/PossibleFragmentSpreads.js b/src/validation/rules/PossibleFragmentSpreads.js index a02bdc3f1a..c2302d90be 100644 --- a/src/validation/rules/PossibleFragmentSpreads.js +++ b/src/validation/rules/PossibleFragmentSpreads.js @@ -8,28 +8,31 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import { doTypesOverlap } from '../../utilities/typeComparators'; -import { typeFromAST } from '../../utilities/typeFromAST'; -import type { GraphQLType } from '../../type/definition'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import { doTypesOverlap } from "../../utilities/typeComparators"; +import { typeFromAST } from "../../utilities/typeFromAST"; +import type { GraphQLType } from "../../type/definition"; export function typeIncompatibleSpreadMessage( fragName: string, parentType: GraphQLType, fragType: GraphQLType ): string { - return `Fragment "${fragName}" cannot be spread here as objects of ` + - `type "${parentType}" can never be of type "${fragType}".`; + return ( + `Fragment "${fragName}" cannot be spread here as objects of ` + + `type "${parentType}" can never be of type "${fragType}".` + ); } export function typeIncompatibleAnonSpreadMessage( parentType: GraphQLType, fragType: GraphQLType ): string { - return 'Fragment cannot be spread here as objects of ' + - `type "${parentType}" can never be of type "${fragType}".`; + return ( + "Fragment cannot be spread here as objects of " + + `type "${parentType}" can never be of type "${fragType}".` + ); } /** @@ -44,26 +47,34 @@ export function PossibleFragmentSpreads(context: ValidationContext): any { InlineFragment(node) { const fragType = context.getType(); const parentType = context.getParentType(); - if (fragType && - parentType && - !doTypesOverlap(context.getSchema(), fragType, parentType)) { - context.reportError(new GraphQLError( - typeIncompatibleAnonSpreadMessage(parentType, fragType), - [ node ] - )); + if ( + fragType && + parentType && + !doTypesOverlap(context.getSchema(), fragType, parentType) + ) { + context.reportError( + new GraphQLError( + typeIncompatibleAnonSpreadMessage(parentType, fragType), + [node] + ) + ); } }, FragmentSpread(node) { const fragName = node.name.value; const fragType = getFragmentType(context, fragName); const parentType = context.getParentType(); - if (fragType && - parentType && - !doTypesOverlap(context.getSchema(), fragType, parentType)) { - context.reportError(new GraphQLError( - typeIncompatibleSpreadMessage(fragName, parentType, fragType), - [ node ] - )); + if ( + fragType && + parentType && + !doTypesOverlap(context.getSchema(), fragType, parentType) + ) { + context.reportError( + new GraphQLError( + typeIncompatibleSpreadMessage(fragName, parentType, fragType), + [node] + ) + ); } } }; diff --git a/src/validation/rules/ProvidedNonNullArguments.js b/src/validation/rules/ProvidedNonNullArguments.js index a02f010036..4937684741 100644 --- a/src/validation/rules/ProvidedNonNullArguments.js +++ b/src/validation/rules/ProvidedNonNullArguments.js @@ -8,20 +8,21 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import keyMap from '../../jsutils/keyMap'; -import { GraphQLNonNull } from '../../type/definition'; -import type { GraphQLType } from '../../type/definition'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import keyMap from "../../jsutils/keyMap"; +import { GraphQLNonNull } from "../../type/definition"; +import type { GraphQLType } from "../../type/definition"; export function missingFieldArgMessage( fieldName: string, argName: string, type: GraphQLType ): string { - return `Field "${fieldName}" argument "${argName}" of type "${type}" ` + - 'is required but not provided.'; + return ( + `Field "${fieldName}" argument "${argName}" of type "${type}" ` + + "is required but not provided." + ); } export function missingDirectiveArgMessage( @@ -29,8 +30,10 @@ export function missingDirectiveArgMessage( argName: string, type: GraphQLType ): string { - return `Directive "@${directiveName}" argument "${argName}" of type ` + - `"${type}" is required but not provided.`; + return ( + `Directive "@${directiveName}" argument "${argName}" of type ` + + `"${type}" is required but not provided.` + ); } /** @@ -54,14 +57,16 @@ export function ProvidedNonNullArguments(context: ValidationContext): any { fieldDef.args.forEach(argDef => { const argAST = argASTMap[argDef.name]; if (!argAST && argDef.type instanceof GraphQLNonNull) { - context.reportError(new GraphQLError( - missingFieldArgMessage( - fieldAST.name.value, - argDef.name, - argDef.type - ), - [ fieldAST ] - )); + context.reportError( + new GraphQLError( + missingFieldArgMessage( + fieldAST.name.value, + argDef.name, + argDef.type + ), + [fieldAST] + ) + ); } }); } @@ -80,14 +85,16 @@ export function ProvidedNonNullArguments(context: ValidationContext): any { directiveDef.args.forEach(argDef => { const argAST = argASTMap[argDef.name]; if (!argAST && argDef.type instanceof GraphQLNonNull) { - context.reportError(new GraphQLError( - missingDirectiveArgMessage( - directiveAST.name.value, - argDef.name, - argDef.type - ), - [ directiveAST ] - )); + context.reportError( + new GraphQLError( + missingDirectiveArgMessage( + directiveAST.name.value, + argDef.name, + argDef.type + ), + [directiveAST] + ) + ); } }); } diff --git a/src/validation/rules/ScalarLeafs.js b/src/validation/rules/ScalarLeafs.js index e48b76edd8..e40f7da29e 100644 --- a/src/validation/rules/ScalarLeafs.js +++ b/src/validation/rules/ScalarLeafs.js @@ -8,12 +8,11 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import type { Field } from '../../language/ast'; -import { isLeafType } from '../../type/definition'; -import type { GraphQLType } from '../../type/definition'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import type { Field } from "../../language/ast"; +import { isLeafType } from "../../type/definition"; +import type { GraphQLType } from "../../type/definition"; export function noSubselectionAllowedMessage( field: string, @@ -42,16 +41,20 @@ export function ScalarLeafs(context: ValidationContext): any { if (type) { if (isLeafType(type)) { if (node.selectionSet) { - context.reportError(new GraphQLError( - noSubselectionAllowedMessage(node.name.value, type), - [ node.selectionSet ] - )); + context.reportError( + new GraphQLError( + noSubselectionAllowedMessage(node.name.value, type), + [node.selectionSet] + ) + ); } } else if (!node.selectionSet) { - context.reportError(new GraphQLError( - requiredSubselectionMessage(node.name.value, type), - [ node ] - )); + context.reportError( + new GraphQLError( + requiredSubselectionMessage(node.name.value, type), + [node] + ) + ); } } } diff --git a/src/validation/rules/UniqueArgumentNames.js b/src/validation/rules/UniqueArgumentNames.js index 723d82f376..23962990fb 100644 --- a/src/validation/rules/UniqueArgumentNames.js +++ b/src/validation/rules/UniqueArgumentNames.js @@ -8,9 +8,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; export function duplicateArgMessage(argName: string): string { return `There can be only one argument named "${argName}".`; @@ -34,10 +33,12 @@ export function UniqueArgumentNames(context: ValidationContext): any { Argument(node) { const argName = node.name.value; if (knownArgNames[argName]) { - context.reportError(new GraphQLError( - duplicateArgMessage(argName), - [ knownArgNames[argName], node.name ] - )); + context.reportError( + new GraphQLError(duplicateArgMessage(argName), [ + knownArgNames[argName], + node.name + ]) + ); } else { knownArgNames[argName] = node.name; } diff --git a/src/validation/rules/UniqueFragmentNames.js b/src/validation/rules/UniqueFragmentNames.js index a0cfdecfe4..0ae21d3e4b 100644 --- a/src/validation/rules/UniqueFragmentNames.js +++ b/src/validation/rules/UniqueFragmentNames.js @@ -8,9 +8,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; export function duplicateFragmentNameMessage(fragName: string): string { return `There can only be one fragment named "${fragName}".`; @@ -28,10 +27,12 @@ export function UniqueFragmentNames(context: ValidationContext): any { FragmentDefinition(node) { const fragmentName = node.name.value; if (knownFragmentNames[fragmentName]) { - context.reportError(new GraphQLError( - duplicateFragmentNameMessage(fragmentName), - [ knownFragmentNames[fragmentName], node.name ] - )); + context.reportError( + new GraphQLError(duplicateFragmentNameMessage(fragmentName), [ + knownFragmentNames[fragmentName], + node.name + ]) + ); } else { knownFragmentNames[fragmentName] = node.name; } diff --git a/src/validation/rules/UniqueInputFieldNames.js b/src/validation/rules/UniqueInputFieldNames.js index c20412d669..2bad1a53c1 100644 --- a/src/validation/rules/UniqueInputFieldNames.js +++ b/src/validation/rules/UniqueInputFieldNames.js @@ -8,9 +8,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; export function duplicateInputFieldMessage(fieldName: string): string { return `There can be only one input field named "${fieldName}".`; @@ -39,10 +38,12 @@ export function UniqueInputFieldNames(context: ValidationContext): any { ObjectField(node) { const fieldName = node.name.value; if (knownNames[fieldName]) { - context.reportError(new GraphQLError( - duplicateInputFieldMessage(fieldName), - [ knownNames[fieldName], node.name ] - )); + context.reportError( + new GraphQLError(duplicateInputFieldMessage(fieldName), [ + knownNames[fieldName], + node.name + ]) + ); } else { knownNames[fieldName] = node.name; } diff --git a/src/validation/rules/UniqueOperationNames.js b/src/validation/rules/UniqueOperationNames.js index 97ff972a2d..62caea8541 100644 --- a/src/validation/rules/UniqueOperationNames.js +++ b/src/validation/rules/UniqueOperationNames.js @@ -8,9 +8,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; export function duplicateOperationNameMessage(operationName: string): string { return `There can only be one operation named "${operationName}".`; @@ -28,16 +27,18 @@ export function UniqueOperationNames(context: ValidationContext): any { const operationName = node.name; if (operationName) { if (knownOperationNames[operationName.value]) { - context.reportError(new GraphQLError( - duplicateOperationNameMessage(operationName.value), - [ knownOperationNames[operationName.value], operationName ] - )); + context.reportError( + new GraphQLError( + duplicateOperationNameMessage(operationName.value), + [knownOperationNames[operationName.value], operationName] + ) + ); } else { knownOperationNames[operationName.value] = operationName; } } return false; }, - FragmentDefinition: () => false, + FragmentDefinition: () => false }; } diff --git a/src/validation/rules/UniqueVariableNames.js b/src/validation/rules/UniqueVariableNames.js index 607b558150..bb9874d699 100644 --- a/src/validation/rules/UniqueVariableNames.js +++ b/src/validation/rules/UniqueVariableNames.js @@ -8,10 +8,9 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import type { VariableDefinition } from '../../language/ast'; -import { GraphQLError } from '../../error'; - +import type { ValidationContext } from "../index"; +import type { VariableDefinition } from "../../language/ast"; +import { GraphQLError } from "../../error"; export function duplicateVariableMessage(variableName: string): string { return `There can be only one variable named "${variableName}".`; @@ -31,10 +30,12 @@ export function UniqueVariableNames(context: ValidationContext): any { VariableDefinition(node: VariableDefinition) { const variableName = node.variable.name.value; if (knownVariableNames[variableName]) { - context.reportError(new GraphQLError( - duplicateVariableMessage(variableName), - [ knownVariableNames[variableName], node.variable.name ] - )); + context.reportError( + new GraphQLError(duplicateVariableMessage(variableName), [ + knownVariableNames[variableName], + node.variable.name + ]) + ); } else { knownVariableNames[variableName] = node.variable.name; } diff --git a/src/validation/rules/VariablesAreInputTypes.js b/src/validation/rules/VariablesAreInputTypes.js index 94bebd9f2f..cf271d23e2 100644 --- a/src/validation/rules/VariablesAreInputTypes.js +++ b/src/validation/rules/VariablesAreInputTypes.js @@ -8,13 +8,12 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import type { VariableDefinition } from '../../language/ast'; -import { print } from '../../language/printer'; -import { isInputType } from '../../type/definition'; -import { typeFromAST } from '../../utilities/typeFromAST'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import type { VariableDefinition } from "../../language/ast"; +import { print } from "../../language/printer"; +import { isInputType } from "../../type/definition"; +import { typeFromAST } from "../../utilities/typeFromAST"; export function nonInputTypeOnVarMessage( variableName: string, @@ -37,10 +36,12 @@ export function VariablesAreInputTypes(context: ValidationContext): any { // If the variable type is not an input type, return an error. if (type && !isInputType(type)) { const variableName = node.variable.name.value; - context.reportError(new GraphQLError( - nonInputTypeOnVarMessage(variableName, print(node.type)), - [ node.type ] - )); + context.reportError( + new GraphQLError( + nonInputTypeOnVarMessage(variableName, print(node.type)), + [node.type] + ) + ); } } }; diff --git a/src/validation/rules/VariablesInAllowedPosition.js b/src/validation/rules/VariablesInAllowedPosition.js index 930e7077e3..43544209c6 100644 --- a/src/validation/rules/VariablesInAllowedPosition.js +++ b/src/validation/rules/VariablesInAllowedPosition.js @@ -8,21 +8,22 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import type { ValidationContext } from '../index'; -import { GraphQLError } from '../../error'; -import { GraphQLNonNull } from '../../type/definition'; -import { isTypeSubTypeOf } from '../../utilities/typeComparators'; -import { typeFromAST } from '../../utilities/typeFromAST'; -import type { GraphQLType } from '../../type/definition'; - +import type { ValidationContext } from "../index"; +import { GraphQLError } from "../../error"; +import { GraphQLNonNull } from "../../type/definition"; +import { isTypeSubTypeOf } from "../../utilities/typeComparators"; +import { typeFromAST } from "../../utilities/typeFromAST"; +import type { GraphQLType } from "../../type/definition"; export function badVarPosMessage( varName: string, varType: GraphQLType, expectedType: GraphQLType ): string { - return `Variable "$${varName}" of type "${varType}" used in position ` + - `expecting type "${expectedType}".`; + return ( + `Variable "$${varName}" of type "${varType}" used in position ` + + `expecting type "${expectedType}".` + ); } /** @@ -54,10 +55,12 @@ export function VariablesInAllowedPosition(context: ValidationContext): any { varType && !isTypeSubTypeOf(schema, effectiveType(varType, varDef), type) ) { - context.reportError(new GraphQLError( - badVarPosMessage(varName, varType, type), - [ varDef, node ] - )); + context.reportError( + new GraphQLError(badVarPosMessage(varName, varType, type), [ + varDef, + node + ]) + ); } } }); @@ -71,7 +74,7 @@ export function VariablesInAllowedPosition(context: ValidationContext): any { // If a variable definition has a default value, it's effectively non-null. function effectiveType(varType, varDef) { - return !varDef.defaultValue || varType instanceof GraphQLNonNull ? - varType : - new GraphQLNonNull(varType); + return !varDef.defaultValue || varType instanceof GraphQLNonNull + ? varType + : new GraphQLNonNull(varType); } diff --git a/src/validation/specifiedRules.js b/src/validation/specifiedRules.js index c1287ef83a..5dc6683123 100644 --- a/src/validation/specifiedRules.js +++ b/src/validation/specifiedRules.js @@ -9,80 +9,78 @@ */ // Spec Section: "Operation Name Uniqueness" -import { UniqueOperationNames } from './rules/UniqueOperationNames'; +import { UniqueOperationNames } from "./rules/UniqueOperationNames"; // Spec Section: "Lone Anonymous Operation" -import { LoneAnonymousOperation } from './rules/LoneAnonymousOperation'; +import { LoneAnonymousOperation } from "./rules/LoneAnonymousOperation"; // Spec Section: "Fragment Spread Type Existence" -import { KnownTypeNames } from './rules/KnownTypeNames'; +import { KnownTypeNames } from "./rules/KnownTypeNames"; // Spec Section: "Fragments on Composite Types" -import { FragmentsOnCompositeTypes } from './rules/FragmentsOnCompositeTypes'; +import { FragmentsOnCompositeTypes } from "./rules/FragmentsOnCompositeTypes"; // Spec Section: "Variables are Input Types" -import { VariablesAreInputTypes } from './rules/VariablesAreInputTypes'; +import { VariablesAreInputTypes } from "./rules/VariablesAreInputTypes"; // Spec Section: "Leaf Field Selections" -import { ScalarLeafs } from './rules/ScalarLeafs'; +import { ScalarLeafs } from "./rules/ScalarLeafs"; // Spec Section: "Field Selections on Objects, Interfaces, and Unions Types" -import { FieldsOnCorrectType } from './rules/FieldsOnCorrectType'; +import { FieldsOnCorrectType } from "./rules/FieldsOnCorrectType"; // Spec Section: "Fragment Name Uniqueness" -import { UniqueFragmentNames } from './rules/UniqueFragmentNames'; +import { UniqueFragmentNames } from "./rules/UniqueFragmentNames"; // Spec Section: "Fragment spread target defined" -import { KnownFragmentNames } from './rules/KnownFragmentNames'; +import { KnownFragmentNames } from "./rules/KnownFragmentNames"; // Spec Section: "Fragments must be used" -import { NoUnusedFragments } from './rules/NoUnusedFragments'; +import { NoUnusedFragments } from "./rules/NoUnusedFragments"; // Spec Section: "Fragment spread is possible" -import { PossibleFragmentSpreads } from './rules/PossibleFragmentSpreads'; +import { PossibleFragmentSpreads } from "./rules/PossibleFragmentSpreads"; // Spec Section: "Fragments must not form cycles" -import { NoFragmentCycles } from './rules/NoFragmentCycles'; +import { NoFragmentCycles } from "./rules/NoFragmentCycles"; // Spec Section: "Variable Uniqueness" -import { UniqueVariableNames } from './rules/UniqueVariableNames'; +import { UniqueVariableNames } from "./rules/UniqueVariableNames"; // Spec Section: "All Variable Used Defined" -import { NoUndefinedVariables } from './rules/NoUndefinedVariables'; +import { NoUndefinedVariables } from "./rules/NoUndefinedVariables"; // Spec Section: "All Variables Used" -import { NoUnusedVariables } from './rules/NoUnusedVariables'; +import { NoUnusedVariables } from "./rules/NoUnusedVariables"; // Spec Section: "Directives Are Defined" -import { KnownDirectives } from './rules/KnownDirectives'; +import { KnownDirectives } from "./rules/KnownDirectives"; // Spec Section: "Argument Names" -import { KnownArgumentNames } from './rules/KnownArgumentNames'; +import { KnownArgumentNames } from "./rules/KnownArgumentNames"; // Spec Section: "Argument Uniqueness" -import { UniqueArgumentNames } from './rules/UniqueArgumentNames'; +import { UniqueArgumentNames } from "./rules/UniqueArgumentNames"; // Spec Section: "Argument Values Type Correctness" -import { ArgumentsOfCorrectType } from './rules/ArgumentsOfCorrectType'; +import { ArgumentsOfCorrectType } from "./rules/ArgumentsOfCorrectType"; // Spec Section: "Argument Optionality" -import { ProvidedNonNullArguments } from './rules/ProvidedNonNullArguments'; +import { ProvidedNonNullArguments } from "./rules/ProvidedNonNullArguments"; // Spec Section: "Variable Default Values Are Correctly Typed" -import { DefaultValuesOfCorrectType } from './rules/DefaultValuesOfCorrectType'; +import { DefaultValuesOfCorrectType } from "./rules/DefaultValuesOfCorrectType"; // Spec Section: "All Variable Usages Are Allowed" -import { VariablesInAllowedPosition } from './rules/VariablesInAllowedPosition'; +import { VariablesInAllowedPosition } from "./rules/VariablesInAllowedPosition"; // Spec Section: "Field Selection Merging" -import { - OverlappingFieldsCanBeMerged -} from './rules/OverlappingFieldsCanBeMerged'; +import { OverlappingFieldsCanBeMerged } from "./rules/OverlappingFieldsCanBeMerged"; // Spec Section: "Input Object Field Uniqueness" -import { UniqueInputFieldNames } from './rules/UniqueInputFieldNames'; +import { UniqueInputFieldNames } from "./rules/UniqueInputFieldNames"; -import type { ValidationContext } from './index'; +import type { ValidationContext } from "./index"; /** * This set includes all validation rules defined by the GraphQL spec. @@ -111,5 +109,5 @@ export const specifiedRules: Array<(context: ValidationContext) => any> = [ DefaultValuesOfCorrectType, VariablesInAllowedPosition, OverlappingFieldsCanBeMerged, - UniqueInputFieldNames, + UniqueInputFieldNames ]; diff --git a/src/validation/validate.js b/src/validation/validate.js index b601e79042..ade518400a 100644 --- a/src/validation/validate.js +++ b/src/validation/validate.js @@ -8,30 +8,29 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import invariant from '../jsutils/invariant'; -import { GraphQLError } from '../error'; -import { visit, visitInParallel, visitWithTypeInfo } from '../language/visitor'; -import * as Kind from '../language/kinds'; +import invariant from "../jsutils/invariant"; +import { GraphQLError } from "../error"; +import { visit, visitInParallel, visitWithTypeInfo } from "../language/visitor"; +import * as Kind from "../language/kinds"; import type { Document, OperationDefinition, Variable, SelectionSet, FragmentSpread, - FragmentDefinition, -} from '../language/ast'; -import { GraphQLSchema } from '../type/schema'; + FragmentDefinition +} from "../language/ast"; +import { GraphQLSchema } from "../type/schema"; import type { GraphQLInputType, GraphQLOutputType, GraphQLCompositeType, GraphQLFieldDefinition, GraphQLArgument -} from '../type/definition'; -import type { GraphQLDirective } from '../type/directives'; -import { TypeInfo } from '../utilities/TypeInfo'; -import { specifiedRules } from './specifiedRules'; - +} from "../type/definition"; +import type { GraphQLDirective } from "../type/directives"; +import { TypeInfo } from "../utilities/TypeInfo"; +import { specifiedRules } from "./specifiedRules"; /** * Implements the "Validation" section of the spec. @@ -51,12 +50,12 @@ export function validate( ast: Document, rules?: Array ): Array { - invariant(schema, 'Must provide schema'); - invariant(ast, 'Must provide document'); + invariant(schema, "Must provide schema"); + invariant(ast, "Must provide document"); invariant( schema instanceof GraphQLSchema, - 'Schema must be an instance of GraphQLSchema. Also ensure that there are ' + - 'not multiple versions of GraphQL installed in your node_modules directory.' + "Schema must be an instance of GraphQLSchema. Also ensure that there are " + + "not multiple versions of GraphQL installed in your node_modules directory." ); const typeInfo = new TypeInfo(schema); return visitUsingRules(schema, typeInfo, ast, rules || specifiedRules); @@ -94,10 +93,12 @@ export class ValidationContext { _ast: Document; _typeInfo: TypeInfo; _errors: Array; - _fragments: {[name: string]: FragmentDefinition}; + _fragments: { [name: string]: FragmentDefinition }; _fragmentSpreads: Map>; - _recursivelyReferencedFragments: - Map>; + _recursivelyReferencedFragments: Map< + OperationDefinition, + Array + >; _variableUsages: Map>; _recursiveVariableUsages: Map>; @@ -131,13 +132,15 @@ export class ValidationContext { getFragment(name: string): ?FragmentDefinition { let fragments = this._fragments; if (!fragments) { - this._fragments = fragments = - this.getDocument().definitions.reduce((frags, statement) => { + this._fragments = fragments = this.getDocument().definitions.reduce( + (frags, statement) => { if (statement.kind === Kind.FRAGMENT_DEFINITION) { frags[statement.name.value] = statement; } return frags; - }, {}); + }, + {} + ); } return fragments[name]; } @@ -146,7 +149,7 @@ export class ValidationContext { let spreads = this._fragmentSpreads.get(node); if (!spreads) { spreads = []; - const setsToVisit: Array = [ node.selectionSet ]; + const setsToVisit: Array = [node.selectionSet]; while (setsToVisit.length !== 0) { const set = setsToVisit.pop(); for (let i = 0; i < set.selections.length; i++) { @@ -170,7 +173,7 @@ export class ValidationContext { if (!fragments) { fragments = []; const collectedNames = Object.create(null); - const nodesToVisit: Array = [ operation ]; + const nodesToVisit: Array = [operation]; while (nodesToVisit.length !== 0) { const node = nodesToVisit.pop(); const spreads = this.getFragmentSpreads(node); @@ -196,12 +199,15 @@ export class ValidationContext { if (!usages) { const newUsages = []; const typeInfo = new TypeInfo(this._schema); - visit(node, visitWithTypeInfo(typeInfo, { - VariableDefinition: () => false, - Variable(variable) { - newUsages.push({ node: variable, type: typeInfo.getInputType() }); - } - })); + visit( + node, + visitWithTypeInfo(typeInfo, { + VariableDefinition: () => false, + Variable(variable) { + newUsages.push({ node: variable, type: typeInfo.getInputType() }); + } + }) + ); usages = newUsages; this._variableUsages.set(node, usages); }