module Effect exposing (Effect(..), batch, fromCmd, map, none, perform, testPerform) {-| @docs Effect, batch, fromCmd, map, none, perform, testPerform -} import Browser.Navigation import Form import Http import Json.Decode as Decode import Pages.Fetcher import Test.PagesProgram.SimulatedEffect as SimulatedEffect exposing (SimulatedEffect) import Url exposing (Url) {-| -} type Effect msg = None | Cmd (Cmd msg) | Batch (List (Effect msg)) | GetStargazers (Result Http.Error Int -> msg) | SetField { formId : String, name : String, value : String } | FetchRouteData { data : Maybe FormData , toMsg : Result Http.Error Url -> msg } | Submit { values : FormData , toMsg : Result Http.Error Url -> msg } | SubmitFetcher (Pages.Fetcher.Fetcher msg) {-| -} type alias RequestInfo = { contentType : String , body : String } {-| -} none : Effect msg none = None {-| -} batch : List (Effect msg) -> Effect msg batch = Batch {-| -} fromCmd : Cmd msg -> Effect msg fromCmd = Cmd {-| -} map : (a -> b) -> Effect a -> Effect b map fn effect = case effect of None -> None Cmd cmd -> Cmd (Cmd.map fn cmd) Batch list -> Batch (List.map (map fn) list) GetStargazers toMsg -> GetStargazers (toMsg >> fn) FetchRouteData fetchInfo -> FetchRouteData { data = fetchInfo.data , toMsg = fetchInfo.toMsg >> fn } Submit fetchInfo -> Submit { values = fetchInfo.values , toMsg = fetchInfo.toMsg >> fn } SetField info -> SetField info SubmitFetcher fetcher -> fetcher |> Pages.Fetcher.map fn |> SubmitFetcher {-| -} perform : { fetchRouteData : { data : Maybe FormData , toMsg : Result Http.Error Url -> pageMsg } -> Cmd msg , submit : { values : FormData , toMsg : Result Http.Error Url -> pageMsg } -> Cmd msg , runFetcher : Pages.Fetcher.Fetcher pageMsg -> Cmd msg , fromPageMsg : pageMsg -> msg , key : Browser.Navigation.Key , setField : { formId : String, name : String, value : String } -> Cmd msg } -> Effect pageMsg -> Cmd msg perform ({ fromPageMsg, key } as helpers) effect = case effect of None -> Cmd.none Cmd cmd -> Cmd.map fromPageMsg cmd SetField info -> helpers.setField info Batch list -> Cmd.batch (List.map (perform helpers) list) GetStargazers toMsg -> Http.get { url = "https://api.github.com/repos/dillonkearns/elm-pages" , expect = Http.expectJson (toMsg >> fromPageMsg) (Decode.field "stargazers_count" Decode.int) } FetchRouteData fetchInfo -> helpers.fetchRouteData fetchInfo Submit record -> helpers.submit record SubmitFetcher record -> helpers.runFetcher record {-| Decompose an Effect into a SimulatedEffect for the test framework. Maintain this function alongside `perform` when adding custom Effect variants. -} testPerform : Effect msg -> SimulatedEffect msg testPerform effect = case effect of None -> SimulatedEffect.none Cmd _ -> SimulatedEffect.none Batch list -> SimulatedEffect.batch (List.map testPerform list) GetStargazers toMsg -> -- In tests, provide a mock value for the stargazers count. -- Alternatively, return SimulatedEffect.none and use -- PagesProgram.simulateMsg to provide the result manually. SimulatedEffect.dispatchMsg (toMsg (Ok 0)) SetField info -> SimulatedEffect.setField info FetchRouteData _ -> SimulatedEffect.none Submit _ -> SimulatedEffect.none SubmitFetcher fetcher -> SimulatedEffect.submitFetcher fetcher type alias FormData = { fields : List ( String, String ) , method : Form.Method , action : String , id : Maybe String }