@aws/neptune-for-graphql
Version:
CLI utility to create and maintain a GraphQL API for Amazon Neptune
158 lines (128 loc) • 7.13 kB
JavaScript
import { readFileSync } from 'node:fs';
import { loggerInit } from '../logger.js';
import { validatedSchemaModel } from '../schemaModelValidator.js';
import { schemaParser, schemaStringify } from '../schemaParser.js';
describe('validatedSchemaModel', () => {
let model;
const schema = readFileSync('./src/test/user-group.graphql', 'utf-8');
beforeAll(() => {
loggerInit('./output', false, 'silent');
model = validatedSchemaModel(schemaParser(schema));
});
test('types definitions should be as expected', () => {
const objectTypes = model.definitions.filter(def => def.kind === 'ObjectTypeDefinition').map(def => def.name.value);
expect(objectTypes).toEqual(expect.arrayContaining(['User','Group','Moderator','Query', 'Mutation']));
const inputTypes = model.definitions.filter(def => def.kind === 'InputObjectTypeDefinition').map(def => def.name.value);
expect(inputTypes).toEqual(expect.arrayContaining(['UserInput','GroupInput','ModeratorInput','Options']));
const enumTypes = model.definitions.filter(def => def.kind === 'EnumTypeDefinition').map(def => def.name.value);
expect(enumTypes).toEqual(expect.arrayContaining(['Role']));
});
test('should only add _id field to object types without ID fields', () => {
const objTypeDefs = model.definitions.filter(def => def.kind === 'ObjectTypeDefinition');
const userType = objTypeDefs.find(def => def.name.value === 'User');
const groupType = objTypeDefs.find(def => def.name.value === 'Group');
const moderatorType = objTypeDefs.find(def => def.name.value === 'Moderator');
expect(userType.fields).toHaveLength(10);
expect(groupType.fields).toHaveLength(4);
expect(moderatorType.fields).toHaveLength(6);
const userIdFields = getIdFields(userType);
const groupIdFields = getIdFields(groupType);
const moderatorIdFields = getIdFields(moderatorType);
expect(userIdFields).toHaveLength(1);
expect(groupIdFields).toHaveLength(1);
expect(moderatorIdFields).toHaveLength(1);
expect(userIdFields[0].name.value).toEqual('userId');
expect(groupIdFields[0].name.value).toEqual('_id');
expect(moderatorIdFields[0].name.value).toEqual('moderatorId');
});
test('should define the same ID fields on a type and its input type', () => {
const typeNames = ['User', 'Group', 'Moderator'];
typeNames.forEach(typeName => {
const type = model.definitions.find(
def =>
def.kind === 'ObjectTypeDefinition' && def.name.value === typeName
);
const inputType = model.definitions.find(
def =>
def.kind === 'InputObjectTypeDefinition' && def.name.value === `${typeName}Input`
);
const idFields = getIdFields(type);
const inputIdFields = getIdFields(inputType);
expect(idFields).toHaveLength(1);
expect(inputIdFields).toHaveLength(1);
expect(idFields[0].name.value).toEqual(inputIdFields[0].name.value);
});
});
test('should add CreateInput with nullable ID and UpdateInput with non-nullable ID as mutation input types', () => {
const typeNames = ['User', 'Group'];
typeNames.forEach(typeName => {
const createInputType = model.definitions.find(
def =>
def.kind === 'InputObjectTypeDefinition' &&
def.name.value === `${typeName}CreateInput`
);
const updateInputType = model.definitions.find(
def =>
def.kind === 'InputObjectTypeDefinition' &&
def.name.value === `${typeName}UpdateInput`
);
expect(createInputType).toBeDefined();
expect(updateInputType).toBeDefined();
const createIdField = getIdFields(createInputType)[0];
const updateIdField = getIdFields(updateInputType)[0];
expect(createIdField.type.kind).toEqual('NamedType');
expect(updateIdField.type.kind).toEqual('NonNullType');
});
});
test('should allow enum types as input fields', () => {
const roleEnumType = model.definitions.find(def => def.kind === 'EnumTypeDefinition' && def.name.value === 'Role');
expect(roleEnumType.values.map(value => value.name.value)).toEqual(expect.arrayContaining(['USER','ADMIN','GUEST']));
const userInput = model.definitions.find(def => def.kind === 'InputObjectTypeDefinition' && def.name.value === 'UserInput');
const userRoleField = userInput.fields.find(field => field.name.value === 'role');
expect(userRoleField.type.name.value).toEqual('Role');
});
test('should output expected validated schema', () => {
const actual = schemaStringify(model, true);
const expected = readFileSync('./src/test/user-group-validated.graphql', 'utf8');
expect(actual).toBe(expected);
});
test('should output expected validated schema with query prefixes', async () => {
const schemaValidator = await loadSchemaValidator();
const modelQueryPrefix = schemaValidator.validatedSchemaModel(schemaParser(schema), {
queryPrefix: 'userGroupQuery_'
});
const actual = schemaStringify(modelQueryPrefix, true);
const expected = readFileSync('./src/test/user-group-validated-with-query-prefix.graphql', 'utf8');
expect(actual).toBe(expected);
})
test('should output expected validated schema with mutation prefixes', async () => {
const schemaValidator = await loadSchemaValidator();
const modelMutationPrefix = schemaValidator.validatedSchemaModel(schemaParser(schema), {
mutationPrefix: 'userGroupMutation_'
});
const actual = schemaStringify(modelMutationPrefix, true);
const expected = readFileSync('./src/test/user-group-validated-with-mutation-prefix.graphql', 'utf8');
expect(actual).toBe(expected);
})
test('should output expected validated schema with query and mutation prefixes', async () => {
const schemaValidator = await loadSchemaValidator();
const modelPrefixes = schemaValidator.validatedSchemaModel(schemaParser(schema), {
queryPrefix: 'userGroupQueryTest_',
mutationPrefix: 'userGroupMutationTest_'
});
const actual = schemaStringify(modelPrefixes, true);
const expected = readFileSync('./src/test/user-group-validated-with-prefixes.graphql', 'utf8');
expect(actual).toBe(expected);
})
function getIdFields(objTypeDef) {
return objTypeDef.fields.filter(
field =>
field.directives.some(directive => directive.name.value === 'id')
);
}
async function loadSchemaValidator() {
// Use timestamp to get fresh module
const timestamp = Date.now();
return await import(`../schemaModelValidator.js?t=${timestamp}`);
}
});