116 lines
3.5 KiB
TypeScript
116 lines
3.5 KiB
TypeScript
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);
|
|
});
|
|
});
|