From f18819a68a9312328193d521b80ee4fa63926e6b Mon Sep 17 00:00:00 2001 From: Alessandro Colace Date: Sun, 14 Jun 2026 17:58:05 +0200 Subject: [PATCH] ci: run the fcx-web test suite on GitHub Actions Adds a matrix CI (format + warnings-as-errors + tests). To boot the suite, the fcxd driver is now opt-out via :start_driver (off in test), the ErrorView test no longer uses the removed Phoenix.View API, and fcx-web is formatted. --- .github/workflows/fcx-web.yml | 107 ++++++++++++++++++ fcx-web/config/config.exs | 3 +- fcx-web/config/prod.exs | 3 +- fcx-web/config/test.exs | 5 +- fcx-web/lib/fullcontrol_x/application.ex | 37 +++--- .../lib/fullcontrol_x_web/commands_live.ex | 3 +- fcx-web/lib/fullcontrol_x_web/components.ex | 3 +- fcx-web/lib/fullcontrol_x_web/info_live.ex | 28 ++++- fcx-web/lib/fullcontrol_x_web/tools_live.ex | 3 + .../lib/fullcontrol_x_web/trackpad_live.ex | 14 ++- fcx-web/mix.exs | 2 +- .../views/error_view_test.exs | 14 +-- 12 files changed, 188 insertions(+), 34 deletions(-) create mode 100644 .github/workflows/fcx-web.yml diff --git a/.github/workflows/fcx-web.yml b/.github/workflows/fcx-web.yml new file mode 100644 index 0000000..0126578 --- /dev/null +++ b/.github/workflows/fcx-web.yml @@ -0,0 +1,107 @@ +name: fcx-web + +on: + push: + pull_request: + +# Cancel superseded runs on the same ref so rapid pushes don't pile up. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +env: + MIX_ENV: test + +jobs: + # Formatting is version-independent, so check it once instead of per matrix cell. + lint: + name: Lint + runs-on: ubuntu-latest + env: + ELIXIR_VERSION: "1.15" + OTP_VERSION: "25" + defaults: + run: + working-directory: fcx-web + steps: + - uses: actions/checkout@v6 + + - name: Set up Elixir / OTP + uses: erlef/setup-beam@v1 + with: + otp-version: ${{ env.OTP_VERSION }} + elixir-version: ${{ env.ELIXIR_VERSION }} + + - name: Cache deps and _build + uses: actions/cache@v5 + with: + path: | + fcx-web/deps + fcx-web/_build + key: ${{ runner.os }}-mix-lint-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ hashFiles('fcx-web/mix.lock') }} + restore-keys: ${{ runner.os }}-mix-lint-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}- + + - name: Install dependencies + run: mix deps.get + + # Compile before format so all dependency apps are loaded. + - name: Compile + run: mix compile + + - name: Check formatting + run: mix format --check-formatted + + test: + name: fcx-web tests (Elixir ${{ matrix.elixir }} / OTP ${{ matrix.otp }}) + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + include: + - elixir: "1.15" + otp: "25" + - elixir: "1.16" + otp: "26" + - elixir: "1.17" + otp: "27" + - elixir: "1.18" + otp: "27" + - elixir: "1.19" + otp: "28" + + defaults: + run: + working-directory: fcx-web + + steps: + - uses: actions/checkout@v6 + + - name: Set up Elixir / OTP + uses: erlef/setup-beam@v1 + with: + otp-version: ${{ matrix.otp }} + elixir-version: ${{ matrix.elixir }} + + - name: Cache deps and _build + uses: actions/cache@v5 + with: + path: | + fcx-web/deps + fcx-web/_build + key: ${{ runner.os }}-mix-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('fcx-web/mix.lock') }} + restore-keys: | + ${{ runner.os }}-mix-${{ matrix.otp }}-${{ matrix.elixir }}- + + - name: Install dependencies + run: mix deps.get + + - name: Compile (warnings as errors) + run: mix compile --warnings-as-errors + + # SQLite test DB — no database service required. + - name: Run tests + run: mix test diff --git a/fcx-web/config/config.exs b/fcx-web/config/config.exs index ea016ae..c26cfca 100644 --- a/fcx-web/config/config.exs +++ b/fcx-web/config/config.exs @@ -11,7 +11,8 @@ config :fullcontrol_x, namespace: FullControlX, ecto_repos: [FullControlX.Repo], fcxd_path: "../zig-out/bin/FullControlX", - files_path: "priv/static/assets" + files_path: "priv/static/assets", + start_driver: true # Configures the endpoint config :fullcontrol_x, FullControlXWeb.Endpoint, diff --git a/fcx-web/config/prod.exs b/fcx-web/config/prod.exs index 160d44d..0b88d7f 100644 --- a/fcx-web/config/prod.exs +++ b/fcx-web/config/prod.exs @@ -9,7 +9,8 @@ import Config # manifest is generated by the `mix phx.digest` task, # which you should run after static files are built and # before starting your production server. -config :fullcontrol_x, FullControlXWeb.Endpoint, cache_static_manifest: "priv/static/cache_manifest.json" +config :fullcontrol_x, FullControlXWeb.Endpoint, + cache_static_manifest: "priv/static/cache_manifest.json" # Do not print debug messages in production config :logger, level: :info diff --git a/fcx-web/config/test.exs b/fcx-web/config/test.exs index 9555d0d..a4c5371 100644 --- a/fcx-web/config/test.exs +++ b/fcx-web/config/test.exs @@ -17,8 +17,11 @@ config :fullcontrol_x, FullControlXWeb.Endpoint, secret_key_base: "EgTKrB+SZcnfHfZUYem501WigH0KvvCe5J6YSP6JfwxM7aKjQ2BQWw2SaCUegyhS", server: false +# No native fcxd binary in test; don't start the driver. +config :fullcontrol_x, start_driver: false + # Print only warnings and errors during test -config :logger, level: :warn +config :logger, level: :warning # Initialize plugs at runtime for faster test compilation config :phoenix, :plug_init_mode, :runtime diff --git a/fcx-web/lib/fullcontrol_x/application.ex b/fcx-web/lib/fullcontrol_x/application.ex index b4fd541..85eaab8 100644 --- a/fcx-web/lib/fullcontrol_x/application.ex +++ b/fcx-web/lib/fullcontrol_x/application.ex @@ -9,20 +9,17 @@ defmodule FullControlX.Application do def start(_type, _args) do FullControlX.print_connection_qrcode() - children = [ - # Start the Ecto repository - FullControlX.Repo, - # Start the Telemetry supervisor - FullControlXWeb.Telemetry, - # Start the PubSub system - {Phoenix.PubSub, name: FullControlX.PubSub}, - # Start the Endpoint (http/https) - FullControlXWeb.Endpoint, - # Start a worker by calling: FullControlX.Worker.start_link(arg) - # {FullControlX.Worker, arg} - {FullControlX.Driver, - name: FullControlX.Driver, fcxd_path: Application.get_env(:fullcontrol_x, :fcxd_path)} - ] + children = + [ + # Start the Ecto repository + FullControlX.Repo, + # Start the Telemetry supervisor + FullControlXWeb.Telemetry, + # Start the PubSub system + {Phoenix.PubSub, name: FullControlX.PubSub}, + # Start the Endpoint (http/https) + FullControlXWeb.Endpoint + ] ++ driver_children() # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options @@ -30,6 +27,18 @@ defmodule FullControlX.Application do Supervisor.start_link(children, opts) end + # Skip the driver where its native fcxd binary isn't built (e.g. test). + defp driver_children do + if Application.get_env(:fullcontrol_x, :start_driver, true) do + [ + {FullControlX.Driver, + name: FullControlX.Driver, fcxd_path: Application.get_env(:fullcontrol_x, :fcxd_path)} + ] + else + [] + end + end + # Tell Phoenix to update the endpoint configuration # whenever the application is updated. @impl true diff --git a/fcx-web/lib/fullcontrol_x_web/commands_live.ex b/fcx-web/lib/fullcontrol_x_web/commands_live.ex index fa10715..9164b91 100644 --- a/fcx-web/lib/fullcontrol_x_web/commands_live.ex +++ b/fcx-web/lib/fullcontrol_x_web/commands_live.ex @@ -12,10 +12,11 @@ defmodule FullControlXWeb.CommandsLive do ~H""" <.header title="FullControlX" />
+ diff --git a/fcx-web/lib/fullcontrol_x_web/components.ex b/fcx-web/lib/fullcontrol_x_web/components.ex index c4fb5a8..f3c68d6 100644 --- a/fcx-web/lib/fullcontrol_x_web/components.ex +++ b/fcx-web/lib/fullcontrol_x_web/components.ex @@ -32,8 +32,7 @@ defmodule FullControlXWeb.Components do def switch(assigns) do ~H""" """ end diff --git a/fcx-web/lib/fullcontrol_x_web/info_live.ex b/fcx-web/lib/fullcontrol_x_web/info_live.ex index e23e454..4f3004f 100644 --- a/fcx-web/lib/fullcontrol_x_web/info_live.ex +++ b/fcx-web/lib/fullcontrol_x_web/info_live.ex @@ -21,31 +21,49 @@ defmodule FullControlXWeb.InfoLive do

