Skip to content

Commit 5b49edc

Browse files
authored
bookmarkcard.tsx and test.tsx file changed (#336)
1 parent 85cfd25 commit 5b49edc

2 files changed

Lines changed: 102 additions & 21 deletions

File tree

frontend/__tests__/Bookmark/NewBookmarkCard.test.tsx

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ describe("Fields logic", () => {
5757
await user.click(toggle);
5858
expect(submit).not.toBeDisabled();
5959

60-
// fields should be populated
60+
// Fields should be populated
6161
expect(url).toHaveValue("https://foodnetwork.com");
6262

6363
const axiosMock = new MockAdapter(instance);
@@ -103,7 +103,7 @@ describe("Fields logic", () => {
103103

104104
await user.click(submit);
105105

106-
// if everything submitted correctly then it should be empty input field.
106+
// If submitted correctly, the fields should be reset.
107107
expect(url).toHaveValue("");
108108
expect(tags).toHaveValue("");
109109
expect(submit).toBeDisabled();
@@ -171,7 +171,7 @@ describe("Fields logic", () => {
171171
await user.type(tags, "food");
172172
expect(submit).not.toBeDisabled();
173173

174-
// fields should be populated
174+
// Fields should be populated
175175
expect(url).toHaveValue("https://foodnetwork.com");
176176

177177
const axiosMock = new MockAdapter(instance);
@@ -226,7 +226,7 @@ describe("Fields logic", () => {
226226

227227
await user.click(submit);
228228

229-
// if everything submitted correctly then it should be empty input field.
229+
// If submitted correctly, the fields should be reset.
230230
expect(url).toHaveValue("");
231231
expect(tags).toHaveValue("");
232232
expect(submit).toBeDisabled();
@@ -276,3 +276,77 @@ describe("Tags Operations", () => {
276276
expect(screen.queryByTestId("Tag2")).toEqual(null);
277277
});
278278
});
279+
280+
describe("Success Toast", () => {
281+
it("displays a green success toast when bookmark is added successfully", async () => {
282+
render(
283+
<div data-bs-theme="dark" className="row pt-3">
284+
<div className="col-6 col-sm-12 col-md-12 col-lg-4">
285+
<NewBookmarkCard />
286+
</div>
287+
</div>,
288+
);
289+
290+
const submit = screen.getByText("Submit");
291+
const tagsInput = screen.getByPlaceholderText("Enter a tag");
292+
const urlInput = screen.getByPlaceholderText(/discover/i);
293+
294+
// Type in the URL (it will be prefixed with "https://")
295+
await user.type(urlInput, "example.com");
296+
expect(urlInput).toHaveValue("https://example.com");
297+
298+
// Type a tag and add it
299+
await user.type(tagsInput, "testtag");
300+
await user.type(tagsInput, "{enter}");
301+
302+
// Setup axios mocks for API calls
303+
const axiosMock = new MockAdapter(instance);
304+
const SERVER_URL = process.env.NEXT_PUBLIC_SERVER_URL;
305+
const tagsAPI = SERVER_URL + "/api/tags";
306+
const bookmarkAPI = SERVER_URL + "/api/bookmark";
307+
308+
const expectedResult = [
309+
{
310+
id: 1,
311+
title: "testtag",
312+
bookmarks: [],
313+
},
314+
];
315+
316+
const expectedBookmark: Bookmark = {
317+
id: 1,
318+
title: "example.com",
319+
url: "https://example.com",
320+
tags: [
321+
{
322+
id: 1,
323+
title: "testtag",
324+
},
325+
],
326+
screenshotUrl: "",
327+
scrapable: true,
328+
};
329+
330+
axiosMock.onPost(tagsAPI, ["testtag"]).reply(() => {
331+
return [200, expectedResult];
332+
});
333+
334+
axiosMock
335+
.onPost(bookmarkAPI, {
336+
title: "https://example.com",
337+
url: "https://example.com",
338+
tagIds: [1],
339+
scrapable: true,
340+
})
341+
.reply(() => {
342+
return [200, expectedBookmark];
343+
});
344+
345+
await user.click(submit);
346+
347+
// Wait for the success toast to appear
348+
expect(
349+
await screen.findByText("Bookmark added successfully!")
350+
).toBeInTheDocument();
351+
});
352+
});

frontend/components/Bookmark/NewBookmarkCard.tsx

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,14 @@ import { AxiosError, AxiosResponse } from "axios";
2020
import { ScrapableNewBookmarkToggle } from "./ScrapableToggle";
2121

2222
async function makeNewBookmark(createBmk: Bookmark): Promise<Bookmark> {
23-
let newBkmkRequest: NewBookmarkRequest;
24-
newBkmkRequest = {
23+
let newBkmkRequest: NewBookmarkRequest = {
2524
title: createBmk.title,
2625
url: createBmk.url,
2726
tagIds: [],
2827
scrapable: createBmk.scrapable,
2928
};
3029
console.log(createBmk.scrapable);
31-
let tagTitles: string[] = createBmk.tags.map((t) => {
32-
return t.title;
33-
});
30+
let tagTitles: string[] = createBmk.tags.map((t) => t.title);
3431

3532
await api.addAllTag(tagTitles).then((response) => {
3633
let respTags: Tag[] = response.data;
@@ -55,16 +52,27 @@ async function makeNewBookmark(createBmk: Bookmark): Promise<Bookmark> {
5552
theme: "colored",
5653
});
5754
}
58-
5955
return;
6056
}
6157
if (!(response instanceof AxiosError)) {
62-
console.log(response.data.scrapable);
58+
// Update the bookmark with the response data
6359
createBmk.id = response.data.id;
6460
createBmk.tags = response.data.tags;
6561
createBmk.screenshotUrl = response.data.screenshotUrl;
6662
createBmk.scrapable = response.data.scrapable;
6763
createBmk.title = response.data.title;
64+
65+
// Show a green success toast for a successful add
66+
toast.success("Bookmark added successfully!", {
67+
position: "bottom-right",
68+
autoClose: 3000,
69+
hideProgressBar: false,
70+
closeOnClick: true,
71+
pauseOnHover: true,
72+
draggable: true,
73+
progress: undefined,
74+
theme: "colored",
75+
});
6876
}
6977
});
7078
return createBmk;
@@ -95,10 +103,8 @@ export default function NewBookmarkCard() {
95103
submittedBmk: NewBookmarkForm,
96104
actions: any,
97105
) => {
98-
// get the the last inputed string and all the tags already entered.
99-
let tags: Tag[] = strTags.map((t) => {
100-
return { title: t, id: -1 };
101-
});
106+
// Get the last inputted string and all the tags already entered.
107+
let tags: Tag[] = strTags.map((t) => ({ title: t, id: -1 }));
102108
if (tagInput) {
103109
tags.push({ title: tagInput, id: -1 });
104110
}
@@ -112,10 +118,12 @@ export default function NewBookmarkCard() {
112118
scrapable: isScrapable,
113119
};
114120

115-
actions.resetForm({ newcard }, setStrTags([]), setTagInput(""));
121+
actions.resetForm({ newcard });
122+
setStrTags([]);
123+
setTagInput("");
116124
let retBkmk = await makeNewBookmark(newBkmk);
117-
// if adding the bookmark was successful.
118-
if (retBkmk.id != -1) {
125+
// If adding the bookmark was successful, dispatch actions.
126+
if (retBkmk.id !== -1) {
119127
retBkmk.tags.forEach((t) => {
120128
let tAct: TagAction = {
121129
type: "add",
@@ -146,7 +154,7 @@ export default function NewBookmarkCard() {
146154
const { key } = e;
147155
const trimmedInput = tagInput.trim();
148156
if (
149-
// add tag via space bar or enter
157+
// Add tag via space bar or enter
150158
(key === "Enter" || key === "Space" || key === " ") &&
151159
trimmedInput.length &&
152160
!strTags.includes(trimmedInput)
@@ -156,8 +164,7 @@ export default function NewBookmarkCard() {
156164
values.tagTitles = strTags.concat(trimmedInput);
157165
setTagInput("");
158166
}
159-
// user hits backspace and the user has input field of 0
160-
// then pop the last tag only if there is one.
167+
// If backspace is pressed on an empty input field, remove the last tag.
161168
if (key === "Backspace" && !tagInput.length && strTags.length) {
162169
e.preventDefault();
163170
const tagsCopy = [...strTags];

0 commit comments

Comments
 (0)