Compare commits

...

2 commits

Author SHA1 Message Date
Ethan Lane 0bb65190a5 Update tests
All checks were successful
Test / build (push) Successful in 8s
2024-07-25 17:48:25 +01:00
Ethan Lane 6e07aba034 Add limit option to the app 2024-07-25 17:48:17 +01:00
10 changed files with 141 additions and 5 deletions

View file

@ -14,11 +14,12 @@ program
.option('-j, --json', 'Output as JSON') .option('-j, --json', 'Output as JSON')
.option('-q, --query-metadata', 'Include query metadata in result') .option('-q, --query-metadata', 'Include query metadata in result')
.option('-o <file>', 'Output to file') .option('-o <file>', 'Output to file')
.addOption(new Option('--sort <sort>', 'Sort by').default('hot').choices(['hot', 'new', 'top'])); .addOption(new Option('--sort <sort>', 'Sort by').default('hot').choices(['hot', 'new', 'top']))
.addOption(new Option('--limit <limit>', 'The amount of posts to fetch from the reddit api').default(100));
program.parse(); program.parse();
const options: ICliOptions = program.opts(); const options: ICliOptions = program.opts();
randomBunny(options.subreddit, options.sort) randomBunny(options.subreddit, options.sort, options.limit)
.then((response) => exit(CliHelper.Endpoint(response, options))); .then((response) => exit(CliHelper.Endpoint(response, options)));

View file

@ -3,4 +3,5 @@ export enum ErrorCode {
FailedToFetchReddit, FailedToFetchReddit,
UnableToParseJSON, UnableToParseJSON,
NoImageResultsFound, NoImageResultsFound,
LimitOutOfRange,
} }

View file

@ -2,4 +2,5 @@ export default class ErrorMessages {
public static readonly FailedToFetchReddit = "Failed to fetch result from Reddit"; public static readonly FailedToFetchReddit = "Failed to fetch result from Reddit";
public static readonly UnableToParseJSON = "Unable to parse the JSON result"; 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 NoImageResultsFound = "No image results found in response from Reddit";
public static readonly LimitOutOfRange = "Limit must be a number between 1 and 100";
} }

View file

@ -3,5 +3,6 @@ export default interface ICliOptions {
json?: boolean, json?: boolean,
sort: "new" | "hot" | "top", sort: "new" | "hot" | "top",
o?: string, o?: string,
limit: number,
queryMetadata?: boolean, queryMetadata?: boolean,
} }

View file

@ -1,4 +1,5 @@
export default interface QueryResult { export default interface QueryResult {
subreddit: string, subreddit: string,
sortBy: string, sortBy: string,
limit: number,
} }

View file

