@element-hq/element-web-playwright-common 1.3.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/expect/screenshot.ts"],"names":[],"mappings":"AAQA,OAAO,EAIH,KAAK,kBAAkB,EACvB,KAAK,OAAO,EACZ,KAAK,IAAI,EACT,KAAK,qCAAqC,EAC1C,KAAK,iBAAiB,EACzB,MAAM,kBAAkB,CAAC;AAW1B,MAAM,WAAW,wBAAyB,SAAQ,qCAAqC;IACnF,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,YAAY,GAAG;IACvB,iBAAiB,EAAE,CACf,IAAI,EAAE,kBAAkB,EACxB,QAAQ,EAAE,IAAI,GAAG,OAAO,EACxB,IAAI,EAAE,GAAG,MAAM,MAAM,EACrB,OAAO,CAAC,EAAE,wBAAwB,KACjC,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACnC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,MAAM,gDAiCjB,CAAC"}
1
+ {"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/expect/screenshot.ts"],"names":[],"mappings":"AAQA,OAAO,EAIH,KAAK,kBAAkB,EACvB,KAAK,OAAO,EACZ,KAAK,IAAI,EACT,KAAK,qCAAqC,EAC1C,KAAK,iBAAiB,EACzB,MAAM,kBAAkB,CAAC;AAa1B,MAAM,WAAW,wBAAyB,SAAQ,qCAAqC;IACnF,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,YAAY,GAAG;IACvB,iBAAiB,EAAE,CACf,IAAI,EAAE,kBAAkB,EACxB,QAAQ,EAAE,IAAI,GAAG,OAAO,EACxB,IAAI,EAAE,GAAG,MAAM,MAAM,EACrB,OAAO,CAAC,EAAE,wBAAwB,KACjC,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACnC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,MAAM,gDA+BjB,CAAC"}
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
8
8
  import { test, expect as baseExpect, } from "@playwright/test";
9
9
  import { sanitizeForFilePath } from "playwright-core/lib/utils";
10
10
  import { extname } from "node:path";
11
+ import { ANNOTATION } from "../stale-screenshot-reporter.js";
11
12
  // Based on https://github.com/microsoft/playwright/blob/2b77ed4d7aafa85a600caa0b0d101b72c8437eeb/packages/playwright/src/util.ts#L206C8-L210C2
