From bf632076b3edd78a1679e88917c295f0e86a9f07 Mon Sep 17 00:00:00 2001
From: Jane Chu <7559015+janechu@users.noreply.github.com>
Date: Mon, 11 Feb 2019 18:20:07 -0800
Subject: [PATCH] feat: add root level component navigation and ability to have
string children
---
.../app/configs/example.data.ts | 1 +
.../src/navigation/navigation.props.ts | 2 +-
.../src/navigation/navigation.spec.tsx | 48 +++----
.../src/navigation/navigation.tsx | 122 ++++++++++--------
.../navigation/navigation.utilities.spec.ts | 43 ++++--
.../src/navigation/navigation.utilities.ts | 13 +-
6 files changed, 137 insertions(+), 92 deletions(-)
diff --git a/packages/fast-navigation-generator-react/app/configs/example.data.ts b/packages/fast-navigation-generator-react/app/configs/example.data.ts
index 255e7ee7e62..583c612fcdb 100644
--- a/packages/fast-navigation-generator-react/app/configs/example.data.ts
+++ b/packages/fast-navigation-generator-react/app/configs/example.data.ts
@@ -11,6 +11,7 @@ const noChildren: any = {
const children: any = {
children: [
+ "Foo",
{
id: get(noChildrenSchema, "id"),
props: noChildren,
diff --git a/packages/fast-navigation-generator-react/src/navigation/navigation.props.ts b/packages/fast-navigation-generator-react/src/navigation/navigation.props.ts
index 22fb8b7ff52..bb2e0e41682 100644
--- a/packages/fast-navigation-generator-react/src/navigation/navigation.props.ts
+++ b/packages/fast-navigation-generator-react/src/navigation/navigation.props.ts
@@ -6,7 +6,7 @@ export interface NavigationState {
/**
* The navigation data
*/
- navigation: TreeNavigation[];
+ navigation: TreeNavigation;
/**
* The open items tracked by data location
diff --git a/packages/fast-navigation-generator-react/src/navigation/navigation.spec.tsx b/packages/fast-navigation-generator-react/src/navigation/navigation.spec.tsx
index 019946d742a..e56ea94bbbd 100644
--- a/packages/fast-navigation-generator-react/src/navigation/navigation.spec.tsx
+++ b/packages/fast-navigation-generator-react/src/navigation/navigation.spec.tsx
@@ -100,9 +100,9 @@ describe("Navigation", () => {
const rendered: any = shallow();
const item: any = rendered.find(treeItemEndPointSelector);
expect(item).toHaveLength(1);
- expect(rendered.find(treeItemExpandListTriggerSelector)).toHaveLength(0);
+ expect(rendered.find(treeItemExpandListTriggerSelector)).toHaveLength(1);
expect(item.props().className).toEqual(managedClasses.navigation_itemLink);
- expect(item.props()["aria-level"]).toEqual(1);
+ expect(item.props()["aria-level"]).toEqual(2);
expect(item.props()["aria-setsize"]).toEqual(1);
expect(item.props()["aria-posinset"]).toEqual(1);
});
@@ -127,13 +127,13 @@ describe("Navigation", () => {
const rendered: any = shallow();
const item: any = rendered.find(treeItemEndPointSelector);
expect(item).toHaveLength(2);
- expect(rendered.find(treeItemExpandListTriggerSelector)).toHaveLength(0);
+ expect(rendered.find(treeItemExpandListTriggerSelector)).toHaveLength(1);
expect(item.at(0).props().className).toEqual(managedClasses.navigation_itemLink);
- expect(item.at(0).props()["aria-level"]).toEqual(1);
+ expect(item.at(0).props()["aria-level"]).toEqual(2);
expect(item.at(0).props()["aria-setsize"]).toEqual(2);
expect(item.at(0).props()["aria-posinset"]).toEqual(1);
expect(item.at(1).props().className).toEqual(managedClasses.navigation_itemLink);
- expect(item.at(1).props()["aria-level"]).toEqual(1);
+ expect(item.at(1).props()["aria-level"]).toEqual(2);
expect(item.at(1).props()["aria-setsize"]).toEqual(2);
expect(item.at(1).props()["aria-posinset"]).toEqual(2);
});
@@ -156,18 +156,18 @@ describe("Navigation", () => {
const rendered: any = shallow();
const linkItem: any = rendered.find(treeItemEndPointSelector);
- const triggerItem: any = rendered.find(treeItemExpandListTriggerSelector);
+ const triggerItem: any = rendered.find(treeItemExpandListTriggerSelector).at(1);
expect(triggerItem).toHaveLength(1);
expect(triggerItem.props().className).toEqual(
managedClasses.navigation_itemExpandListTrigger
);
- expect(triggerItem.parent().props()["aria-level"]).toEqual(1);
+ expect(triggerItem.parent().props()["aria-level"]).toEqual(2);
expect(triggerItem.parent().props()["aria-setsize"]).toEqual(1);
expect(triggerItem.parent().props()["aria-posinset"]).toEqual(1);
expect(linkItem).toHaveLength(1);
expect(linkItem.props().className).toEqual(managedClasses.navigation_itemLink);
- expect(linkItem.props()["aria-level"]).toEqual(2);
+ expect(linkItem.props()["aria-level"]).toEqual(3);
expect(linkItem.props()["aria-setsize"]).toEqual(1);
expect(linkItem.props()["aria-posinset"]).toEqual(1);
});
@@ -196,26 +196,26 @@ describe("Navigation", () => {
const rendered: any = shallow();
const linkItem: any = rendered.find(treeItemEndPointSelector);
- const triggerItem: any = rendered.find(treeItemExpandListTriggerSelector);
+ const triggerItem: any = rendered.find(treeItemExpandListTriggerSelector).at(1);
expect(triggerItem).toHaveLength(1);
expect(triggerItem.props().className).toEqual(
managedClasses.navigation_itemExpandListTrigger
);
- expect(triggerItem.parent().props()["aria-level"]).toEqual(1);
+ expect(triggerItem.parent().props()["aria-level"]).toEqual(2);
expect(triggerItem.parent().props()["aria-setsize"]).toEqual(1);
expect(triggerItem.parent().props()["aria-posinset"]).toEqual(1);
expect(linkItem).toHaveLength(2);
expect(linkItem.at(0).props().className).toEqual(
managedClasses.navigation_itemLink
);
- expect(linkItem.at(0).props()["aria-level"]).toEqual(2);
+ expect(linkItem.at(0).props()["aria-level"]).toEqual(3);
expect(linkItem.at(0).props()["aria-setsize"]).toEqual(2);
expect(linkItem.at(0).props()["aria-posinset"]).toEqual(1);
expect(linkItem.at(1).props().className).toEqual(
managedClasses.navigation_itemLink
);
- expect(linkItem.at(1).props()["aria-level"]).toEqual(2);
+ expect(linkItem.at(1).props()["aria-level"]).toEqual(3);
expect(linkItem.at(1).props()["aria-setsize"]).toEqual(2);
expect(linkItem.at(1).props()["aria-posinset"]).toEqual(2);
});
@@ -257,51 +257,51 @@ describe("Navigation", () => {
const linkItem: any = rendered.find(treeItemEndPointSelector);
const triggerItem: any = rendered.find(treeItemExpandListTriggerSelector);
- expect(triggerItem).toHaveLength(2);
+ expect(triggerItem).toHaveLength(3);
expect(
triggerItem
- .at(0)
+ .at(1)
.parent()
.props()["aria-level"]
- ).toEqual(1);
+ ).toEqual(2);
expect(
triggerItem
- .at(0)
+ .at(1)
.parent()
.props()["aria-setsize"]
).toEqual(2);
expect(
triggerItem
- .at(0)
+ .at(1)
.parent()
.props()["aria-posinset"]
).toEqual(1);
expect(
triggerItem
- .at(1)
+ .at(2)
.parent()
.props()["aria-level"]
- ).toEqual(1);
+ ).toEqual(2);
expect(
triggerItem
- .at(1)
+ .at(2)
.parent()
.props()["aria-setsize"]
).toEqual(2);
expect(
triggerItem
- .at(1)
+ .at(2)
.parent()
.props()["aria-posinset"]
).toEqual(2);
expect(linkItem).toHaveLength(3);
- expect(linkItem.at(0).props()["aria-level"]).toEqual(2);
+ expect(linkItem.at(0).props()["aria-level"]).toEqual(3);
expect(linkItem.at(0).props()["aria-setsize"]).toEqual(2);
expect(linkItem.at(0).props()["aria-posinset"]).toEqual(1);
- expect(linkItem.at(1).props()["aria-level"]).toEqual(2);
+ expect(linkItem.at(1).props()["aria-level"]).toEqual(3);
expect(linkItem.at(1).props()["aria-setsize"]).toEqual(2);
expect(linkItem.at(1).props()["aria-posinset"]).toEqual(2);
- expect(linkItem.at(2).props()["aria-level"]).toEqual(2);
+ expect(linkItem.at(2).props()["aria-level"]).toEqual(3);
expect(linkItem.at(2).props()["aria-setsize"]).toEqual(1);
expect(linkItem.at(2).props()["aria-posinset"]).toEqual(1);
});
diff --git a/packages/fast-navigation-generator-react/src/navigation/navigation.tsx b/packages/fast-navigation-generator-react/src/navigation/navigation.tsx
index 231c7bd0ecf..2e3ca8ad032 100644
--- a/packages/fast-navigation-generator-react/src/navigation/navigation.tsx
+++ b/packages/fast-navigation-generator-react/src/navigation/navigation.tsx
@@ -56,7 +56,7 @@ export default class Navigation extends Foundation<
role={"tree"}
className={this.props.managedClasses.navigation}
>
- {this.renderTreeItems(this.state.navigation, 1)}
+ {this.renderTreeItem(this.state.navigation, 1, 1, 1, 0)}
);
}
@@ -75,6 +75,64 @@ export default class Navigation extends Foundation<
);
}
+ private renderTreeItem(
+ navigation: TreeNavigation,
+ level: number,
+ navigationLength: number,
+ positionInNavigation: number,
+ index: number
+ ): React.ReactNode {
+ if (Array.isArray(navigation.items)) {
+ return (
+
+
+ {navigation.text}
+
+ {this.renderTreeItemContainer(navigation.items, level)}
+
+ );
+ }
+
+ return (
+
+ );
+ }
+
/**
* Renders tree items
*/
@@ -86,60 +144,12 @@ export default class Navigation extends Foundation<
const navigationLength: number = navigation.length;
const positionInNavigation: number = index + 1;
- if (Array.isArray(navigationItem.items)) {
- return (
-
-
- {navigationItem.text}
-
- {this.renderTreeItemContainer(navigationItem.items, level)}
-
- );
- }
-
- return (
-
+ return this.renderTreeItem(
+ navigationItem,
+ level,
+ navigationLength,
+ positionInNavigation,
+ index
);
});
}
@@ -376,7 +386,7 @@ export default class Navigation extends Foundation<
this.state.openItems.find(
(openItem: string) =>
openItem.slice(0, dataLocation.length) === dataLocation
- )
+ ) !== undefined
) {
return true;
}
diff --git a/packages/fast-navigation-generator-react/src/navigation/navigation.utilities.spec.ts b/packages/fast-navigation-generator-react/src/navigation/navigation.utilities.spec.ts
index 3738354c24b..93f05c60bc9 100644
--- a/packages/fast-navigation-generator-react/src/navigation/navigation.utilities.spec.ts
+++ b/packages/fast-navigation-generator-react/src/navigation/navigation.utilities.spec.ts
@@ -21,8 +21,29 @@ const childOptions: ChildOptionItem[] = [
* Gets the navigation
*/
describe("getNavigationFromData", () => {
- test("should return an empty array if no data is passed", () => {
- expect(getNavigationFromData({}, {}, [])).toEqual([]);
+ test("should return a single item if no data is passed", () => {
+ expect(getNavigationFromData({}, {}, [])).toEqual({
+ dataLocation: "",
+ items: [],
+ text: "Undefined",
+ type: "children",
+ });
+ });
+ test("should return a single item if a single string child has been passed", () => {
+ const childrenText: string = "Foo";
+ const data: any = {
+ children: childrenText,
+ };
+ const navigationFromData: TreeNavigation[] = getNavigationFromData(
+ data,
+ childrenSchema,
+ childOptions
+ ).items;
+ expect(navigationFromData).toHaveLength(1);
+ expect(navigationFromData[0].items).toEqual(undefined);
+ expect(navigationFromData[0].dataLocation).toEqual("children");
+ expect(navigationFromData[0].text).toEqual(childrenText);
+ expect(navigationFromData[0].type).toEqual(ItemType.children);
});
test("should return a single item if a single child has been passed", () => {
const data: any = {
@@ -36,7 +57,7 @@ describe("getNavigationFromData", () => {
data,
childrenSchema,
childOptions
- );
+ ).items;
expect(navigationFromData).toHaveLength(1);
expect(navigationFromData[0].items).toEqual(undefined);
expect(navigationFromData[0].dataLocation).toEqual("children");
@@ -44,6 +65,7 @@ describe("getNavigationFromData", () => {
expect(navigationFromData[0].type).toEqual(ItemType.children);
});
test("should return multiple items if multiple children have been passed", () => {
+ const childrenText: string = "Bar";
const data: any = {
children: [
{
@@ -54,6 +76,7 @@ describe("getNavigationFromData", () => {
id: childOptions[0].schema.id,
props: {},
},
+ childrenText,
],
};
@@ -61,9 +84,9 @@ describe("getNavigationFromData", () => {
data,
childrenSchema,
childOptions
- );
+ ).items;
- expect(navigationFromData).toHaveLength(2);
+ expect(navigationFromData).toHaveLength(3);
expect(navigationFromData[0].items).toEqual(undefined);
expect(navigationFromData[0].dataLocation).toEqual("children[0]");
expect(navigationFromData[0].text).toEqual(childOptions[0].schema.title);
@@ -72,6 +95,10 @@ describe("getNavigationFromData", () => {
expect(navigationFromData[1].dataLocation).toEqual("children[1]");
expect(navigationFromData[1].text).toEqual(childOptions[0].schema.title);
expect(navigationFromData[1].type).toEqual(ItemType.children);
+ expect(navigationFromData[2].items).toEqual(undefined);
+ expect(navigationFromData[2].dataLocation).toEqual("children[2]");
+ expect(navigationFromData[2].text).toEqual(childrenText);
+ expect(navigationFromData[2].type).toEqual(ItemType.children);
});
test("should return a nested item if nested children have been passed", () => {
const data: any = {
@@ -90,7 +117,7 @@ describe("getNavigationFromData", () => {
data,
childrenSchema,
childOptions
- );
+ ).items;
expect(navigationFromData).toHaveLength(1);
expect(navigationFromData[0].dataLocation).toEqual("children");
expect(navigationFromData[0].text).toEqual(childOptions[1].schema.title);
@@ -127,7 +154,7 @@ describe("getNavigationFromData", () => {
data,
childrenSchema,
childOptions
- );
+ ).items;
expect(navigationFromData).toHaveLength(1);
expect(navigationFromData[0].dataLocation).toEqual("children");
expect(navigationFromData[0].text).toEqual(childOptions[1].schema.title);
@@ -181,7 +208,7 @@ describe("getNavigationFromData", () => {
data,
childrenSchema,
childOptions
- );
+ ).items;
expect(navigationFromData).toHaveLength(2);
expect(navigationFromData[0].dataLocation).toEqual("children[0]");
expect(navigationFromData[0].text).toEqual(childOptions[1].schema.title);
diff --git a/packages/fast-navigation-generator-react/src/navigation/navigation.utilities.ts b/packages/fast-navigation-generator-react/src/navigation/navigation.utilities.ts
index 232ff075c22..c80dbcbbc75 100644
--- a/packages/fast-navigation-generator-react/src/navigation/navigation.utilities.ts
+++ b/packages/fast-navigation-generator-react/src/navigation/navigation.utilities.ts
@@ -88,7 +88,9 @@ function getNavigationFromChildLocations(
updatedNavigation.push({
text: get(subSchema, "schema.title")
? subSchema.schema.title
- : "Undefined",
+ : typeof get(data, childrenDataLocation) === "string"
+ ? get(data, childrenDataLocation)
+ : "Undefined",
dataLocation: childrenDataLocation,
type: ItemType.children,
});
@@ -104,7 +106,7 @@ export function getNavigationFromData(
data: any,
schema: any,
childOptions: ChildOptionItem[]
-): TreeNavigation[] {
+): TreeNavigation {
const childrenDataLocations: string[] = getDataLocationsOfChildren(
schema,
data,
@@ -118,5 +120,10 @@ export function getNavigationFromData(
childOptions
);
- return navigation;
+ return {
+ text: schema.title ? schema.title : "Undefined",
+ dataLocation: "",
+ items: navigation,
+ type: ItemType.children,
+ };
}