Ctrl K
ComunidadGuías…

tests/app-onboarding-builder-v4.db.test.ts

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

Archivo original ↗Preguntar a KiBot
import { randomUUID } from 'node:crypto'
import { env } from 'node:process'
import { createClient } from '@supabase/supabase-js'
import { describe, expect, it } from 'vitest'

const admin = createClient(env.SUPABASE_URL!, env.SUPABASE_SERVICE_KEY!, { auth: { persistSession: false, autoRefreshToken: false } })
const anonymous = createClient(env.SUPABASE_URL!, env.SUPABASE_ANON_KEY!, { auth: { persistSession: false, autoRefreshToken: false } })

const IOS_STEPS = [
  'start_setup',
  'choose_destination',
  'connect_app_store',
  'prepare_certificate',
  'prepare_profile',
  'successful_cloud_build',
]
const ANDROID_STEPS = [
  'start_setup',
  'prepare_keystore',
  'connect_google_play',
  'successful_cloud_build',
]

describe('builder checklist v4 database initialization', () => {
  it.concurrent('keeps the initializer unavailable to anonymous callers', async () => {
    const { data, error } = await anonymous.rpc('new_builder_onboarding_setup_v1')
    expect(data).toBeNull()
    expect(error).not.toBeNull()
  })

  it.concurrent('defines the exact pending Builder-only setup without selecting a platform', async () => {
    const { data: setup, error } = await admin.rpc('new_builder_onboarding_setup_v1')
    expect(error).toBeNull()
    expect(setup).toMatchObject({
      todo_list_version: 4,
      builder_todo_list_version: '1',
      paths: ['builder'],
      selected_path: 'builder',
      outcome: 'in_progress',
    })
    expect(setup).not.toHaveProperty('ota_todo_list_version')
    expect(setup).not.toHaveProperty('selected_builder_platform')
    expect(Object.keys(setup.steps)).toEqual(['builder'])
    for (const [platform, expectedSteps] of Object.entries({ ios: IOS_STEPS, android: ANDROID_STEPS })) {
      expect(Object.keys(setup.steps.builder[platform]).sort()).toEqual([...expectedSteps].sort())
      expect(Object.values(setup.steps.builder[platform])).toEqual(expectedSteps.map(() => ({ status: 'pending' })))
    }

    const merged = await admin.rpc('merge_app_onboarding_setup', {
      p_existing: { setup, features: { builder: { stage: 'new' } } },
      p_patch: { source: 'cli', steps: { login_cli_mcp: { status: 'done' } } },
    })
    expect(merged.error).toBeNull()
    expect(merged.data.setup.steps).toEqual(setup.steps)
    expect(merged.data.setup.paths).toEqual(['builder'])
    expect(merged.data.setup.outcome).toBe('in_progress')
    expect(merged.data.features).toEqual({ builder: { stage: 'new' } })
  })

  it.concurrent.each([
    ['builder', 'A', true, 'builder'],
    ['builder', null, true, 'ota'],
    ['builder', 'B', true, 'ota'],
    ['ota', 'A', true, 'ota'],
    ['builder', 'A', false, 'ota'],
  ] as const)('assigns creator intent %s, branch %s, creator-owned org %s to the %s checklist', async (intent, branch, ownOrg, expectedPath) => {
    const email = `builder-v4-${randomUUID()}@example.com`
    const orgId = randomUUID()
    const appId = `com.test.builder.v4.${randomUUID()}`
    let userId: string | undefined
    let ownerId: string | undefined
    let ownerEmail: string | undefined
    try {
      const created = await admin.auth.admin.createUser({ email, password: 'builder-v4-test-password', email_confirm: true })
      expect(created.error).toBeNull()
      userId = created.data.user!.id
      if (!ownOrg) {
        ownerEmail = `builder-v4-owner-${randomUUID()}@example.com`
        const owner = await admin.auth.admin.createUser({ email: ownerEmail, password: 'builder-v4-test-password', email_confirm: true })
        expect(owner.error).toBeNull()
        ownerId = owner.data.user!.id
      }
      expect((await admin.from('users').upsert({
        id: userId,
        email,
        onboarding: { intent, abtests: branch ? { builder_todo_list_v4: { branch, assigned_at: new Date().toISOString() } } : {} },
      })).error).toBeNull()
      if (ownerId)
        expect((await admin.from('users').upsert({ id: ownerId, email: ownerEmail })).error).toBeNull()
      expect((await admin.from('orgs').insert({ id: orgId, created_by: ownerId ?? userId, name: 'Builder checklist test', management_email: email, onboarding: { intent: 'builder' } })).error).toBeNull()
      const app = await admin.from('apps').insert({
        app_id: appId,
        owner_org: orgId,
        name: 'Builder checklist test',
        icon_url: '',
        onboarding: { created_by_user_id: userId, setup: { todo_list_version: 2, source: 'manual', outcome: 'in_progress', steps: {} } },
      }).select('onboarding').single()
      expect(app.error).toBeNull()
      const setup = (app.data!.onboarding as any).setup
      expect(setup.todo_list_version).toBe(4)
      expect((app.data!.onboarding as any).created_by_user_id).toBe(userId)
      if (expectedPath === 'ota') {
        expect(setup.steps?.builder).toBeUndefined()
        expect(setup.builder_todo_list_version).toBeUndefined()
        expect(setup.ota_todo_list_version).toBe('1')
        expect(setup.paths).toEqual(['ota'])
        expect(Object.keys(setup.steps.ota)).toHaveLength(7)
      }
      else {
        expect(setup.builder_todo_list_version).toBe('1')
        expect(setup.paths).toEqual(['builder'])
        expect(setup.selected_path).toBe('builder')
        expect(Object.keys(setup.steps)).toEqual(['builder'])
        for (const [platform, expectedSteps] of Object.entries({ ios: IOS_STEPS, android: ANDROID_STEPS })) {
          expect(Object.keys(setup.steps.builder[platform]).sort()).toEqual([...expectedSteps].sort())
          expect(Object.values(setup.steps.builder[platform])).toEqual(expectedSteps.map(() => ({ status: 'pending' })))
        }
      }
      if (expectedPath === 'builder') {
        expect(setup.ota_todo_list_version).toBeUndefined()
        expect(setup.steps.ota).toBeUndefined()
      }

      expect((await admin.from('users').update({ onboarding: { intent: 'builder', abtests: {} } }).eq('id', userId)).error).toBeNull()
      expect((await admin.from('orgs').update({ onboarding: { intent: 'ota' } }).eq('id', orgId)).error).toBeNull()
      const renamed = await admin.from('apps').update({ name: 'Renamed' }).eq('app_id', appId).select('onboarding').single()
      expect(renamed.error).toBeNull()
      expect((renamed.data!.onboarding as any).setup).toEqual(setup)
    }
    finally {
      await admin.from('apps').delete().eq('app_id', appId)
      await admin.from('orgs').delete().eq('id', orgId)
      if (userId) {
        await admin.from('users').delete().eq('id', userId)
        await admin.auth.admin.deleteUser(userId)
      }
      if (ownerId) {
        await admin.from('users').delete().eq('id', ownerId)
        await admin.auth.admin.deleteUser(ownerId)
      }
    }
  })
})