diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1830dfd..622737e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,17 +49,53 @@ jobs: restore-keys: | ${{ runner.os }}-mix- - - name: Install dependencies + # === live_view_responsive project steps === + - name: Install dependencies (live_view_responsive) run: mix deps.get - - name: Compiles without warnings + - name: Compiles without warnings (live_view_responsive) run: mix compile --warnings-as-errors - - name: Check formatting + - name: Check formatting (live_view_responsive) run: mix format --check-formatted - - name: Run Credo in strict mode + - name: Run Credo in strict mode (live_view_responsive) run: mix credo --strict - - name: Run tests + - name: Run tests (live_view_responsive) run: mix test + + # === example_app steps === + - name: Install JS dependencies (example_app/assets) + run: npm install + working-directory: example_app/assets + + - name: Install Google Chrome + uses: browser-actions/setup-chrome@v1 + + - name: Install Chromedriver + uses: nanasess/setup-chromedriver@v2 + + - name: Install dependencies (example_app) + run: mix deps.get + working-directory: example_app + + - name: Compiles without warnings (example_app) + run: mix compile --warnings-as-errors + working-directory: example_app + + - name: Check formatting (example_app) + run: mix format --check-formatted + working-directory: example_app + + - name: Run Credo in strict mode (example_app) + run: mix credo --strict + working-directory: example_app + + - name: Build assets (example_app) + run: mix assets.deploy + working-directory: example_app + + - name: Run tests (example_app) + run: mix test + working-directory: example_app diff --git a/example_app/config/test.exs b/example_app/config/test.exs index ddbf6c7..acca1cc 100644 --- a/example_app/config/test.exs +++ b/example_app/config/test.exs @@ -5,7 +5,22 @@ import Config config :example_app, ExampleAppWeb.Endpoint, http: [ip: {127, 0, 0, 1}, port: 4002], secret_key_base: "nz11cARZHThIJYfcB2c0btc/yXloegtxc+XdeeP6C/lciNzTWwbpag6z6Hs9ejoo", - server: false + server: true + +config :wallaby, + driver: Wallaby.Chrome, + chrome: [ + headless: true, + args: [ + "--no-sandbox", + "--disable-gpu", + "--disable-dev-shm-usage", + "--disable-dev-tools", + "--disable-extensions" + ] + ], + otp_app: :example_app, + base_url: "http://localhost:4002" # In test we don't send emails. config :example_app, ExampleApp.Mailer, adapter: Swoosh.Adapters.Test diff --git a/example_app/lib/example_app/liveview_responsive.ex b/example_app/lib/example_app/liveview_responsive.ex index 4f0642e..c2b7e2e 100644 --- a/example_app/lib/example_app/liveview_responsive.ex +++ b/example_app/lib/example_app/liveview_responsive.ex @@ -1,8 +1,10 @@ defmodule ExampleApp.LiveViewResponsive do - use LiveViewResponsive.Breakpoints, [ + @moduledoc false + + use LiveViewResponsive.Breakpoints, sm: [min_width: 576], md: [min_width: 768], lg: [min_width: 992], portrait: [orientation: :portrait], - ] + landscape: [orientation: :landscape] end diff --git a/example_app/lib/example_app_web/components/core_components.ex b/example_app/lib/example_app_web/components/core_components.ex index a5a4755..39c64d9 100644 --- a/example_app/lib/example_app_web/components/core_components.ex +++ b/example_app/lib/example_app_web/components/core_components.ex @@ -16,6 +16,7 @@ defmodule ExampleAppWeb.CoreComponents do """ use Phoenix.Component + alias Phoenix.HTML.Form alias Phoenix.LiveView.JS import ExampleAppWeb.Gettext @@ -305,7 +306,7 @@ defmodule ExampleAppWeb.CoreComponents do def input(%{type: "checkbox"} = assigns) do assigns = assign_new(assigns, :checked, fn -> - Phoenix.HTML.Form.normalize_value("checkbox", assigns[:value]) + Form.normalize_value("checkbox", assigns[:value]) end) ~H""" diff --git a/example_app/lib/example_app_web/components/layouts/app.html.heex b/example_app/lib/example_app_web/components/layouts/app.html.heex index 7c80751..0d27901 100644 --- a/example_app/lib/example_app_web/components/layouts/app.html.heex +++ b/example_app/lib/example_app_web/components/layouts/app.html.heex @@ -5,7 +5,7 @@

