From 5983528a8d4e20db46638428984c9f3952ede8f3 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 16 Jan 2024 09:48:49 +0000 Subject: [PATCH] Remove Cypress & Playwright in their entirety (#12145) --- .eslintrc.js | 24 +- .github/workflows/cypress.yaml | 231 ---- .github/workflows/element-web.yaml | 8 +- .gitignore | 11 - .percy.yml | 7 - README.md | 6 +- cypress-ci-reporter-config.json | 7 - cypress.config.ts | 54 - cypress/e2e/dummy.spec.ts | 19 - cypress/e2e/utils.ts | 52 - cypress/fixtures/riot.png | Bin 13818 -> 0 bytes cypress/global.d.ts | 62 - cypress/plugins/dendritedocker/index.ts | 207 --- .../templates/default/dendrite.yaml | 378 ------ cypress/plugins/docker/index.ts | 180 --- cypress/plugins/index.ts | 46 - cypress/plugins/log.ts | 35 - cypress/plugins/mailhog/index.ts | 91 -- cypress/plugins/synapsedocker/index.ts | 218 --- .../synapsedocker/templates/COPYME/README.md | 3 - .../templates/COPYME/homeserver.yaml | 72 - .../synapsedocker/templates/COPYME/log.config | 50 - .../synapsedocker/templates/consent/README.md | 1 - .../templates/consent/homeserver.yaml | 84 -- .../templates/consent/log.config | 50 - .../consent/res/templates/privacy/en/1.0.html | 19 - .../res/templates/privacy/en/success.html | 9 - .../synapsedocker/templates/default/README.md | 1 - .../templates/default/homeserver.yaml | 94 -- .../templates/default/log.config | 50 - .../synapsedocker/templates/email/README.md | 1 - .../templates/email/homeserver.yaml | 44 - .../synapsedocker/templates/email/log.config | 50 - cypress/plugins/utils/homeserver.ts | 28 - cypress/plugins/utils/port.ts | 27 - cypress/plugins/webserver.ts | 52 - cypress/support/app.ts | 45 - cypress/support/axe.ts | 101 -- cypress/support/bot.ts | 369 ----- cypress/support/client.ts | 218 --- cypress/support/clipboard.ts | 57 - cypress/support/composer.ts | 48 - cypress/support/config.json.ts | 51 - cypress/support/e2e.ts | 59 - cypress/support/homeserver.ts | 155 --- cypress/support/iframes.ts | 49 - cypress/support/labs.ts | 45 - cypress/support/log.ts | 45 - cypress/support/login.ts | 169 --- cypress/support/mailhog.ts | 54 - cypress/support/percy.ts | 70 - cypress/support/promise.ts | 58 - cypress/support/settings.ts | 190 --- cypress/support/toasts.ts | 27 - cypress/support/util.ts | 84 -- cypress/support/views.ts | 68 - cypress/support/webserver.ts | 52 - cypress/tsconfig.json | 13 - docs/SUMMARY.md | 2 +- docs/cypress.md | 281 ---- package.json | 18 +- .../e2e/audio-player/audio-player.spec.ts | 24 +- playwright/e2e/right-panel/file-panel.spec.ts | 12 +- playwright/e2e/spaces/spaces.spec.ts | 6 +- playwright/e2e/timeline/timeline.spec.ts | 14 +- .../plugins/sliding-sync-proxy/index.ts | 4 +- .../1sec-long-name-audio-file.ogg | Bin .../sample-files}/1sec.ogg | Bin .../sample-files}/element.png | Bin .../matrix-org-client-versions.json | 0 .../sample-files}/upload-first.ogg | Bin .../sample-files}/upload-second.ogg | Bin .../sample-files}/upload-third.ogg | Bin res/css/views/rooms/_ReplyTile.pcss | 13 - sonar-project.properties | 4 +- src/Notifier.ts | 2 +- .../views/settings/ChangePassword.tsx | 2 +- yarn.lock | 1205 +---------------- 78 files changed, 73 insertions(+), 5812 deletions(-) delete mode 100644 .github/workflows/cypress.yaml delete mode 100644 .percy.yml delete mode 100644 cypress-ci-reporter-config.json delete mode 100644 cypress.config.ts delete mode 100644 cypress/e2e/dummy.spec.ts delete mode 100644 cypress/e2e/utils.ts delete mode 100644 cypress/fixtures/riot.png delete mode 100644 cypress/global.d.ts delete mode 100644 cypress/plugins/dendritedocker/index.ts delete mode 100644 cypress/plugins/dendritedocker/templates/default/dendrite.yaml delete mode 100644 cypress/plugins/docker/index.ts delete mode 100644 cypress/plugins/index.ts delete mode 100644 cypress/plugins/log.ts delete mode 100644 cypress/plugins/mailhog/index.ts delete mode 100644 cypress/plugins/synapsedocker/index.ts delete mode 100644 cypress/plugins/synapsedocker/templates/COPYME/README.md delete mode 100644 cypress/plugins/synapsedocker/templates/COPYME/homeserver.yaml delete mode 100644 cypress/plugins/synapsedocker/templates/COPYME/log.config delete mode 100644 cypress/plugins/synapsedocker/templates/consent/README.md delete mode 100644 cypress/plugins/synapsedocker/templates/consent/homeserver.yaml delete mode 100644 cypress/plugins/synapsedocker/templates/consent/log.config delete mode 100644 cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html delete mode 100644 cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html delete mode 100644 cypress/plugins/synapsedocker/templates/default/README.md delete mode 100644 cypress/plugins/synapsedocker/templates/default/homeserver.yaml delete mode 100644 cypress/plugins/synapsedocker/templates/default/log.config delete mode 100644 cypress/plugins/synapsedocker/templates/email/README.md delete mode 100644 cypress/plugins/synapsedocker/templates/email/homeserver.yaml delete mode 100644 cypress/plugins/synapsedocker/templates/email/log.config delete mode 100644 cypress/plugins/utils/homeserver.ts delete mode 100644 cypress/plugins/utils/port.ts delete mode 100644 cypress/plugins/webserver.ts delete mode 100644 cypress/support/app.ts delete mode 100644 cypress/support/axe.ts delete mode 100644 cypress/support/bot.ts delete mode 100644 cypress/support/client.ts delete mode 100644 cypress/support/clipboard.ts delete mode 100644 cypress/support/composer.ts delete mode 100644 cypress/support/config.json.ts delete mode 100644 cypress/support/e2e.ts delete mode 100644 cypress/support/homeserver.ts delete mode 100644 cypress/support/iframes.ts delete mode 100644 cypress/support/labs.ts delete mode 100644 cypress/support/log.ts delete mode 100644 cypress/support/login.ts delete mode 100644 cypress/support/mailhog.ts delete mode 100644 cypress/support/percy.ts delete mode 100644 cypress/support/promise.ts delete mode 100644 cypress/support/settings.ts delete mode 100644 cypress/support/toasts.ts delete mode 100644 cypress/support/util.ts delete mode 100644 cypress/support/views.ts delete mode 100644 cypress/support/webserver.ts delete mode 100644 cypress/tsconfig.json delete mode 100644 docs/cypress.md rename {cypress/fixtures => playwright/sample-files}/1sec-long-name-audio-file.ogg (100%) rename {cypress/fixtures => playwright/sample-files}/1sec.ogg (100%) rename {cypress/fixtures => playwright/sample-files}/element.png (100%) rename {cypress/fixtures => playwright/sample-files}/matrix-org-client-versions.json (100%) rename {cypress/fixtures => playwright/sample-files}/upload-first.ogg (100%) rename {cypress/fixtures => playwright/sample-files}/upload-second.ogg (100%) rename {cypress/fixtures => playwright/sample-files}/upload-third.ogg (100%) diff --git a/.eslintrc.js b/.eslintrc.js index f0720a0252..342dbde484 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -169,7 +169,7 @@ module.exports = { }, overrides: [ { - files: ["src/**/*.{ts,tsx}", "test/**/*.{ts,tsx}", "cypress/**/*.ts", "playwright/**/*.ts"], + files: ["src/**/*.{ts,tsx}", "test/**/*.{ts,tsx}", "playwright/**/*.ts"], extends: ["plugin:matrix-org/typescript", "plugin:matrix-org/react"], rules: { "@typescript-eslint/explicit-function-return-type": [ @@ -233,14 +233,14 @@ module.exports = { }, }, { - files: ["test/**/*.{ts,tsx}", "cypress/**/*.ts", "playwright/**/*.ts"], + files: ["test/**/*.{ts,tsx}", "playwright/**/*.ts"], extends: ["plugin:matrix-org/jest"], rules: { // We don't need super strict typing in test utilities "@typescript-eslint/explicit-function-return-type": "off", "@typescript-eslint/explicit-member-accessibility": "off", - // Jest/Cypress specific + // Jest/Playwright specific // Disabled tests are a reality for now but as soon as all of the xits are // eliminated, we should enforce this. @@ -255,29 +255,11 @@ module.exports = { ], }, }, - { - files: ["cypress/**/*.ts"], - parserOptions: { - project: ["./cypress/tsconfig.json"], - }, - rules: { - // Cypress "promises" work differently - disable some related rules - "jest/valid-expect": "off", - "jest/valid-expect-in-promise": "off", - "jest/no-done-callback": "off", - }, - }, { files: ["playwright/**/*.ts"], parserOptions: { project: ["./playwright/tsconfig.json"], }, - rules: { - // Cypress "promises" work differently - disable some related rules - "jest/valid-expect": "off", - "jest/valid-expect-in-promise": "off", - "jest/no-done-callback": "off", - }, }, ], settings: { diff --git a/.github/workflows/cypress.yaml b/.github/workflows/cypress.yaml deleted file mode 100644 index b0100fcd8d..0000000000 --- a/.github/workflows/cypress.yaml +++ /dev/null @@ -1,231 +0,0 @@ -# Triggers after the layered build has finished, taking the artifact and running cypress on it -# -# Also called by a workflow in matrix-js-sdk. -# -name: Cypress End to End Tests -on: - workflow_run: - workflows: ["Element Web - Build"] - types: - - completed - - # support calls from other workflows - workflow_call: - inputs: - react-sdk-repository: - type: string - required: true - description: "The name of the github repository to check out and build." - secrets: - KNAPSACK_PRO_TEST_SUITE_TOKEN_CYPRESS_RUST: - required: true - KNAPSACK_PRO_TEST_SUITE_TOKEN_CYPRESS_LEGACY: - required: true - TCMS_USERNAME: - required: true - TCMS_PASSWORD: - required: true - -concurrency: - group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.run_id }} - cancel-in-progress: ${{ github.event.workflow_run.event == 'pull_request' }} - -jobs: - prepare: - name: Prepare - if: github.event.workflow_run.conclusion == 'success' - runs-on: ubuntu-latest - permissions: - actions: read - issues: read - statuses: write - pull-requests: read - outputs: - uuid: ${{ steps.uuid.outputs.value }} - pr_id: ${{ steps.prdetails.outputs.pr_id }} - percy_enable: ${{ steps.percy.outputs.value || '0' }} - steps: - # We create the status here and then update it to success/failure in the `report` stage - # This provides an easy link to this workflow_run from the PR before Cypress is done. - - uses: Sibz/github-status-action@071b5370da85afbb16637d6eed8524a06bc2053e # v1 - with: - authToken: ${{ secrets.GITHUB_TOKEN }} - state: pending - context: ${{ github.workflow }} / cypress - sha: ${{ github.event.workflow_run.head_sha }} - target_url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} - - - id: prdetails - if: github.event.workflow_run.event == 'pull_request' || github.event.workflow_run.event == 'merge_group' - uses: matrix-org/pr-details-action@v1.3 - with: - owner: ${{ github.event.workflow_run.head_repository.owner.login }} - branch: ${{ github.event.workflow_run.head_branch }} - - # Percy is disabled while we're figuring out https://github.com/vector-im/wat-internal/issues/36 - # and https://github.com/vector-im/wat-internal/issues/56. We're hoping to turn it back on or switch - # to an alternative in the future. - # # Only run Percy when it is demanded or we are running the daily build - # - name: Enable Percy - # id: percy - # if: | - # github.event.workflow_run.event == 'schedule' || - # ( - # github.event.workflow_run.event == 'merge_group' && - # contains(fromJSON(steps.prdetails.outputs.data).labels.*.name, 'X-Needs-Percy') - # ) - # run: echo "value=1" >> $GITHUB_OUTPUT - - - name: Generate unique ID 💎 - id: uuid - run: echo "value=sha-$GITHUB_SHA-time-$(date +"%s")" >> $GITHUB_OUTPUT - - tests: - name: "Run Tests (${{ matrix.crypto }} crypto)" - needs: prepare - runs-on: ubuntu-latest - permissions: - actions: read - issues: read - pull-requests: read - environment: Cypress - strategy: - fail-fast: false - matrix: - # Run tests using both crypto stacks - crypto: [legacy, rust] - ci_node_total: [2] - ci_node_index: [0, 1] - steps: - # The version of chrome shipped by default may not be consistent across runners - # so we explicitly use a specific version of chrome here. - - uses: browser-actions/setup-chrome@803ef6dfb4fdf22089c9563225d95e4a515820a0 # v1 - - run: echo "BROWSER_PATH=$(which chrome)" >> $GITHUB_ENV - - # There's a 'download artifact' action, but it hasn't been updated for the workflow_run action - # (https://github.com/actions/download-artifact/issues/60) so instead we get this mess: - - name: 📥 Download artifact - uses: dawidd6/action-download-artifact@f29d1b6a8930683e80acedfbe6baa2930cd646b4 # v2 - with: - run_id: ${{ github.event.workflow_run.id }} - name: previewbuild - path: webapp - - # The workflow_run.head_sha is the sha of the head commit but the element-web was built using a simulated - # merge commit - https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request - # so use the sha from the tarball for the checkout of the cypress tests - # to make sure we get a matching set of code and tests. - - name: Grab sha from webapp - id: sha - run: | - echo "sha=$(cat webapp/sha)" >> $GITHUB_OUTPUT - - - uses: actions/checkout@v4 - with: - # XXX: We're checking out untrusted code in a secure context - # We need to be careful to not trust anything this code outputs/may do - # - # Note that (in the absence of a `react-sdk-repository` input), - # we check out from the default repository, which is (for this workflow) the - # *target* repository for the pull request. - # - ref: ${{ steps.sha.outputs.sha }} - persist-credentials: false - path: matrix-react-sdk - repository: ${{ inputs.react-sdk-repository || github.repository }} - - # Enable rust crypto if the calling workflow requests it - - name: Enable rust crypto - if: matrix.crypto == 'rust' - run: | - echo "CYPRESS_RUST_CRYPTO=1" >> "$GITHUB_ENV" - - - name: Run Cypress tests via knapsack pro - uses: cypress-io/github-action@ebe8b24c4428922d0f793a5c4c96853a633180e3 # v6.6.0 - with: - working-directory: matrix-react-sdk - headed: true - start: npx serve -p 8080 -L ../webapp - wait-on: "http://localhost:8080" - record: false - parallel: false - # The built-in Electron runner seems to grind to a halt trying to run the tests, so use chrome. - command: yarn percy exec --parallel -- npx knapsack-pro-cypress --config trashAssetsBeforeRuns=false --browser ${{ env.BROWSER_PATH }} - env: - # Knapsack token and config - KNAPSACK_PRO_TEST_SUITE_TOKEN_CYPRESS: ${{ matrix.crypto == 'rust' && secrets.KNAPSACK_PRO_TEST_SUITE_TOKEN_CYPRESS_RUST || secrets.KNAPSACK_PRO_TEST_SUITE_TOKEN_CYPRESS_LEGACY }} - KNAPSACK_PRO_CI_NODE_TOTAL: ${{ matrix.ci_node_total }} - KNAPSACK_PRO_CI_NODE_INDEX: ${{ matrix.ci_node_index }} - KNAPSACK_PRO_TEST_FILE_PATTERN: cypress/e2e/**/*.spec.ts - KNAPSACK_PRO_BRANCH: ${{ github.event.workflow_run.head_branch }} - KNAPSACK_PRO_COMMIT_HASH: ${{ github.event.workflow_run.head_sha }} - - # Use existing chromium rather than downloading another - PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true - - # pass GitHub token to allow accurately detecting a build vs a re-run build - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - # make Node's os.tmpdir() return something where we actually have permissions - TMPDIR: ${{ runner.temp }} - - # pass the Percy token as an environment variable - PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }} - - # only run percy on legacy crypto (for now) - PERCY_ENABLE: ${{ matrix.crypto == 'legacy' && needs.prepare.outputs.percy_enable || 0 }} - PERCY_BROWSER_EXECUTABLE: ${{ steps.setup-chrome.outputs.chrome-path }} - # tell Percy more details about the context of this run - PERCY_BRANCH: ${{ github.event.workflow_run.head_branch }} - PERCY_COMMIT: ${{ github.event.workflow_run.head_sha }} - PERCY_PULL_REQUEST: ${{ needs.prepare.outputs.pr_id }} - PERCY_PARALLEL_NONCE: ${{ needs.prepare.outputs.uuid }} - # We manually finalize the build in the report stage - PERCY_PARALLEL_TOTAL: -1 - - - name: 📤 Upload results artifact - if: failure() - uses: actions/upload-artifact@v3 - with: - name: cypress-results-${{ matrix.crypto }}-crypto - path: | - matrix-react-sdk/cypress/screenshots - matrix-react-sdk/cypress/videos - matrix-react-sdk/cypress/synapselogs - matrix-react-sdk/cypress/results/cypresslogs - - report: - name: Finalize results - needs: - - prepare - - tests - runs-on: ubuntu-latest - if: always() - permissions: - statuses: write - steps: - - name: Finalize Percy - if: needs.prepare.outputs.percy_enable == '1' - run: npx -p @percy/cli percy build:finalize - env: - PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }} - PERCY_PARALLEL_NONCE: ${{ needs.prepare.outputs.uuid }} - - - name: Skip Percy required check - if: needs.prepare.outputs.percy_enable != '1' - uses: Sibz/github-status-action@071b5370da85afbb16637d6eed8524a06bc2053e # v1 - with: - authToken: ${{ secrets.GITHUB_TOKEN }} - state: success - description: Percy skipped - context: percy/matrix-react-sdk - sha: ${{ github.event.workflow_run.head_sha }} - target_url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} - - - uses: Sibz/github-status-action@071b5370da85afbb16637d6eed8524a06bc2053e # v1 - with: - authToken: ${{ secrets.GITHUB_TOKEN }} - state: ${{ needs.tests.result == 'success' && 'success' || 'failure' }} - context: ${{ github.workflow }} / cypress - sha: ${{ github.event.workflow_run.head_sha }} - target_url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} diff --git a/.github/workflows/element-web.yaml b/.github/workflows/element-web.yaml index 0582ff4e52..de082badb2 100644 --- a/.github/workflows/element-web.yaml +++ b/.github/workflows/element-web.yaml @@ -3,12 +3,6 @@ # as an artifact and run integration tests. name: Element Web - Build on: - # We only need the nightly run for Percy which is disabled while we're - # figuring out https://github.com/vector-im/wat-internal/issues/36 and - # https://github.com/vector-im/wat-internal/issues/56. We're hoping to - # turn it back on or switch to an alternative in the future. - # schedule: - # - cron: "17 4 * * 1-5" # every weekday at 04:17 UTC pull_request: {} merge_group: types: [checks_requested] @@ -82,7 +76,7 @@ jobs: echo $VERSION > webapp/version working-directory: ./element-web - # Record the react-sdk sha so our cypress tests are from the same sha + # Record the react-sdk sha so our Playwright tests are from the same sha - name: Record react-sdk SHA run: | git rev-parse HEAD > element-web/webapp/sha diff --git a/.gitignore b/.gitignore index ecab8be95f..3137cd555b 100644 --- a/.gitignore +++ b/.gitignore @@ -19,14 +19,3 @@ package-lock.json .vscode .vscode/ - -/cypress/videos -/cypress/downloads -/cypress/screenshots -/cypress/synapselogs -/cypress/dendritelogs -/cypress/results - -# These could have files in them but don't currently -# Cypress will still auto-create them though... -/cypress/performance diff --git a/.percy.yml b/.percy.yml deleted file mode 100644 index 7823892423..0000000000 --- a/.percy.yml +++ /dev/null @@ -1,7 +0,0 @@ -version: 2 -snapshot: - widths: - - 1024 - - 1920 -percy: - defer-uploads: true diff --git a/README.md b/README.md index 67ab61a93d..f3f34939a9 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ ![Tests](https://github.com/matrix-org/matrix-react-sdk/actions/workflows/tests.yml/badge.svg) [![Playwright](https://img.shields.io/badge/Playwright-end_to_end_tests-blue)](https://e2e-develop--matrix-react-sdk.netlify.app/) ![Static Analysis](https://github.com/matrix-org/matrix-react-sdk/actions/workflows/static_analysis.yaml/badge.svg) -[![Knapsack Pro Parallel CI builds for Cypress Test - Legacy Crypto](https://img.shields.io/badge/Knapsack%20Pro-Parallel%20%2F%20Cypress%20Test%20--%20Legacy%20Crypto-%230074ff)](https://knapsackpro.com/dashboard/organizations/3882/projects/2469/test_suites/3724/builds?utm_campaign=organization-id-3882&utm_content=test-suite-id-3724&utm_medium=readme&utm_source=knapsack-pro-badge&utm_term=project-id-2469) -[![Knapsack Pro Parallel CI builds for Cypress Test - Rust Crypto](https://img.shields.io/badge/Knapsack%20Pro-Parallel%20%2F%20Cypress%20Test%20--%20Rust%20Crypto-%230074ff)](https://knapsackpro.com/dashboard/organizations/3882/projects/2469/test_suites/3729/builds?utm_campaign=organization-id-3882&utm_content=test-suite-id-3729&utm_medium=readme&utm_source=knapsack-pro-badge&utm_term=project-id-2469) [![Localazy](https://img.shields.io/endpoint?url=https%3A%2F%2Fconnect.localazy.com%2Fstatus%2Felement-web%2Fdata%3Fcontent%3Dall%26title%3Dlocalazy%26logo%3Dtrue)](https://localazy.com/p/element-web) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=matrix-react-sdk&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=matrix-react-sdk) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=matrix-react-sdk&metric=coverage)](https://sonarcloud.io/summary/new_code?id=matrix-react-sdk) @@ -206,5 +204,5 @@ Now the yarn commands should work as normal. ### End-to-End tests -We use Cypress and Element Web for end-to-end tests. See -[`docs/cypress.md`](docs/cypress.md) for more information. +We use Playwright and Element Web for end-to-end tests. See +[`docs/playwright.md`](docs/playwright.md) for more information. diff --git a/cypress-ci-reporter-config.json b/cypress-ci-reporter-config.json deleted file mode 100644 index e9f1330a6f..0000000000 --- a/cypress-ci-reporter-config.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "reporterEnabled": "spec, mocha-junit-reporter", - "mochaJunitReporterReporterOptions": { - "mochaFile": "cypress/results/junit/results-[hash].xml", - "useFullSuiteTitle": true - } -} diff --git a/cypress.config.ts b/cypress.config.ts deleted file mode 100644 index 5351e6d686..0000000000 --- a/cypress.config.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -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 { defineConfig } from "cypress"; - -import registerPlugins from "./cypress/plugins"; - -export default defineConfig({ - videoUploadOnPasses: false, - projectId: "ppvnzg", - experimentalInteractiveRunEvents: true, - experimentalMemoryManagement: true, - defaultCommandTimeout: 10000, - chromeWebSecurity: false, - e2e: { - setupNodeEvents(on, config) { - return registerPlugins(on, config); - }, - baseUrl: "http://localhost:8080", - specPattern: "cypress/e2e/**/*.spec.{js,jsx,ts,tsx}", - }, - env: { - // Docker tag to use for `ghcr.io/matrix-org/sliding-sync` image. - SLIDING_SYNC_PROXY_TAG: "v0.99.3", - HOMESERVER: "synapse", - }, - retries: { - runMode: 4, - openMode: 0, - }, - - // disable logging of HTTP requests made to the Cypress server. They are noisy and not very helpful. - // @ts-ignore https://github.com/cypress-io/cypress/issues/26284 - morgan: false, - - // Create XML result files - reporter: "cypress-multi-reporters", - reporterOptions: { - configFile: "cypress-ci-reporter-config.json", - }, -}); diff --git a/cypress/e2e/dummy.spec.ts b/cypress/e2e/dummy.spec.ts deleted file mode 100644 index 6940c642b5..0000000000 --- a/cypress/e2e/dummy.spec.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2024 The Matrix.org Foundation C.I.C. - -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. -*/ - -/// - -it("Dummy test to make CI pass", () => {}); diff --git a/cypress/e2e/utils.ts b/cypress/e2e/utils.ts deleted file mode 100644 index 0ffb125dae..0000000000 --- a/cypress/e2e/utils.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* -Copyright 2023 Mikhail Aheichyk -Copyright 2023 Nordeck IT + Consulting GmbH. - -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 type { MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; - -/** - * Resolves when room state matches predicate. - * @param win window object - * @param matrixClient MatrixClient instance that can be user or bot - * @param roomId room id to find room and check - * @param predicate defines condition that is used to check the room state - */ -export function waitForRoom( - win: Cypress.AUTWindow, - matrixClient: MatrixClient, - roomId: string, - predicate: (room: Room) => boolean, -): Promise { - return new Promise((resolve, reject) => { - const room = matrixClient.getRoom(roomId); - - if (predicate(room)) { - resolve(); - return; - } - - function onEvent(ev: MatrixEvent) { - if (ev.getRoomId() !== roomId) return; - - if (predicate(room)) { - matrixClient.removeListener(win.matrixcs.ClientEvent.Event, onEvent); - resolve(); - } - } - - matrixClient.on(win.matrixcs.ClientEvent.Event, onEvent); - }); -} diff --git a/cypress/fixtures/riot.png b/cypress/fixtures/riot.png deleted file mode 100644 index ee42954c7826c78416f53af792ee022405d706df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13818 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 T^B6||yQ}; - }; - mxMatrixClientPeg: { - matrixClient?: MatrixClient; - }; - beforeReload?: boolean; // for detecting reloads - // Partial type for the matrix-js-sdk module, exported by browser-matrix - matrixcs: { - MatrixClient: typeof MatrixClient; - ClientEvent: typeof ClientEvent; - RoomMemberEvent: typeof RoomMemberEvent; - RoomStateEvent: typeof RoomStateEvent; - MatrixScheduler: typeof MatrixScheduler; - MemoryStore: typeof MemoryStore; - MemoryCryptoStore: typeof MemoryCryptoStore; - Visibility: typeof Visibility; - Preset: typeof Preset; - createClient(opts: ICreateClientOpts | string); - }; - } - } -} - -export { MatrixClient }; diff --git a/cypress/plugins/dendritedocker/index.ts b/cypress/plugins/dendritedocker/index.ts deleted file mode 100644 index f89f898121..0000000000 --- a/cypress/plugins/dendritedocker/index.ts +++ /dev/null @@ -1,207 +0,0 @@ -/* -Copyright 2023 The Matrix.org Foundation C.I.C. - -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 * as path from "path"; -import * as os from "os"; -import * as crypto from "crypto"; -import * as fse from "fs-extra"; - -import PluginEvents = Cypress.PluginEvents; -import PluginConfigOptions = Cypress.PluginConfigOptions; -import { getFreePort } from "../utils/port"; -import { dockerExec, dockerLogs, dockerRun, dockerStop } from "../docker"; -import { HomeserverConfig, HomeserverInstance } from "../utils/homeserver"; -import { StartHomeserverOpts } from "../../support/homeserver"; - -// A cypress plugins to add command to start & stop dendrites in -// docker with preset templates. - -const dendrites = new Map(); - -const dockerConfigDir = "/etc/dendrite/"; -const dendriteConfigFile = "dendrite.yaml"; - -function randB64Bytes(numBytes: number): string { - return crypto.randomBytes(numBytes).toString("base64").replace(/=*$/, ""); -} - -async function cfgDirFromTemplate(template: string, dendriteImage: string): Promise { - template = "default"; - const templateDir = path.join(__dirname, "templates", template); - - const stats = await fse.stat(templateDir); - if (!stats?.isDirectory) { - throw new Error(`No such template: ${template}`); - } - const tempDir = await fse.mkdtemp(path.join(os.tmpdir(), "react-sdk-dendritedocker-")); - - // copy the contents of the template dir, omitting homeserver.yaml as we'll template that - console.log(`Copy ${templateDir} -> ${tempDir}`); - await fse.copy(templateDir, tempDir, { filter: (f) => path.basename(f) !== dendriteConfigFile }); - - const registrationSecret = randB64Bytes(16); - - const port = await getFreePort(); - const baseUrl = `http://localhost:${port}`; - - // now copy homeserver.yaml, applying substitutions - console.log(`Gen ${path.join(templateDir, dendriteConfigFile)}`); - let hsYaml = await fse.readFile(path.join(templateDir, dendriteConfigFile), "utf8"); - hsYaml = hsYaml.replace(/{{REGISTRATION_SECRET}}/g, registrationSecret); - await fse.writeFile(path.join(tempDir, dendriteConfigFile), hsYaml); - - await dockerRun({ - image: dendriteImage, - params: ["--rm", "--entrypoint=", "-v", `${tempDir}:/mnt`], - containerName: `react-sdk-cypress-dendrite-keygen`, - cmd: ["/usr/bin/generate-keys", "-private-key", "/mnt/matrix_key.pem"], - }); - - return { - port, - baseUrl, - configDir: tempDir, - registrationSecret, - }; -} - -// Start a dendrite instance: the template must be the name of -// one of the templates in the cypress/plugins/dendritedocker/templates -// directory -async function dendriteStart(opts: StartHomeserverOpts): Promise { - return containerStart(opts.template, false); -} - -// Start a dendrite instance using pinecone routing: the template must be the name of -// one of the templates in the cypress/plugins/dendritedocker/templates -// directory -async function dendritePineconeStart(template: string): Promise { - return containerStart(template, true); -} - -async function containerStart(template: string, usePinecone: boolean): Promise { - let dendriteImage = "matrixdotorg/dendrite-monolith:main"; - let dendriteEntrypoint = "/usr/bin/dendrite"; - if (usePinecone) { - dendriteImage = "matrixdotorg/dendrite-demo-pinecone:main"; - dendriteEntrypoint = "/usr/bin/dendrite-demo-pinecone"; - } - const denCfg = await cfgDirFromTemplate(template, dendriteImage); - - console.log(`Starting dendrite with config dir ${denCfg.configDir}...`); - - const dendriteId = await dockerRun({ - image: dendriteImage, - params: [ - "--rm", - "-v", - `${denCfg.configDir}:` + dockerConfigDir, - "-p", - `${denCfg.port}:8008/tcp`, - "--entrypoint", - dendriteEntrypoint, - ], - containerName: `react-sdk-cypress-dendrite`, - cmd: ["--config", dockerConfigDir + dendriteConfigFile, "--really-enable-open-registration", "true", "run"], - }); - - console.log(`Started dendrite with id ${dendriteId} on port ${denCfg.port}.`); - - // Await Dendrite healthcheck - await dockerExec({ - containerId: dendriteId, - params: [ - "curl", - "--connect-timeout", - "30", - "--retry", - "30", - "--retry-delay", - "1", - "--retry-all-errors", - "--silent", - "http://localhost:8008/_matrix/client/versions", - ], - }); - - const dendrite: HomeserverInstance = { serverId: dendriteId, ...denCfg }; - dendrites.set(dendriteId, dendrite); - return dendrite; -} - -async function dendriteStop(id: string): Promise { - const denCfg = dendrites.get(id); - - if (!denCfg) throw new Error("Unknown dendrite ID"); - - const dendriteLogsPath = path.join("cypress", "dendritelogs", id); - await fse.ensureDir(dendriteLogsPath); - - await dockerLogs({ - containerId: id, - stdoutFile: path.join(dendriteLogsPath, "stdout.log"), - stderrFile: path.join(dendriteLogsPath, "stderr.log"), - }); - - await dockerStop({ - containerId: id, - }); - - await fse.remove(denCfg.configDir); - - dendrites.delete(id); - - console.log(`Stopped dendrite id ${id}.`); - // cypress deliberately fails if you return 'undefined', so - // return null to signal all is well, and we've handled the task. - return null; -} - -async function dendritePineconeStop(id: string): Promise { - return dendriteStop(id); -} - -/** - * @type {Cypress.PluginConfig} - */ -export function dendriteDocker(on: PluginEvents, config: PluginConfigOptions) { - on("task", { - dendriteStart, - dendriteStop, - dendritePineconeStart, - dendritePineconeStop, - }); - - on("after:spec", async (spec) => { - // Cleans up any remaining dendrite instances after a spec run - // This is on the theory that we should avoid re-using dendrite - // instances between spec runs: they should be cheap enough to - // start that we can have a separate one for each spec run or even - // test. If we accidentally re-use dendrites, we could inadvertently - // make our tests depend on each other. - for (const denId of dendrites.keys()) { - console.warn(`Cleaning up dendrite ID ${denId} after ${spec.name}`); - await dendriteStop(denId); - } - }); - - on("before:run", async () => { - // tidy up old dendrite log files before each run - await fse.emptyDir(path.join("cypress", "dendritelogs")); - }); -} diff --git a/cypress/plugins/dendritedocker/templates/default/dendrite.yaml b/cypress/plugins/dendritedocker/templates/default/dendrite.yaml deleted file mode 100644 index 634cebbc87..0000000000 --- a/cypress/plugins/dendritedocker/templates/default/dendrite.yaml +++ /dev/null @@ -1,378 +0,0 @@ -# This is the Dendrite configuration file. -# -# The configuration is split up into sections - each Dendrite component has a -# configuration section, in addition to the "global" section which applies to -# all components. - -# The version of the configuration file. -version: 2 - -# Global Matrix configuration. This configuration applies to all components. -global: - # The domain name of this homeserver. - server_name: localhost - - # The path to the signing private key file, used to sign requests and events. - # Note that this is NOT the same private key as used for TLS! To generate a - # signing key, use "./bin/generate-keys --private-key matrix_key.pem". - private_key: matrix_key.pem - - # The paths and expiry timestamps (as a UNIX timestamp in millisecond precision) - # to old signing keys that were formerly in use on this domain name. These - # keys will not be used for federation request or event signing, but will be - # provided to any other homeserver that asks when trying to verify old events. - old_private_keys: - # If the old private key file is available: - # - private_key: old_matrix_key.pem - # expired_at: 1601024554498 - # If only the public key (in base64 format) and key ID are known: - # - public_key: mn59Kxfdq9VziYHSBzI7+EDPDcBS2Xl7jeUdiiQcOnM= - # key_id: ed25519:mykeyid - # expired_at: 1601024554498 - - # How long a remote server can cache our server signing key before requesting it - # again. Increasing this number will reduce the number of requests made by other - # servers for our key but increases the period that a compromised key will be - # considered valid by other homeservers. - key_validity_period: 168h0m0s - - # Global database connection pool, for PostgreSQL monolith deployments only. If - # this section is populated then you can omit the "database" blocks in all other - # sections. For polylith deployments, or monolith deployments using SQLite databases, - # you must configure the "database" block for each component instead. - # database: - # connection_string: postgresql://username:password@hostname/dendrite?sslmode=disable - # max_open_conns: 90 - # max_idle_conns: 5 - # conn_max_lifetime: -1 - - # Configuration for in-memory caches. Caches can often improve performance by - # keeping frequently accessed items (like events, identifiers etc.) in memory - # rather than having to read them from the database. - cache: - # The estimated maximum size for the global cache in bytes, or in terabytes, - # gigabytes, megabytes or kilobytes when the appropriate 'tb', 'gb', 'mb' or - # 'kb' suffix is specified. Note that this is not a hard limit, nor is it a - # memory limit for the entire process. A cache that is too small may ultimately - # provide little or no benefit. - max_size_estimated: 1gb - - # The maximum amount of time that a cache entry can live for in memory before - # it will be evicted and/or refreshed from the database. Lower values result in - # easier admission of new cache entries but may also increase database load in - # comparison to higher values, so adjust conservatively. Higher values may make - # it harder for new items to make it into the cache, e.g. if new rooms suddenly - # become popular. - max_age: 1h - - # The server name to delegate server-server communications to, with optional port - # e.g. localhost:443 - well_known_server_name: "" - - # The server name to delegate client-server communications to, with optional port - # e.g. localhost:443 - well_known_client_name: "" - - # Lists of domains that the server will trust as identity servers to verify third - # party identifiers such as phone numbers and email addresses. - trusted_third_party_id_servers: - - matrix.org - - vector.im - - # Disables federation. Dendrite will not be able to communicate with other servers - # in the Matrix federation and the federation API will not be exposed. - disable_federation: false - - # Configures the handling of presence events. Inbound controls whether we receive - # presence events from other servers, outbound controls whether we send presence - # events for our local users to other servers. - presence: - enable_inbound: false - enable_outbound: false - - # Configures phone-home statistics reporting. These statistics contain the server - # name, number of active users and some information on your deployment config. - # We use this information to understand how Dendrite is being used in the wild. - report_stats: - enabled: false - endpoint: https://matrix.org/report-usage-stats/push - - # Server notices allows server admins to send messages to all users on the server. - server_notices: - enabled: false - # The local part, display name and avatar URL (as a mxc:// URL) for the user that - # will send the server notices. These are visible to all users on the deployment. - local_part: "_server" - display_name: "Server Alerts" - avatar_url: "" - # The room name to be used when sending server notices. This room name will - # appear in user clients. - room_name: "Server Alerts" - - # Configuration for NATS JetStream - jetstream: - # A list of NATS Server addresses to connect to. If none are specified, an - # internal NATS server will be started automatically when running Dendrite in - # monolith mode. For polylith deployments, it is required to specify the address - # of at least one NATS Server node. - addresses: - # - localhost:4222 - - # Disable the validation of TLS certificates of NATS. This is - # not recommended in production since it may allow NATS traffic - # to be sent to an insecure endpoint. - disable_tls_validation: false - - # Persistent directory to store JetStream streams in. This directory should be - # preserved across Dendrite restarts. - storage_path: ./ - - # The prefix to use for stream names for this homeserver - really only useful - # if you are running more than one Dendrite server on the same NATS deployment. - topic_prefix: Dendrite - - # Configuration for Prometheus metric collection. - metrics: - enabled: false - basic_auth: - username: metrics - password: metrics - - # Optional DNS cache. The DNS cache may reduce the load on DNS servers if there - # is no local caching resolver available for use. - dns_cache: - enabled: false - cache_size: 256 - cache_lifetime: "5m" # 5 minutes; https://pkg.go.dev/time@master#ParseDuration - -# Configuration for the Appservice API. -app_service_api: - # Disable the validation of TLS certificates of appservices. This is - # not recommended in production since it may allow appservice traffic - # to be sent to an insecure endpoint. - disable_tls_validation: false - - # Appservice configuration files to load into this homeserver. - config_files: - # - /path/to/appservice_registration.yaml - -# Configuration for the Client API. -client_api: - # Prevents new users from being able to register on this homeserver, except when - # using the registration shared secret below. - registration_disabled: false - - # Prevents new guest accounts from being created. Guest registration is also - # disabled implicitly by setting 'registration_disabled' above. - guests_disabled: true - - # If set, allows registration by anyone who knows the shared secret, regardless - # of whether registration is otherwise disabled. - registration_shared_secret: "{{REGISTRATION_SECRET}}" - - # Whether to require reCAPTCHA for registration. If you have enabled registration - # then this is HIGHLY RECOMMENDED to reduce the risk of your homeserver being used - # for coordinated spam attacks. - enable_registration_captcha: false - - # Settings for ReCAPTCHA. - recaptcha_public_key: "" - recaptcha_private_key: "" - recaptcha_bypass_secret: "" - - # To use hcaptcha.com instead of ReCAPTCHA, set the following parameters, otherwise just keep them empty. - # recaptcha_siteverify_api: "https://hcaptcha.com/siteverify" - # recaptcha_api_js_url: "https://js.hcaptcha.com/1/api.js" - # recaptcha_form_field: "h-captcha-response" - # recaptcha_sitekey_class: "h-captcha" - - # TURN server information that this homeserver should send to clients. - turn: - turn_user_lifetime: "5m" - turn_uris: - # - turn:turn.server.org?transport=udp - # - turn:turn.server.org?transport=tcp - turn_shared_secret: "" - # If your TURN server requires static credentials, then you will need to enter - # them here instead of supplying a shared secret. Note that these credentials - # will be visible to clients! - # turn_username: "" - # turn_password: "" - - # Settings for rate-limited endpoints. Rate limiting kicks in after the threshold - # number of "slots" have been taken by requests from a specific host. Each "slot" - # will be released after the cooloff time in milliseconds. Server administrators - # and appservice users are exempt from rate limiting by default. - rate_limiting: - enabled: true - threshold: 20 - cooloff_ms: 500 - exempt_user_ids: - # - "@user:domain.com" - -# Configuration for the Federation API. -federation_api: - # How many times we will try to resend a failed transaction to a specific server. The - # backoff is 2**x seconds, so 1 = 2 seconds, 2 = 4 seconds, 3 = 8 seconds etc. Once - # the max retries are exceeded, Dendrite will no longer try to send transactions to - # that server until it comes back to life and connects to us again. - send_max_retries: 16 - - # Disable the validation of TLS certificates of remote federated homeservers. Do not - # enable this option in production as it presents a security risk! - disable_tls_validation: false - - # Disable HTTP keepalives, which also prevents connection reuse. Dendrite will typically - # keep HTTP connections open to remote hosts for 5 minutes as they can be reused much - # more quickly than opening new connections each time. Disabling keepalives will close - # HTTP connections immediately after a successful request but may result in more CPU and - # memory being used on TLS handshakes for each new connection instead. - disable_http_keepalives: false - - # Perspective keyservers to use as a backup when direct key fetches fail. This may - # be required to satisfy key requests for servers that are no longer online when - # joining some rooms. - key_perspectives: - - server_name: matrix.org - keys: - - key_id: ed25519:auto - public_key: Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw - - key_id: ed25519:a_RXGa - public_key: l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ - - # This option will control whether Dendrite will prefer to look up keys directly - # or whether it should try perspective servers first, using direct fetches as a - # last resort. - prefer_direct_fetch: false - - database: - connection_string: file:dendrite-federationapi.db - -# Configuration for the Media API. -media_api: - # Storage path for uploaded media. May be relative or absolute. - base_path: ./media_store - - # The maximum allowed file size (in bytes) for media uploads to this homeserver - # (0 = unlimited). If using a reverse proxy, ensure it allows requests at least - #this large (e.g. the client_max_body_size setting in nginx). - max_file_size_bytes: 10485760 - - # Whether to dynamically generate thumbnails if needed. - dynamic_thumbnails: false - - # The maximum number of simultaneous thumbnail generators to run. - max_thumbnail_generators: 10 - - # A list of thumbnail sizes to be generated for media content. - thumbnail_sizes: - - width: 32 - height: 32 - method: crop - - width: 96 - height: 96 - method: crop - - width: 640 - height: 480 - method: scale - - database: - connection_string: file:dendrite-mediaapi.db - -# Configuration for enabling experimental MSCs on this homeserver. -mscs: - mscs: - # - msc2836 # (Threading, see https://github.com/matrix-org/matrix-doc/pull/2836) - # - msc2946 # (Spaces Summary, see https://github.com/matrix-org/matrix-doc/pull/2946) - - database: - connection_string: file:dendrite-msc.db - -# Configuration for the Sync API. -sync_api: - # This option controls which HTTP header to inspect to find the real remote IP - # address of the client. This is likely required if Dendrite is running behind - # a reverse proxy server. - # real_ip_header: X-Real-IP - - # Configuration for the full-text search engine. - search: - # Whether or not search is enabled. - enabled: false - - # The path where the search index will be created in. - index_path: "./searchindex" - - # The language most likely to be used on the server - used when indexing, to - # ensure the returned results match expectations. A full list of possible languages - # can be found at https://github.com/blevesearch/bleve/tree/master/analysis/lang - language: "en" - - database: - connection_string: file:dendrite-syncapi.db - -# Configuration for the User API. -user_api: - # The cost when hashing passwords on registration/login. Default: 10. Min: 4, Max: 31 - # See https://pkg.go.dev/golang.org/x/crypto/bcrypt for more information. - # Setting this lower makes registration/login consume less CPU resources at the cost - # of security should the database be compromised. Setting this higher makes registration/login - # consume more CPU resources but makes it harder to brute force password hashes. This value - # can be lowered if performing tests or on embedded Dendrite instances (e.g WASM builds). - bcrypt_cost: 10 - - # The length of time that a token issued for a relying party from - # /_matrix/client/r0/user/{userId}/openid/request_token endpoint - # is considered to be valid in milliseconds. - # The default lifetime is 3600000ms (60 minutes). - # openid_token_lifetime_ms: 3600000 - - # Users who register on this homeserver will automatically be joined to the rooms listed under "auto_join_rooms" option. - # By default, any room aliases included in this list will be created as a publicly joinable room - # when the first user registers for the homeserver. If the room already exists, - # make certain it is a publicly joinable room, i.e. the join rule of the room must be set to 'public'. - # As Spaces are just rooms under the hood, Space aliases may also be used. - auto_join_rooms: - # - "#main:matrix.org" - - account_database: - connection_string: file:dendrite-userapi.db - -room_server: - database: - connection_string: file:dendrite-roomserverapi.db - -key_server: - database: - connection_string: file:dendrite-keyserverapi.db - -relay_api: - database: - connection_string: file:dendrite-relayapi.db - -# Configuration for Opentracing. -# See https://github.com/matrix-org/dendrite/tree/master/docs/tracing for information on -# how this works and how to set it up. -tracing: - enabled: false - jaeger: - serviceName: "" - disabled: false - rpc_metrics: false - tags: [] - sampler: null - reporter: null - headers: null - baggage_restrictions: null - throttler: null - -# Logging configuration. The "std" logging type controls the logs being sent to -# stdout. The "file" logging type controls logs being written to a log folder on -# the disk. Supported log levels are "debug", "info", "warn", "error". -logging: - - type: std - level: debug - - type: file - level: debug - params: - path: ./logs diff --git a/cypress/plugins/docker/index.ts b/cypress/plugins/docker/index.ts deleted file mode 100644 index e05b4a3c07..0000000000 --- a/cypress/plugins/docker/index.ts +++ /dev/null @@ -1,180 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -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 * as os from "os"; -import * as crypto from "crypto"; -import * as childProcess from "child_process"; -import * as fse from "fs-extra"; - -import PluginEvents = Cypress.PluginEvents; -import PluginConfigOptions = Cypress.PluginConfigOptions; - -// A cypress plugin to run docker commands - -export async function dockerRun(opts: { - image: string; - containerName: string; - params?: string[]; - cmd?: string[]; -}): Promise { - const userInfo = os.userInfo(); - const params = opts.params ?? []; - - if (params?.includes("-v") && userInfo.uid >= 0) { - // Run the docker container as our uid:gid to prevent problems with permissions. - if (await isPodman()) { - // Note: this setup is for podman rootless containers. - - // In podman, run as root in the container, which maps to the current - // user on the host. This is probably the default since Synapse's - // Dockerfile doesn't specify, but we're being explicit here - // because it's important for the permissions to work. - params.push("-u", "0:0"); - - // Tell Synapse not to switch UID - params.push("-e", "UID=0"); - params.push("-e", "GID=0"); - } else { - params.push("-u", `${userInfo.uid}:${userInfo.gid}`); - } - } - - const args = [ - "run", - "--name", - `${opts.containerName}-${crypto.randomBytes(4).toString("hex")}`, - "-d", - "--rm", - ...params, - opts.image, - ]; - - if (opts.cmd) args.push(...opts.cmd); - - return new Promise((resolve, reject) => { - childProcess.execFile("docker", args, (err, stdout) => { - if (err) reject(err); - resolve(stdout.trim()); - }); - }); -} - -export function dockerExec(args: { containerId: string; params: string[] }): Promise { - return new Promise((resolve, reject) => { - childProcess.execFile( - "docker", - ["exec", args.containerId, ...args.params], - { encoding: "utf8" }, - (err, stdout, stderr) => { - if (err) { - console.log(stdout); - console.log(stderr); - reject(err); - return; - } - resolve(); - }, - ); - }); -} - -export async function dockerLogs(args: { - containerId: string; - stdoutFile?: string; - stderrFile?: string; -}): Promise { - const stdoutFile = args.stdoutFile ? await fse.open(args.stdoutFile, "w") : "ignore"; - const stderrFile = args.stderrFile ? await fse.open(args.stderrFile, "w") : "ignore"; - - await new Promise((resolve) => { - childProcess - .spawn("docker", ["logs", args.containerId], { - stdio: ["ignore", stdoutFile, stderrFile], - }) - .once("close", resolve); - }); - - if (args.stdoutFile) await fse.close(stdoutFile); - if (args.stderrFile) await fse.close(stderrFile); -} - -export function dockerStop(args: { containerId: string }): Promise { - return new Promise((resolve, reject) => { - childProcess.execFile("docker", ["stop", args.containerId], (err) => { - if (err) reject(err); - resolve(); - }); - }); -} - -export function dockerRm(args: { containerId: string }): Promise { - return new Promise((resolve, reject) => { - childProcess.execFile("docker", ["rm", args.containerId], (err) => { - if (err) reject(err); - resolve(); - }); - }); -} - -export function dockerIp(args: { containerId: string }): Promise { - return new Promise((resolve, reject) => { - childProcess.execFile( - "docker", - ["inspect", "-f", "{{ .NetworkSettings.IPAddress }}", args.containerId], - (err, stdout) => { - if (err) reject(err); - else resolve(stdout.trim()); - }, - ); - }); -} - -/** - * Detects whether the docker command is actually podman. - * To do this, it looks for "podman" in the output of "docker --help". - */ -export function isPodman(): Promise { - return new Promise((resolve, reject) => { - childProcess.execFile("docker", ["--help"], (err, stdout) => { - if (err) reject(err); - else resolve(stdout.toLowerCase().includes("podman")); - }); - }); -} - -/** - * Supply the right hostname to use to talk to the host machine. On Docker this - * is "host.docker.internal" and on Podman this is "host.containers.internal". - */ -export async function hostContainerName() { - return (await isPodman()) ? "host.containers.internal" : "host.docker.internal"; -} - -/** - * @type {Cypress.PluginConfig} - */ -export function docker(on: PluginEvents, config: PluginConfigOptions) { - on("task", { - dockerRun, - dockerExec, - dockerLogs, - dockerStop, - dockerRm, - dockerIp, - }); -} diff --git a/cypress/plugins/index.ts b/cypress/plugins/index.ts deleted file mode 100644 index d13f025caa..0000000000 --- a/cypress/plugins/index.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -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 installLogsPrinter from "cypress-terminal-report/src/installLogsPrinter"; -import { initPlugins } from "cypress-plugin-init"; - -import PluginEvents = Cypress.PluginEvents; -import PluginConfigOptions = Cypress.PluginConfigOptions; -import { synapseDocker } from "./synapsedocker"; -import { dendriteDocker } from "./dendritedocker"; -import { webserver } from "./webserver"; -import { docker } from "./docker"; -import { log } from "./log"; - -/** - * @type {Cypress.PluginConfig} - */ -export default function (on: PluginEvents, config: PluginConfigOptions) { - initPlugins(on, [docker, synapseDocker, dendriteDocker, webserver, log], config); - installLogsPrinter(on, { - printLogsToConsole: "never", - - // write logs to cypress/results/cypresslogs/.txt - outputRoot: "cypress/results", - outputTarget: { - "cypresslogs|txt": "txt", - }, - - // strip 'cypress/e2e' from log filenames - specRoot: "cypress/e2e", - }); -} diff --git a/cypress/plugins/log.ts b/cypress/plugins/log.ts deleted file mode 100644 index 4b16c9b8cd..0000000000 --- a/cypress/plugins/log.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -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 PluginEvents = Cypress.PluginEvents; -import PluginConfigOptions = Cypress.PluginConfigOptions; - -export function log(on: PluginEvents, config: PluginConfigOptions) { - on("task", { - log(message: string) { - console.log(message); - - return null; - }, - table(message: string) { - console.table(message); - - return null; - }, - }); -} diff --git a/cypress/plugins/mailhog/index.ts b/cypress/plugins/mailhog/index.ts deleted file mode 100644 index a156e93981..0000000000 --- a/cypress/plugins/mailhog/index.ts +++ /dev/null @@ -1,91 +0,0 @@ -/* -Copyright 2023 The Matrix.org Foundation C.I.C. - -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 PluginEvents = Cypress.PluginEvents; -import PluginConfigOptions = Cypress.PluginConfigOptions; -import { getFreePort } from "../utils/port"; -import { dockerIp, dockerRun, dockerStop } from "../docker"; - -// A cypress plugins to add command to manage an instance of Mailhog in Docker - -export interface Instance { - host: string; - smtpPort: number; - httpPort: number; - containerId: string; -} - -const instances = new Map(); - -// Start a synapse instance: the template must be the name of -// one of the templates in the cypress/plugins/synapsedocker/templates -// directory -async function mailhogStart(): Promise { - const smtpPort = await getFreePort(); - const httpPort = await getFreePort(); - - console.log(`Starting mailhog...`); - - const containerId = await dockerRun({ - image: "mailhog/mailhog:latest", - containerName: `react-sdk-cypress-mailhog`, - params: ["--rm", "-p", `${smtpPort}:1025/tcp`, "-p", `${httpPort}:8025/tcp`], - }); - - console.log(`Started mailhog on ports smtp=${smtpPort} http=${httpPort}.`); - - const host = await dockerIp({ containerId }); - const instance: Instance = { smtpPort, httpPort, containerId, host }; - instances.set(containerId, instance); - return instance; -} - -async function mailhogStop(id: string): Promise { - const synCfg = instances.get(id); - - if (!synCfg) throw new Error("Unknown mailhog ID"); - - await dockerStop({ - containerId: id, - }); - - instances.delete(id); - - console.log(`Stopped mailhog id ${id}.`); - // cypress deliberately fails if you return 'undefined', so - // return null to signal all is well, and we've handled the task. - return null; -} - -/** - * @type {Cypress.PluginConfig} - */ -export function mailhogDocker(on: PluginEvents, config: PluginConfigOptions) { - on("task", { - mailhogStart, - mailhogStop, - }); - - on("after:spec", async (spec) => { - // Cleans up any remaining instances after a spec run - for (const synId of instances.keys()) { - console.warn(`Cleaning up synapse ID ${synId} after ${spec.name}`); - await mailhogStop(synId); - } - }); -} diff --git a/cypress/plugins/synapsedocker/index.ts b/cypress/plugins/synapsedocker/index.ts deleted file mode 100644 index 7c278610cc..0000000000 --- a/cypress/plugins/synapsedocker/index.ts +++ /dev/null @@ -1,218 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -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 * as path from "path"; -import * as os from "os"; -import * as crypto from "crypto"; -import * as fse from "fs-extra"; - -import PluginEvents = Cypress.PluginEvents; -import PluginConfigOptions = Cypress.PluginConfigOptions; -import { getFreePort } from "../utils/port"; -import { dockerExec, dockerLogs, dockerRun, dockerStop, hostContainerName, isPodman } from "../docker"; -import { HomeserverConfig, HomeserverInstance } from "../utils/homeserver"; -import { StartHomeserverOpts } from "../../support/homeserver"; - -// A cypress plugins to add command to start & stop synapses in -// docker with preset templates. - -const synapses = new Map(); - -function randB64Bytes(numBytes: number): string { - return crypto.randomBytes(numBytes).toString("base64").replace(/=*$/, ""); -} - -async function cfgDirFromTemplate(opts: StartHomeserverOpts): Promise { - const templateDir = path.join(__dirname, "templates", opts.template); - - const stats = await fse.stat(templateDir); - if (!stats?.isDirectory) { - throw new Error(`No such template: ${opts.template}`); - } - const tempDir = await fse.mkdtemp(path.join(os.tmpdir(), "react-sdk-synapsedocker-")); - - // copy the contents of the template dir, omitting homeserver.yaml as we'll template that - console.log(`Copy ${templateDir} -> ${tempDir}`); - await fse.copy(templateDir, tempDir, { filter: (f) => path.basename(f) !== "homeserver.yaml" }); - - const registrationSecret = randB64Bytes(16); - const macaroonSecret = randB64Bytes(16); - const formSecret = randB64Bytes(16); - - const port = await getFreePort(); - const baseUrl = `http://localhost:${port}`; - - // now copy homeserver.yaml, applying substitutions - const templateHomeserver = path.join(templateDir, "homeserver.yaml"); - const outputHomeserver = path.join(tempDir, "homeserver.yaml"); - console.log(`Gen ${templateHomeserver} -> ${outputHomeserver}`); - let hsYaml = await fse.readFile(templateHomeserver, "utf8"); - hsYaml = hsYaml.replace(/{{REGISTRATION_SECRET}}/g, registrationSecret); - hsYaml = hsYaml.replace(/{{MACAROON_SECRET_KEY}}/g, macaroonSecret); - hsYaml = hsYaml.replace(/{{FORM_SECRET}}/g, formSecret); - hsYaml = hsYaml.replace(/{{PUBLIC_BASEURL}}/g, baseUrl); - hsYaml = hsYaml.replace(/{{OAUTH_SERVER_PORT}}/g, opts.oAuthServerPort?.toString()); - hsYaml = hsYaml.replace(/{{HOST_DOCKER_INTERNAL}}/g, await hostContainerName()); - if (opts.variables) { - let fetchedHostContainer = null; - for (const key in opts.variables) { - let value = String(opts.variables[key]); - - if (value === "{{HOST_DOCKER_INTERNAL}}") { - if (!fetchedHostContainer) { - fetchedHostContainer = await hostContainerName(); - } - value = fetchedHostContainer; - } - - hsYaml = hsYaml.replace(new RegExp("%" + key + "%", "g"), value); - } - } - - await fse.writeFile(outputHomeserver, hsYaml); - - // now generate a signing key (we could use synapse's config generation for - // this, or we could just do this...) - // NB. This assumes the homeserver.yaml specifies the key in this location - const signingKey = randB64Bytes(32); - const outputSigningKey = path.join(tempDir, "localhost.signing.key"); - console.log(`Gen -> ${outputSigningKey}`); - await fse.writeFile(outputSigningKey, `ed25519 x ${signingKey}`); - - return { - port, - baseUrl, - configDir: tempDir, - registrationSecret, - }; -} - -/** - * Start a synapse instance: the template must be the name of - * one of the templates in the cypress/plugins/synapsedocker/templates - * directory. - * - * Any value in opts.variables that is set to `{{HOST_DOCKER_INTERNAL}}' - * will be replaced with 'host.docker.internal' (if we are on Docker) or - * 'host.containers.interal' if we are on Podman. - */ -async function synapseStart(opts: StartHomeserverOpts): Promise { - const synCfg = await cfgDirFromTemplate(opts); - - console.log(`Starting synapse with config dir ${synCfg.configDir}...`); - - const dockerSynapseParams = ["--rm", "-v", `${synCfg.configDir}:/data`, "-p", `${synCfg.port}:8008/tcp`]; - - if (await isPodman()) { - // Make host.containers.internal work to allow Synapse to talk to the - // test OIDC server. - dockerSynapseParams.push("--network"); - dockerSynapseParams.push("slirp4netns:allow_host_loopback=true"); - } else { - // Make host.docker.internal work to allow Synapse to talk to the test - // OIDC server. - dockerSynapseParams.push("--add-host"); - dockerSynapseParams.push("host.docker.internal:host-gateway"); - } - - const synapseId = await dockerRun({ - image: "matrixdotorg/synapse:develop", - containerName: `react-sdk-cypress-synapse`, - params: dockerSynapseParams, - cmd: ["run"], - }); - - console.log(`Started synapse with id ${synapseId} on port ${synCfg.port}.`); - - // Await Synapse healthcheck - await dockerExec({ - containerId: synapseId, - params: [ - "curl", - "--connect-timeout", - "30", - "--retry", - "30", - "--retry-delay", - "1", - "--retry-all-errors", - "--silent", - "http://localhost:8008/health", - ], - }); - - const synapse: HomeserverInstance = { serverId: synapseId, ...synCfg }; - synapses.set(synapseId, synapse); - return synapse; -} - -async function synapseStop(id: string): Promise { - const synCfg = synapses.get(id); - - if (!synCfg) throw new Error("Unknown synapse ID"); - - const synapseLogsPath = path.join("cypress", "synapselogs", id); - await fse.ensureDir(synapseLogsPath); - - await dockerLogs({ - containerId: id, - stdoutFile: path.join(synapseLogsPath, "stdout.log"), - stderrFile: path.join(synapseLogsPath, "stderr.log"), - }); - - await dockerStop({ - containerId: id, - }); - - await fse.remove(synCfg.configDir); - - synapses.delete(id); - - console.log(`Stopped synapse id ${id}.`); - // cypress deliberately fails if you return 'undefined', so - // return null to signal all is well, and we've handled the task. - return null; -} - -/** - * @type {Cypress.PluginConfig} - */ -export function synapseDocker(on: PluginEvents, config: PluginConfigOptions) { - on("task", { - synapseStart, - synapseStop, - }); - - on("after:spec", async (spec) => { - // Cleans up any remaining synapse instances after a spec run - // This is on the theory that we should avoid re-using synapse - // instances between spec runs: they should be cheap enough to - // start that we can have a separate one for each spec run or even - // test. If we accidentally re-use synapses, we could inadvertently - // make our tests depend on each other. - for (const synId of synapses.keys()) { - console.warn(`Cleaning up synapse ID ${synId} after ${spec.name}`); - await synapseStop(synId); - } - }); - - on("before:run", async () => { - // tidy up old synapse log files before each run - await fse.emptyDir(path.join("cypress", "synapselogs")); - }); -} diff --git a/cypress/plugins/synapsedocker/templates/COPYME/README.md b/cypress/plugins/synapsedocker/templates/COPYME/README.md deleted file mode 100644 index df1ed89e6e..0000000000 --- a/cypress/plugins/synapsedocker/templates/COPYME/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Meta-template for synapse templates - -To make another template, you can copy this directory diff --git a/cypress/plugins/synapsedocker/templates/COPYME/homeserver.yaml b/cypress/plugins/synapsedocker/templates/COPYME/homeserver.yaml deleted file mode 100644 index cb58dc8661..0000000000 --- a/cypress/plugins/synapsedocker/templates/COPYME/homeserver.yaml +++ /dev/null @@ -1,72 +0,0 @@ -server_name: "localhost" -pid_file: /data/homeserver.pid -# XXX: This won't actually be right: it lets docker allocate an ephemeral port, -# so we have a chicken-and-egg problem -public_baseurl: http://localhost:8008/ -# Listener is always port 8008 (configured in the container) -listeners: - - port: 8008 - tls: false - bind_addresses: ["::"] - type: http - x_forwarded: true - - resources: - - names: [client, federation, consent] - compress: false - -# An sqlite in-memory database is fast & automatically wipes each time -database: - name: "sqlite3" - args: - database: ":memory:" - -# Needs to be configured to log to the console like a good docker process -log_config: "/data/log.config" - -rc_messages_per_second: 10000 -rc_message_burst_count: 10000 -rc_registration: - per_second: 10000 - burst_count: 10000 - -rc_login: - address: - per_second: 10000 - burst_count: 10000 - account: - per_second: 10000 - burst_count: 10000 - failed_attempts: - per_second: 10000 - burst_count: 10000 - -media_store_path: "/data/media_store" -uploads_path: "/data/uploads" -enable_registration: true -enable_registration_without_verification: true -disable_msisdn_registration: false -# These placeholders will be be replaced with values generated at start -registration_shared_secret: "{{REGISTRATION_SECRET}}" -report_stats: false -macaroon_secret_key: "{{MACAROON_SECRET_KEY}}" -form_secret: "{{FORM_SECRET}}" -# Signing key must be here: it will be generated to this file -signing_key_path: "/data/localhost.signing.key" -email: - enable_notifs: false - smtp_host: "localhost" - smtp_port: 25 - smtp_user: "exampleusername" - smtp_pass: "examplepassword" - require_transport_security: False - notif_from: "Your Friendly %(app)s homeserver " - app_name: Matrix - notif_template_html: notif_mail.html - notif_template_text: notif_mail.txt - notif_for_new_users: True - client_base_url: "http://localhost/element" - -trusted_key_servers: - - server_name: "matrix.org" -suppress_key_server_warning: true diff --git a/cypress/plugins/synapsedocker/templates/COPYME/log.config b/cypress/plugins/synapsedocker/templates/COPYME/log.config deleted file mode 100644 index ac232762da..0000000000 --- a/cypress/plugins/synapsedocker/templates/COPYME/log.config +++ /dev/null @@ -1,50 +0,0 @@ -# Log configuration for Synapse. -# -# This is a YAML file containing a standard Python logging configuration -# dictionary. See [1] for details on the valid settings. -# -# Synapse also supports structured logging for machine readable logs which can -# be ingested by ELK stacks. See [2] for details. -# -# [1]: https://docs.python.org/3.7/library/logging.config.html#configuration-dictionary-schema -# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html - -version: 1 - -formatters: - precise: - format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' - -handlers: - # A handler that writes logs to stderr. Unused by default, but can be used - # instead of "buffer" and "file" in the logger handlers. - console: - class: logging.StreamHandler - formatter: precise - -loggers: - synapse.storage.SQL: - # beware: increasing this to DEBUG will make synapse log sensitive - # information such as access tokens. - level: INFO - - twisted: - # We send the twisted logging directly to the file handler, - # to work around https://github.com/matrix-org/synapse/issues/3471 - # when using "buffer" logger. Use "console" to log to stderr instead. - handlers: [console] - propagate: false - -root: - level: INFO - - # Write logs to the `buffer` handler, which will buffer them together in memory, - # then write them to a file. - # - # Replace "buffer" with "console" to log to stderr instead. (Note that you'll - # also need to update the configuration for the `twisted` logger above, in - # this case.) - # - handlers: [console] - -disable_existing_loggers: false diff --git a/cypress/plugins/synapsedocker/templates/consent/README.md b/cypress/plugins/synapsedocker/templates/consent/README.md deleted file mode 100644 index 713e55f9d5..0000000000 --- a/cypress/plugins/synapsedocker/templates/consent/README.md +++ /dev/null @@ -1 +0,0 @@ -A synapse configured with user privacy consent enabled diff --git a/cypress/plugins/synapsedocker/templates/consent/homeserver.yaml b/cypress/plugins/synapsedocker/templates/consent/homeserver.yaml deleted file mode 100644 index d3a4fa520c..0000000000 --- a/cypress/plugins/synapsedocker/templates/consent/homeserver.yaml +++ /dev/null @@ -1,84 +0,0 @@ -server_name: "localhost" -pid_file: /data/homeserver.pid -public_baseurl: "{{PUBLIC_BASEURL}}" -listeners: - - port: 8008 - tls: false - bind_addresses: ["::"] - type: http - x_forwarded: true - - resources: - - names: [client, federation, consent] - compress: false - -database: - name: "sqlite3" - args: - database: ":memory:" - -log_config: "/data/log.config" - -rc_messages_per_second: 10000 -rc_message_burst_count: 10000 -rc_registration: - per_second: 10000 - burst_count: 10000 - -rc_login: - address: - per_second: 10000 - burst_count: 10000 - account: - per_second: 10000 - burst_count: 10000 - failed_attempts: - per_second: 10000 - burst_count: 10000 - -media_store_path: "/data/media_store" -uploads_path: "/data/uploads" -enable_registration: true -enable_registration_without_verification: true -disable_msisdn_registration: false -registration_shared_secret: "{{REGISTRATION_SECRET}}" -report_stats: false -macaroon_secret_key: "{{MACAROON_SECRET_KEY}}" -form_secret: "{{FORM_SECRET}}" -signing_key_path: "/data/localhost.signing.key" -email: - enable_notifs: false - smtp_host: "localhost" - smtp_port: 25 - smtp_user: "exampleusername" - smtp_pass: "examplepassword" - require_transport_security: False - notif_from: "Your Friendly %(app)s homeserver " - app_name: Matrix - notif_template_html: notif_mail.html - notif_template_text: notif_mail.txt - notif_for_new_users: True - client_base_url: "http://localhost/element" - -user_consent: - template_dir: /data/res/templates/privacy - version: 1.0 - server_notice_content: - msgtype: m.text - body: >- - To continue using this homeserver you must review and agree to the - terms and conditions at %(consent_uri)s - send_server_notice_to_guests: True - block_events_error: >- - To continue using this homeserver you must review and agree to the - terms and conditions at %(consent_uri)s - require_at_registration: true - -server_notices: - system_mxid_localpart: notices - system_mxid_display_name: "Server Notices" - system_mxid_avatar_url: "mxc://localhost:5005/oumMVlgDnLYFaPVkExemNVVZ" - room_name: "Server Notices" -trusted_key_servers: - - server_name: "matrix.org" -suppress_key_server_warning: true diff --git a/cypress/plugins/synapsedocker/templates/consent/log.config b/cypress/plugins/synapsedocker/templates/consent/log.config deleted file mode 100644 index b9123d0f5b..0000000000 --- a/cypress/plugins/synapsedocker/templates/consent/log.config +++ /dev/null @@ -1,50 +0,0 @@ -# Log configuration for Synapse. -# -# This is a YAML file containing a standard Python logging configuration -# dictionary. See [1] for details on the valid settings. -# -# Synapse also supports structured logging for machine readable logs which can -# be ingested by ELK stacks. See [2] for details. -# -# [1]: https://docs.python.org/3.7/library/logging.config.html#configuration-dictionary-schema -# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html - -version: 1 - -formatters: - precise: - format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' - -handlers: - # A handler that writes logs to stderr. Unused by default, but can be used - # instead of "buffer" and "file" in the logger handlers. - console: - class: logging.StreamHandler - formatter: precise - -loggers: - synapse.storage.SQL: - # beware: increasing this to DEBUG will make synapse log sensitive - # information such as access tokens. - level: DEBUG - - twisted: - # We send the twisted logging directly to the file handler, - # to work around https://github.com/matrix-org/synapse/issues/3471 - # when using "buffer" logger. Use "console" to log to stderr instead. - handlers: [console] - propagate: false - -root: - level: DEBUG - - # Write logs to the `buffer` handler, which will buffer them together in memory, - # then write them to a file. - # - # Replace "buffer" with "console" to log to stderr instead. (Note that you'll - # also need to update the configuration for the `twisted` logger above, in - # this case.) - # - handlers: [console] - -disable_existing_loggers: false diff --git a/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html b/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html deleted file mode 100644 index bcc7a590bb..0000000000 --- a/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/1.0.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - Test Privacy policy - - - {% if has_consented %} -

Thank you, you've already accepted the license.

- {% else %} -

Please accept the license!

-
- - - - -
- {% endif %} - - diff --git a/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html b/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html deleted file mode 100644 index 2a2b21eef4..0000000000 --- a/cypress/plugins/synapsedocker/templates/consent/res/templates/privacy/en/success.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - Test Privacy policy - - -

Danke schoen

- - diff --git a/cypress/plugins/synapsedocker/templates/default/README.md b/cypress/plugins/synapsedocker/templates/default/README.md deleted file mode 100644 index 8f6b11f999..0000000000 --- a/cypress/plugins/synapsedocker/templates/default/README.md +++ /dev/null @@ -1 +0,0 @@ -A synapse configured with user privacy consent disabled diff --git a/cypress/plugins/synapsedocker/templates/default/homeserver.yaml b/cypress/plugins/synapsedocker/templates/default/homeserver.yaml deleted file mode 100644 index e51ac1918f..0000000000 --- a/cypress/plugins/synapsedocker/templates/default/homeserver.yaml +++ /dev/null @@ -1,94 +0,0 @@ -server_name: "localhost" -pid_file: /data/homeserver.pid -public_baseurl: "{{PUBLIC_BASEURL}}" -listeners: - - port: 8008 - tls: false - bind_addresses: ["::"] - type: http - x_forwarded: true - - resources: - - names: [client] - compress: false - -database: - name: "sqlite3" - args: - database: ":memory:" - -log_config: "/data/log.config" - -rc_messages_per_second: 10000 -rc_message_burst_count: 10000 -rc_registration: - per_second: 10000 - burst_count: 10000 -rc_joins: - local: - per_second: 9999 - burst_count: 9999 - remote: - per_second: 9999 - burst_count: 9999 -rc_joins_per_room: - per_second: 9999 - burst_count: 9999 -rc_3pid_validation: - per_second: 1000 - burst_count: 1000 - -rc_invites: - per_room: - per_second: 1000 - burst_count: 1000 - per_user: - per_second: 1000 - burst_count: 1000 - -rc_login: - address: - per_second: 10000 - burst_count: 10000 - account: - per_second: 10000 - burst_count: 10000 - failed_attempts: - per_second: 10000 - burst_count: 10000 - -media_store_path: "/data/media_store" -uploads_path: "/data/uploads" -enable_registration: true -enable_registration_without_verification: true -disable_msisdn_registration: false -registration_shared_secret: "{{REGISTRATION_SECRET}}" -report_stats: false -macaroon_secret_key: "{{MACAROON_SECRET_KEY}}" -form_secret: "{{FORM_SECRET}}" -signing_key_path: "/data/localhost.signing.key" - -trusted_key_servers: - - server_name: "matrix.org" -suppress_key_server_warning: true - -ui_auth: - session_timeout: "300s" - -oidc_providers: - - idp_id: test - idp_name: "OAuth test" - issuer: "http://localhost:{{OAUTH_SERVER_PORT}}/oauth" - authorization_endpoint: "http://localhost:{{OAUTH_SERVER_PORT}}/oauth/auth.html" - # the token endpoint receives requests from synapse, rather than the webapp, so needs to escape the docker container. - # Hence, HOST_DOCKER_INTERNAL rather than localhost. This is set to - # host.docker.internal on Docker and host.containers.internal on Podman. - token_endpoint: "http://{{HOST_DOCKER_INTERNAL}}:{{OAUTH_SERVER_PORT}}/oauth/token" - userinfo_endpoint: "http://{{HOST_DOCKER_INTERNAL}}:{{OAUTH_SERVER_PORT}}/oauth/userinfo" - client_id: "synapse" - discover: false - scopes: ["profile"] - skip_verification: true - user_mapping_provider: - config: - display_name_template: "{{ user.name }}" diff --git a/cypress/plugins/synapsedocker/templates/default/log.config b/cypress/plugins/synapsedocker/templates/default/log.config deleted file mode 100644 index b9123d0f5b..0000000000 --- a/cypress/plugins/synapsedocker/templates/default/log.config +++ /dev/null @@ -1,50 +0,0 @@ -# Log configuration for Synapse. -# -# This is a YAML file containing a standard Python logging configuration -# dictionary. See [1] for details on the valid settings. -# -# Synapse also supports structured logging for machine readable logs which can -# be ingested by ELK stacks. See [2] for details. -# -# [1]: https://docs.python.org/3.7/library/logging.config.html#configuration-dictionary-schema -# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html - -version: 1 - -formatters: - precise: - format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' - -handlers: - # A handler that writes logs to stderr. Unused by default, but can be used - # instead of "buffer" and "file" in the logger handlers. - console: - class: logging.StreamHandler - formatter: precise - -loggers: - synapse.storage.SQL: - # beware: increasing this to DEBUG will make synapse log sensitive - # information such as access tokens. - level: DEBUG - - twisted: - # We send the twisted logging directly to the file handler, - # to work around https://github.com/matrix-org/synapse/issues/3471 - # when using "buffer" logger. Use "console" to log to stderr instead. - handlers: [console] - propagate: false - -root: - level: DEBUG - - # Write logs to the `buffer` handler, which will buffer them together in memory, - # then write them to a file. - # - # Replace "buffer" with "console" to log to stderr instead. (Note that you'll - # also need to update the configuration for the `twisted` logger above, in - # this case.) - # - handlers: [console] - -disable_existing_loggers: false diff --git a/cypress/plugins/synapsedocker/templates/email/README.md b/cypress/plugins/synapsedocker/templates/email/README.md deleted file mode 100644 index 40c23ba0be..0000000000 --- a/cypress/plugins/synapsedocker/templates/email/README.md +++ /dev/null @@ -1 +0,0 @@ -A synapse configured to require an email for registration diff --git a/cypress/plugins/synapsedocker/templates/email/homeserver.yaml b/cypress/plugins/synapsedocker/templates/email/homeserver.yaml deleted file mode 100644 index fc20641ab4..0000000000 --- a/cypress/plugins/synapsedocker/templates/email/homeserver.yaml +++ /dev/null @@ -1,44 +0,0 @@ -server_name: "localhost" -pid_file: /data/homeserver.pid -public_baseurl: "{{PUBLIC_BASEURL}}" -listeners: - - port: 8008 - tls: false - bind_addresses: ["::"] - type: http - x_forwarded: true - - resources: - - names: [client] - compress: false - -database: - name: "sqlite3" - args: - database: ":memory:" - -log_config: "/data/log.config" - -media_store_path: "/data/media_store" -uploads_path: "/data/uploads" -enable_registration: true -registrations_require_3pid: - - email -registration_shared_secret: "{{REGISTRATION_SECRET}}" -report_stats: false -macaroon_secret_key: "{{MACAROON_SECRET_KEY}}" -form_secret: "{{FORM_SECRET}}" -signing_key_path: "/data/localhost.signing.key" - -trusted_key_servers: - - server_name: "matrix.org" -suppress_key_server_warning: true - -ui_auth: - session_timeout: "300s" - -email: - smtp_host: "%SMTP_HOST%" - smtp_port: %SMTP_PORT% - notif_from: "Your Friendly %(app)s homeserver " - app_name: my_branded_matrix_server diff --git a/cypress/plugins/synapsedocker/templates/email/log.config b/cypress/plugins/synapsedocker/templates/email/log.config deleted file mode 100644 index ac232762da..0000000000 --- a/cypress/plugins/synapsedocker/templates/email/log.config +++ /dev/null @@ -1,50 +0,0 @@ -# Log configuration for Synapse. -# -# This is a YAML file containing a standard Python logging configuration -# dictionary. See [1] for details on the valid settings. -# -# Synapse also supports structured logging for machine readable logs which can -# be ingested by ELK stacks. See [2] for details. -# -# [1]: https://docs.python.org/3.7/library/logging.config.html#configuration-dictionary-schema -# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html - -version: 1 - -formatters: - precise: - format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' - -handlers: - # A handler that writes logs to stderr. Unused by default, but can be used - # instead of "buffer" and "file" in the logger handlers. - console: - class: logging.StreamHandler - formatter: precise - -loggers: - synapse.storage.SQL: - # beware: increasing this to DEBUG will make synapse log sensitive - # information such as access tokens. - level: INFO - - twisted: - # We send the twisted logging directly to the file handler, - # to work around https://github.com/matrix-org/synapse/issues/3471 - # when using "buffer" logger. Use "console" to log to stderr instead. - handlers: [console] - propagate: false - -root: - level: INFO - - # Write logs to the `buffer` handler, which will buffer them together in memory, - # then write them to a file. - # - # Replace "buffer" with "console" to log to stderr instead. (Note that you'll - # also need to update the configuration for the `twisted` logger above, in - # this case.) - # - handlers: [console] - -disable_existing_loggers: false diff --git a/cypress/plugins/utils/homeserver.ts b/cypress/plugins/utils/homeserver.ts deleted file mode 100644 index d6a4de0411..0000000000 --- a/cypress/plugins/utils/homeserver.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* -Copyright 2023 The Matrix.org Foundation C.I.C. - -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. -*/ - -/// - -export interface HomeserverConfig { - configDir: string; - registrationSecret: string; - baseUrl: string; - port: number; -} - -export interface HomeserverInstance extends HomeserverConfig { - serverId: string; -} diff --git a/cypress/plugins/utils/port.ts b/cypress/plugins/utils/port.ts deleted file mode 100644 index 156ba866d5..0000000000 --- a/cypress/plugins/utils/port.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -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 * as net from "net"; - -export async function getFreePort(): Promise { - return new Promise((resolve) => { - const srv = net.createServer(); - srv.listen(0, () => { - const port = (srv.address()).port; - srv.close(() => resolve(port)); - }); - }); -} diff --git a/cypress/plugins/webserver.ts b/cypress/plugins/webserver.ts deleted file mode 100644 index 55a25a313e..0000000000 --- a/cypress/plugins/webserver.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -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 * as http from "http"; -import { AddressInfo } from "net"; - -import PluginEvents = Cypress.PluginEvents; -import PluginConfigOptions = Cypress.PluginConfigOptions; - -const servers: http.Server[] = []; - -function serveHtmlFile(html: string): string { - const server = http.createServer((req, res) => { - res.writeHead(200, { - "Content-Type": "text/html", - }); - res.end(html); - }); - server.listen(); - servers.push(server); - - return `http://localhost:${(server.address() as AddressInfo).port}/`; -} - -function stopWebServers(): null { - for (const server of servers) { - server.close(); - } - servers.splice(0, servers.length); // clear - - return null; // tell cypress we did the task successfully (doesn't allow undefined) -} - -export function webserver(on: PluginEvents, config: PluginConfigOptions) { - on("task", { serveHtmlFile, stopWebServers }); - on("after:run", stopWebServers); -} diff --git a/cypress/support/app.ts b/cypress/support/app.ts deleted file mode 100644 index 3e9d75173a..0000000000 --- a/cypress/support/app.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -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 Chainable = Cypress.Chainable; -import AUTWindow = Cypress.AUTWindow; - -declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace Cypress { - interface Chainable { - /** - * Applies tweaks to the config read from config.json - */ - tweakConfig(tweaks: Record): Chainable; - } - } -} - -Cypress.Commands.add("tweakConfig", (tweaks: Record): Chainable => { - return cy.window().then((win) => { - // note: we can't *set* the object because the window version is effectively a pointer. - for (const [k, v] of Object.entries(tweaks)) { - // @ts-ignore - for some reason it's not picking up on global.d.ts types. - win.mxReactSdkConfig[k] = v; - } - }); -}); - -// Needed to make this file a module -export {}; diff --git a/cypress/support/axe.ts b/cypress/support/axe.ts deleted file mode 100644 index b830542902..0000000000 --- a/cypress/support/axe.ts +++ /dev/null @@ -1,101 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -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 "cypress-axe"; -import * as axe from "axe-core"; - -import type { Options } from "cypress-axe"; -import Chainable = Cypress.Chainable; - -function terminalLog(violations: axe.Result[]): void { - cy.task( - "log", - `${violations.length} accessibility violation${violations.length === 1 ? "" : "s"} ${ - violations.length === 1 ? "was" : "were" - } detected`, - ); - - // pluck specific keys to keep the table readable - const violationData = violations.map(({ id, impact, description, nodes }) => ({ - id, - impact, - description, - nodes: nodes.length, - })); - - cy.task("table", violationData); -} - -Cypress.Commands.overwrite( - "checkA11y", - ( - originalFn: Chainable["checkA11y"], - context?: string | Node | axe.ContextObject | undefined, - options: Options = {}, - violationCallback?: ((violations: axe.Result[]) => void) | undefined, - skipFailures?: boolean, - ): void => { - return originalFn( - context, - { - ...options, - rules: { - // Disable contrast checking for now as we have too many issues with it - "color-contrast": { - enabled: false, - }, - ...options.rules, - }, - }, - violationCallback ?? terminalLog, - skipFailures, - ); - }, -); - -// Load axe-core into the window under test. -// -// The injectAxe in cypress-axe attempts to load axe via an `eval`. That conflicts with our CSP -// which disallows "unsafe-eval". So, replace it with an implementation that loads it via an -// injected