From c2b9d1e941f1aad805a001622e377d9f60085f7f Mon Sep 17 00:00:00 2001 From: "dan.castillo" Date: Mon, 2 Sep 2024 22:00:23 -0400 Subject: [PATCH] chore: migrate from tap to node:test and c8 --- package.json | 5 +- test/cors.test.js | 866 ++++++++++++++++++++++------------------- test/hooks.test.js | 505 ++++++++++++++---------- test/preflight.test.js | 461 ++++++++++++---------- test/vary.test.js | 104 ++--- 5 files changed, 1079 insertions(+), 862 deletions(-) diff --git a/package.json b/package.json index 702646b..c67d88b 100644 --- a/package.json +++ b/package.json @@ -6,12 +6,11 @@ "type": "commonjs", "types": "types/index.d.ts", "scripts": { - "coverage": "tap --coverage-report=html test", "lint": "standard", "lint:fix": "standard --fix", "test": "npm run test:unit && npm run test:typescript", "test:typescript": "tsd", - "test:unit": "tap test/*.test.js" + "test:unit": "c8 --100 node --test" }, "keywords": [ "fastify", @@ -35,10 +34,10 @@ "@types/node": "^22.0.0", "@typescript-eslint/eslint-plugin": "^7.3.1", "@typescript-eslint/parser": "^7.3.1", + "c8": "^10.1.2", "cors": "^2.8.5", "fastify": "^5.0.0-alpha.3", "standard": "^17.1.0", - "tap": "18.7.1", "tsd": "^0.31.1", "typescript": "^5.4.2" }, diff --git a/test/cors.test.js b/test/cors.test.js index 727c7cb..9aacaa9 100644 --- a/test/cors.test.js +++ b/test/cors.test.js @@ -1,12 +1,13 @@ 'use strict' -const { test } = require('tap') +const { test } = require('node:test') const { createReadStream, statSync, readFileSync } = require('node:fs') const Fastify = require('fastify') const cors = require('../') const { resolve } = require('node:path') +const { setTimeout: sleep } = require('node:timers/promises') -test('Should add cors headers', t => { +test('Should add cors headers', async t => { t.plan(4) const fastify = Fastify() @@ -16,21 +17,21 @@ test('Should add cors headers', t => { reply.send('ok') }) - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - 'access-control-allow-origin': '*' - }) }) + + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + t.assert.deepStrictEqual(res.headers['access-control-allow-origin'], + '*' + ) }) -test('Should add cors headers when payload is a stream', t => { +test('Should add cors headers when payload is a stream', async t => { t.plan(4) const fastify = Fastify() @@ -47,22 +48,26 @@ test('Should add cors headers when payload is a stream', t => { const fileContent = readFileSync(filePath, 'utf-8') - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, fileContent) - t.match(res.headers, { - 'access-control-allow-origin': '*', - 'content-length': statSync(filePath).size - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, fileContent) + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'content-length': res.headers['content-length'] + + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': '*', + 'content-length': statSync(filePath).size.toString() }) }) -test('Should add cors headers (custom values)', t => { +test('Should add cors headers (custom values)', async t => { t.plan(10) const fastify = Fastify() @@ -80,50 +85,64 @@ test('Should add cors headers (custom values)', t => { reply.send('ok') }) - fastify.inject({ + let res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': 'example.com', - 'access-control-allow-credentials': 'true', - 'access-control-expose-headers': 'foo, bar', - 'access-control-allow-methods': 'GET', - 'access-control-allow-headers': 'baz, woo', - 'access-control-max-age': '123', - 'cache-control': 'max-age=321', - 'content-length': '0' - }) - t.notMatch(res.headers, { vary: 'Origin' }) }) - - fastify.inject({ + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-credentials': res.headers['access-control-allow-credentials'], + 'access-control-expose-headers': res.headers['access-control-expose-headers'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + 'access-control-allow-headers': res.headers['access-control-allow-headers'], + 'access-control-max-age': res.headers['access-control-max-age'], + 'cache-control': res.headers['cache-control'], + 'content-length': res.headers['content-length'] + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': 'example.com', + 'access-control-allow-credentials': 'true', + 'access-control-expose-headers': 'foo, bar', + 'access-control-allow-methods': 'GET', + 'access-control-allow-headers': 'baz, woo', + 'access-control-max-age': '123', + 'cache-control': 'max-age=321', + 'content-length': '0' + }) + t.assert.notDeepEqual(res.headers, { vary: 'Origin' }) + + res = await fastify.inject({ method: 'GET', url: '/' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - 'access-control-allow-origin': 'example.com', - 'access-control-allow-credentials': 'true', - 'access-control-expose-headers': 'foo, bar', - 'content-length': '2' - }) - t.notMatch(res.headers, { vary: 'Origin' }) }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeaders2 = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-credentials': res.headers['access-control-allow-credentials'], + 'access-control-expose-headers': res.headers['access-control-expose-headers'], + 'content-length': res.headers['content-length'] + } + t.assert.deepStrictEqual(actualHeaders2, { + 'access-control-allow-origin': 'example.com', + 'access-control-allow-credentials': 'true', + 'access-control-expose-headers': 'foo, bar', + 'content-length': '2' + }) + t.assert.notDeepEqual(res.headers, { vary: 'Origin' }) }) -test('Should support dynamic config (callback)', t => { +test('Should support dynamic config (callback)', async t => { t.plan(16) const configs = [{ @@ -146,11 +165,12 @@ test('Should support dynamic config (callback)', t => { const fastify = Fastify() let requestId = 0 - const configDelegation = function (req, cb) { + const configDelegation = async function (req, cb) { // request should have id - t.ok(req.id) + t.assert.ok(req.id) // request should not have send - t.notOk(req.send) + t.assert.ifError(req.send) + const config = configs[requestId] requestId++ if (config) { @@ -159,68 +179,87 @@ test('Should support dynamic config (callback)', t => { cb(new Error('ouch')) } } - fastify.register(cors, () => configDelegation) + await fastify.register(cors, () => configDelegation) fastify.get('/', (req, reply) => { reply.send('ok') }) - fastify.inject({ + let res = await fastify.inject({ method: 'GET', url: '/' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - 'access-control-allow-origin': 'example.com', - 'access-control-allow-credentials': 'true', - 'access-control-expose-headers': 'foo, bar', - 'content-length': '2', - vary: 'Origin' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-credentials': res.headers['access-control-allow-credentials'], + 'access-control-expose-headers': res.headers['access-control-expose-headers'], + 'content-length': res.headers['content-length'], + vary: res.headers.vary + } + // Sleep to wait for callback + sleep() + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': 'example.com', + 'access-control-allow-credentials': 'true', + 'access-control-expose-headers': 'foo, bar', + 'content-length': '2', + vary: 'Origin' }) - fastify.inject({ + res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': 'sample.com', - 'access-control-allow-credentials': 'true', - 'access-control-expose-headers': 'zoo, bar', - 'access-control-allow-methods': 'GET', - 'access-control-allow-headers': 'baz, foo', - 'access-control-max-age': '321', - 'cache-control': '456', - 'content-length': '0', - vary: 'Origin' - }) }) - - fastify.inject({ + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + const actualHeaders2 = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-credentials': res.headers['access-control-allow-credentials'], + 'access-control-expose-headers': res.headers['access-control-expose-headers'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + 'access-control-allow-headers': res.headers['access-control-allow-headers'], + 'access-control-max-age': res.headers['access-control-max-age'], + 'cache-control': res.headers['cache-control'], + 'content-length': res.headers['content-length'], + vary: res.headers.vary + } + // Sleep to wait for callback + sleep() + t.assert.deepStrictEqual(actualHeaders2, { + 'access-control-allow-origin': 'sample.com', + 'access-control-allow-credentials': 'true', + 'access-control-expose-headers': 'zoo, bar', + 'access-control-allow-methods': 'GET', + 'access-control-allow-headers': 'baz, foo', + 'access-control-max-age': '321', + 'cache-control': '456', + 'content-length': '0', + vary: 'Origin' + }) + + res = await fastify.inject({ method: 'GET', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 500) }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 500) }) -test('Should support dynamic config (Promise)', t => { +test('Should support dynamic config (Promise)', async t => { t.plan(23) const configs = [{ @@ -251,11 +290,11 @@ test('Should support dynamic config (Promise)', t => { const fastify = Fastify() let requestId = 0 - const configDelegation = function (req) { + const configDelegation = async function (req) { // request should have id - t.ok(req.id) + t.assert.ok(req.id) // request should not have send - t.notOk(req.send) + t.assert.ifError(req.send) const config = configs[requestId] requestId++ if (config) { @@ -264,93 +303,117 @@ test('Should support dynamic config (Promise)', t => { return Promise.reject(new Error('ouch')) } } - fastify.register(cors, () => configDelegation) + await fastify.register(cors, () => configDelegation) fastify.get('/', (req, reply) => { reply.send('ok') }) - fastify.inject({ + let res = await fastify.inject({ method: 'GET', url: '/' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - 'access-control-allow-origin': 'example.com', - 'access-control-allow-credentials': 'true', - 'access-control-expose-headers': 'foo, bar', - 'content-length': '2', - vary: 'Origin' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-credentials': res.headers['access-control-allow-credentials'], + 'access-control-expose-headers': res.headers['access-control-expose-headers'], + 'content-length': res.headers['content-length'], + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': 'example.com', + 'access-control-allow-credentials': 'true', + 'access-control-expose-headers': 'foo, bar', + 'content-length': '2', + vary: 'Origin' }) - fastify.inject({ + res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'sample.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': 'sample.com', - 'access-control-allow-credentials': 'true', - 'access-control-expose-headers': 'zoo, bar', - 'access-control-allow-methods': 'GET', - 'access-control-allow-headers': 'baz, foo', - 'access-control-max-age': '321', - 'content-length': '0', - vary: 'Origin' - }) - t.equal(res.headers['cache-control'], undefined, 'cache-control omitted (invalid value)') }) - - fastify.inject({ + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + const acutalHeaders2 = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-credentials': res.headers['access-control-allow-credentials'], + 'access-control-expose-headers': res.headers['access-control-expose-headers'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + 'access-control-allow-headers': res.headers['access-control-allow-headers'], + 'access-control-max-age': res.headers['access-control-max-age'], + 'content-length': res.headers['content-length'], + vary: res.headers.vary + } + t.assert.deepStrictEqual(acutalHeaders2, { + 'access-control-allow-origin': 'sample.com', + 'access-control-allow-credentials': 'true', + 'access-control-expose-headers': 'zoo, bar', + 'access-control-allow-methods': 'GET', + 'access-control-allow-headers': 'baz, foo', + 'access-control-max-age': '321', + 'content-length': '0', + vary: 'Origin' + }) + t.assert.strictEqual(res.headers['cache-control'], undefined, 'cache-control omitted (invalid value)') + + res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': 'sample.com', - 'access-control-allow-credentials': 'true', - 'access-control-expose-headers': 'zoo, bar', - 'access-control-allow-methods': 'GET', - 'access-control-allow-headers': 'baz, foo', - 'access-control-max-age': '321', - 'cache-control': 'public, max-age=456', // cache-control included (custom string) - 'content-length': '0', - vary: 'Origin' - }) }) - - fastify.inject({ + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + const actualHeaders3 = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-credentials': res.headers['access-control-allow-credentials'], + 'access-control-expose-headers': res.headers['access-control-expose-headers'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + 'access-control-allow-headers': res.headers['access-control-allow-headers'], + 'access-control-max-age': res.headers['access-control-max-age'], + 'cache-control': res.headers['cache-control'], + 'content-length': res.headers['content-length'], + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders3, { + 'access-control-allow-origin': 'sample.com', + 'access-control-allow-credentials': 'true', + 'access-control-expose-headers': 'zoo, bar', + 'access-control-allow-methods': 'GET', + 'access-control-allow-headers': 'baz, foo', + 'access-control-max-age': '321', + 'cache-control': 'public, max-age=456', // cache-control included (custom string) + 'content-length': '0', + vary: 'Origin' + }) + + res = await fastify.inject({ method: 'GET', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 500) }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 500) }) -test('Should support dynamic config. (Invalid function)', t => { +test('Should support dynamic config. (Invalid function)', async t => { t.plan(2) const fastify = Fastify() @@ -360,26 +423,25 @@ test('Should support dynamic config. (Invalid function)', t => { reply.send('ok') }) - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 500) }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 500) }) -test('Dynamic origin resolution (valid origin)', t => { +test('Dynamic origin resolution (valid origin)', async t => { t.plan(6) const fastify = Fastify() const origin = function (header, cb) { - t.equal(header, 'example.com') - t.same(this, fastify) + t.assert.strictEqual(header, 'example.com') + t.assert.equal(this, fastify) cb(null, true) } fastify.register(cors, { origin }) @@ -388,28 +450,31 @@ test('Dynamic origin resolution (valid origin)', t => { reply.send('ok') }) - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/', headers: { origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - 'access-control-allow-origin': 'example.com', - vary: 'Origin' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': 'example.com', + vary: 'Origin' }) }) -test('Dynamic origin resolution (not valid origin)', t => { +test('Dynamic origin resolution (not valid origin)', async t => { t.plan(5) const fastify = Fastify() const origin = (header, cb) => { - t.equal(header, 'example.com') + t.assert.strictEqual(header, 'example.com') cb(null, false) } fastify.register(cors, { origin }) @@ -418,71 +483,74 @@ test('Dynamic origin resolution (not valid origin)', t => { reply.send('ok') }) - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/', headers: { origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.same(res.headers, { - 'content-length': '2', - 'content-type': 'text/plain; charset=utf-8', - connection: 'keep-alive', - vary: 'Origin' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeaders = { + 'content-length': res.headers['content-length'], + 'content-type': res.headers['content-type'], + connection: res.headers.connection, + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders, { + 'content-length': '2', + 'content-type': 'text/plain; charset=utf-8', + connection: 'keep-alive', + vary: 'Origin' }) }) -test('Dynamic origin resolution (errored)', t => { +test('Dynamic origin resolution (errored)', async t => { t.plan(3) const fastify = Fastify() const origin = (header, cb) => { - t.equal(header, 'example.com') + t.assert.strictEqual(header, 'example.com') cb(new Error('ouch')) } fastify.register(cors, { origin }) - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/', headers: { origin: 'example.com' } - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 500) }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 500) }) -test('Dynamic origin resolution (invalid result)', t => { +test('Dynamic origin resolution (invalid result)', async t => { t.plan(3) const fastify = Fastify() const origin = (header, cb) => { - t.equal(header, 'example.com') + t.assert.strictEqual(header, 'example.com') cb(null, undefined) } fastify.register(cors, { origin }) - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/', headers: { origin: 'example.com' } - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 500) }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 500) }) -test('Dynamic origin resolution (valid origin - promises)', t => { +test('Dynamic origin resolution (valid origin - promises)', async t => { t.plan(5) const fastify = Fastify() const origin = (header, cb) => { return new Promise((resolve, reject) => { - t.equal(header, 'example.com') + t.assert.strictEqual(header, 'example.com') resolve(true) }) } @@ -492,29 +560,32 @@ test('Dynamic origin resolution (valid origin - promises)', t => { reply.send('ok') }) - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/', headers: { origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - 'access-control-allow-origin': 'example.com', - vary: 'Origin' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': 'example.com', + vary: 'Origin' }) }) -test('Dynamic origin resolution (not valid origin - promises)', t => { +test('Dynamic origin resolution (not valid origin - promises)', async t => { t.plan(5) const fastify = Fastify() const origin = (header, cb) => { return new Promise((resolve, reject) => { - t.equal(header, 'example.com') + t.assert.strictEqual(header, 'example.com') resolve(false) }) } @@ -524,47 +595,51 @@ test('Dynamic origin resolution (not valid origin - promises)', t => { reply.send('ok') }) - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/', headers: { origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.same(res.headers, { - 'content-length': '2', - 'content-type': 'text/plain; charset=utf-8', - connection: 'keep-alive', - vary: 'Origin' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeaders = { + 'content-length': res.headers['content-length'], + 'content-type': res.headers['content-type'], + connection: res.headers.connection, + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders, { + 'content-length': '2', + 'content-type': 'text/plain; charset=utf-8', + connection: 'keep-alive', + vary: 'Origin' }) }) -test('Dynamic origin resolution (errored - promises)', t => { +test('Dynamic origin resolution (errored - promises)', async t => { t.plan(3) const fastify = Fastify() const origin = (header, cb) => { return new Promise((resolve, reject) => { - t.equal(header, 'example.com') + t.assert.strictEqual(header, 'example.com') reject(new Error('ouch')) }) } fastify.register(cors, { origin }) - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/', headers: { origin: 'example.com' } - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 500) }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 500) }) -test('Should reply 404 without cors headers when origin is false', t => { +test('Should reply 404 without cors headers when origin is false', async t => { t.plan(8) const fastify = Fastify() @@ -581,61 +656,68 @@ test('Should reply 404 without cors headers when origin is false', t => { reply.send('ok') }) - fastify.inject({ + let res = await fastify.inject({ method: 'OPTIONS', url: '/' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 404) - t.equal(res.payload, '{"message":"Route OPTIONS:/ not found","error":"Not Found","statusCode":404}') - t.same(res.headers, { - 'content-length': '76', - 'content-type': 'application/json; charset=utf-8', - connection: 'keep-alive' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 404) + t.assert.strictEqual(res.payload, '{"message":"Route OPTIONS:/ not found","error":"Not Found","statusCode":404}') + const actualHeaders = { + 'content-length': res.headers['content-length'], + 'content-type': res.headers['content-type'], + connection: res.headers.connection + } + t.assert.deepStrictEqual(actualHeaders, { + 'content-length': '76', + 'content-type': 'application/json; charset=utf-8', + connection: 'keep-alive' }) - fastify.inject({ + res = await fastify.inject({ method: 'GET', url: '/' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.same(res.headers, { - 'content-length': '2', - 'content-type': 'text/plain; charset=utf-8', - connection: 'keep-alive' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + t.assert.deepStrictEqual(res.headers, { + 'content-length': '2', + 'content-type': 'text/plain; charset=utf-8', + connection: 'keep-alive' }) }) -test('Server error if origin option is falsy but not false', t => { +test('Server error if origin option is falsy but not false', async t => { t.plan(4) const fastify = Fastify() fastify.register(cors, { origin: '' }) - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/', headers: { origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 500) - t.same(res.json(), { statusCode: 500, error: 'Internal Server Error', message: 'Invalid CORS origin option' }) - t.same(res.headers, { - 'content-length': '89', - 'content-type': 'application/json; charset=utf-8', - connection: 'keep-alive' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 500) + t.assert.deepStrictEqual(res.json(), { statusCode: 500, error: 'Internal Server Error', message: 'Invalid CORS origin option' }) + const actualHeaders = { + 'content-length': res.headers['content-length'], + 'content-type': res.headers['content-type'], + connection: res.headers.connection + } + t.assert.deepStrictEqual(actualHeaders, { + 'content-length': '89', + 'content-type': 'application/json; charset=utf-8', + connection: 'keep-alive' }) }) -test('Allow only request from a specific origin', t => { +test('Allow only request from a specific origin', async t => { t.plan(5) const fastify = Fastify() @@ -645,23 +727,22 @@ test('Allow only request from a specific origin', t => { reply.send('ok') }) - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/', headers: { origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - 'access-control-allow-origin': 'other.io' - }) - t.notMatch(res.headers, { vary: 'Origin' }) }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + t.assert.deepStrictEqual(res.headers['access-control-allow-origin'], + 'other.io' + ) + t.assert.notDeepEqual(res.headers, { vary: 'Origin' }) }) -test('Allow only request from multiple specific origin', t => { +test('Allow only request from multiple specific origin', async t => { t.plan(9) const fastify = Fastify() @@ -671,38 +752,40 @@ test('Allow only request from multiple specific origin', t => { reply.send('ok') }) - fastify.inject({ + let res = await fastify.inject({ method: 'GET', url: '/', headers: { origin: 'other.io' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - 'access-control-allow-origin': 'other.io', - vary: 'Origin' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': 'other.io', + vary: 'Origin' }) - fastify.inject({ + res = await fastify.inject({ method: 'GET', url: '/', headers: { origin: 'foo.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - vary: 'Origin' - }) - t.equal(res.headers['access-control-allow-origin'], undefined) }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + t.assert.deepStrictEqual(res.headers.vary, + 'Origin' + ) + t.assert.strictEqual(res.headers['access-control-allow-origin'], undefined) }) -test('Allow only request from a specific origin using regex', t => { +test('Allow only request from a specific origin using regex', async t => { t.plan(8) const fastify = Fastify() @@ -716,24 +799,27 @@ test('Allow only request from a specific origin using regex', t => { // different results with global (e.g. /g) regexes. Therefore, check this // twice to check consistency for (let i = 0; i < 2; i++) { - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/', headers: { origin: 'https://www.example.com/' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - 'access-control-allow-origin': 'https://www.example.com/', - vary: 'Origin' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': 'https://www.example.com/', + vary: 'Origin' }) } }) -test('Disable preflight', t => { +test('Disable preflight', async t => { t.plan(7) const fastify = Fastify() @@ -743,33 +829,31 @@ test('Disable preflight', t => { reply.send('ok') }) - fastify.inject({ + let res = await fastify.inject({ method: 'OPTIONS', url: '/hello' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 404) - t.match(res.headers, { - 'access-control-allow-origin': '*' - }) }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 404) + t.assert.strictEqual(res.headers['access-control-allow-origin'], + '*' + ) - fastify.inject({ + res = await fastify.inject({ method: 'GET', url: '/' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - 'access-control-allow-origin': '*' - }) }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + t.assert.strictEqual(res.headers['access-control-allow-origin'], + '*' + ) }) -test('Should always add vary header to `Origin` for reflected origin', t => { +test('Should always add vary header to `Origin` for reflected origin', async t => { t.plan(12) const fastify = Fastify() @@ -780,53 +864,50 @@ test('Should always add vary header to `Origin` for reflected origin', t => { }) // Invalid Preflight - fastify.inject({ + let res = await fastify.inject({ method: 'OPTIONS', url: '/' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 400) - t.equal(res.payload, 'Invalid Preflight Request') - t.match(res.headers, { - vary: 'Origin' - }) }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 400) + t.assert.strictEqual(res.payload, 'Invalid Preflight Request') + t.assert.strictEqual(res.headers.vary, + 'Origin' + ) // Valid Preflight - fastify.inject({ + res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - vary: 'Origin' - }) }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + t.assert.strictEqual(res.headers.vary, + 'Origin, Access-Control-Request-Headers' + ) // Other Route - fastify.inject({ + res = await fastify.inject({ method: 'GET', url: '/' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - vary: 'Origin' - }) }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + t.assert.strictEqual(res.headers.vary, + 'Origin' + ) }) -test('Should always add vary header to `Origin` for reflected origin (vary is array)', t => { +test('Should always add vary header to `Origin` for reflected origin (vary is array)', async t => { t.plan(4) const fastify = Fastify() @@ -840,21 +921,20 @@ test('Should always add vary header to `Origin` for reflected origin (vary is ar reply.send('ok') }) - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - vary: 'foo, bar, Origin' - }) }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + t.assert.strictEqual(res.headers.vary, + 'foo, bar, Origin' + ) }) -test('Allow only request from with specific headers', t => { +test('Allow only request from with specific headers', async t => { t.plan(8) const fastify = Fastify() @@ -867,38 +947,36 @@ test('Allow only request from with specific headers', t => { reply.send('ok') }) - fastify.inject({ + let res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.match(res.headers, { - 'access-control-allow-headers': 'foo' - }) - t.notMatch(res.headers, { vary: 'Origin' }) }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.deepStrictEqual(res.headers['access-control-allow-headers'], + 'foo' + ) + t.assert.notDeepEqual(res.headers.vary, 'Origin') - fastify.inject({ + res = await fastify.inject({ method: 'GET', url: '/' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - 'access-control-expose-headers': 'bar' - }) }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + t.assert.strictEqual(res.headers['access-control-expose-headers'], + 'bar' + ) }) -test('Should support wildcard config /1', t => { +test('Should support wildcard config /1', async t => { t.plan(4) const fastify = Fastify() @@ -908,18 +986,17 @@ test('Should support wildcard config /1', t => { reply.send('ok') }) - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/' - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.equal(res.headers['access-control-allow-origin'], '*') }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + t.assert.strictEqual(res.headers['access-control-allow-origin'], '*') }) -test('Should support wildcard config /2', t => { +test('Should support wildcard config /2', async t => { t.plan(4) const fastify = Fastify() @@ -929,13 +1006,12 @@ test('Should support wildcard config /2', t => { reply.send('ok') }) - fastify.inject({ + const res = await fastify.inject({ method: 'GET', url: '/' - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.equal(res.headers['access-control-allow-origin'], '*') }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + t.assert.strictEqual(res.headers['access-control-allow-origin'], '*') }) diff --git a/test/hooks.test.js b/test/hooks.test.js index 0ccc75b..d988234 100644 --- a/test/hooks.test.js +++ b/test/hooks.test.js @@ -1,15 +1,23 @@ 'use strict' -const { test } = require('tap') +const { test } = require('node:test') const Fastify = require('fastify') const kFastifyContext = require('fastify/lib/symbols').kRouteContext const cors = require('..') +const { setTimeout: sleep } = require('node:timers/promises') test('Should error on invalid hook option', async (t) => { - t.plan(1) + t.plan(3) const fastify = Fastify() - t.rejects(async () => fastify.register(cors, { hook: 'invalid' }), new TypeError('@fastify/cors: Invalid hook option provided.')) + await t.assert.rejects( + async () => fastify.register(cors, { hook: 'invalid' }), + (err) => { + t.assert.strictEqual(err.name, 'TypeError') + t.assert.strictEqual(err.message, '@fastify/cors: Invalid hook option provided.') + return true + } + ) }) test('Should set hook onRequest if hook option is not set', async (t) => { @@ -20,13 +28,13 @@ test('Should set hook onRequest if hook option is not set', async (t) => { fastify.register(cors) fastify.addHook('onResponse', (request, reply, done) => { - t.equal(request[kFastifyContext].onError, null) - t.equal(request[kFastifyContext].onRequest.length, 1) - t.equal(request[kFastifyContext].onSend, null) - t.equal(request[kFastifyContext].preHandler, null) - t.equal(request[kFastifyContext].preParsing, null) - t.equal(request[kFastifyContext].preSerialization, null) - t.equal(request[kFastifyContext].preValidation, null) + t.assert.strictEqual(request[kFastifyContext].onError, null) + t.assert.strictEqual(request[kFastifyContext].onRequest.length, 1) + t.assert.strictEqual(request[kFastifyContext].onSend, null) + t.assert.strictEqual(request[kFastifyContext].preHandler, null) + t.assert.strictEqual(request[kFastifyContext].preParsing, null) + t.assert.strictEqual(request[kFastifyContext].preSerialization, null) + t.assert.strictEqual(request[kFastifyContext].preValidation, null) done() }) @@ -41,9 +49,12 @@ test('Should set hook onRequest if hook option is not set', async (t) => { url: '/' }) delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeader = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'] + } + t.assert.deepStrictEqual(actualHeader, { 'access-control-allow-origin': '*' }) }) @@ -58,13 +69,13 @@ test('Should set hook onRequest if hook option is set to onRequest', async (t) = }) fastify.addHook('onResponse', (request, reply, done) => { - t.equal(request[kFastifyContext].onError, null) - t.equal(request[kFastifyContext].onRequest.length, 1) - t.equal(request[kFastifyContext].onSend, null) - t.equal(request[kFastifyContext].preHandler, null) - t.equal(request[kFastifyContext].preParsing, null) - t.equal(request[kFastifyContext].preSerialization, null) - t.equal(request[kFastifyContext].preValidation, null) + t.assert.strictEqual(request[kFastifyContext].onError, null) + t.assert.strictEqual(request[kFastifyContext].onRequest.length, 1) + t.assert.strictEqual(request[kFastifyContext].onSend, null) + t.assert.strictEqual(request[kFastifyContext].preHandler, null) + t.assert.strictEqual(request[kFastifyContext].preParsing, null) + t.assert.strictEqual(request[kFastifyContext].preSerialization, null) + t.assert.strictEqual(request[kFastifyContext].preValidation, null) done() }) @@ -79,9 +90,12 @@ test('Should set hook onRequest if hook option is set to onRequest', async (t) = url: '/' }) delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeader = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'] + } + t.assert.deepStrictEqual(actualHeader, { 'access-control-allow-origin': '*' }) }) @@ -96,13 +110,13 @@ test('Should set hook preParsing if hook option is set to preParsing', async (t) }) fastify.addHook('onResponse', (request, reply, done) => { - t.equal(request[kFastifyContext].onError, null) - t.equal(request[kFastifyContext].onRequest, null) - t.equal(request[kFastifyContext].onSend, null) - t.equal(request[kFastifyContext].preHandler, null) - t.equal(request[kFastifyContext].preParsing.length, 1) - t.equal(request[kFastifyContext].preSerialization, null) - t.equal(request[kFastifyContext].preValidation, null) + t.assert.strictEqual(request[kFastifyContext].onError, null) + t.assert.strictEqual(request[kFastifyContext].onRequest, null) + t.assert.strictEqual(request[kFastifyContext].onSend, null) + t.assert.strictEqual(request[kFastifyContext].preHandler, null) + t.assert.strictEqual(request[kFastifyContext].preParsing.length, 1) + t.assert.strictEqual(request[kFastifyContext].preSerialization, null) + t.assert.strictEqual(request[kFastifyContext].preValidation, null) done() }) @@ -117,12 +131,15 @@ test('Should set hook preParsing if hook option is set to preParsing', async (t) url: '/' }) delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeader = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'] + } + t.assert.deepStrictEqual(actualHeader, { 'access-control-allow-origin': '*' }) - t.notMatch(res.headers, { vary: 'Origin' }) + t.assert.notStrictEqual(res.headers.vary, 'Origin') }) test('Should set hook preValidation if hook option is set to preValidation', async (t) => { @@ -135,13 +152,13 @@ test('Should set hook preValidation if hook option is set to preValidation', asy }) fastify.addHook('onResponse', (request, reply, done) => { - t.equal(request[kFastifyContext].onError, null) - t.equal(request[kFastifyContext].onRequest, null) - t.equal(request[kFastifyContext].onSend, null) - t.equal(request[kFastifyContext].preHandler, null) - t.equal(request[kFastifyContext].preParsing, null) - t.equal(request[kFastifyContext].preSerialization, null) - t.equal(request[kFastifyContext].preValidation.length, 1) + t.assert.strictEqual(request[kFastifyContext].onError, null) + t.assert.strictEqual(request[kFastifyContext].onRequest, null) + t.assert.strictEqual(request[kFastifyContext].onSend, null) + t.assert.strictEqual(request[kFastifyContext].preHandler, null) + t.assert.strictEqual(request[kFastifyContext].preParsing, null) + t.assert.strictEqual(request[kFastifyContext].preSerialization, null) + t.assert.strictEqual(request[kFastifyContext].preValidation.length, 1) done() }) @@ -156,12 +173,15 @@ test('Should set hook preValidation if hook option is set to preValidation', asy url: '/' }) delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeader = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'] + } + t.assert.deepStrictEqual(actualHeader, { 'access-control-allow-origin': '*' }) - t.notMatch(res.headers, { vary: 'Origin' }) + t.assert.notStrictEqual(res.headers.vary, 'Origin') }) test('Should set hook preParsing if hook option is set to preParsing', async (t) => { @@ -174,13 +194,13 @@ test('Should set hook preParsing if hook option is set to preParsing', async (t) }) fastify.addHook('onResponse', (request, reply, done) => { - t.equal(request[kFastifyContext].onError, null) - t.equal(request[kFastifyContext].onRequest, null) - t.equal(request[kFastifyContext].onSend, null) - t.equal(request[kFastifyContext].preHandler, null) - t.equal(request[kFastifyContext].preParsing.length, 1) - t.equal(request[kFastifyContext].preSerialization, null) - t.equal(request[kFastifyContext].preValidation, null) + t.assert.strictEqual(request[kFastifyContext].onError, null) + t.assert.strictEqual(request[kFastifyContext].onRequest, null) + t.assert.strictEqual(request[kFastifyContext].onSend, null) + t.assert.strictEqual(request[kFastifyContext].preHandler, null) + t.assert.strictEqual(request[kFastifyContext].preParsing.length, 1) + t.assert.strictEqual(request[kFastifyContext].preSerialization, null) + t.assert.strictEqual(request[kFastifyContext].preValidation, null) done() }) @@ -195,12 +215,15 @@ test('Should set hook preParsing if hook option is set to preParsing', async (t) url: '/' }) delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeader = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'] + } + t.assert.deepStrictEqual(actualHeader, { 'access-control-allow-origin': '*' }) - t.notMatch(res.headers, { vary: 'Origin' }) + t.assert.notStrictEqual(res.headers.vary, 'Origin') }) test('Should set hook preHandler if hook option is set to preHandler', async (t) => { @@ -213,13 +236,13 @@ test('Should set hook preHandler if hook option is set to preHandler', async (t) }) fastify.addHook('onResponse', (request, reply, done) => { - t.equal(request[kFastifyContext].onError, null) - t.equal(request[kFastifyContext].onRequest, null) - t.equal(request[kFastifyContext].onSend, null) - t.equal(request[kFastifyContext].preHandler.length, 1) - t.equal(request[kFastifyContext].preParsing, null) - t.equal(request[kFastifyContext].preSerialization, null) - t.equal(request[kFastifyContext].preValidation, null) + t.assert.strictEqual(request[kFastifyContext].onError, null) + t.assert.strictEqual(request[kFastifyContext].onRequest, null) + t.assert.strictEqual(request[kFastifyContext].onSend, null) + t.assert.strictEqual(request[kFastifyContext].preHandler.length, 1) + t.assert.strictEqual(request[kFastifyContext].preParsing, null) + t.assert.strictEqual(request[kFastifyContext].preSerialization, null) + t.assert.strictEqual(request[kFastifyContext].preValidation, null) done() }) @@ -234,12 +257,15 @@ test('Should set hook preHandler if hook option is set to preHandler', async (t) url: '/' }) delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeader = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'] + } + t.assert.deepStrictEqual(actualHeader, { 'access-control-allow-origin': '*' }) - t.notMatch(res.headers, { vary: 'Origin' }) + t.assert.notStrictEqual(res.headers.vary, 'Origin') }) test('Should set hook onSend if hook option is set to onSend', async (t) => { @@ -252,13 +278,13 @@ test('Should set hook onSend if hook option is set to onSend', async (t) => { }) fastify.addHook('onResponse', (request, reply, done) => { - t.equal(request[kFastifyContext].onError, null) - t.equal(request[kFastifyContext].onRequest, null) - t.equal(request[kFastifyContext].onSend.length, 1) - t.equal(request[kFastifyContext].preHandler, null) - t.equal(request[kFastifyContext].preParsing, null) - t.equal(request[kFastifyContext].preSerialization, null) - t.equal(request[kFastifyContext].preValidation, null) + t.assert.strictEqual(request[kFastifyContext].onError, null) + t.assert.strictEqual(request[kFastifyContext].onRequest, null) + t.assert.strictEqual(request[kFastifyContext].onSend.length, 1) + t.assert.strictEqual(request[kFastifyContext].preHandler, null) + t.assert.strictEqual(request[kFastifyContext].preParsing, null) + t.assert.strictEqual(request[kFastifyContext].preSerialization, null) + t.assert.strictEqual(request[kFastifyContext].preValidation, null) done() }) @@ -273,12 +299,15 @@ test('Should set hook onSend if hook option is set to onSend', async (t) => { url: '/' }) delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeader = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'] + } + t.assert.deepStrictEqual(actualHeader, { 'access-control-allow-origin': '*' }) - t.notMatch(res.headers, { vary: 'Origin' }) + t.assert.notStrictEqual(res.headers.vary, 'Origin') }) test('Should set hook preSerialization if hook option is set to preSerialization', async (t) => { @@ -291,13 +320,13 @@ test('Should set hook preSerialization if hook option is set to preSerialization }) fastify.addHook('onResponse', (request, reply, done) => { - t.equal(request[kFastifyContext].onError, null) - t.equal(request[kFastifyContext].onRequest, null) - t.equal(request[kFastifyContext].onSend, null) - t.equal(request[kFastifyContext].preHandler, null) - t.equal(request[kFastifyContext].preParsing, null) - t.equal(request[kFastifyContext].preSerialization.length, 1) - t.equal(request[kFastifyContext].preValidation, null) + t.assert.strictEqual(request[kFastifyContext].onError, null) + t.assert.strictEqual(request[kFastifyContext].onRequest, null) + t.assert.strictEqual(request[kFastifyContext].onSend, null) + t.assert.strictEqual(request[kFastifyContext].preHandler, null) + t.assert.strictEqual(request[kFastifyContext].preParsing, null) + t.assert.strictEqual(request[kFastifyContext].preSerialization.length, 1) + t.assert.strictEqual(request[kFastifyContext].preValidation, null) done() }) @@ -312,15 +341,18 @@ test('Should set hook preSerialization if hook option is set to preSerialization url: '/' }) delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, '{"nonString":true}') - t.match(res.headers, { + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, '{"nonString":true}') + const actualHeader = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'] + } + t.assert.deepStrictEqual(actualHeader, { 'access-control-allow-origin': '*' }) - t.notMatch(res.headers, { vary: 'Origin' }) + t.assert.notStrictEqual(res.headers.vary, 'Origin') }) -test('Should support custom hook with dynamic config', t => { +test('Should support custom hook with dynamic config', async t => { t.plan(16) const configs = [{ @@ -341,20 +373,20 @@ test('Should support custom hook with dynamic config', t => { const fastify = Fastify() let requestId = 0 - const configDelegation = function (req, cb) { + const configDelegation = async function (req) { // request should have id - t.ok(req.id) + t.assert.ok(req.id) // request should not have send - t.notOk(req.send) + t.assert.ifError(req.send) const config = configs[requestId] requestId++ if (config) { - cb(null, config) + return Promise.resolve(config) } else { - cb(new Error('ouch')) + return Promise.reject(new Error('ouch')) } } - fastify.register(cors, { + await fastify.register(cors, { hook: 'preHandler', delegator: configDelegation }) @@ -363,61 +395,75 @@ test('Should support custom hook with dynamic config', t => { reply.send('ok') }) - fastify.inject({ + let res = await fastify.inject({ method: 'GET', url: '/' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - 'access-control-allow-origin': 'example.com', - 'access-control-allow-credentials': 'true', - 'access-control-expose-headers': 'foo, bar', - 'content-length': '2', - vary: 'Origin' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + let actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-credentials': res.headers['access-control-allow-credentials'], + 'access-control-expose-headers': res.headers['access-control-expose-headers'], + 'content-length': res.headers['content-length'], + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': 'example.com', + 'access-control-allow-credentials': 'true', + 'access-control-expose-headers': 'foo, bar', + 'content-length': '2', + vary: 'Origin' }) - fastify.inject({ + res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': 'sample.com', - 'access-control-allow-credentials': 'true', - 'access-control-expose-headers': 'zoo, bar', - 'access-control-allow-methods': 'GET', - 'access-control-allow-headers': 'baz, foo', - 'access-control-max-age': '321', - 'content-length': '0', - vary: 'Origin' - }) }) - - fastify.inject({ + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-credentials': res.headers['access-control-allow-credentials'], + 'access-control-expose-headers': res.headers['access-control-expose-headers'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + 'access-control-allow-headers': res.headers['access-control-allow-headers'], + 'access-control-max-age': res.headers['access-control-max-age'], + 'content-length': res.headers['content-length'], + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': 'sample.com', + 'access-control-allow-credentials': 'true', + 'access-control-expose-headers': 'zoo, bar', + 'access-control-allow-methods': 'GET', + 'access-control-allow-headers': 'baz, foo', + 'access-control-max-age': '321', + 'content-length': '0', + vary: 'Origin' + }) + + res = await fastify.inject({ method: 'GET', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 500) }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 500) }) -test('Should support custom hook with dynamic config (callback)', t => { +test('Should support custom hook with dynamic config (callback)', async t => { t.plan(16) const configs = [{ @@ -440,9 +486,9 @@ test('Should support custom hook with dynamic config (callback)', t => { let requestId = 0 const configDelegation = function (req, cb) { // request should have id - t.ok(req.id) + t.assert.ok(req.id) // request should not have send - t.notOk(req.send) + t.assert.ifError(req.send) const config = configs[requestId] requestId++ if (config) { @@ -464,11 +510,18 @@ test('Should support custom hook with dynamic config (callback)', t => { method: 'GET', url: '/' }, (err, res) => { - t.error(err) + t.assert.ifError(err) delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-credentials': res.headers['access-control-allow-credentials'], + 'access-control-expose-headers': res.headers['access-control-expose-headers'], + 'content-length': res.headers['content-length'], + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders, { 'access-control-allow-origin': 'example.com', 'access-control-allow-credentials': 'true', 'access-control-expose-headers': 'foo, bar', @@ -485,11 +538,21 @@ test('Should support custom hook with dynamic config (callback)', t => { origin: 'example.com' } }, (err, res) => { - t.error(err) + t.assert.ifError(err) delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-credentials': res.headers['access-control-allow-credentials'], + 'access-control-expose-headers': res.headers['access-control-expose-headers'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + 'access-control-allow-headers': res.headers['access-control-allow-headers'], + 'access-control-max-age': res.headers['access-control-max-age'], + 'content-length': res.headers['content-length'], + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders, { 'access-control-allow-origin': 'sample.com', 'access-control-allow-credentials': 'true', 'access-control-expose-headers': 'zoo, bar', @@ -509,12 +572,13 @@ test('Should support custom hook with dynamic config (callback)', t => { origin: 'example.com' } }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 500) + t.assert.ifError(err) + t.assert.strictEqual(res.statusCode, 500) }) + await sleep() }) -test('Should support custom hook with dynamic config (Promise)', t => { +test('Should support custom hook with dynamic config (Promise)', async t => { t.plan(16) const configs = [{ @@ -535,11 +599,11 @@ test('Should support custom hook with dynamic config (Promise)', t => { const fastify = Fastify() let requestId = 0 - const configDelegation = function (req) { + const configDelegation = async function (req) { // request should have id - t.ok(req.id) + t.assert.ok(req.id) // request should not have send - t.notOk(req.send) + t.assert.ifError(req.send) const config = configs[requestId] requestId++ if (config) { @@ -549,7 +613,7 @@ test('Should support custom hook with dynamic config (Promise)', t => { } } - fastify.register(cors, { + await fastify.register(cors, { hook: 'preParsing', delegator: configDelegation }) @@ -558,61 +622,76 @@ test('Should support custom hook with dynamic config (Promise)', t => { reply.send('ok') }) - fastify.inject({ + let res = await fastify.inject({ method: 'GET', url: '/' - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - 'access-control-allow-origin': 'example.com', - 'access-control-allow-credentials': 'true', - 'access-control-expose-headers': 'foo, bar', - 'content-length': '2', - vary: 'Origin' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + let actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-credentials': res.headers['access-control-allow-credentials'], + 'access-control-expose-headers': res.headers['access-control-expose-headers'], + 'content-length': res.headers['content-length'], + vary: res.headers.vary + } + + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': 'example.com', + 'access-control-allow-credentials': 'true', + 'access-control-expose-headers': 'foo, bar', + 'content-length': '2', + vary: 'Origin' }) - fastify.inject({ + res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': 'sample.com', - 'access-control-allow-credentials': 'true', - 'access-control-expose-headers': 'zoo, bar', - 'access-control-allow-methods': 'GET', - 'access-control-allow-headers': 'baz, foo', - 'access-control-max-age': '321', - 'content-length': '0', - vary: 'Origin' - }) }) - - fastify.inject({ + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-credentials': res.headers['access-control-allow-credentials'], + 'access-control-expose-headers': res.headers['access-control-expose-headers'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + 'access-control-allow-headers': res.headers['access-control-allow-headers'], + 'access-control-max-age': res.headers['access-control-max-age'], + 'content-length': res.headers['content-length'], + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': 'sample.com', + 'access-control-allow-credentials': 'true', + 'access-control-expose-headers': 'zoo, bar', + 'access-control-allow-methods': 'GET', + 'access-control-allow-headers': 'baz, foo', + 'access-control-max-age': '321', + 'content-length': '0', + vary: 'Origin' + }) + + res = await fastify.inject({ method: 'GET', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 500) }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 500) }) -test('Should support custom hook with dynamic config (Promise), but should error /1', t => { +test('Should support custom hook with dynamic config (Promise), but should error /1', async t => { t.plan(6) const fastify = Fastify() @@ -620,7 +699,7 @@ test('Should support custom hook with dynamic config (Promise), but should error return false } - fastify.register(cors, { + await fastify.register(cors, { hook: 'preParsing', delegator: configDelegation }) @@ -629,37 +708,38 @@ test('Should support custom hook with dynamic config (Promise), but should error reply.send('ok') }) - fastify.inject({ + let res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 500) - t.equal(res.payload, '{"statusCode":500,"error":"Internal Server Error","message":"Invalid CORS origin option"}') - t.match(res.headers, { - 'content-length': '89' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 500) + t.assert.strictEqual(res.payload, '{"statusCode":500,"error":"Internal Server Error","message":"Invalid CORS origin option"}') + const actualHeaders = { + 'content-length': res.headers['content-length'] + } + t.assert.deepStrictEqual(actualHeaders, { + 'content-length': '89' }) - fastify.inject({ + res = await fastify.inject({ method: 'GET', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 500) }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 500) }) -test('Should support custom hook with dynamic config (Promise), but should error /2', t => { +test('Should support custom hook with dynamic config (Promise), but should error /2', async t => { t.plan(6) const fastify = Fastify() @@ -667,7 +747,7 @@ test('Should support custom hook with dynamic config (Promise), but should error return false } - fastify.register(cors, { + await fastify.register(cors, { delegator: configDelegation }) @@ -675,32 +755,33 @@ test('Should support custom hook with dynamic config (Promise), but should error reply.send('ok') }) - fastify.inject({ + let res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 500) - t.equal(res.payload, '{"statusCode":500,"error":"Internal Server Error","message":"Invalid CORS origin option"}') - t.match(res.headers, { - 'content-length': '89' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 500) + t.assert.strictEqual(res.payload, '{"statusCode":500,"error":"Internal Server Error","message":"Invalid CORS origin option"}') + const actualHeaders = { + 'content-length': res.headers['content-length'] + } + t.assert.deepStrictEqual(actualHeaders, { + 'content-length': '89' }) - fastify.inject({ + res = await fastify.inject({ method: 'GET', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 500) }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 500) }) diff --git a/test/preflight.test.js b/test/preflight.test.js index b8049ce..0c921ff 100644 --- a/test/preflight.test.js +++ b/test/preflight.test.js @@ -1,43 +1,48 @@ 'use strict' -const { test } = require('tap') +const { test } = require('node:test') const Fastify = require('fastify') const cors = require('../') -test('Should reply to preflight requests', t => { +test('Should reply to preflight requests', async t => { t.plan(4) const fastify = Fastify() - fastify.register(cors) + await fastify.register(cors) - fastify.inject({ + const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': '*', - 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', - vary: 'Access-Control-Request-Headers', - 'content-length': '0' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + vary: res.headers.vary, + 'content-length': res.headers['content-length'] + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': '*', + 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', + vary: 'Access-Control-Request-Headers', + 'content-length': '0' }) }) -test('Should add access-control-allow-headers to response if preflight req has access-control-request-headers', t => { +test('Should add access-control-allow-headers to response if preflight req has access-control-request-headers', async t => { t.plan(4) const fastify = Fastify() - fastify.register(cors) + await fastify.register(cors) - fastify.inject({ + const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { @@ -46,390 +51,438 @@ test('Should add access-control-allow-headers to response if preflight req has a origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': '*', - 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', - 'access-control-allow-headers': 'x-requested-with', - vary: 'Access-Control-Request-Headers', - 'content-length': '0' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + 'access-control-allow-headers': res.headers['access-control-allow-headers'], + vary: res.headers.vary, + 'content-length': res.headers['content-length'] + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': '*', + 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', + 'access-control-allow-headers': 'x-requested-with', + vary: 'Access-Control-Request-Headers', + 'content-length': '0' }) }) -test('Should reply to preflight requests with custom status code', t => { +test('Should reply to preflight requests with custom status code', async t => { t.plan(4) const fastify = Fastify() - fastify.register(cors, { optionsSuccessStatus: 200 }) + await fastify.register(cors, { optionsSuccessStatus: 200 }) - fastify.inject({ + const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': '*', - 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', - vary: 'Access-Control-Request-Headers', - 'content-length': '0' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, '') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + vary: res.headers.vary, + 'content-length': res.headers['content-length'] + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': '*', + 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', + vary: 'Access-Control-Request-Headers', + 'content-length': '0' }) }) -test('Should be able to override preflight response with a route', t => { +test('Should be able to override preflight response with a route', async t => { t.plan(5) const fastify = Fastify() - fastify.register(cors, { preflightContinue: true }) + await fastify.register(cors, { preflightContinue: true }) fastify.options('/', (req, reply) => { reply.send('ok') }) - fastify.inject({ + const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - // Only the base cors headers and no preflight headers - 'access-control-allow-origin': '*' - }) - t.notMatch(res.headers, { vary: 'Origin' }) }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'] + } + t.assert.deepStrictEqual(actualHeaders, { + // Only the base cors headers and no preflight headers + 'access-control-allow-origin': '*' + }) + t.assert.notStrictEqual(res.headers.vary, 'Origin') }) -test('Should reply to all options requests', t => { +test('Should reply to all options requests', async t => { t.plan(4) const fastify = Fastify() - fastify.register(cors) + await fastify.register(cors) - fastify.inject({ + const res = await fastify.inject({ method: 'OPTIONS', url: '/hello', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': '*', - 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', - vary: 'Access-Control-Request-Headers', - 'content-length': '0' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + vary: res.headers.vary, + 'content-length': res.headers['content-length'] + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': '*', + 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', + vary: 'Access-Control-Request-Headers', + 'content-length': '0' }) }) -test('Should support a prefix for preflight requests', t => { +test('Should support a prefix for preflight requests', async t => { t.plan(6) const fastify = Fastify() - fastify.register((instance, opts, next) => { + await fastify.register((instance, opts, next) => { instance.register(cors) next() }, { prefix: '/subsystem' }) - fastify.inject({ + let res = await fastify.inject({ method: 'OPTIONS', url: '/hello' - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 404) }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 404) - fastify.inject({ + res = await fastify.inject({ method: 'OPTIONS', url: '/subsystem/hello', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': '*', - 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', - vary: 'Access-Control-Request-Headers', - 'content-length': '0' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + vary: res.headers.vary, + 'content-length': res.headers['content-length'] + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': '*', + 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', + vary: 'Access-Control-Request-Headers', + 'content-length': '0' }) }) -test('hide options route by default', t => { +test('hide options route by default', async t => { t.plan(2) const fastify = Fastify() fastify.addHook('onRoute', (route) => { if (route.method === 'OPTIONS' && route.url === '*') { - t.equal(route.schema.hide, true) + t.assert.strictEqual(route.schema.hide, true) } }) - fastify.register(cors) + await fastify.register(cors) - fastify.ready(err => { - t.error(err) - }) + const ready = await fastify.ready() + t.assert.ok(ready) }) -test('show options route', t => { +test('show options route', async t => { t.plan(2) const fastify = Fastify() fastify.addHook('onRoute', (route) => { if (route.method === 'OPTIONS' && route.url === '*') { - t.equal(route.schema.hide, false) + t.assert.strictEqual(route.schema.hide, false) } }) - fastify.register(cors, { hideOptionsRoute: false }) + await fastify.register(cors, { hideOptionsRoute: false }) - fastify.ready(err => { - t.error(err) - }) + const ready = await fastify.ready() + t.assert.ok(ready) }) -test('Allow only request from with specific methods', t => { +test('Allow only request from with specific methods', async t => { t.plan(4) const fastify = Fastify() - fastify.register(cors, { methods: ['GET', 'POST'] }) + await fastify.register(cors, { methods: ['GET', 'POST'] }) - fastify.inject({ + const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.match(res.headers, { - 'access-control-allow-methods': 'GET, POST' - }) - t.notMatch(res.headers, { vary: 'Origin' }) }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + const actualHeaders = { + 'access-control-allow-methods': res.headers['access-control-allow-methods'] + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-methods': 'GET, POST' + }) + t.assert.notStrictEqual(res.headers.vary, 'Origin') }) -test('Should reply with 400 error to OPTIONS requests missing origin header when default strictPreflight', t => { +test('Should reply with 400 error to OPTIONS requests missing origin header when default strictPreflight', async t => { t.plan(3) const fastify = Fastify() - fastify.register(cors) + await fastify.register(cors) - fastify.inject({ + const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET' } - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 400) - t.equal(res.payload, 'Invalid Preflight Request') }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 400) + t.assert.strictEqual(res.payload, 'Invalid Preflight Request') }) -test('Should reply with 400 to OPTIONS requests when missing Access-Control-Request-Method header when default strictPreflight', t => { +test('Should reply with 400 to OPTIONS requests when missing Access-Control-Request-Method header when default strictPreflight', async t => { t.plan(3) const fastify = Fastify() - fastify.register(cors, { + await fastify.register(cors, { strictPreflight: true }) - fastify.inject({ + const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { origin: 'example.com' } - }, (err, res) => { - t.error(err) - t.equal(res.statusCode, 400) - t.equal(res.payload, 'Invalid Preflight Request') }) + t.assert.ok(res) + t.assert.strictEqual(res.statusCode, 400) + t.assert.strictEqual(res.payload, 'Invalid Preflight Request') }) -test('Should reply to all preflight requests when strictPreflight is disabled', t => { +test('Should reply to all preflight requests when strictPreflight is disabled', async t => { t.plan(4) const fastify = Fastify() - fastify.register(cors, { strictPreflight: false }) + await fastify.register(cors, { strictPreflight: false }) - fastify.inject({ + const res = await fastify.inject({ method: 'OPTIONS', url: '/' // No access-control-request-method or origin headers - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': '*', - 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', - vary: 'Access-Control-Request-Headers', - 'content-length': '0' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + vary: res.headers.vary, + 'content-length': res.headers['content-length'] + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': '*', + 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', + vary: 'Access-Control-Request-Headers', + 'content-length': '0' }) }) -test('Default empty 200 response with preflightContinue on OPTIONS routes', t => { +test('Default empty 200 response with preflightContinue on OPTIONS routes', async t => { t.plan(4) const fastify = Fastify() - fastify.register(cors, { preflightContinue: true }) + await fastify.register(cors, { preflightContinue: true }) - fastify.inject({ + const res = await fastify.inject({ method: 'OPTIONS', url: '/doesnotexist', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': '*', - 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', - vary: 'Access-Control-Request-Headers' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, '') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': '*', + 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', + vary: 'Access-Control-Request-Headers' }) }) -test('Can override preflight response with preflightContinue', t => { +test('Can override preflight response with preflightContinue', async t => { t.plan(4) const fastify = Fastify() - fastify.register(cors, { preflightContinue: true }) + await fastify.register(cors, { preflightContinue: true }) fastify.options('/', (req, reply) => { reply.send('ok') }) - fastify.inject({ + const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 200) - t.equal(res.payload, 'ok') - t.match(res.headers, { - 'access-control-allow-origin': '*', - 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', - vary: 'Access-Control-Request-Headers' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 200) + t.assert.strictEqual(res.payload, 'ok') + const actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + vary: res.headers.vary + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': '*', + 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', + vary: 'Access-Control-Request-Headers' }) }) -test('Should support ongoing prefix ', t => { +test('Should support ongoing prefix ', async t => { t.plan(12) const fastify = Fastify() - fastify.register(async (instance) => { + await fastify.register(async (instance) => { instance.register(cors) }, { prefix: '/prefix' }) // support prefixed route - fastify.inject({ + let res = await fastify.inject({ method: 'OPTIONS', url: '/prefix', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': '*', - 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', - vary: 'Access-Control-Request-Headers', - 'content-length': '0' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + let actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + vary: res.headers.vary, + 'content-length': res.headers['content-length'] + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': '*', + 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', + vary: 'Access-Control-Request-Headers', + 'content-length': '0' }) // support prefixed route without / continue - fastify.inject({ + res = await fastify.inject({ method: 'OPTIONS', url: '/prefixfoo', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': '*', - 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', - vary: 'Access-Control-Request-Headers', - 'content-length': '0' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + vary: res.headers.vary, + 'content-length': res.headers['content-length'] + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': '*', + 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', + vary: 'Access-Control-Request-Headers', + 'content-length': '0' }) // support prefixed route with / continue - fastify.inject({ + res = await fastify.inject({ method: 'OPTIONS', url: '/prefix/foo', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } - }, (err, res) => { - t.error(err) - delete res.headers.date - t.equal(res.statusCode, 204) - t.equal(res.payload, '') - t.match(res.headers, { - 'access-control-allow-origin': '*', - 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', - vary: 'Access-Control-Request-Headers', - 'content-length': '0' - }) + }) + t.assert.ok(res) + delete res.headers.date + t.assert.strictEqual(res.statusCode, 204) + t.assert.strictEqual(res.payload, '') + actualHeaders = { + 'access-control-allow-origin': res.headers['access-control-allow-origin'], + 'access-control-allow-methods': res.headers['access-control-allow-methods'], + vary: res.headers.vary, + 'content-length': res.headers['content-length'] + } + t.assert.deepStrictEqual(actualHeaders, { + 'access-control-allow-origin': '*', + 'access-control-allow-methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', + vary: 'Access-Control-Request-Headers', + 'content-length': '0' }) }) diff --git a/test/vary.test.js b/test/vary.test.js index dfc0497..ff60101 100644 --- a/test/vary.test.js +++ b/test/vary.test.js @@ -1,10 +1,10 @@ 'use strict' -const test = require('tap').test +const { test } = require('node:test') const createAddFieldnameToVary = require('../vary').createAddFieldnameToVary const parse = require('../vary').parse -test('Should set * even if we set a specific field', t => { +test('Should set * even if we set a specific field', async t => { t.plan(1) const addOriginToVary = createAddFieldnameToVary('Origin') @@ -18,7 +18,7 @@ test('Should set * even if we set a specific field', t => { } addOriginToVary(replyMock) - t.pass() + t.assert.ok(true) // equalivant to tap t.pass() }) test('Should set * even if we set a specific field', t => { @@ -30,8 +30,8 @@ test('Should set * even if we set a specific field', t => { return 'Origin' }, header (name, value) { - t.same(name, 'Vary') - t.same(value, '*') + t.assert.deepStrictEqual(name, 'Vary') + t.assert.deepStrictEqual(value, '*') } } @@ -47,13 +47,13 @@ test('Should set * when field contains a *', t => { return ['Origin', '*', 'Access-Control-Request-Headers'] }, header (name, value) { - t.same(name, 'Vary') - t.same(value, '*') + t.assert.deepStrictEqual(name, 'Vary') + t.assert.deepStrictEqual(value, '*') } } addOriginToVary(replyMock) - t.pass() + t.assert.ok(true) // equalivant to tap t.pass() }) test('Should concat vary values', t => { @@ -65,13 +65,13 @@ test('Should concat vary values', t => { return 'Access-Control-Request-Headers' }, header (name, value) { - t.same(name, 'Vary') - t.same(value, 'Access-Control-Request-Headers, Origin') + t.assert.deepStrictEqual(name, 'Vary') + t.assert.deepStrictEqual(value, 'Access-Control-Request-Headers, Origin') } } addOriginToVary(replyMock) - t.pass() + t.assert.ok(true) // equalivant to tap t.pass() }) test('Should concat vary values ignoring consecutive commas', t => { @@ -83,13 +83,13 @@ test('Should concat vary values ignoring consecutive commas', t => { return ' Access-Control-Request-Headers,Access-Control-Request-Method' }, header (name, value) { - t.same(name, 'Vary') - t.same(value, ' Access-Control-Request-Headers,Access-Control-Request-Method, Origin') + t.assert.deepStrictEqual(name, 'Vary') + t.assert.deepStrictEqual(value, ' Access-Control-Request-Headers,Access-Control-Request-Method, Origin') } } addOriginToVary(replyMock) - t.pass() + t.assert.ok(true) // equalivant to tap t.pass() }) test('Should concat vary values ignoring whitespace', t => { @@ -101,13 +101,13 @@ test('Should concat vary values ignoring whitespace', t => { return ' Access-Control-Request-Headers ,Access-Control-Request-Method' }, header (name, value) { - t.same(name, 'Vary') - t.same(value, ' Access-Control-Request-Headers ,Access-Control-Request-Method, Origin') + t.assert.deepStrictEqual(name, 'Vary') + t.assert.deepStrictEqual(value, ' Access-Control-Request-Headers ,Access-Control-Request-Method, Origin') } } addOriginToVary(replyMock) - t.pass() + t.assert.ok(true) // equalivant to tap t.pass() }) test('Should set the field as value for vary if no vary is defined', t => { @@ -119,8 +119,8 @@ test('Should set the field as value for vary if no vary is defined', t => { return undefined }, header (name, value) { - t.same(name, 'Vary') - t.same(value, 'Origin') + t.assert.deepStrictEqual(name, 'Vary') + t.assert.deepStrictEqual(value, 'Origin') } } @@ -136,8 +136,8 @@ test('Should set * as value for vary if vary contains *', t => { return 'Accept,*' }, header (name, value) { - t.same(name, 'Vary') - t.same(value, '*') + t.assert.deepStrictEqual(name, 'Vary') + t.assert.deepStrictEqual(value, '*') } } @@ -153,8 +153,8 @@ test('Should set Accept-Encoding as value for vary if vary is empty string', t = return '' }, header (name, value) { - t.same(name, 'Vary') - t.same(value, 'Accept-Encoding') + t.assert.deepStrictEqual(name, 'Vary') + t.assert.deepStrictEqual(value, 'Accept-Encoding') } } @@ -171,8 +171,8 @@ test('Should have no issues with values containing dashes', t => { return this.value }, header (name, value) { - t.same(name, 'Vary') - t.same(value, 'Accept-Encoding, X-Foo') + t.assert.deepStrictEqual(name, 'Vary') + t.assert.deepStrictEqual(value, 'Accept-Encoding, X-Foo') this.value = value } } @@ -195,35 +195,43 @@ test('Should ignore the header as value for vary if it is already in vary', t => } addOriginToVary(replyMock) addOriginToVary(replyMock) - t.pass() + + t.assert.ok(true) // equalivant to tap t.pass() }) test('parse', t => { t.plan(18) - t.same(parse(''), []) - t.same(parse('a'), ['a']) - t.same(parse('a,b'), ['a', 'b']) - t.same(parse(' a,b'), ['a', 'b']) - t.same(parse('a,b '), ['a', 'b']) - t.same(parse('a,b,c'), ['a', 'b', 'c']) - t.same(parse('A,b,c'), ['a', 'b', 'c']) - t.same(parse('a,b,c,'), ['a', 'b', 'c']) - t.same(parse('a,b,c, '), ['a', 'b', 'c']) - t.same(parse(',a,b,c'), ['a', 'b', 'c']) - t.same(parse(' ,a,b,c'), ['a', 'b', 'c']) - t.same(parse('a,,b,c'), ['a', 'b', 'c']) - t.same(parse('a,,,b,,c'), ['a', 'b', 'c']) - t.same(parse('a, b,c'), ['a', 'b', 'c']) - t.same(parse('a, b,c'), ['a', 'b', 'c']) - t.same(parse('a, , b,c'), ['a', 'b', 'c']) - t.same(parse('a, , b,c'), ['a', 'b', 'c']) + t.assert.deepStrictEqual(parse(''), []) + t.assert.deepStrictEqual(parse('a'), ['a']) + t.assert.deepStrictEqual(parse('a,b'), ['a', 'b']) + t.assert.deepStrictEqual(parse(' a,b'), ['a', 'b']) + t.assert.deepStrictEqual(parse('a,b '), ['a', 'b']) + t.assert.deepStrictEqual(parse('a,b,c'), ['a', 'b', 'c']) + t.assert.deepStrictEqual(parse('A,b,c'), ['a', 'b', 'c']) + t.assert.deepStrictEqual(parse('a,b,c,'), ['a', 'b', 'c']) + t.assert.deepStrictEqual(parse('a,b,c, '), ['a', 'b', 'c']) + t.assert.deepStrictEqual(parse(',a,b,c'), ['a', 'b', 'c']) + t.assert.deepStrictEqual(parse(' ,a,b,c'), ['a', 'b', 'c']) + t.assert.deepStrictEqual(parse('a,,b,c'), ['a', 'b', 'c']) + t.assert.deepStrictEqual(parse('a,,,b,,c'), ['a', 'b', 'c']) + t.assert.deepStrictEqual(parse('a, b,c'), ['a', 'b', 'c']) + t.assert.deepStrictEqual(parse('a, b,c'), ['a', 'b', 'c']) + t.assert.deepStrictEqual(parse('a, , b,c'), ['a', 'b', 'c']) + t.assert.deepStrictEqual(parse('a, , b,c'), ['a', 'b', 'c']) // one for the cache - t.same(parse('A,b,c'), ['a', 'b', 'c']) + t.assert.deepStrictEqual(parse('A,b,c'), ['a', 'b', 'c']) }) -test('createAddFieldnameToVary', t => { - t.plan(2) - t.same(typeof createAddFieldnameToVary('valid-header'), 'function') - t.throws(() => createAddFieldnameToVary('invalid:header'), TypeError, 'Field contains invalid characters.') +test('createAddFieldnameToVary', async t => { + t.plan(4) + t.assert.strictEqual(typeof createAddFieldnameToVary('valid-header'), 'function') + await t.assert.rejects( + async () => createAddFieldnameToVary('invalid:header'), + (err) => { + t.assert.strictEqual(err.name, 'TypeError') + t.assert.strictEqual(err.message, 'Fieldname contains invalid characters.') + return true + } + ) })