- live_view_responsive + live_view_responsive

diff --git a/example_app/lib/example_app_web/components/live/device_test_live.ex b/example_app/lib/example_app_web/components/live/device_test_live.ex index 0b64273..272723c 100644 --- a/example_app/lib/example_app_web/components/live/device_test_live.ex +++ b/example_app/lib/example_app_web/components/live/device_test_live.ex @@ -1,39 +1,80 @@ defmodule ExampleAppWeb.Components.Live.DeviceTestLive do - @moduledoc false + @moduledoc """ + Live component for testing device/media query responsiveness. Uses Tailwind for styling. + """ use ExampleAppWeb, :live_component use ExampleApp.LiveViewResponsive @impl true def mount(socket) do - socket = socket + socket = + socket |> assign_sm_media_query() |> assign_md_media_query() |> assign_lg_media_query() |> assign_portrait_media_query() + |> assign_landscape_media_query() {:ok, socket} end + @impl true def render(assigns) do ~H""" -
+
<.live_view_responsive myself={@myself} /> -

Device test

-

Media query components

-
    -
  • <.sm_media_query>sm
  • -
  • <.md_media_query>md
  • -
  • <.lg_media_query>lg
  • -
  • <.portrait_media_query>portrait
  • +

    Device Test

    +

    Media Query Components

    +
      +
    • + <.sm_media_query> + sm + +
    • +
    • + <.md_media_query> + md + +
    • +
    • + <.lg_media_query> + lg + +
    • +
    • + <.portrait_media_query> + + portrait + + +
    • +
    • + <.landscape_media_query> + + landscape + + +
    -

    Media query assigns

    -
      -
    • sm
    • -
    • md
    • -
    • lg
    • -
    • portrait
    • +

      Media Query Assigns

      +
        +
      • + sm +
      • +
      • + md +
      • +
      • + lg +
      • +
      • + portrait +
      • +
      • + landscape +
""" diff --git a/example_app/lib/example_app_web/components/live/tree_diagram_live.ex b/example_app/lib/example_app_web/components/live/tree_diagram_live.ex index 8089f54..851be4b 100644 --- a/example_app/lib/example_app_web/components/live/tree_diagram_live.ex +++ b/example_app/lib/example_app_web/components/live/tree_diagram_live.ex @@ -1,128 +1,105 @@ defmodule ExampleAppWeb.Components.Live.TreeDiagramLive do - @moduledoc false + @moduledoc """ + Renders a tree diagram using LiveViewResponsive. Node and row names are in English. + """ - use ExampleAppWeb, :live_component + use ExampleAppWeb, :live_component + use LiveViewResponsive + require Logger - use LiveViewResponsive + @impl true + def mount(socket) do + tree_data = [ + [%{id: 1, template: %{name: "First row"}, children_ids: [2, 3, 5]}], + [ + %{id: 2, template: %{name: "Second row"}, children_ids: [6]}, + %{id: 3, template: %{name: "Second row"}, children_ids: [7]}, + %{id: 4, template: %{name: "Second row"}, children_ids: [8]}, + %{id: 5, template: %{name: "Second row"}, children_ids: [9]} + ], + [ + %{id: 6, template: %{name: "Third row"}, children_ids: [10]}, + %{id: 7, template: %{name: "Third row"}, children_ids: [10]}, + %{id: 8, template: %{name: "Third row"}, children_ids: [10]}, + %{id: 9, template: %{name: "Third row"}, children_ids: [10]} + ], + [%{id: 10, template: %{name: "Fourth row"}, children_ids: []}] + ] - require Logger + socket = + socket + |> assign(:tree, tree_data) + |> assign_media_query(:xl, min_width: 1400) + |> assign_media_query(:lg, min_width: 1000) - @impl true - def mount(socket) do - socket = - socket - |> assign(:tree, [ - [%{id: 1, template: %{name: "Pierwszy wiersz"}, children_ids: [2, 3, 5]}], - [ - %{id: 2, template: %{name: "Drugi wiersz"}, children_ids: [6]}, - %{id: 3, template: %{name: "Drugi wiersz"}, children_ids: [7]}, - %{id: 4, template: %{name: "Drugi wiersz"}, children_ids: [8]}, - %{id: 5, template: %{name: "Drugi wiersz"}, children_ids: [9]}, - ], - [ - %{id: 6, template: %{name: "Trzeci wiersz"}, children_ids: [10]}, - %{id: 7, template: %{name: "Trzeci wiersz"}, children_ids: [10]}, - %{id: 8, template: %{name: "Trzeci wiersz"}, children_ids: [10]}, - %{id: 9, template: %{name: "Trzeci wiersz"}, children_ids: [10]} - ], - [%{id: 10, template: %{name: "Czwarty wiersz"}, children_ids: []}] - ]) - |> assign_media_query(:xl, min_width: 1400) - |> assign_media_query(:lg, min_width: 1000) + {:ok, socket} + end - {:ok, socket} - end + @impl true + def update(assigns, socket) do + columns_count = + cond do + Map.get(assigns, :xl) -> 7 + Map.get(assigns, :lg) -> 5 + true -> 3 + end - @impl true - def update(assigns, socket) do - columns_count = - cond do - Map.get(assigns, :xl) -> 7 - Map.get(assigns, :lg) -> 5 - true -> 3 - end + socket = assign(socket, :columns_count, columns_count) + {:ok, assign(socket, assigns)} + end - socket = assign(socket, :columns_count, columns_count) - - {:ok, assign(socket, assigns)} - end - - @impl true - @spec render(atom() | %{:columns_count => any(), optional(any()) => any()}) :: - Phoenix.LiveView.Rendered.t() - def render(assigns) do - ~H""" -
- <.live_view_responsive myself={@myself} /> - - <.media_query max-width={1224}> -

You are on a tablet or mobile

- - <.media_query min-width={1225}> -

You are on a desktop or laptop

- <.media_query min-width="1400px"> -

You also have a huge screen

- - - - <.media_query orientation="portrait"> -

You are in portrait mode

- - - <.media_query min-resolution="2dppx"> -

You are on a retina screen

- - -
xl
-
lg
- -
-
- <%= if length(row) <= @columns_count do %> -
-
- <%= cell.template.name %> -
+ @impl true + def render(assigns) do + ~H""" +
+ <.live_view_responsive myself={@myself} /> +
+
+ <%= if length(tree_row) <= @columns_count do %> +
+
+ <%= node.template.name %>
- <% else %> - <% cell = Enum.at(row, 0) %> -
-
- <%= cell.template.name %> -
+
+ <% else %> + <% first_node = Enum.at(tree_row, 0) %> +
+
+ <%= first_node.template.name %>
-
-
- <%= "1..#{length(row) - 2}" %> -
+
+
+
+ <%= "1..#{length(tree_row) - 2}" %>
- <% cell = Enum.at(row, -1) %> -
-
- <%= cell.template.name %> -
+
+ <% last_node = Enum.at(tree_row, -1) %> +
+
+ <%= last_node.template.name %>
- <% end %> -
+
+ <% end %>
- """ - end +
+ """ + end end diff --git a/example_app/lib/example_app_web/live/home_live.ex b/example_app/lib/example_app_web/live/home_live.ex index a1ced68..f5d2cd3 100644 --- a/example_app/lib/example_app_web/live/home_live.ex +++ b/example_app/lib/example_app_web/live/home_live.ex @@ -1,8 +1,8 @@ defmodule ExampleAppWeb.HomeLive do use ExampleAppWeb, :live_view - alias ExampleAppWeb.Components.Live.TreeDiagramLive alias ExampleAppWeb.Components.Live.DeviceTestLive + alias ExampleAppWeb.Components.Live.TreeDiagramLive def render(assigns) do ~H""" diff --git a/example_app/mix.exs b/example_app/mix.exs index 5a3d28f..3d3b37a 100644 --- a/example_app/mix.exs +++ b/example_app/mix.exs @@ -5,7 +5,7 @@ defmodule ExampleApp.MixProject do [ app: :example_app, version: "0.1.0", - elixir: "~> 1.14", + elixir: "~> 1.13", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, aliases: aliases(), @@ -32,11 +32,13 @@ defmodule ExampleApp.MixProject do # Type `mix help deps` for examples and options. defp deps do [ + {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, {:phoenix, "~> 1.7.12"}, {:phoenix_html, "~> 4.0"}, {:phoenix_live_reload, "~> 1.2", only: :dev}, {:phoenix_live_view, "~> 0.20.2"}, {:floki, ">= 0.30.0", only: :test}, + {:wallaby, "~> 0.30.10", only: :test}, {:phoenix_live_dashboard, "~> 0.8.3"}, {:esbuild, "~> 0.8", runtime: Mix.env() == :dev}, {:tailwind, "~> 0.2", runtime: Mix.env() == :dev}, diff --git a/example_app/mix.lock b/example_app/mix.lock index d3ca126..e366c24 100644 --- a/example_app/mix.lock +++ b/example_app/mix.lock @@ -1,6 +1,9 @@ %{ "bandit": {:hex, :bandit, "1.5.5", "df28f1c41f745401fe9e85a6882033f5f3442ab6d30c8a2948554062a4ab56e0", [:mix], [{:hpax, "~> 0.2.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "f21579a29ea4bc08440343b2b5f16f7cddf2fea5725d31b72cf973ec729079e1"}, + "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"}, + "certifi": {:hex, :certifi, "2.14.0", "ed3bef654e69cde5e6c022df8070a579a79e8ba2368a00acf3d75b82d9aceeed", [:rebar3], [], "hexpm", "ea59d87ef89da429b8e905264fdec3419f84f2215bb3d81e07a18aac919026c3"}, + "credo": {:hex, :credo, "1.7.12", "9e3c20463de4b5f3f23721527fcaf16722ec815e70ff6c60b86412c695d426c1", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8493d45c656c5427d9c729235b99d498bd133421f3e0a683e5c1b561471291e5"}, "dns_cluster": {:hex, :dns_cluster, "0.1.3", "0bc20a2c88ed6cc494f2964075c359f8c2d00e1bf25518a6a6c7fd277c9b0c66", [:mix], [], "hexpm", "46cb7c4a1b3e52c7ad4cbe33ca5079fbde4840dedeafca2baf77996c2da1bc33"}, "esbuild": {:hex, :esbuild, "0.8.1", "0cbf919f0eccb136d2eeef0df49c4acf55336de864e63594adcea3814f3edf41", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "25fc876a67c13cb0a776e7b5d7974851556baeda2085296c14ab48555ea7560f"}, "expo": {:hex, :expo, "0.5.2", "beba786aab8e3c5431813d7a44b828e7b922bfa431d6bfbada0904535342efe2", [:mix], [], "hexpm", "8c9bfa06ca017c9cb4020fabe980bc7fdb1aaec059fd004c2ab3bff03b1c599c"}, @@ -8,14 +11,20 @@ "finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"}, "floki": {:hex, :floki, "0.36.2", "a7da0193538c93f937714a6704369711998a51a6164a222d710ebd54020aa7a3", [:mix], [], "hexpm", "a8766c0bc92f074e5cb36c4f9961982eda84c5d2b8e979ca67f5c268ec8ed580"}, "gettext": {:hex, :gettext, "0.24.0", "6f4d90ac5f3111673cbefc4ebee96fe5f37a114861ab8c7b7d5b30a1108ce6d8", [:mix], [{:expo, "~> 0.5.1", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "bdf75cdfcbe9e4622dd18e034b227d77dd17f0f133853a1c73b97b3d6c770e8b"}, - "heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "88ab3a0d790e6a47404cba02800a6b25d2afae50", [tag: "v2.1.1", sparse: "optimized"]}, + "hackney": {:hex, :hackney, "1.23.0", "55cc09077112bcb4a69e54be46ed9bc55537763a96cd4a80a221663a7eafd767", [:rebar3], [{:certifi, "~> 2.14.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "6cd1c04cd15c81e5a493f167b226a15f0938a84fc8f0736ebe4ddcab65c0b44e"}, + "heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "88ab3a0d790e6a47404cba02800a6b25d2afae50", [tag: "v2.1.1", sparse: "optimized", depth: 1]}, "hpax": {:hex, :hpax, "0.2.0", "5a58219adcb75977b2edce5eb22051de9362f08236220c9e859a47111c194ff5", [:mix], [], "hexpm", "bea06558cdae85bed075e6c036993d43cd54d447f76d8190a8db0dc5893fa2f1"}, + "httpoison": {:hex, :httpoison, "2.2.3", "a599d4b34004cc60678999445da53b5e653630651d4da3d14675fedc9dd34bd6", [:mix], [{:hackney, "~> 1.21", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "fa0f2e3646d3762fdc73edb532104c8619c7636a6997d20af4003da6cfc53e53"}, + "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "jason": {:hex, :jason, "1.4.3", "d3f984eeb96fe53b85d20e0b049f03e57d075b5acda3ac8d465c969a2536c17b", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "9a90e868927f7c777689baa16d86f4d0e086d968db5c05d917ccff6d443e58a3"}, "live_view_responsive": {:hex, :live_view_responsive, "0.1.1", "08e0f4517accdcf6c7101c9a976117b2cf7867396c2970f7a6eccc20e6d2bd7e", [:mix], [{:phoenix_live_view, ">= 0.20.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "971d2d3f36a085bf0e6761e8f3644cb0c32dc27e5b1c4b365734a26744589a35"}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, + "mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"}, "mint": {:hex, :mint, "1.6.2", "af6d97a4051eee4f05b5500671d47c3a67dac7386045d87a904126fd4bbcea2e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5ee441dffc1892f1ae59127f74afe8fd82fda6587794278d924e4d90ea3d63f9"}, "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, + "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"}, "phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"}, "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.4", "4508e481f791ce62ec6a096e13b061387158cbeefacca68c6c1928e1305e23ed", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "2984aae96994fbc5c61795a73b8fb58153b41ff934019cfb522343d2d3817d59"}, @@ -25,12 +34,17 @@ "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"}, "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"}, "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "swoosh": {:hex, :swoosh, "1.16.9", "20c6a32ea49136a4c19f538e27739bb5070558c0fa76b8a95f4d5d5ca7d319a1", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.0", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "878b1a7a6c10ebbf725a3349363f48f79c5e3d792eb621643b0d276a38acc0a6"}, "tailwind": {:hex, :tailwind, "0.2.3", "277f08145d407de49650d0a4685dc062174bdd1ae7731c5f1da86163a24dfcdb", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "8e45e7a34a676a7747d04f7913a96c770c85e6be810a1d7f91e713d3a3655b5d"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, "telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"}, "telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"}, + "tesla": {:hex, :tesla, "1.14.1", "71c5b031b4e089c0fbfb2b362e24b4478465773ae4ef569760a8c2899ad1e73c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.21", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:mox, "~> 1.0", [hex: :mox, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "c1dde8140a49a3bef5bb622356e77ac5a24ad0c8091f12c3b7fc1077ce797155"}, "thousand_island": {:hex, :thousand_island, "1.3.5", "6022b6338f1635b3d32406ff98d68b843ba73b3aa95cfc27154223244f3a6ca5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2be6954916fdfe4756af3239fb6b6d75d0b8063b5df03ba76fd8a4c87849e180"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, + "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.6", "0437fe56e093fd4ac422de33bf8fc89f7bc1416a3f2d732d8b2c8fd54792fe60", [: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", "e04378d26b0af627817ae84c92083b7e97aca3121196679b73c73b99d0d133ea"}, } diff --git a/example_app/test/e2e/home_page_e2e_test.exs b/example_app/test/e2e/home_page_e2e_test.exs new file mode 100644 index 0000000..f88c1d6 --- /dev/null +++ b/example_app/test/e2e/home_page_e2e_test.exs @@ -0,0 +1,46 @@ +defmodule ExampleAppWeb.E2E.HomePageE2ETest do + use ExUnit.Case, async: false + use Wallaby.Feature + + alias Wallaby.{Browser, Query} + + @breakpoints [ + %{name: "sm", width: 640, height: 800}, + %{name: "md", width: 768, height: 800}, + %{name: "lg", width: 1024, height: 800}, + %{name: "portrait", width: 600, height: 900}, + %{name: "landscape", width: 900, height: 600} + ] + + feature "renders correct elements based on media query assigns for each breakpoint" do + Enum.each(@breakpoints, fn %{name: name, width: width, height: height} -> + {:ok, session} = Wallaby.start_session() + session = Browser.resize_window(session, width, height) + session = Browser.visit(session, "/") + + Browser.assert_has(session, Query.css("span[data-testid='assign-#{name}']")) + + @breakpoints + |> Enum.filter(&(Map.get(&1, :width) > width and Map.get(&1, :height) > height)) + |> Enum.each(fn %{name: other_name} -> + Browser.refute_has(session, Query.css("span[data-testid='assign-#{other_name}']")) + end) + end) + end + + feature "renders correct elements based on media query components for each breakpoint" do + Enum.each(@breakpoints, fn %{name: name, width: width, height: height} -> + {:ok, session} = Wallaby.start_session() + session = Browser.resize_window(session, width, height) + session = Browser.visit(session, "/") + + Browser.assert_has(session, Query.css("span[data-testid='component-#{name}']")) + + @breakpoints + |> Enum.filter(&(Map.get(&1, :width) > width and Map.get(&1, :height) > height)) + |> Enum.each(fn %{name: other_name} -> + Browser.refute_has(session, Query.css("span[data-testid='component-#{other_name}']")) + end) + end) + end +end diff --git a/example_app/test/example_app_web/controllers/error_html_test.exs b/example_app/test/example_app_web/controllers/error_html_test.exs deleted file mode 100644 index ec83e39..0000000 --- a/example_app/test/example_app_web/controllers/error_html_test.exs +++ /dev/null @@ -1,14 +0,0 @@ -defmodule ExampleAppWeb.ErrorHTMLTest do - use ExampleAppWeb.ConnCase, async: true - - # Bring render_to_string/4 for testing custom views - import Phoenix.Template - - test "renders 404.html" do - assert render_to_string(ExampleAppWeb.ErrorHTML, "404", "html", []) == "Not Found" - end - - test "renders 500.html" do - assert render_to_string(ExampleAppWeb.ErrorHTML, "500", "html", []) == "Internal Server Error" - end -end diff --git a/example_app/test/example_app_web/controllers/error_json_test.exs b/example_app/test/example_app_web/controllers/error_json_test.exs deleted file mode 100644 index dfd66c7..0000000 --- a/example_app/test/example_app_web/controllers/error_json_test.exs +++ /dev/null @@ -1,12 +0,0 @@ -defmodule ExampleAppWeb.ErrorJSONTest do - use ExampleAppWeb.ConnCase, async: true - - test "renders 404" do - assert ExampleAppWeb.ErrorJSON.render("404.json", %{}) == %{errors: %{detail: "Not Found"}} - end - - test "renders 500" do - assert ExampleAppWeb.ErrorJSON.render("500.json", %{}) == - %{errors: %{detail: "Internal Server Error"}} - end -end diff --git a/example_app/test/example_app_web/controllers/page_controller_test.exs b/example_app/test/example_app_web/controllers/page_controller_test.exs deleted file mode 100644 index 4e4e49d..0000000 --- a/example_app/test/example_app_web/controllers/page_controller_test.exs +++ /dev/null @@ -1,8 +0,0 @@ -defmodule ExampleAppWeb.PageControllerTest do - use ExampleAppWeb.ConnCase - - test "GET /", %{conn: conn} do - conn = get(conn, ~p"/") - assert html_response(conn, 200) =~ "Peace of mind from prototype to production" - end -end diff --git a/example_app/test/test_helper.exs b/example_app/test/test_helper.exs index 869559e..232b082 100644 --- a/example_app/test/test_helper.exs +++ b/example_app/test/test_helper.exs @@ -1 +1,3 @@ ExUnit.start() + +Application.put_env(:wallaby, :base_url, "http://localhost:4002")