Remove Cypress and update scripts to use Playwright for E2E testing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit f828bd0423)
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -15,11 +15,6 @@ coverage
|
||||
*.local
|
||||
/dist
|
||||
|
||||
# Cypress
|
||||
cypress.env.json
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Playwright
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2023-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
|
||||
// cindy.chang@dsp.im (Cindy Chang), 2024/8/12
|
||||
// imacat.yang@dsp.im (imacat), 2026/3/5
|
||||
/**
|
||||
* @module cypress.config
|
||||
* Cypress E2E test configuration with viewport
|
||||
* settings and base URL.
|
||||
*/
|
||||
|
||||
const { defineConfig } = require("cypress");
|
||||
|
||||
module.exports = defineConfig({
|
||||
defaultCommandTimeout: 6000,
|
||||
viewportWidth: 1280,
|
||||
viewportHeight: 720,
|
||||
e2e: {
|
||||
baseUrl: "http://localhost:4173",
|
||||
specPattern: "cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}",
|
||||
},
|
||||
includeShadowDom: true,
|
||||
env: {},
|
||||
});
|
||||
@@ -1,32 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("Account Management", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
});
|
||||
|
||||
it("displays user list on account admin page", () => {
|
||||
cy.visit("/account-admin");
|
||||
// Should display users from fixture
|
||||
cy.contains("Test Admin").should("exist");
|
||||
cy.contains("Alice Wang").should("exist");
|
||||
cy.contains("Bob Chen").should("exist");
|
||||
});
|
||||
|
||||
it("shows active/inactive status badges", () => {
|
||||
cy.visit("/account-admin");
|
||||
cy.contains("Test Admin").should("exist");
|
||||
// The user list should show status indicators
|
||||
cy.contains("testadmin").should("exist");
|
||||
});
|
||||
|
||||
it("navigates to my-account page", () => {
|
||||
cy.visit("/my-account");
|
||||
cy.url().should("include", "/my-account");
|
||||
});
|
||||
});
|
||||
@@ -1,72 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2024-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// cindy.chang@dsp.im (Cindy Chang), 2024/07/03
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../../support/intercept";
|
||||
|
||||
const MSG_ACCOUNT_NOT_UNIQUE = "Account has already been registered.";
|
||||
|
||||
describe("Account duplication check.", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/account-admin");
|
||||
cy.contains("Test Admin").should("exist");
|
||||
});
|
||||
|
||||
it("When an account already exists, show error message on confirm.", () => {
|
||||
const testAccountName = "000000";
|
||||
|
||||
// First creation: account doesn't exist yet — override via MSW
|
||||
cy.window().then((win) => {
|
||||
const { http, HttpResponse } = win.__msw__;
|
||||
win.__mswWorker__.use(
|
||||
http.get("/api/users/000000", () =>
|
||||
HttpResponse.json(
|
||||
{ detail: "Not found" },
|
||||
{ status: 404 },
|
||||
)),
|
||||
);
|
||||
});
|
||||
|
||||
cy.contains("button", "Create New").should("be.visible").click();
|
||||
cy.get("#input_account_field").type(testAccountName);
|
||||
cy.get("#input_name_field").type(testAccountName);
|
||||
cy.get("#input_first_pwd").type(testAccountName);
|
||||
cy.get(".checkbox-and-text").first().find("div").first().click();
|
||||
|
||||
cy.contains("button", "Confirm")
|
||||
.should("be.visible")
|
||||
.and("be.enabled")
|
||||
.click();
|
||||
cy.contains("Account added").should("be.visible");
|
||||
|
||||
// Second creation: now account exists — override to return 200 via MSW
|
||||
cy.window().then((win) => {
|
||||
const { http, HttpResponse } = win.__msw__;
|
||||
win.__mswWorker__.use(
|
||||
http.get("/api/users/000000", () =>
|
||||
HttpResponse.json({
|
||||
username: "000000",
|
||||
name: "000000",
|
||||
is_admin: false,
|
||||
is_active: true,
|
||||
roles: [],
|
||||
})),
|
||||
);
|
||||
});
|
||||
|
||||
cy.contains("button", "Create New").should("be.visible").click();
|
||||
cy.get("#input_account_field").type(testAccountName);
|
||||
cy.get("#input_name_field").type(testAccountName);
|
||||
cy.get("#input_first_pwd").type(testAccountName);
|
||||
cy.get(".checkbox-and-text").first().find("div").first().click();
|
||||
|
||||
cy.contains("button", "Confirm")
|
||||
.should("be.visible")
|
||||
.and("be.enabled")
|
||||
.click();
|
||||
cy.contains(MSG_ACCOUNT_NOT_UNIQUE).should("be.visible");
|
||||
});
|
||||
});
|
||||
@@ -1,36 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2024-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// cindy.chang@dsp.im (Cindy Chang), 2024/07/02
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../../support/intercept";
|
||||
|
||||
describe("Password validation on create account.", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/account-admin");
|
||||
cy.contains("Test Admin").should("exist");
|
||||
});
|
||||
|
||||
it("When password is too short, confirm button stays disabled.", () => {
|
||||
cy.contains("button", "Create New").should("be.visible").click();
|
||||
|
||||
cy.get("#input_account_field").type("unit-test-0001");
|
||||
cy.get("#input_name_field").type("unit-test-0001");
|
||||
// Password shorter than 6 characters
|
||||
cy.get("#input_first_pwd").type("aaa");
|
||||
|
||||
cy.contains("button", "Confirm").should("be.disabled");
|
||||
});
|
||||
|
||||
it("When password meets minimum length, confirm button enables.", () => {
|
||||
cy.contains("button", "Create New").should("be.visible").click();
|
||||
|
||||
cy.get("#input_account_field").type("unit-test-0001");
|
||||
cy.get("#input_name_field").type("unit-test-0001");
|
||||
cy.get("#input_first_pwd").type("aaaaaa");
|
||||
|
||||
cy.contains("button", "Confirm").should("be.enabled");
|
||||
});
|
||||
});
|
||||
@@ -1,50 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2024-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// cindy.chang@dsp.im (Cindy Chang), 2024/07/02
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../../support/intercept";
|
||||
|
||||
describe("Create an Account", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/account-admin");
|
||||
cy.contains("Test Admin").should("exist");
|
||||
// Override: new usernames should return 404 (account doesn't exist yet)
|
||||
cy.window().then((win) => {
|
||||
const { http, HttpResponse } = win.__msw__;
|
||||
win.__mswWorker__.use(
|
||||
http.get("/api/users/:username", ({ params }) => {
|
||||
if (params.username.startsWith("unit-test-")) {
|
||||
return HttpResponse.json(
|
||||
{ detail: "Not found" },
|
||||
{ status: 404 },
|
||||
);
|
||||
}
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("Create a new account with admin role; should show saved message.", () => {
|
||||
cy.contains("button", "Create New").should("be.visible").click();
|
||||
|
||||
cy.get("#input_account_field").type("unit-test-0001");
|
||||
cy.get("#input_name_field").type("unit-test-0001");
|
||||
cy.get("#input_first_pwd").type("aaaaaa");
|
||||
cy.get(".checkbox-and-text").first().find("div").first().click();
|
||||
|
||||
cy.contains("button", "Confirm")
|
||||
.should("be.visible")
|
||||
.and("be.enabled")
|
||||
.click();
|
||||
cy.contains("Account added").should("be.visible");
|
||||
});
|
||||
|
||||
it("Confirm button is disabled when required fields are empty.", () => {
|
||||
cy.contains("button", "Create New").should("be.visible").click();
|
||||
cy.get("#input_account_field").type("test");
|
||||
cy.contains("button", "Confirm").should("be.disabled");
|
||||
});
|
||||
});
|
||||
@@ -1,29 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2024-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// cindy.chang@dsp.im (Cindy Chang), 2024/07/03
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../../support/intercept";
|
||||
|
||||
describe("Delete an Account", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/account-admin");
|
||||
cy.contains("Test Admin").should("exist");
|
||||
});
|
||||
|
||||
it("Delete button opens confirmation modal and deletes on confirm.", () => {
|
||||
cy.get("img.delete-account").first().click();
|
||||
cy.contains("ARE YOU SURE TO DELETE").should("be.visible");
|
||||
cy.get("#sure_to_delete_acct_btn").click();
|
||||
cy.contains("Account deleted").should("be.visible");
|
||||
});
|
||||
|
||||
it("Cancel button closes the delete confirmation modal.", () => {
|
||||
cy.get("img.delete-account").first().click();
|
||||
cy.contains("ARE YOU SURE TO DELETE").should("be.visible");
|
||||
cy.get("#calcel_delete_acct_btn").click();
|
||||
cy.contains("ARE YOU SURE TO DELETE").should("not.exist");
|
||||
});
|
||||
});
|
||||
@@ -1,29 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2024-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// cindy.chang@dsp.im (Cindy Chang), 2024/07/03
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../../support/intercept";
|
||||
|
||||
const MODAL_TITLE_ACCOUNT_EDIT = "Account Edit";
|
||||
const MSG_ACCOUNT_EDITED = "Saved";
|
||||
|
||||
describe("Edit an account", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/account-admin");
|
||||
cy.contains("Test Admin").should("exist");
|
||||
});
|
||||
|
||||
it("Edit an account; modify name and see saved message.", () => {
|
||||
cy.get(".btn-edit").first().click();
|
||||
cy.contains("h1", MODAL_TITLE_ACCOUNT_EDIT).should("exist");
|
||||
cy.get("#input_name_field").clear();
|
||||
cy.get("#input_name_field").type("Updated Name");
|
||||
|
||||
cy.contains("button", "Confirm").should("be.visible").and("be.enabled");
|
||||
cy.contains("button", "Confirm").click();
|
||||
cy.contains(MSG_ACCOUNT_EDITED).should("be.visible");
|
||||
});
|
||||
});
|
||||
@@ -1,96 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("Account Management CRUD", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/account-admin");
|
||||
cy.contains("Test Admin").should("exist");
|
||||
});
|
||||
|
||||
it("shows Create New button", () => {
|
||||
cy.get("#create_new_acct_btn").should("exist");
|
||||
cy.get("#create_new_acct_btn").should("contain", "Create New");
|
||||
});
|
||||
|
||||
it("opens create new account modal", () => {
|
||||
cy.get("#create_new_acct_btn").click();
|
||||
cy.get("#modal_container").should("be.visible");
|
||||
cy.get("#modal_account_edit_or_create_new").should("be.visible");
|
||||
// Should show account, name, password fields
|
||||
cy.get("#input_account_field").should("exist");
|
||||
cy.get("#input_name_field").should("exist");
|
||||
cy.get("#input_first_pwd").should("exist");
|
||||
});
|
||||
|
||||
it("create account confirm is disabled when fields are empty", () => {
|
||||
cy.get("#create_new_acct_btn").click();
|
||||
cy.get(".confirm-btn").should("be.disabled");
|
||||
});
|
||||
|
||||
it("create account confirm enables when fields are filled", () => {
|
||||
cy.get("#create_new_acct_btn").click();
|
||||
cy.get("#input_account_field").type("newuser");
|
||||
cy.get("#input_name_field").type("New User");
|
||||
cy.get("#input_first_pwd").type("password1234");
|
||||
cy.get(".confirm-btn").should("not.be.disabled");
|
||||
});
|
||||
|
||||
it("cancel button closes the modal", () => {
|
||||
cy.get("#create_new_acct_btn").click();
|
||||
cy.get("#modal_container").should("be.visible");
|
||||
cy.get(".cancel-btn").click();
|
||||
cy.get("#modal_container").should("not.exist");
|
||||
});
|
||||
|
||||
it("close (X) button closes the modal", () => {
|
||||
cy.get("#create_new_acct_btn").click();
|
||||
cy.get("#modal_container").should("be.visible");
|
||||
cy.get('img[alt="X"]').click();
|
||||
cy.get("#modal_container").should("not.exist");
|
||||
});
|
||||
|
||||
it("double-click username opens account info modal", () => {
|
||||
// Double-click on the first account username
|
||||
cy.get(".account-cell").first().dblclick();
|
||||
cy.get("#modal_container").should("be.visible");
|
||||
});
|
||||
|
||||
it("delete button opens delete confirmation modal", () => {
|
||||
// Click the delete icon for a non-current user
|
||||
cy.get(".delete-account").first().click();
|
||||
cy.get("#modal_container").should("be.visible");
|
||||
cy.get("#modal_delete_acct_alert").should("be.visible");
|
||||
});
|
||||
|
||||
it("delete modal has Yes and No buttons", () => {
|
||||
cy.get(".delete-account").first().click();
|
||||
cy.get("#calcel_delete_acct_btn").should("exist");
|
||||
cy.get("#sure_to_delete_acct_btn").should("exist");
|
||||
});
|
||||
|
||||
it("delete modal No button closes the modal", () => {
|
||||
cy.get(".delete-account").first().click();
|
||||
cy.get("#calcel_delete_acct_btn").click();
|
||||
cy.get("#modal_container").should("not.exist");
|
||||
});
|
||||
|
||||
it("shows checkboxes for Set as Admin and Activate in create modal", () => {
|
||||
cy.get("#create_new_acct_btn").click();
|
||||
cy.get("#account_create_checkboxes_section").should("be.visible");
|
||||
cy.contains("Set as admin.").should("exist");
|
||||
cy.contains("Activate now.").should("exist");
|
||||
});
|
||||
|
||||
it("search bar filters user list", () => {
|
||||
// Search filters by username, not display name
|
||||
cy.get("#input_search").type("user1");
|
||||
cy.get('img[alt="search"]').click();
|
||||
// Should only show user1 (Alice Wang)
|
||||
cy.contains("user1").should("exist");
|
||||
});
|
||||
});
|
||||
@@ -1,40 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("Account Info Modal", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/account-admin");
|
||||
cy.contains("Test Admin").should("exist");
|
||||
});
|
||||
|
||||
it("double-click username opens info modal with user data", () => {
|
||||
cy.get(".account-cell").first().dblclick();
|
||||
cy.get("#modal_container").should("be.visible");
|
||||
cy.get("#acct_info_user_name").should("exist");
|
||||
});
|
||||
|
||||
it("info modal shows Account Information header", () => {
|
||||
cy.get(".account-cell").first().dblclick();
|
||||
cy.get("#modal_container").should("be.visible");
|
||||
cy.contains("Account Information").should("exist");
|
||||
});
|
||||
|
||||
it("info modal shows account visit info", () => {
|
||||
cy.get(".account-cell").first().dblclick();
|
||||
cy.get("#modal_container").should("be.visible");
|
||||
cy.get("#account_visit_info").should("exist");
|
||||
cy.get("#account_visit_info").should("contain", "Account:");
|
||||
});
|
||||
|
||||
it("info modal can be closed via X button", () => {
|
||||
cy.get(".account-cell").first().dblclick();
|
||||
cy.get("#modal_container").should("be.visible");
|
||||
cy.get('img[alt="X"]').click();
|
||||
cy.get("#modal_container").should("not.exist");
|
||||
});
|
||||
});
|
||||
@@ -1,87 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2024-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// chiayin.kuo@dsp.im (chiayin), 2024/02/22
|
||||
// cindy.chang@dsp.im (Cindy Chang), 2024/05/30
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("Compare", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
cy.contains("li", "COMPARE").click();
|
||||
});
|
||||
|
||||
it("Compare dropdown sorting options", () => {
|
||||
const expectedOptions = [
|
||||
"By File Name (A to Z)",
|
||||
"By File Name (Z to A)",
|
||||
"By Dependency (A to Z)",
|
||||
"By Dependency (Z to A)",
|
||||
"By File Type (A to Z)",
|
||||
"By File Type (Z to A)",
|
||||
"By Last Update (A to Z)",
|
||||
"By Last Update (Z to A)",
|
||||
];
|
||||
|
||||
cy.get(".p-select").click();
|
||||
cy.get(".p-select-list")
|
||||
.find(".p-select-option")
|
||||
.then(($options) => {
|
||||
const actualOptions = $options
|
||||
.map((index, elem) =>
|
||||
Cypress.$(elem).find(".p-select-option-label").text(),
|
||||
)
|
||||
.get();
|
||||
expect(actualOptions).to.deep.equal(expectedOptions);
|
||||
});
|
||||
});
|
||||
|
||||
it("Grid cards are rendered for compare file selection", () => {
|
||||
cy.get("#compareGridCards").find("li").should("have.length.greaterThan", 0);
|
||||
});
|
||||
|
||||
it("Compare button is disabled until two files are dragged", () => {
|
||||
cy.contains("button", "Compare").should("be.disabled");
|
||||
cy.get("#compareFile0").drag("#primaryDragCard");
|
||||
cy.get("#compareFile1").drag("#secondaryDragCard");
|
||||
cy.contains("button", "Compare").should("be.enabled");
|
||||
});
|
||||
|
||||
it("Enter Compare dashboard and see charts", () => {
|
||||
cy.get("#compareFile0").drag("#primaryDragCard");
|
||||
cy.get("#compareFile1").drag("#secondaryDragCard");
|
||||
cy.contains("button", "Compare").click();
|
||||
cy.url().should("include", "compare");
|
||||
|
||||
// Assert chart title spans are visible
|
||||
cy.contains("span", "Average Cycle Time").should("exist");
|
||||
cy.contains("span", "Cycle Efficiency").should("exist");
|
||||
cy.contains("span", "Average Processing Time").should("exist");
|
||||
cy.contains("span", "Average Processing Time by Activity").should("exist");
|
||||
cy.contains("span", "Average Waiting Time").should("exist");
|
||||
cy.contains("span", "Average Waiting Time between Activity").should(
|
||||
"exist",
|
||||
);
|
||||
});
|
||||
|
||||
it("Compare State button exists on dashboard", () => {
|
||||
cy.get("#compareFile0").drag("#primaryDragCard");
|
||||
cy.get("#compareFile1").drag("#secondaryDragCard");
|
||||
cy.contains("button", "Compare").click();
|
||||
|
||||
cy.get("#compareState").should("exist").and("be.visible");
|
||||
});
|
||||
|
||||
it("Sidebar shows time usage and frequency sections", () => {
|
||||
cy.get("#compareFile0").drag("#primaryDragCard");
|
||||
cy.get("#compareFile1").drag("#secondaryDragCard");
|
||||
cy.contains("button", "Compare").click();
|
||||
|
||||
cy.get("aside").should("exist");
|
||||
cy.get("aside li").should("have.length.greaterThan", 0);
|
||||
});
|
||||
});
|
||||
@@ -1,55 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("Discover Conformance Page", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/discover/log/297310264/conformance");
|
||||
cy.get(".p-radiobutton, [class*=conformance]").first().should("exist");
|
||||
});
|
||||
|
||||
it("page loads and loading overlay disappears", () => {
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
});
|
||||
|
||||
it("displays Rule Settings sidebar", () => {
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("Rule Settings").should("be.visible");
|
||||
});
|
||||
|
||||
it("displays Conformance Checking Results heading", () => {
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("Conformance Checking Results").should("be.visible");
|
||||
});
|
||||
|
||||
it("displays rule type radio options", () => {
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("Have activity").should("be.visible");
|
||||
cy.contains("Activity sequence").should("be.visible");
|
||||
cy.contains("Activity duration").should("be.visible");
|
||||
cy.contains("Processing time").should("be.visible");
|
||||
cy.contains("Waiting time").should("be.visible");
|
||||
cy.contains("Cycle time").should("be.visible");
|
||||
});
|
||||
|
||||
it("displays Clear and Apply buttons", () => {
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("button", "Clear").should("be.visible");
|
||||
cy.contains("button", "Apply").should("exist");
|
||||
});
|
||||
|
||||
it("displays Activity list area", () => {
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("Activity list").should("be.visible");
|
||||
});
|
||||
|
||||
it("displays default placeholder values in results", () => {
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("Conformance Rate").should("be.visible");
|
||||
cy.contains("Cases").should("be.visible");
|
||||
});
|
||||
});
|
||||
@@ -1,55 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("Discover Map Page", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/discover/log/297310264/map");
|
||||
cy.get("#cy").should("exist");
|
||||
});
|
||||
|
||||
it("page loads and cytoscape container exists", () => {
|
||||
cy.get("#cy").should("exist");
|
||||
});
|
||||
|
||||
it("displays left sidebar buttons", () => {
|
||||
// Visualization Setting, Filter, Traces buttons
|
||||
cy.get(".material-symbols-outlined")
|
||||
.contains("track_changes")
|
||||
.should("exist");
|
||||
cy.get(".material-symbols-outlined").contains("tornado").should("exist");
|
||||
cy.get(".material-symbols-outlined").contains("rebase").should("exist");
|
||||
});
|
||||
|
||||
it("displays right sidebar Summary button", () => {
|
||||
cy.get("#sidebar_state").should("exist");
|
||||
cy.get("#iconState").should("exist");
|
||||
});
|
||||
|
||||
it("clicking Visualization Setting button toggles sidebar", () => {
|
||||
// Click the track_changes icon (Visualization Setting)
|
||||
cy.contains("span.material-symbols-outlined", "track_changes")
|
||||
.parent("li")
|
||||
.click();
|
||||
// SidebarView should open
|
||||
cy.contains("Visualization Setting").should("be.visible");
|
||||
});
|
||||
|
||||
it("clicking Summary button toggles sidebar", () => {
|
||||
cy.get("#iconState").click();
|
||||
// SidebarState should open with insights/stats
|
||||
cy.contains("Summary").should("be.visible");
|
||||
});
|
||||
|
||||
it("clicking Traces button toggles sidebar", () => {
|
||||
cy.contains("span.material-symbols-outlined", "rebase")
|
||||
.parent("li")
|
||||
.click();
|
||||
// SidebarTraces should open
|
||||
cy.contains("Traces").should("be.visible");
|
||||
});
|
||||
});
|
||||
@@ -1,66 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("Discover Performance Page", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/discover/log/297310264/performance");
|
||||
cy.get(".chart-container, canvas").should("exist");
|
||||
});
|
||||
|
||||
it("page loads and loading overlay disappears", () => {
|
||||
// Loading overlay should not be visible after data loads
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
});
|
||||
|
||||
it("displays Time Usage sidebar section", () => {
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("Time Usage").should("be.visible");
|
||||
});
|
||||
|
||||
it("displays Frequency sidebar section", () => {
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("Frequency").should("be.visible");
|
||||
});
|
||||
|
||||
it("displays sidebar navigation items", () => {
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("Cycle Time & Efficiency").should("be.visible");
|
||||
cy.contains("Processing Time").should("be.visible");
|
||||
cy.contains("Waiting Time").should("be.visible");
|
||||
cy.contains("Number of Cases").should("be.visible");
|
||||
});
|
||||
|
||||
it("displays chart titles", () => {
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("Average Cycle Time").should("be.visible");
|
||||
cy.contains("Cycle Efficiency").should("be.visible");
|
||||
cy.contains("Average Processing Time").should("be.visible");
|
||||
cy.contains("Average Processing Time by Activity").should("be.visible");
|
||||
cy.contains("Average Waiting Time").should("be.visible");
|
||||
});
|
||||
|
||||
it("displays frequency chart titles", () => {
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("New Cases").should("be.visible");
|
||||
cy.contains("Number of Cases by Activity").should("be.visible");
|
||||
});
|
||||
|
||||
it("renders canvas elements for charts", () => {
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
// Chart.js renders into canvas elements
|
||||
cy.get("canvas").should("have.length.at.least", 5);
|
||||
});
|
||||
|
||||
it("sidebar navigation scrolls to section", () => {
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
// Click on "Waiting Time" in sidebar
|
||||
cy.contains("li", "Waiting Time").click();
|
||||
// The Waiting Time section should be in view
|
||||
cy.get("#waitingTime").should("exist");
|
||||
});
|
||||
});
|
||||
@@ -1,88 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("Discover Tab Navigation", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
});
|
||||
|
||||
describe("navigating from Map page", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("/discover/log/297310264/map");
|
||||
cy.get("#cy").should("exist");
|
||||
});
|
||||
|
||||
it("shows DISCOVER heading and MAP/CONFORMANCE/PERFORMANCE tabs", () => {
|
||||
cy.get("#nav_bar").contains("DISCOVER").should("be.visible");
|
||||
cy.get(".nav-item").should("have.length", 3);
|
||||
cy.get(".nav-item").eq(0).should("contain", "MAP");
|
||||
cy.get(".nav-item").eq(1).should("contain", "CONFORMANCE");
|
||||
cy.get(".nav-item").eq(2).should("contain", "PERFORMANCE");
|
||||
});
|
||||
|
||||
it("clicking PERFORMANCE tab navigates to performance page", () => {
|
||||
cy.get(".nav-item").contains("PERFORMANCE").click();
|
||||
cy.url().should("include", "/performance");
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("Time Usage").should("be.visible");
|
||||
});
|
||||
|
||||
it("clicking CONFORMANCE tab navigates to conformance page", () => {
|
||||
cy.get(".nav-item").contains("CONFORMANCE").click();
|
||||
cy.url().should("include", "/conformance");
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("Rule Settings").should("be.visible");
|
||||
});
|
||||
|
||||
it("shows back arrow to return to Files", () => {
|
||||
cy.get("#backPage").should("exist");
|
||||
cy.get("#backPage").should("have.attr", "href", "/files");
|
||||
});
|
||||
});
|
||||
|
||||
describe("navigating from Performance page", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("/discover/log/297310264/performance");
|
||||
cy.get(".chart-container, canvas").should("exist");
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
});
|
||||
|
||||
it("clicking MAP tab navigates to map page", () => {
|
||||
cy.get(".nav-item").contains("MAP").click();
|
||||
cy.url().should("include", "/map");
|
||||
cy.get("#cy").should("exist");
|
||||
});
|
||||
|
||||
it("clicking CONFORMANCE tab navigates to conformance page", () => {
|
||||
cy.get(".nav-item").contains("CONFORMANCE").click();
|
||||
cy.url().should("include", "/conformance");
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("Rule Settings").should("be.visible");
|
||||
});
|
||||
});
|
||||
|
||||
describe("navigating from Conformance page", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("/discover/log/297310264/conformance");
|
||||
cy.get(".p-radiobutton, [class*=conformance]").first().should("exist");
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
});
|
||||
|
||||
it("clicking MAP tab navigates to map page", () => {
|
||||
cy.get(".nav-item").contains("MAP").click();
|
||||
cy.url().should("include", "/map");
|
||||
cy.get("#cy").should("exist");
|
||||
});
|
||||
|
||||
it("clicking PERFORMANCE tab navigates to performance page", () => {
|
||||
cy.get(".nav-item").contains("PERFORMANCE").click();
|
||||
cy.url().should("include", "/performance");
|
||||
cy.get(String.raw`.z-\[9999\]`, { timeout: 10000 }).should("not.exist");
|
||||
cy.contains("Time Usage").should("be.visible");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,126 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("Edge Cases", () => {
|
||||
describe("Empty states", () => {
|
||||
it("files page handles empty file list", () => {
|
||||
loginWithFixtures();
|
||||
// Visit any page first to load the app and MSW
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
// Override files endpoint with empty array via MSW
|
||||
cy.window().then((win) => {
|
||||
const { http, HttpResponse } = win.__msw__;
|
||||
win.__mswWorker__.use(
|
||||
http.get("/api/files", () => HttpResponse.json([])),
|
||||
);
|
||||
});
|
||||
// Revisit to trigger the new empty response
|
||||
cy.visit("/files");
|
||||
// Table should exist but have no file data
|
||||
cy.get("table").should("exist");
|
||||
cy.contains("sample-process.xes").should("not.exist");
|
||||
});
|
||||
|
||||
it("account admin handles empty user list", () => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
// Override users endpoint with empty array via MSW
|
||||
cy.window().then((win) => {
|
||||
const { http, HttpResponse } = win.__msw__;
|
||||
win.__mswWorker__.use(
|
||||
http.get("/api/users", () => HttpResponse.json([])),
|
||||
);
|
||||
});
|
||||
cy.visit("/account-admin");
|
||||
// Create New button should exist even with no users
|
||||
cy.get("#create_new_acct_btn").should("exist");
|
||||
cy.contains("Test Admin").should("not.exist");
|
||||
});
|
||||
|
||||
it("unauthenticated user is redirected to login", () => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
// Override my-account to return 401
|
||||
cy.window().then((win) => {
|
||||
const { http, HttpResponse } = win.__msw__;
|
||||
win.__mswWorker__.use(
|
||||
http.get("/api/my-account", () =>
|
||||
new HttpResponse(null, { status: 401 }),
|
||||
),
|
||||
);
|
||||
});
|
||||
// Clear cookies to simulate logged out
|
||||
cy.clearCookies();
|
||||
cy.visit("/files");
|
||||
cy.url().should("include", "/login");
|
||||
});
|
||||
|
||||
it("unauthenticated user cannot access account-admin", () => {
|
||||
cy.visit("/account-admin");
|
||||
cy.url().should("include", "/login");
|
||||
});
|
||||
|
||||
it("unauthenticated user cannot access my-account", () => {
|
||||
cy.visit("/my-account");
|
||||
cy.url().should("include", "/login");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Login validation", () => {
|
||||
it("shows error on failed login", () => {
|
||||
// Visit login page first to load the app
|
||||
cy.visit("/login");
|
||||
cy.get("#login_btn_main_btn").should("exist");
|
||||
// Override token endpoint to return 401
|
||||
cy.window().then((win) => {
|
||||
const { http, HttpResponse } = win.__msw__;
|
||||
win.__mswWorker__.use(
|
||||
http.post("/api/oauth/token", () =>
|
||||
HttpResponse.json(
|
||||
{ detail: "Invalid credentials" },
|
||||
{ status: 401 },
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
cy.get("#account").type("wronguser");
|
||||
cy.get("#password").type("wrongpass");
|
||||
cy.get("#login_btn_main_btn").click();
|
||||
cy.url().should("include", "/login");
|
||||
});
|
||||
|
||||
it("confirm stays disabled with only account field filled", () => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/account-admin");
|
||||
cy.contains("Test Admin").should("exist");
|
||||
cy.contains("button", "Create New").click();
|
||||
cy.get("#input_account_field").type("onlyaccount");
|
||||
cy.contains("button", "Confirm").should("be.disabled");
|
||||
});
|
||||
|
||||
it("confirm stays disabled with only name field filled", () => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/account-admin");
|
||||
cy.contains("Test Admin").should("exist");
|
||||
cy.contains("button", "Create New").click();
|
||||
cy.get("#input_name_field").type("onlyname");
|
||||
cy.contains("button", "Confirm").should("be.disabled");
|
||||
});
|
||||
|
||||
it("confirm stays disabled with only password field filled", () => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/account-admin");
|
||||
cy.contains("Test Admin").should("exist");
|
||||
cy.contains("button", "Create New").click();
|
||||
cy.get("#input_first_pwd").type("onlypassword");
|
||||
cy.contains("button", "Confirm").should("be.disabled");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,74 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("File Operations", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
});
|
||||
|
||||
it("file list table has sortable columns", () => {
|
||||
// Check that table headers exist with expected columns
|
||||
cy.get("table").within(() => {
|
||||
cy.contains("th", "Name").should("exist");
|
||||
cy.contains("th", "Dependency").should("exist");
|
||||
cy.contains("th", "File Type").should("exist");
|
||||
cy.contains("th", "Owner").should("exist");
|
||||
cy.contains("th", "Last Update").should("exist");
|
||||
});
|
||||
});
|
||||
|
||||
it("clicking column header sorts the table", () => {
|
||||
// Click "Name" header to sort
|
||||
cy.contains("th", "Name").click();
|
||||
// After sorting, table should still have data
|
||||
cy.get("table tbody tr").should("have.length.greaterThan", 0);
|
||||
});
|
||||
|
||||
it("table rows show file data from fixture", () => {
|
||||
cy.get("table tbody").within(() => {
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
cy.contains("filtered-sample").should("exist");
|
||||
cy.contains("production-log.csv").should("exist");
|
||||
});
|
||||
});
|
||||
|
||||
it("table shows owner names", () => {
|
||||
cy.get("table tbody").within(() => {
|
||||
cy.contains("Test Admin").should("exist");
|
||||
cy.contains("Alice Wang").should("exist");
|
||||
});
|
||||
});
|
||||
|
||||
it("table shows file types", () => {
|
||||
cy.get("table tbody").within(() => {
|
||||
cy.contains("log").should("exist");
|
||||
});
|
||||
});
|
||||
|
||||
it("right-click on file row shows context menu", () => {
|
||||
// PrimeVue DataTable with contextmenu
|
||||
cy.get("table tbody tr").first().rightclick();
|
||||
// Context menu behavior depends on implementation
|
||||
// Just verify the right-click doesn't break anything
|
||||
cy.get("table tbody tr").should("have.length.greaterThan", 0);
|
||||
});
|
||||
|
||||
it("grid view shows file cards", () => {
|
||||
// Switch to grid view
|
||||
cy.get("svg").parent("li.cursor-pointer").last().click();
|
||||
// Grid cards should be visible
|
||||
cy.get("li[title]").should("have.length.greaterThan", 0);
|
||||
});
|
||||
|
||||
it("Import button opens upload modal", () => {
|
||||
cy.get("#import_btn").click();
|
||||
// Upload modal should appear
|
||||
cy.get("#import_btn").should("exist");
|
||||
});
|
||||
});
|
||||
@@ -1,60 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("Files Page", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/files");
|
||||
});
|
||||
|
||||
it("displays the file list after login", () => {
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
cy.contains("h2", "All Files").should("exist");
|
||||
// Should display file names from fixture
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
cy.contains("filtered-sample").should("exist");
|
||||
cy.contains("production-log.csv").should("exist");
|
||||
});
|
||||
|
||||
it("shows Recently Used section", () => {
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
cy.contains("h2", "Recently Used").should("exist");
|
||||
});
|
||||
|
||||
it("switches to DISCOVER tab", () => {
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
cy.contains(".nav-item", "DISCOVER").click();
|
||||
// DISCOVER tab shows filtered file types
|
||||
cy.contains("h2", "All Files").should("exist");
|
||||
});
|
||||
|
||||
it("switches to COMPARE tab and shows drag zones", () => {
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
cy.contains(".nav-item", "COMPARE").click();
|
||||
cy.contains("Performance Comparison").should("exist");
|
||||
cy.contains("Drag and drop a file here").should("exist");
|
||||
});
|
||||
|
||||
it("shows Import button on FILES tab", () => {
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
cy.get("#import_btn").should("contain", "Import");
|
||||
});
|
||||
|
||||
it("can switch between list and grid view", () => {
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
// DataTable (list view) should be visible by default
|
||||
cy.get("table").should("exist");
|
||||
});
|
||||
|
||||
it("double-click file navigates to discover page", () => {
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
// Double-click the first file row in the table
|
||||
// The actual route depends on file type (log→map, log-check→conformance, etc.)
|
||||
cy.get("table tbody tr").first().dblclick();
|
||||
cy.url().should("include", "/discover");
|
||||
});
|
||||
});
|
||||
@@ -1,49 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("Files Page - COMPARE Tab", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
// Switch to COMPARE tab
|
||||
cy.contains("li", "COMPARE").click();
|
||||
});
|
||||
|
||||
it("shows Performance Comparison heading", () => {
|
||||
cy.contains("h2", "Performance Comparison").should("be.visible");
|
||||
});
|
||||
|
||||
it("shows two drag-and-drop slots", () => {
|
||||
cy.get("#primaryDragCard").should("exist");
|
||||
cy.get("#secondaryDragCard").should("exist");
|
||||
});
|
||||
|
||||
it("drag slots show placeholder text", () => {
|
||||
cy.get("#primaryDragCard").should("contain", "Drag and drop a file here");
|
||||
cy.get("#secondaryDragCard").should("contain", "Drag and drop a file here");
|
||||
});
|
||||
|
||||
it("Compare button is disabled when no files are dragged", () => {
|
||||
cy.contains("button", "Compare").should("be.disabled");
|
||||
});
|
||||
|
||||
it("shows sorting dropdown", () => {
|
||||
cy.get(".p-select").should("exist");
|
||||
});
|
||||
|
||||
it("grid cards display file names", () => {
|
||||
cy.get("#compareGridCards").should("exist");
|
||||
cy.get("#compareGridCards li").should("have.length.greaterThan", 0);
|
||||
});
|
||||
|
||||
it("clicking sorting dropdown shows sort options", () => {
|
||||
cy.get(".p-select").click();
|
||||
cy.get(".p-select-list").should("be.visible");
|
||||
cy.contains(".p-select-option", "By File Name").should("exist");
|
||||
});
|
||||
});
|
||||
@@ -1,69 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("Files to Discover Entry Flow", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
});
|
||||
|
||||
describe("double-click table row to enter Discover", () => {
|
||||
it("double-click log file navigates to Map page", () => {
|
||||
// Target the Name column (has class .fileName) to avoid matching Dependency column
|
||||
cy.contains("td.fileName", "sample-process.xes").parent("tr").dblclick();
|
||||
cy.url().should("include", "/discover/log/1/map");
|
||||
cy.get("#cy").should("exist");
|
||||
});
|
||||
|
||||
it("double-click filter file navigates to Map page", () => {
|
||||
cy.contains("td.fileName", "filtered-sample").parent("tr").dblclick();
|
||||
cy.url().should("include", "/discover/filter/10/map");
|
||||
cy.get("#cy").should("exist");
|
||||
});
|
||||
});
|
||||
|
||||
describe("double-click grid card to enter Discover", () => {
|
||||
beforeEach(() => {
|
||||
// Switch to grid view
|
||||
cy.get("svg").parent("li.cursor-pointer").last().click();
|
||||
});
|
||||
|
||||
it("double-click log file grid card navigates to Map page", () => {
|
||||
// Use last() to target the All Files grid section (not Recently Used)
|
||||
cy.get('li[title="sample-process.xes"]').last().dblclick();
|
||||
cy.url().should("include", "/discover/log/1/map");
|
||||
cy.get("#cy").should("exist");
|
||||
});
|
||||
});
|
||||
|
||||
describe("DISCOVER tab filters files", () => {
|
||||
it("clicking DISCOVER tab shows only Log, Filter, and Rule files", () => {
|
||||
cy.get(".nav-item").contains("DISCOVER").click();
|
||||
cy.contains("td.fileName", "sample-process.xes").should("exist");
|
||||
cy.contains("td.fileName", "filtered-sample").should("exist");
|
||||
cy.contains("td.fileName", "conformance-check-1").should("exist");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Navbar state after entering Discover", () => {
|
||||
it("shows DISCOVER heading and tabs after entering from Files", () => {
|
||||
cy.contains("td.fileName", "sample-process.xes").parent("tr").dblclick();
|
||||
cy.url().should("include", "/discover/");
|
||||
cy.get("#nav_bar").contains("DISCOVER").should("be.visible");
|
||||
cy.get(".nav-item").contains("MAP").should("exist");
|
||||
cy.get(".nav-item").contains("CONFORMANCE").should("exist");
|
||||
cy.get(".nav-item").contains("PERFORMANCE").should("exist");
|
||||
});
|
||||
|
||||
it("shows back arrow pointing to /files", () => {
|
||||
cy.contains("td.fileName", "sample-process.xes").parent("tr").dblclick();
|
||||
cy.url().should("include", "/discover/");
|
||||
cy.get("#backPage").should("have.attr", "href", "/files");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["es5", "dom"],
|
||||
"types": ["cypress"]
|
||||
},
|
||||
"include": [
|
||||
"./**/*",
|
||||
"../support/**/*",
|
||||
"/node_modules/cypress",
|
||||
"cypress/**/*.js",],
|
||||
"experimentalShadowDomSupport": true
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { setupApiIntercepts } from "../support/intercept";
|
||||
|
||||
describe("Login Flow", () => {
|
||||
beforeEach(() => {
|
||||
setupApiIntercepts();
|
||||
});
|
||||
|
||||
it("renders the login form", () => {
|
||||
cy.visit("/login");
|
||||
cy.get("h2").should("contain", "LOGIN");
|
||||
cy.get("#account").should("exist");
|
||||
cy.get("#password").should("exist");
|
||||
cy.get("#login_btn_main_btn").should("be.disabled");
|
||||
});
|
||||
|
||||
it("login button is disabled when fields are empty", () => {
|
||||
cy.visit("/login");
|
||||
cy.get("#login_btn_main_btn").should("be.disabled");
|
||||
|
||||
// Only username filled — still disabled
|
||||
cy.get("#account").type("testuser");
|
||||
cy.get("#login_btn_main_btn").should("be.disabled");
|
||||
});
|
||||
|
||||
it("login button enables when both fields are filled", () => {
|
||||
cy.visit("/login");
|
||||
cy.get("#account").type("testadmin");
|
||||
cy.get("#password").type("password123");
|
||||
cy.get("#login_btn_main_btn").should("not.be.disabled");
|
||||
});
|
||||
|
||||
it("successful login redirects to /files", () => {
|
||||
cy.visit("/login");
|
||||
cy.get("#account").type("testadmin");
|
||||
cy.get("#password").type("password123");
|
||||
cy.get("#login_btn_main_btn").click();
|
||||
|
||||
cy.url().should("include", "/files");
|
||||
});
|
||||
|
||||
it("failed login shows error message", () => {
|
||||
// Visit login first to load app + MSW
|
||||
cy.visit("/login");
|
||||
cy.get("#login_btn_main_btn").should("exist");
|
||||
// Override the token endpoint to return 401 via MSW
|
||||
cy.window().then((win) => {
|
||||
const { http, HttpResponse } = win.__msw__;
|
||||
win.__mswWorker__.use(
|
||||
http.post("/api/oauth/token", () =>
|
||||
HttpResponse.json(
|
||||
{ detail: "Incorrect username or password" },
|
||||
{ status: 401 },
|
||||
)),
|
||||
);
|
||||
});
|
||||
|
||||
cy.get("#account").type("wronguser");
|
||||
cy.get("#password").type("wrongpass");
|
||||
cy.get("#login_btn_main_btn").click();
|
||||
|
||||
cy.contains("Incorrect account or password").should("be.visible");
|
||||
});
|
||||
|
||||
it("toggles password visibility", () => {
|
||||
cy.visit("/login");
|
||||
cy.get("#password").type("secret123");
|
||||
cy.get("#password").should("have.attr", "type", "password");
|
||||
|
||||
// Click the eye icon to show password
|
||||
cy.get('label[for="passwordt"] span.cursor-pointer').click();
|
||||
cy.get("#password").should("have.attr", "type", "text");
|
||||
|
||||
// Click again to hide
|
||||
cy.get('label[for="passwordt"] span.cursor-pointer').click();
|
||||
cy.get("#password").should("have.attr", "type", "password");
|
||||
});
|
||||
});
|
||||
@@ -1,67 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("Logout Flow", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
});
|
||||
|
||||
it("shows account menu when head icon is clicked", () => {
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
|
||||
// Click the head icon to open account menu
|
||||
cy.get("#acct_mgmt_button").click();
|
||||
cy.get("#account_menu").should("be.visible");
|
||||
cy.get("#greeting").should("contain", "Test Admin");
|
||||
});
|
||||
|
||||
it("account menu shows admin management link for admin user", () => {
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
|
||||
cy.get("#acct_mgmt_button").click();
|
||||
cy.get("#account_menu").should("be.visible");
|
||||
// Admin user should see account management option
|
||||
cy.get("#btn_acct_mgmt").should("exist");
|
||||
});
|
||||
|
||||
it("account menu has logout button", () => {
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
|
||||
cy.get("#acct_mgmt_button").click();
|
||||
cy.get("#btn_logout_in_menu").should("exist");
|
||||
});
|
||||
|
||||
it("clicking My Account navigates to /my-account", () => {
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
|
||||
cy.get("#acct_mgmt_button").click();
|
||||
cy.get("#btn_mang_ur_acct").click();
|
||||
cy.url().should("include", "/my-account");
|
||||
});
|
||||
|
||||
it("clicking Account Management navigates to /account-admin", () => {
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
|
||||
cy.get("#acct_mgmt_button").click();
|
||||
cy.get("#btn_acct_mgmt").click();
|
||||
cy.url().should("include", "/account-admin");
|
||||
});
|
||||
|
||||
it("logout redirects to login page", () => {
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
|
||||
cy.get("#acct_mgmt_button").click();
|
||||
cy.get("#btn_logout_in_menu").click();
|
||||
cy.url().should("include", "/login");
|
||||
});
|
||||
});
|
||||
@@ -1,73 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("My Account Page", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/my-account");
|
||||
cy.contains("Test Admin").should("exist");
|
||||
});
|
||||
|
||||
it("displays user name heading", () => {
|
||||
cy.get("#general_acct_info_user_name").should("exist");
|
||||
cy.get("#general_acct_info_user_name").should("contain", "Test Admin");
|
||||
});
|
||||
|
||||
it("shows Admin badge for admin user", () => {
|
||||
cy.contains("Admin").should("exist");
|
||||
});
|
||||
|
||||
it("shows visit count info", () => {
|
||||
cy.get("#general_account_visit_info").should("exist");
|
||||
cy.get("#general_account_visit_info").should("contain", "Total visits");
|
||||
});
|
||||
|
||||
it("displays account username (read-only)", () => {
|
||||
cy.contains("Test Admin").should("exist");
|
||||
});
|
||||
|
||||
it("shows Edit button for name field", () => {
|
||||
cy.contains("button", "Edit").should("exist");
|
||||
});
|
||||
|
||||
it("clicking Edit shows input field and Save/Cancel buttons", () => {
|
||||
cy.contains("button", "Edit").first().click();
|
||||
cy.get("#input_name_field").should("exist");
|
||||
cy.contains("button", "Save").should("exist");
|
||||
cy.contains("button", "Cancel").should("exist");
|
||||
});
|
||||
|
||||
it("clicking Cancel reverts name field to read-only", () => {
|
||||
cy.contains("button", "Edit").first().click();
|
||||
cy.get("#input_name_field").should("exist");
|
||||
cy.contains("button", "Cancel").click();
|
||||
cy.get("#input_name_field").should("not.exist");
|
||||
});
|
||||
|
||||
it("shows Reset button for password field", () => {
|
||||
cy.contains("button", "Reset").should("exist");
|
||||
});
|
||||
|
||||
it("clicking Reset shows password input and Save/Cancel", () => {
|
||||
cy.contains("button", "Reset").click();
|
||||
cy.get('input[type="password"]').should("exist");
|
||||
cy.contains("button", "Save").should("exist");
|
||||
cy.contains("button", "Cancel").should("exist");
|
||||
});
|
||||
|
||||
it("clicking Cancel on password field hides the input", () => {
|
||||
cy.contains("button", "Reset").click();
|
||||
cy.get('input[type="password"]').should("exist");
|
||||
// The Cancel button for password is the second one
|
||||
cy.get(".cancel-btn").click();
|
||||
cy.get('input[type="password"]').should("not.exist");
|
||||
});
|
||||
|
||||
it("shows Session section", () => {
|
||||
cy.contains("Session").should("exist");
|
||||
});
|
||||
});
|
||||
@@ -1,62 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures, setupApiIntercepts } from "../support/intercept";
|
||||
|
||||
describe("Navigation and Routing", () => {
|
||||
it("redirects / to /files when logged in", () => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/");
|
||||
cy.url().should("include", "/files");
|
||||
});
|
||||
|
||||
it("shows 404 page for unknown routes", () => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/nonexistent-page");
|
||||
cy.contains("404").should("exist");
|
||||
});
|
||||
|
||||
it("navbar shows correct view name", () => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
cy.get("#nav_bar").should("exist");
|
||||
cy.get("#nav_bar h2").should("contain", "FILES");
|
||||
});
|
||||
|
||||
it("navbar shows back arrow on non-files pages", () => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/discover/log/1/map");
|
||||
// Back arrow should be visible on discover pages
|
||||
cy.get("#backPage").should("exist");
|
||||
});
|
||||
|
||||
it("navbar tabs are clickable on discover page", () => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/discover/log/1/map");
|
||||
// Discover navbar should show MAP, CONFORMANCE, PERFORMANCE tabs
|
||||
cy.contains(".nav-item", "MAP").should("exist");
|
||||
cy.contains(".nav-item", "CONFORMANCE").should("exist");
|
||||
cy.contains(".nav-item", "PERFORMANCE").should("exist");
|
||||
|
||||
// Click CONFORMANCE tab
|
||||
cy.contains(".nav-item", "CONFORMANCE").click();
|
||||
cy.url().should("include", "/conformance");
|
||||
|
||||
// Click PERFORMANCE tab
|
||||
cy.contains(".nav-item", "PERFORMANCE").click();
|
||||
cy.url().should("include", "/performance");
|
||||
|
||||
// Click MAP tab to go back
|
||||
cy.contains(".nav-item", "MAP").click();
|
||||
cy.url().should("include", "/map");
|
||||
});
|
||||
|
||||
it("login page is accessible at /login", () => {
|
||||
setupApiIntercepts();
|
||||
cy.visit("/login");
|
||||
cy.get("h2").should("contain", "LOGIN");
|
||||
});
|
||||
});
|
||||
@@ -1,36 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("404 Not Found Page", () => {
|
||||
it("displays 404 page for non-existent route", () => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/this-page-does-not-exist");
|
||||
cy.contains("404").should("be.visible");
|
||||
cy.contains("The page you are looking for does not exist.").should(
|
||||
"be.visible",
|
||||
);
|
||||
});
|
||||
|
||||
it("has a link back to Files page", () => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/some/random/path");
|
||||
cy.contains("a", "Go to Files")
|
||||
.should("be.visible")
|
||||
.should("have.attr", "href", "/files");
|
||||
});
|
||||
|
||||
it("displays 404 for unauthenticated user on invalid route", () => {
|
||||
cy.visit("/not-a-real-page");
|
||||
cy.url().then((url) => {
|
||||
if (url.includes("/login")) {
|
||||
cy.url().should("include", "/login");
|
||||
} else {
|
||||
cy.contains("404").should("be.visible");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,38 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2024-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// cindy.chang@dsp.im (Cindy Chang), 2024/06/03
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("Discover page navigation tabs", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
});
|
||||
|
||||
it("Double-clicking a log file enters the MAP page.", () => {
|
||||
cy.contains("td.fileName", "sample-process.xes").dblclick();
|
||||
cy.url().should("include", "map");
|
||||
// MAP tab should exist in the navbar
|
||||
cy.contains(".nav-item", "MAP").should("exist");
|
||||
});
|
||||
|
||||
it("Clicking CONFORMANCE tab switches active page.", () => {
|
||||
cy.contains("td.fileName", "sample-process.xes").dblclick();
|
||||
cy.url().should("include", "map");
|
||||
cy.contains(".nav-item", "CONFORMANCE").click();
|
||||
cy.url().should("include", "conformance");
|
||||
cy.contains(".nav-item", "CONFORMANCE").should("have.class", "active");
|
||||
});
|
||||
|
||||
it("Clicking PERFORMANCE tab switches active page.", () => {
|
||||
cy.contains("td.fileName", "sample-process.xes").dblclick();
|
||||
cy.url().should("include", "map");
|
||||
cy.contains(".nav-item", "PERFORMANCE").click();
|
||||
cy.url().should("include", "performance");
|
||||
cy.contains(".nav-item", "PERFORMANCE").should("have.class", "active");
|
||||
});
|
||||
});
|
||||
@@ -1,64 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2024-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// cindy.chang@dsp.im (Cindy Chang), 2024/06/11
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { setupApiIntercepts } from "../support/intercept";
|
||||
|
||||
describe("Paste URL login redirect", () => {
|
||||
it("After login with return-to param, redirects to the remembered page", () => {
|
||||
setupApiIntercepts();
|
||||
|
||||
// Visit login page with a return-to query param (base64-encoded URL)
|
||||
const targetUrl =
|
||||
"http://localhost:4173/discover/conformance/log/1/conformance";
|
||||
const encodedUrl = btoa(targetUrl);
|
||||
cy.visit(`/login?return-to=${encodedUrl}`);
|
||||
|
||||
// Fill in login form
|
||||
cy.get("#account").type("testadmin");
|
||||
cy.get("#password").type("password123");
|
||||
cy.get("form").submit();
|
||||
|
||||
// After login, the app should attempt to redirect to the return-to URL.
|
||||
// Since window.location.href is used (not router.push), we verify the
|
||||
// login form disappears and the token cookie is set.
|
||||
cy.getCookie("luciaToken").should("exist");
|
||||
});
|
||||
|
||||
it("Login without return-to param redirects to /files", () => {
|
||||
setupApiIntercepts();
|
||||
cy.visit("/login");
|
||||
|
||||
cy.get("#account").type("testadmin");
|
||||
cy.get("#password").type("password123");
|
||||
cy.get("form").submit();
|
||||
|
||||
cy.url().should("include", "/files");
|
||||
});
|
||||
|
||||
it("Unauthenticated user cannot access inner pages", () => {
|
||||
// Visit login first to load the app + MSW
|
||||
cy.visit("/login");
|
||||
cy.get("#login_btn_main_btn").should("exist");
|
||||
// Override my-account to return 401 (simulate logged-out state) via MSW
|
||||
cy.window().then((win) => {
|
||||
const { http, HttpResponse } = win.__msw__;
|
||||
win.__mswWorker__.use(
|
||||
http.get("/api/my-account", () =>
|
||||
HttpResponse.json(
|
||||
{ detail: "Not authenticated" },
|
||||
{ status: 401 },
|
||||
)),
|
||||
);
|
||||
});
|
||||
|
||||
cy.visit("/files");
|
||||
|
||||
// Should be redirected to login page
|
||||
cy.url().should("include", "/login");
|
||||
cy.get("#account").should("exist");
|
||||
cy.get("#password").should("exist");
|
||||
});
|
||||
});
|
||||
@@ -1,116 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
import { loginWithFixtures } from "../support/intercept";
|
||||
|
||||
describe("SweetAlert2 Modals", () => {
|
||||
describe("File Context Menu - Rename", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
});
|
||||
|
||||
it("right-click on table row shows context menu with Rename", () => {
|
||||
cy.get("table tbody tr").first().rightclick();
|
||||
cy.contains("Rename").should("be.visible");
|
||||
});
|
||||
|
||||
it("right-click context menu shows Download option", () => {
|
||||
cy.get("table tbody tr").first().rightclick();
|
||||
cy.contains("Download").should("be.visible");
|
||||
});
|
||||
|
||||
it("right-click context menu shows Delete option", () => {
|
||||
cy.get("table tbody tr").first().rightclick();
|
||||
cy.contains("Delete").should("be.visible");
|
||||
});
|
||||
|
||||
it("clicking Rename opens SweetAlert rename dialog", () => {
|
||||
cy.get("table tbody tr").first().rightclick();
|
||||
cy.contains("Rename").click();
|
||||
// SweetAlert popup should appear with RENAME title
|
||||
cy.get(".swal2-popup").should("be.visible");
|
||||
cy.get(".swal2-title").should("contain", "RENAME");
|
||||
cy.get(".swal2-input").should("exist");
|
||||
});
|
||||
|
||||
it("rename dialog has pre-filled file name", () => {
|
||||
cy.get("table tbody tr").first().rightclick();
|
||||
cy.contains("Rename").click();
|
||||
cy.get(".swal2-input").should("not.have.value", "");
|
||||
});
|
||||
|
||||
it("rename dialog can be cancelled", () => {
|
||||
cy.get("table tbody tr").first().rightclick();
|
||||
cy.contains("Rename").click();
|
||||
cy.get(".swal2-popup").should("be.visible");
|
||||
cy.get(".swal2-cancel").click();
|
||||
cy.get(".swal2-popup").should("not.exist");
|
||||
});
|
||||
|
||||
it("clicking Delete opens SweetAlert delete confirmation", () => {
|
||||
cy.get("table tbody tr").first().rightclick();
|
||||
cy.contains("Delete").click();
|
||||
// SweetAlert popup should appear with CONFIRM DELETION
|
||||
cy.get(".swal2-popup").should("be.visible");
|
||||
cy.get(".swal2-title").should("contain", "CONFIRM DELETION");
|
||||
});
|
||||
|
||||
it("delete confirmation shows file name", () => {
|
||||
cy.get("table tbody tr").first().rightclick();
|
||||
cy.contains("Delete").click();
|
||||
cy.get(".swal2-popup").should("be.visible");
|
||||
cy.get(".swal2-html-container").should("contain", "delete");
|
||||
});
|
||||
|
||||
it("delete confirmation can be cancelled", () => {
|
||||
cy.get("table tbody tr").first().rightclick();
|
||||
cy.contains("Delete").click();
|
||||
cy.get(".swal2-popup").should("be.visible");
|
||||
cy.get(".swal2-cancel").click();
|
||||
cy.get(".swal2-popup").should("not.exist");
|
||||
});
|
||||
});
|
||||
|
||||
describe("File Context Menu on Grid View", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/files");
|
||||
cy.contains("sample-process.xes").should("exist");
|
||||
// Switch to grid view
|
||||
cy.get("svg").parent("li.cursor-pointer").last().click();
|
||||
});
|
||||
|
||||
it("right-click on grid card shows context menu", () => {
|
||||
cy.get("li[title]").first().rightclick();
|
||||
cy.contains("Rename").should("be.visible");
|
||||
cy.contains("Delete").should("be.visible");
|
||||
});
|
||||
|
||||
it("grid card rename opens SweetAlert dialog", () => {
|
||||
cy.get("li[title]").first().rightclick();
|
||||
cy.contains("Rename").click();
|
||||
cy.get(".swal2-popup").should("be.visible");
|
||||
cy.get(".swal2-title").should("contain", "RENAME");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Account Delete Confirmation", () => {
|
||||
beforeEach(() => {
|
||||
loginWithFixtures();
|
||||
cy.visit("/account-admin");
|
||||
cy.contains("Test Admin").should("exist");
|
||||
});
|
||||
|
||||
it("delete confirmation Yes button triggers delete API", () => {
|
||||
cy.get(".delete-account").first().click();
|
||||
cy.get("#modal_container").should("be.visible");
|
||||
cy.get("#sure_to_delete_acct_btn").click();
|
||||
// Modal should close after deletion
|
||||
cy.get("#modal_container").should("not.exist");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
時間,案號,居住區域,學區,事件名稱,事件序號,狀態 ,時段,溫度,數量,未知,完成,預期時間
|
||||
2022/05/13 09:25:21,案一,63,富山,事件甲,事件一,Start,早上,95,27,,TRUE,2022/5/14 09:25:21
|
||||
2022/05/13 09:25:21,案一,,,事件甲,事件一,Complete,中午,135,442,,false,2022/5/14 09:25:21
|
||||
2022/05/13 09:30:01,案一,,仁德,事件乙,事件四,Start,中午,110.6,-6, ,,2022/5/14 09:30:01
|
||||
2022/05/13 09:30:01,案一,,,事件乙,事件四,Complete,晚上,-65,4,,true ,2022/5/14 09:30:01
|
||||
|
Binary file not shown.
|
@@ -1 +0,0 @@
|
||||
timestamp,case id,name,instance,status
|
||||
|
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,9 +0,0 @@
|
||||
timestamp,case id,name,status
|
||||
2022/05/13 09:25:21,c1,a,1,start
|
||||
2022/05/13 09:25:21,c1,a,1,complete
|
||||
2022/05/13 09:30:01,c1,b,2,start
|
||||
2022/05/13 09:30:01,c1,b,2,complete
|
||||
2022/05/13 09:48:33,c2,a,6,start
|
||||
2022/05/13 09:48:33,c2,a,6,complete
|
||||
2022/05/13 09:54:27,c2,c,7,start
|
||||
2022/05/13 09:54:27,c2,c,7,complete
|
||||
|
@@ -1,30 +0,0 @@
|
||||
CaseID,Activity,Timestamp,Status,Activity_Instance
|
||||
CID_1,檢傷,2023-01-12 15:32:31,start,1
|
||||
CID_1,檢傷,2023-01-12 15:32:31,complete,1
|
||||
CID_1,第一次醫囑,2023-01-12 15:49:01,start,2
|
||||
CID_1,第一次醫囑,2023-01-12 15:49:01,complete,2
|
||||
CID_1,出院,2023-01-13 03:32:00,start,3
|
||||
CID_1,出院,2023-01-13 03:32:00,complete,3
|
||||
CID_2,檢傷,2023-07-26 08:44:17,start,4
|
||||
CID_2,檢傷,2023-07-26 08:44:17,complete,4
|
||||
CID_2,第一次醫囑,2023-07-26 08:48:05,start,5
|
||||
CID_2,第一次醫囑,2023-07-26 08:48:05,complete,5
|
||||
CID_2,出院,2023-07-26 17:00:49,start,6
|
||||
CID_2,出院,2023-07-26 17:00:49,complete,6
|
||||
CID_3,檢傷,2023-11-27 06:20:48,start,7
|
||||
CID_3,檢傷,2023-11-27 06:20:48,complete,7
|
||||
CID_3,第一次醫囑,2023-11-27 06:40:30,start,8
|
||||
CID_3,第一次醫囑,2023-11-27 06:40:30,complete,8
|
||||
CID_3,出院,2023-11-27 07:21:53,start,9
|
||||
CID_3,出院,2023-11-27 07:21:53,complete,9
|
||||
CID_4,檢傷,2023-11-01 01:20:19,start,10
|
||||
CID_4,檢傷,2023-11-01 01:20:19,complete,10
|
||||
CID_4,第一次醫囑,2023-11-01 01:34:54,start,11
|
||||
CID_4,第一次醫囑,2023-11-01 01:34:54,complete,11
|
||||
CID_4,住院,2023-11-02 06:36:36,start,12
|
||||
CID_4,住院,2023-11-10 02:35:39,complete,12
|
||||
CID_4,出院,2023-11-10 02:35:39,start,13
|
||||
CID_4,出院,2023-11-10 02:35:39,complete,13
|
||||
CID_5,檢傷,2023-07-13 02:49:36,start,14
|
||||
CID_5,檢傷,2023-07-13 02:49:36,complete,14
|
||||
CID_5,第一次醫囑,2023-07-13 03:07:01,start,15
|
||||
|
@@ -1,9 +0,0 @@
|
||||
timestamp,case id,name,instance,status
|
||||
2022/05/13 09:25:21,c1,a,1,start
|
||||
2022/05/13 09:25:21,c1,a,1,
|
||||
2022/05/13 09:30:01,c1,b,2,begin
|
||||
2022/05/13 09:30:01,c1,b,,complete
|
||||
2022/05/13 09:48:33,,,6,start
|
||||
2022;05;13 09;48;33,c2,a,6,complete
|
||||
2022/05/13 09:54:27,c2,c,7,start
|
||||
,c2,c,7,complete
|
||||
|
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"username": " test ",
|
||||
"password": " test "
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2023-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// chiayin.kuo@dsp.im (chiayin), 2023/01/31
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/06
|
||||
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
// -- This is a parent command --
|
||||
import "@4tw/cypress-drag-drop";
|
||||
|
||||
/**
|
||||
* Sets authentication cookies to simulate a logged-in user.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
Cypress.Commands.add("login", () => {
|
||||
cy.setCookie("luciaToken", "fake-access-token-for-testing");
|
||||
cy.setCookie("isLuciaLoggedIn", "true");
|
||||
});
|
||||
// Usage: cy.login()
|
||||
// -- This is a child command --
|
||||
// Click a blank area to close an opened modal: cy.closePopup()
|
||||
/**
|
||||
* Closes the active popup by clicking the top-left area of the page.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
Cypress.Commands.add("closePopup", () => {
|
||||
// Trigger a forced click to close modal overlays consistently.
|
||||
cy.get("body").click({ position: "topLeft" });
|
||||
});
|
||||
@@ -1,26 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2023-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// chiayin.kuo@dsp.im (chiayin), 2023/01/31
|
||||
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import "./commands";
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
require("cypress-xpath"); // Enables xpath helpers used in pointer event checks.
|
||||
@@ -1,21 +0,0 @@
|
||||
// The Lucia project.
|
||||
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// imacat.yang@dsp.im (imacat), 2026/03/05
|
||||
|
||||
/**
|
||||
* API mocking is now handled by MSW (Mock Service Worker).
|
||||
* This function is kept for backward compatibility but does nothing.
|
||||
*/
|
||||
export function setupApiIntercepts() {
|
||||
// MSW handles all API interception via service worker.
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the luciaToken cookie and isLuciaLoggedIn cookie to simulate
|
||||
* a logged-in state. API interception is handled by MSW.
|
||||
*/
|
||||
export function loginWithFixtures() {
|
||||
cy.setCookie("luciaToken", "fake-access-token-for-testing");
|
||||
cy.setCookie("isLuciaLoggedIn", "true");
|
||||
}
|
||||
3271
package-lock.json
generated
3271
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -9,10 +9,9 @@
|
||||
"preview": "vite preview",
|
||||
"test": "vitest",
|
||||
"coverage": "vitest run --coverage",
|
||||
"cy:run": "cypress run",
|
||||
"test:unit": "vitest --environment jsdom",
|
||||
"test:e2e": "start-server-and-test 'vite preview --port 4173' :4173 'cypress run --e2e'",
|
||||
"test:e2e:dev": "start-server-and-test 'vite dev --port 4173' :4173 'cypress open --e2e'",
|
||||
"test:unit": "vitest run",
|
||||
"test:e2e": "playwright test --config tests/e2e/playwright.config.ts",
|
||||
"test:e2e:ui": "playwright test --config tests/e2e/playwright.config.ts --ui",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs",
|
||||
"lint:fix": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix",
|
||||
"docs": "typedoc"
|
||||
@@ -49,7 +48,6 @@
|
||||
"vuedraggable": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@4tw/cypress-drag-drop": "^2.3.1",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@playwright/test": "^1.58.2",
|
||||
"@types/cytoscape": "^3.21.9",
|
||||
@@ -60,17 +58,13 @@
|
||||
"@vue/eslint-config-prettier": "^10.2.0",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"chartjs-plugin-dragdata": "^2.3.1",
|
||||
"cypress": "^15.11.0",
|
||||
"cypress-xpath": "^2.0.1",
|
||||
"eslint": "^10.0.2",
|
||||
"eslint-plugin-cypress": "^6.1.0",
|
||||
"eslint-plugin-vue": "^10.8.0",
|
||||
"jsdom": "^28.1.0",
|
||||
"msw": "^2.12.14",
|
||||
"postcss": "^8.5.8",
|
||||
"prettier": "^3.8.1",
|
||||
"sass": "^1.97.3",
|
||||
"start-server-and-test": "^2.1.5",
|
||||
"tailwindcss": "^4.2.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"typedoc": "^0.28.17",
|
||||
|
||||
Reference in New Issue
Block a user