test: Use Jest (#981)

master
Gilles De Mey 2017-05-11 05:30:32 +02:00 committed by Yiyu He
parent 13c7ca6139
commit d394724200
67 changed files with 745 additions and 852 deletions

View File

@ -19,9 +19,9 @@ before_script:
- "[ ! -f wrk/bin/wrk ] && rm -rf wrk && git clone https://github.com/wg/wrk.git && make -C wrk && mkdir wrk/bin && mv wrk/wrk wrk/bin || true"
- export PATH=$PATH:$PWD/wrk/bin/
script:
- make lint
- make test-travis
- make bench
- npm run lint
- npm run test-cov
- npm run bench
after_script:
- npm install codecov
- ./node_modules/.bin/codecov

View File

@ -1,42 +0,0 @@
SRC = lib/*.js
REQUIRED = --require should --require should-http
TESTS = test/application/* \
test/context/* \
test/request/* \
test/response/*
lint:
@./node_modules/.bin/eslint benchmarks lib test --fix
test:
@NODE_ENV=test node \
./node_modules/.bin/_mocha \
$(REQUIRED) \
$(TESTS) \
--bail
test-cov:
@NODE_ENV=test node \
./node_modules/.bin/istanbul cover \
./node_modules/.bin/_mocha \
-- -u exports \
$(REQUIRED) \
$(TESTS) \
--bail
test-travis: lint
@NODE_ENV=test node \
./node_modules/.bin/istanbul cover \
./node_modules/.bin/_mocha \
--report lcovonly \
-- -u exports \
$(REQUIRED) \
$(TESTS) \
--bail
bench:
@$(MAKE) -C benchmarks
.PHONY: lint test bench

View File

@ -4,7 +4,10 @@
"description": "Koa web app framework",
"main": "lib/application.js",
"scripts": {
"test": "make test"
"test": "jest --forceExit",
"test-cov": "npm run test -- --coverage",
"lint": "eslint benchmarks lib test --fix",
"bench": "make -C benchmarks"
},
"repository": "koajs/koa",
"keywords": [
@ -50,16 +53,24 @@
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^2.1.1",
"istanbul": "^0.4.0",
"mocha": "^3.2.0",
"should": "^6.0.3",
"should-http": "0.0.3",
"supertest": "^3.0.0",
"test-console": "^0.7.1"
"jest": "^20.0.0",
"supertest": "^3.0.0"
},
"engines": {
"node": ">= 6.0.0"
},
"files": [
"lib"
]
],
"jest": {
"testMatch": [
"**/test/!(helpers)/*.js"
],
"coverageReporters": [
"text-summary",
"lcov"
],
"bail": true,
"testEnvironment": "node"
}
}

View File

@ -1,5 +1,5 @@
env:
mocha: true
jest: true
rules:
space-before-blocks: [2, {functions: never, keywords: always}]

View File

@ -10,25 +10,25 @@ describe('app.context', () => {
app1.context.msg = 'hello';
const app2 = new Koa();
it('should merge properties', done => {
it('should merge properties', () => {
app1.use((ctx, next) => {
assert.equal(ctx.msg, 'hello');
ctx.status = 204;
});
request(app1.listen())
return request(app1.listen())
.get('/')
.expect(204, done);
.expect(204);
});
it('should not affect the original prototype', done => {
it('should not affect the original prototype', () => {
app2.use((ctx, next) => {
assert.equal(ctx.msg, undefined);
ctx.status = 204;
});
request(app2.listen())
return request(app2.listen())
.get('/')
.expect(204, done);
.expect(204);
});
});

View File

@ -15,7 +15,7 @@ describe('app', () => {
});
app.on('error', err => {
err.message.should.equal('boom');
assert.equal(err.message, 'boom');
done();
});

View File

@ -1,69 +1,71 @@
'use strict';
const stderr = require('test-console').stderr;
const assert = require('assert');
const Koa = require('../..');
const AssertionError = require('assert').AssertionError;
describe('app.onerror(err)', () => {
it('should throw an error if a non-error is given', done => {
const app = new Koa();
(() => app.onerror('foo')).should.throw(AssertionError, {message: 'non-error thrown: foo'});
done();
beforeEach(() => {
global.console = jest.genMockFromModule('console');
});
it('should do nothing if status is 404', done => {
afterEach(() => {
global.console = require('console');
});
it('should throw an error if a non-error is given', () => {
const app = new Koa();
assert.throws(() => {
app.onerror('foo');
}, AssertionError, 'non-error thrown: foo');
});
it('should do nothing if status is 404', () => {
const app = new Koa();
const err = new Error();
err.status = 404;
const output = stderr.inspectSync(() => app.onerror(err));
app.onerror(err);
output.should.eql([]);
done();
assert.deepEqual(console.error.mock.calls, []);
});
it('should do nothing if .silent', done => {
it('should do nothing if .silent', () => {
const app = new Koa();
app.silent = true;
const err = new Error();
const output = stderr.inspectSync(() => app.onerror(err));
app.onerror(err);
output.should.eql([]);
done();
assert.deepEqual(console.error.mock.calls, []);
});
it('should log the error to stderr', done => {
it('should log the error to stderr', () => {
const app = new Koa();
app.env = 'dev';
const err = new Error();
err.stack = 'Foo';
const output = stderr.inspectSync(() => app.onerror(err));
app.onerror(err);
output.should.eql(['\n', ' Foo\n', '\n']);
done();
const stderr = console.error.mock.calls.join('\n');
assert.deepEqual(stderr, '\n Foo\n');
});
it('should use err.toString() instad of err.stack', done => {
it('should use err.toString() instad of err.stack', () => {
const app = new Koa();
app.env = 'dev';
const err = new Error('mock stack null');
err.stack = null;
const output = stderr.inspectSync(() => app.onerror(err));
app.onerror(err);
output.should.eql(['\n', ' Error: mock stack null\n', '\n']);
done();
const stderr = console.error.mock.calls.join('\n');
assert.equal(stderr, '\n Error: mock stack null\n');
});
});

View File

@ -10,25 +10,25 @@ describe('app.request', () => {
app1.request.message = 'hello';
const app2 = new Koa();
it('should merge properties', done => {
it('should merge properties', () => {
app1.use((ctx, next) => {
assert.equal(ctx.request.message, 'hello');
ctx.status = 204;
});
request(app1.listen())
return request(app1.listen())
.get('/')
.expect(204, done);
.expect(204);
});
it('should not affect the original prototype', done => {
it('should not affect the original prototype', () => {
app2.use((ctx, next) => {
assert.equal(ctx.request.message, undefined);
ctx.status = 204;
});
request(app2.listen())
return request(app2.listen())
.get('/')
.expect(204, done);
.expect(204);
});
});

View File

@ -8,8 +8,16 @@ const Koa = require('../..');
const fs = require('fs');
describe('app.respond', () => {
beforeEach(() => {
global.console = jest.genMockFromModule('console');
});
afterEach(() => {
global.console = require('console');
});
describe('when ctx.respond === false', () => {
it('should function (ctx)', done => {
it('should function (ctx)', () => {
const app = new Koa();
app.use(ctx => {
@ -26,16 +34,15 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(200)
.expect('lol')
.end(done);
.expect('lol');
});
});
describe('when this.type === null', () => {
it('should not send Content-Type header', done => {
it('should not send Content-Type header', async () => {
const app = new Koa();
app.use(ctx => {
@ -45,19 +52,16 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(200)
.end((err, res) => {
if (err) return done(err);
res.should.not.have.header('content-type');
done();
});
.expect(200);
assert.equal(res.headers.hasOwnProperty('Content-Type'), false);
});
});
describe('when HEAD is used', () => {
it('should not respond with the body', done => {
it('should not respond with the body', async () => {
const app = new Koa();
app.use(ctx => {
@ -66,19 +70,16 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.head('/')
.expect(200)
.end((err, res) => {
if (err) return done(err);
res.should.have.header('Content-Type', 'text/plain; charset=utf-8');
res.should.have.header('Content-Length', '5');
assert(!res.text);
done();
});
.expect(200);
assert.equal(res.headers['content-type'], 'text/plain; charset=utf-8');
assert.equal(res.headers['content-length'], '5');
assert(!res.text);
});
it('should keep json headers', done => {
it('should keep json headers', async () => {
const app = new Koa();
app.use(ctx => {
@ -87,19 +88,16 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.head('/')
.expect(200)
.end((err, res) => {
if (err) return done(err);
res.should.have.header('Content-Type', 'application/json; charset=utf-8');
res.should.have.header('Content-Length', '17');
assert(!res.text);
done();
});
.expect(200);
assert.equal(res.headers['content-type'], 'application/json; charset=utf-8');
assert.equal(res.headers['content-length'], '17');
assert(!res.text);
});
it('should keep string headers', done => {
it('should keep string headers', async () => {
const app = new Koa();
app.use(ctx => {
@ -108,19 +106,16 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.head('/')
.expect(200)
.end((err, res) => {
if (err) return done(err);
res.should.have.header('Content-Type', 'text/plain; charset=utf-8');
res.should.have.header('Content-Length', '11');
assert(!res.text);
done();
});
.expect(200);
assert.equal(res.headers['content-type'], 'text/plain; charset=utf-8');
assert.equal(res.headers['content-length'], '11');
assert(!res.text);
});
it('should keep buffer headers', done => {
it('should keep buffer headers', async () => {
const app = new Koa();
app.use(ctx => {
@ -129,19 +124,16 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.head('/')
.expect(200)
.end((err, res) => {
if (err) return done(err);
res.should.have.header('Content-Type', 'application/octet-stream');
res.should.have.header('Content-Length', '11');
assert(!res.text);
done();
});
.expect(200);
assert.equal(res.headers['content-type'], 'application/octet-stream');
assert.equal(res.headers['content-length'], '11');
assert(!res.text);
});
it('should respond with a 404 if no body was set', done => {
it('should respond with a 404 if no body was set', () => {
const app = new Koa();
app.use(ctx => {
@ -150,12 +142,12 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
return request(server)
.head('/')
.expect(404, done);
.expect(404);
});
it('should respond with a 200 if body = ""', done => {
it('should respond with a 200 if body = ""', () => {
const app = new Koa();
app.use(ctx => {
@ -164,12 +156,12 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
return request(server)
.head('/')
.expect(200, done);
.expect(200);
});
it('should not overwrite the content-type', done => {
it('should not overwrite the content-type', () => {
const app = new Koa();
app.use(ctx => {
@ -179,27 +171,27 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
return request(server)
.head('/')
.expect('content-type', /application\/javascript/)
.expect(200, done);
.expect(200);
});
});
describe('when no middleware are present', () => {
it('should 404', done => {
it('should 404', () => {
const app = new Koa();
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(404, done);
.expect(404);
});
});
describe('when res has already been written to', () => {
it('should not cause an app error', done => {
it('should not cause an app error', () => {
const app = new Koa();
app.use((ctx, next) => {
@ -210,23 +202,16 @@ describe('app.respond', () => {
setTimeout(() => res.end('Goodbye'), 0);
});
let errorCaught = false;
app.on('error', err => errorCaught = err);
app.on('error', err => { throw err; });
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(200)
.end((err, res) => {
if (err) return done(err);
if (errorCaught) return done(errorCaught);
done();
});
.expect(200);
});
it('should send the right body', done => {
it('should send the right body', () => {
const app = new Koa();
app.use((ctx, next) => {
@ -244,16 +229,16 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(200)
.expect('HelloGoodbye', done);
.expect('HelloGoodbye');
});
});
describe('when .body is missing', () => {
describe('with status=400', () => {
it('should respond with the associated status message', done => {
it('should respond with the associated status message', () => {
const app = new Koa();
app.use(ctx => {
@ -262,16 +247,16 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(400)
.expect('Content-Length', '11')
.expect('Bad Request', done);
.expect('Bad Request');
});
});
describe('with status=204', () => {
it('should respond without a body', done => {
it('should respond without a body', async () => {
const app = new Koa();
app.use(ctx => {
@ -280,21 +265,17 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(204)
.expect('')
.end((err, res) => {
if (err) return done(err);
.expect('');
res.header.should.not.have.property('content-type');
done();
});
assert.equal(res.headers.hasOwnProperty('content-type'), false);
});
});
describe('with status=205', () => {
it('should respond without a body', done => {
it('should respond without a body', async () => {
const app = new Koa();
app.use(ctx => {
@ -303,21 +284,17 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(205)
.expect('')
.end((err, res) => {
if (err) return done(err);
.expect('');
res.header.should.not.have.property('content-type');
done();
});
assert.equal(res.headers.hasOwnProperty('content-type'), false);
});
});
describe('with status=304', () => {
it('should respond without a body', done => {
it('should respond without a body', async () => {
const app = new Koa();
app.use(ctx => {
@ -326,21 +303,17 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(304)
.expect('')
.end((err, res) => {
if (err) return done(err);
.expect('');
res.header.should.not.have.property('content-type');
done();
});
assert.equal(res.headers.hasOwnProperty('content-type'), false);
});
});
describe('with custom status=700', () => {
it('should respond with the associated status message', done => {
it('should respond with the associated status message', async () => {
const app = new Koa();
statuses['700'] = 'custom status';
@ -350,20 +323,17 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(700)
.expect('custom status')
.end((err, res) => {
if (err) return done(err);
res.res.statusMessage.should.equal('custom status');
done();
});
.expect('custom status');
assert.equal(res.res.statusMessage, 'custom status');
});
});
describe('with custom statusMessage=ok', () => {
it('should respond with the custom status message', done => {
it('should respond with the custom status message', async () => {
const app = new Koa();
app.use(ctx => {
@ -373,20 +343,17 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(200)
.expect('ok')
.end((err, res) => {
if (err) return done(err);
res.res.statusMessage.should.equal('ok');
done();
});
.expect('ok');
assert.equal(res.res.statusMessage, 'ok');
});
});
describe('with custom status without message', () => {
it('should respond with the status code number', done => {
it('should respond with the status code number', () => {
const app = new Koa();
app.use(ctx => {
@ -395,16 +362,16 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(701)
.expect('701', done);
.expect('701');
});
});
});
describe('when .body is a null', () => {
it('should respond 204 by default', done => {
it('should respond 204 by default', async () => {
const app = new Koa();
app.use(ctx => {
@ -413,19 +380,15 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(204)
.expect('')
.end((err, res) => {
if (err) return done(err);
.expect('');
res.header.should.not.have.property('content-type');
done();
});
assert.equal(res.headers.hasOwnProperty('content-type'), false);
});
it('should respond 204 with status=200', done => {
it('should respond 204 with status=200', async () => {
const app = new Koa();
app.use(ctx => {
@ -435,19 +398,15 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(204)
.expect('')
.end((err, res) => {
if (err) return done(err);
.expect('');
res.header.should.not.have.property('content-type');
done();
});
assert.equal(res.headers.hasOwnProperty('content-type'), false);
});
it('should respond 205 with status=205', done => {
it('should respond 205 with status=205', async () => {
const app = new Koa();
app.use(ctx => {
@ -457,19 +416,15 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(205)
.expect('')
.end((err, res) => {
if (err) return done(err);
.expect('');
res.header.should.not.have.property('content-type');
done();
});
assert.equal(res.headers.hasOwnProperty('content-type'), false);
});
it('should respond 304 with status=304', done => {
it('should respond 304 with status=304', async () => {
const app = new Koa();
app.use(ctx => {
@ -479,21 +434,17 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(304)
.expect('')
.end((err, res) => {
if (err) return done(err);
.expect('');
res.header.should.not.have.property('content-type');
done();
});
assert.equal(res.headers.hasOwnProperty('content-type'), false);
});
});
describe('when .body is a string', () => {
it('should respond', done => {
it('should respond', () => {
const app = new Koa();
app.use(ctx => {
@ -502,9 +453,9 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect('Hello', done);
.expect('Hello');
});
});
@ -526,7 +477,7 @@ describe('app.respond', () => {
});
describe('when .body is a Stream', () => {
it('should respond', done => {
it('should respond', async () => {
const app = new Koa();
app.use(ctx => {
@ -536,19 +487,16 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect('Content-Type', 'application/json; charset=utf-8')
.end((err, res) => {
if (err) return done(err);
const pkg = require('../../package');
res.should.not.have.header('Content-Length');
res.body.should.eql(pkg);
done();
});
.expect('Content-Type', 'application/json; charset=utf-8');
const pkg = require('../../package');
assert.equal(res.headers.hasOwnProperty('content-length'), false);
assert.deepEqual(res.body, pkg);
});
it('should strip content-length when overwriting', done => {
it('should strip content-length when overwriting', async () => {
const app = new Koa();
app.use(ctx => {
@ -559,19 +507,16 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect('Content-Type', 'application/json; charset=utf-8')
.end((err, res) => {
if (err) return done(err);
const pkg = require('../../package');
res.should.not.have.header('Content-Length');
res.body.should.eql(pkg);
done();
});
.expect('Content-Type', 'application/json; charset=utf-8');
const pkg = require('../../package');
assert.equal(res.headers.hasOwnProperty('content-length'), false);
assert.deepEqual(res.body, pkg);
});
it('should keep content-length if not overwritten', done => {
it('should keep content-length if not overwritten', async () => {
const app = new Koa();
app.use(ctx => {
@ -582,20 +527,17 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect('Content-Type', 'application/json; charset=utf-8')
.end((err, res) => {
if (err) return done(err);
const pkg = require('../../package');
res.should.have.header('Content-Length');
res.body.should.eql(pkg);
done();
});
.expect('Content-Type', 'application/json; charset=utf-8');
const pkg = require('../../package');
assert.equal(res.headers.hasOwnProperty('content-length'), true);
assert.deepEqual(res.body, pkg);
});
it('should keep content-length if overwritten with the same stream',
done => {
async () => {
const app = new Koa();
app.use(ctx => {
@ -608,16 +550,13 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect('Content-Type', 'application/json; charset=utf-8')
.end((err, res) => {
if (err) return done(err);
const pkg = require('../../package');
res.should.have.header('Content-Length');
res.body.should.eql(pkg);
done();
});
.expect('Content-Type', 'application/json; charset=utf-8');
const pkg = require('../../package');
assert.equal(res.headers.hasOwnProperty('content-length'), true);
assert.deepEqual(res.body, pkg);
});
it('should handle errors', done => {
@ -637,7 +576,7 @@ describe('app.respond', () => {
.end(done);
});
it('should handle errors when no content status', done => {
it('should handle errors when no content status', () => {
const app = new Koa();
app.use(ctx => {
@ -647,9 +586,9 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(204, done);
.expect(204);
});
it('should handle all intermediate stream body errors', done => {
@ -665,12 +604,13 @@ describe('app.respond', () => {
request(server)
.get('/')
.expect(404, done);
.expect(404)
.end(done);
});
});
describe('when .body is an Object', () => {
it('should respond with json', done => {
it('should respond with json', () => {
const app = new Koa();
app.use(ctx => {
@ -679,10 +619,10 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect('Content-Type', 'application/json; charset=utf-8')
.expect('{"hello":"world"}', done);
.expect('{"hello":"world"}');
});
});
@ -695,7 +635,7 @@ describe('app.respond', () => {
});
app.on('error', err => {
err.message.should.equal('boom');
assert.equal(err.message, 'boom');
done();
});
@ -705,7 +645,7 @@ describe('app.respond', () => {
});
describe('with an .expose property', () => {
it('should expose the message', done => {
it('should expose the message', () => {
const app = new Koa();
app.use(ctx => {
@ -715,15 +655,14 @@ describe('app.respond', () => {
throw err;
});
request(app.listen())
return request(app.listen())
.get('/')
.expect(403, 'sorry!')
.end(done);
.expect(403, 'sorry!');
});
});
describe('with a .status property', () => {
it('should respond with .status', done => {
it('should respond with .status', () => {
const app = new Koa();
app.use(ctx => {
@ -732,14 +671,13 @@ describe('app.respond', () => {
throw err;
});
request(app.listen())
return request(app.listen())
.get('/')
.expect(403, 'Forbidden')
.end(done);
.expect(403, 'Forbidden');
});
});
it('should respond with 500', done => {
it('should respond with 500', () => {
const app = new Koa();
app.use(ctx => {
@ -748,13 +686,12 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(500, 'Internal Server Error')
.end(done);
.expect(500, 'Internal Server Error');
});
it('should be catchable', done => {
it('should be catchable', () => {
const app = new Koa();
app.use((ctx, next) => {
@ -771,15 +708,14 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(200, 'Got error')
.end(done);
.expect(200, 'Got error');
});
});
describe('when status and body property', () => {
it('should 200', done => {
it('should 200', () => {
const app = new Koa();
app.use(ctx => {
@ -790,13 +726,13 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(200)
.expect('hello', done);
.expect('hello');
});
it('should 204', done => {
it('should 204', async () => {
const app = new Koa();
app.use(ctx => {
@ -808,13 +744,11 @@ describe('app.respond', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(204)
.end((err, res) => {
res.should.not.have.header('content-type');
done(err);
});
.expect(204);
assert.equal(res.headers.hasOwnProperty('content-type'), false);
});
});
});

View File

@ -10,25 +10,25 @@ describe('app.response', () => {
app1.response.msg = 'hello';
const app2 = new Koa();
it('should merge properties', done => {
it('should merge properties', () => {
app1.use((ctx, next) => {
assert.equal(ctx.response.msg, 'hello');
ctx.status = 204;
});
request(app1.listen())
return request(app1.listen())
.get('/')
.expect(204, done);
.expect(204);
});
it('should not affect the original prototype', done => {
it('should not affect the original prototype', () => {
app2.use((ctx, next) => {
assert.equal(ctx.response.msg, undefined);
ctx.status = 204;
});
request(app2.listen())
return request(app2.listen())
.get('/')
.expect(204, done);
.expect(204);
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const Koa = require('../..');
describe('app.toJSON()', () => {
@ -8,10 +9,10 @@ describe('app.toJSON()', () => {
const app = new Koa();
const obj = app.toJSON();
obj.should.eql({
assert.deepEqual({
subdomainOffset: 2,
proxy: false,
env: 'test'
});
}, obj);
});
});

View File

@ -6,7 +6,7 @@ const assert = require('assert');
const Koa = require('../..');
describe('app.use(fn)', () => {
it('should compose middleware', done => {
it('should compose middleware', async () => {
const app = new Koa();
const calls = [];
@ -33,17 +33,14 @@ describe('app.use(fn)', () => {
const server = app.listen();
request(server)
await request(server)
.get('/')
.expect(404)
.end(err => {
if (err) return done(err);
calls.should.eql([1, 2, 3, 4, 5, 6]);
done();
});
.expect(404);
assert.deepEqual(calls, [1, 2, 3, 4, 5, 6]);
});
it('should compose mixed middleware', done => {
it('should compose mixed middleware', async () => {
process.once('deprecation', () => {}); // silence deprecation message
const app = new Koa();
const calls = [];
@ -70,45 +67,43 @@ describe('app.use(fn)', () => {
const server = app.listen();
request(server)
await request(server)
.get('/')
.expect(404)
.end(err => {
if (err) return done(err);
calls.should.eql([1, 2, 3, 4, 5, 6]);
done();
});
.expect(404);
assert.deepEqual(calls, [1, 2, 3, 4, 5, 6]);
});
// https://github.com/koajs/koa/pull/530#issuecomment-148138051
it('should catch thrown errors in non-async functions', done => {
it('should catch thrown errors in non-async functions', () => {
const app = new Koa();
app.use(ctx => ctx.throw('Not Found', 404));
request(app.listen())
return request(app.listen())
.get('/')
.expect(404)
.end(done);
.expect(404);
});
it('should accept both generator and function middleware', done => {
it('should accept both generator and function middleware', () => {
process.once('deprecation', () => {}); // silence deprecation message
const app = new Koa();
app.use((ctx, next) => { return next(); });
app.use((ctx, next) => next());
app.use(function * (next){ this.body = 'generator'; });
request(app.listen())
return request(app.listen())
.get('/')
.expect(200)
.expect('generator', done);
.expect('generator');
});
it('should throw error for non function', () => {
const app = new Koa();
[null, undefined, 0, false, 'not a function'].forEach(v => (() => app.use(v)).should.throw('middleware must be a function!'));
[null, undefined, 0, false, 'not a function'].forEach(v => {
assert.throws(() => app.use(v), /middleware must be a function!/);
});
});
it('should output deprecation message for generator functions', done => {

View File

@ -12,8 +12,8 @@ describe('ctx.assert(value, status)', () => {
ctx.assert(false, 404);
throw new Error('asdf');
} catch (err) {
assert(404 == err.status);
assert(err.expose);
assert.equal(err.status, 404);
assert.strictEqual(err.expose, true);
}
});
});

View File

@ -1,11 +1,12 @@
'use strict';
const assert = require('assert');
const request = require('supertest');
const Koa = require('../..');
describe('ctx.cookies.set()', () => {
it('should set an unsigned cookie', done => {
it('should set an unsigned cookie', async () => {
const app = new Koa();
app.use((ctx, next) => {
@ -15,21 +16,17 @@ describe('ctx.cookies.set()', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(204)
.end((err, res) => {
if (err) return done(err);
.expect(204);
res.headers['set-cookie'].some(cookie => /^name=/.test(cookie)).should.be.ok;
done();
});
const cookie = res.headers['set-cookie'].some(cookie => /^name=/.test(cookie));
assert.equal(cookie, true);
});
describe('with .signed', () => {
describe('when no .keys are set', () => {
it('should error', done => {
it('should error', () => {
const app = new Koa();
app.use((ctx, next) => {
@ -40,13 +37,13 @@ describe('ctx.cookies.set()', () => {
}
});
request(app.listen())
return request(app.listen())
.get('/')
.expect('.keys required for signed cookies', done);
.expect('.keys required for signed cookies');
});
});
it('should send a signed cookie', done => {
it('should send a signed cookie', async () => {
const app = new Koa();
app.keys = ['a', 'b'];
@ -58,25 +55,19 @@ describe('ctx.cookies.set()', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(204)
.end((err, res) => {
if (err) return done(err);
.expect(204);
const cookies = res.headers['set-cookie'];
const cookies = res.headers['set-cookie'];
cookies.some(cookie => /^name=/.test(cookie)).should.be.ok;
cookies.some(cookie => /^name\.sig=/.test(cookie)).should.be.ok;
done();
});
assert.equal(cookies.some(cookie => /^name=/.test(cookie)), true);
assert.equal(cookies.some(cookie => /(,|^)name\.sig=/.test(cookie)), true);
});
});
describe('with secure', () => {
it('should get secure from request', done => {
it('should get secure from request', async () => {
const app = new Koa();
app.proxy = true;
@ -89,22 +80,15 @@ describe('ctx.cookies.set()', () => {
const server = app.listen();
request(server)
.get('/')
.set('x-forwarded-proto', 'https') // mock secure
.expect(204)
.end((err, res) => {
if (err) return done(err);
const res = await request(server)
.get('/')
.set('x-forwarded-proto', 'https') // mock secure
.expect(204);
const cookies = res.headers['set-cookie'];
cookies.some(cookie => /^name=/.test(cookie)).should.be.ok;
cookies.some(cookie => /^name\.sig=/.test(cookie)).should.be.ok;
cookies.every(cookie => /secure/.test(cookie)).should.be.ok;
done();
});
const cookies = res.headers['set-cookie'];
assert.equal(cookies.some(cookie => /^name=/.test(cookie)), true);
assert.equal(cookies.some(cookie => /(,|^)name\.sig=/.test(cookie)), true);
assert.equal(cookies.every(cookie => /secure/.test(cookie)), true);
});
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
describe('ctx.inspect()', () => {
@ -8,6 +9,6 @@ describe('ctx.inspect()', () => {
const ctx = context();
const toJSON = ctx.toJSON(ctx);
toJSON.should.eql(ctx.inspect());
assert.deepEqual(toJSON, ctx.inspect());
});
});

View File

@ -7,7 +7,15 @@ const Koa = require('../..');
const context = require('../helpers/context');
describe('ctx.onerror(err)', () => {
it('should respond', done => {
beforeEach(() => {
global.console = jest.genMockFromModule('console');
});
afterEach(() => {
global.console = require('console');
});
it('should respond', () => {
const app = new Koa();
app.use((ctx, next) => {
@ -18,15 +26,14 @@ describe('ctx.onerror(err)', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(418)
.expect('Content-Type', 'text/plain; charset=utf-8')
.expect('Content-Length', '4')
.end(done);
.expect('Content-Length', '4');
});
it('should unset all headers', done => {
it('should unset all headers', async () => {
const app = new Koa();
app.use((ctx, next) => {
@ -39,22 +46,17 @@ describe('ctx.onerror(err)', () => {
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(418)
.expect('Content-Type', 'text/plain; charset=utf-8')
.expect('Content-Length', '4')
.end((err, res) => {
if (err) return done(err);
.expect('Content-Length', '4');
res.headers.should.not.have.property('vary');
res.headers.should.not.have.property('x-csrf-token');
done();
});
assert.equal(res.headers.hasOwnProperty('vary'), false);
assert.equal(res.headers.hasOwnProperty('x-csrf-token'), false);
});
it('should set headers specified in the error', done => {
it('should set headers specified in the error', async () => {
const app = new Koa();
app.use((ctx, next) => {
@ -73,27 +75,22 @@ describe('ctx.onerror(err)', () => {
const server = app.listen();
request(server)
.get('/')
.expect(418)
.expect('Content-Type', 'text/plain; charset=utf-8')
.expect('X-New-Header', 'Value')
.end((err, res) => {
if (err) return done(err);
const res = await request(server)
.get('/')
.expect(418)
.expect('Content-Type', 'text/plain; charset=utf-8')
.expect('X-New-Header', 'Value');
res.headers.should.not.have.property('vary');
res.headers.should.not.have.property('x-csrf-token');
done();
});
assert.equal(res.headers.hasOwnProperty('vary'), false);
assert.equal(res.headers.hasOwnProperty('x-csrf-token'), false);
});
it('should ignore error after headerSent', done => {
const app = new Koa();
app.on('error', err => {
err.message.should.equal('mock error');
err.headerSent.should.equal(true);
assert.equal(err.message, 'mock error');
assert.equal(err.headerSent, true);
done();
});
@ -106,14 +103,14 @@ describe('ctx.onerror(err)', () => {
});
request(app.listen())
.get('/')
.expect('X-Foo', 'Bar')
.expect(200, () => {});
.get('/')
.expect('X-Foo', 'Bar')
.expect(200, () => {});
});
describe('when invalid err.status', () => {
describe('not number', () => {
it('should respond 500', done => {
it('should respond 500', () => {
const app = new Koa();
app.use((ctx, next) => {
@ -125,16 +122,16 @@ describe('ctx.onerror(err)', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(500)
.expect('Content-Type', 'text/plain; charset=utf-8')
.expect('Internal Server Error', done);
.expect('Internal Server Error');
});
});
describe('not http status code', () => {
it('should respond 500', done => {
it('should respond 500', () => {
const app = new Koa();
app.use((ctx, next) => {
@ -146,17 +143,17 @@ describe('ctx.onerror(err)', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(500)
.expect('Content-Type', 'text/plain; charset=utf-8')
.expect('Internal Server Error', done);
.expect('Internal Server Error');
});
});
});
describe('when non-error thrown', () => {
it('should response non-error thrown message', done => {
it('should response non-error thrown message', () => {
const app = new Koa();
app.use((ctx, next) => {
@ -165,11 +162,11 @@ describe('ctx.onerror(err)', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(500)
.expect('Content-Type', 'text/plain; charset=utf-8')
.expect('Internal Server Error', done);
.expect('Internal Server Error');
});
it('should use res.getHeaderNames() accessor when available', () => {

View File

@ -6,7 +6,7 @@ const assert = require('assert');
const Koa = require('../..');
describe('ctx.state', () => {
it('should provide a ctx.state namespace', done => {
it('should provide a ctx.state namespace', () => {
const app = new Koa();
app.use(ctx => {
@ -15,9 +15,8 @@ describe('ctx.state', () => {
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(404)
.end(done);
.expect(404);
});
});

View File

@ -5,113 +5,106 @@ const context = require('../helpers/context');
const assert = require('assert');
describe('ctx.throw(msg)', () => {
it('should set .status to 500', done => {
it('should set .status to 500', () => {
const ctx = context();
try {
ctx.throw('boom');
} catch (err) {
assert(500 == err.status);
assert(!err.expose);
done();
assert.equal(err.status, 500);
assert.equal(err.expose, false);
}
});
});
describe('ctx.throw(err)', () => {
it('should set .status to 500', done => {
it('should set .status to 500', () => {
const ctx = context();
const err = new Error('test');
try {
ctx.throw(err);
} catch (err) {
assert(500 == err.status);
assert('test' == err.message);
assert(!err.expose);
done();
assert.equal(err.status, 500);
assert.equal(err.message, 'test');
assert.equal(err.expose, false);
}
});
});
describe('ctx.throw(err, status)', () => {
it('should throw the error and set .status', done => {
it('should throw the error and set .status', () => {
const ctx = context();
const error = new Error('test');
try {
ctx.throw(error, 422);
} catch (err) {
assert(422 == err.status);
assert('test' == err.message);
assert(true === err.expose);
done();
assert.equal(err.status, 422);
assert.equal(err.message, 'test');
assert.equal(err.expose, true);
}
});
});
describe('ctx.throw(status, err)', () => {
it('should throw the error and set .status', done => {
it('should throw the error and set .status', () => {
const ctx = context();
const error = new Error('test');
try {
ctx.throw(422, error);
} catch (err) {
assert(422 == err.status);
assert('test' == err.message);
assert(true === err.expose);
done();
assert.equal(err.status, 422);
assert.equal(err.message, 'test');
assert.equal(err.expose, true);
}
});
});
describe('ctx.throw(msg, status)', () => {
it('should throw an error', done => {
it('should throw an error', () => {
const ctx = context();
try {
ctx.throw('name required', 400);
} catch (err) {
assert('name required' == err.message);
assert(400 == err.status);
assert(true === err.expose);
done();
assert.equal(err.message, 'name required');
assert.equal(err.status, 400);
assert.equal(err.expose, true);
}
});
});
describe('ctx.throw(status, msg)', () => {
it('should throw an error', done => {
it('should throw an error', () => {
const ctx = context();
try {
ctx.throw(400, 'name required');
} catch (err) {
assert('name required' == err.message);
assert(400 == err.status);
assert(true === err.expose);
done();
assert.equal(err.message, 'name required');
assert.equal(400, err.status);
assert.equal(true, err.expose);
}
});
});
describe('ctx.throw(status)', () => {
it('should throw an error', done => {
it('should throw an error', () => {
const ctx = context();
try {
ctx.throw(400);
} catch (err) {
assert('Bad Request' == err.message);
assert(400 == err.status);
assert(true === err.expose);
done();
assert.equal(err.message, 'Bad Request');
assert.equal(err.status, 400);
assert.equal(err.expose, true);
}
});
describe('when not valid status', () => {
it('should not expose', done => {
it('should not expose', () => {
const ctx = context();
try {
@ -119,31 +112,29 @@ describe('ctx.throw(status)', () => {
err.status = -1;
ctx.throw(err);
} catch (err) {
assert('some error' == err.message);
assert(!err.expose);
done();
assert.equal(err.message, 'some error');
assert.equal(err.expose, false);
}
});
});
});
describe('ctx.throw(status, msg, props)', () => {
it('should mixin props', done => {
it('should mixin props', () => {
const ctx = context();
try {
ctx.throw(400, 'msg', { prop: true });
} catch (err) {
assert('msg' == err.message);
assert(400 == err.status);
assert(true === err.expose);
assert(true === err.prop);
done();
assert.equal(err.message, 'msg');
assert.equal(err.status, 400);
assert.equal(err.expose, true);
assert.equal(err.prop, true);
}
});
describe('when props include status', () => {
it('should be ignored', done => {
it('should be ignored', () => {
const ctx = context();
try {
@ -152,60 +143,56 @@ describe('ctx.throw(status, msg, props)', () => {
status: -1
});
} catch (err) {
assert('msg' == err.message);
assert(400 == err.status);
assert(true === err.expose);
assert(true === err.prop);
done();
assert.equal(err.message, 'msg');
assert.equal(err.status, 400);
assert.equal(err.expose, true);
assert.equal(err.prop, true);
}
});
});
});
describe('ctx.throw(msg, props)', () => {
it('should mixin props', done => {
it('should mixin props', () => {
const ctx = context();
try {
ctx.throw('msg', { prop: true });
} catch (err) {
assert('msg' == err.message);
assert(500 == err.status);
assert(false === err.expose);
assert(true === err.prop);
done();
assert.equal(err.message, 'msg');
assert.equal(err.status, 500);
assert.equal(err.expose, false);
assert.equal(err.prop, true);
}
});
});
describe('ctx.throw(status, props)', () => {
it('should mixin props', done => {
it('should mixin props', () => {
const ctx = context();
try {
ctx.throw(400, { prop: true });
} catch (err) {
assert('Bad Request' == err.message);
assert(400 == err.status);
assert(true === err.expose);
assert(true === err.prop);
done();
assert.equal(err.message, 'Bad Request');
assert.equal(err.status, 400);
assert.equal(err.expose, true);
assert.equal(err.prop, true);
}
});
});
describe('ctx.throw(err, props)', () => {
it('should mixin props', done => {
it('should mixin props', () => {
const ctx = context();
try {
ctx.throw(new Error('test'), { prop: true });
} catch (err) {
assert('test' == err.message);
assert(500 == err.status);
assert(false === err.expose);
assert(true === err.prop);
done();
assert.equal(err.message, 'test');
assert.equal(err.status, 500);
assert.equal(err.expose, false);
assert.equal(err.prop, true);
}
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
describe('ctx.toJSON()', () => {
@ -17,21 +18,21 @@ describe('ctx.toJSON()', () => {
const req = obj.request;
const res = obj.response;
req.should.eql({
assert.deepEqual({
method: 'POST',
url: '/items',
header: {
'content-type': 'text/plain'
}
});
}, req);
res.should.eql({
assert.deepEqual({
status: 200,
message: 'OK',
header: {
'content-type': 'text/html; charset=utf-8',
'content-length': '10'
}
});
}, res);
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
describe('ctx.accepts(types)', () => {
@ -9,7 +10,7 @@ describe('ctx.accepts(types)', () => {
it('should return all accepted types', () => {
const ctx = context();
ctx.req.headers.accept = 'application/*;q=0.2, image/jpeg;q=0.8, text/html, text/plain';
ctx.accepts().should.eql(['text/html', 'text/plain', 'image/jpeg', 'application/*']);
assert.deepEqual(ctx.accepts(), ['text/html', 'text/plain', 'image/jpeg', 'application/*']);
});
});
});
@ -19,14 +20,14 @@ describe('ctx.accepts(types)', () => {
it('should return false', () => {
const ctx = context();
ctx.req.headers.accept = 'application/*;q=0.2, image/jpeg;q=0.8, text/html, text/plain';
ctx.accepts('image/png', 'image/tiff').should.be.false;
assert.equal(ctx.accepts('image/png', 'image/tiff'), false);
});
});
describe('when Accept is not populated', () => {
it('should return the first type', () => {
const ctx = context();
ctx.accepts('text/html', 'text/plain', 'image/jpeg', 'application/*').should.equal('text/html');
assert.equal(ctx.accepts('text/html', 'text/plain', 'image/jpeg', 'application/*'), 'text/html');
});
});
});
@ -35,11 +36,11 @@ describe('ctx.accepts(types)', () => {
it('should convert to mime types', () => {
const ctx = context();
ctx.req.headers.accept = 'text/plain, text/html';
ctx.accepts('html').should.equal('html');
ctx.accepts('.html').should.equal('.html');
ctx.accepts('txt').should.equal('txt');
ctx.accepts('.txt').should.equal('.txt');
ctx.accepts('png').should.be.false;
assert.equal(ctx.accepts('html'), 'html');
assert.equal(ctx.accepts('.html'), '.html');
assert.equal(ctx.accepts('txt'), 'txt');
assert.equal(ctx.accepts('.txt'), '.txt');
assert.equal(ctx.accepts('png'), false);
});
});
@ -47,8 +48,8 @@ describe('ctx.accepts(types)', () => {
it('should return the first match', () => {
const ctx = context();
ctx.req.headers.accept = 'text/plain, text/html';
ctx.accepts(['png', 'text', 'html']).should.equal('text');
ctx.accepts(['png', 'html']).should.equal('html');
assert.equal(ctx.accepts(['png', 'text', 'html']), 'text');
assert.equal(ctx.accepts(['png', 'html']), 'html');
});
});
@ -56,8 +57,8 @@ describe('ctx.accepts(types)', () => {
it('should return the first match', () => {
const ctx = context();
ctx.req.headers.accept = 'text/plain, text/html';
ctx.accepts('png', 'text', 'html').should.equal('text');
ctx.accepts('png', 'html').should.equal('html');
assert.equal(ctx.accepts('png', 'text', 'html'), 'text');
assert.equal(ctx.accepts('png', 'html'), 'html');
});
});
@ -65,8 +66,8 @@ describe('ctx.accepts(types)', () => {
it('should return the type', () => {
const ctx = context();
ctx.req.headers.accept = 'text/plain, text/html';
ctx.accepts('text/html').should.equal('text/html');
ctx.accepts('text/plain').should.equal('text/plain');
assert.equal(ctx.accepts('text/html'), 'text/html');
assert.equal(ctx.accepts('text/plain'), 'text/plain');
});
});
@ -74,9 +75,9 @@ describe('ctx.accepts(types)', () => {
it('should return the type', () => {
const ctx = context();
ctx.req.headers.accept = 'application/json, */*';
ctx.accepts('text/html').should.equal('text/html');
ctx.accepts('text/plain').should.equal('text/plain');
ctx.accepts('image/png').should.equal('image/png');
assert.equal(ctx.accepts('text/html'), 'text/html');
assert.equal(ctx.accepts('text/plain'), 'text/plain');
assert.equal(ctx.accepts('image/png'), 'image/png');
});
});
@ -84,10 +85,10 @@ describe('ctx.accepts(types)', () => {
it('should return the type', () => {
const ctx = context();
ctx.req.headers.accept = 'application/json, text/*';
ctx.accepts('text/html').should.equal('text/html');
ctx.accepts('text/plain').should.equal('text/plain');
ctx.accepts('image/png').should.be.false;
ctx.accepts('png').should.be.false;
assert.equal(ctx.accepts('text/html'), 'text/html');
assert.equal(ctx.accepts('text/plain'), 'text/plain');
assert.equal(ctx.accepts('image/png'), false);
assert.equal(ctx.accepts('png'), false);
});
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
describe('ctx.acceptsCharsets()', () => {
@ -9,7 +10,7 @@ describe('ctx.acceptsCharsets()', () => {
it('should return accepted types', () => {
const ctx = context();
ctx.req.headers['accept-charset'] = 'utf-8, iso-8859-1;q=0.2, utf-7;q=0.5';
ctx.acceptsCharsets().should.eql(['utf-8', 'utf-7', 'iso-8859-1']);
assert.deepEqual(ctx.acceptsCharsets(), ['utf-8', 'utf-7', 'iso-8859-1']);
});
});
});
@ -20,7 +21,7 @@ describe('ctx.acceptsCharsets()', () => {
it('should return the best fit', () => {
const ctx = context();
ctx.req.headers['accept-charset'] = 'utf-8, iso-8859-1;q=0.2, utf-7;q=0.5';
ctx.acceptsCharsets('utf-7', 'utf-8').should.equal('utf-8');
assert.equal(ctx.acceptsCharsets('utf-7', 'utf-8'), 'utf-8');
});
});
@ -28,7 +29,7 @@ describe('ctx.acceptsCharsets()', () => {
it('should return false', () => {
const ctx = context();
ctx.req.headers['accept-charset'] = 'utf-8, iso-8859-1;q=0.2, utf-7;q=0.5';
ctx.acceptsCharsets('utf-16').should.be.false;
assert.equal(ctx.acceptsCharsets('utf-16'), false);
});
});
});
@ -36,7 +37,7 @@ describe('ctx.acceptsCharsets()', () => {
describe('when Accept-Charset is not populated', () => {
it('should return the first type', () => {
const ctx = context();
ctx.acceptsCharsets('utf-7', 'utf-8').should.equal('utf-7');
assert.equal(ctx.acceptsCharsets('utf-7', 'utf-8'), 'utf-7');
});
});
});
@ -45,7 +46,7 @@ describe('ctx.acceptsCharsets()', () => {
it('should return the best fit', () => {
const ctx = context();
ctx.req.headers['accept-charset'] = 'utf-8, iso-8859-1;q=0.2, utf-7;q=0.5';
ctx.acceptsCharsets(['utf-7', 'utf-8']).should.equal('utf-8');
assert.equal(ctx.acceptsCharsets(['utf-7', 'utf-8']), 'utf-8');
});
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
describe('ctx.acceptsEncodings()', () => {
@ -9,16 +10,16 @@ describe('ctx.acceptsEncodings()', () => {
it('should return accepted types', () => {
const ctx = context();
ctx.req.headers['accept-encoding'] = 'gzip, compress;q=0.2';
ctx.acceptsEncodings().should.eql(['gzip', 'compress', 'identity']);
ctx.acceptsEncodings('gzip', 'compress').should.equal('gzip');
assert.deepEqual(ctx.acceptsEncodings(), ['gzip', 'compress', 'identity']);
assert.equal(ctx.acceptsEncodings('gzip', 'compress'), 'gzip');
});
});
describe('when Accept-Encoding is not populated', () => {
it('should return identity', () => {
const ctx = context();
ctx.acceptsEncodings().should.eql(['identity']);
ctx.acceptsEncodings('gzip', 'deflate', 'identity').should.equal('identity');
assert.deepEqual(ctx.acceptsEncodings(), ['identity']);
assert.equal(ctx.acceptsEncodings('gzip', 'deflate', 'identity'), 'identity');
});
});
});
@ -27,8 +28,8 @@ describe('ctx.acceptsEncodings()', () => {
it('should return the best fit', () => {
const ctx = context();
ctx.req.headers['accept-encoding'] = 'gzip, compress;q=0.2';
ctx.acceptsEncodings('compress', 'gzip').should.eql('gzip');
ctx.acceptsEncodings('gzip', 'compress').should.eql('gzip');
assert.equal(ctx.acceptsEncodings('compress', 'gzip'), 'gzip');
assert.equal(ctx.acceptsEncodings('gzip', 'compress'), 'gzip');
});
});
@ -36,7 +37,7 @@ describe('ctx.acceptsEncodings()', () => {
it('should return the best fit', () => {
const ctx = context();
ctx.req.headers['accept-encoding'] = 'gzip, compress;q=0.2';
ctx.acceptsEncodings(['compress', 'gzip']).should.eql('gzip');
assert.equal(ctx.acceptsEncodings(['compress', 'gzip']), 'gzip');
});
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
describe('ctx.acceptsLanguages(langs)', () => {
@ -9,7 +10,7 @@ describe('ctx.acceptsLanguages(langs)', () => {
it('should return accepted types', () => {
const ctx = context();
ctx.req.headers['accept-language'] = 'en;q=0.8, es, pt';
ctx.acceptsLanguages().should.eql(['es', 'pt', 'en']);
assert.deepEqual(ctx.acceptsLanguages(), ['es', 'pt', 'en']);
});
});
});
@ -20,7 +21,7 @@ describe('ctx.acceptsLanguages(langs)', () => {
it('should return the best fit', () => {
const ctx = context();
ctx.req.headers['accept-language'] = 'en;q=0.8, es, pt';
ctx.acceptsLanguages('es', 'en').should.equal('es');
assert.equal(ctx.acceptsLanguages('es', 'en'), 'es');
});
});
@ -28,7 +29,7 @@ describe('ctx.acceptsLanguages(langs)', () => {
it('should return false', () => {
const ctx = context();
ctx.req.headers['accept-language'] = 'en;q=0.8, es, pt';
ctx.acceptsLanguages('fr', 'au').should.be.false;
assert.equal(ctx.acceptsLanguages('fr', 'au'), false);
});
});
});
@ -36,7 +37,7 @@ describe('ctx.acceptsLanguages(langs)', () => {
describe('when Accept-Language is not populated', () => {
it('should return the first type', () => {
const ctx = context();
ctx.acceptsLanguages('es', 'en').should.equal('es');
assert.equal(ctx.acceptsLanguages('es', 'en'), 'es');
});
});
});
@ -45,7 +46,7 @@ describe('ctx.acceptsLanguages(langs)', () => {
it('should return the best fit', () => {
const ctx = context();
ctx.req.headers['accept-language'] = 'en;q=0.8, es, pt';
ctx.acceptsLanguages(['es', 'en']).should.equal('es');
assert.equal(ctx.acceptsLanguages(['es', 'en']), 'es');
});
});
});

