aboutsummaryrefslogtreecommitdiffstats
path: root/src/params/uuid.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-01-27 10:47:57 -0800
committerAdam Soltys <[email protected]>2026-01-27 10:47:57 -0800
commit685d085596a1a20d2b5680cf8000313173bbe6fd (patch)
tree314e0563a932e2f15f407d125b955a6620642da5 /src/params/uuid.js
parent4a752a834b349b4aa8841cc5b3cab09854a5dca3 (diff)
downloadcoinos-ui-685d085596a1a20d2b5680cf8000313173bbe6fd.tar.gz
coinos-ui-685d085596a1a20d2b5680cf8000313173bbe6fd.zip
fix import
Diffstat (limited to 'src/params/uuid.js')
0 files changed, 0 insertions, 0 deletions
r: #555 } /* Name.Decorator */ .highlight .ne { color: #B06; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #06B; font-weight: bold } /* Name.Function */ .highlight .nl { color: #369; font-style: italic } /* Name.Label */ .highlight .nn { color: #B06; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #369; font-weight: bold } /* Name.Property */ .highlight .nt { color: #B06; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #369 } /* Name.Variable */ .highlight .ow { color: #080 } /* Operator.Word */ .highlight .w { color: #BBB } /* Text.Whitespace */ .highlight .mb { color: #00D; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #00D; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #00D; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #00D; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #00D; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #D20; background-color: #FFF0F0 } /* Literal.String.Affix */ .highlight .sb { color: #D20; background-color: #FFF0F0 } /* Literal.String.Backtick */ .highlight .sc { color: #D20; background-color: #FFF0F0 } /* Literal.String.Char */ .highlight .dl { color: #D20; background-color: #FFF0F0 } /* Literal.String.Delimiter */ .highlight .sd { color: #D20; background-color: #FFF0F0 } /* Literal.String.Doc */ .highlight .s2 { color: #D20; background-color: #FFF0F0 } /* Literal.String.Double */ .highlight .se { color: #04D; background-color: #FFF0F0 } /* Literal.String.Escape */ .highlight .sh { color: #D20; background-color: #FFF0F0 } /* Literal.String.Heredoc */ .highlight .si { color: #33B; background-color: #FFF0F0 } /* Literal.String.Interpol */ .highlight .sx { color: #2B2; background-color: #F0FFF0 } /* Literal.String.Other */ .highlight .sr { color: #080; background-color: #FFF0FF } /* Literal.String.Regex */ .highlight .s1 { color: #D20; background-color: #FFF0F0 } /* Literal.String.Single */ .highlight .ss { color: #A60; background-color: #FFF0F0 } /* Literal.String.Symbol */ .highlight .bp { color: #038 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #06B; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #369 } /* Name.Variable.Class */ .highlight .vg { color: #D70 } /* Name.Variable.Global */ .highlight .vi { color: #33B } /* Name.Variable.Instance */ .highlight .vm { color: #369 } /* Name.Variable.Magic */ .highlight .il { color: #00D; font-weight: bold } /* Literal.Number.Integer.Long */
// Morph smoke test: boot the built app in headless Chrome, walk the primary
// screens, and assert (a) no page errors, (b) DOM nodes keep their identity
// across background renders — the property the morph exists to provide.
// Usage: bun build.js && bun tools/ui-morph-test.js
import { spawn } from 'node:child_process';
import puppeteer from './puppeteer.js';

const PORT = 5230;
const server = spawn('bun', ['--bun', 'x', 'serve', '-p', String(PORT), 'dist'], { stdio: 'ignore' });
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
await sleep(1500);

let ok = true;
const check = (name, cond, detail = '') => {
  console.log(` ${cond ? '✓' : '✗'} ${name}${detail ? ' — ' + detail : ''}`);
  if (!cond) ok = false;
};

const browser = await puppeteer.launch({ executablePath: '/usr/bin/google-chrome', headless: 'new', args: ['--no-sandbox'] });
const page = await browser.newPage();
const errors = [];
page.on('pageerror', (e) => errors.push(String(e)));
await page.goto(`http://localhost:${PORT}`, { waitUntil: 'networkidle2', timeout: 30000 }).catch(() => {});
await sleep(2000);

// onboarding visible?
const hasButton = await page.evaluate(() => !!document.querySelector('button'));
check('app booted to a screen with buttons', hasButton);

// walk into a wallet if the entry button exists
const clicked = await page.evaluate(() => {
  const btn = [...document.querySelectorAll('button')].find((b) => /create a new wallet/i.test(b.textContent));
  if (btn) { btn.click(); return true; }
  return false;
});
await sleep(4000);
check('entered next screen', await page.evaluate(() => document.body.textContent.length > 100), clicked ? '' : '(no start button — already in wallet)');

// node identity across background renders: tag a button, force renders, compare
const identity = await page.evaluate(async () => {
  const pick = [...document.querySelectorAll('button')].find((b) => b.offsetParent);
  if (!pick) return { skipped: true };
  pick.__marked = true;
  // fire a burst of background-style renders through the wallet's emitter if
  // exposed; otherwise rely on natural ones over the wait
  await new Promise((r) => setTimeout(r, 2500));
  const same = [...document.querySelectorAll('button')].some((b) => b.__marked);
  return { skipped: false, same };
});
check('button node survives background renders', identity.skipped || identity.same,
  identity.skipped ? '(no visible button)' : '');

// push deeper: continue through onboarding screens, then open the Send tab
for (let i = 0; i < 8; i++) {
  const state = await page.evaluate(() => {
    const vis = [...document.querySelectorAll('button')].filter((b) => b.offsetParent);
    const send = vis.find((b) => /^send$/i.test(b.textContent.trim()));
    if (send) { send.click(); return 'send'; }
    for (const re of [/generate seed/i, /continue|i saved|done|skip|next/i]) {
      const b = vis.find((x) => re.test(x.textContent));
      if (b) { b.click(); return b.textContent.trim().slice(0, 20); }
    }
    return 'none';
  });
  console.log('   walk:', state);
  await sleep(3000);
  if (state === 'send') break;
}
check('send tab reachable', await page.evaluate(() =>
  !!([...document.querySelectorAll('input[type=text]')].find((i) => i.offsetParent))), '');

// typing: find a text input if present, type + hold value across renders
const typing = await page.evaluate(() => {
  const inp = [...document.querySelectorAll('input[type=text]')].find((i) => i.offsetParent);
  if (!inp) return { skipped: true };
  inp.focus();
  inp.value = 'morphtest';
  inp.dispatchEvent(new Event('input', { bubbles: true }));
  return { skipped: false };
});
if (!typing.skipped) {
  await sleep(1200);
  const kept = await page.evaluate(() => {
    const inp = [...document.querySelectorAll('input[type=text]')].find((i) => i.value === 'morphtest');
    return !!inp && document.activeElement === inp;
  });
  check('focused input keeps value + focus across renders', kept);
} else {
  check('typing check', true, '(no text input on this screen)');
}

check('no page errors', errors.length === 0, errors.slice(0, 2).join(' | '));
await browser.close();
server.kill();
console.log(ok ? '\n✅ morph smoke passes' : '\n❌ morph smoke failed');
process.exit(ok ? 0 : 1);