Full optimization cycle: Protocol (15 files): - 4-layer SSOT architecture for agent prompts & skills - Anti-Corruption Protocol consolidated from 5 duplicates - Tag-to-tier permissiveness matrix (all @tags allowed at all tiers) Axiom config: - complexity_rules: all 22+ tags available on C1-C5 - contract_type_overrides: removed (was narrowing per-type) - 18 new tags added, LAYER enum expanded (Infra, Frontend, Atom, etc.) - RELATION predicates expanded (USES, CONTAINS, BELONGS_TO, etc.) Code fixes: - 2216 @TAG: normalized to @TAG (colon→space) - 518 [DEF] blocks migrated to #region/#endregion (37 files) - VERIFIES→BINDS_TO, :Class/:Function suffixes removed, paths→IDs - 1173-line _external_stubs.py deleted (EXT: handled natively) - Batch EXT: reference audit (240 targets: 132 external, 99 internal, 9 fix) - QA regression check: 0 regressions across all checks Infrastructure: - DuckDB rebuild stabilized (appender API, INSERT OR IGNORE) - Anchor regex fix (parent-child BINDS_TO now resolves) - EXT:*/DTO:/NEED_CONTEXT: regex fixed in validator - 34MB Doxygen API portal (3194 contract pages)
137 lines
6.3 KiB
JavaScript
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 -> [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
|