From ebf1ab22f86c9f20d9dcf1f63f2279b2b4f561b2 Mon Sep 17 00:00:00 2001 From: Said Shah Date: Wed, 18 Nov 2020 16:28:17 -0500 Subject: [PATCH 1/6] Refactored accessible list and added basic tests --- .../accessible-list/accessible-list.test.tsx | 62 ++++++++++++++- .../accessible-list/accessible-list.tsx | 78 +++++++++++-------- 2 files changed, 102 insertions(+), 38 deletions(-) diff --git a/src/molecules/accessible-list/accessible-list.test.tsx b/src/molecules/accessible-list/accessible-list.test.tsx index 136639e..e014fc8 100644 --- a/src/molecules/accessible-list/accessible-list.test.tsx +++ b/src/molecules/accessible-list/accessible-list.test.tsx @@ -1,7 +1,61 @@ -// import React from "react"; -// import { render } from "@testing-library/react"; -// import { AccessibleList } from "./accessible-list"; +import React from "react"; +import faker from "faker"; +import { render, fireEvent } from "@testing-library/react"; +import { AccessibleList } from "./accessible-list"; +import { KeyboardKeys } from "../../constants/keyboard-keys"; describe("AccessibleList", () => { - test.skip("TODO - https://github.com/AndcultureCode/AndcultureCode.JavaScript.React.Components/issues/19", () => {}); + test("when default props, renders items", () => { + // Arrange + const expected = faker.random.word(); + + // Act + const { getByText } = render( + + + + ); + + // Assert + expect(getByText(expected)).not.toBeNil(); + }); + + test("when onEsc set, calls handler upon escape pressed", () => { + // Arrange + let isChecked = false; + const buttonText = faker.random.word(); + const onEscHandler = () => { + isChecked = true; + }; + + // Act + const { getByText } = render( + + + + ); + fireEvent.keyDown(getByText(buttonText), { key: KeyboardKeys.Escape }); + + // Assert + expect(isChecked).toBeTrue(); + }); + + test("when down arrow pressed, calls setCurrent method", () => { + // Arrange + const buttonText1 = faker.random.word(); + const buttonText2 = faker.random.word(); + + // Act + const { getByText } = render( + + + + + ); + fireEvent.keyDown(getByText(buttonText1), { + key: KeyboardKeys.DownArrow, + }); + + // Assert + }); }); diff --git a/src/molecules/accessible-list/accessible-list.tsx b/src/molecules/accessible-list/accessible-list.tsx index ab90c91..b11294f 100644 --- a/src/molecules/accessible-list/accessible-list.tsx +++ b/src/molecules/accessible-list/accessible-list.tsx @@ -37,47 +37,46 @@ const AccessibleList: React.FunctionComponent = ( }, [refArray, current, props.focusFirstItem]); const handleKeyDown = (e: KeyboardEvent) => { - if ( - e.key === KeyboardKeys.DownArrow && - current === refArray.length - 1 - ) { - e.preventDefault(); - setCurrent(0); - return; - } - - if (e.key === KeyboardKeys.UpArrow && current === 0) { - e.preventDefault(); - setCurrent(refArray.length - 1); - return; + switch (e.key) { + case KeyboardKeys.UpArrow: { + handleUpArrowPress(e); + break; + } + case KeyboardKeys.DownArrow: { + handleDownArrowPress(e); + break; + } + case KeyboardKeys.Escape: { + handleEscapePress(e); + break; + } + default: { + return; + } } + }; - if ( - e.key === KeyboardKeys.DownArrow && - current !== refArray.length - 1 - ) { - e.preventDefault(); - - setCurrent(current + 1); - return; - } + const handleDownArrowPress = (e: KeyboardEvent) => { + const isLastElementFocused = current === refArray.length - 1; + const indexToFocus = isLastElementFocused ? 0 : current + 1; - if (e.key === KeyboardKeys.UpArrow && current !== 0) { - e.preventDefault(); + setCurrentAndPreventDefault(e, indexToFocus); + }; - setCurrent(current - 1); - return; + const handleEscapePress = (e: KeyboardEvent) => { + setCurrentAndPreventDefault(e, 0); + if (props.onEsc != null) { + props.onEsc(); } + }; - if (e.key === KeyboardKeys.Escape) { - e.preventDefault(); - setCurrent(0); + const handleUpArrowPress = (e: KeyboardEvent) => { + const isFirstElementFocused = current === 0; + const indexToFocus = isFirstElementFocused + ? refArray.length - 1 + : current - 1; - if (props.onEsc != null) { - props.onEsc(); - } - return; - } + setCurrentAndPreventDefault(e, indexToFocus); }; const renderChildren = () => { @@ -100,6 +99,17 @@ const AccessibleList: React.FunctionComponent = ( }); }; + const setCurrentAndPreventDefault = ( + e: KeyboardEvent, + indexToFocus: number + ) => { + if (indexToFocus < 0) { + return; + } + e.preventDefault(); + setCurrent(indexToFocus); + }; + return {renderChildren()}; }; From 8ae62b4da65d69ff21bca657da8eae072cd65c5c Mon Sep 17 00:00:00 2001 From: Said Shah Date: Fri, 20 Nov 2020 11:11:24 -0500 Subject: [PATCH 2/6] More refactoring and tests --- .../accessible-list/accessible-list.test.tsx | 34 ++++++++++++++++--- .../accessible-list/accessible-list.tsx | 26 ++++++++------ 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/molecules/accessible-list/accessible-list.test.tsx b/src/molecules/accessible-list/accessible-list.test.tsx index e014fc8..af31cda 100644 --- a/src/molecules/accessible-list/accessible-list.test.tsx +++ b/src/molecules/accessible-list/accessible-list.test.tsx @@ -1,6 +1,6 @@ -import React from "react"; +import React, { Component } from "react"; import faker from "faker"; -import { render, fireEvent } from "@testing-library/react"; +import { render, fireEvent, screen } from "@testing-library/react"; import { AccessibleList } from "./accessible-list"; import { KeyboardKeys } from "../../constants/keyboard-keys"; @@ -40,22 +40,48 @@ describe("AccessibleList", () => { expect(isChecked).toBeTrue(); }); - test("when down arrow pressed, calls setCurrent method", () => { + test("when invalid react element, does not render in list", () => { // Arrange const buttonText1 = faker.random.word(); const buttonText2 = faker.random.word(); // Act - const { getByText } = render( + const { container } = render( + {null} + {undefined} ); + const buttons = container.getElementsByTagName("button"); + + // Assert + expect(buttons).toHaveLength(2); + }); + + it("when onClick set, calls handler upon click", async () => { + // Arrange + let isChecked = false; + const handleClick = () => { + isChecked = true; + }; + const buttonText1 = faker.random.word(); + const buttonText2 = faker.random.words(); + + // Act + const { getByText } = render( + + + + + ); + fireEvent.keyDown(getByText(buttonText1), { key: KeyboardKeys.DownArrow, }); // Assert + expect(isChecked).toBeTrue(); }); }); diff --git a/src/molecules/accessible-list/accessible-list.tsx b/src/molecules/accessible-list/accessible-list.tsx index b11294f..e61f524 100644 --- a/src/molecules/accessible-list/accessible-list.tsx +++ b/src/molecules/accessible-list/accessible-list.tsx @@ -86,16 +86,22 @@ const AccessibleList: React.FunctionComponent = ( return child; } - return React.cloneElement(child, { - ...child.props, - onClick: () => { - if (child.props.onClick != null) { - child.props.onClick(); - } - }, - onKeyDown: handleKeyDown, - ref: (el: HTMLElement) => (refArray[validElementIndex++] = el), - }); + const renderedChild = renderChild(child, validElementIndex); + validElementIndex++; + return renderedChild; + }); + }; + + const renderChild = (child: React.ReactElement, index: number) => { + return React.cloneElement(child, { + ...child.props, + onClick: () => { + if (child.props.onClick != null) { + child.props.onClick(); + } + }, + onKeyDown: handleKeyDown, + ref: (el: HTMLElement) => (refArray[index] = el), }); }; From ac83c1c25e107d9e31d204569620a984422ed360 Mon Sep 17 00:00:00 2001 From: Said Shah Date: Fri, 20 Nov 2020 11:15:19 -0500 Subject: [PATCH 3/6] fixed an onClick test --- src/molecules/accessible-list/accessible-list.test.tsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/molecules/accessible-list/accessible-list.test.tsx b/src/molecules/accessible-list/accessible-list.test.tsx index af31cda..9eccfd2 100644 --- a/src/molecules/accessible-list/accessible-list.test.tsx +++ b/src/molecules/accessible-list/accessible-list.test.tsx @@ -66,20 +66,16 @@ describe("AccessibleList", () => { const handleClick = () => { isChecked = true; }; - const buttonText1 = faker.random.word(); - const buttonText2 = faker.random.words(); + const buttonText = faker.random.word(); // Act const { getByText } = render( - - + ); - fireEvent.keyDown(getByText(buttonText1), { - key: KeyboardKeys.DownArrow, - }); + fireEvent.click(getByText(buttonText)); // Assert expect(isChecked).toBeTrue(); From e1c4ef2243c7270fc199954f7b43cd2fda5abb06 Mon Sep 17 00:00:00 2001 From: Said Shah Date: Tue, 24 Nov 2020 08:43:17 -0500 Subject: [PATCH 4/6] Updated tests --- src/molecules/accessible-list/accessible-list.test.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/molecules/accessible-list/accessible-list.test.tsx b/src/molecules/accessible-list/accessible-list.test.tsx index 9eccfd2..55e6b23 100644 --- a/src/molecules/accessible-list/accessible-list.test.tsx +++ b/src/molecules/accessible-list/accessible-list.test.tsx @@ -54,10 +54,10 @@ describe("AccessibleList", () => { ); - const buttons = container.getElementsByTagName("button"); // Assert - expect(buttons).toHaveLength(2); + expect(container.innerHTML).not.toContain("null"); + expect(container.innerHTML).not.toContain("undefined"); }); it("when onClick set, calls handler upon click", async () => { @@ -74,7 +74,6 @@ describe("AccessibleList", () => { ); - fireEvent.click(getByText(buttonText)); // Assert From b020c9af1f947186934fa1d0452d798f2023b7be Mon Sep 17 00:00:00 2001 From: Said Shah Date: Tue, 24 Nov 2020 08:51:05 -0500 Subject: [PATCH 5/6] Updated test --- src/molecules/accessible-list/accessible-list.test.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/molecules/accessible-list/accessible-list.test.tsx b/src/molecules/accessible-list/accessible-list.test.tsx index 55e6b23..fb529dd 100644 --- a/src/molecules/accessible-list/accessible-list.test.tsx +++ b/src/molecules/accessible-list/accessible-list.test.tsx @@ -42,16 +42,15 @@ describe("AccessibleList", () => { test("when invalid react element, does not render in list", () => { // Arrange - const buttonText1 = faker.random.word(); - const buttonText2 = faker.random.word(); + const buttonText = [faker.random.word(), faker.random.word()]; // Act const { container } = render( - + {null} {undefined} - + ); From 681b9559160f401c7770d2d6fb2756bd9e519e82 Mon Sep 17 00:00:00 2001 From: Said Shah Date: Wed, 25 Nov 2020 14:43:29 -0500 Subject: [PATCH 6/6] Changed assert for invalid element test --- src/molecules/accessible-list/accessible-list.test.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/molecules/accessible-list/accessible-list.test.tsx b/src/molecules/accessible-list/accessible-list.test.tsx index fb529dd..10a2f2f 100644 --- a/src/molecules/accessible-list/accessible-list.test.tsx +++ b/src/molecules/accessible-list/accessible-list.test.tsx @@ -55,8 +55,7 @@ describe("AccessibleList", () => { ); // Assert - expect(container.innerHTML).not.toContain("null"); - expect(container.innerHTML).not.toContain("undefined"); + expect(container.childNodes).toHaveLength(2); }); it("when onClick set, calls handler upon click", async () => {