Skip to content

Commit

Permalink
web: Add type checking and fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
joseivanlopez committed Apr 11, 2024
1 parent 4e07840 commit b80ba46
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 61 deletions.
2 changes: 2 additions & 0 deletions web/src/components/storage/BootSelectionDialog.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
* find current contact information at www.suse.com.
*/

// @ts-check

import React from "react";
import { screen, within } from "@testing-library/react";
import { plainRender } from "~/test-utils";
Expand Down
2 changes: 2 additions & 0 deletions web/src/components/storage/DeviceSelectionDialog.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
* find current contact information at www.suse.com.
*/

// @ts-check

import React from "react";
import { screen, within } from "@testing-library/react";
import { plainRender } from "~/test-utils";
Expand Down
6 changes: 4 additions & 2 deletions web/src/components/storage/ProposalDeviceSection.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
* find current contact information at www.suse.com.
*/

// @ts-check

import React from "react";
import { screen, within } from "@testing-library/react";
import { plainRender } from "~/test-utils";
import { ProposalDeviceSection } from "~/components/storage";

const sda = {
sid: "59",
sid: 59,
isDrive: true,
type: "disk",
vendor: "Micron",
Expand All @@ -46,7 +48,7 @@ const sda = {
};

const sdb = {
sid: "62",
sid: 62,
isDrive: true,
type: "disk",
vendor: "Samsung",
Expand Down
148 changes: 107 additions & 41 deletions web/src/components/storage/ProposalPage.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,23 @@
* find current contact information at www.suse.com.
*/

// @ts-check

import React from "react";
import { act, screen, waitFor } from "@testing-library/react";
import { createCallbackMock, installerRender } from "~/test-utils";
import { createClient } from "~/client";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { StorageClient } from "~/client/storage";
import { IDLE } from "~/client/status";
import { ProposalPage } from "~/components/storage";

/**
* @typedef {import ("~/client/storage").ProposalResult} ProposalResult
* @typedef {import ("~/client/storage").StorageDevice} StorageDevice
* @typedef {import ("~/client/storage").Volume} Volume
*/

jest.mock("~/client");
jest.mock("@patternfly/react-core", () => {
const original = jest.requireActual("@patternfly/react-core");
Expand All @@ -46,9 +56,12 @@ jest.mock("~/context/product", () => ({
})
}));

/** @type {StorageDevice} */
const vda = {
sid: "59",
sid: 59,
type: "disk",
isDrive: true,
description: "",
vendor: "Micron",
model: "Micron 1100 SATA",
driver: ["ahci", "mmcblk"],
Expand All @@ -62,12 +75,14 @@ const vda = {
systems : ["Windows 11", "openSUSE Leap 15.2"],
udevIds: ["ata-Micron_1100_SATA_512GB_12563", "scsi-0ATA_Micron_1100_SATA_512GB"],
udevPaths: ["pci-0000:00-12", "pci-0000:00-12-ata"],
partitionTable: { type: "gpt", partitions: ["/dev/vda1", "/dev/vda2"] }
};

/** @type {StorageDevice} */
const vdb = {
sid: "60",
sid: 60,
type: "disk",
isDrive: true,
description: "",
vendor: "Seagate",
model: "Unknown",
driver: ["ahci", "mmcblk"],
Expand All @@ -76,32 +91,84 @@ const vdb = {
size: 1e+6
};

const storageMock = {
probe: jest.fn().mockResolvedValue(0),
proposal: {
getAvailableDevices: jest.fn().mockResolvedValue([vda, vdb]),
getEncryptionMethods: jest.fn().mockResolvedValue([]),
getProductMountPoints: jest.fn().mockResolvedValue([]),
getResult: jest.fn().mockResolvedValue(undefined),
defaultVolume: jest.fn(mountPath => Promise.resolve({ mountPath })),
calculate: jest.fn().mockResolvedValue(0),
},
system: {
getDevices: jest.fn().mockResolvedValue([vda, vdb])
},
staging: {
getDevices: jest.fn().mockResolvedValue([vda])
},
getErrors: jest.fn().mockResolvedValue([]),
isDeprecated: jest.fn().mockResolvedValue(false),
onDeprecate: jest.fn(),
onStatusChange: jest.fn()
/**
* @param {string} mountPath
* @returns {Volume}
*/
const volume = (mountPath) => {
return (
{
mountPath,
target: "DEFAULT",
fsType: "Btrfs",
minSize: 1024,
maxSize: 1024,
autoSize: false,
snapshots: false,
transactional: false,
outline: {
required: false,
fsTypes: ["Btrfs"],
supportAutoSize: false,
snapshotsConfigurable: false,
snapshotsAffectSizes: false,
sizeRelevantVolumes: [],
adjustByRam: false
}
}
);
};

/** @type {StorageClient} */
let storage;

/** @type {ProposalResult} */
let proposalResult;

beforeEach(() => {
storage = { ...storageMock, proposal: { ...storageMock.proposal } };
proposalResult = {
settings: {
target: "DISK",
targetPVDevices: [],
configureBoot: false,
bootDevice: "",
defaultBootDevice: "",
encryptionPassword: "",
encryptionMethod: "",
spacePolicy: "",
spaceActions: [],
volumes: [],
installationDevices: []
},
actions: []
};

storage = {
probe: jest.fn().mockResolvedValue(0),
// @ts-expect-error Some methods have to be private to avoid type complaint.
proposal: {
getAvailableDevices: jest.fn().mockResolvedValue([vda, vdb]),
getEncryptionMethods: jest.fn().mockResolvedValue([]),
getProductMountPoints: jest.fn().mockResolvedValue([]),
getResult: jest.fn().mockResolvedValue(proposalResult),
defaultVolume: jest.fn(mountPath => Promise.resolve(volume(mountPath))),
calculate: jest.fn().mockResolvedValue(0),
},
// @ts-expect-error Some methods have to be private to avoid type complaint.
system: {
getDevices: jest.fn().mockResolvedValue([vda, vdb])
},
// @ts-expect-error Some methods have to be private to avoid type complaint.
staging: {
getDevices: jest.fn().mockResolvedValue([vda])
},
getErrors: jest.fn().mockResolvedValue([]),
isDeprecated: jest.fn().mockResolvedValue(false),
onDeprecate: jest.fn(),
onStatusChange: jest.fn()
};

// @ts-expect-error
createClient.mockImplementation(() => ({ storage }));
});

Expand All @@ -117,9 +184,8 @@ it("does not probe storage if the storage devices are not deprecated", async ()
});

it("loads the proposal data", async () => {
storage.proposal.getResult = jest.fn().mockResolvedValue(
{ settings: { target: "disk", targetDevice: vda.name } }
);
proposalResult.settings.target = "DISK";
proposalResult.settings.targetDevice = vda.name;

installerRender(<ProposalPage />);

Expand Down Expand Up @@ -152,8 +218,8 @@ describe("when the storage devices become deprecated", () => {
});

it("loads the proposal data", async () => {
const result = { settings: { target: "disk", targetDevice: vda.name } };
storage.proposal.getResult = jest.fn().mockResolvedValue(result);
proposalResult.settings.target = "DISK";
proposalResult.settings.targetDevice = vda.name;

const [mockFunction, callbacks] = createCallbackMock();
storage.onDeprecate = mockFunction;
Expand All @@ -162,7 +228,7 @@ describe("when the storage devices become deprecated", () => {

await screen.findByText(/\/dev\/vda/);

result.settings.targetDevice = vdb.name;
proposalResult.settings.targetDevice = vdb.name;

const [onDeprecateCb] = callbacks;
await act(() => onDeprecateCb());
Expand All @@ -172,28 +238,29 @@ describe("when the storage devices become deprecated", () => {
});

describe("when there is no proposal yet", () => {
beforeEach(() => {
storage.proposal.getResult = jest.fn().mockResolvedValue(undefined);
});

it("shows the page as loading", async () => {
proposalResult = undefined;

installerRender(<ProposalPage />);

screen.getAllByText(/PFSkeleton/);
await waitFor(() => expect(screen.queryByText(/Installation device/)).toBeNull());
});

it("loads the proposal when the service finishes to calculate", async () => {
const defaultResult = proposalResult;
proposalResult = undefined;

const [mockFunction, callbacks] = createCallbackMock();
storage.onStatusChange = mockFunction;

installerRender(<ProposalPage />);

screen.getAllByText(/PFSkeleton/);

storage.proposal.getResult = jest.fn().mockResolvedValue(
{ settings: { target: "disk", targetDevice: vda.name } }
);
proposalResult = defaultResult;
proposalResult.settings.target = "DISK";
proposalResult.settings.targetDevice = vda.name;

const [onStatusChangeCb] = callbacks;
await act(() => onStatusChangeCb(IDLE));
Expand All @@ -203,14 +270,13 @@ describe("when there is no proposal yet", () => {

describe("when there is a proposal", () => {
beforeEach(() => {
storage.proposal.getResult = jest.fn().mockResolvedValue(
{ settings: { target: "disk", targetDevice: vda.name } }
);
proposalResult.settings.target = "DISK";
proposalResult.settings.targetDevice = vda.name;
});

it("does not load the proposal when the service finishes to calculate", async () => {
const [mockFunction, callbacks] = createCallbackMock();
storage.proposal.onStatusChange = mockFunction;
storage.onStatusChange = mockFunction;

installerRender(<ProposalPage />);

Expand Down
Loading

0 comments on commit b80ba46

Please sign in to comment.