@iblai/iblai-js 1.4.3 → 1.4.4

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.
@@ -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;