180 passing / 24 failing
This commit is contained in:
parent
7ccbc5c3c7
commit
afce78a86f
@ -1,6 +1,6 @@
|
||||
import { Document, model, Schema } from 'mongoose';
|
||||
import patterns from '../../types/patterns';
|
||||
import { createdAtToDate, getNameAcronym, useId } from '../../utils/utils';
|
||||
import { createdAtToDate, useId } from '../../utils/utils';
|
||||
import { generateSnowflake } from '../snowflake-entity';
|
||||
|
||||
// properties we don't need to define when creating a guild
|
||||
|
@ -67,15 +67,4 @@ export class WSGuard {
|
||||
const id = this.users.verifyToken(token);
|
||||
return { id };
|
||||
}
|
||||
|
||||
public validateKeys<K extends keyof typeof Prohibited>(type: K, partial: any) {
|
||||
const contains = this.includesProhibited<K>(partial, type);
|
||||
if (contains)
|
||||
throw new TypeError('Contains readonly values');
|
||||
}
|
||||
|
||||
private includesProhibited<K extends keyof typeof Prohibited>(partial: any, type: K) {
|
||||
const keys = Object.keys(partial);
|
||||
return Prohibited[type].some(k => keys.includes(k));
|
||||
}
|
||||
}
|
||||
|
@ -18,18 +18,18 @@ export default class implements WSEvent<'GUILD_UPDATE'> {
|
||||
public async invoke(ws: WebSocket, client: Socket, { guildId, name, iconURL }: WS.Params.GuildUpdate) {
|
||||
await this.guard.validateCan(client, guildId, 'MANAGE_GUILD');
|
||||
|
||||
const partialGuild = { name, iconURL };
|
||||
this.guard.validateKeys('guild', partialGuild);
|
||||
|
||||
const guild = await this.guilds.get(guildId);
|
||||
const partial: Partial<Entity.Guild> = {};
|
||||
const hasChanged = (key: string, value: any) => value && guild[key] !== value;
|
||||
|
||||
if (iconURL) guild.iconURL = iconURL;
|
||||
if (name) guild.name = name;
|
||||
if (hasChanged('iconURL', iconURL)) guild.iconURL = iconURL;
|
||||
if (hasChanged('name', name)) guild.name = name!;
|
||||
|
||||
Object.assign(guild, partial);
|
||||
await guild.save();
|
||||
|
||||
ws.io
|
||||
.to(guildId)
|
||||
.emit('GUILD_UPDATE', { guildId, partialGuild } as WS.Args.GuildUpdate);
|
||||
.emit('GUILD_UPDATE', { guildId, partialGuild: partial } as WS.Args.GuildUpdate);
|
||||
}
|
||||
}
|
||||
|
@ -1,119 +0,0 @@
|
||||
import AddFriend from '../../../src/ws/ws-events/add-friend';
|
||||
import RemoveFriend from '../../../src/ws/ws-events/remove-friend';
|
||||
import { WebSocket } from '../../../src/ws/websocket';
|
||||
import io from 'socket.io-client';
|
||||
import { Mock } from '../../mock/mock';
|
||||
import { expect } from 'chai';
|
||||
import { SelfUserDocument, User } from '../../../src/data/models/user';
|
||||
import { Channel } from '../../../src/data/models/channel';
|
||||
|
||||
describe('add-friend', () => {
|
||||
const client = (io as any)(`http://localhost:${process.env.PORT}`) as any;
|
||||
let event: AddFriend;
|
||||
let ws: WebSocket;
|
||||
|
||||
let sender: SelfUserDocument;
|
||||
let friend: SelfUserDocument;
|
||||
|
||||
beforeEach(async () => {
|
||||
({ event, ws, user: sender as any } = await Mock.defaultSetup(client, AddFriend));
|
||||
|
||||
friend = await Mock.self();
|
||||
});
|
||||
|
||||
afterEach(async () => await Mock.afterEach(ws));
|
||||
after(async () => await Mock.after(client));
|
||||
|
||||
it('user sends request, fulfilled', async () => {
|
||||
await expect(addFriend()).to.be.fulfilled;
|
||||
});
|
||||
|
||||
it('user adds self as friend, rejected', async () => {
|
||||
friend.username = sender.username;
|
||||
|
||||
await expect(addFriend()).to.be.rejectedWith('You cannot add yourself as a friend');
|
||||
});
|
||||
|
||||
it('friend blocked sender, rejected', async () => {
|
||||
friend.ignored?.userIds.push(sender.id);
|
||||
await friend.updateOne(friend);
|
||||
|
||||
await expect(addFriend()).to.be.rejectedWith('This user is blocking you');
|
||||
});
|
||||
|
||||
it('user adds non existing user, rejected', async () => {
|
||||
await friend.deleteOne();
|
||||
|
||||
await expect(addFriend()).to.be.rejectedWith('User Not Found');
|
||||
});
|
||||
|
||||
it('both users add each other, creates one dm channel', async () => {
|
||||
await addFriend();
|
||||
await returnFriend();
|
||||
|
||||
const exists = await Channel.countDocuments({ memberIds: sender.id });
|
||||
expect(exists).to.equal(1);
|
||||
});
|
||||
|
||||
it('user add, remove, then re-add each other, reuses old dm channel', async () => {
|
||||
await addFriend();
|
||||
await returnFriend();
|
||||
|
||||
await removeFriend();
|
||||
|
||||
await addFriend();
|
||||
await returnFriend();
|
||||
|
||||
const docs = await Channel.countDocuments({ type: 'DM' });
|
||||
expect(docs).to.equal(1);
|
||||
});
|
||||
|
||||
it('both users add each other, friend request removed', async () => {
|
||||
await addFriend();
|
||||
await returnFriend();
|
||||
|
||||
sender = await User.findById(sender.id) as any;
|
||||
friend = await User.findById(friend.id) as any;
|
||||
|
||||
expect(sender.friendRequestIds).to.be.empty;
|
||||
expect(friend.friendRequestIds).to.be.empty;
|
||||
});
|
||||
|
||||
it('both users add each other, friend added', async () => {
|
||||
await addFriend();
|
||||
await returnFriend();
|
||||
|
||||
friend = await User.findById(friend.id) as any;
|
||||
sender = await User.findById(sender.id) as any;
|
||||
|
||||
expect(friend.friendIds.length).to.equal(1);
|
||||
expect(sender.friendIds.length).to.equal(1);
|
||||
});
|
||||
|
||||
it('user adds friends twice, rejected', async () => {
|
||||
await addFriend();
|
||||
await expect(addFriend()).to.be.rejectedWith('Friend request already sent');
|
||||
});
|
||||
|
||||
it('user already friends, rejected', async () => {
|
||||
await addFriend();
|
||||
await returnFriend();
|
||||
|
||||
await expect(addFriend()).to.be.rejectedWith('You are already friends');
|
||||
});
|
||||
|
||||
async function addFriend() {
|
||||
return event.invoke(ws, client, { username: friend.username });
|
||||
}
|
||||
|
||||
async function returnFriend() {
|
||||
ws.sessions.set(client.id, friend.id);
|
||||
await event.invoke(ws, client, { username: sender.username });
|
||||
|
||||
ws.sessions.set(client.id, sender.id);
|
||||
}
|
||||
|
||||
async function removeFriend() {
|
||||
await new RemoveFriend().invoke(ws, client, { friendId: friend.id });
|
||||
}
|
||||
});
|
@ -11,11 +11,10 @@ describe('guild-create', () => {
|
||||
let ws: WebSocket;
|
||||
let event: GuildCreate;
|
||||
|
||||
let user: UserDocument;
|
||||
let member: GuildMemberDocument;
|
||||
let user: SelfUserDocument;
|
||||
|
||||
beforeEach(async () => {
|
||||
({ ws, event, member, user } = await Mock.defaultSetup(client, GuildCreate));
|
||||
({ ws, event, user } = await Mock.defaultSetup(client, GuildCreate));
|
||||
});
|
||||
|
||||
afterEach(async () => Mock.afterEach(ws));
|
||||
@ -26,19 +25,17 @@ describe('guild-create', () => {
|
||||
});
|
||||
|
||||
it('user creates guild, added to user.guilds', async () => {
|
||||
const oldCount = user.guilds.length;
|
||||
const oldCount = user.guildIds.length;
|
||||
await guildCreate();
|
||||
|
||||
user = await User.findById(user.id);
|
||||
expect(user.guilds.length).to.be.greaterThan(oldCount);
|
||||
expect(user.guildIds.length).to.be.greaterThan(oldCount);
|
||||
});
|
||||
|
||||
function guildCreate(partialGuild?: Partial<Entity.Guild>) {
|
||||
return event.invoke(ws, client, {
|
||||
partialGuild: {
|
||||
name: 'Mock Guild',
|
||||
...partialGuild,
|
||||
},
|
||||
name: 'Mock Guild',
|
||||
...partialGuild,
|
||||
});
|
||||
}
|
||||
});
|
@ -73,12 +73,12 @@ describe('guild-delete', () => {
|
||||
expect(guild).to.be.null;
|
||||
});
|
||||
|
||||
it('owner deletes guild, removed from all user.guilds', async () => {
|
||||
const oldCount = user.guilds.length;
|
||||
it('owner deletes guild, removed from all user guildIds', async () => {
|
||||
const oldCount = user.guildIds.length;
|
||||
await guildDelete();
|
||||
|
||||
user = await User.findById(user.id);
|
||||
expect(user.guilds.length).to.be.lessThan(oldCount);
|
||||
expect(user.guildIds.length).to.be.lessThan(oldCount);
|
||||
});
|
||||
|
||||
function guildDelete() {
|
||||
@ -90,7 +90,6 @@ describe('guild-delete', () => {
|
||||
user = await User.findById(guild.ownerId);
|
||||
}
|
||||
async function makeNoob() {
|
||||
user = await User.findById(guild.members[1].userId);
|
||||
ws.sessions.set(client.id, user.id);
|
||||
}
|
||||
});
|
||||
|
@ -9,24 +9,20 @@ import { Invite, InviteDocument } from '../../../src/data/models/invite';
|
||||
import { expect, spy } from 'chai';
|
||||
import Guilds from '../../../src/data/guilds';
|
||||
import Users from '../../../src/data/users';
|
||||
import { GuildMember } from '../../../src/data/models/guild-member';
|
||||
|
||||
describe('guild-member-add', () => {
|
||||
const client = (io as any)(`http://localhost:${process.env.PORT}`) as any;
|
||||
let event: GuildMemberAdd;
|
||||
let guilds: Guilds;
|
||||
let users: Users;
|
||||
let ws: WebSocket;
|
||||
|
||||
let user: UserDocument;
|
||||
let user: SelfUserDocument;
|
||||
let guild: GuildDocument;
|
||||
let invite: InviteDocument;
|
||||
|
||||
beforeEach(async() => {
|
||||
({ event, ws, user, guild } = await Mock.defaultSetup(client, GuildMemberAdd));
|
||||
|
||||
guilds = Deps.get<Guilds>(Guilds);
|
||||
users = Deps.get<Users>(Users);
|
||||
|
||||
user = await Mock.user([]);
|
||||
ws.sessions.set(client.id, user.id);
|
||||
|
||||
@ -42,7 +38,6 @@ describe('guild-member-add', () => {
|
||||
|
||||
it('user already joined, rejected', async () => {
|
||||
await guildMemberAdd();
|
||||
|
||||
await expect(guildMemberAdd()).to.be.rejectedWith('User already in guild');
|
||||
});
|
||||
|
||||
@ -54,18 +49,18 @@ describe('guild-member-add', () => {
|
||||
});
|
||||
|
||||
it('valid invite and code, member added to guild', async () => {
|
||||
const oldMemberCount = guild.members.length;
|
||||
const oldMemberCount = await GuildMember.count({ guildId: guild.id });
|
||||
await guildMemberAdd();
|
||||
|
||||
guild = await guilds.get(guild.id);
|
||||
expect(guild.members.length).to.be.greaterThan(oldMemberCount);
|
||||
const newMemberCount = await GuildMember.count({ guildId: guild.id });
|
||||
expect(newMemberCount).to.be.greaterThan(oldMemberCount);
|
||||
});
|
||||
|
||||
it('valid invite and code, guild added to user guilds', async () => {
|
||||
await guildMemberAdd();
|
||||
|
||||
user = await users.get(user.id);
|
||||
expect(user.guilds.length).to.equal(1);
|
||||
user = await Mock.users.get(user.id);
|
||||
expect(user.guildIds.length).to.equal(1);
|
||||
});
|
||||
|
||||
it('invite has reached max uses, is deleted', async () => {
|
||||
@ -86,19 +81,9 @@ describe('guild-member-add', () => {
|
||||
|
||||
it('invalid invite code, rejected', async () => {
|
||||
invite.id = '';
|
||||
|
||||
await expect(guildMemberAdd()).to.be.rejectedWith('Invite Not Found');
|
||||
});
|
||||
|
||||
it('valid invite and code, emits to guild room', async () => {
|
||||
const to = spy.on(ws.io, 'to');
|
||||
|
||||
await guildMemberAdd();
|
||||
|
||||
guild = await guilds.get(guild.id);
|
||||
expect(to).to.have.been.called.with(guild.id);
|
||||
});
|
||||
|
||||
function guildMemberAdd() {
|
||||
return event.invoke(ws, client, { inviteCode: invite.id });
|
||||
}
|
||||
|
@ -4,15 +4,15 @@ import io from 'socket.io-client';
|
||||
import { Mock } from '../../mock/mock';
|
||||
import { GuildDocument } from '../../../src/data/models/guild';
|
||||
import { expect } from 'chai';
|
||||
import { GuildMemberDocument } from '../../../src/data/models/guild-member';
|
||||
import { User, UserDocument } from '../../../src/data/models/user';
|
||||
import { GuildMember, GuildMemberDocument } from '../../../src/data/models/guild-member';
|
||||
import { SelfUserDocument, User } from '../../../src/data/models/user';
|
||||
|
||||
describe('guild-member-remove', () => {
|
||||
const client = (io as any)(`http://localhost:${process.env.PORT}`) as any;
|
||||
|
||||
let event: GuildMemberRemove;
|
||||
let ws: WebSocket;
|
||||
let user: UserDocument;
|
||||
let user: SelfUserDocument;
|
||||
let member: GuildMemberDocument;
|
||||
let guild: GuildDocument;
|
||||
|
||||
@ -32,8 +32,7 @@ describe('guild-member-remove', () => {
|
||||
});
|
||||
|
||||
it('cannot leave owned guild, rejected', async () => {
|
||||
makeGuildOwner();
|
||||
|
||||
await makeGuildOwner();
|
||||
await expect(guildMemberRemove()).to.be.rejectedWith('You cannot leave a guild you own');
|
||||
});
|
||||
|
||||
@ -41,34 +40,36 @@ describe('guild-member-remove', () => {
|
||||
await guildMemberRemove();
|
||||
|
||||
user = await User.findById(user.id);
|
||||
expect(user.guilds).to.not.include(guild.id);
|
||||
expect(user.guildIds).to.not.include(guild.id);
|
||||
});
|
||||
|
||||
it('kick noob member, as noob member, missing permissions', async () => {
|
||||
await makeAnotherNoob();
|
||||
|
||||
await expect(guildMemberRemove()).to.be.rejectedWith('Missing Permissions');
|
||||
});
|
||||
|
||||
it('kick noob member, as guild owner, removed from user guilds', async () => {
|
||||
makeGuildOwner();
|
||||
await makeGuildOwner();
|
||||
|
||||
member = guild.members[1] as GuildMemberDocument;
|
||||
member = await GuildMember.findOne({
|
||||
guildId: guild.id,
|
||||
userId: { $ne: guild.ownerId },
|
||||
});
|
||||
await guildMemberRemove();
|
||||
|
||||
user = await User.findById(member.userId);
|
||||
expect(user.guilds).to.not.include(guild.id);
|
||||
expect(user.guildIds).to.not.include(guild.id);
|
||||
});
|
||||
|
||||
function guildMemberRemove() {
|
||||
return event.invoke(ws, client, {
|
||||
guildId: guild.id,
|
||||
memberId: member.id,
|
||||
});
|
||||
return event.invoke(ws, client, { memberId: member.id });
|
||||
}
|
||||
|
||||
function makeGuildOwner() {
|
||||
member = guild.members[0] as GuildMemberDocument;
|
||||
async function makeGuildOwner() {
|
||||
const member = await GuildMember.findOne({
|
||||
guildId: guild.id,
|
||||
userId: guild.ownerId,
|
||||
});
|
||||
ws.sessions.set(client.id, guild.ownerId);
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,12 @@ import { WebSocket } from '../../../src/ws/websocket';
|
||||
import io from 'socket.io-client';
|
||||
import GuildUpdate from '../../../src/ws/ws-events/guild-update';
|
||||
import { Guild, GuildDocument } from '../../../src/data/models/guild';
|
||||
import { UserDocument } from '../../../src/data/models/user';
|
||||
import { SelfUserDocument, UserDocument } from '../../../src/data/models/user';
|
||||
import { Mock } from '../../mock/mock';
|
||||
import { expect } from 'chai';
|
||||
import { GuildMemberDocument } from '../../../src/data/models/guild-member';
|
||||
import { generateSnowflake } from '../../../src/data/snowflake-entity';
|
||||
import { PermissionTypes } from '../../../src/types/permission-types';
|
||||
|
||||
describe('guild-update', () => {
|
||||
const client = (io as any)(`http://localhost:${process.env.PORT}`) as any;
|
||||
@ -14,11 +15,10 @@ describe('guild-update', () => {
|
||||
let event: GuildUpdate;
|
||||
|
||||
let guild: GuildDocument;
|
||||
let user: UserDocument;
|
||||
let member: GuildMemberDocument;
|
||||
|
||||
beforeEach(async () => {
|
||||
({ ws, event, guild, member, user } = await Mock.defaultSetup(client, GuildUpdate));
|
||||
({ ws, event, guild, member } = await Mock.defaultSetup(client, GuildUpdate));
|
||||
});
|
||||
|
||||
afterEach(async () => Mock.afterEach(ws));
|
||||
@ -44,76 +44,10 @@ describe('guild-update', () => {
|
||||
await expect(guildUpdate({})).to.be.fulfilled;
|
||||
});
|
||||
|
||||
it('name acronym updated', async () => {
|
||||
makeOwner();
|
||||
await guildUpdate({ name: 'K E K K' });
|
||||
|
||||
guild = await Guild.findById(guild.id);
|
||||
expect(guild.nameAcronym).to.equal('KEK');
|
||||
});
|
||||
|
||||
it('contains banned keys, rejected', async () => {
|
||||
makeOwner();
|
||||
await expect(guildUpdate({ id: '123' })).to.be.rejectedWith('Contains readonly values');
|
||||
});
|
||||
|
||||
it('reordered roles correctly, fulfilled', async () => {
|
||||
makeOwner();
|
||||
|
||||
const roleIds = guild.roles.map(r => r.id);
|
||||
await expect(guildUpdate({ roles: roleIds as any })).to.be.fulfilled;
|
||||
});
|
||||
|
||||
it('reordered roles, added a role, rejected', async () => {
|
||||
makeOwner();
|
||||
const newRole = await Mock.role(guild);
|
||||
const roleIds = guild.roles.concat(newRole).map(r => r.id);
|
||||
|
||||
await expect(guildUpdate({ roles: roleIds as any })).to.be.rejectedWith('Cannot add or remove roles this way');
|
||||
});
|
||||
|
||||
it('reordered roles, removed a role, rejected', async () => {
|
||||
makeOwner();
|
||||
await Mock.role(guild);
|
||||
const roleIds = guild.roles.slice(0, 1);
|
||||
|
||||
await expect(guildUpdate({ roles: roleIds as any })).to.be.rejectedWith('Cannot add or remove roles this way');
|
||||
});
|
||||
|
||||
it('reordered roles, moved everyone role, rejected', async () => {
|
||||
makeOwner();
|
||||
const roleIds = [generateSnowflake(), ...guild.roles];
|
||||
|
||||
await expect(guildUpdate({ roles: roleIds as any })).to.be.rejectedWith('Cannot reorder the @everyone role');
|
||||
});
|
||||
|
||||
it('sorted channels, did not add channels, fulfilled', async () => {
|
||||
makeOwner();
|
||||
|
||||
const roleIds = guild.channels.map(r => r.id);
|
||||
await expect(guildUpdate({ channels: roleIds as any })).to.be.fulfilled;
|
||||
});
|
||||
|
||||
it('sorted channels, added a channel, rejected', async () => {
|
||||
makeOwner();
|
||||
const channel = await Mock.channel(guild);
|
||||
const channelIds = guild.channels.concat(channel).map(r => r.id);
|
||||
|
||||
await expect(guildUpdate({ channels: channelIds as any })).to.be.rejectedWith('Cannot add or remove channels this way');
|
||||
});
|
||||
|
||||
it('sorted channels, removed a channel, rejected', async () => {
|
||||
makeOwner();
|
||||
await Mock.channel(guild);
|
||||
const channelIds = guild.channels.slice(0, 1);
|
||||
|
||||
await expect(guildUpdate({ channels: channelIds as any })).to.be.rejectedWith('Cannot add or remove channels this way');
|
||||
});
|
||||
|
||||
function guildUpdate(partialGuild: Partial<Entity.Guild>) {
|
||||
function guildUpdate(partial: Partial<Entity.Guild>) {
|
||||
return event.invoke(ws, client, {
|
||||
guildId: guild.id,
|
||||
partialGuild,
|
||||
...partial,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,8 @@ import io from 'socket.io-client';
|
||||
import { Mock } from '../../mock/mock';
|
||||
import { GuildDocument } from '../../../src/data/models/guild';
|
||||
import { expect } from 'chai';
|
||||
import { Role, RoleDocument } from '../../../src/data/models/role';
|
||||
import { RoleDocument } from '../../../src/data/models/role';
|
||||
import { PermissionTypes } from '../../../src/types/permission-types';
|
||||
|
||||
describe('invite-create', () => {
|
||||
const client = (io as any)(`http://localhost:${process.env.PORT}`) as any;
|
||||
@ -31,10 +32,10 @@ describe('invite-create', () => {
|
||||
await expect(inviteCreate()).to.be.rejectedWith('Missing Permissions');
|
||||
});
|
||||
|
||||
function inviteCreate() {
|
||||
function inviteCreate(options?: Partial<InviteTypes.Options>) {
|
||||
return event.invoke(ws, client, {
|
||||
guildId: guild.id,
|
||||
options: {},
|
||||
options,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -6,6 +6,7 @@ import { GuildDocument } from '../../../src/data/models/guild';
|
||||
import { Invite, InviteDocument } from '../../../src/data/models/invite';
|
||||
import { expect } from 'chai';
|
||||
import { RoleDocument } from '../../../src/data/models/role';
|
||||
import { PermissionTypes } from '../../../src/types/permission-types';
|
||||
|
||||
describe('invite-delete', () => {
|
||||
const client = (io as any)(`http://localhost:${process.env.PORT}`) as any;
|
||||
@ -38,7 +39,6 @@ describe('invite-delete', () => {
|
||||
|
||||
it('guild member, has manage guild perms, fulfilled', async () => {
|
||||
await Mock.giveRolePerms(role, PermissionTypes.General.MANAGE_GUILD);
|
||||
|
||||
await expect(inviteDelete()).to.be.fulfilled;
|
||||
});
|
||||
|
||||
@ -52,7 +52,6 @@ describe('invite-delete', () => {
|
||||
|
||||
it('invite does not exist, rejected', async () => {
|
||||
await invite.deleteOne();
|
||||
|
||||
await expect(inviteDelete()).to.be.rejectedWith('Invite Not Found');
|
||||
});
|
||||
|
||||
|
@ -36,13 +36,11 @@ describe('message-create', () => {
|
||||
|
||||
it('user is guild member without chat perms, rejected', async () => {
|
||||
await Mock.clearRolePerms(guild);
|
||||
|
||||
await expect(messageCreate()).to.be.rejectedWith('Missing Permissions');
|
||||
});
|
||||
|
||||
it('user is guild owner, fulfilled', async () => {
|
||||
ws.sessions.set(client.id, guild.ownerId);
|
||||
|
||||
await expect(messageCreate()).to.be.fulfilled;
|
||||
});
|
||||
|
||||
@ -53,20 +51,19 @@ describe('message-create', () => {
|
||||
expect(channel.lastMessageId).to.be.a('string');
|
||||
});
|
||||
|
||||
it('lastReadMessages updated in author', async () => {
|
||||
it('lastReadMessageIds updated on author document', async () => {
|
||||
await messageCreate();
|
||||
|
||||
channel = await Channel.findById(channel.id) as any;
|
||||
user = await User.findById(user.id) as any;
|
||||
expect(user.lastReadMessages[channel.id]).to.equal(channel.lastMessageId);
|
||||
expect(user.lastReadMessageIds[channel.id]).to.equal(channel.lastMessageId);
|
||||
});
|
||||
|
||||
function messageCreate() {
|
||||
function messageCreate(options?: Partial<Entity.Message>) {
|
||||
return event.invoke(ws, client, {
|
||||
channelId: channel.id,
|
||||
partialMessage: {
|
||||
content: 'hi'
|
||||
},
|
||||
content: 'hi',
|
||||
...options,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -7,7 +7,7 @@ import { GuildDocument } from '../../../src/data/models/guild';
|
||||
import { UserDocument } from '../../../src/data/models/user';
|
||||
import { Message, MessageDocument } from '../../../src/data/models/message';
|
||||
import { generateSnowflake } from '../../../src/data/snowflake-entity';
|
||||
import { Channel } from '../../../src/data/models/channel';
|
||||
import { Channel, ChannelDocument } from '../../../src/data/models/channel';
|
||||
|
||||
describe('message-delete', () => {
|
||||
const client = (io as any)(`http://localhost:${process.env.PORT}`) as any;
|
||||
@ -17,13 +17,12 @@ describe('message-delete', () => {
|
||||
let user: UserDocument;
|
||||
let guild: GuildDocument;
|
||||
let message: MessageDocument;
|
||||
let channelId: string;
|
||||
let channel: ChannelDocument;
|
||||
|
||||
beforeEach(async () => {
|
||||
({ ws, event, user, guild } = await Mock.defaultSetup(client, MessageDelete));
|
||||
({ ws, event, channel, guild } = await Mock.defaultSetup(client, MessageDelete));
|
||||
|
||||
channelId = guild.channels[0].id;
|
||||
message = await Mock.message(user, channelId);
|
||||
message = await Mock.message(user, channel.id);
|
||||
});
|
||||
|
||||
afterEach(async () => await Mock.afterEach(ws));
|
||||
@ -62,25 +61,24 @@ describe('message-delete', () => {
|
||||
|
||||
it('message does not exist, rejected', async () => {
|
||||
await message.deleteOne();
|
||||
|
||||
await expect(deleteMessage()).to.be.rejectedWith('Message Not Found');
|
||||
});
|
||||
|
||||
it('message is last channel message, channel last message updated to previous', async () => {
|
||||
const previousMessage = message;
|
||||
message = await Mock.message(user, channelId);
|
||||
message = await Mock.message(user, channel.id);
|
||||
|
||||
await deleteMessage();
|
||||
|
||||
const channel = await Channel.findById(channelId);
|
||||
expect(channel.lastMessageId).to.equal(previousMessage.id);
|
||||
const newChannel = await Channel.findById(channel.id);
|
||||
expect(newChannel.lastMessageId).to.equal(previousMessage.id);
|
||||
});
|
||||
|
||||
it('message is only channel message, channel last message updated to null', async () => {
|
||||
await deleteMessage();
|
||||
|
||||
const channel = await Channel.findById(channelId);
|
||||
expect(channel.lastMessageId).to.be.null;
|
||||
const newChannel = await Channel.findById(channel.id);
|
||||
expect(newChannel.lastMessageId).to.be.null;
|
||||
});
|
||||
|
||||
async function deleteMessage() {
|
||||
|
@ -1,15 +1,13 @@
|
||||
import MessageUpdate from '../../../src/ws/ws-events/message-update';
|
||||
import { WebSocket } from '../../../src/ws/websocket';
|
||||
import Deps from '../../../src/utils/deps';
|
||||
import { expect } from 'chai';
|
||||
import io from 'socket.io-client';
|
||||
import { Mock } from '../../mock/mock';
|
||||
import { GuildDocument } from '../../../src/data/models/guild';
|
||||
import { User, UserDocument } from '../../../src/data/models/user';
|
||||
import { SelfUserDocument } from '../../../src/data/models/user';
|
||||
import { ChannelDocument } from '../../../src/data/models/channel';
|
||||
import { MessageDocument } from '../../../src/data/models/message';
|
||||
import { generateSnowflake } from '../../../src/data/snowflake-entity';
|
||||
import { Partial } from '../../../src/data/types/ws-types';
|
||||
|
||||
describe('message-update', () => {
|
||||
const client = (io as any)(`http://localhost:${process.env.PORT}`) as any;
|
||||
@ -17,7 +15,7 @@ describe('message-update', () => {
|
||||
let channel: ChannelDocument;
|
||||
let event: MessageUpdate;
|
||||
let ws: WebSocket;
|
||||
let user: UserDocument;
|
||||
let user: SelfUserDocument;
|
||||
let guild: GuildDocument;
|
||||
let message: MessageDocument;
|
||||
|
||||
@ -30,30 +28,22 @@ describe('message-update', () => {
|
||||
afterEach(async () => await Mock.afterEach(ws));
|
||||
after(async () => await Mock.after(client));
|
||||
|
||||
it('user not author, rejected', async () => {
|
||||
it('user not message author, rejected', async () => {
|
||||
await makeGuildOwner();
|
||||
|
||||
await expect(messageUpdate()).to.be.rejectedWith('Unauthorized');
|
||||
});
|
||||
|
||||
it('message does not exist, rejected', async () => {
|
||||
message.id = generateSnowflake();
|
||||
|
||||
await expect(messageUpdate()).to.be.rejectedWith('Message Not Found');
|
||||
});
|
||||
|
||||
it('update includes banned keys, rejected', async () => {
|
||||
await expect(messageUpdate({ id: '123' })).to.be.rejectedWith('Contains readonly values');
|
||||
await expect(messageUpdate({
|
||||
messageId: generateSnowflake(),
|
||||
})).to.be.rejectedWith('Message Not Found');
|
||||
});
|
||||
|
||||
function messageUpdate(options?: Partial<Entity.Message>) {
|
||||
return event.invoke(ws, client, {
|
||||
messageId: message.id,
|
||||
partialMessage: {
|
||||
...options,
|
||||
content: 'test',
|
||||
},
|
||||
withEmbed: true
|
||||
content: 'test',
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,8 @@ import Users from '../../../src/data/users';
|
||||
import { Mock } from '../../mock/mock';
|
||||
import { WebSocket } from '../../../src/ws/websocket';
|
||||
import io from 'socket.io-client';
|
||||
import { SystemBot } from '../../../src/system/bot';
|
||||
import { GuildDocument } from '../../../src/data/models/guild';
|
||||
import { Channel } from '../../../src/data/models/channel';
|
||||
|
||||
describe('ready', () => {
|
||||
const client = (io as any)(`http://localhost:${process.env.PORT}`) as any;
|
||||
@ -16,7 +16,7 @@ describe('ready', () => {
|
||||
let event: Ready;
|
||||
let users: Users;
|
||||
let token: string;
|
||||
let user: UserDocument;
|
||||
let user: SelfUserDocument;
|
||||
let guild: GuildDocument;
|
||||
let ws: WebSocket;
|
||||
|
||||
@ -45,25 +45,6 @@ describe('ready', () => {
|
||||
expect(rooms()).to.include(user.id);
|
||||
});
|
||||
|
||||
it('joins system bot room', async () => {
|
||||
const systemBot = Deps.get<SystemBot>(SystemBot);
|
||||
await systemBot.init();
|
||||
|
||||
await ready();
|
||||
|
||||
expect(rooms()).to.include(systemBot.self.id);
|
||||
});
|
||||
|
||||
it('joins dm channel room', async () => {
|
||||
const dm = await Mock.channel({ type: 'DM' });
|
||||
dm.memberIds.push(user.id);
|
||||
await dm.update(dm);
|
||||
|
||||
await ready();
|
||||
|
||||
expect(rooms()).to.include(dm.id);
|
||||
});
|
||||
|
||||
it('joins self room', async () => {
|
||||
await ready();
|
||||
expect(rooms()).to.include(user.id);
|
||||
@ -82,8 +63,11 @@ describe('ready', () => {
|
||||
await makeOwner();
|
||||
await ready();
|
||||
|
||||
expect(rooms()).to.contain(guild.channels[0].id);
|
||||
expect(rooms()).to.contain(guild.channels[1].id);
|
||||
const guildChannels = await Channel.find({ guildId: guild.id });
|
||||
const ids = guildChannels.map(c => c.id);
|
||||
|
||||
expect(rooms()).to.contain(ids[0]);
|
||||
expect(rooms()).to.contain(ids[1]);
|
||||
expect(rooms()).to.contain(newChannel.id);
|
||||
});
|
||||
|
||||
|
@ -1,62 +0,0 @@
|
||||
import RemoveFriend from '../../../src/ws/ws-events/remove-friend';
|
||||
import { WebSocket } from '../../../src/ws/websocket';
|
||||
import io from 'socket.io-client';
|
||||
import { Mock } from '../../mock/mock';
|
||||
import { expect } from 'chai';
|
||||
import { generateSnowflake } from '../../../src/data/snowflake-entity';
|
||||
import { SelfUserDocument, User, UserDocument } from '../../../src/data/models/user';
|
||||
|
||||
describe('remove-friend', () => {
|
||||
const client = (io as any)(`http://localhost:${process.env.PORT}`) as any;
|
||||
let event: RemoveFriend;
|
||||
let ws: WebSocket;
|
||||
|
||||
let sender: SelfUserDocument;
|
||||
let friend: SelfUserDocument;
|
||||
|
||||
beforeEach(async () => {
|
||||
({ event, ws, user: sender as any } = await Mock.defaultSetup(client, RemoveFriend));
|
||||
friend = await Mock.self();
|
||||
});
|
||||
|
||||
afterEach(async () => await Mock.afterEach(ws));
|
||||
after(async () => await Mock.after(client));
|
||||
|
||||
it('user sends request, fulfilled', async () => {
|
||||
await expect(removeFriend()).to.be.fulfilled;
|
||||
});
|
||||
|
||||
it('user removes self as friend, rejected', async () => {
|
||||
friend.id = sender.id;
|
||||
|
||||
await expect(removeFriend()).to.be.rejectedWith('You cannot remove yourself as a friend');
|
||||
});
|
||||
|
||||
it('removes non existing friend, rejected', async () => {
|
||||
friend.id = generateSnowflake();
|
||||
|
||||
await expect(removeFriend()).to.be.rejectedWith('User Not Found');
|
||||
});
|
||||
|
||||
it('sender cancels request, friend request removed', async () => {
|
||||
await removeFriend();
|
||||
|
||||
sender = await User.findById(sender.id) as any;
|
||||
|
||||
expect(sender.friendRequestIds).to.be.empty;
|
||||
});
|
||||
|
||||
it('sender removes friend, friend removed on both users', async () => {
|
||||
await removeFriend();
|
||||
|
||||
friend = await User.findById(friend.id) as any;
|
||||
sender = await User.findById(sender.id) as any;
|
||||
|
||||
expect(friend.friendIds.length).to.equal(0);
|
||||
expect(sender.friendIds.length).to.equal(0);
|
||||
});
|
||||
|
||||
async function removeFriend() {
|
||||
return event.invoke(ws, client, { friendId: friend.id });
|
||||
}
|
||||
});
|
@ -2,7 +2,7 @@ import UserUpdate from '../../../src/ws/ws-events/user-update';
|
||||
import { WebSocket } from '../../../src/ws/websocket';
|
||||
import io from 'socket.io-client';
|
||||
import{ Mock } from '../../mock/mock';
|
||||
import{ SelfUserDocument, User, UserDocument } from '../../../src/data/models/user';
|
||||
import{ SelfUserDocument, User } from '../../../src/data/models/user';
|
||||
import { expect } from 'chai';
|
||||
import Deps from '../../../src/utils/deps';
|
||||
import Users from '../../../src/data/users';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Channel, ChannelDocument } from '../../src/data/models/channel';
|
||||
import { Guild, GuildDocument } from '../../src/data/models/guild';
|
||||
import { GuildMember, GuildMemberDocument } from '../../src/data/models/guild-member';
|
||||
import { User, SelfUserDocument, UserDocument } from '../../src/data/models/user';
|
||||
import { User, SelfUserDocument } from '../../src/data/models/user';
|
||||
import { generateSnowflake } from '../../src/data/snowflake-entity';
|
||||
import { Role, RoleDocument } from '../../src/data/models/role';
|
||||
import { Message } from '../../src/data/models/message';
|
||||
@ -17,15 +17,17 @@ import GuildMembers from '../../src/data/guild-members';
|
||||
import Channels from '../../src/data/channels';
|
||||
import { PermissionTypes } from '../../src/types/permission-types';
|
||||
import { REST } from '../../src/rest/server';
|
||||
import Users from '../../src/data/users';
|
||||
|
||||
// TODO: mostly replace with data wrappers
|
||||
// TODO: eventually replace with data wrappers
|
||||
export class Mock {
|
||||
private static channels = Deps.get<Channels>(Channels);
|
||||
private static guilds = Deps.get<Guilds>(Guilds);
|
||||
private static guildMembers = Deps.get<GuildMembers>(GuildMembers);
|
||||
private static messages = Deps.get<Messages>(Messages);
|
||||
private static invites = Deps.get<Invites>(Invites);
|
||||
private static roles = Deps.get<Roles>(Roles);
|
||||
public static channels = Deps.get<Channels>(Channels);
|
||||
public static guilds = Deps.get<Guilds>(Guilds);
|
||||
public static guildMembers = Deps.get<GuildMembers>(GuildMembers);
|
||||
public static messages = Deps.get<Messages>(Messages);
|
||||
public static invites = Deps.get<Invites>(Invites);
|
||||
public static roles = Deps.get<Roles>(Roles);
|
||||
public static users = Deps.get<Users>(Users);
|
||||
|
||||
public static async defaultSetup(client: any, eventType: any = function() {}) {
|
||||
Deps.get<REST>(REST);
|
||||
@ -46,6 +48,11 @@ export class Mock {
|
||||
Mock.ioClient(client);
|
||||
ws.sessions.set(client.id, user.id);
|
||||
|
||||
// TODO:
|
||||
// rename 'user' -> ownerUser
|
||||
// rename 'member' -> ownerMember
|
||||
// add 'ownerUser'
|
||||
// add 'ownerMember'
|
||||
return { event, guild, user, member, ws, role, channel };
|
||||
}
|
||||
public static async afterEach(ws) {
|
||||
@ -56,7 +63,7 @@ export class Mock {
|
||||
client.disconnect();
|
||||
}
|
||||
|
||||
// FIXME: garbage coding
|
||||
// FIXME: less maintainable than daily YouTube uploads
|
||||
public static ioClient(client: any) {
|
||||
client.rooms = [];
|
||||
client.sockets = {
|
||||
@ -100,24 +107,15 @@ export class Mock {
|
||||
username: `mock-user-${generateSnowflake()}`,
|
||||
discriminator: 1,
|
||||
...options,
|
||||
} as any);
|
||||
} as any) as any;
|
||||
}
|
||||
|
||||
public static async self(guildIds: string[] = []) {
|
||||
return await this.user({ guildIds }) as any as SelfUserDocument;
|
||||
}
|
||||
|
||||
public static async bot(guildIds: string[] = []): Promise<SelfUserDocument> {
|
||||
return await User.create({
|
||||
bot: true,
|
||||
email: `${generateSnowflake()}@gmail.com`,
|
||||
guildIds,
|
||||
status: 'ONLINE',
|
||||
discriminator: 1,
|
||||
username: `mock-bot-${generateSnowflake()}`,
|
||||
} as any) as any as SelfUserDocument;
|
||||
return await Mock.user({ bot: true, guildIds });
|
||||
}
|
||||
|
||||
public static guildMember(user: SelfUserDocument, guild: GuildDocument): Promise<GuildMemberDocument> {
|
||||
return this.guildMembers.create(guild.id, user);
|
||||
}
|
||||
@ -130,21 +128,15 @@ export class Mock {
|
||||
public static invite(guildId: string, options?: InviteTypes.Options) {
|
||||
return this.invites.create({ options, guildId }, generateSnowflake());
|
||||
}
|
||||
|
||||
public static everyoneRole(guildId: string, permissions = PermissionTypes.defaultPermissions) {
|
||||
return this.roles.create(guildId, { name: '@everyone', permissions });
|
||||
}
|
||||
|
||||
public static async clearRolePerms(guild: Entity.Guild) {
|
||||
await Role.updateMany(
|
||||
{ guildId: guild.id },
|
||||
{ permissions: 0 },
|
||||
);
|
||||
await Role.updateMany({ guildId: guild.id }, { permissions: 0 });
|
||||
}
|
||||
|
||||
public static async giveRolePerms(role: RoleDocument, permissions: PermissionTypes.Permission) {
|
||||
role.permissions |= permissions;
|
||||
await role.save();
|
||||
await role.updateOne({ permissions: role.permissions | permissions });
|
||||
}
|
||||
|
||||
public static async giveEveryoneAdmin(guild: Entity.Guild) {
|
||||
|
@ -46,19 +46,19 @@ console.log(`${space(48 * 3)}TESTS${space(54 * 2)}`.bgWhite.black);
|
||||
// TODO: import('./integration/ws/channel-delete.tests');
|
||||
// TODO: import('./integration/ws/channel-update.tests');
|
||||
import('./integration/ws/guild-member-add.tests'); //fail
|
||||
// import('./integration/ws/guild-member-remove.tests'); //fail
|
||||
// import('./integration/ws/guild-member-update.tests'); // fail
|
||||
// import('./integration/ws/guild-create.tests'); // fail
|
||||
// import('./integration/ws/guild-delete.tests'); // fail
|
||||
// import('./integration/ws/guild-update.tests'); // fail
|
||||
// import('./integration/ws/invite-create.tests'); //fail
|
||||
// import('./integration/ws/invite-delete.tests'); //fail
|
||||
// import('./integration/ws/message-create.tests'); //fail
|
||||
// import('./integration/ws/message-update.tests'); // fail
|
||||
// import('./integration/ws/message-delete.tests'); // fail
|
||||
// import('./integration/ws/ready.tests');
|
||||
import('./integration/ws/guild-member-remove.tests'); //fail
|
||||
import('./integration/ws/guild-member-update.tests'); // fail
|
||||
import('./integration/ws/guild-create.tests'); // fail
|
||||
import('./integration/ws/guild-delete.tests'); // fail
|
||||
import('./integration/ws/guild-update.tests'); // fail
|
||||
import('./integration/ws/invite-create.tests'); //fail
|
||||
import('./integration/ws/invite-delete.tests'); //fail
|
||||
import('./integration/ws/message-create.tests'); //fail
|
||||
import('./integration/ws/message-update.tests'); // fail
|
||||
import('./integration/ws/message-delete.tests'); // fail
|
||||
import('./integration/ws/ready.tests');
|
||||
import('./integration/ws/user-update.tests');
|
||||
// import('./integration/ws/ws-guard.tests'); // fail
|
||||
import('./integration/ws/ws-guard.tests'); // fail
|
||||
|
||||
import('./unit/models/app.tests');
|
||||
import('./unit/models/channel.tests');
|
||||
|
@ -21,16 +21,14 @@ describe('ws-cooldowns', () => {
|
||||
});
|
||||
|
||||
it('handle, exceeds max cooldowns, throws error', () => {
|
||||
for (let i = 0; i < 60; i++)
|
||||
handle();
|
||||
|
||||
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: 'ADD_FRIEND', timestamp: new Date(0).getTime() },
|
||||
{ eventName: 'ADD_FRIEND', timestamp: new Date(0).getTime() },
|
||||
{ eventName: 'MESSAGE_CREATE', timestamp: new Date(0).getTime() },
|
||||
{ eventName: 'MESSAGE_CREATE', timestamp: new Date(0).getTime() },
|
||||
]);
|
||||
|
||||
handle();
|
||||
@ -39,6 +37,6 @@ describe('ws-cooldowns', () => {
|
||||
});
|
||||
|
||||
function handle() {
|
||||
return cooldowns.handle(clientId, 'ADD_FRIEND');
|
||||
return cooldowns.handle(clientId, 'MESSAGE_CREATE');
|
||||
}
|
||||
});
|
||||
|
4
types/ws.d.ts
vendored
4
types/ws.d.ts
vendored
@ -163,8 +163,8 @@ declare namespace WS {
|
||||
}
|
||||
export interface GuildUpdate {
|
||||
guildId: string;
|
||||
name: string;
|
||||
iconURL: string;
|
||||
name?: string;
|
||||
iconURL?: string;
|
||||
}
|
||||
export interface InviteCreate {
|
||||
guildId: string;
|
||||
|
Loading…
x
Reference in New Issue
Block a user