SOURCE / PINNED RELEASE
Made of little things.
Body Journal
- Release
- e8049f8da4e2…
- Author-recorded commit
- 61c04bf0e8aa…
- License
- LICENSE
- Author’s source reference
- nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-6c4554844c7
Archive hash verified: 4369d778da046a8b…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
import { realpathSync } from 'node:fs';
import { mkdir, readFile } from 'node:fs/promises';
import { execFileSync } from 'node:child_process';
const require = createRequire(realpathSync('node_modules/@napplet/conformance-cli/package.json'));
const { chromium } = require('playwright');
const info = JSON.parse(execFileSync('soyli', ['browser', 'path', '--json'], { encoding: 'utf8' }));
const browser = await chromium.launch({ executablePath: info.executables.find(e => e.name === 'chromium' && e.installed).path, headless: true });
const output = '.napplet-space/group-checks'; await mkdir(output, { recursive: true });
const errors = [];
async function resize(page, iframe, frame, w, h) {
await page.setViewportSize({ width: w, height: h });
await iframe.evaluate((el, [w, h]) => el.style.cssText = `position:fixed;inset:0;width:${w}px;height:${h}px;min-width:0;min-height:0;z-index:9999;border:0`, [w, h]);
await frame.waitForFunction(([w, h]) => innerWidth === w && innerHeight === h, [w, h]);
await frame.evaluate(() => new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r))));
}
async function open(page) {
page.on('pageerror', e => errors.push(e.message)); await page.goto(process.argv[2]);
const iframe = page.locator('iframe'); await iframe.waitFor();
const frame = await (await iframe.elementHandle()).contentFrame(); await frame.locator('#app[data-ready=true]').waitFor();
return { iframe, frame };
}
async function addConcerns(frame, touch = false) {
const press = loc => touch ? loc.tap() : loc.click();
await press(frame.locator('#chooseRegion')); await press(frame.locator('[data-region="Left knee"]'));
await press(frame.locator('#generalConcern')); await press(frame.locator('[data-region="Fatigue"]'));
}
const saved = f => f.waitForFunction(() => document.querySelector('#sessionStatus').textContent === 'Session saved');
const card = (f, id) => f.locator(`[data-group-id="${id}"]`);
try {
const page = await browser.newPage({ viewport: { width: 1600, height: 1000 } });
let { iframe, frame: f } = await open(page); await resize(page, iframe, f, 1600, 1000); await addConcerns(f);
await f.locator('#addGroup').click(); const first = await f.locator('.concern-group').getAttribute('data-group-id');
await card(f, first).locator('[data-group-field=name]').fill('Started after running');
await card(f, first).locator('[data-group-field=explanation]').fill('I noticed the knee and tiredness together. I am not sure they are related.');
await card(f, first).locator('[data-group-member="1"]').check(); await card(f, first).locator('[data-group-member="2"]').check();
await f.locator('#addGroup').click(); const second = await f.locator('.concern-group').last().getAttribute('data-group-id');
await card(f, second).locator('[data-group-field=name]').fill('Changes this week'); await card(f, second).locator('[data-group-member="2"]').check();
await card(f, second).locator('.group-toggle').click();
const toggle = card(f, first).locator('.group-toggle'); await toggle.focus(); await toggle.press('Enter');
assert.equal(await toggle.getAttribute('aria-expanded'), 'false');
assert.equal(await toggle.evaluate(e => document.activeElement === e), true);
await saved(f); await page.reload(); ({ iframe, frame: f } = await open(page)); await resize(page, iframe, f, 1600, 1000);
assert.equal(await f.locator('#concernCount').innerText(), '2'); assert.equal(await card(f, first).locator('.group-toggle').getAttribute('aria-expanded'), 'false');
await card(f, first).locator('.group-toggle').click();
assert.equal(await card(f, first).locator('[data-group-member="1"]').isChecked(), true);
assert.equal(await card(f, first).locator('[data-group-member="2"]').isChecked(), true);
assert.match(await card(f, first).locator('[data-group-field=explanation]').inputValue(), /not sure/);
await f.locator('[data-page=review]').first().click();
assert.match(await f.locator('.report-groups').innerText(), /Patient-suspected relationships/);
assert.equal(await f.locator('.report-group').count(), 2);
await f.locator('[data-page=map]').first().click();
for (const theme of ['light', 'dark']) {
await page.setViewportSize({ width: 1600, height: 1000 }); await iframe.evaluate(e => e.style.cssText = '');
const appearance = page.getByRole('button', { name: /Appearance:/ }); let label = '';
for (let i = 0; i < 4; i++) { label = (await appearance.getAttribute('aria-label')) || await appearance.innerText(); if (label.toLowerCase().includes(theme)) break; await appearance.click(); }
assert.ok(label.toLowerCase().includes(theme));
for (const [w, h] of [[1600, 1000], [900, 600], [320, 560], [200, 160]]) {
await resize(page, iframe, f, w, h);
if (w === 200) { assert.ok(await f.locator('.minimum-notice').isVisible()); continue; }
if (w < 761) await f.locator('button[data-panel=concerns]').click();
await card(f, first).locator('[data-group-field=name]').fill('Started after running — symptoms I noticed during a busy week');
const member = card(f, first).locator('[data-group-member="2"]'); await member.scrollIntoViewIfNeeded(); await member.uncheck(); await member.check();
assert.ok(await member.evaluate(e => { const b = e.getBoundingClientRect(); return b.left >= 0 && b.right <= innerWidth && b.top >= 0 && b.bottom <= innerHeight; }));
assert.equal(await f.locator('#concernGroups').evaluate(e => getComputedStyle(e).color), 'rgb(32, 33, 36)');
await card(f, first).locator('.group-toggle').scrollIntoViewIfNeeded(); await page.screenshot({ path: `${output}/${theme}-${w}.png` });
}
}
await resize(page, iframe, f, 1600, 1000);
await card(f, first).locator('[data-group-member="2"]').uncheck();
await card(f, second).locator('.group-toggle').click(); assert.ok(await card(f, second).locator('[data-group-member="2"]').isChecked());
assert.equal(await f.locator('#concernCount').innerText(), '2');
await card(f, second).locator('[data-group-concern="2"]').click(); await f.locator('#deleteConcern').click();
assert.equal(await f.locator('#concernCount').innerText(), '1'); assert.match(await card(f, second).locator('.group-toggle').innerText(), /0 concerns/);
await card(f, first).locator('[data-group-remove]').click(); assert.equal(await f.locator('#concernCount').innerText(), '1');
await saved(f); await page.reload(); ({ iframe, frame: f } = await open(page)); await resize(page, iframe, f, 1600, 1000);
assert.equal(await f.locator('.concern-group').count(), 1); assert.equal(await f.locator('#concernCount').innerText(), '1');
assert.match(await card(f, second).locator('.group-toggle').innerText(), /0 concerns/);
console.log('PASS: groups, shared membership, keyboard focus, summaries, unlink/delete and real SDK reload; all required frames and host themes.');
await page.close();
const context = await browser.newContext({ viewport: { width: 390, height: 844 }, hasTouch: true, isMobile: true });
const tp = await context.newPage(), { iframe: ti, frame: tf } = await open(tp);
await resize(tp, ti, tf, 390, 844); await tf.locator('button[data-panel=concerns]').tap(); await addConcerns(tf, true);
await tf.locator('#addGroup').tap(); await tf.locator('[data-group-field=name]').fill('Touch example');
for (const [w, h] of [[390, 844], [360, 640], [844, 390]]) {
await resize(tp, ti, tf, w, h); const member = tf.locator('[data-group-member="1"]');
await member.scrollIntoViewIfNeeded(); await member.tap();
const checked = await member.isChecked(); await tf.locator('.group-toggle').tap(); await tf.locator('.group-toggle').tap(); assert.equal(await member.isChecked(), checked);
await tp.screenshot({ path: `${output}/touch-${w}.png` });
}
await context.close();
const absent = await browser.newPage({ viewport: { width: 900, height: 600 } }); absent.on('pageerror', e => errors.push(e.message));
await absent.setContent('<iframe sandbox="allow-scripts" style="position:fixed;inset:0;width:900px;height:600px;border:0"></iframe>');
const ai = absent.locator('iframe'); await ai.evaluate((e, html) => e.srcdoc = html, await readFile('dist/index.html', 'utf8'));
const af = await (await ai.elementHandle()).contentFrame(); await af.locator('#app[data-ready=true]').waitFor();
await addConcerns(af); await af.locator('#addGroup').click(); await af.locator('[data-group-field=name]').fill('Session only'); await af.locator('[data-group-member="2"]').check();
assert.match(await af.locator('#sessionStatus').innerText(), /Session only/); await af.locator('[data-page=review]').first().click(); assert.match(await af.locator('.report-groups').innerText(), /Session only/);
assert.deepEqual(errors, []); console.log('PASS: touch portrait/landscape and complete in-memory workflow without optional domains.');
} finally { await browser.close(); }