12
13
  function sanitizeFilePathBeforeExtension(filePath) {
13
14
  const ext = extname(filePath);
@@ -38,10 +39,8 @@ export const expect = baseExpect.extend({
38
39
  await baseExpect(receiver).toHaveScreenshot(screenshotName, options);
39
40
  await style?.evaluate((tag) => tag.remove());
40
41
  testInfo.annotations.push({
41
- // `_` prefix hides it from the HTML reporter
42
- type: "_screenshot",
43
- // include a path relative to `playwright/snapshots/`
44
- description: testInfo.snapshotPath(screenshotName).split("/playwright/snapshots/", 2)[1],
42
+ type: ANNOTATION,
43
+ description: testInfo.snapshotPath(screenshotName),
45
44
  });
46
45
  return { pass: true, message: () => "", name: "toMatchScreenshot" };
47
46
  },
@@ -0,0 +1,19 @@
1
+ import { type Reporter, type TestCase } from "@playwright/test/reporter";
2
+ import { type FullConfig } from "@playwright/test";
3
+ /**
4
+ * The annotation type used to mark screenshots in tests.
5
+ * `_` prefix hides it from the HTML reporter
6
+ */
7
+ export declare const ANNOTATION = "_screenshot";
8
+ declare class StaleScreenshotReporter implements Reporter {
9
+ private readonly snapshotRoots;
10
+ private readonly screenshots;
11
+ private failing;
12
+ private success;
13
+ onBegin(config: FullConfig): void;
14
+ onTestEnd(test: TestCase): void;
15
+ private error;
16
+ onExit(): Promise<void>;
17
+ }
18
+ export default StaleScreenshotReporter;
19
+ //# sourceMappingURL=stale-screenshot-reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stale-screenshot-reporter.d.ts","sourceRoot":"","sources":["../src/stale-screenshot-reporter.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;;GAGG;AACH,eAAO,MAAM,UAAU,gBAAgB,CAAC;AAExC,cAAM,uBAAwB,YAAW,QAAQ;IAC7C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAQ;IAEhB,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAMjC,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IAWtC,OAAO,CAAC,KAAK;IAQA,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAoCvC;AAED,eAAe,uBAAuB,CAAC"}
@@ -0,0 +1,78 @@
1
+ /*
2
+ Copyright 2024 - 2025 New Vector Ltd.
3
+ Copyright 2024 The Matrix.org Foundation C.I.C.
4
+
5
+ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
6
+ Please see LICENSE files in the repository root for full details.
7
+ */
8
+ /**
9
+ * Test reporter which compares the reported screenshots vs those on disk to find stale screenshots
10
+ * Only intended to run from within GitHub Actions
11
+ */
12
+ import { glob } from "glob";
13
+ import path from "node:path";
14
+ /**
15
+ * The annotation type used to mark screenshots in tests.
16
+ * `_` prefix hides it from the HTML reporter
17
+ */
18
+ export const ANNOTATION = "_screenshot";
19
+ class StaleScreenshotReporter {
20
+ snapshotRoots = new Set();
21
+ screenshots = new Set();
22
+ failing = false;
23
+ success = true;
24
+ onBegin(config) {
25
+ for (const project of config.projects) {
26
+ this.snapshotRoots.add(project.snapshotDir);
27
+ }
28
+ }
29
+ onTestEnd(test) {
30
+ if (!test.ok()) {
31
+ this.failing = true;
32
+ }
33
+ for (const annotation of test.annotations) {
34
+ if (annotation.type === ANNOTATION && annotation.description) {
35
+ this.screenshots.add(annotation.description);
36
+ }
37
+ }
38
+ }
39
+ error(msg, file) {
40
+ if (process.env.GITHUB_ACTIONS) {
41
+ console.log(`::error file=${file}::${msg}`);
42
+ }
43
+ console.error(msg, file);
44
+ this.success = false;
45
+ }
46
+ async onExit() {
47
+ if (this.failing)
48
+ return;
49
+ if (!this.snapshotRoots.size) {
50
+ this.error("No snapshot directories found, did you set the snapshotDir in your Playwright config?", "");
51
+ return;
52
+ }
53
+ const screenshotFiles = new Set();
54
+ for (const snapshotRoot of this.snapshotRoots) {
55
+ const files = await glob(`**/*.png`, { cwd: snapshotRoot });
56
+ for (const file of files) {
57
+ screenshotFiles.add(path.join(snapshotRoot, file));
58
+ }
59
+ }
60
+ for (const screenshot of screenshotFiles) {
61
+ if (screenshot.split("-").at(-1) !== "linux.png") {
62
+ this.error("Found screenshot belonging to different platform, this should not be checked in", screenshot);
63
+ }
64
+ }
65
+ for (const screenshot of this.screenshots) {
66
+ screenshotFiles.delete(screenshot);
67
+ }
68
+ if (screenshotFiles.size > 0) {
69
+ for (const screenshot of screenshotFiles) {
70
+ this.error("Stale screenshot file", screenshot);
71
+ }
72
+ }
73
+ if (!this.success) {
74
+ process.exit(1);
75
+ }
76
+ }
77
+ }
78
+ export default StaleScreenshotReporter;
@@ -151,8 +151,8 @@ export type SynapseConfig = typeof DEFAULT_CONFIG;
151
151
  * Waits for HTTP /health 8008 to 200.
152
152
  */
153
153
  export declare class SynapseContainer extends GenericContainer implements HomeserverContainer<SynapseConfig> {
154
- private config;
155
- private mas?;
154
+ protected config: SynapseConfig;
155
+ protected mas?: StartedMatrixAuthenticationServiceContainer;
156
156
  constructor(image?: string);
157
157
  withConfigField(key: string, value: unknown): this;
158
158
  withConfig(config: Partial<SynapseConfig>): this;
@@ -1 +1 @@
1
- {"version":3,"file":"synapse.d.ts","sourceRoot":"","sources":["../../src/testcontainers/synapse.ts"],"names":[],"mappings":"AAOA,OAAO,EACH,wBAAwB,EACxB,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAE5B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAQzE,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACrG,OAAO,EAAE,KAAK,2CAA2C,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,EAAE,GAAG,EAAE,eAAe,EAAa,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEvD,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA2GV,SAAS,GACT;QACI,aAAa,EAAE,OAAO,CAAC;QACvB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,0BAA0B,EAAE,KAAK,CAAC;QAClC,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,mBAAmB,EAAE,MAAM,CAAC;QAC5B,mBAAmB,EAAE,OAAO,CAAC;QAC7B,eAAe,EAAE,MAAM,CAAC;KAC3B;kBAED,SAAS,GACT;QACI,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC/C,4BAA4B,EAAE,OAAO,CAAC;QACtC,kBAAkB,EAAE,MAAM,CAAC;QAC3B,uBAAuB,EAAE,OAAO,CAAC;KACpC;oBAED,SAAS,GACT;QACI,qBAAqB,EAAE,MAAM,CAAC;QAC9B,wBAAwB,EAAE,MAAM,CAAC;QACjC,sBAAsB,EAAE,MAAM,CAAC;QAC/B,SAAS,EAAE,MAAM,CAAC;KACrB;;;;;;;;;;;;CAUV,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,cAAc,CAAC;AAElD;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,gBAAiB,YAAW,mBAAmB,CAAC,aAAa,CAAC;IAChG,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,GAAG,CAAC,CAA8C;gBAEvC,KAAK,SAAuC;IA6CxD,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAKlD,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IAQhD,cAAc,CAAC,OAAO,EAAE,uBAAuB,GAAG,IAAI;IAkBtD,+BAA+B,CAAC,GAAG,CAAC,EAAE,2CAA2C,GAAG,IAAI;IAKzE,KAAK,IAAI,OAAO,CAAC,uBAAuB,CAAC;CA+BlE;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,wBAAyB,YAAW,0BAA0B;aAOnF,OAAO,EAAE,MAAM;IAC/B,OAAO,CAAC,QAAQ,CAAC,wBAAwB;IAP7C,SAAS,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC;IACjC,SAAgB,KAAK,EAAE,eAAe,CAAC;gBAGnC,SAAS,EAAE,oBAAoB,EACf,OAAO,EAAE,MAAM,EACd,wBAAwB,EAAE,MAAM;IAOrD;;;;OAIG;IACI,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAKzD,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAKtC,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;cAK9C,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;YAapC,oBAAoB;cAqClB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;YAYlC,YAAY;IAO1B;;;;;OAKG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAInG;;;;OAIG;IACU,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAI9E;;;;;OAKG;IACU,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAU3F;AAED;;GAEG;AACH,qBAAa,8BAA+B,SAAQ,uBAAuB;IAKnE,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAHpB,SAAS,EAAE,oBAAoB,EAC/B,OAAO,EAAE,MAAM,EACf,wBAAwB,EAAE,MAAM,EACf,GAAG,EAAE,2CAA2C;cAKrD,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAOhD;;;;;OAKG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAInG;;;;;OAKG;IACU,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG3F"}
1
+ {"version":3,"file":"synapse.d.ts","sourceRoot":"","sources":["../../src/testcontainers/synapse.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@element-hq/element-web-playwright-common",
3
3
  "type": "module",
4
- "version": "1.3.0",
4
+ "version": "1.4.1",
5
5
  "license": "SEE LICENSE IN README.md",
6
6
  "repository": {
7
7
  "type": "git",
@@ -13,6 +13,7 @@
13
13
  "node": ">=20.0.0"
14
14
  },
15
15
  "main": "lib/index.js",
16
+ "types": "lib/index.d.ts",
16
17
  "bin": {
17
18
  "playwright-screenshots": "playwright-screenshots.sh"
18
19
  },
@@ -19,6 +19,8 @@ import {
19
19
  import { sanitizeForFilePath } from "playwright-core/lib/utils";
20
20
  import { extname } from "node:path";
21
21
 
22
+ import { ANNOTATION } from "../stale-screenshot-reporter.js";
23
+
22
24
  // Based on https://github.com/microsoft/playwright/blob/2b77ed4d7aafa85a600caa0b0d101b72c8437eeb/packages/playwright/src/util.ts#L206C8-L210C2
23
25
  function sanitizeFilePathBeforeExtension(filePath: string): string {
24
26
  const ext = extname(filePath);
@@ -68,10 +70,8 @@ export const expect = baseExpect.extend<Expectations>({
68
70
  await style?.evaluate((tag) => tag.remove());
69
71
 
70
72
  testInfo.annotations.push({
71
- // `_` prefix hides it from the HTML reporter
72
- type: "_screenshot",
73
- // include a path relative to `playwright/snapshots/`
74
- description: testInfo.snapshotPath(screenshotName).split("/playwright/snapshots/", 2)[1],
73
+ type: ANNOTATION,
74
+ description: testInfo.snapshotPath(screenshotName),
75
75
  });
76
76
 
77
77
  return { pass: true, message: (): string => "", name: "toMatchScreenshot" };
@@ -0,0 +1,94 @@
1
+ /*
2
+ Copyright 2024 - 2025 New Vector Ltd.
3
+ Copyright 2024 The Matrix.org Foundation C.I.C.
4
+
5
+ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
6
+ Please see LICENSE files in the repository root for full details.
7
+ */
8
+
9
+ /**
10
+ * Test reporter which compares the reported screenshots vs those on disk to find stale screenshots
11
+ * Only intended to run from within GitHub Actions
12
+ */
13
+
14
+ import { glob } from "glob";
15
+ import path from "node:path";
16
+ import { type Reporter, type TestCase } from "@playwright/test/reporter";
17
+ import { type FullConfig } from "@playwright/test";
18
+
19
+ /**
20
+ * The annotation type used to mark screenshots in tests.
21
+ * `_` prefix hides it from the HTML reporter
22
+ */
23
+ export const ANNOTATION = "_screenshot";
24
+
25
+ class StaleScreenshotReporter implements Reporter {
26
+ private readonly snapshotRoots = new Set<string>();
27
+ private readonly screenshots = new Set<string>();
28
+ private failing = false;
29
+ private success = true;
30
+
31
+ public onBegin(config: FullConfig): void {
32
+ for (const project of config.projects) {
33
+ this.snapshotRoots.add(project.snapshotDir);
34
+ }
35
+ }
36
+
37
+ public onTestEnd(test: TestCase): void {
38
+ if (!test.ok()) {
39
+ this.failing = true;
40
+ }
41
+ for (const annotation of test.annotations) {
42
+ if (annotation.type === ANNOTATION && annotation.description) {
43
+ this.screenshots.add(annotation.description);
44
+ }
45
+ }
46
+ }
47
+
48
+ private error(msg: string, file: string) {
49
+ if (process.env.GITHUB_ACTIONS) {
50
+ console.log(`::error file=${file}::${msg}`);
51
+ }
52
+ console.error(msg, file);
53
+ this.success = false;
54
+ }
55
+
56
+ public async onExit(): Promise<void> {
57
+ if (this.failing) return;
58
+ if (!this.snapshotRoots.size) {
59
+ this.error("No snapshot directories found, did you set the snapshotDir in your Playwright config?", "");
60
+ return;
61
+ }
62
+
63
+ const screenshotFiles = new Set<string>();
64
+ for (const snapshotRoot of this.snapshotRoots) {
65
+ const files = await glob(`**/*.png`, { cwd: snapshotRoot });
66
+ for (const file of files) {
67
+ screenshotFiles.add(path.join(snapshotRoot, file));
68
+ }
69
+ }
70
+
71
+ for (const screenshot of screenshotFiles) {
72
+ if (screenshot.split("-").at(-1) !== "linux.png") {
73
+ this.error(
74
+ "Found screenshot belonging to different platform, this should not be checked in",
75
+ screenshot,
76
+ );
77
+ }
78
+ }
79
+ for (const screenshot of this.screenshots) {
80
+ screenshotFiles.delete(screenshot);
81
+ }
82
+ if (screenshotFiles.size > 0) {
83
+ for (const screenshot of screenshotFiles) {
84
+ this.error("Stale screenshot file", screenshot);
85
+ }
86
+ }
87
+
88
+ if (!this.success) {
89
+ process.exit(1);
90
+ }
91
+ }
92
+ }
93
+
94
+ export default StaleScreenshotReporter;
@@ -188,8 +188,8 @@ export type SynapseConfig = typeof DEFAULT_CONFIG;
188
188
  * Waits for HTTP /health 8008 to 200.
189
189
  */
190
190
  export class SynapseContainer extends GenericContainer implements HomeserverContainer<SynapseConfig> {
191
- private config: SynapseConfig;
192
- private mas?: StartedMatrixAuthenticationServiceContainer;
191
+ protected config: SynapseConfig;
192
+ protected mas?: StartedMatrixAuthenticationServiceContainer;
193
193
 
194
194
  public constructor(image = "ghcr.io/element-hq/synapse:develop") {
195
195
  super(image);