// #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 -> [E2E.Smoke] // @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