add tab tests

This commit is contained in:
charbelrami 2022-10-04 15:08:57 -03:00
parent 50931dd848
commit a42ef41e8d
4 changed files with 280 additions and 36 deletions

View File

@ -246,10 +246,11 @@ viewTabPanel tab selected =
++ (if selected then
[ -- Used as selector for test queries
Attributes.attribute "data-selected" "true"
, Attributes.style "display" "block"
]
else
[ Attributes.css [ Css.display Css.none ]
[ Attributes.style "display" "none"
]
)
)

View File

@ -118,6 +118,24 @@ pressShiftLeft { targetDetails } =
pressKey { targetDetails = targetDetails, keyCode = 37, shiftKey = True }
releaseRightArrow :
{ targetDetails : List ( String, Encode.Value ) }
-> List Selector
-> ProgramTest model msg effect
-> ProgramTest model msg effect
releaseRightArrow { targetDetails } =
releaseKey { targetDetails = targetDetails, keyCode = 39, shiftKey = False }
releaseLeftArrow :
{ targetDetails : List ( String, Encode.Value ) }
-> List Selector
-> ProgramTest model msg effect
-> ProgramTest model msg effect
releaseLeftArrow { targetDetails } =
releaseKey { targetDetails = targetDetails, keyCode = 37, shiftKey = False }
releaseShiftRight :
{ targetDetails : List ( String, Encode.Value ) }
-> List Selector

View File

