diff --git a/src/scripts/dad-joke.js b/src/scripts/dad-joke.js index 1d5eccf..904152d 100644 --- a/src/scripts/dad-joke.js +++ b/src/scripts/dad-joke.js @@ -1,13 +1,12 @@ const { directMention } = require("@slack/bolt"); -const axios = require("axios"); +const fs = require("node:fs/promises"); const { - cache, helpMessage, stats: { incrementStats }, } = require("../utils"); const sample = require("../utils/sample"); -module.exports = (app) => { +module.exports = async (app) => { helpMessage.registerInteractive( "Dad Jokes", "dad joke", @@ -15,30 +14,16 @@ module.exports = (app) => { true, ); + const jokes = JSON.parse( + await fs.readFile("./dad-joke.json", { encoding: "utf-8" }), + ); + app.message( directMention, /dad joke/i, async ({ message: { thread_ts: thread }, say }) => { incrementStats("dad joke"); - const jokes = await cache("dad jokes", 60, async () => { - try { - const { data } = await axios.get( - "https://fatherhood.gov/jsonapi/node/dad_jokes", - ); - - if (data && data.data) { - return data.data.map((joke) => ({ - setup: joke.attributes.field_joke_opener, - punchline: joke.attributes.field_joke_response, - })); - } - return []; - } catch (e) { - return []; - } - }); - const joke = sample(jokes); if (joke) { say({ diff --git a/src/scripts/dad-joke.json b/src/scripts/dad-joke.json new file mode 100644 index 0000000..da4e3c0 --- /dev/null +++ b/src/scripts/dad-joke.json @@ -0,0 +1,187 @@ +[ + { + "setup": "Why did the scarecrow win an award?", + "punchline": "He was outstanding in his field." + }, + { + "setup": "Did you hear about the two satellites that got married?", + "punchline": "The wedding wasn't much, but the reception was incredible." + }, + { "setup": "February can't March.", "punchline": "But April May!" }, + { + "setup": "Why don't crabs ever give to charity?", + "punchline": "Because they're shellfish." + }, + { + "setup": "Why did the carpenter leave the lumber store?", + "punchline": "Because he got bored." + }, + { + "setup": "Why did the snake go to the doctor?", + "punchline": "Because he had a frog in his throat." + }, + { + "setup": "Why did the ghost buy a box of bandages?", + "punchline": "Because he had so many BOO BOOs." + }, + { + "setup": "What's the difference between the moon and a cheeseburger?", + "punchline": "The moon is in the sky, a cheeseburger is in THIS guy. (Points to belly)" + }, + { + "setup": "If I asked you to choose your favorite feature, would you...", + "punchline": "...pick your nose?" + }, + { + "setup": "Why did the astronaut move to the suburbs?", + "punchline": "He wanted more space." + }, + { + "setup": "Why did the pizza cutter get a speeding ticket?", + "punchline": "Because he was rounding the corner too fast." + }, + { + "setup": "What's big and hairy and wears a bow tie?", + "punchline": "Bigfoot at a fancy party." + }, + { + "setup": "Did you hear the one about the Ballerina Debate Team?", + "punchline": "They always stay on point." + }, + { + "setup": "Have you heard about the sale at the Optimist Store?", + "punchline": "Everything's 50% on." + }, + { + "setup": "Why do optimists have to wear sunglasses?", + "punchline": "Because they're always looking on the bright side." + }, + { + "setup": "Where do fancy cats go to the bathroom?", + "punchline": "The glitter box." + }, + { + "setup": "Why did the golf course hire the dermatologist?", + "punchline": "It needed to have some moles removed." + }, + { + "setup": "Did you hear about the world's greatest watch thief?", + "punchline": "He stole all the time." + }, + { + "setup": "Why was the basketball court all wet?", + "punchline": "People kept dribbling all over it." + }, + { + "setup": "How do you make a bandstand?", + "punchline": "Take away all of the chairs." + }, + { + "setup": "What do you call cheese that's not yours?", + "punchline": "Nacho cheese." + }, + { "setup": "What do you call a fake noodle?", "punchline": "An impasta!" }, + { + "setup": "What kind of tree fits in your hand?", + "punchline": "A palm tree." + }, + { "setup": "How do trees get on the internet?", "punchline": "They log on." }, + { + "setup": "Did you hear about the new book on anti-gravity?", + "punchline": "It's impossible to put down." + }, + { + "setup": "Hear about the guy that got fired from the calendar factory?", + "punchline": "He took too many days off." + }, + { + "setup": "Did you hear about the circus fire?", + "punchline": "It was in tents." + }, + { + "setup": "Do you know what the loudest pet is?", + "punchline": "A trumpet." + }, + { + "setup": "What did the buffalo say to his son when he dropped him off at school?", + "punchline": "Bison" + }, + { + "setup": "What did the ocean say to the shore?", + "punchline": "Nothing. It just waved." + }, + { + "setup": "What did the beaver say to the tree?", + "punchline": "It's been nice gnawing you." + }, + { + "setup": "Hear about the lazy kangaroo?", + "punchline": "He was a real pouch potato." + }, + { + "setup": "Did you hear about the restaurant they're building on the moon?", + "punchline": "The food is supposed to be great, but there's no atmosphere." + }, + { + "setup": "What do you call a man with a rubber toe?", + "punchline": "Roberto." + }, + { + "setup": "Why do you never see elephants hiding in trees?", + "punchline": "Because they're really good at it." + }, + { + "setup": "Hear about the guy that wanted to buy a pair of camouflage pants?", + "punchline": "He couldn't find them anywhere." + }, + { + "setup": "I couldn't figure out the seat belts in my new car...", + "punchline": "...but then it clicked." + }, + { + "setup": "Have you heard the pizza joke that's going around the internet?", + "punchline": "It's a little cheesy." + }, + { "setup": "What's red and smells like paint?", "punchline": "Red paint." }, + { + "setup": "Hear about the guy that stayed up all night wondering where the sun had gone?", + "punchline": "It finally dawned on him." + }, + { + "setup": "Did you hear that they invented a new type broom?", + "punchline": "It's sweeping the nation." + }, + { "setup": "What is brown and sticky?", "punchline": "A stick." }, + { + "setup": "What's more amazing than a talking dog?", + "punchline": "A spelling bee." + }, + { + "setup": "A man went to the doctor. He had a cucumber in one ear. A hot dog in the other ear. And two carrots stuck up his nose. He asked the doctor what was wrong with him and the doctor said:", + "punchline": "\"I don't think you're eating properly.\"" + }, + { + "setup": "What do you call a pony with a sore throat?", + "punchline": "A little horse." + }, + { + "setup": "I used to really hate facial hair.", + "punchline": "Then one day, it grew on me." + }, + { + "setup": "How many apples grow on an apple tree?", + "punchline": "All of them." + }, + { + "setup": "Do you know the name of the boy wizard that loved to play golf?", + "punchline": "Harry Putter." + }, + { + "setup": "Why do bees hum?", + "punchline": "Because they don't know the words." + }, + { + "setup": "What do you get when you cross a snowman with a vampire?", + "punchline": "Frost-bitten." + } +] diff --git a/src/scripts/dad-joke.test.js b/src/scripts/dad-joke.test.js index 8d6088c..f4027e2 100644 --- a/src/scripts/dad-joke.test.js +++ b/src/scripts/dad-joke.test.js @@ -1,16 +1,16 @@ -const { - axios, - getApp, - utils: { cache }, -} = require("../utils/test"); +const fs = require("node:fs/promises"); +const { getApp } = require("../utils/test"); const script = require("./dad-joke"); +jest.mock("fs"); + describe("dad jokes (are the best worst)", () => { const app = getApp(); beforeAll(() => { jest.useFakeTimers(); + fs.readFile = jest.fn(); }); beforeEach(() => { @@ -21,8 +21,11 @@ describe("dad jokes (are the best worst)", () => { jest.useRealTimers(); }); - it("subscribes to dad joke requests", () => { - script(app); + it("subscribes to dad joke requests", async () => { + fs.readFile.mockResolvedValue("[]"); + + await script(app); + expect(app.message).toHaveBeenCalledWith( expect.any(Function), /dad joke/i, @@ -32,114 +35,39 @@ describe("dad jokes (are the best worst)", () => { describe("response to joke requests", () => { let handler; - beforeEach(() => { - script(app); + beforeEach(async () => { + fs.readFile.mockResolvedValue( + JSON.stringify([ + { setup: "joke setup here", punchline: "the funny part" }, + ]), + ); + + await script(app); handler = app.getHandler(); }); const message = { message: { thread_ts: "thread id" }, say: jest.fn() }; - it("fetches jokes from a cache", async () => { - cache.mockResolvedValue([]); + it("responds with a joke", async () => { await handler(message); - expect(cache).toHaveBeenCalledWith("dad jokes", 60, expect.any(Function)); - }); - - describe("gets jokes from fatherhood.gov if the cache is expired or whatever", () => { - let fetch; - beforeEach(async () => { - cache.mockResolvedValue([]); - await handler(message); - fetch = cache.mock.calls[0][2]; - }); - - it("if the API throws an error", async () => { - axios.get.mockRejectedValue("error"); - const out = await fetch(); - - expect(out).toEqual([]); - }); - - it("if the API returns a malformed object", async () => { - axios.get.mockResolvedValue({ data: { data_is_missing: [] } }); - const out = await fetch(); - - expect(out).toEqual([]); - }); - - it("if the API doesn't return any jokes", async () => { - axios.get.mockResolvedValue({ data: { data: [] } }); - const out = await fetch(); - expect(out).toEqual([]); + expect(message.say).toHaveBeenCalledWith({ + icon_emoji: ":dog-joke-setup:", + text: "joke setup here", + thread_ts: "thread id", + username: "Jed Bartlett", }); - it("if the API does return some jokes", async () => { - axios.get.mockResolvedValue({ - data: { - data: [ - { - attributes: { - field_joke_opener: "setup 1", - field_joke_response: "punchline 1", - }, - }, - { - attributes: { - field_joke_opener: "setup 2", - field_joke_response: "punchline 2", - }, - }, - { - attributes: { - field_joke_opener: "setup 3", - field_joke_response: "punchline 3", - }, - }, - ], - }, - }); - const out = await fetch(); - - expect(out).toEqual([ - { setup: "setup 1", punchline: "punchline 1" }, - { setup: "setup 2", punchline: "punchline 2" }, - { setup: "setup 3", punchline: "punchline 3" }, - ]); - }); - }); + // Ensure the punchline part comes after a delay by clearing out the + // existing mock calls. + message.say.mockClear(); + jest.advanceTimersByTime(5000); - describe("responds with a joke", () => { - it("unless there aren't any jokes", async () => { - cache.mockResolvedValue([]); - await handler(message); - expect(message.say).not.toHaveBeenCalled(); - }); - - it("if there is at least one joke", async () => { - cache.mockResolvedValue([ - { setup: "joke setup here", punchline: "the funny part" }, - ]); - await handler(message); - - expect(message.say).toHaveBeenCalledWith({ - icon_emoji: ":dog-joke-setup:", - text: "joke setup here", - thread_ts: "thread id", - username: "Jed Bartlett", - }); - - // Ensure the punchline part comes after a delay by clearing out the - // existing mock calls. - message.say.mockClear(); - jest.advanceTimersByTime(5000); - - expect(message.say).toHaveBeenCalledWith({ - icon_emoji: ":dog-joke:", - text: "the funny part", - thread_ts: "thread id", - username: "Jed \u200bBartlett", - }); + expect(message.say).toHaveBeenCalledWith({ + icon_emoji: ":dog-joke:", + text: "the funny part", + thread_ts: "thread id", + username: "Jed \u200bBartlett", }); }); });