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
|
*.local
|
||||||
/dist
|
/dist
|
||||||
|
|
||||||
# Cypress
|
|
||||||
cypress.env.json
|
|
||||||
/cypress/videos/
|
|
||||||
/cypress/screenshots/
|
|
||||||
|
|
||||||
# Playwright
|
# Playwright
|
||||||
/test-results/
|
/test-results/
|
||||||
/playwright-report/
|
/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",
|
"preview": "vite preview",
|
||||||
"test": "vitest",
|
"test": "vitest",
|
||||||
"coverage": "vitest run --coverage",
|
"coverage": "vitest run --coverage",
|
||||||
"cy:run": "cypress run",
|
"test:unit": "vitest run",
|
||||||
"test:unit": "vitest --environment jsdom",
|
"test:e2e": "playwright test --config tests/e2e/playwright.config.ts",
|
||||||
"test:e2e": "start-server-and-test 'vite preview --port 4173' :4173 'cypress run --e2e'",
|
"test:e2e:ui": "playwright test --config tests/e2e/playwright.config.ts --ui",
|
||||||
"test:e2e:dev": "start-server-and-test 'vite dev --port 4173' :4173 'cypress open --e2e'",
|
|
||||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs",
|
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs",
|
||||||
"lint:fix": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix",
|
"lint:fix": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix",
|
||||||
"docs": "typedoc"
|
"docs": "typedoc"
|
||||||
@@ -49,7 +48,6 @@
|
|||||||
"vuedraggable": "^4.1.0"
|
"vuedraggable": "^4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@4tw/cypress-drag-drop": "^2.3.1",
|
|
||||||
"@eslint/js": "^10.0.1",
|
"@eslint/js": "^10.0.1",
|
||||||
"@playwright/test": "^1.58.2",
|
"@playwright/test": "^1.58.2",
|
||||||
"@types/cytoscape": "^3.21.9",
|
"@types/cytoscape": "^3.21.9",
|
||||||
@@ -60,17 +58,13 @@
|
|||||||
"@vue/eslint-config-prettier": "^10.2.0",
|
"@vue/eslint-config-prettier": "^10.2.0",
|
||||||
"@vue/test-utils": "^2.4.6",
|
"@vue/test-utils": "^2.4.6",
|
||||||
"chartjs-plugin-dragdata": "^2.3.1",
|
"chartjs-plugin-dragdata": "^2.3.1",
|
||||||
"cypress": "^15.11.0",
|
|
||||||
"cypress-xpath": "^2.0.1",
|
|
||||||
"eslint": "^10.0.2",
|
"eslint": "^10.0.2",
|
||||||
"eslint-plugin-cypress": "^6.1.0",
|
|
||||||
"eslint-plugin-vue": "^10.8.0",
|
"eslint-plugin-vue": "^10.8.0",
|
||||||
"jsdom": "^28.1.0",
|
"jsdom": "^28.1.0",
|
||||||
"msw": "^2.12.14",
|
"msw": "^2.12.14",
|
||||||
"postcss": "^8.5.8",
|
"postcss": "^8.5.8",
|
||||||
"prettier": "^3.8.1",
|
"prettier": "^3.8.1",
|
||||||
"sass": "^1.97.3",
|
"sass": "^1.97.3",
|
||||||
"start-server-and-test": "^2.1.5",
|
|
||||||
"tailwindcss": "^4.2.1",
|
"tailwindcss": "^4.2.1",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"typedoc": "^0.28.17",
|
"typedoc": "^0.28.17",
|
||||||
|
|||||||
Reference in New Issue
Block a user