import { execFile } from 'node:child_process'; import { createServer } from 'node:http'; import { mkdtemp, writeFile, rm } from 'node:fs/promises'; import path from 'node:path'; import { promisify } from 'node:util'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { NextRequest } from 'next/server'; import { ProviderFactory } from '../src/providers/factory'; import { VkProvider } from '../src/providers/vk/vk-provider'; import { POST as previewPost } from '../src/app/api/posts/preview/route'; import { defaultSessionStore, SESSION_COOKIE_NAME } from '../src/lib/auth/session'; import { generalApiRateLimiter } from '../src/lib/rate-limiter'; const run = promisify(execFile); afterEach(() => { vi.restoreAllMocks(); vi.unstubAllEnvs(); generalApiRateLimiter.reset(); }); describe('live smoke cannot accept generated VK data', () => { it('rejects explicit mock configuration in production even with a service token', () => { vi.stubEnv('NODE_ENV', 'production'); vi.stubEnv('USE_VK_MOCK', 'true'); vi.stubEnv('VK_SERVICE_TOKEN', 'FAKE_UNUSED_SERVICE_TOKEN'); expect(() => ProviderFactory.getVkProvider()).toThrow(/forbidden in production/); }); it('labels an actual mock provider preview despite its SERVICE auth metadata', async () => { vi.stubEnv('NODE_ENV', 'test'); vi.stubEnv('USE_VK_MOCK', 'true'); const id = await defaultSessionStore.createSession({ id: 'fake-smoke-mode-user', vkUserId: '9001' }); try { const response = await previewPost(new NextRequest('http://localhost/api/posts/preview', { method: 'POST', headers: { cookie: `${SESSION_COOKIE_NAME}=${id}`, 'content-type': 'application/json' }, body: JSON.stringify({ url: 'https://vk.com/wall-1_1' }), })); const body = await response.json(); expect(response.status).toBe(200); expect(body.effectiveCapabilities.accessMode).toBe('PUBLIC_SERVICE'); expect(body.providerMode).toBe('MOCK'); } finally { await defaultSessionStore.destroySession(id); } }); it('labels a real provider instance without exposing its token', async () => { vi.stubEnv('NODE_ENV', 'test'); vi.stubEnv('USE_VK_MOCK', 'false'); vi.stubEnv('VK_SERVICE_TOKEN', 'FAKE_LIVE_MODE_MARKER_TOKEN'); vi.spyOn(VkProvider.prototype, 'fetchPost').mockResolvedValue({ platform: 'VK', ownerId: '-1', postId: '1', sourceUrl: 'https://vk.com/wall-1_1', title: 'Fake response', text: '', likesCount: 2, commentsCount: 0, repostsCount: 0, resolvedAuthType: 'SERVICE', }); const id = await defaultSessionStore.createSession({ id: 'fake-live-mode-user', vkUserId: '9002' }); try { const response = await previewPost(new NextRequest('http://localhost/api/posts/preview', { method: 'POST', headers: { cookie: `${SESSION_COOKIE_NAME}=${id}`, 'content-type': 'application/json' }, body: JSON.stringify({ url: 'https://vk.com/wall-1_1' }), })); const text = await response.text(); expect(response.status).toBe(200); expect(JSON.parse(text).providerMode).toBe('LIVE'); expect(text).not.toContain('FAKE_LIVE_MODE_MARKER_TOKEN'); } finally { await defaultSessionStore.destroySession(id); } }); it.each([ { mode: 'MOCK', count: 2, expected: 1 }, { mode: 'LIVE', count: 0, expected: 1 }, { mode: 'LIVE', count: 2, expected: 0 }, ])('smoke exits $expected for $mode mode with $count participants', async ({ mode, count, expected }) => { let createCalls = 0; let importCalls = 0; const server = createServer((req, res) => { req.resume(); if (req.url === '/api/auth/vk/start') { res.writeHead(307, { location: 'https://id.vk.com/authorize?code_challenge_method=S256' }); res.end(); return; } res.setHeader('content-type', 'application/json'); if (req.url === '/api/auth/me') { res.end(JSON.stringify({ authenticated: true, user: { id: 'fake-user' } })); return; } if (req.url === '/api/posts/preview') { res.end(JSON.stringify({ success: true, providerMode: mode, effectiveCapabilities: { accessMode: 'PUBLIC_SERVICE' }, post: { sourceUrl: 'https://vk.com/wall-1_1', resolvedAuthType: 'SERVICE' } })); return; } if (req.url === '/api/giveaways') { createCalls++; res.statusCode = 201; res.end(JSON.stringify({ success: true, giveaway: { id: 'fake-giveaway' } })); return; } if (req.url === '/api/giveaways/fake-giveaway/participants') { importCalls++; res.end(JSON.stringify({ success: true, providerMode: mode, totalCount: count })); return; } res.statusCode = 404; res.end('{}'); }); await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)); // Keep all local scratch material under the agent's permitted notes area. const dir = await mkdtemp(path.resolve('agents/codex/notes/.smoke-regression-')); try { const port = (server.address() as { port: number }).port; const file = path.join(dir, '.env.local'); await writeFile(file, `VK_SMOKE_BASE_URL=http://127.0.0.1:${port}\nVK_SMOKE_SESSION_COOKIE=randomayzer_session=FAKE_SMOKE_COOKIE\nVK_SMOKE_PUBLIC_POST_URL=https://vk.com/wall-1_1\nVK_SMOKE_GROUP_ID=42\nVK_SMOKE_CREATE_GIVEAWAY=YES\n`, { mode: 0o600 }); let stdout = '', exitCode = 0; try { stdout = (await run('bash', [path.resolve('tools/vk-smoke.sh'), file], { timeout: 20000 })).stdout; } catch (error) { const failure = error as { code: number; stdout: string }; exitCode = failure.code; stdout = failure.stdout; } expect(exitCode).toBe(expected); expect(stdout).toContain('MANUAL B'); expect(stdout).not.toContain('FAKE_SMOKE_COOKIE'); if (mode === 'MOCK') { expect(stdout).toContain('FAIL D'); expect(stdout).not.toContain('PASS G'); expect(stdout).not.toContain('PASS H'); expect(createCalls).toBe(0); expect(importCalls).toBe(0); } else if (count === 0) { expect(stdout).toContain('FAIL G'); expect(stdout).toContain('FAIL H'); } else { expect(stdout).toContain('PASS D'); expect(stdout).toContain('PASS G'); expect(stdout).toContain('PASS H'); expect(importCalls).toBe(2); } } finally { await rm(dir, { recursive: true, force: true }); await new Promise((resolve, reject) => server.close(err => err ? reject(err) : resolve())); } }); });