init commit
This commit is contained in:
parent
ae639426d0
commit
7a491681cc
257 changed files with 95524 additions and 80 deletions
53
test/channel/playlist.js
Normal file
53
test/channel/playlist.js
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
const PlaylistModule = require('../../lib/channel/playlist');
|
||||
const assert = require('assert');
|
||||
const Config = require('../../lib/config');
|
||||
|
||||
describe('PlaylistModule', () => {
|
||||
describe('#handleClean', () => {
|
||||
let fakeChannel = {
|
||||
uniqueName: 'testChannel',
|
||||
logger: {
|
||||
log() {
|
||||
|
||||
}
|
||||
},
|
||||
broadcastToRoom() {
|
||||
},
|
||||
broadcastAll() {
|
||||
},
|
||||
modules: {
|
||||
permissions: {
|
||||
canDeleteVideo() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let fakeUser = {
|
||||
getName() {
|
||||
return 'testUser';
|
||||
},
|
||||
socket: {
|
||||
emit() {
|
||||
}
|
||||
}
|
||||
};
|
||||
let playlistModule = new PlaylistModule(fakeChannel);
|
||||
|
||||
it('rejects invalid regexes', () => {
|
||||
let sentError = false;
|
||||
|
||||
fakeUser.socket.emit = (event, payload) => {
|
||||
assert.strictEqual(event, 'errorMsg');
|
||||
assert.deepStrictEqual(payload, {
|
||||
msg: "Invalid target: -i * -m"
|
||||
});
|
||||
sentError = true;
|
||||
};
|
||||
|
||||
playlistModule.handleClean(fakeUser, "/clean -i * -m", {});
|
||||
|
||||
assert(sentError, 'Expected error due to invalid regex');
|
||||
});
|
||||
});
|
||||
});
|
||||
221
test/channel/poll.js
Normal file
221
test/channel/poll.js
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
const PollModule = require('../../lib/channel/poll');
|
||||
const assert = require('assert');
|
||||
const Config = require('../../lib/config');
|
||||
|
||||
describe('PollModule', () => {
|
||||
describe('#validatePollInput', () => {
|
||||
let pollModule = new PollModule({ uniqueName: 'testChannel', modules: {} });
|
||||
|
||||
it('accepts valid input', () => {
|
||||
let title = '';
|
||||
for (let i = 0; i < 20; i++) {
|
||||
title += 'x';
|
||||
}
|
||||
|
||||
pollModule.validatePollInput(title, ['ab', 'cd']);
|
||||
});
|
||||
|
||||
it('rejects non-string titles', () => {
|
||||
assert.throws(() => {
|
||||
pollModule.validatePollInput(null, []);
|
||||
}, /title/);
|
||||
});
|
||||
|
||||
it('rejects invalidly long titles', () => {
|
||||
let title = '';
|
||||
for (let i = 0; i < 256; i++) {
|
||||
title += 'x';
|
||||
}
|
||||
|
||||
assert.throws(() => {
|
||||
pollModule.validatePollInput(title, []);
|
||||
}, /title/);
|
||||
});
|
||||
|
||||
it('rejects non-array option parameter', () => {
|
||||
assert.throws(() => {
|
||||
pollModule.validatePollInput('poll', 1234);
|
||||
}, /options/);
|
||||
});
|
||||
|
||||
it('rejects too many options', () => {
|
||||
const limit = Config.get('poll.max-options');
|
||||
Config.set('poll.max-options', 2);
|
||||
try {
|
||||
assert.throws(() => {
|
||||
pollModule.validatePollInput('poll', ['1', '2', '3', '4']);
|
||||
}, /maximum of 2 options/);
|
||||
} finally {
|
||||
Config.set('poll.max-options', limit);
|
||||
}
|
||||
});
|
||||
|
||||
it('rejects non-string options', () => {
|
||||
assert.throws(() => {
|
||||
pollModule.validatePollInput('poll', [null]);
|
||||
}, /options must be strings/);
|
||||
});
|
||||
|
||||
it('rejects invalidly long options', () => {
|
||||
let option = '';
|
||||
for (let i = 0; i < 256; i++) {
|
||||
option += 'x';
|
||||
}
|
||||
|
||||
assert.throws(() => {
|
||||
pollModule.validatePollInput('poll', [option]);
|
||||
}, /options must be 1-255 characters/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#handleNewPoll', () => {
|
||||
let fakeChannel = {
|
||||
uniqueName: 'testChannel',
|
||||
logger: {
|
||||
log() {
|
||||
|
||||
}
|
||||
},
|
||||
broadcastToRoom() {
|
||||
},
|
||||
broadcastAll() {
|
||||
},
|
||||
modules: {
|
||||
permissions: {
|
||||
canControlPoll() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let fakeUser = {
|
||||
getName() {
|
||||
return 'testUser';
|
||||
},
|
||||
socket: {
|
||||
emit() {
|
||||
}
|
||||
}
|
||||
};
|
||||
let pollModule;
|
||||
beforeEach(() => {
|
||||
pollModule = new PollModule(fakeChannel);
|
||||
});
|
||||
|
||||
it('creates a valid poll', () => {
|
||||
let sentNewPoll = false;
|
||||
let sentClosePoll = false;
|
||||
fakeChannel.broadcastToRoom = (event, data, room) => {
|
||||
if (room === 'testChannel:viewHidden' && event === 'newPoll') {
|
||||
sentNewPoll = true;
|
||||
}
|
||||
};
|
||||
fakeChannel.broadcastAll = (event) => {
|
||||
if (event === 'closePoll') {
|
||||
sentClosePoll = true;
|
||||
}
|
||||
};
|
||||
pollModule.handleNewPoll(fakeUser, {
|
||||
title: 'test poll',
|
||||
opts: [
|
||||
'option 1',
|
||||
'option 2'
|
||||
],
|
||||
obscured: false
|
||||
}, (ackResult) => {
|
||||
assert(!ackResult.error, `Unexpected error: ${ackResult.error}`);
|
||||
});
|
||||
assert(!sentClosePoll, 'Unexpected broadcast of closePoll event');
|
||||
assert(sentNewPoll, 'Expected broadcast of newPoll event');
|
||||
});
|
||||
|
||||
it('closes an existing poll when a new one is created', () => {
|
||||
let sentNewPoll = 0;
|
||||
let sentClosePoll = 0;
|
||||
let sentUpdatePoll = 0;
|
||||
fakeChannel.broadcastToRoom = (event, data, room) => {
|
||||
if (room === 'testChannel:viewHidden' && event === 'newPoll') {
|
||||
sentNewPoll++;
|
||||
}
|
||||
};
|
||||
fakeChannel.broadcastAll = (event, data) => {
|
||||
if (event === 'closePoll') {
|
||||
sentClosePoll++;
|
||||
} else if (event === 'updatePoll') {
|
||||
sentUpdatePoll++;
|
||||
assert.deepStrictEqual(data.counts, [0, 0]);
|
||||
}
|
||||
};
|
||||
pollModule.handleNewPoll(fakeUser, {
|
||||
title: 'test poll',
|
||||
opts: [
|
||||
'option 1',
|
||||
'option 2'
|
||||
],
|
||||
obscured: true
|
||||
}, (ackResult) => {
|
||||
assert(!ackResult.error, `Unexpected error: ${ackResult.error}`);
|
||||
});
|
||||
|
||||
pollModule.handleNewPoll(fakeUser, {
|
||||
title: 'poll 2',
|
||||
opts: [
|
||||
'option 3',
|
||||
'option 4'
|
||||
],
|
||||
obscured: false
|
||||
}, (ackResult) => {
|
||||
assert(!ackResult.error, `Unexpected error: ${ackResult.error}`);
|
||||
});
|
||||
|
||||
assert.strictEqual(sentClosePoll, 1, 'Expected 1 broadcast of closePoll event');
|
||||
assert.strictEqual(sentUpdatePoll, 1, 'Expected 1 broadcast of updatePoll event');
|
||||
assert.strictEqual(sentNewPoll, 2, 'Expected 2 broadcasts of newPoll event');
|
||||
});
|
||||
|
||||
it('rejects an invalid poll', () => {
|
||||
fakeChannel.broadcastToRoom = (event, data, room) => {
|
||||
assert(false, 'Expected no events to be sent');
|
||||
};
|
||||
fakeChannel.broadcastAll = (event) => {
|
||||
assert(false, 'Expected no events to be sent');
|
||||
};
|
||||
const options = [];
|
||||
for (let i = 0; i < 200; i++) {
|
||||
options.push('option ' + i);
|
||||
}
|
||||
pollModule.handleNewPoll(fakeUser, {
|
||||
title: 'test poll',
|
||||
opts: options,
|
||||
obscured: false
|
||||
}, (ackResult) => {
|
||||
assert.equal(ackResult.error.message, 'Polls are limited to a maximum of 50 options.');
|
||||
});
|
||||
});
|
||||
|
||||
it('handles a rejection with no ack provided by socket.io', () => {
|
||||
fakeChannel.broadcastToRoom = (event, data, room) => {
|
||||
assert(false, 'Expected no events to be sent');
|
||||
};
|
||||
fakeChannel.broadcastAll = (event) => {
|
||||
assert(false, 'Expected no events to be sent');
|
||||
};
|
||||
let sentErrorMsg = false;
|
||||
fakeUser.socket.emit = (event, data) => {
|
||||
if (event === 'errorMsg') {
|
||||
sentErrorMsg = true;
|
||||
}
|
||||
};
|
||||
const options = [];
|
||||
for (let i = 0; i < 200; i++) {
|
||||
options.push('option ' + i);
|
||||
}
|
||||
pollModule.handleNewPoll(fakeUser, {
|
||||
title: 'test poll',
|
||||
opts: options,
|
||||
obscured: false
|
||||
});
|
||||
assert(sentErrorMsg, 'Expected to send errorMsg since ack was missing');
|
||||
});
|
||||
})
|
||||
});
|
||||
138
test/channel/voteskip.js
Normal file
138
test/channel/voteskip.js
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
const VoteskipModule = require('../../lib/channel/voteskip');
|
||||
const assert = require('assert');
|
||||
const Flags = require('../../lib/flags');
|
||||
|
||||
describe('VoteskipModule', () => {
|
||||
let fakeUser;
|
||||
let fakeChannel;
|
||||
let voteskipModule;
|
||||
|
||||
beforeEach(() => {
|
||||
fakeUser = {
|
||||
socket: {
|
||||
emit() {
|
||||
|
||||
}
|
||||
},
|
||||
is() {
|
||||
return false
|
||||
}
|
||||
};
|
||||
fakeChannel = {
|
||||
logger: {
|
||||
log() {
|
||||
|
||||
}
|
||||
},
|
||||
modules: {
|
||||
permissions: {
|
||||
canSeeVoteskipResults() {
|
||||
return true;
|
||||
},
|
||||
canVoteskip() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
options: {
|
||||
get(key) {
|
||||
if (key === 'voteskip_ratio') {
|
||||
return 0.5;
|
||||
} else if (key === 'allow_voteskip') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
playlist: {
|
||||
_playNext() {
|
||||
},
|
||||
|
||||
meta: {
|
||||
count: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
users: [fakeUser],
|
||||
broadcastAll() {
|
||||
}
|
||||
};
|
||||
|
||||
voteskipModule = new VoteskipModule(fakeChannel);
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('resets the vote before changing to the next video', () => {
|
||||
let reset = false, playNext = false;
|
||||
fakeChannel.modules.playlist._playNext = () => {
|
||||
if (!reset) {
|
||||
assert(false, 'Expected voteskip reset prior to playlist._playNext');
|
||||
}
|
||||
|
||||
playNext = true;
|
||||
};
|
||||
fakeUser.socket.emit = (event, data) => {
|
||||
if (event === 'voteskip') {
|
||||
assert.deepEqual(data, { count: 0, need: 0 });
|
||||
reset = true;
|
||||
}
|
||||
};
|
||||
|
||||
voteskipModule.poll = {
|
||||
toUpdateFrame() {
|
||||
return { counts: [1] };
|
||||
}
|
||||
};
|
||||
voteskipModule.update();
|
||||
assert.equal(voteskipModule.poll, false, 'Expected voteskip poll to be reset to false');
|
||||
assert(reset, 'Expected voteskip to be reset');
|
||||
assert(playNext, 'Expected playlist to be advanced');
|
||||
});
|
||||
|
||||
it('broadcasts a message', () => {
|
||||
let sentMessage = false;
|
||||
fakeChannel.broadcastAll = (frame, data) => {
|
||||
assert.strictEqual(frame, 'chatMsg');
|
||||
assert(/voteskip passed/i.test(data.msg), 'Expected voteskip passed message')
|
||||
sentMessage = true;
|
||||
};
|
||||
voteskipModule.poll = {
|
||||
toUpdateFrame() {
|
||||
return { counts: [1] };
|
||||
}
|
||||
};
|
||||
voteskipModule.update();
|
||||
assert(sentMessage, 'Expected voteskip passed message');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#calcUsercounts', () => {
|
||||
it('calculates correctly', () => {
|
||||
fakeChannel.users = [
|
||||
// 1 with permission and not AFK
|
||||
{ is(f) { return false; }, _has_permission: true },
|
||||
// 1 without permission and not AFK
|
||||
{ is(f) { return false; }, _has_permission: false },
|
||||
// 1 afk with permission
|
||||
{ is(f) { return f === Flags.U_AFK; }, _has_permission: true },
|
||||
// 1 afk without permission
|
||||
{ is(f) { return f === Flags.U_AFK; }, _has_permission: false }
|
||||
]
|
||||
|
||||
fakeChannel.modules.permissions.canVoteskip = u => u._has_permission;
|
||||
|
||||
const {
|
||||
total,
|
||||
eligible,
|
||||
afk,
|
||||
noPermission
|
||||
} = voteskipModule.calcUsercounts();
|
||||
|
||||
assert.strictEqual(total, 4, 'mismatch: total');
|
||||
assert.strictEqual(eligible, 1, 'mismatch: eligible');
|
||||
// Permission is checked before AFK; if user is AFK and also does
|
||||
// not have permission, they should be counted in noPermission
|
||||
// but not afk
|
||||
assert.strictEqual(afk, 1, 'mismatch: afk');
|
||||
assert.strictEqual(noPermission, 2, 'mismatch: noPermission');
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue