From a20bdacbe5755105015e2de58538f9911fdeca02 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Wed, 19 Jun 2024 13:33:41 +0100 Subject: [PATCH 1/3] Fix deprecation on unit tests --- tests/index.test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/index.test.ts b/tests/index.test.ts index 053f347..e1caf92 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -37,7 +37,7 @@ describe('randomBunny', () => { expect(result.Result).toBeDefined(); expect(result.Error).toBeUndefined(); - expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); + expect(fetchMock).toHaveBeenCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); }); test('GIVEN sortBy is NOT supplied, expect it to default to hot', async () => { @@ -69,7 +69,7 @@ describe('randomBunny', () => { expect(result.Result).toBeDefined(); expect(result.Error).toBeUndefined(); - expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/hot.json?limit=100'); + expect(fetchMock).toHaveBeenCalledWith('https://reddit.com/r/rabbits/hot.json?limit=100'); }); test('GIVEN sortBy is NOT valid, expect it to default to hot', async () => { @@ -101,7 +101,7 @@ describe('randomBunny', () => { expect(result.Result).toBeDefined(); expect(result.Error).toBeUndefined(); - expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/hot.json?limit=100'); + expect(fetchMock).toHaveBeenCalledWith('https://reddit.com/r/rabbits/hot.json?limit=100'); }); test('GIVEN the fetch fails, EXPECT failure result', async () => { @@ -116,7 +116,7 @@ describe('randomBunny', () => { expect(result.Error!.Code).toBe(ErrorCode.FailedToFetchReddit); expect(result.Error!.Message).toBe(ErrorMessages.FailedToFetchReddit); - expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); + expect(fetchMock).toHaveBeenCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); }); test('GIVEN the result is NOT valid JSON, EXPECT failure result', async () => { @@ -133,7 +133,7 @@ describe('randomBunny', () => { expect(result.Error!.Code).toBe(ErrorCode.UnableToParseJSON); expect(result.Error!.Message).toBe(ErrorMessages.UnableToParseJSON); - expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); + expect(fetchMock).toHaveBeenCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); }); test('GIVEN randomSelect does NOT find a response, EXPECT failure result', async () => { @@ -189,8 +189,8 @@ describe('randomBunny', () => { expect(result.Error!.Code).toBe(ErrorCode.NoImageResultsFound); expect(result.Error!.Message).toBe(ErrorMessages.NoImageResultsFound); - expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); - expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); + expect(fetchMock).toHaveBeenCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); + expect(fetchMock).toHaveBeenCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); }); test("GIVEN data fetched is a gallery AND an image is returned from the helper, EXPECT this to be used", async () => { @@ -223,7 +223,7 @@ describe('randomBunny', () => { expect(result.IsSuccess).toBeTruthy(); expect(result.Result).toBeDefined(); - expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); + expect(fetchMock).toHaveBeenCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); expect(ImageHelper.FetchImageFromRedditGallery).toHaveBeenCalledTimes(1); expect(ImageHelper.FetchImageFromRedditGallery).toHaveBeenCalledWith("https://i.redd.it/gallery/cr8xudsnkgua1"); From b1c7de7e8ca4cf400cb050934948be9d3387aaad Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Wed, 19 Jun 2024 13:45:07 +0100 Subject: [PATCH 2/3] Add string literal types to function --- src/contracts/ICliOptions.ts | 2 +- src/index.ts | 10 +--------- tests/index.test.ts | 32 -------------------------------- 3 files changed, 2 insertions(+), 42 deletions(-) diff --git a/src/contracts/ICliOptions.ts b/src/contracts/ICliOptions.ts index cc3af03..783f6af 100644 --- a/src/contracts/ICliOptions.ts +++ b/src/contracts/ICliOptions.ts @@ -1,6 +1,6 @@ export default interface ICliOptions { subreddit: string, json?: boolean, - sort: string, + sort: "new" | "hot" | "top", queryMetadata?: boolean, } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 75ad628..694a274 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,15 +7,7 @@ import { ErrorCode } from "./constants/ErrorCode"; import ErrorMessages from "./constants/ErrorMessages"; import ImageHelper from "./imageHelper"; -const sortable = [ - 'new', - 'hot', - 'top' -]; - -export default async function randomBunny(subreddit: string, sortBy: string = 'hot'): Promise { - if (!sortable.includes(sortBy)) sortBy = 'hot'; - +export default async function randomBunny(subreddit: string, sortBy: "new" | "hot" | "top" = 'hot'): Promise { const result = await fetch(`https://reddit.com/r/${subreddit}/${sortBy}.json?limit=100`) .then((res) => { return res; diff --git a/tests/index.test.ts b/tests/index.test.ts index e1caf92..f7f7193 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -72,38 +72,6 @@ describe('randomBunny', () => { expect(fetchMock).toHaveBeenCalledWith('https://reddit.com/r/rabbits/hot.json?limit=100'); }); - test('GIVEN sortBy is NOT valid, expect it to default to hot', async () => { - fetchMock.mockResolvedValue({ - body: JSON.stringify({ - data: { - children: [ - { - data: { - archived: false, - downs: 0, - hidden: false, - permalink: '/r/Rabbits/comments/12pa5te/someone_told_pickles_its_monday_internal_fury/', - subreddit: 'Rabbits', - subreddit_subscribers: 298713, - title: 'Someone told pickles it’s Monday… *internal fury*', - ups: 1208, - url: 'https://i.redd.it/cr8xudsnkgua1.jpg', - }, - }, - ], - } - }), - }); - - const result = await randomBunny('rabbits', 'invalid'); - - expect(result.IsSuccess).toBeTruthy(); - expect(result.Result).toBeDefined(); - expect(result.Error).toBeUndefined(); - - expect(fetchMock).toHaveBeenCalledWith('https://reddit.com/r/rabbits/hot.json?limit=100'); - }); - test('GIVEN the fetch fails, EXPECT failure result', async () => { fetchMock.mockRejectedValue('Test Reason') From f315361278476000034342844007b6bc6cf133b8 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Wed, 19 Jun 2024 16:54:51 +0100 Subject: [PATCH 3/3] Add output to file option --- src/cli.ts | 30 +++++++----------------- src/contracts/ICliOptions.ts | 1 + src/{ => helpers}/imageHelper.ts | 0 src/helpers/outputHelper.ts | 31 +++++++++++++++++++++++++ src/index.ts | 2 +- tests/{ => helpers}/imageHelper.test.ts | 2 +- tests/index.test.ts | 2 +- 7 files changed, 43 insertions(+), 25 deletions(-) rename src/{ => helpers}/imageHelper.ts (100%) create mode 100644 src/helpers/outputHelper.ts rename tests/{ => helpers}/imageHelper.test.ts (98%) diff --git a/src/cli.ts b/src/cli.ts index d103e86..13ce7f7 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -2,6 +2,8 @@ import { Command, Option } from "commander"; import randomBunny from "./index"; import ICliOptions from "./contracts/ICliOptions"; import { exit } from "process"; +import OutputHelper from "./helpers/outputHelper"; +import { writeFileSync } from "fs"; const program = new Command(); @@ -12,6 +14,7 @@ program .option('-s, --subreddit ', 'The subreddit to search', 'rabbits') .option('-j, --json', 'Output as JSON') .option('-q, --query-metadata', 'Include query metadata in result') + .option('-o ', 'Output to file') .addOption(new Option('--sort ', 'Sort by').default('hot').choices(['hot', 'new', 'top'])); program.parse(); @@ -21,31 +24,14 @@ const options: ICliOptions = program.opts(); randomBunny(options.subreddit, options.sort) .then((response) => { if (response.IsSuccess) { - const result = response.Result!; + const output = OutputHelper.GenerateOutput(response, options); - const outputLines: string[] = []; - - if (options.json) { - console.log(JSON.stringify(result)); - return; + if (options.o) { + writeFileSync(options.o, output); + } else { + console.log(output); } - outputLines.push(`Archived = ${result.Archived}`); - outputLines.push(`Downvotes = ${result.Downs}`); - outputLines.push(`Hidden = ${result.Hidden}`); - outputLines.push(`Permalink = ${result.Permalink}`); - outputLines.push(`Subreddit = ${result.Subreddit}`); - outputLines.push(`Subreddit Subscribers = ${result.SubredditSubscribers}`); - outputLines.push(`Title = ${result.Title}`); - outputLines.push(`Upvotes = ${result.Ups}`); - outputLines.push(`Url = ${result.Url}`); - - if (options.queryMetadata != null) { - outputLines.push(`Query.Subreddit = ${response.Query.subreddit}`); - outputLines.push(`Query.Sort By = ${response.Query.sortBy}`); - } - - console.log(outputLines.join("\n")); exit(0); } else { const error = response.Error!; diff --git a/src/contracts/ICliOptions.ts b/src/contracts/ICliOptions.ts index 783f6af..355c92f 100644 --- a/src/contracts/ICliOptions.ts +++ b/src/contracts/ICliOptions.ts @@ -2,5 +2,6 @@ export default interface ICliOptions { subreddit: string, json?: boolean, sort: "new" | "hot" | "top", + o?: string, queryMetadata?: boolean, } \ No newline at end of file diff --git a/src/imageHelper.ts b/src/helpers/imageHelper.ts similarity index 100% rename from src/imageHelper.ts rename to src/helpers/imageHelper.ts diff --git a/src/helpers/outputHelper.ts b/src/helpers/outputHelper.ts new file mode 100644 index 0000000..40a2927 --- /dev/null +++ b/src/helpers/outputHelper.ts @@ -0,0 +1,31 @@ +import ICliOptions from "../contracts/ICliOptions"; +import IReturnResult from "../contracts/IReturnResult"; + +export default class OutputHelper { + public static GenerateOutput(response: IReturnResult, options: ICliOptions): string { + const result = response.Result!; + + const outputLines: string[] = []; + + if (options.json) { + return JSON.stringify(result); + } + + outputLines.push(`Archived = ${result.Archived}`); + outputLines.push(`Downvotes = ${result.Downs}`); + outputLines.push(`Hidden = ${result.Hidden}`); + outputLines.push(`Permalink = ${result.Permalink}`); + outputLines.push(`Subreddit = ${result.Subreddit}`); + outputLines.push(`Subreddit Subscribers = ${result.SubredditSubscribers}`); + outputLines.push(`Title = ${result.Title}`); + outputLines.push(`Upvotes = ${result.Ups}`); + outputLines.push(`Url = ${result.Url}`); + + if (options.queryMetadata != null) { + outputLines.push(`Query.Subreddit = ${response.Query.subreddit}`); + outputLines.push(`Query.Sort By = ${response.Query.sortBy}`); + } + + return outputLines.join("\n"); + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 694a274..b1ecc5d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,7 @@ import { List } from 'linqts'; import IFetchResult from "./contracts/IFetchResult"; import { ErrorCode } from "./constants/ErrorCode"; import ErrorMessages from "./constants/ErrorMessages"; -import ImageHelper from "./imageHelper"; +import ImageHelper from "./helpers/imageHelper"; export default async function randomBunny(subreddit: string, sortBy: "new" | "hot" | "top" = 'hot'): Promise { const result = await fetch(`https://reddit.com/r/${subreddit}/${sortBy}.json?limit=100`) diff --git a/tests/imageHelper.test.ts b/tests/helpers/imageHelper.test.ts similarity index 98% rename from tests/imageHelper.test.ts rename to tests/helpers/imageHelper.test.ts index 77227b1..3c6f44e 100644 --- a/tests/imageHelper.test.ts +++ b/tests/helpers/imageHelper.test.ts @@ -1,4 +1,4 @@ -import ImageHelper from "../src/imageHelper"; +import ImageHelper from "../../src/helpers/imageHelper"; import fetch from "got-cjs"; jest.mock('got-cjs'); diff --git a/tests/index.test.ts b/tests/index.test.ts index f7f7193..ffa9015 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,6 +1,6 @@ import { ErrorCode } from "../src/constants/ErrorCode"; import ErrorMessages from "../src/constants/ErrorMessages"; -import ImageHelper from "../src/imageHelper"; +import ImageHelper from "../src/helpers/imageHelper"; import randomBunny from "../src/index"; import fetch from "got-cjs";