How to test?
nagyv opened this issue · 2 comments
Hi,
I would like to test a hapipal project that uses Schwifty. I could create simple unit tests for the Schwifty models without actually requiring the server at all, but when I would like to test my routes I don't know how to get
- the models loaded
- migrations runs properly
- (and possibly) the server not listening
Example router:
'use strict'
const Joi = require('joi')
const handler = async function (request, h) {
// console.log('realm2', request.route.realm)
console.log('models', request.models())
const { Championship } = request.models()
const rounds = await Championship.query()
.eagerAlgorithm(Championship.JoinEagerAlgorithm)
.eager('[matches(orderByCode).[guest_team, home_team], children, main]')
.findById(request.params.championshipId)
return rounds
}
module.exports = {
method: 'GET',
path: '/championships/{championshipId}',
config: {
auth: false,
validate: {
params: {
championshipId: Joi.number()
}
}
},
handler
}
and the accompanying test (as I imagine it) would start somehow like:
'use strict'
const Server = require('../../../server')
// Load modules
const Championship = require('../../models/Championship')
const config = require('../championship-get')
// Test shortcuts
describe('Championship get', () => {
let server
beforeAll(async () => {
server = await Server.deployment(false) // I prefer not to listen in a test
await server.knex().migrate.latest('../lib/migrations') // migrations should run as per manifest, but they don't, and setting the path here is ignored for some reason
server.route(config)
})
beforeEach(async () => {
await Championship.query(server.knex()).insert({
name: 'WSB 2018'
})
})
test('calls its handler', async () => {
const res = await server.inject({
method: 'GET',
url: '/championships/1',
headers: {}
})
expect(res.statusCode).toEqual(200)
})
})
The above fails as request.models()
is empty.
I've figured out that models are to be parsed at the onPreStart event, but I would not start a server when I'm testing. Is there a way to still access models in requests?
The boilerplate is designed so that await Server.deployment(false)
provides you a server
identical to your actual production deployment, but not listening/started. This should be ideal for testing, as you're doing: models should be available and connected to the db, migrations should run if configured that way, all your routes should exist, etc.
I'm confused by your setup because it's hard for me to imagine a situation where you would need to require a route config, model, and your deployment separately, all at the same time. For example, is this route lib/route/championship-get.js
above not already defined on the server
provided by await Server.deployment()
? I would expect haute-couture to have added that route for you.
An aside—which version of schwifty are you using?
P.S. models are available on request.models()
or server.models()
as soon as they're defined using schwifty, but they aren't connected to the database until onPreStart
. Luckily Server.deployment()
ensures onPreStart
occurs because it initializes the server (server.initialize()
) even though it does not start the server.
I've realised that the issue was the same as hapipal/haute-couture#42
These are due to using Jest as a test runner. Moving to Lab fixed the issue.