mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
fix scroll-spy.test.tsx
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
fa9683a170
commit
49faa2f9b7
@ -5,7 +5,7 @@
|
||||
|
||||
import React from "react";
|
||||
import "@testing-library/jest-dom/extend-expect";
|
||||
import { render, waitFor } from "@testing-library/react";
|
||||
import { render, screen, waitFor } from "@testing-library/react";
|
||||
import { ScrollSpy } from "../scroll-spy";
|
||||
import { RecursiveTreeView } from "../../tree-view";
|
||||
|
||||
@ -23,7 +23,6 @@ describe("<ScrollSpy/>", () => {
|
||||
it("renders w/o errors", () => {
|
||||
const { container } = render((
|
||||
<ScrollSpy
|
||||
htmlFor=""
|
||||
render={() => (
|
||||
<div>
|
||||
<section id="application">
|
||||
@ -40,7 +39,6 @@ describe("<ScrollSpy/>", () => {
|
||||
it("calls intersection observer", () => {
|
||||
render((
|
||||
<ScrollSpy
|
||||
htmlFor=""
|
||||
render={() => (
|
||||
<div>
|
||||
<section id="application">
|
||||
@ -55,9 +53,8 @@ describe("<ScrollSpy/>", () => {
|
||||
});
|
||||
|
||||
it("renders dataTree component", async () => {
|
||||
const { queryByTestId } = render((
|
||||
render((
|
||||
<ScrollSpy
|
||||
htmlFor=""
|
||||
render={dataTree => (
|
||||
<div>
|
||||
<nav>
|
||||
@ -71,9 +68,7 @@ describe("<ScrollSpy/>", () => {
|
||||
/>
|
||||
));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(queryByTestId("TreeView")).toBeInTheDocument();
|
||||
});
|
||||
expect(await screen.findByTestId("TreeView")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("throws if no sections founded", () => {
|
||||
@ -84,7 +79,6 @@ describe("<ScrollSpy/>", () => {
|
||||
|
||||
expect(() => render((
|
||||
<ScrollSpy
|
||||
htmlFor=""
|
||||
render={() => (
|
||||
<div>
|
||||
Content
|
||||
@ -101,9 +95,8 @@ describe("<ScrollSpy/>", () => {
|
||||
|
||||
describe("<TreeView/> dataTree inside <ScrollSpy/>", () => {
|
||||
it("contains links to all sections", async () => {
|
||||
const { queryByTitle } = render((
|
||||
render((
|
||||
<ScrollSpy
|
||||
htmlFor=""
|
||||
render={dataTree => (
|
||||
<div>
|
||||
<nav>
|
||||
@ -124,17 +117,14 @@ describe("<TreeView/> dataTree inside <ScrollSpy/>", () => {
|
||||
/>
|
||||
));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(queryByTitle("Application")).toBeInTheDocument();
|
||||
expect(queryByTitle("Appearance")).toBeInTheDocument();
|
||||
expect(queryByTitle("Theme")).toBeInTheDocument();
|
||||
});
|
||||
expect(await screen.findByTitle("Application")).toBeInTheDocument();
|
||||
expect(await screen.findByTitle("Appearance")).toBeInTheDocument();
|
||||
expect(await screen.findByTitle("Theme")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("not showing links to sections without id", async () => {
|
||||
const { queryByTitle } = render((
|
||||
<ScrollSpy
|
||||
htmlFor=""
|
||||
render={dataTree => (
|
||||
<div>
|
||||
<nav>
|
||||
@ -154,17 +144,17 @@ describe("<TreeView/> dataTree inside <ScrollSpy/>", () => {
|
||||
/>
|
||||
));
|
||||
|
||||
expect(await screen.findByTitle("Application")).toBeInTheDocument();
|
||||
expect(await screen.findByTitle("Appearance")).toBeInTheDocument();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(queryByTitle("Application")).toBeInTheDocument();
|
||||
expect(queryByTitle("Appearance")).toBeInTheDocument();
|
||||
expect(queryByTitle("Kubectl")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it("expands parent sections", async () => {
|
||||
const { queryByTitle } = render((
|
||||
render((
|
||||
<ScrollSpy
|
||||
htmlFor=""
|
||||
render={dataTree => (
|
||||
<div>
|
||||
<nav>
|
||||
@ -191,16 +181,13 @@ describe("<TreeView/> dataTree inside <ScrollSpy/>", () => {
|
||||
/>
|
||||
));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(queryByTitle("Application")).toHaveAttribute("aria-expanded");
|
||||
expect(queryByTitle("Kubernetes")).toHaveAttribute("aria-expanded");
|
||||
});
|
||||
expect(await screen.findByTitle("Application")).toHaveAttribute("aria-expanded");
|
||||
expect(await screen.findByTitle("Kubernetes")).toHaveAttribute("aria-expanded");
|
||||
});
|
||||
|
||||
it("skips sections without headings", async () => {
|
||||
const { queryByTitle } = render((
|
||||
render((
|
||||
<ScrollSpy
|
||||
htmlFor=""
|
||||
render={dataTree => (
|
||||
<div>
|
||||
<nav>
|
||||
@ -220,10 +207,11 @@ describe("<TreeView/> dataTree inside <ScrollSpy/>", () => {
|
||||
/>
|
||||
));
|
||||
|
||||
expect(await screen.findByTitle("Application")).toBeInTheDocument();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(queryByTitle("Application")).toBeInTheDocument();
|
||||
expect(queryByTitle("appearance")).not.toBeInTheDocument();
|
||||
expect(queryByTitle("Appearance")).not.toBeInTheDocument();
|
||||
expect(screen.queryByTitle("appearance")).not.toBeInTheDocument();
|
||||
expect(screen.queryByTitle("Appearance")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -10,7 +10,7 @@ import type { NavigationTree } from "../tree-view";
|
||||
|
||||
export interface ScrollSpyProps extends React.DOMAttributes<HTMLElement> {
|
||||
render: (data: NavigationTree[]) => JSX.Element;
|
||||
htmlFor: string; // Id of the element to put observers on
|
||||
htmlFor?: string; // Id of the element to put observers on
|
||||
rootMargin?: string; // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#creating_an_intersection_observer
|
||||
}
|
||||
|
||||
@ -20,12 +20,14 @@ export const ScrollSpy = observer(({ render, htmlFor, rootMargin = "0px 0px -100
|
||||
const [tree, setTree] = useState<NavigationTree[]>([]);
|
||||
const [activeElementId, setActiveElementId] = useState("");
|
||||
|
||||
const setSections = () => {
|
||||
const setSections = (): NodeListOf<HTMLElement> => {
|
||||
sections.current = parent.current?.querySelectorAll("section");
|
||||
|
||||
if (!sections.current?.length) {
|
||||
throw new Error("No <section/> tag founded! Content should be placed inside <section></section> elements to activate navigation.");
|
||||
}
|
||||
|
||||
return sections.current;
|
||||
};
|
||||
|
||||
const getSectionsParentElement = () => {
|
||||
@ -33,14 +35,14 @@ export const ScrollSpy = observer(({ render, htmlFor, rootMargin = "0px 0px -100
|
||||
};
|
||||
|
||||
const updateNavigation = () => {
|
||||
const parentSection = getSectionsParentElement();
|
||||
|
||||
if (parentSection) {
|
||||
setTree(getNavigation(parentSection));
|
||||
}
|
||||
setTree(getNavigation(getSectionsParentElement()));
|
||||
};
|
||||
|
||||
const getNavigation = (element: Element) => {
|
||||
const getNavigation = (element: Element | null | undefined): NavigationTree[] => {
|
||||
if (!element) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const sections = element.querySelectorAll(":scope > section"); // Searching only direct children of an element. Impossible without :scope
|
||||
const children: NavigationTree[] = [];
|
||||
|
||||
@ -50,7 +52,7 @@ export const ScrollSpy = observer(({ render, htmlFor, rootMargin = "0px 0px -100
|
||||
const name = section.querySelector("h1, h2, h3, h4, h5, h6")?.textContent;
|
||||
const selected = id === activeElementId;
|
||||
|
||||
if (!name || !id || !parentId) {
|
||||
if (!name || !id) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -74,13 +76,13 @@ export const ScrollSpy = observer(({ render, htmlFor, rootMargin = "0px 0px -100
|
||||
}
|
||||
};
|
||||
|
||||
const observeSections = () => {
|
||||
const observeSections = (list: NodeListOf<HTMLElement>) => {
|
||||
const options: IntersectionObserverInit = {
|
||||
root: document.getElementById(htmlFor) || getSectionsParentElement(),
|
||||
root: (htmlFor && document.getElementById(htmlFor)) || getSectionsParentElement(),
|
||||
rootMargin,
|
||||
};
|
||||
|
||||
sections.current?.forEach((section) => {
|
||||
list.forEach((section) => {
|
||||
const observer = new IntersectionObserver(handleIntersect, options);
|
||||
const target = section.querySelector("section") || section;
|
||||
|
||||
@ -89,9 +91,10 @@ export const ScrollSpy = observer(({ render, htmlFor, rootMargin = "0px 0px -100
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setSections();
|
||||
observeSections();
|
||||
}, []);
|
||||
const list = setSections();
|
||||
|
||||
observeSections(list);
|
||||
}, [parent.current]);
|
||||
|
||||
useEffect(() => {
|
||||
updateNavigation();
|
||||
|
||||
@ -18,7 +18,7 @@ const deepDash = getDeepDash(_);
|
||||
|
||||
export interface NavigationTree {
|
||||
id: string;
|
||||
parentId: string;
|
||||
parentId?: string;
|
||||
name: string;
|
||||
selected?: boolean;
|
||||
children?: NavigationTree[];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user