Ctrl K
ComunidadGuías…

tests/build-status-builder-checklist.unit.test.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { getBuildStatus } from '../supabase/functions/_backend/public/build/status.ts'

const mocks = vi.hoisted(() => ({
  adminQuery: vi.fn(),
  rlsQuery: vi.fn(),
  checklist: vi.fn(),
  emit: vi.fn(),
  permission: vi.fn(),
  recordBuildTime: vi.fn(),
}))

vi.mock('../supabase/functions/_backend/utils/builder_onboarding_checklist.ts', () => ({ persistBuilderBuildOutcome: mocks.checklist }))
vi.mock('../supabase/functions/_backend/utils/build_tracking.ts', () => ({ emitBuildTransitionEvent: mocks.emit }))
vi.mock('../supabase/functions/_backend/utils/rbac.ts', () => ({ checkPermission: mocks.permission }))
vi.mock('../supabase/functions/_backend/utils/supabase.ts', () => ({
  recordBuildTime: mocks.recordBuildTime,
}))
vi.mock('../supabase/functions/_backend/utils/pg.ts', () => ({
  getPgClient: async () => ({ query: mocks.adminQuery }),
  closeClient: () => {},
}))
vi.mock('../supabase/functions/_backend/utils/pg_rls.ts', async (importOriginal) => {
  const actual = await importOriginal<typeof import('../supabase/functions/_backend/utils/pg_rls.ts')>()
  return {
    ...actual,
    withRlsContext: async (_c: unknown, _principal: unknown, run: (client: unknown) => unknown) => run({ query: mocks.rlsQuery }),
  }
})
vi.mock('../supabase/functions/_backend/utils/utils.ts', () => ({
  getEnv: (_c: unknown, key: string) => key === 'BUILDER_URL' ? 'https://builder.test' : key === 'BUILDER_API_KEY' ? 'builder-key' : '',
}))

const appId = 'com.test.status-checklist'
const jobId = 'builder-job'

function context() {
  return {
    get: (key: string) => key === 'requestId' ? 'request-id' : undefined,
    json: (data: unknown, status = 200) => new Response(JSON.stringify(data), { status }),
  } as any
}

function configureCas(data: Array<{ id: string }>) {
  mocks.adminQuery.mockResolvedValue({ rows: data, rowCount: data.length })
}

beforeEach(() => {
  vi.resetAllMocks()
  mocks.permission.mockResolvedValue(true)
  mocks.checklist.mockResolvedValue(false)
  mocks.emit.mockResolvedValue(undefined)
  mocks.recordBuildTime.mockResolvedValue(undefined)
  const buildRequest = {
    app_id: appId,
    owner_org: '11111111-1111-4111-8111-111111111111',
    requested_by: '22222222-2222-4222-8222-222222222222',
    platform: 'ios',
    status: 'running',
    build_mode: 'release',
  }
  mocks.rlsQuery.mockImplementation(async (text: string) => {
    if (text.includes('FROM public.build_requests'))
      return { rows: [{ row: buildRequest }] }
    return { rows: [{ row: { build_timeout_seconds: 900, build_timeout_updated_at: new Date().toISOString() } }] }
  })
  configureCas([{ id: 'row-id' }])
  vi.spyOn(globalThis, 'fetch').mockResolvedValue(new Response(JSON.stringify({
    job: { status: 'succeeded', started_at: null, completed_at: null, error: null },
    machine: null,
  }), { status: 200, headers: { 'Content-Type': 'application/json' } }))
})

describe('build status Builder checklist persistence', () => {
  it('runs after the CAS winner without changing the endpoint response', async () => {
    const c = context()
    const response = await getBuildStatus(c, { job_id: jobId, app_id: appId, platform: 'ios' }, { key: 'api-key' } as any)

    expect(response.status).toBe(200)
    expect(await response.json()).toMatchObject({ job_id: jobId, status: 'succeeded' })
    expect(mocks.checklist).toHaveBeenCalledWith(c, { appId, platform: 'ios', status: 'succeeded' })
  })

  it('does not run when the CAS update loses its race', async () => {
    configureCas([])
    const response = await getBuildStatus(context(), { job_id: jobId, app_id: appId, platform: 'ios' }, { key: 'api-key' } as any)

    expect(response.status).toBe(200)
    expect(mocks.checklist).not.toHaveBeenCalled()
  })
})