feat(FEAT-MO-004): 实现指数板块详情分析页
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { createMemoryHistory, createRouter } from 'vue-router';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import MarketDetailPage from './MarketDetailPage.vue';
|
||||
|
||||
const { getIndexDetail, getSectorDetail } = vi.hoisted(() => ({
|
||||
getIndexDetail: vi.fn(),
|
||||
getSectorDetail: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('@/api/market-overview/detail', () => ({
|
||||
default: { getIndexDetail, getSectorDetail },
|
||||
}));
|
||||
|
||||
function createTestRouter() {
|
||||
return createRouter({
|
||||
history: createMemoryHistory(),
|
||||
routes: [
|
||||
{
|
||||
path: '/market-overview/indices/:code',
|
||||
component: MarketDetailPage,
|
||||
meta: { detailType: 'index' },
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
const freshResponse = {
|
||||
snapshotId: '20260818-030000',
|
||||
asOf: '2026-08-18T00:00:00.000Z',
|
||||
source: 'tdx' as const,
|
||||
status: 'fresh' as const,
|
||||
warnings: [],
|
||||
data: {
|
||||
instrument: { code: '000001.SH', name: '上证指数', type: 'index' as const },
|
||||
quote: { price: 3380, changePercent: 0.89, direction: 'up' as const, tradeDate: '20260818' },
|
||||
series: [
|
||||
{
|
||||
time: '20260817',
|
||||
open: 3350,
|
||||
high: 3385,
|
||||
low: 3340,
|
||||
close: 3350,
|
||||
amount: 100,
|
||||
volume: 1000,
|
||||
},
|
||||
{
|
||||
time: '20260818',
|
||||
open: 3370,
|
||||
high: 3400,
|
||||
low: 3360,
|
||||
close: 3380,
|
||||
amount: 120,
|
||||
volume: 1100,
|
||||
},
|
||||
],
|
||||
availableViews: { kline: true, intraday: false },
|
||||
},
|
||||
};
|
||||
|
||||
describe('市场详情页', () => {
|
||||
beforeEach(() => {
|
||||
getIndexDetail.mockReset();
|
||||
getSectorDetail.mockReset();
|
||||
});
|
||||
|
||||
it('按路由加载指数详情并显示上海时间、K 线和分时边界', async () => {
|
||||
getIndexDetail.mockResolvedValue(freshResponse);
|
||||
const router = createTestRouter();
|
||||
await router.push('/market-overview/indices/000001.SH');
|
||||
await router.isReady();
|
||||
|
||||
const wrapper = mount(MarketDetailPage, { global: { plugins: [router] } });
|
||||
await vi.waitFor(() =>
|
||||
expect(getIndexDetail).toHaveBeenCalledWith('000001.SH', { period: '1d', count: 120 }),
|
||||
);
|
||||
await vi.waitFor(() => expect(wrapper.text()).toContain('上证指数'));
|
||||
|
||||
expect(wrapper.text()).toContain('上证指数');
|
||||
expect(wrapper.text()).toContain('2026-08-18 08:00:00');
|
||||
expect(wrapper.text()).toContain('日 K 线');
|
||||
expect(wrapper.text()).toContain('当前数据源未提供分时数据');
|
||||
});
|
||||
|
||||
it('路由代码格式非法时不调用 API 并显示不可用边界', async () => {
|
||||
const router = createTestRouter();
|
||||
await router.push('/market-overview/indices/not-a-code');
|
||||
await router.isReady();
|
||||
|
||||
const wrapper = mount(MarketDetailPage, { global: { plugins: [router] } });
|
||||
|
||||
expect(getIndexDetail).not.toHaveBeenCalled();
|
||||
await vi.waitFor(() => expect(wrapper.text()).toContain('详情代码不可用'));
|
||||
});
|
||||
|
||||
it('TDX 返回 unavailable 时显示 warning 而不是伪造图表', async () => {
|
||||
getIndexDetail.mockResolvedValue({
|
||||
...freshResponse,
|
||||
status: 'unavailable',
|
||||
data: null,
|
||||
warnings: ['指数数据不可用'],
|
||||
});
|
||||
const router = createTestRouter();
|
||||
await router.push('/market-overview/indices/000001.SH');
|
||||
await router.isReady();
|
||||
|
||||
const wrapper = mount(MarketDetailPage, { global: { plugins: [router] } });
|
||||
await vi.waitFor(() => expect(getIndexDetail).toHaveBeenCalled());
|
||||
await vi.waitFor(() => expect(wrapper.text()).toContain('指数数据不可用'));
|
||||
|
||||
expect(wrapper.text()).toContain('指数数据不可用');
|
||||
expect(wrapper.find('svg').exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user