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

Is it possible to mock out a valid user for acceptance tests with Wallaby / Hound? #188

Open
asurin opened this issue Aug 4, 2020 · 3 comments

Comments

@asurin
Copy link

asurin commented Aug 4, 2020

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

@danschultzer
Copy link
Collaborator

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

@asurin
Copy link
Author

asurin commented Aug 4, 2020

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!

@danschultzer
Copy link
Collaborator

Would it be helpful if I opened a PR with some guide examples based on this?

Yeah it would! 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants