utils.test.js
1 import { describe, expect, it, vi } from 'vitest'; 2 import { CliError } from '@jackwener/opencli/errors'; 3 import { parseCompanyJobCard, pageFetchJson, resolveCity } from './utils.js'; 4 5 describe('51job resolveCity', () => { 6 it('maps known city names and explicit national scope', () => { 7 expect(resolveCity('杭州')).toBe('080200'); 8 expect(resolveCity('all')).toBe('000000'); 9 expect(resolveCity('000000')).toBe('000000'); 10 }); 11 12 it('rejects unknown non-empty inputs instead of silently widening to 全国', () => { 13 expect(() => resolveCity('杭州z')).toThrowError(CliError); 14 expect(() => resolveCity('杭州z')).toThrow(/Unknown city\/area/); 15 }); 16 }); 17 18 describe('51job pageFetchJson', () => { 19 it('detects WAF challenge HTML and throws ANTI_BOT', async () => { 20 const page = { 21 evaluate: vi.fn().mockResolvedValue({ 22 ok: true, 23 status: 200, 24 text: '<html><title>slider</title></html>', 25 }), 26 }; 27 28 await expect(pageFetchJson(page, 'https://we.51job.com/api/job/search-pc')).rejects.toMatchObject({ 29 code: 'ANTI_BOT', 30 }); 31 }); 32 }); 33 34 describe('51job parseCompanyJobCard', () => { 35 it('parses sensorsdata JSON into a stable row fragment', () => { 36 const row = parseCompanyJobCard({ 37 href: 'https://jobs.51job.com/shanghai/123456789.html', 38 sensorsdata: JSON.stringify({ 39 jobId: '123456789', 40 jobTitle: 'Senior Engineer', 41 jobSalary: '20-30K', 42 jobArea: '上海', 43 jobYear: '3-5年', 44 jobDegree: '本科', 45 funcType: '后端开发', 46 jobTime: '04-22', 47 }), 48 }); 49 50 expect(row).toEqual({ 51 jobId: '123456789', 52 title: 'Senior Engineer', 53 salary: '20-30K', 54 city: '上海', 55 workYear: '3-5年', 56 degree: '本科', 57 funcType: '后端开发', 58 issueDate: '04-22', 59 url: 'https://jobs.51job.com/shanghai/123456789.html', 60 }); 61 }); 62 63 it('returns null on malformed sensorsdata', () => { 64 expect(parseCompanyJobCard({ 65 href: 'https://jobs.51job.com/shanghai/123456789.html', 66 sensorsdata: '{bad json}', 67 })).toBeNull(); 68 }); 69 });