app: add testIDs to workspace header and use them in e2e assertions

This commit is contained in:
Mohamed Boudra
2026-03-05 09:58:02 +07:00
parent 21b9743c61
commit bdfed2db4b
3 changed files with 54 additions and 20 deletions
@@ -8,6 +8,12 @@ function escapeRegex(value: string): string {
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
} }
function workspaceLabelFromPath(value: string): string {
const normalized = value.replace(/\\/g, '/').replace(/\/+$/, '');
const parts = normalized.split('/').filter(Boolean);
return parts[parts.length - 1] ?? normalized;
}
function candidateWorkspaceIds(inputPath: string): string[] { function candidateWorkspaceIds(inputPath: string): string[] {
const trimmed = inputPath.replace(/\/+$/, ''); const trimmed = inputPath.replace(/\/+$/, '');
const candidates = new Set<string>([trimmed]); const candidates = new Set<string>([trimmed]);
@@ -63,6 +69,21 @@ async function switchViaSidebar(input: {
}); });
} }
async function expectWorkspaceHeader(
page: Page,
input: { title: string; subtitle: string }
): Promise<void> {
const titleLocator = page.getByTestId('workspace-header-title');
const subtitleLocator = page.getByTestId('workspace-header-subtitle');
await expect(titleLocator.first()).toHaveText(input.title, {
timeout: 30000,
});
await expect(subtitleLocator.first()).toHaveText(input.subtitle, {
timeout: 30000,
});
}
test('sidebar workspace switch keeps visible content in sync with selected workspace', async ({ page }) => { test('sidebar workspace switch keeps visible content in sync with selected workspace', async ({ page }) => {
const serverId = process.env.E2E_SERVER_ID; const serverId = process.env.E2E_SERVER_ID;
if (!serverId) { if (!serverId) {
@@ -89,13 +110,22 @@ test('sidebar workspace switch keeps visible content in sync with selected works
await page.goto(buildHostWorkspaceRoute(serverId, repoA.path)); await page.goto(buildHostWorkspaceRoute(serverId, repoA.path));
await expect(page).toHaveURL(new RegExp('/workspace/'), { timeout: 30000 }); await expect(page).toHaveURL(new RegExp('/workspace/'), { timeout: 30000 });
await expect(page.getByText('sync-a-branch', { exact: true }).first()).toBeVisible({ timeout: 30000 }); await expectWorkspaceHeader(page, {
title: 'sync-a-branch',
subtitle: workspaceLabelFromPath(repoA.path),
});
await switchViaSidebar({ page, serverId, targetWorkspacePath: repoB.path }); await switchViaSidebar({ page, serverId, targetWorkspacePath: repoB.path });
await expect(page.getByText('sync-b-branch', { exact: true }).first()).toBeVisible({ timeout: 30000 }); await expectWorkspaceHeader(page, {
title: 'sync-b-branch',
subtitle: workspaceLabelFromPath(repoB.path),
});
await switchViaSidebar({ page, serverId, targetWorkspacePath: repoA.path }); await switchViaSidebar({ page, serverId, targetWorkspacePath: repoA.path });
await expect(page.getByText('sync-a-branch', { exact: true }).first()).toBeVisible({ timeout: 30000 }); await expectWorkspaceHeader(page, {
title: 'sync-a-branch',
subtitle: workspaceLabelFromPath(repoA.path),
});
} finally { } finally {
await repoA.cleanup(); await repoA.cleanup();
await repoB.cleanup(); await repoB.cleanup();
@@ -1,21 +1,17 @@
import { usePathname } from "expo-router"; import { usePathname } from 'expo-router'
import { Platform } from "react-native"; import { WorkspaceScreen } from '@/screens/workspace/workspace-screen'
import { WorkspaceScreen } from "@/screens/workspace/workspace-screen";
import { import {
parseHostWorkspaceOpenIntentFromPathname,
parseHostWorkspaceRouteFromPathname, parseHostWorkspaceRouteFromPathname,
} from "@/utils/host-routes"; parseHostWorkspaceOpenIntentFromPathname,
} from '@/utils/host-routes'
export default function HostWorkspaceLayout() { export default function HostWorkspaceLayout() {
const pathname = usePathname(); const expoPathname = usePathname()
const resolvedPathname = const resolvedPathname = expoPathname
Platform.OS === "web" && typeof window !== "undefined" const activeRoute = parseHostWorkspaceRouteFromPathname(resolvedPathname)
? `${window.location.pathname}${window.location.search}${window.location.hash}` const serverId = activeRoute?.serverId ?? ''
: pathname; const workspaceId = activeRoute?.workspaceId ?? ''
const activeRoute = parseHostWorkspaceRouteFromPathname(resolvedPathname); const openIntent = parseHostWorkspaceOpenIntentFromPathname(resolvedPathname)
const serverId = activeRoute?.serverId ?? "";
const workspaceId = activeRoute?.workspaceId ?? "";
const openIntent = parseHostWorkspaceOpenIntentFromPathname(resolvedPathname);
return ( return (
<WorkspaceScreen <WorkspaceScreen
@@ -24,5 +20,5 @@ export default function HostWorkspaceLayout() {
workspaceId={workspaceId} workspaceId={workspaceId}
openIntent={openIntent} openIntent={openIntent}
/> />
); )
} }
@@ -1059,10 +1059,18 @@ function WorkspaceScreenContent({
</> </>
) : ( ) : (
<> <>
<Text style={styles.headerTitle} numberOfLines={1}> <Text
testID="workspace-header-title"
style={styles.headerTitle}
numberOfLines={1}
>
{workspaceHeader.title} {workspaceHeader.title}
</Text> </Text>
<Text style={styles.headerProjectTitle} numberOfLines={1}> <Text
testID="workspace-header-subtitle"
style={styles.headerProjectTitle}
numberOfLines={1}
>
{workspaceHeader.subtitle} {workspaceHeader.subtitle}
</Text> </Text>
</> </>