1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Adding TreeView & ScrollSpy tests

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
Alex Andreev 2021-03-09 14:50:38 +03:00
parent 8339ecc5f1
commit 66994bdf4c
6 changed files with 209 additions and 11 deletions

View File

@ -306,7 +306,7 @@
"concurrently": "^5.2.0",
"css-element-queries": "^1.2.3",
"css-loader": "^3.5.3",
"deepdash-es": "^5.3.5",
"deepdash": "^5.3.5",
"dompurify": "^2.0.11",
"electron": "^9.4.0",
"electron-builder": "^22.7.0",

View File

@ -80,9 +80,9 @@ export class PageLayout extends React.Component<PageLayoutProps> {
<div className="content-scrollable-area">
<div className="content-wrapper">
{ showNavigation && (
<div className="content-navigation">
<nav className="content-navigation">
<RecursiveTreeView data={navigation}/>
</div>
</nav>
)}
<div className={cssNames("content", contentGaps && "flex column gaps", contentClass)}>
{children}

View File

@ -0,0 +1,186 @@
import React from "react";
import "@testing-library/jest-dom/extend-expect";
import { render, waitFor } from "@testing-library/react";
import { ScrollSpy } from "../scroll-spy";
import { RecursiveTreeView } from "../../tree-view";
const observe = jest.fn();
Object.defineProperty(window, "IntersectionObserver", {
writable: true,
value: jest.fn().mockImplementation(() => ({
observe,
unobserve: jest.fn(),
})),
});
describe("<ScrollSpy/>", () => {
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 navigation component", async () => {
const { queryByTestId } = render(<ScrollSpy render={navigation => (
<div>
<nav>
<RecursiveTreeView data={navigation}/>
</nav>
<section id="application">
<h1>Application</h1>
</section>
</div>
)}/>);
await waitFor(() => {
expect(queryByTestId("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/> navigation inside <ScrollSpy/>", () => {
it("contains links to all sections", async () => {
const { queryByTitle } = render(<ScrollSpy render={navigation => (
<div>
<nav>
<RecursiveTreeView data={navigation}/>
</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>
)}/>);
await waitFor(() => {
expect(queryByTitle("Application")).toBeInTheDocument();
expect(queryByTitle("Appearance")).toBeInTheDocument();
expect(queryByTitle("Theme")).toBeInTheDocument();
});
});
it("not showing links to sections without id", async () => {
const { queryByTitle } = render(<ScrollSpy render={navigation => (
<div>
<nav>
<RecursiveTreeView data={navigation}/>
</nav>
<section id="application">
<h1>Application</h1>
<section>
<h2>Kubectl</h2>
</section>
<section id="appearance">
<h2>Appearance</h2>
</section>
</section>
</div>
)}/>);
await waitFor(() => {
expect(queryByTitle("Application")).toBeInTheDocument();
expect(queryByTitle("Appearance")).toBeInTheDocument();
expect(queryByTitle("Kubectl")).not.toBeInTheDocument();
});
});
it("expands parent sections", async () => {
const { queryByTitle } = render(<ScrollSpy render={navigation => (
<div>
<nav>
<RecursiveTreeView data={navigation}/>
</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>
)}/>);
await waitFor(() => {
expect(queryByTitle("Application")).toHaveAttribute("aria-expanded");
expect(queryByTitle("Kubernetes")).toHaveAttribute("aria-expanded");
});
// console.log(prettyDOM());
});
it("skips sections without headings", async () => {
const { queryByTitle } = render(<ScrollSpy render={navigation => (
<div>
<nav>
<RecursiveTreeView data={navigation}/>
</nav>
<section id="application">
<h1>Application</h1>
<section id="appearance">
<p>Appearance</p>
</section>
<section id="theme">
<h2>Theme</h2>
</section>
</section>
</div>
)}/>);
await waitFor(() => {
expect(queryByTitle("Application")).toBeInTheDocument();
expect(queryByTitle("appearance")).not.toBeInTheDocument();
expect(queryByTitle("Appearance")).not.toBeInTheDocument();
});
});
});

View File

@ -31,7 +31,7 @@ export function ScrollSpy(props: Props) {
sections.forEach(section => {
const id = section.getAttribute("id");
const parentId = section.parentElement.id;
const name = section.querySelector("h1, h2, h3, h4, h5, h6").textContent;
const name = section.querySelector("h1, h2, h3, h4, h5, h6")?.textContent;
const selected = id === activeElementId;
if (!name || !id) {

View File

@ -5,7 +5,11 @@ import { Icon } from "../icon";
import TreeView from "@material-ui/lab/TreeView";
import TreeItem from "@material-ui/lab/TreeItem";
import { cssNames } from "../../utils";
import findDeep from "deepdash-es/findDeep";
import _ from "lodash";
import getDeepDash from "deepdash";
const deepDash = getDeepDash(_);
export interface NavigationTree {
id: string;
@ -26,7 +30,7 @@ const scrollToItem = (id: string) => {
};
const getSelectedNode = (data: NavigationTree[]) => {
return findDeep(data, (value, key) => key === "selected" && value === true)?.parent;
return deepDash.findDeep(data, (value, key) => key === "selected" && value === true)?.parent;
};
export function RecursiveTreeView({ data }: Props) {
@ -63,6 +67,7 @@ export function RecursiveTreeView({ data }: Props) {
label={node.name}
onLabelClick={(event) => onLabelClick(event, node.id)}
className={cssNames({selected: node.selected})}
title={node.name}
>
{Array.isArray(node.children) ? node.children.map((node) => renderTree([node])) : null}
</TreeItem>
@ -84,6 +89,7 @@ export function RecursiveTreeView({ data }: Props) {
return (
<TreeView
data-testid="TreeView"
className="TreeView"
expanded={expanded}
onNodeToggle={handleToggle}

View File

@ -4381,12 +4381,13 @@ deep-is@^0.1.3, deep-is@~0.1.3:
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
deepdash-es@^5.3.5:
deepdash@^5.3.5:
version "5.3.5"
resolved "https://registry.yarnpkg.com/deepdash-es/-/deepdash-es-5.3.5.tgz#1217365f6508bb47f1f90def6b4f1c4b5f4ff6eb"
integrity sha512-bezxT+LqAu1Ly8I2LAEFle3fdEAc/bHld9cMAbgYzY+69+P9qTkGtNvC2ZQJEP4C1C2Fx9gVn/TCoQlAivWPDA==
resolved "https://registry.yarnpkg.com/deepdash/-/deepdash-5.3.5.tgz#611bec9c1f2829832d21971dcbefe712e408647d"
integrity sha512-1ZdPPCI1pCEqeAWGSw+Nbpb/2iIV4w3sGPc22H/PDtcApb8+psTzPIoOVD040iBaT2wqZab29Kjrz6G+cd5mqQ==
dependencies:
lodash-es "^4.17.15"
lodash "^4.17.20"
lodash-es "^4.17.20"
deepmerge@^4.2.2:
version "4.2.2"
@ -8644,7 +8645,7 @@ lockfile@^1.0.4:
dependencies:
signal-exit "^3.0.2"
lodash-es@^4.17.15:
lodash-es@^4.17.20:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
@ -8707,6 +8708,11 @@ lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.1
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
lodash@^4.17.20:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
logform@^2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/logform/-/logform-2.1.2.tgz#957155ebeb67a13164069825ce67ddb5bb2dd360"