Host

+
<%= for {key, value} <- @info do %>
- <%= "#{key}: #{value}" %> + {"#{key}: #{value}"}
<% end %>
+

URLs

+
+

QR code

-

<%= @url_in_qrcode %>

+ +

{@url_in_qrcode}

+

FullControlX

-

FullControlX is the official Open Source "spinoff" of the commercial app FullControl.

-

Developed and maintained by Francesco Burelli. More info at Github Project Homepage.

+ +

+ FullControlX is the official Open Source "spinoff" of the commercial app FullControl. +

+ +

+ Developed and maintained by Francesco Burelli. More info at Github Project Homepage. +

""" diff --git a/fcx-web/lib/fullcontrol_x_web/tools_live.ex b/fcx-web/lib/fullcontrol_x_web/tools_live.ex index 5c4207b..4fb43e2 100644 --- a/fcx-web/lib/fullcontrol_x_web/tools_live.ex +++ b/fcx-web/lib/fullcontrol_x_web/tools_live.ex @@ -44,16 +44,19 @@ defmodule FullControlXWeb.ToolsLive do <._button title={button.title} value={button.value} icon={button.icon} /> <% end %> +
<%= for button <- @arrows_buttons do %> <._button title={button.title} value={button.value} icon={button.icon} /> <% end %>
+
<%= for button <- @media_buttons do %> <._button title={button.title} value={button.value} icon={button.icon} /> <% end %>
+
<%= for button <- @audio_buttons do %> <._button title={button.title} value={button.value} icon={button.icon} /> diff --git a/fcx-web/lib/fullcontrol_x_web/trackpad_live.ex b/fcx-web/lib/fullcontrol_x_web/trackpad_live.ex index bb56cb7..3e3bea7 100644 --- a/fcx-web/lib/fullcontrol_x_web/trackpad_live.ex +++ b/fcx-web/lib/fullcontrol_x_web/trackpad_live.ex @@ -17,12 +17,24 @@ defmodule FullControlXWeb.TrackpadLive do

Left click: one tap

+

Right click: one tap with two fingers

+

Scroll: drag with two fingers

+

Drag: one tap and drag or drag with three fingers

-
+ +
""" diff --git a/fcx-web/mix.exs b/fcx-web/mix.exs index 6148e7b..58c1eac 100644 --- a/fcx-web/mix.exs +++ b/fcx-web/mix.exs @@ -5,7 +5,7 @@ defmodule FullControlX.MixProject do [ app: :fullcontrol_x, version: "0.1.0", - elixir: "~> 1.14", + elixir: "~> 1.15", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, aliases: aliases(), diff --git a/fcx-web/test/fullcontrol_x_web/views/error_view_test.exs b/fcx-web/test/fullcontrol_x_web/views/error_view_test.exs index a54d261..5101678 100644 --- a/fcx-web/test/fullcontrol_x_web/views/error_view_test.exs +++ b/fcx-web/test/fullcontrol_x_web/views/error_view_test.exs @@ -1,14 +1,14 @@ defmodule FullControlXWeb.ErrorViewTest do use FullControlXWeb.ConnCase, async: true - # Bring render/3 and render_to_string/3 for testing custom views - import Phoenix.View - - test "renders 404.html" do - assert render_to_string(FullControlXWeb.ErrorView, "404.html", []) == "Not Found" + # ErrorView has no templates, so it falls back to template_not_found/2, + # which returns the status message for the requested template. + test "renders the 404 status message" do + assert FullControlXWeb.ErrorView.template_not_found("404.html", %{}) == "Not Found" end - test "renders 500.html" do - assert render_to_string(FullControlXWeb.ErrorView, "500.html", []) == "Internal Server Error" + test "renders the 500 status message" do + assert FullControlXWeb.ErrorView.template_not_found("500.html", %{}) == + "Internal Server Error" end end