Skip to content

Commit 9e9f0d1

Browse files
committed
cherry-pick(#35062): do not compute git diff on non! PRs
1 parent 12835d6 commit 9e9f0d1

File tree

8 files changed

+129
-68
lines changed

8 files changed

+129
-68
lines changed

docs/src/test-api/class-testconfig.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,10 @@ export default defineConfig({
3939
## property: TestConfig.captureGitInfo
4040
* since: v1.51
4141
- type: ?<[Object]>
42-
- `commit` ?<boolean> Whether to capture commit information such as hash, author, timestamp.
42+
- `commit` ?<boolean> Whether to capture commit and pull request information such as hash, author, timestamp.
4343
- `diff` ?<boolean> Whether to capture commit diff.
4444

45-
* These settings control whether git information is captured and stored in the config [`property: TestConfig.metadata`].
46-
* The structure of the git commit metadata is subject to change.
47-
* Default values for these settings depend on the environment. When tests run as a part of CI where it is safe to obtain git information, the default value is true, false otherwise.
45+
These settings control whether git information is captured and stored in the config [`property: TestConfig.metadata`].
4846

4947
**Usage**
5048

@@ -56,6 +54,20 @@ export default defineConfig({
5654
});
5755
```
5856

57+
**Details**
58+
59+
* Capturing `commit` information is useful when you'd like to see it in your HTML (or a third party) report.
60+
* Capturing `diff` information is useful to enrich the report with the actual source diff. This information can be used to provide intelligent advice on how to fix the test.
61+
62+
:::note
63+
Default values for these settings depend on the environment. When tests run as a part of CI where it is safe to obtain git information, the default value is `true`, `false` otherwise.
64+
:::
65+
66+
:::note
67+
The structure of the git commit metadata is subject to change.
68+
:::
69+
70+
5971
## property: TestConfig.expect
6072
* since: v1.10
6173
- type: ?<[Object]>

packages/playwright/src/isomorphic/types.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ export type CIInfo = {
3636
commitHref: string;
3737
prHref?: string;
3838
prTitle?: string;
39+
prBaseHash?: string;
3940
buildHref?: string;
4041
commitHash?: string;
41-
baseHash?: string;
4242
branch?: string;
4343
};
4444

packages/playwright/src/plugins/gitCommitInfoPlugin.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,22 +71,19 @@ async function ciInfo(): Promise<CIInfo | undefined> {
7171

7272
return {
7373
commitHref: `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/commit/${process.env.GITHUB_SHA}`,
74+
commitHash: process.env.GITHUB_SHA,
7475
prHref: pr ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/pull/${pr.number}` : undefined,
75-
prTitle: pr ? pr.title : undefined,
76+
prTitle: pr?.title,
77+
prBaseHash: pr?.baseHash,
7678
buildHref: `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`,
77-
commitHash: process.env.GITHUB_SHA,
78-
baseHash: pr ? pr.baseHash : process.env.GITHUB_BASE_REF,
79-
branch: process.env.GITHUB_REF_NAME,
8079
};
8180
}
8281

8382
if (process.env.GITLAB_CI) {
8483
return {
8584
commitHref: `${process.env.CI_PROJECT_URL}/-/commit/${process.env.CI_COMMIT_SHA}`,
86-
prHref: process.env.CI_MERGE_REQUEST_IID ? `${process.env.CI_PROJECT_URL}/-/merge_requests/${process.env.CI_MERGE_REQUEST_IID}` : undefined,
87-
buildHref: process.env.CI_JOB_URL,
8885
commitHash: process.env.CI_COMMIT_SHA,
89-
baseHash: process.env.CI_COMMIT_BEFORE_SHA,
86+
buildHref: process.env.CI_JOB_URL,
9087
branch: process.env.CI_COMMIT_REF_NAME,
9188
};
9289
}
@@ -95,7 +92,6 @@ async function ciInfo(): Promise<CIInfo | undefined> {
9592
return {
9693
commitHref: process.env.BUILD_URL,
9794
commitHash: process.env.GIT_COMMIT,
98-
baseHash: process.env.GIT_PREVIOUS_COMMIT,
9995
branch: process.env.GIT_BRANCH,
10096
};
10197
}
@@ -144,13 +140,17 @@ async function gitCommitInfo(gitDir: string): Promise<GitCommitInfo | undefined>
144140

145141
async function gitDiff(gitDir: string, ci?: CIInfo): Promise<string | undefined> {
146142
const diffLimit = 100_000;
147-
if (ci?.baseHash) {
148-
// First try the diff against the base branch.
149-
const diff = await runGit(`git fetch origin ${ci.baseHash} && git diff ${ci.baseHash} HEAD`, gitDir);
143+
if (ci?.prBaseHash) {
144+
await runGit(`git fetch origin ${ci.prBaseHash}`, gitDir);
145+
const diff = await runGit(`git diff ${ci.prBaseHash} HEAD`, gitDir);
150146
if (diff)
151147
return diff.substring(0, diffLimit);
152148
}
153149

150+
// Do not attempt to diff on CI commit.
151+
if (ci)
152+
return;
153+
154154
// Check dirty state first.
155155
const uncommitted = await runGit('git diff', gitDir);
156156
if (uncommitted)

packages/playwright/src/prompt.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,24 @@ export async function attachErrorPrompts(testInfo: TestInfo, sourceCache: Map<st
3030
if (process.env.PLAYWRIGHT_NO_COPY_PROMPT)
3131
return;
3232

33+
const meaningfulSingleLineErrors = new Set(testInfo.errors.filter(e => e.message && !e.message.includes('\n')).map(e => e.message!));
34+
for (const error of testInfo.errors) {
35+
for (const singleLineError of meaningfulSingleLineErrors.keys()) {
36+
if (error.message?.includes(singleLineError))
37+
meaningfulSingleLineErrors.delete(singleLineError);
38+
}
39+
}
40+
3341
for (const [index, error] of testInfo.errors.entries()) {
42+
if (!error.message)
43+
return;
3444
if (testInfo.attachments.find(a => a.name === `_prompt-${index}`))
3545
continue;
3646

47+
// Skip errors that are just a single line - they are likely to already be the error message.
48+
if (!error.message.includes('\n') && !meaningfulSingleLineErrors.has(error.message))
49+
continue;
50+
3751
const metadata = testInfo.config.metadata as MetadataWithCommitInfo;
3852

3953
const promptParts = [

packages/playwright/types/test.d.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -960,11 +960,8 @@ interface TestConfig<TestArgs = {}, WorkerArgs = {}> {
960960
};
961961

962962
/**
963-
* - These settings control whether git information is captured and stored in the config
964-
* [testConfig.metadata](https://playwright.dev/docs/api/class-testconfig#test-config-metadata).
965-
* - The structure of the git commit metadata is subject to change.
966-
* - Default values for these settings depend on the environment. When tests run as a part of CI where it is safe to
967-
* obtain git information, the default value is true, false otherwise.
963+
* These settings control whether git information is captured and stored in the config
964+
* [testConfig.metadata](https://playwright.dev/docs/api/class-testconfig#test-config-metadata).
968965
*
969966
* **Usage**
970967
*
@@ -977,10 +974,20 @@ interface TestConfig<TestArgs = {}, WorkerArgs = {}> {
977974
* });
978975
* ```
979976
*
977+
* **Details**
978+
* - Capturing `commit` information is useful when you'd like to see it in your HTML (or a third party) report.
979+
* - Capturing `diff` information is useful to enrich the report with the actual source diff. This information can
980+
* be used to provide intelligent advice on how to fix the test.
981+
*
982+
* **NOTE** Default values for these settings depend on the environment. When tests run as a part of CI where it is
983+
* safe to obtain git information, the default value is `true`, `false` otherwise.
984+
*
985+
* **NOTE** The structure of the git commit metadata is subject to change.
986+
*
980987
*/
981988
captureGitInfo?: {
982989
/**
983-
* Whether to capture commit information such as hash, author, timestamp.
990+
* Whether to capture commit and pull request information such as hash, author, timestamp.
984991
*/
985992
commit?: boolean;
986993

tests/playwright-test/reporter-html.spec.ts

Lines changed: 73 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,10 +1232,7 @@ for (const useIntermediateMergeReport of [true, false] as const) {
12321232

12331233
const result = await runInlineTest(files, { reporter: 'dot,html' }, {
12341234
PLAYWRIGHT_HTML_OPEN: 'never',
1235-
GITHUB_ACTIONS: '1',
1236-
GITHUB_REPOSITORY: 'microsoft/playwright-example-for-test',
1237-
GITHUB_SERVER_URL: 'https://playwright.dev',
1238-
GITHUB_SHA: 'example-sha',
1235+
...ghaCommitEnv(),
12391236
});
12401237

12411238
await showReport();
@@ -1262,23 +1259,9 @@ for (const useIntermediateMergeReport of [true, false] as const) {
12621259
const baseDir = await writeFiles(files);
12631260
await initGitRepo(baseDir);
12641261

1265-
const eventPath = path.join(baseDir, 'event.json');
1266-
await fs.promises.writeFile(eventPath, JSON.stringify({
1267-
pull_request: {
1268-
title: 'My PR',
1269-
number: 42,
1270-
base: { ref: 'main' },
1271-
},
1272-
}));
1273-
12741262
const result = await runInlineTest(files, { reporter: 'dot,html' }, {
12751263
PLAYWRIGHT_HTML_OPEN: 'never',
1276-
GITHUB_ACTIONS: '1',
1277-
GITHUB_REPOSITORY: 'microsoft/playwright-example-for-test',
1278-
GITHUB_RUN_ID: 'example-run-id',
1279-
GITHUB_SERVER_URL: 'https://playwright.dev',
1280-
GITHUB_SHA: 'example-sha',
1281-
GITHUB_EVENT_PATH: eventPath,
1264+
...(await ghaPullRequestEnv(baseDir))
12821265
});
12831266

12841267
await showReport();
@@ -2746,31 +2729,34 @@ for (const useIntermediateMergeReport of [true, false] as const) {
27462729
await expect(page.locator('.tree-item', { hasText: 'stdout' })).toHaveCount(1);
27472730
});
27482731

2749-
test('should show AI prompt', async ({ runInlineTest, writeFiles, showReport, page }) => {
2732+
test('should include diff in AI prompt', async ({ runInlineTest, writeFiles, showReport, page }) => {
27502733
const files = {
27512734
'uncommitted.txt': `uncommitted file`,
27522735
'playwright.config.ts': `export default {}`,
27532736
'example.spec.ts': `
27542737
import { test, expect } from '@playwright/test';
27552738
test('sample', async ({ page }) => {
27562739
await page.setContent('<button>Click me</button>');
2757-
expect(2).toBe(3);
2740+
expect(2).toBe(2);
27582741
});
27592742
`,
27602743
};
27612744
const baseDir = await writeFiles(files);
27622745
await initGitRepo(baseDir);
2746+
await writeFiles({
2747+
'example.spec.ts': `
2748+
import { test, expect } from '@playwright/test';
2749+
test('sample', async ({ page }) => {
2750+
await page.setContent('<button>Click me</button>');
2751+
expect(2).toBe(3);
2752+
});`
2753+
});
2754+
await execGit(baseDir, ['checkout', '-b', 'pr_branch']);
2755+
await execGit(baseDir, ['commit', '-am', 'changes']);
27632756

2764-
const result = await runInlineTest(files, { reporter: 'dot,html' }, {
2757+
const result = await runInlineTest({}, { reporter: 'dot,html' }, {
27652758
PLAYWRIGHT_HTML_OPEN: 'never',
2766-
GITHUB_ACTIONS: '1',
2767-
GITHUB_REPOSITORY: 'microsoft/playwright-example-for-test',
2768-
GITHUB_RUN_ID: 'example-run-id',
2769-
GITHUB_SERVER_URL: 'https://playwright.dev',
2770-
GITHUB_SHA: 'example-sha',
2771-
GITHUB_REF_NAME: '42/merge',
2772-
GITHUB_BASE_REF: 'HEAD~1',
2773-
PLAYWRIGHT_COPY_PROMPT: '1',
2759+
...(await ghaPullRequestEnv(baseDir)),
27742760
});
27752761

27762762
expect(result.exitCode).toBe(1);
@@ -2786,6 +2772,24 @@ for (const useIntermediateMergeReport of [true, false] as const) {
27862772
expect(prompt, 'contains snapshot').toContain('- button "Click me"');
27872773
expect(prompt, 'contains diff').toContain(`+ expect(2).toBe(3);`);
27882774
});
2775+
2776+
test('should not show prompt for empty timeout error', async ({ runInlineTest, showReport, page }) => {
2777+
const result = await runInlineTest({
2778+
'uncommitted.txt': `uncommitted file`,
2779+
'playwright.config.ts': `export default {}`,
2780+
'example.spec.ts': `
2781+
import { test, expect } from '@playwright/test';
2782+
test('sample', async ({ page }) => {
2783+
test.setTimeout(2000);
2784+
await page.setChecked('input', true);
2785+
});
2786+
`,
2787+
}, { reporter: 'dot,html' }, { PLAYWRIGHT_HTML_OPEN: 'never' });
2788+
expect(result.exitCode).toBe(1);
2789+
await showReport();
2790+
await page.getByRole('link', { name: 'sample' }).click();
2791+
await expect(page.getByRole('button', { name: 'Copy prompt' })).toHaveCount(1);
2792+
});
27892793
});
27902794
}
27912795

@@ -2797,19 +2801,45 @@ function readAllFromStream(stream: NodeJS.ReadableStream): Promise<Buffer> {
27972801
});
27982802
}
27992803

2800-
async function initGitRepo(baseDir) {
2801-
const execGit = async (args: string[]) => {
2802-
const { code, stdout, stderr } = await spawnAsync('git', args, { stdio: 'pipe', cwd: baseDir });
2803-
if (!!code)
2804-
throw new Error(`Non-zero exit of:\n$ git ${args.join(' ')}\nConsole:\nstdout:\n${stdout}\n\nstderr:\n${stderr}\n\n`);
2805-
return;
2804+
async function execGit(baseDir: string, args: string[]) {
2805+
const { code, stdout, stderr } = await spawnAsync('git', args, { stdio: 'pipe', cwd: baseDir });
2806+
if (!!code)
2807+
throw new Error(`Non-zero exit of:\n$ git ${args.join(' ')}\nConsole:\nstdout:\n${stdout}\n\nstderr:\n${stderr}\n\n`);
2808+
return;
2809+
}
2810+
2811+
async function initGitRepo(baseDir: string) {
2812+
await execGit(baseDir, ['init']);
2813+
await execGit(baseDir, ['config', '--local', 'user.email', '[email protected]']);
2814+
await execGit(baseDir, ['config', '--local', 'user.name', 'William']);
2815+
await execGit(baseDir, ['checkout', '-b', 'main']);
2816+
await execGit(baseDir, ['add', 'playwright.config.ts']);
2817+
await execGit(baseDir, ['commit', '-m', 'init']);
2818+
await execGit(baseDir, ['add', '*.ts']);
2819+
await execGit(baseDir, ['commit', '-m', 'chore(html): make this test look nice']);
2820+
}
2821+
2822+
function ghaCommitEnv() {
2823+
return {
2824+
GITHUB_ACTIONS: '1',
2825+
GITHUB_REPOSITORY: 'microsoft/playwright-example-for-test',
2826+
GITHUB_SERVER_URL: 'https://playwright.dev',
2827+
GITHUB_SHA: 'example-sha',
28062828
};
2829+
}
28072830

2808-
await execGit(['init']);
2809-
await execGit(['config', '--local', 'user.email', '[email protected]']);
2810-
await execGit(['config', '--local', 'user.name', 'William']);
2811-
await execGit(['add', 'playwright.config.ts']);
2812-
await execGit(['commit', '-m', 'init']);
2813-
await execGit(['add', '*.ts']);
2814-
await execGit(['commit', '-m', 'chore(html): make this test look nice']);
2831+
async function ghaPullRequestEnv(baseDir: string) {
2832+
const eventPath = path.join(baseDir, 'event.json');
2833+
await fs.promises.writeFile(eventPath, JSON.stringify({
2834+
pull_request: {
2835+
title: 'My PR',
2836+
number: 42,
2837+
base: { sha: 'main' },
2838+
},
2839+
}));
2840+
return {
2841+
...ghaCommitEnv(),
2842+
GITHUB_RUN_ID: 'example-run-id',
2843+
GITHUB_EVENT_PATH: eventPath,
2844+
};
28152845
}

tests/playwright-test/ui-mode-llm.spec.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ test.fixme('openai', async ({ runUITest, server }) => {
4646
}, {
4747
EXPERIMENTAL_OPENAI_API_KEY: 'fake-key',
4848
OPENAI_BASE_URL: server.PREFIX,
49-
PLAYWRIGHT_COPY_PROMPT: '1',
5049
});
5150

5251
await page.getByTitle('Run all').click();
@@ -87,7 +86,6 @@ test.fixme('anthropic', async ({ runUITest, server }) => {
8786
}, {
8887
EXPERIMENTAL_ANTHROPIC_API_KEY: 'fake-key',
8988
ANTHROPIC_BASE_URL: server.PREFIX,
90-
PLAYWRIGHT_COPY_PROMPT: '1',
9189
});
9290

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

tests/playwright-test/ui-mode-trace.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ test('fails', async ({ page }) => {
508508
expect(1).toBe(2);
509509
});
510510
`.trim(),
511-
}, { PLAYWRIGHT_COPY_PROMPT: '1' });
511+
});
512512

513513
await page.getByText('fails').dblclick();
514514

0 commit comments

Comments
 (0)