Skip to content

Commit 771c591

Browse files
evanyan13Evan Yan
andauthored
[CI-4144] OS PLP UI - Update Breadcrumbs to call setrequestconfigs (#128)
* Breacdcrumb changes * Update urlHelpers * Lint * Add mock urlHelper to Breadcrumb story * Add test cases for urlHelpers * Complete test cases for urlHelpers * Update onClick Handler * Update test case for CioPlp for changes in DefaultQueryStringMap * Refactor changes based on feedback * Lint * Improve pathname update logic * Fix failed tests * Lint --------- Co-authored-by: Evan Yan <evan.yan@constructor.io>
1 parent d4297c2 commit 771c591

File tree

14 files changed

+144
-37
lines changed

14 files changed

+144
-37
lines changed

spec/components/Breadcrumbs/Breadcrumbs.test.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ describe('Testing Component: Breadcrumbs', () => {
118118
<Breadcrumbs {...breadcrumbProps} />
119119
</CioPlp>,
120120
);
121-
expect(queryAllByRole('link')).toHaveLength(bootsBreadcrumbs.length);
121+
expect(queryAllByRole('button')).toHaveLength(bootsBreadcrumbs.length);
122122
bootsBreadcrumbs.forEach((breadcrumb) => {
123123
expect(getByText(breadcrumb.breadcrumb)).toBeInTheDocument();
124124
});

spec/components/CioPlp/CioPlp.server.test.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ describe('CioPlp React Server-Side Rendering', () => {
5757
</CioPlp>,
5858
);
5959
expect(html).toContain(
60-
'<div>{&quot;cioClient&quot;:null,&quot;cioClientOptions&quot;:{},&quot;staticRequestConfigs&quot;:{},&quot;itemFieldGetters&quot;:{},&quot;formatters&quot;:{},&quot;callbacks&quot;:{},&quot;urlHelpers&quot;:{&quot;defaultQueryStringMap&quot;:{&quot;query&quot;:&quot;q&quot;,&quot;page&quot;:&quot;page&quot;,&quot;offset&quot;:&quot;offset&quot;,&quot;resultsPerPage&quot;:&quot;numResults&quot;,&quot;filters&quot;:&quot;filters&quot;,&quot;sortBy&quot;:&quot;sortBy&quot;,&quot;sortOrder&quot;:&quot;sortOrder&quot;,&quot;section&quot;:&quot;section&quot;}}}</div>',
60+
'<div class=\"cio-plp\"><div>{&quot;cioClient&quot;:null,&quot;cioClientOptions&quot;:{},&quot;staticRequestConfigs&quot;:{},&quot;itemFieldGetters&quot;:{},&quot;formatters&quot;:{},&quot;callbacks&quot;:{},&quot;urlHelpers&quot;:{&quot;defaultQueryStringMap&quot;:{&quot;query&quot;:&quot;q&quot;,&quot;page&quot;:&quot;page&quot;,&quot;offset&quot;:&quot;offset&quot;,&quot;resultsPerPage&quot;:&quot;numResults&quot;,&quot;filters&quot;:&quot;filters&quot;,&quot;sortBy&quot;:&quot;sortBy&quot;,&quot;sortOrder&quot;:&quot;sortOrder&quot;,&quot;section&quot;:&quot;section&quot;}}}</div></div>',
6161
);
6262
});
6363
});

