CI / Build & Quality Checks (push) Successful in 1m59s
CI / Docker image build & smoke test (push) Skipped
CI / Secret scan (gitleaks) (push) Successful in 7s
CI / Trigger Desktop Build (push) Successful in 5s
CI / Playwright smoke (e2e) (push) Successful in 1m59s
The client never handled beforeinstallprompt and showed no install hint, so phone users only got the PWA if they knew to dig through Share → Add to Home Screen (iOS never prompts; Chromium's mini-infobar is easy to miss). - utils/pwaInstall.ts (pure, 4 tests): show from the second visit, never in Tauri or an installed PWA (display-mode standalone / navigator.standalone), 30-day snooze after a dismissal; kind = real prompt when the browser handed us a deferred beforeinstallprompt, Share-sheet instructions on iOS Safari, nothing elsewhere (Firefox desktop has no install path). - hooks/usePwaInstallPrompt.ts: captures beforeinstallprompt/appinstalled, counts one visit per browser session, waits 6s for the prompt event before deciding, then enqueues a sticky toast; tap → prompt(), X → snooze. - ToastNotif gains onDismiss (fired by the X button only) so the snooze is recorded however the toast is closed. Mounted from ClientNonUIFeatures for signed-in users only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
35 lines
1.4 KiB
TypeScript
35 lines
1.4 KiB
TypeScript
import { describe, it } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { INSTALL_HINT_SNOOZE_MS, installHintKind, shouldShowInstallHint } from './pwaInstall';
|
|
|
|
const base = { isTauri: false, isStandalone: false, visits: 2, dismissedAt: null, now: 1_000_000 };
|
|
|
|
describe('shouldShowInstallHint', () => {
|
|
it('shows from the second visit in a plain browser tab', () => {
|
|
assert.equal(shouldShowInstallHint(base), true);
|
|
assert.equal(shouldShowInstallHint({ ...base, visits: 1 }), false);
|
|
});
|
|
|
|
it('never shows in the desktop app or an installed PWA', () => {
|
|
assert.equal(shouldShowInstallHint({ ...base, isTauri: true }), false);
|
|
assert.equal(shouldShowInstallHint({ ...base, isStandalone: true }), false);
|
|
});
|
|
|
|
it('snoozes for 30 days after a dismissal', () => {
|
|
const dismissedAt = base.now - INSTALL_HINT_SNOOZE_MS + 1;
|
|
assert.equal(shouldShowInstallHint({ ...base, dismissedAt }), false);
|
|
assert.equal(
|
|
shouldShowInstallHint({ ...base, dismissedAt: base.now - INSTALL_HINT_SNOOZE_MS }),
|
|
true,
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('installHintKind', () => {
|
|
it('prefers a real prompt, falls back to iOS instructions, else nothing', () => {
|
|
assert.equal(installHintKind(true, true), 'prompt');
|
|
assert.equal(installHintKind(false, true), 'ios-share');
|
|
assert.equal(installHintKind(false, false), 'none');
|
|
});
|
|
});
|