如何在 Test API 模块内对 Cmd 消息进行模式匹配?

How do I pattern match on a Cmd msg inside a Test API module?

如何在测试 API 模块中对 Cmd 消息进行模式匹配?

我有一个测试 API 可以替代 Web 服务。

sources : Id -> (Result Http.Error (List Source) -> msg) -> Cmd msg
sources profileId msg =
    [ { platform = "WordPress", username = "bizmonger", linksFound = 0 }
    , { platform = "YouTube", username = "bizmonger", linksFound = 0 }
    , { platform = "Whosebug", username = "scott-nimrod", linksFound = 0 }
    ]
        |> Result.Ok
        |> msg
        |> Task.succeed
        |> Task.perform identity

问题:

我收到以下代码的编译错误:

addSource : Id -> Source -> (Result Http.Error (List Source) -> msg) -> Cmd msg
addSource profileId source msg =
    let
        result =
            sources profileId msg
    in
        case result of
            Ok sources ->
                (source :: sources)
                    |> Result.Ok
                    |> msg
                    |> Task.succeed
                    |> Task.perform identity

            Err _ ->
                Cmd.none

Ok sources -> ^^^^^^^^^^ The pattern matches things of type:

Result error value

But the values it will actually be trying to match are:

Cmd msg

注:

我知道这些函数 return 一个 Cmd msg 并且我需要在 Cmd msg 上进行模式匹配。但是,此代码位于 TestAPI 模块中,而不是典型的 UI 模块中。因此,我认为我不必为已经在依赖于此 TestAPI 模块的 UI 客户端中定义的各种消息定义可区分的联合。

附录:

type alias Source =
    { platform : String, username : String, linksFound : Int }

因为这是关于 "mocking" 一个 API 端点,所以我将避免我通常的 "don't box data in a command if you're not triggering side-effects" 演讲。

相反,让我建议拆分您的 sources 函数:

sourceData : List Source
sourceData =
    [ { platform = "WordPress", username = "bizmonger", linksFound = 0 }
    , { platform = "YouTube", username = "bizmonger", linksFound = 0 }
    , { platform = "Whosebug", username = "scott-nimrod", linksFound = 0 }
    ]


mockResponse : a -> (Result Http.Error a -> msg) -> Cmd msg
mockResponse data tagger =
    Result.Ok data
        |> Task.succeed
        |> Task.perform tagger


sources : Id -> (Result Http.Error (List Source) -> msg) -> Cmd msg
sources profileId msg =
    mockResponse sourceData msg

现在,实现您的 addSource 函数变得相当简单,如下所示:

addSource : Id -> Source -> (Result Http.Error (List Source) -> msg) -> Cmd msg
addSource profileId source msg 
    mockResponse (source :: sourceData) msg

我意识到我仍在进行函数式编程。 因此,为什么不将功能组合在一起,从核心要素到更多相关内容。

因此,我做了以下事情:

addSourceBase : Id -> Source -> List Source
addSourceBase profileId source =
    source :: (profileId |> sourcesBase)


addSource : Id -> Source -> (Result Http.Error (List Source) -> msg) -> Cmd msg
addSource profileId source msg =
    source
        |> addSourceBase profileId
        |> Result.Ok
        |> msg
        |> Task.succeed
        |> Task.perform identity