import { test, expect } from '@playwright/test'; import { login, BASE_URL } from '../../helpers/auth'; import * as path from 'path'; import * as fs from 'fs'; test.describe('pbx-configuration', () => { test.beforeEach(async ({ page }) => { await login(page); }); test('pbx-configuration-check-initial_system_setup_and_network_settings', async ({ page }, testInfo) => { testInfo.annotations.push({ type: 'automationStatus', description: 'automated' }); testInfo.annotations.push({ type: 'testType', description: 'check' }); testInfo.annotations.push({ type: 'description', description: 'Verify initial PBX system setup and network settings are correctly configured' }); await test.step('Navigate to Settings → Network', async () => { await page.goto(`${BASE_URL}/admin/settings/network`); }); await test.step('Verify network settings page loads', async () => { await expect(page.locator('body')).not.toContainText(/500|not found/i); }); await test.step('Verify hostname/FQDN field is populated', async () => { const fqdnInput = page.locator('[name*="hostname"],[name*="fqdn"],[id*="hostname"],[id*="fqdn"]').first(); if (await fqdnInput.count() > 0) { const value = await fqdnInput.inputValue(); expect(value.trim()).not.toBe(''); } }); await test.step('Verify IP address field is populated', async () => { const ipInput = page.locator('[name*="ip_address"],[name*="local_ip"],[id*="ip-address"]').first(); if (await ipInput.count() > 0) { const value = await ipInput.inputValue(); expect(value).toMatch(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/); } }); await test.step('Verify DNS server field is populated', async () => { const dnsInput = page.locator('[name*="dns"],[id*="dns"]').first(); if (await dnsInput.count() > 0) { const value = await dnsInput.inputValue(); expect(value.trim()).not.toBe(''); } }); }); test('pbx-configuration-check-dialplan_route_and_outbound_rule_creation', async ({ page }, testInfo) => { testInfo.annotations.push({ type: 'automationStatus', description: 'automated' }); testInfo.annotations.push({ type: 'testType', description: 'check' }); testInfo.annotations.push({ type: 'description', description: 'Verify creation and validation of dial plan rules and outbound routes' }); const testRuleName = `autotest-rule-${Date.now()}`; await test.step('Navigate to Dial Plans / Outbound Routes', async () => { await page.goto(`${BASE_URL}/admin/dialplans/outbound`); }); await test.step('Create a new outbound rule', async () => { await page.locator('button:has-text("Add"),button:has-text("New"),a:has-text("Add Rule")').first().click(); await page.locator('[name*="name"],[id*="rule-name"]').first().fill(testRuleName); await page.locator('[name*="prefix"],[name*="pattern"],[id*="pattern"]').first().fill('9.'); await page.locator('button:has-text("Save"),button[type="submit"]').first().click(); }); await test.step('Verify new rule appears in the list', async () => { await page.goto(`${BASE_URL}/admin/dialplans/outbound`); await expect(page.locator('table, .rule-list').filter({ hasText: testRuleName })).toBeVisible(); }); await test.step('Edit the rule and verify save succeeds', async () => { await page.locator('tr, .rule-item').filter({ hasText: testRuleName }).locator('a:has-text("Edit"),button:has-text("Edit")').first().click(); await page.locator('button:has-text("Save"),button[type="submit"]').first().click(); await expect(page.locator('.alert-success, .success-banner, [class*="success"]').first()).toBeVisible(); }); await test.step('Delete the test rule', async () => { await page.goto(`${BASE_URL}/admin/dialplans/outbound`); await page.locator('tr, .rule-item').filter({ hasText: testRuleName }).locator('button:has-text("Delete"),a:has-text("Delete")').first().click(); await page.locator('button:has-text("Confirm"),button:has-text("Yes")').first().click(); await expect(page.locator('body')).not.toContainText(testRuleName); }); }); test('pbx-configuration-check-backup_restore_full_system_configuration', async ({ page }, testInfo) => { testInfo.annotations.push({ type: 'automationStatus', description: 'automated' }); testInfo.annotations.push({ type: 'testType', description: 'check' }); testInfo.annotations.push({ type: 'description', description: 'Verify full system configuration backup and restore operations work correctly' }); await test.step('Navigate to Backup & Restore', async () => { await page.goto(`${BASE_URL}/admin/backup`); }); await test.step('Trigger a backup and wait for completion', async () => { await page.locator('button:has-text("Create Backup"),button:has-text("Backup Now")').first().click(); await expect(page.locator('.backup-status, .progress, [data-status="complete"]').first()).toBeVisible({ timeout: 60_000 }); }); await test.step('Verify backup file appears in the backup list', async () => { const backupList = page.locator('table, .backup-list'); await expect(backupList.first()).toBeVisible(); const rows = await backupList.locator('tr, .backup-item').count(); expect(rows).toBeGreaterThan(0); }); await test.step('Verify restore button is available for the latest backup', async () => { const restoreBtn = page.locator('button:has-text("Restore"),a:has-text("Restore")').first(); await expect(restoreBtn).toBeVisible(); }); }); test('pbx-configuration-check-bulk_csv_import_export_of_settings', async ({ page }, testInfo) => { testInfo.annotations.push({ type: 'automationStatus', description: 'automated' }); testInfo.annotations.push({ type: 'testType', description: 'check' }); testInfo.annotations.push({ type: 'description', description: 'Verify bulk CSV import and export of settings (extensions, contacts, etc.)' }); const csvContent = 'extension,name,email\n5001,Test User One,test1@test.local\n5002,Test User Two,test2@test.local'; const tmpCsvPath = path.join(process.cwd(), 'test-results', 'bulk-import-test.csv'); await test.step('Navigate to Bulk Import / Export section', async () => { fs.mkdirSync(path.dirname(tmpCsvPath), { recursive: true }); fs.writeFileSync(tmpCsvPath, csvContent, 'utf-8'); await page.goto(`${BASE_URL}/admin/extensions/import`); }); await test.step('Verify import page loads', async () => { await expect(page.locator('input[type="file"], .dropzone, .upload-area').first()).toBeVisible(); }); await test.step('Navigate to export section', async () => { await page.goto(`${BASE_URL}/admin/extensions/export`); }); await test.step('Trigger CSV export and verify download is initiated', async () => { const [download] = await Promise.all([ page.waitForEvent('download', { timeout: 20_000 }), page.locator('button:has-text("Export"),a:has-text("Export CSV"),a:has-text("Download")').first().click(), ]); expect(download.suggestedFilename()).toMatch(/\.csv$/i); }); }); });