node_modules.apollo-codegen-scala.src.__tests__.codeGeneration.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apollo-client-maven-plugin Show documentation
Show all versions of apollo-client-maven-plugin Show documentation
Maven plugin for generating graphql clients
import {
parse,
GraphQLString,
GraphQLList,
GraphQLNonNull,
GraphQLEnumType
} from 'graphql';
import {
generateSource,
classDeclarationForOperation,
caseClassDeclarationForFragment,
caseClassDeclarationForSelectionSet,
typeDeclarationForGraphQLType,
} from '../codeGeneration';
import { loadSchema } from 'apollo-codegen-core/lib/loading';
const schema = loadSchema(require.resolve('../../../common-test/fixtures/starwars/schema.json'));
import CodeGenerator from 'apollo-codegen-core/lib/utilities/CodeGenerator';
import { compileToLegacyIR } from 'apollo-codegen-core/lib/compiler/legacyIR';
describe('Scala code generation', function() {
let generator;
let resetGenerator;
let compileFromSource;
let addFragment;
beforeEach(function() {
resetGenerator = () => {
const context = {
schema: schema,
operations: {},
fragments: {},
typesUsed: {}
}
generator = new CodeGenerator(context);
};
compileFromSource = (source, options = { generateOperationIds: false }) => {
const document = parse(source);
let context = compileToLegacyIR(schema, document);
options.generateOperationIds && Object.assign(context.options, { generateOperationIds: true, operationIdsMap: {} });
options.namespace && Object.assign(context.options, { namespace: options.namespace });
generator.context = context;
return context;
};
addFragment = (fragment) => {
generator.context.fragments[fragment.fragmentName] = fragment;
};
resetGenerator();
});
describe('#generateSource()', function() {
test(`should emit a package declaration when the namespace option is specified`, function() {
const context = compileFromSource(`
query HeroName($episode: Episode) {
hero(episode: $episode) {
name
}
}
`, { namespace: "hello.world" });
expect(generateSource(context)).toMatchSnapshot();
});
});
describe('#classDeclarationForOperation()', function() {
test(`should generate a class declaration for a query with variables`, function() {
const { operations, fragments } = compileFromSource(`
query HeroName($episode: Episode) {
hero(episode: $episode) {
name
}
}
`);
classDeclarationForOperation(generator, operations['HeroName'], Object.values(fragments));
expect(generator.output).toMatchSnapshot();
});
test(`should generate a class declaration for a query with fragment spreads`, function() {
const { operations, fragments } = compileFromSource(`
query Hero {
hero {
...HeroDetails
}
}
fragment HeroDetails on Character {
name
}
`);
classDeclarationForOperation(generator, operations['Hero'], Object.values(fragments));
expect(generator.output).toMatchSnapshot();
});
test(`should generate a class declaration for a query with conditional fragment spreads`, function() {
const { operations, fragments } = compileFromSource(`
query Hero {
hero {
...DroidDetails
}
}
fragment DroidDetails on Droid {
primaryFunction
}
`);
classDeclarationForOperation(generator, operations['Hero'], Object.values(fragments));
expect(generator.output).toMatchSnapshot();
});
test(`should generate a class declaration for a query with a fragment spread nested in an inline fragment`, function() {
const { operations, fragments } = compileFromSource(`
query Hero {
hero {
... on Droid {
...HeroDetails
}
}
}
fragment HeroDetails on Character {
name
}
`);
classDeclarationForOperation(generator, operations['Hero'], Object.values(fragments));
expect(generator.output).toMatchSnapshot();
});
test(`should generate a class declaration for a mutation with variables`, function() {
const { operations, fragments } = compileFromSource(`
mutation CreateReview($episode: Episode) {
createReview(episode: $episode, review: { stars: 5, commentary: "Wow!" }) {
stars
commentary
}
}
`);
classDeclarationForOperation(generator, operations['CreateReview'], Object.values(fragments));
expect(generator.output).toMatchSnapshot();
});
describe(`when generateOperationIds is specified`, function() {
let compileOptions = { generateOperationIds: true };
test(`should generate a class declaration with an operationId property`, function() {
const context = compileFromSource(`
query Hero {
hero {
...HeroDetails
}
}
fragment HeroDetails on Character {
name
}
`, compileOptions);
classDeclarationForOperation(generator, context.operations['Hero'], Object.values(context.fragments));
expect(generator.output).toMatchSnapshot();
});
test(`should generate different operation ids for different operations`, function() {
const context1 = compileFromSource(`
query Hero {
hero {
...HeroDetails
}
}
fragment HeroDetails on Character {
name
}
`, compileOptions);
classDeclarationForOperation(generator, context1.operations['Hero'], Object.values(context1.fragments));
const output1 = generator.output;
resetGenerator();
const context2 = compileFromSource(`
query Hero {
hero {
...HeroDetails
}
}
fragment HeroDetails on Character {
appearsIn
}
`, compileOptions);
classDeclarationForOperation(generator, context2.operations['Hero'], Object.values(context2.fragments));
const output2 = generator.output;
expect(output1).not.toBe(output2);
});
test(`should generate the same operation id regardless of operation formatting/commenting`, function() {
const context1 = compileFromSource(`
query HeroName($episode: Episode) {
hero(episode: $episode) {
name
}
}
`, compileOptions);
classDeclarationForOperation(generator, context1.operations['HeroName'], Object.values(context1.fragments));
const output1 = generator.output;
resetGenerator();
const context2 = compileFromSource(`
# Profound comment
query HeroName($episode:Episode) { hero(episode: $episode) { name } }
# Deeply meaningful comment
`, compileOptions);
classDeclarationForOperation(generator, context2.operations['HeroName'], Object.values(context2.fragments));
const output2 = generator.output;
expect(output1).toBe(output2);
});
test(`should generate the same operation id regardless of fragment order`, function() {
const context1 = compileFromSource(`
query Hero {
hero {
...HeroName
...HeroAppearsIn
}
}
fragment HeroName on Character {
name
}
fragment HeroAppearsIn on Character {
appearsIn
}
`, compileOptions);
classDeclarationForOperation(generator, context1.operations['Hero'], Object.values(context1.fragments));
const output1 = generator.output;
resetGenerator();
const context2 = compileFromSource(`
query Hero {
hero {
...HeroName
...HeroAppearsIn
}
}
fragment HeroAppearsIn on Character {
appearsIn
}
fragment HeroName on Character {
name
}
`, compileOptions);
classDeclarationForOperation(generator, context2.operations['Hero'], Object.values(context2.fragments));
const output2 = generator.output;
expect(output1).toBe(output2);
});
test(`should generate appropriate operation id mapping source when there are nested fragment references`, function() {
const source = `
query Hero {
hero {
...HeroDetails
}
}
fragment HeroName on Character {
name
}
fragment HeroDetails on Character {
...HeroName
appearsIn
}
`;
const context = compileFromSource(source, true);
expect(context.operations['Hero'].sourceWithFragments).toMatchSnapshot();
});
});
});
describe('#caseClassDeclarationForFragment()', function() {
test(`should generate a caseClass declaration for a fragment with an abstract type condition`, function() {
const { fragments } = compileFromSource(`
fragment HeroDetails on Character {
name
appearsIn
}
`);
caseClassDeclarationForFragment(generator, fragments['HeroDetails']);
expect(generator.output).toMatchSnapshot();
});
test(`should generate a caseClass declaration for a fragment with a concrete type condition`, function() {
const { fragments } = compileFromSource(`
fragment DroidDetails on Droid {
name
primaryFunction
}
`);
caseClassDeclarationForFragment(generator, fragments['DroidDetails']);
expect(generator.output).toMatchSnapshot();
});
test(`should generate a caseClass declaration for a fragment with a subselection`, function() {
const { fragments } = compileFromSource(`
fragment HeroDetails on Character {
name
friends {
name
}
}
`);
caseClassDeclarationForFragment(generator, fragments['HeroDetails']);
expect(generator.output).toMatchSnapshot();
});
test(`should generate a caseClass declaration for a fragment that includes a fragment spread`, function() {
const { fragments } = compileFromSource(`
fragment HeroDetails on Character {
name
...MoreHeroDetails
}
fragment MoreHeroDetails on Character {
appearsIn
}
`);
caseClassDeclarationForFragment(generator, fragments['HeroDetails']);
expect(generator.output).toMatchSnapshot();
});
});
describe('#caseClassDeclarationForSelectionSet()', function() {
test(`should generate a caseClass declaration for a selection set`, function() {
caseClassDeclarationForSelectionSet(generator, {
caseClassName: 'Hero',
parentType: schema.getType('Character'),
fields: [
{
responseName: 'name',
fieldName: 'name',
type: GraphQLString
}
]
});
expect(generator.output).toMatchSnapshot();
});
test(`should escape reserved keywords in a caseClass declaration for a selection set`, function() {
caseClassDeclarationForSelectionSet(generator, {
caseClassName: 'Hero',
parentType: schema.getType('Character'),
fields: [
{
responseName: 'private',
fieldName: 'name',
type: GraphQLString
}
]
});
expect(generator.output).toMatchSnapshot();
});
test(`should generate a nested caseClass declaration for a selection set with subselections`, function() {
caseClassDeclarationForSelectionSet(generator, {
caseClassName: 'Hero',
parentType: schema.getType('Character'),
fields: [
{
responseName: 'friends',
fieldName: 'friends',
type: new GraphQLList(schema.getType('Character')),
fields: [
{
responseName: 'name',
fieldName: 'name',
type: GraphQLString
}
]
}
]
});
expect(generator.output).toMatchSnapshot();
});
test(`should generate a caseClass declaration for a selection set with a fragment spread that matches the parent type`, function() {
addFragment({
fragmentName: 'HeroDetails',
typeCondition: schema.getType('Character')
});
caseClassDeclarationForSelectionSet(generator, {
caseClassName: 'Hero',
parentType: schema.getType('Character'),
fragmentSpreads: ['HeroDetails'],
fields: [
{
responseName: 'name',
fieldName: 'name',
type: GraphQLString
}
]
});
expect(generator.output).toMatchSnapshot();
});
test(`should generate a caseClass declaration for a selection set with a fragment spread with a more specific type condition`, function() {
addFragment({
fragmentName: 'DroidDetails',
typeCondition: schema.getType('Droid')
});
caseClassDeclarationForSelectionSet(generator, {
caseClassName: 'Hero',
parentType: schema.getType('Character'),
fragmentSpreads: ['DroidDetails'],
fields: [
{
responseName: 'name',
fieldName: 'name',
type: GraphQLString
}
]
});
expect(generator.output).toMatchSnapshot();
});
test(`should generate a caseClass declaration for a selection set with an inline fragment`, function() {
caseClassDeclarationForSelectionSet(generator, {
caseClassName: 'Hero',
parentType: schema.getType('Character'),
fields: [
{
responseName: 'name',
fieldName: 'name',
type: new GraphQLNonNull(GraphQLString)
}
],
inlineFragments: [
{
typeCondition: schema.getType('Droid'),
possibleTypes: ['Droid'],
fields: [
{
responseName: 'name',
fieldName: 'name',
type: new GraphQLNonNull(GraphQLString)
},
{
responseName: 'primaryFunction',
fieldName: 'primaryFunction',
type: GraphQLString
}
]
}
]
});
expect(generator.output).toMatchSnapshot();
});
test(`should generate a caseClass declaration for a fragment spread nested in an inline fragment`, function() {
addFragment({
fragmentName: 'HeroDetails',
typeCondition: schema.getType('Character')
});
caseClassDeclarationForSelectionSet(generator, {
caseClassName: 'Hero',
parentType: schema.getType('Character'),
fields: [],
inlineFragments: [
{
typeCondition: schema.getType('Droid'),
possibleTypes: ['Droid'],
fields: [],
fragmentSpreads: ['HeroDetails'],
}
]
});
expect(generator.output).toMatchSnapshot();
});
});
describe('#typeDeclarationForGraphQLType()', function() {
test('should generate an enum declaration for a GraphQLEnumType', function() {
const generator = new CodeGenerator({options: {}});
typeDeclarationForGraphQLType(generator, schema.getType('Episode'));
expect(generator.output).toMatchSnapshot();
});
test('should escape identifiers in cases of enum declaration for a GraphQLEnumType', function() {
const generator = new CodeGenerator({options: {}});
const albumPrivaciesEnum = new GraphQLEnumType({
name: 'AlbumPrivacies',
values: { PUBLIC: { value: "PUBLIC" }, PRIVATE: { value: "PRIVATE" } }
});
typeDeclarationForGraphQLType(generator, albumPrivaciesEnum);
expect(generator.output).toMatchSnapshot();
});
test('should generate a caseClass declaration for a GraphQLInputObjectType', function() {
const generator = new CodeGenerator({options: {}});
typeDeclarationForGraphQLType(generator, schema.getType('ReviewInput'));
expect(generator.output).toMatchSnapshot();
});
});
});
© 2015 - 2025 Weber Informatics LLC | Privacy Policy