Skip to content

Commit 8f4fbef

Browse files
authored
Merge pull request #198 from Lemoncode/feature/#183-save-user-recent-searches-(last-5)
Feature/#183 save user recent searches (last 5)
2 parents d909a0d + ab1d86c commit 8f4fbef

1 file changed

Lines changed: 166 additions & 0 deletions

File tree

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
import { describe, it, expect, vi, beforeEach } from "vitest";
2+
import { EmbalseSearchModel } from "../../embalse-search.vm";
3+
import {
4+
addNewSearchEntry,
5+
getStoredSearches,
6+
} from "./recentSearches.bussiness";
7+
8+
// MOCK LOCALSTORAGE
9+
10+
let store: Record<string, string> = {};
11+
12+
const localStorageMock = {
13+
getItem: (key: string) => store[key] || null,
14+
setItem: (key: string, value: string) => {
15+
store[key] = value.toString();
16+
},
17+
clear: () => {
18+
store = {};
19+
},
20+
removeItem: (key: string) => {
21+
delete store[key];
22+
},
23+
};
24+
25+
Object.defineProperty(globalThis, "localStorage", {
26+
value: localStorageMock,
27+
writable: true,
28+
});
29+
30+
describe("recentSearches business logic", () => {
31+
it("should add an entry to an empty list", () => {
32+
// ARRANGE
33+
const embalseList: EmbalseSearchModel[] = [];
34+
const newSearch: EmbalseSearchModel = {
35+
slug: "cenajo",
36+
name: "Cenajo (Albacete)",
37+
};
38+
39+
// ACT
40+
const result = addNewSearchEntry(newSearch, embalseList);
41+
42+
// ASSERT
43+
expect(result).toHaveLength(1);
44+
expect(result[0].slug).toBe("cenajo");
45+
});
46+
47+
it("should move a repeated element to the beginning without duplicating it", () => {
48+
49+
// ARRANGE
50+
const embalseList: EmbalseSearchModel[] = [
51+
{ slug: "gonzalez-lacasa", name: "González Lacasa (La Rioja)" },
52+
{ slug: "chanza", name: "Chanza (Huelva)" },
53+
{ slug: "cenajo", name: "Cenajo (Albacete)" },
54+
];
55+
const newSearch: EmbalseSearchModel = {
56+
slug: "cenajo",
57+
name: "Cenajo (Albacete)",
58+
};
59+
60+
// ACT
61+
const result = addNewSearchEntry(newSearch, embalseList);
62+
63+
// ASSERT
64+
expect(result).toHaveLength(3);
65+
expect(result[0]).toEqual(newSearch);
66+
expect(result[2].slug).toBe("chanza");
67+
});
68+
69+
it("should add the new element to the beginning and remove the oldest one if the array has 5 elements", () => {
70+
71+
// ARRANGE
72+
const embalseList: EmbalseSearchModel[] = [
73+
{ slug: "gonzalez-lacasa", name: "González Lacasa (La Rioja)" },
74+
{ slug: "chanza", name: "Chanza (Huelva)" },
75+
{ slug: "loteta-la", name: "Loteta (La) (Zaragoza)" },
76+
{ slug: "mequinenza", name: "Mequinenza (Zaragoza)" },
77+
{ slug: "certescans", name: "Certescáns (Lleida)" },
78+
];
79+
const newSearch: EmbalseSearchModel = {
80+
slug: "cenajo",
81+
name: "Cenajo (Albacete)",
82+
};
83+
84+
// ACT
85+
const result = addNewSearchEntry(newSearch, embalseList);
86+
87+
// ASSERT
88+
expect(result).toHaveLength(5);
89+
expect(result[0].slug).toBe(newSearch.slug);
90+
expect(result.some((e) => e.slug === newSearch.slug));
91+
expect(result[4].slug).toBe("mequinenza");
92+
});
93+
94+
it("should add an entry to a list that already has elements but is not full", () => {
95+
96+
// ARRANGE
97+
const embalseList: EmbalseSearchModel[] = [
98+
{ slug: "gonzalez-lacasa", name: "González Lacasa (La Rioja)" },
99+
];
100+
const newSearch: EmbalseSearchModel = {
101+
slug: "cenajo",
102+
name: "Cenajo (Albacete)",
103+
};
104+
105+
// ACT
106+
const result = addNewSearchEntry(newSearch, embalseList);
107+
108+
// ASSERT
109+
expect(result).toHaveLength(2);
110+
expect(result[0].slug).toBe("cenajo");
111+
expect(result[1].slug).toBe("gonzalez-lacasa");
112+
});
113+
});
114+
115+
describe("getStoredSearches", () => {
116+
117+
beforeEach(() => {
118+
localStorage.clear();
119+
});
120+
121+
it("should return an array with 5 indices", () => {
122+
123+
// ARRANGE:
124+
localStorage.setItem(
125+
"recent-searches",
126+
JSON.stringify([
127+
{ slug: "loteta-la", name: "Loteta (La) (Zaragoza)" },
128+
{ slug: "gonzalez-lacasa", name: "González Lacasa (La Rioja)" },
129+
{ slug: "chanza", name: "Chanza (Huelva)" },
130+
{ slug: "cenajo", name: "Cenajo (Albacete)" },
131+
{ slug: "mequinenza", name: "Mequinenza (Zaragoza)" },
132+
]),
133+
);
134+
135+
// ACT
136+
const result = getStoredSearches();
137+
138+
// ASSERT
139+
expect(result).toHaveLength(5);
140+
expect(result[0].slug).toEqual("loteta-la");
141+
});
142+
143+
it("should return an empty array if localStorage is empty", () => {
144+
// ARRANGE:
145+
localStorage.clear();
146+
147+
// ACT
148+
const result = getStoredSearches();
149+
150+
// ASSERT
151+
expect(result).toEqual([]);
152+
});
153+
154+
it("should return an empty array when localStorage data is invalid", () => {
155+
// ARRANGE:
156+
localStorageMock.setItem("recent-searches", "invalid-data");
157+
const spyConsole = vi.spyOn(console, "log").mockImplementation(() => {});
158+
159+
// ACT
160+
const result = getStoredSearches();
161+
162+
// ASSERT
163+
expect(result).toEqual([]);
164+
expect(spyConsole).toHaveBeenCalled();
165+
});
166+
});

0 commit comments

Comments
 (0)