diff --git a/.github/workflows/cypress.yaml b/.github/workflows/cypress.yaml index d114217f5c..90b1827bce 100644 --- a/.github/workflows/cypress.yaml +++ b/.github/workflows/cypress.yaml @@ -5,6 +5,9 @@ on: workflows: ["Element Web - Build"] types: - completed +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ workflow_run.event == 'pull_request' }} jobs: prepare: name: Prepare diff --git a/cypress/e2e/crypto/decryption-failure.spec.ts b/cypress/e2e/crypto/decryption-failure.spec.ts index 13e3c56aba..20f748494a 100644 --- a/cypress/e2e/crypto/decryption-failure.spec.ts +++ b/cypress/e2e/crypto/decryption-failure.spec.ts @@ -118,7 +118,12 @@ describe("Decryption Failure Bar", () => { "Verify this device to access all messages", ); - cy.percySnapshot("DecryptionFailureBar prompts user to verify"); + cy.get(".mx_DecryptionFailureBar").percySnapshotElement( + "DecryptionFailureBar prompts user to verify", + { + widths: [320, 640], + }, + ); cy.contains(".mx_DecryptionFailureBar_button", "Resend key requests").should("not.exist"); cy.contains(".mx_DecryptionFailureBar_button", "Verify").click(); @@ -146,8 +151,11 @@ describe("Decryption Failure Bar", () => { "Open another device to load encrypted messages", ); - cy.percySnapshot( + cy.get(".mx_DecryptionFailureBar").percySnapshotElement( "DecryptionFailureBar prompts user to open another device, with Resend Key Requests button", + { + widths: [320, 640], + }, ); cy.intercept("/_matrix/client/r0/sendToDevice/m.room_key_request/*").as("keyRequest"); @@ -155,8 +163,11 @@ describe("Decryption Failure Bar", () => { cy.wait("@keyRequest"); cy.contains(".mx_DecryptionFailureBar_button", "Resend key requests").should("not.exist"); - cy.percySnapshot( + cy.get(".mx_DecryptionFailureBar").percySnapshotElement( "DecryptionFailureBar prompts user to open another device, " + "without Resend Key Requests button", + { + widths: [320, 640], + }, ); }, ); @@ -177,7 +188,9 @@ describe("Decryption Failure Bar", () => { "Reset your keys to prevent future decryption errors", ); - cy.percySnapshot("DecryptionFailureBar prompts user to reset keys"); + cy.get(".mx_DecryptionFailureBar").percySnapshotElement("DecryptionFailureBar prompts user to reset keys", { + widths: [320, 640], + }); cy.contains(".mx_DecryptionFailureBar_button", "Reset").click(); @@ -196,7 +209,12 @@ describe("Decryption Failure Bar", () => { "Some messages could not be decrypted", ); - cy.percySnapshot("DecryptionFailureBar displays general message with no call to action"); + cy.get(".mx_DecryptionFailureBar").percySnapshotElement( + "DecryptionFailureBar displays general message with no call to action", + { + widths: [320, 640], + }, + ); }, ); @@ -210,7 +228,10 @@ describe("Decryption Failure Bar", () => { cy.get(".mx_DecryptionFailureBar").should("exist"); cy.get(".mx_DecryptionFailureBar .mx_Spinner").should("exist"); - cy.percySnapshot("DecryptionFailureBar displays loading spinner"); + cy.get(".mx_DecryptionFailureBar").percySnapshotElement("DecryptionFailureBar displays loading spinner", { + allowSpinners: true, + widths: [320, 640], + }); cy.wait(5000); cy.get(".mx_DecryptionFailureBar .mx_Spinner").should("not.exist"); diff --git a/cypress/e2e/timeline/timeline.spec.ts b/cypress/e2e/timeline/timeline.spec.ts index bef1cd0393..aa5a94a6dd 100644 --- a/cypress/e2e/timeline/timeline.spec.ts +++ b/cypress/e2e/timeline/timeline.spec.ts @@ -159,8 +159,8 @@ describe("Timeline", () => { ".mx_GenericEventListSummary_summary", "created and configured the room.", ).should("exist"); - cy.get(".mx_Spinner").should("not.exist"); - cy.percySnapshot("Configured room on IRC layout"); + + cy.get(".mx_MainSplit").percySnapshotElement("Configured room on IRC layout"); }); it("should add inline start margin to an event line on IRC layout", () => { @@ -185,11 +185,12 @@ describe("Timeline", () => { .should("have.css", "margin-inline-start", "104px") .should("have.css", "inset-inline-start", "0px"); - cy.get(".mx_Spinner").should("not.exist"); // Exclude timestamp from snapshot const percyCSS = - ".mx_RoomView_body .mx_EventTile_info .mx_MessageTimestamp " + "{ visibility: hidden !important; }"; - cy.percySnapshot("Event line with inline start margin on IRC layout", { percyCSS }); + ".mx_RoomView_body .mx_EventTile_info .mx_MessageTimestamp { visibility: hidden !important; }"; + cy.get(".mx_MainSplit").percySnapshotElement("Event line with inline start margin on IRC layout", { + percyCSS, + }); cy.checkA11y(); }); @@ -213,8 +214,7 @@ describe("Timeline", () => { cy.get(".mx_RoomView_body .mx_EventTile_info .mx_MessageTimestamp").click(); // Exclude timestamp from snapshot - const percyCSS = - ".mx_RoomView_body .mx_EventTile .mx_MessageTimestamp " + "{ visibility: hidden !important; }"; + const percyCSS = ".mx_RoomView_body .mx_EventTile .mx_MessageTimestamp { visibility: hidden !important; }"; // should not add inline start padding to a hidden event line on IRC layout cy.setSettingValue("layout", null, SettingLevel.DEVICE, Layout.IRC); @@ -223,14 +223,20 @@ describe("Timeline", () => { "padding-inline-start", "0px", ); - cy.percySnapshot("Hidden event line with zero padding on IRC layout", { percyCSS }); + + cy.get(".mx_MainSplit").percySnapshotElement("Hidden event line with zero padding on IRC layout", { + percyCSS, + }); // should add inline start padding to a hidden event line on modern layout cy.setSettingValue("layout", null, SettingLevel.DEVICE, Layout.Group); cy.get(".mx_EventTile[data-layout=group].mx_EventTile_info .mx_EventTile_line") // calc(var(--EventTile_group_line-spacing-inline-start) + 20px) = 64 + 20 = 84px .should("have.css", "padding-inline-start", "84px"); - cy.percySnapshot("Hidden event line with padding on modern layout", { percyCSS }); + + cy.get(".mx_MainSplit").percySnapshotElement("Hidden event line with padding on modern layout", { + percyCSS, + }); }); it("should click top left of view source event toggle", () => { @@ -329,7 +335,12 @@ describe("Timeline", () => { cy.wait("@mxc"); cy.checkA11y(); + + // Exclude timestamp from snapshot + const percyCSS = + ".mx_RoomView_body .mx_EventTile_info .mx_MessageTimestamp { visibility: hidden !important; }"; cy.get(".mx_EventTile_last").percySnapshotElement("URL Preview", { + percyCSS, widths: [800, 400], }); }); diff --git a/cypress/support/percy.ts b/cypress/support/percy.ts index f5e30a58fc..b0f5c9f7c7 100644 --- a/cypress/support/percy.ts +++ b/cypress/support/percy.ts @@ -22,6 +22,7 @@ declare global { namespace Cypress { interface SnapshotOptions extends PercySnapshotOptions { domTransformation?: (documentClone: Document) => void; + allowSpinners?: boolean; } interface Chainable { @@ -38,6 +39,10 @@ declare global { } Cypress.Commands.add("percySnapshotElement", { prevSubject: "element" }, (subject, name, options) => { + if (!options?.allowSpinners) { + // Await spinners to vanish + cy.get(".mx_Spinner").should("not.exist"); + } cy.percySnapshot(name, { domTransformation: (documentClone) => scope(documentClone, subject.selector), ...options,