mirror of
https://github.com/saltbo/zpan.git
synced 2026-08-28 15:51:29 +08:00
b92df828ab
* ci: parallelize and isolate test suites * ci: avoid unavailable Playwright video runtime * ci: shard coverage and cache docker smoke * ci: balance Playwright shards by test * ci: smoke test the CLI container * ci: enforce merged coverage thresholds * ci: ratchet canonical coverage baseline * ci: make coverage ratchet lossless * ci: organize parallel gates by responsibility * perf(ci): reduce total runner time * perf(ci): balance runner cost and latency * perf(ci): suppress passing test logs * fix(test): make coverage sorting proof deterministic * perf(docker): exclude test-only build inputs * perf(ci): scope Docker smokes to packaging changes * refactor(test): enforce fast test boundaries * test: isolate coverage ownership * perf(test): run backend projects concurrently * perf(ci): separate test layers by runtime * perf(test): separate integration boundaries * perf(ci): prioritize test runners * docs(ci): clarify package scheduling * test: restore shared Cloudflare mocks * fix(preview): isolate Cloudflare E2E build config * fix(auth): bind preview sessions to request origin * revert: remove ineffective preview auth workaround * fix(auth): stop signing JWTs on session reads
98 lines
3.5 KiB
TypeScript
98 lines
3.5 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
import { CAPTCHA_ENABLED_KEY, CAPTCHA_SECRET_OPTION_KEY, CAPTCHA_SITE_KEY_KEY } from '../shared/captcha.js'
|
|
import { systemOptions } from './db/schema.js'
|
|
import { createTestApp } from './test/setup.js'
|
|
|
|
afterEach(() => {
|
|
vi.unstubAllGlobals()
|
|
})
|
|
|
|
describe('auth captcha integration', () => {
|
|
it('rejects protected auth endpoints through the Better Auth captcha plugin', async () => {
|
|
const { app, db } = await createTestApp()
|
|
await db.insert(systemOptions).values([
|
|
{ key: CAPTCHA_ENABLED_KEY, value: 'true' },
|
|
{ key: CAPTCHA_SITE_KEY_KEY, value: 'site-key' },
|
|
{ key: CAPTCHA_SECRET_OPTION_KEY, value: 'secret-key' },
|
|
])
|
|
|
|
const res = await app.request('/api/auth/sign-up/email', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ name: 'Test', email: 'guard@example.com', password: 'password123456' }),
|
|
})
|
|
|
|
expect(res.status).toBe(400)
|
|
await expect(res.json()).resolves.toMatchObject({ message: 'Missing CAPTCHA response' })
|
|
})
|
|
|
|
it('passes verified captcha headers through to Better Auth', async () => {
|
|
const { app, db } = await createTestApp()
|
|
await db.insert(systemOptions).values([
|
|
{ key: CAPTCHA_ENABLED_KEY, value: 'true' },
|
|
{ key: CAPTCHA_SITE_KEY_KEY, value: 'site-key' },
|
|
{ key: CAPTCHA_SECRET_OPTION_KEY, value: 'secret-key' },
|
|
])
|
|
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(new Response(JSON.stringify({ success: true }))))
|
|
|
|
const res = await app.request('/api/auth/sign-up/email', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', 'x-captcha-response': 'token' },
|
|
body: JSON.stringify({
|
|
name: 'Test',
|
|
email: 'guard-valid@example.com',
|
|
password: 'password123456',
|
|
}),
|
|
})
|
|
|
|
expect(res.status).toBe(200)
|
|
expect(fetch).toHaveBeenCalledOnce()
|
|
})
|
|
|
|
it('leaves social auth with Better Auth when captcha is enabled', async () => {
|
|
const { app, db } = await createTestApp()
|
|
await db.insert(systemOptions).values([
|
|
{ key: CAPTCHA_ENABLED_KEY, value: 'true' },
|
|
{ key: CAPTCHA_SITE_KEY_KEY, value: 'site-key' },
|
|
{ key: CAPTCHA_SECRET_OPTION_KEY, value: 'secret-key' },
|
|
])
|
|
|
|
const res = await app.request('/api/auth/sign-in/social', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ provider: 'github', callbackURL: '/files' }),
|
|
})
|
|
|
|
expect(await res.text()).not.toContain('Captcha')
|
|
})
|
|
|
|
it('leaves social auth with Better Auth when captcha is disabled', async () => {
|
|
const { app } = await createTestApp()
|
|
|
|
const res = await app.request('/api/auth/sign-in/social', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ provider: 'github', callbackURL: '/files' }),
|
|
})
|
|
|
|
expect(await res.text()).not.toContain('Captcha is required for social authentication')
|
|
})
|
|
|
|
it('does not apply captcha to social auth requests with malformed bodies', async () => {
|
|
const { app, db } = await createTestApp()
|
|
await db.insert(systemOptions).values([
|
|
{ key: CAPTCHA_ENABLED_KEY, value: 'true' },
|
|
{ key: CAPTCHA_SITE_KEY_KEY, value: 'site-key' },
|
|
{ key: CAPTCHA_SECRET_OPTION_KEY, value: 'secret-key' },
|
|
])
|
|
|
|
const res = await app.request('/api/auth/sign-in/social', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: '{',
|
|
})
|
|
|
|
expect(await res.text()).not.toContain('Invalid captcha token')
|
|
})
|
|
})
|