flaska: Add jsonhandler and basic httperror class
All checks were successful
continuous-integration/appveyor/branch AppVeyor build succeeded
All checks were successful
continuous-integration/appveyor/branch AppVeyor build succeeded
flaska: Add promise-based listen and close methods
This commit is contained in:
parent
5a28a0cf78
commit
9c43b429c4
14 changed files with 358 additions and 61 deletions
1
.npmrc
Normal file
1
.npmrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package-lock=false
|
|
@ -51,7 +51,6 @@ on_success:
|
||||||
if [ $? -eq 0 ] ; then
|
if [ $? -eq 0 ] ; then
|
||||||
echo "Release already exists, nothing to do.";
|
echo "Release already exists, nothing to do.";
|
||||||
else
|
else
|
||||||
./test/7zas a -mx9 "${CURR_VER}_sc-core.7z" package.json index.mjs cli.mjs core bin
|
|
||||||
echo "Creating release on gitea"
|
echo "Creating release on gitea"
|
||||||
RELEASE_RESULT=$(curl \
|
RELEASE_RESULT=$(curl \
|
||||||
-X POST \
|
-X POST \
|
||||||
|
@ -59,13 +58,6 @@ on_success:
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
https://git.nfp.is/api/v1/repos/$APPVEYOR_REPO_NAME/releases \
|
https://git.nfp.is/api/v1/repos/$APPVEYOR_REPO_NAME/releases \
|
||||||
-d "{\"tag_name\":\"v${CURR_VER}\",\"name\":\"v${CURR_VER}\",\"body\":\"Automatic release from Appveyor from ${APPVEYOR_REPO_COMMIT} :\n\n${APPVEYOR_REPO_COMMIT_MESSAGE}\"}")
|
-d "{\"tag_name\":\"v${CURR_VER}\",\"name\":\"v${CURR_VER}\",\"body\":\"Automatic release from Appveyor from ${APPVEYOR_REPO_COMMIT} :\n\n${APPVEYOR_REPO_COMMIT_MESSAGE}\"}")
|
||||||
RELEASE_ID=$(echo $RELEASE_RESULT | jq -r .id)
|
|
||||||
echo "Adding ${CURR_VER}_sc-core.7z to release ${RELEASE_ID}"
|
|
||||||
curl \
|
|
||||||
-X POST \
|
|
||||||
-H "Authorization: token $deploytoken" \
|
|
||||||
-F "attachment=@${CURR_VER}_sc-core.7z" \
|
|
||||||
https://git.nfp.is/api/v1/repos/$APPVEYOR_REPO_NAME/releases/$RELEASE_ID/assets
|
|
||||||
echo '//registry.npmjs.org/:_authToken=${npmtoken}' > ~/.npmrc
|
echo '//registry.npmjs.org/:_authToken=${npmtoken}' > ~/.npmrc
|
||||||
echo "Publishing new version to npm"
|
echo "Publishing new version to npm"
|
||||||
npm publish
|
npm publish
|
||||||
|
|
67
flaska.mjs
67
flaska.mjs
|
@ -57,6 +57,33 @@ export function QueryHandler() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function JsonHandler() {
|
||||||
|
return async function(ctx) {
|
||||||
|
const buffers = [];
|
||||||
|
|
||||||
|
for await (const chunk of ctx.req) {
|
||||||
|
buffers.push(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = Buffer.concat(buffers).toString();
|
||||||
|
|
||||||
|
ctx.req.body = JSON.parse(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HttpError extends Error {
|
||||||
|
constructor(statusCode, message, body = null) {
|
||||||
|
super(message);
|
||||||
|
|
||||||
|
Error.captureStackTrace(this, HttpError);
|
||||||
|
|
||||||
|
let proto = Object.getPrototypeOf(this);
|
||||||
|
proto.name = 'HttpError';
|
||||||
|
|
||||||
|
this.status = statusCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class FlaskaRouter {
|
export class FlaskaRouter {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.root = new Branch()
|
this.root = new Branch()
|
||||||
|
@ -547,12 +574,48 @@ export class Flaska {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
listen(port, cb) {
|
listen(port, orgIp, orgcb) {
|
||||||
|
let ip = orgIp
|
||||||
|
let cb = orgcb
|
||||||
|
if (!cb && typeof(orgIp) === 'function') {
|
||||||
|
ip = '::'
|
||||||
|
cb = orgIp
|
||||||
|
}
|
||||||
if (typeof(port) !== 'number') {
|
if (typeof(port) !== 'number') {
|
||||||
throw new Error('Flaska.listen() called with non-number in port')
|
throw new Error('Flaska.listen() called with non-number in port')
|
||||||
}
|
}
|
||||||
this.compile()
|
this.compile()
|
||||||
this.server = this.http.createServer(this.requestStart.bind(this))
|
this.server = this.http.createServer(this.requestStart.bind(this))
|
||||||
this.server.listen(port, cb)
|
|
||||||
|
this.server.listen(port, ip, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
listenAsync(port, ip = '::') {
|
||||||
|
if (typeof(port) !== 'number') {
|
||||||
|
return Promise.reject(new Error('Flaska.listen() called with non-number in port'))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.compile()
|
||||||
|
this.server = this.http.createServer(this.requestStart.bind(this))
|
||||||
|
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
this.server.listen(port, ip, function(err) {
|
||||||
|
if (err) return rej(err)
|
||||||
|
return res()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
closeAsync() {
|
||||||
|
if (!this.server) return Promise.resolve()
|
||||||
|
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
this.server.close(function(err) {
|
||||||
|
if (err) { return rej(err) }
|
||||||
|
|
||||||
|
// Waiting 0.1 second for it to close down
|
||||||
|
setTimeout(function() { res() }, 100)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
19
package.json
19
package.json
|
@ -1,10 +1,22 @@
|
||||||
{
|
{
|
||||||
"name": "flaska",
|
"name": "flaska",
|
||||||
"version": "0.9.8",
|
"version": "0.9.9",
|
||||||
"description": "Flaska is a micro web-framework for node. It is designed to be fast, simple and lightweight, and is distributed as a single file module with no dependencies.",
|
"description": "Flaska is a micro web-framework for node. It is designed to be fast, simple and lightweight, and is distributed as a single file module with no dependencies.",
|
||||||
"main": "flaska.mjs",
|
"main": "flaska.mjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "eltro"
|
"test": "eltro",
|
||||||
|
"test:watch": "npm-watch test"
|
||||||
|
},
|
||||||
|
"watch": {
|
||||||
|
"test": {
|
||||||
|
"patterns": [
|
||||||
|
"test/*",
|
||||||
|
"flaska.mjs"
|
||||||
|
],
|
||||||
|
"extensions": "mjs",
|
||||||
|
"quiet": true,
|
||||||
|
"inherit": true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -27,7 +39,8 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/nfp-projects/bottle-node#readme",
|
"homepage": "https://github.com/nfp-projects/bottle-node#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eltro": "^1.1.0"
|
"eltro": "^1.3.1",
|
||||||
|
"formidable": "^1.2.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"flaska.mjs",
|
"flaska.mjs",
|
||||||
|
|
|
@ -15,7 +15,6 @@ Client.prototype.customRequest = function(method = 'GET', path, body, options) {
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const opts = defaults(defaults(options, {
|
const opts = defaults(defaults(options, {
|
||||||
agent: false,
|
|
||||||
method: method,
|
method: method,
|
||||||
timeout: 500,
|
timeout: 500,
|
||||||
protocol: urlObj.protocol,
|
protocol: urlObj.protocol,
|
||||||
|
@ -24,6 +23,7 @@ Client.prototype.customRequest = function(method = 'GET', path, body, options) {
|
||||||
host: urlObj.hostname,
|
host: urlObj.hostname,
|
||||||
port: Number(urlObj.port),
|
port: Number(urlObj.port),
|
||||||
path: urlObj.pathname + urlObj.search,
|
path: urlObj.pathname + urlObj.search,
|
||||||
|
headers: {},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const req = http.request(opts)
|
const req = http.request(opts)
|
||||||
|
@ -33,7 +33,6 @@ Client.prototype.customRequest = function(method = 'GET', path, body, options) {
|
||||||
|
|
||||||
req.on('error', reject)
|
req.on('error', reject)
|
||||||
req.on('timeout', function() {
|
req.on('timeout', function() {
|
||||||
console.log(req.destroy())
|
|
||||||
reject(new Error(`Request ${method} ${path} timed out`))
|
reject(new Error(`Request ${method} ${path} timed out`))
|
||||||
})
|
})
|
||||||
req.on('response', res => {
|
req.on('response', res => {
|
||||||
|
@ -45,6 +44,7 @@ Client.prototype.customRequest = function(method = 'GET', path, body, options) {
|
||||||
})
|
})
|
||||||
|
|
||||||
res.on('end', function () {
|
res.on('end', function () {
|
||||||
|
if (!output) return resolve(null)
|
||||||
try {
|
try {
|
||||||
output = JSON.parse(output)
|
output = JSON.parse(output)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -63,6 +63,63 @@ Client.prototype.customRequest = function(method = 'GET', path, body, options) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Client.prototype.get = function(path = '/') {
|
Client.prototype.get = function(url = '/') {
|
||||||
return this.customRequest('GET', path, null)
|
return this.customRequest('GET', url, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
Client.prototype.post = function(url = '/', body = {}) {
|
||||||
|
let parsed = JSON.stringify(body)
|
||||||
|
return this.customRequest('POST', url, parsed, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Content-Length': parsed.length,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Client.prototype.del = function(url = '/', body = {}) {
|
||||||
|
return this.customRequest('DELETE', url, JSON.stringify(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
const random = (length = 8) => {
|
||||||
|
// Declare all characters
|
||||||
|
let chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
|
// Pick characers randomly
|
||||||
|
let str = '';
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
str += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
Client.prototype.upload = function(url, file, method = 'POST', body = {}) {
|
||||||
|
return fs.readFile(file).then(data => {
|
||||||
|
const crlf = '\r\n'
|
||||||
|
const filename = path.basename(file)
|
||||||
|
const boundary = `---------${random(32)}`
|
||||||
|
|
||||||
|
const multipartBody = Buffer.concat([
|
||||||
|
Buffer.from(
|
||||||
|
`${crlf}--${boundary}${crlf}` +
|
||||||
|
`Content-Disposition: form-data; name="file"; filename="${filename}"` + crlf + crlf
|
||||||
|
),
|
||||||
|
data,
|
||||||
|
Buffer.concat(Object.keys(body).map(function(key) {
|
||||||
|
return Buffer.from(''
|
||||||
|
+ `${crlf}--${boundary}${crlf}`
|
||||||
|
+ `Content-Disposition: form-data; name="${key}"` + crlf + crlf
|
||||||
|
+ JSON.stringify(body[key])
|
||||||
|
)
|
||||||
|
})),
|
||||||
|
Buffer.from(`${crlf}--${boundary}--`),
|
||||||
|
])
|
||||||
|
|
||||||
|
return this.customRequest(method, url, multipartBody, {
|
||||||
|
timeout: 5000,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data; boundary=' + boundary,
|
||||||
|
'Content-Length': multipartBody.length,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { Eltro as t, assert} from 'eltro'
|
import { Eltro as t, assert, stub, spy } from 'eltro'
|
||||||
import { Flaska } from '../flaska.mjs'
|
import { Flaska } from '../flaska.mjs'
|
||||||
import { spy, createCtx, fakeHttp } from './helper.mjs'
|
import { createCtx, fakeHttp } from './helper.mjs'
|
||||||
|
|
||||||
const faker = fakeHttp()
|
const faker = fakeHttp()
|
||||||
|
|
||||||
|
@ -441,12 +441,39 @@ t.describe('#listen()', function() {
|
||||||
|
|
||||||
t.test('call http correctly', function() {
|
t.test('call http correctly', function() {
|
||||||
const assertPort = 325897235
|
const assertPort = 325897235
|
||||||
|
const assertIp = 'asdga'
|
||||||
const assertCb = function() { }
|
const assertCb = function() { }
|
||||||
let checkPort = null
|
let checkPort = null
|
||||||
|
let checkIp = null
|
||||||
let checkListenCb = null
|
let checkListenCb = null
|
||||||
|
|
||||||
let testFaker = fakeHttp(null, function(port, cb) {
|
let testFaker = fakeHttp(null, function(port, ip, cb) {
|
||||||
checkPort = port
|
checkPort = port
|
||||||
|
checkIp = ip
|
||||||
|
checkListenCb = cb
|
||||||
|
})
|
||||||
|
let flaska = new Flaska({}, testFaker)
|
||||||
|
assert.ok(flaska.requestStart)
|
||||||
|
flaska.requestStart = function() {
|
||||||
|
checkInternalThis = this
|
||||||
|
checkIsTrue = true
|
||||||
|
}
|
||||||
|
flaska.listen(assertPort, assertIp, assertCb)
|
||||||
|
assert.strictEqual(checkPort, assertPort)
|
||||||
|
assert.strictEqual(checkIp, assertIp)
|
||||||
|
assert.strictEqual(checkListenCb, assertCb)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('call http correctly if only port is specified', function() {
|
||||||
|
const assertPort = 325897235
|
||||||
|
const assertCb = function() { }
|
||||||
|
let checkPort = null
|
||||||
|
let checkIp = null
|
||||||
|
let checkListenCb = null
|
||||||
|
|
||||||
|
let testFaker = fakeHttp(null, function(port, ip, cb) {
|
||||||
|
checkPort = port
|
||||||
|
checkIp = ip
|
||||||
checkListenCb = cb
|
checkListenCb = cb
|
||||||
})
|
})
|
||||||
let flaska = new Flaska({}, testFaker)
|
let flaska = new Flaska({}, testFaker)
|
||||||
|
@ -457,6 +484,7 @@ t.describe('#listen()', function() {
|
||||||
}
|
}
|
||||||
flaska.listen(assertPort, assertCb)
|
flaska.listen(assertPort, assertCb)
|
||||||
assert.strictEqual(checkPort, assertPort)
|
assert.strictEqual(checkPort, assertPort)
|
||||||
|
assert.strictEqual(checkIp, '::')
|
||||||
assert.strictEqual(checkListenCb, assertCb)
|
assert.strictEqual(checkListenCb, assertCb)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -484,3 +512,131 @@ t.describe('#listen()', function() {
|
||||||
assert.strictEqual(checkInternalThis, flaska)
|
assert.strictEqual(checkInternalThis, flaska)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.describe('#listenAsync()', function() {
|
||||||
|
t.test('it should throw if missing port', async function() {
|
||||||
|
let flaska = new Flaska({}, faker)
|
||||||
|
|
||||||
|
let tests = [
|
||||||
|
undefined,
|
||||||
|
'asdf',
|
||||||
|
'123',
|
||||||
|
[],
|
||||||
|
{},
|
||||||
|
function() {},
|
||||||
|
]
|
||||||
|
let errors = await Promise.all(tests.map(x => assert.isRejected(flaska.listenAsync(x))))
|
||||||
|
assert.strictEqual(errors.length, tests.length)
|
||||||
|
for (let i = 0; i < errors.length; i++) {
|
||||||
|
assert.match(errors[i].message, /[Pp]ort/)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('it should automatically call compile', async function() {
|
||||||
|
let assertCalled = false
|
||||||
|
let flaska = new Flaska({}, faker)
|
||||||
|
flaska.compile = function() { assertCalled = true }
|
||||||
|
await flaska.listenAsync(404)
|
||||||
|
assert.strictEqual(assertCalled, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('call http correctly', async function() {
|
||||||
|
const assertPort = 325897235
|
||||||
|
const assertIp = 'asdf'
|
||||||
|
let checkPort = null
|
||||||
|
let checkIp = null
|
||||||
|
|
||||||
|
let testFaker = fakeHttp(null, function(port, ip, cb) {
|
||||||
|
checkPort = port
|
||||||
|
checkIp = ip
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
let flaska = new Flaska({}, testFaker)
|
||||||
|
assert.ok(flaska.requestStart)
|
||||||
|
flaska.requestStart = function() {
|
||||||
|
checkInternalThis = this
|
||||||
|
checkIsTrue = true
|
||||||
|
}
|
||||||
|
await flaska.listenAsync(assertPort, assertIp)
|
||||||
|
assert.strictEqual(checkPort, assertPort)
|
||||||
|
assert.strictEqual(checkIp, assertIp)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('call http correctly if only port specified', async function() {
|
||||||
|
const assertPort = 325897235
|
||||||
|
let checkPort = null
|
||||||
|
let checkIp = null
|
||||||
|
|
||||||
|
let testFaker = fakeHttp(null, function(port, ip, cb) {
|
||||||
|
checkPort = port
|
||||||
|
checkIp = ip
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
let flaska = new Flaska({}, testFaker)
|
||||||
|
assert.ok(flaska.requestStart)
|
||||||
|
flaska.requestStart = function() {
|
||||||
|
checkInternalThis = this
|
||||||
|
checkIsTrue = true
|
||||||
|
}
|
||||||
|
await flaska.listenAsync(assertPort)
|
||||||
|
assert.strictEqual(checkPort, assertPort)
|
||||||
|
assert.strictEqual(checkIp, '::')
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('register requestStart if no async', async function() {
|
||||||
|
let checkIsTrue = false
|
||||||
|
let checkInternalThis = null
|
||||||
|
let checkHandler = null
|
||||||
|
|
||||||
|
let testFaker = fakeHttp(function(cb) {
|
||||||
|
checkHandler = cb
|
||||||
|
})
|
||||||
|
let flaska = new Flaska({}, testFaker)
|
||||||
|
assert.ok(flaska.requestStart)
|
||||||
|
flaska.requestStart = function() {
|
||||||
|
checkInternalThis = this
|
||||||
|
checkIsTrue = true
|
||||||
|
}
|
||||||
|
await flaska.listenAsync(404)
|
||||||
|
assert.strictEqual(typeof(checkHandler), 'function')
|
||||||
|
assert.notStrictEqual(checkHandler, flaska.requestStart)
|
||||||
|
assert.notStrictEqual(checkIsTrue, true)
|
||||||
|
assert.notStrictEqual(checkInternalThis, flaska)
|
||||||
|
checkHandler()
|
||||||
|
assert.strictEqual(checkIsTrue, true)
|
||||||
|
assert.strictEqual(checkInternalThis, flaska)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.describe('#closeAsync()', function() {
|
||||||
|
t.test('it return if server is null', function() {
|
||||||
|
let flaska = new Flaska()
|
||||||
|
flaska.server = null
|
||||||
|
return flaska.closeAsync()
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('it should call close on server correctly', async function() {
|
||||||
|
const assertError = new Error('Pirate Fight')
|
||||||
|
let flaska = new Flaska()
|
||||||
|
flaska.server = {
|
||||||
|
close: stub()
|
||||||
|
}
|
||||||
|
flaska.server.close.returnWith(function(cb) {
|
||||||
|
cb(assertError)
|
||||||
|
})
|
||||||
|
let err = await assert.isRejected(flaska.closeAsync())
|
||||||
|
assert.strictEqual(err, assertError)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('should otherwise work', async function() {
|
||||||
|
let flaska = new Flaska()
|
||||||
|
flaska.server = {
|
||||||
|
close: stub()
|
||||||
|
}
|
||||||
|
flaska.server.close.returnWith(function(cb) {
|
||||||
|
cb(null, { a: 1 })
|
||||||
|
})
|
||||||
|
let res = await flaska.closeAsync()
|
||||||
|
assert.notOk(res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
0
test/flaska.body.test.mjs
Normal file
0
test/flaska.body.test.mjs
Normal file
0
test/flaska.formidable.test.mjs
Normal file
0
test/flaska.formidable.test.mjs
Normal file
|
@ -1,6 +1,6 @@
|
||||||
import { Eltro as t, assert} from 'eltro'
|
import { Eltro as t, spy, assert} from 'eltro'
|
||||||
import { Flaska } from '../flaska.mjs'
|
import { Flaska } from '../flaska.mjs'
|
||||||
import { fakeHttp, createReq, spy, createRes } from './helper.mjs'
|
import { fakeHttp, createReq, createRes } from './helper.mjs'
|
||||||
|
|
||||||
const faker = fakeHttp()
|
const faker = fakeHttp()
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Eltro as t, assert} from 'eltro'
|
import { Eltro as t, spy, assert} from 'eltro'
|
||||||
import { Flaska, FlaskaRouter } from '../flaska.mjs'
|
import { Flaska, FlaskaRouter } from '../flaska.mjs'
|
||||||
import { fakeHttp, createCtx, spy } from './helper.mjs'
|
import { fakeHttp, createCtx } from './helper.mjs'
|
||||||
|
|
||||||
const fakerHttp = fakeHttp()
|
const fakerHttp = fakeHttp()
|
||||||
const fakeStream = { pipeline: spy() }
|
const fakeStream = { pipeline: spy() }
|
||||||
|
|
|
@ -1,40 +1,19 @@
|
||||||
|
import { spy } from 'eltro'
|
||||||
|
|
||||||
const indexMap = [
|
const indexMap = [
|
||||||
'firstCall',
|
'firstCall',
|
||||||
'secondCall',
|
'secondCall',
|
||||||
'thirdCall',
|
'thirdCall',
|
||||||
]
|
]
|
||||||
|
|
||||||
export function spy() {
|
|
||||||
let calls = []
|
|
||||||
let called = 0
|
|
||||||
let func = function(...args) {
|
|
||||||
func.called = true
|
|
||||||
calls.push(args)
|
|
||||||
if (called < indexMap.length) {
|
|
||||||
func[indexMap[called]] = args
|
|
||||||
}
|
|
||||||
called++
|
|
||||||
func.callCount = called
|
|
||||||
}
|
|
||||||
func.called = false
|
|
||||||
func.callCount = called
|
|
||||||
func.onCall = function(i) {
|
|
||||||
return calls[i]
|
|
||||||
}
|
|
||||||
for (let i = 0; i < indexMap.length; i++) {
|
|
||||||
func[indexMap] = null
|
|
||||||
}
|
|
||||||
return func
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fakeHttp(inj1, inj2) {
|
export function fakeHttp(inj1, inj2) {
|
||||||
let intermediate = {
|
let intermediate = {
|
||||||
createServer: function(cb) {
|
createServer: function(cb) {
|
||||||
if (inj1) inj1(cb)
|
if (inj1) inj1(cb)
|
||||||
intermediate.fakeRequest = cb
|
intermediate.fakeRequest = cb
|
||||||
return {
|
return {
|
||||||
listen: function(port, cb) {
|
listen: function(port, ip, cb) {
|
||||||
if (inj2) inj2(port, cb)
|
if (inj2) inj2(port, ip, cb)
|
||||||
else if (cb) cb()
|
else if (cb) cb()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,24 +6,36 @@ const port = 51024
|
||||||
const flaska = new Flaska({})
|
const flaska = new Flaska({})
|
||||||
const client = new Client(port)
|
const client = new Client(port)
|
||||||
|
|
||||||
|
let reqBody = null
|
||||||
|
|
||||||
flaska.get('/', function(ctx) {
|
flaska.get('/', function(ctx) {
|
||||||
ctx.body = { status: true }
|
ctx.body = { status: true }
|
||||||
})
|
})
|
||||||
|
flaska.post('/test', function(ctx) {
|
||||||
t.before(function(cb) {
|
ctx.body = { success: true }
|
||||||
flaska.listen(port, cb)
|
// console.log(ctx)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.describe('', function() {
|
t.before(function() {
|
||||||
t.test('/ should return status true', function() {
|
return flaska.listenAsync(port)
|
||||||
return client.get().then(function(body) {
|
})
|
||||||
|
|
||||||
|
t.describe('/', function() {
|
||||||
|
t.test('should return status true', function() {
|
||||||
|
return client.get('/').then(function(body) {
|
||||||
assert.deepEqual(body, { status: true })
|
assert.deepEqual(body, { status: true })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.after(function(cb) {
|
t.describe('/test', function() {
|
||||||
setTimeout(function() {
|
t.test('should return success and store body', async function() {
|
||||||
flaska.server.close(cb)
|
reqBody = null
|
||||||
}, 1000)
|
let body = await client.post('/test')
|
||||||
|
assert.deepEqual(body, { success: true })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.after(function() {
|
||||||
|
return flaska.closeAsync()
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Eltro as t, assert} from 'eltro'
|
import { Eltro as t, assert} from 'eltro'
|
||||||
import { QueryHandler } from '../flaska.mjs'
|
import { QueryHandler, JsonHandler } from '../flaska.mjs'
|
||||||
|
|
||||||
t.describe('#QueryHandler()', function() {
|
t.describe('#QueryHandler()', function() {
|
||||||
let queryHandler = QueryHandler()
|
let queryHandler = QueryHandler()
|
||||||
|
@ -22,3 +22,27 @@ t.describe('#QueryHandler()', function() {
|
||||||
assert.strictEqual(ctx.query.get('ITEM2'), 'hello world')
|
assert.strictEqual(ctx.query.get('ITEM2'), 'hello world')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.describe('#JsonHandler()', function() {
|
||||||
|
let jsonHandler = JsonHandler()
|
||||||
|
|
||||||
|
t.test('should return a handler', function() {
|
||||||
|
assert.strictEqual(typeof(jsonHandler), 'function')
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('should support separating query from request url', async function() {
|
||||||
|
const assertBody = { a: 1, temp: 'test', hello: 'world'}
|
||||||
|
let parsed = JSON.stringify(assertBody)
|
||||||
|
|
||||||
|
const ctx = {
|
||||||
|
req: [
|
||||||
|
Promise.resolve(Buffer.from(parsed.slice(0, parsed.length / 2))),
|
||||||
|
Promise.resolve(Buffer.from(parsed.slice(parsed.length / 2))),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
await jsonHandler(ctx)
|
||||||
|
assert.notStrictEqual(ctx.req.body, assertBody)
|
||||||
|
assert.deepStrictEqual(ctx.req.body, assertBody)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
BIN
test/test.png
Normal file
BIN
test/test.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 278 KiB |
Loading…
Reference in a new issue