Skip to content
This repository was archived by the owner on Jul 27, 2026. It is now read-only.
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import test, { expect } from "@playwright/test";
import test, { expect, type Page } from "@playwright/test";
import {
advanceOnboardingToLlmStep,
ONBOARDING_BACKEND_STEP,
Expand All @@ -7,9 +7,107 @@ import {
} from "../../support/onboarding-helpers";
import { routeSessionApiKey, SESSION_API_KEY } from "../utils/mock-llm-helpers";

const READY_CLOUD_MODEL = "openhands/mock-ready-cloud-model";
const LOCK_TO_CLOUD_WINDOW_KEY = "__AGENT_CANVAS_LOCK_TO_CLOUD__";

async function seedLockedCloudCookieBackend(page: Page) {
await page.addInitScript(
({ lockToCloudKey }) => {
(window as unknown as Record<string, unknown>)[lockToCloudKey] =
window.location.origin;
window.localStorage.removeItem("openhands-onboarded");
window.localStorage.removeItem("openhands-backends");
window.localStorage.removeItem("openhands-active-backend");
window.localStorage.removeItem("openhands-backend-health");
window.sessionStorage.removeItem("openhands-active-backend");
window.localStorage.setItem("analytics-consent", "false");
window.localStorage.setItem("openhands-telemetry-consent", "denied");
window.localStorage.setItem("openhands-telemetry-first-use", "true");
},
{ lockToCloudKey: LOCK_TO_CLOUD_WINDOW_KEY },
);
}

async function routeReadyCloudProxy(page: Page) {
await page.route("**/api/cloud-proxy", async (route, request) => {
if (request.method() !== "POST") {
await route.fallback();
return;
}

await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
items: [],
next_page_id: null,
current_org_id: "mock-org",
llm_model: READY_CLOUD_MODEL,
llm_base_url: "",
llm_api_key: null,
llm_api_key_set: true,
search_api_key_set: false,
agent: "CodeActAgent",
language: "en",
user_consents_to_analytics: false,
provider_tokens_set: { github: "" },
}),
});
});
}

test.describe.configure({ mode: "serial" });

test.describe("onboarding recent regressions", () => {
// Regression coverage for PR #1942: a ready Cloud backend already has
// everything onboarding would collect, so the home page should not show
// the first-run modal or persist a synthetic completion marker.

test("skips first-run onboarding for a ready Cloud backend", async ({
page,
}) => {
await seedLockedCloudCookieBackend(page);
await routeSessionApiKey(page);
await routeReadyCloudProxy(page);

await page.goto("/", { waitUntil: "domcontentloaded" });

await expect(
page.getByTestId("home-screen"),
"ready Cloud users should land on the home screen",
).toBeVisible({ timeout: 20_000 });
await expect(
page.getByTestId("onboarding-modal"),
"ready Cloud users should not see redundant onboarding",
).toHaveCount(0);
await expect
.poll(
() =>
page.evaluate(() =>
window.localStorage.getItem("openhands-onboarded"),
),
{
message:
"ready Cloud suppression should not fake onboarding completion",
},
)
.toBeNull();
await expect
.poll(
() =>
page.evaluate(() => {
const raw = window.localStorage.getItem("openhands-backends");
const backends = raw ? JSON.parse(raw) : [];
return backends.some(
(backend: { id?: unknown; kind?: unknown }) =>
backend.id === "locked-cloud" && backend.kind === "cloud",
);
}),
{ message: "test should exercise a locked Cloud backend" },
)
.toBe(true);
});

// Regression coverage for #1085 / PR #1100: errant outside
// interactions must not permanently mark onboarding complete.

Expand Down
Loading