From 3992b8c6b6f5115bb727b47a959ed11f05dd3734 Mon Sep 17 00:00:00 2001 From: Sara Tahir Date: Fri, 30 Jan 2026 22:52:02 +0000 Subject: [PATCH 1/3] Fixing the infinite loop --- front-end/views/hashtag.mjs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/front-end/views/hashtag.mjs b/front-end/views/hashtag.mjs index 7b7e996..19b723e 100644 --- a/front-end/views/hashtag.mjs +++ b/front-end/views/hashtag.mjs @@ -15,10 +15,21 @@ import {createHeading} from "../components/heading.mjs"; // Hashtag view: show all tweets containing this tag function hashtagView(hashtag) { - destroy(); + destroy();// Tear down any previously rendered view before drawing this one. + const formattedHashtag = hashtag.startsWith('#') ? hashtag : `#${hashtag}`;// Ensure the hashtag always has a leading '#' so comparisons are reliable. + //Only fetch data if the hashtag has changed since the last render. + // This prevents infinite loops caused by re-renders or route updates. + if (state.currentHashtag !== formattedHashtag) { + state.currentHashtag = hashtag; // Store the new hashtag BEFORE fetching so the next render sees the update. + apiService.getBloomsByHashtag(hashtag); // Retrieve all blooms associated with this hashtag from the API. + } +<<<<<<< Updated upstream apiService.getBloomsByHashtag(hashtag); +======= + +>>>>>>> Stashed changes renderOne( state.isLoggedIn, getLogoutContainer(), From 317167b8fe57369acbcc861e1e6761bbd7ae9efb Mon Sep 17 00:00:00 2001 From: Sara Tahir Date: Fri, 30 Jan 2026 23:03:57 +0000 Subject: [PATCH 2/3] Fixing the infinite loop, using test from prep to ensure the fix is working. Also updated settings to get backend running --- .vscode/settings.json | 3 ++- front-end/tests/hashtag.spec.mjs | 24 ++++++++++++++++++++++++ front-end/views/hashtag.mjs | 6 +----- 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 front-end/tests/hashtag.spec.mjs diff --git a/.vscode/settings.json b/.vscode/settings.json index 166be53..547ec79 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { "liveServer.settings.root": "front-end/", - "python.defaultInterpreterPath": "backend/.venv/bin/python" + "python.defaultInterpreterPath": "backend/.venv/bin/python", + "liveServer.settings.port": 5501 } diff --git a/front-end/tests/hashtag.spec.mjs b/front-end/tests/hashtag.spec.mjs new file mode 100644 index 0000000..f5b6d5d --- /dev/null +++ b/front-end/tests/hashtag.spec.mjs @@ -0,0 +1,24 @@ +import { test, expect } from "@playwright/test" + + +test("should not make infinite hashtag endpoint requests", async ({ page }) => { + // ===== ARRANGE + const requests = []; + page.on("request", (request) => { + if ( + request.url().includes(":3000/hashtag/do") && + request.resourceType() === "fetch" + ) { + requests.push(request); + } + }); + // ====== ACT + // When I navigate to the hashtag + await page.goto("/#/hashtag/do"); + // And I wait a reasonable time for any additional requests + await page.waitForTimeout(200); + + // ====== ASSERT + // Then the number of requests should be 1 + expect(requests.length).toEqual(1); +}); \ No newline at end of file diff --git a/front-end/views/hashtag.mjs b/front-end/views/hashtag.mjs index 19b723e..1d1718f 100644 --- a/front-end/views/hashtag.mjs +++ b/front-end/views/hashtag.mjs @@ -24,12 +24,8 @@ function hashtagView(hashtag) { apiService.getBloomsByHashtag(hashtag); // Retrieve all blooms associated with this hashtag from the API. } -<<<<<<< Updated upstream - apiService.getBloomsByHashtag(hashtag); + -======= - ->>>>>>> Stashed changes renderOne( state.isLoggedIn, getLogoutContainer(), From 1efcbd764c0bf32d3d19f38114f4a643c9f4139b Mon Sep 17 00:00:00 2001 From: Sara Tahir Date: Wed, 4 Feb 2026 16:25:42 +0000 Subject: [PATCH 3/3] =?UTF-8?q?Replaced=20the=20fixed=20waitForTimeout(200?= =?UTF-8?q?)=20in=20the=20hashtag=20test=20with=20a=20=20UI=E2=80=91based?= =?UTF-8?q?=20wait=20using=20the=20first=20[data-bloom]=20element,=20Also?= =?UTF-8?q?=20Updated=20hashtagView=20to=20only=20update=20state.currentHa?= =?UTF-8?q?shtag=20and=20trigger=20a=20fetch=20when=20the=20formatted=20ha?= =?UTF-8?q?shtag=20changes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front-end/tests/hashtag.spec.mjs | 4 ++-- front-end/views/hashtag.mjs | 13 ++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/front-end/tests/hashtag.spec.mjs b/front-end/tests/hashtag.spec.mjs index f5b6d5d..06cca83 100644 --- a/front-end/tests/hashtag.spec.mjs +++ b/front-end/tests/hashtag.spec.mjs @@ -15,8 +15,8 @@ test("should not make infinite hashtag endpoint requests", async ({ page }) => { // ====== ACT // When I navigate to the hashtag await page.goto("/#/hashtag/do"); - // And I wait a reasonable time for any additional requests - await page.waitForTimeout(200); + //Wait for the UI to show the blooms have loaded + await page.locator("[data-bloom]").first().waitFor(); // ====== ASSERT // Then the number of requests should be 1 diff --git a/front-end/views/hashtag.mjs b/front-end/views/hashtag.mjs index 1d1718f..cae20bb 100644 --- a/front-end/views/hashtag.mjs +++ b/front-end/views/hashtag.mjs @@ -14,16 +14,15 @@ import {createHeading} from "../components/heading.mjs"; // Hashtag view: show all tweets containing this tag -function hashtagView(hashtag) { + function hashtagView(hashtag) { destroy();// Tear down any previously rendered view before drawing this one. const formattedHashtag = hashtag.startsWith('#') ? hashtag : `#${hashtag}`;// Ensure the hashtag always has a leading '#' so comparisons are reliable. - //Only fetch data if the hashtag has changed since the last render. - // This prevents infinite loops caused by re-renders or route updates. + if (state.currentHashtag !== formattedHashtag) { - state.currentHashtag = hashtag; // Store the new hashtag BEFORE fetching so the next render sees the update. - apiService.getBloomsByHashtag(hashtag); // Retrieve all blooms associated with this hashtag from the API. + state.currentHashtag = formattedHashtag; + apiService.getBloomsByHashtag(formattedHashtag); } - + renderOne( @@ -57,6 +56,6 @@ function hashtagView(hashtag) { "bloom-template", createBloom ); -} + } export {hashtagView};