diff --git a/src/node/consumer/src/lib/helpers/boolean_helpers.ts b/src/node/consumer/src/lib/helpers/boolean_helpers.ts index 1216bbe..a1c79dd 100644 --- a/src/node/consumer/src/lib/helpers/boolean_helpers.ts +++ b/src/node/consumer/src/lib/helpers/boolean_helpers.ts @@ -1,40 +1,20 @@ export const BooleanHelpers = { - parseBool: (value: string | number | undefined, defaultValue: boolean): boolean => { - switch (typeof value) { - case 'string': - return parseStringToBool(value, defaultValue); - case 'boolean': - return value; - case 'number': - return parseNumberToBool(value, defaultValue); + parseBool: (value: string | undefined, defaultValue: boolean): boolean => { + if (value === undefined) { + return defaultValue; + } + + switch (value.trim().toLowerCase()) { + case 'true': + case 'yes': + case '1': + return true; + case 'false': + case 'no': + case '0': + return false; default: return defaultValue; } } -} - -const parseStringToBool = (input: string, defaultVal: boolean): boolean => { - switch (input.toLowerCase().trim()) { - case 'true': - case 'yes': - case '1': - return true; - case 'false': - case 'no': - case '0': - return false; - default: - return defaultVal - } -} - -const parseNumberToBool = (input: number, defaultVal: boolean): boolean => { - switch (input) { - case 1: - return true; - case 0: - return false; - default: - return defaultVal; - } } \ No newline at end of file diff --git a/src/node/consumer/test/configuration_service.test.ts b/src/node/consumer/test/configuration_service.test.ts deleted file mode 100644 index c751564..0000000 --- a/src/node/consumer/test/configuration_service.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import "reflect-metadata"; // required - -describe('Configuration Tests', () => { - let configurationService; - beforeAll(async () => { - process.env.MONGODB_HOST = 'test_mongodb'; - process.env.MONGODB_PORT = '27017'; - process.env.MONGODB_DB = 'knightcrawler'; - process.env.MONGO_INITDB_ROOT_USERNAME = 'mongo'; - process.env.MONGO_INITDB_ROOT_PASSWORD = 'mongo'; - process.env.NO_CACHE = 'false'; - process.env.MONGODB_COLLECTION = 'knightcrawler_consumer_collection'; - process.env.POSTGRES_HOST = 'postgres'; - process.env.POSTGRES_PORT = '5432'; - process.env.POSTGRES_DB = 'knightcrawler'; - process.env.POSTGRES_USER = 'postgres'; - process.env.POSTGRES_PASSWORD = 'postgres'; - process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'false'; - process.env.TRACKERS_URL = 'https://ngosang.github.io/trackerslist/trackers_all.txt'; - process.env.UDP_TRACKERS_ENABLED = 'false'; - process.env.MAX_CONNECTIONS_PER_TORRENT = '20'; - process.env.TORRENT_TIMEOUT = '30000'; - process.env.RABBIT_URI = 'amqp://localhost'; - process.env.QUEUE_NAME = 'test-queue'; - process.env.IMDB_CONCURRENT = '1'; - process.env.IMDB_INTERVAL_MS = '1000'; - process.env.JOB_CONCURRENCY = '1'; - process.env.JOBS_ENABLED = 'true'; - - // shitty hack cause jest caches modules and resetModules isnt working - ({configurationService} = await import("@services/configuration_service")); - }); - - it('should populate cacheConfig correctly', () => { - const {cacheConfig} = configurationService; - expect(cacheConfig.MONGODB_HOST).toBe('test_mongodb'); - expect(cacheConfig.MONGODB_PORT).toBe('27017'); - expect(cacheConfig.MONGODB_DB).toBe('knightcrawler'); - expect(cacheConfig.MONGO_INITDB_ROOT_USERNAME).toBe('mongo'); - expect(cacheConfig.MONGO_INITDB_ROOT_PASSWORD).toBe('mongo'); - expect(cacheConfig.NO_CACHE).toBe(false); - expect(cacheConfig.COLLECTION_NAME).toBe('knightcrawler_consumer_collection'); - expect(cacheConfig.MONGO_URI).toBe('mongodb://mongo:mongo@test_mongodb:27017/knightcrawler?authSource=admin'); - }); - - it('should populate databaseConfig correctly', () => { - const {databaseConfig} = configurationService; - expect(databaseConfig.POSTGRES_HOST).toBe('postgres'); - expect(databaseConfig.POSTGRES_PORT).toBe(5432); - expect(databaseConfig.POSTGRES_DB).toBe('knightcrawler'); - expect(databaseConfig.POSTGRES_USER).toBe('postgres'); - expect(databaseConfig.POSTGRES_PASSWORD).toBe('postgres'); - expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(false); - expect(databaseConfig.POSTGRES_URI).toBe('postgres://postgres:postgres@postgres:5432/knightcrawler'); - }); - - it('should populate jobConfig correctly', () => { - const {jobConfig} = configurationService; - expect(jobConfig.JOB_CONCURRENCY).toBe(1); - expect(jobConfig.JOBS_ENABLED).toBe(true); - }); - - it('should populate metadataConfig correctly', () => { - const {metadataConfig} = configurationService; - expect(metadataConfig.IMDB_CONCURRENT).toBe(1); - expect(metadataConfig.IMDB_INTERVAL_MS).toBe(1000); - }); - - it('should populate rabbitConfig correctly', () => { - const {rabbitConfig} = configurationService; - expect(rabbitConfig.RABBIT_URI).toBe('amqp://localhost'); - expect(rabbitConfig.QUEUE_NAME).toBe('test-queue'); - }); - - it('should populate torrentConfig correctly', () => { - const {torrentConfig} = configurationService; - expect(torrentConfig.MAX_CONNECTIONS_PER_TORRENT).toBe(20); - expect(torrentConfig.TIMEOUT).toBe(30000); - }); - - it('should populate trackerConfig correctly', () => { - const {trackerConfig} = configurationService; - expect(trackerConfig.TRACKERS_URL).toBe('https://ngosang.github.io/trackerslist/trackers_all.txt'); - expect(trackerConfig.UDP_ENABLED).toBe(false); - }); - -}); \ No newline at end of file diff --git a/src/node/consumer/test/helpers/boolean_helpers.test.ts b/src/node/consumer/test/helpers/boolean_helpers.test.ts new file mode 100644 index 0000000..32e285c --- /dev/null +++ b/src/node/consumer/test/helpers/boolean_helpers.test.ts @@ -0,0 +1,35 @@ +import { BooleanHelpers } from '@helpers/boolean_helpers'; + +describe('BooleanHelpers.parseBool', () => { + it('should return true when value is "true"', () => { + expect(BooleanHelpers.parseBool('true', false)).toBe(true); + }); + + it('should return true when value is "1"', () => { + expect(BooleanHelpers.parseBool('1', false)).toBe(true); + }); + + it('should return true when value is "yes"', () => { + expect(BooleanHelpers.parseBool('yes', false)).toBe(true); + }); + + it('should return false when value is "false"', () => { + expect(BooleanHelpers.parseBool('false', true)).toBe(false); + }); + + it('should return false when value is "0"', () => { + expect(BooleanHelpers.parseBool('0', true)).toBe(false); + }); + + it('should return false when value is "no"', () => { + expect(BooleanHelpers.parseBool('no', true)).toBe(false); + }); + + it('should return default value when value is undefined', () => { + expect(BooleanHelpers.parseBool(undefined, true)).toBe(true); + }); + + it('should return default value when value is not "true", "1", "yes", "false", "0", or "no"', () => { + expect(BooleanHelpers.parseBool('random', true)).toBe(true); + }); +}); \ No newline at end of file diff --git a/src/node/consumer/test/helpers/extension_helpers.test.ts b/src/node/consumer/test/helpers/extension_helpers.test.ts new file mode 100644 index 0000000..ad92d8d --- /dev/null +++ b/src/node/consumer/test/helpers/extension_helpers.test.ts @@ -0,0 +1,33 @@ +import { ExtensionHelpers } from '@helpers/extension_helpers'; + +describe('ExtensionHelpers', () => { + describe('isVideo', () => { + it('should return true when file extension is a video extension', () => { + expect(ExtensionHelpers.isVideo('file.mp4')).toBe(true); + }); + + it('should return false when file extension is not a video extension', () => { + expect(ExtensionHelpers.isVideo('file.txt')).toBe(false); + }); + }); + + describe('isSubtitle', () => { + it('should return true when file extension is a subtitle extension', () => { + expect(ExtensionHelpers.isSubtitle('file.srt')).toBe(true); + }); + + it('should return false when file extension is not a subtitle extension', () => { + expect(ExtensionHelpers.isSubtitle('file.txt')).toBe(false); + }); + }); + + describe('isDisk', () => { + it('should return true when file extension is a disk extension', () => { + expect(ExtensionHelpers.isDisk('file.iso')).toBe(true); + }); + + it('should return false when file extension is not a disk extension', () => { + expect(ExtensionHelpers.isDisk('file.txt')).toBe(false); + }); + }); +}); \ No newline at end of file diff --git a/src/node/consumer/test/helpers/promise_helpers.test.ts b/src/node/consumer/test/helpers/promise_helpers.test.ts new file mode 100644 index 0000000..d265177 --- /dev/null +++ b/src/node/consumer/test/helpers/promise_helpers.test.ts @@ -0,0 +1,55 @@ +import { PromiseHelpers } from '@helpers/promises_helpers'; + +describe('PromiseHelpers', () => { + beforeAll(() => { + jest.useFakeTimers({timerLimit: 5000}); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + describe('sequence', () => { + it('should resolve promises in sequence', async () => { + const promises = [() => Promise.resolve(1), () => Promise.resolve(2), () => Promise.resolve(3)]; + const result = await PromiseHelpers.sequence(promises); + expect(result).toEqual([1, 2, 3]); + }); + }); + + describe('first', () => { + it('should resolve the first fulfilled promise', async () => { + const promises = [Promise.reject('error'), Promise.resolve('success'), Promise.resolve('success2')]; + const result = await PromiseHelpers.first(promises); + expect(result).toBe('success'); + }); + }); + + describe('delay', () => { + it('should delay execution', async () => { + const startTime = Date.now(); + const delayPromise = PromiseHelpers.delay(1000); + jest.runAllTimers(); + await delayPromise; + const endTime = Date.now(); + expect(endTime - startTime).toBeGreaterThanOrEqual(1000); + }, 30000); + }); + + describe('timeout', () => { + it('should reject promise after timeout', async () => { + const promise = new Promise((resolve) => setTimeout(resolve, 2000)); + const timeoutPromise = PromiseHelpers.timeout(1000, promise); + jest.advanceTimersByTime(1000); + await expect(timeoutPromise).rejects.toBe('Timed out'); + }, 20000); + }); + + describe('mostCommonValue', () => { + it('should return the most common value in an array', () => { + const array = [1, 2, 2, 3, 3, 3]; + const result = PromiseHelpers.mostCommonValue(array); + expect(result).toBe(3); + }); + }); +}); \ No newline at end of file diff --git a/src/node/consumer/test/cache_service.test.ts b/src/node/consumer/test/services/cache_service.test.ts similarity index 100% rename from src/node/consumer/test/cache_service.test.ts rename to src/node/consumer/test/services/cache_service.test.ts diff --git a/src/node/consumer/test/services/configuration_service.test.ts b/src/node/consumer/test/services/configuration_service.test.ts new file mode 100644 index 0000000..a82cea5 --- /dev/null +++ b/src/node/consumer/test/services/configuration_service.test.ts @@ -0,0 +1,139 @@ +import "reflect-metadata"; // required + +describe('Configuration Tests', () => { + beforeEach(() => { + jest.resetModules(); + }); + it('should populate cacheConfig correctly', async () => { + process.env.MONGODB_HOST = 'test_mongodb'; + process.env.MONGODB_PORT = '27017'; + process.env.MONGODB_DB = 'knightcrawler'; + process.env.MONGO_INITDB_ROOT_USERNAME = 'mongo'; + process.env.MONGO_INITDB_ROOT_PASSWORD = 'mongo'; + process.env.NO_CACHE = 'false'; + process.env.MONGODB_COLLECTION = 'knightcrawler_consumer_collection'; + const {configurationService} = await import("@services/configuration_service"); + const {cacheConfig} = configurationService; + expect(cacheConfig.MONGODB_HOST).toBe('test_mongodb'); + expect(cacheConfig.MONGODB_PORT).toBe('27017'); + expect(cacheConfig.MONGODB_DB).toBe('knightcrawler'); + expect(cacheConfig.MONGO_INITDB_ROOT_USERNAME).toBe('mongo'); + expect(cacheConfig.MONGO_INITDB_ROOT_PASSWORD).toBe('mongo'); + expect(cacheConfig.NO_CACHE).toBe(false); + expect(cacheConfig.COLLECTION_NAME).toBe('knightcrawler_consumer_collection'); + expect(cacheConfig.MONGO_URI).toBe('mongodb://mongo:mongo@test_mongodb:27017/knightcrawler?authSource=admin'); + }); + + it('should populate databaseConfig correctly', async() => { + process.env.POSTGRES_HOST = 'postgres'; + process.env.POSTGRES_PORT = '5432'; + process.env.POSTGRES_DB = 'knightcrawler'; + process.env.POSTGRES_USER = 'postgres'; + process.env.POSTGRES_PASSWORD = 'postgres'; + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'false'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.POSTGRES_HOST).toBe('postgres'); + expect(databaseConfig.POSTGRES_PORT).toBe(5432); + expect(databaseConfig.POSTGRES_DB).toBe('knightcrawler'); + expect(databaseConfig.POSTGRES_USER).toBe('postgres'); + expect(databaseConfig.POSTGRES_PASSWORD).toBe('postgres'); + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(false); + expect(databaseConfig.POSTGRES_URI).toBe('postgres://postgres:postgres@postgres:5432/knightcrawler'); + }); + + it('should process boolean when true as true for migrations', async() => { + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'true'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(true); + }); + + it('should process boolean when 1 as true for migrations', async() => { + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = '1'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(true); + }); + + it('should process boolean when yes as true for migrations', async() => { + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'yes'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(true); + }); + + it('should process boolean when uppercase TRUE as true for migrations', async() => { + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'TRUE'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(true); + }); + + it('should process boolean when uppercase FALSE as false for migrations', async() => { + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'FALSE'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(false); + }); + + it('should process boolean when no as false for migrations', async() => { + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = 'no'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(false); + }); + + it('should process boolean when no as 0 for migrations', async () => { + process.env.AUTO_CREATE_AND_APPLY_MIGRATIONS = '0'; + const {configurationService} = await import("@services/configuration_service"); + const {databaseConfig} = configurationService; + expect(databaseConfig.AUTO_CREATE_AND_APPLY_MIGRATIONS).toBe(false); + }); + + it('should populate jobConfig correctly', async() => { + process.env.JOB_CONCURRENCY = '1'; + process.env.JOBS_ENABLED = 'true'; + const {configurationService} = await import("@services/configuration_service"); + const {jobConfig} = configurationService; + expect(jobConfig.JOB_CONCURRENCY).toBe(1); + expect(jobConfig.JOBS_ENABLED).toBe(true); + }); + + it('should populate metadataConfig correctly', async() => { + process.env.IMDB_CONCURRENT = '1'; + process.env.IMDB_INTERVAL_MS = '1000'; + const {configurationService} = await import("@services/configuration_service"); + const {metadataConfig} = configurationService; + expect(metadataConfig.IMDB_CONCURRENT).toBe(1); + expect(metadataConfig.IMDB_INTERVAL_MS).toBe(1000); + }); + + it('should populate rabbitConfig correctly', async () => { + process.env.RABBIT_URI = 'amqp://localhost'; + process.env.QUEUE_NAME = 'test-queue'; + const {configurationService} = await import("@services/configuration_service"); + const {rabbitConfig} = configurationService; + expect(rabbitConfig.RABBIT_URI).toBe('amqp://localhost'); + expect(rabbitConfig.QUEUE_NAME).toBe('test-queue'); + }); + + it('should populate torrentConfig correctly', async () => { + process.env.MAX_CONNECTIONS_PER_TORRENT = '20'; + process.env.TORRENT_TIMEOUT = '30000'; + const {configurationService} = await import("@services/configuration_service"); + const {torrentConfig} = configurationService; + expect(torrentConfig.MAX_CONNECTIONS_PER_TORRENT).toBe(20); + expect(torrentConfig.TIMEOUT).toBe(30000); + }); + + it('should populate trackerConfig correctly', async () => { + process.env.TRACKERS_URL = 'https://ngosang.github.io/trackerslist/trackers_all.txt'; + process.env.UDP_TRACKERS_ENABLED = 'false'; + const {configurationService} = await import("@services/configuration_service"); + const {trackerConfig} = configurationService; + expect(trackerConfig.TRACKERS_URL).toBe('https://ngosang.github.io/trackerslist/trackers_all.txt'); + expect(trackerConfig.UDP_ENABLED).toBe(false); + }); + +}); \ No newline at end of file diff --git a/src/node/consumer/test/logging_service.test.ts b/src/node/consumer/test/services/logging_service.test.ts similarity index 100% rename from src/node/consumer/test/logging_service.test.ts rename to src/node/consumer/test/services/logging_service.test.ts diff --git a/src/node/consumer/test/metadata_service.test.ts b/src/node/consumer/test/services/metadata_service.test.ts similarity index 98% rename from src/node/consumer/test/metadata_service.test.ts rename to src/node/consumer/test/services/metadata_service.test.ts index 9184d4c..0b94220 100644 --- a/src/node/consumer/test/metadata_service.test.ts +++ b/src/node/consumer/test/services/metadata_service.test.ts @@ -5,7 +5,7 @@ import {MetadataService} from "@services/metadata_service"; import {IocTypes} from "@setup/ioc_types"; import {Container} from "inversify"; import {setupServer} from "msw/node"; -import * as responses from "./mock-responses/metadata_mock_responses"; +import * as responses from "../mock-responses/metadata_mock_responses"; jest.mock('@services/cache_service', () => { return { diff --git a/src/node/consumer/test/process_torrent_job.test.ts b/src/node/consumer/test/services/process_torrent_job.test.ts similarity index 100% rename from src/node/consumer/test/process_torrent_job.test.ts rename to src/node/consumer/test/services/process_torrent_job.test.ts diff --git a/src/node/consumer/test/torrent_download_service.test.ts b/src/node/consumer/test/services/torrent_download_service.test.ts similarity index 100% rename from src/node/consumer/test/torrent_download_service.test.ts rename to src/node/consumer/test/services/torrent_download_service.test.ts diff --git a/src/node/consumer/test/torrent_entries_service.test.ts b/src/node/consumer/test/services/torrent_entries_service.test.ts similarity index 100% rename from src/node/consumer/test/torrent_entries_service.test.ts rename to src/node/consumer/test/services/torrent_entries_service.test.ts diff --git a/src/node/consumer/test/torrent_file_service.test.ts b/src/node/consumer/test/services/torrent_file_service.test.ts similarity index 100% rename from src/node/consumer/test/torrent_file_service.test.ts rename to src/node/consumer/test/services/torrent_file_service.test.ts diff --git a/src/node/consumer/test/torrent_subtitle_service.test.ts b/src/node/consumer/test/services/torrent_subtitle_service.test.ts similarity index 100% rename from src/node/consumer/test/torrent_subtitle_service.test.ts rename to src/node/consumer/test/services/torrent_subtitle_service.test.ts diff --git a/src/node/consumer/test/tracker_service.test.ts b/src/node/consumer/test/services/tracker_service.test.ts similarity index 96% rename from src/node/consumer/test/tracker_service.test.ts rename to src/node/consumer/test/services/tracker_service.test.ts index 065c7c1..4427817 100644 --- a/src/node/consumer/test/tracker_service.test.ts +++ b/src/node/consumer/test/services/tracker_service.test.ts @@ -5,7 +5,7 @@ import {TrackerService} from '@services/tracker_service'; import {IocTypes} from "@setup/ioc_types"; import {Container} from "inversify"; import {setupServer} from 'msw/node'; -import * as responses from "./mock-responses/trackers_mock_responses"; +import * as responses from "../mock-responses/trackers_mock_responses"; const server = setupServer(responses.trackerTestResponse);