Files
Haven/test/webhookPush.integration.test.js

86 lines
3.0 KiB
JavaScript

'use strict';
/**
* A bot's post in a channel pushes the members' phones like anyone's
* message. It used to push nobody, so people with push turned on heard
* nothing from bots. A silent bot post stays silent.
*
* node --test test/webhookPush.integration.test.js
*/
const test = require('node:test');
const assert = require('node:assert');
const http = require('node:http');
const crypto = require('node:crypto');
const { createHarness, wait } = require('./socketServerHarness');
let relay;
const relayed = [];
const h = createHarness(3512, 'webhook-push');
test.before(async () => {
relay = http.createServer((req, res) => {
let body = '';
req.on('data', (c) => (body += c));
req.on('end', () => {
try { relayed.push(JSON.parse(body)); } catch { relayed.push({ raw: body }); }
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ success: 1, failure: 0, failedTokens: [] }));
});
});
await new Promise((r) => relay.listen(0, '127.0.0.1', r));
process.env.FCM_RELAY_URL = `http://127.0.0.1:${relay.address().port}/push`;
process.env.FCM_PUSH_KEY = 'webhook-push-test';
await h.start();
});
test.after(async () => {
await h.stop();
await new Promise((r) => relay.close(r));
});
const pushesFor = (token, from) => relayed.slice(from).filter((p) => Array.isArray(p.tokens) && p.tokens.includes(token));
async function waitForPush(token, from, ms = 3000) {
for (let t = 0; t < ms; t += 100) {
if (pushesFor(token, from).length) return true;
await wait(100);
}
return false;
}
test('a bot post pushes the channel members', async () => {
const admin = await h.register('admin');
const bob = await h.register('bob');
const A = await h.connect(admin.token);
const B = await h.connect(bob.token);
const list = h.next(A, 'channels-list', (c) => Array.isArray(c) && c.some((x) => x.name === 'alerts'));
A.emit('create-channel', { name: 'alerts' });
const code = (await list).find((c) => c.name === 'alerts').code;
B.emit('join-channel', { code });
await wait(300);
const made = h.next(A, 'webhook-created', (w) => w && w.name === 'Watcher');
A.emit('create-webhook', { channelCode: code, name: 'Watcher' });
const hook = await made;
assert.ok(hook && hook.token, 'webhook made');
const phone = 'phone-' + crypto.randomBytes(8).toString('hex');
B.emit('register-fcm-token', { token: phone });
await wait(300);
B.disconnect();
await wait(300);
let from = relayed.length;
const posted = await h.post(`/api/webhooks/${hook.token}`, { content: 'disk is full' });
assert.ok(posted.success, JSON.stringify(posted));
assert.equal(await waitForPush(phone, from), true, 'bob\'s phone is pushed');
const push = pushesFor(phone, from)[0];
assert.match(JSON.stringify(push), /Watcher/, 'named after the bot');
from = relayed.length;
await h.post(`/api/webhooks/${hook.token}`, { content: 'quiet note', silent: true });
assert.equal(await waitForPush(phone, from, 1500), false, 'a silent bot post pushes nobody');
A.disconnect();
});