Test theme toggle feature (#212)

* WIP

* Add test on theme toggle

* Add teardown logic

* Cleanup menu setting
This commit is contained in:
Chenlei Hu
2024-07-23 17:56:35 -04:00
committed by GitHub
parent 1b7db43f8a
commit 5b4e96f6c5
4 changed files with 120 additions and 25 deletions

View File

@@ -34,6 +34,37 @@ class ComfyNodeSearchBox {
}
}
class ComfyMenu {
public readonly themeToggleButton: Locator;
constructor(public readonly page: Page) {
this.themeToggleButton = page.locator(".comfy-vue-theme-toggle");
}
async toggleTheme() {
await this.themeToggleButton.click();
await this.page.evaluate(() => {
return new Promise((resolve) => {
window["app"].ui.settings.addEventListener(
"Comfy.ColorPalette.change",
resolve,
{ once: true }
);
setTimeout(resolve, 5000);
});
});
}
async getThemeId() {
return await this.page.evaluate(async () => {
return await window["app"].ui.settings.getSettingValue(
"Comfy.ColorPalette"
);
});
}
}
export class ComfyPage {
public readonly url: string;
// All canvas position operations are based on default view of canvas.
@@ -46,8 +77,9 @@ export class ComfyPage {
// Inputs
public readonly workflowUploadInput: Locator;
// Search box
// Components
public readonly searchBox: ComfyNodeSearchBox;
public readonly menu: ComfyMenu;
constructor(public readonly page: Page) {
this.url = process.env.PLAYWRIGHT_TEST_URL || "http://localhost:8188";
@@ -56,6 +88,38 @@ export class ComfyPage {
this.resetViewButton = page.getByRole("button", { name: "Reset View" });
this.workflowUploadInput = page.locator("#comfy-file-input");
this.searchBox = new ComfyNodeSearchBox(page);
this.menu = new ComfyMenu(page);
}
async setup() {
await this.goto();
// Unify font for consistent screenshots.
await this.page.addStyleTag({
url: "https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap",
});
await this.page.addStyleTag({
url: "https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap",
});
await this.page.addStyleTag({
content: `
* {
font-family: 'Roboto Mono', 'Noto Color Emoji';
}`,
});
await this.page.waitForFunction(() => document.fonts.ready);
await this.page.waitForFunction(() => window["app"] !== undefined);
await this.page.evaluate(() => {
window["app"]["canvas"].show_info = false;
});
await this.nextFrame();
// Reset view to force re-rendering of canvas. So that info fields like fps
// become hidden.
await this.resetView();
}
async realod() {
await this.page.reload({ timeout: 15000 });
await this.setup();
}
async goto() {
@@ -76,7 +140,9 @@ export class ComfyPage {
}
async resetView() {
await this.resetViewButton.click();
if (await this.resetViewButton.isVisible()) {
await this.resetViewButton.click();
}
// Avoid "Reset View" button highlight.
await this.page.mouse.move(10, 10);
await this.nextFrame();
@@ -323,29 +389,7 @@ export class ComfyPage {
export const comfyPageFixture = base.extend<{ comfyPage: ComfyPage }>({
comfyPage: async ({ page }, use) => {
const comfyPage = new ComfyPage(page);
await comfyPage.goto();
// Unify font for consistent screenshots.
await page.addStyleTag({
url: "https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap",
});
await page.addStyleTag({
url: "https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap",
});
await page.addStyleTag({
content: `
* {
font-family: 'Roboto Mono', 'Noto Color Emoji';
}`,
});
await page.waitForFunction(() => document.fonts.ready);
await page.waitForFunction(() => window["app"] !== undefined);
await page.evaluate(() => {
window["app"]["canvas"].show_info = false;
});
await comfyPage.nextFrame();
// Reset view to force re-rendering of canvas. So that info fields like fps
// become hidden.
await comfyPage.resetView();
await comfyPage.setup();
await use(comfyPage);
},
});

View File

@@ -0,0 +1,45 @@
import { expect } from "@playwright/test";
import { comfyPageFixture as test } from "./ComfyPage";
test.describe("Menu", () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.page.evaluate(async () => {
await window["app"].ui.settings.setSettingValueAsync(
"Comfy.UseNewMenu",
"Top"
);
});
});
test.afterEach(async ({ comfyPage }) => {
const currentThemeId = await comfyPage.menu.getThemeId();
if (currentThemeId !== "dark") {
await comfyPage.menu.toggleTheme();
}
await comfyPage.page.evaluate(async () => {
await window["app"].ui.settings.setSettingValueAsync(
"Comfy.UseNewMenu",
"Disabled"
);
});
});
test("Toggle theme", async ({ comfyPage }) => {
test.setTimeout(30000);
expect(await comfyPage.menu.getThemeId()).toBe("dark");
await comfyPage.menu.toggleTheme();
expect(await comfyPage.menu.getThemeId()).toBe("light");
// Theme id should persist after reload.
await comfyPage.page.reload();
await comfyPage.setup();
expect(await comfyPage.menu.getThemeId()).toBe("light");
await comfyPage.menu.toggleTheme();
expect(await comfyPage.menu.getThemeId()).toBe("dark");
});
});

View File

@@ -1,6 +1,7 @@
<template>
<Button
:icon="props.icon"
:class="props.class"
text
:pt="{
root: `side-bar-button ${
@@ -25,6 +26,10 @@ const props = defineProps({
type: String,
default: "",
},
class: {
type: String,
default: "",
},
});
const emit = defineEmits(["click"]);

View File

@@ -3,6 +3,7 @@
:icon="icon"
@click="toggleTheme"
:tooltip="$t('sideToolBar.themeToggle')"
class="comfy-vue-theme-toggle"
/>
</template>