flaska/test/flaska.out.test.mjs

572 lines
20 KiB
JavaScript

import { Eltro as t, spy, assert, stub} from 'eltro'
import { FileResponse, Flaska, FlaskaRouter } from '../flaska.mjs'
import { fakeHttp, createCtx } from './helper.mjs'
const fakerHttp = fakeHttp()
const fakeStream = { pipeline: spy() }
t.describe('#requestEnd()', function() {
t.test('calls onerror correctly on error', function(cb) {
const assertError = new Error('test')
const assertBody = { a: 1 }
const assertStatus = 501
// Calculated manually just in case
const assertBodyLength = 7
let onFinish = cb.finish(function(body) {
assert.strictEqual(ctx.status, assertStatus)
assert.strictEqual(ctx.body, assertBody)
assert.strictEqual(ctx.headers['Content-Type'], 'application/json; charset=utf-8')
assert.strictEqual(ctx.headers['Content-Length'], assertBodyLength)
assert.ok(body)
assert.strictEqual(body, '{"a":1}')
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
})
const ctx = createCtx({}, onFinish)
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.onerror(function(err, inctx) {
assert.strictEqual(err, assertError)
assert.strictEqual(inctx, ctx)
inctx.status = assertStatus
inctx.body = assertBody
})
flaska.requestEnd(assertError, ctx)
})
t.test('calls backup onerror correctly if error throws', function(cb) {
const assertErrorNotSeen = new Error('should not be seen')
const assertError = new Error('test')
let onFinish = cb.finish(function(body) {
assert.strictEqual(ctx.status, 500)
assert.strictEqual(ctx.body.status, 500)
assert.strictEqual(ctx.body.message, 'Internal Server Error')
})
const ctx = createCtx({}, onFinish)
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.onerror(function() {
throw assertError
})
flaska.requestEnd(assertErrorNotSeen, ctx)
})
let testMethods = ['GET', 'HEAD']
testMethods.forEach(function(method) {
t.describe(method, function() {
t.test('call res and end correctly when dealing with objects', function(cb) {
const assertStatus = 202
// Calculated manually just in case
const assertBodyLength = 7
const assertBody = { a: 1 }
let onFinish = cb.finish(function(body) {
assert.strictEqual(ctx.status, assertStatus)
assert.strictEqual(ctx.body, assertBody)
assert.strictEqual(ctx.headers['Content-Type'], 'application/json; charset=utf-8')
assert.strictEqual(ctx.headers['Content-Length'], assertBodyLength)
if (method === 'GET') {
assert.ok(body)
assert.strictEqual(body, '{"a":1}')
} else {
assert.notOk(body)
}
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
})
const ctx = createCtx({
method: method,
status: assertStatus,
}, onFinish)
ctx.body = assertBody
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.requestEnd(null, ctx)
})
t.test('call res and end correctly when dealing with buffers', function(cb) {
const assertStatus = 202
// Calculated manually just in case
const assertBodyLength = 11
const assertBody = Buffer.from('hello world')
let onFinish = cb.finish(function(body) {
assert.strictEqual(ctx.status, assertStatus)
assert.strictEqual(ctx.body, assertBody)
assert.strictEqual(ctx.headers['Content-Type'], 'application/octet-stream')
assert.strictEqual(ctx.headers['Content-Length'], assertBodyLength)
if (method === 'GET') {
assert.ok(body)
assert.strictEqual(body, assertBody)
} else {
assert.notOk(body)
}
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
})
const ctx = createCtx({
method: method,
status: assertStatus,
}, onFinish)
ctx.body = assertBody
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.requestEnd(null, ctx)
})
t.test('call res and end correctly when dealing with null and no status override', function(cb) {
// Calculated manually just in case
const assertBodyLength = 0
const assertBody = null
let onFinish = cb.finish(function(body) {
assert.strictEqual(ctx.status, 204)
assert.strictEqual(ctx.body, assertBody)
assert.notOk(ctx.headers['Content-Type'])
assert.notOk(ctx.headers['Content-Length'])
assert.strictEqual(body, undefined)
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
})
const ctx = createCtx({
method: method,
status: 200,
}, onFinish)
ctx.body = assertBody
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.requestEnd(null, ctx)
})
t.test('call res and end correctly when dealing with null and status override', function(cb) {
const assertStatus = 202
// Calculated manually just in case
const assertBody = null
let onFinish = cb.finish(function(body) {
assert.strictEqual(ctx.status, assertStatus)
assert.strictEqual(ctx.body, assertBody)
assert.notOk(ctx.headers['Content-Type'])
assert.strictEqual(ctx.headers['Content-Length'], 0)
assert.strictEqual(body, undefined)
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
})
const ctx = createCtx({
method: method,
status: assertStatus,
}, onFinish)
ctx.body = assertBody
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.requestEnd(null, ctx)
})
t.test('call res and end correctly when dealing with strings', function(cb) {
const assertStatus = 206
// Calculated manually just in case
const assertBodyLength = 4
const assertBody = 'eða'
let onFinish = cb.finish(function(body) {
assert.strictEqual(ctx.status, assertStatus)
assert.strictEqual(ctx.body, assertBody)
assert.strictEqual(ctx.headers['Content-Type'], 'text/plain; charset=utf-8')
assert.strictEqual(ctx.headers['Content-Length'], assertBodyLength)
if (method === 'GET') {
assert.ok(body)
assert.strictEqual(body, assertBody)
} else {
assert.notOk(body)
}
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
})
const ctx = createCtx({
method: method,
status: assertStatus,
}, onFinish)
ctx.body = assertBody
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.requestEnd(null, ctx)
})
t.test('call res and end correctly when dealing with numbers', function(cb) {
const assertStatus = 211
// Calculated manually just in case
const assertBodyLength = 7
const assertBody = 4214124
let onFinish = cb.finish(function(body) {
assert.strictEqual(ctx.status, assertStatus)
assert.strictEqual(ctx.body, assertBody)
assert.strictEqual(ctx.headers['Content-Type'], 'text/plain; charset=utf-8')
assert.strictEqual(ctx.headers['Content-Length'], assertBodyLength)
if (method === 'GET') {
assert.ok(body)
assert.strictEqual(body, assertBody.toString())
} else {
assert.notOk(body)
}
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
})
const ctx = createCtx({
method: method,
status: assertStatus,
}, onFinish)
ctx.body = assertBody
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.requestEnd(null, ctx)
})
if (method === 'GET') {
t.test('call handleRequest if body contains it', function(cb) {
const assertContentType = 'test/test'
const assertContentLength = 1241241
const assertHandle = stub().returnWith(function(checkCtx, secondary) {
assert.notOk(secondary)
assert.strictEqual(checkCtx, ctx)
assert.notOk(ctx.res.writeHead.called)
ctx.type = assertContentType
ctx.headers['Content-Length'] = assertContentLength
return assertBody
})
let body = new FileResponse()
let assertBody = { pipe: function() {} }
let onFinish = cb.finish(function(source, target, callback) {
assert.ok(assertHandle.called)
assert.ok(ctx.res.writeHead)
assert.strictEqual(ctx.body, assertBody)
assert.strictEqual(source, assertBody)
assert.strictEqual(target, ctx.res)
assert.strictEqual(typeof(callback), 'function')
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
assert.strictEqual(ctx.headers['Content-Type'], assertContentType)
assert.strictEqual(ctx.headers['Content-Length'], assertContentLength)
})
const ctx = createCtx({
})
ctx.body = body
fakeStream.pipeline = onFinish
body.handleRequest = assertHandle
let flaska = new Flaska({}, fakerHttp, fakeStream)
try {
flaska.requestEnd(null, ctx)
} catch (err) {
cb(err)
}
})
t.test('call pipeline correctly when dealing with pipe', function(cb) {
const assertStatus = 211
const assertType = 'herp/derp'
const assertBody = { pipe: function() {} }
let onFinish = cb.finish(function(source, target, callback) {
assert.strictEqual(ctx.status, assertStatus)
assert.strictEqual(ctx.headers['Content-Type'], assertType)
assert.strictEqual(source, assertBody)
assert.strictEqual(target, ctx.res)
assert.strictEqual(typeof(callback), 'function')
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
})
const ctx = createCtx({
status: assertStatus,
})
fakeStream.pipeline = onFinish
ctx.body = assertBody
ctx.type = assertType
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.requestEnd(null, ctx)
})
} else {
t.test('call handleRequest if body contains it', function(cb) {
const assertContentType = 'test/test'
const assertContentLength = 1241241
const assertHandle = stub().returnWith(function(checkCtx, secondary) {
assert.notOk(secondary)
assert.strictEqual(checkCtx, ctx)
assert.notOk(ctx.res.writeHead.called)
ctx.type = assertContentType
ctx.headers['Content-Length'] = assertContentLength
return null
})
let body = new FileResponse()
let onFinish = cb.finish(function(body) {
assert.ok(assertHandle.called)
assert.ok(ctx.res.writeHead)
assert.strictEqual(ctx.body, null)
assert.notOk(body)
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
assert.strictEqual(ctx.headers['Content-Type'], assertContentType)
assert.strictEqual(ctx.headers['Content-Length'], assertContentLength)
})
const ctx = createCtx({
method: method,
}, onFinish)
ctx.body = body
body.handleRequest = assertHandle
let flaska = new Flaska({}, fakerHttp, fakeStream)
try {
flaska.requestEnd(null, ctx)
} catch (err) {
cb(err)
}
})
t.test('call pipeline correctly when dealing with pipe', function(cb) {
const assertStatus = 211
const assertType = 'herp/derp'
const assertBody = { pipe: function() {}, destroy: stub() }
let onFinish = cb.finish(function(body) {
assert.strictEqual(ctx.status, assertStatus)
assert.strictEqual(ctx.headers['Content-Type'], assertType)
assert.notOk(ctx.headers['Content-Length'])
assert.notOk(body)
assert.ok(assertBody.destroy.called)
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
})
const ctx = createCtx({
method: method,
status: assertStatus,
}, onFinish)
ctx.body = assertBody
ctx.type = assertType
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.requestEnd(null, ctx)
})
}
})
})
t.test('call _onerror with error if handleRequest throws error', function() {
let body = new FileResponse()
const assertError = new Error('Secrets of the Goddess')
let assertBody = { a : 1 }
const ctx = createCtx({
status: 204,
})
ctx.body = body
const assertHandle = stub().throws(assertError)
body.handleRequest = assertHandle
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska._onerror = stub().returnWith(function(err, checkCtx) {
assert.strictEqual(err, assertError)
checkCtx.body = assertBody
})
flaska.requestEnd(null, ctx)
assert.ok(assertHandle.called)
assert.ok(flaska._onerror.called)
assert.strictEqual(flaska._onerror.firstCall[0], assertError)
assert.ok(ctx.res.writeHead)
assert.strictEqual(ctx.body, assertBody)
})
t.test('call res and end correctly when dealing with custom type', function(cb) {
const assertStatus = 209
const assertBody = 'test'
const assertType = 'something/else'
let onFinish = cb.finish(function(body) {
assert.strictEqual(ctx.status, assertStatus)
assert.strictEqual(ctx.headers['Content-Type'], assertType)
assert.strictEqual(body, assertBody)
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
})
const ctx = createCtx({
status: assertStatus,
body: assertBody,
}, onFinish)
ctx.type = assertType
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.requestEnd(null, ctx)
})
t.test('call pipe should have default type', function(cb) {
let onFinish = cb.finish(function(source, target) {
assert.strictEqual(ctx.status, 200)
assert.strictEqual(ctx.headers['Content-Type'], 'application/octet-stream')
assert.strictEqual(source, ctx.body)
assert.strictEqual(target, ctx.res)
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
})
const ctx = createCtx({})
ctx.body = { pipe: function() {} }
fakeStream.pipeline = onFinish
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.requestEnd(null, ctx)
})
let tests = [
['png', 'image/png'],
['jpg', 'image/jpeg'],
['bmp', 'image/bmp'],
['js', 'text/javascript'],
]
tests.forEach(function(test) {
t.test(`call pipe with file extension ${test[0]} should mimetype ${test[1]}`, function(cb) {
let onFinish = cb.finish(function(source, target) {
assert.strictEqual(ctx.status, 200)
assert.strictEqual(ctx.headers['Content-Type'], test[1])
assert.strictEqual(source, ctx.body)
assert.strictEqual(target, ctx.res)
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
})
const ctx = createCtx({})
ctx.body = { pipe: function() {}, path: './bla/test/temp.' + test[0] }
fakeStream.pipeline = onFinish
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.requestEnd(null, ctx)
})
})
t.test('should return immediately if req is finished', function() {
let onFinish = function() {
throw new Error('should not be called')
}
const ctx = createCtx({ }, onFinish)
ctx.res.writableEnded = true
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.requestEnd(null, ctx)
})
const emptyStatuses = [204, 205, 304]
emptyStatuses.forEach(function(status) {
t.test('call res and end correctly when dealing with status ' + status, function(cb) {
const assertStatus = status
const assertNotBody = 'test'
const assertNotType = 'something/else'
let onFinish = cb.finish(function(body) {
assert.strictEqual(ctx.status, assertStatus)
assert.strictEqual(ctx.res.setHeader.callCount, 0)
assert.ok(ctx.res.writeHead.called)
assert.strictEqual(ctx.res.writeHead.firstCall[0], ctx.status)
assert.strictEqual(ctx.res.writeHead.firstCall[1], ctx.headers)
assert.notOk(body)
})
const ctx = createCtx({
status: assertStatus,
body: assertNotBody,
}, onFinish)
ctx.type = assertNotType
let flaska = new Flaska({}, fakerHttp, fakeStream)
flaska.requestEnd(null, ctx)
})
})
})
t.describe('#requestEnded()', function() {
t.test('calls destroy if body is pipe and is not closed', function() {
const ctx = createCtx({
body: {
pipe: {},
closed: false,
destroy: spy(),
},
})
let flaska = new Flaska({}, fakerHttp)
flaska._afterCompiled = function() {}
flaska.requestEnded(ctx)
assert.ok(ctx.body.destroy.called)
})
t.test('not call destroy if body is pipe but is closed', function() {
const ctx = createCtx({
body: {
pipe: {},
closed: true,
destroy: spy(),
}
})
let flaska = new Flaska({}, fakerHttp)
flaska._afterCompiled = function() {}
flaska.requestEnded(ctx)
assert.notOk(ctx.body.destroy.called)
})
t.test('calls afterCompiled correctly', function() {
const assertError = new Error('test')
const assertCtx = createCtx()
let flaska = new Flaska({}, fakerHttp)
flaska._afterCompiled = function(ctx) {
assert.strictEqual(ctx, assertCtx)
throw assertError
}
assert.throws(function() {
flaska.requestEnded(assertCtx)
}, /test/)
})
t.test('calls afterAsyncCompiled correctly if defined', async function() {
const assertError = new Error('test')
const assertCtx = createCtx()
let flaska = new Flaska({}, fakerHttp)
flaska.compile()
flaska._afterAsyncCompiled = function(ctx) {
assert.strictEqual(ctx, assertCtx)
return Promise.resolve().then(function() { return Promise.reject(assertError) })
}
let err = await assert.isRejected(flaska.requestEnded(assertCtx))
assert.strictEqual(err, assertError)
})
})