Skip to content

Commit 2ba3913

Browse files
authored
Add tests for middleware (#11)
1 parent d9eba69 commit 2ba3913

File tree

6 files changed

+202
-4
lines changed

6 files changed

+202
-4
lines changed

lib/algolia.ex

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,12 @@ defmodule Algolia do
5757
middleware_fn = Keyword.get(opts, :middleware, & &1)
5858
adapter = Keyword.get(opts, :adapter)
5959

60-
middleware = opts |> default_middleware() |> middleware_fn.()
60+
middleware =
61+
opts
62+
|> Keyword.put_new_lazy(:api_key, &api_key/0)
63+
|> Keyword.put_new_lazy(:application_id, &application_id/0)
64+
|> default_middleware()
65+
|> middleware_fn.()
6166

6267
Tesla.client(middleware, adapter)
6368
end

lib/algolia/middleware/base_url.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ defmodule Algolia.Middleware.BaseUrl do
55
def call(env, next, opts) do
66
hint = env.opts[:subdomain_hint]
77
curr_retry = env.opts[:curr_retry]
8-
application_id = Keyword.get_lazy(opts, :application_id, &Algolia.application_id/0)
8+
application_id = Keyword.fetch!(opts, :application_id)
99

1010
host =
1111
case {hint, curr_retry} do

lib/algolia/middleware/headers.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ defmodule Algolia.Middleware.Headers do
33

44
@impl Tesla.Middleware
55
def call(env, next, opts) do
6-
api_key = Keyword.get_lazy(opts, :api_key, &Algolia.api_key/0)
7-
application_id = Keyword.get_lazy(opts, :application_id, &Algolia.application_id/0)
6+
api_key = Keyword.fetch!(opts, :api_key)
7+
application_id = Keyword.fetch!(opts, :application_id)
88

99
env
1010
|> Tesla.put_headers([
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
defmodule Algolia.Middleware.BaseUrlTest do
2+
use ExUnit.Case, async: true
3+
4+
alias Algolia.Middleware.BaseUrl
5+
6+
alias Tesla.Env
7+
8+
@opts [application_id: "application_id"]
9+
10+
describe "read requests" do
11+
test "use dsn subdomain for first request" do
12+
assert {:ok, env} =
13+
BaseUrl.call(
14+
%Env{url: "/1/indexes", opts: [subdomain_hint: :read, curr_retry: 0]},
15+
[],
16+
@opts
17+
)
18+
19+
assert env.url == "https://application_id-dsn.algolia.net/1/indexes"
20+
end
21+
22+
test "use numbered subdomain for subsequent requests" do
23+
assert {:ok, env} =
24+
BaseUrl.call(
25+
%Env{url: "/1/indexes", opts: [subdomain_hint: :read, curr_retry: 1]},
26+
[],
27+
@opts
28+
)
29+
30+
assert env.url == "https://application_id-1.algolianet.com/1/indexes"
31+
32+
assert {:ok, env} =
33+
BaseUrl.call(
34+
%Env{url: "/1/indexes", opts: [subdomain_hint: :read, curr_retry: 3]},
35+
[],
36+
@opts
37+
)
38+
39+
assert env.url == "https://application_id-3.algolianet.com/1/indexes"
40+
end
41+
end
42+
43+
describe "write requests" do
44+
test "use basic subdomain for first request" do
45+
assert {:ok, env} =
46+
BaseUrl.call(
47+
%Env{url: "/1/indexes/foo/bar", opts: [subdomain_hint: :write, curr_retry: 0]},
48+
[],
49+
@opts
50+
)
51+
52+
assert env.url == "https://application_id.algolia.net/1/indexes/foo/bar"
53+
end
54+
55+
test "use numbered subdomain for subsequent requests" do
56+
assert {:ok, env} =
57+
BaseUrl.call(
58+
%Env{url: "/1/indexes/foo/bar", opts: [subdomain_hint: :write, curr_retry: 1]},
59+
[],
60+
@opts
61+
)
62+
63+
assert env.url == "https://application_id-1.algolianet.com/1/indexes/foo/bar"
64+
65+
assert {:ok, env} =
66+
BaseUrl.call(
67+
%Env{url: "/1/indexes/foo/bar", opts: [subdomain_hint: :write, curr_retry: 3]},
68+
[],
69+
@opts
70+
)
71+
72+
assert env.url == "https://application_id-3.algolianet.com/1/indexes/foo/bar"
73+
end
74+
end
75+
76+
describe "insights requests" do
77+
test "use insights host for first request" do
78+
assert {:ok, env} =
79+
BaseUrl.call(
80+
%Env{url: "/1/events", opts: [subdomain_hint: :insights, curr_retry: 0]},
81+
[],
82+
@opts
83+
)
84+
85+
assert env.url == "https://insights.algolia.io/1/events"
86+
end
87+
88+
test "use insights host for retried requests" do
89+
assert {:ok, env} =
90+
BaseUrl.call(
91+
%Env{url: "/1/events", opts: [subdomain_hint: :insights, curr_retry: 3]},
92+
[],
93+
@opts
94+
)
95+
96+
assert env.url == "https://insights.algolia.io/1/events"
97+
end
98+
end
99+
end
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
defmodule Algolia.Middleware.HeadersTest do
2+
use ExUnit.Case, async: true
3+
4+
alias Algolia.Middleware.Headers
5+
6+
alias Tesla.Env
7+
8+
test "with no headers to start" do
9+
assert {:ok, env} = Headers.call(%Env{url: "/foo"}, [], api_key: "abc", application_id: "def")
10+
11+
assert env.headers == [
12+
{"X-Algolia-API-Key", "abc"},
13+
{"X-Algolia-Application-Id", "def"}
14+
]
15+
end
16+
17+
test "adds to the headers that are already present" do
18+
assert {:ok, env} =
19+
Headers.call(%Env{url: "/foo", headers: [{"Content-Type", "application/json"}]}, [],
20+
api_key: "abc",
21+
application_id: "def"
22+
)
23+
24+
assert env.headers == [
25+
{"Content-Type", "application/json"},
26+
{"X-Algolia-API-Key", "abc"},
27+
{"X-Algolia-Application-Id", "def"}
28+
]
29+
end
30+
31+
test "raises if :api_key is missing" do
32+
assert_raise KeyError, fn ->
33+
Headers.call(%Env{url: "/foo"}, [], application_id: "def")
34+
end
35+
end
36+
37+
test "raises if :application_id is missing" do
38+
assert_raise KeyError, fn ->
39+
Headers.call(%Env{url: "/foo"}, [], api_key: "abc")
40+
end
41+
end
42+
end
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
defmodule Algolia.Middleware.RetryTest do
2+
use ExUnit.Case, async: true
3+
4+
setup do
5+
client =
6+
Tesla.client(
7+
[Algolia.Middleware.Retry],
8+
Tesla.Mock
9+
)
10+
11+
{:ok, client: client}
12+
end
13+
14+
test "returns response with successful status code", %{client: client} do
15+
Tesla.Mock.mock(fn
16+
%{url: "/1/indexes", opts: [curr_retry: 0]} ->
17+
{200, [], "OK"}
18+
end)
19+
20+
assert {:ok, %{body: "OK"}} = Tesla.get(client, "/1/indexes")
21+
end
22+
23+
test "returns response with unsuccessful status code", %{client: client} do
24+
Tesla.Mock.mock(fn
25+
%{url: "/1/indexes", opts: [curr_retry: 0]} ->
26+
{500, [], "you did a bad job"}
27+
end)
28+
29+
assert {:ok, %{body: "you did a bad job"}} = Tesla.get(client, "/1/indexes")
30+
end
31+
32+
test "retries when request errors", %{client: client} do
33+
Tesla.Mock.mock(fn
34+
%{url: "/1/indexes", opts: [curr_retry: 3]} ->
35+
{200, [], "OK"}
36+
37+
%{url: "/1/indexes"} ->
38+
{:error, :econnrefused}
39+
end)
40+
41+
assert {:ok, %{body: "OK", opts: [curr_retry: 3]}} = Tesla.get(client, "/1/indexes")
42+
end
43+
44+
test "gives up after 4 attempts", %{client: client} do
45+
Tesla.Mock.mock(fn
46+
%{url: "/1/indexes", opts: [curr_retry: retry]} when retry <= 3 ->
47+
{:error, :econnrefused}
48+
end)
49+
50+
assert {:error, {"Unable to connect to Algolia", 4}} = Tesla.get(client, "/1/indexes")
51+
end
52+
end

0 commit comments

Comments
 (0)