From 2d20365d56d957458da11eb6159464cea3ab95ce Mon Sep 17 00:00:00 2001 From: asepharyana Date: Mon, 14 Sep 2026 18:07:23 +0700 Subject: [PATCH] test(integration): fix stale assertions exposed by refactor - files.test.ts: 302-redirect expectation replaced with 200-proxy assertion (bot token only in server-side fetch, never Location) - deploy-config.test.ts: retarget from deleted .gitea workflow to .github/workflows/deploy.yml (CI migrated to GitHub Actions in 811a688); asserts nix build + VPS deploy shape --- test/deploy-config.test.ts | 21 +++++++++------------ test/files.test.ts | 32 +++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/test/deploy-config.test.ts b/test/deploy-config.test.ts index 4b64bcb..e0225e1 100644 --- a/test/deploy-config.test.ts +++ b/test/deploy-config.test.ts @@ -38,21 +38,18 @@ test('deploy check mode does not require an SSH key file', async () => { expect(stderr).toBe(''); }); -const workflowFile = Bun.file(new URL('../.gitea/workflows/deploy.yml', import.meta.url)); +const workflowFile = Bun.file(new URL('../.github/workflows/deploy.yml', import.meta.url)); -test('gitea workflow deploys pushes to main through deploy script', async () => { +test('deploy workflow builds with nix and deploys to VPS on main', async () => { const text = await workflowFile.text(); - expect(text).toContain('name: Deploy FileDrop'); - expect(text).toContain('branches:\n - main'); - expect(text).toContain('uses: actions/checkout@v4'); + expect(text).toContain('branches: [main]'); + expect(text).toContain('uses: actions/checkout@v7'); expect(text).toContain('uses: oven-sh/setup-bun@v2'); expect(text).toContain('bun install --frozen-lockfile'); - expect(text).toContain('bun run lint'); - expect(text).toContain('bun run build'); - expect(text).toContain('secrets.VPS_HOST'); - expect(text).toContain('secrets.VPS_USER'); - expect(text).toContain('secrets.VPS_SSH_KEY'); - expect(text).toContain('secrets.PRODUCTION_ENV'); - expect(text).toContain('./deploy.sh --no-build'); + expect(text).toContain('bunx biome check src test'); + expect(text).toContain('VPS_HOST'); + expect(text).toContain('VPS_USER'); + expect(text).toContain('nix copy'); + expect(text).toContain('systemctl restart teleuploader'); }); diff --git a/test/files.test.ts b/test/files.test.ts index 95b2df1..d0c011c 100644 --- a/test/files.test.ts +++ b/test/files.test.ts @@ -158,7 +158,7 @@ describe('File Route Handlers', () => { expect(body.error).toBe('File not found'); }); - it('should redirect to telegram file url with 302', async () => { + it('should proxy the telegram file body with 200 (no token leak)', async () => { mockFindByPublicId.mockImplementationOnce(async () => ({ publicId: 'test-id', telegramFileId: 'tg-file-id', @@ -187,13 +187,31 @@ describe('File Route Handlers', () => { updatedAt: new Date('2026-05-18T00:00:00.000Z'), })); - const req = requestWithPublicId('http://localhost:4000/f/test-id', 'test-id'); - const res = await handleFileRedirect(req); + const fetchCalls: string[] = []; + const originalFetch = globalThis.fetch; + globalThis.fetch = (async (url: string | URL | Request) => { + fetchCalls.push(String(url)); + return new Response('fake-image-bytes', { + status: 200, + headers: { 'content-type': 'image/jpeg' }, + }); + }) as typeof fetch; + try { + const req = requestWithPublicId('http://localhost:4000/f/test-id', 'test-id'); + const res = await handleFileRedirect(req); - expect(res.status).toBe(302); - expect(res.headers.get('Location')).toBe( - 'https://api.telegram.org/file/bot123456:ABC-DEF/photos/file_0.jpg', - ); + expect(res.status).toBe(200); + expect(res.headers.get('Location')).toBeNull(); + expect(res.headers.get('Content-Type')).toContain('image/jpeg'); + expect(await res.text()).toBe('fake-image-bytes'); + // The bot token must only go to Telegram server-side, never to the client. + expect(fetchCalls).toHaveLength(1); + expect(fetchCalls[0]).toBe( + 'https://api.telegram.org/file/bot123456:ABC-DEF/photos/file_0.jpg', + ); + } finally { + globalThis.fetch = originalFetch; + } }); it('should return 500 on database or external errors', async () => {