Backend: Use @accord/ion for tests
This commit is contained in:
parent
3f7a5e12e4
commit
e58500de97
6011
backend/package-lock.json
generated
6011
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -8,12 +8,13 @@
|
||||
"dev": "ts-node-dev --transpile-only src/app.ts",
|
||||
"debug": "nodemon --exec 'node --inspect=0.0.0.0:9229 --require ts-node/register src/app.ts' --ext 'ts,yml'",
|
||||
"test": "ts-mocha --exit test/test.ts",
|
||||
"test:full": "ts-mocha test/test.ts"
|
||||
"test:unit": "ts-mocha test/**/**.test.ts"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "ADAMJR",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@accord/ion": "github:accord-dot-app/ion",
|
||||
"body-parser": "^1.19.0",
|
||||
"chai-things": "^0.2.0",
|
||||
"colors": "^1.4.0",
|
||||
@ -45,7 +46,6 @@
|
||||
"striptags": "^3.2.0",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.2.3",
|
||||
"un": "^0.0.0",
|
||||
"winston": "^3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -56,6 +56,7 @@
|
||||
"@types/colors": "^1.2.1",
|
||||
"@types/cors": "^2.8.7",
|
||||
"@types/crypto-js": "^4.0.2",
|
||||
"@types/deasync": "^0.1.2",
|
||||
"@types/dotenv": "^8.2.0",
|
||||
"@types/express": "^4.17.11",
|
||||
"@types/express-rate-limit": "^5.1.1",
|
||||
@ -76,13 +77,9 @@
|
||||
"chai": "^4.2.0",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"chai-spies": "^1.0.0",
|
||||
"i": "^0.3.6",
|
||||
"mocha": "^8.2.1",
|
||||
"nodemon": "^2.0.14",
|
||||
"npm": "^7.6.3",
|
||||
"sazerac": "^2.0.0",
|
||||
"supertest": "^6.1.3",
|
||||
"synchronous-promise": "^2.0.15",
|
||||
"ts-mocha": "^8.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ export default class Channels extends DBWrapper<string, ChannelDocument> {
|
||||
public async get(id: string | undefined) {
|
||||
const channel = await Channel.findById(id);
|
||||
if (!channel)
|
||||
throw new TypeError('Channel Not Found');
|
||||
throw new TypeError('Channel not found');
|
||||
return channel;
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ export class WSCooldowns {
|
||||
public readonly active = new Map<string, EventLog[]>();
|
||||
|
||||
// TODO: handle(userId, eventName, guildId)
|
||||
// required for bots
|
||||
public handle(userId: string, eventName: keyof WS.To) {
|
||||
this.prune(userId);
|
||||
this.add(userId, eventName);
|
||||
@ -14,16 +15,16 @@ export class WSCooldowns {
|
||||
throw new TypeError('You are doing too many things at once!');
|
||||
}
|
||||
|
||||
private get(clientId: string) {
|
||||
return this.active.get(clientId)
|
||||
private get(userId: string) {
|
||||
return this.active.get(userId)
|
||||
?? this.active
|
||||
.set(clientId, [])
|
||||
.get(clientId) as EventLog[];
|
||||
.set(userId, [])
|
||||
.get(userId) as EventLog[];
|
||||
}
|
||||
|
||||
private add(clientId: string, eventName: keyof WS.To) {
|
||||
private add(userId: string, eventName: keyof WS.To) {
|
||||
this
|
||||
.get(clientId)
|
||||
.get(userId)
|
||||
.push({ eventName, timestamp: new Date().getTime() });
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ export class WebSocket {
|
||||
const Event = require(`./ws-events/${file}`).default;
|
||||
try {
|
||||
const event = new Event();
|
||||
this.events.set(event.on, event);
|
||||
this.events.set(event.on, (event));
|
||||
} catch {}
|
||||
}
|
||||
|
||||
@ -46,7 +46,11 @@ export class WebSocket {
|
||||
for (const event of this.events.values())
|
||||
client.on(event.on, async (data: any) => {
|
||||
try {
|
||||
await event.invoke.bind(event)(this, client, data);
|
||||
const instructions = await event.invoke.call(event, this, client, data);
|
||||
for (const { emit, send, to } of instructions)
|
||||
this.io
|
||||
.to(to)
|
||||
.emit(emit, send);
|
||||
} catch (error) {
|
||||
client.emit('error', { message: (error as Error).message });
|
||||
} finally {
|
||||
|
@ -12,7 +12,6 @@ export default class implements WSEvent<'CHANNEL_DELETE'> {
|
||||
const channel = await deps.channels.getText(channelId);
|
||||
await deps.wsGuard.validateCan(client, channel.guildId, 'MANAGE_CHANNELS');
|
||||
|
||||
// clean up the message
|
||||
await User.updateMany(
|
||||
{ voice: { channelId } },
|
||||
{ voice: {} },
|
||||
|
20
backend/test/int/ws/channel-delete.tests.ts
Normal file
20
backend/test/int/ws/channel-delete.tests.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import ChannelDelete from '../../../src/ws/ws-events/channel-delete';
|
||||
import { given, test } from '@accord/ion';
|
||||
import { WebSocket } from '../../../src/ws/websocket';
|
||||
import { WS } from '../../../src/types/ws';
|
||||
|
||||
test(channelDelete, () => {
|
||||
before(() => console.log('before'));
|
||||
|
||||
given({}).rejectWith('Channel not found');
|
||||
|
||||
after(() => console.log('after'));
|
||||
});
|
||||
|
||||
async function channelDelete(args: WS.To['CHANNEL_DELETE']) {
|
||||
await import('../../../src/modules/deps');
|
||||
global['log'] = console;
|
||||
|
||||
const event = new ChannelDelete();
|
||||
return event.invoke(new WebSocket(), {} as any, args);
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { config } from 'dotenv';
|
||||
import { execSync } from 'child_process';
|
||||
import { expect, should, use } from 'chai';
|
||||
import { should, use } from 'chai';
|
||||
import chaiAsPromised from 'chai-as-promised';
|
||||
import chaiSpies from 'chai-spies';
|
||||
import chaiThings from 'chai-things';
|
||||
@ -26,16 +26,12 @@ use(should);
|
||||
try {
|
||||
execSync(`kill -9 $(lsof -i :${process.env.PORT} | tail -n 1 | cut -d ' ' -f5) 2>> /dev/null`);
|
||||
} catch {}
|
||||
|
||||
await import('./int/ws/channel-delete.tests');
|
||||
})();
|
||||
|
||||
// import('./unit/models/app.tests');
|
||||
// import('./unit/models/channel.tests');
|
||||
// import('./unit/models/guild.tests');
|
||||
// import('./unit/models/guild-member.tests');
|
||||
// import('./unit/models/invite.tests');
|
||||
// import('./unit/models/message.tests');
|
||||
// import('./unit/models/role.tests');
|
||||
// import('./unit/models/user.tests');
|
||||
// import('./unit/other/snowflake-entity.tests');
|
||||
// import('./unit/other/ws-cooldowns.tests');
|
||||
import('./unit/ws/channel-delete.tests');
|
||||
/**
|
||||
* e2e: testing the final product (i.e. app)
|
||||
* integration: testing full unit with dependencies
|
||||
* unit: testing one unit (i.e. one class, function etc.) - mocks dependencies
|
||||
*/
|
@ -1,5 +1,5 @@
|
||||
import { generateSnowflake } from '../../../src/data/snowflake-entity';
|
||||
import { test, given } from 'sazerac';
|
||||
import { test, given } from '@accord/ion';
|
||||
import { longString, mongooseError } from '../../test-utils';
|
||||
import { App } from '../../../src/data/models/app';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Channel } from '../../../src/data/models/channel';
|
||||
import { generateSnowflake } from '../../../src/data/snowflake-entity';
|
||||
import { test, given } from 'sazerac';
|
||||
import { test, given } from '@accord/ion';
|
||||
import { longString, mongooseError } from '../../test-utils';
|
||||
|
||||
test(createChannel, () => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { generateSnowflake } from '../../../src/data/snowflake-entity';
|
||||
import { test, given } from 'sazerac';
|
||||
import { test, given } from '@accord/ion';
|
||||
import { mongooseError } from '../../test-utils';
|
||||
import { GuildMember } from '../../../src/data/models/guild-member';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { generateSnowflake } from '../../../src/data/snowflake-entity';
|
||||
import { test, given } from 'sazerac';
|
||||
import { test, given } from '@accord/ion';
|
||||
import { longString, mongooseError } from '../../test-utils';
|
||||
import { Guild } from '../../../src/data/models/guild';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { generateSnowflake } from '../../../src/data/snowflake-entity';
|
||||
import { test, given } from 'sazerac';
|
||||
import { test, given } from '@accord/ion';
|
||||
import { mongooseError } from '../../test-utils';
|
||||
import { Invite } from '../../../src/data/models/invite';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { generateSnowflake } from '../../../src/data/snowflake-entity';
|
||||
import { test, given } from 'sazerac';
|
||||
import { test, given } from '@accord/ion';
|
||||
import { longString, mongooseError } from '../../test-utils';
|
||||
import { Message } from '../../../src/data/models/message';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { generateSnowflake } from '../../../src/data/snowflake-entity';
|
||||
import { test, given } from 'sazerac';
|
||||
import { test, given } from '@accord/ion';
|
||||
import { longString, mongooseError } from '../../test-utils';
|
||||
import { Role } from '../../../src/data/models/role';
|
||||
import { PermissionTypes } from '../../../src/types/permission-types';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { generateSnowflake } from '../../../src/data/snowflake-entity';
|
||||
import { test, given } from 'sazerac';
|
||||
import { test, given } from '@accord/ion';
|
||||
import { longArray, mongooseError } from '../../test-utils';
|
||||
import { User } from '../../../src/data/models/user';
|
||||
import { Mock } from '../../mock/mock';
|
||||
|
41
backend/test/unit/other/ws-cooldowns.test.ts
Normal file
41
backend/test/unit/other/ws-cooldowns.test.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { expect } from 'chai';
|
||||
import { WSCooldowns } from '../../../src/ws/modules/ws-cooldowns';
|
||||
import { given, test } from '@accord/ion';
|
||||
import { generateSnowflake } from '../../../src/data/snowflake-entity';
|
||||
import assert from 'assert';
|
||||
|
||||
describe('ws-cooldowns', () => {
|
||||
let cooldowns = new WSCooldowns();
|
||||
let userId = generateSnowflake();
|
||||
|
||||
test(cooldowns.handle.bind(cooldowns), () => {
|
||||
afterEach(() => {
|
||||
cooldowns = new WSCooldowns();
|
||||
userId = generateSnowflake();
|
||||
});
|
||||
|
||||
given(userId, 'MESSAGE_CREATE')
|
||||
.message('record with user id added')
|
||||
.assert(() => cooldowns.active.has(userId));
|
||||
|
||||
given(userId, 'MESSAGE_CREATE')
|
||||
.message('handle, exceeds max cooldowns, throws error')
|
||||
.assert(() => {
|
||||
const handle = () => cooldowns.handle(userId, 'MESSAGE_CREATE');
|
||||
for (let i = 0; i < 60; i++) handle();
|
||||
|
||||
return expect(handle).to.throw('You are doing too many things at once!');
|
||||
});
|
||||
|
||||
given(userId, 'MESSAGE_CREATE')
|
||||
.message('handle, prunes old cooldowns')
|
||||
.assert(() => {
|
||||
cooldowns.active.set(userId, [
|
||||
{ eventName: 'MESSAGE_CREATE', timestamp: new Date(0).getTime() },
|
||||
{ eventName: 'MESSAGE_CREATE', timestamp: new Date(0).getTime() },
|
||||
]);
|
||||
return expect(cooldowns.active.size).to.equal(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,42 +0,0 @@
|
||||
import { expect } from 'chai';
|
||||
import generateInvite from '../../../src/data/utils/generate-invite';
|
||||
import { WSCooldowns } from '../../../src/ws/modules/ws-cooldowns';
|
||||
|
||||
describe('ws-cooldowns', () => {
|
||||
let clientId: string;
|
||||
let cooldowns: WSCooldowns;
|
||||
|
||||
beforeEach(() => {
|
||||
cooldowns = new WSCooldowns();
|
||||
clientId = generateInvite();
|
||||
});
|
||||
|
||||
it('handle, adds cooldown', () => {
|
||||
handle();
|
||||
expect(cooldowns.active.size).to.equal(1);
|
||||
});
|
||||
|
||||
it('handle, no cooldowns, no error', () => {
|
||||
expect(handle).to.not.throw();
|
||||
});
|
||||
|
||||
it('handle, exceeds max cooldowns, throws error', () => {
|
||||
for (let i = 0; i < 60; i++) handle();
|
||||
expect(handle).to.throw('You are doing too many things at once!');
|
||||
});
|
||||
|
||||
it('handle, prunes old cooldowns', () => {
|
||||
cooldowns.active.set(clientId, [
|
||||
{ eventName: 'MESSAGE_CREATE', timestamp: new Date(0).getTime() },
|
||||
{ eventName: 'MESSAGE_CREATE', timestamp: new Date(0).getTime() },
|
||||
]);
|
||||
|
||||
handle();
|
||||
|
||||
expect(cooldowns.active.size).to.equal(1);
|
||||
});
|
||||
|
||||
function handle() {
|
||||
return cooldowns.handle(clientId, 'MESSAGE_CREATE');
|
||||
}
|
||||
});
|
@ -1,14 +0,0 @@
|
||||
import ChannelDelete from '../../../src/ws/ws-events/channel-delete';
|
||||
import { given, test } from 'sazerac';
|
||||
import { WebSocket } from '../../../src/ws/websocket';
|
||||
import { WS } from '../../../src/types/ws';
|
||||
import SynchronousPromise from 'synchronous-promise';
|
||||
|
||||
test(channelDelete, () => {
|
||||
given().expectError('Channel not found');
|
||||
});
|
||||
|
||||
function channelDelete(args: WS.To['CHANNEL_DELETE']) {
|
||||
const event = new ChannelDelete();
|
||||
return new SynchronousPromise(event.invoke.bind(event))(new WebSocket(), {} as any, args);
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
"lib": ["ES2020", "ES2019"],
|
||||
"module": "CommonJS",
|
||||
"noImplicitAny": false,
|
||||
"declaration": true,
|
||||
"outDir": "lib",
|
||||
"removeComments": true,
|
||||
"resolveJsonModule": true,
|
||||
@ -22,5 +23,6 @@
|
||||
"src",
|
||||
"env",
|
||||
"**/*.ts"
|
||||
]
|
||||
],
|
||||
"exclude": ["test"]
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { given, test } from 'sazerac';
|
||||
import { given, test } from '@accord/ion';
|
||||
import { FormatService } from './format-service';
|
||||
|
||||
describe('format-service', () => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { MentionService } from './mention-service';
|
||||
import { test, given } from 'sazerac';
|
||||
import { test, given } from '@accord/ion';
|
||||
|
||||
describe.skip('mention-service', () => {
|
||||
let service: MentionService;
|
||||
|
Loading…
x
Reference in New Issue
Block a user