import { NfcDeviceEntity } from '../../../src/modules/nfc/entity/device'; import { NfcDeviceService } from '../../../src/modules/nfc/service/device'; import { AdminNfcDeviceController } from '../../../src/modules/nfc/controller/admin/device'; import { CoolCommException } from '@cool-midway/core'; describe('Point 36: NFC 硬件卡片国际物流发货追踪与全生命周期流转 (NFC Fleet Shipping)', () => { let service: NfcDeviceService; let mockRepo: any; let savedDevices: any[]; beforeEach(() => { savedDevices = [ { id: 1, uid: 'UID-NFC-GLOBAL-001', batchNo: 'BATCH-2026-EU-01', material: 'wood', status: 'unbound', sceneMode: 'business', shippingStatus: 'pending', }, ]; mockRepo = { findOneBy: jest.fn(async (query: { id: number }) => { return savedDevices.find(d => d.id === query.id) || null; }), save: jest.fn(async (device: any) => { const index = savedDevices.findIndex(d => d.id === device.id); if (index >= 0) { savedDevices[index] = { ...savedDevices[index], ...device }; return savedDevices[index]; } savedDevices.push(device); return device; }), }; service = new NfcDeviceService(); (service as any).nfcDeviceEntity = mockRepo; }); describe('1. 实体字段契约与默认状态', () => { it('实体实例应包含 shippingStatus, carrier, trackingNumber 等物流追踪属性', () => { const entity = new NfcDeviceEntity(); entity.shippingStatus = 'pending'; entity.carrier = 'dhl'; entity.trackingNumber = 'DHL-987654321'; expect(entity.shippingStatus).toBe('pending'); expect(entity.carrier).toBe('dhl'); expect(entity.trackingNumber).toBe('DHL-987654321'); }); }); describe('2. markShipped 业务逻辑与防呆校验', () => { it('正常标记发货时,更新承运商、运单号与发货状态', async () => { const result = await service.markShipped(1, 'dhl', 'DHL-987654321'); expect(result.shippingStatus).toBe('shipped'); expect(result.carrier).toBe('dhl'); expect(result.trackingNumber).toBe('DHL-987654321'); expect(result.shippedAt).toBeDefined(); }); it('设备不存在时应抛出异常', async () => { await expect(service.markShipped(999, 'fedex', 'FX-123')).rejects.toThrow( CoolCommException ); }); it('缺少运单号时应抛出参数异常', async () => { await expect(service.markShipped(1, 'dhl', '')).rejects.toThrow( '缺少物流运单号' ); }); }); describe('3. 控制器 ship API 存在性与契约', () => { it('AdminNfcDeviceController 必须提供 ship 路由方法', () => { const controller = new AdminNfcDeviceController(); expect(typeof (controller as any).ship).toBe('function'); }); }); });