Files
ss-tools/frontend/e2e/tests/smoke.e2e.js
2026-05-26 09:30:41 +03:00

137 lines
6.3 KiB
JavaScript

// #region SmokeE2E [C:4] [TYPE Test] [SEMANTICS e2e, smoke, golden-path, full-stack]
// @BRIEF Golden-path smoke test: login → settings → translate → git → verify.
// @RELATION BINDS_TO -> [[EXT:list:LoginPage_SettingsPage_TranslateJob_GitConfig]]
// @UX_STATE FullCycle -> All key user journeys executed sequentially.
// @RATIONALE Single sequential test verifies the entire stack without per-test setup overhead.
// Runs in ~30s when backend is warm. Mirrors the manual E2E check.
import { test, expect } from '../fixtures/auth.fixture.js';
import { apiGet, apiPost, apiPut } from '../helpers/api.helper.js';
const FRONTEND_URL = process.env.FRONTEND_URL || 'http://127.0.0.1:8102';
test.describe('Golden Path — Full Stack E2E', () => {
test('complete user journey: login → settings → translate → git', async ({ page }) => {
// ── 1. LOGIN ───────────────────────────────────────────
await test.step('Login as admin', async () => {
await page.goto(`${FRONTEND_URL}/login`);
await page.getByLabel(/Имя пользователя|Username/).fill('admin');
await page.getByLabel(/Пароль|Password/).fill('admin123');
await page.getByRole('button', { name: /Вход|Login/ }).click();
await page.waitForURL(/\/(?!login)/, { timeout: 15_000 });
await expect(page.locator('nav')).toBeVisible();
console.log('[E2E] ✅ Login successful');
});
// ── 2. DASHBOARDS LANDING ──────────────────────────────
await test.step('Dashboard page loads', async () => {
const currentUrl = page.url();
expect(currentUrl).toMatch(/dashboards|\/datasets|\//);
console.log(`[E2E] ✅ Redirected to: ${currentUrl}`);
});
// ── 3. SETTINGS — check environments via UI ────────────
await test.step('Settings — environments tab', async () => {
await page.goto(`${FRONTEND_URL}/settings#/settings/environments`);
await page.waitForSelector('text=Окружения', { timeout: 10_000 });
// Verify environments exist via API
const envs = await apiGet('/api/settings/environments');
expect(envs.length).toBeGreaterThanOrEqual(3);
const envNames = envs.map(e => e.id);
expect(envNames).toContain('ss-dev');
expect(envNames).toContain('ss-preprod');
expect(envNames).toContain('ss-prod');
console.log('[E2E] ✅ Environments configured:', envNames.join(', '));
});
// ── 4. SETTINGS — check LLM via API ────────────────────
await test.step('Settings — LLM provider', async () => {
const status = await apiGet('/api/llm/status');
expect(status.configured).toBe(true);
expect(status.provider_count).toBeGreaterThanOrEqual(1);
console.log(`[E2E] ✅ LLM configured: ${status.provider_name} (${status.default_model})`);
});
// ── 5. SETTINGS — check Git via UI ─────────────────────
await test.step('Settings — Git integration', async () => {
await page.goto(`${FRONTEND_URL}/settings#/settings/git`);
await page.waitForSelector('text=Интеграция Git', { timeout: 10_000 });
const configs = await apiGet('/api/git/config');
expect(configs.length).toBeGreaterThanOrEqual(1);
// At least one config visible in UI
await expect(page.getByText(configs[0].name).first()).toBeVisible({ timeout: 5_000 });
console.log(`[E2E] ✅ Git configured: ${configs[0].name} (${configs[0].provider})`);
});
// ── 6. DATASETS — verify datasources ───────────────────
await test.step('Datasets — verify datasources', async () => {
const datasources = await apiGet('/api/translate/datasources?env_id=ss-dev');
const translateFact = datasources.find(ds =>
ds.table_name === 'translate_fact' && ds.schema === 'dm_view'
);
expect(translateFact).toBeDefined();
expect(translateFact.id).toBe('33');
console.log(`[E2E] ✅ Dataset dm_view.translate_found (id=${translateFact.id})`);
});
// ── 7. TRANSLATION — create job via API ────────────────
await test.step('Translation — create job', async () => {
const providers = await apiGet('/api/llm/providers');
const job = await apiPost('/api/translate/jobs', {
name: `E2E Smoke Test ${Date.now()}`,
description: 'Golden path E2E test',
source_dialect: 'postgresql',
target_dialect: 'postgresql',
source_datasource_id: '33',
source_table: 'dm_view.translate_fact',
target_schema: 'dm_view',
target_table: 'financial_comments_translated',
translation_column: 'comment',
target_column: 'comment_translated',
target_languages: ['ru'],
batch_size: 10,
environment_id: 'ss-dev',
provider_id: providers[0]?.id || null,
});
expect(job.id).toBeTruthy();
expect(job.status).toBe('DRAFT');
console.log(`[E2E] ✅ Translation job created: ${job.id} (${job.status})`);
// Verify in UI
await page.goto(`${FRONTEND_URL}/translate`);
await page.waitForSelector('text=Задания перевода', { timeout: 10_000 });
await expect(page.getByText(job.name).first()).toBeVisible({ timeout: 10_000 });
});
// ── 8. GIT — verify repositories ───────────────────────
await test.step('Git — list repositories', async () => {
const configs = await apiGet('/api/git/config');
if (configs.length > 0 && configs[0].provider === 'GITEA') {
const repos = await apiGet(`/api/git/config/${configs[0].id}/gitea/repos`);
expect(Array.isArray(repos)).toBe(true);
console.log(`[E2E] ✅ Gitea repos: ${repos.length} found`);
// Verify in git UI
await page.goto(`${FRONTEND_URL}/settings#/settings/git`);
await page.waitForTimeout(2000);
}
});
// ── 9. RUN TRANSLATION (or verify it was attempted) ────
await test.step('Translation — run job (verify pipeline)', async () => {
const jobs = await apiGet('/api/translate/jobs');
expect(Array.isArray(jobs)).toBe(true);
if (jobs.length > 0) {
const latestJob = jobs[jobs.length - 1];
console.log(`[E2E] ✅ Latest job: ${latestJob.name}${latestJob.status}`);
}
});
console.log('[E2E] 🎉 Golden path E2E completed successfully');
});
});
// #endregion SmokeE2E