-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: Basic tests describing the "search" feature (#3566)
- Loading branch information
1 parent
aa6ecf7
commit bad5a37
Showing
6 changed files
with
294 additions
and
0 deletions.
There are no files selected for viewing
50 changes: 50 additions & 0 deletions
50
editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/ExternalPortalList.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { FullStore, useStore } from "pages/FlowEditor/lib/store"; | ||
import React from "react"; | ||
import { act } from "react-dom/test-utils"; | ||
import { setup } from "testUtils"; | ||
import { axe } from "vitest-axe"; | ||
|
||
import { ExternalPortalList } from "./ExternalPortalList"; | ||
|
||
const { getState, setState } = useStore; | ||
|
||
let initialState: FullStore; | ||
|
||
beforeAll(() => (initialState = getState())); | ||
afterEach(() => act(() => setState(initialState))); | ||
|
||
const externalPortals: FullStore["externalPortals"] = { | ||
abc: { name: "Portal 1", href: "myTeam/portalOne" }, | ||
def: { name: "Portal 2", href: "myTeam/portalTwo" }, | ||
}; | ||
|
||
it("does not display if there are no external portals in the flow", () => { | ||
const { container } = setup(<ExternalPortalList />); | ||
|
||
expect(container).toBeEmptyDOMElement(); | ||
}); | ||
|
||
it("displays a list of external portals if present in the flow", () => { | ||
act(() => setState({ externalPortals })); | ||
const { container, getAllByRole } = setup(<ExternalPortalList />); | ||
|
||
expect(container).not.toBeEmptyDOMElement(); | ||
expect(getAllByRole("listitem")).toHaveLength(2); | ||
}); | ||
|
||
it("allows users to navigate to the external portals", () => { | ||
act(() => setState({ externalPortals })); | ||
const { container, getAllByRole } = setup(<ExternalPortalList />); | ||
|
||
expect(container).not.toBeEmptyDOMElement(); | ||
const [first, second] = getAllByRole("link") as HTMLAnchorElement[]; | ||
expect(first).toHaveAttribute("href", "../myTeam/portalOne"); | ||
expect(second).toHaveAttribute("href", "../myTeam/portalTwo"); | ||
}); | ||
|
||
it("should not have any accessibility violations on initial load", async () => { | ||
act(() => setState({ externalPortals })); | ||
const { container } = setup(<ExternalPortalList />); | ||
const results = await axe(container); | ||
expect(results).toHaveNoViolations(); | ||
}); |
44 changes: 44 additions & 0 deletions
44
editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/Headline.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import React from "react"; | ||
import { setup } from "testUtils"; | ||
import { FONT_WEIGHT_BOLD } from "theme"; | ||
import { axe } from "vitest-axe"; | ||
|
||
import { Headline } from "./Headline"; | ||
|
||
const sampleText = "The quick fox jumps..."; | ||
const foxIndices: [number, number][] = [[10, 13]]; | ||
|
||
const DEFAULT_FONT_WEIGHT = "400"; | ||
|
||
it("displays matches from the headline in bold", () => { | ||
const { getByText } = setup( | ||
<Headline text={sampleText} matchIndices={foxIndices} variant="data" />, | ||
); | ||
|
||
// Input text is split into characters in order to highlight a substring | ||
const tStyle = window.getComputedStyle(getByText("T")); | ||
const hStyle = window.getComputedStyle(getByText("h")); | ||
const eStyle = window.getComputedStyle(getByText("e")); | ||
|
||
// Non matching text is not in bold | ||
expect(tStyle.fontWeight).toEqual(DEFAULT_FONT_WEIGHT); | ||
expect(hStyle.fontWeight).toEqual(DEFAULT_FONT_WEIGHT); | ||
expect(eStyle.fontWeight).toEqual(DEFAULT_FONT_WEIGHT); | ||
|
||
const fStyle = window.getComputedStyle(getByText("f")); | ||
const oStyle = window.getComputedStyle(getByText("o")); | ||
const xStyle = window.getComputedStyle(getByText("x")); | ||
|
||
// Matching text is in bold | ||
expect(fStyle.fontWeight).toEqual(FONT_WEIGHT_BOLD); | ||
expect(oStyle.fontWeight).toEqual(FONT_WEIGHT_BOLD); | ||
expect(xStyle.fontWeight).toEqual(FONT_WEIGHT_BOLD); | ||
}); | ||
|
||
it("should not have any accessibility violations on initial load", async () => { | ||
const { container } = setup( | ||
<Headline text={sampleText} matchIndices={foxIndices} variant="data" />, | ||
); | ||
const results = await axe(container); | ||
expect(results).toHaveNoViolations(); | ||
}); |
39 changes: 39 additions & 0 deletions
39
editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/NodeSearchResults.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { useStore } from "pages/FlowEditor/lib/store"; | ||
import React from "react"; | ||
import { setup } from "testUtils"; | ||
import { axe } from "vitest-axe"; | ||
|
||
import { flow, results } from "./mocks/simple"; | ||
import { NodeSearchResults } from "./NodeSearchResults"; | ||
|
||
beforeAll(() => useStore.setState({ flow })); | ||
|
||
it("Displays a warning if no results are returned", () => { | ||
const { getByText, getByRole } = setup(<NodeSearchResults results={[]} />); | ||
expect(getByText("No matches found")).toBeInTheDocument(); | ||
expect(getByRole("list")).toBeEmptyDOMElement(); | ||
}); | ||
|
||
it("Displays the count for a single result", () => { | ||
const { getByText, getByRole, getAllByRole } = setup( | ||
<NodeSearchResults results={[results[0]]} />, | ||
); | ||
expect(getByText("1 result:")).toBeInTheDocument(); | ||
expect(getByRole("list")).not.toBeEmptyDOMElement(); | ||
expect(getAllByRole("listitem")).toHaveLength(1); | ||
}); | ||
|
||
it("Displays the count for multiple results", () => { | ||
const { getByText, getByRole, getAllByRole } = setup( | ||
<NodeSearchResults results={results} />, | ||
); | ||
expect(getByText("2 results:")).toBeInTheDocument(); | ||
expect(getByRole("list")).not.toBeEmptyDOMElement(); | ||
expect(getAllByRole("listitem")).toHaveLength(2); | ||
}); | ||
|
||
it("should not have any accessibility violations on initial load", async () => { | ||
const { container } = setup(<NodeSearchResults results={results} />); | ||
const axeResults = await axe(container); | ||
expect(axeResults).toHaveNoViolations(); | ||
}); |
94 changes: 94 additions & 0 deletions
94
editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/index.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import * as planxCore from "@opensystemslab/planx-core"; | ||
import { waitFor } from "@testing-library/react"; | ||
import { FullStore, useStore } from "pages/FlowEditor/lib/store"; | ||
import React from "react"; | ||
import { act } from "react-dom/test-utils"; | ||
import { setup } from "testUtils"; | ||
import { vi } from "vitest"; | ||
import { axe } from "vitest-axe"; | ||
|
||
import Search from "."; | ||
import { flow } from "./mocks/simple"; | ||
|
||
const { setState, getState } = useStore; | ||
|
||
let initialState: FullStore; | ||
|
||
beforeAll(() => (initialState = getState())); | ||
|
||
beforeEach(() => setState({ flow })); | ||
afterEach(() => act(() => setState(initialState))); | ||
|
||
vi.mock("@opensystemslab/planx-core", async (originalModule) => { | ||
const actualModule = await originalModule<typeof planxCore>(); | ||
return { | ||
...actualModule, | ||
// Spy on sortFlow while keeping its original implementation | ||
sortFlow: vi.fn(actualModule.sortFlow), | ||
}; | ||
}); | ||
|
||
test("data field checkbox is checked and disabled", () => { | ||
const { getByLabelText } = setup(<Search />); | ||
const checkbox = getByLabelText("Search only data fields"); | ||
|
||
expect(checkbox).toBeInTheDocument(); | ||
expect(checkbox).toBeChecked(); | ||
expect(checkbox).toBeDisabled(); | ||
}); | ||
|
||
test("entering a search term displays a series of cards", async () => { | ||
const { user, queryByRole, getByRole, getAllByRole, getByLabelText } = setup( | ||
<Search />, | ||
); | ||
|
||
expect(queryByRole("list")).not.toBeInTheDocument(); | ||
|
||
const searchInput = getByLabelText("Search this flow and internal portals"); | ||
user.type(searchInput, "ind"); | ||
|
||
await waitFor(() => expect(getByRole("list")).toBeInTheDocument()); | ||
await waitFor(() => expect(getAllByRole("listitem")).toHaveLength(2)); | ||
}); | ||
|
||
test.todo("cards link to their associated nodes", async () => { | ||
const { user, getAllByRole, getByLabelText } = setup(<Search />); | ||
|
||
const searchInput = getByLabelText("Search this flow and internal portals"); | ||
user.type(searchInput, "ind"); | ||
|
||
await waitFor(() => expect(getAllByRole("listitem")).toHaveLength(2)); | ||
|
||
const [first, second] = getAllByRole("listitem"); | ||
// TODO! | ||
expect(first).toHaveAttribute("href", "link to tR9tdaWOvF (India)"); | ||
expect(second).toHaveAttribute("href", "link to tvUxd2IoPo (Indonesia)"); | ||
}); | ||
|
||
it("orderedFlow is set in the store on render of Search", async () => { | ||
expect(getState().orderedFlow).toBeUndefined(); | ||
|
||
setup(<Search />); | ||
|
||
expect(getState().orderedFlow).toBeDefined(); | ||
}); | ||
|
||
test("setOrderedFlow is only called once on initial render", async () => { | ||
const sortFlowSpy = vi.spyOn(planxCore, "sortFlow"); | ||
expect(sortFlowSpy).not.toHaveBeenCalled(); | ||
|
||
const { user, getAllByRole, getByLabelText } = setup(<Search />); | ||
|
||
const searchInput = getByLabelText("Search this flow and internal portals"); | ||
user.type(searchInput, "ind"); | ||
|
||
await waitFor(() => expect(getAllByRole("listitem")).toHaveLength(2)); | ||
|
||
expect(sortFlowSpy).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it("should not have any accessibility violations on initial load", async () => { | ||
const { container } = setup(<Search />); | ||
const results = await axe(container); | ||
expect(results).toHaveNoViolations(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Search/mocks/simple.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { FlowGraph, IndexedNode } from "@opensystemslab/planx-core/types"; | ||
import { SearchResults } from "hooks/useSearch"; | ||
|
||
export const flow: FlowGraph = { | ||
_root: { | ||
edges: ["Ej0xpn4l8u"], | ||
}, | ||
Ej0xpn4l8u: { | ||
type: 100, | ||
data: { | ||
fn: "country", | ||
text: "Pick a country", | ||
}, | ||
edges: ["VhSydY2fTe", "tR9tdaWOvF", "tvUxd2IoPo"], | ||
}, | ||
VhSydY2fTe: { | ||
type: 200, | ||
data: { | ||
text: "Spain", | ||
val: "spain", | ||
}, | ||
}, | ||
tR9tdaWOvF: { | ||
type: 200, | ||
data: { | ||
text: "India", | ||
val: "india", | ||
}, | ||
}, | ||
tvUxd2IoPo: { | ||
type: 200, | ||
data: { | ||
text: "Indonesia", | ||
val: "indonesia", | ||
}, | ||
}, | ||
}; | ||
|
||
export const results: SearchResults<IndexedNode> = [ | ||
{ | ||
item: { | ||
id: "tR9tdaWOvF", | ||
parentId: "Ej0xpn4l8u", | ||
type: 200, | ||
data: { | ||
text: "India", | ||
val: "india", | ||
}, | ||
}, | ||
key: "data.val", | ||
matchIndices: [[0, 2]], | ||
}, | ||
{ | ||
item: { | ||
id: "tvUxd2IoPo", | ||
parentId: "Ej0xpn4l8u", | ||
type: 200, | ||
data: { | ||
text: "Indonesia", | ||
val: "indonesia", | ||
}, | ||
}, | ||
key: "data.val", | ||
matchIndices: [[0, 2]], | ||
}, | ||
]; |