charlotte-graphql
Version:
Generates GraphQL type definitions and resolvers off of a concise spec.
516 lines (446 loc) • 14.7 kB
JavaScript
'use strict';
const _ = require('lodash');
const { strictEqual } = require('assert');
const { graphql } = require('graphql');
const { makeExecutableSchema } = require('graphql-tools');
const { generateApi } = require('../..');
const types = require('./types');
module.exports = (adapter, _afterEach = _.noop) => {
const { typeDefs, resolvers, typesExpanded } = generateApi({ types, adapter });
const schema = makeExecutableSchema({ typeDefs, resolvers });
const { TestPerson, TestCompany, TestFriendship, TestEmployment } = typesExpanded;
const Person = TestPerson;
const Company = TestCompany;
const Friendship = TestFriendship;
const Employment = TestEmployment;
const query = q => {
return graphql(schema, q).then(response => {
if (response.errors) {
throw response.errors[0];
}
return response.data;
});
};
const TestObjectFactory = (type, defaultName) => (name = defaultName) => adapter.create(type, { name });
const createTestPerson = TestObjectFactory(Person, 'Test Person');
const createTestCompany = TestObjectFactory(Company, 'Test Company');
afterEach(_afterEach);
describe(`integrating with GraphQL`, () => {
describe('creating an object', () => {
it('saves and returns new object with given properties', async () => {
const { created } = await query(`
mutation {
created: createTestPerson(name: "Test Person") {
uuid
name
}
}
`);
const loaded = await adapter.get(TestPerson, created);
strictEqual(typeof created.uuid, 'string');
strictEqual(created.name, 'Test Person');
strictEqual(loaded.uuid, created.uuid);
strictEqual(loaded.name, 'Test Person');
});
it('saves relationships to other objects', async () => {
const person = await createTestPerson('Test Person');
const company = await createTestCompany('Test Company');
const { employment } = await query(`
mutation {
employment: createTestEmployment(
person: {
uuid: "${person.uuid}"
},
company: {
uuid: "${company.uuid}"
}
) {
uuid
person {
uuid
}
company {
uuid
}
}
}
`);
strictEqual(typeof employment.uuid, 'string');
strictEqual(employment.person.uuid, person.uuid);
strictEqual(employment.company.uuid, company.uuid);
});
});
describe('getting an object', () => {
it('returns existing object with properties', async () => {
const created = await createTestPerson('Test Person');
const { loaded } = await query(`
query {
loaded: testPerson(uuid: "${created.uuid}") {
uuid
name
}
}
`);
strictEqual(loaded.uuid, created.uuid);
strictEqual(loaded.name, 'Test Person');
});
it('returns existing object with relationships', async () => {
const person = await createTestPerson('Test Person');
const company = await createTestCompany('Test Company');
const employment = await adapter.create(TestEmployment, { person, company });
const { loaded } = await query(`
query {
loaded: testEmployment(uuid: "${employment.uuid}") {
person {
uuid
}
company {
uuid
}
}
}
`);
strictEqual(loaded.person.uuid, person.uuid);
strictEqual(loaded.company.uuid, company.uuid);
});
it('returns existing object with reciprocal relationships', async () => {
const person = await createTestPerson('Test Person');
const company = await createTestCompany('Test Company');
const employment = await adapter.create(TestEmployment, { person, company });
const { loaded } = await query(`
query {
loaded: testPerson(uuid: "${person.uuid}") {
testEmployments {
uuid
}
}
}
`);
strictEqual(loaded.testEmployments.length, 1);
strictEqual(loaded.testEmployments[0].uuid, employment.uuid);
});
});
describe('updating a single object', () => {
it('saves values', async () => {
const created = await createTestPerson('Test Person');
const { updated } = await query(`
mutation {
updated: updateTestPerson(
uuid: "${created.uuid}",
updates: {
name: "Updated Name"
}
) {
uuid
name
}
}
`);
const loaded = await adapter.get(TestPerson, created);
strictEqual(loaded.uuid, created.uuid);
strictEqual(loaded.name, 'Updated Name');
});
it('saves relationships', async () => {
const person1 = await createTestPerson('Test Person');
const person2 = await createTestPerson('Foo Bar');
const company = await createTestCompany('Test Company');
const employment = await adapter.create(TestEmployment, { person: person1, company: company });
const { updated } = await query(`
mutation {
updated: updateTestEmployment(
uuid: "${employment.uuid}",
updates: {
person: {
uuid: "${person2.uuid}"
}
}
) {
person {
uuid
}
}
}
`);
strictEqual(updated.person.uuid, person2.uuid);
});
});
describe('updating multiple objects', () => {
it('changes values for all matched hyperedges', async () => {
const person1 = await createTestPerson('Person 1');
const person2 = await createTestPerson('Person 2');
const company1 = await createTestCompany('Company 1');
const company2 = await createTestCompany('Company 2');
const employment1 = await adapter.create(TestEmployment, { person: person1, company: company1 });
const employment2 = await adapter.create(TestEmployment, { person: person2, company: company2 });
const { updated } = await query(`
mutation {
updated: updateTestEmployments(
conditions: [{
person: [{
name: ["${person1.name}"]
}]
}],
updates: {
company: { uuid: "${company2.uuid}" }
}
) {
uuid
person { uuid }
company { uuid }
}
}
`);
strictEqual(updated.length, 1);
strictEqual(updated[0].uuid, employment1.uuid);
strictEqual(updated[0].person.uuid, person1.uuid);
strictEqual(updated[0].company.uuid, company2.uuid);
});
});
describe('removing a hyperedge', () => {
it('returns true if successful', async () => {
const person = await createTestPerson('Test Person');
const { result } = await query(`
mutation {
result: removeTestPerson(uuid: "${person.uuid}")
}
`);
strictEqual(result, true);
});
it('returns false if unsuccessful', async () => {
const { result } = await query(`
mutation {
result: removeTestPerson(uuid: "NONEXISTENT")
}
`);
strictEqual(result, false);
});
});
describe('finding hyperedges', () => {
it('matches on properties', async () => {
const person1 = await createTestPerson('Test Person');
const person2 = await createTestPerson('Foo Bar');
const { people } = await query(`
query {
people: testPeople(
conditions: [{ name: ["${person2.name}"] }]
) {
uuid
}
}
`);
strictEqual(people.length, 1);
strictEqual(people[0].uuid, person2.uuid);
});
it('matches on hierarchical relationships', async () => {
const person1 = await createTestPerson('Test Person');
const person2 = await createTestPerson('Foo Bar');
const company = await createTestCompany('Test Company');
const employment1 = await adapter.create(TestEmployment, { person: person1, company });
const employment2 = await adapter.create(TestEmployment, { person: person2, company });
const { employments } = await query(`
query {
employments: testEmployments(
conditions: [{
person: [{
name: ["${person1.name}"]
}]
}]
) {
uuid
person {
uuid
}
company {
uuid
}
}
}
`);
strictEqual(employments.length, 1);
strictEqual(employments[0].uuid, employment1.uuid);
strictEqual(employments[0].person.uuid, person1.uuid);
});
it('matches on reciprocal relationships', async () => {
const person1 = await createTestPerson('Test Person');
const person2 = await createTestPerson('Foo Bar');
const company1 = await createTestCompany('Test Company');
const company2 = await createTestCompany('Another Company');
const employment1 = await adapter.create(TestEmployment, { person: person1, company: company1 });
const employment2 = await adapter.create(TestEmployment, { person: person2, company: company2 });
const { people } = await query(`
query {
people: testPeople(
conditions: [{
testEmployments: [{
company: [{
name: ["Test Company"]
}]
}]
}]
) {
uuid
}
}
`);
strictEqual(people.length, 1);
strictEqual(people[0].uuid, employment1.person.uuid);
});
it('paginates', async () => {
const limit = 3;
const offset = 30;
for (let i = 0; i < 100; i += 1) {
await createTestPerson(`Person ${i}`);
}
const { people } = await query(`
query {
people: testPeople(
pagination: {
limit: ${limit},
offset: ${offset}
}
) {
name
}
}
`);
strictEqual(people.length, limit);
people.forEach((person, i) => {
strictEqual(person.name, `Person ${i + 30}`);
});
});
it('applies gt_ operator', async () => {
for (let x = 0; x <= 4; x += 1) {
await adapter.create(Person, { x, name: 'Person ' + x });
}
const { people } = await query(`
query {
people: testPeople(
conditions: [{
gt_: { x: 3 }
}]
) {
name
x
}
}
`);
strictEqual(people.length, 1);
strictEqual(people[0].x, 4)
});
it('applies gte_ operator', async () => {
for (let x = 0; x <= 4; x += 1) {
await adapter.create(Person, { x, name: 'Person ' + x });
}
const { people } = await query(`
query {
people: testPeople(
conditions: [{
gte_: { x: 4 }
}]
) {
name
x
}
}
`);
strictEqual(people.length, 1);
strictEqual(people[0].x, 4)
});
it('applies lt_ operator', async () => {
for (let x = 0; x <= 4; x += 1) {
await adapter.create(Person, { x, name: 'Person ' + x });
}
const { people } = await query(`
query {
people: testPeople(
conditions: [{
lt_: { x: 1 }
}]
) {
name
x
}
}
`);
strictEqual(people.length, 1);
strictEqual(people[0].x, 0)
});
it('applies lte_ operator', async () => {
for (let x = 0; x <= 4; x += 1) {
await adapter.create(Person, { x, name: 'Person ' + x });
}
const { people } = await query(`
query {
people: testPeople(
conditions: [{
lte_: { x: 0 }
}]
) {
name
x
}
}
`);
strictEqual(people.length, 1);
strictEqual(people[0].x, 0)
});
it('applies not_ operator', async () => {
for (let x = 0; x <= 4; x += 1) {
await adapter.create(Person, { x, name: 'Person ' + x });
}
const { people } = await query(`
query {
people: testPeople(
conditions: [{
not_: { x: 0 }
}]
) {
name
x
}
}
`);
strictEqual(people.length, 4);
strictEqual(people.every(p => p.x !== 0), true);
});
it('applies search_ operator', async () => {
const names = [
'Joe',
'James',
'Joseph'
];
for (let name of names) {
await adapter.create(Person, { name });
}
const { people } = await query(`
query {
people: testPeople(
conditions: [{
search_: { name: "jo" }
}]
) {
name
}
}
`);
strictEqual(people.length, 2);
strictEqual(people.every(p => p.name !== 'James'), true);
});
});
describe('_created and _updated timestamps', () => {
it('are returned as strings', async () => {
const created = await createTestPerson();
const { person: { _created, _updated } } = await query(`
query {
person: testPerson(uuid: "${created.uuid}") {
_created
_updated
}
}
`);
strictEqual(typeof _created, 'string');
strictEqual(typeof _updated, 'string');
});
});
});
};