mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore(ui): start adding ui mode tests (2) (#21608)
This commit is contained in:
parent
17498c30dc
commit
1d870ac407
@ -87,7 +87,8 @@ export async function showTraceViewer(traceUrls: string[], browserName: string,
|
||||
|
||||
if (traceViewerBrowser === 'chromium')
|
||||
await installAppIcon(page);
|
||||
await syncLocalStorageWithSettings(page, 'traceviewer');
|
||||
if (!isUnderTest())
|
||||
await syncLocalStorageWithSettings(page, 'traceviewer');
|
||||
|
||||
const params = traceUrls.map(t => `trace=${t}`);
|
||||
if (isUnderTest()) {
|
||||
|
||||
@ -62,7 +62,7 @@ class UIMode {
|
||||
projectDirs.add(p.testDir);
|
||||
let coalescingTimer: NodeJS.Timeout | undefined;
|
||||
const watcher = chokidar.watch([...projectDirs], { ignoreInitial: true, persistent: true }).on('all', async event => {
|
||||
if (event !== 'add' && event !== 'change')
|
||||
if (event !== 'add' && event !== 'change' && event !== 'unlink')
|
||||
return;
|
||||
if (coalescingTimer)
|
||||
clearTimeout(coalescingTimer);
|
||||
|
||||
@ -72,7 +72,7 @@
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.list-view-entry:not(.highlighted) .toolbar-button:not(.toggled) {
|
||||
.list-view-entry:not(.highlighted):not(.selected) .toolbar-button:not(.toggled) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
@ -149,7 +149,7 @@ export const WatchModeView: React.FC<{}> = ({
|
||||
<div className='vbox watch-mode-sidebar'>
|
||||
<Toolbar>
|
||||
<div className='section-title' style={{ cursor: 'pointer' }} onClick={() => setSettingsVisible(false)}>Tests</div>
|
||||
<ToolbarButton icon='play' title='Run' onClick={() => runTests(visibleTestIds)} disabled={isRunningTest}></ToolbarButton>
|
||||
<ToolbarButton icon='play' title='Run all' onClick={() => runTests(visibleTestIds)} disabled={isRunningTest}></ToolbarButton>
|
||||
<ToolbarButton icon='debug-stop' title='Stop' onClick={() => sendMessageNoReply('stop')} disabled={!isRunningTest}></ToolbarButton>
|
||||
<ToolbarButton icon='refresh' title='Reload' onClick={() => refreshRootSuite(true)} disabled={isRunningTest}></ToolbarButton>
|
||||
<div className='spacer'></div>
|
||||
@ -202,7 +202,7 @@ export const WatchModeView: React.FC<{}> = ({
|
||||
</div>;
|
||||
};
|
||||
|
||||
const TreeListView = TreeView<TreeItem>;
|
||||
const TestTreeView = TreeView<TreeItem>;
|
||||
|
||||
export const TestList: React.FC<{
|
||||
projects: Map<string, boolean>,
|
||||
@ -299,7 +299,7 @@ export const TestList: React.FC<{
|
||||
if (!isVisible)
|
||||
return <></>;
|
||||
|
||||
return <TreeListView
|
||||
return <TestTreeView
|
||||
treeState={treeState}
|
||||
setTreeState={setTreeState}
|
||||
rootItem={rootItem}
|
||||
@ -336,6 +336,7 @@ export const TestList: React.FC<{
|
||||
runningState.itemSelectedByUser = true;
|
||||
setSelectedTreeItemId(treeItem.id);
|
||||
}}
|
||||
autoExpandDeep={!!filterText}
|
||||
noItemsMessage='No tests' />;
|
||||
};
|
||||
|
||||
|
||||
@ -40,6 +40,7 @@ export type TreeViewProps<T> = {
|
||||
dataTestId?: string,
|
||||
treeState: TreeState,
|
||||
setTreeState: (treeState: TreeState) => void,
|
||||
autoExpandDeep?: boolean,
|
||||
};
|
||||
|
||||
const TreeListView = ListView<TreeItem>;
|
||||
@ -57,12 +58,13 @@ export function TreeView<T extends TreeItem>({
|
||||
setTreeState,
|
||||
noItemsMessage,
|
||||
dataTestId,
|
||||
autoExpandDeep,
|
||||
}: TreeViewProps<T>) {
|
||||
const treeItems = React.useMemo(() => {
|
||||
for (let item: TreeItem | undefined = selectedItem?.parent; item; item = item.parent)
|
||||
treeState.expandedItems.set(item.id, true);
|
||||
return flattenTree<T>(rootItem, treeState.expandedItems);
|
||||
}, [rootItem, selectedItem, treeState]);
|
||||
return flattenTree<T>(rootItem, treeState.expandedItems, autoExpandDeep);
|
||||
}, [rootItem, selectedItem, treeState, autoExpandDeep]);
|
||||
|
||||
return <TreeListView
|
||||
items={[...treeItems.keys()]}
|
||||
@ -126,12 +128,12 @@ type TreeItemData = {
|
||||
parent: TreeItem | null,
|
||||
};
|
||||
|
||||
function flattenTree<T extends TreeItem>(rootItem: T, expandedItems: Map<string, boolean | undefined>): Map<T, TreeItemData> {
|
||||
function flattenTree<T extends TreeItem>(rootItem: T, expandedItems: Map<string, boolean | undefined>, autoExpandDeep?: boolean): Map<T, TreeItemData> {
|
||||
const result = new Map<T, TreeItemData>();
|
||||
const appendChildren = (parent: T, depth: number) => {
|
||||
for (const item of parent.children as T[]) {
|
||||
const expandState = expandedItems.get(item.id);
|
||||
const autoExpandMatches = depth === 0 && result.size < 25 && expandState !== false;
|
||||
const autoExpandMatches = (autoExpandDeep || depth === 0) && result.size < 25 && expandState !== false;
|
||||
const expanded = item.children.length ? expandState || autoExpandMatches : undefined;
|
||||
result.set(item, { depth, expanded, parent: rootItem === parent ? null : parent });
|
||||
if (expanded)
|
||||
|
||||
@ -223,6 +223,7 @@ export type RunOptions = {
|
||||
};
|
||||
type Fixtures = {
|
||||
writeFiles: (files: Files) => Promise<string>;
|
||||
deleteFile: (file: string) => Promise<void>;
|
||||
runInlineTest: (files: Files, params?: Params, env?: NodeJS.ProcessEnv, options?: RunOptions) => Promise<RunResult>;
|
||||
runWatchTest: (files: Files, env?: NodeJS.ProcessEnv, options?: RunOptions) => Promise<TestChildProcess>;
|
||||
runTSC: (files: Files) => Promise<TSCResult>;
|
||||
@ -237,6 +238,13 @@ export const test = base
|
||||
await use(files => writeFiles(testInfo, files, false));
|
||||
},
|
||||
|
||||
deleteFile: async ({}, use, testInfo) => {
|
||||
await use(async file => {
|
||||
const baseDir = testInfo.outputPath();
|
||||
await fs.promises.unlink(path.join(baseDir, file));
|
||||
});
|
||||
},
|
||||
|
||||
runInlineTest: async ({ childProcess }, use, testInfo: TestInfo) => {
|
||||
const cacheDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'playwright-test-cache-'));
|
||||
await use(async (files: Files, params: Params = {}, env: NodeJS.ProcessEnv = {}, options: RunOptions = {}) => {
|
||||
|
||||
@ -38,10 +38,16 @@ export function dumpTestTree(page: Page): () => Promise<string> {
|
||||
return ' ';
|
||||
if (icon === 'circle-outline')
|
||||
return '◯';
|
||||
if (icon === 'circle-slash')
|
||||
return '⊘';
|
||||
if (icon === 'check')
|
||||
return '✅';
|
||||
if (icon === 'error')
|
||||
return '❌';
|
||||
if (icon === 'eye')
|
||||
return '👁';
|
||||
if (icon === 'loading')
|
||||
return '↻';
|
||||
return icon;
|
||||
}
|
||||
|
||||
@ -52,8 +58,9 @@ export function dumpTestTree(page: Page): () => Promise<string> {
|
||||
const treeIcon = iconName(iconElements[0]);
|
||||
const statusIcon = iconName(iconElements[1]);
|
||||
const indent = listItem.querySelectorAll('.list-view-indent').length;
|
||||
const watch = listItem.querySelector('.toolbar-button.eye.toggled') ? ' 👁' : '';
|
||||
const selected = listItem.classList.contains('selected') ? ' <=' : '';
|
||||
result.push(' ' + ' '.repeat(indent) + treeIcon + ' ' + statusIcon + ' ' + listItem.textContent + selected);
|
||||
result.push(' ' + ' '.repeat(indent) + treeIcon + ' ' + statusIcon + ' ' + listItem.textContent + watch + selected);
|
||||
}
|
||||
return '\n' + result.join('\n') + '\n ';
|
||||
});
|
||||
|
||||
99
tests/playwright-test/ui-mode-test-run.spec.ts
Normal file
99
tests/playwright-test/ui-mode-test-run.spec.ts
Normal file
@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { test, expect, dumpTestTree } from './ui-mode-fixtures';
|
||||
test.describe.configure({ mode: 'parallel' });
|
||||
|
||||
const basicTestTree = {
|
||||
'a.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', () => {});
|
||||
test('fails', () => { expect(1).toBe(2); });
|
||||
test.describe('suite', () => {
|
||||
test('inner passes', () => {});
|
||||
test('inner fails', () => { expect(1).toBe(2); });
|
||||
});
|
||||
`,
|
||||
'b.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', () => {});
|
||||
test('fails', () => { expect(1).toBe(2); });
|
||||
`,
|
||||
'c.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', () => {});
|
||||
test.skip('skipped', () => {});
|
||||
`,
|
||||
};
|
||||
|
||||
test('should run visible', async ({ runUITest }) => {
|
||||
const page = await runUITest(basicTestTree);
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toContain(`
|
||||
▼ ◯ a.test.ts
|
||||
`);
|
||||
|
||||
await page.getByTitle('Run all').click();
|
||||
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toBe(`
|
||||
▼ ❌ a.test.ts
|
||||
✅ passes
|
||||
❌ fails <=
|
||||
► ❌ suite
|
||||
▼ ❌ b.test.ts
|
||||
✅ passes
|
||||
❌ fails
|
||||
▼ ✅ c.test.ts
|
||||
✅ passes
|
||||
⊘ skipped
|
||||
`);
|
||||
});
|
||||
|
||||
test('should run on double click', async ({ runUITest }) => {
|
||||
const page = await runUITest({
|
||||
'a.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', () => {});
|
||||
test('fails', () => { expect(1).toBe(2); });
|
||||
`,
|
||||
});
|
||||
|
||||
await page.getByText('passes').dblclick();
|
||||
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toBe(`
|
||||
▼ ◯ a.test.ts
|
||||
✅ passes <=
|
||||
◯ fails
|
||||
`);
|
||||
});
|
||||
|
||||
test('should run on Enter', async ({ runUITest }) => {
|
||||
const page = await runUITest({
|
||||
'a.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', () => {});
|
||||
test('fails', () => { expect(1).toBe(2); });
|
||||
`,
|
||||
});
|
||||
|
||||
await page.getByText('fails').click();
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toBe(`
|
||||
▼ ❌ a.test.ts
|
||||
◯ passes
|
||||
❌ fails <=
|
||||
`);
|
||||
});
|
||||
@ -37,7 +37,7 @@ const basicTestTree = {
|
||||
|
||||
test('should list tests', async ({ runUITest }) => {
|
||||
const page = await runUITest(basicTestTree);
|
||||
await expect.poll(dumpTestTree(page)).toBe(`
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toBe(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
@ -51,7 +51,7 @@ test('should list tests', async ({ runUITest }) => {
|
||||
test('should traverse up/down', async ({ runUITest }) => {
|
||||
const page = await runUITest(basicTestTree);
|
||||
await page.getByText('a.test.ts').click();
|
||||
await expect.poll(dumpTestTree(page)).toContain(`
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toContain(`
|
||||
▼ ◯ a.test.ts <=
|
||||
◯ passes
|
||||
◯ fails
|
||||
@ -59,14 +59,14 @@ test('should traverse up/down', async ({ runUITest }) => {
|
||||
`);
|
||||
|
||||
await page.keyboard.press('ArrowDown');
|
||||
await expect.poll(dumpTestTree(page)).toContain(`
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toContain(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ passes <=
|
||||
◯ fails
|
||||
► ◯ suite
|
||||
`);
|
||||
await page.keyboard.press('ArrowDown');
|
||||
await expect.poll(dumpTestTree(page)).toContain(`
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toContain(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ passes
|
||||
◯ fails <=
|
||||
@ -74,7 +74,7 @@ test('should traverse up/down', async ({ runUITest }) => {
|
||||
`);
|
||||
|
||||
await page.keyboard.press('ArrowUp');
|
||||
await expect.poll(dumpTestTree(page)).toContain(`
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toContain(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ passes <=
|
||||
◯ fails
|
||||
@ -87,7 +87,7 @@ test('should expand / collapse groups', async ({ runUITest }) => {
|
||||
|
||||
await page.getByText('suite').click();
|
||||
await page.keyboard.press('ArrowRight');
|
||||
await expect.poll(dumpTestTree(page)).toContain(`
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toContain(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
@ -97,7 +97,7 @@ test('should expand / collapse groups', async ({ runUITest }) => {
|
||||
`);
|
||||
|
||||
await page.keyboard.press('ArrowLeft');
|
||||
await expect.poll(dumpTestTree(page)).toContain(`
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toContain(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
@ -106,14 +106,25 @@ test('should expand / collapse groups', async ({ runUITest }) => {
|
||||
|
||||
await page.getByText('passes').first().click();
|
||||
await page.keyboard.press('ArrowLeft');
|
||||
await expect.poll(dumpTestTree(page)).toContain(`
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toContain(`
|
||||
▼ ◯ a.test.ts <=
|
||||
◯ passes
|
||||
◯ fails
|
||||
`);
|
||||
|
||||
await page.keyboard.press('ArrowLeft');
|
||||
await expect.poll(dumpTestTree(page)).toContain(`
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toContain(`
|
||||
► ◯ a.test.ts <=
|
||||
`);
|
||||
});
|
||||
|
||||
test('should filter by title', async ({ runUITest }) => {
|
||||
const page = await runUITest(basicTestTree);
|
||||
await page.getByPlaceholder('Filter').fill('inner');
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toBe(`
|
||||
▼ ◯ a.test.ts
|
||||
▼ ◯ suite
|
||||
◯ inner passes
|
||||
◯ inner fails
|
||||
`);
|
||||
});
|
||||
|
||||
170
tests/playwright-test/ui-mode-test-update.spec.ts
Normal file
170
tests/playwright-test/ui-mode-test-update.spec.ts
Normal file
@ -0,0 +1,170 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { test, expect, dumpTestTree } from './ui-mode-fixtures';
|
||||
|
||||
test.describe.configure({ mode: 'parallel' });
|
||||
|
||||
const basicTestTree = {
|
||||
'a.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', () => {});
|
||||
test('fails', () => {});
|
||||
test.describe('suite', () => {
|
||||
test('inner passes', () => {});
|
||||
test('inner fails', () => {});
|
||||
});
|
||||
`,
|
||||
'b.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', () => {});
|
||||
test('fails', () => {});
|
||||
`,
|
||||
};
|
||||
|
||||
test('should pick new / deleted files', async ({ runUITest, writeFiles, deleteFile }) => {
|
||||
const page = await runUITest(basicTestTree);
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toBe(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
► ◯ suite
|
||||
▼ ◯ b.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
`);
|
||||
|
||||
await writeFiles({
|
||||
'c.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', () => {});
|
||||
test('fails', () => {});
|
||||
`
|
||||
});
|
||||
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toBe(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
► ◯ suite
|
||||
▼ ◯ b.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
▼ ◯ c.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
`);
|
||||
|
||||
await deleteFile('a.test.ts');
|
||||
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toBe(`
|
||||
▼ ◯ b.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
▼ ◯ c.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
`);
|
||||
});
|
||||
|
||||
test('should pick new / deleted tests', async ({ runUITest, writeFiles, deleteFile }) => {
|
||||
const page = await runUITest(basicTestTree);
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toBe(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
► ◯ suite
|
||||
▼ ◯ b.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
`);
|
||||
|
||||
await writeFiles({
|
||||
'a.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', () => {});
|
||||
test('new', () => {});
|
||||
test('fails', () => {});
|
||||
`
|
||||
});
|
||||
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toBe(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ passes
|
||||
◯ new
|
||||
◯ fails
|
||||
▼ ◯ b.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
`);
|
||||
|
||||
await deleteFile('a.test.ts');
|
||||
|
||||
await writeFiles({
|
||||
'a.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('new', () => {});
|
||||
`
|
||||
});
|
||||
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toBe(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ new
|
||||
▼ ◯ b.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
`);
|
||||
});
|
||||
|
||||
test('should pick new / deleted nested tests', async ({ runUITest, writeFiles, deleteFile }) => {
|
||||
const page = await runUITest(basicTestTree);
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toContain(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
► ◯ suite
|
||||
`);
|
||||
|
||||
await page.getByText('suite').click();
|
||||
await page.keyboard.press('ArrowRight');
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toContain(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ passes
|
||||
◯ fails
|
||||
▼ ◯ suite <=
|
||||
◯ inner passes
|
||||
◯ inner fails
|
||||
`);
|
||||
|
||||
await writeFiles({
|
||||
'a.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', () => {});
|
||||
test.describe('suite', () => {
|
||||
test('inner new', () => {});
|
||||
test('inner fails', () => {});
|
||||
});
|
||||
`
|
||||
});
|
||||
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toContain(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ passes
|
||||
▼ ◯ suite <=
|
||||
◯ inner new
|
||||
◯ inner fails
|
||||
`);
|
||||
});
|
||||
53
tests/playwright-test/ui-mode-test-watch.spec.ts
Normal file
53
tests/playwright-test/ui-mode-test-watch.spec.ts
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { test, expect, dumpTestTree } from './ui-mode-fixtures';
|
||||
|
||||
test.describe.configure({ mode: 'parallel' });
|
||||
|
||||
test('should watch files', async ({ runUITest, writeFiles }) => {
|
||||
const page = await runUITest({
|
||||
'a.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', () => {});
|
||||
test('fails', () => { expect(1).toBe(2); });
|
||||
`,
|
||||
});
|
||||
|
||||
await page.getByText('fails').click();
|
||||
await page.getByRole('listitem').filter({ hasText: 'fails' }).getByTitle('Watch').click();
|
||||
await page.getByRole('listitem').filter({ hasText: 'fails' }).getByTitle('Run').click();
|
||||
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toBe(`
|
||||
▼ ❌ a.test.ts
|
||||
◯ passes
|
||||
❌ fails 👁 <=
|
||||
`);
|
||||
|
||||
await writeFiles({
|
||||
'a.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', () => {});
|
||||
test('fails', () => { expect(1).toBe(1); });
|
||||
`
|
||||
});
|
||||
|
||||
await expect.poll(dumpTestTree(page), { timeout: 0 }).toBe(`
|
||||
▼ ◯ a.test.ts
|
||||
◯ passes
|
||||
✅ fails 👁 <=
|
||||
`);
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user