node-supertest-fetch
node-supertest-fetch copied to clipboard
expectBody not verbose enough
When reading the docs, we could expect:
it('should return a response', async () => {
await fetch('/hello')
.expect(200)
.expect('content-type', /^application\/json/)
.expect({greeting: 'Hello!'});
});
to have the same behavior than:
it('should return a response', async () => {
const response = await fetch('/hello')
.expect(200)
.expect('content-type', /^application\/json/);
expect(await response.json()).toEqual({greeting: 'Hello!'});
});
However these two examples give very different outputs:
AssertionError [ERR_ASSERTION]: Request "GET /me" should have expected JSON body
vs.
expect(received).toEqual(expected)
Expected value to equal:
{"greeting": "Hello!"}
Received:
{"foo": "bar"}
Difference:
- Expected
+ Received
Object {
- "greeting": "Hello!",
+ "foo": "bar",
}
Not sure if this is easily doable but having the actual expect error thrown in the first case would be great as it's quite impractical for now.
Thanks for the great lib!
EDIT I realized that this was due to the fact that I'm using jest version of expect. Since the package is quite small, I think it would be great to rely on it to test assertions. As you'll get nice diffed output.
I just tried cloning a fresh copy
$ git clone [email protected]:jwalton/node-supertest-fetch.git
$ cd node-supertest-fetch
$ npm install
And then I added this to test/test.ts:
it('should generate a nice diff if body is incorrect', async function() {
await fetch(this.server, '/hello')
.expectStatus(200)
.expectHeader('content-type', 'application/json')
.expectBody({greeting: "Hello2!"});
});
And when I npm test
, I get back:
1) supertest-fetch
should generate a nice diff if body is incorrect:
AssertionError [ERR_ASSERTION]: Request "GET /hello" should have expected JSON body
+ expected - actual
{
- "greeting": "Hello!"
+ "greeting": "Hello2!"
}
supertest-fetch is just using straight up assert
, which is also what chai
is based on. If you try something like this in the REPL:
> assert = require('assert');
> let err;
> try { assert.deepStrictEqual({a: "foo"}, {a: "bar"}) } catch(e) { err = e; }
And then have a look at err
, it has an actual
and an expected
field, which is what your test runner (in my case, mocha) should be using to generate that nice looking diff.
So, I guess the first question is, what test runner are you using? I guess Jest? I've never used it, but at a glance Jest is supposed to handle this.
Indeed I'm using jest and I'm not getting a smart output. Tried with your project using jest + ts-jest:
yarn add --dev jest
yarn add --dev ts-jest
With the following jest.config.js
file:
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ['**/?(*.)+(spec|test).(j|t)s?(x)'],
setupFiles: ['<rootDir>/test/setup.js']
};
With this test/setup.js
file:
global.fetch = require('node-fetch');
And the following test/test.spec.ts
:
import http from 'http';
import { fetch } from '../../src';
const server = http.createServer(
(req, res) => {
if(req.url === '/hello') {
res.setHeader('content-type', 'application/json');
res.end(JSON.stringify({greeting: "Hello!"}));
} else if(req.url === '/hellotext') {
res.end("Hello");
} else if(req.url === '/err') {
res.setHeader('content-type', req.headers['content-type'] || 'text/plain');
res.statusCode = 400;
res.end('Boom!\nLong message\n');
} else {
res.statusCode = 404;
res.end();
}
}
);
it('should generate a nice diff if body is incorrect', async function() {
await fetch(server, '/hello')
.expectStatus(200)
.expectHeader('content-type', 'application/json')
.expectBody({greeting: "Hello2!"});
});
Running with yarn jest test/test.spec.ts
won't give you a nice diff.
If you want another quick test, try writing a jest test that just does something like:
assert.deepStrictEqual({a: "foo"}, {a: "bar"});
and see what that does. If that doesn't produce a pretty diff for you, I'd suggest this is something you should raise with the jest project.
Does seem to work fine with jest, in another project:
it.only('test', () => {
require('assert').deepStrictEqual({a: 'foo'}, {a: 'bar'});
});
Gives me:
assert.deepStrictEqual(received, expected)
Expected value to deeply and strictly equal to:
{"a": "bar"}
Received:
{"a": "foo"}
Difference:
- Expected
+ Received
Object {
- "a": "bar",
+ "a": "foo",
}
I believe the technical term I'm looking for is "wat!?"
This is exactly what we're doing in supertest-fetch. -_-
I'm playing with the source to see if I can pinpoint the diff, very strange indeed:
$ /private/tmp/node-supertest-fetch/node_modules/.bin/jest test/spec/test.spec.ts
FAIL test/spec/test.spec.ts
✕ test (11ms)
✕ should generate a nice diff if body is incorrect (26ms)
● test
assert.deepStrictEqual(received, expected)
Expected value to deeply and strictly equal to:
{"a": "bar"}
Received:
{"a": "foo"}
Difference:
- Expected
+ Received
Object {
- "a": "bar",
+ "a": "foo",
}
21 |
22 | it('test', () => {
> 23 | require('assert').deepStrictEqual({a: 'foo'}, {a: 'bar'});
| ^
24 | });
25 |
26 | it('should generate a nice diff if body is incorrect', async function() {
at Object.<anonymous> (test/spec/test.spec.ts:23:23)
● should generate a nice diff if body is incorrect
AssertionError [ERR_ASSERTION]: { greeting: 'Hello!' } deepStrictEqual { greeting: 'Hello2!' }
183 | });
184 | }
> 185 | assert.deepStrictEqual(
| ^
186 | jsonBody,
187 | expectedBody
188 | );
at Test.<anonymous> (src/Test.ts:185:24)
at step (src/Test.ts:32:23)
at Object.next (src/Test.ts:13:53)
at fulfilled (src/Test.ts:4:58)
EDIT the Jest error formatter is here: https://github.com/facebook/jest/blob/master/packages/jest-circus/src/format_node_assert_errors.js
Can't really find what might be going on.