From 4f99c1359e46034aae832d34946af168e9c9d2e2 Mon Sep 17 00:00:00 2001 From: charbelrami Date: Thu, 26 Oct 2023 12:17:38 -0300 Subject: [PATCH] refactor and add ClickableText tests --- tests/Spec/Nri/Ui/ClickableText.elm | 399 +++++++++++++++++++++++++--- 1 file changed, 359 insertions(+), 40 deletions(-) diff --git a/tests/Spec/Nri/Ui/ClickableText.elm b/tests/Spec/Nri/Ui/ClickableText.elm index 48d962aa8..7468326f2 100644 --- a/tests/Spec/Nri/Ui/ClickableText.elm +++ b/tests/Spec/Nri/Ui/ClickableText.elm @@ -1,72 +1,391 @@ -module Spec.Nri.Ui.ClickableText exposing (spec) +module Spec.Nri.Ui.ClickableText exposing (..) import Accessibility.Aria as Aria -import Html.Styled exposing (Html, toUnstyled) +import Accessibility.Role as Role +import Html.Attributes as Attributes +import Html.Styled exposing (..) +import Nri.Test.KeyboardHelpers.V1 as KeyboardHelpers +import Nri.Test.MouseHelpers.V1 as MouseHelpers import Nri.Ui.ClickableText.V3 as ClickableText +import Nri.Ui.UiIcon.V1 as UiIcon import ProgramTest exposing (..) import Spec.Helpers exposing (expectFailure) import Test exposing (..) -import Test.Html.Selector exposing (..) +import Test.Html.Event as Event +import Test.Html.Query as Query +import Test.Html.Selector as Selector exposing (..) spec : Test spec = describe "Nri.Ui.ClickableText.V3" - [ describe "helpfullyDisabledClickableText" helpfullyDisabledClickableText + [ describe "elements" elementTests + , describe "attributes" attributeTests + , describe "icon accessibility" iconAccessibilityTests + , describe "disabled behavior and attributes" disabledStateTests ] -helpfullyDisabledClickableText : List Test -helpfullyDisabledClickableText = - [ test "does not have `aria-disabled=\"true\" when not disabled" <| +type Type_ + = Button + | Link + + +elementTests : List Test +elementTests = + [ testAsButton + , testAsAnchor + , testIconAsSvg + ] + + +testAsButton : Test +testAsButton = + test "the `button` type renders as a button element" <| + \() -> + program Button [] + |> ensureViewHas [ tag "button" ] + |> done + + +testAsAnchor : Test +testAsAnchor = + test "the `link` type renders as an anchor element" <| + \() -> + program Link [] + |> ensureViewHas [ tag "a" ] + |> done + + +testIconAsSvg : Test +testIconAsSvg = + test "renders an svg element when an icon is provided" <| + \() -> + program Button [ ClickableText.icon UiIcon.arrowLeft ] + |> ensureViewHas [ tag "svg" ] + |> done + + +attributeTests : List Test +attributeTests = + [ testHref + , testLinkExternalHref + , testTarget + , testLinkExternalTarget + , testLinkExternalRel + ] + + +testHref : Test +testHref = + test "a link has the `href` attribute set to the provided value" <| + \() -> + program Link [ ClickableText.href "https://example.com" ] + |> ensureViewHas + [ attribute (Attributes.href "https://example.com") + ] + |> done + + +testLinkExternalHref : Test +testLinkExternalHref = + test "an external link has the `href` attribute set to the provided value" <| + \() -> + program Link [ ClickableText.linkExternal "https://example.com" ] + |> ensureViewHas + [ attribute (Attributes.href "https://example.com") + ] + |> done + + +testTarget : Test +testTarget = + test "a default link has the `target` attribute set to `\"_self\"`" <| + \() -> + program Link [ ClickableText.href "https://example.com" ] + |> ensureViewHas + [ attribute (Attributes.target "_self") + ] + |> done + + +testLinkExternalTarget : Test +testLinkExternalTarget = + test "an external link has the `target` attribute set to `\"_blank\"`" <| + \() -> + program Link [ ClickableText.linkExternal "https://example.com" ] + |> ensureViewHas + [ attribute (Attributes.target "_blank") + ] + |> done + + +testLinkExternalRel : Test +testLinkExternalRel = + test "an external link has the `rel` attribute set to `\"noopener noreferrer\"`" <| \() -> - program () - (\_ -> - ClickableText.button "Text" - [] - ) + program Link [ ClickableText.linkExternal "https://example.com" ] + |> ensureViewHas + [ attribute (Attributes.rel "noopener noreferrer") + ] + |> done + + +iconAccessibilityTests : List Test +iconAccessibilityTests = + [ testIconAriaHidden + , testIconRole + , testIconFocusable + , testRightIconAriaHidden + , testRightIconRole + , testRightIconFocusable + , testLinkExternalIconAriaHiddenAbsence + , testLinkExternalIconRole + , testLinkExternalIconFocusable + , testLinkExternalIconSvgTitle + ] + + +testIconAriaHidden : Test +testIconAriaHidden = + test "the icon has the `aria-hidden` attribute set to `\"true\"`" <| + \() -> + program Button [ ClickableText.icon UiIcon.arrowLeft ] + |> ensureViewHas + [ attribute (Aria.hidden True) + ] + |> done + + +testIconRole : Test +testIconRole = + test "the icon has the `role` attribute set to `\"img\"`" <| + \() -> + program Button [ ClickableText.icon UiIcon.arrowLeft ] + |> ensureViewHas + [ attribute Role.img + ] + |> done + + +testIconFocusable : Test +testIconFocusable = + test "the icon has the `focusable` attribute set to `\"false\"`" <| + \() -> + program Button [ ClickableText.icon UiIcon.arrowLeft ] + |> ensureViewHas + [ attribute (Attributes.attribute "focusable" "false") + ] + |> done + + +testRightIconAriaHidden : Test +testRightIconAriaHidden = + test "the right icon has the `aria-hidden` attribute set to `\"true\"`" <| + \() -> + program Button [ ClickableText.rightIcon UiIcon.arrowLeft ] + |> ensureViewHas + [ attribute (Aria.hidden True) + ] + |> done + + +testRightIconRole : Test +testRightIconRole = + test "the right icon has the `role` attribute set to `\"img\"`" <| + \() -> + program Button [ ClickableText.rightIcon UiIcon.arrowLeft ] + |> ensureViewHas + [ attribute Role.img + ] + |> done + + +testRightIconFocusable : Test +testRightIconFocusable = + test "the right icon has the `focusable` attribute set to `\"false\"`" <| + \() -> + program Button [ ClickableText.rightIcon UiIcon.arrowLeft ] + |> ensureViewHas + [ attribute (Attributes.attribute "focusable" "false") + ] + |> done + + +testLinkExternalIconAriaHiddenAbsence : Test +testLinkExternalIconAriaHiddenAbsence = + test "the `aria-hidden` attribute is not present for an external link icon" <| + \() -> + program Link [ ClickableText.linkExternal "https://example.com" ] + |> ensureViewHasNot + [ attribute (Aria.hidden True) + ] + |> done + + +testLinkExternalIconRole : Test +testLinkExternalIconRole = + test "the external link icon has the `role` attribute set to `\"img\"`" <| + \() -> + program Link [ ClickableText.linkExternal "https://example.com" ] + |> ensureViewHas + [ attribute Role.img + ] + |> done + + +testLinkExternalIconFocusable : Test +testLinkExternalIconFocusable = + test "the external link icon has the `focusable` attribute set to `\"false\"`" <| + \() -> + program Link [ ClickableText.linkExternal "https://example.com" ] + |> ensureViewHas + [ attribute (Attributes.attribute "focusable" "false") + ] + |> done + + +testLinkExternalIconSvgTitle : Test +testLinkExternalIconSvgTitle = + test "the external link icon has the `title` tag set to `\"Opens in a new tab\"`" <| + \() -> + program Link [ ClickableText.linkExternal "https://example.com" ] + |> ensureViewHas + [ tag "title" + , containing [ Selector.text "Opens in a new tab" ] + ] + |> done + + +disabledStateTests : List Test +disabledStateTests = + [ testAriaDisabledAbsence + , testAriaDisabled + , testClickable + , testNotClickable + ] + + +testAriaDisabledAbsence : Test +testAriaDisabledAbsence = + test "the `aria-disabled` attribute is not present for an enabled ClickableText" <| + \() -> + program Button [] |> ensureViewHasNot [ attribute (Aria.disabled True) ] |> done - , test "has `aria-disabled=\"true\" when disabled" <| + + +testAriaDisabled : Test +testAriaDisabled = + test "the `aria-disabled` attribute is present and set to `\"true\"` for a disabled ClickableText" <| \() -> - program () - (\_ -> - ClickableText.button "Text" - [ ClickableText.disabled True - ] - ) + program Button [ ClickableText.disabled True ] |> ensureViewHas [ attribute (Aria.disabled True) ] |> done - , test "is clickable when not disabled" <| + + +testClickable : Test +testClickable = + test "is clickable when enabled" <| \() -> - program () - (\_ -> - ClickableText.button "Text" - [ ClickableText.onClick () - ] - ) - |> clickButton "Text" + program Button + [ ClickableText.onClick NoOp + ] + |> clickOnButton |> done - , test "is not clickable when disabled" <| + + +testNotClickable : Test +testNotClickable = + test "is not clickable when disabled" <| \() -> - program () - (\_ -> - ClickableText.button "Text" - [ ClickableText.onClick () - , ClickableText.disabled True - ] - ) - |> clickButton "Text" + program Button + [ ClickableText.disabled True + ] + |> clickOnButton |> done |> expectFailure "Event.expectEvent: I found a node, but it does not listen for \"click\" events like I expected it would." + + +buttonSelectors : List Selector +buttonSelectors = + [ tag "button" ] -program : model -> (model -> Html model) -> ProgramTest model model () -program init view = +type alias TestContext = + ProgramTest Model Msg () + + +pressSpaceOnButton : TestContext -> TestContext +pressSpaceOnButton = + KeyboardHelpers.pressSpace keyboardHelperConfig { targetDetails = [] } buttonSelectors + + +clickOnButton : TestContext -> TestContext +clickOnButton = + MouseHelpers.click mouseHelperConfig buttonSelectors + + +type alias Model = + () + + +init : Model +init = + () + + +type Msg + = NoOp + + +update : Msg -> Model -> Model +update msg state = + case msg of + NoOp -> + state + + +view : Type_ -> List (ClickableText.Attribute Msg) -> Model -> Html Msg +view type_ attributes _ = + div [] + (case type_ of + Button -> + [ ClickableText.button "Accessible name" attributes + ] + + Link -> + [ ClickableText.link "Accessible name" attributes + ] + ) + + +program : Type_ -> List (ClickableText.Attribute Msg) -> TestContext +program type_ attributes = ProgramTest.createSandbox { init = init - , update = \msg model -> msg - , view = \model -> Html.Styled.div [] [ view model ] |> toUnstyled + , update = update + , view = view type_ attributes >> toUnstyled } |> ProgramTest.start () + + +keyboardHelperConfig : KeyboardHelpers.Config (ProgramTest model msg effect) Selector.Selector (Query.Single msg) +keyboardHelperConfig = + { programTest_simulateDomEvent = ProgramTest.simulateDomEvent + , query_find = Query.find + , event_custom = Event.custom + } + + +mouseHelperConfig : MouseHelpers.Config (ProgramTest model msg effect) Selector.Selector (Query.Single msg) +mouseHelperConfig = + { programTest_simulateDomEvent = ProgramTest.simulateDomEvent + , query_find = Query.find + , event_click = Event.click + , event_mouseDown = Event.mouseDown + , event_mouseUp = Event.mouseUp + , event_mouseOver = Event.mouseOver + , event_custom = Event.custom + }