Skip to content
Merged
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
4 changes: 4 additions & 0 deletions packages/trace-viewer/src/ui/uiModeView.css
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@
text-overflow: ellipsis;
}

.status-line .status-line-failed {
color: var(--vscode-testing-iconFailed);
}

.ui-mode-sidebar input[type=search] {
flex: auto;
padding: 0 5px;
Expand Down
27 changes: 21 additions & 6 deletions packages/trace-viewer/src/ui/uiModeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,26 @@ function escapeRegex(text: string) {
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

function renderStatusLine(progress: TeleSuiteUpdaterProgress, total: number, isRunning: boolean) {
const finished = progress.passed + progress.failed + progress.skipped;
const pct = total ? (finished / total) * 100 | 0 : 0;
const counts: React.ReactNode[] = [];
if (progress.passed > 0)
counts.push(`${progress.passed} passed`);
if (progress.failed > 0)
counts.push(<span key='failed' className='status-line-failed'>{progress.failed} failed</span>);
if (progress.skipped > 0)
counts.push(`${progress.skipped} skipped`);
return <div data-testid='status-line' className='status-line'>
<div>
{isRunning && 'Running '}
{finished}/{total} ({pct}%)
{counts.length > 0 && ' — '}
{counts.map((count, i) => <React.Fragment key={i}>{i > 0 ? ', ' : ''}{count}</React.Fragment>)}
</div>
</div>;
}

export const UIModeView: React.FC<{}> = ({
}) => {
const [filterText, setFilterText] = React.useState<string>('');
Expand Down Expand Up @@ -486,12 +506,7 @@ export const UIModeView: React.FC<{}> = ({
runTests={runVisibleTests} />
<Toolbar className='section-toolbar' noMinHeight={true}>
{!isRunningTest && !progress && <div className='section-title'>Tests</div>}
{!isRunningTest && progress && <div data-testid='status-line' className='status-line'>
<div>{progress.passed}/{progress.total} passed ({(progress.passed / progress.total) * 100 | 0}%)</div>
</div>}
{isRunningTest && progress && <div data-testid='status-line' className='status-line'>
<div>Running {progress.passed}/{runningState.testIds.size} passed ({(progress.passed / runningState.testIds.size) * 100 | 0}%)</div>
</div>}
{progress && renderStatusLine(progress, isRunningTest ? runningState.testIds.size : progress.total, !!isRunningTest)}
<ToolbarButton icon='play' title='Run all — F5' onClick={runVisibleTests} disabled={isRunningTest || isLoading}></ToolbarButton>
<ToolbarButton icon='debug-stop' title={'Stop — ' + (isMac ? '⇧F5' : 'Shift + F5')} onClick={() => testServerConnection?.stopTests({})} disabled={!isRunningTest || isLoading} testId={'stop-button'}></ToolbarButton>
<ToolbarButton icon='eye' title='Watch all' toggled={watchAll} onClick={() => {
Expand Down
2 changes: 1 addition & 1 deletion tests/playwright-test/ui-mode-metadata.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ test('should render html report git info metadata', async ({ runUITest }) => {
});

await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
await page.getByTitle('Toggle output').click();

await expect(page.getByTestId('output')).toContainText('ci.link: https://playwright.dev');
Expand Down
2 changes: 1 addition & 1 deletion tests/playwright-test/ui-mode-test-annotations.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ test('should display annotations', async ({ runUITest }) => {
`,
});
await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
await page.getByRole('treeitem', { name: 'suite' }).locator('.codicon-chevron-right').click();
await page.getByText('annotation test').click();
await page.getByText('Annotations', { exact: true }).click();
Expand Down
12 changes: 6 additions & 6 deletions tests/playwright-test/ui-mode-test-attachments.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ test('should contain text attachment', async ({ runUITest }) => {
});
await page.getByText('attach test').click();
await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
await page.getByText('Attachments').click();

await page.locator('.tab-attachments').getByText('text attachment').click();
Expand Down Expand Up @@ -69,7 +69,7 @@ test('should contain binary attachment', async ({ runUITest }) => {
});
await page.getByText('attach test').click();
await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
await page.getByText('Attachments').click();
const downloadPromise = page.waitForEvent('download');
await page.getByRole('link', { name: 'download' }).click();
Expand All @@ -89,7 +89,7 @@ test('should contain string attachment', async ({ runUITest }) => {
});
await page.getByText('attach test').click();
await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
await page.getByText('Attachments').click();
await page.getByText('note', { exact: true }).click();
const downloadPromise = page.waitForEvent('download');
Expand All @@ -116,7 +116,7 @@ test('should linkify string attachments', async ({ runUITest, server }) => {
});
await page.getByText('attach test').click();
await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
await page.getByText('Attachments').click();

const attachmentsPane = page.locator('.attachments-tab');
Expand Down Expand Up @@ -162,7 +162,7 @@ test('should link from attachment step to attachments view', async ({ runUITest

await page.getByText('attach test').click();
await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
await page.getByRole('tab', { name: 'Attachments' }).click();

const panel = page.getByRole('tabpanel', { name: 'Attachments' });
Expand Down Expand Up @@ -193,7 +193,7 @@ test('attachments from inside boxed fixture should be visible', { annotation: {
}, { reporter: 'line' }, {});
await page.getByText('my test').click();
await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');

await page.getByRole('treeitem', { name: 'attach "my attachment"' }).getByLabel('Open Attachment').click();
await expect(page.getByRole('tabpanel', { name: 'Attachments' })).toMatchAriaSnapshot(`
Expand Down
2 changes: 1 addition & 1 deletion tests/playwright-test/ui-mode-test-output.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ test('should print beforeAll console messages once', async ({ runUITest }, testI
await page.getByTitle('Run all').click();
await page.getByText('Console').click();
await page.getByText('print').click();
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
await expect(page.locator('.console-tab .console-line-message')).toHaveText([
'before all log',
'test log',
Expand Down
22 changes: 11 additions & 11 deletions tests/playwright-test/ui-mode-test-run.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ test('should run visible', async ({ runUITest }) => {
- treeitem "[icon-circle-slash] skipped"
`);

await expect(page.getByTestId('status-line')).toHaveText('4/8 passed (50%)');
await expect(page.getByTestId('status-line')).toHaveText('8/8 (100%) — 4 passed, 3 failed, 1 skipped');
});

test('should show running progress', async ({ runUITest }) => {
Expand All @@ -96,9 +96,9 @@ test('should show running progress', async ({ runUITest }) => {
});

await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('Running 1/4 passed (25%)');
await expect(page.getByTestId('status-line')).toHaveText('Running 1/4 (25%) — 1 passed');
await page.getByTestId('stop-button').click();
await expect(page.getByTestId('status-line')).toHaveText('1/4 passed (25%)');
await expect(page.getByTestId('status-line')).toHaveText('2/4 (50%) — 1 passed, 1 skipped');
await page.getByTitle('Reload').click();
await expect(page.getByTestId('status-line')).toBeHidden();
});
Expand Down Expand Up @@ -491,7 +491,7 @@ test('should show time', async ({ runUITest }) => {
- treeitem "[icon-circle-slash] skipped"
`);

await expect(page.getByTestId('status-line')).toHaveText('4/8 passed (50%)');
await expect(page.getByTestId('status-line')).toHaveText('8/8 (100%) — 4 passed, 3 failed, 1 skipped');
});

test('should show test.fail as passing', async ({ runUITest }) => {
Expand Down Expand Up @@ -522,7 +522,7 @@ test('should show test.fail as passing', async ({ runUITest }) => {
- treeitem ${/\[icon-check\] should fail \d+m?s/}
`);

await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
});

test('should ignore repeatEach', async ({ runUITest }) => {
Expand Down Expand Up @@ -558,7 +558,7 @@ test('should ignore repeatEach', async ({ runUITest }) => {
- treeitem ${/\[icon-check\] should pass/}
`);

await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
});

test('should remove output folder before test run', async ({ runUITest }) => {
Expand Down Expand Up @@ -593,7 +593,7 @@ test('should remove output folder before test run', async ({ runUITest }) => {
- treeitem ${/\[icon-check\] should pass/}
`);

await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');

await page.getByTitle('Run all').click();
await expect.poll(dumpTestTree(page)).toBe(`
Expand All @@ -608,7 +608,7 @@ test('should remove output folder before test run', async ({ runUITest }) => {
- treeitem ${/\[icon-check\] should pass/}
`);

await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
});

test('should show proper total when using deps', async ({ runUITest }) => {
Expand Down Expand Up @@ -660,7 +660,7 @@ test('should show proper total when using deps', async ({ runUITest }) => {
- treeitem "[icon-circle-outline] run @chromium chromium"
`);

await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');

await page.getByTitle('run @chromium').dblclick();
await expect.poll(dumpTestTree(page)).toBe(`
Expand All @@ -680,7 +680,7 @@ test('should show proper total when using deps', async ({ runUITest }) => {
- button "Watch"
`);

await expect(page.getByTestId('status-line')).toHaveText('2/2 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('2/2 (100%) — 2 passed');
});

test('should respect --tsconfig option', {
Expand Down Expand Up @@ -746,7 +746,7 @@ test('should respect --tsconfig option', {
- treeitem ${/\[icon-check\] test/}
`);

await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
});

test('should respect --ignore-snapshots option', {
Expand Down
2 changes: 1 addition & 1 deletion tests/playwright-test/ui-mode-test-screencast.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ test('should show screenshots', async ({ runUITest }) => {
`,
});
await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('2/2 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('2/2 (100%) — 2 passed');

await page.getByText('test 1', { exact: true }).click();
await expect(page.getByTestId('actions-tree')).toContainText('Expect');
Expand Down
10 changes: 5 additions & 5 deletions tests/playwright-test/ui-mode-test-setup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ test('should run global setup and teardown', async ({ runUITest }, testInfo) =>
`
}, undefined, { additionalArgs: ['--output=foo'] });
await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');

await page.getByTitle('Toggle output').click();
const output = page.getByTestId('output');
Expand Down Expand Up @@ -85,7 +85,7 @@ test('should teardown on sigint', async ({ runUITest, nodeVersion }) => {
`
});
await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
await page.getByTitle('Toggle output').click();
await expect(page.getByTestId('output')).toContainText('from-global-setup');

Expand Down Expand Up @@ -335,7 +335,7 @@ for (const useWeb of [true, false]) {
`
}, null, { useWeb });
await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
await testProcess.kill('SIGINT');
await expect.poll(() => testProcess.outputLines()).toEqual([
'from-global-teardown0000',
Expand Down Expand Up @@ -368,7 +368,7 @@ test('should restart webserver on reload', async ({ runUITest }) => {
`
}, { DEBUG: 'pw:webserver' });
await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');

await page.getByTitle('Toggle output').click();
await expect(page.getByTestId('output')).toContainText('[WebServer] listening');
Expand All @@ -381,5 +381,5 @@ test('should restart webserver on reload', async ({ runUITest }) => {
await expect(page.getByTestId('output')).not.toContainText('set reuseExistingServer:true');

await page.getByTitle('Run all').click();
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
});
2 changes: 1 addition & 1 deletion tests/playwright-test/ui-mode-test-shortcut.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ test('should run tests', async ({ runUITest }) => {
await page.getByPlaceholder('Filter (e.g. text, @tag)').fill('test 3');
await page.keyboard.press('F5');

await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
await page.getByPlaceholder('Filter (e.g. text, @tag)').fill('');

// Only the filtered test was run.
Expand Down
2 changes: 1 addition & 1 deletion tests/playwright-test/ui-mode-test-source.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ test('should keep showing source when test is pending', async ({ runUITest }, te

await page.getByTitle('Run all').click();
await page.getByTestId('test-tree').getByText('second').click();
await expect(page.getByTestId('status-line')).toHaveText('Running 1/3 passed (33%)');
await expect(page.getByTestId('status-line')).toHaveText('Running 1/3 (33%) — 1 passed');
await expect(page.getByTestId('source-code').locator('.source-tab-file-name')).toHaveText('a.test.ts');
await expect(page.locator('.CodeMirror .source-line-running')).toHaveText(`7 test('second', () => {});`);
});
14 changes: 7 additions & 7 deletions tests/playwright-test/ui-mode-test-watch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ test('should batch watch updates', async ({ runUITest, writeFiles }) => {
'd.test.ts': `import { test } from '@playwright/test'; test('test', () => {});`,
});

await expect(page.getByTestId('status-line')).toHaveText('4/4 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('4/4 (100%) — 4 passed');

await expect.poll(dumpTestTree(page)).toBe(`
▼ ✅ a.test.ts 👁
Expand Down Expand Up @@ -168,7 +168,7 @@ test('should watch all', async ({ runUITest, writeFiles }) => {
'd.test.ts': `import { test } from '@playwright/test'; test('test', () => {});`,
});

await expect(page.getByTestId('status-line')).toHaveText('2/2 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('2/2 (100%) — 2 passed');

await expect.poll(dumpTestTree(page)).toBe(`
▼ ✅ a.test.ts
Expand Down Expand Up @@ -211,7 +211,7 @@ test('should watch new file', async ({ runUITest, writeFiles }) => {
'b.test.ts': ` import { test } from '@playwright/test'; test('test', () => {});`,
});

await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');

await expect.poll(dumpTestTree(page)).toBe(`
▼ ◯ a.test.ts
Expand Down Expand Up @@ -277,7 +277,7 @@ test('should queue watches', async ({ runUITest, writeFiles, createLatch }) => {
await page.getByTitle('Watch all').click();
await page.getByTitle('Run all').click();

await expect(page.getByTestId('status-line')).toHaveText('Running 1/4 passed (25%)');
await expect(page.getByTestId('status-line')).toHaveText('Running 1/4 (25%) — 1 passed');

await writeFiles({
'a.test.ts': `import { test } from '@playwright/test'; test('test', () => {});`,
Expand All @@ -287,12 +287,12 @@ test('should queue watches', async ({ runUITest, writeFiles, createLatch }) => {

// Now watches should not kick in.
await new Promise(f => setTimeout(f, 1000));
await expect(page.getByTestId('status-line')).toHaveText('Running 1/4 passed (25%)');
await expect(page.getByTestId('status-line')).toHaveText('Running 1/4 (25%) — 1 passed');

// Allow test to finish and new watch to kick in.
latch.open();

await expect(page.getByTestId('status-line')).toHaveText('3/3 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('3/3 (100%) — 3 passed');
});

test('should not watch output', async ({ runUITest }) => {
Expand All @@ -317,7 +317,7 @@ test('should not watch output', async ({ runUITest }) => {

await page.getByTitle('Run all').click();

await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');
expect(commands).toContain('runTests');
expect(commands).not.toContain('listTests');
});
Expand Down
2 changes: 1 addition & 1 deletion tests/playwright-test/ui-mode-trace.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ test('should be able to create and dispose APIRequestContext inside Promise.all'
await page.getByText('create api request contexts').dblclick();
await expect(page.getByTestId('workbench-run-status')).toContainText('Passed');

await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
await expect(page.getByTestId('status-line')).toHaveText('1/1 (100%) — 1 passed');

await page.getByText('Errors', { exact: true }).click();
await expect(page.locator('.tab-errors')).toHaveText('No errors');
Expand Down
Loading