UNPKG

@conveyal/commute

Version:
208 lines (173 loc) 6.55 kB
/* globals afterEach, beforeEach, describe, expect, it */ import omit from 'lodash.omit' import nock from 'nock' import request from 'supertest-as-promised' import {requireKeys, timeoutPromise} from './common' import app from '../../server/app' const mockGeocodeResult = require('./mock-geocode-result.json') const mockIsochroneResult = require('./mock-isochrone-result.json') export const parseServerResponse = (res) => { let json try { json = JSON.parse(res.text) } catch (e) { console.error('Unable to parse server response into JSON') console.error(`response text: "${res.text}"`) throw e } try { expect(json.error).toBeFalsy() } catch (err) { console.error(json.error) throw err } expect(res.status).toBe(200) return json } export const prepareGeocodeNock = () => nock( 'https://search.mapzen.com/' ) .get(/v1\/search/) .reply(200, mockGeocodeResult) export const prepareIsochroneNock = () => nock( 'http://mock-r5.com/' ) .get(/calculateIsochrones/) .reply(200, mockIsochroneResult) export function makeRemoveModelsFn (model) { return async function () { await model.remove({}).exec() } } /** * Make a rest endpoint tests with the specified routes * * @param {Object} cfg A configuration object with the following data: * - {Object} endpoints Keys representing endpoints to make and their corresponding options * - {Array} snapshotOmitions An array of strings representing keys that shouldn't be snapshotted * - {bool} geocodePlugin whether or not the model has a geocodePlugin * - {Object} model The mongo model to use * - {String} name The endpoint name * - {Object} parentModel An object describing a parent relationship in this model. * Has the following keys * - {String} childrenField children field in the paret model * - {String} foreignKey foreign key field name * - {Object} model parent model */ export const makeRestEndpointTests = (cfg) => { const endpoints = cfg.endpoints const geocodePlugin = cfg.geocodePlugin const model = cfg.model const name = cfg.name const snapshotOmitions = ['_id'].concat(cfg.snapshotOmitions || []) if (geocodePlugin) { snapshotOmitions.push('positionLastUpdated') } describe('rest endpoint', () => { beforeEach(makeRemoveModelsFn(model)) afterEach(makeRemoveModelsFn(model)) if (endpoints['Collection GET']) { it('should find zero models in fresh state', async () => { // make request const res = await request(app).get(`/api/${name}`) // handle response const json = parseServerResponse(res) expect(json.length).toBe(0) }) } if (endpoints['Collection POST']) { const cfg = endpoints['Collection POST'] let creationData = cfg.creationData || {} const customAssertions = cfg.customAssertions || (() => 'no-op') it('should add model', async () => { if (geocodePlugin) prepareGeocodeNock() if (typeof creationData === 'function') { // assume that the function returns a Promise creationData = await creationData() } // make request const res = await request(app) .post(`/api/${name}`) .send(creationData) // handle response const json = parseServerResponse(res) const entitiesToSnapshot = json.map((entity) => omit(entity, snapshotOmitions)) expect(entitiesToSnapshot).toMatchSnapshot() const count = await model.count().exec() expect(count).toBe(1) customAssertions(json, res) }) } if (endpoints['DELETE']) { it('should delete model', async () => { const cfg = endpoints['DELETE'] let initData = cfg.initData || {} if (geocodePlugin) prepareGeocodeNock() if (typeof initData === 'function') { // assume that the function returns a Promise initData = await initData() } // create model const createdModels = await model.create(initData) const modelId = createdModels[0]._id const customAssertions = cfg.customAssertions || (() => 'no-op') // make request const res = await request(app).delete(`/api/${name}/${modelId}`) // handle response const json = parseServerResponse(res) expect(json.trashed).toBeTruthy() // wait for mongo to save data??? await timeoutPromise(1000) const entity = await model.findById(modelId).exec() expect(entity.trashed).toBeTruthy() customAssertions(json, res) }) } if (endpoints['GET']) { it('should get model', async () => { const cfg = endpoints['GET'] requireKeys(cfg, ['initData']) let initData = cfg.initData if (geocodePlugin) prepareGeocodeNock() if (typeof initData === 'function') { // assume that the function returns a Promise initData = await initData() } // create model const createdModels = await model.create(initData) const modelId = createdModels[0]._id const customAssertions = cfg.customAssertions || (() => 'no-op') // make request const res = await request(app).get(`/api/${name}/${modelId}`) // handle response const json = parseServerResponse(res) expect(omit(json, snapshotOmitions)).toMatchSnapshot() expect(json._id).toEqual(`${modelId}`) customAssertions(json, res) }) } if (endpoints['PUT']) { it('should update model', async () => { const cfg = endpoints['PUT'] requireKeys(cfg, ['customAssertions', 'initData', 'updateData']) const {customAssertions, updateData} = cfg let {initData} = cfg if (geocodePlugin) prepareGeocodeNock() if (typeof initData === 'function') { // assume that the function returns a Promise initData = await initData() } // create model const createdModels = await model.create(initData) const modelId = createdModels[0]._id // make request const res = await request(app).put(`/api/${name}/${modelId}`).send(updateData) // handle response const json = parseServerResponse(res) expect(omit(json, snapshotOmitions)).toMatchSnapshot() const data = await model.findById(modelId).exec() customAssertions(data, json, res) }) } }) }