Code Monkey home page Code Monkey logo

Comments (14)

 avatar commented on May 18, 2024 1

@amatalai I see... I agree and off the top of my head can't think of a good way to support all cases without a lot of edge case conditions. So yes, perhaps raw body parameter should just go away for the mock adapter?

from tesla.

teamon avatar teamon commented on May 18, 2024 1

I'd go with

def json(data) do
  %Tesla.Env{status: 200, body: Posion.encode!(data), headers: %{"content-type" => "application/json"}}
end

Tesla.Mock.mock fn
  env -> json(["some", "data"])
end

As @amatalai wrote, I don't think we can find a bullet-proof solution to handle any data structure as body since adapters always return a very specific ones.

from tesla.

teamon avatar teamon commented on May 18, 2024

from tesla.

teamon avatar teamon commented on May 18, 2024

already decoded body*

from tesla.

 avatar commented on May 18, 2024

I see! Great :) Note that I did try to do that prior to opening this issue and ran into an issue:

...
 setup do
    Tesla.Mock.mock fn
      %{method: :get, url: "http://example.com/json"} ->
        %Tesla.Env{status: 200, body: [%{}]}
    end
...

Result:

  1) test mock adapter calls middleware to decode json (MyAppTest)
     test/my_app_test.exs:13
  ** (ArgumentError) argument error
     code: assert %Tesla.Env{} = env = MyApp.get("/json")
     stacktrace:
       :erlang.iolist_to_binary([%{}])
       (tesla) lib/tesla/middleware/core.ex:31: Tesla.Middleware.Normalize.normalize_body/1
       (elixir) lib/map.ex:727: Map.update!/3
       (tesla) lib/tesla/middleware/json.ex:50: Tesla.Middleware.JSON.call/3
       test/my_app_test.exs:14: (test)

I think something like this in middleware/core.ex would solve the issue:

iex(16)> defmodule Test do
...(16)> def foo(data) when is_map(hd(data)), do: IO.puts "it's a list of maps"
...(16)> def foo(data) when is_list(data), do: IO.puts "default to io list"
...(16)> end
{:module, Test,
 <<70, 79, 82, 49, 0, 0, 4, 100, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 99,
   0, 0, 0, 11, 11, 69, 108, 105, 120, 105, 114, 46, 84, 101, 115, 116, 8, 95,
   95, 105, 110, 102, 111, 95, 95, 9, 102, ...>>, {:foo, 1}}
iex(17)> list_of_maps = [%{}, %{}, %{}]
[%{}, %{}, %{}]
iex(18)> list_of_str = ["Hello", ", ", "world"]
["Hello", ", ", "world"]
iex(19)> Test.foo
foo/1
iex(19)> Test.foo(list_of_str)
default to io list
:ok
iex(20)> Test.foo(list_of_maps)
it's a list of maps
:ok
iex(21)>

The above definitely could be better and should have more sanity checks before hitting the is_map() guard.

from tesla.

 avatar commented on May 18, 2024

Better...

iex(8)> defmodule Test do
...(8)>    def foo(data) when is_list(data) do
...(8)>      case is_map(hd(data)) do
...(8)>        true -> "is map"
...(8)>        false -> "is not a map"
...(8)>      end
...(8)>    end
...(8)> end

{:module, Test,
 <<70, 79, 82, 49, 0, 0, 4, 20, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 84, 0,
   0, 0, 9, 11, 69, 108, 105, 120, 105, 114, 46, 84, 101, 115, 116, 8, 95, 95,
   105, 110, 102, 111, 95, 95, 9, 102, ...>>, {:foo, 1}}
iex(9)> Test.foo([""])
"is not a map"
iex(10)> Test.foo([%{}])
"is map"
iex(11)>

Unless of course, there's a good reason the code doesn't already handle this case. If not, then I'll submit a PR.

from tesla.

 avatar commented on May 18, 2024

See #125

from tesla.

amatalai avatar amatalai commented on May 18, 2024

Hi

iex(8)> defmodule Test do
...(8)>    def foo(data) when is_list(data) do
...(8)>      case is_map(hd(data)) do
...(8)>        true -> "is map"
...(8)>        false -> "is not a map"
...(8)>      end
...(8)>    end
...(8)> end

This approach is invalid for ["foo", %{"bar" => "baz"}], which has valid json representation
"[\"foo\", {\"bar\": \"baz\"}]"

It could be done as case Enum.any?(data, &is_map/1) do, but there's one more edge case
[97, 115, 100, 102]
is this a four integers list after decoding or 'asdf' before charlist => binary conversion?

Personally I would prefer this approach

Tesla.Mock.mock fn
  %{method: :get, url: "http://example.com/json"} ->
    %Tesla.Env{status: 200, body: '[{}]', headers: %{"content-type" => "application/json"}}
  end

as it doesn't need any change in codebase to make mock work and is closer to how it works in reality

from tesla.

 avatar commented on May 18, 2024

@amatalai See #125 , all tests passing.

from tesla.

amatalai avatar amatalai commented on May 18, 2024

@starbelly yes, for one specific case. I meant that it should work for all possible cases.

Use those and it will fail:

  • ["foo", %{"bar" => "baz"}]
  • [97, 115, 100, 102]

Both are valid decoded jsons. In second example it's not even possible to distinguish if it's charlist from adapter or decoded json passed to mock

from tesla.

 avatar commented on May 18, 2024

@amatalai Unless you know of a particular resolution to this problem, I'm gonna go ahead and close my PR in favor of doing away with this feature for the mock adapter.

from tesla.

amatalai avatar amatalai commented on May 18, 2024

At the moment I don't see any solution that will be universal.
As stated before I would prefer to use something like this:

json = [...] |> Poison.encode!
Tesla.Mock.mock fn
  %{method: :get, url: "http://example.com/json"} ->
    %Tesla.Env{status: 200, body: json, headers: %{"content-type" => "application/json"}}
  end

from tesla.

 avatar commented on May 18, 2024

Closing PR #125

from tesla.

 avatar commented on May 18, 2024

Will close this issue in favor of new issue.

from tesla.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.