Files
2026-05-22 11:46:43 +02:00

179 lines
8.7 KiB
TypeScript

import { test, expect } from '@playwright/test';
import { login, BASE_URL } from '../../helpers/auth';
import { markPartial } from '../../helpers/manual';
test.describe('pbx-logs', () => {
test.beforeEach(async ({ page }) => {
await login(page);
});
test('pbx-logs-check-cdr_generation_accuracy_completeness_and_export', async ({ page }, testInfo) => {
testInfo.annotations.push({ type: 'automationStatus', description: 'automated' });
testInfo.annotations.push({ type: 'testType', description: 'check' });
testInfo.annotations.push({ type: 'description', description: 'Verify CDR records are generated, contain all required fields, and can be exported to CSV/PDF' });
await test.step('Navigate to Reports → CDR', async () => {
await page.goto(`${BASE_URL}/admin/logs/cdr`);
});
await test.step('Verify CDR page loads without errors', async () => {
await expect(page.locator('body')).not.toContainText(/500|not found/i);
});
await test.step('Verify CDR table is visible', async () => {
await expect(page.locator('table, .cdr-list, .report-table').first()).toBeVisible();
});
await test.step('Verify required CDR columns are present (start time, duration, from, to, status)', async () => {
const headerText = await page.locator('thead, .table-header').first().textContent() ?? '';
const requiredCols = ['time', 'duration', 'from', 'to', 'status'];
for (const col of requiredCols) {
expect(headerText.toLowerCase()).toContain(col);
}
});
await test.step('Trigger CSV export and verify download', async () => {
const [download] = await Promise.all([
page.waitForEvent('download', { timeout: 20_000 }),
page.locator('button:has-text("Export"),a:has-text("CSV"),a:has-text("Download")').first().click(),
]);
expect(download.suggestedFilename()).toMatch(/\.(csv|xlsx|pdf)$/i);
});
});
test('pbx-logs-check-real_time_active_call_and_registration_monitoring', async ({ page }, testInfo) => {
testInfo.annotations.push({ type: 'automationStatus', description: 'automated' });
testInfo.annotations.push({ type: 'testType', description: 'check' });
testInfo.annotations.push({ type: 'description', description: 'Verify real-time monitoring dashboard shows active calls and SIP registrations with auto-refresh' });
await test.step('Navigate to Monitoring → Active Calls', async () => {
await page.goto(`${BASE_URL}/admin/monitoring/active-calls`);
});
await test.step('Verify active calls panel loads', async () => {
await expect(page.locator('body')).not.toContainText(/500|not found/i);
await expect(page.locator('table, .active-calls, .call-panel').first()).toBeVisible();
});
await test.step('Navigate to Monitoring → Registrations', async () => {
await page.goto(`${BASE_URL}/admin/monitoring/registrations`);
});
await test.step('Verify registrations panel loads', async () => {
await expect(page.locator('table, .registrations, .reg-panel').first()).toBeVisible();
});
await test.step('Verify auto-refresh indicator is present', async () => {
const autoRefresh = page.locator('[data-refresh],[data-auto-refresh],.refresh-indicator,.last-updated').first();
if (await autoRefresh.count() > 0) {
await expect(autoRefresh).toBeVisible();
}
});
});
test('pbx-logs-check-detailed_logging_levels_rotation_and_search', async ({ page }, testInfo) => {
testInfo.annotations.push({ type: 'automationStatus', description: 'automated' });
testInfo.annotations.push({ type: 'testType', description: 'check' });
testInfo.annotations.push({ type: 'description', description: 'Verify detailed logging levels can be configured, log rotation is set up, and log search/filter is functional' });
await test.step('Navigate to System → Logs', async () => {
await page.goto(`${BASE_URL}/admin/logs/system`);
});
await test.step('Verify log viewer loads', async () => {
await expect(page.locator('body')).not.toContainText(/500|not found/i);
await expect(page.locator('.log-viewer, .log-content, pre, textarea').first()).toBeVisible();
});
await test.step('Navigate to log settings (level and rotation)', async () => {
await page.goto(`${BASE_URL}/admin/settings/logging`);
});
await test.step('Verify log level selector is available', async () => {
const levelSelect = page.locator('[name*="log_level"],[id*="log-level"],select').filter({ hasText: /debug|info|warn|error/i }).first();
await expect(levelSelect).toBeVisible();
});
await test.step('Verify log rotation settings are shown', async () => {
const pageText = await page.locator('body').textContent() ?? '';
expect(pageText).toMatch(/rotation|rotate|max.*size|keep.*days/i);
});
await test.step('Test log search / filter functionality', async () => {
await page.goto(`${BASE_URL}/admin/logs/system`);
const searchInput = page.locator('[name*="search"],[placeholder*="search"],[placeholder*="filter"]').first();
if (await searchInput.count() > 0) {
await searchInput.fill('error');
await page.keyboard.press('Enter');
await expect(page.locator('body')).not.toContainText(/500/i);
}
});
});
test('pbx-logs-check-threshold_alarms_cpu_channels_disk_memory', async ({ page }, testInfo) => {
testInfo.annotations.push({ type: 'automationStatus', description: 'automated' });
testInfo.annotations.push({ type: 'testType', description: 'check' });
testInfo.annotations.push({ type: 'description', description: 'Verify threshold-based alarms are configured for CPU, active channels, disk, and memory usage' });
await test.step('Navigate to Monitoring → Alarms / Thresholds', async () => {
await page.goto(`${BASE_URL}/admin/monitoring/alarms`);
});
await test.step('Verify alarms page loads', async () => {
await expect(page.locator('body')).not.toContainText(/500|not found/i);
});
const alarmTypes = ['cpu', 'memory', 'disk', 'channel'];
for (const alarmType of alarmTypes) {
await test.step(`Verify ${alarmType.toUpperCase()} threshold alarm is configurable`, async () => {
const alarmEl = page
.locator('tr, .alarm-item, .threshold-item, .metric-row')
.filter({ hasText: new RegExp(alarmType, 'i') });
if (await alarmEl.count() > 0) {
await expect(alarmEl.first()).toBeVisible();
}
});
}
await test.step('Verify notification email for alarms is configured', async () => {
await page.goto(`${BASE_URL}/admin/settings/notifications`);
const emailField = page.locator('[name*="alert_email"],[name*="notif_email"],[type="email"]').first();
if (await emailField.count() > 0) {
const value = await emailField.inputValue();
expect(value).toMatch(/@/);
}
});
});
test('pbx-logs-check-call_quality_metrics_mos_jitter_loss_per_call', async ({ page }, testInfo) => {
testInfo.annotations.push({ type: 'automationStatus', description: 'partial' });
testInfo.annotations.push({ type: 'testType', description: 'check' });
markPartial('Quality metrics display and reporting UI can be automated; actual metric generation requires active call sessions with measurable network conditions (jitter, packet loss)');
testInfo.annotations.push({ type: 'description', description: 'Verify per-call quality metrics (MOS score, jitter, packet loss) are collected and displayed in the portal' });
await test.step('Navigate to Reports → Call Quality / QoS', async () => {
await page.goto(`${BASE_URL}/admin/reports/call-quality`);
});
await test.step('Verify call quality report page loads', async () => {
await expect(page.locator('body')).not.toContainText(/500|not found/i);
});
await test.step('Verify quality metrics columns are present (MOS, jitter, packet loss)', async () => {
const headerText = (await page.locator('thead, .table-header').first().textContent() ?? '').toLowerCase();
const hasQualityMetrics = /mos|jitter|packet.?loss|r.?value/.test(headerText);
if (!hasQualityMetrics) {
testInfo.annotations.push({ type: 'note', description: 'Quality metrics columns not found — may require active calls or a specific report period to populate' });
}
});
await test.step('Verify date range filter is available', async () => {
const dateFilter = page.locator('[name*="date"],[name*="range"],input[type="date"]').first();
await expect(dateFilter).toBeVisible();
});
// TODO_MANUAL: Establish calls with controlled network impairment (tc qdisc netem) to generate
// measurable jitter and packet loss; verify the portal records accurate MOS scores.
});
});