Skip to content

Commit

Permalink
[test] Move from chai and mocha to builtin node.js test runner and as…
Browse files Browse the repository at this point in the history
…sert libraries
  • Loading branch information
SamuelMarks committed Feb 2, 2024
1 parent e6c96b1 commit f2edf24
Show file tree
Hide file tree
Showing 13 changed files with 4,924 additions and 11,268 deletions.
2 changes: 1 addition & 1 deletion config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { networkInterfaces } from 'os';
import { networkInterfaces } from 'node:os';

import * as Logger from 'bunyan';
import { PostgresConnectionOptions } from 'typeorm/driver/postgres/PostgresConnectionOptions';
Expand Down
15,910 changes: 4,769 additions & 11,141 deletions package-lock.json

Large diffs are not rendered by default.

24 changes: 9 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "restify-orm-scaffold",
"version": "0.0.55",
"version": "0.0.56",
"description": "Sample REST API scaffold built on Node.JS in TypeScript with restify and TypeORM (with Waterline and Sequelize support also).",
"keywords": [
"restify",
Expand All @@ -21,7 +21,7 @@
"scripts": {
"with_bunyan": "node main.js | bunyan",
"start": "node main.js",
"test": "nyc mocha --require ts-node/register --require source-map-support/register --recursive",
"test": "tsx --test test/api/**/test_*.ts",
"coverage": "nyc report --reporter=text-lcov | coveralls"
},
"nyc": {
Expand All @@ -38,11 +38,11 @@
"all": true
},
"dependencies": {
"@offscale/custom-restify-errors": "^0.0.20",
"@offscale/nodejs-utils": "^0.0.26",
"@offscale/orm-mw": "^0.0.27",
"@offscale/restify-validators": "^0.0.18",
"@offscale/routes-merger": "^0.0.22",
"@offscale/custom-restify-errors": "^0.0.21",
"@offscale/nodejs-utils": "^0.0.28",
"@offscale/orm-mw": "^0.0.28",
"@offscale/restify-validators": "^0.0.19",
"@offscale/routes-merger": "^0.0.23",
"argon2": "0.31.2",
"async": "^3.2.5",
"bunyan": "^1.8.15",
Expand All @@ -61,12 +61,10 @@
"@faker-js/faker": "^8.4.0",
"@types/async": "^3.2.24",
"@types/bunyan": "1.8.11",
"@types/chai": "^4.3.11",
"@types/connect": "^3.4.38",
"@types/express": "^4.17.21",
"@types/ioredis": "4.28.10",
"@types/mocha": "^10.0.6",
"@types/node": "^20.11.10",
"@types/node": "^20.11.16",
"@types/redis": "^4.0.10",
"@types/restify": "^8.5.12",
"@types/restify-errors": "^4.3.8",
Expand All @@ -75,16 +73,12 @@
"@types/tv4": "^1.2.33",
"@types/uuid": "^9.0.8",
"ajv": "^8.12.0",
"chai": "^5.0.3",
"chai-json-schema": "^1.5.1",
"chai-json-schema-ajv": "^5.2.4",
"coveralls": "^3.1.1",
"mocha": "^10.2.0",
"mocha-pretty-bunyan": "^1.1.1",
"nyc": "^15.1.0",
"source-map-support": "^0.5.21",
"supertest": "^6.3.4",
"ts-node": "^10.9.2",
"tsx": "^4.7.0",
"typescript": "~5.3.3"
}
}
4 changes: 2 additions & 2 deletions parser.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as ts from 'typescript';
import * as fs from 'fs';
import * as path from 'path';
import * as fs from 'node:fs';
import * as path from 'node:path';

