@nyteshade/lattice-legacy
Version:
OO Underpinnings for ease of GraphQL Implementation
184 lines (152 loc) • 5.61 kB
JavaScript
import {
LatticeFactory as LF,
GQLBase,
GQLEnum,
GQLInterface,
//GQLUnion,
GQLExpressMiddleware,
Schema,
Properties,
resolver,
gql,
typeOf,
META_KEY,
AUTO_PROPS
} from '../es6/lattice'
import Express from 'express'
import { customDedent } from 'ne-tag-fns'
const docTag = customDedent({dropLowest: true})
const TYPE = LF.TYPE
const jsCarPlans = {
name: 'JSCar',
schema: gql`
type JSCar {
make: String,
wheels: Int
}
type Query {
findQuad: JSCar
}
`,
resolvers: {
findQuad(Class, requestData, {make}) {
return new Class({make, wheels: 4}, requestData)
}
},
docs: {
JSCar: {
[TYPE]: docTag`
A sample GraphQL type denoting a, typically, 4 wheeled vehicle
`,
name: `The name of the car`,
wheels: `The total number of wheels connected to the drivetrain`
},
Query: {
findQuad: `Finds the nearest four wheeled vehicle`
}
}
}
(gql`
type Car {
make: String,
wheels: Int
}
type Query {
findQuad(make: String): Car
}
`)
class Car extends GQLBase {
findQuad(requestData, {make}) {
return new Car({make, wheels: 4}, requestData)
}
static apiDocs() {
const { DOC_CLASS, DOC_QUERIES, DOC_FIELDS } = this
return {
[DOC_CLASS]: docTag`
A sample GraphQL type denoting a, typically, 4 wheeled vehicle
`,
[DOC_FIELDS]: {
name: `The name of the car`,
wheels: `The total number of wheels connected to the drivetrain`
},
[DOC_QUERIES]: {
findQuad: `Finds the nearest four wheeled vehicle`
}
}
}
}
describe('Test out the functionality of LatticeFactory', () => {
let reqData = { req: 'request', res: 'response', next: 'next fn()' }
let JSCar = LF.build(jsCarPlans)
let car = new JSCar({make: 'Nissan', wheels: 4}, reqData)
let autoProps = JSCar[META_KEY][AUTO_PROPS]
it('has the built car auto-props function as expected', () => {
let make = JSCar.getProp('make', false)
let wheels = JSCar.getProp('wheels', false)
// We can guarantee that make and wheels are generated by the @Properties
// decorator as an automatic property, meaning there were no defined
// getters or functions for the named property and automatic ones were
// generated for the developer.
expect(make).toBe(autoProps.make.get)
expect(wheels).toBe(autoProps.wheels.get)
})
it('returns the model values as expected for an auto-prop', () => {
// Check the functionality of the auto-prop getters
expect(car.make).toEqual('Nissan')
expect(car.wheels).toBe(4)
})
it('has the same resolver function that we built in the plan', async () => {
// In a normal scenario, we would create a new instance of car with the
// model as the first parameter and the requestData as the second. This
// call to getResolver is made in the GQLBase.getMergedRoot() function
// which is used when the schema is put together at runtime.
let fn = await JSCar.getResolver('findQuad', reqData)
// Things to note here:
// LatticeFactory resolvers receive the type of class that they are as
// first parameter, followed by requestData, finally followed by the actual
// parameters supplied by the various GraphQL engines out there.
// To simulate that here in this test, we call the properly bound resolver
// with the model denoting the make for car1 and for car2 we have to copy
// this behavior by sending the JSCar class object as well as the request
// data automatically bound when the new instance of JSCar was created.
let car1 = fn({make: 'Dodge'})
let car2 = jsCarPlans.resolvers.findQuad(JSCar, reqData, {make: 'Dodge'})
// We should have nearly the same results in both instances of JSCar
expect(car1.make).toEqual(car2.make)
expect(car1 instanceof JSCar).toBe(true)
expect(car2 instanceof JSCar).toBe(true)
expect(car1.requestData).toBe(reqData)
expect(car2.requestData).toBe(reqData)
})
})
describe('Run the same tests on a non-lattice factory version', () => {
let reqData = { req: 'request', res: 'response', next: 'next fn()' }
let car = new Car({make: 'Nissan', wheels: 4}, reqData)
let autoProps = Car[META_KEY][AUTO_PROPS]
it('has the built car auto-props function as expected', () => {
let make = Car.getProp('make', false)
let wheels = Car.getProp('wheels', false)
// We can guarantee that make and wheels are generated by the @Properties
// decorator as an automatic property, meaning there were no defined
// getters or functions for the named property and automatic ones were
// generated for the developer.
expect(make).toBe(autoProps.make.get)
expect(wheels).toBe(autoProps.wheels.get)
})
it('returns the model values as expected for an auto-prop', () => {
// Check the functionality of the auto-prop getters
expect(car.make).toEqual('Nissan')
expect(car.wheels).toBe(4)
})
it('has the same resolver function that we built in the plan', async () => {
// Create a new instance of Car using the normal OOP path through
// Lattice. Fetch the resolver defined in the class and specify the
// make should be 'Dodge'. Verify we have an instance of the class as
// expected and that the model value has the `make` we expect.
let fn = await Car.getResolver('findQuad', reqData)
let car1 = fn({make: 'Dodge'})
expect(car1 instanceof Car).toBe(true)
expect(car1.make).toEqual('Dodge')
expect(car1.requestData).toBe(reqData)
})
})