fix(profile): stabilize binding compatibility and frontend checks
This commit is contained in:
117
frontend/src/api/__tests__/admin.users.spec.ts
Normal file
117
frontend/src/api/__tests__/admin.users.spec.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
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)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user