Querying HTML structure.
Internal.Single msg
A query that expects to find exactly one element.
Contrast with Multiple
.
Internal.Multiple msg
A query that may find any number of elements, including zero.
Contrast with Single
.
fromHtml : Html msg -> Single msg
Translate a Html
value into a Single
query. This is how queries
typically begin.
import Html
import Test.Html.Query as Query
import Test exposing (test)
import Test.Html.Selector exposing (text)
test "Button has the expected text" <|
\() ->
Html.button [] [ Html.text "I'm a button!" ]
|> Query.fromHtml
|> Query.has [ text "I'm a button!" ]
find : List Test.Html.Selector.Selector -> Single msg -> Single msg
Find exactly one descendant element which matches all the given selectors. If no descendants match, or if more than one matches, the test will fail.
import Html exposing (div, ul, li)
import Html.Attributes exposing (class)
import Test.Html.Query as Query
import Test exposing (test)
import Test.Html.Selector exposing (tag, classes)
test "The list has both the classes 'items' and 'active'" <|
\() ->
div []
[ ul [ class "items active" ]
[ li [] [ text "first item" ]
, li [] [ text "second item" ]
, li [] [ text "third item" ]
]
]
|> Query.fromHtml
|> Query.find [ tag "ul" ]
|> Query.has [ classes [ "items", "active" ] ]
findAll : List Test.Html.Selector.Selector -> Single msg -> Multiple msg
Find the descendant elements which match all the given selectors.
import Html exposing (div, ul, li)
import Html.Attributes exposing (class)
import Test.Html.Query as Query
import Test exposing (test)
import Test.Html.Selector exposing (tag)
import Expect
test "The list has three items" <|
\() ->
div []
[ ul [ class "items active" ]
[ li [] [ text "first item" ]
, li [] [ text "second item" ]
, li [] [ text "third item" ]
]
]
|> Query.fromHtml
|> Query.findAll [ tag "li" ]
|> Query.count (Expect.equal 3)
children : List Test.Html.Selector.Selector -> Single msg -> Multiple msg
Return the matched element's immediate child elements.
import Html exposing (div, ul, li)
import Html.Attributes exposing (class)
import Test.Html.Query as Query
import Test exposing (test)
import Test.Html.Selector exposing (tag, classes)
test "The <ul> only has <li> children" <|
\() ->
div []
[ ul [ class "items active" ]
[ li [ class "item"] [ text "first item" ]
, li [ class "item selected"] [ text "second item" ]
, li [ class "item"] [ text "third item" ]
]
]
|> Query.fromHtml
|> Query.find [ class "items" ]
|> Query.children [ class "selected" ]
|> Query.count (Expect.equal 1)
first : Multiple msg -> Single msg
Return the first element in a match. If there were no matches, the test will fail.
Query.first
is a shorthand for Query.index 0
- they do the same thing.
import Html exposing (div, ul, li)
import Html.Attributes exposing (class)
import Test.Html.Query as Query
import Test exposing (test)
import Test.Html.Selector exposing (tag, classes)
test "The first <li> is called 'first item'" <|
\() ->
div []
[ ul [ class "items active" ]
[ li [] [ text "first item" ]
, li [] [ text "second item" ]
, li [] [ text "third item" ]
]
]
|> Query.fromHtml
|> Query.findAll [ tag "li" ]
|> Query.first
|> Query.has [ text "first item" ]
index : Basics.Int -> Multiple msg -> Single msg
Return the element in a match at the given index. For example,
Query.index 0
would match the first element, and Query.index 1
would match
the second element.
You can pass negative numbers to get elements from the end - for example, Query.index -1
will match the last element, and Query.index -2
will match the second-to-last.
If the index falls outside the bounds of the match, the test will fail.
import Html exposing (div, ul, li)
import Html.Attributes exposing (class)
import Test.Html.Query as Query
import Test exposing (test)
import Test.Html.Selector exposing (tag, classes)
test "The second <li> is called 'second item'" <|
\() ->
div []
[ ul [ class "items active" ]
[ li [] [ text "first item" ]
, li [] [ text "second item" ]
, li [] [ text "third item" ]
]
]
|> Query.fromHtml
|> Query.findAll [ tag "li" ]
|> Query.index 1
|> Query.has [ text "second item" ]
keep : Test.Html.Selector.Selector -> Multiple msg -> Multiple msg
Find the descendant elements of the result of findAll
which match all the given selectors.
import Html exposing (div, ul, li)
import Html.Attributes exposing (class)
import Test.Html.Query as Query
import Test exposing (test)
import Test.Html.Selector exposing (tag)
import Expect
test "The list has three items" <|
\() ->
div []
[ ul [ class "items active" ]
[ li [] [ a [] [ text "first item" ]]
, li [] [ a [] [ text "second item" ]]
, li [] [ a [] [ text "third item" ]]
, li [] [ button [] [ text "button" ]]
]
]
|> Query.fromHtml
|> Query.findAll [ tag "li" ]
|> Query.keep ( tag "a" )
|> Expect.all
[ Query.each (Query.has [ tag "a" ])
, Query.first >> Query.has [ text "first item" ]
]
count : (Basics.Int -> Expectation) -> Multiple msg -> Expectation
Expect the number of elements matching the query fits the given expectation.
import Html exposing (div, ul, li)
import Html.Attributes exposing (class)
import Test.Html.Query as Query
import Test exposing (test)
import Test.Html.Selector exposing (tag)
import Expect
test "The list has three items" <|
\() ->
div []
[ ul [ class "items active" ]
[ li [] [ text "first item" ]
, li [] [ text "second item" ]
, li [] [ text "third item" ]
]
]
|> Query.fromHtml
|> Query.findAll [ tag "li" ]
|> Query.count (Expect.equal 3)
contains : List (Html msg) -> Single msg -> Expectation
Expect the element to have at least one descendant matching each node in the list.
import Html exposing (div, ul, li)
import Html.Attributes exposing (class)
import Test.Html.Query as Query
import Test exposing (test)
import Test.Html.Selector exposing (tag, classes)
test "The list has two li: one with the text \"third item\" and \
another one with \"first item\"" <|
\() ->
div []
[ ul [ class "items active" ]
[ li [] [ text "first item" ]
, li [] [ text "second item" ]
, li [] [ text "third item" ]
]
]
|> Query.fromHtml
|> Query.contains
[ li [] [ text "third item" ]
, li [] [ text "first item" ]
]
has : List Test.Html.Selector.Selector -> Single msg -> Expectation
Expect the element to match all of the given selectors.
import Html exposing (div, ul, li)
import Html.Attributes exposing (class)
import Test.Html.Query as Query
import Test exposing (test)
import Test.Html.Selector exposing (tag, classes)
test "The list has both the classes 'items' and 'active'" <|
\() ->
div []
[ ul [ class "items active" ]
[ li [] [ text "first item" ]
, li [] [ text "second item" ]
, li [] [ text "third item" ]
]
]
|> Query.fromHtml
|> Query.find [ tag "ul" ]
|> Query.has [ tag "ul", classes [ "items", "active" ] ]
hasNot : List Test.Html.Selector.Selector -> Single msg -> Expectation
Expect the element to not match all of the given selectors.
import Html exposing (div)
import Html.Attributes as Attributes
import Test.Html.Query as Query
import Test exposing (test)
import Test.Html.Selector exposing (tag, class)
test "The div element has no progress-bar class" <|
\() ->
div [ Attributes.class "button" ] []
|> Query.fromHtml
|> Query.find [ tag "div" ]
|> Query.hasNot [ tag "div", class "progress-bar" ]
each : (Single msg -> Expectation) -> Multiple msg -> Expectation
Expect that a Single
expectation will hold true for each of the
Multiple
matched elements.
import Html exposing (div, ul, li)
import Html.Attributes exposing (class)
import Test.Html.Query as Query
import Test exposing (test)
import Test.Html.Selector exposing (tag, classes)
test "The list has both the classes 'items' and 'active'" <|
\() ->
div []
[ ul [ class "items active" ]
[ li [] [ text "first item" ]
, li [] [ text "second item" ]
, li [] [ text "third item" ]
]
]
|> Query.fromHtml
|> Query.findAll [ tag "ul" ]
|> Query.each
(Expect.all
[ Query.has [ tag "ul" ]
, Query.has [ classes [ "items", "active" ] ]
]
)