@ -24,6 +24,7 @@ export default class OutputHelper {
if (options.queryMetadata != null) { if (options.queryMetadata != null) {
outputLines.push(`Query.Subreddit = ${response.Query.subreddit}`); outputLines.push(`Query.Subreddit = ${response.Query.subreddit}`);
outputLines.push(`Query.Sort By = ${response.Query.sortBy}`); outputLines.push(`Query.Sort By = ${response.Query.sortBy}`);
outputLines.push(`Query.Limit = ${response.Query.limit}`);
} }
return outputLines.join("\n"); return outputLines.join("\n");

View file

@ -7,8 +7,23 @@ import { ErrorCode } from "./constants/ErrorCode";
import ErrorMessages from "./constants/ErrorMessages"; import ErrorMessages from "./constants/ErrorMessages";
import ImageHelper from "./helpers/imageHelper"; import ImageHelper from "./helpers/imageHelper";
export default async function randomBunny(subreddit: string, sortBy: "new" | "hot" | "top" = 'hot'): Promise<IReturnResult> { export default async function randomBunny(subreddit: string, sortBy: "new" | "hot" | "top" = 'hot', limit: number = 100): Promise<IReturnResult> {
const result = await fetch(`https://reddit.com/r/${subreddit}/${sortBy}.json?limit=100`) 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) => { .then((res) => {
return res; return res;
}) })
@ -22,6 +37,7 @@ export default async function randomBunny(subreddit: string, sortBy: "new" | "ho
Query: { Query: {
subreddit: subreddit, subreddit: subreddit,
sortBy: sortBy, sortBy: sortBy,
limit: limit,
}, },
Error: { Error: {
Code: ErrorCode.FailedToFetchReddit, Code: ErrorCode.FailedToFetchReddit,
@ -38,6 +54,7 @@ export default async function randomBunny(subreddit: string, sortBy: "new" | "ho
Query: { Query: {
subreddit: subreddit, subreddit: subreddit,
sortBy: sortBy, sortBy: sortBy,
limit: limit,
}, },
Error: { Error: {
Code: ErrorCode.UnableToParseJSON, Code: ErrorCode.UnableToParseJSON,
@ -60,6 +77,7 @@ export default async function randomBunny(subreddit: string, sortBy: "new" | "ho
Query: { Query: {
subreddit: subreddit, subreddit: subreddit,
sortBy: sortBy, sortBy: sortBy,
limit: limit,
}, },
Error: { Error: {
Code: ErrorCode.NoImageResultsFound, Code: ErrorCode.NoImageResultsFound,
@ -85,6 +103,7 @@ export default async function randomBunny(subreddit: string, sortBy: "new" | "ho
Query: { Query: {
subreddit: subreddit, subreddit: subreddit,
sortBy: sortBy, sortBy: sortBy,
limit: limit,
}, },
Error: { Error: {
Code: ErrorCode.NoImageResultsFound, Code: ErrorCode.NoImageResultsFound,
@ -115,6 +134,7 @@ export default async function randomBunny(subreddit: string, sortBy: "new" | "ho
Query: { Query: {
subreddit: subreddit, subreddit: subreddit,
sortBy: sortBy, sortBy: sortBy,
limit: limit,
}, },
Result: redditResult Result: redditResult
}; };

View file

@ -25,5 +25,6 @@ Title = This is my Ms Bear!
Upvotes = 17 Upvotes = 17
Url = https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d Url = https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d
Query.Subreddit = rabbits Query.Subreddit = rabbits
Query.Sort By = hot" Query.Sort By = hot
Query.Limit = 100"
`; `;

View file

@ -10,6 +10,7 @@ describe("GenerateOutput", () => {
Query: { Query: {
subreddit: "rabbits", subreddit: "rabbits",
sortBy: "hot", sortBy: "hot",
limit: 100,
}, },
Result: { Result: {
Archived: false, Archived: false,
@ -40,6 +41,7 @@ describe("GenerateOutput", () => {
Query: { Query: {
subreddit: "rabbits", subreddit: "rabbits",
sortBy: "hot", sortBy: "hot",
limit: 100,
}, },
Result: { Result: {
Archived: false, Archived: false,
@ -72,6 +74,7 @@ describe("GenerateOutput", () => {
Query: { Query: {
subreddit: "rabbits", subreddit: "rabbits",
sortBy: "hot", sortBy: "hot",
limit: 100,
}, },
Result: { Result: {
Archived: false, Archived: false,

View file

@ -7,6 +7,10 @@ import fetch from "got-cjs";
jest.mock('got-cjs'); jest.mock('got-cjs');
const fetchMock = jest.mocked(fetch); const fetchMock = jest.mocked(fetch);
beforeEach(() => {
fetchMock.mockReset();
});
describe('randomBunny', () => { describe('randomBunny', () => {
test('GIVEN subreddit AND sortBy is supplied, EXPECT successful result', async() => { test('GIVEN subreddit AND sortBy is supplied, EXPECT successful result', async() => {
fetchMock.mockResolvedValue({ fetchMock.mockResolvedValue({
@ -231,4 +235,106 @@ describe('randomBunny', () => {
expect(result.Error?.Code).toBe(ErrorCode.NoImageResultsFound); expect(result.Error?.Code).toBe(ErrorCode.NoImageResultsFound);
expect(result.Error?.Message).toBe(ErrorMessages.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 its 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 its 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 its 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();
});
}); });