feat(web): add vehicle directory views
This commit is contained in:
@@ -196,8 +196,10 @@ test('shows deduplicated Semi vehicle candidates and opens the selected VIN', as
|
||||
|
||||
const view = render(<QueryClientProvider client={client}><MemoryRouter initialEntries={['/vehicles']} future={ROUTER_FUTURE}><Routes><Route path="/vehicles" element={<VehiclePage />} /><Route path="/vehicles/:vin" element={<VehiclePage />} /></Routes></MemoryRouter></QueryClientProvider>);
|
||||
|
||||
expect(await screen.findByRole('heading', { name: '车辆快速定位', level: 5 })).toBeInTheDocument();
|
||||
expect(await screen.findByRole('heading', { name: '查找车辆', level: 5 })).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('查车操作')).toHaveClass('v2-workspace-command-bar', 'v2-vehicle-command-bar');
|
||||
expect(screen.getByRole('tablist', { name: '车辆目录视图' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('tab', { name: '全部车辆' })).toHaveAttribute('aria-selected', 'true');
|
||||
expect(screen.getByRole('heading', { name: '车辆定位', level: 5 }).closest('.semi-card')).toHaveClass('v2-vehicle-query-panel', 'v2-workspace-filter-panel');
|
||||
const input = screen.getByRole('textbox', { name: '搜索车辆' });
|
||||
expect(input).toHaveAttribute('aria-expanded', 'false');
|
||||
@@ -210,10 +212,10 @@ test('shows deduplicated Semi vehicle candidates and opens the selected VIN', as
|
||||
expect(screen.getByRole('heading', { name: '授权车辆目录', level: 5 })).toBeInTheDocument();
|
||||
const directoryMetrics = screen.getByRole('list', { name: '车辆目录摘要' });
|
||||
expect(directoryMetrics.closest('.v2-vehicle-directory-metric-rail')).toHaveClass('semi-card', 'v2-workspace-metric-rail', 'is-queue');
|
||||
expect(Array.from(directoryMetrics.querySelectorAll(':scope > [role="listitem"] > small')).map((item) => item.textContent)).toEqual(['授权车辆', '本页在线', '多源车辆']);
|
||||
expect(Array.from(directoryMetrics.querySelectorAll(':scope > [role="listitem"] > small')).map((item) => item.textContent)).toEqual(['授权车辆', '本页在线', '本页多源']);
|
||||
expect(directoryMetrics.querySelector(':scope > [role="listitem"]:nth-child(1)')).toHaveTextContent('授权车辆2辆账号范围');
|
||||
expect(directoryMetrics.querySelector(':scope > [role="listitem"]:nth-child(2)')).toHaveTextContent('本页在线1辆本页 1 辆');
|
||||
expect(directoryMetrics.querySelector(':scope > [role="listitem"]:nth-child(3)')).toHaveTextContent('多源车辆0辆2+ 协议来源');
|
||||
expect(directoryMetrics.querySelector(':scope > [role="listitem"]:nth-child(3)')).toHaveTextContent('本页多源0辆2+ 协议来源');
|
||||
expect(screen.getByText('第 1 / 1 页').closest('.semi-tag')).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: '刷新车辆目录' })).toHaveClass('semi-button');
|
||||
expect(view.container.querySelector('.v2-vehicle-directory-table.semi-table-wrapper')).toBeInTheDocument();
|
||||
@@ -280,6 +282,8 @@ test('keeps the mobile vehicle directory primary and applies search from a Semi
|
||||
expect(view.container.querySelector('.v2-vehicle-directory-table')).not.toBeInTheDocument();
|
||||
expect(view.container.querySelector('.v2-vehicle-query-panel')).not.toBeInTheDocument();
|
||||
expect(screen.queryByLabelText('查车操作')).not.toBeInTheDocument();
|
||||
expect(screen.getByRole('tablist', { name: '车辆目录视图' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('tab', { name: '全部车辆' })).toHaveAttribute('aria-selected', 'true');
|
||||
const toggle = screen.getByRole('button', { name: '打开车辆搜索:10 辆授权车辆' });
|
||||
expect(toggle).toHaveAttribute('aria-expanded', 'false');
|
||||
fireEvent.click(toggle);
|
||||
@@ -310,6 +314,50 @@ test('keeps the mobile vehicle directory primary and applies search from a Semi
|
||||
expect(screen.getByRole('heading', { name: '授权车辆', level: 5 })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('filters the authorized directory with one consistent Semi view switcher', async () => {
|
||||
const candidate = {
|
||||
vin: initialRealtime.vin,
|
||||
plate: initialRealtime.plate,
|
||||
phone: '',
|
||||
oem: '测试品牌',
|
||||
protocols: ['JT808', 'GB32960'],
|
||||
missingProtocols: [],
|
||||
sourceStatus: [],
|
||||
sourceCount: 2,
|
||||
onlineSourceCount: 2,
|
||||
online: true,
|
||||
lastSeen: initialRealtime.lastSeen,
|
||||
locationText: '广东省广州市',
|
||||
bindingScore: 100,
|
||||
bindingStatus: 'bound'
|
||||
};
|
||||
const vehicles = vi.spyOn(api, 'vehicleCoverage').mockResolvedValue({ items: [candidate], total: 1, limit: 10, offset: 0 });
|
||||
const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
||||
|
||||
render(<QueryClientProvider client={client}><MemoryRouter initialEntries={['/vehicles']} future={ROUTER_FUTURE}><Routes><Route path="/vehicles" element={<VehiclePage />} /></Routes></MemoryRouter></QueryClientProvider>);
|
||||
|
||||
await screen.findByText(initialRealtime.plate);
|
||||
const viewTabs = screen.getByRole('tablist', { name: '车辆目录视图' });
|
||||
expect(viewTabs).toHaveTextContent('全部车辆当前在线当前离线多源车辆');
|
||||
|
||||
fireEvent.click(screen.getByRole('tab', { name: '当前在线' }));
|
||||
await waitFor(() => expect(vehicles.mock.calls[vehicles.mock.calls.length - 1]?.[0]?.get('online')).toBe('online'));
|
||||
expect(screen.getByRole('tab', { name: '当前在线' })).toHaveAttribute('aria-selected', 'true');
|
||||
expect(screen.getByRole('heading', { name: '当前在线', level: 5 })).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByRole('tab', { name: '当前离线' }));
|
||||
await waitFor(() => expect(vehicles.mock.calls[vehicles.mock.calls.length - 1]?.[0]?.get('online')).toBe('offline'));
|
||||
|
||||
fireEvent.click(screen.getByRole('tab', { name: '多源车辆' }));
|
||||
await waitFor(() => expect(vehicles.mock.calls[vehicles.mock.calls.length - 1]?.[0]?.get('coverage')).toBe('multi'));
|
||||
|
||||
fireEvent.click(screen.getByRole('tab', { name: '全部车辆' }));
|
||||
expect(screen.getByRole('tab', { name: '全部车辆' })).toHaveAttribute('aria-selected', 'true');
|
||||
expect(screen.getByRole('heading', { name: '授权车辆目录', level: 5 })).toBeInTheDocument();
|
||||
expect(vehicles.mock.calls[0]?.[0]?.has('online')).toBe(false);
|
||||
expect(vehicles.mock.calls[0]?.[0]?.has('coverage')).toBe(false);
|
||||
});
|
||||
|
||||
test('keeps a partial vehicle query in the directory instead of navigating to an invalid detail route', async () => {
|
||||
const candidate = {
|
||||
vin: initialRealtime.vin,
|
||||
|
||||
Reference in New Issue
Block a user