Ctrl K
ComunidadGuías…

tests/bundle-upsert.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'

const mocks = vi.hoisted(() => ({
  checkPermission: vi.fn(),
  orgPolicy: vi.fn(),
  existingVersion: vi.fn(),
  upsert: vi.fn(),
}))

vi.mock('../supabase/functions/_backend/utils/rbac.ts', () => ({
  checkPermission: (...args: unknown[]) => mocks.checkPermission(...args),
}))

vi.mock('../supabase/functions/_backend/utils/pg.ts', () => ({
  getPgClient: async () => ({ query: async () => ({ rows: [mocks.orgPolicy()] }) }),
  closeClient: () => {},
}))

vi.mock('../supabase/functions/_backend/utils/pg_rls.ts', () => ({
  apikeyPrincipal: (_c: unknown, apikey: string) => ({ kind: 'apikey', apikey }),
  withRlsContext: (_c: unknown, _principal: unknown, run: (client: unknown) => unknown) => run({}),
  queryJsonOne: async (_client: unknown, text: string, values: unknown[]) => {
    if (text.startsWith('INSERT'))
      return mocks.upsert(text, JSON.parse(values[0] as string))
    return mocks.existingVersion()
  },
}))

const { upsertBundle } = await import('../supabase/functions/_backend/public/bundle/upsert.ts')

function createContext() {
  return {
    json: (body: unknown) => Response.json(body),
  } as any
}

const apikey = { key: 'test-key', user_id: 'user-1' } as any

function mockOrgPolicy(enforce: boolean, requiredKey: string | null = null) {
  mocks.orgPolicy.mockReturnValue({
    owner_org: 'org-1',
    orgs: {
      enforce_encrypted_bundles: enforce,
      required_encryption_key: requiredKey,
    },
  })
}

function mockVersions(existingVersion: unknown) {
  mocks.existingVersion.mockReturnValue(existingVersion)
  mocks.upsert.mockReturnValue({
    id: 99,
    app_id: 'com.example.app',
    name: '1.0.0',
    storage_provider: 'r2-direct',
  })
}

describe('bundle upsert endpoint', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    mocks.checkPermission.mockResolvedValue(true)
    mockOrgPolicy(false)
    mockVersions(null)
  })

  it('creates bundle version rows for upload finalize writes', async () => {
    const response = await upsertBundle(
      createContext(),
      {
        app_id: 'com.example.app',
        name: '1.0.0',
        checksum: 'abc',
        storage_provider: 'r2-direct',
        session_key: 'iv-key',
      },
      apikey,
    )

    expect(response.status).toBe(200)
    const body = await response.json() as { id?: number, name?: string }
    expect(body.id).toBe(99)
    expect(body.name).toBe('1.0.0')
    expect(mocks.checkPermission).toHaveBeenCalledWith(expect.anything(), 'app.upload_bundle', {
      appId: 'com.example.app',
    })
    expect(mocks.upsert).toHaveBeenCalledTimes(1)
    expect(mocks.upsert).toHaveBeenCalledWith(
      expect.stringContaining('ON CONFLICT (name, app_id) DO UPDATE SET "app_id" = EXCLUDED."app_id"'),
      {
        app_id: 'com.example.app',
        name: '1.0.0',
        owner_org: 'org-1',
        user_id: 'user-1',
        checksum: 'abc',
        storage_provider: 'r2-direct',
        session_key: 'iv-key',
      },
    )
  })

  it('rejects clearing session_key on an existing version when the org enforces encryption', async () => {
    mockOrgPolicy(true)
    mockVersions({ id: 99, deleted: false, session_key: 'iv-key', key_id: null })

    await expect(upsertBundle(
      createContext(),
      { app_id: 'com.example.app', name: '1.0.0', session_key: null },
      apikey,
    )).rejects.toMatchObject({ status: 400, cause: { error: 'encryption_required' } })
    expect(mocks.upsert).not.toHaveBeenCalled()
  })

  it('rejects swapping key_id on an existing version to a non-required key', async () => {
    mockOrgPolicy(true, 'required-key-value-0123456789')
    mockVersions({ id: 99, deleted: false, session_key: 'iv-key', key_id: 'required-key-value-0' })

    await expect(upsertBundle(
      createContext(),
      { app_id: 'com.example.app', name: '1.0.0', key_id: 'other-key' },
      apikey,
    )).rejects.toMatchObject({ status: 400, cause: { error: 'encryption_key_mismatch' } })
    expect(mocks.upsert).not.toHaveBeenCalled()
  })

  it('allows non-encryption updates on an existing version under an encryption policy', async () => {
    mockOrgPolicy(true)
    mockVersions({ id: 99, deleted: false, session_key: null, key_id: null })

    const response = await upsertBundle(
      createContext(),
      { app_id: 'com.example.app', name: '1.0.0', r2_path: 'orgs/org-1/apps/com.example.app/1.0.0.zip' },
      apikey,
    )

    expect(response.status).toBe(200)
    expect(mocks.upsert).toHaveBeenCalledWith(
      expect.stringContaining('ON CONFLICT (name, app_id)'),
      expect.objectContaining({ r2_path: 'orgs/org-1/apps/com.example.app/1.0.0.zip' }),
    )
  })
})