Add GitLab, pagination, activity timeline, and error resilience e2e tests
Four new test suites expanding integration hub e2e coverage: - gitlab-integration.e2e.spec.ts: Container health, direct probe, connector CRUD lifecycle (create/test/health/delete), SCM tab UI verification. Gracefully skips when GitLab container not running (heavy profile). - pagination.e2e.spec.ts: API-level pagination (pageSize, page params, totalPages, sorting, last-page edge case, out-of-range page). UI pager rendering verification. - activity-timeline.e2e.spec.ts: Page load, stats bar, activity items, event type filter dropdown, clear filters, back navigation. Tests against mock data rendered by the activity component. - error-resilience.e2e.spec.ts: Unreachable endpoint returns failure/unhealthy, non-existent resource 404s, malformed input handling, duplicate name creation, UI empty tab rendering, deleted integration detail page. Also adds GitLab config to shared helpers.ts INTEGRATION_CONFIGS. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* GitLab Integration — End-to-End Tests
|
||||
*
|
||||
* Validates the GitLab SCM connector lifecycle against the real GitLab CE instance:
|
||||
* 1. Container health + direct probe
|
||||
* 2. Connector CRUD via API (create, test-connection, health, delete)
|
||||
* 3. UI: SCM tab shows GitLab row
|
||||
*
|
||||
* Workaround for "heavy profile": Instead of checking Docker CLI (which may
|
||||
* not be available from Playwright workers), we probe GitLab's HTTP endpoint
|
||||
* directly. If it responds, the tests run; otherwise they skip gracefully.
|
||||
*/
|
||||
|
||||
import { execSync } from 'child_process';
|
||||
import { test, expect } from './live-auth.fixture';
|
||||
import {
|
||||
INTEGRATION_CONFIGS,
|
||||
createIntegrationViaApi,
|
||||
cleanupIntegrations,
|
||||
snap,
|
||||
} from './helpers';
|
||||
|
||||
const BASE = process.env['PLAYWRIGHT_BASE_URL'] || 'https://stella-ops.local';
|
||||
const runId = process.env['E2E_RUN_ID'] || 'run1';
|
||||
const GITLAB_URL = 'http://127.1.2.7:8929';
|
||||
|
||||
/**
|
||||
* Probe GitLab via HTTP instead of Docker CLI.
|
||||
* Returns true if GitLab responds (any status < 500) within 3 seconds.
|
||||
*/
|
||||
function gitlabReachable(): boolean {
|
||||
try {
|
||||
// Use curl (available on both Windows and Linux) with a short timeout
|
||||
const out = execSync(
|
||||
`curl -sf -o /dev/null -w "%{http_code}" --connect-timeout 3 ${GITLAB_URL}/`,
|
||||
{ encoding: 'utf-8', timeout: 5_000 },
|
||||
).trim();
|
||||
const code = parseInt(out, 10);
|
||||
return code > 0 && code < 500;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const gitlabRunning = gitlabReachable();
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 1. Reachability
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
test.describe('GitLab Integration — Reachability', () => {
|
||||
test.skip(!gitlabRunning, 'GitLab not reachable at 127.1.2.7:8929');
|
||||
|
||||
test('GitLab responds to HTTP probe', async ({ playwright }) => {
|
||||
const ctx = await playwright.request.newContext({ ignoreHTTPSErrors: true });
|
||||
try {
|
||||
const resp = await ctx.get(`${GITLAB_URL}/`, { timeout: 10_000 });
|
||||
// 302 redirect to login = GitLab is running
|
||||
expect(resp.status()).toBeLessThan(500);
|
||||
} finally {
|
||||
await ctx.dispose();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 2. Connector Lifecycle (API)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
test.describe('GitLab Integration — Connector Lifecycle', () => {
|
||||
test.skip(!gitlabRunning, 'GitLab not reachable');
|
||||
|
||||
test('create GitLab integration and verify CRUD operations', async ({ apiRequest }) => {
|
||||
// Create
|
||||
const id = await createIntegrationViaApi(apiRequest, INTEGRATION_CONFIGS.gitlab, runId);
|
||||
expect(id).toBeTruthy();
|
||||
|
||||
try {
|
||||
// Verify created with correct fields
|
||||
const getResp = await apiRequest.get(`/api/v1/integrations/${id}`);
|
||||
expect(getResp.status()).toBe(200);
|
||||
const integration = await getResp.json();
|
||||
expect(integration.type).toBe(2); // Scm
|
||||
expect(integration.provider).toBe(201); // GitLabServer
|
||||
expect(integration.name).toContain('GitLab');
|
||||
expect(integration.endpoint).toContain('gitlab');
|
||||
|
||||
// Test connection — returns structured response
|
||||
// May return success=false if GitLab requires auth token for /api/v4/version
|
||||
const testResp = await apiRequest.post(`/api/v1/integrations/${id}/test`);
|
||||
expect(testResp.status()).toBe(200);
|
||||
const testBody = await testResp.json();
|
||||
expect(typeof testBody.success).toBe('boolean');
|
||||
expect(testBody.message).toBeTruthy();
|
||||
|
||||
// Health check — returns structured response
|
||||
const healthResp = await apiRequest.get(`/api/v1/integrations/${id}/health`);
|
||||
expect(healthResp.status()).toBe(200);
|
||||
const healthBody = await healthResp.json();
|
||||
expect(typeof healthBody.status).toBe('number');
|
||||
} finally {
|
||||
await cleanupIntegrations(apiRequest, [id]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 3. UI: SCM Tab
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
test.describe('GitLab Integration — UI Verification', () => {
|
||||
test.skip(!gitlabRunning, 'GitLab not reachable');
|
||||
|
||||
test('SCM tab shows GitLab integration', async ({ apiRequest, liveAuthPage: page }) => {
|
||||
const id = await createIntegrationViaApi(apiRequest, INTEGRATION_CONFIGS.gitlab, `ui-${runId}`);
|
||||
|
||||
try {
|
||||
await page.goto(`${BASE}/setup/integrations/scm`, {
|
||||
waitUntil: 'networkidle',
|
||||
timeout: 30_000,
|
||||
});
|
||||
await page.waitForTimeout(2_000);
|
||||
|
||||
const pageContent = await page.textContent('body');
|
||||
expect(pageContent).toContain('GitLab');
|
||||
|
||||
await snap(page, 'gitlab-scm-tab');
|
||||
} finally {
|
||||
await cleanupIntegrations(apiRequest, [id]);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user