118 lines
3.1 KiB
TypeScript
118 lines
3.1 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
const { post } = vi.hoisted(() => ({
|
|
post: vi.fn(),
|
|
}))
|
|
|
|
vi.mock('@/api/client', () => ({
|
|
apiClient: {
|
|
post,
|
|
},
|
|
}))
|
|
|
|
import {
|
|
bindUserAuthIdentity,
|
|
type AdminBindAuthIdentityRequest,
|
|
type AdminBoundAuthIdentity,
|
|
} from '@/api/admin/users'
|
|
|
|
type Assert<T extends true> = T
|
|
type IsExact<T, U> = (
|
|
(<G>() => G extends T ? 1 : 2) extends (<G>() => G extends U ? 1 : 2)
|
|
? ((<G>() => G extends U ? 1 : 2) extends (<G>() => G extends T ? 1 : 2) ? true : false)
|
|
: false
|
|
)
|
|
|
|
type ExpectedAdminBindAuthIdentityRequest = {
|
|
provider_type: string
|
|
provider_key: string
|
|
provider_subject: string
|
|
issuer?: string
|
|
metadata?: Record<string, unknown>
|
|
channel?: {
|
|
channel: string
|
|
channel_app_id: string
|
|
channel_subject: string
|
|
metadata?: Record<string, unknown>
|
|
}
|
|
}
|
|
|
|
type ExpectedAdminBoundAuthIdentity = {
|
|
user_id: number
|
|
provider_type: string
|
|
provider_key: string
|
|
provider_subject: string
|
|
verified_at?: string | null
|
|
issuer?: string | null
|
|
metadata: Record<string, unknown> | null
|
|
created_at: string
|
|
updated_at: string
|
|
channel?: {
|
|
channel: string
|
|
channel_app_id: string
|
|
channel_subject: string
|
|
metadata: Record<string, unknown> | null
|
|
created_at: string
|
|
updated_at: string
|
|
} | null
|
|
}
|
|
|
|
const requestContractExact: Assert<
|
|
IsExact<AdminBindAuthIdentityRequest, ExpectedAdminBindAuthIdentityRequest>
|
|
> = true
|
|
const responseContractExact: Assert<
|
|
IsExact<AdminBoundAuthIdentity, ExpectedAdminBoundAuthIdentity>
|
|
> = true
|
|
|
|
describe('admin users api auth identity binding', () => {
|
|
beforeEach(() => {
|
|
post.mockReset()
|
|
})
|
|
|
|
it('posts the backend-compatible auth identity bind payload and returns the backend response shape', async () => {
|
|
const payload: AdminBindAuthIdentityRequest = {
|
|
provider_type: 'wechat',
|
|
provider_key: 'wechat-main',
|
|
provider_subject: 'union-123',
|
|
metadata: { source: 'admin-repair' },
|
|
channel: {
|
|
channel: 'open',
|
|
channel_app_id: 'wx-open',
|
|
channel_subject: 'openid-123',
|
|
metadata: { scene: 'migration' },
|
|
},
|
|
}
|
|
|
|
const response: AdminBoundAuthIdentity = {
|
|
user_id: 9,
|
|
provider_type: 'wechat',
|
|
provider_key: 'wechat-main',
|
|
provider_subject: 'union-123',
|
|
verified_at: '2026-04-22T00:00:00Z',
|
|
issuer: null,
|
|
metadata: { source: 'admin-repair' },
|
|
created_at: '2026-04-22T00:00:00Z',
|
|
updated_at: '2026-04-22T00:00:00Z',
|
|
channel: {
|
|
channel: 'open',
|
|
channel_app_id: 'wx-open',
|
|
channel_subject: 'openid-123',
|
|
metadata: { scene: 'migration' },
|
|
created_at: '2026-04-22T00:00:00Z',
|
|
updated_at: '2026-04-22T00:00:00Z',
|
|
},
|
|
}
|
|
post.mockResolvedValue({ data: response })
|
|
|
|
const result = await bindUserAuthIdentity(9, payload)
|
|
|
|
expect(post).toHaveBeenCalledWith('/admin/users/9/auth-identities', payload)
|
|
expect(result).toEqual(response)
|
|
})
|
|
|
|
it('keeps bind auth identity request and response types aligned with the backend contract', () => {
|
|
expect(requestContractExact).toBe(true)
|
|
expect(responseContractExact).toBe(true)
|
|
})
|
|
})
|