103 lines
3.8 KiB
TypeScript
103 lines
3.8 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
const adminUser = {
|
|
id: 'user-1',
|
|
email: 'admin@example.test',
|
|
role: 'admin',
|
|
plan: 'internal',
|
|
displayName: 'Dashboard Admin',
|
|
emailVerified: true,
|
|
currentProduct: 'bytelyst-devops',
|
|
products: [{ productId: 'bytelyst-devops', plan: 'internal', role: 'admin' }],
|
|
mfaEnabled: false,
|
|
mfaMethods: [],
|
|
};
|
|
|
|
const services = [
|
|
{
|
|
id: 'trading',
|
|
name: 'Investment Trading',
|
|
scriptPath: '../deploy-invttrdg.sh',
|
|
healthUrl: 'https://api.bytelyst.com/invttrdg/health',
|
|
repoPath: '../learning_ai_invt_trdg',
|
|
status: 'up',
|
|
version: '1.2.3',
|
|
productId: 'bytelyst-devops',
|
|
},
|
|
];
|
|
|
|
const deployments = [
|
|
{
|
|
id: 'deploy-1',
|
|
serviceId: 'trading',
|
|
version: '1.2.3',
|
|
status: 'success',
|
|
logs: 'deployment completed',
|
|
triggeredBy: 'user-1',
|
|
triggeredAt: new Date('2026-05-25T08:00:00Z').toISOString(),
|
|
completedAt: new Date('2026-05-25T08:01:00Z').toISOString(),
|
|
productId: 'bytelyst-devops',
|
|
},
|
|
];
|
|
|
|
test.describe('DevOps Dashboard', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.addInitScript(() => {
|
|
window.localStorage.setItem('access_token', 'e2e-access-token');
|
|
window.localStorage.setItem('refresh_token', 'e2e-refresh-token');
|
|
});
|
|
|
|
await page.route('**/auth/me', async (route) => {
|
|
await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(adminUser) });
|
|
});
|
|
|
|
await page.route('**/api/csrf-token', async (route) => {
|
|
await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ csrfToken: 'csrf-token' }) });
|
|
});
|
|
|
|
await page.route('**/api/services', async (route) => {
|
|
await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(services) });
|
|
});
|
|
|
|
await page.route('**/api/deployments?limit=10', async (route) => {
|
|
await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(deployments) });
|
|
});
|
|
|
|
await page.route('**/api/health/cache', async (route) => {
|
|
await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ message: 'Cache cleared' }) });
|
|
});
|
|
|
|
await page.route('**/api/seed', async (route) => {
|
|
await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ message: 'Seeded default services' }) });
|
|
});
|
|
|
|
await page.goto('/');
|
|
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
|
|
});
|
|
|
|
test('renders services, deployments, and action controls', async ({ page }) => {
|
|
await expect(page.getByText('Services and deployments overview')).toBeVisible();
|
|
await expect(page.getByRole('button', { name: /refresh/i })).toBeVisible();
|
|
await expect(page.getByRole('button', { name: /create service/i })).toBeVisible();
|
|
await expect(page.getByRole('heading', { name: 'Investment Trading' })).toBeVisible();
|
|
await expect(page.getByText('Recent Deployments')).toBeVisible();
|
|
await expect(page.getByRole('cell', { name: '1.2.3' })).toBeVisible();
|
|
});
|
|
|
|
test('refreshes service and deployment data', async ({ page }) => {
|
|
const refreshButton = page.getByRole('button', { name: /refresh/i });
|
|
await refreshButton.click();
|
|
await expect(refreshButton).toBeEnabled();
|
|
await expect(page.getByRole('heading', { name: 'Investment Trading' })).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test('login page renders the platform credential form without baked-in credentials', async ({ page }) => {
|
|
await page.goto('/login');
|
|
|
|
await expect(page.getByRole('heading', { name: 'DevOps Dashboard Login' })).toBeVisible();
|
|
await expect(page.getByLabel('Email')).toHaveValue('');
|
|
await expect(page.getByLabel('Password')).toHaveValue('');
|
|
await expect(page.getByLabel('Product ID')).toHaveValue('bytelyst-devops');
|
|
});
|