Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ const IdentityGroupsPanelConfirmModal: FC<Props> = ({
const modifiedGroupNames = Object.keys(identityGroupsChangeSummary);
const successMessage =
modifiedGroupNames.length > 1 ? (
`Updated groups for ${modifiedGroupNames.length} identities`
`Updated groups for ${modifiedGroupNames.length} identities.`
) : (
<>
Updated groups for{" "}
Expand All @@ -87,6 +87,7 @@ const IdentityGroupsPanelConfirmModal: FC<Props> = ({
value={modifiedGroupNames[0]}
to={`${ROOT_PATH}/ui/permissions/identities`}
/>
.
</>
);

Expand Down
1 change: 1 addition & 0 deletions src/util/instanceMigration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export const useInstanceMigration = ({
projectName={instance.project}
location={instance.location}
/>
.
</>
);
}
Expand Down
23 changes: 12 additions & 11 deletions tests/docs-screenshots.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { getClipPosition } from "./helpers/doc-screenshots";
import { openInstancePanel } from "./helpers/instancePanel";
import { deleteNetworkAcl } from "./helpers/network-acls";
import { dirDriver, storageDriverLabels } from "util/storageOptions";
import { dismissNotification } from "./helpers/notification";

test.beforeEach(() => {
test.skip(
Expand Down Expand Up @@ -173,7 +174,7 @@ test("networks", async ({ page }) => {

await page.getByPlaceholder("Enter name").fill(networkACL);
await page.getByRole("button", { name: "Create", exact: true }).click();
await page.getByTestId("notification-close-button").click();
await dismissNotification(page, `created`);
await page.getByRole("link", { name: networkACL }).click();
await page.getByText("Click the ACL name").waitFor();
await page.screenshot({
Expand Down Expand Up @@ -222,7 +223,7 @@ test("network peering", async ({ page }) => {
.click();
await page.getByText("Add rule").click();
await page.getByRole("button", { name: "Create", exact: true }).click();
await page.getByTestId("notification-close-button").click();
await dismissNotification(page, `created`);

// Create network
await createOvnUplink(page, uplinkNetwork);
Expand All @@ -242,7 +243,7 @@ test("network peering", async ({ page }) => {
network3,
true,
);
await page.getByTestId("notification-close-button").click();
await dismissNotification(page, `created`);
await page.screenshot({
path: "tests/screenshots/doc/images/networks/network_list_local_peerings.png",
clip: getClipPosition(240, 0, 1440, 450),
Expand Down Expand Up @@ -326,7 +327,7 @@ test("storage volumes", async ({ page }) => {
await page.getByPlaceholder("Enter value").fill("100");
await page.getByLabel("Select disk size unit").selectOption("MB");
await page.getByRole("button", { name: "Create", exact: true }).click();
await page.getByTestId("notification-close-button").click();
await dismissNotification(page, `created`);
await page.getByRole("link", { name: volumeName }).click();
await page.getByText("Overview").waitFor();
await page.screenshot({
Expand Down Expand Up @@ -467,8 +468,7 @@ test("LXD - Tutorial folder", async ({ page }) => {
});

await page.getByRole("button", { name: "Create and start" }).click();
await page.getByTestId("notification-close-button").click();
await page.getByText(`Created and started instance ${instance}.`).waitFor();
await dismissNotification(page, `Created and started instance ${instance}.`);
await openInstancePanel(page, instance);
await page.getByText("Instance summary").click();
await page.screenshot({
Expand Down Expand Up @@ -550,9 +550,10 @@ test("LXD - Tutorial - Graphical consoles", async ({ page }) => {
await page
.getByRole("button", { name: "Create and start", exact: true })
.click();
await page.getByTestId("notification-close-button").click();
await page.getByRole("link", { name: vminstance }).first().waitFor();
await page.getByText(`Created and started instance ${vminstance}.`).waitFor();
await dismissNotification(
page,
`Created and started instance ${vminstance}.`,
);
await visitInstance(page, vminstance);
await page.getByText("General").click();
await page.getByTestId("tab-link-Console").click();
Expand Down Expand Up @@ -763,7 +764,7 @@ test("LXD - UI Folder - Networks", async ({ page }) => {

await page.getByLabel("Delete port 0").click();
await page.getByRole("button", { name: "Create" }).click();
await page.getByTestId("notification-close-button").click();
await dismissNotification(page, `created`);
await page.screenshot({
path: "tests/screenshots/doc/images/UI/forward_delete.png",
clip: getClipPosition(240, 0, 1440, 360),
Expand All @@ -781,7 +782,7 @@ test("LXD - UI Folder - Networks", async ({ page }) => {
});

await page.getByRole("button", { name: "Update" }).click();
await page.getByTestId("notification-close-button").click();
await dismissNotification(page, `updated`);
await expect(page.getByTitle("Edit network forward")).toBeVisible();
await page.screenshot({
path: "tests/screenshots/doc/images/UI/forward_edit_ex1.png",
Expand Down
7 changes: 4 additions & 3 deletions tests/helpers/cluster-groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { gotoURL } from "./navigate";
import { randomNameSuffix } from "./name";
import type { LxdVersions } from "../fixtures/lxd-test";
import { test } from "../fixtures/lxd-test";
import { dismissNotification } from "./notification";

export const skipIfNotSupported = (lxdVersion: LxdVersions) => {
test.skip(
Expand Down Expand Up @@ -35,7 +36,7 @@ export const createClusterGroup = async (page: Page, group: string) => {
const panel = page.getByLabel("Side panel");
await panel.getByRole("button", { name: "Create group" }).click();

await page.waitForSelector(`text=Cluster group ${group} created.`);
await dismissNotification(page, `Cluster group ${group} created.`);
};

export const deleteClusterGroup = async (page: Page, group: string) => {
Expand All @@ -48,7 +49,7 @@ export const deleteClusterGroup = async (page: Page, group: string) => {
.click();
await page.getByText("Delete", { exact: true }).click();

await page.waitForSelector(`text=Cluster group ${group} deleted.`);
await dismissNotification(page, `Cluster group ${group} deleted.`);
};

export const toggleClusterGroupMember = async (
Expand All @@ -69,5 +70,5 @@ export const toggleClusterGroupMember = async (
.click();
await page.getByRole("button", { name: "Save changes" }).click();

await page.waitForSelector(`text=Cluster group ${group} saved.`);
await dismissNotification(page, `Cluster group ${group} saved.`);
};
3 changes: 2 additions & 1 deletion tests/helpers/cluster-links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { expect, test } from "../fixtures/lxd-test";
import { randomNameSuffix } from "./name";
import type { Page } from "@playwright/test";
import { gotoURL } from "./navigate";
import { dismissNotification } from "./notification";

export const skipIfNotSupported = (lxdVersion: LxdVersions) => {
test.skip(
Expand Down Expand Up @@ -55,5 +56,5 @@ export const deleteClusterLink = async (page: Page, link: string) => {
.getByRole("button", { name: "Delete cluster link" })
.click();

await page.waitForSelector(`text=Cluster link ${link} deleted.`);
await dismissNotification(page, `Cluster link ${link} deleted.`);
};
3 changes: 2 additions & 1 deletion tests/helpers/images.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { expect } from "../fixtures/lxd-test";
import type { Page } from "@playwright/test";
import { gotoURL } from "./navigate";
import { dismissNotification } from "./notification";

export const visitLocalImages = async (page: Page, project: string) => {
await gotoURL(page, `/ui/project/${project}/local-images`);
Expand Down Expand Up @@ -38,5 +39,5 @@ export const deleteImage = async (page: Page, imageIdentifier: string) => {
.getByRole("button", { name: "Delete" })
.click();

await page.waitForSelector(`text=Image ${imageName} deleted.`);
await dismissNotification(page, `Image ${imageName} deleted.`);
};
7 changes: 3 additions & 4 deletions tests/helpers/instancePanel.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Page } from "@playwright/test";
import { expect } from "@playwright/test";
import { gotoURL } from "./navigate";
import { dismissNotification } from "./notification";

export const openInstancePanel = async (page: Page, instance: string) => {
await gotoURL(page, "/ui/");
Expand Down Expand Up @@ -30,8 +31,7 @@ export const startInstanceFromPanel = async (page: Page, instance: string) => {
const startButton = instanceDetailPanel.locator("css=button[title=Start]");
await startButton.click();

await page.waitForSelector(`text=Instance ${instance} started.`);
await page.getByTestId("notification-close-button").click();
await dismissNotification(page, `Instance ${instance} started.`);
await checkInstanceStatus(page, "Running");
};

Expand All @@ -49,8 +49,7 @@ export const stopInstanceFromPanel = async (page: Page, instance: string) => {
});
await confirmStopButton.click();

await page.waitForSelector(`text=Instance ${instance} stopped.`);
await page.getByTestId("notification-close-button").click();
await dismissNotification(page, `Instance ${instance} stopped.`);
await checkInstanceStatus(page, "Stopped");
};

Expand Down
28 changes: 13 additions & 15 deletions tests/helpers/instances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { gotoURL } from "./navigate";
import { expect } from "../fixtures/lxd-test";
import { visitLocalImages } from "./images";
import { searchEntityListPage } from "./search";
import { dismissNotification } from "./notification";

const DEFAULT_IMAGE = "alpine/3.23/cloud";

Expand Down Expand Up @@ -82,8 +83,7 @@ export const saveInstance = async (
const name =
changeCount === 1 ? "Save 1 change" : `Save ${changeCount} changes`;
await page.getByRole("button", { name }).click();
await expect(page.getByText(`Instance ${instance} updated.`)).toBeVisible();
await page.getByRole("button", { name: "Close notification" }).click();
await dismissNotification(page, `Instance ${instance} updated.`);
};

export const forceStopInstance = async (
Expand All @@ -95,8 +95,7 @@ export const forceStopInstance = async (
await page.getByRole("button", { name: "Stop" }).click();
await page.getByText("Force stop").click();
await page.getByText("Stop", { exact: true }).click();
await expect(page.getByText(`Instance ${instance} stopped.`)).toBeVisible();
await page.getByTestId("notification-close-button").click();
await dismissNotification(page, `Instance ${instance} stopped.`);
};

export const deleteInstance = async (
Expand All @@ -117,7 +116,7 @@ export const deleteInstance = async (
.getByRole("dialog", { name: "Confirm delete" })
.getByRole("button", { name: "Delete" })
.click();
await page.waitForSelector(`text=Instance ${instance} deleted.`);
await dismissNotification(page, `Instance ${instance} deleted.`);
};

export const renameInstance = async (
Expand All @@ -130,7 +129,7 @@ export const renameInstance = async (
await page.getByRole("textbox").press("Control+a");
await page.getByRole("textbox").fill(newName);
await page.getByRole("button", { name: "Save" }).click();
await page.waitForSelector(`text=Instance ${oldName} renamed to ${newName}.`);
await dismissNotification(page, `Instance ${oldName} renamed to ${newName}.`);
};

export const createAndStartInstance = async (
Expand Down Expand Up @@ -158,14 +157,13 @@ export const createAndStartInstance = async (
.getByRole("combobox", { name: "Instance type" })
.selectOption(type);
await page.getByRole("button", { name: "Create and start" }).first().click();

await page.waitForSelector(`text=Created and started instance ${instance}.`);
await page.getByText(`Created and started instance ${instance}.`).waitFor();
};

export const visitAndStartInstance = async (page: Page, instance: string) => {
await visitInstance(page, instance);
await page.getByRole("button", { name: "Start", exact: true }).click();
await page.waitForSelector(`text=Instance ${instance} started.`);
await dismissNotification(page, `Instance ${instance} started.`);
};

export const visitAndStopInstance = async (page: Page, instance: string) => {
Expand All @@ -175,7 +173,7 @@ export const visitAndStopInstance = async (page: Page, instance: string) => {
await page.keyboard.down("Shift");
await stopButton.click();
await page.keyboard.up("Shift");
await page.waitForSelector(`text=Instance ${instance} stopped.`);
await dismissNotification(page, `Instance ${instance} stopped.`);
}
};

Expand All @@ -189,7 +187,7 @@ export const createImageFromInstance = async (
await page.getByRole("button", { name: "Create Image" }).click();
await page.getByLabel("Alias").fill(imageAlias);
await page.getByText("Create image", { exact: true }).click();
await page.waitForSelector(`text=Image created from instance ${instance}.`);
await dismissNotification(page, `Image created from instance ${instance}.`);
};

export const removeCustomImages = async (page: Page) => {
Expand All @@ -204,8 +202,7 @@ export const removeCustomImages = async (page: Page) => {
await page.keyboard.down("Shift");
await row.getByRole("button", { name: "Delete" }).click();
await page.keyboard.up("Shift");
await page.waitForSelector("text=/Image .* deleted\\./");
await page.getByTestId("notification-close-button").click();
await dismissNotification(page, `deleted`);
}
}
};
Expand All @@ -229,7 +226,8 @@ export const migrateInstanceRootStorage = async (
.getByLabel("Confirm migration")
.getByRole("button", { name: "Migrate", exact: true })
.click();
await page.waitForSelector(
`text=Instance ${instance} root storage successfully moved to pool ${pool}`,
await dismissNotification(
page,
`Instance ${instance} root storage successfully moved to pool ${pool}.`,
);
};
12 changes: 7 additions & 5 deletions tests/helpers/network-acls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { randomNameSuffix } from "./name";
import { gotoURL } from "./navigate";
import { expect } from "../fixtures/lxd-test";
import { visitNetwork } from "./network";
import { dismissNotification } from "./notification";

export const randomNetworkAclName = (): string => {
return `test-${randomNameSuffix()}`;
Expand All @@ -26,7 +27,7 @@ export const createNetworkAcl = async (page: Page, networkAcl: string) => {
await page.getByRole("button", { name: "Add rule", exact: true }).click();

await page.getByRole("button", { name: "Create", exact: true }).click();
await page.waitForSelector(`text=Network ACL ${networkAcl} created.`);
await dismissNotification(page, `Network ACL ${networkAcl} created.`);
};

export const editNetworkAcl = async (page: Page, networkAcl: string) => {
Expand All @@ -39,7 +40,7 @@ export const editNetworkAcl = async (page: Page, networkAcl: string) => {
await page.getByRole("button", { name: "Remove rule", exact: true }).click();

await page.getByRole("button", { name: "Save 2 changes" }).click();
await page.waitForSelector(`text=Network ACL ${networkAcl} updated.`);
await dismissNotification(page, `Network ACL ${networkAcl} updated.`);

await expect(page.getByText("desc-value")).not.toBeVisible();
await expect(page.getByText("1.2.3.4:23")).not.toBeVisible();
Expand All @@ -55,8 +56,9 @@ export const renameNetworkAcl = async (
await page.locator("li", { hasText: oldName }).click();
await page.getByRole("textbox").first().fill(newName);
await page.getByRole("button", { name: "Save" }).click();
await page.waitForSelector(
`text=Network ACL ${oldName} renamed to ${newName}.`,
await dismissNotification(
page,
`Network ACL ${oldName} renamed to ${newName}.`,
);
};

Expand All @@ -68,7 +70,7 @@ export const deleteNetworkAcl = async (page: Page, networkAcl: string) => {
.getByRole("button", { name: "Delete" })
.click();

await page.waitForSelector(`text=Network ACL ${networkAcl} deleted.`);
await dismissNotification(page, `Network ACL ${networkAcl} deleted.`);
};

export const visitNetworkAcl = async (page: Page, networkAcl: string) => {
Expand Down
3 changes: 2 additions & 1 deletion tests/helpers/notification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ export const checkNotificationHidden = async (page: Page) => {
await expect(notification).toBeHidden();
};

export const dismissNotification = async (page: Page) => {
export const dismissNotification = async (page: Page, caption: string) => {
await page.getByText(caption).waitFor();
const notification = page.locator(".toast-notification");
await notification
.getByRole("button", { name: "Close notification" })
Expand Down
2 changes: 1 addition & 1 deletion tests/helpers/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ import type { Page } from "@playwright/test";
import { expect } from "../fixtures/lxd-test";

export const validateOperation = async (page: Page, title: string) => {
await page.getByText("Operations").click();
await page.getByText("Operations", { exact: true }).click();
await expect(page.getByText(title)).toBeVisible();
};
Loading
Loading