update product list page
This commit is contained in:
@@ -49,7 +49,7 @@ const mockProducts: ProductRecord[] = [
|
||||
company_id: 2,
|
||||
platform_id: 1,
|
||||
store_id: 2,
|
||||
status_id: 0,
|
||||
status_id: 3,
|
||||
platform_item_id: 'TB002',
|
||||
platform_model_id: null,
|
||||
name: '测试商品B - 这是一个非常长的商品名称用于测试省略号效果',
|
||||
@@ -340,7 +340,8 @@ describe('ProductsPage', () => {
|
||||
|
||||
const tags = wrapper.findAll('.ant-tag')
|
||||
const tagTexts = tags.map((t) => t.text())
|
||||
expect(tagTexts).toContain('上架')
|
||||
// mockProducts: status_id=1 → 草稿, status_id=3 → 下架
|
||||
expect(tagTexts).toContain('草稿')
|
||||
expect(tagTexts).toContain('下架')
|
||||
})
|
||||
|
||||
@@ -451,6 +452,106 @@ describe('ProductsPage', () => {
|
||||
expect(drawerHtml).toContain('tb_001')
|
||||
})
|
||||
|
||||
describe('status mapping coverage', () => {
|
||||
const statusExpectations: Array<{ id: number; text: string; color: string }> = [
|
||||
{ id: 1, text: '草稿', color: 'default' },
|
||||
{ id: 2, text: '在售', color: 'green' },
|
||||
{ id: 3, text: '下架', color: 'orange' },
|
||||
{ id: 4, text: '封禁', color: 'red' },
|
||||
{ id: 5, text: '审核中', color: 'blue' },
|
||||
{ id: 6, text: '卖家删除', color: 'volcano' },
|
||||
{ id: 7, text: '平台删除', color: 'volcano' },
|
||||
]
|
||||
|
||||
it.each(statusExpectations)(
|
||||
'renders status_id=$id as "$text"',
|
||||
async ({ id, text }) => {
|
||||
const { api } = await import('@/utils/request')
|
||||
const singleProduct = { ...mockProducts[0], id: 100 + id, status_id: id }
|
||||
vi.mocked(api.get).mockImplementation((url: string) => {
|
||||
if (url === '/api/v1/products')
|
||||
return Promise.resolve({ items: [singleProduct], total: 1, page: 1, per_page: 15 }) as never
|
||||
if (url === '/api/v1/companies') return Promise.resolve(mockLookupCompanies) as never
|
||||
if (url === '/api/v1/platforms') return Promise.resolve(mockLookupPlatforms) as never
|
||||
if (url === '/api/v1/stores') return Promise.resolve(mockLookupStores) as never
|
||||
return Promise.resolve([]) as never
|
||||
})
|
||||
|
||||
const { default: ProductsPage } = await import('../index.vue')
|
||||
wrapper = mount(ProductsPage, {
|
||||
attachTo: document.body,
|
||||
global: {
|
||||
stubs: {
|
||||
SearchOutlined: { template: '<span />' },
|
||||
ReloadOutlined: { template: '<span />' },
|
||||
EyeOutlined: { template: '<span />' },
|
||||
CascadeFilter: { template: '<div class="cascade-filter-stub" />' },
|
||||
},
|
||||
},
|
||||
})
|
||||
await flushPromises()
|
||||
await nextTick()
|
||||
|
||||
const tags = wrapper.findAll('.ant-tag')
|
||||
const tagTexts = tags.map((t) => t.text())
|
||||
expect(tagTexts).toContain(text)
|
||||
},
|
||||
)
|
||||
|
||||
it('renders fallback for unknown status_id', async () => {
|
||||
const { api } = await import('@/utils/request')
|
||||
const unknownProduct = { ...mockProducts[0], id: 999, status_id: 99 }
|
||||
vi.mocked(api.get).mockImplementation((url: string) => {
|
||||
if (url === '/api/v1/products')
|
||||
return Promise.resolve({ items: [unknownProduct], total: 1, page: 1, per_page: 15 }) as never
|
||||
if (url === '/api/v1/companies') return Promise.resolve(mockLookupCompanies) as never
|
||||
if (url === '/api/v1/platforms') return Promise.resolve(mockLookupPlatforms) as never
|
||||
if (url === '/api/v1/stores') return Promise.resolve(mockLookupStores) as never
|
||||
return Promise.resolve([]) as never
|
||||
})
|
||||
|
||||
const { default: ProductsPage } = await import('../index.vue')
|
||||
wrapper = mount(ProductsPage, {
|
||||
attachTo: document.body,
|
||||
global: {
|
||||
stubs: {
|
||||
SearchOutlined: { template: '<span />' },
|
||||
ReloadOutlined: { template: '<span />' },
|
||||
EyeOutlined: { template: '<span />' },
|
||||
CascadeFilter: { template: '<div class="cascade-filter-stub" />' },
|
||||
},
|
||||
},
|
||||
})
|
||||
await flushPromises()
|
||||
await nextTick()
|
||||
|
||||
const tags = wrapper.findAll('.ant-tag')
|
||||
const tagTexts = tags.map((t) => t.text())
|
||||
expect(tagTexts).toContain('状态 99')
|
||||
})
|
||||
})
|
||||
|
||||
it('renders all 7 status filter options', async () => {
|
||||
await mountPage()
|
||||
|
||||
// Ant Design Vue 渲染 select options 到 body portal,需先打开下拉
|
||||
const selectEl = document.body.querySelector('.ant-select-selector')
|
||||
selectEl?.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }))
|
||||
await flushPromises()
|
||||
await nextTick()
|
||||
|
||||
const optionEls = document.body.querySelectorAll('.ant-select-item-option')
|
||||
const optionTexts = Array.from(optionEls).map((el) => el.textContent?.trim())
|
||||
expect(optionTexts).toContain('草稿')
|
||||
expect(optionTexts).toContain('在售')
|
||||
expect(optionTexts).toContain('下架')
|
||||
expect(optionTexts).toContain('封禁')
|
||||
expect(optionTexts).toContain('审核中')
|
||||
expect(optionTexts).toContain('卖家删除')
|
||||
expect(optionTexts).toContain('平台删除')
|
||||
expect(optionTexts.length).toBe(7)
|
||||
})
|
||||
|
||||
it('shows placeholder when ext/raw is null', async () => {
|
||||
const { api } = await mountPage()
|
||||
vi.mocked(api.get)
|
||||
|
||||
@@ -19,8 +19,13 @@ const rawDetail = ref<RawProductDetail | null>(null)
|
||||
let detailRequestId = 0
|
||||
|
||||
const statusMap: Record<number, { text: string; color: string }> = {
|
||||
1: { text: '上架', color: 'green' },
|
||||
0: { text: '下架', color: 'red' },
|
||||
1: { text: '草稿', color: 'default' },
|
||||
2: { text: '在售', color: 'green' },
|
||||
3: { text: '下架', color: 'orange' },
|
||||
4: { text: '封禁', color: 'red' },
|
||||
5: { text: '审核中', color: 'blue' },
|
||||
6: { text: '卖家删除', color: 'volcano' },
|
||||
7: { text: '平台删除', color: 'volcano' },
|
||||
}
|
||||
|
||||
const columns = [
|
||||
@@ -133,8 +138,13 @@ async function handleViewDetail(record: { id: number }) {
|
||||
allow-clear
|
||||
style="width: 120px"
|
||||
>
|
||||
<a-select-option :value="1">上架</a-select-option>
|
||||
<a-select-option :value="0">下架</a-select-option>
|
||||
<a-select-option :value="1">草稿</a-select-option>
|
||||
<a-select-option :value="2">在售</a-select-option>
|
||||
<a-select-option :value="3">下架</a-select-option>
|
||||
<a-select-option :value="4">封禁</a-select-option>
|
||||
<a-select-option :value="5">审核中</a-select-option>
|
||||
<a-select-option :value="6">卖家删除</a-select-option>
|
||||
<a-select-option :value="7">平台删除</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="商品名称">
|
||||
|
||||
Reference in New Issue
Block a user