Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 0 additions & 26 deletions frontend/e2e/BPNavigation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,6 @@ test.describe('Binding Policy - Navigation', () => {
expect(hasHeading || hasCreateButton || hasTable || hasEmptyState).toBeTruthy();
});

test('should handle page reload', async ({ page }) => {
await bpPage.goto();

// Reload page
await page.reload();
await page.waitForLoadState('domcontentloaded');
await page.waitForTimeout(2000);

// Verify URL is still correct after reload
await expect(page).toHaveURL(/\/bp/, { timeout: 5000 });

// Verify page didn't crash - check for any content
const bodyText = await page.locator('body').textContent();
expect(bodyText).toBeTruthy();
expect(bodyText!.length).toBeGreaterThan(0);
});

test('should maintain authentication after navigation', async ({ page }) => {
await bpPage.goto();

Expand All @@ -63,15 +46,6 @@ test.describe('Binding Policy - Navigation', () => {
await expect(page).not.toHaveURL(/\/login/);
});

test('should display page within acceptable time', async () => {
const startTime = Date.now();
await bpPage.goto();
const loadTime = Date.now() - startTime;

// Page should load within 5 seconds
expect(loadTime).toBeLessThan(5000);
});

test('should have proper page title', async () => {
await bpPage.goto();

Expand Down
205 changes: 1 addition & 204 deletions frontend/e2e/Dashboard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,6 @@ test.describe('Dashboard Page', () => {
const linkCount = await navLinks.count();
expect(linkCount).toBeGreaterThan(0);
});

test('dashboard has proper page structure', async ({ page }) => {
await expect(page.locator('h1').first()).toBeVisible();

const cards = page.locator(
'div[class*="rounded"], div[class*="shadow"], div[class*="border"]'
);
const cardCount = await cards.count();
expect(cardCount).toBeGreaterThan(0);
});
});

test.describe('Statistics Cards', () => {
Expand Down Expand Up @@ -170,34 +160,6 @@ test.describe('Dashboard Page', () => {
expect(iconCount).toBeGreaterThan(0);
});

test('progress bars display correct values from MSW', async ({ page }) => {
const percentageElements = page.locator('span:has-text("/ 100%")');
const percentageCount = await percentageElements.count();
expect(percentageCount).toBeGreaterThan(0);

const hasCpuValue = (await page.locator('text=/45(\\.2)?% \\/ 100%/').count()) > 0;
const hasMemoryValue = (await page.locator('text=/67(\\.8)?% \\/ 100%/').count()) > 0;
const hasPodValue = (await page.locator('text=/92% \\/ 100%/').count()) > 0;

expect(hasCpuValue || hasMemoryValue || hasPodValue).toBeTruthy();
});

test('progress bars have tooltips with detailed information', async ({ page }) => {
const tooltipTriggers = page.locator('svg[width="12"][height="12"]');
const triggerCount = await tooltipTriggers.count();
expect(triggerCount).toBeGreaterThan(0);

const tooltipContainers = page.locator(
'div[class*="invisible"][class*="absolute"][class*="z-50"]'
);
const containerCount = await tooltipContainers.count();
expect(containerCount).toBeGreaterThan(0);

const groupElements = page.locator('span[class*="group"]');
const groupCount = await groupElements.count();
expect(groupCount).toBeGreaterThan(0);
});

test('cluster status distribution is visible', async ({ page }) => {
await expect(page.getByRole('heading', { name: 'Cluster Status' })).toBeVisible();
await expect(page.locator('text=Active Clusters').first()).toBeVisible();
Expand All @@ -217,20 +179,6 @@ test.describe('Dashboard Page', () => {
await expect(page.locator('text=Active').first()).toBeVisible();
});

test('cluster items show capacity information', async ({ page }) => {
const capacityElements = page.locator(
'text=/\\d+\\s*(GB|MB|Ki|Mi|Gi)|\\d+\\s*cpu|\\d+\\s*pods/i'
);
const capacityCount = await capacityElements.count();
expect(capacityCount).toBeGreaterThan(0);

const hasCpuValue = (await page.locator('text=/16/').count()) > 0;
const hasMemoryValue = (await page.locator('text=/\\d+\\s*GB/').count()) > 0;
const hasPodValue = (await page.locator('text=/110/').count()) > 0;

expect(hasCpuValue || hasMemoryValue || hasPodValue).toBeTruthy();
});

test('cluster items are clickable and open detail dialog', async ({ page }) => {
const firstCluster = page.getByRole('heading', { name: 'cluster1' }).first();
await firstCluster.click();
Expand Down Expand Up @@ -275,52 +223,6 @@ test.describe('Dashboard Page', () => {

expect(hasUserData || hasActivityStructure || hasStatusIndicators).toBeTruthy();
});

test('recent activity items are clickable', async ({ page }) => {
// Look for any activity-related links that might navigate to admin
const activityLinks = page.locator(
'a[href*="admin"], a[href*="/admin"], a:has-text("admin")'
);
const linkCount = await activityLinks.count();

if (linkCount > 0) {
await activityLinks.first().click();
await expect(page).toHaveURL(/admin/, { timeout: 5000 });
} else {
// If no admin links found, test any clickable activity item
const anyActivityLink = page.locator('a').first();
if ((await anyActivityLink.count()) > 0) {
const initialUrl = page.url();
await anyActivityLink.click();

// Wait for potential navigation
await page.waitForTimeout(1000);

// Check if navigation occurred or if link was clicked successfully
const currentUrl = page.url();
const navigationOccurred = currentUrl !== initialUrl;
const linkWasClickable = true; // If we got here, the link was clickable

// Test passes if either navigation occurred OR link was successfully clicked
expect(navigationOccurred || linkWasClickable).toBeTruthy();
} else {
// Skip test if no links found
console.log('No activity links found, skipping navigation test');
expect(true).toBeTruthy();
}
}
});

test('refresh button updates activity data', async ({ page }) => {
const refreshButton = page.getByRole('button', { name: /Refresh/i });
await refreshButton.click();

await expect(page.locator('text=admin').first()).toBeVisible();
});

test('activity items show proper timestamps', async ({ page }) => {
await expect(page.locator('text=ago').first()).toBeVisible();
});
});

test.describe('MSW Integration and Data Flow', () => {
Expand All @@ -331,54 +233,6 @@ test.describe('Dashboard Page', () => {

expect(hasHandlers).toBeTruthy();
});

test('dashboard handles API errors gracefully', async ({ page }) => {
await page.evaluate(() => {
window.__msw?.worker?.resetHandlers();
});

await page.reload();
await page.waitForLoadState('domcontentloaded');

const hasErrorIcon =
(await page
.locator('svg[data-lucide="alert-triangle"], svg[data-lucide="AlertTriangle"]')
.count()) > 0;
const hasErrorHeading = (await page.locator('h3').count()) > 0; // Error heading
const hasErrorButton = (await page.locator('button').count()) > 0; // Try Again button
const hasErrorContainer =
(await page.locator('div[class*="border-red-200"], div[class*="text-red-600"]').count()) >
0;

const hasAnyErrorText =
(await page.locator('text=/error|failed|unable|loading/i').count()) > 0;
const hasRedStyling = (await page.locator('[class*="red"]').count()) > 0;
const hasAlertIcon = (await page.locator('svg').count()) > 0; // Any SVG icon

const hasErrorState =
hasErrorIcon ||
hasErrorHeading ||
hasErrorButton ||
hasErrorContainer ||
hasAnyErrorText ||
hasRedStyling ||
hasAlertIcon;

if (!hasErrorState) {
const currentUrl = page.url();
const isOnDashboard = currentUrl.includes('/') && !currentUrl.includes('/login');

if (isOnDashboard) {
console.log(
'No error state detected, but dashboard is still accessible - this might be expected behavior'
);
expect(true).toBeTruthy(); // Pass the test
return;
}
}

expect(hasErrorState).toBeTruthy();
});
});

test.describe('Responsive Design', () => {
Expand Down Expand Up @@ -425,23 +279,6 @@ test.describe('Dashboard Page', () => {
const focusedElement = page.locator(':focus');
await expect(focusedElement).toBeVisible();
});

test('dashboard has proper color contrast', async ({ page }) => {
const textElements = page
.locator('p, span, div')
.filter({ hasText: /Total Clusters|Active Clusters/i });
const firstText = textElements.first();

const styles = await firstText.evaluate(el => {
const computed = window.getComputedStyle(el);
return {
color: computed.color,
backgroundColor: computed.backgroundColor,
};
});

expect(styles.color).toBeTruthy();
});
});

test.describe('Theme Integration', () => {
Expand All @@ -468,45 +305,5 @@ test.describe('Dashboard Page', () => {
});
});

test.describe('Error Handling', () => {
test('dashboard handles network errors gracefully', async ({ page }) => {
await page.route('**/api/**', route => route.abort());

await page.reload();
await page.waitForLoadState('domcontentloaded');

const hasErrorText =
(await page.locator('text=/Error|Failed|Unable|error|failed/i').count()) > 0;
const hasErrorIcon =
(await page
.locator('svg[data-lucide="alert-triangle"], svg[data-lucide="AlertTriangle"]')
.count()) > 0;
const hasErrorButton =
(await page.locator('button:has-text("Try Again"), button:has-text("Retry")').count()) > 0;
const hasErrorContainer =
(await page
.locator('div[class*="border-red"], div[class*="text-red"], div[class*="bg-red"]')
.count()) > 0;
const hasFallbackText = (await page.locator('text=/No data|Loading|empty/i').count()) > 0;

const dashboardStillWorks =
(await page.getByRole('heading', { name: 'Dashboard' }).count()) > 0;
const hasDashboardContent =
(await page.getByRole('link', { name: 'Total Clusters' }).count()) > 0;

const hasAnyContent = (await page.locator('body').count()) > 0;
const hasAnyText = (await page.locator('text=/./').count()) > 0;

const hasErrorState =
hasErrorText || hasErrorIcon || hasErrorButton || hasErrorContainer || hasFallbackText;
const dashboardFunctional = dashboardStillWorks || hasDashboardContent;
const pageHasContent = hasAnyContent && hasAnyText;

if (!hasErrorState && dashboardFunctional) {
expect(true).toBeTruthy();
return;
}
expect(hasErrorState || dashboardFunctional || pageHasContent).toBeTruthy();
});
});
test.describe('Error Handling', () => {});
});
11 changes: 0 additions & 11 deletions frontend/e2e/ITS.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { test, expect } from '@playwright/test';
import { AuthHelper, ITSPage, MSWHelper } from './pages';

Expand Down Expand Up @@ -96,15 +96,4 @@
await itsPage.page.waitForTimeout(500);
await expect(itsPage.searchInput).toHaveValue('');
});

test('responsive design works on mobile', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 667 });
await itsPage.openWithScenario(msw, 'itsSuccess');
await page.waitForTimeout(500);
await expect(itsPage.table.first()).toBeVisible({ timeout: 15000 });
await expect(itsPage.clusterRow('cluster1')).toBeVisible();
if (await itsPage.importButton.isVisible()) {
await expect(itsPage.importButton).toBeVisible();
}
});
});
18 changes: 0 additions & 18 deletions frontend/e2e/ITSTableFeature.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,24 +80,6 @@ test.describe('ITS Table Features Tests', () => {
}
});

test('table row selection persists across actions', async () => {
const checkboxes = itsPage.rowCheckboxes;
const checkboxCount = await checkboxes.count();

if (checkboxCount > 0) {
await checkboxes.first().check();
await expect(checkboxes.first()).toBeChecked();

const searchInput = itsPage.searchInput;
await searchInput.fill('cluster1');
await itsPage.page.waitForTimeout(1000);
await searchInput.clear();
await itsPage.page.waitForTimeout(1000);

await expect(checkboxes.first()).toBeChecked();
}
});

test('table displays empty state when no results', async () => {
const searchInput = itsPage.searchInput;
await searchInput.fill('nonexistent-cluster-xyz');
Expand Down
Loading
Loading