chore(html-reporter): show project name always for the test file (#19905)
Fixes https://github.com/microsoft/playwright/issues/19874
This commit is contained in:
parent
db5087e951
commit
e2a2196e6a
|
|
@ -28,7 +28,7 @@ test('should render counters', async ({ mount }) => {
|
||||||
skipped: 10,
|
skipped: 10,
|
||||||
ok: false,
|
ok: false,
|
||||||
duration: 100000
|
duration: 100000
|
||||||
}} filterText='' setFilterText={() => {}}></HeaderView>);
|
}} filterText='' setFilterText={() => {}} projectNames={[]}></HeaderView>);
|
||||||
await expect(component.locator('a', { hasText: 'All' }).locator('.counter')).toHaveText('100');
|
await expect(component.locator('a', { hasText: 'All' }).locator('.counter')).toHaveText('100');
|
||||||
await expect(component.locator('a', { hasText: 'Passed' }).locator('.counter')).toHaveText('42');
|
await expect(component.locator('a', { hasText: 'Passed' }).locator('.counter')).toHaveText('42');
|
||||||
await expect(component.locator('a', { hasText: 'Failed' }).locator('.counter')).toHaveText('31');
|
await expect(component.locator('a', { hasText: 'Failed' }).locator('.counter')).toHaveText('31');
|
||||||
|
|
@ -36,7 +36,7 @@ test('should render counters', async ({ mount }) => {
|
||||||
await expect(component.locator('a', { hasText: 'Skipped' }).locator('.counter')).toHaveText('10');
|
await expect(component.locator('a', { hasText: 'Skipped' }).locator('.counter')).toHaveText('10');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should toggle filters', async ({ page, mount: mount }) => {
|
test('should toggle filters', async ({ page, mount }) => {
|
||||||
const filters: string[] = [];
|
const filters: string[] = [];
|
||||||
const component = await mount(<HeaderView
|
const component = await mount(<HeaderView
|
||||||
stats={{
|
stats={{
|
||||||
|
|
@ -49,7 +49,9 @@ test('should toggle filters', async ({ page, mount: mount }) => {
|
||||||
duration: 100000
|
duration: 100000
|
||||||
}}
|
}}
|
||||||
filterText=''
|
filterText=''
|
||||||
setFilterText={(filterText: string) => filters.push(filterText)}>
|
setFilterText={(filterText: string) => filters.push(filterText)}
|
||||||
|
projectNames={[]}
|
||||||
|
>
|
||||||
</HeaderView>);
|
</HeaderView>);
|
||||||
await component.locator('a', { hasText: 'All' }).click();
|
await component.locator('a', { hasText: 'All' }).click();
|
||||||
await component.locator('a', { hasText: 'Passed' }).click();
|
await component.locator('a', { hasText: 'Passed' }).click();
|
||||||
|
|
@ -62,3 +64,36 @@ test('should toggle filters', async ({ page, mount: mount }) => {
|
||||||
await expect(page).toHaveURL(/#\?q=s:skipped/);
|
await expect(page).toHaveURL(/#\?q=s:skipped/);
|
||||||
expect(filters).toEqual(['', 's:passed', 's:failed', 's:flaky', 's:skipped']);
|
expect(filters).toEqual(['', 's:passed', 's:failed', 's:flaky', 's:skipped']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should show the project names', async ({ mount }) => {
|
||||||
|
const stats = {
|
||||||
|
total: 100,
|
||||||
|
expected: 42,
|
||||||
|
unexpected: 31,
|
||||||
|
flaky: 17,
|
||||||
|
skipped: 10,
|
||||||
|
ok: false,
|
||||||
|
duration: 100000
|
||||||
|
};
|
||||||
|
await test.step('with 1 project', async () => {
|
||||||
|
const component = await mount(<HeaderView
|
||||||
|
stats={stats}
|
||||||
|
filterText=''
|
||||||
|
setFilterText={() => {}}
|
||||||
|
projectNames={['my-project']}
|
||||||
|
>
|
||||||
|
</HeaderView>);
|
||||||
|
await expect(component.getByText('Project: my-project')).toBeVisible();
|
||||||
|
});
|
||||||
|
await test.step('with more than 1 project', async () => {
|
||||||
|
const component = await mount(<HeaderView
|
||||||
|
stats={stats}
|
||||||
|
filterText=''
|
||||||
|
setFilterText={() => {}}
|
||||||
|
projectNames={['great-project', 'my-project']}
|
||||||
|
>
|
||||||
|
</HeaderView>);
|
||||||
|
await expect(component.getByText('my-project')).toBeHidden();
|
||||||
|
await expect(component.getByText('great-project')).toBeHidden();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@ export const HeaderView: React.FC<React.PropsWithChildren<{
|
||||||
stats: Stats,
|
stats: Stats,
|
||||||
filterText: string,
|
filterText: string,
|
||||||
setFilterText: (filterText: string) => void,
|
setFilterText: (filterText: string) => void,
|
||||||
}>> = ({ stats, filterText, setFilterText }) => {
|
projectNames: string[],
|
||||||
|
}>> = ({ stats, filterText, setFilterText, projectNames }) => {
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
window.addEventListener('popstate', () => {
|
window.addEventListener('popstate', () => {
|
||||||
|
|
@ -56,7 +57,10 @@ export const HeaderView: React.FC<React.PropsWithChildren<{
|
||||||
}}></input>
|
}}></input>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div className='pt-2'><span data-testid="overall-duration" style={{ color: 'var(--color-fg-subtle)', paddingRight: '10px', float: 'right' }}>Total time: {msToString(stats.duration)}</span></div>
|
<div className='pt-2'>
|
||||||
|
{projectNames.length === 1 && <span data-testid="project-name" style={{ color: 'var(--color-fg-subtle)', float: 'left' }}>Project: {projectNames[0]}</span>}
|
||||||
|
<span data-testid="overall-duration" style={{ color: 'var(--color-fg-subtle)', paddingRight: '10px', float: 'right' }}>Total time: {msToString(stats.duration)}</span>
|
||||||
|
</div>
|
||||||
</>);
|
</>);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,13 +74,13 @@ const InnerMetadataView: React.FC<Metainfo> = metadata => {
|
||||||
{metadata['revision.subject'] || 'Commit Metainfo'}
|
{metadata['revision.subject'] || 'Commit Metainfo'}
|
||||||
</span>} initialExpanded={false} dataTestId='metadata-chip'>
|
</span>} initialExpanded={false} dataTestId='metadata-chip'>
|
||||||
{metadata['revision.subject'] &&
|
{metadata['revision.subject'] &&
|
||||||
<MetadatViewItem
|
<MetadataViewItem
|
||||||
testId='revision.subject'
|
testId='revision.subject'
|
||||||
content={<span>{metadata['revision.subject']}</span>}
|
content={<span>{metadata['revision.subject']}</span>}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
{metadata['revision.id'] &&
|
{metadata['revision.id'] &&
|
||||||
<MetadatViewItem
|
<MetadataViewItem
|
||||||
testId='revision.id'
|
testId='revision.id'
|
||||||
content={<span>{metadata['revision.id']}</span>}
|
content={<span>{metadata['revision.id']}</span>}
|
||||||
href={metadata['revision.link']}
|
href={metadata['revision.link']}
|
||||||
|
|
@ -88,13 +88,13 @@ const InnerMetadataView: React.FC<Metainfo> = metadata => {
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
{(metadata['revision.author'] || metadata['revision.email']) &&
|
{(metadata['revision.author'] || metadata['revision.email']) &&
|
||||||
<MetadatViewItem
|
<MetadataViewItem
|
||||||
content={`${metadata['revision.author']} ${metadata['revision.email']}`}
|
content={`${metadata['revision.author']} ${metadata['revision.email']}`}
|
||||||
icon='person'
|
icon='person'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
{metadata['revision.timestamp'] &&
|
{metadata['revision.timestamp'] &&
|
||||||
<MetadatViewItem
|
<MetadataViewItem
|
||||||
testId='revision.timestamp'
|
testId='revision.timestamp'
|
||||||
content={
|
content={
|
||||||
<>
|
<>
|
||||||
|
|
@ -107,23 +107,23 @@ const InnerMetadataView: React.FC<Metainfo> = metadata => {
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
{metadata['ci.link'] &&
|
{metadata['ci.link'] &&
|
||||||
<MetadatViewItem
|
<MetadataViewItem
|
||||||
content='CI/CD Logs'
|
content='CI/CD Logs'
|
||||||
href={metadata['ci.link']}
|
href={metadata['ci.link']}
|
||||||
icon='externalLink'
|
icon='externalLink'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
{metadata['timestamp'] &&
|
{metadata['timestamp'] &&
|
||||||
<MetadatViewItem
|
<MetadataViewItem
|
||||||
content={<span style={{ color: 'var(--color-fg-subtle)' }}>
|
content={<span style={{ color: 'var(--color-fg-subtle)' }}>
|
||||||
Report generated on {Intl.DateTimeFormat(undefined, { dateStyle: 'full', timeStyle: 'long' }).format(metadata['timestamp'])}
|
Report generated on {Intl.DateTimeFormat(undefined, { dateStyle: 'full', timeStyle: 'long' }).format(metadata['timestamp'])}
|
||||||
</span>}></MetadatViewItem>
|
</span>}></MetadataViewItem>
|
||||||
}
|
}
|
||||||
</AutoChip>
|
</AutoChip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const MetadatViewItem: React.FC<{ content: JSX.Element | string; icon?: keyof typeof icons, href?: string, testId?: string }> = ({ content, icon, href, testId }) => {
|
const MetadataViewItem: React.FC<{ content: JSX.Element | string; icon?: keyof typeof icons, href?: string, testId?: string }> = ({ content, icon, href, testId }) => {
|
||||||
return (
|
return (
|
||||||
<div className='my-1 hbox' data-test-id={testId} >
|
<div className='my-1 hbox' data-test-id={testId} >
|
||||||
<div className='mr-2'>
|
<div className='mr-2'>
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ export const ReportView: React.FC<{
|
||||||
|
|
||||||
return <div className='htmlreport vbox px-4 pb-4'>
|
return <div className='htmlreport vbox px-4 pb-4'>
|
||||||
<main>
|
<main>
|
||||||
{report?.json() && <HeaderView stats={report.json().stats} filterText={filterText} setFilterText={setFilterText}></HeaderView>}
|
{report?.json() && <HeaderView stats={report.json().stats} filterText={filterText} setFilterText={setFilterText} projectNames={report.json().projectNames}></HeaderView>}
|
||||||
{report?.json().metadata && <MetadataView {...report?.json().metadata as Metainfo} />}
|
{report?.json().metadata && <MetadataView {...report?.json().metadata as Metainfo} />}
|
||||||
<Route predicate={testFilesRoutePredicate}>
|
<Route predicate={testFilesRoutePredicate}>
|
||||||
<TestFilesView report={report?.json()} filter={filter} expandedFiles={expandedFiles} setExpandedFiles={setExpandedFiles}></TestFilesView>
|
<TestFilesView report={report?.json()} filter={filter} expandedFiles={expandedFiles} setExpandedFiles={setExpandedFiles}></TestFilesView>
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ test('should generate report', async ({ runInlineTest, showReport, page }) => {
|
||||||
await expect(page.locator('.test-file-test-outcome-skipped >> text=skipped')).toBeVisible();
|
await expect(page.locator('.test-file-test-outcome-skipped >> text=skipped')).toBeVisible();
|
||||||
|
|
||||||
await expect(page.getByTestId('overall-duration'), 'should contain humanized total time with at most 1 decimal place').toContainText(/^Total time: \d+(\.\d)?(ms|s|m)$/);
|
await expect(page.getByTestId('overall-duration'), 'should contain humanized total time with at most 1 decimal place').toContainText(/^Total time: \d+(\.\d)?(ms|s|m)$/);
|
||||||
|
await expect(page.getByTestId('project-name'), 'should contain project name').toContainText('project-name');
|
||||||
|
|
||||||
await expect(page.locator('.metadata-view')).not.toBeVisible();
|
await expect(page.locator('.metadata-view')).not.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue