feat: add new config prop populateGitInfo (#34329)
Co-authored-by: Yury Semikhatsky <yurys@chromium.org>
This commit is contained in:
parent
cea5dad686
commit
61d595ae48
|
@ -321,6 +321,22 @@ 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 [`property: TestConfig.metadata`] with Git info. The metadata will automatically appear in the HTML report and is available in Reporter API.
|
||||
|
||||
**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">>
|
||||
|
|
|
@ -46,6 +46,7 @@ export class FullConfigInternal {
|
|||
readonly plugins: TestRunnerPluginRegistration[];
|
||||
readonly projects: FullProjectInternal[] = [];
|
||||
readonly singleTSConfigPath?: string;
|
||||
readonly populateGitInfo: boolean;
|
||||
cliArgs: string[] = [];
|
||||
cliGrep: string | undefined;
|
||||
cliGrepInvert: string | undefined;
|
||||
|
@ -75,10 +76,15 @@ 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, false);
|
||||
|
||||
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);
|
||||
|
||||
// Make sure we reuse same metadata instance between FullConfigInternal instances,
|
||||
// so that plugins such as gitCommitInfoPlugin can populate metadata once.
|
||||
userConfig.metadata = userConfig.metadata || {};
|
||||
|
||||
this.config = {
|
||||
configFile: resolvedConfigFile,
|
||||
rootDir: pathResolve(configDir, userConfig.testDir) || configDir,
|
||||
|
@ -90,7 +96,7 @@ export class FullConfigInternal {
|
|||
grep: takeFirst(userConfig.grep, defaultGrep),
|
||||
grepInvert: takeFirst(userConfig.grepInvert, null),
|
||||
maxFailures: takeFirst(configCLIOverrides.debug ? 1 : undefined, configCLIOverrides.maxFailures, userConfig.maxFailures, 0),
|
||||
metadata: takeFirst(userConfig.metadata, {}),
|
||||
metadata: userConfig.metadata,
|
||||
preserveOutput: takeFirst(userConfig.preserveOutput, 'always'),
|
||||
reporter: takeFirst(configCLIOverrides.reporter, resolveReporters(userConfig.reporter, configDir), [[defaultReporter]]),
|
||||
reportSlowTests: takeFirst(userConfig.reportSlowTests, { max: 5, threshold: 15000 }),
|
||||
|
|
|
@ -17,9 +17,15 @@
|
|||
import { createGuid, spawnAsync } from 'playwright-core/lib/utils';
|
||||
import type { TestRunnerPlugin } from './';
|
||||
import type { FullConfig } from '../../types/testReporter';
|
||||
import type { FullConfigInternal } from '../common/config';
|
||||
|
||||
const GIT_OPERATIONS_TIMEOUT_MS = 1500;
|
||||
|
||||
export const addGitCommitInfoPlugin = (fullConfig: FullConfigInternal) => {
|
||||
if (fullConfig.populateGitInfo)
|
||||
fullConfig.plugins.push({ factory: gitCommitInfo });
|
||||
};
|
||||
|
||||
export const gitCommitInfo = (options?: GitCommitInfoPluginOptions): TestRunnerPlugin => {
|
||||
return {
|
||||
name: 'playwright:git-commit-info',
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
import type { FullResult, TestError } from '../../types/testReporter';
|
||||
import { webServerPluginsForConfig } from '../plugins/webServerPlugin';
|
||||
import { addGitCommitInfoPlugin } from '../plugins/gitCommitInfoPlugin';
|
||||
import { collectFilesForProject, filterProjects } from './projectUtils';
|
||||
import { createErrorCollectingReporter, createReporters } from './reporters';
|
||||
import { TestRun, createApplyRebaselinesTask, createClearCacheTask, createGlobalSetupTasks, createLoadTask, createPluginSetupTasks, createReportBeginTask, createRunTestsTasks, createStartDevServerTask, runTasks } from './tasks';
|
||||
|
@ -70,6 +71,8 @@ export class Runner {
|
|||
const config = this._config;
|
||||
const listOnly = config.cliListOnly;
|
||||
|
||||
addGitCommitInfoPlugin(config);
|
||||
|
||||
// Legacy webServer support.
|
||||
webServerPluginsForConfig(config).forEach(p => config.plugins.push({ factory: p }));
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ import { baseFullConfig } from '../isomorphic/teleReceiver';
|
|||
import { InternalReporter } from '../reporters/internalReporter';
|
||||
import type { ReporterV2 } from '../reporters/reporterV2';
|
||||
import { internalScreen } from '../reporters/base';
|
||||
import { addGitCommitInfoPlugin } from '../plugins/gitCommitInfoPlugin';
|
||||
|
||||
const originalStdoutWrite = process.stdout.write;
|
||||
const originalStderrWrite = process.stderr.write;
|
||||
|
@ -406,6 +407,7 @@ export class TestServerDispatcher implements TestServerInterface {
|
|||
// Preserve plugin instances between setup and build.
|
||||
if (!this._plugins) {
|
||||
webServerPluginsForConfig(config).forEach(p => config.plugins.push({ factory: p }));
|
||||
addGitCommitInfoPlugin(config);
|
||||
this._plugins = config.plugins || [];
|
||||
} else {
|
||||
config.plugins.splice(0, config.plugins.length, ...this._plugins);
|
||||
|
|
|
@ -1293,6 +1293,24 @@ interface TestConfig<TestArgs = {}, WorkerArgs = {}> {
|
|||
*/
|
||||
outputDir?: string;
|
||||
|
||||
/**
|
||||
* Whether to populate [testConfig.metadata](https://playwright.dev/docs/api/class-testconfig#test-config-metadata)
|
||||
* with Git info. The metadata will automatically appear in the HTML report and is available in Reporter API.
|
||||
*
|
||||
* **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
|
||||
|
|
|
@ -1142,14 +1142,12 @@ for (const useIntermediateMergeReport of [true, false] as const) {
|
|||
});
|
||||
|
||||
test.describe('gitCommitInfo plugin', () => {
|
||||
test('should include metadata', async ({ runInlineTest, writeFiles, showReport, page }) => {
|
||||
test('should include metadata with populateGitInfo = true', async ({ runInlineTest, writeFiles, showReport, page }) => {
|
||||
const files = {
|
||||
'uncommitted.txt': `uncommitted file`,
|
||||
'playwright.config.ts': `
|
||||
import { gitCommitInfo } from 'playwright/lib/plugins';
|
||||
import { test, expect } from '@playwright/test';
|
||||
const plugins = [gitCommitInfo()];
|
||||
export default { '@playwright/test': { plugins } };
|
||||
export default { populateGitInfo: true };
|
||||
`,
|
||||
'example.spec.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
@ -1195,6 +1193,25 @@ for (const useIntermediateMergeReport of [true, false] as const) {
|
|||
await expect.soft(page.getByTestId('metadata-error')).not.toBeVisible();
|
||||
});
|
||||
|
||||
test('should not include metadata with populateGitInfo = false', async ({ runInlineTest, showReport, page }) => {
|
||||
const result = await runInlineTest({
|
||||
'uncommitted.txt': `uncommitted file`,
|
||||
'playwright.config.ts': `
|
||||
export default { populateGitInfo: false };
|
||||
`,
|
||||
'example.spec.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('my sample test', async ({}) => { expect(2).toBe(2); });
|
||||
`,
|
||||
}, { reporter: 'dot,html' }, { PLAYWRIGHT_HTML_OPEN: 'never' }, undefined);
|
||||
|
||||
await showReport();
|
||||
|
||||
expect(result.exitCode).toBe(0);
|
||||
await expect.soft(page.locator('text="my sample test"')).toBeVisible();
|
||||
await expect.soft(page.getByTestId('metadata-error')).not.toBeVisible();
|
||||
await expect.soft(page.getByTestId('metadata-chip')).not.toBeVisible();
|
||||
});
|
||||
|
||||
test('should use explicitly supplied metadata', async ({ runInlineTest, showReport, page }) => {
|
||||
const result = await runInlineTest({
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* 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 } from './ui-mode-fixtures';
|
||||
|
||||
test('should render html report git info metadata', async ({ runUITest }) => {
|
||||
const { page } = await runUITest({
|
||||
'reporter.ts': `
|
||||
module.exports = class Reporter {
|
||||
onBegin(config, suite) {
|
||||
console.log('ci.link:', config.metadata['ci.link']);
|
||||
}
|
||||
}
|
||||
`,
|
||||
'playwright.config.ts': `
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
populateGitInfo: true,
|
||||
reporter: './reporter.ts',
|
||||
});
|
||||
`,
|
||||
'a.test.js': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('should work', async ({}) => {});
|
||||
`
|
||||
}, {
|
||||
BUILD_URL: 'https://playwright.dev',
|
||||
});
|
||||
|
||||
await page.getByTitle('Run all').click();
|
||||
await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)');
|
||||
await page.getByTitle('Toggle output').click();
|
||||
|
||||
await expect(page.getByTestId('output')).toContainText('ci.link: https://playwright.dev');
|
||||
});
|
Loading…
Reference in New Issue