View File

@ -24,13 +24,13 @@ describe('req.charset', () => {
it('should return the charset', () => {
const req = request();
req.header['content-type'] = 'text/plain; charset=utf-8';
req.charset.should.equal('utf-8');
assert.equal(req.charset, 'utf-8');
});
it('should return "" if content-type is invalid', () => {
const req = request();
req.header['content-type'] = 'application/json; application/text; charset=utf-8';
req.charset.should.equal('');
assert.equal(req.charset, '');
});
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
describe('ctx.fresh', () => {
@ -8,7 +9,7 @@ describe('ctx.fresh', () => {
it('should return false', () => {
const ctx = context();
ctx.req.method = 'POST';
ctx.fresh.should.be.false;
assert.equal(ctx.fresh, false);
});
});
@ -19,7 +20,7 @@ describe('ctx.fresh', () => {
ctx.req.method = 'GET';
ctx.req.headers['if-none-match'] = '123';
ctx.set('ETag', '123');
ctx.fresh.should.be.false;
assert.equal(ctx.fresh, false);
});
});
@ -31,7 +32,7 @@ describe('ctx.fresh', () => {
ctx.req.method = 'GET';
ctx.req.headers['if-none-match'] = '123';
ctx.set('ETag', '123');
ctx.fresh.should.be.true;
assert.equal(ctx.fresh, true);
});
});
@ -42,7 +43,7 @@ describe('ctx.fresh', () => {
ctx.req.method = 'GET';
ctx.req.headers['if-none-match'] = '123';
ctx.set('ETag', 'hey');
ctx.fresh.should.be.false;
assert.equal(ctx.fresh, false);
});
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
describe('ctx.get(name)', () => {
@ -8,10 +9,10 @@ describe('ctx.get(name)', () => {
const ctx = context();
ctx.req.headers.host = 'http://google.com';
ctx.req.headers.referer = 'http://google.com';
ctx.get('HOST').should.equal('http://google.com');
ctx.get('Host').should.equal('http://google.com');
ctx.get('host').should.equal('http://google.com');
ctx.get('referer').should.equal('http://google.com');
ctx.get('referrer').should.equal('http://google.com');
assert.equal(ctx.get('HOST'), 'http://google.com');
assert.equal(ctx.get('Host'), 'http://google.com');
assert.equal(ctx.get('host'), 'http://google.com');
assert.equal(ctx.get('referer'), 'http://google.com');
assert.equal(ctx.get('referrer'), 'http://google.com');
});
});

View File

@ -1,11 +1,12 @@
'use strict';
const assert = require('assert');
const request = require('../helpers/context').request;
describe('req.header', () => {
it('should return the request header object', () => {
const req = request();
req.header.should.equal(req.req.headers);
assert.deepEqual(req.header, req.req.headers);
});
});

View File

@ -1,11 +1,12 @@
'use strict';
const assert = require('assert');
const request = require('../helpers/context').request;
describe('req.headers', () => {
it('should return the request header object', () => {
const req = request();
req.headers.should.equal(req.req.headers);
assert.deepEqual(req.headers, req.req.headers);
});
});

View File

@ -8,7 +8,7 @@ describe('req.host', () => {
it('should return host with port', () => {
const req = request();
req.header.host = 'foo.com:3000';
req.host.should.equal('foo.com:3000');
assert.equal(req.host, 'foo.com:3000');
});
describe('with no host present', () => {
@ -24,7 +24,7 @@ describe('req.host', () => {
const req = request();
req.header['x-forwarded-host'] = 'bar.com';
req.header.host = 'foo.com';
req.host.should.equal('foo.com');
assert.equal(req.host, 'foo.com');
});
});
@ -34,7 +34,7 @@ describe('req.host', () => {
req.app.proxy = true;
req.header['x-forwarded-host'] = 'bar.com, baz.com';
req.header.host = 'foo.com';
req.host.should.equal('bar.com');
assert.equal(req.host, 'bar.com');
});
});
});

