brian-watkins / elm-spec

Describe the behavior of Elm programs
https://package.elm-lang.org/packages/brian-watkins/elm-spec/latest/
MIT License
29 stars 4 forks source link

Unable to get 'withSubscriptions' working #77

Closed dotnetspec closed 2 months ago

dotnetspec commented 2 months ago

Hi,

I'm attempting to use the withSubscriptions function to test a subscription I use to interact with an Elm port that interfaces with a JavaScript module that communicates with a hardware device. I looked at your Subscriptions sample code:

I have a setup similar to your first scenario (i.e. relatively simple):

sendsSubscriptionSpec : Spec Model Msg
sendsSubscriptionSpec =
  Spec.describe "a worker with subscriptions"
  [ scenario "subscriptions are registered always" (
      given (
        Setup.init ( { count = 0, subscribe = True }, Cmd.none )
          |> Setup.withUpdate testUpdate
          |> Setup.withSubscriptions testSubscriptions
      )
      |> when "some subscription messages are sent"
        [ Port.send "listenForSuperObject" (Encode.object [ ("number", Encode.int 41) ])
        , Port.send "listenForSuperObject" (Encode.object [ ("number", Encode.int 78) ])
        ]
      |> it "updates the model" (
        Observer.observeModel .count
          |> expect (equals 78)
      )
    )

The Elm subscription code, in the app under test, works. i.e. when I run the server at localhost, and click a button in the web app UI, the hardware device I am using to connect to via a port to JavaScript returns the expected json and changes the html element text in Elm from "Not connected yet" to "Connected". This is my test:

jsonObj : E.Value
jsonObj =
    E.object
        [ ( "operationEventMsg", E.string "1KrEBrdLTotPZWDRQN1WUn7PDbXA7fwfsS" )
        ]

runSpecTests : Spec Pages.Hardware.Model Pages.Hardware.Msg
runSpecTests =
    describe
        "Scenarios based on a Haveno Web App MVP"
        [ 
          scenario "1. Connecting the Hardware Wallet"
            (given
                (Setup.init
                    (Pages.Hardware.init { time = Nothing, flagUrl = placeholderUrl })
                    |> Setup.withView Pages.Hardware.view
                    |> Setup.withSubscriptions Pages.Hardware.hardwareSubscriptions
                )
                |> when "we simulate clicking the ledger connect button"
                    [ Spec.Command.send <|
                        Spec.Command.fake
                            Pages.Hardware.ClickedLedgerConnect
                    ]
                |> when "sent the right message over the port"
                    [ 
                      Spec.Port.send "receiveMessageFromJs" jsonObj
                    ]
                |> Spec.observeThat
                    [ it "displays a message indicating the lns is connected and initialized"
                        (Markup.observeElement
                            |> Markup.query
                            -- NOTE: It appears that the test ONLY matches on the first element that matches the selector
                            << by [ tag "h6" ]
                            |> Spec.expect
                                (Claim.isSomethingWhere <|
                                    Markup.text <|
                                        Claim.isStringContaining 1 "Connected"
                                )
                        )
                    ]
            )
        ]

In the JavaScript I have: app.ports.receiveMessageFromJs.send({ operationEventMsg: bitcoinAddress });

In the main app, back in Elm this outputs to console as: "{\"operationEventMsg\":\"1KrEBrdLTotPZWDRQN1WUn7PDbXA7fwfsS\"}"

and in Elm I can decode this to determine that the hardware is connected (handled by ResponseDataFromMain in Pages.Hardware.update). So correctly formatted json received from the subscription/port should pass the test.

Port definition in Hardware.elm:

hardwareSubscriptions : Model -> Sub Msg
hardwareSubscriptions _ =
    Sub.batch [receiveMessageFromJs ResponseDataFromMain]

-- NAV: Ports
port receiveMessageFromJs : (D.Value -> msg) -> Sub msg

However, sending a subscription to the port via the test fails. I have tried to determine if there's something wrong with the way I defined jsonObj but, as far as I can tell, it's seems correct (I do not know any other way I could encode it).

I found it a bit difficult to get to grips with Step.log and I am not sure if that would help here?

I am not sure what else I can/should try as the options for debugging appear limited(?).

I'm hoping I've simply missed something relatively straightforward (?).

Thanks in advance if your are able to assist ...

dotnetspec commented 2 months ago

I missed out: |> Setup.withUpdate Pages.Hardware.update