@tapcart/mobile-components 0.12.8 → 0.12.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/hooks/use-recommendations.d.ts.map +1 -1
- package/dist/components/hooks/use-recommendations.js +7 -1
- package/dist/components/hooks/use-recommendations.test.d.ts +2 -0
- package/dist/components/hooks/use-recommendations.test.d.ts.map +1 -0
- package/dist/components/hooks/use-recommendations.test.js +85 -0
- package/dist/lib/variablesCart.util.d.ts.map +1 -1
- package/dist/lib/variablesCart.util.js +3 -0
- package/dist/styles.css +3 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-recommendations.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-recommendations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAOxE,UAAU,sBAAsB;IAE9B,YAAY,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAGxC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,MAAM,EAAE,MAAM,CAAA;CACf;AAUD,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,EAAE,GAAG,EAAE,CAAA;IACb,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,GAAG,CAAA;CACX;AAmBD,QAAA,MAAM,kBAAkB,yEASrB,sBAAsB,KAAG,
|
|
1
|
+
{"version":3,"file":"use-recommendations.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-recommendations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAOxE,UAAU,sBAAsB;IAE9B,YAAY,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAGxC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,MAAM,EAAE,MAAM,CAAA;CACf;AAUD,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,EAAE,GAAG,EAAE,CAAA;IACb,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,GAAG,CAAA;CACX;AAmBD,QAAA,MAAM,kBAAkB,yEASrB,sBAAsB,KAAG,uBA2H3B,CAAA;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
|
|
@@ -35,7 +35,13 @@ queryVariables, apiURL, }) => {
|
|
|
35
35
|
? query
|
|
36
36
|
: (searchParams === null || searchParams === void 0 ? void 0 : searchParams.get("recommendation")) || "";
|
|
37
37
|
// Check if resolved recommendation meets minimum length requirement
|
|
38
|
-
|
|
38
|
+
// Allow fetching when:
|
|
39
|
+
// - query is empty → show trending searches
|
|
40
|
+
// - query meets minimum length (≥3 chars)
|
|
41
|
+
// - searchClient has a customSearchConfig (e.g., filter-only queries on PDP)
|
|
42
|
+
const shouldFetch = !recommendation.trim().length ||
|
|
43
|
+
recommendation.length >= MIN_QUERY_LENGTH ||
|
|
44
|
+
(usingSearchClient && Boolean(customSearchConfig));
|
|
39
45
|
const [cachedRecommendation, setCachedRecommendations] = React.useState(recommendationsLocalStorage.getCacheItem({
|
|
40
46
|
id: `${recommendation}-${queryVariables === null || queryVariables === void 0 ? void 0 : queryVariables.language}`,
|
|
41
47
|
}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-recommendations.test.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-recommendations.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { renderHook } from "@testing-library/react";
|
|
2
|
+
import { useRecommendations } from "./use-recommendations";
|
|
3
|
+
// Mock next/navigation
|
|
4
|
+
jest.mock("next/navigation", () => ({
|
|
5
|
+
useSearchParams: () => new URLSearchParams(),
|
|
6
|
+
}));
|
|
7
|
+
// Mock SWR to give us control over fetching behavior
|
|
8
|
+
jest.mock("swr", () => {
|
|
9
|
+
return {
|
|
10
|
+
__esModule: true,
|
|
11
|
+
default: (key, fetcher, _options) => {
|
|
12
|
+
// If key is null, SWR doesn't fetch
|
|
13
|
+
if (key === null) {
|
|
14
|
+
return { data: undefined, error: undefined, isLoading: false };
|
|
15
|
+
}
|
|
16
|
+
return { data: undefined, error: undefined, isLoading: true };
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
// Mock the local storage cache
|
|
21
|
+
jest.mock("../libs/cache/RecommendationsLocalStorage", () => {
|
|
22
|
+
return {
|
|
23
|
+
__esModule: true,
|
|
24
|
+
default: jest.fn().mockImplementation(() => ({
|
|
25
|
+
getCacheItem: jest.fn().mockReturnValue(null),
|
|
26
|
+
setCacheItem: jest.fn(),
|
|
27
|
+
})),
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
describe("useRecommendations", () => {
|
|
31
|
+
const mockSearchClient = {
|
|
32
|
+
getRecommendations: jest.fn().mockResolvedValue({
|
|
33
|
+
products: [{ id: "1", title: "Product 1" }],
|
|
34
|
+
searches: ["suggestion 1"],
|
|
35
|
+
facets: [],
|
|
36
|
+
totalResults: 1,
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
39
|
+
const defaultProps = {
|
|
40
|
+
queryVariables: { appId: "test-app" },
|
|
41
|
+
apiURL: "http://test.com/recommendations",
|
|
42
|
+
};
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
jest.clearAllMocks();
|
|
45
|
+
});
|
|
46
|
+
it("should fetch trending recommendations when query is empty", () => {
|
|
47
|
+
const { result } = renderHook(() => useRecommendations(Object.assign({ searchClient: mockSearchClient, query: "" }, defaultProps)));
|
|
48
|
+
// Empty query now triggers a trending recommendations fetch
|
|
49
|
+
expect(result.current.isLoading).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
it("should not fetch when query is below MIN_QUERY_LENGTH and no customSearchConfig", () => {
|
|
52
|
+
const { result } = renderHook(() => useRecommendations(Object.assign({ searchClient: mockSearchClient, query: "ab" }, defaultProps)));
|
|
53
|
+
expect(result.current.products).toEqual([]);
|
|
54
|
+
expect(result.current.isLoading).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
it("should fetch trending when no searchClient and empty search params", () => {
|
|
57
|
+
const { result } = renderHook(() => useRecommendations(Object.assign({ query: "ab" }, defaultProps)));
|
|
58
|
+
// Without searchClient, recommendation comes from searchParams (empty string)
|
|
59
|
+
// Empty query now triggers a trending fetch
|
|
60
|
+
expect(result.current.isLoading).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
it("should fetch when query meets MIN_QUERY_LENGTH", () => {
|
|
63
|
+
const { result } = renderHook(() => useRecommendations(Object.assign({ searchClient: mockSearchClient, query: "abc" }, defaultProps)));
|
|
64
|
+
// SWR mock returns isLoading: true when key is not null
|
|
65
|
+
expect(result.current.isLoading).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
it("should fetch when customSearchConfig is provided with searchClient even with empty query", () => {
|
|
68
|
+
const customSearchConfig = {
|
|
69
|
+
filter: 'attributes.mfield_bnb__seriesId = 584945 AND NOT id: ANY("9338273530096")',
|
|
70
|
+
pageSize: 6,
|
|
71
|
+
};
|
|
72
|
+
const { result } = renderHook(() => useRecommendations(Object.assign({ searchClient: mockSearchClient, query: "", customSearchConfig }, defaultProps)));
|
|
73
|
+
// shouldFetch should be true due to customSearchConfig bypass, so SWR gets a key and returns isLoading: true
|
|
74
|
+
expect(result.current.isLoading).toBe(true);
|
|
75
|
+
});
|
|
76
|
+
it("should fetch trending when customSearchConfig is provided without searchClient and empty query", () => {
|
|
77
|
+
const customSearchConfig = {
|
|
78
|
+
filter: "attributes.mfield_bnb__seriesId = 584945",
|
|
79
|
+
pageSize: 6,
|
|
80
|
+
};
|
|
81
|
+
const { result } = renderHook(() => useRecommendations(Object.assign({ query: "", customSearchConfig }, defaultProps)));
|
|
82
|
+
// Empty query now triggers a trending fetch regardless of searchClient
|
|
83
|
+
expect(result.current.isLoading).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"variablesCart.util.d.ts","sourceRoot":"","sources":["../../lib/variablesCart.util.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EACT,sBAAsB,EACtB,6BAA6B,EAO9B,MAAM,kBAAkB,CAAA;AAEzB,eAAO,MAAM,2BAA2B;;cAM5B,MAAM;;0BAEI;YAChB,gBAAgB,CAAC,EAAE,MAAM,CAAA;YACzB,KAAK,EAAE,MAAM,CAAA;YACb,cAAc,CAAC,EAAE,MAAM,CAAA;SACxB,EAAE;;;;;;CAyBN,CAAA;
|
|
1
|
+
{"version":3,"file":"variablesCart.util.d.ts","sourceRoot":"","sources":["../../lib/variablesCart.util.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EACT,sBAAsB,EACtB,6BAA6B,EAO9B,MAAM,kBAAkB,CAAA;AAEzB,eAAO,MAAM,2BAA2B;;cAM5B,MAAM;;0BAEI;YAChB,gBAAgB,CAAC,EAAE,MAAM,CAAA;YACzB,KAAK,EAAE,MAAM,CAAA;YACb,cAAc,CAAC,EAAE,MAAM,CAAA;SACxB,EAAE;;;;;;CAyBN,CAAA;AA8FD,eAAO,MAAM,6BAA6B,SAClC,MAAM,QACN,SAAS,GAAG,IAAI,YAUvB,CAAA;AAED,eAAO,MAAM,2BAA2B,SAChC,MAAM,QACN,SAAS,GAAG,IAAI,YAUvB,CAAA;AAoMD,MAAM,MAAM,uBAAuB,GAAG;IACpC,yBAAyB,EAAE,sBAAsB,EAAE,CAAA;IACnD,gBAAgB,EAAE,6BAA6B,EAAE,CAAA;IACjD,cAAc,EAAE,OAAO,CAAA;IACvB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,oBAAoB,EAAE,MAAM,CAAA;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,oBAAoB,EAAE,MAAM,CAAA;IAC5B,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAA;AAED,eAAO,MAAM,iCAAiC,EAAE,uBAU/C,CAAA;AAED,eAAO,MAAM,8BAA8B,SACnC,SAAS,GAAG,IAAI,KACrB,uBAmCF,CAAA"}
|
|
@@ -42,6 +42,9 @@ const getOrderLevelDiscounts = (cart) => {
|
|
|
42
42
|
if (discount.code) {
|
|
43
43
|
code = ((discount === null || discount === void 0 ? void 0 : discount.code) || "").toUpperCase();
|
|
44
44
|
}
|
|
45
|
+
else if (discount.title) {
|
|
46
|
+
code = ((discount === null || discount === void 0 ? void 0 : discount.title) || "").toUpperCase();
|
|
47
|
+
}
|
|
45
48
|
else if ((_b = (_a = discount.kind) === null || _a === void 0 ? void 0 : _a.manual) === null || _b === void 0 ? void 0 : _b.code) {
|
|
46
49
|
code = (((_d = (_c = discount === null || discount === void 0 ? void 0 : discount.kind) === null || _c === void 0 ? void 0 : _c.manual) === null || _d === void 0 ? void 0 : _d.code) || "").toUpperCase();
|
|
47
50
|
}
|
package/dist/styles.css
CHANGED