diff --git a/src/ViperIDE.html b/src/ViperIDE.html index dc81094..d7dbd76 100644 --- a/src/ViperIDE.html +++ b/src/ViperIDE.html @@ -32,10 +32,10 @@
- - - - + + + +
diff --git a/src/app.js b/src/app.js index 27bce28..244a368 100644 --- a/src/app.js +++ b/src/app.js @@ -2606,6 +2606,12 @@ function showOfflineReadyToast(version) { openWelcomeTab() }) + /* The connect buttons ship disabled: until this script has wired up the + terminal and the handlers, a click has nothing to act on. */ + for (const t of ['sim', 'ws', 'ble', 'usb']) { + QID(`btn-conn-${t}`).disabled = false + } + setTimeout(() => { document.body.classList.add('loaded') }, 100) diff --git a/test/browser/early-connect.spec.js b/test/browser/early-connect.spec.js new file mode 100644 index 0000000..6eb9c98 --- /dev/null +++ b/test/browser/early-connect.spec.js @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +// +// A click on Connect made the instant the page starts loading used to be +// lost: the button was live before the script behind it had run, so the click +// hit an undefined `app` and nothing happened. The buttons now stay disabled +// until the app can honour the click, so an early click waits for that and +// then connects. +import { test, expect } from '@playwright/test' + +const DELAY_MS = 3000 + +/* The app ships as one inline script at the end of index.html. To simulate a + slow load, serve the same page with that script parked in an inert block + and only started DELAY_MS later; the buttons above it are on screen the + whole time. */ +async function slowApp(page) { + await page.route('**/index.html', async (route) => { + const res = await route.fetch() + const html = await res.text() + const start = html.indexOf('') + const code = html.slice(start + ' +` + await route.fulfill({ response: res, body: html.slice(0, start) + late + html.slice(end + ''.length) }) + }) +} + +test('connect clicked while the page is still loading connects once ready', async ({ page }) => { + await slowApp(page) + await page.goto('/index.html') + // Playwright waits for the button to be enabled before it clicks. + await page.locator('#btn-conn-sim').click() + await expect(page.locator('#xterm')).toContainText('>>>', { timeout: 45_000 }) +}) + +test('connect buttons are disabled until the app is ready', async ({ page }) => { + await slowApp(page) + await page.goto('/index.html') + await expect(page.locator('#btn-conn-sim')).toBeDisabled() + await expect(page.locator('#btn-conn-sim')).toBeEnabled({ timeout: 15_000 }) +})