#!/usr/bin/env elixir
# live_interaction_contracts — multi-version conformance harness (test target).
#
# One LiveView renders every browser-native machine under test (popover, dialog,
# details, native select, focused input, scroll) plus shared "nearby" patch
# sources (keyed list, stream), and exposes a single generic `bump` event so the
# driver can patch any region's content / attribute / sibling in isolation.
#
# The LiveView version is selected by the LV_SPEC env var so the SAME app can run
# against multiple versions:
# LV_SPEC unset / "stable" -> {:phoenix_live_view, "~> 1.1"}
# LV_SPEC "1.2.7" -> {:phoenix_live_view, "1.2.7"}
# LV_SPEC "github:owner/repo#ref" -> git dependency at ref
# LV_SPEC "path:/abs/path" -> local path dependency
#
# Run: LV_SPEC=1.2.7 elixir app.exs (http://127.0.0.1:4123)
lv_dep =
case System.get_env("LV_SPEC") do
nil -> {:phoenix_live_view, "~> 1.1"}
"" -> {:phoenix_live_view, "~> 1.1"}
"stable" -> {:phoenix_live_view, "~> 1.1"}
"path:" <> path -> {:phoenix_live_view, path: path}
"github:" <> rest ->
case String.split(rest, "#", parts: 2) do
[repo, ref] -> {:phoenix_live_view, github: repo, ref: ref}
[repo] -> {:phoenix_live_view, github: repo}
end
version -> {:phoenix_live_view, version}
end
Mix.install([
{:phoenix, "~> 1.8"},
lv_dep,
{:bandit, "~> 1.7"},
{:jason, "~> 1.4"}
])
Application.put_env(:phoenix, :json_library, Jason)
Application.put_env(:lic, LICWeb.Endpoint,
http: [ip: {127, 0, 0, 1}, port: String.to_integer(System.get_env("PORT") || "4123")],
server: true,
adapter: Bandit.PhoenixAdapter,
live_view: [signing_salt: "lic-harness-salt"],
secret_key_base: String.duplicate("live-interaction-contracts!", 4),
pubsub_server: LIC.PubSub,
check_origin: false,
debug_errors: true
)
defmodule LICWeb.Layout do
use Phoenix.Component
@phoenix_js File.read!(Application.app_dir(:phoenix, "priv/static/phoenix.min.js"))
@lv_js File.read!(Application.app_dir(:phoenix_live_view, "priv/static/phoenix_live_view.min.js"))
def render("root.html", assigns) do
assigns = assign(assigns, phoenix_js: @phoenix_js, lv_js: @lv_js)
~H"""
live_interaction_contracts harness
<%= @inner_content %>
"""
end
end
defmodule LICWeb.MainLive do
use Phoenix.LiveView
alias Phoenix.LiveView.JS
def mount(_p, _s, socket) do
{:ok,
socket
|> assign(bumps: %{}, order: ["i1", "i2", "i3", "i4"], p: "none", aha_rev: 0)
|> stream(:sitems, for(i <- 1..3, do: %{id: "s#{i}", label: "S#{i}-v0"}))}
end
def handle_params(params, _uri, socket), do: {:noreply, assign(socket, p: params["p"] || "none")}
defp b(assigns, k), do: Map.get(assigns.bumps, k, 0)
def render(assigns) do
~H"""
banner-{b(assigns, "banner")}
<%!-- shared nearby patch sources --%>
id}>{id}
{it.label}
<%!-- ===== POPOVER (browser top-layer, no attr reflection) ===== --%>
pop-{b(assigns, "pop_content")}aha-pop-{@aha_rev}
sib-{b(assigns, "pop_sib")}
<%!-- ===== DIALOG (open reflected into `open` attribute) ===== --%>
<%!-- Same machine and patch as #dlg; only its browser-owned state surface is protected. --%>
sib-{b(assigns, "dlg_sib")}
<%!-- Focused causal trial: one acknowledged diff touches all three state holders. --%>
<%!-- ===== DETAILS/SUMMARY (open reflected into `open` attribute) ===== --%>
summary