diff --git a/.changeset/all-pandas-hide.md b/.changeset/all-pandas-hide.md new file mode 100644 index 0000000000..657654830b --- /dev/null +++ b/.changeset/all-pandas-hide.md @@ -0,0 +1,5 @@ +--- +"landscape-ui": patch +--- + +Sort the local repositories packages list so it stays consistent diff --git a/src/features/local-repositories/components/ImportRepositoryPackagesSidePanel/ValidationResult/ValidationResult.test.tsx b/src/features/local-repositories/components/ImportRepositoryPackagesSidePanel/ValidationResult/ValidationResult.test.tsx index ad819ded92..cd4ae1705a 100644 --- a/src/features/local-repositories/components/ImportRepositoryPackagesSidePanel/ValidationResult/ValidationResult.test.tsx +++ b/src/features/local-repositories/components/ImportRepositoryPackagesSidePanel/ValidationResult/ValidationResult.test.tsx @@ -85,9 +85,7 @@ describe("ValidationResult", () => { ).toBeInTheDocument(); expect(screen.getByText(/packages to import/i)).toBeInTheDocument(); - expect( - screen.getByText("python3-snap-http_1.4.0-0ubuntu0_all"), - ).toBeInTheDocument(); + expect(screen.getByText("package1-0.2.1")).toBeInTheDocument(); expect(screen.getByText(/page 1 of 10/i)).toBeInTheDocument(); }); @@ -97,9 +95,7 @@ describe("ValidationResult", () => { ); expect(screen.getByText(/packages to import/i)).toBeInTheDocument(); - expect( - screen.getByText("python3-snap-http_1.4.0-0ubuntu0_all"), - ).toBeInTheDocument(); + expect(screen.getByText("package1-0.2.1")).toBeInTheDocument(); expect(screen.getByText("package2-1.0.0")).toBeInTheDocument(); }); }); diff --git a/src/features/local-repositories/components/LocalRepositoryPackagesList/LocalRepositoryPackagesList.test.tsx b/src/features/local-repositories/components/LocalRepositoryPackagesList/LocalRepositoryPackagesList.test.tsx index 98506e10c0..bbd2b022fb 100644 --- a/src/features/local-repositories/components/LocalRepositoryPackagesList/LocalRepositoryPackagesList.test.tsx +++ b/src/features/local-repositories/components/LocalRepositoryPackagesList/LocalRepositoryPackagesList.test.tsx @@ -1,27 +1,34 @@ import { renderWithProviders } from "@/tests/render"; import { describe, it, expect } from "vitest"; import LocalRepositoryPackagesList from "./LocalRepositoryPackagesList"; -import { paginatedPackages } from "@/tests/mocks/localRepositories"; +import { + paginatedPackages, + sortedPackages, +} from "@/tests/mocks/localRepositories"; import { screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -const singlePagePackages = paginatedPackages.slice(0, 10); - describe("LocalRepositoryPackagesList", () => { - it("renders table with default column header", async () => { + it("renders table with default column header and paginated data", async () => { renderWithProviders( - , + , ); expect( await screen.findByRole("columnheader", { name: "Package name" }), ).toBeInTheDocument(); + + for (const pkg of sortedPackages.slice(0, 10)) { + expect(await screen.findByText(pkg)).toBeInTheDocument(); + } + + expect(await screen.findByText(/page 1 of 3/i)).toBeInTheDocument(); }); it("renders custom header when provided", async () => { renderWithProviders( , ); @@ -31,15 +38,6 @@ describe("LocalRepositoryPackagesList", () => { ).toBeInTheDocument(); }); - it("renders package names in table rows", async () => { - renderWithProviders( - , - ); - - expect(await screen.findByText("package-1")).toBeInTheDocument(); - expect(screen.getByText("package-2")).toBeInTheDocument(); - }); - it("renders empty message when no packages", async () => { renderWithProviders(); @@ -48,28 +46,22 @@ describe("LocalRepositoryPackagesList", () => { ).toBeInTheDocument(); }); - it("renders pagination info if more than 1 page", async () => { - renderWithProviders( - , - ); - - expect(await screen.findByText(/page 1 of 3/i)).toBeInTheDocument(); - }); - it("navigates to next page on click", async () => { const user = userEvent.setup(); renderWithProviders( , ); - await screen.findByText("package-1"); - expect(screen.queryByText("package-11")).not.toBeInTheDocument(); + assert(sortedPackages[0]); + assert(sortedPackages[10]); + await screen.findByText(sortedPackages[0]); + expect(screen.queryByText(sortedPackages[10])).not.toBeInTheDocument(); const nextButton = screen.getByRole("button", { name: /next/i }); await user.click(nextButton); - expect(screen.getByText("package-11")).toBeInTheDocument(); - expect(screen.queryByText("package-1")).not.toBeInTheDocument(); + expect(screen.getByText(sortedPackages[10])).toBeInTheDocument(); + expect(screen.queryByText(sortedPackages[0])).not.toBeInTheDocument(); }); it("navigates to previous page on click", async () => { @@ -78,16 +70,18 @@ describe("LocalRepositoryPackagesList", () => { , ); - await screen.findByText("package-1"); + assert(sortedPackages[0]); + assert(sortedPackages[10]); + await screen.findByText(sortedPackages[0]); const nextButton = screen.getByRole("button", { name: /next/i }); await user.click(nextButton); - expect(screen.getByText("package-11")).toBeInTheDocument(); + expect(screen.getByText(sortedPackages[10])).toBeInTheDocument(); const prevButton = screen.getByRole("button", { name: /previous/i }); await user.click(prevButton); - expect(screen.getByText("package-1")).toBeInTheDocument(); + expect(screen.getByText(sortedPackages[0])).toBeInTheDocument(); }); }); diff --git a/src/features/local-repositories/components/LocalRepositoryPackagesList/LocalRepositoryPackagesList.tsx b/src/features/local-repositories/components/LocalRepositoryPackagesList/LocalRepositoryPackagesList.tsx index 08328ee24f..a497dafa25 100644 --- a/src/features/local-repositories/components/LocalRepositoryPackagesList/LocalRepositoryPackagesList.tsx +++ b/src/features/local-repositories/components/LocalRepositoryPackagesList/LocalRepositoryPackagesList.tsx @@ -16,7 +16,13 @@ const LocalRepositoryPackagesList: FC = ({ const [currentPage, setCurrentPage] = useState(1); const pageSize = 10; - const formattedPackages: LocalPackage[] = packages.map((name) => ({ name })); + const formattedPackages = useMemo( + () => + packages + .map((name) => ({ name })) + .toSorted((a, b) => a.name.localeCompare(b.name)), + [packages], + ); const pagedPackages = useMemo( () => formattedPackages.slice( diff --git a/src/features/local-repositories/components/ViewLocalRepositorySidePanel/components/ViewRepositoryPackagesTab/ViewRepositoryPackagesTab.test.tsx b/src/features/local-repositories/components/ViewLocalRepositorySidePanel/components/ViewRepositoryPackagesTab/ViewRepositoryPackagesTab.test.tsx index 607a536cd8..20b0993b05 100644 --- a/src/features/local-repositories/components/ViewLocalRepositorySidePanel/components/ViewRepositoryPackagesTab/ViewRepositoryPackagesTab.test.tsx +++ b/src/features/local-repositories/components/ViewLocalRepositorySidePanel/components/ViewRepositoryPackagesTab/ViewRepositoryPackagesTab.test.tsx @@ -2,7 +2,7 @@ import { renderWithProviders } from "@/tests/render"; import { describe, it, expect } from "vitest"; import { screen } from "@testing-library/react"; import ViewRepositoryPackagesTab from "./ViewRepositoryPackagesTab"; -import { repositories } from "@/tests/mocks/localRepositories"; +import { repositories, sortedPackages } from "@/tests/mocks/localRepositories"; describe("ViewRepositoryPackagesTab", () => { it("renders table with correct header after loading", async () => { @@ -16,8 +16,7 @@ describe("ViewRepositoryPackagesTab", () => { await screen.findByRole("columnheader", { name: "Package name" }), ).toBeInTheDocument(); - expect(await screen.findByText("package-1")).toBeInTheDocument(); - expect(screen.getByText("package-2")).toBeInTheDocument(); - expect(screen.getByText("package-3")).toBeInTheDocument(); + assert(sortedPackages[0]); + expect(await screen.findByText(sortedPackages[0])).toBeInTheDocument(); }); }); diff --git a/src/features/overview/components/DonutChart/DonutChart.test.tsx b/src/features/overview/components/DonutChart/DonutChart.test.tsx index 6028c50c13..bf361e9e3d 100644 --- a/src/features/overview/components/DonutChart/DonutChart.test.tsx +++ b/src/features/overview/components/DonutChart/DonutChart.test.tsx @@ -136,14 +136,8 @@ describe("DonutChart", () => { it("uses light-mode default colors by default", () => { const { container } = renderChart(); const arcs = getArcs(container); - expect(arcs[0]).toHaveAttribute( - "stroke", - colorMap.green.light.default, - ); - expect(arcs[1]).toHaveAttribute( - "stroke", - colorMap.orange.light.default, - ); + expect(arcs[0]).toHaveAttribute("stroke", colorMap.green.light.default); + expect(arcs[1]).toHaveAttribute("stroke", colorMap.orange.light.default); expect(arcs[2]).toHaveAttribute("stroke", colorMap.red.light.default); }); @@ -151,14 +145,8 @@ describe("DonutChart", () => { localStorage.setItem("_landscape_dark_theme", "true"); const { container } = renderChart(); const arcs = getArcs(container); - expect(arcs[0]).toHaveAttribute( - "stroke", - colorMap.green.dark.default, - ); - expect(arcs[2]).toHaveAttribute( - "stroke", - colorMap.red.dark.default, - ); + expect(arcs[0]).toHaveAttribute("stroke", colorMap.green.dark.default); + expect(arcs[2]).toHaveAttribute("stroke", colorMap.red.dark.default); }); it("keeps default colors on every ring when one is hovered (dim via CSS opacity, not palette swap)", async () => { @@ -168,14 +156,8 @@ describe("DonutChart", () => { await user.hover(getRingGroup(0)); const arcs = getArcs(container); - expect(arcs[0]).toHaveAttribute( - "stroke", - colorMap.green.light.default, - ); - expect(arcs[1]).toHaveAttribute( - "stroke", - colorMap.orange.light.default, - ); + expect(arcs[0]).toHaveAttribute("stroke", colorMap.green.light.default); + expect(arcs[1]).toHaveAttribute("stroke", colorMap.orange.light.default); expect(arcs[2]).toHaveAttribute("stroke", colorMap.red.light.default); }); @@ -185,9 +167,7 @@ describe("DonutChart", () => { await user.hover(getRingGroup(0)); - expect(getRingGroup(0).getAttribute("class") ?? "").toMatch( - /ring--active/, - ); + expect(getRingGroup(0).getAttribute("class") ?? "").toMatch(/ring--active/); expect(getRingGroup(0).getAttribute("class") ?? "").not.toMatch( /ring--inactive/, ); @@ -211,9 +191,7 @@ describe("DonutChart", () => { expect(getRingGroup(1).getAttribute("class") ?? "").toMatch( /ring--inactive/, ); - expect(getRingGroup(2).getAttribute("class") ?? "").toMatch( - /ring--active/, - ); + expect(getRingGroup(2).getAttribute("class") ?? "").toMatch(/ring--active/); }); it("resets state when the inner container loses pointer", async () => { @@ -228,7 +206,9 @@ describe("DonutChart", () => { ) as HTMLElement; fireEvent.mouseLeave(inner); - expect(getRingGroup(0).getAttribute("class") ?? "").not.toMatch(/ring--active/); + expect(getRingGroup(0).getAttribute("class") ?? "").not.toMatch( + /ring--active/, + ); }); it("activates a ring on keyboard focus and clears on blur", () => { @@ -291,9 +271,7 @@ describe("DonutChart", () => { ], }); - expect(screen.getByTestId("donut-center-number").textContent).toBe( - "12.3K", - ); + expect(screen.getByTestId("donut-center-number").textContent).toBe("12.3K"); }); it("formats compactly when a large ring is hovered", async () => { @@ -309,9 +287,7 @@ describe("DonutChart", () => { await user.hover(getRingGroup(0)); - expect(screen.getByTestId("donut-center-number").textContent).toBe( - "87.4K", - ); + expect(screen.getByTestId("donut-center-number").textContent).toBe("87.4K"); expect(screen.getByTestId("donut-center-sublabel").textContent).toBe( "of 100K", ); @@ -319,9 +295,7 @@ describe("DonutChart", () => { it("renders a track circle behind each ring with the track class", () => { const { container } = renderChart(); - const tracks = container.querySelectorAll( - `circle[class*='track']`, - ); + const tracks = container.querySelectorAll(`circle[class*='track']`); expect(tracks).toHaveLength(3); }); }); diff --git a/src/features/saved-searches/components/SavedSearchList/SavedSearchList.tsx b/src/features/saved-searches/components/SavedSearchList/SavedSearchList.tsx index ffd496fb0d..6ccc3f91f4 100644 --- a/src/features/saved-searches/components/SavedSearchList/SavedSearchList.tsx +++ b/src/features/saved-searches/components/SavedSearchList/SavedSearchList.tsx @@ -88,9 +88,7 @@ const SavedSearchList: FC = ({