chore(ui-mode): expand all button (#32994)

<img width="230" alt="image"
src="https://github.com/user-attachments/assets/dd7fa3a1-39ec-4b88-9279-d664c9c4e5cd">


Reference https://github.com/microsoft/playwright/issues/32825
This commit is contained in:
Yury Semikhatsky 2024-10-07 15:42:12 -07:00 committed by GitHub
parent 4d13677ebd
commit 6ba5ee3a83
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 45 additions and 2 deletions

View file

@ -47,12 +47,14 @@ export const TestListView: React.FC<{
isLoading?: boolean, isLoading?: boolean,
onItemSelected: (item: { treeItem?: TreeItem, testCase?: reporterTypes.TestCase, testFile?: SourceLocation }) => void, onItemSelected: (item: { treeItem?: TreeItem, testCase?: reporterTypes.TestCase, testFile?: SourceLocation }) => void,
requestedCollapseAllCount: number, requestedCollapseAllCount: number,
requestedExpandAllCount: number,
setFilterText: (text: string) => void, setFilterText: (text: string) => void,
onRevealSource: () => void, onRevealSource: () => void,
}> = ({ filterText, testModel, testServerConnection, testTree, runTests, runningState, watchAll, watchedTreeIds, setWatchedTreeIds, isLoading, onItemSelected, requestedCollapseAllCount, setFilterText, onRevealSource }) => { }> = ({ filterText, testModel, testServerConnection, testTree, runTests, runningState, watchAll, watchedTreeIds, setWatchedTreeIds, isLoading, onItemSelected, requestedCollapseAllCount, requestedExpandAllCount, setFilterText, onRevealSource }) => {
const [treeState, setTreeState] = React.useState<TreeState>({ expandedItems: new Map() }); const [treeState, setTreeState] = React.useState<TreeState>({ expandedItems: new Map() });
const [selectedTreeItemId, setSelectedTreeItemId] = React.useState<string | undefined>(); const [selectedTreeItemId, setSelectedTreeItemId] = React.useState<string | undefined>();
const [collapseAllCount, setCollapseAllCount] = React.useState(requestedCollapseAllCount); const [collapseAllCount, setCollapseAllCount] = React.useState(requestedCollapseAllCount);
const [expandAllCount, setExpandAllCount] = React.useState(requestedExpandAllCount);
// Look for a first failure within the run batch to select it. // Look for a first failure within the run batch to select it.
React.useEffect(() => { React.useEffect(() => {
@ -67,6 +69,16 @@ export const TestListView: React.FC<{
return; return;
} }
if (expandAllCount !== requestedExpandAllCount) {
treeState.expandedItems.clear();
for (const item of testTree.flatTreeItems())
treeState.expandedItems.set(item.id, true);
setExpandAllCount(requestedExpandAllCount);
setSelectedTreeItemId(undefined);
setTreeState({ ...treeState });
return;
}
if (!runningState || runningState.itemSelectedByUser) if (!runningState || runningState.itemSelectedByUser)
return; return;
let selectedTreeItem: TreeItem | undefined; let selectedTreeItem: TreeItem | undefined;
@ -85,7 +97,7 @@ export const TestListView: React.FC<{
if (selectedTreeItem) if (selectedTreeItem)
setSelectedTreeItemId(selectedTreeItem.id); setSelectedTreeItemId(selectedTreeItem.id);
}, [runningState, setSelectedTreeItemId, testTree, collapseAllCount, setCollapseAllCount, requestedCollapseAllCount, treeState, setTreeState]); }, [runningState, setSelectedTreeItemId, testTree, collapseAllCount, setCollapseAllCount, requestedCollapseAllCount, expandAllCount, setExpandAllCount, requestedExpandAllCount, treeState, setTreeState]);
// Compute selected item. // Compute selected item.
const { selectedTreeItem } = React.useMemo(() => { const { selectedTreeItem } = React.useMemo(() => {

View file

@ -90,6 +90,7 @@ export const UIModeView: React.FC<{}> = ({
const commandQueue = React.useRef(Promise.resolve()); const commandQueue = React.useRef(Promise.resolve());
const runTestBacklog = React.useRef<Set<string>>(new Set()); const runTestBacklog = React.useRef<Set<string>>(new Set());
const [collapseAllCount, setCollapseAllCount] = React.useState(0); const [collapseAllCount, setCollapseAllCount] = React.useState(0);
const [expandAllCount, setExpandAllCount] = React.useState(0);
const [isDisconnected, setIsDisconnected] = React.useState(false); const [isDisconnected, setIsDisconnected] = React.useState(false);
const [hasBrowsers, setHasBrowsers] = React.useState(true); const [hasBrowsers, setHasBrowsers] = React.useState(true);
const [testServerConnection, setTestServerConnection] = React.useState<TestServerConnection>(); const [testServerConnection, setTestServerConnection] = React.useState<TestServerConnection>();
@ -473,6 +474,9 @@ export const UIModeView: React.FC<{}> = ({
<ToolbarButton icon='collapse-all' title='Collapse all' onClick={() => { <ToolbarButton icon='collapse-all' title='Collapse all' onClick={() => {
setCollapseAllCount(collapseAllCount + 1); setCollapseAllCount(collapseAllCount + 1);
}} /> }} />
<ToolbarButton icon='expand-all' title='Expand all' onClick={() => {
setExpandAllCount(expandAllCount + 1);
}} />
</Toolbar> </Toolbar>
<TestListView <TestListView
filterText={filterText} filterText={filterText}
@ -487,6 +491,7 @@ export const UIModeView: React.FC<{}> = ({
setWatchedTreeIds={setWatchedTreeIds} setWatchedTreeIds={setWatchedTreeIds}
isLoading={isLoading} isLoading={isLoading}
requestedCollapseAllCount={collapseAllCount} requestedCollapseAllCount={collapseAllCount}
requestedExpandAllCount={expandAllCount}
setFilterText={setFilterText} setFilterText={setFilterText}
onRevealSource={onRevealSource} onRevealSource={onRevealSource}
/> />

View file

@ -297,6 +297,32 @@ test('should collapse all', async ({ runUITest }) => {
`); `);
}); });
test('should expand all', {
annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32825' }
}, async ({ runUITest }) => {
const { page } = await runUITest(basicTestTree);
await page.getByTestId('test-tree').getByText('suite').click();
await page.getByTitle('Collapse all').click();
await expect.poll(dumpTestTree(page)).toContain(`
a.test.ts
b.test.ts
`);
await page.getByTitle('Expand all').click();
await expect.poll(dumpTestTree(page)).toContain(`
a.test.ts
passes
fails
suite
inner passes
inner fails
b.test.ts
passes
fails
`);
});
test('should resolve title conflicts', async ({ runUITest }) => { test('should resolve title conflicts', async ({ runUITest }) => {
const { page } = await runUITest({ const { page } = await runUITest({
'a.test.ts': ` 'a.test.ts': `