Skip to content

Commit b8b8a1e

Browse files
committed
breadcrumb component now accepts an object array with name and href information needed. Allows path with multiple slashes to be applied to a href
1 parent bc4b1aa commit b8b8a1e

File tree

3 files changed

+56
-118
lines changed

3 files changed

+56
-118
lines changed

src/components/Breadcrumbs.stories.tsx

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,48 @@ type Story = StoryObj<typeof meta>;
1212

1313
export const Default: Story = {
1414
args: {
15-
path: "/first/second/third/last/",
15+
path: [
16+
{ name: "first", href: "first" },
17+
{ name: "second", href: "second/could/be/here" },
18+
{ name: "third", href: "third" },
19+
{ name: "last", href: "/" },
20+
],
1621
},
1722
};
1823

1924
export const ShortPath: Story = {
2025
args: {
21-
path: "just one",
26+
path: [{ name: "just one", href: "/" }],
2227
},
2328
};
2429

2530
export const LongPath: Story = {
2631
args: {
27-
path: "/first/the second/third/fourth/almost last/last one/",
32+
path: [
33+
{ name: "first", href: "first" },
34+
{ name: "the second", href: "the/second" },
35+
{ name: "third", href: "third" },
36+
{ name: "fourth", href: "fourth/could/be/here" },
37+
{ name: "almost last", href: "almost last" },
38+
{ name: "last one", href: "/" },
39+
],
2840
},
2941
};
3042

3143
export const Empty: Story = {
3244
args: {
33-
path: "",
45+
path: [],
3446
},
3547
};
3648

3749
export const ColorChange: Story = {
3850
args: {
39-
path: ["first", "second", "third", "last"],
51+
path: [
52+
{ name: "first", href: "first" },
53+
{ name: "second", href: "second/could/be/here" },
54+
{ name: "third", href: "third" },
55+
{ name: "last", href: "/" },
56+
],
4057
rootProps: {
4158
sx: { backgroundColor: "blue" },
4259
},

src/components/Breadcrumbs.test.tsx

Lines changed: 23 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,12 @@ import { render, RenderResult } from "@testing-library/react";
22
import { Breadcrumbs, getCrumbs } from "./Breadcrumbs";
33
import "@testing-library/jest-dom";
44

5+
const defaultArrayObject = [
6+
{ name: "first", href: "first/is/this" },
7+
{ name: "second", href: "second" },
8+
{ name: "last one", href: "last one" },
9+
];
510
describe("Breadcrumbs", () => {
6-
const crumbFirst = "first",
7-
crumbFirstTitle = "First",
8-
crumbSecond = "second",
9-
crumbSecondTitle = "Second",
10-
crumbLast = "last one",
11-
crumbLastTitle = "Last one",
12-
defaultStringPath = `/${crumbFirst}/${crumbSecond}/${crumbLast}`,
13-
defaultArrayPath = [crumbFirst, crumbSecond, crumbLast];
14-
1511
function testHomeExists(renderResult: RenderResult) {
1612
const { getByTestId } = renderResult;
1713
const homeIcon = getByTestId("HomeIcon");
@@ -20,48 +16,12 @@ describe("Breadcrumbs", () => {
2016
expect(homeIcon.parentElement).toHaveAttribute("href", "/");
2117
}
2218

23-
function testCrumbsExist(renderResult: RenderResult) {
24-
const { getAllByRole, getByRole, getByText, queryByRole } = renderResult;
25-
26-
expect(getAllByRole("link")).toHaveLength(3);
27-
28-
testHomeExists(renderResult);
29-
30-
let crumb = getByRole("link", { name: crumbFirstTitle });
31-
expect(crumb).toBeInTheDocument();
32-
expect(crumb).toHaveAttribute("href", `/${crumbFirst}`);
33-
34-
crumb = getByRole("link", { name: crumbSecondTitle });
35-
expect(crumb).toBeInTheDocument();
36-
expect(crumb).toHaveAttribute("href", `/${crumbFirst}/${crumbSecond}`);
37-
38-
expect(
39-
queryByRole("link", { name: crumbLastTitle }),
40-
).not.toBeInTheDocument();
41-
expect(getByText(crumbLastTitle)).toBeInTheDocument();
42-
}
43-
4419
it("should render without errors", () => {
45-
render(<Breadcrumbs path={defaultStringPath} />);
46-
});
47-
48-
it("should use a path as string", () => {
49-
testCrumbsExist(render(<Breadcrumbs path={defaultStringPath} />));
50-
});
51-
52-
it("should use a path as array", () => {
53-
testCrumbsExist(render(<Breadcrumbs path={defaultArrayPath} />));
20+
render(<Breadcrumbs path={defaultArrayObject} />);
5421
});
5522

5623
it("should show just home when an empty string", () => {
57-
const renderResult = render(<Breadcrumbs path={""} />);
58-
testHomeExists(renderResult);
59-
expect(renderResult.getAllByRole("link")).toHaveLength(1);
60-
});
61-
62-
it("should show just home when an empty array", () => {
6324
const renderResult = render(<Breadcrumbs path={[]} />);
64-
6525
testHomeExists(renderResult);
6626
expect(renderResult.getAllByRole("link")).toHaveLength(1);
6727
});
@@ -83,56 +43,23 @@ describe("getCrumbs", () => {
8343
},
8444
];
8545

86-
it("should match if path string", () => {
87-
expect(getCrumbs("/first/second/last one")).toStrictEqual(correctCrumbs);
88-
});
89-
90-
it("should match if last slash included", () => {
91-
expect(getCrumbs("/first/second/last one/")).toStrictEqual(correctCrumbs);
92-
});
93-
94-
it("should match if first slash excluded", () => {
95-
expect(getCrumbs("first/second/last one")).toStrictEqual(correctCrumbs);
96-
});
97-
98-
it("should match if first slash excluded and last slash included", () => {
99-
expect(getCrumbs("first/second/last one")).toStrictEqual(correctCrumbs);
100-
});
101-
102-
it("should match path string with multi separators", () => {
103-
expect(getCrumbs("///first//second/last one")).toStrictEqual(correctCrumbs);
104-
});
105-
106-
it("should return an empty array when an empty string is passed", () => {
107-
expect(getCrumbs("")).toStrictEqual([]);
108-
});
109-
110-
it("should return an empty array when spaces are passed", () => {
111-
expect(getCrumbs(" ")).toStrictEqual([]);
112-
});
113-
114-
it("should match if path array", () => {
115-
expect(getCrumbs(["first", "second", "last one"])).toStrictEqual(
116-
correctCrumbs,
117-
);
118-
});
119-
120-
it("should match if path array with empty", () => {
121-
expect(getCrumbs(["first", "second", "last one", ""])).toStrictEqual(
122-
correctCrumbs,
123-
);
124-
});
125-
126-
it("should match by removing empty item", () => {
127-
expect(getCrumbs(["first", "second", "last one", ""])).toStrictEqual(
128-
correctCrumbs,
129-
);
130-
});
131-
132-
it("should match by removing spaces only", () => {
133-
expect(getCrumbs(["first", "second", "last one", " "])).toStrictEqual(
134-
correctCrumbs,
135-
);
46+
it("should match with correct array object passed", () => {
47+
expect(
48+
getCrumbs([
49+
{
50+
name: "first",
51+
href: "/first",
52+
},
53+
{
54+
name: "second",
55+
href: "/first/second",
56+
},
57+
{
58+
name: "last one",
59+
href: "/first/second/last one",
60+
},
61+
])
62+
).toStrictEqual(correctCrumbs);
13663
});
13764

13865
it("should return an empty array when an empty array is passed", () => {

src/components/Breadcrumbs.tsx

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,26 @@ import {
1313
import HomeIcon from "@mui/icons-material/Home";
1414
import NavigateNextIcon from "@mui/icons-material/NavigateNext";
1515

16-
interface BreadcrumbsProps {
17-
path: string | string[];
18-
rootProps?: PaperProps;
19-
muiBreadcrumbsProps?: Mui_BreadcrumbsProps;
20-
}
21-
2216
type CrumbData = {
2317
name: string;
2418
href: string;
2519
};
2620

21+
interface BreadcrumbsProps {
22+
path: Array<CrumbData>;
23+
rootProps?: PaperProps;
24+
muiBreadcrumbsProps?: Mui_BreadcrumbsProps;
25+
}
26+
2727
/**
2828
* Create CrumbData from crumb parts with links
29-
* @param path A single string path, or an array of string parts
29+
* @param pathData An array object that take in crumb names and hrefs
3030
*/
31-
export function getCrumbs(path: string | string[]): CrumbData[] {
32-
if (typeof path === "string") {
33-
path = path.split("/");
34-
}
35-
36-
const crumbs = path.filter((item) => item.trim() !== "");
37-
38-
return crumbs.map((crumb, i) => {
31+
export function getCrumbs(pathData: Array<CrumbData>): CrumbData[] {
32+
return pathData.map((obj, i) => {
3933
return {
40-
name: crumb.charAt(0).toUpperCase() + crumb.slice(1),
41-
href: "/" + crumbs.slice(0, i + 1).join("/"),
34+
name: obj.name.charAt(0).toUpperCase() + obj.name.slice(1),
35+
href: obj.href,
4236
};
4337
});
4438
}

0 commit comments

Comments
 (0)