commands.test.js
1 import { describe, expect, it, vi } from 'vitest'; 2 import { getRegistry } from '@jackwener/opencli/registry'; 3 import './search.js'; 4 import './detail.js'; 5 import './reviews.js'; 6 import './cart.js'; 7 import './add-cart.js'; 8 function createPageMock() { 9 return { 10 goto: vi.fn().mockResolvedValue(undefined), 11 evaluate: vi.fn().mockResolvedValue({ title: 'Demo', price: '¥99' }), 12 snapshot: vi.fn().mockResolvedValue(undefined), 13 click: vi.fn().mockResolvedValue(undefined), 14 typeText: vi.fn().mockResolvedValue(undefined), 15 pressKey: vi.fn().mockResolvedValue(undefined), 16 scrollTo: vi.fn().mockResolvedValue(undefined), 17 getFormState: vi.fn().mockResolvedValue({ forms: [], orphanFields: [] }), 18 wait: vi.fn().mockResolvedValue(undefined), 19 tabs: vi.fn().mockResolvedValue([]), 20 selectTab: vi.fn().mockResolvedValue(undefined), 21 networkRequests: vi.fn().mockResolvedValue([]), 22 consoleMessages: vi.fn().mockResolvedValue([]), 23 scroll: vi.fn().mockResolvedValue(undefined), 24 autoScroll: vi.fn().mockResolvedValue(undefined), 25 installInterceptor: vi.fn().mockResolvedValue(undefined), 26 getInterceptedRequests: vi.fn().mockResolvedValue([]), 27 getCookies: vi.fn().mockResolvedValue([]), 28 screenshot: vi.fn().mockResolvedValue(''), 29 waitForCapture: vi.fn().mockResolvedValue(undefined), 30 }; 31 } 32 describe('taobao command registration', () => { 33 it('registers all taobao shopping commands', () => { 34 for (const name of ['search', 'detail', 'reviews', 'cart', 'add-cart']) { 35 expect(getRegistry().get(`taobao/${name}`)).toBeDefined(); 36 } 37 }); 38 }); 39 describe('taobao command safety', () => { 40 it('rejects invalid numeric ids before evaluating page scripts', async () => { 41 const page = createPageMock(); 42 const detail = getRegistry().get('taobao/detail'); 43 await expect(detail.func(page, { id: 'bad-id' })).rejects.toMatchObject({ 44 name: 'ArgumentError', 45 code: 'ARGUMENT', 46 }); 47 expect(page.goto).not.toHaveBeenCalled(); 48 expect(page.evaluate).not.toHaveBeenCalled(); 49 }); 50 it('supports dry-run for add-cart without clicking add-to-cart', async () => { 51 const page = createPageMock(); 52 const addCart = getRegistry().get('taobao/add-cart'); 53 const result = await addCart.func(page, { id: '827563850178', 'dry-run': true, spec: '红色 XL' }); 54 expect(result).toEqual([ 55 expect.objectContaining({ 56 status: 'dry-run', 57 item_id: '827563850178', 58 }), 59 ]); 60 expect(page.goto).toHaveBeenCalledTimes(1); 61 expect(page.goto).toHaveBeenCalledWith('https://www.taobao.com'); 62 expect(page.evaluate).toHaveBeenCalledTimes(2); 63 }); 64 });