Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix path_string crash when path includes list #1338

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion lib/absinthe/resolution.ex
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ defmodule Absinthe.Resolution do
In this case `5` is the 0 based index in the list of users the field is currently
at.
"""
@spec path(t()) :: [String.t() | integer()]
def path(%{path: path}) do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this spec is correct. This returns the query nodes, not strings. Also, in the case of lists, it returns integers.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll switch to [String.t() | integer()]

path
|> Enum.reverse()
Expand Down Expand Up @@ -235,13 +236,37 @@ defmodule Absinthe.Resolution do

def call(res, _), do: res

@doc """
Get a list of strings representing the path to this field resolution.
The index of list items is dropped and the schema type is included.

## Examples
Given some query:
```graphql
query {users { email }}
```

If you called this function inside a resolver on the users email field it
returns a value like:

```elixir
resolve fn _, _, resolution ->
Absinthe.Resolution.path(resolution) #=> ["email", "0", "users", "RootQueryType"]
end
```
"""
@spec path_string(t()) :: [String.t()]
def path_string(%__MODULE__{path: path}) do
Enum.map(path, fn
path
|> Enum.map(fn
%{name: name, alias: alias} ->
alias || name

%{schema_node: schema_node} ->
schema_node.name

n when is_integer(n) ->
Integer.to_string(n)
end)
end

Expand Down
8 changes: 6 additions & 2 deletions test/absinthe/resolution/middleware_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ defmodule Absinthe.MiddlewareTest do
field :path, :path do
resolve fn _, _ -> {:ok, %{}} end
end

field :list_of_paths, list_of(:path) do
resolve fn _, _ -> {:ok, [%{}]} end
end
end

object :path do
Expand Down Expand Up @@ -188,13 +192,13 @@ defmodule Absinthe.MiddlewareTest do

test "it gets the path of the current field" do
doc = """
{foo: path { bar: path { result }}}
{foo: listOfPaths { bar: path { result }}}
"""

assert {:ok, %{data: data}} =
Absinthe.run(doc, __MODULE__.Schema, context: %{current_user: %{}})

assert %{"foo" => %{"bar" => %{"result" => ["result", "bar", "foo", "RootQueryType"]}}} ==
assert %{"foo" => [%{"bar" => %{"result" => ["result", "bar", "0", "foo", "RootQueryType"]}}]} ==
data
end
end