| 1 | // Stilte hoort niets te kosten (Barts punt, 9-8).
|
|---|
| 2 | //
|
|---|
| 3 | // De inbox doet dit al met `since` + `wait`: niets veranderd is een 304. De
|
|---|
| 4 | // guardian-wachtrijen stuurden bij elke verversing de hele lijst terug -- bij
|
|---|
| 5 | // honderd wards veertienhonderd objecten die de telefoon opnieuw moet opbouwen.
|
|---|
| 6 | //
|
|---|
| 7 | // Wat hier bewaakt wordt: dat de ETag over de INHOUD gaat (verandert er iets,
|
|---|
| 8 | // dan verandert hij mee) en dat een leeg antwoord NOOIT een 304 oplevert. Dat
|
|---|
| 9 | // tweede is dezelfde les als de '0'-uitzondering bij de inbox: gaat er iets mis
|
|---|
| 10 | // bij het opbouwen, dan is de hash van niets ook stabiel, en zit een client voor
|
|---|
| 11 | // eeuwig op 304 te kijken naar een leeg scherm.
|
|---|
| 12 | //
|
|---|
| 13 | // Run: npm test
|
|---|
| 14 | import { test } from 'node:test';
|
|---|
| 15 | import assert from 'node:assert/strict';
|
|---|
| 16 |
|
|---|
| 17 | process.env.DATABASE_PATH = ':memory:';
|
|---|
| 18 | const AP = await import('../src/services/ActivityPubService.js');
|
|---|
| 19 |
|
|---|
| 20 | function nepRes() {
|
|---|
| 21 | return {
|
|---|
| 22 | code: 200, body: null, headers: {},
|
|---|
| 23 | set(k, v) { this.headers[String(k).toLowerCase()] = v; return this; },
|
|---|
| 24 | type(t) { this.headers['content-type'] = t; return this; },
|
|---|
| 25 | status(c) { this.code = c; return this; },
|
|---|
| 26 | end() { this.body = ''; return this; },
|
|---|
| 27 | send(b) { this.body = b; return this; },
|
|---|
| 28 | };
|
|---|
| 29 | }
|
|---|
| 30 | const req = (etag) => ({ headers: etag ? { 'if-none-match': etag } : {} });
|
|---|
| 31 | const coll = (n) => ({ type: 'OrderedCollection', orderedItems: Array.from({ length: n }, (_, i) => ({ id: `x${i}` })) });
|
|---|
| 32 |
|
|---|
| 33 | test('dezelfde inhoud levert de tweede keer een 304 op', () => {
|
|---|
| 34 | const r1 = nepRes();
|
|---|
| 35 | AP.sendMaybe304(req(), r1, coll(3));
|
|---|
| 36 | assert.equal(r1.code, 200);
|
|---|
| 37 | assert.ok(r1.headers.etag, 'er is een merksteen');
|
|---|
| 38 |
|
|---|
| 39 | const r2 = nepRes();
|
|---|
| 40 | AP.sendMaybe304(req(r1.headers.etag), r2, coll(3));
|
|---|
| 41 | assert.equal(r2.code, 304);
|
|---|
| 42 | assert.equal(r2.body, '', 'en geen inhoud');
|
|---|
| 43 | });
|
|---|
| 44 |
|
|---|
| 45 | test('verandert er iets, dan verandert de merksteen mee', () => {
|
|---|
| 46 | const r1 = nepRes(); AP.sendMaybe304(req(), r1, coll(3));
|
|---|
| 47 | const r2 = nepRes(); AP.sendMaybe304(req(r1.headers.etag), r2, coll(4));
|
|---|
| 48 | assert.equal(r2.code, 200, 'vier items is niet drie');
|
|---|
| 49 | assert.notEqual(r2.headers.etag, r1.headers.etag);
|
|---|
| 50 | });
|
|---|
| 51 |
|
|---|
| 52 | test('een LEEG antwoord krijgt nooit een 304', () => {
|
|---|
| 53 | // De gevaarlijke stille fout: gaat het opbouwen mis en komt er een lege lijst
|
|---|
| 54 | // uit, dan is die hash ook stabiel en kijkt een client voor eeuwig naar niets.
|
|---|
| 55 | const r1 = nepRes();
|
|---|
| 56 | AP.sendMaybe304(req(), r1, coll(0));
|
|---|
| 57 | assert.equal(r1.code, 200);
|
|---|
| 58 | assert.equal(r1.headers.etag, undefined, 'geen merksteen op leegte');
|
|---|
| 59 |
|
|---|
| 60 | const r2 = nepRes();
|
|---|
| 61 | AP.sendMaybe304(req('"wat-dan-ook"'), r2, coll(0));
|
|---|
| 62 | assert.equal(r2.code, 200, 'en dus ook nooit een 304');
|
|---|
| 63 | });
|
|---|
| 64 |
|
|---|
| 65 | test('de client krijgt te horen dat hij mag bewaren en moet navragen', () => {
|
|---|
| 66 | // Zonder no-cache stuurt een browser geen If-None-Match, en is de ETag
|
|---|
| 67 | // decoratie. En Vary op Authorization, want dit is een eigenaar-antwoord.
|
|---|
| 68 | const r = nepRes();
|
|---|
| 69 | AP.sendMaybe304(req(), r, coll(2));
|
|---|
| 70 | assert.match(r.headers['cache-control'], /no-cache/);
|
|---|
| 71 | assert.equal(r.headers.vary, 'Authorization');
|
|---|
| 72 | });
|
|---|
| 73 |
|
|---|
| 74 | test('een antwoord dat geen collectie is werkt ook', () => {
|
|---|
| 75 | // Het paneel is geen OrderedCollection maar een gewoon object.
|
|---|
| 76 | const r1 = nepRes(); AP.sendMaybe304(req(), r1, { wards: [], strings: { a: 'b' } });
|
|---|
| 77 | const r2 = nepRes(); AP.sendMaybe304(req(r1.headers.etag), r2, { wards: [], strings: { a: 'b' } });
|
|---|
| 78 | assert.equal(r2.code, 304);
|
|---|
| 79 | });
|
|---|