diff --git a/cypress.config.js b/cypress.config.js index 3f2d6e8..0af0a7f 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -16,11 +16,11 @@ const { defineConfig } = require("cypress"); module.exports = defineConfig({ defaultCommandTimeout: 6000, viewportWidth: 1280, - viewportHeight:720, + viewportHeight: 720, e2e: { baseUrl: "http://localhost:4173", specPattern: "cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}", }, includeShadowDom: true, - env: {} + env: {}, }); diff --git a/cypress/e2e/accountAdmin.cy.js b/cypress/e2e/accountAdmin.cy.js index 2038923..68b16af 100644 --- a/cypress/e2e/accountAdmin.cy.js +++ b/cypress/e2e/accountAdmin.cy.js @@ -3,32 +3,32 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('Account Management', () => { +describe("Account Management", () => { beforeEach(() => { loginWithFixtures(); }); - it('displays user list on account admin page', () => { - cy.visit('/account-admin'); - cy.wait('@getUsers'); + it("displays user list on account admin page", () => { + cy.visit("/account-admin"); + cy.wait("@getUsers"); // Should display users from fixture - cy.contains('Test Admin').should('exist'); - cy.contains('Alice Wang').should('exist'); - cy.contains('Bob Chen').should('exist'); + 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.wait('@getUsers'); + it("shows active/inactive status badges", () => { + cy.visit("/account-admin"); + cy.wait("@getUsers"); // The user list should show status indicators - cy.contains('testadmin').should('exist'); + cy.contains("testadmin").should("exist"); }); - it('navigates to my-account page', () => { - cy.visit('/my-account'); - cy.wait('@getMyAccount'); - cy.url().should('include', '/my-account'); + it("navigates to my-account page", () => { + cy.visit("/my-account"); + cy.wait("@getMyAccount"); + cy.url().should("include", "/my-account"); }); }); diff --git a/cypress/e2e/accountAdmin/accountDuplicationCheck.cy.js b/cypress/e2e/accountAdmin/accountDuplicationCheck.cy.js index e20aa7e..464cd34 100644 --- a/cypress/e2e/accountAdmin/accountDuplicationCheck.cy.js +++ b/cypress/e2e/accountAdmin/accountDuplicationCheck.cy.js @@ -4,55 +4,61 @@ // cindy.chang@dsp.im (Cindy Chang), 2024/07/03 // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../../support/intercept'; +import { loginWithFixtures } from "../../support/intercept"; -const MSG_ACCOUNT_NOT_UNIQUE = 'Account has already been registered.'; +const MSG_ACCOUNT_NOT_UNIQUE = "Account has already been registered."; -describe('Account duplication check.', () => { +describe("Account duplication check.", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/account-admin'); - cy.wait('@getUsers'); + cy.visit("/account-admin"); + cy.wait("@getUsers"); }); - it('When an account already exists, show error message on confirm.', () => { - const testAccountName = '000000'; + it("When an account already exists, show error message on confirm.", () => { + const testAccountName = "000000"; // First creation: account doesn't exist yet - cy.intercept('GET', '/api/users/000000', { + cy.intercept("GET", "/api/users/000000", { statusCode: 404, - body: { detail: 'Not found' }, - }).as('checkNewUser'); + body: { detail: "Not found" }, + }).as("checkNewUser"); - 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", "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') + cy.contains("button", "Confirm") + .should("be.visible") + .and("be.enabled") .click(); - cy.wait('@postUser'); - cy.contains('Account added').should('be.visible'); + cy.wait("@postUser"); + cy.contains("Account added").should("be.visible"); // Second creation: now account exists — override to return 200 - cy.intercept('GET', '/api/users/000000', { + cy.intercept("GET", "/api/users/000000", { statusCode: 200, - body: { username: '000000', name: '000000', is_admin: false, is_active: true, roles: [] }, - }).as('checkExistingUser'); + body: { + username: "000000", + name: "000000", + is_admin: false, + is_active: true, + roles: [], + }, + }).as("checkExistingUser"); - 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", "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') + cy.contains("button", "Confirm") + .should("be.visible") + .and("be.enabled") .click(); - cy.contains(MSG_ACCOUNT_NOT_UNIQUE).should('be.visible'); + cy.contains(MSG_ACCOUNT_NOT_UNIQUE).should("be.visible"); }); }); diff --git a/cypress/e2e/accountAdmin/confirmPasswordMessage.cy.js b/cypress/e2e/accountAdmin/confirmPasswordMessage.cy.js index ed700df..ec5bd88 100644 --- a/cypress/e2e/accountAdmin/confirmPasswordMessage.cy.js +++ b/cypress/e2e/accountAdmin/confirmPasswordMessage.cy.js @@ -4,33 +4,33 @@ // cindy.chang@dsp.im (Cindy Chang), 2024/07/02 // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../../support/intercept'; +import { loginWithFixtures } from "../../support/intercept"; -describe('Password validation on create account.', () => { +describe("Password validation on create account.", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/account-admin'); - cy.wait('@getUsers'); + cy.visit("/account-admin"); + cy.wait("@getUsers"); }); - it('When password is too short, confirm button stays disabled.', () => { - cy.contains('button', 'Create New').should('be.visible').click(); + 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'); + 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.get("#input_first_pwd").type("aaa"); - cy.contains('button', 'Confirm').should('be.disabled'); + 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(); + 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.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'); + cy.contains("button", "Confirm").should("be.enabled"); }); }); diff --git a/cypress/e2e/accountAdmin/createAccount.cy.js b/cypress/e2e/accountAdmin/createAccount.cy.js index cc9cf60..b3080a6 100644 --- a/cypress/e2e/accountAdmin/createAccount.cy.js +++ b/cypress/e2e/accountAdmin/createAccount.cy.js @@ -4,39 +4,39 @@ // cindy.chang@dsp.im (Cindy Chang), 2024/07/02 // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../../support/intercept'; +import { loginWithFixtures } from "../../support/intercept"; -describe('Create an Account', () => { +describe("Create an Account", () => { beforeEach(() => { loginWithFixtures(); // Override: new usernames should return 404 (account doesn't exist yet) - cy.intercept('GET', '/api/users/unit-test-*', { + cy.intercept("GET", "/api/users/unit-test-*", { statusCode: 404, - body: { detail: 'Not found' }, - }).as('checkNewUser'); - cy.visit('/account-admin'); - cy.wait('@getUsers'); + body: { detail: "Not found" }, + }).as("checkNewUser"); + cy.visit("/account-admin"); + cy.wait("@getUsers"); }); - it('Create a new account with admin role; should show saved message.', () => { - cy.contains('button', 'Create New').should('be.visible').click(); + 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.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') + cy.contains("button", "Confirm") + .should("be.visible") + .and("be.enabled") .click(); - cy.wait('@postUser'); - cy.contains('Account added').should('be.visible'); + cy.wait("@postUser"); + 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'); + 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"); }); }); diff --git a/cypress/e2e/accountAdmin/deleteAccount.cy.js b/cypress/e2e/accountAdmin/deleteAccount.cy.js index dbac1fc..5494821 100644 --- a/cypress/e2e/accountAdmin/deleteAccount.cy.js +++ b/cypress/e2e/accountAdmin/deleteAccount.cy.js @@ -4,27 +4,27 @@ // cindy.chang@dsp.im (Cindy Chang), 2024/07/03 // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../../support/intercept'; +import { loginWithFixtures } from "../../support/intercept"; -describe('Delete an Account', () => { +describe("Delete an Account", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/account-admin'); - cy.wait('@getUsers'); + cy.visit("/account-admin"); + cy.wait("@getUsers"); }); - 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.wait('@deleteUser'); - cy.contains('Account deleted').should('be.visible'); + 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.wait("@deleteUser"); + 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'); + 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"); }); }); diff --git a/cypress/e2e/accountAdmin/editAccount.cy.js b/cypress/e2e/accountAdmin/editAccount.cy.js index 2ab6de0..86d2579 100644 --- a/cypress/e2e/accountAdmin/editAccount.cy.js +++ b/cypress/e2e/accountAdmin/editAccount.cy.js @@ -4,30 +4,30 @@ // cindy.chang@dsp.im (Cindy Chang), 2024/07/03 // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../../support/intercept'; +import { loginWithFixtures } from "../../support/intercept"; -const MODAL_TITLE_ACCOUNT_EDIT = 'Account Edit'; -const MSG_ACCOUNT_EDITED = 'Saved'; +const MODAL_TITLE_ACCOUNT_EDIT = "Account Edit"; +const MSG_ACCOUNT_EDITED = "Saved"; -describe('Edit an account', () => { +describe("Edit an account", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/account-admin'); - cy.wait('@getUsers'); + cy.visit("/account-admin"); + cy.wait("@getUsers"); }); - it('Edit an account; modify name and see saved message.', () => { - cy.get('.btn-edit').first().click(); - cy.wait('@getUserDetail'); + it("Edit an account; modify name and see saved message.", () => { + cy.get(".btn-edit").first().click(); + cy.wait("@getUserDetail"); - cy.contains('h1', MODAL_TITLE_ACCOUNT_EDIT).should('exist'); - cy.get('#input_name_field').clear().type('Updated Name'); + cy.contains("h1", MODAL_TITLE_ACCOUNT_EDIT).should("exist"); + cy.get("#input_name_field").clear().type("Updated Name"); - cy.contains('button', 'Confirm') - .should('be.visible') - .and('be.enabled') + cy.contains("button", "Confirm") + .should("be.visible") + .and("be.enabled") .click(); - cy.wait('@putUser'); - cy.contains(MSG_ACCOUNT_EDITED).should('be.visible'); + cy.wait("@putUser"); + cy.contains(MSG_ACCOUNT_EDITED).should("be.visible"); }); }); diff --git a/cypress/e2e/accountCrud.cy.js b/cypress/e2e/accountCrud.cy.js index 00981d7..88f7e89 100644 --- a/cypress/e2e/accountCrud.cy.js +++ b/cypress/e2e/accountCrud.cy.js @@ -3,94 +3,94 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('Account Management CRUD', () => { +describe("Account Management CRUD", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/account-admin'); - cy.wait('@getUsers'); + cy.visit("/account-admin"); + cy.wait("@getUsers"); }); - it('shows Create New button', () => { - cy.get('#create_new_acct_btn').should('exist'); - cy.get('#create_new_acct_btn').should('contain', 'Create New'); + 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'); + 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'); + 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 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("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("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'); + 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'); + cy.get("#modal_container").should("not.exist"); }); - it('double-click username opens account info modal', () => { + 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'); + cy.get(".account-cell").first().dblclick(); + cy.get("#modal_container").should("be.visible"); }); - it('delete button opens delete confirmation modal', () => { + 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'); + 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 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("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("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', () => { + it("search bar filters user list", () => { // Search filters by username, not display name - cy.get('#input_search').type('user1'); + cy.get("#input_search").type("user1"); cy.get('img[alt="search"]').click(); // Should only show user1 (Alice Wang) - cy.contains('user1').should('exist'); + cy.contains("user1").should("exist"); }); }); diff --git a/cypress/e2e/accountInfo.cy.js b/cypress/e2e/accountInfo.cy.js index 30b6d36..7820346 100644 --- a/cypress/e2e/accountInfo.cy.js +++ b/cypress/e2e/accountInfo.cy.js @@ -3,38 +3,38 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('Account Info Modal', () => { +describe("Account Info Modal", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/account-admin'); - cy.wait('@getUsers'); + cy.visit("/account-admin"); + cy.wait("@getUsers"); }); - 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("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 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 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'); + 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'); + cy.get("#modal_container").should("not.exist"); }); }); diff --git a/cypress/e2e/compare.cy.js b/cypress/e2e/compare.cy.js index 0cfb486..be5e99d 100644 --- a/cypress/e2e/compare.cy.js +++ b/cypress/e2e/compare.cy.js @@ -5,78 +5,86 @@ // cindy.chang@dsp.im (Cindy Chang), 2024/05/30 // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('Compare', () => { +describe("Compare", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/files'); - cy.wait('@getFiles'); - cy.contains('li', 'COMPARE').click(); + cy.visit("/files"); + cy.wait("@getFiles"); + cy.contains("li", "COMPARE").click(); }); - it('Compare dropdown sorting options', () => { + 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)', + "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 => { + 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()) + .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("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("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.wait('@getCompare'); - cy.url().should('include', 'compare'); + it("Enter Compare dashboard and see charts", () => { + cy.get("#compareFile0").drag("#primaryDragCard"); + cy.get("#compareFile1").drag("#secondaryDragCard"); + cy.contains("button", "Compare").click(); + cy.wait("@getCompare"); + 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'); + 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.wait('@getCompare'); + it("Compare State button exists on dashboard", () => { + cy.get("#compareFile0").drag("#primaryDragCard"); + cy.get("#compareFile1").drag("#secondaryDragCard"); + cy.contains("button", "Compare").click(); + cy.wait("@getCompare"); - cy.get('#compareState').should('exist').and('be.visible'); + 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.wait('@getCompare'); + it("Sidebar shows time usage and frequency sections", () => { + cy.get("#compareFile0").drag("#primaryDragCard"); + cy.get("#compareFile1").drag("#secondaryDragCard"); + cy.contains("button", "Compare").click(); + cy.wait("@getCompare"); - cy.get('aside').should('exist'); - cy.get('aside li').should('have.length.greaterThan', 0); + cy.get("aside").should("exist"); + cy.get("aside li").should("have.length.greaterThan", 0); }); }); diff --git a/cypress/e2e/discoverConformance.cy.js b/cypress/e2e/discoverConformance.cy.js index 810b2c0..466f248 100644 --- a/cypress/e2e/discoverConformance.cy.js +++ b/cypress/e2e/discoverConformance.cy.js @@ -3,53 +3,53 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('Discover Conformance Page', () => { +describe("Discover Conformance Page", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/discover/log/297310264/conformance'); - cy.wait('@getLogCheckParams'); + cy.visit("/discover/log/297310264/conformance"); + cy.wait("@getLogCheckParams"); }); - it('page loads and loading overlay disappears', () => { - cy.get('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); + it("page loads and loading overlay disappears", () => { + cy.get(".z-\\[9999\\]", { timeout: 10000 }).should("not.exist"); }); - it('displays Rule Settings sidebar', () => { - cy.get('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); - cy.contains('Rule Settings').should('be.visible'); + it("displays Rule Settings sidebar", () => { + cy.get(".z-\\[9999\\]", { timeout: 10000 }).should("not.exist"); + cy.contains("Rule Settings").should("be.visible"); }); - it('displays Conformance Checking Results heading', () => { - cy.get('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); - cy.contains('Conformance Checking Results').should('be.visible'); + it("displays Conformance Checking Results heading", () => { + cy.get(".z-\\[9999\\]", { timeout: 10000 }).should("not.exist"); + cy.contains("Conformance Checking Results").should("be.visible"); }); - it('displays rule type radio options', () => { - cy.get('.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 rule type radio options", () => { + cy.get(".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('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); - cy.contains('button', 'Clear').should('be.visible'); - cy.contains('button', 'Apply').should('exist'); + it("displays Clear and Apply buttons", () => { + cy.get(".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('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); - cy.contains('Activity list').should('be.visible'); + it("displays Activity list area", () => { + cy.get(".z-\\[9999\\]", { timeout: 10000 }).should("not.exist"); + cy.contains("Activity list").should("be.visible"); }); - it('displays default placeholder values in results', () => { - cy.get('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); - cy.contains('Conformance Rate').should('be.visible'); - cy.contains('Cases').should('be.visible'); + it("displays default placeholder values in results", () => { + cy.get(".z-\\[9999\\]", { timeout: 10000 }).should("not.exist"); + cy.contains("Conformance Rate").should("be.visible"); + cy.contains("Cases").should("be.visible"); }); }); diff --git a/cypress/e2e/discoverMap.cy.js b/cypress/e2e/discoverMap.cy.js index 6467171..81b4514 100644 --- a/cypress/e2e/discoverMap.cy.js +++ b/cypress/e2e/discoverMap.cy.js @@ -3,49 +3,55 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('Discover Map Page', () => { +describe("Discover Map Page", () => { beforeEach(() => { loginWithFixtures(); // Suppress Cytoscape rendering errors in headless mode - cy.on('uncaught:exception', () => false); - cy.visit('/discover/log/297310264/map'); - cy.wait('@getDiscover'); + cy.on("uncaught:exception", () => false); + cy.visit("/discover/log/297310264/map"); + cy.wait("@getDiscover"); }); - it('page loads and cytoscape container exists', () => { - cy.get('#cy').should('exist'); + it("page loads and cytoscape container exists", () => { + cy.get("#cy").should("exist"); }); - it('displays left sidebar buttons', () => { + 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'); + 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("displays right sidebar Summary button", () => { + cy.get("#sidebar_state").should("exist"); + cy.get("#iconState").should("exist"); }); - it('clicking Visualization Setting button toggles sidebar', () => { + 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(); + cy.contains("span.material-symbols-outlined", "track_changes") + .parent("li") + .click(); // SidebarView should open - cy.contains('Visualization Setting').should('be.visible'); + cy.contains("Visualization Setting").should("be.visible"); }); - it('clicking Summary button toggles sidebar', () => { - cy.get('#iconState').click(); + it("clicking Summary button toggles sidebar", () => { + cy.get("#iconState").click(); // SidebarState should open with insights/stats - cy.contains('Summary').should('be.visible'); + cy.contains("Summary").should("be.visible"); }); - it('clicking Traces button toggles sidebar', () => { - cy.contains('span.material-symbols-outlined', 'rebase').parent('li').click(); + 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'); + cy.contains("Traces").should("be.visible"); }); }); diff --git a/cypress/e2e/discoverPerformance.cy.js b/cypress/e2e/discoverPerformance.cy.js index d690b75..ea9ea22 100644 --- a/cypress/e2e/discoverPerformance.cy.js +++ b/cypress/e2e/discoverPerformance.cy.js @@ -3,64 +3,64 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('Discover Performance Page', () => { +describe("Discover Performance Page", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/discover/log/297310264/performance'); - cy.wait('@getPerformance'); + cy.visit("/discover/log/297310264/performance"); + cy.wait("@getPerformance"); }); - it('page loads and loading overlay disappears', () => { + it("page loads and loading overlay disappears", () => { // Loading overlay should not be visible after data loads - cy.get('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); + cy.get(".z-\\[9999\\]", { timeout: 10000 }).should("not.exist"); }); - it('displays Time Usage sidebar section', () => { - cy.get('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); - cy.contains('Time Usage').should('be.visible'); + it("displays Time Usage sidebar section", () => { + cy.get(".z-\\[9999\\]", { timeout: 10000 }).should("not.exist"); + cy.contains("Time Usage").should("be.visible"); }); - it('displays Frequency sidebar section', () => { - cy.get('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); - cy.contains('Frequency').should('be.visible'); + it("displays Frequency sidebar section", () => { + cy.get(".z-\\[9999\\]", { timeout: 10000 }).should("not.exist"); + cy.contains("Frequency").should("be.visible"); }); - it('displays sidebar navigation items', () => { - cy.get('.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 sidebar navigation items", () => { + cy.get(".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('.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 chart titles", () => { + cy.get(".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('.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("displays frequency chart titles", () => { + cy.get(".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('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); + it("renders canvas elements for charts", () => { + cy.get(".z-\\[9999\\]", { timeout: 10000 }).should("not.exist"); // Chart.js renders into canvas elements - cy.get('canvas').should('have.length.at.least', 5); + cy.get("canvas").should("have.length.at.least", 5); }); - it('sidebar navigation scrolls to section', () => { - cy.get('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); + it("sidebar navigation scrolls to section", () => { + cy.get(".z-\\[9999\\]", { timeout: 10000 }).should("not.exist"); // Click on "Waiting Time" in sidebar - cy.contains('li', 'Waiting Time').click(); + cy.contains("li", "Waiting Time").click(); // The Waiting Time section should be in view - cy.get('#waitingTime').should('exist'); + cy.get("#waitingTime").should("exist"); }); }); diff --git a/cypress/e2e/discoverTabs.cy.js b/cypress/e2e/discoverTabs.cy.js index 0cd55f3..1ed86b7 100644 --- a/cypress/e2e/discoverTabs.cy.js +++ b/cypress/e2e/discoverTabs.cy.js @@ -3,94 +3,94 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('Discover Tab Navigation', () => { +describe("Discover Tab Navigation", () => { beforeEach(() => { loginWithFixtures(); // Suppress Cytoscape rendering errors in headless mode - cy.on('uncaught:exception', () => false); + cy.on("uncaught:exception", () => false); }); - describe('navigating from Map page', () => { + describe("navigating from Map page", () => { beforeEach(() => { - cy.visit('/discover/log/297310264/map'); - cy.wait('@getDiscover'); + cy.visit("/discover/log/297310264/map"); + cy.wait("@getDiscover"); }); - 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("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.wait('@getPerformance'); - cy.get('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); - cy.contains('Time Usage').should('be.visible'); + it("clicking PERFORMANCE tab navigates to performance page", () => { + cy.get(".nav-item").contains("PERFORMANCE").click(); + cy.url().should("include", "/performance"); + cy.wait("@getPerformance"); + cy.get(".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.wait('@getLogCheckParams'); - cy.get('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); - cy.contains('Rule Settings').should('be.visible'); + it("clicking CONFORMANCE tab navigates to conformance page", () => { + cy.get(".nav-item").contains("CONFORMANCE").click(); + cy.url().should("include", "/conformance"); + cy.wait("@getLogCheckParams"); + cy.get(".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'); + 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', () => { + describe("navigating from Performance page", () => { beforeEach(() => { - cy.visit('/discover/log/297310264/performance'); - cy.wait('@getPerformance'); - cy.get('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); + cy.visit("/discover/log/297310264/performance"); + cy.wait("@getPerformance"); + cy.get(".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.wait('@getDiscover'); - cy.get('#cy').should('exist'); + it("clicking MAP tab navigates to map page", () => { + cy.get(".nav-item").contains("MAP").click(); + cy.url().should("include", "/map"); + cy.wait("@getDiscover"); + 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.wait('@getLogCheckParams'); - cy.get('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); - cy.contains('Rule Settings').should('be.visible'); + it("clicking CONFORMANCE tab navigates to conformance page", () => { + cy.get(".nav-item").contains("CONFORMANCE").click(); + cy.url().should("include", "/conformance"); + cy.wait("@getLogCheckParams"); + cy.get(".z-\\[9999\\]", { timeout: 10000 }).should("not.exist"); + cy.contains("Rule Settings").should("be.visible"); }); }); - describe('navigating from Conformance page', () => { + describe("navigating from Conformance page", () => { beforeEach(() => { - cy.visit('/discover/log/297310264/conformance'); - cy.wait('@getLogCheckParams'); - cy.get('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); + cy.visit("/discover/log/297310264/conformance"); + cy.wait("@getLogCheckParams"); + cy.get(".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.wait('@getDiscover'); - cy.get('#cy').should('exist'); + it("clicking MAP tab navigates to map page", () => { + cy.get(".nav-item").contains("MAP").click(); + cy.url().should("include", "/map"); + cy.wait("@getDiscover"); + 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.wait('@getPerformance'); - cy.get('.z-\\[9999\\]', { timeout: 10000 }).should('not.exist'); - cy.contains('Time Usage').should('be.visible'); + it("clicking PERFORMANCE tab navigates to performance page", () => { + cy.get(".nav-item").contains("PERFORMANCE").click(); + cy.url().should("include", "/performance"); + cy.wait("@getPerformance"); + cy.get(".z-\\[9999\\]", { timeout: 10000 }).should("not.exist"); + cy.contains("Time Usage").should("be.visible"); }); }); }); diff --git a/cypress/e2e/edgeCases.cy.js b/cypress/e2e/edgeCases.cy.js index c111f2d..246e07d 100644 --- a/cypress/e2e/edgeCases.cy.js +++ b/cypress/e2e/edgeCases.cy.js @@ -3,92 +3,92 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('Edge Cases', () => { - describe('Empty states', () => { - it('files page handles empty file list', () => { +describe("Edge Cases", () => { + describe("Empty states", () => { + it("files page handles empty file list", () => { loginWithFixtures(); // Override files intercept with empty array - cy.intercept('GET', '/api/files', { + cy.intercept("GET", "/api/files", { statusCode: 200, body: [], - }).as('getEmptyFiles'); - cy.visit('/files'); - cy.wait('@getEmptyFiles'); + }).as("getEmptyFiles"); + cy.visit("/files"); + cy.wait("@getEmptyFiles"); // Table should exist but have no file data - cy.get('table').should('exist'); - cy.contains('sample-process.xes').should('not.exist'); + cy.get("table").should("exist"); + cy.contains("sample-process.xes").should("not.exist"); }); - it('account admin handles empty user list', () => { + it("account admin handles empty user list", () => { loginWithFixtures(); - cy.intercept('GET', '/api/users', { + cy.intercept("GET", "/api/users", { statusCode: 200, body: [], - }).as('getEmptyUsers'); - cy.visit('/account-admin'); - cy.wait('@getEmptyUsers'); + }).as("getEmptyUsers"); + cy.visit("/account-admin"); + cy.wait("@getEmptyUsers"); // Create New button should still work - cy.get('#create_new_acct_btn').should('exist'); + cy.get("#create_new_acct_btn").should("exist"); }); }); - describe('Authentication guard', () => { - it('unauthenticated user is redirected to login', () => { + describe("Authentication guard", () => { + it("unauthenticated user is redirected to login", () => { // No loginWithFixtures - not logged in - cy.visit('/files'); - cy.url().should('include', '/login'); + 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 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'); + 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', () => { - cy.intercept('POST', '/api/oauth/token', { + describe("Login validation", () => { + it("shows error on failed login", () => { + cy.intercept("POST", "/api/oauth/token", { statusCode: 401, - body: { detail: 'Invalid credentials' }, - }).as('failedLogin'); - cy.visit('/login'); - cy.get('#account').type('wrong'); - cy.get('#password').type('wrong'); - cy.get('form').submit(); - cy.wait('@failedLogin'); + body: { detail: "Invalid credentials" }, + }).as("failedLogin"); + cy.visit("/login"); + cy.get("#account").type("wrong"); + cy.get("#password").type("wrong"); + cy.get("form").submit(); + cy.wait("@failedLogin"); // Should stay on login page - cy.url().should('include', '/login'); + cy.url().should("include", "/login"); }); }); - describe('Account creation validation', () => { + describe("Account creation validation", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/account-admin'); - cy.wait('@getUsers'); - cy.get('#create_new_acct_btn').click(); + cy.visit("/account-admin"); + cy.wait("@getUsers"); + cy.get("#create_new_acct_btn").click(); }); - it('confirm stays disabled with only account field filled', () => { - cy.get('#input_account_field').type('newuser'); - cy.get('.confirm-btn').should('be.disabled'); + it("confirm stays disabled with only account field filled", () => { + cy.get("#input_account_field").type("newuser"); + cy.get(".confirm-btn").should("be.disabled"); }); - it('confirm stays disabled with only name field filled', () => { - cy.get('#input_name_field').type('New User'); - cy.get('.confirm-btn').should('be.disabled'); + it("confirm stays disabled with only name field filled", () => { + cy.get("#input_name_field").type("New User"); + cy.get(".confirm-btn").should("be.disabled"); }); - it('confirm stays disabled with only password field filled', () => { - cy.get('#input_first_pwd').type('password1234'); - cy.get('.confirm-btn').should('be.disabled'); + it("confirm stays disabled with only password field filled", () => { + cy.get("#input_first_pwd").type("password1234"); + cy.get(".confirm-btn").should("be.disabled"); }); }); }); diff --git a/cypress/e2e/fileOperations.cy.js b/cypress/e2e/fileOperations.cy.js index 10c3959..145f9a5 100644 --- a/cypress/e2e/fileOperations.cy.js +++ b/cypress/e2e/fileOperations.cy.js @@ -3,72 +3,72 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('File Operations', () => { +describe("File Operations", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/files'); - cy.wait('@getFiles'); + cy.visit("/files"); + cy.wait("@getFiles"); }); - it('file list table has sortable columns', () => { + 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'); + 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', () => { + it("clicking column header sorts the table", () => { // Click "Name" header to sort - cy.contains('th', 'Name').click(); + cy.contains("th", "Name").click(); // After sorting, table should still have data - cy.get('table tbody tr').should('have.length.greaterThan', 0); + 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 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 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("table shows file types", () => { + cy.get("table tbody").within(() => { + cy.contains("log").should("exist"); }); }); - it('right-click on file row shows context menu', () => { + it("right-click on file row shows context menu", () => { // PrimeVue DataTable with contextmenu - cy.get('table tbody tr').first().rightclick(); + 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); + cy.get("table tbody tr").should("have.length.greaterThan", 0); }); - it('grid view shows file cards', () => { + it("grid view shows file cards", () => { // Switch to grid view - cy.get('svg').parent('li.cursor-pointer').last().click(); + cy.get("svg").parent("li.cursor-pointer").last().click(); // Grid cards should be visible - cy.get('li[title]').should('have.length.greaterThan', 0); + cy.get("li[title]").should("have.length.greaterThan", 0); }); - it('Import button opens upload modal', () => { - cy.get('#import_btn').click(); + it("Import button opens upload modal", () => { + cy.get("#import_btn").click(); // Upload modal should appear - cy.get('#import_btn').should('exist'); + cy.get("#import_btn").should("exist"); }); }); diff --git a/cypress/e2e/files.cy.js b/cypress/e2e/files.cy.js index 211e871..197bdc8 100644 --- a/cypress/e2e/files.cy.js +++ b/cypress/e2e/files.cy.js @@ -3,58 +3,58 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('Files Page', () => { +describe("Files Page", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/files'); + cy.visit("/files"); }); - it('displays the file list after login', () => { - cy.wait('@getFiles'); - cy.contains('h2', 'All Files').should('exist'); + it("displays the file list after login", () => { + cy.wait("@getFiles"); + 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'); + 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.wait('@getFiles'); - cy.contains('h2', 'Recently Used').should('exist'); + it("shows Recently Used section", () => { + cy.wait("@getFiles"); + cy.contains("h2", "Recently Used").should("exist"); }); - it('switches to DISCOVER tab', () => { - cy.wait('@getFiles'); - cy.contains('.nav-item', 'DISCOVER').click(); + it("switches to DISCOVER tab", () => { + cy.wait("@getFiles"); + cy.contains(".nav-item", "DISCOVER").click(); // DISCOVER tab shows filtered file types - cy.contains('h2', 'All Files').should('exist'); + cy.contains("h2", "All Files").should("exist"); }); - it('switches to COMPARE tab and shows drag zones', () => { - cy.wait('@getFiles'); - cy.contains('.nav-item', 'COMPARE').click(); - cy.contains('Performance Comparison').should('exist'); - cy.contains('Drag and drop a file here').should('exist'); + it("switches to COMPARE tab and shows drag zones", () => { + cy.wait("@getFiles"); + 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.wait('@getFiles'); - cy.get('#import_btn').should('contain', 'Import'); + it("shows Import button on FILES tab", () => { + cy.wait("@getFiles"); + cy.get("#import_btn").should("contain", "Import"); }); - it('can switch between list and grid view', () => { - cy.wait('@getFiles'); + it("can switch between list and grid view", () => { + cy.wait("@getFiles"); // DataTable (list view) should be visible by default - cy.get('table').should('exist'); + cy.get("table").should("exist"); }); - it('double-click file navigates to discover page', () => { - cy.wait('@getFiles'); + it("double-click file navigates to discover page", () => { + cy.wait("@getFiles"); // 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'); + cy.get("table tbody tr").first().dblclick(); + cy.url().should("include", "/discover"); }); }); diff --git a/cypress/e2e/filesCompare.cy.js b/cypress/e2e/filesCompare.cy.js index 7bdf398..161170a 100644 --- a/cypress/e2e/filesCompare.cy.js +++ b/cypress/e2e/filesCompare.cy.js @@ -3,47 +3,47 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('Files Page - COMPARE Tab', () => { +describe("Files Page - COMPARE Tab", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/files'); - cy.wait('@getFiles'); + cy.visit("/files"); + cy.wait("@getFiles"); // Switch to COMPARE tab - cy.contains('li', 'COMPARE').click(); + cy.contains("li", "COMPARE").click(); }); - it('shows Performance Comparison heading', () => { - cy.contains('h2', 'Performance Comparison').should('be.visible'); + 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("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("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("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("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("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'); + 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"); }); }); diff --git a/cypress/e2e/filesToDiscover.cy.js b/cypress/e2e/filesToDiscover.cy.js index 452ecc7..9e796bc 100644 --- a/cypress/e2e/filesToDiscover.cy.js +++ b/cypress/e2e/filesToDiscover.cy.js @@ -3,72 +3,72 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('Files to Discover Entry Flow', () => { +describe("Files to Discover Entry Flow", () => { beforeEach(() => { loginWithFixtures(); // Suppress Cytoscape rendering errors in headless mode - cy.on('uncaught:exception', () => false); - cy.visit('/files'); - cy.wait('@getFiles'); + cy.on("uncaught:exception", () => false); + cy.visit("/files"); + cy.wait("@getFiles"); }); - describe('double-click table row to enter Discover', () => { - it('double-click log file navigates to Map page', () => { + 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.wait('@getDiscover'); - cy.get('#cy').should('exist'); + cy.contains("td.fileName", "sample-process.xes").parent("tr").dblclick(); + cy.url().should("include", "/discover/log/1/map"); + cy.wait("@getDiscover"); + 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.wait('@getFilterDiscover'); - 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.wait("@getFilterDiscover"); + cy.get("#cy").should("exist"); }); }); - describe('double-click grid card to enter Discover', () => { + describe("double-click grid card to enter Discover", () => { beforeEach(() => { // Switch to grid view - cy.get('svg').parent('li.cursor-pointer').last().click(); + cy.get("svg").parent("li.cursor-pointer").last().click(); }); - it('double-click log file grid card navigates to Map page', () => { + 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.wait('@getDiscover'); - cy.get('#cy').should('exist'); + cy.url().should("include", "/discover/log/1/map"); + cy.wait("@getDiscover"); + 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("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'); + 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'); + 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"); }); }); }); diff --git a/cypress/e2e/login.cy.js b/cypress/e2e/login.cy.js index 2d26c1d..10a0fae 100644 --- a/cypress/e2e/login.cy.js +++ b/cypress/e2e/login.cy.js @@ -3,74 +3,74 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { setupApiIntercepts, loginWithFixtures } from '../support/intercept'; +import { setupApiIntercepts, loginWithFixtures } from "../support/intercept"; -describe('Login Flow', () => { +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("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'); + 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'); + 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("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(); + 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.wait('@postToken'); - cy.url().should('include', '/files'); + cy.wait("@postToken"); + cy.url().should("include", "/files"); }); - it('failed login shows error message', () => { + it("failed login shows error message", () => { // Override the token intercept to return 401 - cy.intercept('POST', '/api/oauth/token', { + cy.intercept("POST", "/api/oauth/token", { statusCode: 401, - body: { detail: 'Incorrect username or password' }, - }).as('postTokenFail'); + body: { detail: "Incorrect username or password" }, + }).as("postTokenFail"); - cy.visit('/login'); - cy.get('#account').type('wronguser'); - cy.get('#password').type('wrongpass'); - cy.get('#login_btn_main_btn').click(); + cy.visit("/login"); + cy.get("#account").type("wronguser"); + cy.get("#password").type("wrongpass"); + cy.get("#login_btn_main_btn").click(); - cy.wait('@postTokenFail'); - cy.contains('Incorrect account or password').should('be.visible'); + cy.wait("@postTokenFail"); + 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'); + 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'); + 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'); + cy.get("#password").should("have.attr", "type", "password"); }); }); diff --git a/cypress/e2e/logout.cy.js b/cypress/e2e/logout.cy.js index 1439b08..0029031 100644 --- a/cypress/e2e/logout.cy.js +++ b/cypress/e2e/logout.cy.js @@ -3,65 +3,65 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('Logout Flow', () => { +describe("Logout Flow", () => { beforeEach(() => { loginWithFixtures(); }); - it('shows account menu when head icon is clicked', () => { - cy.visit('/files'); - cy.wait('@getFiles'); + it("shows account menu when head icon is clicked", () => { + cy.visit("/files"); + cy.wait("@getFiles"); // 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'); + 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.wait('@getFiles'); + it("account menu shows admin management link for admin user", () => { + cy.visit("/files"); + cy.wait("@getFiles"); - cy.get('#acct_mgmt_button').click(); - cy.get('#account_menu').should('be.visible'); + 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'); + cy.get("#btn_acct_mgmt").should("exist"); }); - it('account menu has logout button', () => { - cy.visit('/files'); - cy.wait('@getFiles'); + it("account menu has logout button", () => { + cy.visit("/files"); + cy.wait("@getFiles"); - cy.get('#acct_mgmt_button').click(); - cy.get('#btn_logout_in_menu').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.wait('@getFiles'); + it("clicking My Account navigates to /my-account", () => { + cy.visit("/files"); + cy.wait("@getFiles"); - cy.get('#acct_mgmt_button').click(); - cy.get('#btn_mang_ur_acct').click(); - cy.url().should('include', '/my-account'); + 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.wait('@getFiles'); + it("clicking Account Management navigates to /account-admin", () => { + cy.visit("/files"); + cy.wait("@getFiles"); - cy.get('#acct_mgmt_button').click(); - cy.get('#btn_acct_mgmt').click(); - cy.url().should('include', '/account-admin'); + 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.wait('@getFiles'); + it("logout redirects to login page", () => { + cy.visit("/files"); + cy.wait("@getFiles"); - cy.get('#acct_mgmt_button').click(); - cy.get('#btn_logout_in_menu').click(); - cy.url().should('include', '/login'); + cy.get("#acct_mgmt_button").click(); + cy.get("#btn_logout_in_menu").click(); + cy.url().should("include", "/login"); }); }); diff --git a/cypress/e2e/myAccount.cy.js b/cypress/e2e/myAccount.cy.js index c6b3bb4..52d084c 100644 --- a/cypress/e2e/myAccount.cy.js +++ b/cypress/e2e/myAccount.cy.js @@ -3,71 +3,71 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('My Account Page', () => { +describe("My Account Page", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/my-account'); - cy.wait('@getUserDetail'); + cy.visit("/my-account"); + cy.wait("@getUserDetail"); }); - 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("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 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("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("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("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 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("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("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 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'); + 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'); + cy.get(".cancel-btn").click(); + cy.get('input[type="password"]').should("not.exist"); }); - it('shows Session section', () => { - cy.contains('Session').should('exist'); + it("shows Session section", () => { + cy.contains("Session").should("exist"); }); }); diff --git a/cypress/e2e/navigation.cy.js b/cypress/e2e/navigation.cy.js index 82088c1..800ef4a 100644 --- a/cypress/e2e/navigation.cy.js +++ b/cypress/e2e/navigation.cy.js @@ -3,60 +3,60 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures, setupApiIntercepts } from '../support/intercept'; +import { loginWithFixtures, setupApiIntercepts } from "../support/intercept"; -describe('Navigation and Routing', () => { - it('redirects / to /files when logged in', () => { +describe("Navigation and Routing", () => { + it("redirects / to /files when logged in", () => { loginWithFixtures(); - cy.visit('/'); - cy.url().should('include', '/files'); + cy.visit("/"); + cy.url().should("include", "/files"); }); - it('shows 404 page for unknown routes', () => { + it("shows 404 page for unknown routes", () => { loginWithFixtures(); - cy.visit('/nonexistent-page'); - cy.contains('404').should('exist'); + cy.visit("/nonexistent-page"); + cy.contains("404").should("exist"); }); - it('navbar shows correct view name', () => { + it("navbar shows correct view name", () => { loginWithFixtures(); - cy.visit('/files'); - cy.wait('@getFiles'); - cy.get('#nav_bar').should('exist'); - cy.get('#nav_bar h2').should('contain', 'FILES'); + cy.visit("/files"); + cy.wait("@getFiles"); + cy.get("#nav_bar").should("exist"); + cy.get("#nav_bar h2").should("contain", "FILES"); }); - it('navbar shows back arrow on non-files pages', () => { + it("navbar shows back arrow on non-files pages", () => { loginWithFixtures(); - cy.visit('/discover/log/1/map'); + cy.visit("/discover/log/1/map"); // Back arrow should be visible on discover pages - cy.get('#backPage').should('exist'); + cy.get("#backPage").should("exist"); }); - it('navbar tabs are clickable on discover page', () => { + it("navbar tabs are clickable on discover page", () => { loginWithFixtures(); - cy.visit('/discover/log/1/map'); + 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'); + 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'); + 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'); + 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'); + cy.contains(".nav-item", "MAP").click(); + cy.url().should("include", "/map"); }); - it('login page is accessible at /login', () => { + it("login page is accessible at /login", () => { setupApiIntercepts(); - cy.visit('/login'); - cy.get('h2').should('contain', 'LOGIN'); + cy.visit("/login"); + cy.get("h2").should("contain", "LOGIN"); }); }); diff --git a/cypress/e2e/notFound404.cy.js b/cypress/e2e/notFound404.cy.js index 4b169b3..c0f8fff 100644 --- a/cypress/e2e/notFound404.cy.js +++ b/cypress/e2e/notFound404.cy.js @@ -3,36 +3,38 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('404 Not Found Page', () => { +describe("404 Not Found Page", () => { beforeEach(() => { // Suppress Navbar error on 404 page (route.matched[1] is null) - cy.on('uncaught:exception', () => false); + cy.on("uncaught:exception", () => false); }); - it('displays 404 page for non-existent route', () => { + 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'); + 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', () => { + 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'); + 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'); + 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'); + if (url.includes("/login")) { + cy.url().should("include", "/login"); } else { - cy.contains('404').should('be.visible'); + cy.contains("404").should("be.visible"); } }); }); diff --git a/cypress/e2e/pageAdmin.cy.js b/cypress/e2e/pageAdmin.cy.js index 7cbdec7..6fd6688 100644 --- a/cypress/e2e/pageAdmin.cy.js +++ b/cypress/e2e/pageAdmin.cy.js @@ -4,35 +4,35 @@ // cindy.chang@dsp.im (Cindy Chang), 2024/06/03 // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('Discover page navigation tabs', () => { +describe("Discover page navigation tabs", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/files'); - cy.wait('@getFiles'); + cy.visit("/files"); + cy.wait("@getFiles"); }); - it('Double-clicking a log file enters the MAP page.', () => { - cy.contains('td.fileName', 'sample-process.xes').dblclick(); - cy.url().should('include', 'map'); + 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'); + 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 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'); + 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"); }); }); diff --git a/cypress/e2e/pasteUrlLoginRedirect.cy.js b/cypress/e2e/pasteUrlLoginRedirect.cy.js index 8fda038..db6edd9 100644 --- a/cypress/e2e/pasteUrlLoginRedirect.cy.js +++ b/cypress/e2e/pasteUrlLoginRedirect.cy.js @@ -4,54 +4,55 @@ // cindy.chang@dsp.im (Cindy Chang), 2024/06/11 // imacat.yang@dsp.im (imacat), 2026/03/05 -import { setupApiIntercepts } from '../support/intercept'; +import { setupApiIntercepts } from "../support/intercept"; -describe('Paste URL login redirect', () => { - it('After login with return-to param, redirects to the remembered page', () => { +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 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(); - cy.wait('@postToken'); + cy.get("#account").type("testadmin"); + cy.get("#password").type("password123"); + cy.get("form").submit(); + cy.wait("@postToken"); // 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'); + cy.getCookie("luciaToken").should("exist"); }); - it('Login without return-to param redirects to /files', () => { + it("Login without return-to param redirects to /files", () => { setupApiIntercepts(); - cy.visit('/login'); + cy.visit("/login"); - cy.get('#account').type('testadmin'); - cy.get('#password').type('password123'); - cy.get('form').submit(); - cy.wait('@postToken'); + cy.get("#account").type("testadmin"); + cy.get("#password").type("password123"); + cy.get("form").submit(); + cy.wait("@postToken"); - cy.url().should('include', '/files'); + cy.url().should("include", "/files"); }); - it('Unauthenticated user cannot access inner pages', () => { + it("Unauthenticated user cannot access inner pages", () => { setupApiIntercepts(); // Override my-account to return 401 (simulate logged-out state) - cy.intercept('GET', '/api/my-account', { + cy.intercept("GET", "/api/my-account", { statusCode: 401, - body: { detail: 'Not authenticated' }, - }).as('getMyAccountUnauth'); + body: { detail: "Not authenticated" }, + }).as("getMyAccountUnauth"); - cy.visit('/files'); + cy.visit("/files"); // Should be redirected to login page - cy.url().should('include', '/login'); - cy.get('#account').should('exist'); - cy.get('#password').should('exist'); + cy.url().should("include", "/login"); + cy.get("#account").should("exist"); + cy.get("#password").should("exist"); }); }); diff --git a/cypress/e2e/sweetAlertModals.cy.js b/cypress/e2e/sweetAlertModals.cy.js index 8b1ec12..6b4d5a1 100644 --- a/cypress/e2e/sweetAlertModals.cy.js +++ b/cypress/e2e/sweetAlertModals.cy.js @@ -3,113 +3,113 @@ // Authors: // imacat.yang@dsp.im (imacat), 2026/03/05 -import { loginWithFixtures } from '../support/intercept'; +import { loginWithFixtures } from "../support/intercept"; -describe('SweetAlert2 Modals', () => { - describe('File Context Menu - Rename', () => { +describe("SweetAlert2 Modals", () => { + describe("File Context Menu - Rename", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/files'); - cy.wait('@getFiles'); + cy.visit("/files"); + cy.wait("@getFiles"); }); - 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 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 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("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(); + 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'); + 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 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("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(); + 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'); + 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 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'); + 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', () => { + describe("File Context Menu on Grid View", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/files'); - cy.wait('@getFiles'); + cy.visit("/files"); + cy.wait("@getFiles"); // Switch to grid view - cy.get('svg').parent('li.cursor-pointer').last().click(); + 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("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'); + 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', () => { + describe("Account Delete Confirmation", () => { beforeEach(() => { loginWithFixtures(); - cy.visit('/account-admin'); - cy.wait('@getUsers'); + cy.visit("/account-admin"); + cy.wait("@getUsers"); }); - 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(); - cy.wait('@deleteUser'); + 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(); + cy.wait("@deleteUser"); // Modal should close after deletion }); }); diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 791df0b..9e5f54c 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -14,16 +14,16 @@ // https://on.cypress.io/custom-commands // *********************************************** // -- This is a parent command -- -import '@4tw/cypress-drag-drop' +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'); +Cypress.Commands.add("login", () => { + cy.setCookie("luciaToken", "fake-access-token-for-testing"); + cy.setCookie("isLuciaLoggedIn", "true"); }); // Usage: cy.login() // -- This is a child command -- @@ -33,8 +33,8 @@ Cypress.Commands.add('login', () => { * * @returns {void} */ -Cypress.Commands.add('closePopup', () => { +Cypress.Commands.add("closePopup", () => { // Trigger a forced click to close modal overlays consistently. - cy.get('body').click({ position: 'topLeft'}); + cy.get("body").click({ position: "topLeft" }); cy.wait(1000); -}) +}); diff --git a/cypress/support/e2e.js b/cypress/support/e2e.js index 549bc56..67318bd 100644 --- a/cypress/support/e2e.js +++ b/cypress/support/e2e.js @@ -20,11 +20,11 @@ // Import commands.js using ES2015 syntax: import "./commands"; -Cypress.on('uncaught:exception', (err, runnable) => { +Cypress.on("uncaught:exception", (err, runnable) => { // returning false here prevents Cypress from failing the test - return false -}) + return false; +}); // Alternatively you can use CommonJS syntax: // require('./commands') -require('cypress-xpath') // Enables xpath helpers used in pointer event checks. +require("cypress-xpath"); // Enables xpath helpers used in pointer event checks. diff --git a/cypress/support/intercept.js b/cypress/support/intercept.js index 70744ef..92c71b6 100644 --- a/cypress/support/intercept.js +++ b/cypress/support/intercept.js @@ -9,174 +9,174 @@ */ export function setupApiIntercepts() { // Auth - cy.intercept('POST', '/api/oauth/token', { - fixture: 'api/token.json', - }).as('postToken'); + cy.intercept("POST", "/api/oauth/token", { + fixture: "api/token.json", + }).as("postToken"); // User account - cy.intercept('GET', '/api/my-account', { - fixture: 'api/my-account.json', - }).as('getMyAccount'); + cy.intercept("GET", "/api/my-account", { + fixture: "api/my-account.json", + }).as("getMyAccount"); - cy.intercept('PUT', '/api/my-account', { + cy.intercept("PUT", "/api/my-account", { statusCode: 200, body: { success: true }, - }).as('putMyAccount'); + }).as("putMyAccount"); // Files - cy.intercept('GET', '/api/files', { - fixture: 'api/files.json', - }).as('getFiles'); + cy.intercept("GET", "/api/files", { + fixture: "api/files.json", + }).as("getFiles"); // Users (account management) - cy.intercept('GET', '/api/users', { - fixture: 'api/users.json', - }).as('getUsers'); + cy.intercept("GET", "/api/users", { + fixture: "api/users.json", + }).as("getUsers"); - cy.intercept('POST', '/api/users', { + cy.intercept("POST", "/api/users", { statusCode: 200, body: { success: true }, - }).as('postUser'); + }).as("postUser"); - cy.intercept('DELETE', '/api/users/*', { + cy.intercept("DELETE", "/api/users/*", { statusCode: 200, body: { success: true }, - }).as('deleteUser'); + }).as("deleteUser"); - cy.intercept('PUT', '/api/users/*', { + cy.intercept("PUT", "/api/users/*", { statusCode: 200, body: { success: true }, - }).as('putUser'); + }).as("putUser"); // User detail (GET /api/users/:username) - cy.intercept('GET', '/api/users/*', { - fixture: 'api/user-detail.json', - }).as('getUserDetail'); + cy.intercept("GET", "/api/users/*", { + fixture: "api/user-detail.json", + }).as("getUserDetail"); // User roles - cy.intercept('PUT', '/api/users/*/roles/*', { + cy.intercept("PUT", "/api/users/*/roles/*", { statusCode: 200, body: { success: true }, - }).as('putUserRole'); + }).as("putUserRole"); - cy.intercept('DELETE', '/api/users/*/roles/*', { + cy.intercept("DELETE", "/api/users/*/roles/*", { statusCode: 200, body: { success: true }, - }).as('deleteUserRole'); + }).as("deleteUserRole"); // Filter detail (for fetchFunnel when entering filter from Files) - cy.intercept('GET', /\/api\/filters\/\d+$/, { + cy.intercept("GET", /\/api\/filters\/\d+$/, { statusCode: 200, - body: { rules: [], log: { id: 1 }, name: 'filtered-sample' }, - }).as('getFilterDetail'); + body: { rules: [], log: { id: 1 }, name: "filtered-sample" }, + }).as("getFilterDetail"); // Discover (map data) - cy.intercept('GET', '/api/logs/*/discover', { - fixture: 'api/discover.json', - }).as('getDiscover'); + cy.intercept("GET", "/api/logs/*/discover", { + fixture: "api/discover.json", + }).as("getDiscover"); - cy.intercept('GET', '/api/filters/*/discover', { - fixture: 'api/discover.json', - }).as('getFilterDiscover'); + cy.intercept("GET", "/api/filters/*/discover", { + fixture: "api/discover.json", + }).as("getFilterDiscover"); // Performance - cy.intercept('GET', '/api/logs/*/performance', { - fixture: 'api/performance.json', - }).as('getPerformance'); + cy.intercept("GET", "/api/logs/*/performance", { + fixture: "api/performance.json", + }).as("getPerformance"); - cy.intercept('GET', '/api/filters/*/performance', { - fixture: 'api/performance.json', - }).as('getFilterPerformance'); + cy.intercept("GET", "/api/filters/*/performance", { + fixture: "api/performance.json", + }).as("getFilterPerformance"); // Traces - cy.intercept('GET', '/api/logs/*/traces', { - fixture: 'api/traces.json', - }).as('getTraces'); + cy.intercept("GET", "/api/logs/*/traces", { + fixture: "api/traces.json", + }).as("getTraces"); - cy.intercept('GET', '/api/filters/*/traces', { - fixture: 'api/traces.json', - }).as('getFilterTraces'); + cy.intercept("GET", "/api/filters/*/traces", { + fixture: "api/traces.json", + }).as("getFilterTraces"); // Trace detail (must be after traces list intercepts) - cy.intercept('GET', /\/api\/logs\/.*\/traces\/\d+/, { - fixture: 'api/trace-detail.json', - }).as('getTraceDetail'); + cy.intercept("GET", /\/api\/logs\/.*\/traces\/\d+/, { + fixture: "api/trace-detail.json", + }).as("getTraceDetail"); - cy.intercept('GET', /\/api\/filters\/.*\/traces\/\d+/, { - fixture: 'api/trace-detail.json', - }).as('getFilterTraceDetail'); + cy.intercept("GET", /\/api\/filters\/.*\/traces\/\d+/, { + fixture: "api/trace-detail.json", + }).as("getFilterTraceDetail"); // Temp filters - cy.intercept('GET', '/api/temp-filters/*/discover', { - fixture: 'api/discover.json', - }).as('getTempFilterDiscover'); + cy.intercept("GET", "/api/temp-filters/*/discover", { + fixture: "api/discover.json", + }).as("getTempFilterDiscover"); - cy.intercept('GET', '/api/temp-filters/*/traces', { - fixture: 'api/traces.json', - }).as('getTempFilterTraces'); + cy.intercept("GET", "/api/temp-filters/*/traces", { + fixture: "api/traces.json", + }).as("getTempFilterTraces"); // Filter params - cy.intercept('GET', '/api/filters/params*', { + cy.intercept("GET", "/api/filters/params*", { statusCode: 200, body: {}, - }).as('getFilterParams'); + }).as("getFilterParams"); - cy.intercept('GET', '/api/filters/has-result*', { + cy.intercept("GET", "/api/filters/has-result*", { statusCode: 200, body: false, - }).as('getFilterHasResult'); + }).as("getFilterHasResult"); // Conformance check params - cy.intercept('GET', '/api/log-checks/params*', { - fixture: 'api/filter-params.json', - }).as('getLogCheckParams'); + cy.intercept("GET", "/api/log-checks/params*", { + fixture: "api/filter-params.json", + }).as("getLogCheckParams"); - cy.intercept('GET', '/api/filter-checks/params*', { - fixture: 'api/filter-params.json', - }).as('getFilterCheckParams'); + cy.intercept("GET", "/api/filter-checks/params*", { + fixture: "api/filter-params.json", + }).as("getFilterCheckParams"); // Compare dashboard - cy.intercept('GET', /\/api\/compare\?datasets=/, { - fixture: 'api/compare.json', - }).as('getCompare'); + cy.intercept("GET", /\/api\/compare\?datasets=/, { + fixture: "api/compare.json", + }).as("getCompare"); // Dependents (for delete confirmation) - cy.intercept('GET', '/api/logs/*/dependents', { + cy.intercept("GET", "/api/logs/*/dependents", { statusCode: 200, body: [], - }).as('getLogDependents'); + }).as("getLogDependents"); - cy.intercept('GET', '/api/filters/*/dependents', { + cy.intercept("GET", "/api/filters/*/dependents", { statusCode: 200, body: [], - }).as('getFilterDependents'); + }).as("getFilterDependents"); - cy.intercept('GET', '/api/log-checks/*/dependents', { + cy.intercept("GET", "/api/log-checks/*/dependents", { statusCode: 200, body: [], - }).as('getLogCheckDependents'); + }).as("getLogCheckDependents"); - cy.intercept('GET', '/api/filter-checks/*/dependents', { + cy.intercept("GET", "/api/filter-checks/*/dependents", { statusCode: 200, body: [], - }).as('getFilterCheckDependents'); + }).as("getFilterCheckDependents"); // Rename - cy.intercept('PUT', '/api/logs/*/rename', { + cy.intercept("PUT", "/api/logs/*/rename", { statusCode: 200, body: { success: true }, - }).as('renameLog'); + }).as("renameLog"); - cy.intercept('PUT', '/api/filters/*/rename', { + cy.intercept("PUT", "/api/filters/*/rename", { statusCode: 200, body: { success: true }, - }).as('renameFilter'); + }).as("renameFilter"); // Deletion - cy.intercept('DELETE', '/api/deletion/*', { + cy.intercept("DELETE", "/api/deletion/*", { statusCode: 200, body: { success: true }, - }).as('deleteDeletion'); + }).as("deleteDeletion"); } /** @@ -185,6 +185,6 @@ export function setupApiIntercepts() { */ export function loginWithFixtures() { setupApiIntercepts(); - cy.setCookie('luciaToken', 'fake-access-token-for-testing'); - cy.setCookie('isLuciaLoggedIn', 'true'); + cy.setCookie("luciaToken", "fake-access-token-for-testing"); + cy.setCookie("isLuciaLoggedIn", "true"); } diff --git a/src/api/auth.js b/src/api/auth.js index 4d65701..cd5fb21 100644 --- a/src/api/auth.js +++ b/src/api/auth.js @@ -4,8 +4,12 @@ // imacat.yang@dsp.im (imacat), 2023/9/23 /** @module auth Authentication token refresh utilities. */ -import axios from 'axios'; -import { getCookie, setCookie, setCookieWithoutExpiration } from '@/utils/cookieUtil.js'; +import axios from "axios"; +import { + getCookie, + setCookie, + setCookieWithoutExpiration, +} from "@/utils/cookieUtil.js"; /** * Refreshes the access token using the stored refresh token cookie. @@ -18,27 +22,29 @@ import { getCookie, setCookie, setCookieWithoutExpiration } from '@/utils/cookie * @throws {Error} If the refresh request fails. */ export async function refreshTokenAndGetNew() { - const api = '/api/oauth/token'; + const api = "/api/oauth/token"; const config = { headers: { - 'Content-Type': 'application/x-www-form-urlencoded', + "Content-Type": "application/x-www-form-urlencoded", }, }; const data = { - grant_type: 'refresh_token', - refresh_token: getCookie('luciaRefreshToken'), + grant_type: "refresh_token", + refresh_token: getCookie("luciaRefreshToken"), }; const response = await axios.post(api, data, config); const newAccessToken = response.data.access_token; const newRefreshToken = response.data.refresh_token; - setCookieWithoutExpiration('luciaToken', newAccessToken); + setCookieWithoutExpiration("luciaToken", newAccessToken); // Expire in ~6 months const expiredMs = new Date(); expiredMs.setMonth(expiredMs.getMonth() + 6); - const days = Math.ceil((expiredMs.getTime() - Date.now()) / (24 * 60 * 60 * 1000)); - setCookie('luciaRefreshToken', newRefreshToken, days); + const days = Math.ceil( + (expiredMs.getTime() - Date.now()) / (24 * 60 * 60 * 1000), + ); + setCookie("luciaRefreshToken", newRefreshToken, days); return newAccessToken; } diff --git a/src/api/client.js b/src/api/client.js index ae3d3fc..df5d38f 100644 --- a/src/api/client.js +++ b/src/api/client.js @@ -8,15 +8,15 @@ * 401 token refresh with request queuing. */ -import axios from 'axios'; -import { getCookie, deleteCookie } from '@/utils/cookieUtil.js'; +import axios from "axios"; +import { getCookie, deleteCookie } from "@/utils/cookieUtil.js"; /** Axios instance configured with auth interceptors. */ const apiClient = axios.create(); // Request interceptor: automatically attach Authorization header apiClient.interceptors.request.use((config) => { - const token = getCookie('luciaToken'); + const token = getCookie("luciaToken"); if (token) { config.headers.Authorization = `Bearer ${token}`; } @@ -54,7 +54,7 @@ apiClient.interceptors.response.use( if ( error.response?.status !== 401 || originalRequest._retried || - originalRequest.url === '/api/oauth/token' + originalRequest.url === "/api/oauth/token" ) { return Promise.reject(error); } @@ -76,7 +76,7 @@ apiClient.interceptors.response.use( try { // Dynamic import to avoid circular dependency with login store - const { refreshTokenAndGetNew } = await import('@/api/auth.js'); + const { refreshTokenAndGetNew } = await import("@/api/auth.js"); const newToken = await refreshTokenAndGetNew(); isRefreshing = false; onRefreshSuccess(newToken); @@ -87,11 +87,11 @@ apiClient.interceptors.response.use( onRefreshFailure(refreshError); // Refresh failed: clear auth and redirect to login - deleteCookie('luciaToken'); - window.location.href = '/login'; + deleteCookie("luciaToken"); + window.location.href = "/login"; return Promise.reject(refreshError); } - } + }, ); export default apiClient; diff --git a/src/components/AccountMenu/AcctMenu.vue b/src/components/AccountMenu/AcctMenu.vue index 05d9cb8..cc03d90 100644 --- a/src/components/AccountMenu/AcctMenu.vue +++ b/src/components/AccountMenu/AcctMenu.vue @@ -1,32 +1,51 @@ diff --git a/src/components/Badge.vue b/src/components/Badge.vue index 02d0ae3..7fa25dd 100644 --- a/src/components/Badge.vue +++ b/src/components/Badge.vue @@ -1,18 +1,18 @@ +
+ {{ displayText }} +
+ - +defineProps({ + isActivated: { + type: Boolean, + required: true, + default: true, + }, + displayText: { + type: String, + required: true, + default: "Status", + }, +}); + diff --git a/src/components/Button.vue b/src/components/Button.vue index abace7c..bb8f50f 100644 --- a/src/components/Button.vue +++ b/src/components/Button.vue @@ -1,18 +1,16 @@ diff --git a/src/components/ButtonFilled.vue b/src/components/ButtonFilled.vue index 7d047d0..7c0d8a1 100644 --- a/src/components/ButtonFilled.vue +++ b/src/components/ButtonFilled.vue @@ -1,19 +1,18 @@ diff --git a/src/components/Compare/SidebarStates.vue b/src/components/Compare/SidebarStates.vue index 1dfd99a..2fd9ba3 100644 --- a/src/components/Compare/SidebarStates.vue +++ b/src/components/Compare/SidebarStates.vue @@ -1,5 +1,14 @@