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

How to integrate with Wallaby integration tests #62

Open
stabenfeldt opened this issue Dec 23, 2024 · 5 comments
Open

How to integrate with Wallaby integration tests #62

stabenfeldt opened this issue Dec 23, 2024 · 5 comments
Labels
discuss Share your constructive thoughts on how to make progress with this issue documentation Improvements or additions to documentation enhancement New feature or enhancement of existing functionality help wanted If you can help make progress with this issue, please comment! priority-1 Highest priority issue. This is costing us money every minute that passes. T4h Time Estimate 4 Hours technical A technical issue that requires understanding of the code, infrastructure or dependencies user-feedback Feedback from people using the App

Comments

@stabenfeldt
Copy link

stabenfeldt commented Dec 23, 2024

Hi,

When a user signs in with his company's credentials and is redirected back to the provided endpoint, we get the user profile from
ElixirAuthMicrosoft.get_user_profile(token.access_token)
We store this in the session and redirect the user to the app:

    conn = put_session(conn, :profile, profile)
    conn
    |> redirect(to: "/")

Fair enough, but how do I replicate this in a sign_in_user function in my Wallaby tests?
I found this post on ElixirForum. I've tried to massage it to fit with the auth logic provided by elixir-auth-mirosoft, but I don't understand everything and could need help to get the last pieces to fit together.

A simple test to see if a user has signed in

defmodule MyApp.FrontPageTest do
  use ExUnit.Case, async: true
  use Wallaby.Feature

  import Wallaby.Query
  import MyAppWeb.TestHelpers

  setup context do
    log_in(context)
  end

  feature "The frontpage as a logged in user", %{session: session} do
    IO.inspect(session, label: "Session")
    session
    |> visit("/")
    |> Wallaby.Browser.text() |> IO.inspect()  # This is as expected for visitors, but not logged in users.
  end

This is the session we inspect:

