From 40aa5ad0fb097db6fffc139e8ff8d32c030b192a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 27 Nov 2023 10:00:16 +0000 Subject: [PATCH] Migrate analytics-toast.spec.ts from Cypress to Playwright (#11939) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- cypress/e2e/toasts/analytics-toast.spec.ts | 98 ------------------- playwright/e2e/toasts/analytics-toast.spec.ts | 53 ++++++++++ playwright/element-web-test.ts | 6 ++ playwright/pages/toasts.ts | 60 ++++++++++++ 4 files changed, 119 insertions(+), 98 deletions(-) delete mode 100644 cypress/e2e/toasts/analytics-toast.spec.ts create mode 100644 playwright/e2e/toasts/analytics-toast.spec.ts create mode 100644 playwright/pages/toasts.ts diff --git a/cypress/e2e/toasts/analytics-toast.spec.ts b/cypress/e2e/toasts/analytics-toast.spec.ts deleted file mode 100644 index 4cc8baa838..0000000000 --- a/cypress/e2e/toasts/analytics-toast.spec.ts +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright 2022 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -/// - -import { HomeserverInstance } from "../../plugins/utils/homeserver"; -import Chainable = Cypress.Chainable; - -function assertNoToasts(): void { - cy.get(".mx_Toast_toast").should("not.exist"); -} - -function getToast(expectedTitle: string): Chainable { - return cy.contains(".mx_Toast_toast h2", expectedTitle).should("exist").closest(".mx_Toast_toast"); -} - -function acceptToast(expectedTitle: string): void { - getToast(expectedTitle).within(() => { - cy.get(".mx_Toast_buttons .mx_AccessibleButton_kind_primary").click(); - }); -} - -function rejectToast(expectedTitle: string): void { - getToast(expectedTitle).within(() => { - cy.get(".mx_Toast_buttons .mx_AccessibleButton_kind_danger_outline").click(); - }); -} - -describe("Analytics Toast", () => { - let homeserver: HomeserverInstance; - - afterEach(() => { - cy.stopHomeserver(homeserver); - }); - - it("should not show an analytics toast if config has nothing about posthog", () => { - cy.intercept("/config.json?cachebuster=*", (req) => { - req.continue((res) => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { posthog, ...body } = res.body; - res.send(200, body); - }); - }); - - cy.startHomeserver("default").then((data) => { - homeserver = data; - cy.initTestUser(homeserver, "Tod"); - }); - - rejectToast("Notifications"); - assertNoToasts(); - }); - - describe("with posthog enabled", () => { - beforeEach(() => { - cy.intercept("/config.json?cachebuster=*", (req) => { - req.continue((res) => { - res.send(200, { - ...res.body, - posthog: { - project_api_key: "foo", - api_host: "bar", - }, - }); - }); - }); - - cy.startHomeserver("default").then((data) => { - homeserver = data; - cy.initTestUser(homeserver, "Tod"); - rejectToast("Notifications"); - }); - }); - - it("should show an analytics toast which can be accepted", () => { - acceptToast("Help improve Element"); - assertNoToasts(); - }); - - it("should show an analytics toast which can be rejected", () => { - rejectToast("Help improve Element"); - assertNoToasts(); - }); - }); -}); diff --git a/playwright/e2e/toasts/analytics-toast.spec.ts b/playwright/e2e/toasts/analytics-toast.spec.ts new file mode 100644 index 0000000000..2ce2f82962 --- /dev/null +++ b/playwright/e2e/toasts/analytics-toast.spec.ts @@ -0,0 +1,53 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { test } from "../../element-web-test"; + +test.describe("Analytics Toast", () => { + test.use({ + displayName: "Tod", + }); + + test("should not show an analytics toast if config has nothing about posthog", async ({ user, toasts }) => { + await toasts.rejectToast("Notifications"); + await toasts.assertNoToasts(); + }); + + test.describe("with posthog enabled", () => { + test.use({ + config: { + posthog: { + project_api_key: "foo", + api_host: "bar", + }, + }, + }); + + test.beforeEach(async ({ user, toasts }) => { + await toasts.rejectToast("Notifications"); + }); + + test("should show an analytics toast which can be accepted", async ({ user, toasts }) => { + await toasts.acceptToast("Help improve Element"); + await toasts.assertNoToasts(); + }); + + test("should show an analytics toast which can be rejected", async ({ user, toasts }) => { + await toasts.rejectToast("Help improve Element"); + await toasts.assertNoToasts(); + }); + }); +}); diff --git a/playwright/element-web-test.ts b/playwright/element-web-test.ts index 51cb003489..ee1ae67f3a 100644 --- a/playwright/element-web-test.ts +++ b/playwright/element-web-test.ts @@ -24,6 +24,7 @@ import { Credentials, HomeserverInstance, StartHomeserverOpts } from "./plugins/ import { Synapse } from "./plugins/synapse"; import { Instance } from "./plugins/mailhog"; import { OAuthServer } from "./plugins/oauth_server"; +import { Toasts } from "./pages/toasts"; const CONFIG_JSON: Partial = { // This is deliberately quite a minimal config.json, so that we can test that the default settings @@ -60,6 +61,7 @@ export const test = base.extend< }; displayName?: string; mailhog?: { api: mailhog.API; instance: Instance }; + toasts: Toasts; } >({ crypto: ["legacy", { option: true }], @@ -147,6 +149,10 @@ export const test = base.extend< expect(results.violations).toEqual([]); }), + + toasts: async ({ page }, use) => { + await use(new Toasts(page)); + }, }); test.use({}); diff --git a/playwright/pages/toasts.ts b/playwright/pages/toasts.ts new file mode 100644 index 0000000000..0785f33c23 --- /dev/null +++ b/playwright/pages/toasts.ts @@ -0,0 +1,60 @@ +/* +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 { Page, expect, Locator } from "@playwright/test"; + +export class Toasts { + public constructor(private readonly page: Page) {} + + /** + * Assert that a toast with the given title exists, and return it + * + * @param expectedTitle - Expected title of the toast + * @returns the Locator for the matching toast + */ + public async getToast(expectedTitle: string): Promise { + const toast = this.page.locator(".mx_Toast_toast", { hasText: expectedTitle }).first(); + await expect(toast).toBeVisible(); + return toast; + } + + /** + * Assert that no toasts exist + */ + public async assertNoToasts(): Promise { + await expect(this.page.locator(".mx_Toast_toast")).not.toBeVisible(); + } + + /** + * Accept a toast with the given title, only works for the first toast in the stack + * + * @param expectedTitle - Expected title of the toast + */ + public async acceptToast(expectedTitle: string): Promise { + const toast = await this.getToast(expectedTitle); + await toast.locator(".mx_Toast_buttons .mx_AccessibleButton_kind_primary").click(); + } + + /** + * Reject a toast with the given title, only works for the first toast in the stack + * + * @param expectedTitle - Expected title of the toast + */ + public async rejectToast(expectedTitle: string): Promise { + const toast = await this.getToast(expectedTitle); + await toast.locator(".mx_Toast_buttons .mx_AccessibleButton_kind_danger_outline").click(); + } +}