Merge pull request #2886 from devvaansh/WEB-493-tests-add-e-2-e-regression-test-for-audit-trails-csv-download

E2E regression test for Audit Trails CSV download
This commit is contained in:
Gopi Kishan
2025-12-13 14:28:03 +05:30
committed by GitHub
6 changed files with 180 additions and 19 deletions
-12
View File
@@ -6,17 +6,5 @@ last 2 versions
> 0.5%
Firefox ESR
not dead
not and_qq 14.9
not and_uc 15.5
not android 142
not kaios 2.5
not kaios 3.0-3.1
not op_mini all
not op_mob 80
not opera 122
not opera 121
not samsung 28
not samsung 29
not samsung 27
# For IE 9-11 support, please uncomment the next line and adjust as needed
# IE 9-11
+5 -1
View File
@@ -55,7 +55,11 @@ testem.log
.DS_Store
Thumbs.db
.vscode/
cypress/
# Cypress - only ignore downloads, screenshots, and videos
cypress/downloads/
cypress/screenshots/
cypress/videos/
src/assets/env.js
src/environments/.env.ts
+2 -1
View File
@@ -11,7 +11,8 @@ export default defineConfig({
setupNodeEvents(on, config) {
return require('./cypress/plugins/index.ts')(on, config);
},
baseUrl: 'http://localhost:4200'
baseUrl: 'http://localhost:4200',
experimentalStudio: true // enable Cypress Studio
},
component: {
+169
View File
@@ -0,0 +1,169 @@
describe('Audit Trails', () => {
// Test data constants for easy maintenance
const TEST_USER = {
username: 'mifos',
password: 'password'
};
const BASE_URL = 'http://localhost:4200';
beforeEach(() => {
// Start each test from a clean state
cy.visit(BASE_URL);
});
it('should login, search for system, navigate to audit trails, and download CSV without errors', () => {
// Step 1: Login to the application
loginToApplication(TEST_USER.username, TEST_USER.password);
// Step 2: Handle the warning dialog if it appears
handleWarningDialog();
// Step 3: Use global search to find "system"
searchInGlobalSearchBar('system');
// Step 4: Click directly on Audit Trails button (no need to click System menu first!)
clickAuditTrailsButton();
// Step 5: Download CSV from audit trails page
downloadCSV();
// Step 6: Verify no errors occurred (Regression Check)
verifyNoErrorToast();
});
// Helper Functions for better readability and reusability
/**
* Logs into the application with provided credentials
*/
function loginToApplication(username: string, password: string) {
// Find username input - using multiple selectors for stability
cy.get('input[placeholder="Username"], input[formcontrolname="username"], input[type="text"]')
.first()
.should('be.visible')
.clear()
.type(username);
// Find password input
cy.get('input[placeholder="Password"], input[type="password"]').should('be.visible').clear().type(password);
// Click the login button using text content (most stable)
cy.contains('button', 'Login').click({ force: true });
// Wait for login to complete
cy.url().should('not.include', '/login');
}
/**
* Handles the warning/info dialog that appears after login
*/
function handleWarningDialog() {
// Wait for dialog to appear and close it
cy.get('mat-dialog-container', { timeout: 10000 })
.should('be.visible')
.within(() => {
cy.contains('button', /close|ok|continue/i).click({ force: true });
});
// Wait for dialog to close
cy.wait(1000);
}
/**
* Uses the global search bar to search for content
* Based on the original recording: mat-mdc-text-field-wrapper
*/
function searchInGlobalSearchBar(searchTerm: string) {
// Find the search field using the class you provided
cy.get('.mat-mdc-text-field-wrapper input, .mdc-text-field input')
.first()
.should('be.visible')
.clear()
.type(searchTerm);
// Wait for search results/autocomplete to appear
cy.wait(1000);
// Select the matching option from the dropdown
cy.get('mat-option').should('be.visible');
cy.contains('mat-option', searchTerm, { matchCase: false }).click();
}
/**
* Clicks on the Audit Trails button that appears after searching for "system"
* After the search, a menu opens with various options including Audit Trails
*/
function clickAuditTrailsButton() {
// After searching for "system", a menu opens
// We need to click the Audit Trails option directly from that menu
// Class: mat-mdc-list-item mdc-list-item mat-mdc-list-item-interactive
cy.get('.mat-mdc-list-item.mdc-list-item')
.contains(/audit.*trail/i)
.should('be.visible')
.click({ force: true });
// Wait for audit trails page to load
cy.url().should('include', 'audit');
cy.wait(2000);
}
/**
* Downloads the CSV file from the audit trails page
* Based on original: looks for download button
*/
function downloadCSV() {
// Wait for the audit trails page to load completely
cy.wait(2000); // Ideally use cy.intercept, but wait is okay for now
// strategy : Try the Icon first (Most reliable based on previous errors), then fallback to text
cy.get('body').then(($body) => {
// Check for the specific Excel Icon we found earlier
if ($body.find('.fa-file-excel-o').length > 0) {
cy.get('.fa-file-excel-o').parent().click({ force: true });
cy.log('Clicked download button using Icon class');
}
// fallback: Check for ARIA labels or Text
else if ($body.find('button[aria-label*="ownload"]').length > 0) {
cy.get('button[aria-label*="ownload"]').click({ force: true });
cy.log('Clicked download button using Aria Label');
} else {
// Last resort: Text
cy.contains('button', /csv|download|export/i).click({ force: true });
}
});
// Wait for download to process
cy.wait(2000);
}
/**
* regression check : Verifies that no error toast appears
* This ensures the download operation completed successfully
*/
function verifyNoErrorToast() {
// Primary check: No error toast should appear
// Using specific toast selectors to avoid false positives from unrelated error classes
// like mat-error, error-text, etc.
cy.get('.toast-container .toast-error, .toast-error, [data-cy="toast-error"]', { timeout: 5000 }).should(
'not.exist'
);
// Additional check: If any toast exists, ensure it doesn't have error styling
cy.get('body').then(($body) => {
const toastExists = $body.find('.toast-container .toast').length > 0;
if (toastExists) {
cy.get('.toast-container .toast').filter(':visible').should('not.have.class', 'toast-error');
cy.log('✓ Regression check passed: Toast found but no error styling detected');
} else {
cy.log('✓ Regression check passed: No toast notifications detected');
}
});
// Note: CSV download verification
// Cypress automatically downloads files to cypress/downloads folder
// You can manually verify the CSV file after the test completes
// Or add cy.readFile('cypress/downloads/filename.csv') for automated verification
}
});
+2 -3
View File
@@ -2,8 +2,8 @@ describe('Login Page', () => {
it('Visits the initial web page', () => {
cy.visit('/');
cy.url().should('includes', 'login');
cy.get('#mat-input-0').should ('be.visible');
cy.get('#mat-input-1').should ('be.visible');
cy.get('#mat-input-0').should('be.visible');
cy.get('#mat-input-1').should('be.visible');
cy.contains('Login');
cy.contains('Remember me');
});
@@ -26,5 +26,4 @@ describe('Login Page', () => {
cy.get('#logout').click();
cy.contains('Username');
});
});
+2 -2
View File
@@ -2,7 +2,7 @@
"extends": "../tsconfig.json",
"include": ["**/*.ts"],
"compilerOptions": {
"sourceMap": false,
"types": ["cypress"]
"sourceMap": false,
"types": ["cypress"]
}
}