Skip to content
Open
Show file tree
Hide file tree
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
6 changes: 4 additions & 2 deletions apps/web/src/styles/viewer/theater.css
Original file line number Diff line number Diff line change
Expand Up @@ -1039,14 +1039,16 @@
-webkit-backdrop-filter: blur(16px);
opacity: 0;
transform: translate(-50%, 6px);
pointer-events: none;
/* Keep the pill's own hitbox active while visually hidden. An iframe does
not reliably propagate hover to its parent canvas, so disabling pointer
events here made the iframe permanently intercept the navigation. */
pointer-events: auto;
transition: opacity 140ms cubic-bezier(0.23, 1, 0.32, 1), transform 140ms cubic-bezier(0.23, 1, 0.32, 1);
}
.comment-preview-canvas:hover .deck-floating-nav,
.deck-floating-nav:hover {
opacity: 1;
transform: translate(-50%, 0);
pointer-events: auto;
}
.deck-floating-button {
width: 30px;
Expand Down
19 changes: 6 additions & 13 deletions e2e/ui/entry-chrome-flows.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, test } from '@/playwright/suite';
import { ensureRailOpen, openNewProjectModal } from '@/playwright/rail';
import { settingsSurface } from '@/playwright/amr';
import { openSettingsDialog, settingsSurface } from '@/playwright/amr';
import { expectStableCount } from '@/playwright/assertions';
import { openHomeTemplateMenu } from '@/playwright/home-hero';
import type {
Expand Down Expand Up @@ -731,6 +731,7 @@ test('[P1] Settings About reads desktop updater status and runs a manual update
(window as unknown as { __odUpdaterCalls: string[] }).__odUpdaterCalls.push('check');
return checkedStatus;
},
'clear-cache': async () => idleStatus,
download: async () => checkedStatus,
install: async () => checkedStatus,
quit: async () => ({ ok: true }),
Expand All @@ -755,10 +756,7 @@ test('[P1] Settings About reads desktop updater status and runs a manual update
});

await gotoEntryHome(page);
await page.getByTestId('entry-settings-menu-trigger').click();
await page.getByTestId('entry-settings-open-details').click();
const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible();
const dialog = await openSettingsDialog(page);

await dialog.getByRole('button', { name: /^About\b/i }).click();
await expect(dialog.locator('.settings-about-version-num')).toContainText('0.13.4');
Expand Down Expand Up @@ -825,6 +823,7 @@ test('[P1] Settings About surfaces prerelease updater check failures with retry
(window as unknown as { __odUpdaterCalls: string[] }).__odUpdaterCalls.push('check');
return failedStatus;
},
'clear-cache': async () => idleStatus,
download: async () => failedStatus,
install: async () => failedStatus,
quit: async () => ({ ok: true }),
Expand All @@ -849,10 +848,7 @@ test('[P1] Settings About surfaces prerelease updater check failures with retry
});

await gotoEntryHome(page);
await page.getByTestId('entry-settings-menu-trigger').click();
await page.getByTestId('entry-settings-open-details').click();
const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible();
const dialog = await openSettingsDialog(page);

await dialog.getByRole('button', { name: /^About\b/i }).click();
await expect(dialog.locator('.settings-about-version-num')).toContainText('0.16.0-prerelease.1');
Expand Down Expand Up @@ -941,10 +937,7 @@ test('[P1] Settings BYOK connection failures emit a classified analytics error c
});

await gotoEntryHome(page);
await page.getByTestId('entry-settings-menu-trigger').click();
await page.getByTestId('entry-settings-open-details').click();
const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible();
const dialog = await openSettingsDialog(page);

const connectionTest = dialog.locator('.settings-byok-connection-test');
await expect(connectionTest).toBeVisible();
Expand Down
3 changes: 2 additions & 1 deletion e2e/ui/entry-topbar.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, test } from '@/playwright/suite';
import { ensureRailOpen } from '@/playwright/rail';
import { settingsSurface } from '@/playwright/amr';
import { routeAgents } from '@/playwright/mock-factory';
import { routeAgents, suppressWhatsNew } from '@/playwright/mock-factory';
import { T } from '@/timeouts';
import type { Page } from '@playwright/test';

