diff --git a/web/package/agama-web-ui.changes b/web/package/agama-web-ui.changes index d82edd78a6..c92fd1c0b4 100644 --- a/web/package/agama-web-ui.changes +++ b/web/package/agama-web-ui.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Jan 16 12:58:15 UTC 2026 - David Diaz + +- Updated the overview software summary to inform users about + blocking issues (gh#agama-project/agama#3035). + ------------------------------------------------------------------- Wed Jan 14 23:27:16 UTC 2026 - Imobach Gonzalez Sosa diff --git a/web/src/components/overview/SoftwareSummary.test.tsx b/web/src/components/overview/SoftwareSummary.test.tsx index 8a2afe4724..ef6e511b2f 100644 --- a/web/src/components/overview/SoftwareSummary.test.tsx +++ b/web/src/components/overview/SoftwareSummary.test.tsx @@ -24,12 +24,14 @@ import { screen, within } from "@testing-library/react"; import { installerRender, mockProgresses } from "~/test-utils"; import { useProposal } from "~/hooks/model/proposal/software"; import { useSelectedPatterns } from "~/hooks/model/system/software"; +import { useIssues } from "~/hooks/model/issue"; import { SOFTWARE } from "~/routes/paths"; import { SelectedBy } from "~/model/proposal/software"; import SoftwareSummary from "./SoftwareSummary"; const mockUseProposalFn: jest.Mock> = jest.fn(); const mockUseSelectedPatternsFn: jest.Mock> = jest.fn(); +const mockUseIssuesFn: jest.Mock> = jest.fn(); jest.mock("~/hooks/model/proposal/software", () => ({ useProposal: () => mockUseProposalFn(), @@ -39,9 +41,15 @@ jest.mock("~/hooks/model/system/software", () => ({ useSelectedPatterns: () => mockUseSelectedPatternsFn(), })); +jest.mock("~/hooks/model/issue", () => ({ + ...jest.requireActual("~/hooks/model/issue"), + useIssues: () => mockUseIssuesFn(), +})); + describe("SoftwareSummary", () => { beforeEach(() => { mockProgresses([]); + mockUseIssuesFn.mockReturnValue([]); mockUseProposalFn.mockReturnValue({ usedSpace: 6291456, patterns: {} }); // 6 GiB mockUseSelectedPatternsFn.mockReturnValue([]); }); @@ -83,6 +91,27 @@ describe("SoftwareSummary", () => { }); describe("when software data is loaded (no progress active)", () => { + describe("but there are issues", () => { + beforeEach(() => { + mockUseIssuesFn.mockReturnValue([ + { + description: "Fake Issue", + class: "generic", + details: "Fake Issue details", + scope: "software", + }, + ]); + }); + + it("renders `Invalid software selection` text", () => { + installerRender(); + + screen.getByText("Invalid software selection"); + expect(screen.queryByText("Required packages")).toBeNull(); + expect(screen.queryByText(/Needs about/)).toBeNull(); + }); + }); + it("renders 'Required packages' without patterns count when no none is selected", () => { mockUseProposalFn.mockReturnValue({ usedSpace: 1955420, patterns: {} }); mockUseSelectedPatternsFn.mockReturnValue([]); diff --git a/web/src/components/overview/SoftwareSummary.tsx b/web/src/components/overview/SoftwareSummary.tsx index c6ad6398f8..a404bb91fa 100644 --- a/web/src/components/overview/SoftwareSummary.tsx +++ b/web/src/components/overview/SoftwareSummary.tsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2025] SUSE LLC + * Copyright (c) [2025-2026] SUSE LLC * * All Rights Reserved. * @@ -21,16 +21,18 @@ */ import React from "react"; +import { isEmpty } from "radashi"; import xbytes from "xbytes"; import { sprintf } from "sprintf-js"; +import Summary from "~/components/core/Summary"; +import Link from "~/components/core/Link"; import { useProposal } from "~/hooks/model/proposal/software"; import { useProgressTracking } from "~/hooks/use-progress-tracking"; import { useSelectedPatterns } from "~/hooks/model/system/software"; +import { useIssues } from "~/hooks/model/issue"; import { SOFTWARE } from "~/routes/paths"; import { _, n_ } from "~/i18n"; -import Summary from "~/components/core/Summary"; -import Link from "~/components/core/Link"; /** * Renders a summary text describing the software selection. @@ -70,16 +72,20 @@ const Description = () => { */ export default function SoftwareSummary() { const { loading } = useProgressTracking("software"); + const issues = useIssues("software"); + const hasIssues = !isEmpty(issues); + return ( {_("Software")} } - value={} - description={} + value={hasIssues ? _("Invalid software selection") : } + description={!hasIssues && } isLoading={loading} /> );