Skip to content

Commit

Permalink
[web] Link to changing product visible only from Overview
Browse files Browse the repository at this point in the history
Now that pages can put their relevant actions at the top of the Sidebar, makes
sense that the Overview page place the "Change selected product" there.
  • Loading branch information
dgdavid committed Mar 13, 2023
1 parent a7cd3e0 commit 41fa27a
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 43 deletions.
2 changes: 0 additions & 2 deletions web/src/components/core/Sidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import React, { useEffect, useRef, useState } from "react";
import { Icon, PageActions, PageOptionsSlot } from "~/components/layout";
import { About, Disclosure, LogsButton, ShowLogButton, ShowTerminalButton } from "~/components/core";
import { ChangeProductLink } from "~/components/software";
import { TargetIpsPopup } from "~/components/network";

/**
Expand Down Expand Up @@ -54,7 +53,6 @@ import { TargetIpsPopup } from "~/components/network";
const FixedLinks = React.memo(() => (
<div className="flex-stack">
<h3>Other options</h3>
<ChangeProductLink />
<Disclosure label="Diagnosis tools" data-keep-sidebar-open>
<ShowLogButton />
<LogsButton data-keep-sidebar-open="true" />
Expand Down
22 changes: 11 additions & 11 deletions web/src/components/core/Sidebar.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ import { plainRender, mockComponent, mockLayout } from "~/test-utils";
import { Sidebar } from "~/components/core";

jest.mock("~/components/layout/Layout", () => mockLayout());
jest.mock("~/components/core/About", () => mockComponent(<button>About button mock</button>));
jest.mock("~/components/core/LogsButton", () => mockComponent(<a href="#" data-keep-sidebar-open="true">Download logs mock</a>));
jest.mock("~/components/software/ChangeProductLink", () => mockComponent(<a href="#">Change product mock</a>));
jest.mock("~/components/core/About", () => mockComponent(<a href="#">About link mock</a>));
jest.mock("~/components/core/LogsButton", () => mockComponent(<button data-keep-sidebar-open="true">Download logs mock</button>));
jest.mock("~/components/core/ShowLogButton", () => mockComponent(<button href="#">Show logs mock</button>));
jest.mock("~/components/network/TargetIpsPopup", () => mockComponent("Host Ips Mock"));

it("renders the sidebar initially hidden", async () => {
Expand Down Expand Up @@ -84,23 +84,23 @@ describe("onClick bubbling", () => {
await user.click(nav);
expect(nav).toHaveAttribute("data-state", "visible");

// user clicks on a link set for keeping the sidebar open
const downloadLink = within(nav).getByRole("link", { name: "Download logs mock" });
await user.click(downloadLink);
// user clicks on a button set for keeping the sidebar open
const downloadButton = within(nav).getByRole("button", { name: "Download logs mock" });
await user.click(downloadButton);
expect(nav).toHaveAttribute("data-state", "visible");

// user clicks a link NOT set for keeping the sidebar open
const changeProductLink = within(nav).getByRole("link", { name: "Change product mock" });
await user.click(changeProductLink);
// user clicks a button NOT set for keeping the sidebar open
const showLogsButton = within(nav).getByRole("button", { name: "Show logs mock" });
await user.click(showLogsButton);
expect(nav).toHaveAttribute("data-state", "hidden");

// open it again
await user.click(openLink);
expect(nav).toHaveAttribute("data-state", "visible");

// user clicks on a button
const aboutButton = within(nav).getByRole("button", { name: "About button mock" });
await user.click(aboutButton);
const aboutLink = within(nav).getByRole("link", { name: "About link mock" });
await user.click(aboutLink);
expect(nav).toHaveAttribute("data-state", "hidden");
});
});
9 changes: 7 additions & 2 deletions web/src/components/overview/Overview.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) [2022] SUSE LLC
* Copyright (c) [2022-2023] SUSE LLC
*
* All Rights Reserved.
*
Expand All @@ -23,7 +23,8 @@ import React, { useState } from "react";
import { useSoftware } from "~/context/software";
import { Navigate } from "react-router-dom";

import { Page, InstallButton } from "~/components/core";
import { Page, PageOptions, InstallButton } from "~/components/core";
import { ChangeProductLink } from "~/components/software";
import {
L10nSection,
NetworkSection,
Expand All @@ -46,6 +47,10 @@ function Overview() {
icon="inventory_2"
action={<InstallButton onClick={() => setShowErrors(true)} />}
>
<PageOptions>
<ChangeProductLink />
</PageOptions>

<L10nSection />
<NetworkSection />
<StorageSection showErrors />
Expand Down
46 changes: 18 additions & 28 deletions web/src/components/overview/Overview.test.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) [2022] SUSE LLC
* Copyright (c) [2022-2023] SUSE LLC
*
* All Rights Reserved.
*
Expand All @@ -26,7 +26,7 @@ import Overview from "./Overview";
import { createClient } from "~/client";

let mockProduct;
let mockProducts = [
const mockProducts = [
{ id: "openSUSE", name: "openSUSE Tumbleweed" },
{ id: "Leap Micro", name: "openSUSE Micro" }
];
Expand All @@ -50,21 +50,9 @@ jest.mock("~/components/overview/StorageSection", () => mockComponent("Storage S
jest.mock("~/components/overview/NetworkSection", () => mockComponent("Network Section"));
jest.mock("~/components/overview/UsersSection", () => mockComponent("Users Section"));
jest.mock("~/components/overview/SoftwareSection", () => mockComponent("Software Section"));
jest.mock("~/components/core/PageOptions", () => mockComponent("PageOptions"));
jest.mock("~/components/core/InstallButton", () => mockComponent("Install Button"));

it("renders the Overview and the Install button", async () => {
installerRender(<Overview />);
const title = screen.getByText(/openSUSE Tumbleweed/i);
expect(title).toBeInTheDocument();

await screen.findByText("Localization Section");
await screen.findByText("Network Section");
await screen.findByText("Storage Section");
await screen.findByText("Users Section");
await screen.findByText("Software Section");
await screen.findByText("Install Button");
});

beforeEach(() => {
mockProduct = { id: "openSUSE", name: "openSUSE Tumbleweed" };
createClient.mockImplementation(() => {
Expand All @@ -79,28 +67,30 @@ beforeEach(() => {
});
});

describe("when no product is selected", () => {
beforeEach(() => {
mockProduct = null;
});

it("redirects to the product selection page", async () => {
describe("when product is selected", () => {
it("renders the Overview and the Install button", async () => {
installerRender(<Overview />);
const title = screen.getByText(/openSUSE Tumbleweed/i);
expect(title).toBeInTheDocument();

// react-router-dom Navigate is mocked. See test-utils for more details.
await screen.findByText("Navigating to /products");
await screen.findByText("Localization Section");
await screen.findByText("Network Section");
await screen.findByText("Storage Section");
await screen.findByText("Users Section");
await screen.findByText("Software Section");
await screen.findByText("Install Button");
});
});

describe("if there is only one product", () => {
describe("when no product is selected", () => {
beforeEach(() => {
mockProducts = [mockProduct];
mockProduct = null;
});

it("does not show the action for changing the selected product", async () => {
it("redirects to the product selection page", async () => {
installerRender(<Overview />);

await screen.findByText("openSUSE Tumbleweed");
expect(screen.queryByLabelText("Change selected product")).not.toBeInTheDocument();
// react-router-dom Navigate is mocked. See test-utils for more details.
await screen.findByText("Navigating to /products");
});
});

0 comments on commit 41fa27a

Please sign in to comment.