Spaces:
Runtime error
Runtime error
| const t = require('tap') | |
| const test = t.test | |
| const Fastify = require('..') | |
| const fp = require('fastify-plugin') | |
| const sget = require('simple-get').concat | |
| const symbols = require('../lib/symbols.js') | |
| test('server methods should exist', t => { | |
| t.plan(2) | |
| const fastify = Fastify() | |
| t.ok(fastify.decorate) | |
| t.ok(fastify.hasDecorator) | |
| }) | |
| test('should check if the given decoration already exist when null', t => { | |
| t.plan(1) | |
| const fastify = Fastify() | |
| fastify.decorate('null', null) | |
| fastify.ready(() => { | |
| t.ok(fastify.hasDecorator('null')) | |
| }) | |
| }) | |
| test('server methods should be encapsulated via .register', t => { | |
| t.plan(2) | |
| const fastify = Fastify() | |
| fastify.register((instance, opts, done) => { | |
| instance.decorate('test', () => {}) | |
| t.ok(instance.test) | |
| done() | |
| }) | |
| fastify.ready(() => { | |
| t.notOk(fastify.test) | |
| }) | |
| }) | |
| test('hasServerMethod should check if the given method already exist', t => { | |
| t.plan(2) | |
| const fastify = Fastify() | |
| fastify.register((instance, opts, done) => { | |
| instance.decorate('test', () => {}) | |
| t.ok(instance.hasDecorator('test')) | |
| done() | |
| }) | |
| fastify.ready(() => { | |
| t.notOk(fastify.hasDecorator('test')) | |
| }) | |
| }) | |
| test('decorate should throw if a declared dependency is not present', t => { | |
| t.plan(3) | |
| const fastify = Fastify() | |
| fastify.register((instance, opts, done) => { | |
| try { | |
| instance.decorate('test', () => {}, ['dependency']) | |
| t.fail() | |
| } catch (e) { | |
| t.same(e.code, 'FST_ERR_DEC_MISSING_DEPENDENCY') | |
| t.same(e.message, 'The decorator is missing dependency \'dependency\'.') | |
| } | |
| done() | |
| }) | |
| fastify.ready(() => t.pass()) | |
| }) | |
| test('decorate should throw if declared dependency is not array', t => { | |
| t.plan(3) | |
| const fastify = Fastify() | |
| fastify.register((instance, opts, done) => { | |
| try { | |
| instance.decorate('test', () => {}, {}) | |
| t.fail() | |
| } catch (e) { | |
| t.same(e.code, 'FST_ERR_DEC_DEPENDENCY_INVALID_TYPE') | |
| t.same(e.message, 'The dependencies of decorator \'test\' must be of type Array.') | |
| } | |
| done() | |
| }) | |
| fastify.ready(() => t.pass()) | |
| }) | |
| // issue #777 | |
| test('should pass error for missing request decorator', t => { | |
| t.plan(2) | |
| const fastify = Fastify() | |
| const plugin = fp(function (instance, opts, done) { | |
| done() | |
| }, { | |
| decorators: { | |
| request: ['foo'] | |
| } | |
| }) | |
| fastify | |
| .register(plugin) | |
| .ready((err) => { | |
| t.type(err, Error) | |
| t.match(err, /The decorator 'foo'/) | |
| }) | |
| }) | |
| test('decorateReply inside register', t => { | |
| t.plan(11) | |
| const fastify = Fastify() | |
| fastify.register((instance, opts, done) => { | |
| instance.decorateReply('test', 'test') | |
| instance.get('/yes', (req, reply) => { | |
| t.ok(reply.test, 'test exists') | |
| reply.send({ hello: 'world' }) | |
| }) | |
| done() | |
| }) | |
| fastify.get('/no', (req, reply) => { | |
| t.notOk(reply.test) | |
| reply.send({ hello: 'world' }) | |
| }) | |
| fastify.listen({ port: 0 }, err => { | |
| t.error(err) | |
| t.teardown(() => { fastify.close() }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/yes' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/no' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| }) | |
| }) | |
| test('decorateReply as plugin (inside .after)', t => { | |
| t.plan(11) | |
| const fastify = Fastify() | |
| fastify.register((instance, opts, done) => { | |
| instance.register(fp((i, o, n) => { | |
| instance.decorateReply('test', 'test') | |
| n() | |
| })).after(() => { | |
| instance.get('/yes', (req, reply) => { | |
| t.ok(reply.test) | |
| reply.send({ hello: 'world' }) | |
| }) | |
| }) | |
| done() | |
| }) | |
| fastify.get('/no', (req, reply) => { | |
| t.notOk(reply.test) | |
| reply.send({ hello: 'world' }) | |
| }) | |
| fastify.listen({ port: 0 }, err => { | |
| t.error(err) | |
| t.teardown(() => { fastify.close() }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/yes' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/no' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| }) | |
| }) | |
| test('decorateReply as plugin (outside .after)', t => { | |
| t.plan(11) | |
| const fastify = Fastify() | |
| fastify.register((instance, opts, done) => { | |
| instance.register(fp((i, o, n) => { | |
| instance.decorateReply('test', 'test') | |
| n() | |
| })) | |
| instance.get('/yes', (req, reply) => { | |
| t.ok(reply.test) | |
| reply.send({ hello: 'world' }) | |
| }) | |
| done() | |
| }) | |
| fastify.get('/no', (req, reply) => { | |
| t.notOk(reply.test) | |
| reply.send({ hello: 'world' }) | |
| }) | |
| fastify.listen({ port: 0 }, err => { | |
| t.error(err) | |
| t.teardown(() => { fastify.close() }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/yes' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/no' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| }) | |
| }) | |
| test('decorateRequest inside register', t => { | |
| t.plan(11) | |
| const fastify = Fastify() | |
| fastify.register((instance, opts, done) => { | |
| instance.decorateRequest('test', 'test') | |
| instance.get('/yes', (req, reply) => { | |
| t.ok(req.test, 'test exists') | |
| reply.send({ hello: 'world' }) | |
| }) | |
| done() | |
| }) | |
| fastify.get('/no', (req, reply) => { | |
| t.notOk(req.test) | |
| reply.send({ hello: 'world' }) | |
| }) | |
| fastify.listen({ port: 0 }, err => { | |
| t.error(err) | |
| t.teardown(() => { fastify.close() }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/yes' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/no' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| }) | |
| }) | |
| test('decorateRequest as plugin (inside .after)', t => { | |
| t.plan(11) | |
| const fastify = Fastify() | |
| fastify.register((instance, opts, done) => { | |
| instance.register(fp((i, o, n) => { | |
| instance.decorateRequest('test', 'test') | |
| n() | |
| })).after(() => { | |
| instance.get('/yes', (req, reply) => { | |
| t.ok(req.test) | |
| reply.send({ hello: 'world' }) | |
| }) | |
| }) | |
| done() | |
| }) | |
| fastify.get('/no', (req, reply) => { | |
| t.notOk(req.test) | |
| reply.send({ hello: 'world' }) | |
| }) | |
| fastify.listen({ port: 0 }, err => { | |
| t.error(err) | |
| t.teardown(() => { fastify.close() }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/yes' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/no' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| }) | |
| }) | |
| test('decorateRequest as plugin (outside .after)', t => { | |
| t.plan(11) | |
| const fastify = Fastify() | |
| fastify.register((instance, opts, done) => { | |
| instance.register(fp((i, o, n) => { | |
| instance.decorateRequest('test', 'test') | |
| n() | |
| })) | |
| instance.get('/yes', (req, reply) => { | |
| t.ok(req.test) | |
| reply.send({ hello: 'world' }) | |
| }) | |
| done() | |
| }) | |
| fastify.get('/no', (req, reply) => { | |
| t.notOk(req.test) | |
| reply.send({ hello: 'world' }) | |
| }) | |
| fastify.listen({ port: 0 }, err => { | |
| t.error(err) | |
| t.teardown(() => { fastify.close() }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/yes' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/no' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| }) | |
| }) | |
| test('decorators should be instance separated', t => { | |
| t.plan(1) | |
| const fastify1 = Fastify() | |
| const fastify2 = Fastify() | |
| fastify1.decorate('test', 'foo') | |
| fastify2.decorate('test', 'foo') | |
| fastify1.decorateRequest('test', 'foo') | |
| fastify2.decorateRequest('test', 'foo') | |
| fastify1.decorateReply('test', 'foo') | |
| fastify2.decorateReply('test', 'foo') | |
| t.pass() | |
| }) | |
| test('hasRequestDecorator', t => { | |
| const requestDecoratorName = 'my-decorator-name' | |
| t.test('is a function', t => { | |
| t.plan(1) | |
| const fastify = Fastify() | |
| t.ok(fastify.hasRequestDecorator) | |
| }) | |
| t.test('should check if the given request decoration already exist', t => { | |
| t.plan(2) | |
| const fastify = Fastify() | |
| t.notOk(fastify.hasRequestDecorator(requestDecoratorName)) | |
| fastify.decorateRequest(requestDecoratorName, 42) | |
| t.ok(fastify.hasRequestDecorator(requestDecoratorName)) | |
| }) | |
| t.test('should check if the given request decoration already exist when null', t => { | |
| t.plan(2) | |
| const fastify = Fastify() | |
| t.notOk(fastify.hasRequestDecorator(requestDecoratorName)) | |
| fastify.decorateRequest(requestDecoratorName, null) | |
| t.ok(fastify.hasRequestDecorator(requestDecoratorName)) | |
| }) | |
| t.test('should be plugin encapsulable', t => { | |
| t.plan(4) | |
| const fastify = Fastify() | |
| t.notOk(fastify.hasRequestDecorator(requestDecoratorName)) | |
| fastify.register(function (fastify2, opts, done) { | |
| fastify2.decorateRequest(requestDecoratorName, 42) | |
| t.ok(fastify2.hasRequestDecorator(requestDecoratorName)) | |
| done() | |
| }) | |
| t.notOk(fastify.hasRequestDecorator(requestDecoratorName)) | |
| fastify.ready(function () { | |
| t.notOk(fastify.hasRequestDecorator(requestDecoratorName)) | |
| }) | |
| }) | |
| t.test('should be inherited', t => { | |
| t.plan(2) | |
| const fastify = Fastify() | |
| fastify.decorateRequest(requestDecoratorName, 42) | |
| fastify.register(function (fastify2, opts, done) { | |
| t.ok(fastify2.hasRequestDecorator(requestDecoratorName)) | |
| done() | |
| }) | |
| fastify.ready(function () { | |
| t.ok(fastify.hasRequestDecorator(requestDecoratorName)) | |
| }) | |
| }) | |
| t.end() | |
| }) | |
| test('hasReplyDecorator', t => { | |
| const replyDecoratorName = 'my-decorator-name' | |
| t.test('is a function', t => { | |
| t.plan(1) | |
| const fastify = Fastify() | |
| t.ok(fastify.hasReplyDecorator) | |
| }) | |
| t.test('should check if the given reply decoration already exist', t => { | |
| t.plan(2) | |
| const fastify = Fastify() | |
| t.notOk(fastify.hasReplyDecorator(replyDecoratorName)) | |
| fastify.decorateReply(replyDecoratorName, 42) | |
| t.ok(fastify.hasReplyDecorator(replyDecoratorName)) | |
| }) | |
| t.test('should check if the given reply decoration already exist when null', t => { | |
| t.plan(2) | |
| const fastify = Fastify() | |
| t.notOk(fastify.hasReplyDecorator(replyDecoratorName)) | |
| fastify.decorateReply(replyDecoratorName, null) | |
| t.ok(fastify.hasReplyDecorator(replyDecoratorName)) | |
| }) | |
| t.test('should be plugin encapsulable', t => { | |
| t.plan(4) | |
| const fastify = Fastify() | |
| t.notOk(fastify.hasReplyDecorator(replyDecoratorName)) | |
| fastify.register(function (fastify2, opts, done) { | |
| fastify2.decorateReply(replyDecoratorName, 42) | |
| t.ok(fastify2.hasReplyDecorator(replyDecoratorName)) | |
| done() | |
| }) | |
| t.notOk(fastify.hasReplyDecorator(replyDecoratorName)) | |
| fastify.ready(function () { | |
| t.notOk(fastify.hasReplyDecorator(replyDecoratorName)) | |
| }) | |
| }) | |
| t.test('should be inherited', t => { | |
| t.plan(2) | |
| const fastify = Fastify() | |
| fastify.decorateReply(replyDecoratorName, 42) | |
| fastify.register(function (fastify2, opts, done) { | |
| t.ok(fastify2.hasReplyDecorator(replyDecoratorName)) | |
| done() | |
| }) | |
| fastify.ready(function () { | |
| t.ok(fastify.hasReplyDecorator(replyDecoratorName)) | |
| }) | |
| }) | |
| t.end() | |
| }) | |
| test('should register properties via getter/setter objects', t => { | |
| t.plan(3) | |
| const fastify = Fastify() | |
| fastify.register((instance, opts, done) => { | |
| instance.decorate('test', { | |
| getter () { | |
| return 'a getter' | |
| } | |
| }) | |
| t.ok(instance.test) | |
| t.ok(instance.test, 'a getter') | |
| done() | |
| }) | |
| fastify.ready(() => { | |
| t.notOk(fastify.test) | |
| }) | |
| }) | |
| test('decorateRequest should work with getter/setter', t => { | |
| t.plan(5) | |
| const fastify = Fastify() | |
| fastify.register((instance, opts, done) => { | |
| instance.decorateRequest('test', { | |
| getter () { | |
| return 'a getter' | |
| } | |
| }) | |
| instance.get('/req-decorated-get-set', (req, res) => { | |
| res.send({ test: req.test }) | |
| }) | |
| done() | |
| }) | |
| fastify.get('/not-decorated', (req, res) => { | |
| t.notOk(req.test) | |
| res.send() | |
| }) | |
| fastify.ready(() => { | |
| fastify.inject({ url: '/req-decorated-get-set' }, (err, res) => { | |
| t.error(err) | |
| t.same(JSON.parse(res.payload), { test: 'a getter' }) | |
| }) | |
| fastify.inject({ url: '/not-decorated' }, (err, res) => { | |
| t.error(err) | |
| t.pass() | |
| }) | |
| }) | |
| }) | |
| test('decorateReply should work with getter/setter', t => { | |
| t.plan(5) | |
| const fastify = Fastify() | |
| fastify.register((instance, opts, done) => { | |
| instance.decorateReply('test', { | |
| getter () { | |
| return 'a getter' | |
| } | |
| }) | |
| instance.get('/res-decorated-get-set', (req, res) => { | |
| res.send({ test: res.test }) | |
| }) | |
| done() | |
| }) | |
| fastify.get('/not-decorated', (req, res) => { | |
| t.notOk(res.test) | |
| res.send() | |
| }) | |
| fastify.ready(() => { | |
| fastify.inject({ url: '/res-decorated-get-set' }, (err, res) => { | |
| t.error(err) | |
| t.same(JSON.parse(res.payload), { test: 'a getter' }) | |
| }) | |
| fastify.inject({ url: '/not-decorated' }, (err, res) => { | |
| t.error(err) | |
| t.pass() | |
| }) | |
| }) | |
| }) | |
| test('should register empty values', t => { | |
| t.plan(2) | |
| const fastify = Fastify() | |
| fastify.register((instance, opts, done) => { | |
| instance.decorate('test', null) | |
| t.ok(Object.hasOwn(instance, 'test')) | |
| done() | |
| }) | |
| fastify.ready(() => { | |
| t.notOk(fastify.test) | |
| }) | |
| }) | |
| test('nested plugins can override things', t => { | |
| t.plan(6) | |
| const fastify = Fastify() | |
| const rootFunc = () => {} | |
| fastify.decorate('test', rootFunc) | |
| fastify.decorateRequest('test', rootFunc) | |
| fastify.decorateReply('test', rootFunc) | |
| fastify.register((instance, opts, done) => { | |
| const func = () => {} | |
| instance.decorate('test', func) | |
| instance.decorateRequest('test', func) | |
| instance.decorateReply('test', func) | |
| t.equal(instance.test, func) | |
| t.equal(instance[symbols.kRequest].prototype.test, func) | |
| t.equal(instance[symbols.kReply].prototype.test, func) | |
| done() | |
| }) | |
| fastify.ready(() => { | |
| t.equal(fastify.test, rootFunc) | |
| t.equal(fastify[symbols.kRequest].prototype.test, rootFunc) | |
| t.equal(fastify[symbols.kReply].prototype.test, rootFunc) | |
| }) | |
| }) | |
| test('a decorator should addSchema to all the encapsulated tree', t => { | |
| t.plan(1) | |
| const fastify = Fastify() | |
| const decorator = function (instance, opts, done) { | |
| instance.decorate('decoratorAddSchema', function (whereAddTheSchema) { | |
| instance.addSchema({ | |
| $id: 'schema', | |
| type: 'string' | |
| }) | |
| }) | |
| done() | |
| } | |
| fastify.register(fp(decorator)) | |
| fastify.register(function (instance, opts, done) { | |
| instance.register((subInstance, opts, done) => { | |
| subInstance.decoratorAddSchema() | |
| done() | |
| }) | |
| done() | |
| }) | |
| fastify.ready(t.error) | |
| }) | |
| test('after can access to a decorated instance and previous plugin decoration', t => { | |
| t.plan(11) | |
| const TEST_VALUE = {} | |
| const OTHER_TEST_VALUE = {} | |
| const NEW_TEST_VALUE = {} | |
| const fastify = Fastify() | |
| fastify.register(fp(function (instance, options, done) { | |
| instance.decorate('test', TEST_VALUE) | |
| done() | |
| })).after(function (err, instance, done) { | |
| t.error(err) | |
| t.equal(instance.test, TEST_VALUE) | |
| instance.decorate('test2', OTHER_TEST_VALUE) | |
| done() | |
| }) | |
| fastify.register(fp(function (instance, options, done) { | |
| t.equal(instance.test, TEST_VALUE) | |
| t.equal(instance.test2, OTHER_TEST_VALUE) | |
| instance.decorate('test3', NEW_TEST_VALUE) | |
| done() | |
| })).after(function (err, instance, done) { | |
| t.error(err) | |
| t.equal(instance.test, TEST_VALUE) | |
| t.equal(instance.test2, OTHER_TEST_VALUE) | |
| t.equal(instance.test3, NEW_TEST_VALUE) | |
| done() | |
| }) | |
| fastify.get('/', function (req, res) { | |
| t.equal(this.test, TEST_VALUE) | |
| t.equal(this.test2, OTHER_TEST_VALUE) | |
| res.send({}) | |
| }) | |
| fastify.inject('/') | |
| .then(response => { | |
| t.equal(response.statusCode, 200) | |
| }) | |
| }) | |
| test('decorate* should throw if called after ready', async t => { | |
| t.plan(6) | |
| const fastify = Fastify() | |
| fastify.get('/', (request, reply) => { | |
| reply.send({ | |
| hello: 'world' | |
| }) | |
| }) | |
| await fastify.listen({ port: 0 }) | |
| try { | |
| fastify.decorate('test', true) | |
| t.fail('should not decorate') | |
| } catch (err) { | |
| t.same(err.code, 'FST_ERR_DEC_AFTER_START') | |
| t.same(err.message, "The decorator 'test' has been added after start!") | |
| } | |
| try { | |
| fastify.decorateRequest('test', true) | |
| t.fail('should not decorate') | |
| } catch (e) { | |
| t.same(e.code, 'FST_ERR_DEC_AFTER_START') | |
| t.same(e.message, "The decorator 'test' has been added after start!") | |
| } | |
| try { | |
| fastify.decorateReply('test', true) | |
| t.fail('should not decorate') | |
| } catch (e) { | |
| t.same(e.code, 'FST_ERR_DEC_AFTER_START') | |
| t.same(e.message, "The decorator 'test' has been added after start!") | |
| } | |
| await fastify.close() | |
| }) | |
| test('decorate* should emit error if an array is passed', t => { | |
| t.plan(2) | |
| const fastify = Fastify() | |
| try { | |
| fastify.decorateRequest('test_array', []) | |
| t.fail('should not decorate') | |
| } catch (err) { | |
| t.same(err.code, 'FST_ERR_DEC_REFERENCE_TYPE') | |
| t.same(err.message, "The decorator 'test_array' of type 'object' is a reference type. Use the { getter, setter } interface instead.") | |
| } | |
| }) | |
| test('server.decorate should not emit error if reference type is passed', async t => { | |
| t.plan(1) | |
| const fastify = Fastify() | |
| fastify.decorate('test_array', []) | |
| fastify.decorate('test_object', {}) | |
| await fastify.ready() | |
| t.pass('Done') | |
| }) | |
| test('decorate* should emit warning if object type is passed', t => { | |
| t.plan(2) | |
| const fastify = Fastify() | |
| try { | |
| fastify.decorateRequest('test_object', { foo: 'bar' }) | |
| t.fail('should not decorate') | |
| } catch (err) { | |
| t.same(err.code, 'FST_ERR_DEC_REFERENCE_TYPE') | |
| t.same(err.message, "The decorator 'test_object' of type 'object' is a reference type. Use the { getter, setter } interface instead.") | |
| } | |
| }) | |
| test('decorate* should not emit warning if object with getter/setter is passed', t => { | |
| const fastify = Fastify() | |
| fastify.decorateRequest('test_getter_setter', { | |
| setter (val) { | |
| this._ = val | |
| }, | |
| getter () { | |
| return 'a getter' | |
| } | |
| }) | |
| t.end('Done') | |
| }) | |
| test('decorateRequest with getter/setter can handle encapsulation', async t => { | |
| t.plan(24) | |
| const fastify = Fastify({ logger: true }) | |
| fastify.decorateRequest('test_getter_setter_holder') | |
| fastify.decorateRequest('test_getter_setter', { | |
| getter () { | |
| this.test_getter_setter_holder ??= {} | |
| return this.test_getter_setter_holder | |
| } | |
| }) | |
| fastify.get('/', async function (req, reply) { | |
| t.same(req.test_getter_setter, {}, 'a getter') | |
| req.test_getter_setter.a = req.id | |
| t.same(req.test_getter_setter, { a: req.id }) | |
| }) | |
| fastify.addHook('onResponse', async function hook (req, reply) { | |
| t.same(req.test_getter_setter, { a: req.id }) | |
| }) | |
| await Promise.all([ | |
| fastify.inject('/').then(res => t.same(res.statusCode, 200)), | |
| fastify.inject('/').then(res => t.same(res.statusCode, 200)), | |
| fastify.inject('/').then(res => t.same(res.statusCode, 200)), | |
| fastify.inject('/').then(res => t.same(res.statusCode, 200)), | |
| fastify.inject('/').then(res => t.same(res.statusCode, 200)), | |
| fastify.inject('/').then(res => t.same(res.statusCode, 200)) | |
| ]) | |
| }) | |
| test('decorateRequest with getter/setter can handle encapsulation with arrays', async t => { | |
| t.plan(24) | |
| const fastify = Fastify({ logger: true }) | |
| fastify.decorateRequest('array_holder') | |
| fastify.decorateRequest('my_array', { | |
| getter () { | |
| this.array_holder ??= [] | |
| return this.array_holder | |
| } | |
| }) | |
| fastify.get('/', async function (req, reply) { | |
| t.same(req.my_array, []) | |
| req.my_array.push(req.id) | |
| t.same(req.my_array, [req.id]) | |
| }) | |
| fastify.addHook('onResponse', async function hook (req, reply) { | |
| t.same(req.my_array, [req.id]) | |
| }) | |
| await Promise.all([ | |
| fastify.inject('/').then(res => t.same(res.statusCode, 200)), | |
| fastify.inject('/').then(res => t.same(res.statusCode, 200)), | |
| fastify.inject('/').then(res => t.same(res.statusCode, 200)), | |
| fastify.inject('/').then(res => t.same(res.statusCode, 200)), | |
| fastify.inject('/').then(res => t.same(res.statusCode, 200)), | |
| fastify.inject('/').then(res => t.same(res.statusCode, 200)) | |
| ]) | |
| }) | |
| test('decorate* should not emit error if string,bool,numbers are passed', t => { | |
| const fastify = Fastify() | |
| fastify.decorateRequest('test_str', 'foo') | |
| fastify.decorateRequest('test_bool', true) | |
| fastify.decorateRequest('test_number', 42) | |
| fastify.decorateRequest('test_null', null) | |
| fastify.decorateRequest('test_undefined', undefined) | |
| fastify.decorateReply('test_str', 'foo') | |
| fastify.decorateReply('test_bool', true) | |
| fastify.decorateReply('test_number', 42) | |
| fastify.decorateReply('test_null', null) | |
| fastify.decorateReply('test_undefined', undefined) | |
| t.end('Done') | |
| }) | |
| test('Request/reply decorators should be able to access the server instance', async t => { | |
| t.plan(6) | |
| const server = require('..')({ logger: false }) | |
| server.decorateRequest('assert', rootAssert) | |
| server.decorateReply('assert', rootAssert) | |
| server.get('/root-assert', async (req, rep) => { | |
| req.assert() | |
| rep.assert() | |
| return 'done' | |
| }) | |
| server.register(async instance => { | |
| instance.decorateRequest('assert', nestedAssert) | |
| instance.decorateReply('assert', nestedAssert) | |
| instance.decorate('foo', 'bar') | |
| instance.get('/nested-assert', async (req, rep) => { | |
| req.assert() | |
| rep.assert() | |
| return 'done' | |
| }) | |
| }) | |
| await server.inject({ method: 'GET', url: '/root-assert' }) | |
| await server.inject({ method: 'GET', url: '/nested-assert' }) | |
| // ---- | |
| function rootAssert () { | |
| t.equal(this.server, server) | |
| } | |
| function nestedAssert () { | |
| t.not(this.server, server) | |
| t.equal(this.server.foo, 'bar') | |
| } | |
| }) | |
| test('plugin required decorators', async t => { | |
| const plugin1 = fp( | |
| async (instance) => { | |
| instance.decorateRequest('someThing', null) | |
| instance.addHook('onRequest', async (request, reply) => { | |
| request.someThing = 'hello' | |
| }) | |
| }, | |
| { | |
| name: 'custom-plugin-one' | |
| } | |
| ) | |
| const plugin2 = fp( | |
| async () => { | |
| // nothing | |
| }, | |
| { | |
| name: 'custom-plugin-two', | |
| dependencies: ['custom-plugin-one'], | |
| decorators: { | |
| request: ['someThing'] | |
| } | |
| } | |
| ) | |
| const app = Fastify() | |
| app.register(plugin1) | |
| app.register(plugin2) | |
| await app.ready() | |
| }) | |
| test('decorateRequest/decorateReply empty string', t => { | |
| t.plan(7) | |
| const fastify = Fastify() | |
| fastify.decorateRequest('test', '') | |
| fastify.decorateReply('test2', '') | |
| fastify.get('/yes', (req, reply) => { | |
| t.equal(req.test, '') | |
| t.equal(reply.test2, '') | |
| reply.send({ hello: 'world' }) | |
| }) | |
| t.teardown(fastify.close.bind(fastify)) | |
| fastify.listen({ port: 0 }, err => { | |
| t.error(err) | |
| t.teardown(() => { fastify.close() }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/yes' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| }) | |
| }) | |
| test('decorateRequest/decorateReply is undefined', t => { | |
| t.plan(7) | |
| const fastify = Fastify() | |
| fastify.decorateRequest('test', undefined) | |
| fastify.decorateReply('test2', undefined) | |
| fastify.get('/yes', (req, reply) => { | |
| t.equal(req.test, undefined) | |
| t.equal(reply.test2, undefined) | |
| reply.send({ hello: 'world' }) | |
| }) | |
| t.teardown(fastify.close.bind(fastify)) | |
| fastify.listen({ port: 0 }, err => { | |
| t.error(err) | |
| t.teardown(() => { fastify.close() }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/yes' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| }) | |
| }) | |
| test('decorateRequest/decorateReply is not set to a value', t => { | |
| t.plan(7) | |
| const fastify = Fastify() | |
| fastify.decorateRequest('test') | |
| fastify.decorateReply('test2') | |
| fastify.get('/yes', (req, reply) => { | |
| t.equal(req.test, undefined) | |
| t.equal(reply.test2, undefined) | |
| reply.send({ hello: 'world' }) | |
| }) | |
| t.teardown(fastify.close.bind(fastify)) | |
| fastify.listen({ port: 0 }, err => { | |
| t.error(err) | |
| t.teardown(() => { fastify.close() }) | |
| sget({ | |
| method: 'GET', | |
| url: 'http://localhost:' + fastify.server.address().port + '/yes' | |
| }, (err, response, body) => { | |
| t.error(err) | |
| t.equal(response.statusCode, 200) | |
| t.equal(response.headers['content-length'], '' + body.length) | |
| t.same(JSON.parse(body), { hello: 'world' }) | |
| }) | |
| }) | |
| }) | |
| test('decorateRequest with dependencies', (t) => { | |
| t.plan(2) | |
| const app = Fastify() | |
| const decorator1 = 'bar' | |
| const decorator2 = 'foo' | |
| app.decorate('decorator1', decorator1) | |
| app.decorateRequest('decorator1', decorator1) | |
| if ( | |
| app.hasDecorator('decorator1') && | |
| app.hasRequestDecorator('decorator1') | |
| ) { | |
| t.doesNotThrow(() => app.decorateRequest('decorator2', decorator2, ['decorator1'])) | |
| t.ok(app.hasRequestDecorator('decorator2')) | |
| } | |
| }) | |
| test('decorateRequest with dependencies (functions)', (t) => { | |
| t.plan(2) | |
| const app = Fastify() | |
| const decorator1 = () => 'bar' | |
| const decorator2 = () => 'foo' | |
| app.decorate('decorator1', decorator1) | |
| app.decorateRequest('decorator1', decorator1) | |
| if ( | |
| app.hasDecorator('decorator1') && | |
| app.hasRequestDecorator('decorator1') | |
| ) { | |
| t.doesNotThrow(() => app.decorateRequest('decorator2', decorator2, ['decorator1'])) | |
| t.ok(app.hasRequestDecorator('decorator2')) | |
| } | |
| }) | |
| test('chain of decorators on Request', async (t) => { | |
| const fastify = Fastify() | |
| fastify.register(fp(async function (fastify) { | |
| fastify.decorateRequest('foo', 'toto') | |
| fastify.decorateRequest('bar', () => 'tata') | |
| }, { | |
| name: 'first' | |
| })) | |
| fastify.get('/foo', async function (request, reply) { | |
| return request.foo | |
| }) | |
| fastify.get('/bar', function (request, reply) { | |
| return request.bar() | |
| }) | |
| fastify.register(async function second (fastify) { | |
| fastify.get('/foo', async function (request, reply) { | |
| return request.foo | |
| }) | |
| fastify.get('/bar', async function (request, reply) { | |
| return request.bar() | |
| }) | |
| fastify.register(async function fourth (fastify) { | |
| fastify.get('/plugin3/foo', async function (request, reply) { | |
| return request.foo | |
| }) | |
| fastify.get('/plugin3/bar', function (request, reply) { | |
| return request.bar() | |
| }) | |
| }) | |
| fastify.register(fp(async function (fastify) { | |
| fastify.decorateRequest('fooB', 'toto') | |
| fastify.decorateRequest('barB', () => 'tata') | |
| }, { | |
| name: 'third' | |
| })) | |
| }, | |
| { prefix: '/plugin2', name: 'plugin2' } | |
| ) | |
| await fastify.ready() | |
| { | |
| const response = await fastify.inject('/foo') | |
| t.equal(response.body, 'toto') | |
| } | |
| { | |
| const response = await fastify.inject('/bar') | |
| t.equal(response.body, 'tata') | |
| } | |
| { | |
| const response = await fastify.inject('/plugin2/foo') | |
| t.equal(response.body, 'toto') | |
| } | |
| { | |
| const response = await fastify.inject('/plugin2/bar') | |
| t.equal(response.body, 'tata') | |
| } | |
| { | |
| const response = await fastify.inject('/plugin2/plugin3/foo') | |
| t.equal(response.body, 'toto') | |
| } | |
| { | |
| const response = await fastify.inject('/plugin2/plugin3/bar') | |
| t.equal(response.body, 'tata') | |
| } | |
| }) | |
| test('chain of decorators on Reply', async (t) => { | |
| const fastify = Fastify() | |
| fastify.register(fp(async function (fastify) { | |
| fastify.decorateReply('foo', 'toto') | |
| fastify.decorateReply('bar', () => 'tata') | |
| }, { | |
| name: 'first' | |
| })) | |
| fastify.get('/foo', async function (request, reply) { | |
| return reply.foo | |
| }) | |
| fastify.get('/bar', function (request, reply) { | |
| return reply.bar() | |
| }) | |
| fastify.register(async function second (fastify) { | |
| fastify.get('/foo', async function (request, reply) { | |
| return reply.foo | |
| }) | |
| fastify.get('/bar', async function (request, reply) { | |
| return reply.bar() | |
| }) | |
| fastify.register(async function fourth (fastify) { | |
| fastify.get('/plugin3/foo', async function (request, reply) { | |
| return reply.foo | |
| }) | |
| fastify.get('/plugin3/bar', function (request, reply) { | |
| return reply.bar() | |
| }) | |
| }) | |
| fastify.register(fp(async function (fastify) { | |
| fastify.decorateReply('fooB', 'toto') | |
| fastify.decorateReply('barB', () => 'tata') | |
| }, { | |
| name: 'third' | |
| })) | |
| }, | |
| { prefix: '/plugin2', name: 'plugin2' } | |
| ) | |
| await fastify.ready() | |
| { | |
| const response = await fastify.inject('/foo') | |
| t.equal(response.body, 'toto') | |
| } | |
| { | |
| const response = await fastify.inject('/bar') | |
| t.equal(response.body, 'tata') | |
| } | |
| { | |
| const response = await fastify.inject('/plugin2/foo') | |
| t.equal(response.body, 'toto') | |
| } | |
| { | |
| const response = await fastify.inject('/plugin2/bar') | |
| t.equal(response.body, 'tata') | |
| } | |
| { | |
| const response = await fastify.inject('/plugin2/plugin3/foo') | |
| t.equal(response.body, 'toto') | |
| } | |
| { | |
| const response = await fastify.inject('/plugin2/plugin3/bar') | |
| t.equal(response.body, 'tata') | |
| } | |
| }) | |