@ -28,7 +28,7 @@ keyboardTests =
\() ->
Highlightable.initFragments Nothing "Pothos indirect light"
|> program marker
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> done
, test "has only one element included in the tab sequence" <|
\() ->
@ -40,55 +40,55 @@ keyboardTests =
\() ->
Highlightable.initFragments Nothing "Pothos indirect light"
|> program marker
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> rightArrow
|> ensureFocusOn "indirect"
|> ensureTabbable "indirect"
|> ensureOnlyOneInTabSequence (String.words "Pothos indirect light")
|> rightArrow
|> ensureFocusOn "light"
|> ensureTabbable "light"
-- once we're on the final element, pressing right arrow again should
-- _not_ wrap the focus. We should stay right where we are!
|> rightArrow
|> ensureFocusOn "light"
|> ensureTabbable "light"
|> done
, test "moves focus left on left arrow key" <|
\() ->
Highlightable.initFragments Nothing "Pothos indirect light"
|> program marker
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> rightArrow
|> ensureFocusOn "indirect"
|> ensureTabbable "indirect"
|> leftArrow
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> ensureOnlyOneInTabSequence (String.words "Pothos indirect light")
-- once we're on the first element, pressing left arrow again should
-- _not_ wrap the focus. We should stay right where we are!
|> leftArrow
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> done
, test "moves focus right on shift + right arrow" <|
\() ->
Highlightable.initFragments Nothing "Pothos indirect light"
|> program marker
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> shiftRight
|> ensureFocusOn "indirect"
|> ensureTabbable "indirect"
|> shiftRight
|> ensureFocusOn "light"
|> ensureTabbable "light"
|> shiftRight
|> ensureFocusOn "light"
|> ensureTabbable "light"
|> done
, test "moves focus left on shift + left arrow" <|
\() ->
Highlightable.initFragments Nothing "Pothos indirect light"
|> program marker
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> rightArrow
|> ensureFocusOn "indirect"
|> ensureTabbable "indirect"
|> shiftLeft
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> shiftLeft
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> done
, test "expands selection one element to the right on shift + right arrow and highlight selected elements" <|
\() ->
@ -124,13 +124,13 @@ keyboardTests =
\() ->
Highlightable.initFragments Nothing "Pothos indirect light"
|> program marker
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> shiftRight
|> releaseShiftRight
|> ensureMarked [ "Pothos", " ", "indirect" ]
|> ensureFocusOn "indirect"
|> ensureTabbable "indirect"
|> rightArrow
|> ensureFocusOn "light"
|> ensureTabbable "light"
|> shiftLeft
|> releaseShiftLeft
|> ensureMarked [ "Pothos", " ", "indirect", " ", "light" ]
@ -139,7 +139,7 @@ keyboardTests =
\() ->
Highlightable.initFragments Nothing "Pothos indirect light"
|> program marker
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> mouseDown "Pothos"
|> mouseUp "Pothos"
|> ensureMarked [ "Pothos" ]
@ -148,7 +148,7 @@ keyboardTests =
\() ->
Highlightable.initFragments Nothing "Pothos indirect light"
|> program marker
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> mouseDown "Pothos"
|> mouseOver "indirect"
|> mouseUp "Pothos"
@ -158,7 +158,7 @@ keyboardTests =
\() ->
Highlightable.initFragments Nothing "Pothos indirect light"
|> program marker
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> space
|> ensureMarked [ "Pothos" ]
|> done
@ -166,10 +166,10 @@ keyboardTests =
\() ->
Highlightable.initFragments Nothing "Pothos indirect light"
|> program marker
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> space
|> ensureMarked [ "Pothos" ]
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> mouseDown "Pothos"
|> mouseUp "Pothos"
|> expectViewHasNot
@ -178,7 +178,7 @@ keyboardTests =
\() ->
Highlightable.initFragments Nothing "Pothos indirect light"
|> program marker
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> shiftRight
|> releaseShiftRight
|> ensureMarked [ "Pothos", " ", "indirect" ]
@ -190,19 +190,19 @@ keyboardTests =
\() ->
Highlightable.initFragments Nothing "Pothos indirect light"
|> program marker
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> space
|> ensureMarked [ "Pothos" ]
|> ensureFocusOn "Pothos"
|> ensureTabbable "Pothos"
|> space
|> expectViewHasNot
[ Selector.tag "mark" ]
]
ensureFocusOn : String -> TestContext marker -> TestContext marker
ensureFocusOn word textContext =
textContext
ensureTabbable : String -> TestContext marker -> TestContext marker
ensureTabbable word testContext =
testContext
|> ensureView
(Query.find [ Selector.attribute (Key.tabbable True) ]
>> Query.has [ Selector.text word ]
@ -210,8 +210,8 @@ ensureFocusOn word textContext =
ensureOnlyOneInTabSequence : List String -> TestContext marker -> TestContext marker
ensureOnlyOneInTabSequence words textContext =
textContext
ensureOnlyOneInTabSequence words testContext =
testContext
|> ensureView
(Query.findAll [ Selector.attribute (Key.tabbable True) ]
>> Query.count (Expect.equal 1)
@ -223,8 +223,8 @@ ensureOnlyOneInTabSequence words textContext =
ensureMarked : List String -> TestContext marker -> TestContext marker
ensureMarked words textContext =
textContext
ensureMarked words testContext =
testContext
|> ensureView
(Query.find [ Selector.tag "mark" ]
>> Query.children [ Selector.tag "span" ]
@ -232,6 +232,10 @@ ensureMarked words textContext =
)
-- TODO: ensure other elements are not marked
space : TestContext marker -> TestContext marker
space =
KeyboardHelpers.pressSpaceKey { targetDetails = [] }

221
tests/Spec/Nri/Ui/Tabs.elm Normal file
View File

@ -0,0 +1,221 @@
module Spec.Nri.Ui.Tabs exposing (spec)
import Accessibility.Key as Key
import Accessibility.Role as Role
import Browser.Dom as Dom
import Expect
import Html.Styled as Html exposing (..)
import Nri.Ui.Tabs.V7 as Tabs
import ProgramTest exposing (..)
import Spec.KeyboardHelpers as KeyboardHelpers
import Task
import Test exposing (..)
import Test.Html.Query as Query
import Test.Html.Selector as Selector
spec : Test
spec =
describe "Nri.Ui.Tabs.V7"
[ describe "panel rendering" panelRenderingTests
, describe "keyboard behavior" keyboardTests
]
panelRenderingTests : List Test
panelRenderingTests =
[ test "displays the associated panel when a tab is activated" <|
\() ->
program
|> ensureTabbable "Tab 0"
|> ensurePanelDisplayed "Panel 0"
|> done
, test "has only one panel displayed" <|
\() ->
program
|> ensureOnlyOnePanelDisplayed [ "Panel 0", "Panel 1", "Panel 2" ]
|> done
]
keyboardTests : List Test
keyboardTests =
[ test "has a focusable tab" <|
\() ->
program
|> ensureTabbable "Tab 0"
|> done
, test "all panels are focusable" <|
\() ->
program
|> ensurePanelsFocusable [ "Panel 0", "Panel 1", "Panel 2" ]
|> done
, test "has only one tab included in the tab sequence" <|
\() ->
program
|> ensureOnlyOneTabInSequence [ "Tab 0", "Tab 1", "Tab 2" ]
|> done
, test "moves focus right on right arrow key" <|
\() ->
program
|> ensureTabbable "Tab 0"
|> releaseRightArrow
|> ensureTabbable "Tab 1"
|> ensureOnlyOneTabInSequence [ "Tab 0", "Tab 1", "Tab 2" ]
|> releaseRightArrow
|> ensureTabbable "Tab 2"
|> done
, test "moves focus left on left arrow key" <|
\() ->
program
|> ensureTabbable "Tab 0"
|> releaseRightArrow
|> ensureTabbable "Tab 1"
|> releaseLeftArrow
|> ensureTabbable "Tab 0"
|> ensureOnlyOneTabInSequence [ "Tab 0", "Tab 1", "Tab 2" ]
|> done
, test "when the focus is on the first element, move focus to the last element on left arrow key" <|
\() ->
program
|> ensureTabbable "Tab 0"
|> releaseLeftArrow
|> ensureTabbable "Tab 2"
|> ensureOnlyOneTabInSequence [ "Tab 0", "Tab 1", "Tab 2" ]
|> done
, test "when the focus is on the last element, move focus to the first element on right arrow key" <|
\() ->
program
|> ensureTabbable "Tab 0"
|> releaseLeftArrow
|> ensureTabbable "Tab 2"
|> releaseRightArrow
|> ensureTabbable "Tab 0"
|> ensureOnlyOneTabInSequence [ "Tab 0", "Tab 1", "Tab 2" ]
|> done
]
type alias TestContext =
ProgramTest State Msg ()
ensureTabbable : String -> TestContext -> TestContext
ensureTabbable word testContext =
testContext
|> ensureView
(Query.find [ Selector.attribute Role.tab, Selector.attribute (Key.tabbable True) ]
>> Query.has [ Selector.text word ]
)
ensurePanelsFocusable : List String -> TestContext -> TestContext
ensurePanelsFocusable words testContext =
testContext
|> ensureView
(Query.findAll [ Selector.attribute Role.tabPanel, Selector.attribute (Key.tabbable True) ]
>> Expect.all (List.indexedMap (\i w -> Query.index i >> Query.has [ Selector.text w ]) words)
)
ensurePanelDisplayed : String -> TestContext -> TestContext
ensurePanelDisplayed word testContext =
testContext
|> ensureView
(Query.find [ Selector.attribute Role.tabPanel, Selector.style "display" "block" ]
>> Query.has [ Selector.text word ]
)
ensureOnlyOnePanelDisplayed : List String -> TestContext -> TestContext
ensureOnlyOnePanelDisplayed panels testContext =
testContext
|> ensureView
(Query.findAll [ Selector.attribute Role.tabPanel, Selector.style "display" "block" ]
>> Query.count (Expect.equal 1)
)
|> ensureView
(Query.findAll [ Selector.attribute Role.tabPanel, Selector.style "display" "none" ]
>> Query.count (Expect.equal (List.length panels - 1))
)
ensureOnlyOneTabInSequence : List String -> TestContext -> TestContext
ensureOnlyOneTabInSequence tabs testContext =
testContext
|> ensureView
(Query.findAll [ Selector.attribute Role.tab, Selector.attribute (Key.tabbable True) ]
>> Query.count (Expect.equal 1)
)
|> ensureView
(Query.findAll [ Selector.attribute Role.tab, Selector.attribute (Key.tabbable False) ]
>> Query.count (Expect.equal (List.length tabs - 1))
)
releaseRightArrow : TestContext -> TestContext
releaseRightArrow =
KeyboardHelpers.releaseRightArrow { targetDetails = [] }
[ Selector.attribute Role.tab, Selector.attribute (Key.tabbable True) ]
releaseLeftArrow : TestContext -> TestContext
releaseLeftArrow =
KeyboardHelpers.releaseLeftArrow { targetDetails = [] }
[ Selector.attribute Role.tab, Selector.attribute (Key.tabbable True) ]
type alias State =
{ selected : Int
}
init : State
init =
{ selected = 0
}
type Msg
= FocusAndSelectTab { select : Int, focus : Maybe String }
| Focused (Result Dom.Error ())
update : Msg -> State -> State
update msg model =
case msg of
FocusAndSelectTab { select, focus } ->
Tuple.first
( { model | selected = select }
, focus
|> Maybe.map (Dom.focus >> Task.attempt Focused)
|> Maybe.withDefault Cmd.none
)
Focused error ->
Tuple.first ( model, Cmd.none )
view model =
Tabs.view
{ title = Nothing
, alignment = Tabs.Left
, customSpacing = Nothing
, focusAndSelect = FocusAndSelectTab
, selected = model.selected
, tabs =
[ Tabs.build { id = 0, idString = "tab-0" } [ Tabs.tabString "Tab 0", Tabs.panelHtml (text "Panel 0") ]
, Tabs.build { id = 1, idString = "tab-1" } [ Tabs.tabString "Tab 1", Tabs.panelHtml (text "Panel 1") ]
, Tabs.build { id = 2, idString = "tab-2" } [ Tabs.tabString "Tab 2", Tabs.panelHtml (text "Panel 2") ]
]
}
program : TestContext
program =
ProgramTest.createSandbox
{ init = init
, update = update
, view = view >> Html.toUnstyled
}
|> ProgramTest.start ()