interface DocEntry {
name?: string;
Expand Down
25 changes: 11 additions & 14 deletions test/api/auth/auth_test_sdk.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as chai from 'chai';
import { expect } from 'chai';
import assert from "node:assert/strict";

import { Server } from 'restify';
import supertest, { Response } from 'supertest';
import Ajv from "ajv"

import { getError, sanitiseSchema, supertestGetError } from '@offscale/nodejs-utils';
import { AccessTokenType } from '@offscale/nodejs-utils/interfaces';
Expand All @@ -11,18 +12,13 @@ import { User } from '../../../api/user/models';
import { user_mocks } from '../user/user_mocks';
import { UserTestSDK } from '../user/user_test_sdk';
import { removeNullProperties } from '../../../utils';
// tslint:disable-next-line:no-var-requires
const chaiJsonSchema = require('chai-json-schema');
// import { saltSeeker } from '../../../api/user/utils';
// import { saltSeekerCb } from '../../../main';

/* tslint:disable:no-var-requires */
const user_schema = sanitiseSchema(require('./../user/schema.json'), User._omit);
const auth_schema = require('./schema.json');

// @ts-ignore
chai.use(chaiJsonSchema);

export class AuthTestSDK {
private user_sdk: UserTestSDK;

Expand All @@ -34,7 +30,7 @@ export class AuthTestSDK {
return new Promise<Response>((resolve, reject) => {
if (user == null) return reject(new TypeError('`user` argument to `login` must be defined'));

expect(auth_routes.login).to.be.an.instanceOf(Function);
assert.ok(auth_routes.login instanceof Function);
supertest(this.app)
.post('/api/auth')
.send(user)
Expand All @@ -45,13 +41,14 @@ export class AuthTestSDK {
if (err != null) return reject(supertestGetError(err, res));
else if (res.error) return reject(getError(res.error));
try {
expect(res.body).to.be.an('object');
expect(res.body).to.have.property('access_token');
expect(res.body.access_token).to.have.lengthOf.at.least(1);
expect(res.header['x-access-token']).to.eql(res.body.access_token);
expect(removeNullProperties(res.body)).to.be.jsonSchema(auth_schema);
assert.ok(res.body instanceof Object);
assert.ok(res.body.hasOwnProperty('access_token'));
assert.ok(res.body.access_token.length > 0);
assert.strictEqual(res.header['x-access-token'], res.body.access_token);
const validate = new Ajv({allErrors: true}).compile(auth_schema);
assert.ok(validate(removeNullProperties(res.body)), validate.errors?.toString());
} catch (e) {
return reject(e as Chai.AssertionError);
return reject(e);
}
return resolve(res);
});
Expand Down
29 changes: 19 additions & 10 deletions test/api/auth/test_auth_api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as path from 'node:path';
import { basename } from 'node:path';
import { describe, before, after, it } from 'node:test';

import { waterfall } from 'async';
import { createLogger } from 'bunyan';
import * as path from 'path';
import { basename } from 'path';

import { Server } from 'restify';

Expand Down Expand Up @@ -31,18 +33,18 @@ const connection_name = `${tapp_name}::${path.basename(__filename).replace(/\./g

const logger = createLogger({ name: tapp_name });

describe('Auth::routes', () => {
describe('Auth::routes', (t) => {
let sdk: AuthTestSDK;

before(done =>
before((t, done) =>
waterfall([
tearDownConnections,
(cb: (err: Error | undefined) => void) => {
AccessToken.reset();
return cb(void 0);
},
(cb: (err: Error | undefined) => void) => setupOrmApp(
model_route_to_map(models_and_routes), { connection_name, logger },
(cb: (err: Error | undefined) => void) => setupOrmApp(
model_route_to_map(models_and_routes), { connection_name, logger },
{ skip_start_app: true, app_name: tapp_name, logger },
cb
),
Expand All @@ -57,15 +59,22 @@ describe('Auth::routes', () => {
)
);

after('deregister_all', async () => await unregister_all(sdk, mocks));
after('tearDownConnections', tearDownConnections);
after('closeApp', done => closeApp(sdk!.app)(done));
// deregister_all
after(async () => await unregister_all(sdk, mocks));

// tearDownConnections
after((t, done) => tearDownConnections(done));

// closeApp
after((t, done) => closeApp(sdk!.app)(done));

describe('/api/auth', () => {
before(async () => await unregister_all(sdk, mocks));
after(async () => await unregister_all(sdk, mocks));

it('POST should login user', async () => await sdk.register_login(mocks[1]));
// POST should login user
it((t, done) =>
sdk.register_login(mocks[1]).then(e => done(void 0)).catch(done));

it('DELETE should logout user', async () => {
const user_mock = mocks[2];
Expand Down
21 changes: 11 additions & 10 deletions test/api/root/test_root_api.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { basename } from 'path';
import { basename } from 'node:path';
import { describe, after, before, it } from "node:test";

import { createLogger } from 'bunyan';
import { expect } from 'chai';
import supertest, { Response } from 'supertest';
import { Server } from 'restify';

import { TApp } from '@offscale/routes-merger/interfaces';

import { setupOrmApp } from '../../../main';
import { closeApp } from '../../shared_tests';
import assert from "node:assert/strict";

const tapp_name = `test::${basename(__dirname)}`;
const logger = createLogger({ name: tapp_name });

describe('Root::routes', () => {
let app: Server;

before(done => setupOrmApp(new Map(),
before((t, done) => setupOrmApp(new Map(),
{ orms_in: undefined, logger },
{ skip_use: true, skip_start_app: true, app_name: tapp_name, logger },
(err: Error, _app?: TApp) => {
Expand All @@ -26,23 +27,23 @@ describe('Root::routes', () => {
})
);

after(done => closeApp(app)(done));
after((t, done) => closeApp(app)(done));

describe('/', () =>
it('should get version', done => {
it('should get version', (t, done) => {
supertest(app)
.get('/')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.end((err, res: Response) => {
if (err != null) return done(err);
try {
expect(res.status).to.be.equal(200);
expect(res.body).to.be.an.instanceOf(Object);
expect(res.body).to.have.property('version');
expect(res.body.version.split('.').length - 1).to.be.equal(2);
assert.strictEqual(res.status, 200);
assert.ok(res.body instanceof Object);
assert.ok(res.body.hasOwnProperty('version'));
assert.strictEqual(res.body.version.split('.').length - 1, 2);
} catch (e) {
return done(e as Chai.AssertionError);
return done(e);
}
return done(void 0);
});
Expand Down
20 changes: 12 additions & 8 deletions test/api/user/test_user_admin_api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as path from 'node:path';
import { basename } from 'node:path';
import { describe, after, before, it } from "node:test";

import { map, waterfall } from 'async';
import { createLogger } from 'bunyan';
import * as path from 'path';
import { basename } from 'path';
import { Server } from 'restify';

import { exceptionToErrorResponse, model_route_to_map } from '@offscale/nodejs-utils';
Expand All @@ -16,6 +18,7 @@ import { closeApp, tearDownConnections, unregister_all } from '../../shared_test
import { AuthTestSDK } from '../auth/auth_test_sdk';
import { user_mocks } from './user_mocks';
import { UserTestSDK } from './user_test_sdk';
import { Response } from "supertest";

const models_and_routes: IModelRoute = {
user: all_models_and_routes_as_mr['user'],
Expand All @@ -34,7 +37,7 @@ describe('User::admin::routes', () => {
let auth_sdk: AuthTestSDK;
let app: Server;

before(done =>
before((t, done) =>
waterfall([
tearDownConnections,
(cb: (err: Error | undefined) => void) => {
Expand All @@ -59,8 +62,8 @@ describe('User::admin::routes', () => {
)
);

after(tearDownConnections);
after(done => closeApp(app)(done));
after((t, done) => tearDownConnections(done));
after((t, done) => closeApp(app)(done));

/*
after('destroy objects', done => {
Expand All @@ -70,7 +73,8 @@ describe('User::admin::routes', () => {
*/

describe('ADMIN /api/user/:email', () => {
before('register_all', done => map(mocks, (user, cb) =>
// register_all
before((t, done) => map(mocks, (user, cb) =>
sdk.register(user)
.then(res => {
user.access_token = res!.header['x-access-token'];
Expand All @@ -82,7 +86,7 @@ describe('User::admin::routes', () => {
after(async () => await unregister_all(auth_sdk, mocks));

it('GET should retrieve other user', async () =>
await sdk.read(mocks[0].access_token!, mocks[1])
await (sdk.read as unknown as ((access_token: AccessTokenType, expected_user: User) => Promise<void>))(mocks[0].access_token!, mocks[1])
);

it('PUT should update other user', async () => {
Expand All @@ -91,7 +95,7 @@ describe('User::admin::routes', () => {
});

it('GET /api/users should get all users', async () =>
await sdk.get_all(mocks[4].access_token!)
await (sdk.get_all as unknown as ((access_token: string) => Promise<void>))(mocks[4].access_token!)
);

it('DELETE should unregister other user', async () => {
Expand Down

0 comments on commit f2edf24

Please sign in to comment.