mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fixup scroll-spy
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
8f508d1582
commit
8025471eee
@ -1,235 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from "react";
|
|
||||||
import "@testing-library/jest-dom/extend-expect";
|
|
||||||
import { screen, waitFor } from "@testing-library/react";
|
|
||||||
import { ScrollSpy } from "../scroll-spy";
|
|
||||||
import { RecursiveTreeView } from "../../tree-view";
|
|
||||||
import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
|
|
||||||
import { type DiRender, renderFor } from "../../test-utils/renderFor";
|
|
||||||
|
|
||||||
const observe = jest.fn();
|
|
||||||
|
|
||||||
Object.defineProperty(window, "IntersectionObserver", {
|
|
||||||
writable: true,
|
|
||||||
value: jest.fn().mockImplementation(() => ({
|
|
||||||
observe,
|
|
||||||
unobserve: jest.fn(),
|
|
||||||
})),
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("<ScrollSpy/>", () => {
|
|
||||||
let render: DiRender;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
|
||||||
|
|
||||||
render = renderFor(di);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("renders w/o errors", () => {
|
|
||||||
const { container } = render((
|
|
||||||
<ScrollSpy
|
|
||||||
render={() => (
|
|
||||||
<div>
|
|
||||||
<section id="application">
|
|
||||||
<h1>Application</h1>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
|
|
||||||
expect(container).toBeInstanceOf(HTMLElement);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("calls intersection observer", () => {
|
|
||||||
render((
|
|
||||||
<ScrollSpy
|
|
||||||
render={() => (
|
|
||||||
<div>
|
|
||||||
<section id="application">
|
|
||||||
<h1>Application</h1>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
|
|
||||||
expect(observe).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("renders dataTree component", async () => {
|
|
||||||
render((
|
|
||||||
<ScrollSpy
|
|
||||||
render={dataTree => (
|
|
||||||
<div>
|
|
||||||
<nav>
|
|
||||||
<RecursiveTreeView data={dataTree}/>
|
|
||||||
</nav>
|
|
||||||
<section id="application">
|
|
||||||
<h1>Application</h1>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
|
|
||||||
expect(await screen.findByTestId("TreeView")).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("throws if no sections founded", () => {
|
|
||||||
// Prevent writing to stderr during this render.
|
|
||||||
const err = console.error;
|
|
||||||
|
|
||||||
console.error = jest.fn();
|
|
||||||
|
|
||||||
expect(() => render((
|
|
||||||
<ScrollSpy
|
|
||||||
render={() => (
|
|
||||||
<div>
|
|
||||||
Content
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
))).toThrow();
|
|
||||||
|
|
||||||
// Restore writing to stderr.
|
|
||||||
console.error = err;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe("<TreeView/> dataTree inside <ScrollSpy/>", () => {
|
|
||||||
let render: DiRender;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
|
||||||
|
|
||||||
render = renderFor(di);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("contains links to all sections", async () => {
|
|
||||||
render((
|
|
||||||
<ScrollSpy
|
|
||||||
render={dataTree => (
|
|
||||||
<div>
|
|
||||||
<nav>
|
|
||||||
<RecursiveTreeView data={dataTree}/>
|
|
||||||
</nav>
|
|
||||||
<section id="application">
|
|
||||||
<h1>Application</h1>
|
|
||||||
<section id="appearance">
|
|
||||||
<h2>Appearance</h2>
|
|
||||||
</section>
|
|
||||||
<section id="theme">
|
|
||||||
<h2>Theme</h2>
|
|
||||||
<div>description</div>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
|
|
||||||
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
|
|
||||||
render={dataTree => (
|
|
||||||
<div>
|
|
||||||
<nav>
|
|
||||||
<RecursiveTreeView data={dataTree}/>
|
|
||||||
</nav>
|
|
||||||
<section id="application">
|
|
||||||
<h1>Application</h1>
|
|
||||||
<section>
|
|
||||||
<h2>Kubectl</h2>
|
|
||||||
</section>
|
|
||||||
<section id="appearance">
|
|
||||||
<h2>Appearance</h2>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
|
|
||||||
expect(await screen.findByTitle("Application")).toBeInTheDocument();
|
|
||||||
expect(await screen.findByTitle("Appearance")).toBeInTheDocument();
|
|
||||||
|
|
||||||
await waitFor(() => {
|
|
||||||
expect(queryByTitle("Kubectl")).not.toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("expands parent sections", async () => {
|
|
||||||
render((
|
|
||||||
<ScrollSpy
|
|
||||||
render={dataTree => (
|
|
||||||
<div>
|
|
||||||
<nav>
|
|
||||||
<RecursiveTreeView data={dataTree}/>
|
|
||||||
</nav>
|
|
||||||
<section id="application">
|
|
||||||
<h1>Application</h1>
|
|
||||||
<section id="appearance">
|
|
||||||
<h2>Appearance</h2>
|
|
||||||
</section>
|
|
||||||
<section id="theme">
|
|
||||||
<h2>Theme</h2>
|
|
||||||
<div>description</div>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
<section id="Kubernetes">
|
|
||||||
<h1>Kubernetes</h1>
|
|
||||||
<section id="kubectl">
|
|
||||||
<h2>Kubectl</h2>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
|
|
||||||
expect(await screen.findByTitle("Application")).toHaveAttribute("aria-expanded");
|
|
||||||
expect(await screen.findByTitle("Kubernetes")).toHaveAttribute("aria-expanded");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("skips sections without headings", async () => {
|
|
||||||
render((
|
|
||||||
<ScrollSpy
|
|
||||||
render={dataTree => (
|
|
||||||
<div>
|
|
||||||
<nav>
|
|
||||||
<RecursiveTreeView data={dataTree}/>
|
|
||||||
</nav>
|
|
||||||
<section id="application">
|
|
||||||
<h1>Application</h1>
|
|
||||||
<section id="appearance">
|
|
||||||
<p>Appearance</p>
|
|
||||||
</section>
|
|
||||||
<section id="theme">
|
|
||||||
<h2>Theme</h2>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
|
|
||||||
expect(await screen.findByTitle("Application")).toBeInTheDocument();
|
|
||||||
|
|
||||||
await waitFor(() => {
|
|
||||||
expect(screen.queryByTitle("appearance")).not.toBeInTheDocument();
|
|
||||||
expect(screen.queryByTitle("Appearance")).not.toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -6,7 +6,14 @@
|
|||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { useMutationObserver } from "../../hooks";
|
import { useMutationObserver } from "../../hooks";
|
||||||
import type { NavigationTree } from "../tree-view";
|
|
||||||
|
export interface NavigationTree {
|
||||||
|
id: string;
|
||||||
|
parentId?: string;
|
||||||
|
name: string;
|
||||||
|
selected?: boolean;
|
||||||
|
children?: NavigationTree[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface ScrollSpyProps extends React.DOMAttributes<HTMLElement> {
|
export interface ScrollSpyProps extends React.DOMAttributes<HTMLElement> {
|
||||||
render: (data: NavigationTree[]) => JSX.Element;
|
render: (data: NavigationTree[]) => JSX.Element;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user