179 lines
8.7 KiB
TypeScript
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.
|
|
});
|
|
});
|