import { describe, expect, test } from 'bun:test'; import { diffProfile } from '../src/diff.js'; import type { CanonicalProfile, ScrapedProfile } from '../src/types.js'; const canonical: CanonicalProfile = { name: 'Quinn', tagline: "Don't fall in love!", location: 'Manhattan, NY', age: '24', bio: 'Up-and-coming companion touring the country this year.', phone: '+14244663669', rates: [ { service: 'Incall', duration: '1 hour', price: 1000 }, { service: 'Incall', duration: '2 hours', price: 1800 }, { service: 'Outcall', duration: '1 hour', price: 1200 }, ], tour: [ { city: 'Denver', region: 'CO', startDate: '2026-07-01', endDate: '2026-07-04', status: 'upcoming' }, { city: 'Chicago', region: 'IL', startDate: '2026-08-10', endDate: null, status: 'upcoming' }, ], socials: { onlyfans: 'transquinnftw', twitter: 'transquinnftw' }, verifiedProfiles: [], }; function scraped(over: Partial): ScrapedProfile { return { platform: 'tryst', url: 'https://tryst.link/escort/transquinnftw', fetchedAt: '2026-06-26T00:00:00.000Z', via: 'direct', rates: [], tour: [], socials: {}, images: [], warnings: [], raw: { jsonLdCount: 0, textLength: 0 }, ...over, }; } describe('diffProfile', () => { test('clean match yields zero discrepancies', () => { const s = scraped({ tagline: "Don't fall in love!", phone: '(424) 466-3669', rates: [ { service: 'Incall', duration: '1 hour', price: 1000, raw: '1 hour $1000' }, { service: 'Incall', duration: '2 hours', price: 1800, raw: '2 hours $1800' }, { service: 'Outcall', duration: '1 hour', price: 1200, raw: 'outcall 1 hour $1200' }, ], tour: [ { city: 'Denver', region: 'CO', startDate: '2026-07-01', raw: 'Denver, CO Jul 1' }, { city: 'Chicago', region: 'IL', startDate: '2026-08-10', raw: 'Chicago, IL Aug 10' }, ], socials: { onlyfans: 'transquinnftw', twitter: 'transquinnftw' }, }); const r = diffProfile(canonical, s); expect(r.summary.critical).toBe(0); expect(r.summary.warning).toBe(0); expect(r.discrepancies).toHaveLength(0); }); test('price mismatch is critical', () => { const s = scraped({ rates: [{ service: 'Incall', duration: '1 hour', price: 900, raw: '1 hour $900' }], }); const r = diffProfile(canonical, s, { fields: { rates: true } }); const hit = r.discrepancies.find((d) => d.field === 'rate:incall|60m'); expect(hit?.severity).toBe('critical'); expect(hit?.kind).toBe('mismatch'); expect(hit?.canonical).toBe('$1000'); expect(hit?.scraped).toBe('$900'); }); test('wrong phone is critical', () => { const s = scraped({ phone: '+13105550000' }); const r = diffProfile(canonical, s, { fields: { contact: true } }); const hit = r.discrepancies.find((d) => d.field === 'phone'); expect(hit?.severity).toBe('critical'); }); test('tagline drift is a warning', () => { const s = scraped({ tagline: 'Fall in love with me' }); const r = diffProfile(canonical, s, { fields: { identity: true } }); const hit = r.discrepancies.find((d) => d.field === 'tagline'); expect(hit?.severity).toBe('warning'); }); test('missing canonical rate is a warning when scrape had labels', () => { const s = scraped({ rates: [{ service: 'Incall', duration: '1 hour', price: 1000, raw: '1 hour $1000' }], }); const r = diffProfile(canonical, s, { fields: { rates: true } }); const missing = r.discrepancies.filter((d) => d.kind === 'missing' && d.field.startsWith('rate:')); expect(missing.length).toBeGreaterThanOrEqual(1); expect(missing.every((d) => d.severity === 'warning')).toBe(true); }); test('empty scrape skips rate/tour groups instead of flagging all missing', () => { const s = scraped({ phone: '(424) 466-3669' }); const r = diffProfile(canonical, s); expect(r.summary.skipped).toContain('rates'); expect(r.summary.skipped).toContain('tour'); // No false "missing rate" noise from an empty scrape. expect(r.discrepancies.some((d) => d.field.startsWith('rate:'))).toBe(false); }); test('platform advertises a city not in the tour → info/stale', () => { const s = scraped({ tour: [{ city: 'Miami', region: 'FL', startDate: '2026-09-01', raw: 'Miami, FL Sep 1' }], }); const r = diffProfile(canonical, s, { fields: { tour: true } }); const stale = r.discrepancies.find((d) => d.field === 'tour:extra:miami'); expect(stale?.kind).toBe('stale'); expect(stale?.severity).toBe('info'); }); test('social handle mismatch is a warning', () => { const s = scraped({ socials: { onlyfans: 'someoneelse' } }); const r = diffProfile(canonical, s, { fields: { contact: true } }); const hit = r.discrepancies.find((d) => d.field === 'social:onlyfans'); expect(hit?.severity).toBe('warning'); }); });