Compare commits

...

3 commits

Author SHA1 Message Date
Ethan Lane f315361278 Add output to file option 2024-06-19 16:54:51 +01:00
Ethan Lane b1c7de7e8c Add string literal types to function 2024-06-19 13:45:07 +01:00
Ethan Lane a20bdacbe5 Fix deprecation on unit tests 2024-06-19 13:33:41 +01:00
7 changed files with 52 additions and 74 deletions

View file

@ -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 <subreddit>', 'The subreddit to search', 'rabbits')
.option('-j, --json', 'Output as JSON')
.option('-q, --query-metadata', 'Include query metadata in result')
.option('-o <file>', 'Output to file')
.addOption(new Option('--sort <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!;

View file

@ -1,6 +1,7 @@
export default interface ICliOptions {
subreddit: string,
json?: boolean,
sort: string,
sort: "new" | "hot" | "top",
o?: string,
queryMetadata?: boolean,
}

View file

@ -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");
}
}

View file

@ -5,17 +5,9 @@ import { List } from 'linqts';
import IFetchResult from "./contracts/IFetchResult";
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<IReturnResult> {
if (!sortable.includes(sortBy)) sortBy = 'hot';
import ImageHelper from "./helpers/imageHelper";
export default async function randomBunny(subreddit: string, sortBy: "new" | "hot" | "top" = 'hot'): Promise<IReturnResult> {
const result = await fetch(`https://reddit.com/r/${subreddit}/${sortBy}.json?limit=100`)
.then((res) => {
return res;

View file

@ -1,4 +1,4 @@
import ImageHelper from "../src/imageHelper";
import ImageHelper from "../../src/helpers/imageHelper";
import fetch from "got-cjs";
jest.mock('got-cjs');

View file

@ -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";
@ -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,39 +69,7 @@ describe('randomBunny', () => {
expect(result.Result).toBeDefined();
expect(result.Error).toBeUndefined();
expect(fetchMock).toBeCalledWith('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 its 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).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 +84,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 +101,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 +157,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 +191,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");