test(admin): 精选/看板/广告位 api 单测——game-admin api 层全覆盖(28 测)

补齐 game-admin 5 wanxiang api 模块的运营接口测,成完整 api 回归基线:
- feed.spec(4):精选池 getFeaturedPage/saveFeatured
- telemetry.spec(4):看板 getGameStatPage/getGameStat
- ad.spec(7):广告位 CRUD——**重点钉 method-per-op(create=POST/update=PUT/delete=DELETE,方法错配=真 bug)**+ revenue page
- 均 mock 兜底 + 真实 url/method/data 贴 frozen 契约

验证:`npm test` 28/28 绿(project7+trade6+feed4+telemetry4+ad7)。game-admin api 层(含两关键决策门+运营 CRUD)全有回归测。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
lili 2026-06-17 17:08:03 -07:00
parent 0a363ec3aa
commit 709912bd1d
3 changed files with 158 additions and 0 deletions

View File

@ -0,0 +1,71 @@
/**
* ad.spec.ts ·广 api CRUD HTTP method-per-op(create=post/update=put/delete=delete,
* = bug)+ mock + url/data frozen ad.yaml `npm test`
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
vi.mock('@/config/axios', () => ({ default: { get: vi.fn(), post: vi.fn(), put: vi.fn(), delete: vi.fn() } }))
import request from '@/config/axios'
import { getAdSlotPage, getAdSlot, createAdSlot, updateAdSlot, deleteAdSlot, getAdRevenuePage } from './ad'
const req = request as unknown as Record<'get' | 'post' | 'put' | 'delete', ReturnType<typeof vi.fn>>
describe('wanxiang/ad 广告位 api', () => {
beforeEach(() => vi.clearAllMocks())
afterEach(() => vi.unstubAllEnvs())
describe('mock 兜底', () => {
beforeEach(() => vi.stubEnv('VITE_APP_WANXIANG_MOCK', 'true'))
it('各接口走 mock,不打真实 request', async () => {
await getAdSlotPage({ pageNo: 1, pageSize: 10 })
await getAdSlot(1)
await createAdSlot({ slotId: 's1', type: 'rewarded', provider: 'mock', enabled: true })
await updateAdSlot({ id: 1, slotId: 's1', type: 'rewarded', provider: 'mock', enabled: false })
await deleteAdSlot(1)
await getAdRevenuePage({ pageNo: 1, pageSize: 10 })
expect(req.get).not.toHaveBeenCalled()
expect(req.post).not.toHaveBeenCalled()
expect(req.put).not.toHaveBeenCalled()
expect(req.delete).not.toHaveBeenCalled()
})
})
describe('真实模式method-per-op 钉死)', () => {
beforeEach(() => vi.stubEnv('VITE_APP_WANXIANG_MOCK', 'false'))
it('getAdSlotPage → GET /ad/slot/page', async () => {
req.get.mockResolvedValue({ list: [], total: 0 })
await getAdSlotPage({ pageNo: 1, pageSize: 10 })
expect(req.get).toHaveBeenCalledWith({ url: '/ad/slot/page', params: { pageNo: 1, pageSize: 10 } })
})
it('getAdSlot → GET /ad/slot/get?id=', async () => {
req.get.mockResolvedValue({})
await getAdSlot(7)
expect(req.get).toHaveBeenCalledWith({ url: '/ad/slot/get?id=7' })
})
it('createAdSlot → POST /ad/slot/create + data', async () => {
req.post.mockResolvedValue(1)
const data = { slotId: 's1', type: 'rewarded', provider: 'mock', enabled: true }
await createAdSlot(data)
expect(req.post).toHaveBeenCalledWith({ url: '/ad/slot/create', data })
})
it('updateAdSlot → PUT /ad/slot/update + data(非 POST)', async () => {
req.put.mockResolvedValue(true)
const data = { id: 1, slotId: 's1', type: 'rewarded', provider: 'mock', enabled: false }
await updateAdSlot(data)
expect(req.put).toHaveBeenCalledWith({ url: '/ad/slot/update', data })
expect(req.post).not.toHaveBeenCalled()
})
it('deleteAdSlot → DELETE /ad/slot/delete?id=', async () => {
req.delete.mockResolvedValue(true)
await deleteAdSlot(9)
expect(req.delete).toHaveBeenCalledWith({ url: '/ad/slot/delete?id=9' })
})
it('getAdRevenuePage → GET /ad/revenue/page', async () => {
req.get.mockResolvedValue({ list: [], total: 0 })
await getAdRevenuePage({ pageNo: 1, pageSize: 10 })
expect(req.get).toHaveBeenCalledWith({ url: '/ad/revenue/page', params: { pageNo: 1, pageSize: 10 } })
})
})
})

View File

@ -0,0 +1,44 @@
/**
* feed.spec.ts · api mock + url/method/data frozen feed.yaml `npm test`
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
vi.mock('@/config/axios', () => ({ default: { get: vi.fn(), post: vi.fn() } }))
import request from '@/config/axios'
import { getFeaturedPage, saveFeatured } from './feed'
const req = request as unknown as { get: ReturnType<typeof vi.fn>; post: ReturnType<typeof vi.fn> }
describe('wanxiang/feed 精选 api', () => {
beforeEach(() => vi.clearAllMocks())
afterEach(() => vi.unstubAllEnvs())
describe('mock 兜底', () => {
beforeEach(() => vi.stubEnv('VITE_APP_WANXIANG_MOCK', 'true'))
it('getFeaturedPage → mock,不打真接口', async () => {
const r = await getFeaturedPage({ pageNo: 1, pageSize: 10 })
expect(r).toBeTruthy()
expect(req.get).not.toHaveBeenCalled()
})
it('saveFeatured → mock,不打真接口', async () => {
await saveFeatured({ gameId: 1, featured: true, boostWeight: 50 })
expect(req.post).not.toHaveBeenCalled()
})
})
describe('真实模式', () => {
beforeEach(() => vi.stubEnv('VITE_APP_WANXIANG_MOCK', 'false'))
it('getFeaturedPage → GET /feed/featured/page + params', async () => {
req.get.mockResolvedValue({ list: [], total: 0 })
await getFeaturedPage({ pageNo: 1, pageSize: 10 })
expect(req.get).toHaveBeenCalledWith({ url: '/feed/featured/page', params: { pageNo: 1, pageSize: 10 } })
})
it('saveFeatured → POST /feed/featured + data', async () => {
req.post.mockResolvedValue(true)
const data = { gameId: 1, featured: true, boostWeight: 80 }
await saveFeatured(data)
expect(req.post).toHaveBeenCalledWith({ url: '/feed/featured', data })
})
})
})

View File

@ -0,0 +1,43 @@
/**
* telemetry.spec.ts · api mock + url/method frozen telemetry.yaml `npm test`
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
vi.mock('@/config/axios', () => ({ default: { get: vi.fn(), post: vi.fn() } }))
import request from '@/config/axios'
import { getGameStatPage, getGameStat } from './telemetry'
const req = request as unknown as { get: ReturnType<typeof vi.fn> }
describe('wanxiang/telemetry 看板 api', () => {
beforeEach(() => vi.clearAllMocks())
afterEach(() => vi.unstubAllEnvs())
describe('mock 兜底', () => {
beforeEach(() => vi.stubEnv('VITE_APP_WANXIANG_MOCK', 'true'))
it('getGameStatPage → mock,不打真接口', async () => {
const r = await getGameStatPage({ pageNo: 1, pageSize: 10 })
expect(r).toBeTruthy()
expect(req.get).not.toHaveBeenCalled()
})
it('getGameStat → mock,不打真接口', async () => {
await getGameStat(1001)
expect(req.get).not.toHaveBeenCalled()
})
})
describe('真实模式', () => {
beforeEach(() => vi.stubEnv('VITE_APP_WANXIANG_MOCK', 'false'))
it('getGameStatPage → GET /telemetry/game-stat/page + params', async () => {
req.get.mockResolvedValue({ list: [], total: 0 })
await getGameStatPage({ pageNo: 2, pageSize: 20 })
expect(req.get).toHaveBeenCalledWith({ url: '/telemetry/game-stat/page', params: { pageNo: 2, pageSize: 20 } })
})
it('getGameStat → GET /telemetry/game-stat/{id}', async () => {
req.get.mockResolvedValue({})
await getGameStat(1001)
expect(req.get).toHaveBeenCalledWith({ url: '/telemetry/game-stat/1001' })
})
})
})