153 lines
5.3 KiB
JavaScript
153 lines
5.3 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import { compileFunction } from 'node:vm';
|
|
import { createRequire } from 'node:module';
|
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
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,
|
|
target: ts.ScriptTarget.ES2022,
|
|
jsx: ts.JsxEmit.ReactJSX,
|
|
},
|
|
},
|
|
).outputText;
|
|
const module = { exports: {} };
|
|
compileFunction(code, ['require', 'module', 'exports'])(
|
|
(key) => mocks[key] ?? require(key),
|
|
module,
|
|
module.exports,
|
|
);
|
|
return module.exports;
|
|
}
|
|
const lib = load('../../resources/js/lib/product-usage.ts');
|
|
const child = load('../../resources/js/components/search-usage-report.tsx', {
|
|
'@/lib/product-usage': lib,
|
|
'@/pages/investment/shared': { card: '' },
|
|
});
|
|
const search = {
|
|
installed: true,
|
|
enabled_now: true,
|
|
applicable: true,
|
|
from: '2026-11-02',
|
|
to: '2026-11-03',
|
|
timezone: 'UTC',
|
|
read_at: '2026-11-03T12:00:00Z',
|
|
definition_version: 'SYNTHETIC-v1',
|
|
available_definitions: ['SYNTHETIC-v1', 'SYNTHETIC-v2'],
|
|
definition_conflict_now: false,
|
|
responses: 2,
|
|
zero_responses: 0,
|
|
zero_rate: 0,
|
|
channels: [
|
|
{
|
|
id: 'known',
|
|
label: 'SYNTHETIC archived <edition>',
|
|
responses: 2,
|
|
zero_responses: 0,
|
|
zero_rate: 0,
|
|
first_recorded_at: '2026-11-02T10:00:00Z',
|
|
last_recorded_at: '2026-11-02T11:00:00Z',
|
|
definition_versions: ['SYNTHETIC-v1'],
|
|
},
|
|
{
|
|
id: 'unknown',
|
|
label: 'SYNTHETIC unobserved channel',
|
|
responses: null,
|
|
zero_responses: null,
|
|
zero_rate: null,
|
|
first_recorded_at: null,
|
|
last_recorded_at: null,
|
|
definition_versions: [],
|
|
},
|
|
],
|
|
limits: ['SYNTHETIC recorded subset only'],
|
|
exclusions: ['SYNTHETIC autocomplete excluded'],
|
|
completeness: 'unverified_best_effort',
|
|
temporal_basis: 'daily_aggregate_at_report_snapshot',
|
|
};
|
|
test('daily capture shows measured zero separately from missing channel data and discloses its actual unit and coverage', () => {
|
|
const html = renderToStaticMarkup(child.default({ search }));
|
|
assert.match(html, /0 %/);
|
|
assert.match(html, /Sem medição/);
|
|
assert.match(html, /Cobertura parcial/);
|
|
assert.match(html, /dia actual é parcial/);
|
|
assert.match(html, /não há corte por fracção de segundo/);
|
|
assert.match(
|
|
html,
|
|
/pessoas, bots e pesquisas únicas não são identificados/,
|
|
);
|
|
assert.match(html, /SYNTHETIC archived <edition>/);
|
|
assert.match(html, /SYNTHETIC autocomplete excluded/);
|
|
const missing = renderToStaticMarkup(
|
|
child.default({
|
|
search: {
|
|
...search,
|
|
installed: false,
|
|
enabled_now: false,
|
|
applicable: false,
|
|
responses: null,
|
|
zero_responses: null,
|
|
zero_rate: null,
|
|
definition_conflict_now: true,
|
|
},
|
|
}),
|
|
);
|
|
assert.match(missing, /Ainda não há dados de recolha/);
|
|
assert.match(missing, /histórico registado mantém-se/);
|
|
assert.match(missing, /não têm associação comprovada ao serviço/);
|
|
assert.match(missing, /configuração diferente com o mesmo identificador/);
|
|
assert.match(missing, /Respostas: Sem medição/);
|
|
});
|
|
test('the applied collection edition survives the GET filter and export and has a separate time basis from desk events', () => {
|
|
const report = {
|
|
definition_version: 'SYNTHETIC report',
|
|
generated_at: '2026-11-03T12:00:00Z',
|
|
observed_before: '2026-11-03T12:00:00Z',
|
|
timezone: 'UTC',
|
|
filters: {
|
|
from: '2026-11-02',
|
|
to: '2026-11-03',
|
|
service_code: null,
|
|
search_definition: 'SYNTHETIC-v1',
|
|
},
|
|
services: [],
|
|
coverage: {},
|
|
metrics: [],
|
|
unmeasured: [],
|
|
limits: [],
|
|
fingerprint: 'a'.repeat(64),
|
|
read_consistency: 'repeatable_read',
|
|
search,
|
|
};
|
|
const page = load('../../resources/js/pages/management/product-usage.tsx', {
|
|
'@inertiajs/react': {
|
|
Link: 'a',
|
|
usePage: () => ({ props: { errors: {} } }),
|
|
},
|
|
'@/pages/investment/shared': {
|
|
Frame: 'main',
|
|
card: '',
|
|
input: '',
|
|
button: '',
|
|
},
|
|
'@/lib/product-usage': lib,
|
|
'@/components/search-usage-report': child,
|
|
}).default;
|
|
const html = renderToStaticMarkup(page({ report }));
|
|
assert.match(html, /name="search_definition"/);
|
|
assert.match(html, /<option(?=[^>]*value="SYNTHETIC-v1")(?=[^>]*selected)/);
|
|
assert.match(html, /Eventos do Balcão anteriores/);
|
|
assert.match(html, /Pesquisas usam as contagens diárias/);
|
|
assert.deepEqual(JSON.parse(lib.usageExport(report)).search, search);
|
|
assert.equal(
|
|
JSON.parse(lib.usageExport(report)).filters.search_definition,
|
|
'SYNTHETIC-v1',
|
|
);
|
|
});
|