Files
Investidor-V2/tests/frontend/desk-payment-evidence.test.mjs
T

311 lines
11 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import { createRequire } from 'node:module';
import { compileFunction } from 'node:vm';
import ts from 'typescript';
const require = createRequire(import.meta.url);
function load(file, mocks) {
const code = ts.transpileModule(
fs.readFileSync(new URL(file, import.meta.url), 'utf8'),
{
compilerOptions: {
module: ts.ModuleKind.CommonJS,
jsx: ts.JsxEmit.ReactJSX,
target: ts.ScriptTarget.ES2022,
},
},
).outputText;
const module = { exports: {} };
compileFunction(code, ['require', 'module', 'exports'])(
(name) => mocks[name] ?? require(name),
module,
module.exports,
);
return module.exports;
}
function nodes(tree) {
if (Array.isArray(tree)) return tree.flatMap(nodes);
if (!tree || typeof tree !== 'object') return [];
return [tree, ...nodes(tree.props?.children)];
}
const text = (tree) =>
typeof tree === 'string'
? tree
: Array.isArray(tree)
? tree.map(text).join('')
: tree?.props
? text(tree.props.children)
: typeof tree === 'number'
? String(tree)
: '';
const document = {
id: 'link-one',
document_id: 'original-one',
file_name: 'SYNTHETIC proof.txt',
version_no: 3,
source_reference: 'SYNTHETIC document source',
status: 'active',
malware_scan_status: 'clean',
};
const payment = {
id: 'payment-one',
reference: 'SYNTHETIC reference',
amount: '25.50',
currency: 'MZN',
source_reference: 'SYNTHETIC amount purpose',
document_id: null,
version: 1,
status: 'pending',
verified_by: null,
reason: null,
};
const shared = { card: '', input: '', button: '' };
function formsHarness(file, defaults, pickerMock = {}) {
const forms = [],
calls = [];
let cursor = 0,
serial = 0,
tree,
props = defaults;
const loaded = load(file, {
'@inertiajs/react': {
useForm(initial) {
const i = cursor++;
forms[i] ??= {
data: { ...initial },
errors: {},
processing: false,
setData(key, value) {
this.data[key] = value;
},
transform(callback) {
this.transformer = callback;
},
reset(...keys) {
for (const key of keys) this.data[key] = initial[key];
},
put(url, options) {
calls.push({
url,
method: 'PUT',
data: { ...this.data },
options,
});
},
post(url, options) {
calls.push({
url,
method: 'POST',
data: this.transformer
? this.transformer(this.data)
: { ...this.data },
options,
});
},
};
return forms[i];
},
},
'@/lib/operation-key': {
createOperationKey: () => `synthetic-key-${++serial}`,
},
'@/pages/investment/shared': shared,
'./desk-payment-document-form': pickerMock,
});
const Component = loaded.default ?? loaded.RequestOperations;
function render(patch = {}) {
props = { ...props, ...patch };
cursor = 0;
tree = Component(props);
}
render();
return {
forms,
calls,
render,
all: () => nodes(tree),
text: () => text(tree),
find: (type, label) =>
nodes(tree).find(
(n) => n.type === type && (!label || text(n).includes(label)),
),
submit() {
nodes(tree)
.find((n) => n.type === 'form')
.props.onSubmit({ preventDefault() {} });
},
};
}
const proofHarness = () =>
formsHarness(
'../../resources/js/components/desk-payment-document-form.tsx',
{ requestId: 'request-one', payment, documents: [document] },
);
test('adding proof to a pending payment sends only new documentary facts and conserves financial declaration', () => {
const h = proofHarness();
h.find('select').props.onChange({ target: { value: document.id } });
h.render();
h.find('textarea').props.onChange({
target: { value: 'SYNTHETIC reason' },
});
h.render();
h.find('input').props.onChange({ target: { checked: true } });
h.render();
h.submit();
assert.match(h.calls[0].url, /pagamentos\/payment-one\/comprovativo$/);
assert.equal(h.calls[0].method, 'PUT');
assert.deepEqual(
Object.keys(h.calls[0].data).sort(),
[
'version',
'document_link_id',
'reason',
'consent',
'client_key',
].sort(),
);
assert.equal(h.calls[0].data.document_link_id, document.id);
assert.equal(h.calls[0].data.version, 1);
assert.equal(h.calls[0].data.consent, true);
assert.match(
h.text(),
/referência, o valor e a moeda já registados são conservados/,
);
assert.equal(h.all().filter((n) => n.type === 'input').length, 1);
});
test('failed retry keeps payload and operation key while editing deliberately starts a new operation', () => {
const h = proofHarness();
h.forms[0].setData('document_link_id', document.id);
h.forms[0].setData('reason', 'SYNTHETIC original reason');
h.forms[0].setData('consent', true);
h.submit();
h.submit();
assert.deepEqual(h.calls[0].data, h.calls[1].data);
const original = h.forms[0].data.client_key;
h.find('textarea').props.onChange({
target: { value: 'SYNTHETIC edited reason' },
});
h.render();
assert.notEqual(h.forms[0].data.client_key, original);
assert.equal(h.forms[0].data.consent, false);
assert.equal(h.forms[0].data.document_link_id, document.id);
h.forms[0].setData('consent', true);
h.submit();
const key = h.forms[0].data.client_key;
h.calls.at(-1).options.onSuccess();
h.render({ payment: { ...payment, version: 2 } });
assert.equal(h.forms[0].data.version, 2);
assert.equal(h.forms[0].data.reason, '');
assert.equal(h.forms[0].data.document_link_id, '');
assert.notEqual(h.forms[0].data.client_key, key);
});
test('new server version requires deliberate adoption and does not erase reason or selected proof', () => {
const h = proofHarness();
h.forms[0].setData('document_link_id', document.id);
h.forms[0].setData('reason', 'SYNTHETIC unsaved reason');
h.forms[0].setData('consent', true);
h.render({ payment: { ...payment, version: 3 } });
assert.equal(h.find('button', 'Guardar comprovativo').props.disabled, true);
h.submit();
assert.equal(h.calls.length, 0);
h.find('button', 'Usar versão actual').props.onClick();
h.render();
assert.equal(h.forms[0].data.version, 3);
assert.equal(h.forms[0].data.document_link_id, document.id);
assert.equal(h.forms[0].data.reason, 'SYNTHETIC unsaved reason');
assert.equal(h.forms[0].data.consent, false);
});
test('read-only operations preserve payment history without offering manual business forms', () => {
const Proof = () => null;
const h = formsHarness(
'../../resources/js/components/desk-internal-operations.tsx',
{
requestId: 'request-one',
owner: false,
reviewer: false,
documents: [document],
payments: [payment],
},
{ default: Proof },
);
assert.match(h.text(), /SYNTHETIC reference/);
assert.match(h.text(), /Comprovativo ainda não associado/);
assert.equal(h.all().filter((n) => n.type === 'form').length, 0);
assert.equal(h.all().filter((n) => n.type === Proof).length, 0);
h.render({ payments: [{ ...payment, document_id: document.document_id }] });
assert.match(h.text(), /metadados da associação não capturados à época/);
});
test('only pending or disputed payment offers proof correction and creation uses exact link without copying amount provenance', () => {
const Proof = () => null;
const h = formsHarness(
'../../resources/js/components/desk-internal-operations.tsx',
{
requestId: 'request-one',
owner: true,
reviewer: false,
documents: [document],
payments: [
payment,
{ ...payment, id: 'verified', status: 'internal_verified' },
{ ...payment, id: 'issue', status: 'internal_issue' },
],
},
{ default: Proof },
);
assert.equal(h.all().filter((n) => n.type === Proof).length, 2);
const selector = h
.all()
.find(
(n) =>
n.type === 'select' &&
n.props.value === h.forms[0].data.document_link_id,
);
assert.ok(
nodes(selector).some(
(n) => n.type === 'option' && n.props.value === document.id,
),
);
selector.props.onChange({ target: { value: document.id } });
h.render();
assert.equal(h.forms[0].data.document_link_id, document.id);
assert.equal(h.forms[0].data.source_reference, '');
assert.equal(h.forms[0].data.amount, '');
});
test('historical evidence shows the frozen file version and separates documentary reference from amount purpose', () => {
const h = formsHarness(
'../../resources/js/components/desk-internal-operations.tsx',
{
requestId: 'request-one',
owner: false,
reviewer: false,
documents: [],
payments: [
{
...payment,
document_id: document.document_id,
document_evidence: {
link_id: document.id,
file_name: document.file_name,
document_version: 3,
source_reference: document.source_reference,
valid_until: '2028-01-02',
},
},
],
},
{ default: () => null },
);
assert.match(h.text(), /Fonte do valor: SYNTHETIC amount purpose/);
assert.match(
h.text(),
/SYNTHETIC proof.txt.*versão 3.*SYNTHETIC document source.*2028-01-02/,
);
});