Session: %Wallaby.Session{
  id: "222",
  url: "http://localhost:51652/session/222",
  session_url: "http://localhost:51652/session/22",
  driver: Wallaby.Chrome,
  capabilities: %{
    version: "",
    chromeOptions: %{
      args: ["--no-sandbox", "window-size=1280,800", "--disable-gpu",
       "--headless", "--fullscreen",
       "--user-agent=Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36/BeamMetadata (2222==)"],
      binary: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
    },
    cssSelectorsEnabled: true,
    javascriptEnabled: false,
    loadImages: false,
    loggingPrefs: %{browser: "DEBUG"},
    nativeEvents: false,
    platform: "ANY",
    rotatable: false,
    takesScreenshot: true,
    unhandledPromptBehavior: "accept"
  },
  server: Wallaby.Chrome.Chromedriver,
  screenshots: []

TestHelpers

defmodule MyAppWeb.TestHelpers do
  import Wallaby.Browser
  use Wallaby.DSL

  @user_remember_me "_my_app_web_user_remember_me"

  def log_in(%{session: session} = context) do

    # This is the profile data normally returned by ElixirAuthMicrosoft.get_user_profile(token.access_token)
    # Implemented in the MicrosoftAuthController
    profile = %{
      id: "123",
      mail: "[email protected]",
      userPrincipalName: "[email protected]",
      displayName: "John.Doe",
      "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
      businessPhones: ["+47 955 22 44"],
      givenName: "John",
      surname: "Doe",
      jobTitle: "Software Craftsman",
      officeLocation: "Oslo"
    }

    conn = %Plug.Conn{secret_key_base: "secret_key_base"}
    conn = Plug.Conn.put_session(conn, :profile, profile)

    session
    |> visit("/")
    |> set_cookie(@user_remember_me, conn.resp_cookies[@user_remember_me][:value])

    {:ok, %{session: session}}
  end
end

What obvious steps am I missing?
How can I build a sign_in helper that mimics what we do in the MicrosoftAuthController callback?

BTW: I've been using ElixirAuthMicrosoft for 6 months now, and it works like a charm! I just need to get this final piece in place. 😊

@nelsonic nelsonic added enhancement New feature or enhancement of existing functionality help wanted If you can help make progress with this issue, please comment! documentation Improvements or additions to documentation discuss Share your constructive thoughts on how to make progress with this issue priority-1 Highest priority issue. This is costing us money every minute that passes. T4h Time Estimate 4 Hours technical A technical issue that requires understanding of the code, infrastructure or dependencies labels Dec 23, 2024
@LuchoTurtle
Copy link
Member

Hey @stabenfeldt , thanks for opening the issue! :D

I personally haven't had the chance to use Wallaby, so I'm having a bit of trouble navigating through your issue. I'm assuming you are creating the log_in helper function so you only need to log in the user one time when testing, instead of doing so in each test.

Can you provide a small example project that I can run or provide a bit of more detail? I'm having trouble understanding what you exactly want to do.

Your helper function seems to be similar to https://elixirforum.com/t/wallaby-testing-when-browser-session-is-required-i-e-login/8034/10, which they stated it works with mix phx.gen.auth, where their cookie strategy may differ from this package's. I've a few questions:

Thank you! Have a merry Christmas!

(sorry if responses are slow right now, Christmas time with family and stuff :p )

@nelsonic nelsonic added the user-feedback Feedback from people using the App label Dec 25, 2024
@stabenfeldt
Copy link
Author

Hi @LuchoTurtle,

Thanks for replying to my issue, and I'm also sorry for being slow to reply. I'm in the mountains at the cabin, celebrating Christmas with my family. 🎅🏼😅
I'll assemble an example project when I get back home.

Enjoy the rest of your vacation with the family.
Thanks for taking the time to help me out! ❤️

@stabenfeldt
Copy link
Author

stabenfeldt commented Jan 7, 2025

Hi guys, I hope you had a relaxing and nice vacation! 🤩

I've made a quick and dirty POC.
Login with elixir-auth-microsoft works as expected when running in dev.

I would be grateful if you could help me to get the Wallaby tests running.
I'm not sure how to mutate the session to simulate a user logging in.

Testing as a visitor works, but not as a signed-in user.

  feature "Visit the frontpage as a visitor", %{session: session} do
    session
    |> visit("/")
    |> assert_has(css(".phx-hero", text: "To get started, login to your Microsoft Account"))
  end

  feature "Visit the frontpage as a logged in user", %{session: session} do
    session
    |> visit("/")
    |> assert_has(css(".phx-hero", text: "Welcome John Doe"))
  end

@LuchoTurtle
Copy link
Member

Thanks for providing the repo! I'm running mix test test/app_web/features/frontpage.exs and both tests are failing. I assume this should not happen since you say that testing as a visitor works.

The log_in function was missing, as well as setup context, so I added them to test/app_web/features/frontpage.exs.

defmodule AppWeb.FrontPageFeatureTest do
  use AppWeb.ConnCase
  use Wallaby.Feature
  import Wallaby.Query
  import Wallaby.Browser
  use Wallaby.DSL

  @user_remember_me "_my_app_web_user_remember_me"

  def log_in(%{session: session} = _context) do

    # This is the profile data normally returned by ElixirAuthMicrosoft.get_user_profile(token.access_token)
    # Implemented in the MicrosoftAuthController
    profile = %{
      id: "123",
      mail: "[email protected]",
      userPrincipalName: "[email protected]",
      displayName: "John.Doe",
      "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
      businessPhones: ["+47 955 22 44"],
      givenName: "John",
      surname: "Doe",
      jobTitle: "Software Craftsman",
      officeLocation: "Oslo"
    }

    conn = %Plug.Conn{secret_key_base: "secret_key_base"}
    conn = Plug.Conn.put_session(conn, :profile, profile)

    session
    |> visit("/")
    |> set_cookie(@user_remember_me, conn.resp_cookies[@user_remember_me][:value])

    {:ok, %{session: session}}
  end

  setup context do
    log_in(context)
  end


  feature "Visit the frontpage as a visitor", %{session: session} do
    session
    |> visit("/")
    |> assert_has(css(".phx-hero", text: "To get started, login to your Microsoft Account"))
  end

  feature "Visit the frontpage as a logged in user", %{session: session} do
    session
    |> visit("/")
    |> assert_has(css(".phx-hero", text: "Welcome John Doe"))
  end

end

It yields a ** (ArgumentError) session not fetched, call fetch_session/2. Are these errors expected? I'm not well-versed in Wallaby to know if these are common or not.

In either case, I'll try to see what the issue is tomorrow.

In any case, we do offer an easy way to mock the calls from our package. If you turn on the httpoison_mock flag in the config/test.exs file, the package will mock the response without you having to do calls to your Microsot app.
If this is useful to you, would you want to have a way to control this mocking better (in each test)? If that helps in your testing, maybe that's a possible solution to this whole ordeal :D

Let me know! And thank you again for the feedback, I hope you had an amazing Christmas and New Year's! 🎉

@stabenfeldt
Copy link
Author

stabenfeldt commented Jan 30, 2025

Hi guys,

Sorry for not replying earlier. I got occupied with something else.

I just verified that only the test verifying that you have logged in fails.

$  mix  test test/app_web/features/frontpage.exs

  1) feature Visit the frontpage as a logged in user (AppWeb.FrontPageFeatureTest)
     test/app_web/features/frontpage.exs:13
     ** (Wallaby.ExpectationNotMetError) Expected to find 1 visible element that matched the css '.phx-hero' and contained the text 'Welcome John Doe', but 0 visible elements were found.

     code: |> assert_has(css(".phx-hero", text: "Welcome John Doe"))
     stacktrace:
       test/app_web/features/frontpage.exs:17: (test)

.
Finished in 4.6 seconds (0.00s async, 4.6s sync)
2 features, 1 failure

Can you please try again with the latest version of the main branch?
I did however have to run brew upgrade chromedriver, as I got this error first:
warning: Looks like you're trying to run Wallaby with a mismatched version of Chrome: 132.0.6834 and chromedriver: 131.0.6778.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discuss Share your constructive thoughts on how to make progress with this issue documentation Improvements or additions to documentation enhancement New feature or enhancement of existing functionality help wanted If you can help make progress with this issue, please comment! priority-1 Highest priority issue. This is costing us money every minute that passes. T4h Time Estimate 4 Hours technical A technical issue that requires understanding of the code, infrastructure or dependencies user-feedback Feedback from people using the App
Projects
None yet
Development

No branches or pull requests

3 participants