Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -568,13 +568,28 @@ describe('useSidebarBreadcrumbs', () => {

it('returns first level link', () => {
const pathname = '/somePathName';
const sidebar = [testCategory(), testLink({href: pathname})];
const sidebar = [testCategory(), testLink({href: pathname, docId: 'doc1'})];

expect(createUseSidebarBreadcrumbsMock(sidebar)(pathname)).toEqual([
sidebar[1],
]);
});

it('returns doc links only', () => {
const pathname = '/somePathName';

// A link that is not a doc link should not appear in the breadcrumbs
// See https://github.com/facebook/docusaurus/pull/11616
const nonDocLink = testLink({href: pathname});
const docLink = testLink({href: pathname, docId: 'doc1'});

const sidebar = [testCategory(), nonDocLink, docLink];

expect(createUseSidebarBreadcrumbsMock(sidebar)(pathname)).toEqual([
docLink,
]);
});

it('returns nested category', () => {
const pathname = '/somePathName';

Expand Down Expand Up @@ -613,7 +628,7 @@ describe('useSidebarBreadcrumbs', () => {
it('returns nested link', () => {
const pathname = '/somePathName';

const link = testLink({href: pathname});
const link = testLink({href: pathname, docId: 'docNested'});

const categoryLevel3 = testCategory({
items: [testLink(), link, testLink()],
Expand Down Expand Up @@ -657,6 +672,35 @@ describe('useSidebarBreadcrumbs', () => {
createUseSidebarBreadcrumbsMock(undefined, false)('/foo'),
).toBeNull();
});

// Regression test for https://github.com/facebook/docusaurus/issues/11612
it('returns the category that owns the URL, not a category with a link pointing to it', () => {
const categoryA: PropSidebarItemCategory = testCategory({
label: 'Category A',
href: '/category-a',
items: [
testLink({href: '/category-a/doc1', label: 'Doc 1'}),
testLink({href: '/category-a/doc2', label: 'Doc 2'}),
// This link points to Category B's generated-index
testLink({href: '/category-b', label: 'Go to Category B'}),
],
});

const categoryB: PropSidebarItemCategory = testCategory({
label: 'Category B',
href: '/category-b',
items: [
testLink({href: '/category-b/item1', label: 'Item 1'}),
testLink({href: '/category-b/item2', label: 'Item 2'}),
],
});

const sidebar: PropSidebar = [categoryA, categoryB];

expect(createUseSidebarBreadcrumbsMock(sidebar)('/category-b')).toEqual([
categoryB,
]);
});
});

describe('useCurrentSidebarCategory', () => {
Expand Down Expand Up @@ -708,12 +752,16 @@ describe('useCurrentSidebarCategory', () => {
expect(mockUseCurrentSidebarCategory('/cat2')).toEqual(category2);
});

it('works for category link item', () => {
const link = testLink({href: '/my/link/path'});
it('works for category doc link item', () => {
const pathname = '/my/link/path';
const nonDocLink = testLink({href: pathname});
const docLink = testLink({href: pathname, docId: 'doc1'});

const category: PropSidebarItemCategory = testCategory({
href: '/cat1',
items: [testLink(), testLink(), link, testCategory()],
items: [testLink(), testLink(), nonDocLink, docLink, testCategory()],
});

const sidebar: PropSidebar = [
testLink(),
testLink(),
Expand All @@ -724,18 +772,28 @@ describe('useCurrentSidebarCategory', () => {
const mockUseCurrentSidebarCategory =
createUseCurrentSidebarCategoryMock(sidebar);

expect(mockUseCurrentSidebarCategory('/my/link/path')).toEqual(category);
expect(mockUseCurrentSidebarCategory(pathname)).toEqual(category);
});

it('works for nested category link item', () => {
const link = testLink({href: '/my/link/path'});
const pathname = '/my/link/path';
const nonDocLink = testLink({href: pathname});
const docLink = testLink({href: pathname, docId: 'doc1'});

const category2: PropSidebarItemCategory = testCategory({
href: '/cat2',
items: [testLink(), testLink(), link, testCategory()],
items: [
testLink(),
testLink(),
testCategory({items: [nonDocLink]}),
nonDocLink,
docLink,
testCategory(),
],
});
const category1: PropSidebarItemCategory = testCategory({
href: '/cat1',
items: [testLink(), testLink(), category2, testCategory()],
items: [testLink(), nonDocLink, testLink(), category2, testCategory()],
});
const sidebar: PropSidebar = [
testLink(),
Expand Down Expand Up @@ -780,6 +838,38 @@ describe('useCurrentSidebarCategory', () => {
`"Unexpected: cant find current sidebar in context"`,
);
});

// Regression test for https://github.com/facebook/docusaurus/issues/11612
it('returns the category that owns the URL, not a category with a link pointing to it', () => {
const categoryA: PropSidebarItemCategory = testCategory({
label: 'Category A',
href: '/category-a',
items: [
testLink({href: '/category-a/doc1', label: 'Doc 1'}),
testLink({href: '/category-a/doc2', label: 'Doc 2'}),
// This link points to Category B's generated-index
testLink({href: '/category-b', label: 'Go to Category B'}),
],
});

const categoryB: PropSidebarItemCategory = testCategory({
label: 'Category B',
href: '/category-b',
items: [
testLink({href: '/category-b/item1', label: 'Item 1'}),
testLink({href: '/category-b/item2', label: 'Item 2'}),
],
});

const sidebar: PropSidebar = [categoryA, categoryB];

const mockUseCurrentSidebarCategory =
createUseCurrentSidebarCategoryMock(sidebar);

// When visiting /category-b, we should get Category B (the owner),
// not Category A (which just has a link to it)
expect(mockUseCurrentSidebarCategory('/category-b')).toEqual(categoryB);
});
});

describe('useCurrentSidebarSiblings', () => {
Expand All @@ -805,10 +895,10 @@ describe('useCurrentSidebarSiblings', () => {
testCategory(),
];

const mockUseCurrentSidebarCategory =
const mockUseCurrentSidebarSiblings =
createUseCurrentSidebarSiblingsMock(sidebar);

expect(mockUseCurrentSidebarCategory('/cat')).toEqual(category.items);
expect(mockUseCurrentSidebarSiblings('/cat')).toEqual(category.items);
});

it('works for sidebar root', () => {
Expand All @@ -823,10 +913,10 @@ describe('useCurrentSidebarSiblings', () => {
testCategory(),
];

const mockUseCurrentSidebarCategory =
const mockUseCurrentSidebarSiblings =
createUseCurrentSidebarSiblingsMock(sidebar);

expect(mockUseCurrentSidebarCategory('/rootLink')).toEqual(sidebar);
expect(mockUseCurrentSidebarSiblings('/rootLink')).toEqual(sidebar);
});

it('works for nested sidebar category', () => {
Expand All @@ -852,10 +942,13 @@ describe('useCurrentSidebarSiblings', () => {
});

it('works for category link item', () => {
const link = testLink({href: '/my/link/path'});
const pathname = '/my/link/path';
const nonDocLink = testLink({href: pathname});
const docLink = testLink({href: pathname, docId: 'doc1'});

const category: PropSidebarItemCategory = testCategory({
href: '/cat1',
items: [testLink(), testLink(), link, testCategory()],
items: [testLink(), testLink(), nonDocLink, docLink, testCategory()],
});
const sidebar: PropSidebar = [
testLink(),
Expand All @@ -864,23 +957,24 @@ describe('useCurrentSidebarSiblings', () => {
testCategory(),
];

const mockUseCurrentSidebarCategory =
const mockUseCurrentSidebarSiblings =
createUseCurrentSidebarSiblingsMock(sidebar);

expect(mockUseCurrentSidebarCategory('/my/link/path')).toEqual(
category.items,
);
expect(mockUseCurrentSidebarSiblings(pathname)).toEqual(category.items);
});

it('works for nested category link item', () => {
const link = testLink({href: '/my/link/path'});
const pathname = '/my/link/path';
const nonDocLink = testLink({href: pathname});
const docLink = testLink({href: pathname, docId: 'doc1'});

const category2: PropSidebarItemCategory = testCategory({
href: '/cat2',
items: [testLink(), testLink(), link, testCategory()],
items: [testLink(), testLink(), nonDocLink, testCategory()],
});
const category1: PropSidebarItemCategory = testCategory({
href: '/cat1',
items: [testLink(), testLink(), category2, testCategory()],
items: [testLink(), testLink(), category2, docLink, testCategory()],
});
const sidebar: PropSidebar = [
testLink(),
Expand All @@ -889,18 +983,16 @@ describe('useCurrentSidebarSiblings', () => {
testCategory(),
];

const mockUseCurrentSidebarCategory =
const mockUseCurrentSidebarSiblings =
createUseCurrentSidebarSiblingsMock(sidebar);

expect(mockUseCurrentSidebarCategory('/my/link/path')).toEqual(
category2.items,
);
expect(mockUseCurrentSidebarSiblings(pathname)).toEqual(category1.items);
});

it('throws when sidebar is missing', () => {
const mockUseCurrentSidebarCategory = createUseCurrentSidebarSiblingsMock();
const mockUseCurrentSidebarSiblings = createUseCurrentSidebarSiblingsMock();
expect(() =>
mockUseCurrentSidebarCategory('/cat'),
mockUseCurrentSidebarSiblings('/cat'),
).toThrowErrorMatchingInlineSnapshot(
`"Unexpected: cant find current sidebar in context"`,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,15 +234,22 @@ function getSidebarBreadcrumbs({
}): PropSidebarBreadcrumbsItem[] {
const breadcrumbs: PropSidebarBreadcrumbsItem[] = [];

function extract(items: PropSidebarItem[]) {
function extract(items: PropSidebarItem[]): boolean {
for (const item of items) {
if (
(item.type === 'category' &&
(isSamePath(item.href, pathname) || extract(item.items))) ||
(item.type === 'link' && isSamePath(item.href, pathname))
// Extract category item
if (item.type === 'category') {
if (isSamePath(item.href, pathname) || extract(item.items)) {
breadcrumbs.unshift(item);
return true;
}
}
// Extract doc item
else if (
item.type === 'link' &&
item.docId &&
isSamePath(item.href, pathname)
) {
const filtered = onlyCategories && item.type !== 'category';
if (!filtered) {
if (!onlyCategories) {
breadcrumbs.unshift(item);
}
return true;
Expand Down
Loading