diff --git a/README.md b/README.md index 9b0a7ae..ef78789 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,14 @@ Official [Buildkite Test Engine](https://buildkite.com/platform/test-engine) col ], ``` + If you would like to pass execution tags through to Test Engine, then you can use Playwright's tagging syntax as follows: + + ``` + test('has tags', { tag: ['@type:feature'] }, ...) + ``` + + This will be threaded through to Test Engine as an execution tag with key set to `type` and value set to `feature`. + ### Cypress Update your [Cypress configuration](https://docs.cypress.io/guides/references/configuration):
diff --git a/e2e/playwright.test.js b/e2e/playwright.test.js index 4d53ca3..6eb33bc 100644 --- a/e2e/playwright.test.js +++ b/e2e/playwright.test.js @@ -61,25 +61,28 @@ describe('examples/playwright', () => { expect(data).toHaveProperty("run_env.version") expect(data).toHaveProperty("run_env.collector", "js-buildkite-test-collector") - expect(data).toHaveProperty("tags", { "hello": "playwright" }) // examples/playwright/playwright.config.js - expect(data).toHaveProperty("data[0].scope", ' chromium example.spec.js has title') expect(data).toHaveProperty("data[0].name", 'has title') expect(data).toHaveProperty("data[0].location", "tests/example.spec.js:3:1") expect(data).toHaveProperty("data[0].file_name", "tests/example.spec.js") - expect(data).toHaveProperty("data[0].result", 'passed') + expect(data).toHaveProperty("data[0].result", "passed") expect(data).toHaveProperty("data[1].scope", " chromium example.spec.js says hello") expect(data).toHaveProperty("data[1].name", "says hello") expect(data).toHaveProperty("data[1].location", "tests/example.spec.js:9:1") expect(data).toHaveProperty("data[1].file_name", "tests/example.spec.js") expect(data).toHaveProperty("data[1].result", "failed") - expect(data).toHaveProperty("data[1].failure_reason", "Timed out 5000ms waiting for expect(received).toHaveText(expected)") + expect(data).toHaveProperty("data[1].failure_reason", "Error: Timed out 5000ms waiting for expect(locator).toHaveText(expected)") expect(data).toHaveProperty("data[1].failure_expanded", expect.arrayContaining([ expect.objectContaining({ - expanded: expect.arrayContaining(['Expected string: "Hello, World!"', 'Received string: ""']) + expanded: expect.arrayContaining(['Expected string: "Hello, World!"', 'Received: ']) }) ])) + + expect(data).toHaveProperty("data[2].tags", { foo: "bar" }); + expect(data).toHaveProperty("data[3].tags", { foo: "bar", baz: 'qux' }); + expect(data).toHaveProperty("data[4].tags", {}); + expect(stdout).toMatch(/Test Engine .* response/m) }, TIMEOUT); @@ -117,10 +120,10 @@ describe('examples/playwright', () => { expect(data).toHaveProperty("data[0].location", "tests/example.spec.js:3:1") expect(data).toHaveProperty("data[0].file_name", "tests/example.spec.js") expect(data).toHaveProperty("data[0].result", 'failed') - expect(data).toHaveProperty("data[1].failure_reason", "Test timeout of 1ms exceeded.") + expect(data).toHaveProperty("data[1].failure_reason", "Test timeout of 1ms exceeded while setting up \"browserName\".") expect(data).toHaveProperty("data[1].failure_expanded", expect.arrayContaining([ expect.objectContaining({ - expanded: expect.arrayContaining(["Test timeout of 1ms exceeded."]) + expanded: expect.arrayContaining(["Test timeout of 1ms exceeded while setting up \"browserName\"."]) }) ])) @@ -129,10 +132,10 @@ describe('examples/playwright', () => { expect(data).toHaveProperty("data[1].location", "tests/example.spec.js:9:1") expect(data).toHaveProperty("data[1].file_name", "tests/example.spec.js") expect(data).toHaveProperty("data[1].result", "failed") - expect(data).toHaveProperty("data[1].failure_reason", "Test timeout of 1ms exceeded.") + expect(data).toHaveProperty("data[1].failure_reason", "Test timeout of 1ms exceeded while setting up \"browserName\".") expect(data).toHaveProperty("data[1].failure_expanded", expect.arrayContaining([ expect.objectContaining({ - expanded: expect.arrayContaining(["Test timeout of 1ms exceeded."]) + expanded: expect.arrayContaining(["Test timeout of 1ms exceeded while setting up \"browserName\"."]) }) ])) expect(stdout).toMatch(/Test Engine .* response/m) diff --git a/examples/playwright/package.json b/examples/playwright/package.json index 6907429..09f6c78 100644 --- a/examples/playwright/package.json +++ b/examples/playwright/package.json @@ -1,7 +1,7 @@ { "name": "buildkite-test-collector-playwright-example", "devDependencies": { - "@playwright/test": "^1.38.1", + "@playwright/test": "^1.43.0", "buildkite-test-collector": "file:../.." }, "scripts": { diff --git a/examples/playwright/tests/example.spec.js b/examples/playwright/tests/example.spec.js index 4a8d3de..51d0ea9 100644 --- a/examples/playwright/tests/example.spec.js +++ b/examples/playwright/tests/example.spec.js @@ -13,3 +13,21 @@ test('says hello', async ({ page }, { retry }) => { const h1 = await page.locator(retry == 0 ? 'h2' : 'h1'); await expect(h1).toHaveText('Hello, World!'); }); + +test('has scalar tag', { tag: '@foo:bar' }, async ({ page }) => { + await page.goto('/'); + + await expect(page).toHaveTitle(/Buildkite/); +}); + +test('has array of tags', { tag: ['@foo:bar', '@baz:qux'] }, async ({ page }) => { + await page.goto('/'); + + await expect(page).toHaveTitle(/Buildkite/); +}); + +test("has a tag we don't care about", { tag: '@foobar' }, async ({ page }) => { + await page.goto('/'); + + await expect(page).toHaveTitle(/Buildkite/); +}); diff --git a/package-lock.json b/package-lock.json index 45b4c98..a981775 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "uuid": "^8.3.2" }, "devDependencies": { - "@playwright/test": "^1.38.1", + "@playwright/test": "^1.43.0", "jasmine": "^4.2.1", "jest": "^29.3.1", "mocha": "^10.0.0", @@ -100,7 +100,7 @@ "http-server": "^14.1.1" }, "devDependencies": { - "@playwright/test": "^1.38.1", + "@playwright/test": "^1.43.0", "buildkite-test-collector": "file:../.." } }, @@ -2162,17 +2162,18 @@ } }, "node_modules/@playwright/test": { - "version": "1.38.1", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.52.0.tgz", + "integrity": "sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "playwright": "1.38.1" + "playwright": "1.52.0" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/@sinclair/typebox": { @@ -7918,31 +7919,33 @@ } }, "node_modules/playwright": { - "version": "1.38.1", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz", + "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.38.1" + "playwright-core": "1.52.0" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { - "version": "1.38.1", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz", + "integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==", "dev": true, - "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/portfinder": { @@ -10596,10 +10599,12 @@ } }, "@playwright/test": { - "version": "1.38.1", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.52.0.tgz", + "integrity": "sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==", "dev": true, "requires": { - "playwright": "1.38.1" + "playwright": "1.52.0" } }, "@sinclair/typebox": { @@ -11229,7 +11234,7 @@ "buildkite-test-collector": { "version": "file:", "requires": { - "@playwright/test": "^1.38.1", + "@playwright/test": "^1.43.0", "axios": "^1.8.2", "buildkite-test-collector-cypress-example": "file:examples/cypress", "buildkite-test-collector-jasmine-example": "file:examples/jasmine", @@ -12571,10 +12576,12 @@ } }, "@playwright/test": { - "version": "1.38.1", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.52.0.tgz", + "integrity": "sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==", "dev": true, "requires": { - "playwright": "1.38.1" + "playwright": "1.52.0" } }, "@sinclair/typebox": { @@ -13252,7 +13259,7 @@ "buildkite-test-collector-playwright-example": { "version": "file:examples/playwright", "requires": { - "@playwright/test": "^1.38.1", + "@playwright/test": "^1.43.0", "buildkite-test-collector": "file:../..", "http-server": "^14.1.1" } @@ -16492,15 +16499,19 @@ } }, "playwright": { - "version": "1.38.1", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz", + "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==", "dev": true, "requires": { "fsevents": "2.3.2", - "playwright-core": "1.38.1" + "playwright-core": "1.52.0" } }, "playwright-core": { - "version": "1.38.1", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz", + "integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==", "dev": true }, "portfinder": { @@ -17427,7 +17438,7 @@ "buildkite-test-collector-playwright-example": { "version": "file:examples/playwright", "requires": { - "@playwright/test": "^1.38.1", + "@playwright/test": "^1.43.0", "buildkite-test-collector": "file:../..", "http-server": "^14.1.1" } @@ -20667,15 +20678,19 @@ } }, "playwright": { - "version": "1.38.1", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz", + "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==", "dev": true, "requires": { "fsevents": "2.3.2", - "playwright-core": "1.38.1" + "playwright-core": "1.52.0" } }, "playwright-core": { - "version": "1.38.1", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz", + "integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==", "dev": true }, "portfinder": { diff --git a/package.json b/package.json index 6af5ea5..aac4491 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "uuid": "^8.3.2" }, "devDependencies": { - "@playwright/test": "^1.38.1", + "@playwright/test": "^1.43.0", "jasmine": "^4.2.1", "jest": "^29.3.1", "mocha": "^10.0.0", diff --git a/playwright/reporter.js b/playwright/reporter.js index 9fc7359..e0860d9 100644 --- a/playwright/reporter.js +++ b/playwright/reporter.js @@ -27,6 +27,7 @@ class PlaywrightBuildkiteTestEngineReporter { this._tags = options?.tags; this._options = options; this._paths = new Paths({ cwd: process.cwd() }, this._testEnv.location_prefix); + this._tagPattern = /^@[^:]+:[^:]+$/; } onBegin() { } @@ -49,6 +50,14 @@ class PlaywrightBuildkiteTestEngineReporter { const fileName = this._paths.prefixTestPath(test.location.file); const location = [fileName, test.location.line, test.location.column].join(':'); + const filteredTags = test.tags.filter(tag => this._tagPattern.test(tag)); + const tags = filteredTags.reduce((acc, test) => { + const [key, value] = test.slice(1).split(':'); + acc[key] = value; + + return acc; + }, {}); + this._testResults.push({ 'id': test.id, 'name': test.title, @@ -62,7 +71,8 @@ class PlaywrightBuildkiteTestEngineReporter { 'section': 'top', 'start_at': testResult.startTime.getTime(), 'duration': testResult.duration / 1000, - } + }, + 'tags': tags }); }