feat(auth): manage vehicle grant intervals

This commit is contained in:
lingniu
2026-07-16 18:01:23 +08:00
parent d6b857240c
commit ddc1bb2d96
6 changed files with 586 additions and 96 deletions

View File

@@ -29,7 +29,8 @@ test('deduplicates vehicle candidates by VIN and renders granted vehicles plate
authProvider: 'local',
menuKeys: ['monitor'],
vehicleVins: ['VIN001'],
vehicles: [{ vin: 'VIN001', plate: '粤A11111' }],
vehicles: [{ vin: 'VIN001', plate: '粤A11111', validFrom: '2026-06-05T00:00:00+08:00', sourceSystem: 'manual', grantedBy: '平台管理员' }],
grantHistory: [{ id: 1, vin: 'VIN001', plate: '粤A11111', validFrom: '2026-06-05T00:00:00+08:00', sourceSystem: 'manual', grantedBy: '平台管理员', revokedBy: '', createdAt: '2026-07-16T00:00:00Z', updatedAt: '2026-07-16T00:00:00Z' }],
createdAt: '2026-07-16T00:00:00Z',
updatedAt: '2026-07-16T00:00:00Z'
}]);
@@ -40,7 +41,7 @@ test('deduplicates vehicle candidates by VIN and renders granted vehicles plate
render(<QueryClientProvider client={client}><UsersPage /></QueryClientProvider>);
fireEvent.click(await screen.findByRole('button', { name: /华东客户/ }));
expect(await screen.findByRole('button', { name: '移除 粤A11111' })).toHaveTextContent('粤A11111VIN001');
expect((await screen.findByRole('button', { name: '移除 粤A11111' })).closest('article')).toHaveTextContent('粤A11111VIN001');
fireEvent.change(screen.getByRole('textbox', { name: '按车牌或 VIN 搜索' }), { target: { value: '粤A22222' } });
await waitFor(() => expect(mocks.vehicleCoverage).toHaveBeenCalled());
@@ -49,5 +50,25 @@ test('deduplicates vehicle candidates by VIN and renders granted vehicles plate
expect((mocks.vehicleCoverage.mock.calls[0][0] as URLSearchParams).get('keyword')).toBe('粤A22222');
fireEvent.click(candidates[0]);
expect(await screen.findByRole('button', { name: '移除 粤A22222' })).toHaveTextContent('粤A22222VIN002');
expect((await screen.findByRole('button', { name: '移除 粤A22222' })).closest('article')).toHaveTextContent('粤A22222VIN002');
});
test('submits per-vehicle authorization interval instead of only a VIN list', async () => {
mocks.adminUsers.mockResolvedValue([{
id: 7, username: 'customer-east', displayName: '华东客户', userType: 'customer', status: 'enabled',
customerRef: '', tenantRef: '', authProvider: 'local', menuKeys: ['statistics'], vehicleVins: ['VIN001'],
vehicles: [{ vin: 'VIN001', plate: '粤A11111', validFrom: '2026-07-16T14:08:18+08:00', sourceSystem: 'manual', grantedBy: '平台管理员' }],
grantHistory: [], createdAt: '2026-07-16T00:00:00Z', updatedAt: '2026-07-16T00:00:00Z'
}]);
mocks.updateCustomerUser.mockResolvedValue({ id: 7 });
const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
render(<QueryClientProvider client={client}><UsersPage /></QueryClientProvider>);
fireEvent.click(await screen.findByRole('button', { name: /华东客户/ }));
fireEvent.change(await screen.findByLabelText('粤A11111 启用时间'), { target: { value: '2026-06-05T00:00' } });
fireEvent.click(screen.getByRole('button', { name: '保存权限' }));
await waitFor(() => expect(mocks.updateCustomerUser).toHaveBeenCalled());
expect(mocks.updateCustomerUser.mock.calls[0][1]).toMatchObject({
vehicleVins: ['VIN001'],
vehicleGrants: [{ vin: 'VIN001', validFrom: '2026-06-05T00:00', validTo: '' }]
});
});