Test that Msg is not emitted on disabled button

I have a button that, if set to be disabled, does not emit any Msgs and I want to write a test that this is true.

Currently I have this “disabled functionality” by conditionally adding the onClick handler from Html.Events.onClick only if the configuration record of the button has disabled set to False.

basically the code looks like this:

if not options.disabled then
   -- add onClick handler from Html.Events
else
  -- do not add onClick handler

The following is the test I would like to have:

test "Does not emit a Msg" <|
                \_ ->
                    button "disabled button"
                        |> onClick Clicked
                        |> disabled True
                        |> toHtml
                        |> Query.fromHtml
                        |> Event.simulate (Event.click)
                        |> Event.expect never

Is there a way to actually implement the above (currently hypothetical) test?

Would something like this suffice?

module ButtonTest exposing (suite)

import Expect
import Html exposing (Html)
import Main exposing (Msg(..))
import Test exposing (Test, describe, test)
import Test.Html.Event as Event exposing (Event)
import Test.Html.Query as Query
import Test.Html.Selector exposing (tag)


buttonDisabled : Html Msg
buttonDisabled =
    Main.view False


buttonEnabled : Html Msg
buttonEnabled =
    Main.view True


findButton : Html msg -> Query.Single msg
findButton view =
    view
        |> Query.fromHtml
        |> Query.find [ tag "button" ]


clickButton : Query.Single msg -> Event msg
clickButton button =
    Event.simulate
        Event.click
        button


suite : Test
suite =
    describe "Button"
        [ test "Enabled" <|
            \_ ->
                buttonEnabled
                    |> findButton
                    |> clickButton
                    |> Event.expect Click
        , test "Disabled" <|
            \_ ->
                buttonDisabled
                    |> findButton
                    |> clickButton
                    |> Event.toResult
                    |> Expect.notEqual (Ok Click)
        ]


It tests the following:

module Main exposing (Msg(..), main, view)

import Browser
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick)



-- INIT


init : () -> ( Model, Cmd Msg )
init _ =
    ( initialModel, Cmd.none )



-- MODEL


type alias Model =
    Bool


initialModel : Model
initialModel =
    True



-- UPDATE


type Msg
    = Click


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Click ->
            ( model, Cmd.none )



-- VIEW


view : Model -> Html.Html Msg
view model =
    div
        []
        [ button
            (if model then
                [ onClick Click ]

             else
                []
            )
            [ text "Button" ]
        ]



-- MAIN


main : Program () Model Msg
main =
    Browser.element
        { init = init
        , view = view
        , update = update
        , subscriptions = \_ -> Sub.none
        }

It’s a simplified version of what you’re trying to do. Just a thought :grinning:

1 Like

In update, replace case msg of with case Debug.log "message" msg and it will log in your console whenever a msg occurs

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.