Fleet UI: VPP apps with self service shows correct install status (#28739)

This commit is contained in:
RachelElysia 2025-05-02 10:41:06 -04:00 committed by GitHub
parent c68de7c953
commit e5f56fc9fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 164 additions and 3 deletions

View file

@ -0,0 +1 @@
Fleet UI: Install Status correctly displays available for self-service for VPP apps

View file

@ -0,0 +1,160 @@
import React from "react";
import { render, screen } from "@testing-library/react";
import { renderWithSetup } from "test/test-utils";
import {
createMockHostAppStoreApp,
createMockHostSoftwarePackage,
} from "__mocks__/hostMock";
import InstallStatusCell from "./InstallStatusCell";
// Mock lodash uniqueId to always return the same id for stable tests
jest.mock("lodash", () => ({
...jest.requireActual("lodash"),
uniqueId: jest.fn(() => "test-tooltip-id"),
}));
const testSoftwarePackage = createMockHostSoftwarePackage();
describe("InstallStatusCell - component", () => {
it("renders 'Installed' status with tooltip", async () => {
const { user } = renderWithSetup(
<InstallStatusCell
status="installed"
software_package={testSoftwarePackage}
/>
);
expect(screen.getByText("Installed")).toBeInTheDocument();
await user.hover(screen.getByText("Installed"));
expect(screen.getByText(/Software is installed/i)).toBeInTheDocument();
});
it("renders 'Installing (pending)' status with tooltip", async () => {
const { user } = renderWithSetup(
<InstallStatusCell
status="pending_install"
software_package={testSoftwarePackage}
/>
);
expect(screen.getByText("Installing (pending)")).toBeInTheDocument();
await user.hover(screen.getByText("Installing (pending)"));
expect(
screen.getByText(/Fleet is installing or will install/i)
).toBeInTheDocument();
});
it("renders 'Uninstalling (pending)' status with tooltip", async () => {
const { user } = renderWithSetup(
<InstallStatusCell
status="pending_uninstall"
software_package={testSoftwarePackage}
/>
);
expect(screen.getByText("Uninstalling (pending)")).toBeInTheDocument();
await user.hover(screen.getByText("Uninstalling (pending)"));
expect(
screen.getByText(/Fleet is uninstalling or will uninstall/i)
).toBeInTheDocument();
});
it("renders 'Install (failed)' status with tooltip", async () => {
const { user } = renderWithSetup(
<InstallStatusCell
status="failed_install"
software_package={testSoftwarePackage}
/>
);
expect(screen.getByText("Install (failed)")).toBeInTheDocument();
await user.hover(screen.getByText("Install (failed)"));
expect(
screen.getByText(/The host failed to install software/i)
).toBeInTheDocument();
});
it("renders 'Uninstall (failed)' status with tooltip", async () => {
const { user } = renderWithSetup(
<InstallStatusCell
status="failed_uninstall"
software_package={testSoftwarePackage}
/>
);
expect(screen.getByText("Uninstall (failed)")).toBeInTheDocument();
await user.hover(screen.getByText("Uninstall (failed)"));
expect(
screen.getByText(/The host failed to uninstall software/i)
).toBeInTheDocument();
});
it("renders 'Available for install' for package", async () => {
const { user } = renderWithSetup(
<InstallStatusCell software_package={testSoftwarePackage} status={null} />
);
expect(screen.getByText("Available for install")).toBeInTheDocument();
await user.hover(screen.getByText("Available for install"));
expect(screen.getByText(/can be installed/i)).toBeInTheDocument();
});
it("renders 'Available for install' for App Store app", async () => {
const { user } = renderWithSetup(
<InstallStatusCell
software_package={{ ...testSoftwarePackage, self_service: false }}
status={null}
/>
);
expect(screen.getByText("Available for install")).toBeInTheDocument();
await user.hover(screen.getByText("Available for install"));
expect(screen.getByText(/can be installed/i)).toBeInTheDocument();
});
it("renders 'Self-service' for package with self_service true", async () => {
const { user } = renderWithSetup(
<InstallStatusCell
software_package={{
...testSoftwarePackage,
name: "SelfService Software",
self_service: true,
}}
status={null}
/>
);
expect(screen.getAllByText("Self-service").length).toBeGreaterThan(0);
await user.hover(screen.getAllByText("Self-service")[0]);
expect(screen.getByText(/can be installed/i)).toBeInTheDocument();
});
it("renders 'Self-service' for App Store app with self_service true", async () => {
const { user } = renderWithSetup(
<InstallStatusCell
app_store_app={createMockHostAppStoreApp({ self_service: true })}
status={null}
/>
);
expect(screen.getAllByText("Self-service").length).toBeGreaterThan(0);
await user.hover(screen.getAllByText("Self-service")[0]);
expect(screen.getByText(/Software can be installed/i)).toBeInTheDocument();
});
it("renders placeholder for missing status and packages", () => {
render(<InstallStatusCell status={null} />);
expect(screen.getByText("---")).toBeInTheDocument();
});
});

View file

@ -123,7 +123,8 @@ export const INSTALL_STATUS_DISPLAY_OPTIONS: Record<
},
};
type IInstallStatusCellProps = IHostSoftware;
type IInstallStatusCellProps = Pick<IHostSoftware, "status"> &
Partial<Pick<IHostSoftware, "software_package" | "app_store_app">>;
const InstallStatusCell = ({
status,
@ -138,8 +139,7 @@ const InstallStatusCell = ({
if (status !== null) {
displayStatus = status;
} else if (software_package?.self_service) {
// currently only software packages can be self-service
} else if (software_package?.self_service || app_store_app?.self_service) {
displayStatus = "selfService";
} else if (hasPackage || hasAppStoreApp) {
displayStatus = "avaiableForInstall";