This is an automated email from the ASF dual-hosted git repository.

yasithdev pushed a commit to branch feat/generic-experiment-launcher
in repository https://gitbox.apache.org/repos/asf/airavata-portals.git

commit 0064d23c67e88e86608bc72b04d0068e6739e1cc
Author: yasithdev <[email protected]>
AuthorDate: Fri Apr 24 23:17:10 2026 -0400

    test(launcher): Playwright error-path coverage (gate, preview fail, project 
change)
---
 .../tests/e2e/specs/launch-error-paths.spec.ts     | 60 ++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/airavata-django-portal/tests/e2e/specs/launch-error-paths.spec.ts 
b/airavata-django-portal/tests/e2e/specs/launch-error-paths.spec.ts
new file mode 100644
index 000000000..6d50c17a4
--- /dev/null
+++ b/airavata-django-portal/tests/e2e/specs/launch-error-paths.spec.ts
@@ -0,0 +1,60 @@
+import { test, expect } from "../fixtures/auth";
+
+test("strict-forward gate: cannot click tab 2 before tab 1 is valid", async ({ 
page }) => {
+  await page.goto("/workspace/launch");
+  await expect(page.locator("button[role='tab']").nth(1)).toBeDisabled();
+});
+
+test("preview failure shows error and disables launch", async ({ page }) => {
+  // Intercept the preview endpoint and return 502
+  await page.route("**/api/launcher/experiment-drafts/preview/", (route) =>
+    route.fulfill({ status: 502, body: JSON.stringify({ message: "airavata 
down" }) }),
+  );
+
+  await page.goto("/workspace/launch");
+  await page.getByPlaceholder(/Experiment name/i).fill("err-stub");
+  await page.locator("select[data-test='exp-project']").selectOption({ index: 
1 });
+  await page.locator("[data-test='app-tile-namd']").click();
+  await page.locator("[data-test='iface-card-run']").click();
+  // Pick a storage for sim_dir and fill its path
+  const storageSelects = page.locator("select").filter({ hasText: /My 
Home|Bridges/ });
+  await storageSelects.first().selectOption({ index: 1 });
+  await page.locator("input[data-test='file-path-sim_dir']").fill("/x");
+  await page.locator("input[data-test='scalar-steps']").fill("1");
+  await page.locator("input[data-test='file-out-path-trajectory']").fill("/y");
+  await page.locator("button[role='tab']").nth(1).click();
+  await page.locator("select[data-test='cr']").selectOption("bridges-2");
+  await page.locator("select[data-test='partition']").selectOption("RM");
+  await page.locator("button[role='tab']").nth(2).click();
+
+  await expect(page.locator(".alert-danger")).toContainText("airavata down");
+  await expect(page.locator("button[data-test='launch']")).toBeDisabled();
+});
+
+test("project change clears runtime selections", async ({ page }) => {
+  await page.goto("/workspace/launch");
+  await page.getByPlaceholder(/Experiment name/i).fill("proj-change");
+  await page.locator("select[data-test='exp-project']").selectOption({ index: 
1 });
+
+  // The confirm dialog is what we're testing — accept it when prompted
+  page.on("dialog", (d) => d.accept());
+
+  await page.locator("[data-test='app-tile-namd']").click();
+  await page.locator("[data-test='iface-card-run']").click();
+  // Storage + path for sim_dir
+  const storageSelects = page.locator("select").filter({ hasText: /My 
Home|Bridges/ });
+  await storageSelects.first().selectOption({ index: 1 });
+  await page.locator("input[data-test='file-path-sim_dir']").fill("/x");
+  await page.locator("input[data-test='scalar-steps']").fill("1");
+  await page.locator("input[data-test='file-out-path-trajectory']").fill("/y");
+  await page.locator("button[role='tab']").nth(1).click();
+  await page.locator("select[data-test='cr']").selectOption("bridges-2");
+
+  // Switch project — the dropdown only has projects from session data; pick 
the second.
+  // If only one project exists, this test no-ops on the assertion below.
+  const opts = await page.locator("select[data-test='exp-project'] 
option").allTextContents();
+  if (opts.length > 2) {
+    await page.locator("select[data-test='exp-project']").selectOption({ 
index: 2 });
+    await expect(page.locator("select[data-test='cr']")).toHaveValue("");
+  }
+});

Reply via email to