|
@@ -5,11 +5,16 @@ import { vi, describe, it, expect } from 'vitest'
|
|
|
import { CustomerDetailPage } from '../CustomerDetailPage'
|
|
import { CustomerDetailPage } from '../CustomerDetailPage'
|
|
|
|
|
|
|
|
const getCustomerById = vi.fn()
|
|
const getCustomerById = vi.fn()
|
|
|
|
|
+const listCustomerSimulationGallery = vi.fn()
|
|
|
|
|
|
|
|
vi.mock('../../../../services/api/customers', () => ({
|
|
vi.mock('../../../../services/api/customers', () => ({
|
|
|
getCustomerById: (...args: unknown[]) => getCustomerById(...args),
|
|
getCustomerById: (...args: unknown[]) => getCustomerById(...args),
|
|
|
}))
|
|
}))
|
|
|
|
|
|
|
|
|
|
+vi.mock('../../../../services/api/simulations', () => ({
|
|
|
|
|
+ listCustomerSimulationGallery: (...args: unknown[]) => listCustomerSimulationGallery(...args),
|
|
|
|
|
+}))
|
|
|
|
|
+
|
|
|
vi.mock('../../../../shared/pageContext', async () => {
|
|
vi.mock('../../../../shared/pageContext', async () => {
|
|
|
const actual = await vi.importActual<typeof import('../../../../shared/pageContext')>('../../../../shared/pageContext')
|
|
const actual = await vi.importActual<typeof import('../../../../shared/pageContext')>('../../../../shared/pageContext')
|
|
|
return {
|
|
return {
|
|
@@ -40,6 +45,7 @@ vi.mock('../../../../shared/pageContext', async () => {
|
|
|
photos: {
|
|
photos: {
|
|
|
badge: '照片与模拟',
|
|
badge: '照片与模拟',
|
|
|
title: '过往照片和AI发型模拟',
|
|
title: '过往照片和AI发型模拟',
|
|
|
|
|
+ empty: '暂无 AI 发型模拟结果',
|
|
|
items: [
|
|
items: [
|
|
|
{ label: '到店前', title: '到店时记录', alt: '到店时的照片' },
|
|
{ label: '到店前', title: '到店时记录', alt: '到店时的照片' },
|
|
|
{ label: 'AI发型模拟', title: 'AI发型模拟结果', alt: 'AI发型模拟结果' },
|
|
{ label: 'AI发型模拟', title: 'AI发型模拟结果', alt: 'AI发型模拟结果' },
|
|
@@ -84,6 +90,9 @@ describe('CustomerDetailPage', () => {
|
|
|
avatar: 'https://example.com/avatar.png',
|
|
avatar: 'https://example.com/avatar.png',
|
|
|
visitFrequencyLabel: '约 2 个月',
|
|
visitFrequencyLabel: '约 2 个月',
|
|
|
})
|
|
})
|
|
|
|
|
+ listCustomerSimulationGallery.mockResolvedValue({
|
|
|
|
|
+ items: [],
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
render(
|
|
render(
|
|
|
<HelmetProvider>
|
|
<HelmetProvider>
|
|
@@ -106,7 +115,8 @@ describe('CustomerDetailPage', () => {
|
|
|
expect(nextVisitCard).not.toBeNull()
|
|
expect(nextVisitCard).not.toBeNull()
|
|
|
expect(within(nextVisitCard as HTMLElement).queryByText('当前版本暂未开发')).not.toBeInTheDocument()
|
|
expect(within(nextVisitCard as HTMLElement).queryByText('当前版本暂未开发')).not.toBeInTheDocument()
|
|
|
expect(screen.getByRole('button', { name: '发送提醒(未开发)' })).toBeDisabled()
|
|
expect(screen.getByRole('button', { name: '发送提醒(未开发)' })).toBeDisabled()
|
|
|
- expect(screen.getAllByRole('button', { name: 'AI发型模拟' }).length).toBeGreaterThan(0)
|
|
|
|
|
|
|
+ expect(screen.getAllByRole('link', { name: 'AI发型模拟' }).length).toBeGreaterThan(0)
|
|
|
|
|
+ expect(screen.getByText('暂无 AI 发型模拟结果')).toBeInTheDocument()
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
it('renders 未填写 when followContent is empty', async () => {
|
|
it('renders 未填写 when followContent is empty', async () => {
|
|
@@ -119,6 +129,9 @@ describe('CustomerDetailPage', () => {
|
|
|
followContent: '',
|
|
followContent: '',
|
|
|
visitFrequencyLabel: '未记录',
|
|
visitFrequencyLabel: '未记录',
|
|
|
})
|
|
})
|
|
|
|
|
+ listCustomerSimulationGallery.mockResolvedValue({
|
|
|
|
|
+ items: [],
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
render(
|
|
render(
|
|
|
<HelmetProvider>
|
|
<HelmetProvider>
|
|
@@ -136,4 +149,74 @@ describe('CustomerDetailPage', () => {
|
|
|
|
|
|
|
|
expect(screen.getByText('未填写')).toBeInTheDocument()
|
|
expect(screen.getByText('未填写')).toBeInTheDocument()
|
|
|
})
|
|
})
|
|
|
|
|
+
|
|
|
|
|
+ it('navigates to simulation create page with customerId', async () => {
|
|
|
|
|
+ getCustomerById.mockResolvedValue({
|
|
|
|
|
+ id: '5',
|
|
|
|
|
+ name: 'Mika',
|
|
|
|
|
+ phone: '090-1111-2222',
|
|
|
|
|
+ nextFollowDate: '2026-06-30',
|
|
|
|
|
+ recommendVisitDate: '2026-07-10',
|
|
|
|
|
+ followContent: 'follow',
|
|
|
|
|
+ visitFrequencyLabel: '未记录',
|
|
|
|
|
+ })
|
|
|
|
|
+ listCustomerSimulationGallery.mockResolvedValue({
|
|
|
|
|
+ items: [],
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ render(
|
|
|
|
|
+ <HelmetProvider>
|
|
|
|
|
+ <MemoryRouter initialEntries={['/zh/customers/5']}>
|
|
|
|
|
+ <Routes>
|
|
|
|
|
+ <Route path="/:locale/customers/:customerId" element={<CustomerDetailPage />} />
|
|
|
|
|
+ </Routes>
|
|
|
|
|
+ </MemoryRouter>
|
|
|
|
|
+ </HelmetProvider>,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ await waitFor(() => {
|
|
|
|
|
+ expect(screen.getByText('Mika')).toBeInTheDocument()
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ expect(
|
|
|
|
|
+ screen.getAllByRole('link', { name: 'AI发型模拟' })[0],
|
|
|
|
|
+ ).toHaveAttribute('href', '/zh/simulation?customerId=5')
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ it('renders gallery cards and links each image card to simulation detail', async () => {
|
|
|
|
|
+ getCustomerById.mockResolvedValue({
|
|
|
|
|
+ id: '5',
|
|
|
|
|
+ name: 'Mika',
|
|
|
|
|
+ phone: '090-1111-2222',
|
|
|
|
|
+ nextFollowDate: '2026-06-30',
|
|
|
|
|
+ recommendVisitDate: '2026-07-10',
|
|
|
|
|
+ followContent: 'follow',
|
|
|
|
|
+ visitFrequencyLabel: '未记录',
|
|
|
|
|
+ })
|
|
|
|
|
+ listCustomerSimulationGallery.mockResolvedValue({
|
|
|
|
|
+ items: [
|
|
|
|
|
+ {
|
|
|
|
|
+ simulationId: '91',
|
|
|
|
|
+ taskId: 'task-11',
|
|
|
|
|
+ imageUrl: 'https://cdn.example.com/result-1.png',
|
|
|
|
|
+ templateName: 'Layer Bob',
|
|
|
|
|
+ createdAt: '2026-06-28T09:00:00.000Z',
|
|
|
|
|
+ taskStatus: 'SUCCESSES',
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ render(
|
|
|
|
|
+ <HelmetProvider>
|
|
|
|
|
+ <MemoryRouter initialEntries={['/zh/customers/5']}>
|
|
|
|
|
+ <Routes>
|
|
|
|
|
+ <Route path="/:locale/customers/:customerId" element={<CustomerDetailPage />} />
|
|
|
|
|
+ </Routes>
|
|
|
|
|
+ </MemoryRouter>
|
|
|
|
|
+ </HelmetProvider>,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ const card = await screen.findByRole('link', { name: /Layer Bob/i })
|
|
|
|
|
+ expect(card).toHaveAttribute('href', '/zh/simulation/result/91')
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|