diff --git a/front-end/tests/hashtag.spec.mjs b/front-end/tests/hashtag.spec.mjs new file mode 100644 index 0000000..2418580 --- /dev/null +++ b/front-end/tests/hashtag.spec.mjs @@ -0,0 +1,31 @@ +import { test, expect } from "@playwright/test"; + +test("should not make infinite hashtag endpoint requests", async ({ page }) => { + // ===== ARRANGE + const requests = []; + const hashtag = "SwizBiz"; + + page.on("request", (request) => { + if ( + request.url().includes(`:3000/hashtag/${hashtag}`) && + request.resourceType() === "fetch" + ) { + requests.push(request); + } + }); + // ====== ACT + // When I navigate to the hashtag + await page.goto(`/#/hashtag/${hashtag}`); + + // Wait for the hashtag API to respond before continuing + await page.waitForResponse( + (response) => + response.url().includes(`/hashtag/${hashtag}`) && + response.status() === 200, + ); + + // ====== ASSERT + // Then the number of requests should be 1 + console.log("Number of requests:", requests.length); + expect(requests.length).toEqual(1); +}); diff --git a/front-end/views/hashtag.mjs b/front-end/views/hashtag.mjs index 7b7e996..c63005e 100644 --- a/front-end/views/hashtag.mjs +++ b/front-end/views/hashtag.mjs @@ -17,14 +17,29 @@ import {createHeading} from "../components/heading.mjs"; function hashtagView(hashtag) { destroy(); - apiService.getBloomsByHashtag(hashtag); + // Normalize the hashtag to always include a leading '#' and + // prevent infinite API calls by only fetching if the hashtag has changed + const normalizedHashtag = hashtag.startsWith("#") ? hashtag : `#${hashtag}`; + if (state.currentHashtag !== normalizedHashtag) { + // Update state only if the hashtag changed + state.currentHashtag = normalizedHashtag; + + // Fetch blooms for the new hashtag + apiService.getBloomsByHashtag(normalizedHashtag).then(()=>{ + // Check that the hashtag is still current to avoid old data + if (state.currentHashtag === normalizedHashtag){ + // Nothing to do here for now + } + }); + } renderOne( state.isLoggedIn, getLogoutContainer(), "logout-template", - createLogout + createLogout, ); + document .querySelector("[data-action='logout']") ?.addEventListener("click", handleLogout); @@ -32,7 +47,7 @@ function hashtagView(hashtag) { state.isLoggedIn, getLoginContainer(), "login-template", - createLogin + createLogin, ); document .querySelector("[data-action='login']") @@ -42,13 +57,13 @@ function hashtagView(hashtag) { state.currentHashtag, getHeadingContainer(), "heading-template", - createHeading + createHeading, ); renderEach( state.hashtagBlooms || [], getTimelineContainer(), "bloom-template", - createBloom + createBloom, ); }