Files
Investidor-V2/tests/frontend/investor-context-api.test.mjs
T
2026-11-02 20:31:15 +02:00

197 lines
6.8 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { contextApi } from '../../resources/js/lib/investor-context.ts';
const success = { ok: true, json: async () => ({ saved: true }) };
await test('context handles compact CSRF cookies and rejects malformed writes before transport', async () => {
let calls = 0;
await withTransport(
async (_url, options) => {
calls++;
if (options.method !== 'GET')
assert.equal(
options.headers['X-XSRF-TOKEN'],
'synthetic/token',
);
return success;
},
async () => {
globalThis.document.cookie = 'other=x;XSRF-TOKEN=synthetic%2Ftoken';
await contextApi('/synthetic', {});
globalThis.document.cookie = 'XSRF-TOKEN=%broken';
await assert.rejects(
contextApi('/synthetic', {}, 'POST', true),
/sessão/,
);
assert.equal(calls, 1);
await contextApi('/synthetic');
assert.equal(calls, 2);
},
);
});
async function withTransport(fetch, callback) {
const previousFetch = globalThis.fetch;
const previousDocument = globalThis.document;
globalThis.fetch = fetch;
globalThis.document = { cookie: 'XSRF-TOKEN=synthetic%20token' };
try {
await callback();
} finally {
globalThis.fetch = previousFetch;
globalThis.document = previousDocument;
}
}
void test('context requests preserve Unicode payload and authentication while using byte-based keepalive eligibility', async () => {
const requests = [];
await withTransport(
async (_url, options) => {
requests.push(options);
return success;
},
async () => {
for (const text of [
'Preparação de investimento',
'ç'.repeat(33000),
'a'.repeat(65000),
]) {
const body = { declarations: { project_summary: text } };
assert.deepEqual(
await contextApi('/synthetic', body, 'POST', true),
{ saved: true },
);
const request = requests.at(-1);
assert.equal(request.body, JSON.stringify(body));
assert.equal(
request.keepalive,
new TextEncoder().encode(request.body).byteLength < 60000,
);
assert.equal(request.credentials, 'same-origin');
assert.equal(
request.headers['X-XSRF-TOKEN'],
'synthetic token',
);
}
assert.equal(requests[1].body.length < 60000, true);
assert.equal(requests[1].keepalive, false);
},
);
});
void test('concurrent context requests share the keepalive budget and release it after completion', async () => {
const requests = [];
let finish;
await withTransport(
(_url, options) => {
requests.push(options);
return requests.length === 1
? new Promise((resolve) => {
finish = resolve;
})
: Promise.resolve(success);
},
async () => {
const body = { text: 'a'.repeat(40000) };
const first = contextApi('/first', body, 'POST', true);
await contextApi('/second', body, 'POST', true);
assert.deepEqual(
requests.map((request) => request.keepalive),
[true, false],
);
finish(success);
await first;
await contextApi('/third', body, 'POST', true);
assert.equal(requests[2].keepalive, true);
},
);
});
void test('failed context transport releases the reserved budget without retrying a write', async () => {
const requests = [];
await withTransport(
async (_url, options) => {
requests.push(options);
if (requests.length === 1)
throw new Error('Synthetic transport error');
return success;
},
async () => {
const body = { text: 'a'.repeat(40000) };
await assert.rejects(
contextApi('/first', body, 'POST', true),
/Synthetic transport error/,
);
await contextApi('/second', body, 'POST', true);
assert.equal(requests.length, 2);
assert.equal(
requests.every((request) => request.keepalive),
true,
);
},
);
});
void test('ordinary context writes and reads retain their existing method and error behavior', async () => {
const requests = [];
await withTransport(
async (_url, options) => {
requests.push(options);
return requests.length === 3
? {
ok: false,
status: 409,
json: async () => ({
message: 'Synthetic version conflict',
}),
}
: success;
},
async () => {
await contextApi('/read');
await contextApi('/write', { value: 'ç' });
await assert.rejects(
contextApi('/conflict', { value: 'kept' }),
/Synthetic version conflict/,
);
assert.equal(requests[0].method, 'GET');
assert.equal(requests[0].body, undefined);
assert.equal(requests[0].headers['X-XSRF-TOKEN'], undefined);
assert.equal(requests[1].method, 'POST');
assert.equal(
requests.every((request) => request.keepalive === false),
true,
);
},
);
});
void test('invalid successful context response remains a failure and releases keepalive budget', async () => {
let calls = 0;
await withTransport(
async (_url, options) => {
calls++;
assert.equal(options.keepalive, true);
return calls === 1
? new Response('<html>unexpected</html>', { status: 200 })
: success;
},
async () => {
await assert.rejects(
contextApi(
'/synthetic',
{ text: 'a'.repeat(40000) },
'POST',
true,
),
/HTTP 200/,
);
assert.equal(calls, 1);
assert.deepEqual(
await contextApi(
'/synthetic',
{ text: 'a'.repeat(40000) },
'POST',
true,
),
{ saved: true },
);
},
);
});