diff --git a/ui/src/ui/views/config.browser.test.ts b/ui/src/ui/views/config.browser.test.ts index c0e8686d766..ffdbf604fc9 100644 --- a/ui/src/ui/views/config.browser.test.ts +++ b/ui/src/ui/views/config.browser.test.ts @@ -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 = {}): { 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(".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);