Back to Funclet
SOURCE / PINNED RELEASE

Made of little things.

Funclet

Release
0b497cfc2f66…
Author-recorded commit
1e531b24f490…
License
LICENSE
Author’s source reference
nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-6b7a37cac1d

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

tests/live-release.mjs
// Unmodified published artifact, real website and public relays. No intercepted data.
import assert from 'node:assert/strict';
import { realpathSync, mkdirSync } from 'node:fs';
import { createRequire } from 'node:module';
import { execFileSync } from 'node:child_process';
const url = process.argv[2];
assert.ok(url?.startsWith('https://napplet.soy/'), 'Pass a published napplet.soy URL');
const require = createRequire(`${realpathSync('node_modules/@napplet/conformance-cli')}/package.json`);
const { chromium, devices } = require('playwright');
const mobile = process.argv.includes('--mobile');
const executables = JSON.parse(execFileSync('soyli', ['browser', 'path', '--json'], { encoding: 'utf8' })).executables;
const browser = await chromium.launch({ executablePath: executables.find(x => x.installed && x.name.startsWith('chromium')).path });
mkdirSync('.napplet-space/testing', { recursive: true });
try {
  const page = await browser.newPage(mobile ? { ...devices['Pixel 7'], deviceScaleFactor: 3 } : { viewport: { width: 1400, height: 1100 } });
  const errors = []; page.on('pageerror', error => errors.push(error.message));
  await page.goto(url);
  await page.getByRole('button', { name: 'Start Funclet', exact: true }).click({ timeout: 20000 });
  const frame = page.frameLocator('iframe').first();
  await frame.locator('.station-row').first().waitFor({ timeout: 30000 });
  const initial = await frame.locator('#results').innerText();
  assert.doesNotMatch(initial, /Untitled station/i);
  assert.ok(await frame.locator('.station-row').count() >= 40, 'Directory must retain Wavefunc stations');
  await frame.locator('#search').fill('idm');
  await frame.locator('#search').press('Enter');
  await frame.locator('#results[aria-busy="false"]').waitFor({ timeout: 25000 });
  const results = await frame.locator('#results').innerText();
  assert.doesNotMatch(results, /OUTBOX_READ|signal did not come through/i);
  assert.match(results, /IDM AMBIENT/);
  assert.match(results, /SOMAFM CLIQHOP IDM/);
  console.log(`PASS: published browse and IDM search (${await frame.locator('.station-row').count()} stations)`);
  await page.locator('iframe').first().screenshot({ path: `.napplet-space/testing/published-${mobile?'mobile':'desktop'}.png` });
  await frame.locator('#favourites-tab').click();
  await frame.getByRole('heading', { name: 'Bring your favourites along.' }).waitFor();
  console.log('PASS: signed-out favourites state');
  if (mobile) {
    await frame.locator('#explore-tab').tap();
    await frame.locator('#search').fill('Omarchy');await frame.locator('#search').press('Enter');
    await frame.getByRole('button',{name:'Listen to Omarchy Radio',exact:true}).tap({timeout:30000});
    await frame.locator('#playback-label').filter({hasText:'ON AIR'}).waitFor({timeout:30000});
    // The normal host permission prompt can cover the player on first use.
    const connectButton=page.getByRole('button',{name:'Connect',exact:true});
    if(await connectButton.isVisible())await connectButton.tap();
    const stage=frame.locator('#receiver-stage');const canvas=stage.locator('.receiver-canvas');
    await stage.scrollIntoViewIfNeeded();
    assert.equal(await stage.getAttribute('data-renderer'),'webgl');
    const first=await canvas.screenshot();await page.waitForTimeout(350);
    assert.ok(!first.equals(await canvas.screenshot()),'published mobile receiver must animate');
    const app=page.frames().find(f=>f.url()==='about:srcdoc');
    assert.equal(await app.evaluate(()=>matchMedia('(pointer:coarse)').matches),true);
    for(const [width,height] of [[844,390],[390,844]]) {
      await page.setViewportSize({width,height});await stage.scrollIntoViewIfNeeded();await page.waitForTimeout(200);
      const size=await canvas.evaluate(el=>({width:el.width,height:el.height,antialias:el.getContext('webgl2').getContextAttributes().antialias}));
      assert.ok(size.width*size.height<=400_000&&Math.max(size.width,size.height)<=1024);
      assert.equal(size.antialias,false);assert.equal(await stage.getAttribute('data-renderer'),'webgl');
    }
    await frame.getByRole('button',{name:'Pause radio',exact:true}).tap();
    await frame.locator('#playback-label').filter({hasText:'PAUSED'}).waitFor();
    await frame.getByRole('button',{name:'Play radio',exact:true}).tap();
    await frame.locator('#playback-label').filter({hasText:'ON AIR'}).waitFor();
    await page.locator('iframe').first().screenshot({path:'.napplet-space/testing/published-mobile-playing.png'});
    console.log('PASS: published Android-density 3D animation, rotation, buffer limits and real playback');
  }
  assert.deepEqual(errors,[]);
} finally { await browser.close(); }