View File

@ -8,7 +8,7 @@ describe('req.hostname', () => {
it('should return hostname void of port', () => {
const req = request();
req.header.host = 'foo.com:3000';
req.hostname.should.equal('foo.com');
assert.equal(req.hostname, 'foo.com');
});
describe('with no host present', () => {
@ -24,7 +24,7 @@ describe('req.hostname', () => {
const req = request();
req.header['x-forwarded-host'] = 'bar.com';
req.header.host = 'foo.com';
req.hostname.should.equal('foo.com');
assert.equal(req.hostname, 'foo.com');
});
});
@ -34,7 +34,7 @@ describe('req.hostname', () => {
req.app.proxy = true;
req.header['x-forwarded-host'] = 'bar.com, baz.com';
req.header.host = 'foo.com';
req.hostname.should.equal('bar.com');
assert.equal(req.hostname, 'bar.com');
});
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const Stream = require('stream');
const http = require('http');
const Koa = require('../../');
@ -18,10 +19,10 @@ describe('ctx.href', () => {
__proto__: Stream.Readable.prototype
};
const ctx = context(req);
ctx.href.should.equal('http://localhost/users/1?next=/dashboard');
assert.equal(ctx.href, 'http://localhost/users/1?next=/dashboard');
// change it also work
ctx.url = '/foo/users/1?next=/dashboard';
ctx.href.should.equal('http://localhost/users/1?next=/dashboard');
assert.equal(ctx.href, 'http://localhost/users/1?next=/dashboard');
});
it('should work with `GET http://example.com/foo`', done => {
@ -36,12 +37,12 @@ describe('ctx.href', () => {
path: 'http://example.com/foo',
port: address.port
}, res => {
res.statusCode.should.equal(200);
assert.equal(res.statusCode, 200);
let buf = '';
res.setEncoding('utf8');
res.on('data', s => buf += s);
res.on('end', () => {
buf.should.equal('http://example.com/foo');
assert.equal(buf, 'http://example.com/foo');
done();
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const request = require('../helpers/context').request;
describe('ctx.idempotent', () => {
@ -10,7 +11,7 @@ describe('ctx.idempotent', () => {
function check(method){
const req = request();
req.method = method;
req.idempotent.should.equal(true);
assert.equal(req.idempotent, true);
}
});
});
@ -19,7 +20,7 @@ describe('ctx.idempotent', () => {
it('should return false', () => {
const req = request();
req.method = 'POST';
req.idempotent.should.equal(false);
assert.equal(req.idempotent, false);
});
});
});

View File

@ -20,12 +20,12 @@ describe('req.inspect()', () => {
req.url = 'example.com';
req.header.host = 'example.com';
req.inspect().should.eql({
assert.deepEqual({
method: 'GET',
url: 'example.com',
header: {
host: 'example.com'
}
});
}, req.inspect());
});
});

View File

@ -15,7 +15,7 @@ describe('req.ip', () => {
req.headers['x-forwarded-for'] = '127.0.0.1';
req.socket.remoteAddress = '127.0.0.2';
const request = Request(req, undefined, app);
request.ip.should.equal('127.0.0.1');
assert.equal(request.ip, '127.0.0.1');
});
});
@ -24,7 +24,7 @@ describe('req.ip', () => {
const req = { socket: new Stream.Duplex() };
req.socket.remoteAddress = '127.0.0.2';
const request = Request(req);
request.ip.should.equal('127.0.0.2');
assert.equal(request.ip, '127.0.0.2');
});
describe('with req.socket.remoteAddress not present', () => {
@ -44,6 +44,6 @@ describe('req.ip', () => {
req.socket.remoteAddress = '127.0.0.2';
const request = Request(req);
req.socket.remoteAddress = '127.0.0.1';
request.ip.should.equal('127.0.0.2');
assert.equal(request.ip, '127.0.0.2');
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const request = require('../helpers/context').request;
describe('req.ips', () => {
@ -10,7 +11,7 @@ describe('req.ips', () => {
const req = request();
req.app.proxy = false;
req.header['x-forwarded-for'] = '127.0.0.1,127.0.0.2';
req.ips.should.eql([]);
assert.deepEqual(req.ips, []);
});
});
@ -19,7 +20,7 @@ describe('req.ips', () => {
const req = request();
req.app.proxy = true;
req.header['x-forwarded-for'] = '127.0.0.1,127.0.0.2';
req.ips.should.eql(['127.0.0.1', '127.0.0.2']);
assert.deepEqual(req.ips, ['127.0.0.1', '127.0.0.2']);
});
});
});

View File

@ -10,16 +10,16 @@ describe('ctx.is(type)', () => {
ctx.header['content-type'] = 'text/html; charset=utf-8';
ctx.header['transfer-encoding'] = 'chunked';
ctx.is('text/*').should.equal('text/html');
assert.equal(ctx.is('text/*'), 'text/html');
});
describe('when no body is given', () => {
it('should return null', () => {
const ctx = context();
assert(null === ctx.is());
assert(null === ctx.is('image/*'));
assert(null === ctx.is('image/*', 'text/*'));
assert.equal(ctx.is(), null);
assert.equal(ctx.is('image/*'), null);
assert.equal(ctx.is('image/*', 'text/*'), null);
});
});
@ -28,9 +28,9 @@ describe('ctx.is(type)', () => {
const ctx = context();
ctx.header['transfer-encoding'] = 'chunked';
ctx.is().should.be.false;
ctx.is('image/*').should.be.false;
ctx.is('text/*', 'image/*').should.be.false;
assert.equal(ctx.is(), false);
assert.equal(ctx.is('image/*'), false);
assert.equal(ctx.is('text/*', 'image/*'), false);
});
});
@ -40,7 +40,7 @@ describe('ctx.is(type)', () => {
ctx.header['content-type'] = 'image/png';
ctx.header['transfer-encoding'] = 'chunked';
ctx.is().should.equal('image/png');
assert.equal(ctx.is(), 'image/png');
});
});
@ -50,17 +50,17 @@ describe('ctx.is(type)', () => {
ctx.header['content-type'] = 'image/png';
ctx.header['transfer-encoding'] = 'chunked';
ctx.is('png').should.equal('png');
ctx.is('.png').should.equal('.png');
ctx.is('image/png').should.equal('image/png');
ctx.is('image/*').should.equal('image/png');
ctx.is('*/png').should.equal('image/png');
assert.equal(ctx.is('png'), 'png');
assert.equal(ctx.is('.png'), '.png');
assert.equal(ctx.is('image/png'), 'image/png');
assert.equal(ctx.is('image/*'), 'image/png');
assert.equal(ctx.is('*/png'), 'image/png');
ctx.is('jpeg').should.be.false;
ctx.is('.jpeg').should.be.false;
ctx.is('image/jpeg').should.be.false;
ctx.is('text/*').should.be.false;
ctx.is('*/jpeg').should.be.false;
assert.equal(ctx.is('jpeg'), false);
assert.equal(ctx.is('.jpeg'), false);
assert.equal(ctx.is('image/jpeg'), false);
assert.equal(ctx.is('text/*'), false);
assert.equal(ctx.is('*/jpeg'), false);
});
});
@ -70,22 +70,22 @@ describe('ctx.is(type)', () => {
ctx.header['content-type'] = 'image/png';
ctx.header['transfer-encoding'] = 'chunked';
ctx.is('png').should.equal('png');
ctx.is('.png').should.equal('.png');
ctx.is('text/*', 'image/*').should.equal('image/png');
ctx.is('image/*', 'text/*').should.equal('image/png');
ctx.is('image/*', 'image/png').should.equal('image/png');
ctx.is('image/png', 'image/*').should.equal('image/png');
assert.equal(ctx.is('png'), 'png');
assert.equal(ctx.is('.png'), '.png');
assert.equal(ctx.is('text/*', 'image/*'), 'image/png');
assert.equal(ctx.is('image/*', 'text/*'), 'image/png');
assert.equal(ctx.is('image/*', 'image/png'), 'image/png');
assert.equal(ctx.is('image/png', 'image/*'), 'image/png');
ctx.is(['text/*', 'image/*']).should.equal('image/png');
ctx.is(['image/*', 'text/*']).should.equal('image/png');
ctx.is(['image/*', 'image/png']).should.equal('image/png');
ctx.is(['image/png', 'image/*']).should.equal('image/png');
assert.equal(ctx.is(['text/*', 'image/*']), 'image/png');
assert.equal(ctx.is(['image/*', 'text/*']), 'image/png');
assert.equal(ctx.is(['image/*', 'image/png']), 'image/png');
assert.equal(ctx.is(['image/png', 'image/*']), 'image/png');
ctx.is('jpeg').should.be.false;
ctx.is('.jpeg').should.be.false;
ctx.is('text/*', 'application/*').should.be.false;
ctx.is('text/html', 'text/plain', 'application/json; charset=utf-8').should.be.false;
assert.equal(ctx.is('jpeg'), false);
assert.equal(ctx.is('.jpeg'), false);
assert.equal(ctx.is('text/*', 'application/*'), false);
assert.equal(ctx.is('text/html', 'text/plain', 'application/json; charset=utf-8'), false);
});
});
@ -95,9 +95,9 @@ describe('ctx.is(type)', () => {
ctx.header['content-type'] = 'application/x-www-form-urlencoded';
ctx.header['transfer-encoding'] = 'chunked';
ctx.is('urlencoded').should.equal('urlencoded');
ctx.is('json', 'urlencoded').should.equal('urlencoded');
ctx.is('urlencoded', 'json').should.equal('urlencoded');
assert.equal(ctx.is('urlencoded'), 'urlencoded');
assert.equal(ctx.is('json', 'urlencoded'), 'urlencoded');
assert.equal(ctx.is('urlencoded', 'json'), 'urlencoded');
});
});
});

View File

@ -8,11 +8,11 @@ describe('ctx.length', () => {
it('should return length in content-length', () => {
const req = request();
req.header['content-length'] = '10';
req.length.should.equal(10);
assert.equal(req.length, 10);
});
it('with no content-length present', () => {
const req = request();
assert(null == req.length);
assert.equal(req.length, undefined);
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const Stream = require('stream');
const context = require('../helpers/context');
@ -16,9 +17,9 @@ describe('ctx.origin', () => {
__proto__: Stream.Readable.prototype
};
const ctx = context(req);
ctx.origin.should.equal('http://localhost');
assert.equal(ctx.origin, 'http://localhost');
// change it also work
ctx.url = '/foo/users/1?next=/dashboard';
ctx.origin.should.equal('http://localhost');
assert.equal(ctx.origin, 'http://localhost');
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
const parseurl = require('parseurl');
@ -8,7 +9,7 @@ describe('ctx.path', () => {
it('should return the pathname', () => {
const ctx = context();
ctx.url = '/login?next=/dashboard';
ctx.path.should.equal('/login');
assert.equal(ctx.path, '/login');
});
});
@ -18,22 +19,22 @@ describe('ctx.path=', () => {
ctx.url = '/login?next=/dashboard';
ctx.path = '/logout';
ctx.path.should.equal('/logout');
ctx.url.should.equal('/logout?next=/dashboard');
assert.equal(ctx.path, '/logout');
assert.equal(ctx.url, '/logout?next=/dashboard');
});
it('should change .url but not .originalUrl', () => {
const ctx = context({ url: '/login' });
ctx.path = '/logout';
ctx.url.should.equal('/logout');
ctx.originalUrl.should.equal('/login');
ctx.request.originalUrl.should.equal('/login');
assert.equal(ctx.url, '/logout');
assert.equal(ctx.originalUrl, '/login');
assert.equal(ctx.request.originalUrl, '/login');
});
it('should not affect parseurl', () => {
const ctx = context({ url: '/login?foo=bar' });
ctx.path = '/login';
const url = parseurl(ctx.req);
url.path.should.equal('/login?foo=bar');
assert.equal(url.path, '/login?foo=bar');
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const request = require('../helpers/context').request;
describe('req.protocol', () => {
@ -8,7 +9,7 @@ describe('req.protocol', () => {
it('should return "https"', () => {
const req = request();
req.req.socket = { encrypted: true };
req.protocol.should.equal('https');
assert.equal(req.protocol, 'https');
});
});
@ -16,7 +17,7 @@ describe('req.protocol', () => {
it('should return "http"', () => {
const req = request();
req.req.socket = {};
req.protocol.should.equal('http');
assert.equal(req.protocol, 'http');
});
});
@ -27,7 +28,7 @@ describe('req.protocol', () => {
req.app.proxy = true;
req.req.socket = {};
req.header['x-forwarded-proto'] = 'https, http';
req.protocol.should.equal('https');
assert.equal(req.protocol, 'https');
});
describe('and X-Forwarded-Proto is empty', () => {
@ -36,7 +37,7 @@ describe('req.protocol', () => {
req.app.proxy = true;
req.req.socket = {};
req.header['x-forwarded-proto'] = '';
req.protocol.should.equal('http');
assert.equal(req.protocol, 'http');
});
});
});
@ -46,7 +47,7 @@ describe('req.protocol', () => {
const req = request();
req.req.socket = {};
req.header['x-forwarded-proto'] = 'https, http';
req.protocol.should.equal('http');
assert.equal(req.protocol, 'http');
});
});
});

View File

@ -1,27 +1,26 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
const should = require('should');
describe('ctx.query', () => {
describe('when missing', () => {
it('should return an empty object', () => {
const ctx = context({ url: '/' });
should(ctx.query).empty;
assert.deepEqual(ctx.query, {});
});
it('should return the same object each time it\'s accessed', done => {
it('should return the same object each time it\'s accessed', () => {
const ctx = context({ url: '/' });
ctx.query.a = '2';
ctx.query.a.should.equal('2');
done();
assert.equal(ctx.query.a, '2');
});
});
it('should return a parsed query-string', () => {
const ctx = context({ url: '/?page=2' });
ctx.query.page.should.equal('2');
assert.equal(ctx.query.page, '2');
});
});
@ -29,16 +28,16 @@ describe('ctx.query=', () => {
it('should stringify and replace the querystring and search', () => {
const ctx = context({ url: '/store/shoes' });
ctx.query = { page: 2, color: 'blue' };
ctx.url.should.equal('/store/shoes?page=2&color=blue');
ctx.querystring.should.equal('page=2&color=blue');
ctx.search.should.equal('?page=2&color=blue');
assert.equal(ctx.url, '/store/shoes?page=2&color=blue');
assert.equal(ctx.querystring, 'page=2&color=blue');
assert.equal(ctx.search, '?page=2&color=blue');
});
it('should change .url but not .originalUrl', () => {
const ctx = context({ url: '/store/shoes' });
ctx.query = { page: 2 };
ctx.url.should.equal('/store/shoes?page=2');
ctx.originalUrl.should.equal('/store/shoes');
ctx.request.originalUrl.should.equal('/store/shoes');
assert.equal(ctx.url, '/store/shoes?page=2');
assert.equal(ctx.originalUrl, '/store/shoes');
assert.equal(ctx.request.originalUrl, '/store/shoes');
});
});

View File

@ -1,21 +1,21 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
const parseurl = require('parseurl');
const should = require('should');
describe('ctx.querystring', () => {
it('should return the querystring', () => {
const ctx = context({ url: '/store/shoes?page=2&color=blue' });
ctx.querystring.should.equal('page=2&color=blue');
assert.equal(ctx.querystring, 'page=2&color=blue');
});
describe('when ctx.req not present', () => {
it('should return an empty string', () => {
const ctx = context();
ctx.request.req = null;
ctx.querystring.should.equal('');
assert.equal(ctx.querystring, '');
});
});
});
@ -24,31 +24,31 @@ describe('ctx.querystring=', () => {
it('should replace the querystring', () => {
const ctx = context({ url: '/store/shoes' });
ctx.querystring = 'page=2&color=blue';
ctx.url.should.equal('/store/shoes?page=2&color=blue');
ctx.querystring.should.equal('page=2&color=blue');
assert.equal(ctx.url, '/store/shoes?page=2&color=blue');
assert.equal(ctx.querystring, 'page=2&color=blue');
});
it('should update ctx.search and ctx.query', () => {
const ctx = context({ url: '/store/shoes' });
ctx.querystring = 'page=2&color=blue';
ctx.url.should.equal('/store/shoes?page=2&color=blue');
ctx.search.should.equal('?page=2&color=blue');
should(ctx.query).have.property('page', '2');
should(ctx.query).have.property('color', 'blue');
assert.equal(ctx.url, '/store/shoes?page=2&color=blue');
assert.equal(ctx.search, '?page=2&color=blue');
assert.equal(ctx.query.page, '2');
assert.equal(ctx.query.color, 'blue');
});
it('should change .url but not .originalUrl', () => {
const ctx = context({ url: '/store/shoes' });
ctx.querystring = 'page=2&color=blue';
ctx.url.should.equal('/store/shoes?page=2&color=blue');
ctx.originalUrl.should.equal('/store/shoes');
ctx.request.originalUrl.should.equal('/store/shoes');
assert.equal(ctx.url, '/store/shoes?page=2&color=blue');
assert.equal(ctx.originalUrl, '/store/shoes');
assert.equal(ctx.request.originalUrl, '/store/shoes');
});
it('should not affect parseurl', () => {
const ctx = context({ url: '/login?foo=bar' });
ctx.querystring = 'foo=bar';
const url = parseurl(ctx.req);
url.path.should.equal('/login?foo=bar');
assert.equal(url.path, '/login?foo=bar');
});
});

View File

@ -1,38 +1,38 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
const should = require('should');
describe('ctx.search=', () => {
it('should replace the search', () => {
const ctx = context({ url: '/store/shoes' });
ctx.search = '?page=2&color=blue';
ctx.url.should.equal('/store/shoes?page=2&color=blue');
ctx.search.should.equal('?page=2&color=blue');
assert.equal(ctx.url, '/store/shoes?page=2&color=blue');
assert.equal(ctx.search, '?page=2&color=blue');
});
it('should update ctx.querystring and ctx.query', () => {
const ctx = context({ url: '/store/shoes' });
ctx.search = '?page=2&color=blue';
ctx.url.should.equal('/store/shoes?page=2&color=blue');
ctx.querystring.should.equal('page=2&color=blue');
should(ctx.query).have.property('page', '2');
should(ctx.query).have.property('color', 'blue');
assert.equal(ctx.url, '/store/shoes?page=2&color=blue');
assert.equal(ctx.querystring, 'page=2&color=blue');
assert.equal(ctx.query.page, '2');
assert.equal(ctx.query.color, 'blue');
});
it('should change .url but not .originalUrl', () => {
const ctx = context({ url: '/store/shoes' });
ctx.search = '?page=2&color=blue';
ctx.url.should.equal('/store/shoes?page=2&color=blue');
ctx.originalUrl.should.equal('/store/shoes');
ctx.request.originalUrl.should.equal('/store/shoes');
assert.equal(ctx.url, '/store/shoes?page=2&color=blue');
assert.equal(ctx.originalUrl, '/store/shoes');
assert.equal(ctx.request.originalUrl, '/store/shoes');
});
describe('when missing', () => {
it('should return ""', () => {
const ctx = context({ url: '/store/shoes' });
ctx.search.should.equal('');
assert.equal(ctx.search, '');
});
});
});

View File

@ -1,12 +1,13 @@
'use strict';
const assert = require('assert');
const request = require('../helpers/context').request;
describe('req.secure', () => {
it('should return true when encrypted', () => {
const req = request();
req.req.socket = { encrypted: true };
req.secure.should.be.true;
assert.equal(req.secure, true);
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
describe('req.stale', () => {
@ -10,7 +11,7 @@ describe('req.stale', () => {
ctx.method = 'GET';
ctx.req.headers['if-none-match'] = '"123"';
ctx.set('ETag', '"123"');
ctx.fresh.should.be.true;
ctx.stale.should.be.false;
assert.equal(ctx.fresh, true);
assert.equal(ctx.stale, false);
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const request = require('../helpers/context').request;
describe('req.subdomains', () => {
@ -8,20 +9,20 @@ describe('req.subdomains', () => {
const req = request();
req.header.host = 'tobi.ferrets.example.com';
req.app.subdomainOffset = 2;
req.subdomains.should.eql(['ferrets', 'tobi']);
assert.deepEqual(req.subdomains, ['ferrets', 'tobi']);
req.app.subdomainOffset = 3;
req.subdomains.should.eql(['tobi']);
assert.deepEqual(req.subdomains, ['tobi']);
});
it('should work with no host present', () => {
const req = request();
req.subdomains.should.eql([]);
assert.deepEqual(req.subdomains, []);
});
it('should check if the host is an ip address, even with a port', () => {
const req = request();
req.header.host = '127.0.0.1:3000';
req.subdomains.should.eql([]);
assert.deepEqual(req.subdomains, []);
});
});

View File

@ -8,11 +8,11 @@ describe('req.type', () => {
it('should return type void of parameters', () => {
const req = request();
req.header['content-type'] = 'text/html; charset=utf-8';
req.type.should.equal('text/html');
assert.equal(req.type, 'text/html');
});
it('with no host present', () => {
const req = request();
assert('' === req.type);
assert.equal(req.type, '');
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
describe('ctx.append(name, val)', () => {
@ -8,7 +9,7 @@ describe('ctx.append(name, val)', () => {
const ctx = context();
ctx.append('x-foo', 'bar1');
ctx.append('x-foo', 'bar2');
ctx.response.header['x-foo'].should.eql(['bar1', 'bar2']);
assert.deepEqual(ctx.response.header['x-foo'], ['bar1', 'bar2']);
});
it('should accept array of values', () => {
@ -16,7 +17,7 @@ describe('ctx.append(name, val)', () => {
ctx.append('Set-Cookie', ['foo=bar', 'fizz=buzz']);
ctx.append('Set-Cookie', 'hi=again');
ctx.response.header['set-cookie'].should.eql(['foo=bar', 'fizz=buzz', 'hi=again']);
assert.deepEqual(ctx.response.header['set-cookie'], ['foo=bar', 'fizz=buzz', 'hi=again']);
});
it('should get reset by res.set(field, val)', () => {
@ -27,7 +28,7 @@ describe('ctx.append(name, val)', () => {
ctx.set('Link', '<http://127.0.0.1/>');
ctx.response.header.link.should.equal('<http://127.0.0.1/>');
assert.equal(ctx.response.header.link, '<http://127.0.0.1/>');
});
it('should work with res.set(field, val) first', () => {
@ -36,6 +37,6 @@ describe('ctx.append(name, val)', () => {
ctx.set('Link', '<http://localhost/>');
ctx.append('Link', '<http://localhost:80/>');
ctx.response.header.link.should.eql(['<http://localhost/>', '<http://localhost:80/>']);
assert.deepEqual(ctx.response.header.link, ['<http://localhost/>', '<http://localhost:80/>']);
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
const request = require('supertest');
const Koa = require('../..');
@ -11,7 +12,7 @@ describe('ctx.attachment([filename])', () => {
const ctx = context();
ctx.attachment('path/to/tobi.png');
const str = 'attachment; filename="tobi.png"';
ctx.response.header['content-disposition'].should.equal(str);
assert.equal(ctx.response.header['content-disposition'], str);
});
});
@ -19,7 +20,7 @@ describe('ctx.attachment([filename])', () => {
it('should not set filename param', () => {
const ctx = context();
ctx.attachment();
ctx.response.header['content-disposition'].should.equal('attachment');
assert.equal(ctx.response.header['content-disposition'], 'attachment');
});
});
@ -28,10 +29,10 @@ describe('ctx.attachment([filename])', () => {
const ctx = context();
ctx.attachment('path/to/include-no-ascii-char-中文名-ok.png');
const str = 'attachment; filename="include-no-ascii-char-???-ok.png"; filename*=UTF-8\'\'include-no-ascii-char-%E4%B8%AD%E6%96%87%E5%90%8D-ok.png';
ctx.response.header['content-disposition'].should.equal(str);
assert.equal(ctx.response.header['content-disposition'], str);
});
it('should work with http client', done => {
it('should work with http client', () => {
const app = new Koa();
app.use((ctx, next) => {
@ -39,11 +40,11 @@ describe('ctx.attachment([filename])', () => {
ctx.body = {foo: 'bar'};
});
request(app.listen())
return request(app.listen())
.get('/')
.expect('content-disposition', 'attachment; filename="include-no-ascii-char-???-ok.json"; filename*=UTF-8\'\'include-no-ascii-char-%E4%B8%AD%E6%96%87%E5%90%8D-ok.json')
.expect({foo: 'bar'})
.expect(200, done);
.expect(200);
});
});
});

View File

@ -11,7 +11,7 @@ describe('res.body=', () => {
const res = response();
res.type = 'png';
res.body = Buffer.from('something');
assert('image/png' == res.header['content-type']);
assert.equal('image/png', res.header['content-type']);
});
describe('when body is an object', () => {
@ -19,10 +19,10 @@ describe('res.body=', () => {
const res = response();
res.body = '<em>hey</em>';
assert('text/html; charset=utf-8' == res.header['content-type']);
assert.equal('text/html; charset=utf-8', res.header['content-type']);
res.body = { foo: 'bar' };
assert('application/json; charset=utf-8' == res.header['content-type']);
assert.equal('application/json; charset=utf-8', res.header['content-type']);
});
});
@ -30,7 +30,7 @@ describe('res.body=', () => {
const res = response();
res.type = 'html';
res.body = 'something';
res.length.should.equal(9);
assert.equal(res.length, 9);
});
});
@ -38,20 +38,20 @@ describe('res.body=', () => {
it('should default to text', () => {
const res = response();
res.body = 'Tobi';
assert('text/plain; charset=utf-8' == res.header['content-type']);
assert.equal('text/plain; charset=utf-8', res.header['content-type']);
});
it('should set length', () => {
const res = response();
res.body = 'Tobi';
assert('4' == res.header['content-length']);
assert.equal('4', res.header['content-length']);
});
describe('and contains a non-leading <', () => {
it('should default to text', () => {
const res = response();
res.body = 'aklsdjf < klajsdlfjasd';
assert('text/plain; charset=utf-8' == res.header['content-type']);
assert.equal('text/plain; charset=utf-8', res.header['content-type']);
});
});
});
@ -60,7 +60,7 @@ describe('res.body=', () => {
it('should default to html', () => {
const res = response();
res.body = '<h1>Tobi</h1>';
assert('text/html; charset=utf-8' == res.header['content-type']);
assert.equal('text/html; charset=utf-8', res.header['content-type']);
});
it('should set length', () => {
@ -82,7 +82,7 @@ describe('res.body=', () => {
it('should default to html', () => {
const res = response();
res.body = ' <h1>Tobi</h1>';
assert('text/html; charset=utf-8' == res.header['content-type']);
assert.equal('text/html; charset=utf-8', res.header['content-type']);
});
});
});
@ -98,7 +98,7 @@ describe('res.body=', () => {
const res = response();
res.body = '<?xml version="1.0" encoding="UTF-8"?>\n<俄语>данные</俄语>';
assert('text/html; charset=utf-8' == res.header['content-type']);
assert.equal('text/html; charset=utf-8', res.header['content-type']);
});
});
@ -106,7 +106,7 @@ describe('res.body=', () => {
it('should default to an octet stream', () => {
const res = response();
res.body = fs.createReadStream('LICENSE');
assert('application/octet-stream' == res.header['content-type']);
assert.equal('application/octet-stream', res.header['content-type']);
});
});
@ -114,13 +114,13 @@ describe('res.body=', () => {
it('should default to an octet stream', () => {
const res = response();
res.body = Buffer.from('hey');
assert('application/octet-stream' == res.header['content-type']);
assert.equal('application/octet-stream', res.header['content-type']);
});
it('should set length', () => {
const res = response();
res.body = Buffer.from('Tobi');
assert('4' == res.header['content-length']);
assert.equal('4', res.header['content-length']);
});
});
@ -128,7 +128,7 @@ describe('res.body=', () => {
it('should default to json', () => {
const res = response();
res.body = { foo: 'bar' };
assert('application/json; charset=utf-8' == res.header['content-type']);
assert.equal('application/json; charset=utf-8', res.header['content-type']);
});
});
});

View File

@ -1,25 +1,26 @@
'use strict';
const assert = require('assert');
const response = require('../helpers/context').response;
describe('res.etag=', () => {
it('should not modify an etag with quotes', () => {
const res = response();
res.etag = '"asdf"';
res.header.etag.should.equal('"asdf"');
assert.equal(res.header.etag, '"asdf"');
});
it('should not modify a weak etag', () => {
const res = response();
res.etag = 'W/"asdf"';
res.header.etag.should.equal('W/"asdf"');
assert.equal(res.header.etag, 'W/"asdf"');
});
it('should add quotes around an etag if necessary', () => {
const res = response();
res.etag = 'asdf';
res.header.etag.should.equal('"asdf"');
assert.equal(res.header.etag, '"asdf"');
});
});
@ -27,6 +28,6 @@ describe('res.etag', () => {
it('should return etag', () => {
const res = response();
res.etag = '"asdf"';
res.etag.should.equal('"asdf"');
assert.equal(res.etag, '"asdf"');
});
});

View File

@ -7,25 +7,25 @@ const Koa = require('../..');
const http = require('http');
describe('ctx.flushHeaders()', () => {
it('should set headersSent', done => {
it('should set headersSent', () => {
const app = new Koa();
app.use((ctx, next) => {
ctx.body = 'Body';
ctx.status = 200;
ctx.flushHeaders();
assert(ctx.res.headersSent);
assert.equal(ctx.res.headersSent, true);
});
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(200)
.expect('Body', done);
.expect('Body');
});
it('should allow a response afterwards', done => {
it('should allow a response afterwards', () => {
const app = new Koa();
app.use((ctx, next) => {
@ -36,14 +36,14 @@ describe('ctx.flushHeaders()', () => {
});
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(200)
.expect('Content-Type', 'text/plain')
.expect('Body', done);
.expect('Body');
});
it('should send the correct status code', done => {
it('should send the correct status code', () => {
const app = new Koa();
app.use((ctx, next) => {
@ -54,14 +54,14 @@ describe('ctx.flushHeaders()', () => {
});
const server = app.listen();
request(server)
return request(server)
.get('/')
.expect(401)
.expect('Content-Type', 'text/plain')
.expect('Body', done);
.expect('Body');
});
it('should fail to set the headers after flushHeaders', done => {
it('should fail to set the headers after flushHeaders', async () => {
const app = new Koa();
app.use((ctx, next) => {
@ -87,14 +87,13 @@ describe('ctx.flushHeaders()', () => {
});
const server = app.listen();
request(server)
const res = await request(server)
.get('/')
.expect(401)
.expect('Content-Type', 'text/plain')
.expect('ctx.set fail ctx.status fail ctx.length fail', (err, res) => {
assert(res.headers['x-shouldnt-work'] === undefined, 'header set after flushHeaders');
done(err);
});
.expect('ctx.set fail ctx.status fail ctx.length fail');
assert.equal(res.headers['x-shouldnt-work'], undefined, 'header set after flushHeaders');
});
it('should flush headers first and delay to send data', done => {

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const request = require('supertest');
const response = require('../helpers/context').response;
const Koa = require('../..');
@ -9,14 +10,14 @@ describe('res.header', () => {
it('should return the response header object', () => {
const res = response();
res.set('X-Foo', 'bar');
res.header.should.eql({ 'x-foo': 'bar' });
assert.deepEqual(res.header, { 'x-foo': 'bar' });
});
it('should use res.getHeaders() accessor when available', () => {
const res = response();
res.res._headers = null;
res.res.getHeaders = () => ({ 'x-foo': 'baz' });
res.header.should.eql({ 'x-foo': 'baz' });
assert.deepEqual(res.header, { 'x-foo': 'baz' });
});
it('should return the response header object when no mocks are in use', async () => {
@ -31,14 +32,14 @@ describe('res.header', () => {
await request(app.listen())
.get('/');
header.should.eql({ 'x-foo': '42' });
assert.deepEqual(header, { 'x-foo': '42' });
});
describe('when res._headers not present', () => {
it('should return empty object', () => {
const res = response();
res.res._headers = null;
res.header.should.eql({});
assert.deepEqual(res.header, {});
});
});
});

View File

@ -1,20 +1,21 @@
'use strict';
const assert = require('assert');
const response = require('../helpers/context').response;
describe('res.header', () => {
it('should return the response header object', () => {
const res = response();
res.set('X-Foo', 'bar');
res.headers.should.eql({ 'x-foo': 'bar' });
assert.deepEqual(res.headers, { 'x-foo': 'bar' });
});
describe('when res._headers not present', () => {
it('should return empty object', () => {
const res = response();
res.res._headers = null;
res.headers.should.eql({});
assert.deepEqual(res.headers, {});
});
});
});

View File

@ -10,7 +10,7 @@ describe('res.inspect()', () => {
const res = response();
res.body = 'hello';
delete res.res;
assert(null == res.inspect());
assert.equal(res.inspect(), null);
});
});
@ -18,7 +18,7 @@ describe('res.inspect()', () => {
const res = response();
res.body = 'hello';
res.inspect().should.eql({
assert.deepEqual({
body: 'hello',
status: 200,
message: 'OK',
@ -26,6 +26,6 @@ describe('res.inspect()', () => {
'content-length': '5',
'content-type': 'text/plain; charset=utf-8'
}
});
}, res.inspect());
});
});

View File

@ -9,15 +9,15 @@ describe('response.is(type)', () => {
const res = context().response;
res.type = 'text/html; charset=utf-8';
res.is('text/*').should.equal('text/html');
assert.equal(res.is('text/*'), 'text/html');
});
describe('when no type is set', () => {
it('should return false', () => {
const res = context().response;
assert(false === res.is());
assert(false === res.is('html'));
assert.equal(res.is(), false);
assert.equal(res.is('html'), false);
});
});
@ -26,7 +26,7 @@ describe('response.is(type)', () => {
const res = context().response;
res.type = 'text/html; charset=utf-8';
res.is().should.equal('text/html');
assert.equal(res.is(), 'text/html');
});
});
@ -35,17 +35,17 @@ describe('response.is(type)', () => {
const res = context().response;
res.type = 'image/png';
res.is('png').should.equal('png');
res.is('.png').should.equal('.png');
res.is('image/png').should.equal('image/png');
res.is('image/*').should.equal('image/png');
res.is('*/png').should.equal('image/png');
assert.equal(res.is('png'), 'png');
assert.equal(res.is('.png'), '.png');
assert.equal(res.is('image/png'), 'image/png');
assert.equal(res.is('image/*'), 'image/png');
assert.equal(res.is('*/png'), 'image/png');
res.is('jpeg').should.be.false;
res.is('.jpeg').should.be.false;
res.is('image/jpeg').should.be.false;
res.is('text/*').should.be.false;
res.is('*/jpeg').should.be.false;
assert.equal(res.is('jpeg'), false);
assert.equal(res.is('.jpeg'), false);
assert.equal(res.is('image/jpeg'), false);
assert.equal(res.is('text/*'), false);
assert.equal(res.is('*/jpeg'), false);
});
});
@ -54,22 +54,22 @@ describe('response.is(type)', () => {
const res = context().response;
res.type = 'image/png';
res.is('png').should.equal('png');
res.is('.png').should.equal('.png');
res.is('text/*', 'image/*').should.equal('image/png');
res.is('image/*', 'text/*').should.equal('image/png');
res.is('image/*', 'image/png').should.equal('image/png');
res.is('image/png', 'image/*').should.equal('image/png');
assert.equal(res.is('png'), 'png');
assert.equal(res.is('.png'), '.png');
assert.equal(res.is('text/*', 'image/*'), 'image/png');
assert.equal(res.is('image/*', 'text/*'), 'image/png');
assert.equal(res.is('image/*', 'image/png'), 'image/png');
assert.equal(res.is('image/png', 'image/*'), 'image/png');
res.is(['text/*', 'image/*']).should.equal('image/png');
res.is(['image/*', 'text/*']).should.equal('image/png');
res.is(['image/*', 'image/png']).should.equal('image/png');
res.is(['image/png', 'image/*']).should.equal('image/png');
assert.equal(res.is(['text/*', 'image/*']), 'image/png');
assert.equal(res.is(['image/*', 'text/*']), 'image/png');
assert.equal(res.is(['image/*', 'image/png']), 'image/png');
assert.equal(res.is(['image/png', 'image/*']), 'image/png');
res.is('jpeg').should.be.false;
res.is('.jpeg').should.be.false;
res.is('text/*', 'application/*').should.be.false;
res.is('text/html', 'text/plain', 'application/json; charset=utf-8').should.be.false;
assert.equal(res.is('jpeg'), false);
assert.equal(res.is('.jpeg'), false);
assert.equal(res.is('text/*', 'application/*'), false);
assert.equal(res.is('text/html', 'text/plain', 'application/json; charset=utf-8'), false);
});
});
@ -78,9 +78,9 @@ describe('response.is(type)', () => {
const res = context().response;
res.type = 'application/x-www-form-urlencoded';
res.is('urlencoded').should.equal('urlencoded');
res.is('json', 'urlencoded').should.equal('urlencoded');
res.is('urlencoded', 'json').should.equal('urlencoded');
assert.equal(res.is('urlencoded'), 'urlencoded');
assert.equal(res.is('json', 'urlencoded'), 'urlencoded');
assert.equal(res.is('urlencoded', 'json'), 'urlencoded');
});
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const response = require('../helpers/context').response;
describe('res.lastModified', () => {
@ -8,14 +9,14 @@ describe('res.lastModified', () => {
const res = response();
const date = new Date();
res.lastModified = date;
res.header['last-modified'].should.equal(date.toUTCString());
assert.equal(res.header['last-modified'], date.toUTCString());
});
it('should work with date strings', () => {
const res = response();
const date = new Date();
res.lastModified = date.toString();
res.header['last-modified'].should.equal(date.toUTCString());
assert.equal(res.header['last-modified'], date.toUTCString());
});
it('should get the header as a Date', () => {
@ -23,13 +24,13 @@ describe('res.lastModified', () => {
const res = response();
const date = new Date();
res.lastModified = date;
(res.lastModified.getTime() / 1000).should.equal(Math.floor(date.getTime() / 1000));
assert.equal((res.lastModified.getTime() / 1000), Math.floor(date.getTime() / 1000));
});
describe('when lastModified not set', () => {
it('should get undefined', () => {
const res = response();
(res.lastModified === undefined).should.be.ok;
assert.equal(res.lastModified, undefined);
});
});
});

View File

@ -2,7 +2,6 @@
'use strict';
const response = require('../helpers/context').response;
const should = require('should');
const assert = require('assert');
const fs = require('fs');
@ -11,7 +10,7 @@ describe('res.length', () => {
it('should return a number', () => {
const res = response();
res.header['content-length'] = '120';
res.length.should.equal(120);
assert.equal(res.length, 120);
});
});
});
@ -21,7 +20,7 @@ describe('res.length', () => {
it('should return a number', () => {
const res = response();
res.set('Content-Length', '1024');
res.length.should.equal(1024);
assert.equal(res.length, 1024);
});
});
@ -32,37 +31,37 @@ describe('res.length', () => {
res.body = 'foo';
res.remove('Content-Length');
res.length.should.equal(3);
assert.equal(res.length, 3);
res.body = 'foo';
res.length.should.equal(3);
assert.equal(res.length, 3);
res.body = Buffer.from('foo bar');
res.remove('Content-Length');
res.length.should.equal(7);
assert.equal(res.length, 7);
res.body = Buffer.from('foo bar');
res.length.should.equal(7);
assert.equal(res.length, 7);
res.body = { hello: 'world' };
res.remove('Content-Length');
res.length.should.equal(17);
assert.equal(res.length, 17);
res.body = { hello: 'world' };
res.length.should.equal(17);
assert.equal(res.length, 17);
res.body = fs.createReadStream('package.json');
should.not.exist(res.length);
assert.equal(res.length, undefined);
res.body = null;
should.not.exist(res.length);
assert.equal(res.length, undefined);
});
});
describe('and .body is not', () => {
it('should return undefined', () => {
const res = response();
assert(null == res.length);
assert.equal(res.length, undefined);
});
});
});

View File

@ -1,20 +1,21 @@
'use strict';
const assert = require('assert');
const response = require('../helpers/context').response;
describe('res.message', () => {
it('should return the response status message', () => {
const res = response();
res.status = 200;
res.message.should.equal('OK');
assert.equal(res.message, 'OK');
});
describe('when res.message not present', () => {
it('should look up in statuses', () => {
const res = response();
res.res.statusCode = 200;
res.message.should.equal('OK');
assert.equal(res.message, 'OK');
});
});
});
@ -24,7 +25,7 @@ describe('res.message=', () => {
const res = response();
res.status = 200;
res.message = 'ok';
res.res.statusMessage.should.equal('ok');
res.inspect().message.should.equal('ok');
assert.equal(res.res.statusMessage, 'ok');
assert.equal(res.inspect().message, 'ok');
});
});

View File

@ -1,14 +1,15 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
describe('ctx.redirect(url)', () => {
it('should redirect to the given url', () => {
const ctx = context();
ctx.redirect('http://google.com');
ctx.response.header.location.should.equal('http://google.com');
ctx.status.should.equal(302);
assert.equal(ctx.response.header.location, 'http://google.com');
assert.equal(ctx.status, 302);
});
describe('with "back"', () => {
@ -16,26 +17,26 @@ describe('ctx.redirect(url)', () => {
const ctx = context();
ctx.req.headers.referrer = '/login';
ctx.redirect('back');
ctx.response.header.location.should.equal('/login');
assert.equal(ctx.response.header.location, '/login');
});
it('should redirect to Referer', () => {
const ctx = context();
ctx.req.headers.referer = '/login';
ctx.redirect('back');
ctx.response.header.location.should.equal('/login');
assert.equal(ctx.response.header.location, '/login');
});
it('should default to alt', () => {
const ctx = context();
ctx.redirect('back', '/index.html');
ctx.response.header.location.should.equal('/index.html');
assert.equal(ctx.response.header.location, '/index.html');
});
it('should default redirect to /', () => {
const ctx = context();
ctx.redirect('back');
ctx.response.header.location.should.equal('/');
assert.equal(ctx.response.header.location, '/');
});
});
@ -45,8 +46,8 @@ describe('ctx.redirect(url)', () => {
const url = 'http://google.com';
ctx.header.accept = 'text/html';
ctx.redirect(url);
ctx.response.header['content-type'].should.equal('text/html; charset=utf-8');
ctx.body.should.equal(`Redirecting to <a href="${url}">${url}</a>.`);
assert.equal(ctx.response.header['content-type'], 'text/html; charset=utf-8');
assert.equal(ctx.body, `Redirecting to <a href="${url}">${url}</a>.`);
});
it('should escape the url', () => {
@ -55,8 +56,8 @@ describe('ctx.redirect(url)', () => {
ctx.header.accept = 'text/html';
ctx.redirect(url);
url = escape(url);
ctx.response.header['content-type'].should.equal('text/html; charset=utf-8');
ctx.body.should.equal(`Redirecting to <a href="${url}">${url}</a>.`);
assert.equal(ctx.response.header['content-type'], 'text/html; charset=utf-8');
assert.equal(ctx.body, `Redirecting to <a href="${url}">${url}</a>.`);
});
});
@ -66,7 +67,7 @@ describe('ctx.redirect(url)', () => {
const url = 'http://google.com';
ctx.header.accept = 'text/plain';
ctx.redirect(url);
ctx.body.should.equal(`Redirecting to ${url}.`);
assert.equal(ctx.body, `Redirecting to ${url}.`);
});
});
@ -77,8 +78,8 @@ describe('ctx.redirect(url)', () => {
ctx.status = 301;
ctx.header.accept = 'text/plain';
ctx.redirect('http://google.com');
ctx.status.should.equal(301);
ctx.body.should.equal(`Redirecting to ${url}.`);
assert.equal(ctx.status, 301);
assert.equal(ctx.body, `Redirecting to ${url}.`);
});
});
@ -89,8 +90,8 @@ describe('ctx.redirect(url)', () => {
ctx.status = 304;
ctx.header.accept = 'text/plain';
ctx.redirect('http://google.com');
ctx.status.should.equal(302);
ctx.body.should.equal(`Redirecting to ${url}.`);
assert.equal(ctx.status, 302);
assert.equal(ctx.body, `Redirecting to ${url}.`);
});
});
@ -101,9 +102,9 @@ describe('ctx.redirect(url)', () => {
const url = 'http://google.com';
ctx.header.accept = 'text/plain';
ctx.redirect('http://google.com');
ctx.status.should.equal(302);
ctx.body.should.equal(`Redirecting to ${url}.`);
ctx.type.should.equal('text/plain');
assert.equal(ctx.status, 302);
assert.equal(ctx.body, `Redirecting to ${url}.`);
assert.equal(ctx.type, 'text/plain');
});
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
describe('ctx.remove(name)', () => {
@ -8,6 +9,6 @@ describe('ctx.remove(name)', () => {
const ctx = context();
ctx.set('x-foo', 'bar');
ctx.remove('x-foo');
ctx.response.header.should.eql({});
assert.deepEqual(ctx.response.header, {});
});
});

View File

@ -1,25 +1,26 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
describe('ctx.set(name, val)', () => {
it('should set a field value', () => {
const ctx = context();
ctx.set('x-foo', 'bar');
ctx.response.header['x-foo'].should.equal('bar');
assert.equal(ctx.response.header['x-foo'], 'bar');
});
it('should coerce to a string', () => {
const ctx = context();
ctx.set('x-foo', 5);
ctx.response.header['x-foo'].should.equal('5');
assert.equal(ctx.response.header['x-foo'], '5');
});
it('should set a field value of array', () => {
const ctx = context();
ctx.set('x-foo', ['foo', 'bar']);
ctx.response.header['x-foo'].should.eql([ 'foo', 'bar' ]);
assert.deepEqual(ctx.response.header['x-foo'], [ 'foo', 'bar' ]);
});
});
@ -32,7 +33,7 @@ describe('ctx.set(object)', () => {
bar: '2'
});
ctx.response.header.foo.should.equal('1');
ctx.response.header.bar.should.equal('2');
assert.equal(ctx.response.header.foo, '1');
assert.equal(ctx.response.header.bar, '2');
});
});

View File

@ -1,12 +1,13 @@
'use strict';
const assert = require('assert');
const response = require('../helpers/context').response;
const Stream = require('stream');
describe('res.socket', () => {
it('should return the request socket object', () => {
const res = response();
res.socket.should.be.instanceOf(Stream);
assert.equal(res.socket instanceof Stream, true);
});
});

View File

@ -13,7 +13,7 @@ describe('res.status=', () => {
it('should set the status', () => {
const res = response();
res.status = 403;
res.status.should.equal(403);
assert.equal(res.status, 403);
});
it('should not throw', () => {
@ -32,12 +32,12 @@ describe('res.status=', () => {
});
describe('and custom status', () => {
before(() => statuses['700'] = 'custom status');
beforeEach(() => statuses['700'] = 'custom status');
it('should set the status', () => {
const res = response();
res.status = 700;
res.status.should.equal(700);
assert.equal(res.status, 700);
});
it('should not throw', () => {
@ -52,8 +52,8 @@ describe('res.status=', () => {
});
});
function strip(status){
it('should strip content related header fields', done => {
function strip (status) {
it('should strip content related header fields', async () => {
const app = new Koa();
app.use(ctx => {
@ -67,19 +67,17 @@ describe('res.status=', () => {
assert(null == ctx.response.header['transfer-encoding']);
});
request(app.listen())
const res = await request(app.listen())
.get('/')
.expect(status)
.end((err, res) => {
res.should.not.have.header('content-type');
res.should.not.have.header('content-length');
res.should.not.have.header('content-encoding');
res.text.should.have.length(0);
done(err);
});
.expect(status);
assert.equal(res.headers.hasOwnProperty('content-type'), false);
assert.equal(res.headers.hasOwnProperty('content-length'), false);
assert.equal(res.headers.hasOwnProperty('content-encoding'), false);
assert.equal(res.text.length, 0);
});
it('should strip content releated header fields after status set', done => {
it('should strip content releated header fields after status set', async () => {
const app = new Koa();
app.use(ctx => {
@ -90,16 +88,14 @@ describe('res.status=', () => {
ctx.set('Transfer-Encoding', 'chunked');
});
request(app.listen())
const res = await request(app.listen())
.get('/')
.expect(status)
.end((err, res) => {
res.should.not.have.header('content-type');
res.should.not.have.header('content-length');
res.should.not.have.header('content-encoding');
res.text.should.have.length(0);
done(err);
});
.expect(status);
assert.equal(res.headers.hasOwnProperty('content-type'), false);
assert.equal(res.headers.hasOwnProperty('content-length'), false);
assert.equal(res.headers.hasOwnProperty('content-encoding'), false);
assert.equal(res.text.length, 0);
});
}

View File

@ -9,8 +9,8 @@ describe('ctx.type=', () => {
it('should set the Content-Type', () => {
const ctx = context();
ctx.type = 'text/plain';
ctx.type.should.equal('text/plain');
ctx.response.header['content-type'].should.equal('text/plain; charset=utf-8');
assert.equal(ctx.type, 'text/plain');
assert.equal(ctx.response.header['content-type'], 'text/plain; charset=utf-8');
});
});
@ -18,8 +18,8 @@ describe('ctx.type=', () => {
it('should lookup the mime', () => {
const ctx = context();
ctx.type = 'json';
ctx.type.should.equal('application/json');
ctx.response.header['content-type'].should.equal('application/json; charset=utf-8');
assert.equal(ctx.type, 'application/json');
assert.equal(ctx.response.header['content-type'], 'application/json; charset=utf-8');
});
});
@ -27,8 +27,8 @@ describe('ctx.type=', () => {
it('should default the charset', () => {
const ctx = context();
ctx.type = 'text/html';
ctx.type.should.equal('text/html');
ctx.response.header['content-type'].should.equal('text/html; charset=utf-8');
assert.equal(ctx.type, 'text/html');
assert.equal(ctx.response.header['content-type'], 'text/html; charset=utf-8');
});
});
@ -36,8 +36,8 @@ describe('ctx.type=', () => {
it('should not default the charset', () => {
const ctx = context();
ctx.type = 'text/html; charset=foo';
ctx.type.should.equal('text/html');
ctx.response.header['content-type'].should.equal('text/html; charset=foo');
assert.equal(ctx.type, 'text/html');
assert.equal(ctx.response.header['content-type'], 'text/html; charset=foo');
});
});
@ -63,7 +63,7 @@ describe('ctx.type', () => {
it('should return the mime', () => {
const ctx = context();
ctx.type = 'json';
ctx.type.should.equal('application/json');
assert.equal(ctx.type, 'application/json');
});
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const context = require('../helpers/context');
describe('ctx.vary(field)', () => {
@ -8,7 +9,7 @@ describe('ctx.vary(field)', () => {
it('should set it', () => {
const ctx = context();
ctx.vary('Accept');
ctx.response.header.vary.should.equal('Accept');
assert.equal(ctx.response.header.vary, 'Accept');
});
});
@ -17,7 +18,7 @@ describe('ctx.vary(field)', () => {
const ctx = context();
ctx.vary('Accept');
ctx.vary('Accept-Encoding');
ctx.response.header.vary.should.equal('Accept, Accept-Encoding');
assert.equal(ctx.response.header.vary, 'Accept, Accept-Encoding');
});
});
@ -28,7 +29,7 @@ describe('ctx.vary(field)', () => {
ctx.vary('Accept-Encoding');
ctx.vary('Accept');
ctx.vary('Accept-Encoding');
ctx.response.header.vary.should.equal('Accept, Accept-Encoding');
assert.equal(ctx.response.header.vary, 'Accept, Accept-Encoding');
});
});
});

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const Koa = require('../../');
const net = require('net');
@ -31,8 +32,8 @@ describe('res.writable', () => {
const server = app.listen();
requestTwice(server, (_, datas) => {
const responses = Buffer.concat(datas).toString();
responses.should.match(/request 1, writable: true/);
responses.should.match(/request 2, writable: true/);
assert.equal(/request 1, writable: true/.test(responses), true);
assert.equal(/request 2, writable: true/.test(responses), true);
done();
});
});