/** * Extraction Quality Tests * * Tests real-world AI response patterns to verify content surfacing. * Each test simulates a user query + AI response and checks that * the right content types are extracted with correct data. */ import { describe, it, expect } from 'vitest' import { extractAllFilms, extractAllSongs, extractAllPodcasts, extractAllBooks, extractAllTVSeries, extractAllPlaces, extractAllImages, extractCodeBlocks, extractApps, } from '@/composables/contentExtraction' import { extractMagazineSections, extractMarkdownLinks, extractBoldDomainLinks, extractBareDomainLinks, } from '@/composables/contentExtraction' import { isBookQuery, isBookLikeResponse, isTVQuery, isPlaceQuery, isPlaceLikeResponse, isMusicQuery, isCodeQuery, isCodeLikeResponse, isNewsQuery, isNewsLikeResponse, isWebsitesQuery, isAppQuery, isNostrQuery, isNostrLikeResponse, isAppLikeResponse, isImageQuery, filterTabsByContext, preferredFirstTab, } from '@/composables/contentFiltering' // ─── Helper: simulate full pipeline ───────────────────────────── function extractAll(text: string, userQuery: string) { const films = extractAllFilms(text) const songs = extractAllSongs(text, userQuery) const podcasts = extractAllPodcasts(text) const books = extractAllBooks(text, userQuery) const tvSeries = extractAllTVSeries(text, userQuery) const images = extractAllImages(text, userQuery) const places = extractAllPlaces(text, userQuery) const codeBlocks = extractCodeBlocks(text) const apps = extractApps(text, userQuery) return { films, songs, podcasts, books, tvSeries, images, places, codeBlocks, apps } } // ═══════════════════════════════════════════════════════════════════ // BOOKS — pattern-based extraction // ═══════════════════════════════════════════════════════════════════ describe('Books: pattern extraction from AI responses', () => { it('extracts books from "Title by Author" format', () => { const text = `Here are some essential Bitcoin books: The Bitcoin Standard by Saifedean Ammous is a great starting point. It covers the history of money and why Bitcoin matters. You might also enjoy Mastering Bitcoin by Andreas Antonopoulos for the technical side.` const books = extractAllBooks(text, 'recommend bitcoin books') expect(books.length).toBeGreaterThanOrEqual(2) expect(books.some(b => b.title.includes('Bitcoin Standard'))).toBe(true) expect(books.some(b => b.title.includes('Mastering Bitcoin'))).toBe(true) }) it('extracts books from numbered list with bold and "by"', () => { const text = `Top books on money: 1. **The Bitcoin Standard** by Saifedean Ammous 2. **The Fiat Standard** by Saifedean Ammous 3. **Broken Money** by Lyn Alden 4. **The Price of Tomorrow** by Jeff Booth` const books = extractAllBooks(text, 'books about money') expect(books.length).toBeGreaterThanOrEqual(4) }) it('extracts books from em-dash format', () => { const text = `Essential reads: - The Sovereign Individual — James Dale Davidson (1997) - The Bitcoin Standard — Saifedean Ammous (2018) - Broken Money — Lyn Alden (2023)` const books = extractAllBooks(text, 'book recommendations') expect(books.length).toBeGreaterThanOrEqual(2) }) it('single "by Author" triggers isBookLikeResponse', () => { const text = 'I highly recommend The Bitcoin Standard by Saifedean Ammous. It is an excellent book on monetary theory.' expect(isBookLikeResponse(text)).toBe(true) }) it('isBookQuery matches common book queries', () => { expect(isBookQuery('best books about bitcoin')).toBe(true) expect(isBookQuery('what should I read')).toBe(true) expect(isBookQuery('recommend me a novel')).toBe(true) expect(isBookQuery('any good nonfiction books')).toBe(true) }) it('does not extract books from film responses', () => { const text = '[[film_ext:Inception|2010|Christopher Nolan]] is great. Directed by Christopher Nolan.' const books = extractAllBooks(text, 'what is inception') expect(books).toHaveLength(0) }) }) // ═══════════════════════════════════════════════════════════════════ // TV SERIES — pattern-based extraction // ═══════════════════════════════════════════════════════════════════ describe('TV Series: pattern extraction from AI responses', () => { it('extracts TV shows from numbered list with years', () => { const text = `Best TV dramas of all time: 1. **Breaking Bad** (2008–2013) 2. **The Wire** (2002–2008) 3. **The Sopranos** (1999–2007) 4. **Better Call Saul** (2015–2022)` const series = extractAllTVSeries(text, 'best tv shows') expect(series.length).toBeGreaterThanOrEqual(4) expect(series.some(s => s.title.includes('Breaking Bad'))).toBe(true) }) it('extracts shows with "N seasons" format', () => { const text = `Some great binge watches: **Breaking Bad** — 5 seasons of incredible storytelling **Better Call Saul** — 6 seasons, a worthy prequel` const series = extractAllTVSeries(text, 'what should I binge') expect(series.length).toBeGreaterThanOrEqual(2) }) it('isTVLikeResponse triggers with single season mention', () => { const text = 'Breaking Bad ran for 5 seasons on AMC and is widely considered one of the best TV dramas ever made.' expect(isTVQuery('best tv shows')).toBe(true) // Should pass with just 1 "season" mention now const hasKeyword = /\b(season|episodes?|showrunner|streaming|renewed|cancelled|premiere|network|HBO|Netflix|AMC)\b/i.test(text) expect(hasKeyword).toBe(true) }) it('does not extract TV from non-TV contexts', () => { const text = 'Bitcoin has seen a new season of adoption. The network grows stronger.' const series = extractAllTVSeries(text, 'what is bitcoin') expect(series).toHaveLength(0) }) }) // ═══════════════════════════════════════════════════════════════════ // PLACES — pattern-based extraction // ═══════════════════════════════════════════════════════════════════ describe('Places: pattern extraction from AI responses', () => { it('extracts places with explicit type words', () => { const text = `Best pizza in New York: 1. **Joe's Pizza** — classic New York pizza joint since 1975 2. **Di Fara Pizza** — legendary Brooklyn pizzeria` const places = extractAllPlaces(text, 'best pizza in new york') expect(places.length).toBeGreaterThanOrEqual(1) }) it('extracts places from bold + description without type word (place query)', () => { const text = `Great dinner spots in Austin: 1. **Franklin Barbecue** — World-famous brisket, expect a long line but worth every minute 2. **Uchi** — Innovative Japanese cuisine with a Texas twist 3. **Launderette** — New American comfort food in a converted laundromat` const places = extractAllPlaces(text, 'where to eat in austin') expect(places.length).toBeGreaterThanOrEqual(3) }) it('isPlaceQuery matches food/restaurant queries', () => { expect(isPlaceQuery('best restaurants in london')).toBe(true) expect(isPlaceQuery('where to eat in tokyo')).toBe(true) expect(isPlaceQuery('good brunch spots')).toBe(true) expect(isPlaceQuery('I am hungry')).toBe(true) }) it('does not extract places from non-place contexts', () => { const text = '**Bitcoin** — A peer-to-peer electronic cash system' const places = extractAllPlaces(text, 'what is bitcoin') expect(places).toHaveLength(0) }) }) // ═══════════════════════════════════════════════════════════════════ // SONGS — coexistence with other content types // ═══════════════════════════════════════════════════════════════════ describe('Songs: coexistence with other content', () => { it('returns explicit song tags even when film tags present', () => { const text = `Great movie with an amazing soundtrack: [[film_ext:Guardians of the Galaxy|2014|James Gunn]] Featured songs: [[song_ext:Hooked on a Feeling|Blue Swede|1974]] [[song_ext:Come and Get Your Love|Redbone|1974]]` const songs = extractAllSongs(text, 'guardians of the galaxy soundtrack') expect(songs.length).toBeGreaterThanOrEqual(2) }) it('returns explicit song tags even when book tags present', () => { const text = `[[book_ext:Norwegian Wood|Haruki Murakami|1987]] The title references the Beatles song: [[song_ext:Norwegian Wood|The Beatles|1965]]` const songs = extractAllSongs(text, 'tell me about norwegian wood') expect(songs.length).toBeGreaterThanOrEqual(1) expect(songs[0].title).toBe('Norwegian Wood') }) it('skips pattern-based songs when film tags present (no explicit song tags)', () => { const text = `[[film_ext:Inception|2010|Christopher Nolan]] Great film. The music by Hans Zimmer is amazing — "Time" is iconic.` const songs = extractAllSongs(text, 'tell me about inception') expect(songs).toHaveLength(0) }) it('extracts songs for music queries', () => { const text = `Here are some great rock songs: "Bohemian Rhapsody" by Queen is a masterpiece. "Stairway to Heaven" by Led Zeppelin is another classic.` const songs = extractAllSongs(text, 'best rock songs') expect(songs.length).toBeGreaterThanOrEqual(1) }) }) // ═══════════════════════════════════════════════════════════════════ // CODE BLOCKS — extraction and classification // ═══════════════════════════════════════════════════════════════════ describe('Code blocks: extraction and classification', () => { it('extracts fenced code blocks with language', () => { const text = `Here's a simple function: \`\`\`typescript function greet(name: string): string { return \`Hello, \${name}!\` } \`\`\` And here's the Python version: \`\`\`python def greet(name: str) -> str: return f"Hello, {name}!" \`\`\` ` const blocks = extractCodeBlocks(text) expect(blocks).toHaveLength(2) expect(blocks[0].language).toBe('typescript') expect(blocks[1].language).toBe('python') expect(blocks[0].code).toContain('function greet') }) it('extracts code blocks without language specifier', () => { const text = `Run this command: \`\`\` npm install \`\`\` ` const blocks = extractCodeBlocks(text) expect(blocks).toHaveLength(1) expect(blocks[0].language).toBe('text') }) it('extracts label from preceding heading', () => { const text = `**Setup Script** \`\`\`bash #!/bin/bash echo "Setting up..." \`\`\` ` const blocks = extractCodeBlocks(text) expect(blocks).toHaveLength(1) expect(blocks[0].label).toBe('Setup Script') }) it('isCodeQuery matches programming queries', () => { expect(isCodeQuery('write me a function to sort an array')).toBe(true) expect(isCodeQuery('how to implement binary search in python')).toBe(true) expect(isCodeQuery('debug this javascript error')).toBe(true) expect(isCodeQuery('best typescript libraries')).toBe(true) }) it('isCodeQuery does not match non-code queries', () => { expect(isCodeQuery('best movies of 2024')).toBe(false) expect(isCodeQuery('recommend restaurants in paris')).toBe(false) }) it('isCodeLikeResponse triggers with 3+ code blocks', () => { const text = '```js\na\n```\n```py\nb\n```\n```go\nc\n```' expect(isCodeLikeResponse(text)).toBe(true) }) it('isCodeLikeResponse does not trigger with 1-2 blocks', () => { const text = '```js\na\n```\nSome text\n```py\nb\n```' expect(isCodeLikeResponse(text)).toBe(false) }) }) // ═══════════════════════════════════════════════════════════════════ // IMAGES — threshold behavior // ═══════════════════════════════════════════════════════════════════ describe('Images: threshold and alt text', () => { it('returns single image for image queries', () => { const text = '' const images = extractAllImages(text, 'show me a sunset image') expect(images).toHaveLength(1) }) it('returns single image with meaningful alt text', () => { const text = '' const images = extractAllImages(text, 'bitcoin price') expect(images).toHaveLength(1) }) it('skips single image without alt text for non-image query', () => { const text = 'https://example.com/random.jpg' const images = extractAllImages(text, 'what is bitcoin') expect(images).toHaveLength(0) }) it('returns 2+ images for any query', () => { const text = 'https://example.com/a.jpg https://example.com/b.png' const images = extractAllImages(text, 'what is bitcoin') expect(images).toHaveLength(2) }) }) // ═══════════════════════════════════════════════════════════════════ // TAB FILTERING — comprehensive routing // ═══════════════════════════════════════════════════════════════════ describe('Tab filtering: correct tabs surfaced', () => { it('surfaces book tab for book query with books', () => { const tabs = filterTabsByContext('best bitcoin books', false, false, false, true, false, false, false, false, false, false, false, false, false) expect(tabs).toContain('book') }) it('surfaces code tab for code query with code', () => { const tabs = filterTabsByContext('write a typescript function', false, false, false, false, false, false, false, false, false, false, false, false, true) expect(tabs).toContain('code') expect(tabs[0]).toBe('code') // should be first }) it('surfaces multiple tabs when multiple content types present', () => { const tabs = filterTabsByContext('movies and music', true, true, false, false, false, false, false, false, false, false, false, false, false) expect(tabs).toContain('film') expect(tabs).toContain('song') }) it('surfaces place tab for restaurant query', () => { const tabs = filterTabsByContext('best restaurants in london', false, false, false, false, false, false, true, false, false, false, false, false, false) expect(tabs).toContain('place') expect(tabs[0]).toBe('place') }) it('surfaces TV tab for TV query', () => { const tabs = filterTabsByContext('best tv shows to binge', false, false, false, false, true, false, false, false, false, false, false, false, false) expect(tabs).toContain('tvshow') }) }) // ═══════════════════════════════════════════════════════════════════ // FULL PIPELINE — realistic AI responses // ═══════════════════════════════════════════════════════════════════ describe('Full pipeline: realistic AI responses', () => { it('book recommendation response', () => { const query = 'recommend some books about bitcoin and economics' const response = `Here are my top recommendations: 1. **The Bitcoin Standard** by Saifedean Ammous — The definitive work on why Bitcoin matters for sound money. 2. **Broken Money** by Lyn Alden — A thorough analysis of the monetary system and how Bitcoin fits in. 3. **The Fiat Standard** by Saifedean Ammous — The sequel exploring the fiat monetary system. 4. **The Price of Tomorrow** by Jeff Booth — How deflation will shape the future economy. 5. **Mastering Bitcoin** by Andreas Antonopoulos — Technical deep-dive into how Bitcoin works. Each of these books offers a unique perspective on money, technology, and economics.` const result = extractAll(response, query) expect(result.books.length).toBeGreaterThanOrEqual(4) expect(result.films).toHaveLength(0) expect(result.songs).toHaveLength(0) }) it('restaurant recommendation response', () => { const query = 'best sushi in tokyo' const response = `Here are Tokyo's finest sushi restaurants: 1. **Sukiyabashi Jiro** — The legendary 3-Michelin-star omakase experience in Ginza 2. **Sushi Saito** — Another 3-star establishment known for exquisite nigiri 3. **Sushi Yoshitake** — Intimate counter seating with seasonal specialties 4. **Kyubey** — Classic Ginza sushi since 1935, welcoming to tourists` const result = extractAll(response, query) expect(result.places.length).toBeGreaterThanOrEqual(3) expect(result.books).toHaveLength(0) }) it('coding response with multiple code blocks', () => { const query = 'implement binary search in typescript' const response = `Here's a binary search implementation: **Iterative approach** \`\`\`typescript function binarySearch(arr: number[], target: number): number { let left = 0 let right = arr.length - 1 while (left <= right) { const mid = Math.floor((left + right) / 2) if (arr[mid] === target) return mid if (arr[mid] < target) left = mid + 1 else right = mid - 1 } return -1 } \`\`\` **Recursive approach** \`\`\`typescript function binarySearchRecursive(arr: number[], target: number, left = 0, right = arr.length - 1): number { if (left > right) return -1 const mid = Math.floor((left + right) / 2) if (arr[mid] === target) return mid if (arr[mid] < target) return binarySearchRecursive(arr, target, mid + 1, right) return binarySearchRecursive(arr, target, left, mid - 1) } \`\`\` **Usage** \`\`\`typescript const arr = [1, 3, 5, 7, 9, 11] console.log(binarySearch(arr, 7)) // 3 console.log(binarySearchRecursive(arr, 7)) // 3 \`\`\` ` const result = extractAll(response, query) expect(result.codeBlocks.length).toBeGreaterThanOrEqual(3) expect(result.codeBlocks[0].language).toBe('typescript') expect(result.codeBlocks[0].label).toBe('Iterative approach') expect(isCodeQuery(query)).toBe(true) expect(isCodeLikeResponse(response)).toBe(true) }) it('TV show recommendation response', () => { const query = 'best tv series of all time' const response = `Here are the greatest TV series ever made: 1. **Breaking Bad** (2008–2013) — A chemistry teacher turned drug lord. 5 seasons of perfect television. 2. **The Wire** (2002–2008) — A sprawling look at Baltimore's institutions. 5 seasons. 3. **The Sopranos** (1999–2007) — The show that started the golden age of TV. 6 seasons. 4. **Mad Men** (2007–2015) — 1960s advertising world, beautifully crafted. 7 seasons. 5. **Chernobyl** (2019) — A devastating miniseries about the nuclear disaster.` const result = extractAll(response, query) expect(result.tvSeries.length).toBeGreaterThanOrEqual(4) expect(result.films).toHaveLength(0) }) it('mixed film and song tags coexist', () => { const query = 'tell me about the guardians of the galaxy soundtrack' const response = `Guardians of the Galaxy has one of the best movie soundtracks: [[film_ext:Guardians of the Galaxy|2014|James Gunn]] The "Awesome Mix Vol. 1" features: [[song_ext:Hooked on a Feeling|Blue Swede|1974]] [[song_ext:Come and Get Your Love|Redbone|1974]] [[song_ext:Spirit in the Sky|Norman Greenbaum|1969]] [[song_ext:Escape (The Piña Colada Song)|Rupert Holmes|1979]]` const result = extractAll(response, query) expect(result.films.length).toBeGreaterThanOrEqual(1) expect(result.songs.length).toBeGreaterThanOrEqual(4) }) }) // ═══════════════════════════════════════════════════════════════════ // EDGE CASES — tricky patterns that commonly fail // ═══════════════════════════════════════════════════════════════════ describe('Edge cases: commonly failing patterns', () => { it('does not false-positive books from link markdown', () => { const text = 'Check out [The Bitcoin Standard](https://example.com) by visiting the website.' const books = extractAllBooks(text, 'bitcoin resources') // Should not extract "The Bitcoin Standard" as a book from a markdown link expect(books.every(b => !b.title.includes('Bitcoin Standard'))).toBe(true) }) it('does not extract place names from non-place bold text', () => { const text = `Key Bitcoin concepts: 1. **Proof of Work** — The consensus mechanism that secures Bitcoin 2. **Hash Rate** — The computational power of the network` const places = extractAllPlaces(text, 'explain bitcoin') expect(places).toHaveLength(0) }) it('handles quoted titles in book extraction', () => { const text = '"The Bitcoin Standard" by Saifedean Ammous is essential reading for understanding sound money.' const books = extractAllBooks(text, 'what books should I read about bitcoin') expect(books.length).toBeGreaterThanOrEqual(1) }) it('does not extract TV series from Bitcoin season references', () => { const text = 'This is a new season for Bitcoin adoption. The network hashrate reached new highs.' const series = extractAllTVSeries(text, 'bitcoin news') expect(series).toHaveLength(0) }) it('extracts books from smart/curly quotes', () => { const text = '\u201CThe Bitcoin Standard\u201D by Saifedean Ammous is a must-read.' const books = extractAllBooks(text, 'bitcoin books') expect(books.length).toBeGreaterThanOrEqual(1) expect(books[0].title).toContain('Bitcoin Standard') }) it('extracts places when query mentions pizza', () => { expect(isPlaceQuery('best pizza near me')).toBe(true) expect(isPlaceQuery('pizza recommendations')).toBe(true) }) it('does not false-positive songs from film director "by" pattern', () => { const text = '[[film_ext:Inception|2010|Christopher Nolan]]\n\nInception, directed by Christopher Nolan, is a mind-bending thriller.' const songs = extractAllSongs(text, 'tell me about inception') expect(songs).toHaveLength(0) }) it('handles books with single-word titles in bold', () => { const text = '1. **Sapiens** by Yuval Noah Harari — A brief history of humankind' const books = extractAllBooks(text, 'best nonfiction books') expect(books.length).toBeGreaterThanOrEqual(1) }) it('extracts multiple places from varied formatting', () => { const query = 'where to eat in paris' const text = `Top restaurants in Paris: 1. **Le Comptoir du Panth\u00e9on** \u2014 Classic French bistro with incredible steak frites 2. **Chez Janou** \u2014 Famous for its chocolate mousse, cozy Proven\u00e7al atmosphere 3. **L'As du Fallafel** \u2014 Best falafel in the Marais, always a queue` const places = extractAllPlaces(text, query) expect(places.length).toBeGreaterThanOrEqual(3) }) it('extracts TV shows from "created by" format', () => { const text = `1. **Breaking Bad** (2008\u20132013) \u2014 Created by Vince Gilligan. A chemistry teacher becomes a drug lord. 2. **The Wire** (2002\u20132008) \u2014 Created by David Simon. A deep look at Baltimore institutions.` const series = extractAllTVSeries(text, 'best tv dramas') expect(series.length).toBeGreaterThanOrEqual(2) }) it('does not extract books when response is about films', () => { const text = `Great sci-fi films: 1. **Blade Runner** (1982) \u2014 Directed by Ridley Scott 2. **2001: A Space Odyssey** (1968) \u2014 Directed by Stanley Kubrick` const books = extractAllBooks(text, 'best sci-fi movies') expect(books).toHaveLength(0) }) it('extracts code blocks with varied languages', () => { const text = `**HTML** \`\`\`html