@iblai/iblai-js 1.4.3 → 1.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data-layer/playwright/audit-log-helpers.d.ts +119 -0
- package/dist/data-layer/playwright/index.d.ts +1 -0
- package/dist/playwright/index.cjs +391 -0
- package/dist/playwright/index.cjs.map +1 -1
- package/dist/playwright/index.d.ts +120 -1
- package/dist/playwright/index.esm.js +366 -1
- package/dist/playwright/index.esm.js.map +1 -1
- package/dist/playwright/playwright/audit-log-helpers.d.ts +119 -0
- package/dist/playwright/playwright/index.d.ts +1 -0
- package/dist/web-containers/playwright/audit-log-helpers.d.ts +119 -0
- package/dist/web-containers/playwright/index.d.ts +1 -0
- package/dist/web-containers/source/index.esm.js +1318 -638
- package/dist/web-containers/source/next/index.esm.js +950 -406
- package/dist/web-utils/playwright/audit-log-helpers.d.ts +119 -0
- package/dist/web-utils/playwright/index.d.ts +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Page } from '@playwright/test';
|
|
2
|
+
/**
|
|
3
|
+
* Navigate to the Audit tab within the Analytics section.
|
|
4
|
+
* Assumes the user is already on the analytics page (any tab).
|
|
5
|
+
*/
|
|
6
|
+
export declare function navigateToAuditLog(page: Page): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Verify the audit log table is visible with correct headers.
|
|
9
|
+
*/
|
|
10
|
+
export declare function verifyAuditLogTableVisible(page: Page): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Get the number of rows currently displayed in the audit log table.
|
|
13
|
+
* Returns 0 if no table body rows are found.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getAuditLogRowCount(page: Page): Promise<number>;
|
|
16
|
+
/**
|
|
17
|
+
* Verify that audit log entries contain expected data structure
|
|
18
|
+
* (person name in first cell, action description in second, timestamp in third).
|
|
19
|
+
*/
|
|
20
|
+
export declare function verifyAuditLogEntryStructure(page: Page): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Verify the empty state is displayed when there are no audit log entries.
|
|
23
|
+
*/
|
|
24
|
+
export declare function verifyAuditLogEmptyState(page: Page): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Verify the 403 permission error state is displayed.
|
|
27
|
+
*/
|
|
28
|
+
export declare function verifyAuditLogPermissionError(page: Page): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Verify the generic error state is displayed.
|
|
31
|
+
*/
|
|
32
|
+
export declare function verifyAuditLogGenericError(page: Page): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Verify the loading spinner is displayed while audit logs are being fetched.
|
|
35
|
+
*/
|
|
36
|
+
export declare function verifyAuditLogLoading(page: Page): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Wait for the audit log data to finish loading.
|
|
39
|
+
* Waits for either table data, empty state, or error state to appear.
|
|
40
|
+
*/
|
|
41
|
+
export declare function waitForAuditLogDataLoaded(page: Page, timeout?: number): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Filter audit log entries by action type.
|
|
44
|
+
* @param action - One of 'All Actions', 'Create', 'Update', or 'Delete'
|
|
45
|
+
*/
|
|
46
|
+
export declare function filterByAction(page: Page, action: 'All Actions' | 'Create' | 'Update' | 'Delete'): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Filter audit log entries by actor/person using the search combobox.
|
|
49
|
+
* @param actorName - The username to filter by, or empty string to clear the filter
|
|
50
|
+
*/
|
|
51
|
+
export declare function filterByActor(page: Page, actorName: string): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Get the list of actors available in the actor filter dropdown.
|
|
54
|
+
* Opens the dropdown, reads the options, then closes it.
|
|
55
|
+
*/
|
|
56
|
+
export declare function getAvailableActors(page: Page): Promise<string[]>;
|
|
57
|
+
/**
|
|
58
|
+
* Open the date range picker and select a date range.
|
|
59
|
+
* @param fromDate - Start date to select
|
|
60
|
+
* @param toDate - End date to select
|
|
61
|
+
*/
|
|
62
|
+
export declare function filterByDateRange(page: Page, fromDate: Date, toDate: Date): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Clear the date range filter by clicking the date picker and resetting.
|
|
65
|
+
*/
|
|
66
|
+
export declare function clearDateRangeFilter(page: Page): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Get the current pagination info text (e.g., "Showing 1 to 20 of 45 results").
|
|
69
|
+
* Returns null if pagination is not visible.
|
|
70
|
+
*/
|
|
71
|
+
export declare function getPaginationInfo(page: Page): Promise<string | null>;
|
|
72
|
+
/**
|
|
73
|
+
* Navigate to the next page of audit log results.
|
|
74
|
+
*/
|
|
75
|
+
export declare function goToNextPage(page: Page): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Navigate to the previous page of audit log results.
|
|
78
|
+
*/
|
|
79
|
+
export declare function goToPreviousPage(page: Page): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Navigate to the first page of audit log results.
|
|
82
|
+
*/
|
|
83
|
+
export declare function goToFirstPage(page: Page): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Navigate to the last page of audit log results.
|
|
86
|
+
* Finds the highest numbered page link in the pagination.
|
|
87
|
+
*/
|
|
88
|
+
export declare function goToLastPage(page: Page): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Navigate to a specific page number by clicking its page button.
|
|
91
|
+
*/
|
|
92
|
+
export declare function goToPage(page: Page, pageNumber: number): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Verify the current page is highlighted/active in pagination.
|
|
95
|
+
*/
|
|
96
|
+
export declare function verifyCurrentPage(page: Page, expectedPage: number): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Check if the next page button is disabled (i.e., we're on the last page).
|
|
99
|
+
*/
|
|
100
|
+
export declare function isOnLastPage(page: Page): Promise<boolean>;
|
|
101
|
+
/**
|
|
102
|
+
* Check if the previous page button is disabled (i.e., we're on the first page).
|
|
103
|
+
*/
|
|
104
|
+
export declare function isOnFirstPage(page: Page): Promise<boolean>;
|
|
105
|
+
/**
|
|
106
|
+
* Full workflow: Navigate to audit log tab, wait for data to load,
|
|
107
|
+
* and verify the table is visible. Use this as a test setup helper.
|
|
108
|
+
*/
|
|
109
|
+
export declare function navigateToAuditLogAndWaitForData(page: Page): Promise<void>;
|
|
110
|
+
/**
|
|
111
|
+
* Verify audit log entries are displayed after applying action filter.
|
|
112
|
+
* Returns the row count after filtering.
|
|
113
|
+
*/
|
|
114
|
+
export declare function filterByActionAndVerify(page: Page, action: 'All Actions' | 'Create' | 'Update' | 'Delete'): Promise<number>;
|
|
115
|
+
/**
|
|
116
|
+
* Verify audit log entries are displayed after applying actor filter.
|
|
117
|
+
* Returns the row count after filtering.
|
|
118
|
+
*/
|
|
119
|
+
export declare function filterByActorAndVerify(page: Page, actorName: string): Promise<number>;
|
|
@@ -16,5 +16,6 @@ export type { EnvConfig, AuthFlowType } from './env-config';
|
|
|
16
16
|
export { buildReportUrl, parseReportUrlParams, navigateToReportDownload, verifyPreparingPhase, verifyDownloadingPhase, verifyDonePhase, verifyErrorPhase, clickBackHome, clickDownloadAgain, clickManualDownloadLink, waitForReportDownload, } from './report-download';
|
|
17
17
|
export type { ReportDownloadOptions } from './report-download';
|
|
18
18
|
export { isMemoryTabVisible, switchToMemoryTab, verifyMemoryTabSettings, verifyMemoryTabMemoriesList, openAddMemoryDialog, toggleMemorySwitch, addMemory, deleteFirstMemory, deleteMemoryByContent, archiveFirstMemory, archiveMemoryByContent, getMemoryCount, verifyMemoryExists, verifyMemoryNotExists, } from './memory-test-helpers';
|
|
19
|
+
export { navigateToAuditLog, verifyAuditLogTableVisible, getAuditLogRowCount, verifyAuditLogEntryStructure, verifyAuditLogEmptyState, verifyAuditLogPermissionError, verifyAuditLogGenericError, verifyAuditLogLoading, waitForAuditLogDataLoaded, filterByAction, filterByActor, getAvailableActors, filterByDateRange, clearDateRangeFilter, getPaginationInfo, goToNextPage, goToPreviousPage, goToFirstPage, goToLastPage, goToPage, verifyCurrentPage, isOnLastPage, isOnFirstPage, navigateToAuditLogAndWaitForData, filterByActionAndVerify, filterByActorAndVerify, } from './audit-log-helpers';
|
|
19
20
|
export { createPlaywrightConfig, generateProjectConfig, generateBrowserSetupProjects, getBrowserKey, } from './playwright-config';
|
|
20
21
|
export type { PlatformConfig, CreatePlaywrightConfigOptions } from './playwright-config';
|
|
@@ -1710,6 +1710,371 @@ async function verifyMemoryNotExists(page, content) {
|
|
|
1710
1710
|
logger.info(`Verified memory removed: "${content}"`);
|
|
1711
1711
|
}
|
|
1712
1712
|
|
|
1713
|
+
// ============================
|
|
1714
|
+
// Navigation Helpers
|
|
1715
|
+
// ============================
|
|
1716
|
+
/**
|
|
1717
|
+
* Navigate to the Audit tab within the Analytics section.
|
|
1718
|
+
* Assumes the user is already on the analytics page (any tab).
|
|
1719
|
+
*/
|
|
1720
|
+
async function navigateToAuditLog(page) {
|
|
1721
|
+
const auditLogTab = page.getByRole('tab', { name: 'Audit' });
|
|
1722
|
+
await test$1.expect(auditLogTab).toBeVisible({ timeout: 60000 });
|
|
1723
|
+
await auditLogTab.click();
|
|
1724
|
+
await waitForPageReady(page);
|
|
1725
|
+
await safeWaitForURL(page, /\/analytics\/audit-log$/);
|
|
1726
|
+
logger.info('Successfully navigated to Audit page');
|
|
1727
|
+
}
|
|
1728
|
+
// ============================
|
|
1729
|
+
// Table Verification Helpers
|
|
1730
|
+
// ============================
|
|
1731
|
+
/**
|
|
1732
|
+
* Verify the audit log table is visible with correct headers.
|
|
1733
|
+
*/
|
|
1734
|
+
async function verifyAuditLogTableVisible(page) {
|
|
1735
|
+
const table = page.locator('table');
|
|
1736
|
+
await test$1.expect(table).toBeVisible({ timeout: 30000 });
|
|
1737
|
+
await test$1.expect(table.locator('th').filter({ hasText: 'Person' })).toBeVisible();
|
|
1738
|
+
await test$1.expect(table.locator('th').filter({ hasText: 'Action' })).toBeVisible();
|
|
1739
|
+
await test$1.expect(table.locator('th').filter({ hasText: 'Timestamp' })).toBeVisible();
|
|
1740
|
+
logger.info('Audit log table is visible with correct headers');
|
|
1741
|
+
}
|
|
1742
|
+
/**
|
|
1743
|
+
* Get the number of rows currently displayed in the audit log table.
|
|
1744
|
+
* Returns 0 if no table body rows are found.
|
|
1745
|
+
*/
|
|
1746
|
+
async function getAuditLogRowCount(page) {
|
|
1747
|
+
const rows = page.locator('table tbody tr');
|
|
1748
|
+
const count = await rows.count();
|
|
1749
|
+
logger.info(`Audit log table has ${count} rows`);
|
|
1750
|
+
return count;
|
|
1751
|
+
}
|
|
1752
|
+
/**
|
|
1753
|
+
* Verify that audit log entries contain expected data structure
|
|
1754
|
+
* (person name in first cell, action description in second, timestamp in third).
|
|
1755
|
+
*/
|
|
1756
|
+
async function verifyAuditLogEntryStructure(page) {
|
|
1757
|
+
const firstRow = page.locator('table tbody tr').first();
|
|
1758
|
+
await test$1.expect(firstRow).toBeVisible({ timeout: 30000 });
|
|
1759
|
+
const cells = firstRow.locator('td');
|
|
1760
|
+
const cellCount = await cells.count();
|
|
1761
|
+
test$1.expect(cellCount).toBe(3);
|
|
1762
|
+
// Person cell should have text content
|
|
1763
|
+
const personText = await cells.nth(0).textContent();
|
|
1764
|
+
test$1.expect(personText === null || personText === void 0 ? void 0 : personText.trim().length).toBeGreaterThan(0);
|
|
1765
|
+
// Action cell should have text content
|
|
1766
|
+
const actionText = await cells.nth(1).textContent();
|
|
1767
|
+
test$1.expect(actionText === null || actionText === void 0 ? void 0 : actionText.trim().length).toBeGreaterThan(0);
|
|
1768
|
+
// Timestamp cell should have text content
|
|
1769
|
+
const timestampText = await cells.nth(2).textContent();
|
|
1770
|
+
test$1.expect(timestampText === null || timestampText === void 0 ? void 0 : timestampText.trim().length).toBeGreaterThan(0);
|
|
1771
|
+
logger.info(`Audit log entry: Person="${personText === null || personText === void 0 ? void 0 : personText.trim()}", Action="${actionText === null || actionText === void 0 ? void 0 : actionText.trim()}", Timestamp="${timestampText === null || timestampText === void 0 ? void 0 : timestampText.trim()}"`);
|
|
1772
|
+
}
|
|
1773
|
+
// ============================
|
|
1774
|
+
// Empty & Error State Helpers
|
|
1775
|
+
// ============================
|
|
1776
|
+
/**
|
|
1777
|
+
* Verify the empty state is displayed when there are no audit log entries.
|
|
1778
|
+
*/
|
|
1779
|
+
async function verifyAuditLogEmptyState(page) {
|
|
1780
|
+
const emptyMessage = page.getByText('No audit log entries found for this tenant.');
|
|
1781
|
+
await test$1.expect(emptyMessage).toBeVisible({ timeout: 30000 });
|
|
1782
|
+
logger.info('Audit log empty state is displayed');
|
|
1783
|
+
}
|
|
1784
|
+
/**
|
|
1785
|
+
* Verify the 403 permission error state is displayed.
|
|
1786
|
+
*/
|
|
1787
|
+
async function verifyAuditLogPermissionError(page) {
|
|
1788
|
+
const errorMessage = page.getByText('You do not have permission to view audit logs.');
|
|
1789
|
+
await test$1.expect(errorMessage).toBeVisible({ timeout: 30000 });
|
|
1790
|
+
logger.info('Audit log permission error is displayed');
|
|
1791
|
+
}
|
|
1792
|
+
/**
|
|
1793
|
+
* Verify the generic error state is displayed.
|
|
1794
|
+
*/
|
|
1795
|
+
async function verifyAuditLogGenericError(page) {
|
|
1796
|
+
const errorMessage = page.getByText('An error occurred while loading audit logs.');
|
|
1797
|
+
await test$1.expect(errorMessage).toBeVisible({ timeout: 30000 });
|
|
1798
|
+
logger.info('Audit log generic error is displayed');
|
|
1799
|
+
}
|
|
1800
|
+
/**
|
|
1801
|
+
* Verify the loading spinner is displayed while audit logs are being fetched.
|
|
1802
|
+
*/
|
|
1803
|
+
async function verifyAuditLogLoading(page) {
|
|
1804
|
+
const spinner = page.locator('.animate-spin');
|
|
1805
|
+
await test$1.expect(spinner).toBeVisible({ timeout: 10000 });
|
|
1806
|
+
logger.info('Audit log loading spinner is displayed');
|
|
1807
|
+
}
|
|
1808
|
+
/**
|
|
1809
|
+
* Wait for the audit log data to finish loading.
|
|
1810
|
+
* Waits for either table data, empty state, or error state to appear.
|
|
1811
|
+
*/
|
|
1812
|
+
async function waitForAuditLogDataLoaded(page, timeout = 60000) {
|
|
1813
|
+
await page
|
|
1814
|
+
.locator('table tbody tr, [class*="empty"], [class*="error"]')
|
|
1815
|
+
.first()
|
|
1816
|
+
.waitFor({ state: 'visible', timeout })
|
|
1817
|
+
.catch(() => {
|
|
1818
|
+
// Also check for known text states
|
|
1819
|
+
});
|
|
1820
|
+
// Wait for spinner to disappear
|
|
1821
|
+
const spinner = page.locator('.animate-spin');
|
|
1822
|
+
const isSpinnerVisible = await spinner.isVisible().catch(() => false);
|
|
1823
|
+
if (isSpinnerVisible) {
|
|
1824
|
+
await test$1.expect(spinner).not.toBeVisible({ timeout });
|
|
1825
|
+
}
|
|
1826
|
+
logger.info('Audit log data has finished loading');
|
|
1827
|
+
}
|
|
1828
|
+
// ============================
|
|
1829
|
+
// Filter Interaction Helpers
|
|
1830
|
+
// ============================
|
|
1831
|
+
/**
|
|
1832
|
+
* Filter audit log entries by action type.
|
|
1833
|
+
* @param action - One of 'All Actions', 'Create', 'Update', or 'Delete'
|
|
1834
|
+
*/
|
|
1835
|
+
async function filterByAction(page, action) {
|
|
1836
|
+
const selectTrigger = page.locator('[role="combobox"][dir="ltr"]');
|
|
1837
|
+
await test$1.expect(selectTrigger).toBeVisible({ timeout: 10000 });
|
|
1838
|
+
await selectTrigger.click();
|
|
1839
|
+
const option = page.getByRole('option', { name: action });
|
|
1840
|
+
await test$1.expect(option).toBeVisible({ timeout: 5000 });
|
|
1841
|
+
await option.click();
|
|
1842
|
+
await waitForAuditLogDataLoaded(page);
|
|
1843
|
+
logger.info(`Filtered audit log by action: ${action}`);
|
|
1844
|
+
}
|
|
1845
|
+
/**
|
|
1846
|
+
* Filter audit log entries by actor/person using the search combobox.
|
|
1847
|
+
* @param actorName - The username to filter by, or empty string to clear the filter
|
|
1848
|
+
*/
|
|
1849
|
+
async function filterByActor(page, actorName) {
|
|
1850
|
+
const actorButton = page.getByLabel('Search for User');
|
|
1851
|
+
await test$1.expect(actorButton).toBeVisible({ timeout: 10000 });
|
|
1852
|
+
await actorButton.click();
|
|
1853
|
+
// Wait for the command popover to open
|
|
1854
|
+
const searchInput = page.getByPlaceholder('Search user...');
|
|
1855
|
+
await test$1.expect(searchInput).toBeVisible({ timeout: 5000 });
|
|
1856
|
+
if (actorName) {
|
|
1857
|
+
await searchInput.fill(actorName);
|
|
1858
|
+
// Select the matching actor from the dropdown
|
|
1859
|
+
const actorItem = page.locator('[cmdk-item]').filter({ hasText: actorName });
|
|
1860
|
+
await test$1.expect(actorItem).toBeVisible({ timeout: 5000 });
|
|
1861
|
+
await actorItem.click();
|
|
1862
|
+
}
|
|
1863
|
+
else {
|
|
1864
|
+
// Select "All Users" to clear the filter
|
|
1865
|
+
const allPeopleItem = page.locator('[cmdk-item]').filter({ hasText: 'All Users' });
|
|
1866
|
+
await test$1.expect(allPeopleItem).toBeVisible({ timeout: 5000 });
|
|
1867
|
+
await allPeopleItem.click();
|
|
1868
|
+
}
|
|
1869
|
+
await waitForAuditLogDataLoaded(page);
|
|
1870
|
+
logger.info(`Filtered audit log by actor: ${actorName || 'All Users'}`);
|
|
1871
|
+
}
|
|
1872
|
+
/**
|
|
1873
|
+
* Get the list of actors available in the actor filter dropdown.
|
|
1874
|
+
* Opens the dropdown, reads the options, then closes it.
|
|
1875
|
+
*/
|
|
1876
|
+
async function getAvailableActors(page) {
|
|
1877
|
+
const actorButton = page.getByLabel('Search for User');
|
|
1878
|
+
await test$1.expect(actorButton).toBeVisible({ timeout: 10000 });
|
|
1879
|
+
await actorButton.click();
|
|
1880
|
+
// Wait for the command popover
|
|
1881
|
+
await test$1.expect(page.getByPlaceholder('Search user...')).toBeVisible({ timeout: 5000 });
|
|
1882
|
+
const actorItems = page.locator('[cmdk-item] .font-medium.text-gray-700');
|
|
1883
|
+
const count = await actorItems.count();
|
|
1884
|
+
const actors = [];
|
|
1885
|
+
for (let i = 0; i < count; i++) {
|
|
1886
|
+
const text = await actorItems.nth(i).textContent();
|
|
1887
|
+
if (text)
|
|
1888
|
+
actors.push(text.trim());
|
|
1889
|
+
}
|
|
1890
|
+
// Close the dropdown by pressing Escape
|
|
1891
|
+
await page.keyboard.press('Escape');
|
|
1892
|
+
logger.info(`Available actors: ${actors.join(', ')}`);
|
|
1893
|
+
return actors;
|
|
1894
|
+
}
|
|
1895
|
+
/**
|
|
1896
|
+
* Open the date range picker and select a date range.
|
|
1897
|
+
* @param fromDate - Start date to select
|
|
1898
|
+
* @param toDate - End date to select
|
|
1899
|
+
*/
|
|
1900
|
+
async function filterByDateRange(page, fromDate, toDate) {
|
|
1901
|
+
const dateButton = page.getByRole('button', {
|
|
1902
|
+
name: /Pick a Date Range|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/,
|
|
1903
|
+
});
|
|
1904
|
+
await test$1.expect(dateButton).toBeVisible({ timeout: 10000 });
|
|
1905
|
+
await dateButton.click();
|
|
1906
|
+
// Wait for calendar to appear
|
|
1907
|
+
const calendar = page.locator('[role="grid"]').first();
|
|
1908
|
+
await test$1.expect(calendar).toBeVisible({ timeout: 5000 });
|
|
1909
|
+
// Select the from date
|
|
1910
|
+
const fromDay = String(fromDate.getDate());
|
|
1911
|
+
const fromButton = calendar.getByRole('gridcell', { name: fromDay, exact: true }).first();
|
|
1912
|
+
await fromButton.click();
|
|
1913
|
+
// Select the to date
|
|
1914
|
+
const toDay = String(toDate.getDate());
|
|
1915
|
+
const toButton = calendar.getByRole('gridcell', { name: toDay, exact: true }).first();
|
|
1916
|
+
await toButton.click();
|
|
1917
|
+
// Close by clicking outside
|
|
1918
|
+
await page.locator('body').click({ position: { x: 0, y: 0 } });
|
|
1919
|
+
await waitForAuditLogDataLoaded(page);
|
|
1920
|
+
logger.info(`Filtered audit log by date range: ${fromDate.toISOString().split('T')[0]} to ${toDate.toISOString().split('T')[0]}`);
|
|
1921
|
+
}
|
|
1922
|
+
/**
|
|
1923
|
+
* Clear the date range filter by clicking the date picker and resetting.
|
|
1924
|
+
*/
|
|
1925
|
+
async function clearDateRangeFilter(page) {
|
|
1926
|
+
const dateButton = page.getByRole('button', { name: /Pick a Date Range/ });
|
|
1927
|
+
// If button shows "Pick a Date Range", filter is already cleared
|
|
1928
|
+
const isCleared = await dateButton.isVisible().catch(() => false);
|
|
1929
|
+
if (isCleared) {
|
|
1930
|
+
logger.info('Date range filter is already cleared');
|
|
1931
|
+
return;
|
|
1932
|
+
}
|
|
1933
|
+
logger.info('Date range filter cleared');
|
|
1934
|
+
}
|
|
1935
|
+
// ============================
|
|
1936
|
+
// Pagination Helpers
|
|
1937
|
+
// ============================
|
|
1938
|
+
/**
|
|
1939
|
+
* Get the current pagination info text (e.g., "Showing 1 to 20 of 45 results").
|
|
1940
|
+
* Returns null if pagination is not visible.
|
|
1941
|
+
*/
|
|
1942
|
+
async function getPaginationInfo(page) {
|
|
1943
|
+
var _a;
|
|
1944
|
+
const paginationText = page.locator('.text-sm.text-gray-700');
|
|
1945
|
+
const isVisible = await paginationText.isVisible().catch(() => false);
|
|
1946
|
+
if (!isVisible) {
|
|
1947
|
+
logger.info('Pagination info is not visible (likely single page)');
|
|
1948
|
+
return null;
|
|
1949
|
+
}
|
|
1950
|
+
const text = await paginationText.textContent();
|
|
1951
|
+
logger.info(`Pagination info: ${text === null || text === void 0 ? void 0 : text.trim()}`);
|
|
1952
|
+
return (_a = text === null || text === void 0 ? void 0 : text.trim()) !== null && _a !== void 0 ? _a : null;
|
|
1953
|
+
}
|
|
1954
|
+
/**
|
|
1955
|
+
* Navigate to the next page of audit log results.
|
|
1956
|
+
*/
|
|
1957
|
+
async function goToNextPage(page) {
|
|
1958
|
+
const nextLink = page.getByRole('link', { name: 'Go to next page' });
|
|
1959
|
+
await test$1.expect(nextLink).toBeVisible({ timeout: 5000 });
|
|
1960
|
+
await nextLink.click();
|
|
1961
|
+
await waitForAuditLogDataLoaded(page);
|
|
1962
|
+
logger.info('Navigated to next page');
|
|
1963
|
+
}
|
|
1964
|
+
/**
|
|
1965
|
+
* Navigate to the previous page of audit log results.
|
|
1966
|
+
*/
|
|
1967
|
+
async function goToPreviousPage(page) {
|
|
1968
|
+
const prevLink = page.getByRole('link', { name: 'Go to previous page' });
|
|
1969
|
+
await test$1.expect(prevLink).toBeVisible({ timeout: 5000 });
|
|
1970
|
+
await prevLink.click();
|
|
1971
|
+
await waitForAuditLogDataLoaded(page);
|
|
1972
|
+
logger.info('Navigated to previous page');
|
|
1973
|
+
}
|
|
1974
|
+
/**
|
|
1975
|
+
* Navigate to the first page of audit log results.
|
|
1976
|
+
*/
|
|
1977
|
+
async function goToFirstPage(page) {
|
|
1978
|
+
await goToPage(page, 1);
|
|
1979
|
+
logger.info('Navigated to first page');
|
|
1980
|
+
}
|
|
1981
|
+
/**
|
|
1982
|
+
* Navigate to the last page of audit log results.
|
|
1983
|
+
* Finds the highest numbered page link in the pagination.
|
|
1984
|
+
*/
|
|
1985
|
+
async function goToLastPage(page) {
|
|
1986
|
+
const paginationNav = page.getByRole('navigation', { name: 'pagination' });
|
|
1987
|
+
await test$1.expect(paginationNav).toBeVisible({ timeout: 5000 });
|
|
1988
|
+
const pageLinks = paginationNav.getByRole('link');
|
|
1989
|
+
const count = await pageLinks.count();
|
|
1990
|
+
// The last numeric link before "Next" is the last page
|
|
1991
|
+
let lastPageNum = 1;
|
|
1992
|
+
for (let i = 0; i < count; i++) {
|
|
1993
|
+
const text = await pageLinks.nth(i).textContent();
|
|
1994
|
+
const num = Number(text === null || text === void 0 ? void 0 : text.trim());
|
|
1995
|
+
if (!isNaN(num) && num > lastPageNum) {
|
|
1996
|
+
lastPageNum = num;
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
await goToPage(page, lastPageNum);
|
|
2000
|
+
logger.info(`Navigated to last page (${lastPageNum})`);
|
|
2001
|
+
}
|
|
2002
|
+
/**
|
|
2003
|
+
* Navigate to a specific page number by clicking its page button.
|
|
2004
|
+
*/
|
|
2005
|
+
async function goToPage(page, pageNumber) {
|
|
2006
|
+
const pageLink = page
|
|
2007
|
+
.getByRole('navigation', { name: 'pagination' })
|
|
2008
|
+
.getByRole('link', { name: String(pageNumber), exact: true });
|
|
2009
|
+
await test$1.expect(pageLink).toBeVisible({ timeout: 5000 });
|
|
2010
|
+
await pageLink.click();
|
|
2011
|
+
await waitForAuditLogDataLoaded(page);
|
|
2012
|
+
logger.info(`Navigated to page ${pageNumber}`);
|
|
2013
|
+
}
|
|
2014
|
+
/**
|
|
2015
|
+
* Verify the current page is highlighted/active in pagination.
|
|
2016
|
+
*/
|
|
2017
|
+
async function verifyCurrentPage(page, expectedPage) {
|
|
2018
|
+
const pageLink = page
|
|
2019
|
+
.getByRole('navigation', { name: 'pagination' })
|
|
2020
|
+
.getByRole('link', { name: String(expectedPage), exact: true });
|
|
2021
|
+
await test$1.expect(pageLink).toBeVisible({ timeout: 5000 });
|
|
2022
|
+
await test$1.expect(pageLink).toHaveClass(/bg-blue-500/);
|
|
2023
|
+
logger.info(`Verified current page is ${expectedPage}`);
|
|
2024
|
+
}
|
|
2025
|
+
/**
|
|
2026
|
+
* Check if the next page button is disabled (i.e., we're on the last page).
|
|
2027
|
+
*/
|
|
2028
|
+
async function isOnLastPage(page) {
|
|
2029
|
+
const nextLink = page.getByRole('link', { name: 'Go to next page' });
|
|
2030
|
+
const hasDisabledClass = await nextLink
|
|
2031
|
+
.evaluate((el) => el.classList.contains('pointer-events-none'))
|
|
2032
|
+
.catch(() => true);
|
|
2033
|
+
return hasDisabledClass;
|
|
2034
|
+
}
|
|
2035
|
+
/**
|
|
2036
|
+
* Check if the previous page button is disabled (i.e., we're on the first page).
|
|
2037
|
+
*/
|
|
2038
|
+
async function isOnFirstPage(page) {
|
|
2039
|
+
const prevLink = page.getByRole('link', { name: 'Go to previous page' });
|
|
2040
|
+
const hasDisabledClass = await prevLink
|
|
2041
|
+
.evaluate((el) => el.classList.contains('pointer-events-none'))
|
|
2042
|
+
.catch(() => true);
|
|
2043
|
+
return hasDisabledClass;
|
|
2044
|
+
}
|
|
2045
|
+
// ============================
|
|
2046
|
+
// Combined Workflow Helpers
|
|
2047
|
+
// ============================
|
|
2048
|
+
/**
|
|
2049
|
+
* Full workflow: Navigate to audit log tab, wait for data to load,
|
|
2050
|
+
* and verify the table is visible. Use this as a test setup helper.
|
|
2051
|
+
*/
|
|
2052
|
+
async function navigateToAuditLogAndWaitForData(page) {
|
|
2053
|
+
await navigateToAuditLog(page);
|
|
2054
|
+
await waitForAuditLogDataLoaded(page);
|
|
2055
|
+
logger.info('Audit log page ready with data loaded');
|
|
2056
|
+
}
|
|
2057
|
+
/**
|
|
2058
|
+
* Verify audit log entries are displayed after applying action filter.
|
|
2059
|
+
* Returns the row count after filtering.
|
|
2060
|
+
*/
|
|
2061
|
+
async function filterByActionAndVerify(page, action) {
|
|
2062
|
+
await filterByAction(page, action);
|
|
2063
|
+
const count = await getAuditLogRowCount(page);
|
|
2064
|
+
logger.info(`After filtering by "${action}": ${count} entries found`);
|
|
2065
|
+
return count;
|
|
2066
|
+
}
|
|
2067
|
+
/**
|
|
2068
|
+
* Verify audit log entries are displayed after applying actor filter.
|
|
2069
|
+
* Returns the row count after filtering.
|
|
2070
|
+
*/
|
|
2071
|
+
async function filterByActorAndVerify(page, actorName) {
|
|
2072
|
+
await filterByActor(page, actorName);
|
|
2073
|
+
const count = await getAuditLogRowCount(page);
|
|
2074
|
+
logger.info(`After filtering by actor "${actorName}": ${count} entries found`);
|
|
2075
|
+
return count;
|
|
2076
|
+
}
|
|
2077
|
+
|
|
1713
2078
|
/** Extract browser key from device name (e.g., 'Desktop Chrome' -> 'chrome') */
|
|
1714
2079
|
function getBrowserKey(deviceName) {
|
|
1715
2080
|
return deviceName.toLowerCase().replace(/^desktop\s+/, '');
|
|
@@ -1848,6 +2213,7 @@ exports.archiveMemoryByContent = archiveMemoryByContent;
|
|
|
1848
2213
|
exports.buildReportUrl = buildReportUrl;
|
|
1849
2214
|
exports.canChatWithEmbedMentor = canChatWithEmbedMentor;
|
|
1850
2215
|
exports.checkAdminStatus = checkAdminStatus;
|
|
2216
|
+
exports.clearDateRangeFilter = clearDateRangeFilter;
|
|
1851
2217
|
exports.clickBackHome = clickBackHome;
|
|
1852
2218
|
exports.clickDownloadAgain = clickDownloadAgain;
|
|
1853
2219
|
exports.clickManualDownloadLink = clickManualDownloadLink;
|
|
@@ -1859,19 +2225,36 @@ exports.deleteFirstMemory = deleteFirstMemory;
|
|
|
1859
2225
|
exports.deleteMemoryByContent = deleteMemoryByContent;
|
|
1860
2226
|
exports.expectNoAccessibilityViolations = expectNoAccessibilityViolations;
|
|
1861
2227
|
exports.expectNoAccessibilityViolationsOnDialogs = expectNoAccessibilityViolationsOnDialogs;
|
|
2228
|
+
exports.filterByAction = filterByAction;
|
|
2229
|
+
exports.filterByActionAndVerify = filterByActionAndVerify;
|
|
2230
|
+
exports.filterByActor = filterByActor;
|
|
2231
|
+
exports.filterByActorAndVerify = filterByActorAndVerify;
|
|
2232
|
+
exports.filterByDateRange = filterByDateRange;
|
|
1862
2233
|
exports.generateBrowserSetupProjects = generateBrowserSetupProjects;
|
|
1863
2234
|
exports.generateProjectConfig = generateProjectConfig;
|
|
2235
|
+
exports.getAuditLogRowCount = getAuditLogRowCount;
|
|
2236
|
+
exports.getAvailableActors = getAvailableActors;
|
|
1864
2237
|
exports.getBrowserKey = getBrowserKey;
|
|
1865
2238
|
exports.getMemoryCount = getMemoryCount;
|
|
1866
2239
|
exports.getMentorIdFromUrl = getMentorIdFromUrl;
|
|
2240
|
+
exports.getPaginationInfo = getPaginationInfo;
|
|
2241
|
+
exports.goToFirstPage = goToFirstPage;
|
|
2242
|
+
exports.goToLastPage = goToLastPage;
|
|
2243
|
+
exports.goToNextPage = goToNextPage;
|
|
2244
|
+
exports.goToPage = goToPage;
|
|
2245
|
+
exports.goToPreviousPage = goToPreviousPage;
|
|
1867
2246
|
exports.inviteUserTest = inviteUserTest;
|
|
1868
2247
|
exports.isFirefox = isFirefox;
|
|
1869
2248
|
exports.isJSON = isJSON;
|
|
1870
2249
|
exports.isMemoryTabVisible = isMemoryTabVisible;
|
|
2250
|
+
exports.isOnFirstPage = isOnFirstPage;
|
|
2251
|
+
exports.isOnLastPage = isOnLastPage;
|
|
1871
2252
|
exports.logger = logger;
|
|
1872
2253
|
exports.loginWithEmailAndPassword = loginWithEmailAndPassword;
|
|
1873
2254
|
exports.loginWithMicrosoftIdp = loginWithMicrosoftIdp;
|
|
1874
2255
|
exports.navigateToAccountComponent = navigateToAccountComponent;
|
|
2256
|
+
exports.navigateToAuditLog = navigateToAuditLog;
|
|
2257
|
+
exports.navigateToAuditLogAndWaitForData = navigateToAuditLogAndWaitForData;
|
|
1875
2258
|
exports.navigateToDataReports = navigateToDataReports;
|
|
1876
2259
|
exports.navigateToReportDownload = navigateToReportDownload;
|
|
1877
2260
|
exports.openAddMemoryDialog = openAddMemoryDialog;
|
|
@@ -1901,6 +2284,13 @@ exports.signUpWithEmailAndPassword = signUpWithEmailAndPassword;
|
|
|
1901
2284
|
exports.switchToMemoryTab = switchToMemoryTab;
|
|
1902
2285
|
exports.test = test;
|
|
1903
2286
|
exports.toggleMemorySwitch = toggleMemorySwitch;
|
|
2287
|
+
exports.verifyAuditLogEmptyState = verifyAuditLogEmptyState;
|
|
2288
|
+
exports.verifyAuditLogEntryStructure = verifyAuditLogEntryStructure;
|
|
2289
|
+
exports.verifyAuditLogGenericError = verifyAuditLogGenericError;
|
|
2290
|
+
exports.verifyAuditLogLoading = verifyAuditLogLoading;
|
|
2291
|
+
exports.verifyAuditLogPermissionError = verifyAuditLogPermissionError;
|
|
2292
|
+
exports.verifyAuditLogTableVisible = verifyAuditLogTableVisible;
|
|
2293
|
+
exports.verifyCurrentPage = verifyCurrentPage;
|
|
1904
2294
|
exports.verifyDonePhase = verifyDonePhase;
|
|
1905
2295
|
exports.verifyDownloadingPhase = verifyDownloadingPhase;
|
|
1906
2296
|
exports.verifyErrorPhase = verifyErrorPhase;
|
|
@@ -1909,6 +2299,7 @@ exports.verifyMemoryNotExists = verifyMemoryNotExists;
|
|
|
1909
2299
|
exports.verifyMemoryTabMemoriesList = verifyMemoryTabMemoriesList;
|
|
1910
2300
|
exports.verifyMemoryTabSettings = verifyMemoryTabSettings;
|
|
1911
2301
|
exports.verifyPreparingPhase = verifyPreparingPhase;
|
|
2302
|
+
exports.waitForAuditLogDataLoaded = waitForAuditLogDataLoaded;
|
|
1912
2303
|
exports.waitForDialogReady = waitForDialogReady;
|
|
1913
2304
|
exports.waitForElementStable = waitForElementStable;
|
|
1914
2305
|
exports.waitForPageLoad = waitForPageLoad;
|