feat: add Husky hooks and fix provider tutorial UI/logic
- Add Husky pre-commit and pre-push hooks for linting, type checking, and build validation - Fix visual hierarchy bug in the provider onboarding tutorial - Remove feedback modal - Move MinIO bucket creation logic to before app startup - Wire MiniMax audio through voice generation pipeline - Fix scene insertion issues - Fix portal tutorial modal and harden panel variant task flow
This commit is contained in:
72
tests/unit/components/llm-stage-stream-card-error.test.ts
Normal file
72
tests/unit/components/llm-stage-stream-card-error.test.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import * as React from 'react'
|
||||
import { createElement } from 'react'
|
||||
import type { ComponentProps, ReactElement } from 'react'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { renderToStaticMarkup } from 'react-dom/server'
|
||||
import { NextIntlClientProvider } from 'next-intl'
|
||||
import type { AbstractIntlMessages } from 'next-intl'
|
||||
import LLMStageStreamCard from '@/components/llm-console/LLMStageStreamCard'
|
||||
|
||||
const messages = {
|
||||
progress: {
|
||||
status: {
|
||||
completed: '已完成',
|
||||
failed: '失败',
|
||||
processing: '进行中',
|
||||
queued: '排队中',
|
||||
pending: '未开始',
|
||||
},
|
||||
stageCard: {
|
||||
stage: '阶段',
|
||||
realtimeStream: '实时流',
|
||||
currentStage: '当前阶段',
|
||||
outputTitle: 'AI 实时输出 · {stage}',
|
||||
waitingModelOutput: '等待模型输出...',
|
||||
reasoningNotProvided: '该步骤未返回思考过程',
|
||||
},
|
||||
runtime: {
|
||||
llm: {
|
||||
processing: '模型处理中...',
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const
|
||||
|
||||
const renderWithIntl = (node: ReactElement) => {
|
||||
const providerProps: ComponentProps<typeof NextIntlClientProvider> = {
|
||||
locale: 'zh',
|
||||
messages: messages as unknown as AbstractIntlMessages,
|
||||
timeZone: 'Asia/Shanghai',
|
||||
children: node,
|
||||
}
|
||||
|
||||
return renderToStaticMarkup(
|
||||
createElement(NextIntlClientProvider, providerProps),
|
||||
)
|
||||
}
|
||||
|
||||
describe('LLMStageStreamCard error rendering', () => {
|
||||
it('renders the error without any feedback action entry', () => {
|
||||
Reflect.set(globalThis, 'React', React)
|
||||
const html = renderWithIntl(
|
||||
createElement(LLMStageStreamCard, {
|
||||
title: '内容到剧本',
|
||||
stages: [{
|
||||
id: 'story_to_script',
|
||||
title: '内容到剧本',
|
||||
status: 'failed',
|
||||
progress: 0,
|
||||
}],
|
||||
activeStageId: 'story_to_script',
|
||||
outputText: '',
|
||||
errorMessage: 'Failed to fetch',
|
||||
}),
|
||||
)
|
||||
|
||||
expect(html).toContain('Failed to fetch')
|
||||
expect(html).not.toContain('复制错误详情')
|
||||
expect(html).not.toContain('打开问题反馈表单')
|
||||
expect(html).not.toContain('Copy error detail')
|
||||
expect(html).not.toContain('Open feedback form')
|
||||
})
|
||||
})
|
||||
115
tests/unit/components/navbar-download-logs.test.ts
Normal file
115
tests/unit/components/navbar-download-logs.test.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import * as React from 'react'
|
||||
import { createElement } from 'react'
|
||||
import type { ComponentProps, ReactElement } from 'react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { renderToStaticMarkup } from 'react-dom/server'
|
||||
import { NextIntlClientProvider } from 'next-intl'
|
||||
import type { AbstractIntlMessages } from 'next-intl'
|
||||
import Navbar from '@/components/Navbar'
|
||||
|
||||
const useSessionMock = vi.fn()
|
||||
|
||||
vi.mock('next-auth/react', () => ({
|
||||
useSession: () => useSessionMock(),
|
||||
}))
|
||||
|
||||
vi.mock('next/image', () => ({
|
||||
default: ({ alt, ...props }: { alt: string } & Record<string, unknown>) => createElement('img', { alt, ...props }),
|
||||
}))
|
||||
|
||||
vi.mock('@/components/LanguageSwitcher', () => ({
|
||||
default: () => createElement('div', null, 'LanguageSwitcher'),
|
||||
}))
|
||||
|
||||
vi.mock('@/hooks/common/useGithubReleaseUpdate', () => ({
|
||||
useGithubReleaseUpdate: () => ({
|
||||
currentVersion: '0.3.0',
|
||||
update: null,
|
||||
shouldPulse: false,
|
||||
showModal: false,
|
||||
openModal: () => undefined,
|
||||
dismissCurrentUpdate: () => undefined,
|
||||
checkNow: async () => undefined,
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/i18n/navigation', () => ({
|
||||
Link: ({
|
||||
href,
|
||||
children,
|
||||
...props
|
||||
}: {
|
||||
href: string | { pathname: string }
|
||||
children: React.ReactNode
|
||||
} & Record<string, unknown>) => {
|
||||
const resolvedHref = typeof href === 'string' ? href : href.pathname
|
||||
return createElement('a', { href: resolvedHref, ...props }, children)
|
||||
},
|
||||
}))
|
||||
|
||||
const messages = {
|
||||
nav: {
|
||||
workspace: '工作区',
|
||||
assetHub: '资产中心',
|
||||
profile: '设置中心',
|
||||
downloadLogs: '下载日志',
|
||||
signin: '登录',
|
||||
signup: '注册',
|
||||
},
|
||||
common: {
|
||||
appName: 'waoowaoo',
|
||||
betaVersion: 'Beta v{version}',
|
||||
updateNotice: {
|
||||
openDialog: '打开更新弹窗',
|
||||
updateTag: '更新',
|
||||
checkUpdate: '检查更新',
|
||||
upToDate: '已是最新版本',
|
||||
},
|
||||
},
|
||||
} as const
|
||||
|
||||
const renderWithIntl = (node: ReactElement) => {
|
||||
const providerProps: ComponentProps<typeof NextIntlClientProvider> = {
|
||||
locale: 'zh',
|
||||
messages: messages as unknown as AbstractIntlMessages,
|
||||
timeZone: 'Asia/Shanghai',
|
||||
children: node,
|
||||
}
|
||||
|
||||
return renderToStaticMarkup(
|
||||
createElement(NextIntlClientProvider, providerProps),
|
||||
)
|
||||
}
|
||||
|
||||
describe('Navbar download logs entry', () => {
|
||||
beforeEach(() => {
|
||||
useSessionMock.mockReset()
|
||||
})
|
||||
|
||||
it('renders the download logs entry on the far-right action group for signed-in users', () => {
|
||||
Reflect.set(globalThis, 'React', React)
|
||||
useSessionMock.mockReturnValue({
|
||||
data: { user: { name: 'Earth' } },
|
||||
status: 'authenticated',
|
||||
})
|
||||
|
||||
const html = renderWithIntl(createElement(Navbar))
|
||||
|
||||
expect(html).toContain('下载日志')
|
||||
expect(html).toContain('href="/api/admin/download-logs"')
|
||||
expect(html).toContain('download=""')
|
||||
})
|
||||
|
||||
it('does not render the download logs entry for signed-out users', () => {
|
||||
Reflect.set(globalThis, 'React', React)
|
||||
useSessionMock.mockReturnValue({
|
||||
data: null,
|
||||
status: 'unauthenticated',
|
||||
})
|
||||
|
||||
const html = renderWithIntl(createElement(Navbar))
|
||||
|
||||
expect(html).not.toContain('下载日志')
|
||||
expect(html).not.toContain('/api/admin/download-logs')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user