diff --git a/registrations/test/integration/admin_test.exs b/registrations/test/integration/admin_test.exs index 5dd1aec2..e30f2dbc 100644 --- a/registrations/test/integration/admin_test.exs +++ b/registrations/test/integration/admin_test.exs @@ -92,7 +92,7 @@ defmodule Registrations.Integration.Admin do Users.build_team_from(session, a.id) - assert Nav.info_text(session) == "Team built successfully" + Nav.assert_info_text(session, "Team built successfully") assert Users.teamed(session, a.id) assert Users.teamed(session, b.id) @@ -136,7 +136,7 @@ defmodule Registrations.Integration.Admin do Nav.users_link().click(session) Users.build_team_from(session, a.id) - assert Nav.error_text(session) == "Team built with placeholders!" + Nav.assert_error_text(session, "Team built with placeholders!") Nav.teams_link().click(session) @@ -193,13 +193,13 @@ defmodule Registrations.Integration.Admin do refute page_source(session) =~ "francine.pascal@example.com" visit(session, "/messages") - assert Nav.error_text(session) == "Who are you?" + Nav.assert_error_text(session, "Who are you?") visit(session, "/teams") - assert Nav.error_text(session) == "Who are you?" + Nav.assert_error_text(session, "Who are you?") visit(session, "/settings") - assert Nav.error_text(session) == "Who are you?" + Nav.assert_error_text(session, "Who are you?") end end @@ -245,7 +245,7 @@ defmodule Registrations.Integration.UnmnemonicDevices.Admin do insert(:user, email: "francine.pascal@example.com") visit(session, "/settings") - assert Nav.error_text(session) == "Who are you?" + Nav.assert_error_text(session, "Who are you?") end test "admin can view team JSON that includes voicepasses", %{session: session} do @@ -265,6 +265,7 @@ defmodule Registrations.Integration.UnmnemonicDevices.Admin do visit(session, "/") Login.login_as_admin(session) + Nav.assert_logged_in_as(session, "octavia.butler@example.com") visit(session, "/api/teams") json = decode_json_from_page(session) diff --git a/registrations/test/integration/home_test.exs b/registrations/test/integration/home_test.exs index 7597feaf..97c36c37 100644 --- a/registrations/test/integration/home_test.exs +++ b/registrations/test/integration/home_test.exs @@ -171,6 +171,7 @@ defmodule Registrations.Waydowntown.Integration.Home do Login.fill_email(session, "Octavia.butler@example.com") Login.fill_password(session, "Xenogenesis") Login.submit(session) + Nav.assert_logged_in_as(session, "octavia.butler@example.com") visit(session, "/") refute(Home.placeholder_exists?(session)) @@ -191,7 +192,7 @@ defmodule Registrations.Waydowntown.Integration.Home do Home.fill_waitlist_question(session, "When will the event take place?") Home.submit_waitlist(session) - assert Nav.info_text(session) == "we’ll let you know when registration opens" + Nav.assert_info_text(session, "we’ll let you know when registration opens") wait_for_emails([sent_email]) assert sent_email.to == [{"", "mdrysdale@waydown.town"}] @@ -240,7 +241,7 @@ defmodule Registrations.Waydowntown.Integration.Home do Home.submit_waitlist(session) - assert Nav.info_text(session) == "was that an email address?" + Nav.assert_info_text(session, "was that an email address?") assert wait_for_emails([]) == [] end @@ -268,7 +269,7 @@ defmodule Registrations.Waydowntown.Integration.Home do Home.fill_waitlist_question(session, "When will the event take place?") Home.submit_waitlist(session) - assert Nav.info_text(session) == "we’ll let you know when registration opens" + Nav.assert_info_text(session, "we’ll let you know when registration opens") assert wait_for_emails([]) == [] end @@ -296,7 +297,7 @@ defmodule Registrations.Waydowntown.Integration.Home do Home.fill_waitlist_question(session, "When will this unwanted event take place?") Home.submit_waitlist(session) - assert Nav.info_text(session) == "we’ll let you know when registration opens" + Nav.assert_info_text(session, "we’ll let you know when registration opens") assert wait_for_emails([]) == [] end diff --git a/registrations/test/integration/invitations_test.exs b/registrations/test/integration/invitations_test.exs index c6b295fc..919551e2 100644 --- a/registrations/test/integration/invitations_test.exs +++ b/registrations/test/integration/invitations_test.exs @@ -55,6 +55,6 @@ defmodule Registrations.Integration.Invitations do Register.fill_password_confirmation(session, "simulteneity") Register.submit(session) - assert Nav.logout_link().text(session) == "Log out bedap@example.com" + Nav.assert_logged_in_as(session, "bedap@example.com") end end diff --git a/registrations/test/integration/messages_test.exs b/registrations/test/integration/messages_test.exs index 703c85f7..af978d1c 100644 --- a/registrations/test/integration/messages_test.exs +++ b/registrations/test/integration/messages_test.exs @@ -47,7 +47,7 @@ defmodule Registrations.Integration.Messages do Messages.send(session) - assert Nav.info_text(session) == "Message was sent" + Nav.assert_info_text(session, "Message was sent") wait_for_emails([empty_email, _ignored1, email, _ignored2]) assert email.to == [{"", "user@example.com"}] @@ -96,7 +96,7 @@ defmodule Registrations.Integration.Messages do Messages.send_to_me(session) - assert Nav.info_text(session) == "Message was sent" + Nav.assert_info_text(session, "Message was sent") wait_for_emails([email]) assert email.to == [{"", "admin@example.com"}] @@ -129,7 +129,7 @@ defmodule Registrations.Integration.Messages do Messages.send(session) - assert Nav.info_text(session) == "Message was sent" + Nav.assert_info_text(session, "Message was sent") wait_for_emails([email]) assert email.from == {"Knut", "knut@example.com"} @@ -175,7 +175,7 @@ defmodule Registrations.Integration.Messages do Messages.send(session) - assert Nav.info_text(session) == "Message was sent" + Nav.assert_info_text(session, "Message was sent") sent_emails = wait_for_emails([_email1, _email2, _email3, _email4]) diff --git a/registrations/test/integration/questions_test.exs b/registrations/test/integration/questions_test.exs index cc9b00e6..61f368ae 100644 --- a/registrations/test/integration/questions_test.exs +++ b/registrations/test/integration/questions_test.exs @@ -21,7 +21,7 @@ defmodule Registrations.ClandestineRendezvous.Integration.Questions do Home.submit_question(session) - assert Nav.info_text(session) == "Your question has been submitted." + Nav.assert_info_text(session, "Your question has been submitted.") wait_for_emails([sent_email]) assert sent_email.to == [{"", "b@events.chromatin.ca"}] @@ -58,7 +58,7 @@ defmodule Registrations.UnmnemonicDevices.Integration.Questions do Home.submit_question(session) - assert Nav.info_text(session) == "Your question has been submitted." + Nav.assert_info_text(session, "Your question has been submitted.") wait_for_emails([sent_email]) assert sent_email.to == [{"", "knut@chromatin.ca"}] diff --git a/registrations/test/integration/registrations_test.exs b/registrations/test/integration/registrations_test.exs index b12f144c..03ac1df3 100644 --- a/registrations/test/integration/registrations_test.exs +++ b/registrations/test/integration/registrations_test.exs @@ -19,8 +19,10 @@ defmodule Registrations.Integration.ClandestineRendezvous.Registrations do Register.submit(session) - assert Nav.error_text(session) == - "Oops, something went wrong! Please check the errors below:\nPassword can't be blank\nEmail can't be blank" + Nav.assert_error_text( + session, + "Oops, something went wrong! Please check the errors below:\nPassword can't be blank\nEmail can't be blank" + ) assert Register.email_error(session) == "Email can't be blank" # FIXME fix plural detection @@ -29,15 +31,17 @@ defmodule Registrations.Integration.ClandestineRendezvous.Registrations do Register.fill_email(session, "franklin.w.dixon@example.com") Register.submit(session) - assert Nav.error_text(session) == - "Oops, something went wrong! Please check the errors below:\nPassword can't be blank" + Nav.assert_error_text( + session, + "Oops, something went wrong! Please check the errors below:\nPassword can't be blank" + ) Register.fill_email(session, "samuel.delaney@example.com") Register.fill_password(session, "nestofspiders") Register.fill_password_confirmation(session, "nestofspiders") Register.submit(session) - assert Nav.info_text(session) == "Your account was created" + Nav.assert_info_text(session, "Your account was created") wait_for_emails([admin_email, welcome_email]) @@ -50,7 +54,7 @@ defmodule Registrations.Integration.ClandestineRendezvous.Registrations do assert String.contains?(welcome_email.text_body, "secret society") assert String.contains?(welcome_email.html_body, "secret society") - assert Nav.logout_link().text(session) == "Log out samuel.delaney@example.com" + Nav.assert_logged_in_as(session, "samuel.delaney@example.com") assert Details.active?(session) end @@ -67,20 +71,22 @@ defmodule Registrations.Integration.ClandestineRendezvous.Registrations do Login.fill_password(session, "Parable of the Talents") Login.submit(session) - assert Nav.error_text(session) == - "The provided login details did not work. Please verify your credentials, and try again." + Nav.assert_error_text( + session, + "The provided login details did not work. Please verify your credentials, and try again." + ) Login.fill_password(session, "Xenogenesis") Login.submit(session) - assert Nav.info_text(session) == "Logged in" - assert Nav.logout_link().text(session) == "Log out octavia.butler@example.com" + Nav.assert_info_text(session, "Logged in") + Nav.assert_logged_in_as(session, "octavia.butler@example.com") assert Details.active?(session) Nav.logout_link().click(session) - assert Nav.info_text(session) == "Logged out" + Nav.assert_info_text(session, "Logged out") assert Nav.login_link().present?(session) assert Nav.register_link().present?(session) end @@ -99,25 +105,30 @@ defmodule Registrations.Integration.ClandestineRendezvous.Registrations do Account.fill_current_password(session, "Wrong") Account.submit(session) - assert Nav.error_text(session) == - "Oops, something went wrong! Please check the errors below:\nCurrent password is invalid" + Nav.assert_error_text( + session, + "Oops, something went wrong! Please check the errors below:\nCurrent password is invalid" + ) Account.fill_current_password(session, "Xenogenesis") Account.fill_new_password(session, "abcde") Account.fill_new_password_confirmation(session, "vwxyz") Account.submit(session) - assert Nav.error_text(session) == - "Oops, something went wrong! Please check the errors below:\nPassword should be at least 8 character(s)\nPassword confirmation does not match confirmation" + Nav.assert_error_text( + session, + "Oops, something went wrong! Please check the errors below:\nPassword should be at least 8 character(s)\nPassword confirmation does not match confirmation" + ) Account.fill_current_password(session, "Xenogenesis") Account.fill_new_password(session, "Lilith’s Brood") Account.fill_new_password_confirmation(session, "Lilith’s Brood") Account.submit(session) - assert Nav.info_text(session) == "Your account has been updated." + Nav.assert_info_text(session, "Your account has been updated.") Nav.logout_link().click(session) + Nav.assert_info_text(session, "Logged out") visit(session, "/") Nav.login_link().click(session) @@ -126,13 +137,15 @@ defmodule Registrations.Integration.ClandestineRendezvous.Registrations do Login.fill_password(session, "Xenogenesis") Login.submit(session) - assert Nav.error_text(session) == - "The provided login details did not work. Please verify your credentials, and try again." + Nav.assert_error_text( + session, + "The provided login details did not work. Please verify your credentials, and try again." + ) Login.fill_password(session, "Lilith’s Brood") Login.submit(session) - assert Nav.info_text(session) == "Logged in" + Nav.assert_info_text(session, "Logged in") end test "forgot password", %{session: session} do @@ -148,8 +161,10 @@ defmodule Registrations.Integration.ClandestineRendezvous.Registrations do ForgotPassword.fill_email(session, "octavia.butler@example.com") ForgotPassword.submit(session) - assert Nav.info_text(session) == - "If an account for the provided email exists, an email with reset instructions will be sent to you. Please check your inbox." + Nav.assert_info_text( + session, + "If an account for the provided email exists, an email with reset instructions will be sent to you. Please check your inbox." + ) wait_for_emails([forgot_password_email]) @@ -167,7 +182,7 @@ defmodule Registrations.Integration.ClandestineRendezvous.Registrations do assert String.starts_with?(reset_path, "/reset-password/") visit(session, "/reset-password/fake") - assert Nav.error_text(session) == "The reset token has expired." + Nav.assert_error_text(session, "The reset token has expired.") visit(session, reset_path) @@ -175,30 +190,32 @@ defmodule Registrations.Integration.ClandestineRendezvous.Registrations do Account.fill_new_password_confirmation(session, "awrongpassword") Account.submit(session) - assert Nav.error_text(session) == - "Oops, something went wrong! Please check the errors below:\nPassword confirmation does not match confirmation" + Nav.assert_error_text( + session, + "Oops, something went wrong! Please check the errors below:\nPassword confirmation does not match confirmation" + ) Account.fill_new_password(session, "anewpassword") Account.fill_new_password_confirmation(session, "anewpassword") Account.submit(session) - assert Nav.info_text(session) == "The password has been updated." + Nav.assert_info_text(session, "The password has been updated.") Login.fill_email(session, "Octavia.butler@example.com") Login.fill_password(session, "anewpassword") Login.submit(session) - assert Nav.logout_link().text(session) == "Log out octavia.butler@example.com" + Nav.assert_logged_in_as(session, "octavia.butler@example.com") Nav.logout_link().click(session) Login.login_as(session, "octavia.butler@example.com", "anewpassword") - assert Nav.logout_link().text(session) == "Log out octavia.butler@example.com" + Nav.assert_logged_in_as(session, "octavia.butler@example.com") Nav.logout_link().click(session) visit(session, reset_path) - assert Nav.error_text(session) == "The reset token has expired." + Nav.assert_error_text(session, "The reset token has expired.") end test "delete account", %{session: session} do @@ -210,7 +227,7 @@ defmodule Registrations.Integration.ClandestineRendezvous.Registrations do Nav.edit_details(session) Details.delete_account(session) - assert Nav.info_text(session) == "Your account has been deleted. Sorry to see you go!" + Nav.assert_info_text(session, "Your account has been deleted. Sorry to see you go!") wait_for_emails([admin_email]) @@ -227,7 +244,7 @@ defmodule Registrations.Integration.ClandestineRendezvous.Registrations do Login.fill_password(session, "Xenogenesis") Login.submit(session) - assert Nav.info_text(session) == "Your account has been deleted. Sorry to see you go!" + Nav.assert_info_text(session, "Your account has been deleted. Sorry to see you go!") end test "when registration is closed, a warning is displayed on the registration and details routes", @@ -242,14 +259,18 @@ defmodule Registrations.Integration.ClandestineRendezvous.Registrations do Nav.register_link().click(session) - assert Nav.error_text(session) == - "Registration is closed; however, you may continue and we will email you" + Nav.assert_error_text( + session, + "Registration is closed; however, you may continue and we will email you" + ) insert(:octavia) Login.login_as_admin(session) - assert Nav.error_text(session) == - "You may change your details but it’s too late to guarantee the changes can be integrated" + Nav.assert_error_text( + session, + "You may change your details but it’s too late to guarantee the changes can be integrated" + ) end end diff --git a/registrations/test/integration/teams_test.exs b/registrations/test/integration/teams_test.exs index 88b80bb2..c07e3d08 100644 --- a/registrations/test/integration/teams_test.exs +++ b/registrations/test/integration/teams_test.exs @@ -65,7 +65,7 @@ defmodule Registrations.Integration.Teams do Details.submit(session) - assert Nav.info_text(session) == "Your details were saved" + Nav.assert_info_text(session, "Your details were saved") assert Details.accessibility_text(session) == "Some accessibility information" assert Details.comments().value(session) == "Some comments" @@ -81,7 +81,7 @@ defmodule Registrations.Integration.Teams do assert sent_email.text_body == ~s([accessibility: "Some accessibility information", comments: "Some comments", proposed_team_name: "Simultaneity", risk_aversion: 3, source: "A source", team_emails: "shevek@example.com bedap@example.com sabul@example.com laia@example.com nooo"]) - [bedap, shevek] = Enum.sort_by(Details.mutuals(session), & &1.email) + [bedap, shevek] = Enum.sort_by(Details.mutuals(session, count: 2), & &1.email) assert shevek.email == "shevek@example.com" assert shevek.symbol == "✓" @@ -99,14 +99,14 @@ defmodule Registrations.Integration.Teams do assert bedap.risk_aversion.value == "✓ Don’t hold back" assert bedap.risk_aversion.agreement? - [sadik] = Details.proposers(session) + [sadik] = Details.proposers(session, count: 1) assert sadik.email == "sadik@example.com" assert sadik.symbol == "?" assert sadik.text == "This person has you listed in their team. Add their address to your team emails list if you agree." - [rulag, tuio] = Enum.sort_by(Details.proposals_by_mutuals(session), & &1.email) + [rulag, tuio] = Enum.sort_by(Details.proposals_by_mutuals(session, count: 2), & &1.email) assert rulag.email == "rulag@example.com" assert rulag.symbol == "?" @@ -120,12 +120,12 @@ defmodule Registrations.Integration.Teams do assert tuio.text == "bedap@example.com and shevek@example.com have this address in their team emails lists. Add it if you agree." - [invalid] = Details.invalids(session) + [invalid] = Details.invalids(session, count: 1) assert invalid.email == "nooo" assert invalid.symbol == "✘" assert invalid.text == "This doesn’t seem like a valid email address!" - [laia, sabul] = Enum.sort_by(Details.proposees(session), & &1.email) + [laia, sabul] = Enum.sort_by(Details.proposees(session, count: 2), & &1.email) assert sabul.email == "sabul@example.com" assert sabul.symbol == "✘" @@ -146,7 +146,7 @@ defmodule Registrations.Integration.Teams do sadik.add.() Details.submit(session) - assert length(Details.mutuals(session)) == 3 + assert length(Details.mutuals(session, count: 3)) == 3 end test "team emails can be appended to", %{session: session} do @@ -208,20 +208,26 @@ defmodule Registrations.Integration.Teams do Details.submit(session) - assert Error.present?(session), - "Expected an error about the attending field being blank" + Error.assert_present( + session, + "Expected an error about the attending field being blank" + ) Details.Attending.yes(session) Details.submit(session) - refute Error.present?(session), - "Expected no error when the person said they were attending" + Error.assert_absent( + session, + "Expected no error when the person said they were attending" + ) Details.Attending.no(session) Details.submit(session) - refute Error.present?(session), - "Expected no error when the person said they were not attending" + Error.assert_absent( + session, + "Expected no error when the person said they were not attending" + ) end test "visiting the details page redirects to login when there is no session", %{ @@ -229,7 +235,7 @@ defmodule Registrations.Integration.Teams do } do visit(session, "/details") - assert Nav.info_text(session) == "Please log in to edit your details" + Nav.assert_info_text(session, "Please log in to edit your details") Login.fill_email(session, "anemail") end diff --git a/registrations/test/support/json_helpers.ex b/registrations/test/support/json_helpers.ex index 3391d6b6..b8fc74b2 100644 --- a/registrations/test/support/json_helpers.ex +++ b/registrations/test/support/json_helpers.ex @@ -2,18 +2,34 @@ defmodule Registrations.TestJsonHelpers do @moduledoc false import Wallaby.Browser, only: [page_source: 1] + require WaitForIt def decode_json_from_page(session) do - body = page_source(session) + WaitForIt.wait!(json_ready?(session), timeout: 10_000) - json = - case Floki.find(body, "pre") do - [] -> body - nodes -> Floki.text(nodes) - end - - json + session + |> page_source() + |> extract_json() |> String.trim() |> Jason.decode!() end + + defp json_ready?(session) do + session + |> page_source() + |> extract_json() + |> String.trim() + |> json_prefix?() + end + + defp json_prefix?(json) do + String.starts_with?(json, "{") or String.starts_with?(json, "[") + end + + defp extract_json(body) do + case Floki.find(body, "pre") do + [] -> body + nodes -> Floki.text(nodes) + end + end end diff --git a/registrations/test/support/pages/details.ex b/registrations/test/support/pages/details.ex index b4561f8a..be24edf3 100644 --- a/registrations/test/support/pages/details.ex +++ b/registrations/test/support/pages/details.ex @@ -3,6 +3,7 @@ defmodule Registrations.Pages.Details do alias Wallaby.Browser alias Wallaby.Element alias Wallaby.Query + require WaitForIt def edit_account(session) do Browser.click(session, Query.css("a.account")) @@ -14,15 +15,15 @@ defmodule Registrations.Pages.Details do end) end - def proposers(session) do + def proposers(session, opts \\ []) do session - |> Browser.all(Query.css("[data-test-proposers]")) + |> rows_with_wait("[data-test-proposers]", opts) |> Enum.map(&email_and_text_row(&1)) end - def mutuals(session) do + def mutuals(session, opts \\ []) do session - |> Browser.all(Query.css("[data-test-mutuals]")) + |> rows_with_wait("[data-test-mutuals]", opts) |> Enum.map(fn row -> proposed_team_name_element = Browser.find(row, Query.css(".proposed-team-name")) risk_aversion_element = Browser.find(row, Query.css(".risk-aversion")) @@ -44,21 +45,21 @@ defmodule Registrations.Pages.Details do end) end - def proposals_by_mutuals(session) do + def proposals_by_mutuals(session, opts \\ []) do session - |> Browser.all(Query.css("[data-test-proposals-by-mutuals]")) + |> rows_with_wait("[data-test-proposals-by-mutuals]", opts) |> Enum.map(&email_and_text_row(&1)) end - def invalids(session) do + def invalids(session, opts \\ []) do session - |> Browser.all(Query.css("[data-test-invalids]")) + |> rows_with_wait("[data-test-invalids]", opts) |> Enum.map(&email_and_text_row(&1)) end - def proposees(session) do + def proposees(session, opts \\ []) do session - |> Browser.all(Query.css("[data-test-proposees]")) + |> rows_with_wait("[data-test-proposees]", opts) |> Enum.map(&email_and_text_row(&1)) end @@ -162,6 +163,7 @@ defmodule Registrations.Pages.Details do @moduledoc false alias Wallaby.Browser alias Wallaby.Query + require WaitForIt def present?(session) do Browser.has?(session, Query.css(".form-group.attending")) @@ -169,20 +171,39 @@ defmodule Registrations.Pages.Details do def yes(session) do Browser.click(session, Query.css("input.attending-true")) + WaitForIt.wait!(Browser.has?(session, Query.css("input.attending-true:checked"))) end def no(session) do Browser.click(session, Query.css("input.attending-false")) + WaitForIt.wait!(Browser.has?(session, Query.css("input.attending-false:checked"))) end defmodule Error do @moduledoc false alias Wallaby.Browser alias Wallaby.Query + require WaitForIt def present?(session) do Browser.has?(session, Query.css(".errors .attending")) end + + def assert_present(session, message \\ nil) do + WaitForIt.wait!(present?(session)) + + if not present?(session) do + raise(message || "Expected attending error to be present") + end + end + + def assert_absent(session, message \\ nil) do + WaitForIt.wait!(!present?(session)) + + if present?(session) do + raise(message || "Expected attending error to be absent") + end + end end end @@ -216,6 +237,16 @@ defmodule Registrations.Pages.Details do Browser.click(session, Query.css("#submit")) end + defp rows_with_wait(session, selector, opts) do + expected = Keyword.get(opts, :count) + + if expected do + WaitForIt.wait!(length(Browser.all(session, Query.css(selector))) == expected) + end + + Browser.all(session, Query.css(selector)) + end + defp email_and_text_row(row) do %{ email: Element.text(Browser.find(row, Query.css(".email"))), diff --git a/registrations/test/support/pages/home.ex b/registrations/test/support/pages/home.ex index 061a5454..8696125b 100644 --- a/registrations/test/support/pages/home.ex +++ b/registrations/test/support/pages/home.ex @@ -47,6 +47,7 @@ defmodule Registrations.Pages.Home do @moduledoc false alias Wallaby.Browser alias Wallaby.Query + require WaitForIt @selector "#pi" @@ -55,7 +56,16 @@ defmodule Registrations.Pages.Home do end def click(session) do - Browser.click(session, Query.css(@selector)) + WaitForIt.wait!( + try do + Browser.click(session, Query.css(@selector)) + true + rescue + Wallaby.StaleReferenceError -> false + Wallaby.QueryError -> false + RuntimeError -> false + end + ) end end diff --git a/registrations/test/support/pages/nav.ex b/registrations/test/support/pages/nav.ex index 746acb5a..7f447744 100644 --- a/registrations/test/support/pages/nav.ex +++ b/registrations/test/support/pages/nav.ex @@ -2,17 +2,40 @@ defmodule Registrations.Pages.Nav do @moduledoc false alias Wallaby.Browser alias Wallaby.Query + require WaitForIt + + @flash_timeout 10_000 def present?(session) do Browser.has?(session, Query.css(".row.nav")) end - def info_text(session) do - Browser.text(session, Query.css(".alert-info")) + def info_text(session, expected \\ nil) do + flash_text(session, ".alert-info", expected) + end + + def error_text(session, expected \\ nil) do + flash_text(session, ".alert-danger", expected) end - def error_text(session) do - Browser.text(session, Query.css(".alert-danger")) + def assert_info_text(session, expected) do + assert_flash_text(session, ".alert-info", expected) + end + + def assert_error_text(session, expected) do + assert_flash_text(session, ".alert-danger", expected) + end + + def assert_logged_in_as(session, email) do + expected = "log out #{email}" + + WaitForIt.wait!( + case safe_text(session, "a.logout") do + {:ok, text} -> normalize_text(text) == normalize_text(expected) + :error -> false + end, + timeout: @flash_timeout + ) end def register_link do @@ -53,15 +76,24 @@ defmodule Registrations.Pages.Nav do @moduledoc false alias Wallaby.Browser alias Wallaby.Query + require WaitForIt @selector "a.logout" + @logout_timeout 10_000 def text(session) do + WaitForIt.wait(Browser.has?(session, Query.css(@selector))) Browser.text(session, Query.css(@selector)) end def click(session) do + WaitForIt.wait!(Browser.has?(session, Query.css(@selector)), timeout: @logout_timeout) Browser.click(session, Query.css(@selector)) + WaitForIt.wait!( + not Browser.has?(session, Query.css(@selector)) or + Browser.has?(session, Query.css("a.login")), + timeout: @logout_timeout + ) end end @@ -69,10 +101,12 @@ defmodule Registrations.Pages.Nav do @moduledoc false alias Wallaby.Browser alias Wallaby.Query + require WaitForIt @selector "a.login" def click(session) do + WaitForIt.wait(Browser.has?(session, Query.css(@selector))) Browser.click(session, Query.css(@selector)) end @@ -85,10 +119,12 @@ defmodule Registrations.Pages.Nav do @moduledoc false alias Wallaby.Browser alias Wallaby.Query + require WaitForIt @selector "a.register" def click(session) do + WaitForIt.wait(Browser.has?(session, Query.css(@selector))) Browser.click(session, Query.css(@selector)) end @@ -136,4 +172,50 @@ defmodule Registrations.Pages.Nav do Browser.click(session, Query.css(@selector)) end end + + defp flash_text(session, selector, expected) when is_binary(expected) do + WaitForIt.wait!(flash_text_matches?(session, selector, expected), timeout: @flash_timeout) + expected + end + + defp flash_text(session, selector, nil) do + WaitForIt.wait!(match?({:ok, _}, safe_text(session, selector)), timeout: @flash_timeout) + + {:ok, text} = safe_text(session, selector) + text + end + + defp flash_text_matches?(session, selector, expected) do + case safe_text(session, selector) do + {:ok, text} -> normalize_text(text) == normalize_text(expected) + :error -> false + end + end + + defp safe_text(session, selector) do + try do + {:ok, Browser.text(session, Query.css(selector))} + rescue + Wallaby.StaleReferenceError -> :error + Wallaby.QueryError -> :error + end + end + + defp assert_flash_text(session, selector, expected) do + WaitForIt.wait!(flash_text_matches?(session, selector, expected), timeout: @flash_timeout) + + {:ok, text} = safe_text(session, selector) + if normalize_text(text) != normalize_text(expected) do + raise "Expected #{inspect(expected)}, got #{inspect(text)}" + end + + text + end + + defp normalize_text(text) do + text + |> String.downcase() + |> String.replace(~r/\s+/, " ") + |> String.trim() + end end