import { Eltro as t, spy, assert} from 'eltro' import { Flaska } from '../flaska.mjs' import { fakeHttp, createReq, createRes } from './helper.mjs' const faker = fakeHttp() t.describe('#requestStart()', function() { t.test('calls on correct events on both req and res', function(cb) { const assertErrorOne = new Error('Erics Birth') const assertErrorTwo = new Error('Contactic Eric') const onReqError = spy() const onResError = spy() const onEnded = spy() const assertReq = createReq({ url: '', a: 1 }) const assertRes = createRes({ b: 2 }) let flaska = new Flaska({}, faker) flaska.onreqerror(onReqError) flaska.onreserror(onResError) flaska.requestEnded = onEnded flaska.requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.strictEqual(assertReq.on.callCount, 1) assert.strictEqual(assertRes.on.callCount, 2) assert.strictEqual(assertRes.on.firstCall[0], 'error') assert.strictEqual(typeof(assertRes.on.firstCall[1]), 'function') assertRes.on.firstCall[1](assertErrorTwo, ctx) assert.strictEqual(onResError.callCount, 1) assert.strictEqual(onResError.firstCall[0], assertErrorTwo) assert.strictEqual(onResError.firstCall[1], ctx) assert.strictEqual(assertRes.on.secondCall[0], 'finish') assert.strictEqual(typeof(assertRes.on.secondCall[1]), 'function') assert.strictEqual(onEnded.callCount, 0) assertRes.on.secondCall[1]() assert.strictEqual(onEnded.callCount, 1) assert.strictEqual(onEnded.firstCall[0], ctx) assert.strictEqual(assertReq.on.firstCall[0], 'error') assert.strictEqual(typeof(assertReq.on.firstCall[1]), 'function') assertReq.on.firstCall[1](assertErrorOne, ctx) assert.strictEqual(onReqError.callCount, 1) assert.strictEqual(onReqError.firstCall[0], assertErrorOne) assert.strictEqual(onReqError.firstCall[1], ctx) }) flaska._beforeCompiled = function(ctx) { throw new Error() } flaska.requestStart(assertReq, assertRes) }) t.test('calls beforeCompiled correctly', function(cb) { const assertError = new Error('test') const assertReq = createReq({ url: '', a: 1 }) const assertRes = createRes({ b: 2 }) let flaska = new Flaska({}, faker) flaska.requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.strictEqual(err, assertError) assert.deepStrictEqual(ctx.state, {}) assert.strictEqual(ctx.req, assertReq) assert.strictEqual(ctx.res, assertRes) }) flaska._beforeCompiled = function(ctx) { assert.strictEqual(ctx.req, assertReq) assert.strictEqual(ctx.res, assertRes) throw assertError } flaska.requestStart(assertReq, assertRes) }) t.test('calls beforeAsyncCompiled correctly if defined', function(cb) { const assertError = new Error('test') const assertReq = createReq({ url: '', a: 1 }) const assertRes = createRes({ b: 2 }) let flaska = new Flaska({}, faker) flaska.compile() flaska._beforeAsyncCompiled = function(ctx) { assert.strictEqual(ctx.req, assertReq) assert.strictEqual(ctx.res, assertRes) return Promise.resolve().then(function() { return Promise.reject(assertError) }) } flaska.requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.strictEqual(err, assertError) assert.deepStrictEqual(ctx.state, {}) assert.strictEqual(ctx.req, assertReq) assert.strictEqual(ctx.res, assertRes) }) flaska.requestStart(assertReq, assertRes) }) t.test('calls correct router with correct url and context', function(cb) { const assertError = new Error('test') const assertMethod = 'test' const assertPath = '/test/me' const assertSearch = '?asdf=test' const assertLog = { info: function() {}, error: function() {} } let flaska = new Flaska({ log: assertLog }, faker) assert.strictEqual(flaska.log, assertLog) flaska.compile() flaska.routers.test = { match: function(path) { assert.strictEqual(path, assertPath) throw assertError } } flaska.requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.strictEqual(err, assertError) assert.strictEqual(ctx.url, assertPath) assert.strictEqual(ctx.search, assertSearch) assert.strictEqual(ctx.method, assertMethod) assert.strictEqual(ctx.status, 200) assert.strictEqual(ctx.body, null) assert.strictEqual(ctx.type, null) assert.strictEqual(ctx.length, null) assert.strictEqual(ctx.log, assertLog) assert.ok(ctx.query) assert.ok(ctx.query.get) assert.ok(ctx.query.set) assert.ok(ctx.query.delete) assert.deepEqual( Object.keys(ctx.headers).sort(), ['Server','X-Content-Type-Options','Content-Security-Policy','Cross-Origin-Opener-Policy','Cross-Origin-Resource-Policy','Cross-Origin-Embedder-Policy','Date'].sort() ) assert.strictEqual(ctx.headers['Server'], 'Flaska') assert.strictEqual(ctx.headers['X-Content-Type-Options'], 'nosniff') assert.strictEqual(ctx.headers['Content-Security-Policy'], `default-src 'self'; style-src 'self' 'unsafe-inline'; img-src * data: blob:; font-src 'self' data:; object-src 'none'; frame-ancestors 'none'`) assert.strictEqual(ctx.headers['Cross-Origin-Opener-Policy'], 'same-origin') assert.strictEqual(ctx.headers['Cross-Origin-Resource-Policy'], 'same-origin') assert.strictEqual(ctx.headers['Cross-Origin-Embedder-Policy'], 'require-corp') assert.ok(new Date(ctx.headers['Date']).getDate()) }) flaska.requestStart(createReq({ url: assertPath + assertSearch, method: assertMethod, }), createRes()) }) t.test('correctly adds default headers', function(cb) { const assertError = new Error('test') const defaultHeaders = { 'Test': 'Asdf', 'Herp': 'Derp', } let flaska = new Flaska({ defaultHeaders: defaultHeaders, }, faker) flaska.compile() flaska.routers.test = { match: function(path) { throw assertError } } flaska.requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.strictEqual(err, assertError) let keys = Object.keys(defaultHeaders) assert.strictEqual(Object.keys(ctx.headers).length, keys.length + 1) for (let key of keys) { assert.strictEqual(ctx.headers[key], defaultHeaders[key]) } assert.ok(ctx.headers['Date']) }) flaska.requestStart(createReq({ url: '/', method: 'test', }), createRes()) }) t.test('calls correct router with correct url and context if beforeAsync', function(cb) { const assertError = new Error('test') const assertMethod = 'test' const assertPath = '/test/me' const assertSearch = '?asdf=test' let calledBefore = false let flaska = new Flaska({}, faker) flaska.compile() flaska._beforeAsyncCompiled = function() { calledBefore = true return Promise.resolve() } flaska.routers.test = { match: function(path) { assert.strictEqual(path, assertPath) throw assertError } } flaska.requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.ok(calledBefore) assert.strictEqual(err, assertError) assert.strictEqual(ctx.url, assertPath) assert.strictEqual(ctx.search, assertSearch) assert.strictEqual(ctx.method, assertMethod) }) flaska.requestStart(createReq({ url: assertPath + assertSearch, method: assertMethod, }), createRes()) }) t.test('calls handlers correctly', function(cb) { const assertError = new Error('test') const assertMiddles = [1, 2] const assertParams = { a: 1, b: 2 } let checkMiddleCtx = null let flaska = new Flaska({}, faker) flaska.compile() flaska.routers.GET.match = function() { return { path: { handlers: assertMiddles, }, params: assertParams, } } flaska.runHandlers = function(ctx, middles, index) { assert.strictEqual(index, 0) assert.strictEqual(middles, assertMiddles) checkMiddleCtx = ctx throw assertError } flaska.requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.ok(ctx) assert.strictEqual(err, assertError) assert.strictEqual(ctx, checkMiddleCtx) assert.strictEqual(ctx.params, assertParams) }) flaska.requestStart(createReq({ url: '', method: 'GET', }), createRes({})) }) t.test('calls route handler correctly', function(cb) { const assertError = new Error('test') let checkHandlerCtx = null let handler = function(ctx) { assert.strictEqual(ctx.params.id, 'test') checkHandlerCtx = ctx throw assertError } let flaska = new Flaska({}, faker) flaska.get('/:id', handler) flaska.compile() flaska.requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.ok(ctx) assert.strictEqual(err, assertError) assert.strictEqual(ctx, checkHandlerCtx) }) flaska.requestStart(createReq({ url: '/test', method: 'GET', }), createRes()) }) t.test('calls 404 if route handler is not found', function(cb) { const on404Error = spy() let handler = function() { throw new Error('should not be called') } let flaska = new Flaska({}, faker) flaska.on404(on404Error) flaska.get('/test', function() { throw new Error('should not be called') }) flaska.compile() flaska.requestEnd = cb.finish(function(err, ctx) { assert.notOk(err) assert.ok(ctx) assert.strictEqual(on404Error.callCount, 1) assert.strictEqual(on404Error.firstCall[0], ctx) }) flaska.requestStart(createReq({ url: '/nope', method: 'GET', }), createRes()) }) t.test('calls 404 if route handler is not found and supports promise', function(cb) { let checkCtx = null const assertError = new Error('should be seen') const on404Error = function(ctx) { checkCtx = ctx return Promise.resolve().then(function() { return Promise.reject(assertError) }) } let flaska = new Flaska({}, faker) flaska.on404(on404Error) flaska.get('/test', function() { throw new Error('should not be called') }) flaska.compile() flaska.requestEnd = cb.finish(function(err, ctx) { assert.strictEqual(err, assertError) assert.ok(ctx) assert.strictEqual(ctx, checkCtx) }) flaska.requestStart(createReq({ url: '/nope', method: 'GET', }), createRes()) }) t.test(`should handle unexpected errors in on404 correctly`, function(cb) { const assertError = new Error('should be seen') let checkCtx = null let flaska = new Flaska({}, faker) flaska.on404(function(ctx) { checkCtx = ctx throw assertError }) flaska.get('/test', function() { throw new Error('should not be called') }) flaska.compile() flaska.requestEnd = cb.finish(function(err, ctx) { assert.strictEqual(err, assertError) assert.ok(ctx) assert.strictEqual(ctx, checkCtx) }) flaska.requestStart(createReq({ url: '/nope', method: 'GET', }), createRes()) }) t.test(`should handle unexpected errors in middleware correctly`, function(cb) { const assertError = new Error('should be seen') let checkCtx = null let flaska = new Flaska({}, faker) let middles = [function(ctx) { checkCtx = ctx throw assertError }] flaska.get('/test', middles, function() { throw new Error('should not be called') }) flaska.compile() flaska.requestEnd = cb.finish(function(err, ctx) { assert.strictEqual(err, assertError) assert.ok(ctx) assert.strictEqual(ctx, checkCtx) }) flaska.requestStart(createReq({ url: '/test', method: 'GET', }), createRes()) }) t.test('should work with synchronous handler', function(cb) { const assertBody = { a: 1 } let handler = function(ctx) { assert.strictEqual(ctx.params.path, 'test/something/here') ctx.body = assertBody } let flaska = new Flaska({}, faker) flaska.get('/::path', handler) flaska.compile() flaska.requestEnd = cb.finish(function(err, ctx) { assert.notOk(err) assert.ok(ctx) assert.strictEqual(ctx.body, assertBody) }) flaska.requestStart(createReq({ url: '/test/something/here', method: 'GET', }), createRes()) }) t.test('calls runHandlers correctly if is promise', function(cb) { const assertError = new Error('test') const assertMiddles = [1] let flaska = new Flaska({}, faker) flaska.compile() flaska.routers.GET.match = function() { return { path: { handlers: function() {}, }, middlewares: assertMiddles, } } flaska.runHandlers = function() { return Promise.resolve().then(function() { return Promise.reject(assertError) }) } flaska.requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.ok(ctx) assert.strictEqual(err, assertError) }) flaska.requestStart(createReq({ url: '', method: 'GET', }), createRes()) }) t.test('calls route handler correctly with promise middle', function(cb) { const assertError = new Error('test') let checkHandlerCtx = null let handler = function(ctx) { assert.strictEqual(ctx.params.id, 'test') checkHandlerCtx = ctx throw assertError } let flaska = new Flaska({}, faker) flaska.get('/:id', [function() { return Promise.resolve() }], handler) flaska.compile() flaska.requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.ok(ctx) assert.strictEqual(err, assertError) assert.strictEqual(ctx, checkHandlerCtx) }) flaska.requestStart(createReq({ url: '/test', method: 'GET', }), createRes()) }) t.test('calls promise route handler correctly with promise middle', function(cb) { const assertError = new Error('test') let checkHandlerCtx = null let handler = function(ctx) { assert.strictEqual(ctx.params.id, 'test') checkHandlerCtx = ctx return Promise.resolve().then(function() { return Promise.reject(assertError) }) } let flaska = new Flaska({}, faker) flaska.get('/:id', [function() { return Promise.resolve() }], handler) flaska.compile() flaska.requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.ok(ctx) assert.strictEqual(err, assertError) assert.strictEqual(ctx, checkHandlerCtx) }) flaska.requestStart(createReq({ url: '/test', method: 'GET', }), createRes()) }) t.test('should work with promise middle and promise handler correctly', function(cb) { const assertBody = { a: 1 } const assertState = { b: 2 } let middle = function(ctx) { return Promise.resolve().then(function() { ctx.state = assertState }) } let handler = function(ctx) { assert.strictEqual(ctx.params.path, 'test/something/here') assert.strictEqual(ctx.state, assertState) return Promise.resolve().then(function() { ctx.body = assertBody }) } let flaska = new Flaska({}, faker) flaska.get('/::path', [middle], handler) flaska.compile() flaska.requestEnd = cb.finish(function(err, ctx) { assert.notOk(err) assert.ok(ctx) assert.strictEqual(ctx.body, assertBody) assert.strictEqual(ctx.state, assertState) }) flaska.requestStart(createReq({ url: '/test/something/here', method: 'GET', }), createRes()) }) t.test('calls route handler correctly if promise', function(cb) { const assertError = new Error('test') let checkHandlerCtx = null let handler = function(ctx) { assert.strictEqual(ctx.params.id, 'test') checkHandlerCtx = ctx return Promise.resolve().then(function() { return Promise.reject(assertError) }) } let flaska = new Flaska({}, faker) flaska.get('/:id', handler) flaska.compile() flaska.requestEnd = cb.finish(function(err, ctx) { assert.ok(err) assert.ok(ctx) assert.strictEqual(err, assertError) assert.strictEqual(ctx, checkHandlerCtx) }) flaska.requestStart(createReq({ url: '/test', method: 'GET', }), createRes()) }) t.test('should work with promise handler', function(cb) { const assertBody = { a: 1 } let handler = function(ctx) { return Promise.resolve().then(function() { assert.strictEqual(ctx.params.path, 'test/something/here') ctx.body = assertBody }) } let flaska = new Flaska({}, faker) flaska.get('/::path', [], handler) flaska.compile() flaska.requestEnd = cb.finish(function(err, ctx) { assert.notOk(err) assert.ok(ctx) assert.strictEqual(ctx.body, assertBody) }) flaska.requestStart(createReq({ url: '/test/something/here', method: 'GET', }), createRes()) }) })