spec/hooks/useBrowseReaults/useBrowseResults.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ describe('Testing Hook: useBrowseResults', () => {
6969

7070
const url = getUrlFromState(
7171
{ filterValue: '123', filters, resultsPerPage, page },
72-
{ baseUrl: 'https://example.com/browse/123' },
72+
'https://example.com/browse/123',
7373
);
7474

7575
window.location.href = url;

spec/hooks/useSearchResults/useSearchResults.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ describe('Testing Hook: useSearchResults', () => {
7474
const page = 1;
7575
const url = getUrlFromState(
7676
{ query, filters, resultsPerPage, page },
77-
{ baseUrl: 'https://example.com/search' },
77+
'https://example.com/search',
7878
);
7979

8080
window.location.href = url;

spec/urlHelpers.test.tsx

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ import { RequestConfigs } from '../src/types';
1414
describe('Testing Default UrlHelpers: getUrlFromState', () => {
1515
test('Should encode all request parameters as defined in defaultQueryStringMap', () => {
1616
const url = new URL(
17-
getUrlFromState(testRequestState as RequestConfigs, {
18-
baseUrl: 'https://www.example.com/a/random/path',
19-
}),
17+
getUrlFromState(testRequestState as RequestConfigs, 'https://www.example.com/a/random/path'),
2018
);
2119
const params = url.searchParams;
2220

@@ -49,9 +47,7 @@ describe('Testing Default UrlHelpers: getUrlFromState', () => {
4947
});
5048

5149
test('Should not encode parameters not defined in defaultQueryStringMap', () => {
52-
const urlString = getUrlFromState(testRequestState as RequestConfigs, {
53-
baseUrl: 'https://www.example.com/a/random/path',
54-
});
50+
const urlString = getUrlFromState(testRequestState as RequestConfigs, 'https://www.example.com/a/random/path');
5551
const url = new URL(urlString);
5652
const params = url.searchParams;
5753

@@ -72,6 +68,50 @@ describe('Testing Default UrlHelpers: getUrlFromState', () => {
7268
expect(params.has(testRequestState.filterName)).toBe(false);
7369
expect(params.has(testRequestState.filterValue)).toBe(false);
7470
});
71+
72+
test('Should update pathname when filterName and filterValue are provided', () => {
73+
const url = new URL(
74+
getUrlFromState(testRequestState as RequestConfigs, 'https://www.example.com/a/random/path'),
75+
)
76+
77+
expect(url.pathname).toBe('/group_id/Styles');
78+
});
79+
80+
test('Should handle empty pathname correctly', () => {
81+
const url = new URL(
82+
getUrlFromState(testRequestState as RequestConfigs, 'https://www.example.com'),
83+
);
84+
expect(url.pathname).toBe('/group_id/Styles');
85+
});
86+
87+
test('Should replace existing group_id in pathname', () => {
88+
const url = new URL(
89+
getUrlFromState(
90+
testRequestState as RequestConfigs,
91+
'https://www.example.com/path/group_id/old-value'
92+
),
93+
);
94+
expect(url.pathname).toBe('/path/group_id/Styles');
95+
});
96+
97+
test('Should replace existing collection_id in pathname', () => {
98+
const url = new URL(
99+
getUrlFromState(
100+
{ ...testRequestState, filterName: 'collection_id' } as RequestConfigs,
101+
'https://www.example.com/path/collection_id/old-value'
102+
),
103+
);
104+
expect(url.pathname).toBe('/path/collection_id/Styles');
105+
});
106+
107+
test('Should retain pathname when filterName and filterValue are not provided', () => {
108+
const { filterName, filterValue, ...testRequestStateWithoutFilters } = testRequestState;
109+
const url = new URL(
110+
getUrlFromState(testRequestStateWithoutFilters as RequestConfigs, 'https://www.example.com/a/random/path'),
111+
)
112+
113+
expect(url.pathname).toBe('/a/random/path');
114+
});
75115
});
76116

77117
describe('Testing Default UrlHelpers: getStateFromUrl', () => {

src/components/Breadcrumbs/BreadcrumbElement.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,37 @@ import ChevronRightIcon from './ChevronRightIcon';
55

66
export default function BreadcrumbElement({
77
path,
8+
groupId,
89
breadcrumb,
910
isCurrentPage = false,
11+
onClick,
1012
}: BreadcrumbProps) {
1113
// If it's a parent breadcrumb but doesn't have a path and label OR
1214
// It is a current page and it doesn't have a label, don't render.
1315
if ((!isCurrentPage && !path && !breadcrumb) || (isCurrentPage && !breadcrumb)) {
1416
return null;
1517
}
18+
19+
const handleClick = () => {
20+
if (onClick && groupId) {
21+
onClick(groupId);
22+
}
23+
};
24+
1625
return (
1726
<>
1827
<li
1928
className={concatStyles(
2029
'cio-plp-breadcrumb',
2130
!isCurrentPage && 'cio-plp-parent-breadcrumb',
2231
)}>
23-
{!isCurrentPage ? <a href={path}>{breadcrumb}</a> : <span>{breadcrumb}</span>}
32+
{!isCurrentPage ? (
33+
<button type='button' onClick={handleClick}>
34+
{breadcrumb}
35+
</button>
36+
) : (
37+
<span>{breadcrumb}</span>
38+
)}
2439
</li>
2540
{!isCurrentPage && <ChevronRightIcon />}
2641
</>

src/components/Breadcrumbs/Breadcrumbs.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
justify-content: center;
1515
padding: 4px 8px;
1616
text-align: center;
17+
cursor: pointer;
1718
}
1819

1920
.cio-plp-parent-breadcrumb {
@@ -39,6 +40,16 @@
3940
font-weight: 500;
4041
}
4142

43+
.cio-plp-breadcrumb button {
44+
color: rgba(0, 0, 0, 0.85);
45+
background: none;
46+
border: none;
47+
padding: 0px;
48+
font-size: medium;
49+
font-weight: 500;
50+
cursor: pointer;
51+
}
52+
4253
.cio-plp-more-breadcrumbs-menu {
4354
position: relative;
4455
display: inline-block;

src/components/Breadcrumbs/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,19 @@ import BreadcrumbElement from './BreadcrumbElement';
77
import MoreBreadcrumbsMenu from './MoreBreadcrumbsMenu';
88

99
export default function Breadcrumbs(props: BreadcrumbsProps) {
10-
const { breadcrumbs = [], currentPage } = useCioBreadcrumb(props);
10+
const { breadcrumbs = [], currentPage, onBreadcrumbClick } = useCioBreadcrumb(props);
1111
if (!currentPage && (!breadcrumbs || breadcrumbs.length === 0)) return null;
1212

1313
const { firstItems, middle, lastItems } = splitBreadcrumbs(breadcrumbs);
1414
return (
1515
<nav aria-label='plp-breadcrumbs'>
1616
<ul className='cio-breadcrumbs-container'>
1717
{firstItems.map((breadcrumb) => (
18-
<BreadcrumbElement key={breadcrumb.path} {...breadcrumb} />
18+
<BreadcrumbElement key={breadcrumb.path} {...breadcrumb} onClick={onBreadcrumbClick} />
1919
))}
2020
{middle.length > 0 && <MoreBreadcrumbsMenu breadcrumbs={middle} />}
2121
{lastItems.map((breadcrumb) => (
22-
<BreadcrumbElement key={breadcrumb.path} {...breadcrumb} />
22+
<BreadcrumbElement key={breadcrumb.path} {...breadcrumb} onClick={onBreadcrumbClick} />
2323
))}
2424
<BreadcrumbElement breadcrumb={currentPage} isCurrentPage />
2525
</ul>

src/components/Breadcrumbs/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export type BreadcrumbsProps = UseCioBreadcrumbProps;
44

55
export interface BreadcrumbProps extends Partial<Breadcrumb> {
66
isCurrentPage?: boolean;
7+
onClick?: (path: string) => void;
78
}
89

910
export interface MoreBreadcrumbsMenuProps {

src/hooks/useCioBreadcrumb.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import { useMemo } from 'react';
1+
import { useCallback, useMemo } from 'react';
22
import { PlpItemGroup } from '../types';
3+
import useRequestConfigs from './useRequestConfigs';
34

45
export interface Breadcrumb {
56
path: string;
7+
groupId: string;
68
breadcrumb: string;
79
}
810

@@ -14,6 +16,7 @@ const generateBreadcrumbs = (currentGroup?: PlpItemGroup) => {
1416

1517
return {
1618
path: pathAccumulator,
19+
groupId: parent.groupId,
1720
breadcrumb: parent.displayName,
1821
};
1922
});
@@ -37,9 +40,17 @@ export interface UseCioBreadcrumbProps {
3740

3841
export default function useCioBreadcrumb(props: UseCioBreadcrumbProps) {
3942
const { groups, filterValue } = props;
43+
const { setRequestConfigs } = useRequestConfigs();
4044

4145
const currentGroup = useMemo(() => getCurrentGroup(groups, filterValue), [groups, filterValue]);
4246
const breadcrumbs = generateBreadcrumbs(currentGroup);
4347

44-
return { breadcrumbs, currentPage: currentGroup?.displayName };
48+
const onBreadcrumbClick = useCallback(
49+
(groupId: string) => {
50+
setRequestConfigs({ filterName: 'groupId', filterValue: groupId });
51+
},
52+
[setRequestConfigs],
53+
);
54+
55+
return { breadcrumbs, currentPage: currentGroup?.displayName, onBreadcrumbClick };
4556
}

0 commit comments

Comments
 (0)