114 lines
4.8 KiB
JavaScript
114 lines
4.8 KiB
JavaScript
|
|
// Integration smoke for server. Spin on random port, hit REST, check WS broadcast.
|
||
|
|
'use strict';
|
||
|
|
|
||
|
|
const http = require('http');
|
||
|
|
const { createServer } = require('./index');
|
||
|
|
|
||
|
|
let BASE;
|
||
|
|
let handle;
|
||
|
|
|
||
|
|
beforeEach(async () => {
|
||
|
|
handle = createServer({ dbPath: ':memory:' });
|
||
|
|
await new Promise(r => handle.server.listen(0, r));
|
||
|
|
const addr = handle.server.address();
|
||
|
|
BASE = `http://127.0.0.1:${addr.port}`;
|
||
|
|
});
|
||
|
|
afterEach(async () => {
|
||
|
|
await new Promise(r => handle.close(r));
|
||
|
|
});
|
||
|
|
|
||
|
|
async function req(method, path, body) {
|
||
|
|
const res = await fetch(`${BASE}${path}`, {
|
||
|
|
method,
|
||
|
|
headers: body ? { 'Content-Type': 'application/json' } : undefined,
|
||
|
|
body: body ? JSON.stringify(body) : undefined,
|
||
|
|
});
|
||
|
|
const text = await res.text();
|
||
|
|
const json = text ? JSON.parse(text) : null;
|
||
|
|
return { status: res.status, json };
|
||
|
|
}
|
||
|
|
|
||
|
|
describe('server REST', () => {
|
||
|
|
test('health', async () => {
|
||
|
|
const { status, json } = await req('GET', '/health');
|
||
|
|
expect(status).toBe(200);
|
||
|
|
expect(json.ok).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('campaign create + list', async () => {
|
||
|
|
const { json: c } = await req('POST', '/api/campaigns', { name: 'Test', backgroundUrl: '' });
|
||
|
|
expect(c.name).toBe('Test');
|
||
|
|
const { json: list } = await req('GET', '/api/campaigns');
|
||
|
|
expect(list).toHaveLength(1);
|
||
|
|
expect(list[0].id).toBe(c.id);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('encounter create + add monster + start', async () => {
|
||
|
|
const { json: c } = await req('POST', '/api/campaigns', { name: 'C' });
|
||
|
|
const { json: e } = await req('POST', `/api/campaigns/${c.id}/encounters`, { name: 'E' });
|
||
|
|
expect(e.participants).toEqual([]);
|
||
|
|
|
||
|
|
const { json: addRes } = await req('POST', `/api/campaigns/${c.id}/encounters/${e.id}/participants`, {
|
||
|
|
type: 'monster', name: 'Goblin', maxHp: 7, initMod: 2, isNpc: false,
|
||
|
|
});
|
||
|
|
expect(addRes.encounter.participants).toHaveLength(1);
|
||
|
|
expect(addRes.encounter.participants[0].name).toBe('Goblin');
|
||
|
|
expect(addRes.roll.total).toBeGreaterThan(2);
|
||
|
|
|
||
|
|
const { json: started } = await req('POST', `/api/campaigns/${c.id}/encounters/${e.id}/start`);
|
||
|
|
expect(started.isStarted).toBe(true);
|
||
|
|
expect(started.round).toBe(1);
|
||
|
|
expect(started.currentTurnParticipantId).toBe(addRes.encounter.participants[0].id);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('next turn advances', async () => {
|
||
|
|
const { json: c } = await req('POST', '/api/campaigns', { name: 'C' });
|
||
|
|
const { json: e } = await req('POST', `/api/campaigns/${c.id}/encounters`, { name: 'E' });
|
||
|
|
const ids = [];
|
||
|
|
for (let i = 0; i < 3; i++) {
|
||
|
|
const { json: r } = await req('POST', `/api/campaigns/${c.id}/encounters/${e.id}/participants`, {
|
||
|
|
type: 'monster', name: `M${i}`, maxHp: 10, initMod: i,
|
||
|
|
});
|
||
|
|
ids.push(r.encounter.participants[r.encounter.participants.length - 1].id);
|
||
|
|
}
|
||
|
|
await req('POST', `/api/campaigns/${c.id}/encounters/${e.id}/start`);
|
||
|
|
const { json: t1 } = await req('POST', `/api/campaigns/${c.id}/encounters/${e.id}/nextTurn`);
|
||
|
|
expect(t1.currentTurnParticipantId).not.toBe(t1.turnOrderIds[0]);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('damage to 0 deactivates', async () => {
|
||
|
|
const { json: c } = await req('POST', '/api/campaigns', { name: 'C' });
|
||
|
|
const { json: e } = await req('POST', `/api/campaigns/${c.id}/encounters`, { name: 'E' });
|
||
|
|
const { json: r } = await req('POST', `/api/campaigns/${c.id}/encounters/${e.id}/participants`, {
|
||
|
|
type: 'monster', name: 'Orc', maxHp: 5, initMod: 0,
|
||
|
|
});
|
||
|
|
const pid = r.encounter.participants[0].id;
|
||
|
|
await req('POST', `/api/campaigns/${c.id}/encounters/${e.id}/start`);
|
||
|
|
const { json: after } = await req('POST', `/api/campaigns/${c.id}/encounters/${e.id}/participants/${pid}/hp`, {
|
||
|
|
changeType: 'damage', amount: 5,
|
||
|
|
});
|
||
|
|
expect(after.participants[0].currentHp).toBe(0);
|
||
|
|
expect(after.participants[0].isActive).toBe(false);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('error: start with no participants', async () => {
|
||
|
|
const { json: c } = await req('POST', '/api/campaigns', { name: 'C' });
|
||
|
|
const { json: e } = await req('POST', `/api/campaigns/${c.id}/encounters`, { name: 'E' });
|
||
|
|
const { status, json } = await req('POST', `/api/campaigns/${c.id}/encounters/${e.id}/start`);
|
||
|
|
expect(status).toBe(400);
|
||
|
|
expect(json.error).toMatch(/participants/i);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('logs recorded on actions', async () => {
|
||
|
|
const { json: c } = await req('POST', '/api/campaigns', { name: 'C' });
|
||
|
|
const { json: e } = await req('POST', `/api/campaigns/${c.id}/encounters`, { name: 'E' });
|
||
|
|
await req('POST', `/api/campaigns/${c.id}/encounters/${e.id}/participants`, {
|
||
|
|
type: 'monster', name: 'Goblin', maxHp: 7, initMod: 2,
|
||
|
|
});
|
||
|
|
await req('POST', `/api/campaigns/${c.id}/encounters/${e.id}/start`);
|
||
|
|
const { json: logs } = await req('GET', '/api/logs');
|
||
|
|
expect(logs.length).toBeGreaterThanOrEqual(2);
|
||
|
|
expect(logs.some(l => /Combat started/.test(l.message))).toBe(true);
|
||
|
|
});
|
||
|
|
});
|