|
- import type { APIRequestContext } from '@playwright/test'
-
- import { adminCredentials } from './helpers'
-
- export interface ContentAssetRecord {
- id: string
- versionId: string
- code: string
- name: string
- type: string
- storageUri: string
- mimeType: string
- sizeBytes: number
- sha256: string
- metadata: Record<string, unknown>
- status: string
- sortOrder: number
- }
-
- export interface ContentDependencyRecord {
- id: string
- targetProjectId: string
- targetVersionId: string
- relationType: string
- required: boolean
- sortOrder: number
- }
-
- export interface ContentDetailRecord {
- project: {
- id: string
- type: string
- code: string
- name: string
- status: string
- currentVersionId: string
- publishedVersionId: string | null
- version: number
- }
- currentVersion: {
- id: string
- projectId: string
- versionNo: number
- versionCode: string
- status: string
- content: Record<string, unknown>
- dependencies: ContentDependencyRecord[]
- assets: ContentAssetRecord[]
- }
- }
-
- interface ApiEnvelope<T> {
- data?: T
- }
-
- export interface ContentApiSession {
- headers: Record<string, string>
- }
-
- export type CleanupOutcome = 'removed' | 'not-found' | 'failed' | 'not-created'
-
- export interface CleanupRecord {
- kind: '模型工程' | '场景工程'
- id: string | null
- code: string
- outcome: CleanupOutcome
- statusCode?: number
- message?: string
- }
-
- const endpoint = (projectId: string) => `/api/tran/v1/content/projects/${encodeURIComponent(projectId)}`
-
- const readData = async <T>(response: Awaited<ReturnType<APIRequestContext['get']>>, operation: string): Promise<T> => {
- if (!response.ok()) throw new Error(`${operation}失败(HTTP ${response.status()})`)
- const body = await response.json() as ApiEnvelope<T>
- if (body.data === undefined) throw new Error(`${operation}失败:响应未包含 data`)
- return body.data
- }
-
- export async function openContentApiSession(request: APIRequestContext): Promise<ContentApiSession> {
- const credentials = adminCredentials()
- const response = await request.post('/api/auth/v1/auth/login', {
- data: {
- username: credentials.username,
- password: credentials.password,
- roleCode: 'admin',
- rememberMe: false,
- },
- })
- const body = await readData<{ accessToken?: string }>(response, 'E2E API 登录')
- if (!body.accessToken) throw new Error('E2E API 登录失败:响应未返回访问令牌')
- return { headers: { Authorization: `Bearer ${body.accessToken}` } }
- }
-
- export async function closeContentApiSession(
- request: APIRequestContext,
- session: ContentApiSession | null,
- ): Promise<void> {
- if (!session) return
- await request.post('/api/auth/v1/auth/logout', { headers: session.headers }).catch(() => undefined)
- }
-
- export async function readContentDetail(
- request: APIRequestContext,
- session: ContentApiSession,
- projectId: string,
- ): Promise<ContentDetailRecord> {
- const response = await request.get(endpoint(projectId), { headers: session.headers })
- return readData<ContentDetailRecord>(response, '读取内容工程')
- }
-
- export async function removeContentProject(
- request: APIRequestContext,
- session: ContentApiSession,
- kind: CleanupRecord['kind'],
- projectId: string | null,
- code: string,
- ): Promise<CleanupRecord> {
- if (!projectId) return { kind, id: null, code, outcome: 'not-created' }
-
- try {
- const detailResponse = await request.get(endpoint(projectId), { headers: session.headers })
- if (detailResponse.status() === 404) return { kind, id: projectId, code, outcome: 'not-found' }
- if (!detailResponse.ok()) {
- return {
- kind,
- id: projectId,
- code,
- outcome: 'failed',
- statusCode: detailResponse.status(),
- message: '清理前读取工程失败',
- }
- }
-
- const detailBody = await detailResponse.json() as ApiEnvelope<ContentDetailRecord>
- const projectVersion = detailBody.data?.project.version
- if (!Number.isInteger(projectVersion)) {
- return { kind, id: projectId, code, outcome: 'failed', message: '清理前未取得工程乐观锁版本' }
- }
-
- const deleteResponse = await request.delete(endpoint(projectId), {
- headers: session.headers,
- params: { version: String(projectVersion) },
- })
- if (deleteResponse.ok()) return { kind, id: projectId, code, outcome: 'removed' }
- if (deleteResponse.status() === 404) return { kind, id: projectId, code, outcome: 'not-found' }
- return {
- kind,
- id: projectId,
- code,
- outcome: 'failed',
- statusCode: deleteResponse.status(),
- message: '服务端拒绝删除测试工程',
- }
- } catch {
- return { kind, id: projectId, code, outcome: 'failed', message: '清理 API 调用异常' }
- }
- }
|