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 { renderToStaticMarkup } from 'react-dom/server'; import ts from 'typescript'; const require = createRequire(import.meta.url); function load(file, mocks) { const output = 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(output, ['require', 'module', 'exports'])( (name) => mocks[name] ?? require(name), module, module.exports, ); return module.exports.default; } function nodes(tree) { if (!tree || typeof tree !== 'object') return []; if (Array.isArray(tree)) return tree.flatMap(nodes); return [tree, ...nodes(tree.props?.children)]; } await test('the quick search has a native GET destination and submits the actual input value even after browser autofill', () => { let sent, edited; const Hero = load('../../resources/js/components/portal-hero.tsx', { react: { useState: (initial) => [initial, () => {}], useEffect() {} }, '@inertiajs/react': { Link: 'a', router: { get: (url, data) => { sent = { url, data }; }, }, }, 'lucide-react': { ArrowRight: () => null, Search: () => null }, }); const tree = Hero({ query: 'stale rendered value', setQuery: (value) => { edited = value; }, }); const form = nodes(tree).find((node) => node.type === 'form'); const input = nodes(tree).find( (node) => node.type === 'input' && node.props.name === 'q', ); assert.equal(form.props.action, '/pesquisa'); assert.equal(form.props.method, 'get'); assert.equal(input.props.maxLength, 120); input.props.onChange({ target: { value: 'plantio de algodao' } }); assert.equal(edited, 'plantio de algodao'); const original = globalThis.FormData; try { globalThis.FormData = class { constructor(element) { this.element = element; } get(key) { assert.equal(key, 'q'); return this.element.value; } }; let prevented = false; form.props.onSubmit({ preventDefault() { prevented = true; }, currentTarget: { value: ' plantio de algodao ' }, }); assert.equal(prevented, true); assert.deepEqual(sent, { url: '/pesquisa', data: { q: 'plantio de algodao' }, }); } finally { globalThis.FormData = original; } const html = renderToStaticMarkup(tree); assert.ok(html.includes('Pesquisa rápida no InvesteMoz')); assert.ok(html.includes('action="/pesquisa"')); assert.ok(html.includes('Pesquisar')); }); await test('related processing fiches are explicitly distinct from the requested cultivation and disappear during pending or failed searches', () => { const Related = load( '../../resources/js/components/opportunity-related-results.tsx', { '@inertiajs/react': { Link: 'a' } }, ); const related = { query: 'plantio de algodao', subject: 'algodao', href: '/oportunidades?sector=qa&q=algodao', items: [ { id: 1, slug: 'synthetic-processing', title: 'Synthetic processing', summary: 'Descaroçamento e transformação de algodão.', }, ], }; const props = { related, loading: false, error: '', total: 0 }; const html = renderToStaticMarkup(Related(props)); assert.ok( html.includes('não correspond') || html.includes( 'Não encontrámos fichas que correspondam a todos os termos', ), ); assert.ok(html.includes('outras etapas da cadeia')); assert.ok(html.includes('Descaroçamento e transformação de algodão')); assert.ok(html.includes('q=plantio+de+algodao')); assert.ok(html.includes('Ver a pesquisa relacionada')); for (const state of [ { loading: true }, { error: 'failure' }, { total: 1 }, { related: null }, ]) { assert.equal(Related({ ...props, ...state }), null); } });