From 7e1921a472677f0bd63449ddb8bffa9dc9c684f6 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sun, 10 May 2026 12:00:18 +0100 Subject: [PATCH 1/2] fix(updater): build expected paths via path.join in updater tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Windows backend job has been red on develop since #7607 (tier-2 auto-update) merged: RollbackHandler.test.ts:122 and UpdateExecutor.test.ts:66 asserted POSIX-style paths, but the implementations build the same paths via path.join — which emits backslashes on Windows. The tests pass on Linux/macOS only by coincidence. Switch the expected values to path.join(deps.repoDir, ...) / path.join(deps.backupDir, ...) so they track whatever the implementation produces on the host platform. No production code changes. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/tests/backend-new/specs/updater/RollbackHandler.test.ts | 5 +++-- src/tests/backend-new/specs/updater/UpdateExecutor.test.ts | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/tests/backend-new/specs/updater/RollbackHandler.test.ts b/src/tests/backend-new/specs/updater/RollbackHandler.test.ts index 8a30cbcb769..14b684989f2 100644 --- a/src/tests/backend-new/specs/updater/RollbackHandler.test.ts +++ b/src/tests/backend-new/specs/updater/RollbackHandler.test.ts @@ -1,3 +1,4 @@ +import path from 'node:path'; import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest'; import {checkPendingVerification, performRollback, RollbackDeps} from '../../../../node/updater/RollbackHandler'; import {EMPTY_STATE} from '../../../../node/updater/types'; @@ -120,8 +121,8 @@ describe('performRollback', () => { }; await performRollback(state, deps); expect(deps.copyFile).toHaveBeenCalledWith( - '/srv/etherpad/var/update-backup/pnpm-lock.yaml', - '/srv/etherpad/pnpm-lock.yaml', + path.join(deps.backupDir, 'pnpm-lock.yaml'), + path.join(deps.repoDir, 'pnpm-lock.yaml'), ); const lastSave = (deps.saveState as any).mock.calls.at(-1)[0]; expect(lastSave.execution.status).toBe('rolled-back'); diff --git a/src/tests/backend-new/specs/updater/UpdateExecutor.test.ts b/src/tests/backend-new/specs/updater/UpdateExecutor.test.ts index 18fa118fc1b..9ae8815dba8 100644 --- a/src/tests/backend-new/specs/updater/UpdateExecutor.test.ts +++ b/src/tests/backend-new/specs/updater/UpdateExecutor.test.ts @@ -1,3 +1,4 @@ +import path from 'node:path'; import {describe, it, expect, vi, beforeEach} from 'vitest'; import {executeUpdate, ExecutorDeps} from '../../../../node/updater/UpdateExecutor'; import {EMPTY_STATE, UpdateState} from '../../../../node/updater/types'; @@ -64,7 +65,10 @@ describe('executeUpdate', () => { const r = await executeUpdate(deps); expect(r).toEqual({outcome: 'pending-verification'}); expect(copies).toEqual([ - {src: '/srv/etherpad/pnpm-lock.yaml', dst: '/srv/etherpad/var/update-backup/pnpm-lock.yaml'}, + { + src: path.join(deps.repoDir, 'pnpm-lock.yaml'), + dst: path.join(deps.backupDir, 'pnpm-lock.yaml'), + }, ]); expect(states.at(-1)?.execution.status).toBe('pending-verification'); expect((states.at(-1)?.execution as any).fromSha).toBe('abc123'); From 08c479dec2ffdd6e541efe11e6a700cd5c9b506b Mon Sep 17 00:00:00 2001 From: John McLear Date: Sun, 10 May 2026 12:16:52 +0100 Subject: [PATCH 2/2] fix(admin-spec): assert installed-plugins by name, not row count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ep_set_title_on_pad@0.7.2 took on ep_plugin_helpers as a transitive plugin dependency, so installing it now adds two rows to the installed-plugins table (the new plugin + its helper plugin) rather than one. The Playwright spec hard-coded `toHaveCount(2)` after install and `toHaveCount(1)` after uninstall, so it has been red on develop since #7705 merged the new admin bundle (every Frontend admin tests job, every Node version). Switch the assertions to scope by row text — `tr` containing `ep_set_title_on_pad` — and check that exactly one such row exists after install and zero after uninstall. This survives whatever transitive plugin deps the chosen test plugin pulls along, which is the only thing this spec actually cares about. Verified locally on a fresh Etherpad install: 3/3 admin-update-plugins tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../admin-spec/adminupdateplugins.spec.ts | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/tests/frontend-new/admin-spec/adminupdateplugins.spec.ts b/src/tests/frontend-new/admin-spec/adminupdateplugins.spec.ts index 0728f6c9ef6..b426fc6f661 100644 --- a/src/tests/frontend-new/admin-spec/adminupdateplugins.spec.ts +++ b/src/tests/frontend-new/admin-spec/adminupdateplugins.spec.ts @@ -48,23 +48,22 @@ test.describe('Plugins page', ()=> { // Select Installation button await pluginRow.locator('td').nth(4).locator('button').first().click() - await page.waitForTimeout(100) await page.waitForSelector('table tbody') - const installedPlugins = page.locator('table tbody').first() - const installedPluginsRows = installedPlugins.locator('tr') - await expect(installedPluginsRows).toHaveCount(2, { - timeout: 15000 - }) - const installedPluginRow = installedPluginsRows.nth(1) + // The installed-plugins table can grow by more than one row if the + // installed plugin pulls in transitive plugin deps (e.g. + // ep_set_title_on_pad depends on ep_plugin_helpers as of 0.7.2), so + // assert by name rather than by row count. + const installedPlugins = page.locator('table tbody').first() + const installedPluginRow = installedPlugins.locator('tr', {hasText: 'ep_set_title_on_pad'}) + await expect(installedPluginRow).toHaveCount(1, {timeout: 15000}) - await expect(installedPluginRow).toContainText('ep_set_title_on_pad') await installedPluginRow.locator('td').nth(2).locator('button').first().click() - // Wait for the uninstallation to complete - await expect(installedPluginsRows).toHaveCount(1, { - timeout: 15000 - }) + // Wait for the uninstallation to complete: the row for + // ep_set_title_on_pad should disappear. Other installed plugins + // (etherpad-lite itself, transitive plugin deps) may stay. + await expect(installedPluginRow).toHaveCount(0, {timeout: 15000}) await page.waitForTimeout(5000) }) })