Files
Investidor-V2/tests/frontend/education-work-queue.test.mjs

165 lines
5.1 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),
Empty = () => null;
const mocks = {
react: React,
'@inertiajs/react': {
Link: ({ href, children }) =>
React.createElement('a', { href }, children),
router: {},
useForm: (data) => ({
data,
errors: {},
processing: false,
isDirty: false,
}),
},
'@/lib/portal-api': {
newSubmissionKey: () => '00000000-0000-4000-8000-000000000001',
},
'@/components/education-submitted-snapshot': { default: Empty },
'@/components/investment-territory': { TerritoryFields: Empty },
'../management/shared': {
Management: ({ children }) =>
React.createElement('main', null, children),
Field: ({ label, children }) =>
React.createElement('label', null, label, children),
Pagination: Empty,
control: '',
button: '',
},
};
const output = ts.transpileModule(
fs.readFileSync(
new URL(
'../../resources/js/pages/education/index.tsx',
import.meta.url,
),
'utf8',
),
{
compilerOptions: {
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES2022,
jsx: ts.JsxEmit.ReactJSX,
},
},
).outputText;
const module = { exports: {} };
compileFunction(output, ['require', 'module', 'exports'])(
(name) => mocks[name] ?? require(name),
module,
module.exports,
);
const Index = module.exports.default;
const counts = {
total: 3,
submitted: 1,
reviewed: 1,
rejected: 0,
expired: 1,
to_review: 2,
};
const group = (data) => ({
data,
total: data.length,
current_page: 1,
last_page: 1,
links: [],
});
const base = {
today: '2026-11-03',
territories: [],
projects: [],
providers: [],
courses: [],
occupations: [],
skills: [],
draftsAvailable: false,
ownDrafts: null,
filters: { scope: 'all' },
workQueue: {
actor_id: 1,
drafts: 1,
demands: counts,
capacities: { ...counts, total: 1, submitted: 0, to_review: 4 },
},
indicators: {
demand_records: 42,
capacity_records: 17,
pending_demands: 9,
expired_demands: 4,
},
demands: group([
{
id: 'one',
qualification: 'SYNTHETIC qualification',
quantity: 1000,
status: 'submitted',
version_no: 1,
valid_until: '2027-12-31',
period_start: '2027-01-01',
period_end: '2027-06-30',
source: 'SYNTHETIC source',
can_review: false,
review_unavailable: 'self',
details_url: '/management/education/demands/one?scope=mine',
},
]),
capacities: group([]),
};
const render = (patch) =>
renderToStaticMarkup(React.createElement(Index, { ...base, ...patch }));
test('personal record counts coexist with the unchanged global indicators and retain separate categories', () => {
const html = render();
assert.match(html, /O meu acompanhamento/);
assert.match(html, /Declarações de procura:.*?<strong>42/s);
assert.match(html, /Submetidas por mim: 3/);
assert.match(html, /Submetidas por mim: 1/);
assert.doesNotMatch(html, /Submetidas por mim: 1000/);
assert.match(html, /Disponíveis para a minha revisão independente: 2/);
assert.match(html, /Disponíveis para a minha revisão independente: 4/);
});
test('a declaration links to its detailed context and the list no longer asks for repeated review forms', () => {
const html = render();
assert.ok(
html.includes('href="/management/education/demands/one?scope=mine"'),
);
assert.match(html, /Consultar declaração/);
assert.match(html, /a revisão cabe a outro gestor/);
assert.doesNotMatch(
html,
/Guardar decisão|Justificação e evidência da revisão/,
);
});
test('the independent review scope hides an inapplicable status question and preserves the normal filters', () => {
const html = render({
filters: { scope: 'review', q: 'SYNTHETIC', status: '' },
});
assert.match(html, /value="review" selected/);
assert.doesNotMatch(html, /<label>Estado/);
assert.match(html, /Qualificação/);
assert.match(html, /SYNTHETIC/);
assert.match(render({ filters: { scope: 'mine' } }), /<label>Estado/);
});
test('an unavailable draft count is not presented as zero and declaration text is escaped', () => {
const html = render({
workQueue: { ...base.workQueue, drafts: null },
demands: group([
{
...base.demands.data[0],
qualification: '<img src=x onerror=alert(1)>',
},
]),
});
assert.doesNotMatch(html, /Rascunhos privados por concluir: 0|<img/);
assert.ok(html.includes('&lt;img'));
});