@element-hq/element-web-playwright-common 2.3.0 → 3.0.0

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.
Files changed (42) hide show
  1. package/Dockerfile +14 -8
  2. package/README.md +2 -2
  3. package/docker-entrypoint.sh +1 -8
  4. package/lib/expect/axe.d.ts +1 -1
  5. package/lib/expect/axe.d.ts.map +1 -1
  6. package/lib/expect/screenshot.d.ts +1 -1
  7. package/lib/expect/screenshot.d.ts.map +1 -1
  8. package/lib/fixtures/axe.d.ts +2 -2
  9. package/lib/fixtures/axe.d.ts.map +1 -1
  10. package/lib/fixtures/services.d.ts.map +1 -1
  11. package/lib/fixtures/services.js +2 -22
  12. package/lib/fixtures/user.d.ts +2 -2
  13. package/lib/fixtures/user.d.ts.map +1 -1
  14. package/lib/flaky-reporter.d.ts +24 -0
  15. package/lib/flaky-reporter.d.ts.map +1 -0
  16. package/lib/flaky-reporter.js +153 -0
  17. package/lib/stale-screenshot-reporter.d.ts +2 -1
  18. package/lib/stale-screenshot-reporter.d.ts.map +1 -1
  19. package/lib/stale-screenshot-reporter.js +13 -5
  20. package/lib/testcontainers/index.d.ts +2 -1
  21. package/lib/testcontainers/index.d.ts.map +1 -1
  22. package/lib/testcontainers/index.js +2 -1
  23. package/lib/testcontainers/mas.d.ts +5 -2
  24. package/lib/testcontainers/mas.d.ts.map +1 -1
  25. package/lib/testcontainers/mas.js +14 -2
  26. package/lib/testcontainers/postgres.d.ts +5 -0
  27. package/lib/testcontainers/postgres.d.ts.map +1 -0
  28. package/lib/testcontainers/postgres.js +31 -0
  29. package/lib/testcontainers/synapse.d.ts +6 -0
  30. package/lib/testcontainers/synapse.d.ts.map +1 -1
  31. package/lib/testcontainers/synapse.js +17 -1
  32. package/package.json +9 -10
  33. package/playwright-screenshots.sh +33 -126
  34. package/project.json +38 -0
  35. package/src/fixtures/services.ts +3 -22
  36. package/src/flaky-reporter.ts +188 -0
  37. package/src/stale-screenshot-reporter.ts +14 -4
  38. package/src/testcontainers/index.ts +2 -0
  39. package/src/testcontainers/mas.ts +21 -0
  40. package/src/testcontainers/postgres.ts +40 -0
  41. package/src/testcontainers/synapse.ts +24 -1
  42. package/tsconfig.json +8 -3
package/Dockerfile CHANGED
@@ -1,18 +1,24 @@
1
1
  ARG PLAYWRIGHT_VERSION
2
2
  FROM mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-noble
3
+ # Expose the argument to this build stage
4
+ ARG PLAYWRIGHT_VERSION
3
5
 
4
6
  WORKDIR /work
5
7
 
6
8
  # fonts-dejavu is needed for the same RTL rendering as on CI
7
9
  RUN apt-get update && apt-get -y install docker.io fonts-dejavu
8
-
9
- # Set up corepack
10
- RUN corepack enable
11
- ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0
12
-
13
- # Add environment variable so consumers can skip developer-centric scripts
14
- ENV PLAYWRIGHT_COMMON_DOCKER=1
10
+ # Install the matching playwright runtime, the docker image only includes browsers
11
+ RUN npm i -g playwright@${PLAYWRIGHT_VERSION}
15
12
 
16
13
  COPY docker-entrypoint.sh /docker-entrypoint.sh
17
14
 
18
- ENTRYPOINT ["/docker-entrypoint.sh"]
15
+ # We use `docker-init` as PID 1, which means that the container shuts down correctly on SIGTERM.
16
+ #
17
+ # (The problem is that PID 1 doesn't get default signal handlers, and
18
+ # playwright server doesn't register a SIGTERM handler, so if that ends up as
19
+ # PID 1, then it ignores SIGTERM. Likewise bash doesn't set a SIGTERM handler by default.
20
+ #
21
+ # The easiest solution is to use docker-init, which is in fact `tini` (https://github.com/krallin/tini).
22
+ #
23
+ # See https://github.com/krallin/tini/issues/8#issuecomment-146135930 for a good explanation of all this.)
24
+ ENTRYPOINT ["/usr/bin/docker-init", "/docker-entrypoint.sh"]
package/README.md CHANGED
@@ -18,9 +18,9 @@ The API is versioned using semver, with the major version incremented for breaki
18
18
 
19
19
  ## Copyright & License
20
20
 
21
- Copyright (c) 2025 New Vector Ltd
21
+ Copyright (c) 2026 Element Creations Ltd
22
22
 
23
- This software is multi licensed by New Vector Ltd (Element). It can be used either:
23
+ This software is multi licensed by Element Creations Ltd (Element). It can be used either:
24
24
 
25
25
  (1) for free under the terms of the GNU Affero General Public License (as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version); OR
26
26
 
@@ -1,9 +1,2 @@
1
1
  #!/bin/bash
2
-
3
- set -e
4
-
5
- if [[ "$YARN_INSTALL" == "true" ]]; then
6
- yarn install --frozen-lockfile
7
- fi
8
-
9
- npx playwright test --update-snapshots --reporter line "$@"
2
+ exec /usr/bin/playwright run-server --port "$PORT" --host 0.0.0.0
@@ -7,5 +7,5 @@ export type Expectations = {
7
7
  */
8
8
  toHaveNoViolations: (this: ExpectMatcherState, receiver: AxeBuilder) => Promise<MatcherReturnType>;
9
9
  };
10
- export declare const expect: import("@playwright/test").Expect<Expectations>;
10
+ export declare const expect: import("playwright/test").Expect<Expectations>;
11
11
  //# sourceMappingURL=axe.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"axe.d.ts","sourceRoot":"","sources":["../../src/expect/axe.ts"],"names":[],"mappings":"AAQA,OAAO,EAA8B,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE/G,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,MAAM,YAAY,GAAG;IACvB;;;OAGG;IACH,kBAAkB,EAAE,CAAC,IAAI,EAAE,kBAAkB,EAAE,QAAQ,EAAE,UAAU,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACtG,CAAC;AAEF,eAAO,MAAM,MAAM,iDAgBjB,CAAC"}
