Compare commits

..

No commits in common. "8a726b386ed0d995de81ca7816f3b005a4a229bd" and "27e08e6f866c67e2c425e13aa428b4cc34475613" have entirely different histories.

6 changed files with 11 additions and 252 deletions

View file

@ -1,6 +1,6 @@
{ {
"name": "random-bunny", "name": "random-bunny",
"version": "2.1.6", "version": "2.1.5",
"description": "Get a random subreddit image url", "description": "Get a random subreddit image url",
"license": "MIT", "license": "MIT",
"author": "Vylpes", "author": "Vylpes",
@ -18,7 +18,6 @@
"dependencies": { "dependencies": {
"glob-parent": "^6.0.0", "glob-parent": "^6.0.0",
"got-cjs": "^12.5.4", "got-cjs": "^12.5.4",
"htmlparser2": "^9.1.0",
"linqts": "^1.14.4" "linqts": "^1.14.4"
}, },
"scripts": { "scripts": {

View file

@ -1,19 +0,0 @@
import fetch from "got-cjs";
import * as htmlparser from "htmlparser2";
export default class ImageHelper {
public static async FetchImageFromRedditGallery(url: string): Promise<string | undefined> {
const fetched = await fetch(url);
if (!fetched || fetched.errored || fetched.statusCode != 200) {
return undefined;
}
const dom = htmlparser.parseDocument(fetched.body);
const img = htmlparser.DomUtils.findOne((x => x.tagName == "img" && x.attributes.find(y => y.value.includes("https://preview.redd.it")) != null), dom.children, true);
const imgSrc = img?.attributes.find(x => x.name == "src")?.value;
return imgSrc;
}
}

View file

@ -3,7 +3,6 @@ import IRedditResult from "./contracts/IRedditResult.js";
import fetch from "got-cjs"; import fetch from "got-cjs";
import { List } from 'linqts'; import { List } from 'linqts';
import IFetchResult from "./contracts/IFetchResult.js"; import IFetchResult from "./contracts/IFetchResult.js";
import ImageHelper from "./imageHelper";
const sortable = [ const sortable = [
'new', 'new',
@ -14,7 +13,7 @@ const sortable = [
export default async function randomBunny(subreddit: string, sortBy?: string): Promise<IReturnResult> { export default async function randomBunny(subreddit: string, sortBy?: string): Promise<IReturnResult> {
if (!sortBy || !sortable.includes(sortBy)) sortBy = 'hot'; if (!sortBy || !sortable.includes(sortBy)) sortBy = 'hot';
const result = await fetch(`https://reddit.com/r/${subreddit}/${sortBy}.json?limit=100`); const result = await fetch(`https://reddit.com/r/${subreddit}/${sortBy}.json`);
if (!result) { if (!result) {
return { return {
@ -33,7 +32,7 @@ export default async function randomBunny(subreddit: string, sortBy?: string): P
const data: IFetchResult[] = json.data.children; const data: IFetchResult[] = json.data.children;
const dataWithImages = new List<IFetchResult>(data) const dataWithImages = new List<IFetchResult>(data)
.Where(x => x!.data.url.includes('.jpg') || x!.data.url.includes('.png') || x!.data.url.includes("/gallery/")) .Where(x => x!.data.url.includes('.jpg') || x!.data.url.includes('.png'))
.ToArray(); .ToArray();
let random = 0; let random = 0;
@ -50,22 +49,6 @@ export default async function randomBunny(subreddit: string, sortBy?: string): P
const randomData = randomSelect.data; const randomData = randomSelect.data;
let url: string;
if (randomData.url.includes("/gallery")) {
const galleryImage = await ImageHelper.FetchImageFromRedditGallery(randomData.url);
if (!galleryImage) {
return {
IsSuccess: false,
}
}
url = galleryImage;
} else {
url = randomData.url;
}
const redditResult: IRedditResult = { const redditResult: IRedditResult = {
Archived: randomData['archived'], Archived: randomData['archived'],
Downs: randomData['downs'], Downs: randomData['downs'],
@ -75,7 +58,7 @@ export default async function randomBunny(subreddit: string, sortBy?: string): P
SubredditSubscribers: randomData['subreddit_subscribers'], SubredditSubscribers: randomData['subreddit_subscribers'],
Title: randomData['title'], Title: randomData['title'],
Ups: randomData['ups'], Ups: randomData['ups'],
Url: url, Url: randomData['url']
}; };
return { return {

View file

@ -1,90 +0,0 @@
import ImageHelper from "../src/imageHelper";
import fetch from "got-cjs";
jest.mock('got-cjs');
const fetchMock = jest.mocked(fetch);
describe("FetchImageFromRedditGallery", () => {
test("EXPECT image url to be returned", async () => {
fetchMock.mockResolvedValue({
body: "<html><body><img src='https://preview.redd.it/image.png' /></body></html>",
errored: undefined,
statusCode: 200,
});
const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image");
expect(fetchMock).toHaveBeenCalledTimes(1);
expect(fetchMock).toHaveBeenCalledWith("https://redd.it/gallery/image");
expect(result).toBe("https://preview.redd.it/image.png");
});
test("GIVEN fetch is unable to return data, EXPECT undefined returned", async () => {
fetchMock.mockResolvedValue(null);
const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image");
expect(result).toBeUndefined();
});
test("GIVEN fetch is an error, EXPECT undefined returned", async () => {
fetchMock.mockResolvedValue({
body: "<html><body><img src='https://preview.redd.it/image.png' /></body></html>",
errored: "Error",
statusCode: 200,
});
const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image");
expect(result).toBeUndefined();
});
test("GIVEN fetch is not status code of 200, EXPECT undefined returned", async () => {
fetchMock.mockResolvedValue({
body: "<html><body><img src='https://preview.redd.it/image.png' /></body></html>",
errored: undefined,
statusCode: 500,
});
const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image");
expect(result).toBeUndefined();
});
test("GIVEN image tag is not found, EXPECT undefined returned", async () => {
fetchMock.mockResolvedValue({
body: "<html><body></body></html>",
errored: undefined,
statusCode: 200,
});
const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image");
expect(result).toBeUndefined();
});
test("GIVEN image source attribute is not found, EXPECT undefined returned", async () => {
fetchMock.mockResolvedValue({
body: "<html><body><img /></body></html>",
errored: undefined,
statusCode: 200,
});
const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image");
expect(result).toBeUndefined();
});
test("GIVEN image source attribute is not found that is a preview.redd.it url, EXPECT undefined returned", async () => {
fetchMock.mockResolvedValue({
body: "<html><body><img src='main.png' /></body></html>",
errored: undefined,
statusCode: 200,
});
const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image");
expect(result).toBeUndefined();
});
});

View file

@ -1,4 +1,3 @@
import ImageHelper from "../src/imageHelper";
import randomBunny from "../src/index"; import randomBunny from "../src/index";
import fetch from "got-cjs"; import fetch from "got-cjs";
@ -34,7 +33,7 @@ describe('randomBunny', () => {
expect(result.IsSuccess).toBeTruthy(); expect(result.IsSuccess).toBeTruthy();
expect(result.Result).toBeDefined(); expect(result.Result).toBeDefined();
expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json');
}); });
test('GIVEN sortBy is NOT supplied, expect it to default to hot', async () => { test('GIVEN sortBy is NOT supplied, expect it to default to hot', async () => {
@ -65,7 +64,7 @@ describe('randomBunny', () => {
expect(result.IsSuccess).toBeTruthy(); expect(result.IsSuccess).toBeTruthy();
expect(result.Result).toBeDefined(); expect(result.Result).toBeDefined();
expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/hot.json?limit=100'); expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/hot.json');
}); });
test('GIVEN sortBy is NOT valid, expect it to default to hot', async () => { test('GIVEN sortBy is NOT valid, expect it to default to hot', async () => {
@ -96,7 +95,7 @@ describe('randomBunny', () => {
expect(result.IsSuccess).toBeTruthy(); expect(result.IsSuccess).toBeTruthy();
expect(result.Result).toBeDefined(); expect(result.Result).toBeDefined();
expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/hot.json?limit=100'); expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/hot.json');
}); });
test('GIVEN the fetch fails, EXPECT failure result', async () => { test('GIVEN the fetch fails, EXPECT failure result', async () => {
@ -107,7 +106,7 @@ describe('randomBunny', () => {
expect(result.IsSuccess).toBeFalsy(); expect(result.IsSuccess).toBeFalsy();
expect(result.Result).toBeUndefined(); expect(result.Result).toBeUndefined();
expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json');
}); });
test('GIVEN the result is NOT valid JSON, EXPECT failure result', async () => { test('GIVEN the result is NOT valid JSON, EXPECT failure result', async () => {
@ -120,7 +119,7 @@ describe('randomBunny', () => {
expect(result.IsSuccess).toBeFalsy(); expect(result.IsSuccess).toBeFalsy();
expect(result.Result).toBeUndefined(); expect(result.Result).toBeUndefined();
expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json');
}); });
test('GIVEN randomSelect does NOT find a response, EXPECT failure result', async () => { test('GIVEN randomSelect does NOT find a response, EXPECT failure result', async () => {
@ -137,7 +136,7 @@ describe('randomBunny', () => {
expect(result.IsSuccess).toBeFalsy(); expect(result.IsSuccess).toBeFalsy();
expect(result.Result).toBeUndefined(); expect(result.Result).toBeUndefined();
expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json');
}); });
test('GIVEN randomSelect does NOT find a valid response, EXPECT failure result', async () => { test('GIVEN randomSelect does NOT find a valid response, EXPECT failure result', async () => {
@ -168,74 +167,6 @@ describe('randomBunny', () => {
expect(result.IsSuccess).toBeFalsy(); expect(result.IsSuccess).toBeFalsy();
expect(result.Result).toBeUndefined(); expect(result.Result).toBeUndefined();
expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json?limit=100'); expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json');
});
test("GIVEN data fetched is a gallery AND an image is returned from the helper, EXPECT this to be used", 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/gallery/cr8xudsnkgua1',
},
},
],
}
}),
});
ImageHelper.FetchImageFromRedditGallery = jest.fn().mockResolvedValue("https://i.redd.it/cr8xudsnkgua1.jpg")
const result = await randomBunny('rabbits', 'new');
expect(result.IsSuccess).toBeTruthy();
expect(result.Result).toBeDefined();
expect(fetchMock).toBeCalledWith('https://reddit.com/r/rabbits/new.json?limit=100');
expect(ImageHelper.FetchImageFromRedditGallery).toHaveBeenCalledTimes(1);
expect(ImageHelper.FetchImageFromRedditGallery).toHaveBeenCalledWith("https://i.redd.it/gallery/cr8xudsnkgua1")
});
test("GIVEN data fetched is a gallery AND an image is not returned from the helper, EXPECT error", 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/gallery/cr8xudsnkgua1',
},
},
],
}
}),
});
ImageHelper.FetchImageFromRedditGallery = jest.fn().mockResolvedValue(undefined)
const result = await randomBunny('rabbits', 'new');
expect(ImageHelper.FetchImageFromRedditGallery).toHaveBeenCalledTimes(1);
expect(result.IsSuccess).toBe(false);
}); });
}); });

