From e411cec5450420f10473f4fc4d3f8d6da1598fa4 Mon Sep 17 00:00:00 2001 From: freearhey <7253922+freearhey@users.noreply.github.com> Date: Wed, 30 Apr 2025 03:50:36 +0300 Subject: [PATCH] Update tests --- tests/core/searchEngine.test.js | 340 ++++++++++++++++++++++++++++++ tests/store.test.js | 361 -------------------------------- 2 files changed, 340 insertions(+), 361 deletions(-) create mode 100644 tests/core/searchEngine.test.js delete mode 100644 tests/store.test.js diff --git a/tests/core/searchEngine.test.js b/tests/core/searchEngine.test.js new file mode 100644 index 000000000..17ce43612 --- /dev/null +++ b/tests/core/searchEngine.test.js @@ -0,0 +1,340 @@ +import { ApiClient, DataProcessor, DataLoader, SearchEngine } from '../../src/core' +import { expect, it, describe, beforeEach } from 'vitest' +import AxiosMockAdapter from 'axios-mock-adapter' +import axios from 'axios' +import path from 'path' +import fs from 'fs' + +const searchEngine = new SearchEngine() + +beforeEach(async () => { + const client = new ApiClient() + const processor = new DataProcessor() + const dataLoader = new DataLoader({ client, processor }) + + client.instance = axios.create({ + baseURL: 'https://iptv-org.github.io/api' + }) + + const mockAxios = new AxiosMockAdapter(client.instance) + + mockAxios.onGet(`categories.json`).reply(200, loadJson('categories.json')) + mockAxios.onGet(`countries.json`).reply(200, loadJson('countries.json')) + mockAxios.onGet(`languages.json`).reply(200, loadJson('languages.json')) + mockAxios.onGet(`blocklist.json`).reply(200, loadJson('blocklist.json')) + mockAxios.onGet(`timezones.json`).reply(200, loadJson('timezones.json')) + mockAxios.onGet(`channels.json`).reply(200, loadJson('channels.json')) + mockAxios.onGet(`regions.json`).reply(200, loadJson('regions.json')) + mockAxios.onGet(`streams.json`).reply(200, loadJson('streams.json')) + mockAxios.onGet(`guides.json`).reply(200, loadJson('guides.json')) + mockAxios.onGet(`feeds.json`).reply(200, loadJson('feeds.json')) + mockAxios.onGet(`subdivisions.json`).reply(200, loadJson('subdivisions.json')) + + const data = await dataLoader.load() + const searchableData = data.channels.map(channel => channel.getSearchable()) + + searchEngine.createIndex(searchableData) +}) + +describe('search', () => { + it('returns empty list if there is no such channel', () => { + let results = searchEngine.search('lorem') + + expect(results.count()).toBe(0) + }) + + it('can find channel by name', () => { + let results = searchEngine.search('name:002') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: '002RadioTV.do' + }) + }) + + it('can find channels by multiple words', () => { + let results = searchEngine.search('Xtrema Cartoons') + + expect(results.count()).toBe(2) + expect(results.first()).toMatchObject({ + id: 'XtremaCartoons.ar' + }) + expect(results.all()[1]).toMatchObject({ + id: 'XtremaRetroCartoons.ar' + }) + }) + + it('can search for one of two words', () => { + let results = searchEngine.search('Johannesburg,002') + + expect(results.count()).toBe(2) + expect(results.first()).toMatchObject({ + id: '002RadioTV.do' + }) + expect(results.all()[1]).toMatchObject({ + id: 'FashionTVJohannesburg.fr' + }) + }) + + it('can search for exact word matches', () => { + let results = searchEngine.search('"Xtrema Cartoons"') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'XtremaCartoons.ar' + }) + }) + + it('can find channels by id', () => { + let results = searchEngine.search('id:002RadioTV.do') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: '002RadioTV.do' + }) + }) + + it('can find channels by feed name', () => { + let results = searchEngine.search('Panregional') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: '13MaxTelevision.ar' + }) + }) + + it('can find channels by alternative names', () => { + let results = searchEngine.search('alt_names:التلفزيون') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'TV1.dz' + }) + }) + + it('can find channels by network', () => { + let results = searchEngine.search('network:Hope') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'K11UUD1.as' + }) + }) + + it('can find channels without the owner', () => { + let results = searchEngine.search('owners:^$') + + expect(results.count()).toBe(7) + expect(results.first()).toMatchObject({ + id: '002RadioTV.do' + }) + }) + + it('can find channels by country code', () => { + let results = searchEngine.search('country:DO') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: '002RadioTV.do' + }) + }) + + it('can find channels that are broadcast from the same region', () => { + let results = searchEngine.search('subdivision:AR-W') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: '13MaxTelevision.ar' + }) + }) + + it('can find channels that are broadcast from the same city', () => { + let results = searchEngine.search('city:Corrientes') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: '13MaxTelevision.ar' + }) + }) + + it('can find channels that have the same category', () => { + let results = searchEngine.search('categories:lifestyle') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'FashionTVJohannesburg.fr' + }) + }) + + it('can find channels with website', () => { + let results = searchEngine.search('website:.') + + expect(results.count()).toBe(14) + expect(results.first()).toMatchObject({ + id: '002RadioTV.do' + }) + }) + + it('can find channels marked as NSFW', () => { + let results = searchEngine.search('is_nsfw:true') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'Bizarre.al' + }) + }) + + it('can find closed channels', () => { + let results = searchEngine.search('is_closed:true') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'AynaTV.af' + }) + }) + + it('can find blocked channels', () => { + let results = searchEngine.search('is_blocked:true') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'Bizarre.al' + }) + }) + + it('can find channels by query in lower case', () => { + let results = searchEngine.search('tv2') + + expect(results.count()).toBe(2) + expect(results.first()).toMatchObject({ + id: 'SEN502.us' + }) + expect(results.all()[1]).toMatchObject({ + id: 'CFCNTV2.ca' + }) + }) + + it('can find channel by alternative name after another query', () => { + searchEngine.search('tv2') + let results = searchEngine.search('alt_names:tv2') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'SEN502.us' + }) + }) + + it('can find channels that have streams', () => { + let results = searchEngine.search('streams:>0') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'XtremaCartoons.ar' + }) + }) + + it('can find channels that have guides', () => { + let results = searchEngine.search('guides:>0') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'LaLiganaZap.ao' + }) + }) + + it('can find channel by country name', () => { + let results = searchEngine.search('"dominican republic"') + + expect(results.count()).toBe(3) + expect(results.first()).toMatchObject({ + id: '002RadioTV.do' + }) + }) + + it('can find channel by display name from the guides', () => { + let results = searchEngine.search('La Liga HD') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'LaLiganaZap.ao' + }) + }) + + it('can find channel by stream url', () => { + let results = searchEngine.search( + 'https://stmv6.voxtvhd.com.br/xtremacartoons/xtremacartoons/playlist.m3u8' + ) + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'XtremaCartoons.ar' + }) + }) + + it('can find channels by broadcast area code', () => { + let results = searchEngine.search('broadcast_area:s/AR-W') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: '13MaxTelevision.ar' + }) + }) + + it('can find channel by broadcast location code', () => { + let results = searchEngine.search('eur') + + expect(results.count()).toBe(2) + expect(results.first()).toMatchObject({ + id: 'Bizarre.al' + }) + }) + + it('can find channel by broadcast location name', () => { + let results = searchEngine.search('europe') + + expect(results.count()).toBe(2) + expect(results.first()).toMatchObject({ + id: 'Bizarre.al' + }) + }) + + it('can find channels by exact language code', () => { + let results = searchEngine.search('language:fra') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'SEN502.us' + }) + }) + + it('can find channels by language name', () => { + let results = searchEngine.search('french') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'SEN502.us' + }) + }) + + it('can find channels by video format', () => { + let results = searchEngine.search('video_format:576i') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'Bizarre.al' + }) + }) + + it('can find channels by timezone id', () => { + let results = searchEngine.search('timezone:Europe/London') + + expect(results.count()).toBe(1) + expect(results.first()).toMatchObject({ + id: 'Bizarre.al' + }) + }) +}) + +function loadJson(filepath) { + return JSON.parse(fs.readFileSync(path.resolve('tests/__data__/input/', filepath), 'utf8')) +} diff --git a/tests/store.test.js b/tests/store.test.js deleted file mode 100644 index 7f83ff4aa..000000000 --- a/tests/store.test.js +++ /dev/null @@ -1,361 +0,0 @@ -import { loadData, search, searchResults } from '../src/store' -import { expect, it, describe, beforeEach, afterEach, vi } from 'vitest' -import { get } from 'svelte/store' -import path from 'path' -import fs from 'fs' -import AxiosMockAdapter from 'axios-mock-adapter' -import axios from 'axios' -import { ApiClient, DataProcessor } from '../src/core' - -beforeEach(async () => { - const client = new ApiClient() - const processor = new DataProcessor() - - client.instance = axios.create({ - baseURL: 'https://iptv-org.github.io/api' - }) - - const mockAxios = new AxiosMockAdapter(client.instance) - - mockAxios.onGet(`categories.json`).reply(200, loadJson('categories.json')) - mockAxios.onGet(`countries.json`).reply(200, loadJson('countries.json')) - mockAxios.onGet(`languages.json`).reply(200, loadJson('languages.json')) - mockAxios.onGet(`blocklist.json`).reply(200, loadJson('blocklist.json')) - mockAxios.onGet(`timezones.json`).reply(200, loadJson('timezones.json')) - mockAxios.onGet(`channels.json`).reply(200, loadJson('channels.json')) - mockAxios.onGet(`regions.json`).reply(200, loadJson('regions.json')) - mockAxios.onGet(`streams.json`).reply(200, loadJson('streams.json')) - mockAxios.onGet(`guides.json`).reply(200, loadJson('guides.json')) - mockAxios.onGet(`feeds.json`).reply(200, loadJson('feeds.json')) - mockAxios.onGet(`subdivisions.json`).reply(200, loadJson('subdivisions.json')) - - await loadData({ client, processor }) -}) - -describe('search', () => { - it('return all channels by default', () => { - const results = get(searchResults).all() - expect(results.length).toBe(15) - }) - - it('returns empty list if there is no such channel', () => { - search('lorem') - - const results = get(searchResults).all() - expect(results.length).toBe(0) - }) - - it('can find channel by name', () => { - search('name:002') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: '002RadioTV.do' - }) - }) - - it('can find channels by multiple words', () => { - search('Xtrema Cartoons') - - const results = get(searchResults).all() - expect(results.length).toBe(2) - expect(results[0]).toMatchObject({ - id: 'XtremaCartoons.ar' - }) - expect(results[1]).toMatchObject({ - id: 'XtremaRetroCartoons.ar' - }) - }) - - it('can search for one of two words', () => { - search('Johannesburg,002') - - const results = get(searchResults).all() - expect(results.length).toBe(2) - expect(results[0]).toMatchObject({ - id: '002RadioTV.do' - }) - expect(results[1]).toMatchObject({ - id: 'FashionTVJohannesburg.fr' - }) - }) - - it('can search for exact word matches', () => { - search('"Xtrema Cartoons"') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'XtremaCartoons.ar' - }) - }) - - it('can find channels by id', () => { - search('id:002RadioTV.do') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: '002RadioTV.do' - }) - }) - - it('can find channels by alternative names', () => { - search('alt_names:التلفزيون') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'TV1.dz' - }) - }) - - it('can find channels by network', () => { - search('network:Hope') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'K11UUD1.as' - }) - }) - - it('can find channels without the owner', () => { - search('owners:^$') - - const results = get(searchResults).all() - expect(results.length).toBe(7) - expect(results[0]).toMatchObject({ - id: '002RadioTV.do' - }) - }) - - it('can find channels by country code', () => { - search('country:DO') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: '002RadioTV.do' - }) - }) - - it('can find channels that are broadcast from the same region', () => { - search('subdivision:AR-W') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: '13MaxTelevision.ar' - }) - }) - - it('can find channels that are broadcast from the same city', () => { - search('city:Corrientes') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: '13MaxTelevision.ar' - }) - }) - - it('can find channels that have the same category', () => { - search('categories:lifestyle') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'FashionTVJohannesburg.fr' - }) - }) - - it('can find channels with website', () => { - search('website:.') - - const results = get(searchResults).all() - expect(results.length).toBe(14) - expect(results[0]).toMatchObject({ - id: '002RadioTV.do' - }) - }) - - it('can find channels marked as NSFW', () => { - search('is_nsfw:true') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'Bizarre.al' - }) - }) - - it('can find closed channels', () => { - search('is_closed:true') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'AynaTV.af' - }) - }) - - it('can find blocked channels', () => { - search('is_blocked:true') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'Bizarre.al' - }) - }) - - it('can find channels by query in lower case', () => { - search('tv2') - - const results = get(searchResults).all() - expect(results.length).toBe(2) - expect(results[0]).toMatchObject({ - id: 'SEN502.us' - }) - expect(results[1]).toMatchObject({ - id: 'CFCNTV2.ca' - }) - }) - - it('can find channel by alternative name after another query', () => { - search('tv2') - search('alt_names:tv2') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'SEN502.us' - }) - }) - - it('can find channels that have streams', () => { - search('streams:>0') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'XtremaCartoons.ar' - }) - }) - - it('can find channels that have guides', () => { - search('guides:>0') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'LaLiganaZap.ao' - }) - }) - - it('can find channel by country name', () => { - search('"dominican republic"') - - const results = get(searchResults).all() - expect(results.length).toBe(3) - expect(results[0]).toMatchObject({ - id: '002RadioTV.do' - }) - }) - - it('can find channel by display name from the guides', () => { - search('La Liga HD') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'LaLiganaZap.ao' - }) - }) - - it('can find channel by stream url', () => { - search('https://stmv6.voxtvhd.com.br/xtremacartoons/xtremacartoons/playlist.m3u8') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'XtremaCartoons.ar' - }) - }) - - it('can find channels by broadcast area code', () => { - search('broadcast_area:s/AR-W') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: '13MaxTelevision.ar' - }) - }) - - it('can find channel by broadcast location code', () => { - search('eur') - - const results = get(searchResults).all() - expect(results.length).toBe(2) - expect(results[0]).toMatchObject({ - id: 'Bizarre.al' - }) - }) - - it('can find channel by broadcast location name', () => { - search('europe') - - const results = get(searchResults).all() - expect(results.length).toBe(2) - expect(results[0]).toMatchObject({ - id: 'Bizarre.al' - }) - }) - - it('can find channels by exact language code', () => { - search('language:fra') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'SEN502.us' - }) - }) - - it('can find channels by language name', () => { - search('french') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'SEN502.us' - }) - }) - - it('can find channels by video format', () => { - search('video_format:576i') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'Bizarre.al' - }) - }) - - it('can find channels by timezone id', () => { - search('timezone:Europe/London') - - const results = get(searchResults).all() - expect(results.length).toBe(1) - expect(results[0]).toMatchObject({ - id: 'Bizarre.al' - }) - }) -}) - -function loadJson(filepath) { - return JSON.parse(fs.readFileSync(path.resolve('tests/__data__/input/', filepath), 'utf8')) -}