Files
Investidor-V2/tests/frontend/education-review.test.mjs
T

319 lines
12 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { harness, props, text } from './helpers/education-review.mjs';
const form = 'education-review';
function historyPage(page = 1) {
return {
data: [], total: 24, current_page: page, last_page: 2,
prev_page_url: page === 2 ? '/management/education/demands/one?scope=review&history_page=1' : null,
next_page_url: page === 1 ? '/management/education/demands/one?scope=review&history_page=2' : null,
};
}
test('history paging keeps the prepared review and does not ask to discard it', () => {
const h = harness(props({ history: historyPage() }));
h.change(form, reason, 'SYNTHETIC reasoning still being prepared.');
const next = h.all().find(node => node.type === 'a' && text(node) === 'Seguinte');
assert.equal(next.props.preserveState, true);
assert.equal(next.props.preserveScroll, true);
assert.match(next.props.href, /scope=review&history_page=2$/);
assert.equal(h.leave(next.props.preserveState), false);
assert.equal(h.confirmCalls, 0);
h.render({ ...h.props, history: historyPage(2) });
assert.equal(h.field(form, reason).props.value, 'SYNTHETIC reasoning still being prepared.');
const previous = h.all().find(node => node.type === 'a' && text(node) === 'Anterior');
assert.equal(previous.props.preserveState, true);
assert.equal(previous.props.preserveScroll, true);
assert.equal(h.sent.length, 0);
assert.equal(h.leave(), true); // Leaving the declaration still protects unsaved work.
});
test('history paging keeps an uncertain attempt recoverable under the same command key', () => {
const h = harness(props({ history: historyPage() }));
const request = prepared(h);
h.fail(request);
h.render({ ...h.props, history: historyPage(2) });
const retry = h.submit(form);
assert.deepEqual(retry.data, request.data);
assert.equal(h.sent.length, 2); // One explicit retry; paging itself sends no decision.
});
test('history paging cannot silently approve a newer declaration version', () => {
const h = harness(props({ history: historyPage() }));
h.change(form, reason, 'SYNTHETIC review prepared against version one.');
h.render({
...h.props, history: historyPage(2),
declaration: { ...h.props.declaration, version_no: 2, quantity: 31 },
});
h.submit(form);
assert.equal(h.sent.length, 0);
assert.equal(h.field(form, reason).props.value, 'SYNTHETIC review prepared against version one.');
assert.match(text(h.tree), /A declaração mudou/);
h.click('Confirmar a leitura desta versão');
const request = h.submit(form);
assert.equal(request.data.version_no, 2);
});
test('history paging with a different actor remounts instead of disclosing the prepared reason', () => {
const h = harness(props({ history: historyPage() }));
h.change(form, reason, 'SYNTHETIC private reasoning of the previous actor.');
h.render({
...h.props, actorId: 3, history: historyPage(2),
declaration: { ...h.props.declaration, review_context: { actor_id: 3, commands: [] } },
});
assert.equal(h.field(form, reason).props.value, '');
assert.equal(h.sent.length, 0);
});
test('the private detail renders preserved reasons, unavailable entries and contextual history pagination', () => {
const h = harness(
props({
history: {
data: [
{
id: 'one',
version: 3,
actor: 'SYNTHETIC reviewer',
occurred_at: '2026-11-03',
available: true,
status: 'rejected',
reason: 'SYNTHETIC preserved reason',
previous_reason: 'SYNTHETIC older reason',
},
{
id: 'two',
version: 2,
actor: null,
occurred_at: '2026-11-02',
available: false,
status: null,
reason: null,
previous_reason: null,
},
],
total: 12,
current_page: 1,
last_page: 2,
prev_page_url: null,
next_page_url:
'/management/education/demands/one?scope=mine&history_page=2',
},
}),
);
assert.match(text(h.tree), /Registos de revisão disponíveis/);
assert.match(text(h.tree), /SYNTHETIC preserved reason/);
assert.match(
text(h.tree),
/Fundamento anterior capturado: SYNTHETIC older reason/,
);
assert.match(text(h.tree), /Fundamento indisponível para leitura/);
assert.ok(h.tree);
});
test('the submitter sees the declaration without being asked to review it', () => {
const initial = props();
initial.declaration.can_review = false;
initial.declaration.review_unavailable = 'self';
const h = harness(initial);
assert.equal(h.button('Guardar decisão'), undefined);
assert.match(text(h.tree), /outro gestor/);
});
test('a newer declaration cannot silently replace the version on which the review was prepared', () => {
const h = harness();
h.change(
form,
'Justificação e evidência da revisão',
'SYNTHETIC prepared reason with evidence.',
);
h.render({
...h.props,
declaration: { ...h.props.declaration, version_no: 2, quantity: 30 },
});
h.submit(form);
assert.equal(h.sent.length, 0);
});
const reason = 'Justificação e evidência da revisão';
function prepared(h) {
h.change(form, reason, 'SYNTHETIC independent review with evidence.');
return h.submit(form);
}
function accepted(h, request = h.sent.at(-1), patch = {}) {
return {
...h.props,
declaration: {
...h.props.declaration,
version_no: request.data.version_no + 1,
status: request.data.status,
review_reason: request.data.review_reason,
review_context: {
actor_id: h.props.actorId,
commands: [
{
key: request.data.client_key,
version: request.data.version_no + 1,
},
],
},
},
...patch,
};
}
test('explicit comparison adopts the current version without discarding the prepared decision', () => {
const h = harness();
h.change(form, reason, 'SYNTHETIC prepared reason with evidence.');
h.render({
...h.props,
declaration: { ...h.props.declaration, version_no: 2, quantity: 30 },
});
assert.match(text(h.tree), /Analisada: 5.*Actual: 30/);
h.click('Confirmar a leitura desta versão');
const request = h.submit(form);
assert.equal(request.data.version_no, 2);
assert.equal(
request.data.review_reason,
'SYNTHETIC prepared reason with evidence.',
);
});
test('confirmation clears only sent event values and preserves later edits', () => {
const h = harness(),
request = prepared(h);
h.change(form, reason, 'SYNTHETIC later reason with evidence.');
h.change(form, 'Decisão interna', 'rejected');
h.success(accepted(h, request), request);
assert.equal(
h.field(form, reason).props.value,
'SYNTHETIC later reason with evidence.',
);
assert.equal(h.field(form, 'Decisão interna').props.value, 'rejected');
const next = h.submit(form);
assert.equal(next.data.version_no, 2);
assert.notEqual(next.data.client_key, request.data.client_key);
});
test('an uncertain result retries exactly the original version, decision and key', () => {
const h = harness(),
request = prepared(h);
h.fail(request);
h.change(form, reason, 'SYNTHETIC later reason with evidence.');
const retry = h.submit(form);
assert.deepEqual(retry.data, request.data);
h.success(accepted(h, retry), retry);
assert.equal(
h.field(form, reason).props.value,
'SYNTHETIC later reason with evidence.',
);
});
test('a fresh authorised read confirms the receipt without sending another decision', () => {
const h = harness(),
request = prepared(h);
h.fail(request, 500);
h.click('Actualizar dados da declaração');
assert.deepEqual(h.reloads[0].only, [
'declaration',
'references',
'today',
'actorId',
'kind',
'history',
]);
h.refreshed(accepted(h, request));
assert.equal(h.sent.length, 1);
assert.equal(h.field(form, reason).props.value, '');
assert.equal(h.leave(), false);
assert.match(text(h.tree), /Revisão registada/);
});
test('another actor cannot acknowledge or erase a local pending review', () => {
const h = harness(),
request = prepared(h);
request.options.onSuccess({ props: accepted(h, request, { actorId: 3 }) });
request.form.processing = false;
h.render();
assert.equal(
h.field(form, reason).props.value,
'SYNTHETIC independent review with evidence.',
);
assert.deepEqual(h.submit(form).data, request.data);
});
test('an obsolete callback cannot alter the draft of the next account', () => {
const h = harness(),
request = prepared(h);
h.render({
...h.props,
actorId: 3,
declaration: {
...h.props.declaration,
review_context: { actor_id: 3, commands: [] },
},
});
h.change(form, reason, 'SYNTHETIC next account review.');
request.options.onSuccess({ props: accepted(h, request, { actorId: 1 }) });
request.form.processing = false;
h.render();
assert.equal(
h.field(form, reason).props.value,
'SYNTHETIC next account review.',
);
});
test('a later decision remains current when an earlier receipt is acknowledged', () => {
const h = harness(),
request = prepared(h);
h.fail(request);
const next = accepted(h, request);
next.declaration.version_no = 3;
next.declaration.status = 'rejected';
h.render(next);
assert.match(text(h.tree), /A declaração mudou/);
assert.equal(h.sent.length, 1);
h.submit(form);
assert.equal(h.sent.length, 1);
h.click('Confirmar a leitura desta versão');
const fresh = h.submit(form);
assert.equal(fresh.data.version_no, 3);
assert.notEqual(fresh.data.client_key, request.data.client_key);
});
test('a competing newer version without the receipt requires explicit adoption before a new decision', () => {
const h = harness(),
request = prepared(h);
h.fail(request, 409);
h.click('Actualizar declaração');
h.refreshed({
...h.props,
declaration: { ...h.props.declaration, version_no: 2, quantity: 20 },
});
h.click('Confirmar a leitura desta versão');
const next = h.submit(form);
assert.equal(next.data.version_no, 2);
assert.notEqual(next.data.client_key, request.data.client_key);
});
test('expired declarations retain prepared text without a new decision form', () => {
const h = harness(),
request = prepared(h);
h.fail(request, 422);
h.render({
...h.props,
declaration: {
...h.props.declaration,
can_review: false,
review_unavailable: 'expired',
},
});
assert.equal(h.button('Guardar decisão'), undefined);
assert.equal(h.button('Recuperar a mesma revisão'), undefined);
assert.match(text(h.tree), /Fundamento preparado nesta página/);
assert.match(text(h.tree), /SYNTHETIC independent review/);
});
test('validation preserves the draft and a decision-only change has one leave guard', () => {
const h = harness();
h.change(form, 'Decisão interna', 'rejected');
assert.equal(h.leave(), true);
assert.equal(h.confirmCalls, 1);
const request = prepared(h);
h.validation({ review_reason: 'SYNTHETIC validation' }, request);
assert.equal(
h.field(form, reason).props.value,
'SYNTHETIC independent review with evidence.',
);
const next = h.submit(form);
assert.notEqual(next.data.client_key, request.data.client_key);
});