test: require config view action buttons

This commit is contained in:
Peter Steinberger
2026-05-08 16:11:06 +01:00
parent cfdcd730bf
commit a9ea60db5d

View File

@@ -76,6 +76,17 @@ describe("config view", () => {
};
}
function requireActionButton(
button: HTMLButtonElement | undefined,
text: string,
): HTMLButtonElement {
expect(button).toBeInstanceOf(HTMLButtonElement);
if (!(button instanceof HTMLButtonElement)) {
throw new Error(`Expected ${text} action button`);
}
return button;
}
function renderConfigView(overrides: Partial<ConfigProps> = {}): {
container: HTMLElement;
props: ConfigProps;
@@ -153,10 +164,11 @@ describe("config view", () => {
formMode: "form",
formValue: { mixed: "x" },
});
let { saveButton, applyButton } = findActionButtons(container);
expect(saveButton).not.toBeUndefined();
expect(saveButton?.disabled).toBe(false);
expect(applyButton?.disabled).toBe(false);
let actionButtons = findActionButtons(container);
let saveButton = requireActionButton(actionButtons.saveButton, "Save");
let applyButton = requireActionButton(actionButtons.applyButton, "Apply");
expect(saveButton.disabled).toBe(false);
expect(applyButton.disabled).toBe(false);
renderCase({
schema: null,
@@ -164,24 +176,24 @@ describe("config view", () => {
formValue: { gateway: { mode: "local" } },
originalValue: {},
});
({ saveButton, applyButton } = findActionButtons(container));
expect(saveButton).not.toBeUndefined();
expect(saveButton?.disabled).toBe(true);
expect(applyButton?.disabled).toBe(true);
actionButtons = findActionButtons(container);
saveButton = requireActionButton(actionButtons.saveButton, "Save");
applyButton = requireActionButton(actionButtons.applyButton, "Apply");
expect(saveButton.disabled).toBe(true);
expect(applyButton.disabled).toBe(true);
renderCase({
formMode: "raw",
raw: "{\n}\n",
originalRaw: "{\n}\n",
});
let clearButton: HTMLButtonElement | undefined;
({ clearButton, saveButton, applyButton } = findActionButtons(container));
expect(clearButton).not.toBeUndefined();
expect(saveButton).not.toBeUndefined();
expect(applyButton).not.toBeUndefined();
expect(clearButton?.disabled).toBe(true);
expect(saveButton?.disabled).toBe(true);
expect(applyButton?.disabled).toBe(true);
actionButtons = findActionButtons(container);
let clearButton = requireActionButton(actionButtons.clearButton, "Clear");
saveButton = requireActionButton(actionButtons.saveButton, "Save");
applyButton = requireActionButton(actionButtons.applyButton, "Apply");
expect(clearButton.disabled).toBe(true);
expect(saveButton.disabled).toBe(true);
expect(applyButton.disabled).toBe(true);
const onReset = vi.fn();
renderCase({
@@ -190,14 +202,15 @@ describe("config view", () => {
originalRaw: "{\n}\n",
onReset,
});
({ clearButton, saveButton, applyButton } = findActionButtons(container));
expect(saveButton).not.toBeUndefined();
expect(applyButton).not.toBeUndefined();
expect(clearButton?.disabled).toBe(false);
expect(saveButton?.disabled).toBe(false);
expect(applyButton?.disabled).toBe(false);
actionButtons = findActionButtons(container);
clearButton = requireActionButton(actionButtons.clearButton, "Clear");
saveButton = requireActionButton(actionButtons.saveButton, "Save");
applyButton = requireActionButton(actionButtons.applyButton, "Apply");
expect(clearButton.disabled).toBe(false);
expect(saveButton.disabled).toBe(false);
expect(applyButton.disabled).toBe(false);
clearButton?.click();
clearButton.click();
expect(onReset).toHaveBeenCalledTimes(1);
});
@@ -222,26 +235,30 @@ describe("config view", () => {
renderCase({ saving: true });
let busyButton = findButtonContainingText(container, "Saving…");
let { clearButton, applyButton } = findActionButtons(container);
let actionButtons = findActionButtons(container);
let clearButton = requireActionButton(actionButtons.clearButton, "Clear");
let applyButton = requireActionButton(actionButtons.applyButton, "Apply");
expect(busyButton.disabled).toBe(true);
expect(busyButton.getAttribute("aria-busy")).toBe("true");
expect(busyButton.querySelectorAll(".config-action-spinner")).toHaveLength(1);
expect(clearButton?.disabled).toBe(false);
expect(applyButton?.disabled).toBe(false);
expect(clearButton.disabled).toBe(false);
expect(applyButton.disabled).toBe(false);
renderCase({ applying: true });
busyButton = findButtonContainingText(container, "Applying…");
({ clearButton } = findActionButtons(container));
actionButtons = findActionButtons(container);
clearButton = requireActionButton(actionButtons.clearButton, "Clear");
expect(busyButton.disabled).toBe(true);
expect(busyButton.querySelectorAll(".config-action-spinner")).toHaveLength(1);
expect(clearButton?.disabled).toBe(false);
expect(clearButton.disabled).toBe(false);
renderCase({ updating: true });
busyButton = findButtonContainingText(container, "Updating…");
({ clearButton } = findActionButtons(container));
actionButtons = findActionButtons(container);
clearButton = requireActionButton(actionButtons.clearButton, "Clear");
expect(busyButton.disabled).toBe(true);
expect(busyButton.querySelectorAll(".config-action-spinner")).toHaveLength(1);
expect(clearButton?.disabled).toBe(false);
expect(clearButton.disabled).toBe(false);
});
it("switches mode via the sidebar toggle", () => {
@@ -281,14 +298,10 @@ describe("config view", () => {
originalValue: { gateway: { mode: "local" } },
});
const formButton = Array.from(container.querySelectorAll("button")).find(
(btn) => btn.textContent?.trim() === "Form",
);
const rawButton = Array.from(container.querySelectorAll("button")).find(
(btn) => btn.textContent?.trim() === "Raw",
);
expect(formButton?.classList.contains("active")).toBe(true);
expect(rawButton?.disabled).toBe(true);
const formButton = findButtonByText(container, "Form");
const rawButton = findButtonByText(container, "Raw");
expect(formButton.classList.contains("active")).toBe(true);
expect(rawButton.disabled).toBe(true);
const rawNotice = container.querySelector(".config-actions__notice");
const actionButtons = container.querySelector(".config-actions__buttons");
expect(rawNotice).not.toBeNull();
@@ -300,7 +313,7 @@ describe("config view", () => {
);
expect(container.querySelector(".config-raw-field")).toBeNull();
rawButton?.click();
rawButton.click();
expect(onFormModeChange).not.toHaveBeenCalled();
});
@@ -935,16 +948,14 @@ describe("config view", () => {
onOpenCustomThemeImport,
});
const customButton = Array.from(container.querySelectorAll("button")).find(
(btn) => btn.textContent?.trim() === "Import",
);
const customButton = findButtonByText(container, "Import");
expect(customButton?.disabled).toBe(false);
expect(customButton.disabled).toBe(false);
expect(normalizedText(container)).toContain(
"Click Import to add one browser-local tweakcn theme",
);
customButton?.click();
customButton.click();
expect(onOpenCustomThemeImport).toHaveBeenCalledTimes(1);
});
@@ -957,11 +968,9 @@ describe("config view", () => {
customThemeImportFocusToken: 1,
});
const importButton = Array.from(container.querySelectorAll("button")).find((btn) =>
btn.textContent?.includes("Import theme"),
);
const importButton = findButtonContainingText(container, "Import theme");
expect(importButton?.disabled).toBe(true);
expect(importButton.disabled).toBe(true);
expect(container.querySelector(".settings-theme-import__input")).not.toBeNull();
expect(
container.querySelector<HTMLAnchorElement>(".settings-theme-import__external")?.href,
@@ -987,21 +996,15 @@ describe("config view", () => {
onCustomThemeImportUrlChange,
});
const customButton = Array.from(container.querySelectorAll("button")).find(
(btn) => btn.textContent?.trim() === "Light Green",
);
expect(customButton?.disabled).toBe(false);
customButton?.click();
const customButton = findButtonByText(container, "Light Green");
expect(customButton.disabled).toBe(false);
customButton.click();
expect(setTheme).toHaveBeenCalledWith("custom", expect.any(Object));
const replaceButton = Array.from(container.querySelectorAll("button")).find((btn) =>
btn.textContent?.includes("Replace Light Green"),
);
const clearButton = Array.from(container.querySelectorAll("button")).find((btn) =>
btn.textContent?.includes("Clear Light Green"),
);
replaceButton?.click();
clearButton?.click();
const replaceButton = findButtonContainingText(container, "Replace Light Green");
const clearButton = findButtonContainingText(container, "Clear Light Green");
replaceButton.click();
clearButton.click();
expect(onImportCustomTheme).toHaveBeenCalledTimes(1);
expect(onClearCustomTheme).toHaveBeenCalledTimes(1);