Make remote daemon update failures actionable (#2120)

* fix(settings): show daemon update failures

React Native web ignores Alert.alert, so failed remote updates reset to an enabled button without any user-visible explanation. Keep updater progress and failure as explicit rendered state, including the daemon's error, and cover the real browser-to-daemon failure path.

* test(settings): harden daemon update regression

* fix(settings): disable Desktop-managed daemon updates

Desktop-bundled daemons advertised npm self-update even though the install-origin checks always rejected it. Report Desktop ownership to clients, render actionable guidance, and refuse stale requests before touching npm.
This commit is contained in:
Mohamed Boudra
2026-07-16 21:04:31 +08:00
committed by GitHub
parent f4509fe044
commit 6aba0370ae
33 changed files with 531 additions and 92 deletions
+45 -1
View File
@@ -1,4 +1,4 @@
import { test } from "./fixtures";
import { expect, test } from "./fixtures";
import { gotoAppShell, openSettings } from "./helpers/app";
import { getE2EDaemonPort } from "./helpers/daemon-port";
import { TEST_HOST_LABEL } from "./helpers/daemon-registry";
@@ -18,6 +18,7 @@ import {
expectRetiredSidebarSectionsAbsent,
expectHostPageVisible,
expectLocalHostEntryFirst,
seedSavedSettingsHosts,
} from "./helpers/settings";
test.describe("Settings host page", () => {
@@ -69,6 +70,49 @@ test.describe("Settings host page", () => {
await expectHostActionCards(page, serverId);
});
test("a failed remote daemon update remains visible in the host UI", async ({
page,
outdatedDaemon,
}) => {
await seedSavedSettingsHosts(page, [outdatedDaemon]);
await page.reload();
await openSettings(page);
await openSettingsHost(page, outdatedDaemon.serverId);
await openHostSection(page, outdatedDaemon.serverId, "host");
page.once("dialog", (dialog) => dialog.accept());
const updateButton = page.getByTestId("host-page-update-button");
await updateButton.click();
await expect(
updateButton.filter({ hasText: /Preparing update|Downloading packages|Installing/ }),
).toBeDisabled();
const updateFailure = page.getByTestId("host-page-update-error");
await expect(updateFailure).toBeVisible();
await expect(updateFailure).toContainText("Update failed");
await expect(updateFailure).toContainText("Failed to update the daemon:");
await expect(updateButton).toBeEnabled();
});
test("a Desktop-managed daemon explains why its update action is disabled", async ({
page,
desktopManagedOutdatedDaemon,
}) => {
await seedSavedSettingsHosts(page, [desktopManagedOutdatedDaemon]);
await page.reload();
await openSettings(page);
await openSettingsHost(page, desktopManagedOutdatedDaemon.serverId);
await openHostSection(page, desktopManagedOutdatedDaemon.serverId, "host");
const updateCard = page.getByTestId("host-page-update-card");
await expect(updateCard).toBeVisible();
await expect(updateCard).toContainText(
"This daemon is managed by Paseo Desktop. Update Paseo Desktop on the host.",
);
await expect(page.getByTestId("host-page-update-button")).toBeDisabled();
});
test("clicking the label pencil reveals the inline editor", async ({ page }) => {
const serverId = getServerId();