Expand All @@ -27,6 +27,7 @@ async function gotoEntryHome(page: Page) {
}

test.beforeEach(async ({ page }) => {
await suppressWhatsNew(page);
await page.addInitScript((key) => {
window.localStorage.clear();
window.sessionStorage.clear();
Expand Down
64 changes: 55 additions & 9 deletions e2e/ui/home-hero-rail.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,7 @@ test('[P1] home composer sends referenced workspace context into project creatio

test('[P1] home staged workspace context auto-sends into the first project run', async ({ page }) => {
const prompt = 'Create a project and immediately use the Home-staged context.';
const projectId = 'home-autosend-context-project';
let projectId = '';
const conversationId = 'conv-home-autosend-context';
const runBodies: Array<Record<string, unknown>> = [];
let createdProjectMetadata: Record<string, unknown> = {};
Expand All @@ -963,7 +963,13 @@ test('[P1] home staged workspace context auto-sends into the first project run',
return;
}
if (request.method() === 'POST') {
const body = request.postDataJSON() as { metadata?: Record<string, unknown>; name?: string; pendingPrompt?: string };
const body = request.postDataJSON() as {
id?: string;
metadata?: Record<string, unknown>;
name?: string;
pendingPrompt?: string;
};
projectId = body.id ?? 'home-autosend-context-project';
createdProjectMetadata = body.metadata ?? {};
await route.fulfill({
json: {
Expand Down Expand Up @@ -992,8 +998,12 @@ test('[P1] home staged workspace context auto-sends into the first project run',
},
});
});
await page.route(`**/api/projects/${projectId}`, async (route) => {
await page.route('**/api/projects/*', async (route) => {
const request = route.request();
if (!projectId || new URL(request.url()).pathname !== `/api/projects/${projectId}`) {
await route.fallback();
return;
}
if (request.method() === 'GET') {
await route.fulfill({
json: {
Expand Down Expand Up @@ -1030,7 +1040,14 @@ test('[P1] home staged workspace context auto-sends into the first project run',
}
await route.fallback();
});
await page.route(`**/api/projects/${projectId}/conversations`, async (route) => {
await page.route('**/api/projects/*/conversations', async (route) => {
if (
!projectId
|| new URL(route.request().url()).pathname !== `/api/projects/${projectId}/conversations`
) {
await route.fallback();
return;
}
if (route.request().method() !== 'GET') {
await route.fallback();
return;
Expand All @@ -1051,24 +1068,53 @@ test('[P1] home staged workspace context auto-sends into the first project run',
},
});
});
await page.route(`**/api/projects/${projectId}/conversations/${conversationId}/messages`, async (route) => {
await page.route('**/api/projects/*/conversations/*/messages', async (route) => {
if (
!projectId
|| new URL(route.request().url()).pathname
!== `/api/projects/${projectId}/conversations/${conversationId}/messages`
) {
await route.fallback();
return;
}
if (route.request().method() !== 'GET') {
await route.fallback();
return;
}
await route.fulfill({ json: { messages: [] } });
});
await page.route(`**/api/projects/${projectId}/conversations/${conversationId}/messages/*`, async (route) => {
await page.route('**/api/projects/*/conversations/*/messages/*', async (route) => {
if (
!projectId
|| !new URL(route.request().url()).pathname.startsWith(
`/api/projects/${projectId}/conversations/${conversationId}/messages/`,
)
) {
await route.fallback();
return;
}
if (route.request().method() !== 'PUT') {
await route.fallback();
return;
}
await route.fulfill({ json: { ok: true } });
});
await page.route(`**/api/projects/${projectId}/conversations/${conversationId}/comments`, async (route) => {
await page.route('**/api/projects/*/conversations/*/comments', async (route) => {
if (
!projectId
|| new URL(route.request().url()).pathname
!== `/api/projects/${projectId}/conversations/${conversationId}/comments`
) {
await route.fallback();
return;
}
await route.fulfill({ json: { comments: [] } });
});
await page.route(`**/api/projects/${projectId}/files`, async (route) => {
await page.route('**/api/projects/*/files', async (route) => {
if (!projectId || new URL(route.request().url()).pathname !== `/api/projects/${projectId}/files`) {
await route.fallback();
return;
}
await route.fulfill({ json: { files: [] } });
});
await page.route('**/api/live-artifacts**', async (route) => {
Expand Down Expand Up @@ -1354,7 +1400,7 @@ test('[P1] home suggestion entry remains retryable after create failures', async
await expect.poll(projectCreateCount).toBe(1);
await expect(page).toHaveURL(/\/$/);
await expect(page.getByTestId('home-hero-submit')).toBeEnabled();
await expect(page.getByRole('alert').filter({ hasText: /Failed to start the run/i })).toBeVisible();
await expect(page.getByRole('alert').filter({ hasText: /Could not create project/i })).toBeVisible();
await runRequests.expectNone({ message: 'failed blank project create should not start a run' });

await page.getByTestId('home-hero-submit').click();
Expand Down
3 changes: 2 additions & 1 deletion e2e/ui/message-center.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect, test } from '@/playwright/suite';
import { routeAgents } from '@/playwright/mock-factory';
import { routeAgents, suppressWhatsNew } from '@/playwright/mock-factory';
import { ensureRailOpen } from '@/playwright/rail';
import type { Page } from '@playwright/test';

Expand All @@ -9,6 +9,7 @@ const READ_KEY = 'open-design.message-center.anonymous-read-ids.v1';
test.describe.configure({ timeout: 30_000 });

async function seedEntryHome(page: Page, options?: { locale?: string }) {
await suppressWhatsNew(page);
await page.addInitScript(({ key, locale }) => {
window.localStorage.clear();
window.sessionStorage.clear();
Expand Down
7 changes: 2 additions & 5 deletions e2e/ui/project-management-flows.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2302,7 +2302,6 @@ test('[P1] BYOK OpenCode project run sends provider config through the daemon co
apiKey: 'sk-openai-e2e',
baseUrl: 'https://api.openai.com/v1',
model: 'gpt-4o-mini',
apiVersion: '',
},
analyticsHints: {
runtimeType: 'byok',
Expand Down Expand Up @@ -4181,10 +4180,8 @@ async function routeHandoffEditors(page: Page): Promise<void> {
}

async function openHandoffCliTab(page: Page): Promise<Locator> {
await page.getByRole('button', { name: 'Share', exact: true }).click();
const unifiedPopover = page.locator('.chrome-unified-popover:visible');
await unifiedPopover.getByRole('tab', { name: 'Send to...' }).click();
const menu = unifiedPopover.getByTestId('handoff-menu');
await page.getByTestId('handoff-caret').click();
const menu = page.getByTestId('handoff-menu');
await expect(menu).toBeVisible();
await menu.getByRole('tab', { name: /^Copy for CLI$/ }).click();
return menu;
Expand Down
5 changes: 3 additions & 2 deletions e2e/ui/real-daemon-run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
createFakeAgentRuntimes,
FAKE_AGENT_RUNTIME_IDS,
} from '@/playwright/fake-agents';
import { trackRunRequests } from '@/playwright/mock-factory';
import { suppressWhatsNew, trackRunRequests } from '@/playwright/mock-factory';
import type { FakeAgentId } from '@/playwright/fake-agents';
import { T } from '@/timeouts';

Expand Down Expand Up @@ -48,6 +48,7 @@ test.beforeAll(async () => {

test.beforeEach(async ({ page }) => {
test.setTimeout(T.xlong);
await suppressWhatsNew(page);

await resetDaemonAppConfig(page);

Expand Down Expand Up @@ -206,7 +207,7 @@ test('[P1] real daemon run treats an in-place artifact edit as produced work', a
}, { timeout: 15_000 })
.toContainEqual({
runStatus: 'succeeded',
producedFiles: [],
producedFiles: [GENERATED_FILE],
traceObjectFiles: [GENERATED_FILE],
resultDeliveryState: 'delivered',
});
Expand Down
Loading
Loading