Files
Investidor-V2/tests/frontend/partnership-agreements.test.mjs
T

258 lines
9.1 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { harness, props, text } from './helpers/partnership-room.mjs';
test('an uncertain agreement action exposes recovery of the frozen attempt', () => {
const h = harness(props());
h.change('agreement', 'Motivo da ação', 'SYNTHETIC reason');
const request = h.click('Confirmar pela minha parte');
h.fail(request);
assert.ok(h.button('Recuperar a mesma acção'));
});
function ack(h, request, patch = {}) {
const command = request.data;
const statuses = {
record: 'agreement_recorded',
confirm: 'agreement_recorded',
start: 'execution',
complete: 'closed',
cancel: 'cancelled',
renew: 'negotiation',
};
const agreement = { ...h.props.room.agreement };
if (command.action === 'record') {
agreement.title = command.title.trim();
agreement.terms = command.terms.trim();
agreement.confirmations = {};
} else if (command.action === 'confirm') {
agreement.confirmations = {
...agreement.confirmations,
[h.props.agreementParty]: {
actor_id: h.props.agreementActorId,
date: '2026-11-03',
reason: command.reason.trim(),
},
};
}
return {
...h.props,
room: {
...h.props.room,
agreement,
version: command.version + 1,
status: statuses[command.action],
...patch,
},
agreementCommands: [
{
key: command.client_key,
action: command.action,
version: command.version + 1,
status: patch.status ?? statuses[command.action],
party:
command.action === 'confirm'
? h.props.agreementParty
: null,
},
],
};
}
const adopt = 'Usar este contexto e conservar as alterações escolhidas';
const recover = 'Recuperar a mesma acção';
const refresh = 'Comparar com os dados actuais da sala';
function prepared() {
const h = harness(props());
h.change('agreement', 'Motivo da ação', 'SYNTHETIC decision');
return h;
}
test('confirmation recovery freezes context and reason while preserving later preparation', () => {
const h = prepared();
h.change(
'agreement',
'Título do instrumento',
'SYNTHETIC unrecorded title',
);
const first = h.click('Confirmar pela minha parte');
const frozen = { ...first.data };
assert.equal(first.data.partnership_version, 4);
assert.equal(first.data.interest_version, 3);
assert.equal(first.data.title, undefined);
h.fail(first);
h.change('agreement', 'Motivo da ação', 'SYNTHETIC next reason');
const repeated = h.click(recover);
assert.deepEqual(repeated.data, frozen);
h.success(ack(h, repeated), repeated);
assert.equal(
h.field('agreement', 'Motivo da ação').props.value,
'SYNTHETIC next reason',
);
assert.equal(
h.field('agreement', 'Título do instrumento').props.value,
'SYNTHETIC unrecorded title',
);
assert.equal(h.button(recover), undefined);
});
test('record recovery preserves terms written after the original command', () => {
const h = prepared();
h.change(
'agreement',
'Condições e plano de valor',
'SYNTHETIC submitted terms',
);
const first = h.click('Registar versão do acordo');
h.fail(first);
h.change('agreement', 'Condições e plano de valor', 'SYNTHETIC next terms');
const repeated = h.click(recover);
assert.equal(repeated.data.terms, 'SYNTHETIC submitted terms');
h.success(ack(h, repeated), repeated);
assert.equal(
h.field('agreement', 'Condições e plano de valor').props.value,
'SYNTHETIC next terms',
);
assert.equal(h.field('agreement', 'Motivo da ação').props.value, '');
});
test('a terminal cancellation still permits recovery of the same command', () => {
const h = prepared();
const first = h.click('Cancelar conexão com motivo');
h.fail(first);
const terminal = ack(h, first);
h.render(terminal);
assert.equal(h.button(recover).props.disabled, false);
const repeated = h.click(recover);
assert.deepEqual(repeated.data, first.data);
h.success(terminal, repeated);
assert.equal(h.button(recover), undefined);
});
test('a fresh read can acknowledge a committed attempt without another write', () => {
const h = prepared();
const first = h.click('Confirmar pela minha parte');
h.fail(first);
h.click(refresh);
h.refreshed(ack(h, first));
assert.equal(h.sent.length, 1);
assert.equal(h.button(recover), undefined);
assert.equal(h.field('agreement', 'Motivo da ação').props.value, '');
});
test('a recovered command followed by a bilateral decision requires explicit review', () => {
const h = prepared();
const first = h.click('Confirmar pela minha parte');
h.fail(first);
const repeated = h.click(recover);
const later = ack(h, repeated, {
version: first.data.version + 2,
status: 'agreed',
});
later.room.agreement.confirmations.candidate = {
actor_id: 2,
date: '2026-11-03',
reason: 'SYNTHETIC other decision',
};
later.agreementCommands[0].status = 'agreement_recorded';
h.success(later, repeated);
assert.ok(h.button(adopt));
assert.equal(h.button('Iniciar acompanhamento').props.disabled, true);
h.click(adopt);
h.change('agreement', 'Motivo da ação', 'SYNTHETIC start after review');
assert.equal(h.button('Iniciar acompanhamento').props.disabled, false);
});
test('a changed proposal with the same room version requires context adoption', () => {
const h = prepared();
h.render({
...h.props,
partnership: { ...h.props.partnership, version: 5 },
});
assert.equal(h.button('Confirmar pela minha parte').props.disabled, true);
h.click(adopt);
const request = h.click('Confirmar pela minha parte');
assert.equal(request.data.partnership_version, 5);
assert.equal(request.data.version, 2);
});
test('an exact command receipt with a newer parent context still requires review', () => {
const h = prepared();
const first = h.click('Confirmar pela minha parte');
const next = ack(h, first);
next.interest = { ...next.interest, version: 4 };
h.success(next, first);
assert.ok(h.button(adopt));
assert.equal(
h.button('Actualizar confirmação da minha parte').props.disabled,
true,
);
h.click(adopt);
h.change('agreement', 'Motivo da ação', 'SYNTHETIC updated context');
assert.equal(
h.button('Actualizar confirmação da minha parte').props.disabled,
false,
);
});
test('missing own receipt or an incompatible confirmation stamp never clears a draft', () => {
for (const wrong of ['receipt', 'stamp']) {
const h = prepared();
const first = h.click('Confirmar pela minha parte');
const next = ack(h, first);
if (wrong === 'receipt') next.agreementCommands = [];
else next.room.agreement.confirmations.proponent.actor_id = 9;
h.success(next, first);
assert.equal(
h.field('agreement', 'Motivo da ação').props.value,
'SYNTHETIC decision',
);
assert.ok(h.button(recover));
assert.equal(h.button(adopt).props.disabled, true);
}
});
test('lost write authority blocks recovery and another actor does not inherit its draft', () => {
const h = prepared();
const first = h.click('Confirmar pela minha parte');
h.fail(first);
h.fail(first, 403);
assert.equal(h.button(recover).props.disabled, true);
h.render({
...h.props,
actorId: 2,
agreementActorId: 2,
agreementParty: 'candidate',
agreementCommands: [],
});
h.success(ack(h, first), first);
assert.equal(h.field('agreement', 'Motivo da ação').props.value, '');
assert.equal(h.button(recover), undefined);
});
test('a current confirmation is identified as an update rather than another party', () => {
const initial = props();
initial.room.agreement.confirmations.proponent = {
actor_id: 1,
reason: 'SYNTHETIC old',
date: '2026-11-02',
};
const h = harness(initial);
assert.ok(h.button('Actualizar confirmação da minha parte'));
assert.equal(h.button('Confirmar pela minha parte'), undefined);
assert.match(text(h.tree), /proponente/i);
});
test('a callback from an abandoned attempt does not freeze its replacement', () => {
const h = prepared();
const first = h.click('Confirmar pela minha parte');
h.fail(first);
h.click(refresh);
h.refreshed(h.props);
h.click(adopt);
const second = h.click('Confirmar pela minha parte');
assert.notEqual(second.data.client_key, first.data.client_key);
h.fail(first);
h.success(ack(h, second), second);
assert.equal(h.button(recover), undefined);
assert.equal(h.field('agreement', 'Motivo da ação').props.value, '');
});