morphit/apps/web/scripts/orderbook-hide-confirm-smoke.ts

73 lines
3.1 KiB
TypeScript

/**
* orderbook-hide-confirm-smoke — cp453
*
* THE BUG THIS GUARDS. The orderbook eyeball toggle used to call `hideAccount`
* directly on a single, unconfirmed click. The eyeball sits inside the card's
* stretched "open order" click area, so a stray click silently hid an account —
* and because the chat inbox filters hidden peers (CHAT-UI-DESIGN.md), that
* silently swallowed every chat thread with them too (a trader's messages
* vanished with no signal). Hiding must now go through a confirmation that
* warns about the chat consequence; unhide stays instant (harmless).
*
* These are source-level invariants, tamper-tested: flipping any of them red.
*/
import { readFileSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const repo = join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
const read = (rel: string): string => readFileSync(join(repo, rel), 'utf8');
let failures = 0;
function check(name: string, cond: boolean): void {
console.log(` ${cond ? '✓' : '✗'} ${name}`);
if (!cond) failures++;
}
const ob = read('apps/web/src/routes/[lang]/orderbook/+page.svelte');
const en = JSON.parse(read('apps/web/src/lib/i18n/locales/en.json')) as {
orderbook: Record<string, string>;
};
// 1. Hide is NOT fired directly by the eyeball — the toggle sets a pending
// account (opens the confirm). Unhide still fires instantly.
check(
'eyeball "hide" opens confirmation (sets accountPendingHide), does NOT call hideAccount inline',
/accountIsHidden \? unhideAccount\(o\.account\) : \(accountPendingHide = o\.account\)/.test(ob)
);
// 2. hideAccount is reachable ONLY from the ConfirmModal's onConfirm.
const hideCalls = [...ob.matchAll(/(?<!un)hideAccount\(/g)].length;
const unhideInToggle = /unhideAccount\(o\.account\)/.test(ob);
check('hideAccount( appears exactly once (the confirm handler), not on the raw toggle', hideCalls === 1);
check('unhide remains an instant, unconfirmed action', unhideInToggle);
// 3. A destructive ConfirmModal gates it, wired to accountPendingHide.
check(
'a destructive ConfirmModal is bound to accountPendingHide and calls hideAccount on confirm',
/<ConfirmModal[\s\S]*?open=\{accountPendingHide !== null\}[\s\S]*?variant="destructive"[\s\S]*?if \(accountPendingHide\) hideAccount\(accountPendingHide\)/.test(
ob
)
);
// 4. The confirm body must EDUCATE about the chat consequence — the whole point.
check(
'the hide-confirm body warns that chats are hidden too',
/hide_confirm_body/.test(ob) && /chat/i.test(en.orderbook.hide_confirm_title + en.orderbook.hide_confirm_body)
);
// 5. All three confirm keys exist (title/body/yes); cancel reuses common.cancel.
check(
'hide_confirm title/body/yes keys present + cancel reuses common.cancel',
Boolean(en.orderbook.hide_confirm_title) &&
Boolean(en.orderbook.hide_confirm_body) &&
Boolean(en.orderbook.hide_confirm_yes) &&
/cancelLabel=\{\$_\('common\.cancel'\)/.test(ob)
);
if (failures === 0) {
console.log('✓ all 6 orderbook-hide-confirm scenarios passed');
} else {
console.log(`\n✗ ${failures}/6 orderbook-hide-confirm scenarios failed`);
process.exit(1);
}