diff --git a/web/package/agama-web-ui.changes b/web/package/agama-web-ui.changes index 853afb56bb..ffb421a543 100644 --- a/web/package/agama-web-ui.changes +++ b/web/package/agama-web-ui.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Mon Mar 9 09:19:30 UTC 2026 - David Diaz + +- Allow downloading the user config (jsc#PED-15453). + ------------------------------------------------------------------- Thu Mar 5 11:46:24 UTC 2026 - Imobach Gonzalez Sosa diff --git a/web/src/components/core/InstallerOptionsMenu.test.tsx b/web/src/components/core/InstallerOptionsMenu.test.tsx new file mode 100644 index 0000000000..c4c54cbb9e --- /dev/null +++ b/web/src/components/core/InstallerOptionsMenu.test.tsx @@ -0,0 +1,101 @@ +/* + * Copyright (c) [2026] SUSE LLC + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, contact SUSE LLC. + * + * To contact SUSE LLC about this file by physical or electronic mail, you may + * find current contact information at www.suse.com. + */ + +import React from "react"; +import { screen } from "@testing-library/react"; +import { plainRender } from "~/test-utils"; +import InstallerOptionsMenu from "./InstallerOptionsMenu"; + +jest.mock("~/components/core/ChangeProductOption", () => () => ( + Change product +)); + +describe("InstallerOptionsMenu", () => { + describe("toggle button", () => { + it("renders a toggle with 'More installer options' aria-label", () => { + plainRender(); + screen.getByRole("button", { name: /More installer options/i }); + }); + + it("renders the 'More' label by default", () => { + plainRender(); + expect(screen.getByRole("button", { name: /More installer options/i })).toHaveTextContent( + "More", + ); + }); + + it("hides the 'More' label when hideLabel is true", () => { + plainRender(); + const toggle = screen.getByRole("button", { name: /More installer options/i }); + expect(toggle).not.toHaveTextContent("More"); + }); + }); + + describe("dropdown open/close behavior", () => { + it("is closed by default", () => { + plainRender(); + expect(screen.queryByRole("menu")).toBeNull(); + }); + + it("opens the dropdown when the toggle is clicked", async () => { + const { user } = plainRender(); + await user.click(screen.getByRole("button", { name: /More installer options/i })); + screen.getByRole("menu"); + }); + + it("closes the dropdown after selecting an item", async () => { + const { user } = plainRender(); + await user.click(screen.getByRole("button", { name: /More installer options/i })); + const menu = screen.getByRole("menu"); + await user.click(screen.getByRole("menuitem", { name: /Download config/i })); + expect(menu).not.toBeVisible(); + }); + }); + + describe("dropdown items", () => { + it("renders the 'Change product' option when showChangeProductOption is true", async () => { + const { user } = plainRender(); + await user.click(screen.getByRole("button", { name: /More installer options/i })); + screen.getByRole("menuitem", { name: /Change product/i }); + }); + + it("does not render the 'Change product' option by default", async () => { + const { user } = plainRender(); + await user.click(screen.getByRole("button", { name: /More installer options/i })); + expect(screen.queryByRole("menuitem", { name: /Change product/i })).not.toBeInTheDocument(); + }); + + it("renders the 'Download config' link", async () => { + const { user } = plainRender(); + await user.click(screen.getByRole("button", { name: /More installer options/i })); + const link = screen.getByRole("menuitem", { name: /Download config/i }); + expect(link).toHaveAttribute("download", "agama-config.json"); + }); + + it("renders the 'Download logs' link", async () => { + const { user } = plainRender(); + await user.click(screen.getByRole("button", { name: /More installer options/i })); + const link = screen.getByRole("menuitem", { name: /Download logs/i }); + expect(link).toHaveAttribute("download", "agama-logs.tar.gz"); + }); + }); +}); diff --git a/web/src/components/core/InstallerOptionsMenu.tsx b/web/src/components/core/InstallerOptionsMenu.tsx index a481f2cbe3..d0c578a2a8 100644 --- a/web/src/components/core/InstallerOptionsMenu.tsx +++ b/web/src/components/core/InstallerOptionsMenu.tsx @@ -87,6 +87,9 @@ export default function InstallerOptionsMenu({ > {showChangeProductOption && } + + {_("Download config")} + {_("Download logs")} diff --git a/web/src/routes/paths.ts b/web/src/routes/paths.ts index c8a4950cd5..4a55df6907 100644 --- a/web/src/routes/paths.ts +++ b/web/src/routes/paths.ts @@ -53,6 +53,7 @@ const ROOT = { installationFinished: "/installation/finished", installationExit: "/installation/exit", logs: "/api/v2/private/download_logs", + config: "/api/v2/config", }; const USER = {