import { expect } from 'chai';
import { describe, it } from 'mocha';
import { dedent } from '../../__testUtils__/dedent.js';
import { kitchenSinkSDL } from '../../__testUtils__/kitchenSinkSDL.js';
import { Kind } from '../kinds.js';
import { parse } from '../parser.js';
import { print } from '../printer.js';
describe('Printer: SDL document', () => {
it('prints minimal ast', () => {
const ast = {
kind: Kind.SCALAR_TYPE_DEFINITION,
name: { kind: Kind.NAME, value: 'foo' },
} as const;
expect(print(ast)).to.equal('scalar foo');
});
it('produces helpful error messages', () => {
const badAST = { random: 'Data' };
expect(() => print(badAST)).to.throw(
'Invalid AST Node: { random: "Data" }.',
);
});
it('prints kitchen sink without altering ast', () => {
const ast = parse(kitchenSinkSDL, { noLocation: true });
const astBeforePrintCall = JSON.stringify(ast);
const printed = print(ast);
const printedAST = parse(printed, { noLocation: true });
expect(printedAST).to.deep.equal(ast);
expect(JSON.stringify(ast)).to.equal(astBeforePrintCall);
expect(printed).to.equal(dedent`
"""This is a description of the schema as a whole."""
schema {
query: QueryType
mutation: MutationType
}
"""
This is a description
of the \`Foo\` type.
"""
type Foo implements Bar & Baz & Two {
"Description of the \`one\` field."
one: Type
"""This is a description of the \`two\` field."""
two(
"""This is a description of the \`argument\` argument."""
argument: InputType!
): Type
"""This is a description of the \`three\` field."""
three(argument: InputType, other: String): Int
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: InputType = { key: "value" }): Type
seven(argument: Int = null): Type
}
type AnnotatedObject @onObject(arg: "value") {
annotatedField(arg: Type = "default" @onArgumentDefinition): Type @onField
}
type UndefinedType
extend type Foo {
seven(argument: [String]): Type
}
extend type Foo @onType
interface Bar {
one: Type
four(argument: String = "string"): String
}
interface AnnotatedInterface @onInterface {
annotatedField(arg: Type @onArgumentDefinition): Type @onField
}
interface UndefinedInterface
extend interface Bar implements Two {
two(argument: InputType!): Type
}
extend interface Bar @onInterface
interface Baz implements Bar & Two {
one: Type
two(argument: InputType!): Type
four(argument: String = "string"): String
}
union Feed = Story | Article | Advert
union AnnotatedUnion @onUnion = A | B
union AnnotatedUnionTwo @onUnion = A | B
union UndefinedUnion
extend union Feed = Photo | Video
extend union Feed @onUnion
scalar CustomScalar
scalar AnnotatedScalar @onScalar
extend scalar CustomScalar @onScalar
enum Site {
"""This is a description of the \`DESKTOP\` value"""
DESKTOP
"""This is a description of the \`MOBILE\` value"""
MOBILE
"This is a description of the \`WEB\` value"
WEB
}
enum AnnotatedEnum @onEnum {
ANNOTATED_VALUE @onEnumValue
OTHER_VALUE
}
enum UndefinedEnum
extend enum Site {
VR
}
extend enum Site @onEnum
input InputType {
key: String!
answer: Int = 42
}
input AnnotatedInput @onInputObject {
annotatedField: Type @onInputFieldDefinition
}
input UndefinedInput
extend input InputType {
other: Float = 1.23e4 @onInputFieldDefinition
}
extend input InputType @onInputObject
"""This is a description of the \`@skip\` directive"""
directive @skip(
"""This is a description of the \`if\` argument"""
if: Boolean! @onArgumentDefinition
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @include2(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @myRepeatableDir(name: String!) repeatable on OBJECT | INTERFACE
extend schema @onSchema
extend schema @onSchema {
subscription: SubscriptionType
}
`);
});
});