-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Anil Kulkarni
committed
Jun 27, 2018
1 parent
038d4a9
commit 7276317
Showing
3 changed files
with
112 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
defmodule Wand.Hex do | ||
alias HTTPoison.{Error, Response} | ||
@http Wand.Interfaces.Http.impl() | ||
@base "https://hex.pm/" | ||
@headers [{"Accept", "application/json"}] | ||
|
||
def releases(package) do | ||
URI.parse(@base) | ||
|> URI.merge("/api/packages/#{URI.encode(package)}") | ||
|> @http.get(@headers) | ||
|> parse_response | ||
end | ||
|
||
defp parse_response({:ok, %Response{status_code: 200, body: body}}) do | ||
Poison.decode(body) | ||
|> parse_json | ||
end | ||
|
||
defp parse_response({:ok, %Response{status_code: 404}}) do | ||
{:error, :not_found} | ||
end | ||
defp parse_response({:ok, %Response{}}), do: {:error, :bad_response} | ||
defp parse_response({:error, %Error{}}), do: {:error, :no_connection} | ||
|
||
defp parse_json({:ok, %{"releases" => releases}}) do | ||
releases = Enum.map(releases, &Map.get(&1, "version")) | ||
|> Enum.reject(&(&1 == nil or Version.parse(&1) == :error)) | ||
|
||
case releases do | ||
[] -> {:error, :not_found} | ||
releases -> {:ok, releases} | ||
end | ||
end | ||
defp parse_json(_), do: {:error, :bad_response} | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
defmodule HexTest do | ||
use ExUnit.Case, async: true | ||
import Mox | ||
alias Wand.Hex | ||
alias HTTPoison.{Response, Error} | ||
|
||
setup :verify_on_exit! | ||
|
||
test "releases returns :not_found if the package isn't on hex" do | ||
stub_http(:ok, 404, "") | ||
assert Hex.releases("not_a_module") == {:error, :not_found} | ||
end | ||
|
||
test "returns :not_found if there are no releases" do | ||
stub_http(:ok, 200, %{releases: []}) | ||
assert Hex.releases("poison") == {:error, :not_found} | ||
end | ||
|
||
test "releases returns :no_connection if HTTPoison returns an error" do | ||
stub_http(:error) | ||
assert Hex.releases("poison") == {:error, :no_connection} | ||
end | ||
|
||
test "returns :bad_response when the server returns non-json" do | ||
stub_http(:ok, 200, "[NOT JSON") | ||
assert Hex.releases("poison") == {:error, :bad_response} | ||
end | ||
|
||
test "returns :bad_response when the server returns a 400" do | ||
stub_http(:ok, 400, "") | ||
assert Hex.releases("poison") == {:error, :bad_response} | ||
end | ||
|
||
test "returns :bad_response when missing the releases key" do | ||
stub_http(:ok, 200, "{}") | ||
assert Hex.releases("poison") == {:error, :bad_response} | ||
end | ||
|
||
test "returns the releases" do | ||
stub_http(:ok, 200, valid_body()) | ||
expected = {:ok, ["3.1.0", "3.0.0", "2.2.0", "2.1.0", "2.0.1", "2.0.0", "1.5.2", | ||
"1.5.1", "1.5.0", "1.4.0", "1.3.1", "1.3.0", "1.2.1", "1.2.0", | ||
"1.1.1", "1.1.0", "1.0.3", "1.0.2", "1.0.1", "1.0.0"]} | ||
assert Hex.releases("poison") == expected | ||
end | ||
|
||
test "strips out invalid releases" do | ||
stub_http(:ok, 200, %{ | ||
releases: [ | ||
%{version: "1.1.0"}, | ||
%{missing_version: "1.1.0"}, | ||
%{version: "ABC"}, | ||
] | ||
}) | ||
assert Hex.releases("poison") == {:ok, ["1.1.0"]} | ||
end | ||
|
||
defp stub_http(:ok, status, %{}=contents), do: stub_http(:ok, status, Poison.encode!(contents)) | ||
defp stub_http(:ok, status, contents) do | ||
response = %Response{ | ||
status_code: status, | ||
body: contents, | ||
} | ||
expect(Wand.HttpMock, :get, fn _url, _headers -> {:ok, response} end) | ||
end | ||
|
||
defp stub_http(:error) do | ||
# expect(Wand.HttpMock, :get, fn(url, headers) -> HTTPoison.get(url, headers) end) | ||
response = %Error{id: nil, reason: :nxdomain} | ||
expect(Wand.HttpMock, :get, fn(_url, _headers) -> {:error, response} end) | ||
end | ||
|
||
defp valid_body() do | ||
"{\"docs_html_url\":\"https://hexdocs.pm/poison/\",\"downloads\":{\"all\":6270192,\"day\":13995,\"recent\":962319,\"week\":81020},\"html_url\":\"https://hex.pm/packages/poison\",\"inserted_at\":\"2014-08-20T04:43:51.000000\",\"meta\":{\"description\":\"An incredibly fast, pure Elixir JSON library\",\"licenses\":[\"CC0-1.0\"],\"links\":{\"GitHub\":\"https://github.com/devinus/poison\"},\"maintainers\":[\"Devin Torres\"]},\"name\":\"poison\",\"owners\":[{\"email\":\"devin@devintorr.es\",\"url\":\"https://hex.pm/api/users/devinus\",\"username\":\"devinus\"}],\"releases\":[{\"url\":\"https://hex.pm/api/packages/poison/releases/3.1.0\",\"version\":\"3.1.0\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/3.0.0\",\"version\":\"3.0.0\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/2.2.0\",\"version\":\"2.2.0\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/2.1.0\",\"version\":\"2.1.0\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/2.0.1\",\"version\":\"2.0.1\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/2.0.0\",\"version\":\"2.0.0\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/1.5.2\",\"version\":\"1.5.2\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/1.5.1\",\"version\":\"1.5.1\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/1.5.0\",\"version\":\"1.5.0\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/1.4.0\",\"version\":\"1.4.0\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/1.3.1\",\"version\":\"1.3.1\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/1.3.0\",\"version\":\"1.3.0\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/1.2.1\",\"version\":\"1.2.1\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/1.2.0\",\"version\":\"1.2.0\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/1.1.1\",\"version\":\"1.1.1\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/1.1.0\",\"version\":\"1.1.0\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/1.0.3\",\"version\":\"1.0.3\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/1.0.2\",\"version\":\"1.0.2\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/1.0.1\",\"version\":\"1.0.1\"},{\"url\":\"https://hex.pm/api/packages/poison/releases/1.0.0\",\"version\":\"1.0.0\"}],\"repository\":\"hexpm\",\"retirements\":{},\"updated_at\":\"2017-01-15T01:34:31.327060\",\"url\":\"https://hex.pm/api/packages/poison\"}" | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
Mox.defmock(Wand.FileMock, for: Wand.Interfaces.File) | ||
Mox.defmock(Wand.HexMock, for: Wand.Interfaces.Http) | ||
Mox.defmock(Wand.HttpMock, for: Wand.Interfaces.Http) | ||
Mox.defmock(Wand.IOMock, for: Wand.Interfaces.IO) | ||
Mox.defmock(Wand.SystemMock, for: Wand.Interfaces.System) |