Pokemon_server / test /server /punishments.js
Jofthomas's picture
Jofthomas HF staff
Upload 4781 files
5c2ed06 verified
'use strict';
/**
* Tests for Punishments.
*
* @author mia-pi-git
* @author Annika
*/
const assert = require('../assert');
const { makeUser, makeConnection } = require('../users-utils');
const { Punishments } = require('../../dist/server/punishments');
const TEST_PUNISHMENT_DURATION = 1000; // 1 second
describe("Punishments", () => {
it("Should properly sort punishments by weight", () => {
const list = [
{ type: "LOCK", id: "User 1", expireTime: Date.now() + 1000, reason: '' },
{ type: "SEMILOCK", id: "User 2", expireTime: Date.now() + 1000, reason: '' },
{ type: "BAN", id: "", expireTime: Date.now() + 1000, reason: '' },
];
Punishments.byWeight(list);
assert.equal(list[0].type, 'BAN');
});
it("Should prevent a user from having two punishments of the same type", () => {
Punishments.userids.add('banmeplease', { type: 'BAN', expireTime: Date.now() + 30 * 1000, id: 'banmeplease', reason: '' });
Punishments.userids.add("banmeplease", { type: 'BAN', expireTime: Date.now() + 30 * 1000, id: 'banmeplease', reason: 'ok' });
assert.equal(Punishments.userids.get('banmeplease').length, 1);
});
it("Should overwrite the old reason when a user receives two of the same punishment", () => {
Punishments.userids.add('banmeplease', { type: 'BAN', expireTime: Date.now() + 30 * 1000, id: 'banmeplease', reason: '' });
Punishments.userids.add("banmeplease", { type: 'BAN', expireTime: Date.now() + 30 * 1000, id: 'banmeplease', reason: 'ok' });
assert.equal(Punishments.userids.getByType('banmeplease', 'BAN').reason, 'ok');
});
it("Should properly filter out expiring punishments", () => {
const punishments = [{ type: 'BAN', expireTime: Date.now() - 1000, id: 'banmeplease', reason: '' }];
Punishments.userids.removeExpiring(punishments);
assert.equal(punishments.length, 0);
});
it("Should be able to remove only one punishment from the list by passing an object", () => {
const [expireTime, reason, id] = [Date.now() + 1000, '', 'banmeplease'];
Punishments.userids.add(id, { type: 'BAN', expireTime, reason, id });
Punishments.userids.add(id, { type: 'RICKROLL', expireTime, reason, id });
Punishments.userids.deleteOne(id, { type: 'RICKROLL', expireTime, reason, id });
assert.equal(Punishments.userids.get(id).length, 1);
});
it('should properly search for IP punishments by type', () => {
const [expireTime, reason, id] = [Date.now() + 1000, '', 'banmeplease'];
Punishments.ips.add('127.0.0.1', { type: 'BAN', expireTime, reason, id });
Punishments.ips.add('127.0.0.1', { type: 'RICKROLL', expireTime, reason, id });
Punishments.ips.add('127.0.*', { type: 'RANGEBAN', expireTime, reason, id });
const allIPPunishments = Punishments.ipSearch('127.0.0.1');
assert(Array.isArray(allIPPunishments));
assert.equal(allIPPunishments.length, 3);
const ban = Punishments.ipSearch('127.0.0.1', 'BAN');
assert(!Array.isArray(ban));
assert.equal(ban.type, 'BAN');
const rickroll = Punishments.ipSearch('127.0.0.1', 'RICKROLL');
assert(!Array.isArray(rickroll));
assert.equal(rickroll.type, 'RICKROLL');
});
});
describe('broader, more integrated Punishments tests', function () {
before(() => {
this.room = Rooms.get('lobby');
this.parse = async function (message) {
Chat.loadPlugins();
const context = new Chat.CommandContext({
message,
room: this.room,
user: this.user,
connection: this.connection,
});
return context.parse();
};
});
describe('room bans', () => {
before(() => {
this.user = makeUser("Roomban Me Please", '127.0.0.8');
this.connection = this.user.connections[0];
this.user.joinRoom(this.room.roomid, this.connection);
});
beforeEach(async () => Punishments.roomBan(this.room, this.user, Date.now() + TEST_PUNISHMENT_DURATION, this.user.id, false, 'test'));
afterEach(() => Punishments.roomUnban(this.room, this.user.id));
it('should force the user to leave the room and prevent them from rejoining', async () => {
assert.equal(this.user.id in this.room.users, false, `user should not be in the room`);
let joinAttempt = await this.user.tryJoinRoom(this.room, this.connection);
assert.equal(joinAttempt, false, `user should be unable to join a room they are banned from`);
Punishments.roomUnban(this.room, this.user.id);
joinAttempt = await this.user.tryJoinRoom(this.room, this.connection);
assert.equal(joinAttempt, true, `user should be able to join the room once they are unbanned`);
});
it.skip('should expire on its own', done => {
assert(Punishments.hasRoomPunishType(this.room, 'roombanmeplease', 'ROOMBAN'), `should be in effect`);
setTimeout(() => {
assert(!Punishments.hasRoomPunishType(this.room, 'roombanmeplease', 'ROOMBAN'), `should have expired`);
done();
}, TEST_PUNISHMENT_DURATION);
});
});
describe('locks (network) (slow)', () => {
before(() => {
this.user = makeUser("Lock Me Please", '127.0.0.3');
this.connection = this.user.connections[0];
this.user.joinRoom(this.room.roomid, this.connection);
});
beforeEach(async () => Punishments.lock(this.user, Date.now() + TEST_PUNISHMENT_DURATION, this.user.id, false, 'test'));
afterEach(() => Punishments.unlock(this.user.id));
it('should prevent users from chatting in rooms while they are locked', async () => {
const initialLogLength = this.room.log.log.length;
await this.parse("Hi! I'm a locked user!");
assert.equal(this.room.log.log.length, initialLogLength, `user should be unable to sucessfully chat while locked`);
Punishments.unlock(this.user.id);
await this.parse("/msgroom lobby,Hi! I'm no longer locked!");
// we can't just check the roomlog length because unlocking adds a |n| message to
const lastMessage = this.room.log.log.pop();
assert(lastMessage.endsWith(` Lock Me Please|Hi! I'm no longer locked!`), `user should have sucessfuly sent a message after being locked`);
});
// This test relies on Chat#parse returning `false` when permission is denied.
// I'm not sure if this is an intended feature, but the way Chat is currently implemented,
// an `ErrorMessage` is the only time `false` will be returned by Chat#parse (unless a chat command returns it, which /msg does not).
// If you are here because this test is failing, check if the above assumptions are still valid.
// If they are not, the test should either be refactored to use another way of
// determining whether a PM was sucessful (such as modifying Chat.sendPM), or skipped entirely.
it('should prevent users from sending PMs other than to staff while they are locked', async () => {
makeUser("Some Random Reg", '127.0.0.4');
makeUser("Annika", '127.0.0.5').tempGroup = '~';
let result = await this.parse("/msg Some Random Reg, Hi! I'm a locked user!");
assert.equal(result, false, `user should be unable to sucessfully send PMs while locked`);
result = await this.parse("/msg Annika, Hi! I'm a locked user!");
assert.notEqual(result, false, `user should be able to send PMs to global staff while locked`);
Punishments.unlock(this.user.id);
result = await this.parse("/msg Annika, Hi! I'm a locked user!");
assert.notEqual(result, false, `user should be able to send PMs after being unlocked`);
result = await this.parse("/msg Some Random Reg, Hi! I'm a locked user!");
assert.notEqual(result, false, `user should be able to send PMs after being unlocked`);
});
// expiry tests are skipped because they fail when another test fails.
// I don't know why this happens; I'm guessing it's an ideosycrasy of Mocha.
it.skip('should expire on its own', done => {
assert(this.user.locked);
assert(Punishments.hasPunishType(this.user.id, 'LOCK'));
setTimeout(() => {
assert(!this.user.locked);
assert(!Punishments.hasPunishType(this.user.id, 'LOCK'));
done();
}, TEST_PUNISHMENT_DURATION);
});
});
describe('namelocks (network) (slow)', () => {
before(() => {
this.user = makeUser("Namelock Me Please", '127.0.0.6');
this.connection = this.user.connections[0];
this.user.joinRoom(this.room.roomid, this.connection);
});
beforeEach(async () => Punishments.namelock(this.user, Date.now() + TEST_PUNISHMENT_DURATION, this.user.id, false, 'test'));
afterEach(() => Punishments.unnamelock(this.user.id));
it('should prevent the user from having a username', async () => {
assert(this.user.id.startsWith('guest'));
await this.user.rename('some other name', '', false, this.connection);
assert(this.user.id.startsWith('guest'));
});
it.skip('should expire on its own', done => {
assert(this.user.locked);
assert(this.user.namelocked);
assert(Punishments.hasPunishType('namelockmeplease', 'NAMELOCK'));
setTimeout(() => {
assert(!this.user.locked);
assert(!this.user.namelocked);
assert(!Punishments.hasPunishType('namelockmeplease', 'NAMELOCK'));
done();
}, TEST_PUNISHMENT_DURATION);
});
});
describe('global bans (network) (slow)', () => {
before(() => {
this.user = makeUser("Ban Me Please", '127.0.0.7');
this.connection = this.user.connections[0];
this.user.joinRoom(this.room.roomid, this.connection);
});
beforeEach(async () => Punishments.ban(this.user, Date.now() + TEST_PUNISHMENT_DURATION, this.user.id, false, 'test'));
afterEach(() => Punishments.unban(this.user.id));
it('should disconnect the user and prevent them from reconnecting', () => {
assert.equal(this.user.connected, false, `user should be disconnected`);
const conn = makeConnection('127.0.0.7');
assert(Punishments.checkIpBanned(conn), `IP should be banned`);
});
it.skip('should expire on its own', done => {
assert(Punishments.checkIpBanned(makeConnection('127.0.0.7')), `IP should be banned`);
assert(Punishments.hasPunishType('banmeplease', 'BAN'));
setTimeout(() => {
assert(!Punishments.checkIpBanned(makeConnection('127.0.0.7')), `IP should no longer be banned`);
assert(!Punishments.hasPunishType('banmeplease', 'BAN'));
done();
}, TEST_PUNISHMENT_DURATION);
});
});
});