first commit

This commit is contained in:
2026-05-22 11:46:43 +02:00
commit 2ebd8fb16b
29 changed files with 3356 additions and 0 deletions
+152
View File
@@ -0,0 +1,152 @@
import { test, expect } from '@playwright/test';
import { login, BASE_URL } from '../../helpers/auth';
import { markManual, markPartial, markWrite } from '../../helpers/manual';
import { attachWriteResult } from '../../helpers/writeResult';
const DOCS_URL = process.env.DOCS_URL ?? `${BASE_URL}/docs`;
test.describe('core-features', () => {
test.beforeEach(async ({ page }) => {
await login(page);
});
test('core-features-write-summary_of_each_new_feature_per_release', async ({ page }, testInfo) => {
testInfo.annotations.push({ type: 'automationStatus', description: 'automated' });
markWrite();
testInfo.annotations.push({ type: 'description', description: 'Extract and record a summary of each new feature included in this release' });
const captured: Record<string, unknown> = {};
await test.step('Navigate to Release Notes / What\'s New section', async () => {
await page.goto(`${DOCS_URL}/release-notes`);
captured['url'] = page.url();
});
await test.step('Extract feature list items', async () => {
const features = await page
.locator('h2, h3, li, .feature-item')
.filter({ hasText: /feature|new|added|introduced/i })
.allTextContents();
captured['newFeatures'] = features;
captured['count'] = features.length;
});
await test.step('Attach feature summary to report', async () => {
await attachWriteResult(testInfo, captured, 'feature-summary');
});
expect(captured['count']).toBeGreaterThan(0);
});
test('core-features-check-integration_of_new_features_with_existing_call_processing_and_modules', async ({ page }, testInfo) => {
testInfo.annotations.push({ type: 'automationStatus', description: 'partial' });
testInfo.annotations.push({ type: 'testType', description: 'check' });
markPartial('UI configuration and module settings can be verified via admin portal; actual call-flow integration requires active telephony endpoints outside Playwright scope');
testInfo.annotations.push({ type: 'description', description: 'Verify new features integrate correctly with existing call processing and system modules' });
await test.step('Navigate to admin portal modules section', async () => {
await page.goto(`${BASE_URL}/admin/modules`);
});
await test.step('Verify modules list is visible and no error state is shown', async () => {
await expect(page.locator('body')).not.toContainText(/error|failed|unavailable/i);
});
await test.step('Verify new feature settings are accessible in the portal', async () => {
await expect(page.locator('main, .content').first()).toBeVisible();
});
// TODO_MANUAL: For each new feature, trigger a call flow that exercises it and
// verify the call completes without errors in the call log.
});
test('core-features-check-backward_compatibility_of_new_features', async ({ page }, testInfo) => {
testInfo.annotations.push({ type: 'automationStatus', description: 'partial' });
testInfo.annotations.push({ type: 'testType', description: 'check' });
markPartial('Configuration import compatibility and settings migration can be verified via admin portal; functional backward compatibility with older endpoint firmware requires manual telephony testing');
testInfo.annotations.push({ type: 'description', description: 'Verify new features are backward-compatible with existing configurations and older endpoint firmware' });
await test.step('Import a backup from the previous version', async () => {
await page.goto(`${BASE_URL}/admin/backup`);
await expect(page.locator('body')).not.toContainText(/error/i);
});
await test.step('Verify configuration is shown without migration errors', async () => {
await expect(page.locator('.alert-danger, .error-banner').first()).toHaveCount(0);
});
// TODO_MANUAL: Register an older SIP endpoint (previous firmware) and verify it
// still registers and can complete calls without errors.
});
test('core-features-check-performance_and_resource_impact_assessment_of_new_features', async ({ page }, testInfo) => {
testInfo.annotations.push({ type: 'automationStatus', description: 'manual' });
testInfo.annotations.push({ type: 'testType', description: 'check' });
markManual('Requires dedicated SIP load generator (SIPp), performance monitoring infrastructure, and sustained load; cannot be executed with Playwright alone');
testInfo.annotations.push({ type: 'description', description: 'Assess CPU/memory/network resource impact of new features under representative call load' });
// Manual steps:
// 1. Establish a baseline resource measurement with current stable build.
// 2. Enable each new feature one at a time.
// 3. Run SIPp with a representative concurrent-call scenario (e.g., 100 simultaneous calls).
// 4. Capture CPU, RAM, and I/O metrics every 30 s for at least 10 minutes.
// 5. Compare metrics against the baseline.
// 6. Record any resource spike or degradation > 10% as a finding.
});
test('core-features-write-analysis_of_new_security_risks', async ({ page }, testInfo) => {
testInfo.annotations.push({ type: 'automationStatus', description: 'manual' });
markWrite();
markManual('Security risk analysis requires expert threat modelling, source code review, and human judgment; not automatable via browser automation');
testInfo.annotations.push({ type: 'description', description: 'Identify, analyse, and document new security risks introduced by features in this release' });
// Manual steps:
// 1. Obtain the diff / commit list for this release.
// 2. Review each new feature for new attack surfaces (new APIs, new ports, new auth flows).
// 3. Run OWASP ZAP or equivalent against new endpoints.
// 4. Document findings: risk level (Critical/High/Medium/Low), description, CVE if applicable.
// 5. Record results in the security risk register.
});
test('core-features-write-ui_ux_and_admin_portal_changes_validation', async ({ page }, testInfo) => {
testInfo.annotations.push({ type: 'automationStatus', description: 'automated' });
markWrite();
testInfo.annotations.push({ type: 'description', description: 'Capture and record all UI/UX changes in the admin portal for this release (screenshots + text)' });
const captured: Record<string, unknown> = {};
const navSections = ['dashboard', 'extensions', 'trunks', 'dialplans', 'settings', 'security', 'logs'];
await test.step('Iterate admin portal main sections and capture screenshots', async () => {
captured['sections'] = [];
for (const section of navSections) {
await page.goto(`${BASE_URL}/admin/${section}`);
const title = await page.title();
const screenshot = await page.screenshot({ fullPage: false });
await testInfo.attach(`screenshot-${section}`, { body: screenshot, contentType: 'image/png' });
(captured['sections'] as string[]).push(`${section}: ${title}`);
}
});
await test.step('Attach section inventory to report', async () => {
await attachWriteResult(testInfo, captured, 'ui-changes');
});
expect((captured['sections'] as string[]).length).toBeGreaterThan(0);
});
test('core-features-check-provisioning_changes_for_new_features', async ({ page }, testInfo) => {
testInfo.annotations.push({ type: 'automationStatus', description: 'automated' });
testInfo.annotations.push({ type: 'testType', description: 'check' });
testInfo.annotations.push({ type: 'description', description: 'Verify provisioning settings and workflows for new features are accessible and correctly displayed in the admin portal' });
await test.step('Navigate to provisioning settings', async () => {
await page.goto(`${BASE_URL}/admin/provisioning`);
});
await test.step('Verify provisioning page loads without errors', async () => {
await expect(page.locator('body')).not.toContainText(/500|error|not found/i);
});
await test.step('Verify provisioning options are visible', async () => {
await expect(page.locator('main, .content, form').first()).toBeVisible();
});
});
});