fix(app/e2e): fix composer-lock test — mock provider + prompt so lock releases (#739)

* fix(app/e2e): fix composer-lock test — use mock provider + prompt so lock releases

Two bugs in the "composer is locked while new workspace agent is being
created" test:

1. expectComposerDisabled used toBeDisabled() but React Native TextInput
   with editable={false} renders as <textarea readonly> on web, not
   <textarea disabled>. Fixed to not.toBeEditable().

2. clickNewWorkspaceButton created an agent with no prompt, leaving the
   agent permanently "idle". showPendingCreateSubmitLoading only clears
   when authoritativeStatus is non-bootstrapping, but "idle" counts as
   bootstrapping — so the composer lock never released. Fixed by opening
   the new-workspace composer, filling a prompt, then clicking Create so
   the mock agent transitions to "running" after agent_created is released.

Also switches buildCreateAgentPreferences to provider "mock" with the
ten-second-stream model so E2E tests exercise app behavior without
depending on real provider availability.

* fix(app): add aria-checked to Switch for E2E toBeChecked() assertions

React Native Web does not map accessibilityState.checked to aria-checked
for role="switch", so Playwright's toBeChecked() always finds the element
unchecked. Adding aria-checked={value} directly to the Pressable sets the
attribute explicitly.

Update the switch.test.tsx mock to accept and pass through the explicit
aria-checked prop, keeping the mock faithful to the fixed component.
This commit is contained in:
Mohamed Boudra
2026-05-05 12:13:14 +08:00
committed by GitHub
parent 7eec25033f
commit c9f1e1b821
5 changed files with 22 additions and 6 deletions

View File

@@ -24,9 +24,9 @@ import {
openGithubWorkspace,
} from "./helpers/composer";
import {
clickNewWorkspaceButton,
connectNewWorkspaceDaemonClient,
delayBrowserAgentCreatedStatus,
openNewWorkspaceComposer,
openProjectViaDaemon,
} from "./helpers/new-workspace";
import { gotoAppShell } from "./helpers/app";
@@ -255,10 +255,16 @@ test.describe("Composer attachments", () => {
targetWorkspacePath: openedProject.workspaceId,
});
await clickNewWorkspaceButton(page, {
await openNewWorkspaceComposer(page, {
projectKey: openedProject.projectKey,
projectDisplayName: openedProject.projectDisplayName,
});
await fillComposerDraft(page, "lock test prompt");
const createButton = page
.getByTestId("message-input-root")
.getByRole("button", { name: "Create" });
await expect(createButton).toBeVisible({ timeout: 30_000 });
await createButton.click();
await agentCreatedDelay.waitForCreateRequest();
await agentCreatedDelay.waitForDelayedCreatedStatus();

View File

@@ -22,7 +22,9 @@ export async function expectComposerVisible(
}
export async function expectComposerDisabled(page: Page): Promise<void> {
await expect(composerInput(page)).toBeDisabled({ timeout: 10_000 });
// React Native TextInput with editable={false} renders as <textarea readonly> on web,
// not <textarea disabled>. Use not.toBeEditable() to match either form.
await expect(composerInput(page)).not.toBeEditable({ timeout: 10_000 });
}
export async function expectComposerDraft(page: Page, text: string): Promise<void> {

View File

@@ -30,10 +30,15 @@ export function buildSeededHost(input: {
};
}
export const TEST_MOCK_PROVIDER_PREFERENCES = {
...TEST_PROVIDER_PREFERENCES,
mock: { model: "ten-second-stream" },
} as const;
export function buildCreateAgentPreferences(serverId: string) {
return {
serverId,
provider: "codex" as const,
providerPreferences: TEST_PROVIDER_PREFERENCES,
provider: "mock" as const,
providerPreferences: TEST_MOCK_PROVIDER_PREFERENCES,
};
}

View File

@@ -32,6 +32,7 @@ vi.mock("react-native-reanimated", () => ({
vi.mock("react-native", () => ({
Pressable: ({
"aria-checked": ariaChecked,
accessibilityLabel,
accessibilityRole,
accessibilityState,
@@ -40,6 +41,7 @@ vi.mock("react-native", () => ({
onPress,
testID,
}: {
"aria-checked"?: boolean;
accessibilityLabel?: string;
accessibilityRole?: string;
accessibilityState?: { checked?: boolean; disabled?: boolean };
@@ -51,7 +53,7 @@ vi.mock("react-native", () => ({
React.createElement(
"button",
{
"aria-checked": accessibilityState?.checked,
"aria-checked": ariaChecked ?? accessibilityState?.checked,
"aria-disabled": accessibilityState?.disabled,
"aria-label": accessibilityLabel,
"data-disabled": disabled,

View File

@@ -100,6 +100,7 @@ export function Switch({
accessibilityRole="switch"
accessibilityState={accessibilityState}
accessibilityLabel={accessibilityLabel}
aria-checked={value}
testID={testID}
style={pressableStyle}
>