Skip to content

Commit

Permalink
#9154: add E2E runtime test
Browse files Browse the repository at this point in the history
  • Loading branch information
twschiller committed Sep 14, 2024
1 parent 8d201f6 commit 936f4c7
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 3 deletions.
95 changes: 95 additions & 0 deletions end-to-end-tests/tests/runtime/modVariables/variableSync.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (C) 2024 PixieBrix, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { test, expect } from "../../../fixtures/testBase";
import { ActivateModPage } from "../../../pageObjects/extensionConsole/modsPage";
// @ts-expect-error -- https://youtrack.jetbrains.com/issue/AQUA-711/Provide-a-run-configuration-for-Playwright-tests-in-specs-with-fixture-imports-only
import { type Frame, type Page, test as base } from "@playwright/test";
import { getSidebarPage } from "../../../utils";

test.describe("Mod Variable Sync", () => {
test("session variable cross-tab sync", async ({ page, extensionId }) => {
await test.step("activate mod", async () => {
const modId = "@e2e-testing/state-sync";
const modActivationPage = new ActivateModPage(page, extensionId, modId);
await modActivationPage.goto();
await modActivationPage.clickActivateAndWaitForModsPageRedirect();

await page.goto("/frames-builder.html");
});

// Waiting for the mod to be ready before opening sidebar
await expect(page.getByText("Local: 0")).toBeVisible();

// The mod contains a trigger to open the sidebar on h1
await page.click("h1");
const sideBarPage = await getSidebarPage(page, extensionId);
await expect(
sideBarPage.getByRole("heading", { name: "State Sync Demo" }),
).toBeVisible();

await test.step("verify same tab increment", async () => {
await sideBarPage.getByRole("button", { name: "Increment" }).click();

await expect(sideBarPage.getByText("Sync: 1")).toBeVisible();
await expect(sideBarPage.getByText("Local: 1")).toBeVisible();

await expect(page.getByText("Sync: 1")).toBeVisible();
await expect(page.getByText("Local: 1")).toBeVisible();

const frameLocator = page.frameLocator("iframe");
await expect(frameLocator.getByText("Sync: 1")).toBeVisible();
await expect(frameLocator.getByText("Local: 0")).toBeVisible();
});

// Close the sidebar, because getSidebarPage currently can't distinguish between multiple sidebars
await sideBarPage.getByRole("button", { name: "Close" }).click();
await sideBarPage.getByRole("button", { name: "Close" }).click();

const otherPage = await page.context().newPage();
await otherPage.goto(page.url());

// Waiting for the mod to be ready before opening sidebar
await expect(otherPage.getByText("Local: 0")).toBeVisible();

await otherPage.click("h1");
const otherSideBarPage = await getSidebarPage(otherPage, extensionId);
await expect(
otherSideBarPage.getByRole("heading", { name: "State Sync Demo" }),
).toBeVisible();

await test.step("verify cross tab increment", async () => {
// Should be available on first run of the panel
await expect(otherSideBarPage.getByText("Sync: 1")).toBeVisible();
await expect(otherSideBarPage.getByText("Local: ")).toBeVisible();

await otherSideBarPage.getByRole("button", { name: "Increment" }).click();

await expect(otherSideBarPage.getByText("Sync: 2")).toBeVisible();
await expect(otherSideBarPage.getByText("Local: 1")).toBeVisible();

// Should automatically sync to the original tab
await expect(page.getByText("Sync: 2")).toBeVisible();
await expect(page.getByText("Local: 1")).toBeVisible();

const frameLocator = page.frameLocator("iframe");
await expect(frameLocator.getByText("Sync: 2")).toBeVisible();
// Local variable doesn't exist in the frame
await expect(frameLocator.getByText("Local: 0")).toBeVisible();
});
});
});
14 changes: 11 additions & 3 deletions end-to-end-tests/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,18 @@ export async function runModViaQuickBar(page: Page, modName: string) {
}

function findSidebarPage(page: Page, extensionId: string): Page | undefined {
return page
const matches = page
.context()
.pages()
.find((value) =>
.filter((value) =>
value.url().startsWith(`chrome-extension://${extensionId}/sidebar.html`),
);

if (matches.length > 1) {
throw new Error("Multiple sidebar pages found");
}

return matches[0];
}

/**
Expand All @@ -111,10 +117,12 @@ export function isSidebarOpen(page: Page, extensionId: string): boolean {
/**
* Finds the Pixiebrix sidebar page/frame.
*
* NOTE: returns the sidebar found, not necessarily the one for the provided page.
*
* Automatically clicks "OK" on the dialog that appears if the sidebar requires a user gesture to open
* This is a Page contained in the browser sidepanel window.
*
* @throws {Error} if the sidebar is not available
* @throws {Error} if the sidebar is not available or multiple pages have the sidebar open
*/
export async function getSidebarPage(
page: Page,
Expand Down

0 comments on commit 936f4c7

Please sign in to comment.