morr0350 (3) [Avatar] Offline
#1
I had to make some updates to the unit tests in Chapter 6 to get them working - there are probably other solutions, but this was how I got them all working (notes at bottom):

module PhotoGrooveTests exposing (..)

import Expect exposing (Expectation)
import Html.Attributes as Attr
import Fuzz exposing (Fuzzer, int, list, string)
import Test exposing (..)
import Test.Html.Event as Event
import Test.Html.Query as Query
import Test.Html.Selector exposing (text, tag, attribute)
import PhotoGroove exposing (..)
import Json.Decode exposing (decodeString, decodeValue)
import Json.Encode as Encode

decoderTest : Test
decoderTest =
    fuzz2 string int "title defaults to (untitled)" <|
        \url size -> 
            [ ( "url", Encode.string url )
            , ( "size", Encode.int size )
            ]
            |> Encode.object
            |> decodeValue photoDecoder
            |> Result.map .title
            |> Expect.equal (Ok "(untitled)")

stateTransitions: Test
stateTransitions =
    describe "state transitions"
        [ fuzz string " ClickUrl selects the given photo by URL " <|
            \url ->
                { initialModel | status = (Loaded (List.map photoFromUrl [url, "test1.jpg", "test2.jpg"]) "") }
                    |> PhotoGroove.update (ClickedPhoto url)
                    |> Tuple.first
                    |> .status
                    |> Expect.equal (Loaded (List.map photoFromUrl [url, "test1.jpg", "test2.jpg"]) url)


        , fuzz (list string) "LoadPhotos selects the first photo " <|
            \urls ->
                let
                    photos = List.map photoFromUrl urls
                    mdl = PhotoGroove.initialModel 
                    photoRes = PhotoGroove.update (GotPhotos (Ok photos)) mdl
                    photoMdl = Tuple.first photoRes
                    photoStatus = .status photoMdl
                    gotPhotosResult =
                        [ ( Loaded photos (Maybe.withDefault "" (List.head urls) ))
                        ,  ( Errored "No photos found.")
                        ]
                in
                    Expect.equal (List.any (\x -> x == photoStatus) gotPhotosResult) True 
        ]

photoFromUrl : String -> Photo
photoFromUrl url =
    { url = url, size = 0, title = "" }

dom: Test
dom =
    describe "dom tests"
        [ test "No thumbnails render when there are no photos to render" <|
                \_ ->
                    PhotoGroove.initialModel
                        |> PhotoGroove.view
                        |> Query.fromHtml
                        |> Query.findAll [ tag "img" ]
                        |> Query.count ( Expect.equal 0 )
        , fuzz urlFuzzer "URLs render as thumbnails" <|
            \urls ->
                let 
                    thumbnailChecks: List (Query.Single msg -> Expectation)
                    thumbnailChecks =
                        List.map thumbnailRendered urls
                in
                    { initialModel | status = (Loaded (List.map photoFromUrl urls) "") }
                        |> PhotoGroove.view
                        |> Query.fromHtml
                        |> Expect.all thumbnailChecks
        ]

thumbnailRendered: String -> Query.Single msg -> Expectation
thumbnailRendered url query =
    query 
    |> Query.findAll [ tag "img", attribute <| Attr.src (urlPrefix ++ url) ]
    |> Query.count (Expect.atLeast 1)

urlFuzzer: Fuzzer (List String)
urlFuzzer = 
    Fuzz.intRange 1 5
        |> Fuzz.map urlsFromCount

urlsFromCount: Int -> List String
urlsFromCount urlCount =
    List.range 1 urlCount
        |> List.map (\num -> String.fromInt num ++ ".png")

clickThumbnail: Test
clickThumbnail =
    fuzz3 urlFuzzer string urlFuzzer "clicking a thumbnail selects it" <|
        \urlsBefore urlToSelect urlsAfter ->
            let
                url =
                    urlToSelect ++ ".jpeg"
                photos =
                    (urlsBefore ++ url :: urlsAfter)
                    |> List.map photoFromUrl
                srcToClick =
                    urlPrefix ++ url
            in
                { initialModel | status = (Loaded photos "") }
                    |> PhotoGroove.view
                    |> Query.fromHtml
                    |> Query.find [ tag "img", attribute <| Attr.src srcToClick ]
                    |> Event.simulate Event.click
                    |> Event.expect (ClickedPhoto url)


Line 34-35: Since we no longer keep selectedPhoto in the model, I had to update this to reflect the new "status" key that contains photo state
Lines 46-51: Since we have two possible states that could come out of this test, depending on what the fuzz generates, I updated the test to assert that one of the two states is returned
Line 47: List.head returns a Maybe a, rather than just an 'a, so I updated the test to Maybe.withDefault to convert the value to just an 'a
LIne 75: Updated the test again to handle the 'status' key of the model that contains the photos list
Lines 84 and 113: Test.Html.Selector.attribute now seems to take a chained function as the second argument rather than two strings
LIne 95: String.fromInt has replaced Basic.toString in Elm 0.19