Skip to content

Instantly share code, notes, and snippets.

@doublemarked
Last active February 6, 2019 22:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save doublemarked/f0255b7a81610aa4884fbc1a58a8764b to your computer and use it in GitHub Desktop.
Save doublemarked/f0255b7a81610aa4884fbc1a58a8764b to your computer and use it in GitHub Desktop.
Testing Loopback Projects (a simplified extraction)
// File Location: test/unit/user/
const appRoot = require('app-root-path')
const bootstrap = appRoot.require('/test/bootstrap')
const expect = bootstrap.expect
describe('Example Unit Tests', function () {
const User = bootstrap.app.models.User
it('lets you work with your models', function () {
return User.create(factories.create('User', { username: 'testo' }))
.then(user => {
expect(user.username).to.equal('testo')
})
})
})
// File Location: test/api/user/
const appRoot = require('app-root-path')
const bootstrap = appRoot.require('/test/bootstrap')
const expect = bootstrap.expect
describe('Example Integration Tests', function () {
const User = bootstrap.app.models.User
before(function () {
this.protoUser = bootstrap.factories.create('User')
return User.create(this.protoUser)
.then(user => {
this.user = user
})
})
it('is possible to login via the API', function () {
return bootstrap
.performLogin(this.protoUser.email, this.protoUser.password)
.expect(200)
.expect(bootstrap.apiModelResponse('AccessToken'))
.then(res => {
expect(res.userId).to.equal(this.user.id)
})
})
})
// File Location: test/bootstrap.js
const appRoot = require('app-root-path')
const request = require('supertest-as-promised')
const chai = require('chai')
const expect = chai.expect
const app = appRoot.require('.')
const factories = require('./factories')
chai.use(require('chai-as-promised'))
require('./chai-types')
before(done => {
// You can also consider wiping your test db or importing fixtures in this hook, if needed.
if (!app.booting) {
return done()
}
process.stdout.write('Waiting for app boot...')
app.on('booted', () => done())
})
module.exports = {
app,
factories,
chai,
expect,
jsonRequest: function jsonRequest(verb, url, accessToken) {
const req = request(app)[verb](url)
req.set('Content-Type', 'application/json')
req.set('Accept', 'application/json')
if (accessToken) {
req.set('Authorization', accessToken.id)
}
return req.expect('Content-Type', /json/)
},
performLogin: function performLogin(username, password, expectedResult = STATUS_OK) {
return bootstrap.jsonRequest('post', '/api/Users/login')
.send({ email: username, password })
.expect(expectedResult)
},
emptyResponse: function emptyResponse(res) {
expect(res.body).to.be.empty()
},
apiErrorResponse: function apiErrorResponse(res) {
expect(res.body).to.be.an.apiError()
},
apiModelResponse: function apiModelResponse(modelType) {
return res => {
expect(res.body).to.be.a[modelType]()
}
},
}
// File Location: test/chai-types.js
/*
* This file contains all of our custom assertion methods, which validate types
*/
const chai = require('chai')
const expect = chai.expect
// Helper for Loopback-style API errors
chai.Assertion.addMethod('apiError', function apiError() {
const obj = this._obj
expect(obj).to.be.an('object')
expect(obj.error).to.be.an('object')
expect(obj.error).to.contain.keys('name', 'status', 'message')
})
chai.Assertion.addMethod('AccessToken', function AccessToken() {
const obj = this._obj
expect(obj).to.be.an('object')
expect(obj).to.contain.keys('id', 'ttl', 'created', 'userId')
})
chai.Assertion.addMethod('User', function User() {
const obj = this._obj
expect(obj).to.be.an('object')
expect(obj).to.have.property('id')
expect(obj).to.have.property('email')
expect(obj).to.not.have.property('password')
expect(obj.id).to.be.ok()
})
// etc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment