diff --git a/apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx b/apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx index 3fd1b60c0..33f3f7ef7 100644 --- a/apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx +++ b/apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx @@ -1,8 +1,66 @@ import { testEnvConfig } from "../fixture/test-env.config"; import { DeployBasePage } from "./DeployBasePage"; + export class BuildTemplatePage extends DeployBasePage { async gotoInteractive() { await this.page.goto(testEnvConfig.BASE_URL); await this.page.getByTestId("sidebar-sdl-builder-link").first().click(); } + + async fillImageName(imageName: string) { + await this.page.getByTestId("image-name-input").fill(imageName); + } + + async addService() { + await this.page.getByRole("button", { name: /add service/i }).click(); + } + + async clickDeploy() { + await this.page.getByRole("button", { name: /^deploy$/i }).click(); + } + + async clickPreview() { + await this.page.getByRole("button", { name: /preview/i }).click(); + } + + async clickReset() { + await this.page.getByRole("button", { name: /reset/i }).click(); + } + + getPreviewTextLocator(text: string) { + return this.page.getByText(text).first(); + } + + async closePreview() { + await this.page.getByRole("button", { name: /close/i }).first().click(); + } + + getImageNameInput() { + return this.page.getByTestId("image-name-input"); + } + + getDeployButton() { + return this.page.getByRole("button", { name: /^deploy$/i }); + } + + getPreviewButton() { + return this.page.getByRole("button", { name: /preview/i }); + } + + getAddServiceButton() { + return this.page.getByRole("button", { name: /add service/i }); + } + + getServiceLocator(serviceName: string) { + const escapedName = serviceName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + return this.page.getByText(new RegExp(`${escapedName}:`)).first(); + } + + getServiceNameInput(serviceName: string) { + return this.page.getByRole("textbox").filter({ hasText: serviceName }); + } + + async waitForServiceAdded(serviceName: string, timeout = 10000) { + await this.page.locator(`input[type="text"][value="${serviceName}"]`).first().waitFor({ state: "visible", timeout }); + } } diff --git a/apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts b/apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts new file mode 100644 index 000000000..4b285bbcb --- /dev/null +++ b/apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts @@ -0,0 +1,107 @@ +import type { BrowserContext, Page } from "@playwright/test"; + +import { expect, test } from "./fixture/base-test"; +import { BuildTemplatePage } from "./pages/BuildTemplatePage"; + +test.describe("SDL Builder Deployment Flow", () => { + test("navigate to SDL builder page", async ({ page, context }) => { + const { sdlBuilderPage } = await setup({ page, context }); + + await expect(sdlBuilderPage.getDeployButton()).toBeVisible(); + await expect(sdlBuilderPage.getPreviewButton()).toBeVisible(); + await expect(sdlBuilderPage.getAddServiceButton()).toBeVisible(); + }); + + test("fill image name and preview SDL", async ({ page, context }) => { + const { sdlBuilderPage } = await setup({ page, context, imageName: "nginx:latest" }); + + await sdlBuilderPage.clickPreview(); + + await expect(sdlBuilderPage.getPreviewTextLocator("nginx:latest")).toBeVisible(); + await expect(sdlBuilderPage.getPreviewTextLocator("version:")).toBeVisible(); + await expect(sdlBuilderPage.getPreviewTextLocator("services:")).toBeVisible(); + + await sdlBuilderPage.closePreview(); + }); + + test("create deployment from SDL builder", async ({ page, context }) => { + const { sdlBuilderPage } = await setup({ page, context, imageName: "nginx:alpine" }); + + await sdlBuilderPage.clickDeploy(); + + await expect(page.getByTestId("connect-wallet-btn").first()).toBeVisible({ timeout: 10000 }); + }); + + test("add multiple services", async ({ page, context }) => { + const { sdlBuilderPage } = await setup({ page, context, imageName: "nginx:latest" }); + + await sdlBuilderPage.addService(); + + await sdlBuilderPage.waitForServiceAdded("service-2"); + + await sdlBuilderPage.clickPreview(); + await expect(sdlBuilderPage.getPreviewTextLocator("service-1")).toBeVisible(); + await expect(sdlBuilderPage.getPreviewTextLocator("service-2")).toBeVisible(); + await sdlBuilderPage.closePreview(); + }); + + test("preview SDL with different images", async ({ page, context }) => { + const { sdlBuilderPage } = await setup({ page, context }); + + const images = ["postgres:15", "redis:7", "node:18-alpine"]; + + for (const image of images) { + await sdlBuilderPage.fillImageName(image); + await sdlBuilderPage.clickPreview(); + await expect(sdlBuilderPage.getPreviewTextLocator(image)).toBeVisible(); + await sdlBuilderPage.closePreview(); + } + }); + + test("verify SDL YAML structure", async ({ page, context }) => { + const { sdlBuilderPage } = await setup({ page, context, imageName: "ubuntu:22.04" }); + + await sdlBuilderPage.clickPreview(); + + await expect(sdlBuilderPage.getPreviewTextLocator("version:")).toBeVisible(); + await expect(sdlBuilderPage.getPreviewTextLocator("services:")).toBeVisible(); + await expect(sdlBuilderPage.getPreviewTextLocator("profiles:")).toBeVisible(); + await expect(sdlBuilderPage.getPreviewTextLocator("deployment:")).toBeVisible(); + + await sdlBuilderPage.closePreview(); + }); + + test("add service then preview shows both services", async ({ page, context }) => { + const { sdlBuilderPage } = await setup({ page, context, imageName: "nginx:latest" }); + + await sdlBuilderPage.addService(); + await sdlBuilderPage.waitForServiceAdded("service-2"); + + await sdlBuilderPage.clickPreview(); + + await expect(sdlBuilderPage.getServiceLocator("service-1")).toBeVisible(); + await expect(sdlBuilderPage.getServiceLocator("service-2")).toBeVisible(); + + await sdlBuilderPage.closePreview(); + }); + + test("preview button always available with valid image", async ({ page, context }) => { + const sdlBuilderPage = new BuildTemplatePage(context, page, "sdl-builder"); + await sdlBuilderPage.gotoInteractive(); + + await sdlBuilderPage.fillImageName("alpine:latest"); + + await expect(sdlBuilderPage.getPreviewButton()).toBeEnabled(); + }); + + async function setup({ page, context, imageName }: { page: Page; context: BrowserContext; imageName?: string }) { + const sdlBuilderPage = new BuildTemplatePage(context, page, "sdl-builder"); + await sdlBuilderPage.gotoInteractive(); + + if (imageName) { + await sdlBuilderPage.fillImageName(imageName); + } + + return { sdlBuilderPage }; + } +});