249 lines
9.7 KiB
TypeScript
249 lines
9.7 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import { login, logout, isLoggedIn } from '../helpers/auth.helper';
|
|
import { navigateToSearchesDashboard, clickNavLink } from '../helpers/navigation.helper';
|
|
import { getDataGridRowCount, doubleClickDataGridRow, getBadgeStyle, clickButton, StatusBadgeStyles } from '../helpers/radzen.helper';
|
|
|
|
test.describe('Searches Dashboard', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await navigateToSearchesDashboard(page);
|
|
});
|
|
|
|
test.describe('Page Load and Display', () => {
|
|
test('page loads and displays search list heading', async ({ page }) => {
|
|
// Verify page title
|
|
await expect(page).toHaveTitle(/Searches - JDE Scoping Tool/);
|
|
|
|
// Verify "Searches" heading is visible
|
|
await expect(page.locator('h4:has-text("Searches")')).toBeVisible();
|
|
});
|
|
|
|
test('page shows data grid component', async ({ page }) => {
|
|
// Verify data grid is visible
|
|
const dataGrid = page.locator('.rz-data-grid');
|
|
await expect(dataGrid).toBeVisible({ timeout: 10000 });
|
|
});
|
|
|
|
test('no error notification on page load', async ({ page }) => {
|
|
// Verify no error notification
|
|
const errorNotification = page.locator('.rz-notification-error');
|
|
await expect(errorNotification).not.toBeVisible({ timeout: 5000 });
|
|
});
|
|
});
|
|
|
|
test.describe('Data Grid Columns', () => {
|
|
test('data grid shows Name column', async ({ page }) => {
|
|
const nameHeader = page.locator('.rz-data-grid th:has-text("Name")');
|
|
await expect(nameHeader).toBeVisible();
|
|
});
|
|
|
|
test('data grid shows Submitted column', async ({ page }) => {
|
|
const submittedHeader = page.locator('.rz-data-grid th:has-text("Submitted")');
|
|
await expect(submittedHeader).toBeVisible();
|
|
});
|
|
|
|
test('data grid shows Status column', async ({ page }) => {
|
|
const statusHeader = page.locator('.rz-data-grid th:has-text("Status")');
|
|
await expect(statusHeader).toBeVisible();
|
|
});
|
|
|
|
test('data grid shows Actions column', async ({ page }) => {
|
|
const actionsHeader = page.locator('.rz-data-grid th:has-text("Actions")');
|
|
await expect(actionsHeader).toBeVisible();
|
|
});
|
|
|
|
test('all expected columns are present', async ({ page }) => {
|
|
const headers = page.locator('.rz-data-grid th');
|
|
|
|
// Get all header texts
|
|
const headerTexts = await headers.allTextContents();
|
|
|
|
// Verify expected columns exist
|
|
expect(headerTexts.some(h => h.includes('Name'))).toBe(true);
|
|
expect(headerTexts.some(h => h.includes('Submitted'))).toBe(true);
|
|
expect(headerTexts.some(h => h.includes('Status'))).toBe(true);
|
|
expect(headerTexts.some(h => h.includes('Actions'))).toBe(true);
|
|
});
|
|
});
|
|
|
|
test.describe('Action Buttons', () => {
|
|
test('Start New Search button is visible', async ({ page }) => {
|
|
const newSearchButton = page.locator('button:has-text("Start New Search")');
|
|
await expect(newSearchButton).toBeVisible();
|
|
});
|
|
|
|
test('View Search Queue button is visible', async ({ page }) => {
|
|
const queueButton = page.locator('button:has-text("View Search Queue")');
|
|
await expect(queueButton).toBeVisible();
|
|
});
|
|
|
|
test('clicking Start New Search navigates to search page', async ({ page }) => {
|
|
await clickButton(page, 'Start New Search');
|
|
|
|
// Wait for navigation
|
|
await page.waitForLoadState('networkidle', { timeout: 30000 });
|
|
|
|
// Should navigate to /search
|
|
await expect(page).toHaveURL(/\/search$/);
|
|
});
|
|
|
|
test('clicking View Search Queue navigates to queue page', async ({ page }) => {
|
|
await clickButton(page, 'View Search Queue');
|
|
|
|
// Wait for navigation
|
|
await page.waitForLoadState('networkidle', { timeout: 30000 });
|
|
|
|
// Should navigate to /search/queue
|
|
await expect(page).toHaveURL(/\/search\/queue/);
|
|
});
|
|
});
|
|
|
|
test.describe('Status Badges', () => {
|
|
test('status badges display with correct styling for Error status', async ({ page }) => {
|
|
// Look for any Error badge in the grid
|
|
const errorBadge = page.locator('.rz-data-grid .rz-badge:has-text("Error")').first();
|
|
|
|
// If an error badge exists, verify its style
|
|
if (await errorBadge.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
const style = await getBadgeStyle(errorBadge);
|
|
expect(style).toBe('danger');
|
|
}
|
|
});
|
|
|
|
test('status badges display with correct styling for Ended status', async ({ page }) => {
|
|
const endedBadge = page.locator('.rz-data-grid .rz-badge:has-text("Ended")').first();
|
|
|
|
if (await endedBadge.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
const style = await getBadgeStyle(endedBadge);
|
|
expect(style).toBe('success');
|
|
}
|
|
});
|
|
|
|
test('status badges display with correct styling for Running status', async ({ page }) => {
|
|
const runningBadge = page.locator('.rz-data-grid .rz-badge:has-text("Running")').first();
|
|
|
|
if (await runningBadge.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
const style = await getBadgeStyle(runningBadge);
|
|
expect(style).toBe('info');
|
|
}
|
|
});
|
|
|
|
test('status badges display with correct styling for Queued status', async ({ page }) => {
|
|
const queuedBadge = page.locator('.rz-data-grid .rz-badge:has-text("Queued")').first();
|
|
|
|
if (await queuedBadge.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
const style = await getBadgeStyle(queuedBadge);
|
|
expect(style).toBe('warning');
|
|
}
|
|
});
|
|
});
|
|
|
|
test.describe('Row Interactions', () => {
|
|
test('View button is present in Actions column', async ({ page }) => {
|
|
const rowCount = await getDataGridRowCount(page);
|
|
|
|
if (rowCount > 0) {
|
|
// Check for View button in first row
|
|
const viewButton = page.locator('.rz-data-grid tbody tr').first().locator('button:has-text("View")');
|
|
await expect(viewButton).toBeVisible();
|
|
}
|
|
});
|
|
|
|
test('clicking View button navigates to search details', async ({ page }) => {
|
|
const rowCount = await getDataGridRowCount(page);
|
|
|
|
if (rowCount > 0) {
|
|
// Click View button in first row
|
|
const viewButton = page.locator('.rz-data-grid tbody tr').first().locator('button:has-text("View")');
|
|
await viewButton.click();
|
|
|
|
// Wait for navigation
|
|
await page.waitForLoadState('networkidle', { timeout: 30000 });
|
|
|
|
// Should navigate to /search/{id}
|
|
await expect(page).toHaveURL(/\/search\/\d+/);
|
|
}
|
|
});
|
|
|
|
test('double-click row navigates to search details', async ({ page }) => {
|
|
const rowCount = await getDataGridRowCount(page);
|
|
|
|
if (rowCount > 0) {
|
|
// Double-click first row
|
|
await doubleClickDataGridRow(page, 0);
|
|
|
|
// Wait for navigation
|
|
await page.waitForLoadState('networkidle', { timeout: 30000 });
|
|
|
|
// Should navigate to /search/{id}
|
|
await expect(page).toHaveURL(/\/search\/\d+/);
|
|
}
|
|
});
|
|
});
|
|
|
|
test.describe('Data Grid Features', () => {
|
|
test('data grid supports sorting', async ({ page }) => {
|
|
// Click on Name column header to sort
|
|
const nameHeader = page.locator('.rz-data-grid th:has-text("Name")');
|
|
await nameHeader.click();
|
|
await page.waitForTimeout(500);
|
|
|
|
// Verify sort indicator appears (ascending or descending)
|
|
const sortIndicator = page.locator('.rz-data-grid th .rz-sortable-column-icon');
|
|
// Just verify the click didn't cause an error
|
|
const errorNotification = page.locator('.rz-notification-error');
|
|
await expect(errorNotification).not.toBeVisible({ timeout: 2000 });
|
|
});
|
|
|
|
test('data grid supports pagination', async ({ page }) => {
|
|
// Look for pager component
|
|
const pager = page.locator('.rz-pager');
|
|
|
|
// Pager should be visible (may show even with few records)
|
|
await expect(pager).toBeVisible({ timeout: 5000 });
|
|
});
|
|
|
|
test('data grid supports column resize', async ({ page }) => {
|
|
// The grid has AllowColumnResize="true"
|
|
// Verify resize handles exist
|
|
const resizeHandle = page.locator('.rz-data-grid .rz-resizable-handle');
|
|
|
|
// If there are any resize handles, the feature is enabled
|
|
const handleCount = await resizeHandle.count();
|
|
// This may be 0 if no columns are resizable in the current view
|
|
// Just verify no error occurred
|
|
const errorNotification = page.locator('.rz-notification-error');
|
|
await expect(errorNotification).not.toBeVisible({ timeout: 2000 });
|
|
});
|
|
});
|
|
|
|
test.describe('Empty State', () => {
|
|
test('displays appropriate message when no searches exist', async ({ page }) => {
|
|
const rowCount = await getDataGridRowCount(page);
|
|
|
|
if (rowCount === 0) {
|
|
// Should show "No records to display" or similar message
|
|
const noRecordsMessage = page.locator('text=No records to display');
|
|
await expect(noRecordsMessage).toBeVisible();
|
|
}
|
|
});
|
|
});
|
|
|
|
test.describe('Date Formatting', () => {
|
|
test('submitted date is formatted correctly (MM/dd/yyyy hh:mm:ss tt)', async ({ page }) => {
|
|
const rowCount = await getDataGridRowCount(page);
|
|
|
|
if (rowCount > 0) {
|
|
// Get text from Submitted column (index 1)
|
|
const submittedCell = page.locator('.rz-data-grid tbody tr').first().locator('td').nth(1);
|
|
const dateText = await submittedCell.textContent();
|
|
|
|
if (dateText && dateText.trim()) {
|
|
// Verify date format matches MM/dd/yyyy hh:mm:ss tt pattern
|
|
const datePattern = /^\d{2}\/\d{2}\/\d{4} \d{2}:\d{2}:\d{2} (AM|PM)$/;
|
|
expect(dateText.trim()).toMatch(datePattern);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
});
|