Back to Black Site
SOURCE / PINNED RELEASE

Made of little things.

Black Site

Release
666bc7c74ebd…
Author-recorded commit
05e95af79676…
License
LICENSE
Author’s source reference
nostr://npub12lm3rxsva8kfempyjkxupt09e02n3fezurkyadyqfejdc5e0r2kscqty6r/wss%3A%2F%2Fgit.napplet.soy%2F/n-d2225ddc391

Archive hash verified: 1544e072e245c4a8…. The source-to-build association is the author’s claim; it has not been independently rebuilt.

scripts/test-keyboard-host.mjs
// Usage: soyli dev --port 0, then soyli run test:keyboard:host <printed URL>.
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
import { readdir } from 'node:fs/promises';
import { join } from 'node:path';
import { homedir } from 'node:os';
const require = createRequire(import.meta.url);
const harnessRequire = createRequire(require.resolve('@napplet/conformance-cli/package.json'));
const { chromium } = harnessRequire('playwright');
const url = process.argv[2];
if (!url) throw new Error('Supply the URL printed by your running soyli dev session');
const browserRoot = join(homedir(), '.cache/napplet-space/toolchains/browsers');
const installations = (await readdir(browserRoot)).filter(name => name.startsWith('chromium_headless_shell-')).sort();
const executablePath = process.env.CHROME || join(browserRoot, installations.at(-1), 'chrome-headless-shell-linux64/chrome-headless-shell');
const browser = await chromium.launch({ headless: true, executablePath });
try {
  const page = await browser.newPage({ viewport: { width: 1200, height: 800 } });
  const errors = [];
  page.on('pageerror', error => errors.push(error.message));
  await page.addInitScript(() => {
    window.keyboardMessages = [];
    window.addEventListener('message', event => {
      if (event.data?.type?.startsWith('keys.')) window.keyboardMessages.push(event.data);
    });
  });
  await page.goto(url);
  const frame = await (async () => {
    await page.locator('iframe').first().waitFor();
    return page.frames().find(candidate => candidate !== page.mainFrame());
  })();
  await frame.waitForFunction(() => window.keyboardMessages.filter(m => m.type === 'keys.registerAction.result').length === 9);
  assert.equal(await frame.evaluate(() => Boolean(window.napplet?.keys)), true);
  await frame.locator('#menu [data-go="deploy"]').click();
  const paused = () => frame.locator('#pause').evaluate(element => element.classList.contains('on'));
  await page.keyboard.press('p');
  assert.equal(await paused(), true);
  await page.keyboard.down('p');
  await page.keyboard.down('p');
  await page.keyboard.up('p');
  assert.equal(await paused(), false, 'repeat must not toggle pause twice');
  await page.keyboard.press('i');
  assert.equal(await frame.locator('#inv').evaluate(element => element.classList.contains('on')), true);
  await page.keyboard.press('i');
  assert.equal(await frame.locator('#inv').evaluate(element => element.classList.contains('on')), false);
  const shellSend = async message => {
    await page.evaluate(message => document.querySelector('iframe').contentWindow.postMessage(message, '*'), message);
    await page.waitForTimeout(50);
  };
  // Trusted parent fixture exercises complete binding replacement by the runtime shim.
  await shellSend({ type: 'keys.bindings', bindings: [{ actionId: 'blacksite.pause', key: 'o' }] });
  await page.keyboard.press('p');
  assert.equal(await paused(), false, 'old fixed binding must be inactive after remapping');
  await page.keyboard.press('o');
  assert.equal(await paused(), true, 'new runtime binding must invoke pause');
  await shellSend({ type: 'keys.action', actionId: 'blacksite.pause' });
  assert.equal(await paused(), false, 'shell-triggered action must invoke resume');
  await page.keyboard.press('Escape');
  assert.equal(await paused(), true);
  await page.keyboard.press('z');
  await page.waitForTimeout(50);
  const forwards = await page.evaluate(() => window.keyboardMessages.filter(m => m.type === 'keys.forward').map(m => m.key));
  assert.ok(forwards.includes('z'), 'unbound keys must reach shell');
  assert.ok(!forwards.includes('o'), 'bound keys must not forward');
  for (const [width, height, notice] of [[200,160,true], [320,560,true], [900,600,false], [1600,1000,false]]) {
    await page.setViewportSize({ width, height });
    assert.equal(await frame.locator('#tooSmall').isVisible(), notice);
  }
  assert.deepEqual(errors, []);
  console.log('PASS: registration, pause, repeat, inventory, remapping, shell action, forwarding, four frame sizes');
} finally {
  await browser.close();
}