From 6e07aba034713283dec58b5336f9969331781145 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Thu, 25 Jul 2024 17:48:17 +0100 Subject: [PATCH 1/2] Add limit option to the app --- src/cli.ts | 5 +++-- src/constants/ErrorCode.ts | 1 + src/constants/ErrorMessages.ts | 1 + src/contracts/ICliOptions.ts | 1 + src/contracts/QueryResult.ts | 1 + src/helpers/outputHelper.ts | 1 + src/index.ts | 24 ++++++++++++++++++++++-- 7 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/cli.ts b/src/cli.ts index 0d739e2..8b1eced 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -14,11 +14,12 @@ program .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'])); + .addOption(new Option('--sort ', 'Sort by').default('hot').choices(['hot', 'new', 'top'])) + .addOption(new Option('--limit ', 'The amount of posts to fetch from the reddit api').default(100)); program.parse(); const options: ICliOptions = program.opts(); -randomBunny(options.subreddit, options.sort) +randomBunny(options.subreddit, options.sort, options.limit) .then((response) => exit(CliHelper.Endpoint(response, options))); \ No newline at end of file diff --git a/src/constants/ErrorCode.ts b/src/constants/ErrorCode.ts index bbf3fef..6a1e720 100644 --- a/src/constants/ErrorCode.ts +++ b/src/constants/ErrorCode.ts @@ -3,4 +3,5 @@ export enum ErrorCode { FailedToFetchReddit, UnableToParseJSON, NoImageResultsFound, + LimitOutOfRange, } \ No newline at end of file diff --git a/src/constants/ErrorMessages.ts b/src/constants/ErrorMessages.ts index 4c5e24a..180e335 100644 --- a/src/constants/ErrorMessages.ts +++ b/src/constants/ErrorMessages.ts @@ -2,4 +2,5 @@ export default class ErrorMessages { public static readonly FailedToFetchReddit = "Failed to fetch result from Reddit"; public static readonly UnableToParseJSON = "Unable to parse the JSON result"; public static readonly NoImageResultsFound = "No image results found in response from Reddit"; + public static readonly LimitOutOfRange = "Limit must be a number between 1 and 100"; } \ No newline at end of file diff --git a/src/contracts/ICliOptions.ts b/src/contracts/ICliOptions.ts index 355c92f..a2844e4 100644 --- a/src/contracts/ICliOptions.ts +++ b/src/contracts/ICliOptions.ts @@ -3,5 +3,6 @@ export default interface ICliOptions { json?: boolean, sort: "new" | "hot" | "top", o?: string, + limit: number, queryMetadata?: boolean, } \ No newline at end of file diff --git a/src/contracts/QueryResult.ts b/src/contracts/QueryResult.ts index ee97e30..03bdacc 100644 --- a/src/contracts/QueryResult.ts +++ b/src/contracts/QueryResult.ts @@ -1,4 +1,5 @@ export default interface QueryResult { subreddit: string, sortBy: string, + limit: number, } \ No newline at end of file diff --git a/src/helpers/outputHelper.ts b/src/helpers/outputHelper.ts index 40a2927..2e25935 100644 --- a/src/helpers/outputHelper.ts +++ b/src/helpers/outputHelper.ts @@ -24,6 +24,7 @@ export default class OutputHelper { if (options.queryMetadata != null) { outputLines.push(`Query.Subreddit = ${response.Query.subreddit}`); outputLines.push(`Query.Sort By = ${response.Query.sortBy}`); + outputLines.push(`Query.Limit = ${response.Query.limit}`); } return outputLines.join("\n"); diff --git a/src/index.ts b/src/index.ts index b1ecc5d..3e573af 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,8 +7,23 @@ import { ErrorCode } from "./constants/ErrorCode"; import ErrorMessages from "./constants/ErrorMessages"; 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`) +export default async function randomBunny(subreddit: string, sortBy: "new" | "hot" | "top" = 'hot', limit: number = 100): Promise { + if (limit < 1 || limit > 100) { + return { + IsSuccess: false, + Query: { + subreddit: subreddit, + sortBy: sortBy, + limit: limit, + }, + Error: { + Code: ErrorCode.LimitOutOfRange, + Message: ErrorMessages.LimitOutOfRange, + } + }; + } + + const result = await fetch(`https://reddit.com/r/${subreddit}/${sortBy}.json?limit=${limit}`) .then((res) => { return res; }) @@ -22,6 +37,7 @@ export default async function randomBunny(subreddit: string, sortBy: "new" | "ho Query: { subreddit: subreddit, sortBy: sortBy, + limit: limit, }, Error: { Code: ErrorCode.FailedToFetchReddit, @@ -38,6 +54,7 @@ export default async function randomBunny(subreddit: string, sortBy: "new" | "ho Query: { subreddit: subreddit, sortBy: sortBy, + limit: limit, }, Error: { Code: ErrorCode.UnableToParseJSON, @@ -60,6 +77,7 @@ export default async function randomBunny(subreddit: string, sortBy: "new" | "ho Query: { subreddit: subreddit, sortBy: sortBy, + limit: limit, }, Error: { Code: ErrorCode.NoImageResultsFound, @@ -85,6 +103,7 @@ export default async function randomBunny(subreddit: string, sortBy: "new" | "ho Query: { subreddit: subreddit, sortBy: sortBy, + limit: limit, }, Error: { Code: ErrorCode.NoImageResultsFound, @@ -115,6 +134,7 @@ export default async function randomBunny(subreddit: string, sortBy: "new" | "ho Query: { subreddit: subreddit, sortBy: sortBy, + limit: limit, }, Result: redditResult }; From 0bb65190a599d33128cd8cb0e2c36313911abec2 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Thu, 25 Jul 2024 17:48:25 +0100 Subject: [PATCH 2/2] Update tests --- .../__snapshots__/outputHelper.test.ts.snap | 3 +- tests/helpers/outputHelper.test.ts | 3 + tests/index.test.ts | 106 ++++++++++++++++++ 3 files changed, 111 insertions(+), 1 deletion(-) diff --git a/tests/helpers/__snapshots__/outputHelper.test.ts.snap b/tests/helpers/__snapshots__/outputHelper.test.ts.snap index 0aa5dcc..79f386f 100644 --- a/tests/helpers/__snapshots__/outputHelper.test.ts.snap +++ b/tests/helpers/__snapshots__/outputHelper.test.ts.snap @@ -25,5 +25,6 @@ Title = This is my Ms Bear! Upvotes = 17 Url = https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d Query.Subreddit = rabbits -Query.Sort By = hot" +Query.Sort By = hot +Query.Limit = 100" `; diff --git a/tests/helpers/outputHelper.test.ts b/tests/helpers/outputHelper.test.ts index 8c9893d..a0f1959 100644 --- a/tests/helpers/outputHelper.test.ts +++ b/tests/helpers/outputHelper.test.ts @@ -10,6 +10,7 @@ describe("GenerateOutput", () => { Query: { subreddit: "rabbits", sortBy: "hot", + limit: 100, }, Result: { Archived: false, @@ -40,6 +41,7 @@ describe("GenerateOutput", () => { Query: { subreddit: "rabbits", sortBy: "hot", + limit: 100, }, Result: { Archived: false, @@ -72,6 +74,7 @@ describe("GenerateOutput", () => { Query: { subreddit: "rabbits", sortBy: "hot", + limit: 100, }, Result: { Archived: false, diff --git a/tests/index.test.ts b/tests/index.test.ts index ffa9015..2de4607 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -7,6 +7,10 @@ import fetch from "got-cjs"; jest.mock('got-cjs'); const fetchMock = jest.mocked(fetch); +beforeEach(() => { + fetchMock.mockReset(); +}); + describe('randomBunny', () => { test('GIVEN subreddit AND sortBy is supplied, EXPECT successful result', async() => { fetchMock.mockResolvedValue({ @@ -231,4 +235,106 @@ describe('randomBunny', () => { expect(result.Error?.Code).toBe(ErrorCode.NoImageResultsFound); expect(result.Error?.Message).toBe(ErrorMessages.NoImageResultsFound); }); + + test("GIVEN limit is supplied, EXPECT limit sent to the API", 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', 'new', 50); + + expect(result.IsSuccess).toBeTruthy(); + expect(result.Result).toBeDefined(); + expect(result.Error).toBeUndefined(); + + expect(fetchMock).toHaveBeenCalledWith('https://reddit.com/r/rabbits/new.json?limit=50'); + }); + + test("GIVEN limit is less than 1, EXPECT error to be returned", 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', 'new', 0); + + expect(result.IsSuccess).toBeFalsy(); + expect(result.Result).toBeUndefined(); + expect(result.Error).toBeDefined(); + + expect(result.Error!.Code).toBe(ErrorCode.LimitOutOfRange); + expect(result.Error!.Message).toBe(ErrorMessages.LimitOutOfRange); + + expect(fetchMock).not.toHaveBeenCalled(); + }); + + test("GIVEN limit is greater than 100, EXPECT error to be returned", 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', 'new', 101); + + expect(result.IsSuccess).toBeFalsy(); + expect(result.Result).toBeUndefined(); + expect(result.Error).toBeDefined(); + + expect(result.Error!.Code).toBe(ErrorCode.LimitOutOfRange); + expect(result.Error!.Message).toBe(ErrorMessages.LimitOutOfRange); + + expect(fetchMock).not.toHaveBeenCalled(); + }); }); \ No newline at end of file