Skip to content

Commit ab89664

Browse files
committed
fix: properly clean up state on sign out
1 parent e3f0b2b commit ab89664

5 files changed

Lines changed: 68 additions & 4 deletions

File tree

lib/teslamate/api.ex

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ defmodule TeslaMate.Api do
8181
end
8282

8383
def sign_out(name \\ @name) do
84-
true = :ets.delete(name, :auth)
85-
:ok
86-
rescue
87-
_ in ArgumentError -> {:error, :not_signed_in}
84+
case fetch_auth(name) do
85+
{:error, :not_signed_in} -> {:error, :not_signed_in}
86+
{:ok, %Auth{}} -> GenServer.call(name, :sign_out, @timeout)
87+
end
8888
end
8989

9090
# Callbacks
@@ -173,6 +173,14 @@ defmodule TeslaMate.Api do
173173
end
174174
end
175175

176+
def handle_call(:sign_out, _from, %State{name: name} = state) do
177+
:ets.delete(name, :auth)
178+
if is_reference(state.refresh_timer), do: Process.cancel_timer(state.refresh_timer)
179+
:ok = call(state.deps.auth, :delete_tokens)
180+
:ok = call(state.deps.vehicles, :restart)
181+
{:reply, :ok, %State{state | refresh_timer: nil}}
182+
end
183+
176184
@impl true
177185
def handle_info(:refresh_auth, %State{name: name} = state) do
178186
case fetch_auth(name) do

lib/teslamate/auth.ex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ defmodule TeslaMate.Auth do
5757
end
5858
end
5959

60+
def delete_tokens do
61+
Repo.delete_all(Tokens)
62+
:ok
63+
end
64+
6065
defp create_tokens(attrs) do
6166
%Tokens{}
6267
|> Tokens.changeset(attrs)

test/support/mocks/auth.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ defmodule AuthMock do
1212

1313
def get_tokens(name), do: GenServer.call(name, :get_tokens)
1414
def save(name, auth), do: GenServer.call(name, {:save, auth})
15+
def delete_tokens(name), do: GenServer.call(name, :delete_tokens)
1516

1617
# Callbacks
1718

@@ -33,4 +34,9 @@ defmodule AuthMock do
3334
send(pid, {AuthMock, event})
3435
{:reply, :ok, state}
3536
end
37+
38+
def handle_call(:delete_tokens = event, _from, %State{pid: pid} = state) do
39+
send(pid, {AuthMock, event})
40+
{:reply, :ok, %State{state | tokens: nil}}
41+
end
3642
end

test/teslamate/api_test.exs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,37 @@ defmodule TeslaMate.ApiTest do
165165
end
166166
end
167167

168+
describe "sign out" do
169+
test "deletes the tokens and restarts the vehicles", %{test: name} do
170+
with_mocks [auth_mock(self()), vehicle_mock(self())] do
171+
:ok = start_api(name, tokens: @valid_tokens)
172+
173+
assert_receive {TeslaApi.Auth, {:refresh, %TeslaApi.Auth{}}}
174+
assert_receive {AuthMock, {:save, %TeslaApi.Auth{}}}
175+
assert true == Api.signed_in?(name)
176+
177+
assert :ok = Api.sign_out(name)
178+
179+
assert_receive {AuthMock, :delete_tokens}
180+
assert_receive {VehiclesMock, :restart}
181+
assert false == Api.signed_in?(name)
182+
183+
refute_receive _
184+
end
185+
end
186+
187+
test "fails if not signed in", %{test: name} do
188+
with_mocks [auth_mock(self()), vehicle_mock(self())] do
189+
:ok = start_api(name, tokens: nil)
190+
191+
assert false == Api.signed_in?(name)
192+
assert {:error, :not_signed_in} = Api.sign_out(name)
193+
194+
refute_receive _
195+
end
196+
end
197+
end
198+
168199
describe "refresh" do
169200
test "refreshes tokens", %{test: name} do
170201
with_mocks [auth_mock(self()), vehicle_mock(self())] do

test/teslamate/auth_test.exs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,19 @@ defmodule TeslaMate.AuthTest do
3636
assert %{refresh: ["can't be blank"], access: ["can't be blank"]} ==
3737
errors_on(changeset)
3838
end
39+
40+
test "delete_tokens/0 removes the stored tokens" do
41+
assert :ok = Auth.save(@valid_attrs)
42+
assert Auth.get_tokens()
43+
44+
assert :ok = Auth.delete_tokens()
45+
assert Auth.get_tokens() == nil
46+
end
47+
48+
test "delete_tokens/0 is a no-op when there are no tokens" do
49+
assert Auth.get_tokens() == nil
50+
assert :ok = Auth.delete_tokens()
51+
assert Auth.get_tokens() == nil
52+
end
3953
end
4054
end

0 commit comments

Comments
 (0)