diff --git a/.gitignore b/.gitignore index a7538fd..b4f08e5 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ electron/release/ tests/cached_assets/ # E2E tests +test-results/ tests/node_modules/ tests/test-results/ tests/playwright-report/ diff --git a/tests/integration.spec.js b/tests/integration.spec.js index 06ffce4..5579d76 100644 --- a/tests/integration.spec.js +++ b/tests/integration.spec.js @@ -1157,6 +1157,48 @@ test.describe('Custom patches', () => { await expect(page.locator('#step-manual-version')).not.toBeHidden(); }); + test('switching from manual to connect resets manual state', async ({ page }) => { + test.skip(!hasFirmwareZip(), `Firmware not found at ${FIRMWARE_PATH}`); + + await page.goto('/'); + await expect(page.locator('h1')).toContainText('KoboPatch'); + + // Start in manual mode, select patches, reach version picker + await page.click('#btn-manual'); + await expect(page.locator('#step-mode')).not.toBeHidden(); + await page.click('input[name="mode"][value="patches"]'); + await page.click('#btn-mode-next'); + await expect(page.locator('#step-manual-version')).not.toBeHidden(); + + // Go back all the way to the connect step + await page.click('#btn-manual-version-back'); + await expect(page.locator('#step-mode')).not.toBeHidden(); + await page.click('#btn-mode-back'); + await expect(page.locator('#step-connect')).not.toBeHidden(); + + // Change mind: click "Connect to Kobo" — manualMode must be reset + await injectMockDevice(page, { hasNickelMenu: false, overrideFirmware: true }); + await page.click('#btn-connect'); + await expect(page.locator('#step-connect-instructions')).not.toBeHidden(); + await page.click('#btn-connect-ready'); + await expect(page.locator('#step-device')).not.toBeHidden(); + + // Continue to mode selection, pick patches + await page.click('#btn-device-next'); + await expect(page.locator('#step-mode')).not.toBeHidden(); + await page.click('input[name="mode"][value="patches"]'); + await page.click('#btn-mode-next'); + + // Should go to the device-aware patches step, NOT the manual version picker + await expect(page.locator('#step-patches')).not.toBeHidden(); + await expect(page.locator('#step-manual-version')).toBeHidden(); + + // Back from patches should return to mode selection, not manual version + await page.click('#btn-patches-back'); + await expect(page.locator('#step-mode')).not.toBeHidden(); + await expect(page.locator('#step-manual-version')).toBeHidden(); + }); + test('no device — back navigation through manual mode flow', async ({ page }) => { await page.goto('/'); await goToManualMode(page); diff --git a/web/src/js/app.js b/web/src/js/app.js index 8d0f7ee..086d586 100644 --- a/web/src/js/app.js +++ b/web/src/js/app.js @@ -367,6 +367,10 @@ function displayDeviceInfo(info) { // "Connect my Kobo" shows the instructions step first (not the file picker). btnConnect.addEventListener('click', () => { + // Reset any state from a previous manual-mode attempt so it does not + // leak into the device-connected flow (e.g. back navigation would + // otherwise land on the manual version picker). + state.manualMode = false; track('flow-start', { method: 'connect' }); showStep(stepConnectInstructions); });