View file

@ -1716,36 +1716,6 @@ doctrine@^3.0.0:
dependencies: dependencies:
esutils "^2.0.2" esutils "^2.0.2"
dom-serializer@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53"
integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==
dependencies:
domelementtype "^2.3.0"
domhandler "^5.0.2"
entities "^4.2.0"
domelementtype@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
domhandler@^5.0.2, domhandler@^5.0.3:
version "5.0.3"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31"
integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
dependencies:
domelementtype "^2.3.0"
domutils@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e"
integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==
dependencies:
dom-serializer "^2.0.0"
domelementtype "^2.3.0"
domhandler "^5.0.3"
dot-prop@^5.2.0: dot-prop@^5.2.0:
version "5.3.0" version "5.3.0"
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
@ -1787,11 +1757,6 @@ end-of-stream@^1.1.0:
dependencies: dependencies:
once "^1.4.0" once "^1.4.0"
entities@^4.2.0, entities@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
error-ex@^1.3.1: error-ex@^1.3.1:
version "1.3.2" version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
@ -2321,16 +2286,6 @@ html-escaper@^2.0.0:
resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
htmlparser2@^9.1.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-9.1.0.tgz#cdb498d8a75a51f739b61d3f718136c369bc8c23"
integrity sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==
dependencies:
domelementtype "^2.3.0"
domhandler "^5.0.3"
domutils "^3.1.0"
entities "^4.5.0"
http-cache-semantics@^4.0.0: http-cache-semantics@^4.0.0:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"