pow_assent
pow_assent copied to clipboard
Is it possible to mock out a valid user for acceptance tests with Wallaby / Hound?
I'm currently working on switching an app that uses Samly out to use pow/pow_assent. It currently has a large body of acceptance tests using Wallaby. With Samly, the assertion manager can essentially be entirely swapped out, making it fairly simple for us to use mocks to simulate a variety of connection states.
Is there a recommended way to do something similar here? Pretty much everything I've come up with involves basically removing the auth library for the test
env and injecting a user manually into session but this is super fragile and makes a lot of code messy!
edit: To clarify, it's not too hard to create a dummy plug that sets :current_user
in the assigns and fools the pages(s) into thinking a user's in session - Right now to have the app behave correctly on the DB-side I'm also having to basically reconstruct the upsert
functionality in pow_assert in the aforementioned, which is what seems messy/fragile as I'm basically mirroring portions of package in my own test support file
I would either mock the strategy or the http adapter .
Normally I mock the http adapter:
defmodule MockHTTPAdapter do
@moduledoc false
alias Assent.HTTPAdapter.HTTPResponse
def request(:post, "http://example.com/oauth/access_token", body, _headers, nil) do
case URI.decode_query(body) do
%{"code" => "valid_" <> token} ->
{:ok, %HTTPResponse{status: 200, body: %{"access_token" => token}}}
_any ->
{:ok, %HTTPResponse{status: 401, body: ""}}
end
end
def request(:get, "http://example.com/user", _body, _header, nil) do
{:ok, %HTTPResponse{status: 200, body: %{id: 1}}}
end
end
Then you can add it to the test config:
config :my_app, :pow_assent,
http_adapter: MockHTTPAdapter
The above is OAuth2, so to test the flow I check if the code
in params returned starts with valid_
. Makes it very easy to test. Often with ExUnit I add the module in the test modules and set the application env in a setup
callback.
Alternatively you can mock the strategy:
defmodule TwitterMock do
@moduledoc false
@behaviour Assent.Strategy
@impl true
def authorize_url(_config),
do: {:ok, %{url: "https://provider.example.com/oauth/authorize", session_params: %{a: 1}}}
@impl true
def callback(_config, %{"code" => "valid"}), do: {:ok, %{user: %{"sub" => 1, "email" => "[email protected]", "name" => "John Doe"}, token: %{"access_token" => "access_token"}}}
def callback(_config, _params), do: {:error, "Invalid params"}
end
config :my_app, :pow_assent,
providers: [
twitter: [strategy: TwitterMock]
]
In PowAssent I use bypass with a test provider: https://github.com/pow-auth/pow_assent/blob/master/test/support/test_provider.ex
This is awesome feedback - very much appreciated. It sounds like mocking the HTTP adapter might be the best way to proceed - I tried mocking the strategy but I think the system still hits up the URL in question.
Would it be helpful if I opened a PR with some guide examples based on this? If so happy to pay the time you spent writing this back with one!
Would it be helpful if I opened a PR with some guide examples based on this?
Yeah it would! 😄