120 lines
3.9 KiB
JavaScript
120 lines
3.9 KiB
JavaScript
import assert from 'assert';
|
|
|
|
import { createTestContext } from './helpers/test_context.js';
|
|
import { setRoomMaxOccupants } from './helpers/test_observer.js';
|
|
|
|
const CONFERENCE = 'conference.localhost';
|
|
const BASE = 'http://localhost:5280';
|
|
|
|
let _roomCounter = 0;
|
|
const room = () => `census-${++_roomCounter}@${CONFERENCE}`;
|
|
|
|
/**
|
|
* Fetch GET /room-census and return the parsed body.
|
|
*
|
|
* @returns {Promise<{room_census: Array}>}
|
|
*/
|
|
async function getRoomCensus() {
|
|
const res = await fetch(`${BASE}/room-census`);
|
|
const text = await res.text();
|
|
|
|
assert.equal(res.status, 200, `GET /room-census must return 200, got ${res.status}: ${text}`);
|
|
|
|
let body;
|
|
|
|
try {
|
|
body = JSON.parse(text);
|
|
} catch (e) {
|
|
assert.fail(`GET /room-census returned non-JSON: ${text}`);
|
|
}
|
|
|
|
return body;
|
|
}
|
|
|
|
describe('mod_muc_census', () => {
|
|
|
|
let ctx;
|
|
|
|
beforeEach(() => {
|
|
ctx = createTestContext();
|
|
});
|
|
|
|
afterEach(() => ctx.cleanup());
|
|
|
|
it('returns 200 with a room_census array', async () => {
|
|
const body = await getRoomCensus();
|
|
|
|
assert.ok(Array.isArray(body.room_census),
|
|
`response must have a room_census array, got: ${JSON.stringify(body)}`);
|
|
});
|
|
|
|
it('only active rooms appear in census after a room is destroyed', async () => {
|
|
const r1 = room();
|
|
const r2 = room();
|
|
const r1Name = r1.split('@')[0];
|
|
const r2Name = r2.split('@')[0];
|
|
|
|
// Bring up both rooms.
|
|
const focus1 = await ctx.connectFocus(r1);
|
|
|
|
await ctx.connectFocus(r2);
|
|
const c1 = await ctx.connect();
|
|
const c2 = await ctx.connect();
|
|
|
|
await c1.joinRoom(r1);
|
|
await c2.joinRoom(r2);
|
|
|
|
const { room_census: before } = await getRoomCensus();
|
|
|
|
assert.ok(before.find(e => e.room_name && e.room_name.startsWith(r1Name)),
|
|
'room1 must appear in census while active');
|
|
assert.ok(before.find(e => e.room_name && e.room_name.startsWith(r2Name)),
|
|
'room2 must appear in census while active');
|
|
|
|
// Destroy room1 by disconnecting all its occupants.
|
|
await c1.disconnect();
|
|
await focus1.disconnect();
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
|
|
const { room_census: after } = await getRoomCensus();
|
|
|
|
assert.ok(!after.find(e => e.room_name && e.room_name.startsWith(r1Name)),
|
|
'room1 must not appear in census after all occupants leave');
|
|
assert.ok(after.find(e => e.room_name && e.room_name.startsWith(r2Name)),
|
|
'room2 must still appear in census');
|
|
});
|
|
|
|
it('tracks room occupancy and updates when clients leave', async () => {
|
|
const r = room();
|
|
const roomName = r.split('@')[0];
|
|
|
|
await ctx.connectFocus(r);
|
|
await setRoomMaxOccupants(r, 5);
|
|
|
|
const c1 = await ctx.connect();
|
|
const c2 = await ctx.connect();
|
|
|
|
await c1.joinRoom(r);
|
|
await c2.joinRoom(r);
|
|
|
|
// Room must appear with correct participant count and fields.
|
|
const { room_census: census1 } = await getRoomCensus();
|
|
const entry1 = census1.find(e => e.room_name && e.room_name.startsWith(roomName));
|
|
|
|
assert.ok(entry1, `room ${roomName} must appear in census after join`);
|
|
assert.ok(typeof entry1.created_time !== 'undefined', 'entry must have created_time');
|
|
assert.equal(entry1.participants, 2, 'participants must equal number of non-focus clients');
|
|
|
|
// After one client leaves the count must drop.
|
|
await c2.disconnect();
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
|
|
const { room_census: census2 } = await getRoomCensus();
|
|
const entry2 = census2.find(e => e.room_name && e.room_name.startsWith(roomName));
|
|
|
|
assert.ok(entry2, 'room must still appear after one client leaves');
|
|
assert.equal(entry2.participants, 1,
|
|
`participant count must be 1 after disconnect (got ${entry2.participants})`);
|
|
});
|
|
});
|