diff --git a/.gitignore b/.gitignore index 7d257d7e9a..489b5ccb39 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ package-lock.json /cypress/downloads /cypress/screenshots /cypress/synapselogs +/cypress/dendritelogs # These could have files in them but don't currently # Cypress will still auto-create them though... /cypress/performance diff --git a/cypress.config.ts b/cypress.config.ts index 3aca5da28d..253857e375 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -33,6 +33,7 @@ export default defineConfig({ env: { // Docker tag to use for `ghcr.io/matrix-org/sliding-sync-proxy` image. SLIDING_SYNC_PROXY_TAG: "v0.6.0", + HOMESERVER: "synapse", }, retries: { runMode: 4, diff --git a/cypress/e2e/composer/composer.spec.ts b/cypress/e2e/composer/composer.spec.ts index 0b042ccefe..6d2879ff10 100644 --- a/cypress/e2e/composer/composer.spec.ts +++ b/cypress/e2e/composer/composer.spec.ts @@ -16,25 +16,25 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { SettingLevel } from "../../../src/settings/SettingLevel"; describe("Composer", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); describe("CIDER", () => { beforeEach(() => { - cy.initTestUser(synapse, "Janet").then(() => { + cy.initTestUser(homeserver, "Janet").then(() => { cy.createRoom({ name: "Composing Room" }); }); cy.viewRoomByName("Composing Room"); @@ -101,7 +101,7 @@ describe("Composer", () => { describe("WYSIWYG", () => { beforeEach(() => { cy.enableLabsFeature("feature_wysiwyg_composer"); - cy.initTestUser(synapse, "Janet").then(() => { + cy.initTestUser(homeserver, "Janet").then(() => { cy.createRoom({ name: "Composing Room" }); }); cy.viewRoomByName("Composing Room"); diff --git a/cypress/e2e/create-room/create-room.spec.ts b/cypress/e2e/create-room/create-room.spec.ts index 704fa4a981..72805d5e12 100644 --- a/cypress/e2e/create-room/create-room.spec.ts +++ b/cypress/e2e/create-room/create-room.spec.ts @@ -16,7 +16,7 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import Chainable = Cypress.Chainable; function openCreateRoomDialog(): Chainable> { @@ -26,18 +26,18 @@ function openCreateRoomDialog(): Chainable> { } describe("Create Room", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Jim"); + cy.initTestUser(homeserver, "Jim"); }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("should allow us to create a public room with name, topic & address set", () => { diff --git a/cypress/e2e/crypto/crypto.spec.ts b/cypress/e2e/crypto/crypto.spec.ts index eb0e762829..716eff8ddb 100644 --- a/cypress/e2e/crypto/crypto.spec.ts +++ b/cypress/e2e/crypto/crypto.spec.ts @@ -18,12 +18,12 @@ import type { ISendEventResponse, MatrixClient, Room } from "matrix-js-sdk/src/m import type { VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; import type { ISasEvent } from "matrix-js-sdk/src/crypto/verification/SAS"; import type { CypressBot } from "../../support/bot"; -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import Chainable = Cypress.Chainable; type EmojiMapping = [emoji: string, name: string]; interface CryptoTestContext extends Mocha.Context { - synapse: SynapseInstance; + homeserver: HomeserverInstance; bob: CypressBot; } @@ -155,16 +155,16 @@ const verify = function (this: CryptoTestContext) { describe("Cryptography", function () { beforeEach(function () { - cy.startSynapse("default") - .as("synapse") - .then((synapse: SynapseInstance) => { - cy.initTestUser(synapse, "Alice", undefined, "alice_"); - cy.getBot(synapse, { displayName: "Bob", autoAcceptInvites: false, userIdPrefix: "bob_" }).as("bob"); + cy.startHomeserver("default") + .as("homeserver") + .then((homeserver: HomeserverInstance) => { + cy.initTestUser(homeserver, "Alice", undefined, "alice_"); + cy.getBot(homeserver, { displayName: "Bob", autoAcceptInvites: false, userIdPrefix: "bob_" }).as("bob"); }); }); afterEach(function (this: CryptoTestContext) { - cy.stopSynapse(this.synapse); + cy.stopHomeserver(this.homeserver); }); it("setting up secure key backup should work", () => { @@ -215,7 +215,7 @@ describe("Cryptography", function () { cy.bootstrapCrossSigning(); // bob has a second, not cross-signed, device - cy.loginBot(this.synapse, this.bob.getUserId(), this.bob.__cypress_password, {}).as("bobSecondDevice"); + cy.loginBot(this.homeserver, this.bob.getUserId(), this.bob.__cypress_password, {}).as("bobSecondDevice"); autoJoin(this.bob); diff --git a/cypress/e2e/crypto/decryption-failure.spec.ts b/cypress/e2e/crypto/decryption-failure.spec.ts index c947240400..6cc0a69e3c 100644 --- a/cypress/e2e/crypto/decryption-failure.spec.ts +++ b/cypress/e2e/crypto/decryption-failure.spec.ts @@ -17,7 +17,7 @@ limitations under the License. import type { VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; import type { ISasEvent } from "matrix-js-sdk/src/crypto/verification/SAS"; import type { MatrixClient } from "matrix-js-sdk/src/matrix"; -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { UserCredentials } from "../../support/login"; import Chainable = Cypress.Chainable; @@ -56,20 +56,20 @@ const handleVerificationRequest = (request: VerificationRequest): Chainable { - let synapse: SynapseInstance | undefined; + let homeserver: HomeserverInstance | undefined; let testUser: UserCredentials | undefined; let bot: MatrixClient | undefined; let roomId: string; beforeEach(function () { - cy.startSynapse("default").then((syn: SynapseInstance) => { - synapse = syn; - cy.initTestUser(synapse, TEST_USER) + cy.startHomeserver("default").then((hs: HomeserverInstance) => { + homeserver = hs; + cy.initTestUser(homeserver, TEST_USER) .then((creds: UserCredentials) => { testUser = creds; }) .then(() => { - cy.getBot(synapse, { displayName: BOT_USER }).then((cli) => { + cy.getBot(homeserver, { displayName: BOT_USER }).then((cli) => { bot = cli; }); }) @@ -97,7 +97,7 @@ describe("Decryption Failure Bar", () => { }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it( @@ -105,7 +105,7 @@ describe("Decryption Failure Bar", () => { "and there are other verified devices or backups", () => { let otherDevice: MatrixClient | undefined; - cy.loginBot(synapse, testUser.username, testUser.password, {}) + cy.loginBot(homeserver, testUser.username, testUser.password, {}) .then(async (cli) => { otherDevice = cli; await otherDevice.bootstrapCrossSigning({ @@ -169,7 +169,7 @@ describe("Decryption Failure Bar", () => { "should prompt the user to reset keys, if this device isn't verified " + "and there are no other verified devices or backups", () => { - cy.loginBot(synapse, testUser.username, testUser.password, {}).then(async (cli) => { + cy.loginBot(homeserver, testUser.username, testUser.password, {}).then(async (cli) => { await cli.bootstrapCrossSigning({ authUploadDeviceSigningKeys: async (makeRequest) => { await makeRequest({}); diff --git a/cypress/e2e/editing/editing.spec.ts b/cypress/e2e/editing/editing.spec.ts index 9051a70c60..f8d7dd1e3f 100644 --- a/cypress/e2e/editing/editing.spec.ts +++ b/cypress/e2e/editing/editing.spec.ts @@ -19,7 +19,7 @@ limitations under the License. import type { MsgType } from "matrix-js-sdk/src/@types/event"; import type { ISendEventResponse } from "matrix-js-sdk/src/@types/requests"; import type { EventType } from "matrix-js-sdk/src/@types/event"; -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import Chainable = Cypress.Chainable; const sendEvent = (roomId: string): Chainable => { @@ -30,12 +30,12 @@ const sendEvent = (roomId: string): Chainable => { }; describe("Editing", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; - cy.initTestUser(synapse, "Edith").then(() => { + cy.startHomeserver("default").then((data) => { + homeserver = data; + cy.initTestUser(homeserver, "Edith").then(() => { cy.injectAxe(); return cy.createRoom({ name: "Test room" }).as("roomId"); }); @@ -43,7 +43,7 @@ describe("Editing", () => { }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("should close the composer when clicking save after making a change and undoing it", () => { diff --git a/cypress/e2e/integration-manager/get-openid-token.spec.ts b/cypress/e2e/integration-manager/get-openid-token.spec.ts index f799437862..f7b3eeaeca 100644 --- a/cypress/e2e/integration-manager/get-openid-token.spec.ts +++ b/cypress/e2e/integration-manager/get-openid-token.spec.ts @@ -16,7 +16,7 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { UserCredentials } from "../../support/login"; const ROOM_NAME = "Integration Manager Test"; @@ -73,17 +73,17 @@ function sendActionFromIntegrationManager(integrationManagerUrl: string) { describe("Integration Manager: Get OpenID Token", () => { let testUser: UserCredentials; - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; let integrationManagerUrl: string; beforeEach(() => { cy.serveHtmlFile(INTEGRATION_MANAGER_HTML).then((url) => { integrationManagerUrl = url; }); - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, USER_DISPLAY_NAME, () => { + cy.initTestUser(homeserver, USER_DISPLAY_NAME, () => { cy.window().then((win) => { win.localStorage.setItem("mx_scalar_token", INTEGRATION_MANAGER_TOKEN); win.localStorage.setItem(`mx_scalar_token_at_${integrationManagerUrl}`, INTEGRATION_MANAGER_TOKEN); @@ -122,7 +122,7 @@ describe("Integration Manager: Get OpenID Token", () => { }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); cy.stopWebServers(); }); diff --git a/cypress/e2e/integration-manager/kick.spec.ts b/cypress/e2e/integration-manager/kick.spec.ts index e182d840de..2cd66fa51b 100644 --- a/cypress/e2e/integration-manager/kick.spec.ts +++ b/cypress/e2e/integration-manager/kick.spec.ts @@ -16,7 +16,7 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { MatrixClient } from "../../global"; import { UserCredentials } from "../../support/login"; @@ -94,17 +94,17 @@ function expectKickedMessage(shouldExist: boolean) { describe("Integration Manager: Kick", () => { let testUser: UserCredentials; - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; let integrationManagerUrl: string; beforeEach(() => { cy.serveHtmlFile(INTEGRATION_MANAGER_HTML).then((url) => { integrationManagerUrl = url; }); - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, USER_DISPLAY_NAME, () => { + cy.initTestUser(homeserver, USER_DISPLAY_NAME, () => { cy.window().then((win) => { win.localStorage.setItem("mx_scalar_token", INTEGRATION_MANAGER_TOKEN); win.localStorage.setItem(`mx_scalar_token_at_${integrationManagerUrl}`, INTEGRATION_MANAGER_TOKEN); @@ -140,12 +140,12 @@ describe("Integration Manager: Kick", () => { name: ROOM_NAME, }).as("roomId"); - cy.getBot(synapse, { displayName: BOT_DISPLAY_NAME, autoAcceptInvites: true }).as("bob"); + cy.getBot(homeserver, { displayName: BOT_DISPLAY_NAME, autoAcceptInvites: true }).as("bob"); }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); cy.stopWebServers(); }); diff --git a/cypress/e2e/integration-manager/read_events.spec.ts b/cypress/e2e/integration-manager/read_events.spec.ts index 662df22813..c331038db9 100644 --- a/cypress/e2e/integration-manager/read_events.spec.ts +++ b/cypress/e2e/integration-manager/read_events.spec.ts @@ -16,7 +16,7 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { UserCredentials } from "../../support/login"; const ROOM_NAME = "Integration Manager Test"; @@ -87,17 +87,17 @@ function sendActionFromIntegrationManager( describe("Integration Manager: Read Events", () => { let testUser: UserCredentials; - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; let integrationManagerUrl: string; beforeEach(() => { cy.serveHtmlFile(INTEGRATION_MANAGER_HTML).then((url) => { integrationManagerUrl = url; }); - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, USER_DISPLAY_NAME, () => { + cy.initTestUser(homeserver, USER_DISPLAY_NAME, () => { cy.window().then((win) => { win.localStorage.setItem("mx_scalar_token", INTEGRATION_MANAGER_TOKEN); win.localStorage.setItem(`mx_scalar_token_at_${integrationManagerUrl}`, INTEGRATION_MANAGER_TOKEN); @@ -136,7 +136,7 @@ describe("Integration Manager: Read Events", () => { }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); cy.stopWebServers(); }); diff --git a/cypress/e2e/integration-manager/send_event.spec.ts b/cypress/e2e/integration-manager/send_event.spec.ts index 7b706b047d..ac412e2468 100644 --- a/cypress/e2e/integration-manager/send_event.spec.ts +++ b/cypress/e2e/integration-manager/send_event.spec.ts @@ -16,7 +16,7 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { UserCredentials } from "../../support/login"; const ROOM_NAME = "Integration Manager Test"; @@ -93,17 +93,17 @@ function sendActionFromIntegrationManager( describe("Integration Manager: Send Event", () => { let testUser: UserCredentials; - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; let integrationManagerUrl: string; beforeEach(() => { cy.serveHtmlFile(INTEGRATION_MANAGER_HTML).then((url) => { integrationManagerUrl = url; }); - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, USER_DISPLAY_NAME, () => { + cy.initTestUser(homeserver, USER_DISPLAY_NAME, () => { cy.window().then((win) => { win.localStorage.setItem("mx_scalar_token", INTEGRATION_MANAGER_TOKEN); win.localStorage.setItem(`mx_scalar_token_at_${integrationManagerUrl}`, INTEGRATION_MANAGER_TOKEN); @@ -142,7 +142,7 @@ describe("Integration Manager: Send Event", () => { }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); cy.stopWebServers(); }); diff --git a/cypress/e2e/lazy-loading/lazy-loading.spec.ts b/cypress/e2e/lazy-loading/lazy-loading.spec.ts index 4c6ce14dfe..e174364aeb 100644 --- a/cypress/e2e/lazy-loading/lazy-loading.spec.ts +++ b/cypress/e2e/lazy-loading/lazy-loading.spec.ts @@ -16,7 +16,7 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { MatrixClient } from "../../global"; import Chainable = Cypress.Chainable; @@ -26,7 +26,7 @@ interface Charly { } describe("Lazy Loading", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; let bob: MatrixClient; const charlies: Charly[] = []; @@ -35,12 +35,12 @@ describe("Lazy Loading", () => { win.localStorage.setItem("mx_lhs_size", "0"); // Collapse left panel for these tests }); - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Alice"); + cy.initTestUser(homeserver, "Alice"); - cy.getBot(synapse, { + cy.getBot(homeserver, { displayName: "Bob", startClient: false, autoAcceptInvites: false, @@ -50,7 +50,7 @@ describe("Lazy Loading", () => { for (let i = 1; i <= 10; i++) { const displayName = `Charly #${i}`; - cy.getBot(synapse, { + cy.getBot(homeserver, { displayName, startClient: false, autoAcceptInvites: false, @@ -62,7 +62,7 @@ describe("Lazy Loading", () => { }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); const name = "Lazy Loading Test"; diff --git a/cypress/e2e/location/location.spec.ts b/cypress/e2e/location/location.spec.ts index 614c88cf8b..0d512705a0 100644 --- a/cypress/e2e/location/location.spec.ts +++ b/cypress/e2e/location/location.spec.ts @@ -16,11 +16,11 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import Chainable = Cypress.Chainable; describe("Location sharing", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; const selectLocationShareTypeOption = (shareType: string): Chainable => { return cy.get(`[data-test-id="share-location-option-${shareType}"]`); @@ -34,15 +34,15 @@ describe("Location sharing", () => { cy.window().then((win) => { win.localStorage.setItem("mx_lhs_size", "0"); // Collapse left panel for these tests }); - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Tom"); + cy.initTestUser(homeserver, "Tom"); }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("sends and displays pin drop location message successfully", () => { diff --git a/cypress/e2e/login/consent.spec.ts b/cypress/e2e/login/consent.spec.ts index dc62ca6060..6175300567 100644 --- a/cypress/e2e/login/consent.spec.ts +++ b/cypress/e2e/login/consent.spec.ts @@ -18,21 +18,21 @@ limitations under the License. import { SinonStub } from "cypress/types/sinon"; -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; describe("Consent", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { - cy.startSynapse("consent").then((data) => { - synapse = data; + cy.startHomeserver("consent").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Bob"); + cy.initTestUser(homeserver, "Bob"); }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("should prompt the user to consent to terms when server deems it necessary", () => { @@ -53,8 +53,8 @@ describe("Consent", () => { cy.get("@windowOpen").then((stub) => { const url = stub.getCall(0).args[0]; - // Go to Synapse's consent page and accept it - cy.origin(synapse.baseUrl, { args: { url } }, ({ url }) => { + // Go to Homeserver's consent page and accept it + cy.origin(homeserver.baseUrl, { args: { url } }, ({ url }) => { cy.visit(url); cy.get('[type="submit"]').click(); diff --git a/cypress/e2e/login/login.spec.ts b/cypress/e2e/login/login.spec.ts index de75c28a2e..59d9c499ce 100644 --- a/cypress/e2e/login/login.spec.ts +++ b/cypress/e2e/login/login.spec.ts @@ -16,17 +16,17 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; describe("Login", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { cy.stubDefaultServer(); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); describe("m.login.password", () => { @@ -34,9 +34,9 @@ describe("Login", () => { const password = "p4s5W0rD"; beforeEach(() => { - cy.startSynapse("consent").then((data) => { - synapse = data; - cy.registerUser(synapse, username, password); + cy.startHomeserver("consent").then((data) => { + homeserver = data; + cy.registerUser(homeserver, username, password); cy.visit("/#/login"); }); }); @@ -49,7 +49,7 @@ describe("Login", () => { cy.checkA11y(); cy.get(".mx_ServerPicker_change").click(); - cy.get(".mx_ServerPickerDialog_otherHomeserver").type(synapse.baseUrl); + cy.get(".mx_ServerPickerDialog_otherHomeserver").type(homeserver.baseUrl); cy.get(".mx_ServerPickerDialog_continue").click(); // wait for the dialog to go away cy.get(".mx_ServerPickerDialog").should("not.exist"); @@ -64,9 +64,9 @@ describe("Login", () => { describe("logout", () => { beforeEach(() => { - cy.startSynapse("consent").then((data) => { - synapse = data; - cy.initTestUser(synapse, "Erin"); + cy.startHomeserver("consent").then((data) => { + homeserver = data; + cy.initTestUser(homeserver, "Erin"); }); }); diff --git a/cypress/e2e/polls/polls.spec.ts b/cypress/e2e/polls/polls.spec.ts index c092d4f647..477c195ac3 100644 --- a/cypress/e2e/polls/polls.spec.ts +++ b/cypress/e2e/polls/polls.spec.ts @@ -18,14 +18,14 @@ limitations under the License. import { PollResponseEvent } from "matrix-events-sdk"; -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { MatrixClient } from "../../global"; import Chainable = Cypress.Chainable; const hideTimestampCSS = ".mx_MessageTimestamp { visibility: hidden !important; }"; describe("Polls", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; type CreatePollOptions = { title: string; @@ -81,20 +81,20 @@ describe("Polls", () => { cy.window().then((win) => { win.localStorage.setItem("mx_lhs_size", "0"); // Collapse left panel for these tests }); - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Tom"); + cy.initTestUser(homeserver, "Tom"); }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("should be creatable and votable", () => { let bot: MatrixClient; - cy.getBot(synapse, { displayName: "BotBob" }).then((_bot) => { + cy.getBot(homeserver, { displayName: "BotBob" }).then((_bot) => { bot = _bot; }); @@ -163,7 +163,7 @@ describe("Polls", () => { it("should be editable from context menu if no votes have been cast", () => { let bot: MatrixClient; - cy.getBot(synapse, { displayName: "BotBob" }).then((_bot) => { + cy.getBot(homeserver, { displayName: "BotBob" }).then((_bot) => { bot = _bot; }); @@ -206,7 +206,7 @@ describe("Polls", () => { it("should not be editable from context menu if votes have been cast", () => { let bot: MatrixClient; - cy.getBot(synapse, { displayName: "BotBob" }).then((_bot) => { + cy.getBot(homeserver, { displayName: "BotBob" }).then((_bot) => { bot = _bot; }); @@ -256,10 +256,10 @@ describe("Polls", () => { it("should be displayed correctly in thread panel", () => { let botBob: MatrixClient; let botCharlie: MatrixClient; - cy.getBot(synapse, { displayName: "BotBob" }).then((_bot) => { + cy.getBot(homeserver, { displayName: "BotBob" }).then((_bot) => { botBob = _bot; }); - cy.getBot(synapse, { displayName: "BotCharlie" }).then((_bot) => { + cy.getBot(homeserver, { displayName: "BotCharlie" }).then((_bot) => { botCharlie = _bot; }); diff --git a/cypress/e2e/register/register.spec.ts b/cypress/e2e/register/register.spec.ts index df5eafb6a0..f6ea4379be 100644 --- a/cypress/e2e/register/register.spec.ts +++ b/cypress/e2e/register/register.spec.ts @@ -16,21 +16,21 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; describe("Registration", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { cy.stubDefaultServer(); cy.visit("/#/register"); - cy.startSynapse("consent").then((data) => { - synapse = data; + cy.startHomeserver("consent").then((data) => { + homeserver = data; }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("registers an account and lands on the home screen", () => { @@ -42,13 +42,13 @@ describe("Registration", () => { cy.get(".mx_Dialog").percySnapshotElement("Server Picker", { widths: [516] }); cy.checkA11y(); - cy.get(".mx_ServerPickerDialog_otherHomeserver").type(synapse.baseUrl); + cy.get(".mx_ServerPickerDialog_otherHomeserver").type(homeserver.baseUrl); cy.get(".mx_ServerPickerDialog_continue").click(); // wait for the dialog to go away cy.get(".mx_ServerPickerDialog").should("not.exist"); cy.get("#mx_RegistrationForm_username").should("be.visible"); - // Hide the server text as it contains the randomly allocated Synapse port + // Hide the server text as it contains the randomly allocated Homeserver port const percyCSS = ".mx_ServerPicker_server { visibility: hidden !important; }"; cy.percySnapshot("Registration", { percyCSS }); cy.checkA11y(); @@ -88,7 +88,7 @@ describe("Registration", () => { it("should require username to fulfil requirements and be available", () => { cy.get(".mx_ServerPicker_change", { timeout: 15000 }).click(); cy.get(".mx_ServerPickerDialog_continue").should("be.visible"); - cy.get(".mx_ServerPickerDialog_otherHomeserver").type(synapse.baseUrl); + cy.get(".mx_ServerPickerDialog_otherHomeserver").type(homeserver.baseUrl); cy.get(".mx_ServerPickerDialog_continue").click(); // wait for the dialog to go away cy.get(".mx_ServerPickerDialog").should("not.exist"); diff --git a/cypress/e2e/regression-tests/pills-click-in-app.spec.ts b/cypress/e2e/regression-tests/pills-click-in-app.spec.ts index 4e48426997..301da254da 100644 --- a/cypress/e2e/regression-tests/pills-click-in-app.spec.ts +++ b/cypress/e2e/regression-tests/pills-click-in-app.spec.ts @@ -16,21 +16,21 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; describe("Pills", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Sally"); + cy.initTestUser(homeserver, "Sally"); }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("should navigate clicks internally to the app", () => { diff --git a/cypress/e2e/right-panel/right-panel.spec.ts b/cypress/e2e/right-panel/right-panel.spec.ts index 84e9db9ac6..6ada7f41d4 100644 --- a/cypress/e2e/right-panel/right-panel.spec.ts +++ b/cypress/e2e/right-panel/right-panel.spec.ts @@ -16,7 +16,7 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import Chainable = Cypress.Chainable; const ROOM_NAME = "Test room"; @@ -43,12 +43,12 @@ const checkRoomSummaryCard = (name: string): Chainable> => { }; describe("RightPanel", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; - cy.initTestUser(synapse, NAME).then(() => + cy.startHomeserver("default").then((data) => { + homeserver = data; + cy.initTestUser(homeserver, NAME).then(() => cy.window({ log: false }).then(() => { cy.createRoom({ name: ROOM_NAME }); cy.createSpace({ name: SPACE_NAME }); @@ -58,7 +58,7 @@ describe("RightPanel", () => { }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); describe("in rooms", () => { diff --git a/cypress/e2e/room-directory/room-directory.spec.ts b/cypress/e2e/room-directory/room-directory.spec.ts index b0fec151a7..fe4474d31e 100644 --- a/cypress/e2e/room-directory/room-directory.spec.ts +++ b/cypress/e2e/room-directory/room-directory.spec.ts @@ -16,23 +16,23 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { MatrixClient } from "../../global"; describe("Room Directory", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Ray"); - cy.getBot(synapse, { displayName: "Paul" }).as("bot"); + cy.initTestUser(homeserver, "Ray"); + cy.getBot(homeserver, { displayName: "Paul" }).as("bot"); }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("should allow admin to add alias & publish room to directory", () => { diff --git a/cypress/e2e/room/room.spec.ts b/cypress/e2e/room/room.spec.ts index 1d09475166..a8a3a9a7e6 100644 --- a/cypress/e2e/room/room.spec.ts +++ b/cypress/e2e/room/room.spec.ts @@ -18,34 +18,34 @@ limitations under the License. import { EventType } from "matrix-js-sdk/src/@types/event"; -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { MatrixClient } from "../../global"; describe("Room Directory", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Alice"); + cy.initTestUser(homeserver, "Alice"); }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("should switch between existing dm rooms without a loader", () => { let bobClient: MatrixClient; let charlieClient: MatrixClient; - cy.getBot(synapse, { + cy.getBot(homeserver, { displayName: "Bob", }).then((bob) => { bobClient = bob; }); - cy.getBot(synapse, { + cy.getBot(homeserver, { displayName: "Charlie", }).then((charlie) => { charlieClient = charlie; diff --git a/cypress/e2e/settings/device-management.spec.ts b/cypress/e2e/settings/device-management.spec.ts index 32e99faf77..af0cdf6c2a 100644 --- a/cypress/e2e/settings/device-management.spec.ts +++ b/cypress/e2e/settings/device-management.spec.ts @@ -16,34 +16,34 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import type { UserCredentials } from "../../support/login"; describe("Device manager", () => { - let synapse: SynapseInstance | undefined; + let homeserver: HomeserverInstance | undefined; let user: UserCredentials | undefined; beforeEach(() => { cy.enableLabsFeature("feature_new_device_manager"); - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Alice") + cy.initTestUser(homeserver, "Alice") .then((credentials) => { user = credentials; }) .then(() => { // create some extra sessions to manage - return cy.loginUser(synapse, user.username, user.password); + return cy.loginUser(homeserver, user.username, user.password); }) .then(() => { - return cy.loginUser(synapse, user.username, user.password); + return cy.loginUser(homeserver, user.username, user.password); }); }); }); afterEach(() => { - cy.stopSynapse(synapse!); + cy.stopHomeserver(homeserver!); }); it("should display sessions", () => { diff --git a/cypress/e2e/settings/hidden-rr-migration.spec.ts b/cypress/e2e/settings/hidden-rr-migration.spec.ts index 8fd9482310..729bf7ebd7 100644 --- a/cypress/e2e/settings/hidden-rr-migration.spec.ts +++ b/cypress/e2e/settings/hidden-rr-migration.spec.ts @@ -16,10 +16,10 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; -function seedLabs(synapse: SynapseInstance, labsVal: boolean | null): void { - cy.initTestUser(synapse, "Sally", () => { +function seedLabs(homeserver: HomeserverInstance, labsVal: boolean | null): void { + cy.initTestUser(homeserver, "Sally", () => { // seed labs flag cy.window({ log: false }).then((win) => { if (typeof labsVal === "boolean") { @@ -61,30 +61,30 @@ describe("Hidden Read Receipts Setting Migration", () => { // For a security-sensitive feature like hidden read receipts, it's absolutely vital // that we migrate the setting appropriately. - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("should not migrate the lack of a labs flag", () => { - seedLabs(synapse, null); + seedLabs(homeserver, null); testForVal(null); }); it("should migrate labsHiddenRR=false as sendRR=true", () => { - seedLabs(synapse, false); + seedLabs(homeserver, false); testForVal(true); }); it("should migrate labsHiddenRR=true as sendRR=false", () => { - seedLabs(synapse, true); + seedLabs(homeserver, true); testForVal(false); }); }); diff --git a/cypress/e2e/sliding-sync/sliding-sync.ts b/cypress/e2e/sliding-sync/sliding-sync.ts index 3d9f9b35f9..1b2642eeb4 100644 --- a/cypress/e2e/sliding-sync/sliding-sync.ts +++ b/cypress/e2e/sliding-sync/sliding-sync.ts @@ -20,43 +20,45 @@ import _ from "lodash"; import { MatrixClient } from "matrix-js-sdk/src/matrix"; import { Interception } from "cypress/types/net-stubbing"; -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { SettingLevel } from "../../../src/settings/SettingLevel"; import { Layout } from "../../../src/settings/enums/Layout"; import { ProxyInstance } from "../../plugins/sliding-sync"; describe("Sliding Sync", () => { beforeEach(() => { - cy.startSynapse("default") - .as("synapse") - .then((synapse) => { - cy.startProxy(synapse).as("proxy"); + cy.startHomeserver("default") + .as("homeserver") + .then((homeserver) => { + cy.startProxy(homeserver).as("proxy"); }); - cy.all([cy.get("@synapse"), cy.get("@proxy")]).then(([synapse, proxy]) => { - cy.enableLabsFeature("feature_sliding_sync"); + cy.all([cy.get("@homeserver"), cy.get("@proxy")]).then( + ([homeserver, proxy]) => { + cy.enableLabsFeature("feature_sliding_sync"); - cy.intercept("/config.json?cachebuster=*", (req) => { - return req.continue((res) => { - res.send(200, { - ...res.body, - setting_defaults: { - feature_sliding_sync_proxy_url: `http://localhost:${proxy.port}`, - }, + cy.intercept("/config.json?cachebuster=*", (req) => { + return req.continue((res) => { + res.send(200, { + ...res.body, + setting_defaults: { + feature_sliding_sync_proxy_url: `http://localhost:${proxy.port}`, + }, + }); }); }); - }); - cy.initTestUser(synapse, "Sloth").then(() => { - return cy.window({ log: false }).then(() => { - cy.createRoom({ name: "Test Room" }).as("roomId"); + cy.initTestUser(homeserver, "Sloth").then(() => { + return cy.window({ log: false }).then(() => { + cy.createRoom({ name: "Test Room" }).as("roomId"); + }); }); - }); - }); + }, + ); }); afterEach(() => { - cy.get("@synapse").then(cy.stopSynapse); + cy.get("@homeserver").then(cy.stopHomeserver); cy.get("@proxy").then(cy.stopProxy); }); @@ -84,9 +86,9 @@ describe("Sliding Sync", () => { }; const createAndJoinBob = () => { // create a Bob user - cy.get("@synapse").then((synapse) => { + cy.get("@homeserver").then((homeserver) => { return cy - .getBot(synapse, { + .getBot(homeserver, { displayName: "Bob", }) .as("bob"); diff --git a/cypress/e2e/spaces/spaces.spec.ts b/cypress/e2e/spaces/spaces.spec.ts index 47232dc5af..f07746c0f5 100644 --- a/cypress/e2e/spaces/spaces.spec.ts +++ b/cypress/e2e/spaces/spaces.spec.ts @@ -18,7 +18,7 @@ limitations under the License. import type { MatrixClient } from "matrix-js-sdk/src/client"; import type { ICreateRoomOpts } from "matrix-js-sdk/src/@types/requests"; -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import Chainable = Cypress.Chainable; import { UserCredentials } from "../../support/login"; @@ -59,14 +59,14 @@ function spaceChildInitialState(roomId: string): ICreateRoomOpts["initial_state" } describe("Spaces", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; let user: UserCredentials; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Sue").then((_user) => { + cy.initTestUser(homeserver, "Sue").then((_user) => { user = _user; cy.mockClipboard(); }); @@ -74,7 +74,7 @@ describe("Spaces", () => { }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it.only("should allow user to create public space", () => { @@ -173,7 +173,7 @@ describe("Spaces", () => { it("should allow user to invite another to a space", () => { let bot: MatrixClient; - cy.getBot(synapse, { displayName: "BotBob" }).then((_bot) => { + cy.getBot(homeserver, { displayName: "BotBob" }).then((_bot) => { bot = _bot; }); @@ -208,7 +208,7 @@ describe("Spaces", () => { }); cy.getSpacePanelButton("My Space").should("exist"); - cy.getBot(synapse, { displayName: "BotBob" }).then({ timeout: 10000 }, async (bot) => { + cy.getBot(homeserver, { displayName: "BotBob" }).then({ timeout: 10000 }, async (bot) => { const { room_id: roomId } = await bot.createRoom(spaceCreateOptions("Space Space")); await bot.invite(roomId, user.userId); }); diff --git a/cypress/e2e/spotlight/spotlight.spec.ts b/cypress/e2e/spotlight/spotlight.spec.ts index 9b89365714..d9ead17bb3 100644 --- a/cypress/e2e/spotlight/spotlight.spec.ts +++ b/cypress/e2e/spotlight/spotlight.spec.ts @@ -17,7 +17,7 @@ limitations under the License. /// import { MatrixClient } from "../../global"; -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import Chainable = Cypress.Chainable; import Loggable = Cypress.Loggable; import Timeoutable = Cypress.Timeoutable; @@ -136,7 +136,7 @@ Cypress.Commands.add("startDM", (name: string) => { }); describe("Spotlight", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; const bot1Name = "BotBob"; let bot1: MatrixClient; @@ -154,16 +154,16 @@ describe("Spotlight", () => { let room3Id: string; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; - cy.initTestUser(synapse, "Jim") + cy.startHomeserver("default").then((data) => { + homeserver = data; + cy.initTestUser(homeserver, "Jim") .then(() => - cy.getBot(synapse, { displayName: bot1Name }).then((_bot1) => { + cy.getBot(homeserver, { displayName: bot1Name }).then((_bot1) => { bot1 = _bot1; }), ) .then(() => - cy.getBot(synapse, { displayName: bot2Name }).then((_bot2) => { + cy.getBot(homeserver, { displayName: bot2Name }).then((_bot2) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars bot2 = _bot2; }), @@ -205,7 +205,7 @@ describe("Spotlight", () => { afterEach(() => { cy.visit("/#/home"); - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("should be able to add and remove filters via keyboard", () => { diff --git a/cypress/e2e/threads/threads.spec.ts b/cypress/e2e/threads/threads.spec.ts index 7b616bd13f..0de87ea9cd 100644 --- a/cypress/e2e/threads/threads.spec.ts +++ b/cypress/e2e/threads/threads.spec.ts @@ -16,7 +16,7 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { MatrixClient } from "../../global"; function markWindowBeforeReload(): void { @@ -25,7 +25,7 @@ function markWindowBeforeReload(): void { } describe("Threads", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { // Default threads to ON for this spec @@ -33,15 +33,15 @@ describe("Threads", () => { cy.window().then((win) => { win.localStorage.setItem("mx_lhs_size", "0"); // Collapse left panel for these tests }); - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Tom"); + cy.initTestUser(homeserver, "Tom"); }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("should reload when enabling threads beta", () => { @@ -75,7 +75,7 @@ describe("Threads", () => { it("should be usable for a conversation", () => { let bot: MatrixClient; - cy.getBot(synapse, { + cy.getBot(homeserver, { displayName: "BotBob", autoAcceptInvites: false, }).then((_bot) => { diff --git a/cypress/e2e/timeline/timeline.spec.ts b/cypress/e2e/timeline/timeline.spec.ts index 90406eae02..17b763a089 100644 --- a/cypress/e2e/timeline/timeline.spec.ts +++ b/cypress/e2e/timeline/timeline.spec.ts @@ -18,7 +18,7 @@ limitations under the License. import type { ISendEventResponse } from "matrix-js-sdk/src/@types/requests"; import type { EventType, MsgType } from "matrix-js-sdk/src/@types/event"; -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { SettingLevel } from "../../../src/settings/SettingLevel"; import { Layout } from "../../../src/settings/enums/Layout"; import Chainable = Cypress.Chainable; @@ -67,7 +67,7 @@ const sendEvent = (roomId: string, html = false): Chainable }; describe("Timeline", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; let roomId: string; @@ -75,9 +75,9 @@ describe("Timeline", () => { let newAvatarUrl: string; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; - cy.initTestUser(synapse, OLD_NAME).then(() => + cy.startHomeserver("default").then((data) => { + homeserver = data; + cy.initTestUser(homeserver, OLD_NAME).then(() => cy.createRoom({ name: ROOM_NAME }).then((_room1Id) => { roomId = _room1Id; }), @@ -86,7 +86,7 @@ describe("Timeline", () => { }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); describe("useOnlyCurrentProfiles", () => { diff --git a/cypress/e2e/toasts/analytics-toast.ts b/cypress/e2e/toasts/analytics-toast.ts index 4c9cbed02f..4cc8baa838 100644 --- a/cypress/e2e/toasts/analytics-toast.ts +++ b/cypress/e2e/toasts/analytics-toast.ts @@ -16,7 +16,7 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import Chainable = Cypress.Chainable; function assertNoToasts(): void { @@ -40,10 +40,10 @@ function rejectToast(expectedTitle: string): void { } describe("Analytics Toast", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("should not show an analytics toast if config has nothing about posthog", () => { @@ -55,9 +55,9 @@ describe("Analytics Toast", () => { }); }); - cy.startSynapse("default").then((data) => { - synapse = data; - cy.initTestUser(synapse, "Tod"); + cy.startHomeserver("default").then((data) => { + homeserver = data; + cy.initTestUser(homeserver, "Tod"); }); rejectToast("Notifications"); @@ -78,9 +78,9 @@ describe("Analytics Toast", () => { }); }); - cy.startSynapse("default").then((data) => { - synapse = data; - cy.initTestUser(synapse, "Tod"); + cy.startHomeserver("default").then((data) => { + homeserver = data; + cy.initTestUser(homeserver, "Tod"); rejectToast("Notifications"); }); }); diff --git a/cypress/e2e/update/update.spec.ts b/cypress/e2e/update/update.spec.ts index eaf039b6ea..99a8fb32a9 100644 --- a/cypress/e2e/update/update.spec.ts +++ b/cypress/e2e/update/update.spec.ts @@ -16,19 +16,19 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; describe("Update", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("should navigate to ?updated=$VERSION if realises it is immediately out of date on load", () => { @@ -42,7 +42,7 @@ describe("Update", () => { }, }).as("version"); - cy.initTestUser(synapse, "Ursa"); + cy.initTestUser(homeserver, "Ursa"); cy.wait("@version"); cy.url() diff --git a/cypress/e2e/user-menu/user-menu.spec.ts b/cypress/e2e/user-menu/user-menu.spec.ts index 841dc82e85..bec1821e1b 100644 --- a/cypress/e2e/user-menu/user-menu.spec.ts +++ b/cypress/e2e/user-menu/user-menu.spec.ts @@ -16,25 +16,25 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import type { UserCredentials } from "../../support/login"; describe("User Menu", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; let user: UserCredentials; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Jeff").then((credentials) => { + cy.initTestUser(homeserver, "Jeff").then((credentials) => { user = credentials; }); }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("should contain our name & userId", () => { diff --git a/cypress/e2e/user-onboarding/user-onboarding-new.ts b/cypress/e2e/user-onboarding/user-onboarding-new.ts index a3975cb5ac..b4b6c83105 100644 --- a/cypress/e2e/user-onboarding/user-onboarding-new.ts +++ b/cypress/e2e/user-onboarding/user-onboarding-new.ts @@ -17,18 +17,18 @@ limitations under the License. /// import { MatrixClient } from "../../global"; -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; describe("User Onboarding (new user)", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; const bot1Name = "BotBob"; let bot1: MatrixClient; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; - cy.initTestUser(synapse, "Jane Doe"); + cy.startHomeserver("default").then((data) => { + homeserver = data; + cy.initTestUser(homeserver, "Jane Doe"); cy.window({ log: false }).then((win) => { win.localStorage.setItem("mx_registration_time", "1656633601"); }); @@ -36,7 +36,7 @@ describe("User Onboarding (new user)", () => { // wait for the app to load return cy.get(".mx_MatrixChat", { timeout: 15000 }); }); - cy.getBot(synapse, { displayName: bot1Name }).then((_bot1) => { + cy.getBot(homeserver, { displayName: bot1Name }).then((_bot1) => { bot1 = _bot1; }); cy.get(".mx_UserOnboardingPage").should("exist"); @@ -51,7 +51,7 @@ describe("User Onboarding (new user)", () => { }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("page is shown and preference exists", () => { diff --git a/cypress/e2e/user-onboarding/user-onboarding-old.ts b/cypress/e2e/user-onboarding/user-onboarding-old.ts index 90ae73b257..7f0c2b7612 100644 --- a/cypress/e2e/user-onboarding/user-onboarding-old.ts +++ b/cypress/e2e/user-onboarding/user-onboarding-old.ts @@ -16,15 +16,15 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; describe("User Onboarding (old user)", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; - cy.initTestUser(synapse, "Jane Doe"); + cy.startHomeserver("default").then((data) => { + homeserver = data; + cy.initTestUser(homeserver, "Jane Doe"); cy.window({ log: false }).then((win) => { win.localStorage.setItem("mx_registration_time", "2"); }); @@ -37,7 +37,7 @@ describe("User Onboarding (old user)", () => { afterEach(() => { cy.visit("/#/home"); - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("page and preference are hidden", () => { diff --git a/cypress/e2e/user-view/user-view.spec.ts b/cypress/e2e/user-view/user-view.spec.ts index df7bd933ae..529ef16cf1 100644 --- a/cypress/e2e/user-view/user-view.spec.ts +++ b/cypress/e2e/user-view/user-view.spec.ts @@ -16,23 +16,23 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { MatrixClient } from "../../global"; describe("UserView", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Violet"); - cy.getBot(synapse, { displayName: "Usman" }).as("bot"); + cy.initTestUser(homeserver, "Violet"); + cy.getBot(homeserver, { displayName: "Usman" }).as("bot"); }); }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); }); it("should render the user view as expected", () => { diff --git a/cypress/e2e/widgets/layout.spec.ts b/cypress/e2e/widgets/layout.spec.ts index 886b3062c8..16bee8d222 100644 --- a/cypress/e2e/widgets/layout.spec.ts +++ b/cypress/e2e/widgets/layout.spec.ts @@ -17,7 +17,7 @@ limitations under the License. import { IWidget } from "matrix-widget-api"; -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; const ROOM_NAME = "Test Room"; const WIDGET_ID = "fake-widget"; @@ -34,14 +34,14 @@ const WIDGET_HTML = ` describe("Widget Layout", () => { let widgetUrl: string; - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; let roomId: string; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Sally"); + cy.initTestUser(homeserver, "Sally"); }); cy.serveHtmlFile(WIDGET_HTML).then((url) => { widgetUrl = url; @@ -91,7 +91,7 @@ describe("Widget Layout", () => { }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); cy.stopWebServers(); }); diff --git a/cypress/e2e/widgets/stickers.spec.ts b/cypress/e2e/widgets/stickers.spec.ts index c714b84416..5c016b406a 100644 --- a/cypress/e2e/widgets/stickers.spec.ts +++ b/cypress/e2e/widgets/stickers.spec.ts @@ -16,7 +16,7 @@ limitations under the License. /// -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; const STICKER_PICKER_WIDGET_ID = "fake-sticker-picker"; const STICKER_PICKER_WIDGET_NAME = "Fake Stickers"; @@ -102,13 +102,13 @@ describe("Stickers", () => { // See sendStickerFromPicker() for more detail on iframe comms. let stickerPickerUrl: string; - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Sally"); + cy.initTestUser(homeserver, "Sally"); }); cy.serveHtmlFile(WIDGET_HTML).then((url) => { stickerPickerUrl = url; @@ -116,7 +116,7 @@ describe("Stickers", () => { }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); cy.stopWebServers(); }); diff --git a/cypress/e2e/widgets/widget-pip-close.spec.ts b/cypress/e2e/widgets/widget-pip-close.spec.ts index 59376d8572..ca717947d0 100644 --- a/cypress/e2e/widgets/widget-pip-close.spec.ts +++ b/cypress/e2e/widgets/widget-pip-close.spec.ts @@ -20,7 +20,7 @@ limitations under the License. import { IWidget } from "matrix-widget-api/src/interfaces/IWidget"; import type { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix"; -import { SynapseInstance } from "../../plugins/synapsedocker"; +import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { UserCredentials } from "../../support/login"; const DEMO_WIDGET_ID = "demo-widget-id"; @@ -90,7 +90,7 @@ function waitForRoomWidget(win: Cypress.AUTWindow, widgetId: string, roomId: str } describe("Widget PIP", () => { - let synapse: SynapseInstance; + let homeserver: HomeserverInstance; let user: UserCredentials; let bot: MatrixClient; let demoWidgetUrl: string; @@ -173,13 +173,13 @@ describe("Widget PIP", () => { } beforeEach(() => { - cy.startSynapse("default").then((data) => { - synapse = data; + cy.startHomeserver("default").then((data) => { + homeserver = data; - cy.initTestUser(synapse, "Mike").then((_user) => { + cy.initTestUser(homeserver, "Mike").then((_user) => { user = _user; }); - cy.getBot(synapse, { displayName: "Bot", autoAcceptInvites: false }).then((_bot) => { + cy.getBot(homeserver, { displayName: "Bot", autoAcceptInvites: false }).then((_bot) => { bot = _bot; }); }); @@ -189,7 +189,7 @@ describe("Widget PIP", () => { }); afterEach(() => { - cy.stopSynapse(synapse); + cy.stopHomeserver(homeserver); cy.stopWebServers(); }); diff --git a/cypress/plugins/dendritedocker/index.ts b/cypress/plugins/dendritedocker/index.ts new file mode 100644 index 0000000000..43791d9bae --- /dev/null +++ b/cypress/plugins/dendritedocker/index.ts @@ -0,0 +1,181 @@ +/* +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"; + +// A cypress plugins to add command to start & stop dendrites in +// docker with preset templates. + +const dendrites = new Map(); + +function randB64Bytes(numBytes: number): string { + return crypto.randomBytes(numBytes).toString("base64").replace(/=*$/, ""); +} + +async function cfgDirFromTemplate(template: string): Promise { + template = "default"; + const templateDir = path.join(__dirname, "templates", template); + const configFile = "dendrite.yaml"; + + 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) !== configFile }); + + 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, configFile)}`); + let hsYaml = await fse.readFile(path.join(templateDir, configFile), "utf8"); + hsYaml = hsYaml.replace(/{{REGISTRATION_SECRET}}/g, registrationSecret); + await fse.writeFile(path.join(tempDir, configFile), hsYaml); + + await dockerRun({ + image: "matrixdotorg/dendrite-monolith:main", + 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(template: string): Promise { + const denCfg = await cfgDirFromTemplate(template); + + console.log(`Starting dendrite with config dir ${denCfg.configDir}...`); + + const dendriteId = await dockerRun({ + image: "matrixdotorg/dendrite-monolith:main", + params: [ + "--rm", + "-v", + `${denCfg.configDir}:/etc/dendrite`, + "-p", + `${denCfg.port}:8008/tcp`, + "--entrypoint", + "/usr/bin/dendrite-monolith-server", + ], + containerName: `react-sdk-cypress-dendrite`, + cmd: ["--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; +} + +/** + * @type {Cypress.PluginConfig} + */ +export function dendriteDocker(on: PluginEvents, config: PluginConfigOptions) { + on("task", { + dendriteStart, + dendriteStop, + }); + + 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 new file mode 100644 index 0000000000..8af5854d6c --- /dev/null +++ b/cypress/plugins/dendritedocker/templates/default/dendrite.yaml @@ -0,0 +1,374 @@ +# 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 + +# 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 index 7c5fa1555a..e3c1cad7bd 100644 --- a/cypress/plugins/docker/index.ts +++ b/cypress/plugins/docker/index.ts @@ -30,7 +30,7 @@ export function dockerRun(opts: { image: string; containerName: string; params?: string[]; - cmd?: string; + cmd?: string[]; }): Promise { const userInfo = os.userInfo(); const params = opts.params ?? []; @@ -49,7 +49,7 @@ export function dockerRun(opts: { opts.image, ]; - if (opts.cmd) args.push(opts.cmd); + if (opts.cmd) args.push(...opts.cmd); return new Promise((resolve, reject) => { childProcess.execFile("docker", args, (err, stdout) => { diff --git a/cypress/plugins/index.ts b/cypress/plugins/index.ts index 603f31ed09..1971a70c5b 100644 --- a/cypress/plugins/index.ts +++ b/cypress/plugins/index.ts @@ -19,6 +19,7 @@ limitations under the License. import PluginEvents = Cypress.PluginEvents; import PluginConfigOptions = Cypress.PluginConfigOptions; import { synapseDocker } from "./synapsedocker"; +import { dendriteDocker } from "./dendritedocker"; import { slidingSyncProxyDocker } from "./sliding-sync"; import { webserver } from "./webserver"; import { docker } from "./docker"; @@ -30,6 +31,7 @@ import { log } from "./log"; export default function (on: PluginEvents, config: PluginConfigOptions) { docker(on, config); synapseDocker(on, config); + dendriteDocker(on, config); slidingSyncProxyDocker(on, config); webserver(on, config); log(on, config); diff --git a/cypress/plugins/sliding-sync/index.ts b/cypress/plugins/sliding-sync/index.ts index c2495325e0..8204fb578d 100644 --- a/cypress/plugins/sliding-sync/index.ts +++ b/cypress/plugins/sliding-sync/index.ts @@ -20,7 +20,7 @@ import PluginEvents = Cypress.PluginEvents; import PluginConfigOptions = Cypress.PluginConfigOptions; import { dockerExec, dockerIp, dockerRun, dockerStop } from "../docker"; import { getFreePort } from "../utils/port"; -import { SynapseInstance } from "../synapsedocker"; +import { HomeserverInstance } from "../utils/homeserver"; // A cypress plugin to add command to start & stop https://github.com/matrix-org/sliding-sync // SLIDING_SYNC_PROXY_TAG env used as the docker tag to use for `ghcr.io/matrix-org/sliding-sync-proxy` image. @@ -35,7 +35,7 @@ const instances = new Map(); const PG_PASSWORD = "p4S5w0rD"; -async function proxyStart(dockerTag: string, synapse: SynapseInstance): Promise { +async function proxyStart(dockerTag: string, homeserver: HomeserverInstance): Promise { console.log(new Date(), "Starting sliding sync proxy..."); const postgresId = await dockerRun({ @@ -45,7 +45,7 @@ async function proxyStart(dockerTag: string, synapse: SynapseInstance): Promise< }); const postgresIp = await dockerIp({ containerId: postgresId }); - const synapseIp = await dockerIp({ containerId: synapse.synapseId }); + const homeserverIp = await dockerIp({ containerId: homeserver.serverId }); console.log(new Date(), "postgres container up"); const waitTimeMillis = 30000; @@ -81,7 +81,7 @@ async function proxyStart(dockerTag: string, synapse: SynapseInstance): Promise< "-e", "SYNCV3_SECRET=bwahahaha", "-e", - `SYNCV3_SERVER=http://${synapseIp}:8008`, + `SYNCV3_SERVER=http://${homeserverIp}:8008`, "-e", `SYNCV3_DB=user=postgres dbname=postgres password=${PG_PASSWORD} host=${postgresIp} sslmode=disable`, ], diff --git a/cypress/plugins/synapsedocker/index.ts b/cypress/plugins/synapsedocker/index.ts index 4a864eb56d..3615e4d511 100644 --- a/cypress/plugins/synapsedocker/index.ts +++ b/cypress/plugins/synapsedocker/index.ts @@ -25,29 +25,18 @@ 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"; // A cypress plugins to add command to start & stop synapses in // docker with preset templates. -interface SynapseConfig { - configDir: string; - registrationSecret: string; - // Synapse must be configured with its public_baseurl so we have to allocate a port & url at this stage - baseUrl: string; - port: number; -} - -export interface SynapseInstance extends SynapseConfig { - synapseId: string; -} - -const synapses = new Map(); +const synapses = new Map(); function randB64Bytes(numBytes: number): string { return crypto.randomBytes(numBytes).toString("base64").replace(/=*$/, ""); } -async function cfgDirFromTemplate(template: string): Promise { +async function cfgDirFromTemplate(template: string): Promise { const templateDir = path.join(__dirname, "templates", template); const stats = await fse.stat(templateDir); @@ -94,7 +83,7 @@ async function cfgDirFromTemplate(template: string): Promise { // Start a synapse instance: the template must be the name of // one of the templates in the cypress/plugins/synapsedocker/templates // directory -async function synapseStart(template: string): Promise { +async function synapseStart(template: string): Promise { const synCfg = await cfgDirFromTemplate(template); console.log(`Starting synapse with config dir ${synCfg.configDir}...`); @@ -103,7 +92,7 @@ async function synapseStart(template: string): Promise { image: "matrixdotorg/synapse:develop", containerName: `react-sdk-cypress-synapse`, params: ["--rm", "-v", `${synCfg.configDir}:/data`, "-p", `${synCfg.port}:8008/tcp`], - cmd: "run", + cmd: ["run"], }); console.log(`Started synapse with id ${synapseId} on port ${synCfg.port}.`); @@ -125,7 +114,7 @@ async function synapseStart(template: string): Promise { ], }); - const synapse: SynapseInstance = { synapseId, ...synCfg }; + const synapse: HomeserverInstance = { serverId: synapseId, ...synCfg }; synapses.set(synapseId, synapse); return synapse; } diff --git a/cypress/plugins/utils/homeserver.ts b/cypress/plugins/utils/homeserver.ts new file mode 100644 index 0000000000..d6a4de0411 --- /dev/null +++ b/cypress/plugins/utils/homeserver.ts @@ -0,0 +1,28 @@ +/* +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/support/bot.ts b/cypress/support/bot.ts index 750cd566bb..745ec4002c 100644 --- a/cypress/support/bot.ts +++ b/cypress/support/bot.ts @@ -17,8 +17,8 @@ limitations under the License. /// import type { ISendEventResponse, MatrixClient, Room } from "matrix-js-sdk/src/matrix"; -import { SynapseInstance } from "../plugins/synapsedocker"; -import { Credentials } from "./synapse"; +import { HomeserverInstance } from "../plugins/utils/homeserver"; +import { Credentials } from "./homeserver"; import Chainable = Cypress.Chainable; interface CreateBotOpts { @@ -61,19 +61,19 @@ declare global { interface Chainable { /** * Returns a new Bot instance - * @param synapse the instance on which to register the bot user + * @param homeserver the instance on which to register the bot user * @param opts create bot options */ - getBot(synapse: SynapseInstance, opts: CreateBotOpts): Chainable; + getBot(homeserver: HomeserverInstance, opts: CreateBotOpts): Chainable; /** * Returns a new Bot instance logged in as an existing user - * @param synapse the instance on which to register the bot user + * @param homeserver the instance on which to register the bot user * @param username the username for the bot to log in with * @param password the password for the bot to log in with * @param opts create bot options */ loginBot( - synapse: SynapseInstance, + homeserver: HomeserverInstance, username: string, password: string, opts: CreateBotOpts, @@ -102,7 +102,7 @@ declare global { } function setupBotClient( - synapse: SynapseInstance, + homeserver: HomeserverInstance, credentials: Credentials, opts: CreateBotOpts, ): Chainable { @@ -119,7 +119,7 @@ function setupBotClient( }; const cli = new win.matrixcs.MatrixClient({ - baseUrl: synapse.baseUrl, + baseUrl: homeserver.baseUrl, userId: credentials.userId, deviceId: credentials.deviceId, accessToken: credentials.accessToken, @@ -160,15 +160,15 @@ function setupBotClient( }); } -Cypress.Commands.add("getBot", (synapse: SynapseInstance, opts: CreateBotOpts): Chainable => { +Cypress.Commands.add("getBot", (homeserver: HomeserverInstance, opts: CreateBotOpts): Chainable => { opts = Object.assign({}, defaultCreateBotOptions, opts); const username = Cypress._.uniqueId(opts.userIdPrefix); const password = Cypress._.uniqueId("password_"); return cy - .registerUser(synapse, username, password, opts.displayName) + .registerUser(homeserver, username, password, opts.displayName) .then((credentials) => { cy.log(`Registered bot user ${username} with displayname ${opts.displayName}`); - return setupBotClient(synapse, credentials, opts); + return setupBotClient(homeserver, credentials, opts); }) .then((client): Chainable => { Object.assign(client, { __cypress_password: password }); @@ -178,10 +178,15 @@ Cypress.Commands.add("getBot", (synapse: SynapseInstance, opts: CreateBotOpts): Cypress.Commands.add( "loginBot", - (synapse: SynapseInstance, username: string, password: string, opts: CreateBotOpts): Chainable => { + ( + homeserver: HomeserverInstance, + username: string, + password: string, + opts: CreateBotOpts, + ): Chainable => { opts = Object.assign({}, defaultCreateBotOptions, { bootstrapCrossSigning: false }, opts); - return cy.loginUser(synapse, username, password).then((credentials) => { - return setupBotClient(synapse, credentials, opts); + return cy.loginUser(homeserver, username, password).then((credentials) => { + return setupBotClient(homeserver, credentials, opts); }); }, ); diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index 4470c2192e..10014a4bd6 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -19,7 +19,7 @@ limitations under the License. import "@percy/cypress"; import "cypress-real-events"; -import "./synapse"; +import "./homeserver"; import "./login"; import "./labs"; import "./client"; diff --git a/cypress/support/synapse.ts b/cypress/support/homeserver.ts similarity index 63% rename from cypress/support/synapse.ts rename to cypress/support/homeserver.ts index 69e05969cb..8510e3640a 100644 --- a/cypress/support/synapse.ts +++ b/cypress/support/homeserver.ts @@ -1,5 +1,5 @@ /* -Copyright 2022 The Matrix.org Foundation C.I.C. +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. @@ -20,34 +20,34 @@ import * as crypto from "crypto"; import Chainable = Cypress.Chainable; import AUTWindow = Cypress.AUTWindow; -import { SynapseInstance } from "../plugins/synapsedocker"; +import { HomeserverInstance } from "../plugins/utils/homeserver"; declare global { // eslint-disable-next-line @typescript-eslint/no-namespace namespace Cypress { interface Chainable { /** - * Start a synapse instance with a given config template. - * @param template path to template within cypress/plugins/synapsedocker/template/ directory. + * Start a homeserver instance with a given config template. + * @param template path to template within cypress/plugins/{homeserver}docker/template/ directory. */ - startSynapse(template: string): Chainable; + startHomeserver(template: string): Chainable; /** - * Custom command wrapping task:synapseStop whilst preventing uncaught exceptions - * for if Synapse stopping races with the app's background sync loop. - * @param synapse the synapse instance returned by startSynapse + * Custom command wrapping task:{homeserver}Stop whilst preventing uncaught exceptions + * for if Homeserver stopping races with the app's background sync loop. + * @param homeserver the homeserver instance returned by start{Homeserver} */ - stopSynapse(synapse: SynapseInstance): Chainable; + stopHomeserver(homeserver: HomeserverInstance): Chainable; /** - * Register a user on the given Synapse using the shared registration secret. - * @param synapse the synapse instance returned by startSynapse + * Register a user on the given Homeserver using the shared registration secret. + * @param homeserver the homeserver instance returned by start{Homeserver} * @param username the username of the user to register * @param password the password of the user to register * @param displayName optional display name to set on the newly registered user */ registerUser( - synapse: SynapseInstance, + homeserver: HomeserverInstance, username: string, password: string, displayName?: string, @@ -56,16 +56,18 @@ declare global { } } -function startSynapse(template: string): Chainable { - return cy.task("synapseStart", template); +function startHomeserver(template: string): Chainable { + const homeserverName = Cypress.env("HOMESERVER"); + return cy.task(homeserverName + "Start", template); } -function stopSynapse(synapse?: SynapseInstance): Chainable { - if (!synapse) return; - // Navigate away from app to stop the background network requests which will race with Synapse shutting down +function stopHomeserver(homeserver?: HomeserverInstance): Chainable { + if (!homeserver) return; + // Navigate away from app to stop the background network requests which will race with Homeserver shutting down return cy.window({ log: false }).then((win) => { win.location.href = "about:blank"; - cy.task("synapseStop", synapse.synapseId); + const homeserverName = Cypress.env("HOMESERVER"); + cy.task(homeserverName + "Stop", homeserver.serverId); }); } @@ -77,12 +79,12 @@ export interface Credentials { } function registerUser( - synapse: SynapseInstance, + homeserver: HomeserverInstance, username: string, password: string, displayName?: string, ): Chainable { - const url = `${synapse.baseUrl}/_synapse/admin/v1/register`; + const url = `${homeserver.baseUrl}/_synapse/admin/v1/register`; return cy .then(() => { // get a nonce @@ -91,7 +93,7 @@ function registerUser( .then((response) => { const { nonce } = response.body; const mac = crypto - .createHmac("sha1", synapse.registrationSecret) + .createHmac("sha1", homeserver.registrationSecret) .update(`${nonce}\0${username}\0${password}\0notadmin`) .digest("hex"); @@ -121,6 +123,6 @@ function registerUser( })); } -Cypress.Commands.add("startSynapse", startSynapse); -Cypress.Commands.add("stopSynapse", stopSynapse); +Cypress.Commands.add("startHomeserver", startHomeserver); +Cypress.Commands.add("stopHomeserver", stopHomeserver); Cypress.Commands.add("registerUser", registerUser); diff --git a/cypress/support/login.ts b/cypress/support/login.ts index 338da2f9db..308c1ea639 100644 --- a/cypress/support/login.ts +++ b/cypress/support/login.ts @@ -17,7 +17,7 @@ limitations under the License. /// import Chainable = Cypress.Chainable; -import { SynapseInstance } from "../plugins/synapsedocker"; +import { HomeserverInstance } from "../plugins/utils/homeserver"; export interface UserCredentials { accessToken: string; @@ -41,7 +41,7 @@ declare global { * useed. */ initTestUser( - synapse: SynapseInstance, + homeserver: HomeserverInstance, displayName: string, prelaunchFn?: () => void, userIdPrefix?: string, @@ -52,7 +52,7 @@ declare global { * @param username login username * @param password login password */ - loginUser(synapse: SynapseInstance, username: string, password: string): Chainable; + loginUser(synapse: HomeserverInstance, username: string, password: string): Chainable; } } } @@ -60,8 +60,8 @@ declare global { // eslint-disable-next-line max-len Cypress.Commands.add( "loginUser", - (synapse: SynapseInstance, username: string, password: string): Chainable => { - const url = `${synapse.baseUrl}/_matrix/client/r0/login`; + (homeserver: HomeserverInstance, username: string, password: string): Chainable => { + const url = `${homeserver.baseUrl}/_matrix/client/r0/login`; return cy .request<{ access_token: string; @@ -95,7 +95,7 @@ Cypress.Commands.add( Cypress.Commands.add( "initTestUser", ( - synapse: SynapseInstance, + homeserver: HomeserverInstance, displayName: string, prelaunchFn?: () => void, userIdPrefix = "user_", @@ -112,15 +112,15 @@ Cypress.Commands.add( const username = Cypress._.uniqueId(userIdPrefix); const password = Cypress._.uniqueId("password_"); return cy - .registerUser(synapse, username, password, displayName) + .registerUser(homeserver, username, password, displayName) .then(() => { - return cy.loginUser(synapse, username, password); + return cy.loginUser(homeserver, username, password); }) .then((response) => { cy.log(`Registered test user ${username} with displayname ${displayName}`); cy.window({ log: false }).then((win) => { // Seed the localStorage with the required credentials - win.localStorage.setItem("mx_hs_url", synapse.baseUrl); + win.localStorage.setItem("mx_hs_url", homeserver.baseUrl); win.localStorage.setItem("mx_user_id", response.userId); win.localStorage.setItem("mx_access_token", response.accessToken); win.localStorage.setItem("mx_device_id", response.deviceId); diff --git a/cypress/support/proxy.ts b/cypress/support/proxy.ts index 97480bdbe1..b40584ec7f 100644 --- a/cypress/support/proxy.ts +++ b/cypress/support/proxy.ts @@ -19,7 +19,7 @@ limitations under the License. import Chainable = Cypress.Chainable; import AUTWindow = Cypress.AUTWindow; import { ProxyInstance } from "../plugins/sliding-sync"; -import { SynapseInstance } from "../plugins/synapsedocker"; +import { HomeserverInstance } from "../plugins/utils/homeserver"; declare global { // eslint-disable-next-line @typescript-eslint/no-namespace @@ -27,9 +27,9 @@ declare global { interface Chainable { /** * Start a sliding sync proxy instance. - * @param synapse the synapse instance returned by startSynapse + * @param homeserver the homeserver instance returned by startHomeserver */ - startProxy(synapse: SynapseInstance): Chainable; + startProxy(homeserver: HomeserverInstance): Chainable; /** * Custom command wrapping task:proxyStop whilst preventing uncaught exceptions @@ -41,13 +41,13 @@ declare global { } } -function startProxy(synapse: SynapseInstance): Chainable { - return cy.task("proxyStart", synapse); +function startProxy(homeserver: HomeserverInstance): Chainable { + return cy.task("proxyStart", homeserver); } function stopProxy(proxy?: ProxyInstance): Chainable { if (!proxy) return; - // Navigate away from app to stop the background network requests which will race with Synapse shutting down + // Navigate away from app to stop the background network requests which will race with Homeserver shutting down return cy.window({ log: false }).then((win) => { win.location.href = "about:blank"; cy.task("proxyStop", proxy); diff --git a/docs/cypress.md b/docs/cypress.md index 4abac65bdf..b354b693cc 100644 --- a/docs/cypress.md +++ b/docs/cypress.md @@ -21,7 +21,7 @@ be tested. When running Cypress tests yourself, the standard `yarn start` from t element-web project is fine: leave it running it a different terminal as you would when developing. -The tests use Docker to launch Synapse instances to test against, so you'll also +The tests use Docker to launch Homeserver (Synapse or Dendrite) instances to test against, so you'll also need to have Docker installed and working in order to run the Cypress tests. There are a few different ways to run the tests yourself. The simplest is to run: @@ -58,10 +58,10 @@ Synapse can be launched with different configurations in order to test element in different configurations. `cypress/plugins/synapsedocker/templates` contains template configuration files for each different configuration. -Each test suite can then launch whatever Synapse instances it needs it whatever +Each test suite can then launch whatever Synapse instances it needs in whatever configurations. -Note that although tests should stop the Synapse instances after running and the +Note that although tests should stop the Homeserver instances after running and the plugin also stop any remaining instances after all tests have run, it is possible to be left with some stray containers if, for example, you terminate a test such that the `after()` does not run and also exit Cypress uncleanly. All the containers @@ -82,29 +82,29 @@ a read. ### Getting a Synapse The key difference is in starting Synapse instances. Tests use this plugin via -`cy.startSynapse()` to provide a Synapse instance to log into: +`cy.startHomeserver()` to provide a Homeserver instance to log into: ```javascript -cy.startSynapse("consent").then((result) => { - synapse = result; +cy.startHomeserver("consent").then((result) => { + homeserver = result; }); ``` -This returns an object with information about the Synapse instance, including what port +This returns an object with information about the Homeserver instance, including what port it was started on and the ID that needs to be passed to shut it down again. It also returns the registration shared secret (`registrationSecret`) that can be used to -register users via the REST API. The Synapse has been ensured ready to go by awaiting +register users via the REST API. The Homeserver has been ensured ready to go by awaiting its internal health-check. -Synapse instances should be reasonably cheap to start (you may see the first one take a +Homeserver instances should be reasonably cheap to start (you may see the first one take a while as it pulls the Docker image), so it's generally expected that tests will start a -Synapse instance for each test suite, i.e. in `before()`, and then tear it down in `after()`. +Homeserver instance for each test suite, i.e. in `before()`, and then tear it down in `after()`. -To later destroy your Synapse you should call `stopSynapse`, passing the SynapseInstance +To later destroy your Homeserver you should call `stopHomeserver`, passing the HomeserverInstance object you received when starting it. ```javascript -cy.stopSynapse(synapse); +cy.stopHomeserver(homeserver); ``` ### Synapse Config Templates @@ -131,10 +131,10 @@ in a template can be referenced in the config as `/data/foo.html`. There exists a basic utility to start the app with a random user already logged in: ```javascript -cy.initTestUser(synapse, "Jeff"); +cy.initTestUser(homeserver, "Jeff"); ``` -It takes the SynapseInstance you received from `startSynapse` and a display name for your test user. +It takes the HomeserverInstance you received from `startHomeserver` and a display name for your test user. This custom command will register a random userId using the registrationSecret with a random password and the given display name. The returned Chainable will contain details about the credentials for if they are needed for User-Interactive Auth or similar but localStorage will already be seeded with them @@ -147,11 +147,11 @@ but the signature can be maintained for simpler maintenance. Many tests will also want to start with the client in a room, ready to send & receive messages. Best way to do this may be to get an access token for the user and use this to create a room with the REST -API before logging the user in. You can make use of `cy.getBot(synapse)` and `cy.getClient()` to do this. +API before logging the user in. You can make use of `cy.getBot(homeserver)` and `cy.getClient()` to do this. ### Convenience APIs -We should probably end up with convenience APIs that wrap the synapse creation, logging in and room +We should probably end up with convenience APIs that wrap the homeserver creation, logging in and room creation that can be called to set up tests. ### Using matrix-js-sdk