diff --git a/playwright/e2e/app-loading/guest-registration.spec.ts b/playwright/e2e/app-loading/guest-registration.spec.ts new file mode 100644 index 0000000000..17ec369359 --- /dev/null +++ b/playwright/e2e/app-loading/guest-registration.spec.ts @@ -0,0 +1,45 @@ +/* +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. +*/ + +/* + * Tests for application startup with guest registration enabled on the server. + */ + +import { expect, test } from "../../element-web-test"; + +test.use({ + startHomeserverOpts: "guest-enabled", + config: async ({ homeserver }, use) => { + await use({ + default_server_config: { + "m.homeserver": { base_url: homeserver.config.baseUrl }, + }, + }); + }, +}); + +test("Shows the welcome page by default", async ({ page }) => { + await page.goto("/"); + await expect(page.getByRole("heading", { name: "Welcome to Element!" })).toBeVisible(); + await expect(page.getByRole("link", { name: "Sign in" })).toBeVisible(); +}); + +test("Room link correctly loads a room view", async ({ page }) => { + await page.goto("/#/room/!room:id"); + await page.waitForSelector(".mx_MatrixChat", { timeout: 30000 }); + await expect(page).toHaveURL(/\/#\/room\/!room:id$/); + await expect(page.getByRole("heading", { name: "Join the conversation with an account" })).toBeVisible(); +}); diff --git a/playwright/e2e/app-loading/stored-credentials.spec.ts b/playwright/e2e/app-loading/stored-credentials.spec.ts new file mode 100644 index 0000000000..1fe89d37e5 --- /dev/null +++ b/playwright/e2e/app-loading/stored-credentials.spec.ts @@ -0,0 +1,68 @@ +/* +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. +*/ + +import { expect, test } from "../../element-web-test"; +import { ElementAppPage } from "../../pages/ElementAppPage"; + +/* + * Tests for application startup with credentials stored in localstorage. + */ + +test.use({ displayName: "Boris" }); + +test("Shows the homepage by default", async ({ pageWithCredentials: page }) => { + await page.goto("/"); + await page.waitForSelector(".mx_MatrixChat", { timeout: 30000 }); + + await expect(page).toHaveURL(/\/#\/home/); + await expect(page.getByRole("heading", { name: "Welcome Boris", exact: true })).toBeVisible(); +}); + +test("Shows the last known page on reload", async ({ pageWithCredentials: page }) => { + await page.goto("/"); + await page.waitForSelector(".mx_MatrixChat", { timeout: 30000 }); + + const app = new ElementAppPage(page); + await app.client.createRoom({ name: "Test Room" }); + await app.viewRoomByName("Test Room"); + + // Navigate away + await page.goto("about:blank"); + + // And back again + await page.goto("/"); + await page.waitForSelector(".mx_MatrixChat", { timeout: 30000 }); + + // Check that the room reloaded + await expect(page).toHaveURL(/\/#\/room\//); + await expect(page.locator(".mx_LegacyRoomHeader")).toContainText("Test Room"); +}); + +test("Room link correctly loads a room view", async ({ pageWithCredentials: page }) => { + await page.goto("/#/room/!room:id"); + await page.waitForSelector(".mx_MatrixChat", { timeout: 30000 }); + + await expect(page).toHaveURL(/\/#\/room\/!room:id$/); + await expect(page.getByRole("button", { name: "Join the discussion" })).toBeVisible(); +}); + +test("Login link redirects to home page", async ({ pageWithCredentials: page }) => { + await page.goto("/#/login"); + await page.waitForSelector(".mx_MatrixChat", { timeout: 30000 }); + + await expect(page).toHaveURL(/\/#\/home/); + await expect(page.getByRole("heading", { name: "Welcome Boris", exact: true })).toBeVisible(); +}); diff --git a/playwright/plugins/homeserver/synapse/templates/guest-enabled/README.md b/playwright/plugins/homeserver/synapse/templates/guest-enabled/README.md new file mode 100644 index 0000000000..e1fef0b9d4 --- /dev/null +++ b/playwright/plugins/homeserver/synapse/templates/guest-enabled/README.md @@ -0,0 +1 @@ +A synapse configured with guest registration enabled. diff --git a/playwright/plugins/homeserver/synapse/templates/guest-enabled/homeserver.yaml b/playwright/plugins/homeserver/synapse/templates/guest-enabled/homeserver.yaml new file mode 100644 index 0000000000..1faa39c3a7 --- /dev/null +++ b/playwright/plugins/homeserver/synapse/templates/guest-enabled/homeserver.yaml @@ -0,0 +1,105 @@ +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" +allow_guest_access: true +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. + token_endpoint: "http://host.containers.internal:{{OAUTH_SERVER_PORT}}/oauth/token" + userinfo_endpoint: "http://host.containers.internal:{{OAUTH_SERVER_PORT}}/oauth/userinfo" + client_id: "synapse" + discover: false + scopes: ["profile"] + skip_verification: true + client_auth_method: none + user_mapping_provider: + config: + display_name_template: "{{ user.name }}" + +# Inhibit background updates as this Synapse isn't long-lived +background_updates: + min_batch_size: 100000 + sleep_duration_ms: 100000 + +experimental_features: + # Needed for e2e/crypto/crypto.spec.ts > Cryptography > decryption failure + # messages > non-joined historical messages. + # Can be removed after Synapse enables it by default + msc4115_membership_on_events: true diff --git a/playwright/plugins/homeserver/synapse/templates/guest-enabled/log.config b/playwright/plugins/homeserver/synapse/templates/guest-enabled/log.config new file mode 100644 index 0000000000..ac232762da --- /dev/null +++ b/playwright/plugins/homeserver/synapse/templates/guest-enabled/log.config @@ -0,0 +1,50 @@ +# 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