Some checks are pending
Go Benchmark / Performance Regression Check (push) Waiting to run
Cerberus Integration / Cerberus Security Stack Integration (push) Waiting to run
Upload Coverage to Codecov / Backend Codecov Upload (push) Waiting to run
Upload Coverage to Codecov / Frontend Codecov Upload (push) Waiting to run
CodeQL - Analyze / CodeQL analysis (go) (push) Waiting to run
CodeQL - Analyze / CodeQL analysis (javascript-typescript) (push) Waiting to run
CrowdSec Integration / CrowdSec Bouncer Integration (push) Waiting to run
Docker Build, Publish & Test / build-and-push (push) Waiting to run
Docker Build, Publish & Test / Security Scan PR Image (push) Blocked by required conditions
Quality Checks / Auth Route Protection Contract (push) Waiting to run
Quality Checks / Codecov Trigger/Comment Parity Guard (push) Waiting to run
Quality Checks / Backend (Go) (push) Waiting to run
Quality Checks / Frontend (React) (push) Waiting to run
Rate Limit integration / Rate Limiting Integration (push) Waiting to run
Security Scan (PR) / Trivy Binary Scan (push) Waiting to run
Supply Chain Verification (PR) / Verify Supply Chain (push) Waiting to run
WAF integration / Coraza WAF Integration (push) Waiting to run
527 lines
16 KiB
TypeScript
Executable File
527 lines
16 KiB
TypeScript
Executable File
/**
|
|
* Backup & Restore E2E Tests
|
|
*
|
|
* Tests for complete backup and restore workflows including
|
|
* scheduling, verification, and disaster recovery scenarios.
|
|
*
|
|
* Test Categories (20-24 tests):
|
|
* - Group A: Backup Creation (5 tests)
|
|
* - Group B: Backup Scheduling (4 tests)
|
|
* - Group C: Restore Operations (5 tests)
|
|
* - Group D: Backup Verification (4 tests)
|
|
* - Group E: Error Handling (4 tests)
|
|
*
|
|
* API Endpoints:
|
|
* - GET /api/v1/backups
|
|
* - POST /api/v1/backups
|
|
* - DELETE /api/v1/backups/:id
|
|
* - POST /api/v1/backups/:id/restore
|
|
* - GET /api/v1/backups/:id/download
|
|
*/
|
|
|
|
import { test, expect, loginUser, TEST_PASSWORD } from '../fixtures/auth-fixtures';
|
|
import { generateProxyHost } from '../fixtures/proxy-hosts';
|
|
import { generateAccessList } from '../fixtures/access-lists';
|
|
import { generateDnsProvider } from '../fixtures/dns-providers';
|
|
import {
|
|
waitForToast,
|
|
waitForLoadingComplete,
|
|
waitForAPIResponse,
|
|
waitForModal,
|
|
clickAndWaitForResponse,
|
|
} from '../utils/wait-helpers';
|
|
|
|
/**
|
|
* Selectors for Backup pages
|
|
*/
|
|
const SELECTORS = {
|
|
// Backup List
|
|
backupTable: '[data-testid="backup-list"], table',
|
|
backupRow: '[data-testid="backup-row"], tbody tr',
|
|
createBackupBtn: 'button:has-text("Create Backup"), button:has-text("Backup Now")',
|
|
deleteBackupBtn: 'button:has-text("Delete"), [data-testid="delete-backup"]',
|
|
restoreBackupBtn: 'button:has-text("Restore"), [data-testid="restore-backup"]',
|
|
downloadBackupBtn: 'button:has-text("Download"), [data-testid="download-backup"]',
|
|
|
|
// Backup Form
|
|
backupNameInput: 'input[name="name"], #backup-name',
|
|
backupDescriptionInput: 'textarea[name="description"], #backup-description',
|
|
includeConfigCheckbox: 'input[name="include_config"], #include-config',
|
|
includeDataCheckbox: 'input[name="include_data"], #include-data',
|
|
|
|
// Schedule Configuration
|
|
scheduleEnabledToggle: 'input[name="schedule_enabled"], [data-testid="schedule-toggle"]',
|
|
scheduleFrequency: 'select[name="frequency"], #schedule-frequency',
|
|
scheduleTime: 'input[name="schedule_time"], #schedule-time',
|
|
retentionDays: 'input[name="retention_days"], #retention-days',
|
|
|
|
// Restore Modal
|
|
restoreModal: '[data-testid="restore-modal"], .modal',
|
|
confirmRestoreBtn: 'button:has-text("Confirm Restore"), button:has-text("Yes, Restore")',
|
|
restoreWarning: '[data-testid="restore-warning"], .warning',
|
|
|
|
// Status Indicators
|
|
backupStatus: '[data-testid="backup-status"], .backup-status',
|
|
progressBar: '[data-testid="progress-bar"], .progress',
|
|
backupSize: '[data-testid="backup-size"], .backup-size',
|
|
backupDate: '[data-testid="backup-date"], .backup-date',
|
|
|
|
// Common
|
|
saveButton: 'button:has-text("Save"), button[type="submit"]',
|
|
cancelButton: 'button:has-text("Cancel")',
|
|
loadingSkeleton: '[data-testid="loading-skeleton"], .loading',
|
|
};
|
|
|
|
test.describe('Backup & Restore E2E', () => {
|
|
// ===========================================================================
|
|
// Group A: Backup Creation (5 tests)
|
|
// ===========================================================================
|
|
test.describe('Group A: Backup Creation', () => {
|
|
test('should display backup list page', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backups page', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify backups page loads', async () => {
|
|
const heading = page.locator('h1, h2').first();
|
|
await expect(heading).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should create manual backup via API', async ({
|
|
page,
|
|
adminUser,
|
|
testData,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
// Create some data to back up
|
|
const proxyConfig = generateProxyHost();
|
|
await testData.createProxyHost({
|
|
domain: proxyConfig.domain,
|
|
forwardHost: proxyConfig.forwardHost,
|
|
forwardPort: proxyConfig.forwardPort,
|
|
});
|
|
|
|
await test.step('Verify proxy host was created', async () => {
|
|
await page.goto('/proxy-hosts');
|
|
await waitForLoadingComplete(page);
|
|
await expect(page.getByText(proxyConfig.domain)).toBeVisible();
|
|
});
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify backups page loads', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should create backup with configuration only', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify backup creation options', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should create backup with all data included', async ({
|
|
page,
|
|
adminUser,
|
|
testData,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
// Create multiple resources
|
|
const proxy = generateProxyHost();
|
|
const acl = generateAccessList();
|
|
|
|
await testData.createProxyHost({
|
|
domain: proxy.domain,
|
|
forwardHost: proxy.forwardHost,
|
|
forwardPort: proxy.forwardPort,
|
|
});
|
|
|
|
await testData.createAccessList({
|
|
name: acl.name,
|
|
type: acl.type,
|
|
ipRules: acl.ipRules,
|
|
});
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify backup page content', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should show backup creation progress', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify page loads', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
});
|
|
|
|
// ===========================================================================
|
|
// Group B: Backup Scheduling (4 tests)
|
|
// ===========================================================================
|
|
test.describe('Group B: Backup Scheduling', () => {
|
|
test('should display backup schedule settings', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backup settings', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify settings page', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should configure daily backup schedule', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backup settings', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify schedule configuration options', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should configure weekly backup schedule', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backup settings', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify settings page loads', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should set backup retention policy', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backup settings', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify retention policy options', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
});
|
|
|
|
// ===========================================================================
|
|
// Group C: Restore Operations (5 tests)
|
|
// ===========================================================================
|
|
test.describe('Group C: Restore Operations', () => {
|
|
test('should display restore options for backup', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify backup list page', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should restore proxy hosts from backup', async ({
|
|
page,
|
|
adminUser,
|
|
testData,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
// Create proxy host that would be in a backup
|
|
const proxyInput = generateProxyHost();
|
|
const createdProxy = await testData.createProxyHost({
|
|
domain: proxyInput.domain,
|
|
forwardHost: proxyInput.forwardHost,
|
|
forwardPort: proxyInput.forwardPort,
|
|
});
|
|
|
|
await test.step('Verify proxy host exists', async () => {
|
|
await page.goto('/proxy-hosts');
|
|
await waitForLoadingComplete(page);
|
|
await expect(page.getByText(createdProxy.domain)).toBeVisible();
|
|
});
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
});
|
|
|
|
test('should restore access lists from backup', async ({
|
|
page,
|
|
adminUser,
|
|
testData,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
// Create access list that would be in a backup
|
|
const acl = generateAccessList();
|
|
await testData.createAccessList({
|
|
name: acl.name,
|
|
type: acl.type,
|
|
ipRules: acl.ipRules,
|
|
});
|
|
|
|
await test.step('Verify access list exists', async () => {
|
|
await page.goto('/access-lists');
|
|
await waitForLoadingComplete(page);
|
|
await expect(page.getByText(acl.name)).toBeVisible();
|
|
});
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
});
|
|
|
|
test('should show restore confirmation warning', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify page content', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should perform full system restore', async ({
|
|
page,
|
|
adminUser,
|
|
testData,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
// Create multiple resources
|
|
const proxyInput = generateProxyHost();
|
|
const acl = generateAccessList();
|
|
|
|
const createdProxy = await testData.createProxyHost({
|
|
domain: proxyInput.domain,
|
|
forwardHost: proxyInput.forwardHost,
|
|
forwardPort: proxyInput.forwardPort,
|
|
});
|
|
|
|
await testData.createAccessList({
|
|
name: acl.name,
|
|
type: acl.type,
|
|
ipRules: acl.ipRules,
|
|
});
|
|
|
|
await test.step('Verify resources exist', async () => {
|
|
await page.goto('/proxy-hosts');
|
|
await waitForLoadingComplete(page);
|
|
await expect(page.getByText(createdProxy.domain)).toBeVisible();
|
|
});
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
});
|
|
});
|
|
|
|
// ===========================================================================
|
|
// Group D: Backup Verification (4 tests)
|
|
// ===========================================================================
|
|
test.describe('Group D: Backup Verification', () => {
|
|
test('should display backup details', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify backup list page', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should verify backup integrity', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify page loads', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should download backup file', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify download options exist', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should show backup size and date', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify backup metadata displayed', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
});
|
|
|
|
// ===========================================================================
|
|
// Group E: Error Handling (4 tests)
|
|
// ===========================================================================
|
|
test.describe('Group E: Error Handling', () => {
|
|
test('should handle backup creation failure gracefully', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify page loads', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should handle restore failure gracefully', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify page content', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should handle corrupted backup file', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backups', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify error handling UI', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('should handle insufficient storage during backup', async ({
|
|
page,
|
|
adminUser,
|
|
}) => {
|
|
await loginUser(page, adminUser);
|
|
|
|
await test.step('Navigate to backup settings', async () => {
|
|
await page.goto('/tasks/backups');
|
|
await waitForLoadingComplete(page);
|
|
});
|
|
|
|
await test.step('Verify settings page', async () => {
|
|
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
|
|
});
|
|
});
|
|
});
|
|
});
|