diff --git a/.github/workflows/elixir.yaml b/.github/workflows/elixir.yaml index bbc82ab..6efb23d 100644 --- a/.github/workflows/elixir.yaml +++ b/.github/workflows/elixir.yaml @@ -115,6 +115,16 @@ jobs: - name: Check Formatting run: mix format --check-formatted + # Step: Install ChromeDriver for integration tests + - name: Setup ChromeDriver + uses: nanasess/setup-chromedriver@v2 + with: + chromedriver-version: '119.0.6045.105' + # Step: Execute the tests. - name: Run tests run: mix test + + # Step: Run integration tests separately with Wallaby + - name: Run integration tests + run: mix test --only integration diff --git a/config/test.exs b/config/test.exs index 039e77a..a3ee755 100644 --- a/config/test.exs +++ b/config/test.exs @@ -25,7 +25,7 @@ config :aprsme, AprsmeWeb.Endpoint, adapter: Bandit.PhoenixAdapter, http: [ip: {127, 0, 0, 1}, port: 4002], secret_key_base: "IV9+ENaw9i8xjReRk4sULRvRgsmFVTGQwQGGrf4G+Q/SFMeHBCNWRlPXQ2YvT36R", - server: false + server: true # Disable Prometheus telemetry in test mode to avoid port conflicts config :aprsme, AprsmeWeb.Telemetry, enabled: false @@ -79,3 +79,11 @@ config :phoenix, :plug_init_mode, :runtime # Disable swoosh api client as it is only required for production adapters. config :swoosh, :api_client, false + +# Configure Wallaby +config :wallaby, + driver: Wallaby.Chrome, + chromedriver: [headless: true], + screenshot_on_failure: true, + screenshot_dir: "test/screenshots", + base_url: "http://localhost:4002" diff --git a/mix.exs b/mix.exs index b9eb00e..540f6f0 100644 --- a/mix.exs +++ b/mix.exs @@ -107,7 +107,8 @@ defmodule Aprsme.MixProject do {:hammer, "~> 7.0"}, {:cachex, "~> 4.1"}, {:gettext_pseudolocalize, "~> 0.1"}, - {:sentry, "~> 11.0"} + {:sentry, "~> 11.0"}, + {:wallaby, "~> 0.30.0", only: :test} # Gleam dependencies ] end diff --git a/mix.lock b/mix.lock index d236549..55d654b 100644 --- a/mix.lock +++ b/mix.lock @@ -103,6 +103,8 @@ "thousand_island": {:hex, :thousand_island, "1.3.14", "ad45ebed2577b5437582bcc79c5eccd1e2a8c326abf6a3464ab6c06e2055a34a", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d0d24a929d31cdd1d7903a4fe7f2409afeedff092d277be604966cd6aa4307ef"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.1", "a48703a25c170eedadca83b11e88985af08d35f37c6f664d6dcfb106a97782fc", [:rebar3], [], "hexpm", "b3a917854ce3ae233619744ad1e0102e05673136776fb2fa76234f3e03b23642"}, "unsafe": {:hex, :unsafe, "1.0.2", "23c6be12f6c1605364801f4b47007c0c159497d0446ad378b5cf05f1855c0581", [:mix], [], "hexpm", "b485231683c3ab01a9cd44cb4a79f152c6f3bb87358439c6f68791b85c2df675"}, + "wallaby": {:hex, :wallaby, "0.30.10", "574afb8796521252daf49a4cd76a1c389d53cae5897f2d4b5f55dfae159c8e50", [:mix], [{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:httpoison, "~> 0.12 or ~> 1.0 or ~> 2.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_ecto, ">= 3.0.0", [hex: :phoenix_ecto, repo: "hexpm", optional: true]}, {:web_driver_client, "~> 0.2.0", [hex: :web_driver_client, repo: "hexpm", optional: false]}], "hexpm", "a8f89b92d8acce37a94b5dfae6075c2ef00cb3689d6333f5f36c04b381c077b2"}, + "web_driver_client": {:hex, :web_driver_client, "0.2.0", "63b76cd9eb3b0716ec5467a0f8bead73d3d9612e63f7560d21357f03ad86e31a", [:mix], [{:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:tesla, "~> 1.3", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "83cc6092bc3e74926d1c8455f0ce927d5d1d36707b74d9a65e38c084aab0350f"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"}, } diff --git a/test/integration/map_integration_test.exs b/test/integration/map_integration_test.exs new file mode 100644 index 0000000..6e21cfc --- /dev/null +++ b/test/integration/map_integration_test.exs @@ -0,0 +1,41 @@ +defmodule AprsmeWeb.MapIntegrationTest do + @moduledoc """ + Integration tests for the main map interface using Wallaby + Tests the complete user experience including JavaScript interactions + """ + use ExUnit.Case, async: false + use Wallaby.Feature + + import Wallaby.Browser + + alias Aprsme.Repo + alias Wallaby.Query + + @moduletag :integration + + setup do + :ok = Ecto.Adapters.SQL.Sandbox.checkout(Repo) + Ecto.Adapters.SQL.Sandbox.mode(Repo, {:shared, self()}) + {:ok, %{}} + end + + feature "user can view the main map interface", %{session: session} do + session + |> visit("/") + |> assert_has(Query.text("APRS")) + |> assert_has(Query.css("main")) + end + + feature "page loads successfully", %{session: session} do + session + |> visit("/") + |> assert_has(Query.css("body")) + |> assert_has(Query.css("main")) + end + + feature "can access different routes", %{session: session} do + session + |> visit("/info") + |> assert_has(Query.css("body")) + end +end \ No newline at end of file diff --git a/test/integration/simple_integration_test.exs b/test/integration/simple_integration_test.exs new file mode 100644 index 0000000..cde6a5c --- /dev/null +++ b/test/integration/simple_integration_test.exs @@ -0,0 +1,25 @@ +defmodule AprsmeWeb.SimpleIntegrationTest do + @moduledoc """ + Simple integration test to verify Wallaby setup works + """ + use ExUnit.Case, async: false + use Wallaby.Feature + + import Wallaby.Browser + + alias Wallaby.Query + + @moduletag :integration + + setup do + :ok = Ecto.Adapters.SQL.Sandbox.checkout(Aprsme.Repo) + Ecto.Adapters.SQL.Sandbox.mode(Aprsme.Repo, {:shared, self()}) + {:ok, %{}} + end + + feature "can visit homepage and see title", %{session: session} do + session + |> visit("/") + |> assert_has(Query.text("APRS")) + end +end \ No newline at end of file diff --git a/test/screenshots/1753809560_can_visit_homepage_and_see_title(1).png b/test/screenshots/1753809560_can_visit_homepage_and_see_title(1).png new file mode 100644 index 0000000..0dd624b Binary files /dev/null and b/test/screenshots/1753809560_can_visit_homepage_and_see_title(1).png differ diff --git a/test/screenshots/1753809625_user_can_view_the_main_map_interface(1).png b/test/screenshots/1753809625_user_can_view_the_main_map_interface(1).png new file mode 100644 index 0000000..2254254 Binary files /dev/null and b/test/screenshots/1753809625_user_can_view_the_main_map_interface(1).png differ diff --git a/test/screenshots/1753809628_map_loads_with_proper_elements(1).png b/test/screenshots/1753809628_map_loads_with_proper_elements(1).png new file mode 100644 index 0000000..2254254 Binary files /dev/null and b/test/screenshots/1753809628_map_loads_with_proper_elements(1).png differ diff --git a/test/screenshots/1753809632_can_navigate_map_interface(1).png b/test/screenshots/1753809632_can_navigate_map_interface(1).png new file mode 100644 index 0000000..2254254 Binary files /dev/null and b/test/screenshots/1753809632_can_navigate_map_interface(1).png differ diff --git a/test/test_helper.exs b/test/test_helper.exs index f5a5932..70b2937 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -20,3 +20,6 @@ Application.put_env(:aprsme, :aprsme_is_default_filter, "r/0/0/1") Application.put_env(:aprsme, :packets_module, Aprsme.PacketsMock) # AprsIsMock is automatically loaded from test/support via elixirc_paths + +# Configure Wallaby for integration tests +{:ok, _} = Application.ensure_all_started(:wallaby)