- Added integration tests (Preseem, Gaiia, Slack, webhooks) - Added SNMP configuration and discovery tests - Added form validation and error handling tests - Added detailed alert workflow tests (lifecycle, actions, filtering, history) - Added agent token management tests (creation, assignment, deletion) Covers: - Third-party integration UI - SNMP credential hierarchy (org/site/device) - Form validation and error states - Alert bulk actions and filtering - Agent token lifecycle and device assignment
194 lines
6.7 KiB
TypeScript
194 lines
6.7 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('Form Validation and Error Handling', () => {
|
|
test.describe('Site Form Validation', () => {
|
|
test('shows validation error for empty site name', async ({ page }) => {
|
|
await page.goto('/sites/new');
|
|
|
|
if ((await page.url()).includes('/sites/new')) {
|
|
// Try to submit empty form
|
|
const submitButton = page.locator('button[type="submit"]').first();
|
|
|
|
if (await submitButton.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
await submitButton.click();
|
|
await page.waitForTimeout(500);
|
|
|
|
// Look for error message
|
|
const errorMessage = page.locator(
|
|
'.error, [role="alert"], :has-text("required"), :has-text("can\'t be blank")'
|
|
).first();
|
|
|
|
if (await errorMessage.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
await expect(errorMessage).toBeVisible();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
test('shows field-level validation errors', async ({ page }) => {
|
|
await page.goto('/sites/new');
|
|
|
|
if ((await page.url()).includes('/sites/new')) {
|
|
const nameField = page.locator('input[name*="name"]').first();
|
|
|
|
if (await nameField.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
// Focus and blur to trigger validation
|
|
await nameField.focus();
|
|
await nameField.blur();
|
|
await page.waitForTimeout(300);
|
|
|
|
// Look for field error
|
|
const fieldError = page.locator('.error, [role="alert"]').first();
|
|
|
|
if (await fieldError.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
await expect(fieldError).toBeVisible();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
test.describe('Device Form Validation', () => {
|
|
test('validates IP address format', async ({ page }) => {
|
|
await page.goto('/devices/new');
|
|
|
|
if ((await page.url()).includes('/devices/new')) {
|
|
const ipField = page.locator('input[name*="ip"], input[name*="host"]').first();
|
|
|
|
if (await ipField.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
// Enter invalid IP
|
|
await ipField.fill('invalid-ip');
|
|
await ipField.blur();
|
|
await page.waitForTimeout(300);
|
|
|
|
// Look for validation error
|
|
const error = page.locator(
|
|
':has-text("invalid"), :has-text("format"), .error'
|
|
).first();
|
|
|
|
if (await error.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
await expect(error).toBeVisible();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
test('shows required field indicators', async ({ page }) => {
|
|
await page.goto('/devices/new');
|
|
|
|
if ((await page.url()).includes('/devices/new')) {
|
|
// Look for required field markers
|
|
const requiredMarker = page.locator(
|
|
'label:has-text("*"), .required, [aria-required="true"]'
|
|
).first();
|
|
|
|
if (await requiredMarker.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
await expect(requiredMarker).toBeVisible();
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
test.describe('Error States', () => {
|
|
test('shows error page for non-existent resources', async ({ page }) => {
|
|
await page.goto('/devices/00000000-0000-0000-0000-000000000000');
|
|
await page.waitForTimeout(500);
|
|
|
|
// Should show 404 or error message
|
|
const errorIndicator = page.locator(
|
|
':has-text("not found"), :has-text("404"), :has-text("doesn\'t exist")'
|
|
).first();
|
|
|
|
if (await errorIndicator.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
await expect(errorIndicator).toBeVisible();
|
|
}
|
|
});
|
|
|
|
test('handles network errors gracefully', async ({ page }) => {
|
|
await page.goto('/devices');
|
|
|
|
// Look for any error boundaries or fallbacks
|
|
await expect(page.locator('body')).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test.describe('Form Submission States', () => {
|
|
test('shows loading state during form submission', async ({ page }) => {
|
|
await page.goto('/sites/new');
|
|
|
|
if ((await page.url()).includes('/sites/new')) {
|
|
const nameField = page.locator('input[name*="name"]').first();
|
|
const submitButton = page.locator('button[type="submit"]').first();
|
|
|
|
if (await nameField.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
await nameField.fill(`Test Site ${Date.now()}`);
|
|
|
|
if (await submitButton.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
await submitButton.click();
|
|
|
|
// Look for loading indicator (briefly)
|
|
const loadingIndicator = page.locator(
|
|
'[disabled], .loading, :has-text("Saving"), :has-text("Creating")'
|
|
).first();
|
|
|
|
if (await loadingIndicator.isVisible({ timeout: 1000 }).catch(() => false)) {
|
|
await expect(loadingIndicator).toBeVisible();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
test('disables submit button during submission', async ({ page }) => {
|
|
await page.goto('/sites/new');
|
|
|
|
if ((await page.url()).includes('/sites/new')) {
|
|
const submitButton = page.locator('button[type="submit"]').first();
|
|
|
|
if (await submitButton.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
const nameField = page.locator('input[name*="name"]').first();
|
|
|
|
if (await nameField.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
await nameField.fill(`Test Site ${Date.now()}`);
|
|
await submitButton.click();
|
|
|
|
// Button should be disabled during submission
|
|
const isDisabled = await submitButton.isDisabled().catch(() => false);
|
|
if (isDisabled) {
|
|
expect(isDisabled).toBe(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
test.describe('Success Messages', () => {
|
|
test('shows success message after creating resource', async ({ page }) => {
|
|
await page.goto('/sites/new');
|
|
|
|
if ((await page.url()).includes('/sites/new')) {
|
|
const nameField = page.locator('input[name*="name"]').first();
|
|
const submitButton = page.locator('button[type="submit"]').first();
|
|
|
|
if (await nameField.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
await nameField.fill(`E2E Test Site ${Date.now()}`);
|
|
|
|
if (await submitButton.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
await submitButton.click();
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Look for success message
|
|
const successMessage = page.locator(
|
|
':has-text("created"), :has-text("success"), .success, [role="status"]'
|
|
).first();
|
|
|
|
if (await successMessage.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
await expect(successMessage).toBeVisible();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
});
|