mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-29 03:39:13 -04:00
chat: New option to completely disable chat
This commit is contained in:
parent
310a371234
commit
dda284cbe9
13 changed files with 274 additions and 126 deletions
|
@ -2,6 +2,8 @@
|
|||
|
||||
const assert = require('assert').strict;
|
||||
const common = require('../../common');
|
||||
const plugins = require('../../../../static/js/pluginfw/plugins');
|
||||
const settings = require('../../../../node/utils/Settings');
|
||||
|
||||
let agent;
|
||||
const apiKey = common.apiKey;
|
||||
|
@ -13,7 +15,12 @@ const timestamp = Date.now();
|
|||
const endPoint = (point) => `/api/${apiVersion}/${point}?apikey=${apiKey}`;
|
||||
|
||||
describe(__filename, function () {
|
||||
const backups = {settings: {}};
|
||||
|
||||
before(async function () {
|
||||
backups.settings.integratedChat = settings.integratedChat;
|
||||
settings.integratedChat = true;
|
||||
await plugins.update();
|
||||
agent = await common.init();
|
||||
await agent.get('/api/')
|
||||
.expect(200)
|
||||
|
@ -37,7 +44,16 @@ describe(__filename, function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('message sequence', function () {
|
||||
after(async function () {
|
||||
Object.assign(settings, backups.settings);
|
||||
await plugins.update();
|
||||
});
|
||||
|
||||
describe('settings.integratedChat = true', function () {
|
||||
beforeEach(async function () {
|
||||
settings.integratedChat = true;
|
||||
});
|
||||
|
||||
it('appendChatMessage', async function () {
|
||||
await agent.get(`${endPoint('appendChatMessage')}&padID=${padID}&text=blalblalbha` +
|
||||
`&authorID=${authorID}&time=${timestamp}`)
|
||||
|
@ -68,6 +84,40 @@ describe(__filename, function () {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('settings.integratedChat = false', function () {
|
||||
beforeEach(async function () {
|
||||
settings.integratedChat = false;
|
||||
});
|
||||
|
||||
it('appendChatMessage returns an error', async function () {
|
||||
await agent.get(`${endPoint('appendChatMessage')}&padID=${padID}&text=blalblalbha` +
|
||||
`&authorID=${authorID}&time=${timestamp}`)
|
||||
.expect(500)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect((res) => {
|
||||
assert.equal(res.body.code, 2);
|
||||
});
|
||||
});
|
||||
|
||||
it('getChatHead returns an error', async function () {
|
||||
await agent.get(`${endPoint('getChatHead')}&padID=${padID}`)
|
||||
.expect(500)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect((res) => {
|
||||
assert.equal(res.body.code, 2);
|
||||
});
|
||||
});
|
||||
|
||||
it('getChatHistory returns an error', async function () {
|
||||
await agent.get(`${endPoint('getChatHistory')}&padID=${padID}`)
|
||||
.expect(500)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect((res) => {
|
||||
assert.equal(res.body.code, 2);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function makeid() {
|
||||
|
|
|
@ -6,29 +6,37 @@ const assert = require('assert').strict;
|
|||
const common = require('../common');
|
||||
const padManager = require('../../../node/db/PadManager');
|
||||
const pluginDefs = require('../../../static/js/pluginfw/plugin_defs');
|
||||
const plugins = require('../../../static/js/pluginfw/plugins');
|
||||
const settings = require('../../../node/utils/Settings');
|
||||
|
||||
const logger = common.logger;
|
||||
|
||||
const checkHook = async (hookName, checkFn) => {
|
||||
if (pluginDefs.hooks[hookName] == null) pluginDefs.hooks[hookName] = [];
|
||||
await new Promise((resolve, reject) => {
|
||||
pluginDefs.hooks[hookName].push({
|
||||
hook_fn: async (hookName, context) => {
|
||||
if (checkFn == null) return;
|
||||
logger.debug(`hook ${hookName} invoked`);
|
||||
try {
|
||||
// Make sure checkFn is called only once.
|
||||
const _checkFn = checkFn;
|
||||
checkFn = null;
|
||||
await _checkFn(context);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
},
|
||||
let hook;
|
||||
try {
|
||||
await new Promise((resolve, reject) => {
|
||||
hook = {
|
||||
hook_fn: async (hookName, context) => {
|
||||
if (checkFn == null) return;
|
||||
logger.debug(`hook ${hookName} invoked`);
|
||||
try {
|
||||
// Make sure checkFn is called only once.
|
||||
const _checkFn = checkFn;
|
||||
checkFn = null;
|
||||
await _checkFn(context);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
},
|
||||
};
|
||||
pluginDefs.hooks[hookName].push(hook);
|
||||
});
|
||||
});
|
||||
} finally {
|
||||
pluginDefs.hooks[hookName] = pluginDefs.hooks[hookName].filter((h) => h !== hook);
|
||||
}
|
||||
};
|
||||
|
||||
const sendMessage = async (socket, data) => (
|
||||
|
@ -37,119 +45,146 @@ const sendChat = async (socket, message) => (
|
|||
await sendMessage(socket, {type: 'CHAT_MESSAGE', message}));
|
||||
|
||||
describe(__filename, function () {
|
||||
const backups = {settings: {}};
|
||||
let clientVars;
|
||||
const padId = 'testChatPad';
|
||||
const hooksBackup = {};
|
||||
let socket;
|
||||
|
||||
const connect = async () => {
|
||||
socket = await common.connect();
|
||||
({data: clientVars} = await common.handshake(socket, padId));
|
||||
};
|
||||
|
||||
before(async function () {
|
||||
for (const [name, defs] of Object.entries(pluginDefs.hooks)) {
|
||||
if (defs == null) continue;
|
||||
hooksBackup[name] = defs;
|
||||
}
|
||||
backups.settings.integratedChat = settings.integratedChat;
|
||||
});
|
||||
|
||||
beforeEach(async function () {
|
||||
for (const [name, defs] of Object.entries(hooksBackup)) pluginDefs.hooks[name] = [...defs];
|
||||
for (const name of Object.keys(pluginDefs.hooks)) {
|
||||
if (hooksBackup[name] == null) delete pluginDefs.hooks[name];
|
||||
}
|
||||
if (await padManager.doesPadExist(padId)) {
|
||||
const pad = await padManager.getPad(padId);
|
||||
await pad.remove();
|
||||
}
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
Object.assign(pluginDefs.hooks, hooksBackup);
|
||||
for (const name of Object.keys(pluginDefs.hooks)) {
|
||||
if (hooksBackup[name] == null) delete pluginDefs.hooks[name];
|
||||
afterEach(async function () {
|
||||
if (socket) {
|
||||
socket.close();
|
||||
socket = null;
|
||||
}
|
||||
});
|
||||
|
||||
describe('chatNewMessage hook', function () {
|
||||
let authorId;
|
||||
let socket;
|
||||
after(async function () {
|
||||
Object.assign(settings, backups.settings);
|
||||
await plugins.update();
|
||||
});
|
||||
|
||||
describe('settings.integratedChat = true', function () {
|
||||
before(async function () {
|
||||
settings.integratedChat = true;
|
||||
await plugins.update();
|
||||
});
|
||||
|
||||
beforeEach(async function () {
|
||||
socket = await common.connect();
|
||||
const {data: clientVars} = await common.handshake(socket, padId);
|
||||
authorId = clientVars.userId;
|
||||
await connect();
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
socket.close();
|
||||
});
|
||||
|
||||
it('message', async function () {
|
||||
const start = Date.now();
|
||||
await Promise.all([
|
||||
checkHook('chatNewMessage', ({message}) => {
|
||||
assert(message != null);
|
||||
assert(message instanceof ChatMessage);
|
||||
assert.equal(message.authorId, authorId);
|
||||
assert.equal(message.text, this.test.title);
|
||||
assert(message.time >= start);
|
||||
assert(message.time <= Date.now());
|
||||
}),
|
||||
sendChat(socket, {text: this.test.title}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('pad', async function () {
|
||||
await Promise.all([
|
||||
checkHook('chatNewMessage', ({pad}) => {
|
||||
assert(pad != null);
|
||||
assert(pad instanceof Pad);
|
||||
assert.equal(pad.id, padId);
|
||||
}),
|
||||
sendChat(socket, {text: this.test.title}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('padId', async function () {
|
||||
await Promise.all([
|
||||
checkHook('chatNewMessage', (context) => {
|
||||
assert.equal(context.padId, padId);
|
||||
}),
|
||||
sendChat(socket, {text: this.test.title}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('mutations propagate', async function () {
|
||||
const listen = async (type) => await new Promise((resolve) => {
|
||||
const handler = (msg) => {
|
||||
if (msg.type !== 'COLLABROOM') return;
|
||||
if (msg.data == null || msg.data.type !== type) return;
|
||||
resolve(msg.data);
|
||||
socket.off('message', handler);
|
||||
};
|
||||
socket.on('message', handler);
|
||||
describe('chatNewMessage hook', function () {
|
||||
it('message', async function () {
|
||||
const start = Date.now();
|
||||
await Promise.all([
|
||||
checkHook('chatNewMessage', ({message}) => {
|
||||
assert(message != null);
|
||||
assert(message instanceof ChatMessage);
|
||||
assert.equal(message.authorId, clientVars.userId);
|
||||
assert.equal(message.text, this.test.title);
|
||||
assert(message.time >= start);
|
||||
assert(message.time <= Date.now());
|
||||
}),
|
||||
sendChat(socket, {text: this.test.title}),
|
||||
]);
|
||||
});
|
||||
|
||||
const modifiedText = `${this.test.title} <added changes>`;
|
||||
const customMetadata = {foo: this.test.title};
|
||||
await Promise.all([
|
||||
checkHook('chatNewMessage', ({message}) => {
|
||||
message.text = modifiedText;
|
||||
message.customMetadata = customMetadata;
|
||||
}),
|
||||
(async () => {
|
||||
const {message} = await listen('CHAT_MESSAGE');
|
||||
assert(message != null);
|
||||
assert.equal(message.text, modifiedText);
|
||||
assert.deepEqual(message.customMetadata, customMetadata);
|
||||
})(),
|
||||
sendChat(socket, {text: this.test.title}),
|
||||
]);
|
||||
// Simulate fetch of historical chat messages when a pad is first loaded.
|
||||
await Promise.all([
|
||||
(async () => {
|
||||
const {messages: [message]} = await listen('CHAT_MESSAGES');
|
||||
assert(message != null);
|
||||
assert.equal(message.text, modifiedText);
|
||||
assert.deepEqual(message.customMetadata, customMetadata);
|
||||
})(),
|
||||
sendMessage(socket, {type: 'GET_CHAT_MESSAGES', start: 0, end: 0}),
|
||||
]);
|
||||
it('pad', async function () {
|
||||
await Promise.all([
|
||||
checkHook('chatNewMessage', ({pad}) => {
|
||||
assert(pad != null);
|
||||
assert(pad instanceof Pad);
|
||||
assert.equal(pad.id, padId);
|
||||
}),
|
||||
sendChat(socket, {text: this.test.title}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('padId', async function () {
|
||||
await Promise.all([
|
||||
checkHook('chatNewMessage', (context) => {
|
||||
assert.equal(context.padId, padId);
|
||||
}),
|
||||
sendChat(socket, {text: this.test.title}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('mutations propagate', async function () {
|
||||
const listen = async (type) => await new Promise((resolve) => {
|
||||
const handler = (msg) => {
|
||||
if (msg.type !== 'COLLABROOM') return;
|
||||
if (msg.data == null || msg.data.type !== type) return;
|
||||
resolve(msg.data);
|
||||
socket.off('message', handler);
|
||||
};
|
||||
socket.on('message', handler);
|
||||
});
|
||||
|
||||
const modifiedText = `${this.test.title} <added changes>`;
|
||||
const customMetadata = {foo: this.test.title};
|
||||
await Promise.all([
|
||||
checkHook('chatNewMessage', ({message}) => {
|
||||
message.text = modifiedText;
|
||||
message.customMetadata = customMetadata;
|
||||
}),
|
||||
(async () => {
|
||||
const {message} = await listen('CHAT_MESSAGE');
|
||||
assert(message != null);
|
||||
assert.equal(message.text, modifiedText);
|
||||
assert.deepEqual(message.customMetadata, customMetadata);
|
||||
})(),
|
||||
sendChat(socket, {text: this.test.title}),
|
||||
]);
|
||||
// Simulate fetch of historical chat messages when a pad is first loaded.
|
||||
await Promise.all([
|
||||
(async () => {
|
||||
const {messages: [message]} = await listen('CHAT_MESSAGES');
|
||||
assert(message != null);
|
||||
assert.equal(message.text, modifiedText);
|
||||
assert.deepEqual(message.customMetadata, customMetadata);
|
||||
})(),
|
||||
sendMessage(socket, {type: 'GET_CHAT_MESSAGES', start: 0, end: 0}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('settings.integratedChat = false', function () {
|
||||
before(async function () {
|
||||
settings.integratedChat = false;
|
||||
await plugins.update();
|
||||
});
|
||||
|
||||
beforeEach(async function () {
|
||||
await connect();
|
||||
});
|
||||
|
||||
it('clientVars.chatHead is unset', async function () {
|
||||
assert(!('chatHead' in clientVars), `chatHead should be unset, is ${clientVars.chatHead}`);
|
||||
});
|
||||
|
||||
it('rejects CHAT_MESSAGE messages', async function () {
|
||||
await assert.rejects(sendChat(socket, {text: 'this is a test'}), /unknown message type/);
|
||||
});
|
||||
|
||||
it('rejects GET_CHAT_MESSAGES messages', async function () {
|
||||
const msg = {type: 'GET_CHAT_MESSAGES', start: 0, end: 0};
|
||||
await assert.rejects(sendMessage(socket, msg), /unknown message type/);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue