const assert = require('node:assert/strict'); const fs = require('node:fs'); const test = require('node:test'); const vm = require('node:vm'); const script = fs.readFileSync( new URL('../static/js/android-back-button.js', `file://${__filename}`), 'utf8' ); function createHarness({platform = 'android', pathname = '/', openDialog = false, openDetails = false} = {}) { const calls = []; const dialog = {close: () => calls.push('dialog.close')}; const details = {open: true}; const capacitor = { getPlatform: () => platform, addListener: (plugin, event, handler) => { calls.push(`listener:${plugin}:${event}`); capacitor.backHandler = handler; return {remove: async () => {}}; }, nativePromise: (plugin, method) => { calls.push(`${plugin}.${method}`); return Promise.resolve(); } }; vm.runInNewContext(script, { window: {Capacitor: capacitor}, document: { querySelector: selector => selector === 'dialog[open]' ? (openDialog ? dialog : null) : (openDetails ? details : null) }, location: {pathname, replace: path => calls.push(`replace:${path}`)}, history: {back: () => calls.push('history.back')} }); return {calls, capacitor, details}; } test('Android back closes an open dialog or details panel first', () => { const dialog = createHarness({openDialog: true}); dialog.capacitor.backHandler({canGoBack: true}); assert.deepEqual(dialog.calls, ['listener:App:backButton', 'dialog.close']); const details = createHarness({openDetails: true}); details.capacitor.backHandler({canGoBack: true}); assert.equal(details.details.open, false); assert.deepEqual(details.calls, ['listener:App:backButton']); }); test('Android back follows WebView history away from the start page', () => { const {calls, capacitor} = createHarness({pathname: '/messages'}); capacitor.backHandler({canGoBack: true}); assert.deepEqual(calls, ['listener:App:backButton', 'history.back']); }); test('Android back returns to the start page when a deep link has no history', () => { const {calls, capacitor} = createHarness({pathname: '/messages/42'}); capacitor.backHandler({canGoBack: false}); assert.deepEqual(calls, ['listener:App:backButton', 'replace:/']); }); test('Android back exits only from the start page', () => { const {calls, capacitor} = createHarness(); capacitor.backHandler({canGoBack: false}); assert.deepEqual(calls, ['listener:App:backButton', 'App.exitApp']); }); test('web browsers do not register the native back handler', () => { const {calls} = createHarness({platform: 'web'}); assert.deepEqual(calls, []); });