first commit
This commit is contained in:
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user