import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import { compileFunction } from 'node:vm'; import ts from 'typescript'; await test('blocked browser storage cannot prevent authentication or clearing a submitted interest', () => { const source = fs.readFileSync( new URL( '../../resources/js/hooks/use-interest-draft.ts', import.meta.url, ), 'utf8', ); const output = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, }, }).outputText; const module = { exports: {} }; let destination; const storage = { getItem() { throw new Error('blocked'); }, setItem() { throw new Error('blocked'); }, removeItem() { throw new Error('blocked'); }, }; compileFunction(output, [ 'require', 'module', 'exports', 'sessionStorage', 'window', 'location', ])( (name) => name === 'react' ? { useState: (init) => [init(), () => {}], useEffect: (effect) => effect(), } : { newSubmissionKey: () => 'synthetic-key' }, module, module.exports, storage, { location: { assign: (url) => { destination = url; }, }, }, { pathname: '/oportunidades/teste', search: '?sector=1' }, ); const draft = module.exports.useInterestDraft('synthetic', { name: 'Synthetic', email: 'synthetic@example.invalid', }); assert.equal(draft.key, 'synthetic-key'); assert.doesNotThrow(() => draft.clear()); assert.doesNotThrow(() => draft.authenticate()); assert.equal( destination, '/participar/entrar?return=%2Foportunidades%2Fteste%3Fsector%3D1', ); }); test('reused interest hook isolates opportunities, retains deliberate edits and restores after reload', () => { const source = fs.readFileSync( new URL( '../../resources/js/hooks/use-interest-draft.ts', import.meta.url, ), 'utf8', ); const output = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, }, }).outputText; const saved = new Map(); let sequence = 0; function mount(storage = saved) { let value, changed, effect; const module = { exports: {} }; compileFunction(output, [ 'require', 'module', 'exports', 'sessionStorage', 'window', 'location', ])( (name) => name === 'react' ? { useState(init) { value ??= init(); return [ value, (next) => { value = typeof next === 'function' ? next(value) : next; changed = true; }, ]; }, useEffect(callback) { effect = callback; }, } : { newSubmissionKey: () => 'synthetic-' + ++sequence }, module, module.exports, { getItem: (key) => storage.get(key) ?? null, setItem: (key, data) => storage.set(key, data), removeItem: (key) => storage.delete(key), }, { location: { assign() {} } }, { pathname: '/negocios/a', search: '?province_id=p' }, ); return (name, initial = { message: 'initial ' + name }) => { changed = false; let result = module.exports.useInterestDraft(name, initial); // React discards a render-phase reset and renders the new scoped state. if (changed) result = module.exports.useInterestDraft(name, initial); effect(); return result; }; } const render = mount(); const a = render('business:A'); a.setForm({ message: 'deliberate A' }); render('business:A'); const b = render('business:B'); assert.equal(b.form.message, 'initial business:B'); assert.notEqual(a.key, b.key); b.setForm({ message: 'deliberate B' }); render('business:B'); assert.equal(render('business:A').form.message, 'deliberate A'); assert.equal(mount()('business:B').form.message, 'deliberate B'); assert.equal( mount(new Map())('business:A').form.message, 'initial business:A', ); assert.equal( JSON.parse(saved.get('investemoz-interest:business:A')).form.message, 'deliberate A', ); });