Files
Investidor-V2/tests/frontend/opportunity-technical-incidents.test.mjs
T

355 lines
12 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';
import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
const require = createRequire(import.meta.url),
module = { exports: {} };
const output = ts.transpileModule(
fs.readFileSync(
new URL(
'../../resources/js/components/opportunity-technical-incidents.tsx',
import.meta.url,
),
'utf8',
),
{
compilerOptions: {
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES2022,
jsx: ts.JsxEmit.ReactJSX,
},
},
).outputText;
compileFunction(output, ['require', 'module', 'exports'])(
(name) =>
name === '@/lib/technical-incident-labels'
? load('resources/js/lib/technical-incident-labels.ts')
: require(name),
module,
module.exports,
);
const render = (incidents) =>
renderToStaticMarkup(
React.createElement(module.exports.default, { incidents }),
);
const base = {
reference: 'SYNTHETIC-reference',
operation: 'submit',
version: 4,
occurred_at: '2026-11-03',
error_code: 'database_failure',
};
test('no incident produces no empty form or duplicate question', () =>
assert.equal(render([]), ''));
test('the reader identifies the attempt and support scope without a business retry or decision', () => {
const html = render([base]);
assert.match(html, /Submissão para validação/);
assert.match(html, /versão observada 4/);
assert.match(html, /SYNTHETIC-reference/);
assert.match(html, /Consulte o estado actual antes de repetir/);
assert.match(html, /Suporte técnico consulta os incidentes/);
assert.doesNotMatch(html, /<button|<form|href=/);
});
function load(path, mocks = {}) {
const result = { exports: {} };
const code = ts.transpileModule(
fs.readFileSync(new URL('../../' + path, import.meta.url), 'utf8'),
{
compilerOptions: {
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES2022,
jsx: ts.JsxEmit.ReactJSX,
},
},
).outputText;
compileFunction(code, ['require', 'module', 'exports'])(
(name) =>
mocks[name] ??
(name === '@/components/technical-incident-notice'
? { default: () => null }
: undefined) ??
(name.startsWith('@/')
? load('resources/js/' + name.slice(2) + '.ts')
: require(name)),
result,
result.exports,
);
return result.exports;
}
test('the actual profile navigation exposes the support queue only through the server capability', () => {
const { profileLinks } = load(
'resources/js/components/profile-navigation.tsx',
{ '@inertiajs/react': { Link: 'a', usePage: () => ({ props: {} }) } },
);
const access = {
mine: null,
create: null,
request: '/perfil/promotor',
review: null,
administration: null,
};
assert.equal(
profileLinks(access).some(
(link) => link.href === '/suporte-tecnico/incidentes',
),
false,
);
assert.equal(
profileLinks({
...access,
technicalSupport: '/suporte-tecnico/incidentes',
}).find((link) => link.href === '/suporte-tecnico/incidentes').title,
'Suporte técnico',
);
});
test('the actual queue presents minimal metadata and an honest empty state without private process links', () => {
const Queue = load('resources/js/pages/profiles/technical-support.tsx', {
'@inertiajs/react': {
Link: ({ href, children, ...rest }) =>
React.createElement('a', { href, ...rest }, children),
},
'../management/shared': {
Management: ({ children }) =>
React.createElement('main', null, children),
Pagination: () => null,
},
}).default;
const page = (data) =>
renderToStaticMarkup(
React.createElement(Queue, {
incidents: {
data,
total: data.length,
current_page: 1,
last_page: 1,
prev_page_url: null,
next_page_url: null,
},
}),
);
assert.match(page([]), /Não existem incidentes disponíveis neste âmbito/);
const html = page([base]);
assert.match(html, /SYNTHETIC-reference/);
assert.match(html, /não concede acesso aos processos ou documentos/);
assert.doesNotMatch(html, /minhas-oportunidades|<form|<button/);
});
test('the support queue exposes the authorised treatment link and preserves its state and page', () => {
const Queue = load('resources/js/pages/profiles/technical-support.tsx', {
'@inertiajs/react': {
Link: ({ href, children, ...rest }) =>
React.createElement('a', { href, ...rest }, children),
},
'../management/shared': {
Management: ({ children }) =>
React.createElement('main', null, children),
Pagination: () => null,
},
}).default;
const html = renderToStaticMarkup(
React.createElement(Queue, {
filters: { status: 'resolved' },
incidents: {
data: [
{
...base,
details_url: '/suporte-tecnico/incidentes/one',
handling: {
status: 'resolved',
assignee_name: 'SYNTHETIC support',
},
},
],
total: 1,
current_page: 3,
last_page: 3,
prev_page_url: null,
next_page_url: null,
},
}),
);
assert.ok(
html.includes(
'href="/suporte-tecnico/incidentes/one?page=3&amp;status=resolved"',
),
);
assert.match(html, /Estado técnico: Resolvido/);
assert.match(html, /aria-current="page"/);
assert.doesNotMatch(html, /minhas-oportunidades/);
});
test('the existing JSON transport preserves the incident reference and never repeats a failed write', async () => {
const transport = load('resources/js/lib/profile-json.ts');
const oldFetch = globalThis.fetch,
oldDocument = globalThis.document;
let calls = 0;
globalThis.document = { cookie: 'XSRF-TOKEN=SYNTHETIC' };
globalThis.fetch = async () => {
calls++;
return {
ok: false,
status: 503,
headers: { get: () => null },
json: async () => ({
message: 'SYNTHETIC incident reference: one',
reference: 'one',
incident_recorded: true,
}),
};
};
try {
await assert.rejects(
transport.profileJson('/minhas-oportunidades/1/workflow', {
action: 'submit',
}),
/SYNTHETIC incident reference: one/,
);
assert.equal(calls, 1);
} finally {
globalThis.fetch = oldFetch;
globalThis.document = oldDocument;
}
});
test('publication is distinct and untrusted reference text remains escaped', () => {
const html = render([
{
...base,
operation: 'publish',
error_code: 'workflow_unavailable',
reference: '<img src=x onerror=alert(1)>',
},
]);
assert.match(html, /Publicação/);
assert.match(html, /Falha técnica/);
assert.doesNotMatch(html, /<img/);
assert.match(html, /&lt;img/);
});
for (const [operation, label] of [
['upload_document', 'Carregamento de documento'],
['upload_image', 'Carregamento de imagem'],
['prepare_image', 'Preparação de imagens WebP'],
]) {
test('the reader distinguishes ' + operation + ' from publication', () => {
const html = render([{ ...base, operation }]);
assert.ok(html.includes(label));
assert.doesNotMatch(html, />Publicação/);
});
}
test('the support link exposes only a valid count alongside the server capability', () => {
const { profileLinks } = load(
'resources/js/components/profile-navigation.tsx',
{ '@inertiajs/react': { Link: 'a', usePage: () => ({ props: {} }) } },
);
const access = {
request: '/perfil/promotor',
technicalSupport: '/suporte-tecnico/incidentes',
};
assert.match(
profileLinks({ ...access, technicalSupportUnread: 3 }).find(
(link) => link.href === access.technicalSupport,
).title,
/3 por consultar/,
);
for (const count of [null, -1, 0, 1.2, Infinity, '4'])
assert.equal(
profileLinks({ ...access, technicalSupportUnread: count }).find(
(link) => link.href === access.technicalSupport,
).title,
'Suporte técnico',
);
assert.equal(
profileLinks({
request: access.request,
technicalSupportUnread: 3,
}).some((link) => link.href === access.technicalSupport),
false,
);
});
test('an unknown technical operation is not labelled as a publication', () => {
const html = render([{ ...base, operation: 'unknown_operation' }]);
assert.match(html, /Operação técnica não identificada/);
assert.doesNotMatch(html, />Publicação/);
});
for (const [code, label] of [
['scan_dispatch_unconfirmed', 'Encaminhamento da análise sem confirmação.'],
['scan_inconclusive', 'Análise de segurança inconclusiva.'],
['scan_worker_failed', 'Falha na execução da análise de segurança.'],
[
'scan_cleanup_unconfirmed',
'Limpeza do ficheiro temporário por confirmar.',
],
]) {
test(
'the scan reader distinguishes ' +
code +
' from a failed resource save',
() => {
const html = render([
{ ...base, operation: 'scan_document', error_code: code },
]);
assert.ok(html.includes(label));
assert.match(html, /Análise de segurança de documento/);
assert.match(html, /O recurso já foi registado/);
assert.doesNotMatch(html, />Publicação/);
},
);
}
test('the scan reader never renders an unrecognized internal error code', () => {
const html = render([
{
...base,
operation: 'scan_document',
error_code: 'PRIVATE INTERNAL TOKEN',
},
]);
assert.doesNotMatch(html, /PRIVATE INTERNAL/);
assert.match(html, /Falha técnica durante a operação/);
});
test('unread and technical status filters preserve each other and the detail return context', () => {
const Queue = load('resources/js/pages/profiles/technical-support.tsx', {
'@inertiajs/react': {
Link: ({ children, ...rest }) =>
React.createElement('a', rest, children),
},
'../management/shared': {
Management: ({ children }) =>
React.createElement('main', null, children),
Pagination: () => null,
},
}).default;
const html = renderToStaticMarkup(
React.createElement(Queue, {
filters: { status: 'resolved', unread: true },
incidents: {
data: [
{ ...base, details_url: '/suporte-tecnico/incidentes/one' },
],
current_page: 2,
total: 1,
last_page: 2,
},
}),
);
assert.ok(
html.includes(
'href="/suporte-tecnico/incidentes?status=open&amp;unread=1"',
),
);
assert.ok(
html.includes('href="/suporte-tecnico/incidentes?status=resolved"'),
);
assert.ok(
html.includes(
'href="/suporte-tecnico/incidentes/one?page=2&amp;status=resolved&amp;unread=1"',
),
);
});