1
+ {"version":3,"file":"axe.d.ts","sourceRoot":"","sources":["../../src/expect/axe.ts"],"names":[],"mappings":"AAQA,OAAO,EAA8B,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE/G,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,MAAM,YAAY,GAAG;IACvB;;;OAGG;IACH,kBAAkB,EAAE,CAAC,IAAI,EAAE,kBAAkB,EAAE,QAAQ,EAAE,UAAU,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACtG,CAAC;AAEF,eAAO,MAAM,MAAM,gDAgBjB,CAAC"}
@@ -9,5 +9,5 @@ export type Expectations = {
9
9
  * Provides an upgrade to the `toHaveScreenshot` expectation.
10
10
  * Unfortunately, we can't just extend the existing `toHaveScreenshot` expectation
11
11
  */
12
- export declare const expect: import("@playwright/test").Expect<Expectations>;
12
+ export declare const expect: import("playwright/test").Expect<Expectations>;
13
13
  //# sourceMappingURL=screenshot.d.ts.map
@@ -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;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,iDA+BjB,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"}
@@ -1,8 +1,8 @@
1
1
  import { AxeBuilder } from "@axe-core/playwright";
2
- export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & {
2
+ export declare const test: import("playwright/test").TestType<import("playwright/test").PlaywrightTestArgs & import("playwright/test").PlaywrightTestOptions & {
3
3
  /**
4
4
  * AxeBuilder instance for the current page
5
5
  */
6
6
  axe: AxeBuilder;
7
- }, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions>;
7
+ }, import("playwright/test").PlaywrightWorkerArgs & import("playwright/test").PlaywrightWorkerOptions>;
8
8
  //# sourceMappingURL=axe.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"axe.d.ts","sourceRoot":"","sources":["../../src/fixtures/axe.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIlD,eAAO,MAAM,IAAI;IACb;;OAEG;SACE,UAAU;wGAMjB,CAAC"}
1
+ {"version":3,"file":"axe.d.ts","sourceRoot":"","sources":["../../src/fixtures/axe.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIlD,eAAO,MAAM,IAAI;IACb;;OAEG;SACE,UAAU;sGAMjB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../src/fixtures/services.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAuB,KAAK,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAElG,OAAO,EACH,KAAK,aAAa,EAElB,KAAK,2CAA2C,EAChD,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,EAE/B,KAAK,uBAAuB,EAC/B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAK5C;;GAEG;AACH,MAAM,WAAW,YAAY;IACzB;;;OAGG;IACH,aAAa,EAAE,aAAa,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC1B;;OAEG;IACH,aAAa,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACrB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,EAAE,cAAc,CAAC;IAExB;;OAEG;IACH,QAAQ,EAAE,0BAA0B,CAAC;IAErC;;OAEG;IACH,OAAO,EAAE,uBAAuB,CAAC;IAEjC;;OAEG;IACH,WAAW,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC1C;;OAEG;IACH,UAAU,EAAE,0BAA0B,CAAC;IAEvC;;;OAGG;IACH,GAAG,CAAC,EAAE,2CAA2C,CAAC;CACrD;AAED,eAAO,MAAM,IAAI;;gJA0Gf,CAAC"}
1
+ {"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../src/fixtures/services.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAE7E,OAAO,EACH,KAAK,aAAa,EAElB,KAAK,2CAA2C,EAChD,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,EAE/B,KAAK,uBAAuB,EAC/B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAM5C;;GAEG;AACH,MAAM,WAAW,YAAY;IACzB;;;OAGG;IACH,aAAa,EAAE,aAAa,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC1B;;OAEG;IACH,aAAa,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACrB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,EAAE,cAAc,CAAC;IAExB;;OAEG;IACH,QAAQ,EAAE,0BAA0B,CAAC;IAErC;;OAEG;IACH,OAAO,EAAE,uBAAuB,CAAC;IAEjC;;OAEG;IACH,WAAW,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC1C;;OAEG;IACH,UAAU,EAAE,0BAA0B,CAAC;IAEvC;;;OAGG;IACH,GAAG,CAAC,EAAE,2CAA2C,CAAC;CACrD;AAED,eAAO,MAAM,IAAI;;gJAsFf,CAAC"}
@@ -5,12 +5,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5
5
  Please see LICENSE files in the repository root for full details.
6
6
  */
7
7
  import { Network } from "testcontainers";
8
- import { PostgreSqlContainer } from "@testcontainers/postgresql";
9
8
  import { SynapseContainer, MailpitContainer, } from "../testcontainers/index.js";
10
9
  import { Logger } from "../utils/logger.js";
11
10
  // We want to avoid using `mergeTests` in index.ts because it drops useful type information about the fixtures. Instead,
12
11
  // we add `axe` into our fixture suite by using its `test` as a base, so that there is a linear hierarchy.
13
12
  import { test as base } from "./axe.js";
13
+ import { makePostgres } from "../testcontainers/postgres.js";
14
14
  export const test = base.extend({
15
15
  logger: [
16
16
  // eslint-disable-next-line no-empty-pattern
@@ -31,27 +31,7 @@ export const test = base.extend({
31
31
  ],
32
32
  postgres: [
33
33
  async ({ logger, network }, use) => {
34
- const container = await new PostgreSqlContainer("postgres:13.3-alpine")
35
- .withNetwork(network)
36
- .withNetworkAliases("postgres")
37
- .withLogConsumer(logger.getConsumer("postgres"))
38
- .withTmpFs({
39
- "/dev/shm/pgdata/data": "",
40
- })
41
- .withEnvironment({
42
- PG_DATA: "/dev/shm/pgdata/data",
43
- })
44
- .withCommand([
45
- "-c",
46
- "shared_buffers=128MB",
47
- "-c",
48
- `fsync=off`,
49
- "-c",
50
- `synchronous_commit=off`,
51
- "-c",
52
- "full_page_writes=off",
53
- ])
54
- .start();
34
+ const container = await makePostgres(network, logger);
55
35
  await use(container);
56
36
  await container.stop();
57
37
  },
@@ -2,7 +2,7 @@ import { type Page } from "@playwright/test";
2
2
  import { type Credentials } from "../utils/api.js";
3
3
  /** Adds an initScript to the given page which will populate localStorage appropriately so that Element will use the given credentials. */
4
4
  export declare function populateLocalStorageWithCredentials(page: Page, credentials: Credentials): Promise<void>;
5
- export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & {
5
+ export declare const test: import("playwright/test").TestType<import("playwright/test").PlaywrightTestArgs & import("playwright/test").PlaywrightTestOptions & {
6
6
  axe: import("@axe-core/playwright").AxeBuilder;
7
7
  } & import("./services.js").TestFixtures & {
8
8
  /**
@@ -31,5 +31,5 @@ export declare const test: import("@playwright/test").TestType<import("@playwrig
31
31
  * app.
32
32
  */
33
33
  user: Credentials;
34
- }, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions & import("./services.js").WorkerOptions & import("./services.js").Services>;
34
+ }, import("playwright/test").PlaywrightWorkerArgs & import("playwright/test").PlaywrightWorkerOptions & import("./services.js").WorkerOptions & import("./services.js").Services>;
35
35
  //# sourceMappingURL=user.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/fixtures/user.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAI7C,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,0IAA0I;AAC1I,wBAAsB,mCAAmC,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,iBAuB7F;AAED,eAAO,MAAM,IAAI;;;IACb;;;;;OAKG;kBACW,MAAM;IAEpB;;;OAGG;iBACU,WAAW;IAExB;;;;;;OAMG;yBACkB,IAAI;IAEzB;;;;OAIG;UACG,WAAW;mLA+BnB,CAAC"}
1
+ {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/fixtures/user.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAI7C,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,0IAA0I;AAC1I,wBAAsB,mCAAmC,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,iBAuB7F;AAED,eAAO,MAAM,IAAI;;;IACb;;;;;OAKG;kBACW,MAAM;IAEpB;;;OAGG;iBACU,WAAW;IAExB;;;;;;OAMG;yBACkB,IAAI;IAEzB;;;;OAIG;UACG,WAAW;iLA+BnB,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Flaky test reporter, creating & updating GitHub issues
3
+ * Only intended to run from within GitHub Actions
4
+ */
5
+ import type { Reporter, TestCase } from "@playwright/test/reporter";
6
+ declare class FlakyReporter implements Reporter {
7
+ private flakes;
8
+ onTestEnd(test: TestCase): void;
9
+ /**
10
+ * Parse link header to retrieve pagination links
11
+ * @see https://docs.github.com/en/rest/using-the-rest-api/using-pagination-in-the-rest-api?apiVersion=2022-11-28#using-link-headers
12
+ * @param link link header from response or undefined
13
+ * @returns an empty object if link is undefined otherwise returns a map from type to link
14
+ */
15
+ private parseLinkHeader;
16
+ /**
17
+ * Fetch all flaky test issues that were updated since Jan-1-2024
18
+ * @returns A promise that resolves to a list of issues
19
+ */
20
+ getAllIssues(): Promise<any[]>;
21
+ onExit(): Promise<void>;
22
+ }
23
+ export default FlakyReporter;
24
+ //# sourceMappingURL=flaky-reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flaky-reporter.d.ts","sourceRoot":"","sources":["../src/flaky-reporter.ts"],"names":[],"mappings":"AAQA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAuBpE,cAAM,aAAc,YAAW,QAAQ;IACnC,OAAO,CAAC,MAAM,CAAiC;IAExC,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IA2CtC;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAevB;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAuBvB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAuDvC;AAED,eAAe,aAAa,CAAC"}
@@ -0,0 +1,153 @@
1
+ /*
2
+ Copyright 2024 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
+ const REPO = "element-hq/element-web";
9
+ const LABEL = "Z-Flaky-Test";
10
+ const ISSUE_TITLE_PREFIX = "Flaky playwright test: ";
11
+ const ANSI_COLOUR_REGEX = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
12
+ // We see quite a few test flakes which are caused by the app exploding
13
+ // so we have some magic strings we check the logs for to better track the flake with its cause
14
+ const SPECIAL_CASES = {
15
+ "ChunkLoadError": "ChunkLoadError",
16
+ "Unreachable code should not be executed": "Rust crypto panic",
17
+ "Out of bounds memory access": "Rust crypto memory error",
18
+ };
19
+ class FlakyReporter {
20
+ flakes = new Map();
21
+ onTestEnd(test) {
22
+ // Ignores flakes on Dendrite and Pinecone as they have their own flakes we do not track
23
+ if (["Dendrite", "Pinecone"].includes(test.parent.project().name))
24
+ return;
25
+ if (test.outcome() === "flaky") {
26
+ const failures = [];
27
+ const timedOutRuns = test.results.filter((result) => result.status === "timedOut");
28
+ const pageLogs = timedOutRuns.flatMap((result) => result.attachments.filter((attachment) => attachment.name.startsWith("page-")));
29
+ // If a test failed due to a systemic fault then the test is not flaky, the app is, record it as such.
30
+ const specialCases = Object.keys(SPECIAL_CASES).filter((log) => pageLogs.some((attachment) => attachment.name.startsWith("page-") && attachment.body?.includes(log)));
31
+ if (specialCases.length > 0) {
32
+ failures.push(...specialCases.map((specialCase) => SPECIAL_CASES[specialCase]));
33
+ }
34
+ // Check for fixtures failing to set up
35
+ const errorMessages = timedOutRuns
36
+ .map((r) => r.error?.message?.replace(ANSI_COLOUR_REGEX, ""))
37
+ .filter(Boolean);
38
+ for (const error of errorMessages) {
39
+ if (error.startsWith("Fixture") && error.endsWith("exceeded during setup.")) {
40
+ failures.push(error);
41
+ }
42
+ }
43
+ if (failures.length < 1) {
44
+ failures.push(`${test.location.file.split("playwright/e2e/")[1]}: ${test.title}`);
45
+ }
46
+ for (const title of failures) {
47
+ if (!this.flakes.has(title)) {
48
+ this.flakes.set(title, []);
49
+ }
50
+ this.flakes.get(title).push(test);
51
+ }
52
+ }
53
+ }
54
+ /**
55
+ * Parse link header to retrieve pagination links
56
+ * @see https://docs.github.com/en/rest/using-the-rest-api/using-pagination-in-the-rest-api?apiVersion=2022-11-28#using-link-headers
57
+ * @param link link header from response or undefined
58
+ * @returns an empty object if link is undefined otherwise returns a map from type to link
59
+ */
60
+ parseLinkHeader(link) {
61
+ /**
62
+ * link looks like:
63
+ * <https://api.github.com/repositories/1300192/issues?page=2>; rel="prev", <https://api.github.com/repositories/1300192/issues?page=4>;
64
+ */
65
+ const map = {};
66
+ if (!link)
67
+ return map;
68
+ const matches = link.matchAll(/(<(?<link>.+?)>; rel="(?<type>.+?)")/g);
69
+ for (const match of matches) {
70
+ const { link, type } = match.groups;
71
+ map[type] = link;
72
+ }
73
+ return map;
74
+ }
75
+ /**
76
+ * Fetch all flaky test issues that were updated since Jan-1-2024
77
+ * @returns A promise that resolves to a list of issues
78
+ */
79
+ async getAllIssues() {
80
+ const issues = [];
81
+ const { GITHUB_TOKEN, GITHUB_API_URL } = process.env;
82
+ // See https://docs.github.com/en/rest/issues/issues?apiVersion=2022-11-28#list-repository-issues
83
+ let url = `${GITHUB_API_URL}/repos/${REPO}/issues?labels=${LABEL}&state=all&per_page=100&sort=updated&since=2024-01-01`;
84
+ const headers = {
85
+ Authorization: `Bearer ${GITHUB_TOKEN}`,
86
+ Accept: "application / vnd.github + json",
87
+ };
88
+ while (url) {
89
+ // Fetch issues and add to list
90
+ const issuesResponse = await fetch(url, { headers });
91
+ const fetchedIssues = await issuesResponse.json();
92
+ issues.push(...fetchedIssues);
93
+ // Get the next link for fetching more results
94
+ const linkHeader = issuesResponse.headers.get("Link");
95
+ const parsed = this.parseLinkHeader(linkHeader);
96
+ url = parsed.next;
97
+ }
98
+ return issues;
99
+ }
100
+ async onExit() {
101
+ if (this.flakes.size === 0) {
102
+ console.log("No flakes found");
103
+ return;
104
+ }
105
+ console.log("Found flakes: ");
106
+ for (const flake of this.flakes) {
107
+ console.log(flake);
108
+ }
109
+ const { GITHUB_TOKEN, GITHUB_API_URL, GITHUB_SERVER_URL, GITHUB_REPOSITORY, GITHUB_RUN_ID } = process.env;
110
+ if (!GITHUB_TOKEN)
111
+ return;
112
+ const issues = await this.getAllIssues();
113
+ for (const [flake, results] of this.flakes) {
114
+ const title = ISSUE_TITLE_PREFIX + "`" + flake + "`";
115
+ const existingIssue = issues.find((issue) => issue.title === title);
116
+ const headers = { Authorization: `Bearer ${GITHUB_TOKEN}` };
117
+ const body = `${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}`;
118
+ const labels = [LABEL, ...results.map((test) => `${LABEL}-${test.parent.project()?.name}`)];
119
+ if (existingIssue) {
120
+ console.log(`Found issue ${existingIssue.number} for ${flake}, adding comment...`);
121
+ // Ensure that the test is open
122
+ await fetch(existingIssue.url, {
123
+ method: "PATCH",
124
+ headers,
125
+ body: JSON.stringify({ state: "open" }),
126
+ });
127
+ await fetch(`${existingIssue.url}/labels`, {
128
+ method: "POST",
129
+ headers,
130
+ body: JSON.stringify({ labels }),
131
+ });
132
+ await fetch(`${existingIssue.url}/comments`, {
133
+ method: "POST",
134
+ headers,
135
+ body: JSON.stringify({ body }),
136
+ });
137
+ }
138
+ else {
139
+ console.log(`Creating new issue for ${flake}...`);
140
+ await fetch(`${GITHUB_API_URL}/repos/${REPO}/issues`, {
141
+ method: "POST",
142
+ headers,
143
+ body: JSON.stringify({
144
+ title,
145
+ body,
146
+ labels: [...labels],
147
+ }),
148
+ });
149
+ }
150
+ }
151
+ }
152
+ }
153
+ export default FlakyReporter;
@@ -8,11 +8,12 @@ export declare const ANNOTATION = "_screenshot";
8
8
  declare class StaleScreenshotReporter implements Reporter {
9
9
  private readonly snapshotRoots;
10
10
  private readonly screenshots;
11
- private failing;
11
+ private readonly failing;
12
12
  private success;
13
13
  onBegin(config: FullConfig): void;
14
14
  onTestEnd(test: TestCase): void;
15
15
  private error;
16
+ private checkStaleScreenshots;
16
17
  onExit(): Promise<void>;
17
18
  }
18
19
  export default StaleScreenshotReporter;
@@ -1 +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"}
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,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,OAAO,CAAQ;IAEhB,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAMjC,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IActC,OAAO,CAAC,KAAK;YAQC,qBAAqB;IAgCtB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAWvC;AAED,eAAe,uBAAuB,CAAC"}
@@ -19,7 +19,7 @@ export const ANNOTATION = "_screenshot";
19
19
  class StaleScreenshotReporter {
20
20
  snapshotRoots = new Set();
21
21
  screenshots = new Set();
22
- failing = false;
22
+ failing = new Set();
23
23
  success = true;
24
24
  onBegin(config) {
25
25
  for (const project of config.projects) {
@@ -28,8 +28,10 @@ class StaleScreenshotReporter {
28
28
  }
29
29
  onTestEnd(test) {
30
30
  if (!test.ok()) {
31
- this.failing = true;
31
+ this.failing.add(test.id);
32
+ return;
32
33
  }
34
+ this.failing.delete(test.id); // delete if passed on re-run
33
35
  for (const annotation of test.annotations) {
34
36
  if (annotation.type === ANNOTATION && annotation.description) {
35
37
  this.screenshots.add(annotation.description);
@@ -43,9 +45,7 @@ class StaleScreenshotReporter {
43
45
  console.error(msg, file);
44
46
  this.success = false;
45
47
  }
46
- async onExit() {
47
- if (this.failing)
48
- return;
48
+ async checkStaleScreenshots() {
49
49
  if (!this.snapshotRoots.size) {
50
50
  this.error("No snapshot directories found, did you set the snapshotDir in your Playwright config?", "");
51
51
  return;
@@ -70,6 +70,14 @@ class StaleScreenshotReporter {
70
70
  this.error("Stale screenshot file", screenshot);
71
71
  }
72
72
  }
73
+ }
74
+ async onExit() {
75
+ if (this.failing.size) {
76
+ this.error(`${this.failing.size} tests failed, skipping stale screenshot reporter.`, "");
77
+ }
78
+ else {
79
+ await this.checkStaleScreenshots();
80
+ }
73
81
  if (!this.success) {
74
82
  process.exit(1);
75
83
  }
@@ -1,6 +1,7 @@
1
1
  export { PostgreSqlContainer, StartedPostgreSqlContainer } from "@testcontainers/postgresql";
2
+ export { makePostgres } from "./postgres.js";
2
3
  export type { HomeserverInstance, HomeserverContainer, StartedHomeserverContainer } from "./HomeserverContainer.js";
3
4
  export { type SynapseConfig, SynapseContainer, StartedSynapseContainer } from "./synapse.js";
4
- export { type MasConfig, MatrixAuthenticationServiceContainer, StartedMatrixAuthenticationServiceContainer, } from "./mas.js";
5
+ export { type MasConfig, MatrixAuthenticationServiceContainer, StartedMatrixAuthenticationServiceContainer, makeMas, } from "./mas.js";
5
6
  export { type MailpitClient, MailpitContainer, StartedMailpitContainer } from "./mailpit.js";
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testcontainers/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAC7F,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACpH,OAAO,EAAE,KAAK,aAAa,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAC7F,OAAO,EACH,KAAK,SAAS,EACd,oCAAoC,EACpC,2CAA2C,GAC9C,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,KAAK,aAAa,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testcontainers/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAC7F,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACpH,OAAO,EAAE,KAAK,aAAa,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAC7F,OAAO,EACH,KAAK,SAAS,EACd,oCAAoC,EACpC,2CAA2C,EAC3C,OAAO,GACV,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,KAAK,aAAa,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC"}
@@ -5,6 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5
5
  Please see LICENSE files in the repository root for full details.
6
6
  */
7
7
  export { PostgreSqlContainer, StartedPostgreSqlContainer } from "@testcontainers/postgresql";
8
+ export { makePostgres } from "./postgres.js";
8
9
  export { SynapseContainer, StartedSynapseContainer } from "./synapse.js";
9
- export { MatrixAuthenticationServiceContainer, StartedMatrixAuthenticationServiceContainer, } from "./mas.js";
10
+ export { MatrixAuthenticationServiceContainer, StartedMatrixAuthenticationServiceContainer, makeMas, } from "./mas.js";
10
11
  export { MailpitContainer, StartedMailpitContainer } from "./mailpit.js";
@@ -1,7 +1,8 @@
1
- import { AbstractStartedContainer, GenericContainer, type StartedTestContainer, type ExecResult } from "testcontainers";
1
+ import { AbstractStartedContainer, GenericContainer, type StartedTestContainer, type ExecResult, type StartedNetwork } from "testcontainers";
2
2
  import { type StartedPostgreSqlContainer } from "@testcontainers/postgresql";
3
3
  import { type Credentials } from "../utils/api.js";
4
4
  import type { RootConfig as MasConfig } from "./mas-config.js";
5
+ import type { Logger } from "../utils/logger.js";
5
6
  export { type MasConfig };
6
7
  /**
7
8
  * A container running the Matrix Authentication Service.
@@ -29,8 +30,9 @@ export declare class MatrixAuthenticationServiceContainer extends GenericContain
29
30
  export declare class StartedMatrixAuthenticationServiceContainer extends AbstractStartedContainer {
30
31
  readonly baseUrl: string;
31
32
  private readonly args;
33
+ readonly sharedSecret: string;
32
34
  private adminTokenPromise?;
33
- constructor(container: StartedTestContainer, baseUrl: string, args: string[]);
35
+ constructor(container: StartedTestContainer, baseUrl: string, args: string[], sharedSecret: string);
34
36
  /**
35
37
  * Retrieves a valid HS admin token
36
38
  */
@@ -55,4 +57,5 @@ export declare class StartedMatrixAuthenticationServiceContainer extends Abstrac
55
57
  */
56
58
  setThreepid(username: string, medium: string, address: string): Promise<void>;
57
59
  }
60
+ export declare function makeMas(postgres: StartedPostgreSqlContainer, network: StartedNetwork, logger: Logger, config: Partial<MasConfig>, name?: string): Promise<StartedMatrixAuthenticationServiceContainer>;
58
61
  //# sourceMappingURL=mas.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mas.d.ts","sourceRoot":"","sources":["../../src/testcontainers/mas.ts"],"names":[],"mappings":"AAOA,OAAO,EACH,wBAAwB,EACxB,gBAAgB,EAChB,KAAK,oBAAoB,EAEzB,KAAK,UAAU,EAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAK7E,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAKnD,OAAO,KAAK,EAAE,UAAU,IAAI,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EAAE,KAAK,SAAS,EAAE,CAAC;AAmH1B;;;;;GAKG;AACH,qBAAa,oCAAqC,SAAQ,gBAAgB;IACtE,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiC;gBAGlD,EAAE,EAAE,0BAA0B,EAC9B,KAAK,GAAE,MAAkE;IAe7E;;;OAGG;IACI,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI;IAQnD;;OAEG;IACmB,KAAK,IAAI,OAAO,CAAC,2CAA2C,CAAC;CA0BtF;AAED;;GAEG;AACH,qBAAa,2CAA4C,SAAQ,wBAAwB;aAKjE,OAAO,EAAE,MAAM;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI;IALzB,OAAO,CAAC,iBAAiB,CAAC,CAAkB;gBAGxC,SAAS,EAAE,oBAAoB,EACf,OAAO,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EAAE;IAKnC;;OAEG;IACU,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAYhC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;YAQ1D,kBAAkB;YAgClB,6BAA6B;YAmB7B,oBAAoB;IAoBlC;;;;;;OAMG;IACU,YAAY,CACrB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAIlD;;;;;OAKG;IACU,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAO7F"}
1
+ {"version":3,"file":"mas.d.ts","sourceRoot":"","sources":["../../src/testcontainers/mas.ts"],"names":[],"mappings":"AAOA,OAAO,EACH,wBAAwB,EACxB,gBAAgB,EAChB,KAAK,oBAAoB,EAEzB,KAAK,UAAU,EACf,KAAK,cAAc,EACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAK7E,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAKnD,OAAO,KAAK,EAAE,UAAU,IAAI,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO,EAAE,KAAK,SAAS,EAAE,CAAC;AAmH1B;;;;;GAKG;AACH,qBAAa,oCAAqC,SAAQ,gBAAgB;IACtE,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiC;gBAGlD,EAAE,EAAE,0BAA0B,EAC9B,KAAK,GAAE,MAAkE;IAgB7E;;;OAGG;IACI,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI;IAQnD;;OAEG;IACmB,KAAK,IAAI,OAAO,CAAC,2CAA2C,CAAC;CA2BtF;AAED;;GAEG;AACH,qBAAa,2CAA4C,SAAQ,wBAAwB;aAKjE,OAAO,EAAE,MAAM;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI;aACL,YAAY,EAAE,MAAM;IANxC,OAAO,CAAC,iBAAiB,CAAC,CAAkB;gBAGxC,SAAS,EAAE,oBAAoB,EACf,OAAO,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EAAE,EACf,YAAY,EAAE,MAAM;IAKxC;;OAEG;IACU,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAYhC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;YAQ1D,kBAAkB;YAgClB,6BAA6B;YAmB7B,oBAAoB;IAoBlC;;;;;;OAMG;IACU,YAAY,CACrB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAIlD;;;;;OAKG;IACU,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAO7F;AAED,wBAAsB,OAAO,CACzB,QAAQ,EAAE,0BAA0B,EACpC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,EAC1B,IAAI,SAAQ,GACb,OAAO,CAAC,2CAA2C,CAAC,CAQtD"}
@@ -132,6 +132,7 @@ export class MatrixAuthenticationServiceContainer extends GenericContainer {
132
132
  constructor(db, image = "ghcr.io/element-hq/matrix-authentication-service:latest") {
133
133
  super(image);
134
134
  const initialConfig = deepCopy(DEFAULT_CONFIG);
135
+ initialConfig.database.host = db.getHostname();
135
136
  initialConfig.database.username = db.getUsername();
136
137
  initialConfig.database.password = db.getPassword();
137
138
  this.config = initialConfig;
@@ -170,7 +171,7 @@ export class MatrixAuthenticationServiceContainer extends GenericContainer {
170
171
  content: YAML.stringify(this.config),
171
172
  },
172
173
  ]);
173
- return new StartedMatrixAuthenticationServiceContainer(await super.start(), `http://localhost:${port}`, this.args);
174
+ return new StartedMatrixAuthenticationServiceContainer(await super.start(), `http://localhost:${port}`, this.args, this.config.matrix.secret);
174
175
  }
175
176
  }
176
177
  /**
@@ -179,11 +180,13 @@ export class MatrixAuthenticationServiceContainer extends GenericContainer {
179
180
  export class StartedMatrixAuthenticationServiceContainer extends AbstractStartedContainer {
180
181
  baseUrl;
181
182
  args;
183
+ sharedSecret;
182
184
  adminTokenPromise;
183
- constructor(container, baseUrl, args) {
185
+ constructor(container, baseUrl, args, sharedSecret) {
184
186
  super(container);
185
187
  this.baseUrl = baseUrl;
186
188
  this.args = args;
189
+ this.sharedSecret = sharedSecret;
187
190
  }
188
191
  /**
189
192
  * Retrieves a valid HS admin token
@@ -265,3 +268,12 @@ export class StartedMatrixAuthenticationServiceContainer extends AbstractStarted
265
268
  await this.manage("add-email", username, address);
266
269
  }
267
270
  }
271
+ export async function makeMas(postgres, network, logger, config, name = "mas") {
272
+ const container = await new MatrixAuthenticationServiceContainer(postgres)
273
+ .withNetwork(network)
274
+ .withNetworkAliases(name)
275
+ .withLogConsumer(logger.getConsumer(name))
276
+ .withConfig(config)
277
+ .start();
278
+ return container;
279
+ }
@@ -0,0 +1,5 @@
1
+ import { type StartedPostgreSqlContainer } from "@testcontainers/postgresql";
2
+ import { type StartedNetwork } from "testcontainers";
3
+ import { type Logger } from "../utils/logger.js";
4
+ export declare function makePostgres(network: StartedNetwork, logger: Logger, name?: string): Promise<StartedPostgreSqlContainer>;
5
+ //# sourceMappingURL=postgres.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/testcontainers/postgres.ts"],"names":[],"mappings":"AAOA,OAAO,EAAuB,KAAK,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAClG,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,wBAAsB,YAAY,CAC9B,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,MAAM,EACd,IAAI,SAAa,GAClB,OAAO,CAAC,0BAA0B,CAAC,CAuBrC"}
@@ -0,0 +1,31 @@
1
+ /*
2
+ Copyright 2026 Element Creations Ltd.
3
+
4
+ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5
+ Please see LICENSE files in the repository root for full details.
6
+ */
7
+ import { PostgreSqlContainer } from "@testcontainers/postgresql";
8
+ export async function makePostgres(network, logger, name = "postgres") {
9
+ const container = await new PostgreSqlContainer("postgres:13.3-alpine")
10
+ .withNetwork(network)
11
+ .withNetworkAliases(name)
12
+ .withLogConsumer(logger.getConsumer(name))
13
+ .withTmpFs({
14
+ "/dev/shm/pgdata/data": "",
15
+ })
16
+ .withEnvironment({
17
+ PG_DATA: "/dev/shm/pgdata/data",
18
+ })
19
+ .withCommand([
20
+ "-c",
21
+ "shared_buffers=128MB",
22
+ "-c",
23
+ `fsync=off`,
24
+ "-c",
25
+ `synchronous_commit=off`,
26
+ "-c",
27
+ "full_page_writes=off",
28
+ ])
29
+ .start();
30
+ return container;
31
+ }
@@ -153,6 +153,12 @@ declare const DEFAULT_CONFIG: {
153
153
  module: string;
154
154
  config?: Record<string, unknown>;
155
155
  }>;
156
+ matrix_authentication_service: undefined | {
157
+ enabled?: boolean;
158
+ endpoint?: string;
159
+ secret?: string | null;
160
+ secret_path?: string | null;
161
+ };
156
162
  };
157
163
  /**
158
164
  * Incomplete type describing the configuration for a Synapse homeserver
@@ -1 +1 @@
1
- {"version":3,"file":"synapse.d.ts","sourceRoot":"","sources":["../../src/testcontainers/synapse.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"synapse.d.ts","sourceRoot":"","sources":["../../src/testcontainers/synapse.ts"],"names":[],"mappings":"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"}