defmodule ToweropsWeb.ScheduleLiveTest do use ToweropsWeb.ConnCase, async: true import Phoenix.LiveViewTest import Towerops.OnCallFixtures alias Towerops.OnCall setup :register_and_log_in_user setup %{conn: conn, user: user} do {:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id) conn = Plug.Conn.put_session(conn, :current_organization_id, organization.id) %{conn: conn, organization: organization} end describe "Index" do test "mounts and lists schedules", %{conn: conn, organization: organization} do schedule = schedule_fixture(organization.id, %{name: "Primary Rotation"}) {:ok, _view, html} = live(conn, ~p"/schedules") assert html =~ "Schedules" assert html =~ "Primary Rotation" assert html =~ schedule.timezone end test "shows empty state when no schedules", %{conn: conn} do {:ok, _view, html} = live(conn, ~p"/schedules") assert html =~ "No schedules" assert html =~ "Create an on-call schedule" end test "shows who is currently on-call for each schedule", %{ conn: conn, organization: organization, user: user } do schedule = schedule_fixture(organization.id) layer = layer_fixture(schedule.id, %{ start_date: ~U[2025-01-01 09:00:00Z], handoff_time: ~T[09:00:00], rotation_type: "weekly" }) layer_member_fixture(layer.id, user.id) {:ok, _view, html} = live(conn, ~p"/schedules") assert html =~ user.email end test "renders date navigation controls", %{conn: conn, organization: organization} do _ = schedule_fixture(organization.id) {:ok, view, html} = live(conn, ~p"/schedules") assert html =~ "Today" assert html =~ "2 Weeks" assert has_element?(view, "button[phx-click=\"prev\"]") assert has_element?(view, "button[phx-click=\"next\"]") end test "renders a per-schedule gantt strip with the on-call user's name", %{ conn: conn, organization: organization, user: user } do schedule = schedule_fixture(organization.id, %{name: "Primary"}) layer = layer_fixture(schedule.id, %{ start_date: ~U[2025-01-01 09:00:00Z], handoff_time: ~T[09:00:00], rotation_type: "weekly" }) layer_member_fixture(layer.id, user.id) {:ok, _view, html} = live(conn, ~p"/schedules") assert html =~ "On-Call Now" assert html =~ user.email # Gantt cell uses inline grid-column style derived from segment offsets. assert html =~ ~r/grid-column:\s*\d+\s*\/\s*span\s*\d+/ end test "navigates the date window when prev/next/today are clicked", %{ conn: conn, organization: organization } do _ = schedule_fixture(organization.id) {:ok, view, _html} = live(conn, ~p"/schedules?start=2026-04-01&range=14") view |> element("button[phx-click=\"next\"]") |> render_click() assert_patched(view, ~p"/schedules?#{[tab: "schedules", start: "2026-04-15", range: 14]}") view |> element("button[phx-click=\"prev\"]") |> render_click() assert_patched(view, ~p"/schedules?#{[tab: "schedules", start: "2026-04-01", range: 14]}") end test "respects the range query param", %{conn: conn, organization: organization} do _ = schedule_fixture(organization.id) {:ok, _view, html} = live(conn, ~p"/schedules?range=7") assert html =~ "1 Week" # The range select should preselect 1 Week assert html =~ ~r/