chore: clean up git commit metadata props and UI (#34867)
This commit is contained in:
		
							parent
							
								
									b148cbad76
								
							
						
					
					
						commit
						411f938296
					
				|  | @ -239,7 +239,7 @@ export default defineConfig({ | |||
| 
 | ||||
| Metadata contains key-value pairs to be included in the report. For example, HTML report will display it as key-value pairs, and JSON report will include metadata serialized as json. | ||||
| 
 | ||||
| See also [`property: TestConfig.populateGitInfo`] that populates metadata. | ||||
| Providing `'git.commit.info': {}` property will populate it with the git commit details. This is useful for CI/CD environments. | ||||
| 
 | ||||
| **Usage** | ||||
| 
 | ||||
|  | @ -326,26 +326,6 @@ This path will serve as the base directory for each test file snapshot directory | |||
| ## property: TestConfig.snapshotPathTemplate = %%-test-config-snapshot-path-template-%% | ||||
| * since: v1.28 | ||||
| 
 | ||||
| ## property: TestConfig.populateGitInfo | ||||
| * since: v1.51 | ||||
| - type: ?<[boolean]> | ||||
| 
 | ||||
| Whether to populate `'git.commit.info'` field of the [`property: TestConfig.metadata`] with Git commit info and CI/CD information. | ||||
| 
 | ||||
| This information will appear in the HTML and JSON reports and is available in the Reporter API. | ||||
| 
 | ||||
| On Github Actions, this feature is enabled by default. | ||||
| 
 | ||||
| **Usage** | ||||
| 
 | ||||
| ```js title="playwright.config.ts" | ||||
| import { defineConfig } from '@playwright/test'; | ||||
| 
 | ||||
| export default defineConfig({ | ||||
|   populateGitInfo: !!process.env.CI, | ||||
| }); | ||||
| ``` | ||||
| 
 | ||||
| ## property: TestConfig.preserveOutput | ||||
| * since: v1.10 | ||||
| - type: ?<[PreserveOutput]<"always"|"never"|"failures-only">> | ||||
|  |  | |||
|  | @ -37,10 +37,6 @@ | |||
|   line-height: 24px; | ||||
| } | ||||
| 
 | ||||
| .metadata-section { | ||||
|   align-items: center; | ||||
| } | ||||
| 
 | ||||
| .metadata-properties { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|  | @ -57,9 +53,8 @@ | |||
|   border-bottom: 1px solid var(--color-border-default); | ||||
| } | ||||
| 
 | ||||
| .git-commit-info a { | ||||
| .metadata-view a { | ||||
|   color: var(--color-fg-default); | ||||
|   font-weight: 600; | ||||
| } | ||||
| 
 | ||||
| .copyable-property { | ||||
|  |  | |||
|  | @ -87,12 +87,12 @@ const InnerMetadataView = () => { | |||
|       <GitCommitInfoView info={gitCommitInfo}/> | ||||
|       {entries.length > 0 && <div className='metadata-separator' />} | ||||
|     </>} | ||||
|     <div className='metadata-section metadata-properties'> | ||||
|     <div className='metadata-section metadata-properties' role='list'> | ||||
|       {entries.map(([propertyName, value]) => { | ||||
|         const valueString = typeof value !== 'object' || value === null || value === undefined ? String(value) : JSON.stringify(value); | ||||
|         const trimmedValue = valueString.length > 1000 ? valueString.slice(0, 1000) + '\u2026' : valueString; | ||||
|         return ( | ||||
|           <div key={propertyName} className='copyable-property'> | ||||
|           <div key={propertyName} className='copyable-property' role='listitem'> | ||||
|             <CopyToClipboardContainer value={valueString}> | ||||
|               <span style={{ fontWeight: 'bold' }} title={propertyName}>{propertyName}</span> | ||||
|               : <span title={trimmedValue}>{linkifyText(trimmedValue)}</span> | ||||
|  | @ -105,47 +105,38 @@ const InnerMetadataView = () => { | |||
| }; | ||||
| 
 | ||||
| const GitCommitInfoView: React.FC<{ info: GitCommitInfo }> = ({ info }) => { | ||||
|   const email = info['revision.email'] ? ` <${info['revision.email']}>` : ''; | ||||
|   const author = `${info['revision.author'] || ''}${email}`; | ||||
|   const email = info.revision?.email ? ` <${info.revision?.email}>` : ''; | ||||
|   const author = `${info.revision?.author || ''}${email}`; | ||||
| 
 | ||||
|   let subject = info['revision.subject'] || ''; | ||||
|   let link = info['revision.link']; | ||||
|   let shortSubject = info['revision.id']?.slice(0, 7) || 'unknown'; | ||||
|   let subject = info.revision?.subject || ''; | ||||
|   let link = info.revision?.link; | ||||
| 
 | ||||
|   if (info['pull.link'] && info['pull.title']) { | ||||
|     subject = info['pull.title']; | ||||
|     link = info['pull.link']; | ||||
|     shortSubject = link ? 'Pull Request' : ''; | ||||
|   if (info.pull_request?.link && info.pull_request?.title) { | ||||
|     subject = info.pull_request?.title; | ||||
|     link = info.pull_request?.link; | ||||
|   } | ||||
| 
 | ||||
|   const shortTimestamp = Intl.DateTimeFormat(undefined, { dateStyle: 'medium' }).format(info['revision.timestamp']); | ||||
|   const longTimestamp = Intl.DateTimeFormat(undefined, { dateStyle: 'full', timeStyle: 'long' }).format(info['revision.timestamp']); | ||||
|   return <div className='hbox git-commit-info metadata-section'> | ||||
|     <div className='vbox metadata-properties'> | ||||
|       <div> | ||||
|         {link ? ( | ||||
|           <a href={link} target='_blank' rel='noopener noreferrer' title={subject}> | ||||
|             {subject} | ||||
|           </a> | ||||
|         ) : <span title={subject}> | ||||
|   const shortTimestamp = Intl.DateTimeFormat(undefined, { dateStyle: 'medium' }).format(info.revision?.timestamp); | ||||
|   const longTimestamp = Intl.DateTimeFormat(undefined, { dateStyle: 'full', timeStyle: 'long' }).format(info.revision?.timestamp); | ||||
|   return <div className='metadata-section' role='list'> | ||||
|     <div role='listitem'> | ||||
|       {link ? ( | ||||
|         <a href={link} target='_blank' rel='noopener noreferrer' title={subject}> | ||||
|           {subject} | ||||
|         </span>} | ||||
|       </div> | ||||
|       <div className='hbox'> | ||||
|         <span className='mr-1'>{author}</span> | ||||
|         <span title={longTimestamp}> on {shortTimestamp}</span> | ||||
|         {info['ci.link'] && ( | ||||
|           <> | ||||
|             <span className='mx-2'>·</span> | ||||
|             <a href={info['ci.link']} target='_blank' rel='noopener noreferrer' title='CI/CD logs'>Logs</a> | ||||
|           </> | ||||
|         )} | ||||
|       </div> | ||||
|         </a> | ||||
|       ) : <span title={subject}> | ||||
|         {subject} | ||||
|       </span>} | ||||
|     </div> | ||||
|     <div role='listitem' className='hbox'> | ||||
|       <span className='mr-1'>{author}</span> | ||||
|       <span title={longTimestamp}> on {shortTimestamp}</span> | ||||
|       {info.ci?.link && ( | ||||
|         <> | ||||
|           <span className='mx-2'>·</span> | ||||
|           <a href={info.ci?.link} target='_blank' rel='noopener noreferrer' title='CI/CD logs'>Logs</a> | ||||
|         </> | ||||
|       )} | ||||
|     </div> | ||||
|     {link ? ( | ||||
|       <a href={link} target='_blank' rel='noopener noreferrer' title='View commit details'> | ||||
|         {shortSubject} | ||||
|       </a> | ||||
|     ) : !!shortSubject && <span>{shortSubject}</span>} | ||||
|   </div>; | ||||
| }; | ||||
|  |  | |||
|  | @ -50,7 +50,7 @@ const PromptButton: React.FC<{ | |||
|   const gitCommitInfo = useGitCommitInfo(); | ||||
|   const prompt = React.useMemo(() => fixTestPrompt( | ||||
|       error, | ||||
|       gitCommitInfo?.['pull.diff'] ?? gitCommitInfo?.['revision.diff'], | ||||
|       gitCommitInfo?.pull_request?.diff ?? gitCommitInfo?.revision?.diff, | ||||
|       result?.attachments.find(a => a.name === 'pageSnapshot')?.body | ||||
|   ), [gitCommitInfo, result, error]); | ||||
| 
 | ||||
|  |  | |||
|  | @ -48,7 +48,6 @@ export class FullConfigInternal { | |||
|   readonly plugins: TestRunnerPluginRegistration[]; | ||||
|   readonly projects: FullProjectInternal[] = []; | ||||
|   readonly singleTSConfigPath?: string; | ||||
|   readonly populateGitInfo: boolean; | ||||
|   cliArgs: string[] = []; | ||||
|   cliGrep: string | undefined; | ||||
|   cliGrepInvert: string | undefined; | ||||
|  | @ -78,7 +77,6 @@ export class FullConfigInternal { | |||
|     const privateConfiguration = (userConfig as any)['@playwright/test']; | ||||
|     this.plugins = (privateConfiguration?.plugins || []).map((p: any) => ({ factory: p })); | ||||
|     this.singleTSConfigPath = pathResolve(configDir, userConfig.tsconfig); | ||||
|     this.populateGitInfo = takeFirst(userConfig.populateGitInfo, defaultPopulateGitInfo); | ||||
| 
 | ||||
|     this.globalSetups = (Array.isArray(userConfig.globalSetup) ? userConfig.globalSetup : [userConfig.globalSetup]).map(s => resolveScript(s, configDir)).filter(script => script !== undefined); | ||||
|     this.globalTeardowns = (Array.isArray(userConfig.globalTeardown) ? userConfig.globalTeardown : [userConfig.globalTeardown]).map(s => resolveScript(s, configDir)).filter(script => script !== undefined); | ||||
|  | @ -301,7 +299,6 @@ function resolveScript(id: string | undefined, rootDir: string): string | undefi | |||
| 
 | ||||
| export const defaultGrep = /.*/; | ||||
| export const defaultReporter = process.env.CI ? 'dot' : 'list'; | ||||
| const defaultPopulateGitInfo = process.env.GITHUB_ACTIONS === 'true'; | ||||
| 
 | ||||
| const configInternalSymbol = Symbol('configInternalSymbol'); | ||||
| 
 | ||||
|  |  | |||
|  | @ -15,16 +15,22 @@ | |||
|  */ | ||||
| 
 | ||||
| export interface GitCommitInfo { | ||||
|   'revision.id'?: string; | ||||
|   'revision.author'?: string; | ||||
|   'revision.email'?: string; | ||||
|   'revision.subject'?: string; | ||||
|   'revision.timestamp'?: number | Date; | ||||
|   'revision.link'?: string; | ||||
|   'revision.diff'?: string; | ||||
|   'pull.link'?: string; | ||||
|   'pull.diff'?: string; | ||||
|   'pull.base'?: string; | ||||
|   'pull.title'?: string; | ||||
|   'ci.link'?: string; | ||||
|   revision?: { | ||||
|     id?: string; | ||||
|     author?: string; | ||||
|     email?: string; | ||||
|     subject?: string; | ||||
|     timestamp?: number; | ||||
|     link?: string; | ||||
|     diff?: string; | ||||
|   }, | ||||
|   pull_request?: { | ||||
|     link?: string; | ||||
|     diff?: string; | ||||
|     base?: string; | ||||
|     title?: string; | ||||
|   }, | ||||
|   ci?: { | ||||
|     link?: string; | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -26,7 +26,8 @@ import type { GitCommitInfo } from '../isomorphic/types'; | |||
| const GIT_OPERATIONS_TIMEOUT_MS = 1500; | ||||
| 
 | ||||
| export const addGitCommitInfoPlugin = (fullConfig: FullConfigInternal) => { | ||||
|   if (fullConfig.populateGitInfo) | ||||
|   const commitProperty = fullConfig.config.metadata['git.commit.info']; | ||||
|   if (commitProperty && typeof commitProperty === 'object' && Object.keys(commitProperty).length === 0) | ||||
|     fullConfig.plugins.push({ factory: gitCommitInfo }); | ||||
| }; | ||||
| 
 | ||||
|  | @ -35,10 +36,10 @@ export const gitCommitInfo = (options?: GitCommitInfoPluginOptions): TestRunnerP | |||
|     name: 'playwright:git-commit-info', | ||||
| 
 | ||||
|     setup: async (config: FullConfig, configDir: string) => { | ||||
|       const fromEnv = await linksFromEnv(); | ||||
|       const fromCLI = await gitStatusFromCLI(options?.directory || configDir, fromEnv); | ||||
|       const commitInfo = await linksFromEnv(); | ||||
|       await enrichStatusFromCLI(options?.directory || configDir, commitInfo); | ||||
|       config.metadata = config.metadata || {}; | ||||
|       config.metadata['git.commit.info'] = { ...fromEnv, ...fromCLI }; | ||||
|       config.metadata['git.commit.info'] = commitInfo; | ||||
|     }, | ||||
|   }; | ||||
| }; | ||||
|  | @ -47,28 +48,39 @@ interface GitCommitInfoPluginOptions { | |||
|   directory?: string; | ||||
| } | ||||
| 
 | ||||
| async function linksFromEnv() { | ||||
|   const out: Partial<GitCommitInfo> = {}; | ||||
| async function linksFromEnv(): Promise<GitCommitInfo> { | ||||
|   const out: GitCommitInfo = {}; | ||||
|   // Jenkins: https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables
 | ||||
|   if (process.env.BUILD_URL) | ||||
|     out['ci.link'] = process.env.BUILD_URL; | ||||
|   if (process.env.BUILD_URL) { | ||||
|     out.ci = out.ci || {}; | ||||
|     out.ci.link = process.env.BUILD_URL; | ||||
|   } | ||||
|   // GitLab: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html
 | ||||
|   if (process.env.CI_PROJECT_URL && process.env.CI_COMMIT_SHA) | ||||
|     out['revision.link'] = `${process.env.CI_PROJECT_URL}/-/commit/${process.env.CI_COMMIT_SHA}`; | ||||
|   if (process.env.CI_JOB_URL) | ||||
|     out['ci.link'] = process.env.CI_JOB_URL; | ||||
|   if (process.env.CI_PROJECT_URL && process.env.CI_COMMIT_SHA) { | ||||
|     out.revision = out.revision || {}; | ||||
|     out.revision.link = `${process.env.CI_PROJECT_URL}/-/commit/${process.env.CI_COMMIT_SHA}`; | ||||
|   } | ||||
|   if (process.env.CI_JOB_URL) { | ||||
|     out.ci = out.ci || {}; | ||||
|     out.ci.link = process.env.CI_JOB_URL; | ||||
|   } | ||||
|   // GitHub: https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables
 | ||||
|   if (process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY && process.env.GITHUB_SHA) | ||||
|     out['revision.link'] = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/commit/${process.env.GITHUB_SHA}`; | ||||
|   if (process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY && process.env.GITHUB_RUN_ID) | ||||
|     out['ci.link'] = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`; | ||||
|   if (process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY && process.env.GITHUB_SHA) { | ||||
|     out.revision = out.revision || {}; | ||||
|     out.revision.link = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/commit/${process.env.GITHUB_SHA}`; | ||||
|   } | ||||
|   if (process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY && process.env.GITHUB_RUN_ID) { | ||||
|     out.ci = out.ci || {}; | ||||
|     out.ci.link = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`; | ||||
|   } | ||||
|   if (process.env.GITHUB_EVENT_PATH) { | ||||
|     try { | ||||
|       const json = JSON.parse(await fs.promises.readFile(process.env.GITHUB_EVENT_PATH, 'utf8')); | ||||
|       if (json.pull_request) { | ||||
|         out['pull.title'] = json.pull_request.title; | ||||
|         out['pull.link'] = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/pull/${json.pull_request.number}`; | ||||
|         out['pull.base'] = json.pull_request.base.ref; | ||||
|         out.pull_request = out.pull_request || {}; | ||||
|         out.pull_request.title = json.pull_request.title; | ||||
|         out.pull_request.link = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/pull/${json.pull_request.number}`; | ||||
|         out.pull_request.base = json.pull_request.base.ref; | ||||
|       } | ||||
|     } catch { | ||||
|     } | ||||
|  | @ -76,7 +88,7 @@ async function linksFromEnv() { | |||
|   return out; | ||||
| } | ||||
| 
 | ||||
| async function gitStatusFromCLI(gitDir: string, envInfo: Pick<GitCommitInfo, 'pull.base'>): Promise<GitCommitInfo | undefined> { | ||||
| async function enrichStatusFromCLI(gitDir: string, commitInfo: GitCommitInfo) { | ||||
|   const separator = `:${createGuid().slice(0, 4)}:`; | ||||
|   const commitInfoResult = await spawnAsync( | ||||
|       'git', | ||||
|  | @ -90,23 +102,24 @@ async function gitStatusFromCLI(gitDir: string, envInfo: Pick<GitCommitInfo, 'pu | |||
|   let timestamp: number = Number.parseInt(rawTimestamp, 10); | ||||
|   timestamp = Number.isInteger(timestamp) ? timestamp * 1000 : 0; | ||||
| 
 | ||||
|   const result: GitCommitInfo = { | ||||
|     'revision.id': id, | ||||
|     'revision.author': author, | ||||
|     'revision.email': email, | ||||
|     'revision.subject': subject, | ||||
|     'revision.timestamp': timestamp, | ||||
|   commitInfo.revision = { | ||||
|     ...commitInfo.revision, | ||||
|     id, | ||||
|     author, | ||||
|     email, | ||||
|     subject, | ||||
|     timestamp, | ||||
|   }; | ||||
| 
 | ||||
|   const diffLimit = 1_000_000; // 1MB
 | ||||
|   if (envInfo['pull.base']) { | ||||
|   if (commitInfo.pull_request?.base) { | ||||
|     const pullDiffResult = await spawnAsync( | ||||
|         'git', | ||||
|         ['diff', envInfo['pull.base']], | ||||
|         ['diff', commitInfo.pull_request?.base], | ||||
|         { stdio: 'pipe', cwd: gitDir, timeout: GIT_OPERATIONS_TIMEOUT_MS } | ||||
|     ); | ||||
|     if (!pullDiffResult.code) | ||||
|       result['pull.diff'] = pullDiffResult.stdout.substring(0, diffLimit); | ||||
|       commitInfo.pull_request!.diff = pullDiffResult.stdout.substring(0, diffLimit); | ||||
|   } else { | ||||
|     const diffResult = await spawnAsync( | ||||
|         'git', | ||||
|  | @ -114,8 +127,6 @@ async function gitStatusFromCLI(gitDir: string, envInfo: Pick<GitCommitInfo, 'pu | |||
|         { stdio: 'pipe', cwd: gitDir, timeout: GIT_OPERATIONS_TIMEOUT_MS } | ||||
|     ); | ||||
|     if (!diffResult.code) | ||||
|       result['revision.diff'] = diffResult.stdout.substring(0, diffLimit); | ||||
|       commitInfo.revision!.diff = diffResult.stdout.substring(0, diffLimit); | ||||
|   } | ||||
| 
 | ||||
|   return result; | ||||
| } | ||||
|  |  | |||
|  | @ -1285,9 +1285,8 @@ interface TestConfig<TestArgs = {}, WorkerArgs = {}> { | |||
|    * Metadata contains key-value pairs to be included in the report. For example, HTML report will display it as | ||||
|    * key-value pairs, and JSON report will include metadata serialized as json. | ||||
|    * | ||||
|    * See also | ||||
|    * [testConfig.populateGitInfo](https://playwright.dev/docs/api/class-testconfig#test-config-populate-git-info) that
 | ||||
|    * populates metadata. | ||||
|    * Providing `'git.commit.info': {}` property will populate it with the git commit details. This is useful for CI/CD | ||||
|    * environments. | ||||
|    * | ||||
|    * **Usage** | ||||
|    * | ||||
|  | @ -1360,29 +1359,6 @@ interface TestConfig<TestArgs = {}, WorkerArgs = {}> { | |||
|    */ | ||||
|   outputDir?: string; | ||||
| 
 | ||||
|   /** | ||||
|    * Whether to populate `'git.commit.info'` field of the | ||||
|    * [testConfig.metadata](https://playwright.dev/docs/api/class-testconfig#test-config-metadata) with Git commit info
 | ||||
|    * and CI/CD information. | ||||
|    * | ||||
|    * This information will appear in the HTML and JSON reports and is available in the Reporter API. | ||||
|    * | ||||
|    * On Github Actions, this feature is enabled by default. | ||||
|    * | ||||
|    * **Usage** | ||||
|    * | ||||
|    * ```js
 | ||||
|    * // playwright.config.ts
 | ||||
|    * import { defineConfig } from '@playwright/test'; | ||||
|    * | ||||
|    * export default defineConfig({ | ||||
|    *   populateGitInfo: !!process.env.CI, | ||||
|    * }); | ||||
|    * ``` | ||||
|    * | ||||
|    */ | ||||
|   populateGitInfo?: boolean; | ||||
| 
 | ||||
|   /** | ||||
|    * Whether to preserve test output in the | ||||
|    * [testConfig.outputDir](https://playwright.dev/docs/api/class-testconfig#test-config-output-dir). Defaults to
 | ||||
|  |  | |||
|  | @ -101,7 +101,7 @@ function Error({ message, error, errorId, sdkLanguage, pageSnapshot, revealInSou | |||
|   const [showLLM, setShowLLM] = React.useState(false); | ||||
|   const llmAvailable = useIsLLMAvailable(); | ||||
|   const gitCommitInfo = useGitCommitInfo(); | ||||
|   const diff = gitCommitInfo?.['pull.diff'] ?? gitCommitInfo?.['revision.diff']; | ||||
|   const diff = gitCommitInfo?.pull_request?.diff ?? gitCommitInfo?.revision?.diff; | ||||
| 
 | ||||
|   let location: string | undefined; | ||||
|   let longLocation: string | undefined; | ||||
|  |  | |||
|  | @ -1187,13 +1187,12 @@ for (const useIntermediateMergeReport of [true, false] as const) { | |||
|       ]); | ||||
|     }); | ||||
| 
 | ||||
|     test('should include metadata with populateGitInfo = true', async ({ runInlineTest, writeFiles, showReport, page }) => { | ||||
|     test('should include metadata with git.commit.info', async ({ runInlineTest, writeFiles, showReport, page }) => { | ||||
|       const files = { | ||||
|         'uncommitted.txt': `uncommitted file`, | ||||
|         'playwright.config.ts': ` | ||||
|           export default { | ||||
|             populateGitInfo: true, | ||||
|             metadata: { foo: 'value1', bar: { prop: 'value2' }, baz: ['value3', 123] } | ||||
|             metadata: { 'git.commit.info': {}, foo: 'value1', bar: { prop: 'value2' }, baz: ['value3', 123] } | ||||
|           }; | ||||
|         `,
 | ||||
|         'example.spec.ts': ` | ||||
|  | @ -1230,20 +1229,23 @@ for (const useIntermediateMergeReport of [true, false] as const) { | |||
|       expect(result.exitCode).toBe(0); | ||||
|       await page.getByRole('button', { name: 'Metadata' }).click(); | ||||
|       await expect(page.locator('.metadata-view')).toMatchAriaSnapshot(` | ||||
|         - 'link "chore(html): make this test look nice"' | ||||
|         - text: /^William <shakespeare@example.local> on/ | ||||
|         - link /^[a-f0-9]{7}$/ | ||||
|         - text: 'foo : value1 bar : {"prop":"value2"} baz : ["value3",123]' | ||||
|         - list: | ||||
|           - listitem: | ||||
|             - 'link "chore(html): make this test look nice"' | ||||
|           - listitem: /William <shakespeare@example\\.local>/ | ||||
|         - list: | ||||
|           - listitem: "foo : value1" | ||||
|           - listitem: "bar : {\\"prop\\":\\"value2\\"}" | ||||
|           - listitem: "baz : [\\"value3\\",123]" | ||||
|       `);
 | ||||
|     }); | ||||
| 
 | ||||
|     test('should include metadata with populateGitInfo on GHA', async ({ runInlineTest, writeFiles, showReport, page }) => { | ||||
|     test('should include metadata with git.commit.info on GHA', async ({ runInlineTest, writeFiles, showReport, page }) => { | ||||
|       const files = { | ||||
|         'uncommitted.txt': `uncommitted file`, | ||||
|         'playwright.config.ts': ` | ||||
|           export default { | ||||
|             populateGitInfo: true, | ||||
|             metadata: { foo: 'value1', bar: { prop: 'value2' }, baz: ['value3', 123] } | ||||
|             metadata: { 'git.commit.info': {}, foo: 'value1', bar: { prop: 'value2' }, baz: ['value3', 123] } | ||||
|           }; | ||||
|         `,
 | ||||
|         'example.spec.ts': ` | ||||
|  | @ -1291,18 +1293,23 @@ for (const useIntermediateMergeReport of [true, false] as const) { | |||
|       expect(result.exitCode).toBe(0); | ||||
|       await page.getByRole('button', { name: 'Metadata' }).click(); | ||||
|       await expect(page.locator('.metadata-view')).toMatchAriaSnapshot(` | ||||
|         - 'link "My PR"' | ||||
|         - text: /^William <shakespeare@example.local> on/ | ||||
|         - link "Logs" | ||||
|         - link "Pull Request" | ||||
|         - text: 'foo : value1 bar : {"prop":"value2"} baz : ["value3",123]' | ||||
|         - list: | ||||
|           - listitem: | ||||
|             - link "My PR" | ||||
|           - listitem: | ||||
|             - text: /William <shakespeare@example\\.local>/ | ||||
|             - link "Logs" | ||||
|         - list: | ||||
|           - listitem: "foo : value1" | ||||
|           - listitem: "bar : {\\"prop\\":\\"value2\\"}" | ||||
|           - listitem: "baz : [\\"value3\\",123]" | ||||
|       `);
 | ||||
|     }); | ||||
| 
 | ||||
|     test('should not include git metadata with populateGitInfo = false', async ({ runInlineTest, showReport, page }) => { | ||||
|     test('should not include git metadata w/o git.commit.info', async ({ runInlineTest, showReport, page }) => { | ||||
|       const result = await runInlineTest({ | ||||
|         'playwright.config.ts': ` | ||||
|           export default { populateGitInfo: false }; | ||||
|           export default {}; | ||||
|         `,
 | ||||
|         'example.spec.ts': ` | ||||
|           import { test, expect } from '@playwright/test'; | ||||
|  | @ -1323,7 +1330,7 @@ for (const useIntermediateMergeReport of [true, false] as const) { | |||
|         'playwright.config.ts': ` | ||||
|           export default { | ||||
|             metadata: { | ||||
|               'git.commit.info': { 'revision.timestamp': 'hi' } | ||||
|               'git.commit.info': { revision: { timestamp: 'hi' } } | ||||
|             }, | ||||
|           }; | ||||
|         `,
 | ||||
|  | @ -2757,8 +2764,12 @@ for (const useIntermediateMergeReport of [true, false] as const) { | |||
|         'uncommitted.txt': `uncommitted file`, | ||||
|         'playwright.config.ts': ` | ||||
|           export default { | ||||
|             populateGitInfo: true, | ||||
|             metadata: { foo: 'value1', bar: { prop: 'value2' }, baz: ['value3', 123] } | ||||
|             metadata: { | ||||
|               'git.commit.info': {}, | ||||
|               foo: 'value1', | ||||
|               bar: { prop: 'value2' }, | ||||
|               baz: ['value3', 123] | ||||
|             } | ||||
|           }; | ||||
|         `,
 | ||||
|         'example.spec.ts': ` | ||||
|  |  | |||
|  | @ -21,14 +21,14 @@ test('should render html report git info metadata', async ({ runUITest }) => { | |||
|     'reporter.ts': ` | ||||
|       module.exports = class Reporter { | ||||
|         onBegin(config, suite) { | ||||
|           console.log('ci.link:', config.metadata['git.commit.info']['ci.link']); | ||||
|           console.log('ci.link:', config.metadata['git.commit.info'].ci.link); | ||||
|         } | ||||
|       } | ||||
|     `,
 | ||||
|     'playwright.config.ts': ` | ||||
|       import { defineConfig } from '@playwright/test'; | ||||
|       export default defineConfig({ | ||||
|         populateGitInfo: true, | ||||
|         metadata: { 'git.commit.info': {} }, | ||||
|         reporter: './reporter.ts', | ||||
|       }); | ||||
|     `,
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue