Migrate to jest for better debugging experience

ava is not yet integrated in popular IDEs.
This commit is contained in:
Franck Royer 2021-03-17 15:34:58 +11:00
parent 33a6176181
commit 5c29394937
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
8 changed files with 4774 additions and 2303 deletions

9
jest.config.js Normal file
View File

@ -0,0 +1,9 @@
const {defaults} = require('jest-config');
module.exports = {
testEnvironment: 'node',
moduleFileExtensions: [...defaults.moduleFileExtensions, 'd.ts'],
testTimeout: 10_000,
roots: [
'<rootDir>/build/main' // testing javascript output due to type issues with protobuf. TODO: try out ts-proto
]
};

6941
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -23,13 +23,13 @@
"test:lint": "eslint src --ext .ts", "test:lint": "eslint src --ext .ts",
"test:prettier": "prettier \"src/**/*.ts\" --list-different", "test:prettier": "prettier \"src/**/*.ts\" --list-different",
"test:spelling": "cspell \"{README.md,.github/*.md,src/**/*.ts}\"", "test:spelling": "cspell \"{README.md,.github/*.md,src/**/*.ts}\"",
"test:unit": "nyc --silent ava", "test:unit": "nyc --silent jest",
"test:lint-proto": "buf lint", "test:lint-proto": "buf lint",
"check-cli": "run-s test diff-integration-tests check-integration-tests", "check-cli": "run-s test diff-integration-tests check-integration-tests",
"check-integration-tests": "run-s check-integration-test:*", "check-integration-tests": "run-s check-integration-test:*",
"diff-integration-tests": "mkdir -p diff && rm -rf diff/test && cp -r test diff/test && rm -rf diff/test/test-*/.git && cd diff && git init --quiet && git add -A && git commit --quiet --no-verify --allow-empty -m 'WIP' && echo '\\n\\nCommitted most recent integration test output in the \"diff\" directory. Review the changes with \"cd diff && git diff HEAD\" or your preferred git diff viewer.'", "diff-integration-tests": "mkdir -p diff && rm -rf diff/test && cp -r test diff/test && rm -rf diff/test/test-*/.git && cd diff && git init --quiet && git add -A && git commit --quiet --no-verify --allow-empty -m 'WIP' && echo '\\n\\nCommitted most recent integration test output in the \"diff\" directory. Review the changes with \"cd diff && git diff HEAD\" or your preferred git diff viewer.'",
"watch:build": "tsc -p tsconfig.json -w", "watch:build": "tsc -p tsconfig.json -w",
"watch:test": "nyc --silent ava --watch", "watch:test": "nyc --silent jest --watch",
"cov": "run-s build test:unit cov:html cov:lcov && open-cli coverage/index.html", "cov": "run-s build test:unit cov:html cov:lcov && open-cli coverage/index.html",
"cov:html": "nyc report --reporter=html", "cov:html": "nyc report --reporter=html",
"cov:lcov": "nyc report --reporter=lcov", "cov:lcov": "nyc report --reporter=lcov",
@ -60,17 +60,16 @@
"yarg": "^1.0.8" "yarg": "^1.0.8"
}, },
"devDependencies": { "devDependencies": {
"@ava/typescript": "^1.1.1",
"@istanbuljs/nyc-config-typescript": "^1.0.1", "@istanbuljs/nyc-config-typescript": "^1.0.1",
"@types/app-root-path": "^1.2.4", "@types/app-root-path": "^1.2.4",
"@types/axios": "^0.14.0", "@types/axios": "^0.14.0",
"@types/google-protobuf": "^3.7.4",
"@types/jest": "^26.0.20",
"@types/node": "^14.14.31", "@types/node": "^14.14.31",
"@types/tail": "^2.0.0", "@types/tail": "^2.0.0",
"@typescript-eslint/eslint-plugin": "^4.0.1", "@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1", "@typescript-eslint/parser": "^4.0.1",
"app-root-path": "^3.0.0", "app-root-path": "^3.0.0",
"ava": "^3.15.0",
"ava-fast-check": "^4.0.2",
"axios": "^0.21.1", "axios": "^0.21.1",
"codecov": "^3.5.0", "codecov": "^3.5.0",
"cspell": "^4.1.0", "cspell": "^4.1.0",
@ -80,9 +79,11 @@
"eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-functional": "^3.0.2", "eslint-plugin-functional": "^3.0.2",
"eslint-plugin-import": "^2.22.0", "eslint-plugin-import": "^2.22.0",
"fast-check": "^2.13.0", "fast-check": "^2.14.0",
"gh-pages": "^3.1.0", "gh-pages": "^3.1.0",
"grpc_tools_node_protoc_ts": "^5.1.3", "grpc_tools_node_protoc_ts": "^5.1.3",
"jest": "^26.6.3",
"jest-fast-check": "^1.0.2",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"nyc": "^15.1.0", "nyc": "^15.1.0",
"open-cli": "^6.0.1", "open-cli": "^6.0.1",
@ -103,18 +104,6 @@
"LICENSE", "LICENSE",
"README.md" "README.md"
], ],
"ava": {
"failFast": true,
"timeout": "60s",
"typescript": {
"rewritePaths": {
"src/": "build/main/"
}
},
"files": [
"!build/module/**"
]
},
"config": { "config": {
"commitizen": { "commitizen": {
"path": "cz-conventional-changelog" "path": "cz-conventional-changelog"

View File

@ -1,4 +1,4 @@
import test from 'ava'; import 'jest';
import Libp2p from 'libp2p'; import Libp2p from 'libp2p';
import Pubsub from 'libp2p-interfaces/src/pubsub'; import Pubsub from 'libp2p-interfaces/src/pubsub';
@ -8,7 +8,7 @@ import { createNode } from './node';
import { Message } from './waku_message'; import { Message } from './waku_message';
import { CODEC, TOPIC, WakuRelay } from './waku_relay'; import { CODEC, TOPIC, WakuRelay } from './waku_relay';
test('Publishes message', async (t) => { test('Publishes message', async () => {
const message = Message.fromUtf8String('Bird bird bird, bird is the word!'); const message = Message.fromUtf8String('Bird bird bird, bird is the word!');
const [node1, node2] = await Promise.all([createNode(), createNode()]); const [node1, node2] = await Promise.all([createNode(), createNode()]);
@ -31,25 +31,25 @@ test('Publishes message', async (t) => {
const node1Received = await promise; const node1Received = await promise;
t.true(node1Received.isEqualTo(message)); expect(node1Received.isEqualTo(message)).toBeTruthy();
}); });
test('Registers waku relay protocol', async (t) => { test('Registers waku relay protocol', async () => {
const node = await createNode(); const node = await createNode();
const protocols = Array.from(node.upgrader.protocols.keys()); const protocols = Array.from(node.upgrader.protocols.keys());
t.truthy(protocols.findIndex((value) => value == CODEC)); expect(protocols.findIndex((value) => value == CODEC)).toBeTruthy();
}); });
test('Does not register any sub protocol', async (t) => { test('Does not register any sub protocol', async () => {
const node = await createNode(); const node = await createNode();
const protocols = Array.from(node.upgrader.protocols.keys()); const protocols = Array.from(node.upgrader.protocols.keys());
t.truthy(protocols.findIndex((value) => value.match(/sub/))); expect(protocols.findIndex((value) => value.match(/sub/))).toBeTruthy();
}); });
test('Nim-interop: nim-waku node connects to js node', async (t) => { test('Nim-interop: nim-waku node connects to js node', async () => {
const node = await createNode(); const node = await createNode();
const peerId = node.peerId.toB58String(); const peerId = node.peerId.toB58String();
@ -59,12 +59,12 @@ test('Nim-interop: nim-waku node connects to js node', async (t) => {
); );
const multiAddrWithId = localMultiaddr + '/p2p/' + peerId; const multiAddrWithId = localMultiaddr + '/p2p/' + peerId;
const nimWaku = new NimWaku(t.title); const nimWaku = new NimWaku(expect.getState().currentTestName);
await nimWaku.start({ staticnode: multiAddrWithId }); await nimWaku.start({ staticnode: multiAddrWithId });
const nimPeers = await nimWaku.peers(); const nimPeers = await nimWaku.peers();
t.deepEqual(nimPeers, [ expect(nimPeers).toEqual([
{ {
multiaddr: multiAddrWithId, multiaddr: multiAddrWithId,
protocol: CODEC, protocol: CODEC,
@ -75,10 +75,10 @@ test('Nim-interop: nim-waku node connects to js node', async (t) => {
const nimPeerId = await nimWaku.getPeerId(); const nimPeerId = await nimWaku.getPeerId();
const jsPeers = node.peerStore.peers; const jsPeers = node.peerStore.peers;
t.true(jsPeers.has(nimPeerId.toB58String())); expect(jsPeers.has(nimPeerId.toB58String())).toBeTruthy();
}); });
test('Nim-interop: js node receives default subscription from nim node', async (t) => { test('Nim-interop: js node receives default subscription from nim node', async () => {
const node = await createNode(); const node = await createNode();
const peerId = node.peerId.toB58String(); const peerId = node.peerId.toB58String();
@ -88,16 +88,16 @@ test('Nim-interop: js node receives default subscription from nim node', async (
); );
const multiAddrWithId = localMultiaddr + '/p2p/' + peerId; const multiAddrWithId = localMultiaddr + '/p2p/' + peerId;
const nimWaku = new NimWaku(t.title); const nimWaku = new NimWaku(expect.getState().currentTestName);
await nimWaku.start({ staticnode: multiAddrWithId }); await nimWaku.start({ staticnode: multiAddrWithId });
const nimPeerId = await nimWaku.getPeerId(); const nimPeerId = await nimWaku.getPeerId();
const subscribers = node.pubsub.getSubscribers(TOPIC); const subscribers = node.pubsub.getSubscribers(TOPIC);
t.true(subscribers.includes(nimPeerId.toB58String())); expect(subscribers).toContain(nimPeerId.toB58String());
}); });
test('Nim-interop: js node sends message to nim node', async (t) => { test('Nim-interop: js node sends message to nim node', async () => {
const message = Message.fromUtf8String('This is a message'); const message = Message.fromUtf8String('This is a message');
const node = await createNode(); const node = await createNode();
const wakuRelayNode = new WakuRelay(node.pubsub); const wakuRelayNode = new WakuRelay(node.pubsub);
@ -113,7 +113,7 @@ test('Nim-interop: js node sends message to nim node', async (t) => {
); );
const multiAddrWithId = localMultiaddr + '/p2p/' + peerId; const multiAddrWithId = localMultiaddr + '/p2p/' + peerId;
const nimWaku = new NimWaku(t.title); const nimWaku = new NimWaku(expect.getState().currentTestName);
await nimWaku.start({ staticnode: multiAddrWithId }); await nimWaku.start({ staticnode: multiAddrWithId });
await patchPeerStore(nimWaku, node); await patchPeerStore(nimWaku, node);
@ -124,14 +124,14 @@ test('Nim-interop: js node sends message to nim node', async (t) => {
const msgs = await nimWaku.messages(); const msgs = await nimWaku.messages();
t.is(msgs[0].contentTopic, message.contentTopic); expect(msgs[0].contentTopic).toEqual(message.contentTopic);
t.is(msgs[0].version, message.version); expect(msgs[0].version).toEqual(message.version);
const payload = Buffer.from(msgs[0].payload); const payload = Buffer.from(msgs[0].payload);
t.is(Buffer.compare(payload, message.payload), 0); expect(Buffer.compare(payload, message.payload)).toBe(0);
}); });
test('Nim-interop: nim node sends message to js node', async (t) => { test('Nim-interop: nim node sends message to js node', async () => {
const message = Message.fromUtf8String('Here is another message.'); const message = Message.fromUtf8String('Here is another message.');
const node = await createNode(); const node = await createNode();
const wakuRelayNode = new WakuRelay(node.pubsub); const wakuRelayNode = new WakuRelay(node.pubsub);
@ -142,7 +142,7 @@ test('Nim-interop: nim node sends message to js node', async (t) => {
); );
const multiAddrWithId = localMultiaddr + '/p2p/' + peerId; const multiAddrWithId = localMultiaddr + '/p2p/' + peerId;
const nimWaku = new NimWaku(t.title); const nimWaku = new NimWaku(expect.getState().currentTestName);
await nimWaku.start({ staticnode: multiAddrWithId }); await nimWaku.start({ staticnode: multiAddrWithId });
await patchPeerStore(nimWaku, node); await patchPeerStore(nimWaku, node);
@ -159,11 +159,11 @@ test('Nim-interop: nim node sends message to js node', async (t) => {
const receivedMsg = await receivedPromise; const receivedMsg = await receivedPromise;
t.is(receivedMsg.contentTopic, message.contentTopic); expect(receivedMsg.contentTopic).toBe(message.contentTopic);
t.is(receivedMsg.version, message.version); expect(receivedMsg.version).toBe(message.version);
const payload = Buffer.from(receivedMsg.payload); const payload = Buffer.from(receivedMsg.payload);
t.is(Buffer.compare(payload, message.payload), 0); expect(Buffer.compare(payload, message.payload)).toBe(0);
}); });
function waitForNextData(pubsub: Pubsub): Promise<Message> { function waitForNextData(pubsub: Pubsub): Promise<Message> {

View File

@ -1,40 +1,15 @@
import { fc, testProp } from 'ava-fast-check'; import { fc, testProp } from 'jest-fast-check';
import { WakuMessage } from '../gen/proto/waku/v2/waku_pb';
import { Message } from './waku_message'; import { Message } from './waku_message';
// This test is more about documenting how protobuf library works than testing it
testProp('Protobuf round trip binary serialization', [fc.string()], (t, s) => {
const wakuMsg = new WakuMessage();
wakuMsg.setPayload(Buffer.from(s, 'utf-8'));
const binary = wakuMsg.serializeBinary();
const actual = WakuMessage.deserializeBinary(binary);
const payload = actual.getPayload();
let buf;
if (typeof payload === 'string') {
buf = Buffer.from(payload, 'base64');
} else {
buf = Buffer.from(payload);
}
t.deepEqual(s, buf.toString('utf-8'));
});
testProp( testProp(
'Waku message round trip binary serialization', 'Waku message round trip binary serialization',
[fc.string()], [fc.fullUnicodeString()],
(t, s) => { (s) => {
const msg = Message.fromUtf8String(s); const msg = Message.fromUtf8String(s);
const binary = msg.toBinary(); const binary = msg.toBinary();
const actual = Message.fromBinary(binary); const actual = Message.fromBinary(binary);
t.true( expect(actual.isEqualTo(msg)).toBeTruthy();
actual.isEqualTo(msg),
`${JSON.stringify(actual)}\n${JSON.stringify(msg)}`
);
} }
); );

View File

@ -59,6 +59,7 @@ export class Message {
// Purely for tests purposes. // Purely for tests purposes.
// We do consider protobuf field when checking equality // We do consider protobuf field when checking equality
// As the content is held by the other fields. // As the content is held by the other fields.
// TODO: Consider using WakuMessage.equals
isEqualTo(other: Message) { isEqualTo(other: Message) {
return ( return (
Buffer.compare(this.payload, other.payload) === 0 && Buffer.compare(this.payload, other.payload) === 0 &&

View File

@ -1,8 +1,6 @@
import test from 'ava';
import { argsToArray, bufToHex, defaultArgs, strToHex } from './nim_waku'; import { argsToArray, bufToHex, defaultArgs, strToHex } from './nim_waku';
test('Correctly serialized arguments', (t) => { test('Correctly serialized arguments', () => {
const args = defaultArgs(); const args = defaultArgs();
Object.assign(args, { portsShift: 42 }); Object.assign(args, { portsShift: 42 });
@ -17,18 +15,18 @@ test('Correctly serialized arguments', (t) => {
'--ports-shift=42', '--ports-shift=42',
]; ];
t.deepEqual(actual, expected); expect(actual).toEqual(expected);
}); });
test('Convert utf-8 string to hex', (t) => { test('Convert utf-8 string to hex', () => {
const str = 'This is an utf-8 string.'; const str = 'This is an utf-8 string.';
const expected = '0x5468697320697320616e207574662d3820737472696e672e'; const expected = '0x5468697320697320616e207574662d3820737472696e672e';
const actual = strToHex(str); const actual = strToHex(str);
t.deepEqual(actual, expected); expect(actual).toEqual(expected);
}); });
test('Convert buffer to hex', (t) => { test('Convert buffer to hex', () => {
const buf = Uint8Array.from([ const buf = Uint8Array.from([
0x54, 0x54,
0x68, 0x68,
@ -58,5 +56,5 @@ test('Convert buffer to hex', (t) => {
const expected = '0x5468697320697320616e207574662d3820737472696e672e'; const expected = '0x5468697320697320616e207574662d3820737472696e672e';
const actual = bufToHex(buf); const actual = bufToHex(buf);
t.deepEqual(actual, expected); expect(actual).toEqual(expected);
}); });

View File

@ -41,7 +41,7 @@
// "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, // "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */,
"lib": ["es2017"], "lib": ["es2017"],
"types": ["node"], "types": ["node", "jest"],
"typeRoots": ["node_modules/@types", "src/types"] "typeRoots": ["node_modules/@types", "src/types"]
}, },
"include": ["src/**/*.ts"], "include": ["src/**/*.ts"],