UNPKG

fastify-cli

Version:

Run a fastify route with one command!

468 lines (378 loc) 12 kB
'use strict' const fs = require('fs') const path = require('path') const crypto = require('crypto') const baseFilename = `${__dirname}/fixtures/test_${crypto.randomBytes(16).toString('hex')}` const t = require('tap') const test = t.test const sget = require('simple-get').concat const sinon = require('sinon') const proxyquire = require('proxyquire').noPreserveCache() const start = require('../start') const onTravis = !!process.env.TRAVIS let _port = 3001 function getPort () { return '' + _port++ } // FIXME // paths are relative to the root of the project // this can be run only from there test('should start the server', t => { t.plan(6) const argv = [ '-p', getPort(), './examples/plugin.js' ] start.start(argv, function (err, fastify) { t.error(err) sget({ method: 'GET', url: `http://localhost:${fastify.server.address().port}` }, (err, response, body) => { t.error(err) t.strictEqual(response.statusCode, 200) t.strictEqual(response.headers['content-length'], '' + body.length) t.deepEqual(JSON.parse(body), { hello: 'world' }) fastify.close(() => { t.pass('server closed') }) }) }) }) test('should start fastify with custom options', t => { t.plan(1) // here the test should fail because of the wrong certificate // or because the server is booted without the custom options try { const argv = [ '-p', getPort(), '-o', 'true', './examples/plugin-with-options.js' ] start.start(argv).close() t.fail('Custom options') } catch (e) { t.pass('Custom options') } }) test('should start the server at the given prefix', t => { t.plan(6) const argv = [ '-p', getPort(), '-r', '/api/hello', './examples/plugin.js' ] start.start(argv, (err, fastify) => { t.error(err) sget({ method: 'GET', url: `http://localhost:${fastify.server.address().port}/api/hello` }, (err, response, body) => { t.error(err) t.strictEqual(response.statusCode, 200) t.strictEqual(response.headers['content-length'], '' + body.length) t.deepEqual(JSON.parse(body), { hello: 'world' }) fastify.close(() => { t.pass('server closed') }) }) }) }) test('should start fastify at given socket path', t => { t.plan(3) const sockFile = path.resolve('test.sock') const argv = [ '-s', sockFile, '-o', 'true', './examples/plugin.js' ] const fastify = start.start(argv) try { fs.unlinkSync(sockFile) } catch (e) { } fastify.ready(err => { t.error(err) var request = require('http').request({ method: 'GET', path: '/', socketPath: sockFile }, function (response) { t.deepEqual(response.statusCode, 200) fastify.close(() => { t.pass('server closed') }) }) request.end() }) }) test('should only accept plugin functions with 3 arguments', t => { t.plan(1) const oldStop = start.stop t.tearDown(() => { start.stop = oldStop }) start.stop = function (err) { t.equal(err.message, 'Plugin function should contain 3 arguments. Refer to documentation for more information.') } const argv = [ '-p', getPort(), './test/data/incorrect-plugin.js' ] start.start(argv) }) test('should error with a good timeout value', t => { t.plan(1) const start = proxyquire('../start', { 'assert': { ifError (err) { t.equal(err.message, `ERR_AVVIO_PLUGIN_TIMEOUT: plugin did not start in time: ${__dirname}/data/timeout-plugin.js`) } } }) const argv = [ '-p', '3040', '-T', '100', './test/data/timeout-plugin.js' ] start.start(argv) }) test('should throw on file not found', t => { t.plan(1) const oldStop = start.stop t.tearDown(() => { start.stop = oldStop }) start.stop = function (err) { t.ok(/Cannot find module.*not-found/.test(err.message), err.message) } const argv = [ '-p', getPort(), './data/not-found.js' ] start.start(argv) }) test('should throw on package not found', t => { t.plan(1) const oldStop = start.stop t.tearDown(() => { start.stop = oldStop }) start.stop = function (err) { t.ok(/Cannot find module.*unknown-package/.test(err.message), err.message) } const argv = [ '-p', getPort(), './test/data/package-not-found.js' ] start.start(argv) }) test('should throw on parsing error', t => { t.plan(1) const oldStop = start.stop t.tearDown(() => { start.stop = oldStop }) start.stop = function (err) { t.equal(err.constructor, SyntaxError) } const argv = [ '-p', getPort(), './test/data/parsing-error.js' ] start.start(argv) }) test('should start the server with an async/await plugin', t => { if (Number(process.versions.node[0]) < 7) { t.pass('Skip because Node version < 7') return t.end() } t.plan(6) const argv = [ '-p', getPort(), './examples/async-await-plugin.js' ] start.start(argv, (err, fastify) => { t.error(err) sget({ method: 'GET', url: `http://localhost:${fastify.server.address().port}` }, (err, response, body) => { t.error(err) t.strictEqual(response.statusCode, 200) t.strictEqual(response.headers['content-length'], '' + body.length) t.deepEqual(JSON.parse(body), { hello: 'world' }) fastify.close(() => { t.pass('server closed') }) }) }) }) test('should exit without error on help', t => { t.plan(1) const oldStop = start.stop t.tearDown(() => { start.stop = oldStop }) start.stop = function (err) { t.equal(err, undefined) } const argv = [ '-p', getPort(), '-h', 'true' ] start.start(argv) }) test('should throw the right error on require file', t => { t.plan(1) const oldStop = start.stop t.tearDown(() => { start.stop = oldStop }) start.stop = function (err) { t.ok(/undefinedVariable is not defined/.test(err.message), err.message) } const argv = [ '-p', getPort(), './test/data/undefinedVariable.js' ] start.start(argv) }) test('should respond 413 - Payload too large', t => { t.plan(6) const bodyTooLarge = '{1: 11}' const bodySmaller = '{1: 1}' const argv = [ '-p', getPort(), '--body-limit', bodyTooLarge.length + 2 - 1, './examples/plugin.js' ] start.start(argv, (err, fastify) => { t.error(err) sget({ method: 'POST', url: `http://localhost:${fastify.server.address().port}`, body: bodyTooLarge, json: true }, (err, response) => { t.error(err) t.strictEqual(response.statusCode, 413) sget({ method: 'POST', url: `http://localhost:${fastify.server.address().port}`, body: bodySmaller, json: true }, (err, response) => { t.error(err) t.strictEqual(response.statusCode, 200) fastify.close(() => { t.pass('server closed') }) }) }) }) }) test('should start the server (using env var)', t => { t.plan(6) process.env.FASTIFY_PORT = getPort() const argv = [ './examples/plugin.js' ] start.start(argv, (err, fastify) => { t.error(err) sget({ method: 'GET', url: `http://localhost:${fastify.server.address().port}` }, (err, response, body) => { t.error(err) t.strictEqual(response.statusCode, 200) t.strictEqual(response.headers['content-length'], '' + body.length) t.deepEqual(JSON.parse(body), { hello: 'world' }) delete process.env.FASTIFY_PORT fastify.close(() => { t.pass('server closed') }) }) }) }) test('should start the server (using PORT-env var)', t => { t.plan(6) process.env.PORT = getPort() const argv = [ './examples/plugin.js' ] start.start(argv, (err, fastify) => { t.error(err) sget({ method: 'GET', url: `http://localhost:${fastify.server.address().port}` }, (err, response, body) => { t.error(err) t.strictEqual(response.statusCode, 200) t.strictEqual(response.headers['content-length'], '' + body.length) t.deepEqual(JSON.parse(body), { hello: 'world' }) delete process.env.PORT fastify.close(() => { t.pass('server closed') }) }) }) }) test('should start the server (using FASTIFY_PORT-env preceding PORT-env var)', t => { t.plan(6) process.env.FASTIFY_PORT = getPort() process.env.PORT = getPort() const argv = [ './examples/plugin.js' ] start.start(argv, (err, fastify) => { t.error(err) sget({ method: 'GET', url: `http://localhost:${process.env.FASTIFY_PORT}` }, (err, response, body) => { t.error(err) t.strictEqual(response.statusCode, 200) t.strictEqual(response.headers['content-length'], '' + body.length) t.deepEqual(JSON.parse(body), { hello: 'world' }) delete process.env.FASTIFY_PORT delete process.env.PORT fastify.close(() => { t.pass('server closed') }) }) }) }) test('should start the server at the given prefix (using env var)', t => { t.plan(6) process.env.FASTIFY_PORT = getPort() process.env.FASTIFY_PREFIX = '/api/hello' const argv = [ './examples/plugin.js' ] start.start(argv, (err, fastify) => { t.error(err) sget({ method: 'GET', url: `http://localhost:${process.env.FASTIFY_PORT}/api/hello` }, (err, response, body) => { t.error(err) t.strictEqual(response.statusCode, 200) t.strictEqual(response.headers['content-length'], '' + body.length) t.deepEqual(JSON.parse(body), { hello: 'world' }) delete process.env.FASTIFY_PORT delete process.env.FASTIFY_PREFIX fastify.close(() => { t.pass('server closed') }) }) }) }) test('should start the server at the given prefix (using env var read from dotenv)', t => { t.plan(4) const start = proxyquire('../start', { dotenv: { config () { t.pass('config called') process.env.FASTIFY_PORT = 8080 } } }) const argv = [ './examples/plugin.js' ] start.start(argv, (err, fastify) => { t.error(err) t.strictEqual(fastify.server.address().port, 8080) delete process.env.FASTIFY_PORT fastify.close(() => { t.pass('server closed') }) }) }) test('The plugin is registered with fastify-plugin', t => { t.plan(3) const argv = [ './examples/plugin.js' ] start.start(argv, function (err, fastify) { t.error(err) t.strictEqual(fastify.test, true) fastify.close(function () { t.pass('close called') }) }) }) test('should start the server listening on 0.0.0.0 when runing in docker', t => { t.plan(3) const isDocker = sinon.stub() isDocker.returns(true) const start = proxyquire('../start', { 'is-docker': isDocker }) const argv = [ '-p', getPort(), './examples/plugin.js' ] start.start(argv, (err, fastify) => { t.error(err) t.strictEqual(fastify.server.address().address, '0.0.0.0') fastify.close(function () { t.pass('close called') }) }) }) test('should start the server with watch options that the child process restart when directory changed', { skip: onTravis }, (t) => { t.plan(6) const tmpjs = path.resolve(baseFilename + '.js') fs.writeFile(tmpjs, 'hello world', function (err) { t.error(err) const argv = [ '-p', '3042', '-w', './examples/plugin.js' ] const fastifyEmitter = start.start(argv) t.tearDown(() => { if (fs.existsSync(tmpjs)) { fs.unlinkSync(tmpjs) } fastifyEmitter.emit('close') }) fastifyEmitter.on('start', () => { t.pass('should receive start event') t.pass('change tmpjs') fs.writeFileSync(tmpjs, 'hello fastify', { flag: 'a+' }) // chokidar watch can't caught change event in travis CI, but local test is all ok. you can remove annotation in local environment. }) fastifyEmitter.on('restart', () => { t.pass('should receive restart event') }) fastifyEmitter.on('ready', () => { t.pass('should receive ready event') }) }) })