UNPKG

charlotte-graphql

Version:

Generates GraphQL type definitions and resolvers off of a concise spec.

516 lines (446 loc) 14.7 kB
'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'); }); }); }); };