diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 0000000..ad4c529 --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,53 @@ +name: Build and upload docker image + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + attestations: write + id-token: write + + steps: + - uses: actions/checkout@v4 + + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Docker image + id: push + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v1 + with: + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}} + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true diff --git a/lib/mentat/activities.ex b/lib/mentat/activities.ex new file mode 100644 index 0000000..8feb502 --- /dev/null +++ b/lib/mentat/activities.ex @@ -0,0 +1,104 @@ +defmodule Mentat.Activities do + @moduledoc """ + The Activities context. + """ + + import Ecto.Query, warn: false + alias Mentat.Repo + + alias Mentat.Activities.ActivityRecord + + @doc """ + Returns the list of activity_records. + + ## Examples + + iex> list_activity_records() + [%ActivityRecord{}, ...] + + """ + def list_activity_records do + Repo.all(ActivityRecord) + end + + @doc """ + Gets a single activity_record. + + Raises `Ecto.NoResultsError` if the Activity record does not exist. + + ## Examples + + iex> get_activity_record!(123) + %ActivityRecord{} + + iex> get_activity_record!(456) + ** (Ecto.NoResultsError) + + """ + def get_activity_record!(id), do: Repo.get!(ActivityRecord, id) + + @doc """ + Creates a activity_record. + + ## Examples + + iex> create_activity_record(%{field: value}) + {:ok, %ActivityRecord{}} + + iex> create_activity_record(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_activity_record(attrs \\ %{}) do + %ActivityRecord{} + |> ActivityRecord.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a activity_record. + + ## Examples + + iex> update_activity_record(activity_record, %{field: new_value}) + {:ok, %ActivityRecord{}} + + iex> update_activity_record(activity_record, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_activity_record(%ActivityRecord{} = activity_record, attrs) do + activity_record + |> ActivityRecord.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a activity_record. + + ## Examples + + iex> delete_activity_record(activity_record) + {:ok, %ActivityRecord{}} + + iex> delete_activity_record(activity_record) + {:error, %Ecto.Changeset{}} + + """ + def delete_activity_record(%ActivityRecord{} = activity_record) do + Repo.delete(activity_record) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking activity_record changes. + + ## Examples + + iex> change_activity_record(activity_record) + %Ecto.Changeset{data: %ActivityRecord{}} + + """ + def change_activity_record(%ActivityRecord{} = activity_record, attrs \\ %{}) do + ActivityRecord.changeset(activity_record, attrs) + end +end diff --git a/lib/mentat/activities/activity_record.ex b/lib/mentat/activities/activity_record.ex new file mode 100644 index 0000000..713a247 --- /dev/null +++ b/lib/mentat/activities/activity_record.ex @@ -0,0 +1,53 @@ +defmodule Mentat.Activities.ActivityRecord do + use Ecto.Schema + import Ecto.Changeset + + @required_fields [:start_time, :end_time, :value, :measuring_scale, :user_id, :provider_id] + @optional_fields [:tags, :details] + + @primary_key {:id, :binary_id, autogenerate: true} + @foreign_key_type :binary_id + schema "activity_records" do + field :value, :decimal + field :details, :map + field :start_time, :utc_datetime + field :end_time, :utc_datetime + field :tags, {:array, :string} + + field :measuring_scale, Ecto.Enum, + values: [ + work_min: 1, + side_project_min: 2, + steps: 3, + steps_distance: 4, + floors: 5, + workout_min: 6, + coffees: 7, + alcoholic_drinks: 8, + sleep_min: 9, + sleep_light_min: 10, + sleep_deep_min: 11, + sleep_rem_min: 12, + sleep_awake_min: 13, + sleep_awakenings: 14, + meditation_min: 15, + weight: 16, + heartrate: 17, + heartrate_resting: 18, + heartrate_variability: 19, + reading_min: 20 + ] + + belongs_to :user, User + belongs_to :provider, Provider + + timestamps(type: :utc_datetime) + end + + @doc false + def changeset(activity_record, attrs) do + activity_record + |> cast(attrs, @required_fields ++ @optional_fields) + |> validate_required(@required_fields) + end +end diff --git a/lib/mentat_web/live/activity_record_live/form_component.ex b/lib/mentat_web/live/activity_record_live/form_component.ex new file mode 100644 index 0000000..5ae2cfb --- /dev/null +++ b/lib/mentat_web/live/activity_record_live/form_component.ex @@ -0,0 +1,112 @@ +defmodule MentatWeb.ActivityRecordLive.FormComponent do + use MentatWeb, :live_component + + alias Mentat.Integrations + alias Mentat.Activities + + @impl true + def render(assigns) do + ~H""" +
+ <.header> + <%= @title %> + <:subtitle>Use this form to manage activity_record records in your database. + + + <.simple_form + for={@form} + id="activity_record-form" + phx-target={@myself} + phx-change="validate" + phx-submit="save" + > + <.input field={@form[:start_time]} type="datetime-local" label="Start time" /> + <.input field={@form[:end_time]} type="datetime-local" label="End time" /> + <.input field={@form[:value]} type="number" label="Value" step="any" /> + <%!-- <.input --%> + <%!-- field={@form[:tags]} --%> + <%!-- type="select" --%> + <%!-- multiple --%> + <%!-- label="Tags" --%> + <%!-- options={[{"Option 1", "option1"}, {"Option 2", "option2"}]} --%> + <%!-- /> --%> + <.input + field={@form[:measuring_scale]} + type="select" + label="Measuring scale" + prompt="Choose a value" + options={Ecto.Enum.values(Mentat.Activities.ActivityRecord, :measuring_scale)} + /> + <.input + field={@form[:provider_id]} + type="select" + label="Provider" + prompt="Choose a value" + options={Integrations.list_providers() |> Enum.map(&{&1.label, &1.id})} + /> + <:actions> + <.button phx-disable-with="Saving...">Save Activity record + + +
+ """ + end + + @impl true + def update(%{activity_record: activity_record} = assigns, socket) do + {:ok, + socket + |> assign(assigns) + |> assign_new(:form, fn -> + to_form(Activities.change_activity_record(activity_record)) + end)} + end + + @impl true + def handle_event("validate", %{"activity_record" => activity_record_params}, socket) do + changeset = + Activities.change_activity_record(socket.assigns.activity_record, activity_record_params) + + {:noreply, assign(socket, form: to_form(changeset, action: :validate))} + end + + def handle_event("save", %{"activity_record" => activity_record_params}, socket) do + save_activity_record(socket, socket.assigns.action, activity_record_params) + end + + defp save_activity_record(socket, :edit, activity_record_params) do + case Activities.update_activity_record(socket.assigns.activity_record, activity_record_params) do + {:ok, activity_record} -> + notify_parent({:saved, activity_record}) + + {:noreply, + socket + |> put_flash(:info, "Activity record updated successfully") + |> push_patch(to: socket.assigns.patch)} + + {:error, %Ecto.Changeset{} = changeset} -> + {:noreply, assign(socket, form: to_form(changeset))} + end + end + + defp save_activity_record(socket, :new, activity_record_params) do + case Activities.create_activity_record( + Map.merge(activity_record_params, %{ + "user_id" => socket.assigns.current_user.id + }) + ) do + {:ok, activity_record} -> + notify_parent({:saved, activity_record}) + + {:noreply, + socket + |> put_flash(:info, "Activity record created successfully") + |> push_patch(to: socket.assigns.patch)} + + {:error, %Ecto.Changeset{} = changeset} -> + {:noreply, assign(socket, form: to_form(changeset))} + end + end + + defp notify_parent(msg), do: send(self(), {__MODULE__, msg}) +end diff --git a/lib/mentat_web/live/activity_record_live/index.ex b/lib/mentat_web/live/activity_record_live/index.ex new file mode 100644 index 0000000..413ea12 --- /dev/null +++ b/lib/mentat_web/live/activity_record_live/index.ex @@ -0,0 +1,47 @@ +defmodule MentatWeb.ActivityRecordLive.Index do + use MentatWeb, :live_view + + alias Mentat.Activities + alias Mentat.Activities.ActivityRecord + + @impl true + def mount(_params, _session, socket) do + {:ok, stream(socket, :activity_records, Activities.list_activity_records())} + end + + @impl true + def handle_params(params, _url, socket) do + {:noreply, apply_action(socket, socket.assigns.live_action, params)} + end + + defp apply_action(socket, :edit, %{"id" => id}) do + socket + |> assign(:page_title, "Edit Activity record") + |> assign(:activity_record, Activities.get_activity_record!(id)) + end + + defp apply_action(socket, :new, _params) do + socket + |> assign(:page_title, "New Activity record") + |> assign(:activity_record, %ActivityRecord{}) + end + + defp apply_action(socket, :index, _params) do + socket + |> assign(:page_title, "Listing Activity records") + |> assign(:activity_record, nil) + end + + @impl true + def handle_info({MentatWeb.ActivityRecordLive.FormComponent, {:saved, activity_record}}, socket) do + {:noreply, stream_insert(socket, :activity_records, activity_record)} + end + + @impl true + def handle_event("delete", %{"id" => id}, socket) do + activity_record = Activities.get_activity_record!(id) + {:ok, _} = Activities.delete_activity_record(activity_record) + + {:noreply, stream_delete(socket, :activity_records, activity_record)} + end +end diff --git a/lib/mentat_web/live/activity_record_live/index.html.heex b/lib/mentat_web/live/activity_record_live/index.html.heex new file mode 100644 index 0000000..141d58f --- /dev/null +++ b/lib/mentat_web/live/activity_record_live/index.html.heex @@ -0,0 +1,56 @@ +<.header> + Listing Activity records + <:actions> + <.link patch={~p"/activity_records/new"}> + <.button>New Activity record + + + + +<.table + id="activity_records" + rows={@streams.activity_records} + row_click={ + fn {_id, activity_record} -> JS.navigate(~p"/activity_records/#{activity_record}") end + } +> + <:col :let={{_id, activity_record}} label="Start time"><%= activity_record.start_time %> + <:col :let={{_id, activity_record}} label="End time"><%= activity_record.end_time %> + <:col :let={{_id, activity_record}} label="Value"><%= activity_record.value %> + <:col :let={{_id, activity_record}} label="Details"><%= activity_record.details %> + <:col :let={{_id, activity_record}} label="Tags"><%= activity_record.tags %> + <:col :let={{_id, activity_record}} label="Measuring scale"> + <%= activity_record.measuring_scale %> + + <:action :let={{_id, activity_record}}> +
+ <.link navigate={~p"/activity_records/#{activity_record}"}>Show +
+ <.link patch={~p"/activity_records/#{activity_record}/edit"}>Edit + + <:action :let={{id, activity_record}}> + <.link + phx-click={JS.push("delete", value: %{id: activity_record.id}) |> hide("##{id}")} + data-confirm="Are you sure?" + > + Delete + + + + +<.modal + :if={@live_action in [:new, :edit]} + id="activity_record-modal" + show + on_cancel={JS.patch(~p"/activity_records")} +> + <.live_component + module={MentatWeb.ActivityRecordLive.FormComponent} + id={@activity_record.id || :new} + title={@page_title} + action={@live_action} + activity_record={@activity_record} + patch={~p"/activity_records"} + current_user={@current_user} + /> + diff --git a/lib/mentat_web/live/activity_record_live/show.ex b/lib/mentat_web/live/activity_record_live/show.ex new file mode 100644 index 0000000..a5cf1df --- /dev/null +++ b/lib/mentat_web/live/activity_record_live/show.ex @@ -0,0 +1,21 @@ +defmodule MentatWeb.ActivityRecordLive.Show do + use MentatWeb, :live_view + + alias Mentat.Activities + + @impl true + def mount(_params, _session, socket) do + {:ok, socket} + end + + @impl true + def handle_params(%{"id" => id}, _, socket) do + {:noreply, + socket + |> assign(:page_title, page_title(socket.assigns.live_action)) + |> assign(:activity_record, Activities.get_activity_record!(id))} + end + + defp page_title(:show), do: "Show Activity record" + defp page_title(:edit), do: "Edit Activity record" +end diff --git a/lib/mentat_web/live/activity_record_live/show.html.heex b/lib/mentat_web/live/activity_record_live/show.html.heex new file mode 100644 index 0000000..b829da1 --- /dev/null +++ b/lib/mentat_web/live/activity_record_live/show.html.heex @@ -0,0 +1,31 @@ +<.header> + Activity record <%= @activity_record.id %> + <:subtitle>This is a activity_record record from your database. + <:actions> + <.link patch={~p"/activity_records/#{@activity_record}/show/edit"} phx-click={JS.push_focus()}> + <.button>Edit activity_record + + + + +<.list> + <:item title="Start time"><%= @activity_record.start_time %> + <:item title="End time"><%= @activity_record.end_time %> + <:item title="Value"><%= @activity_record.value %> + <:item title="Details"><%= @activity_record.details %> + <:item title="Tags"><%= @activity_record.tags %> + <:item title="Measuring scale"><%= @activity_record.measuring_scale %> + + +<.back navigate={~p"/activity_records"}>Back to activity_records + +<.modal :if={@live_action == :edit} id="activity_record-modal" show on_cancel={JS.patch(~p"/activity_records/#{@activity_record}")}> + <.live_component + module={MentatWeb.ActivityRecordLive.FormComponent} + id={@activity_record.id} + title={@page_title} + action={@live_action} + activity_record={@activity_record} + patch={~p"/activity_records/#{@activity_record}"} + /> + diff --git a/lib/mentat_web/live/provider_live/form_component.ex b/lib/mentat_web/live/provider_live/form_component.ex index ce50838..ed2a6bb 100644 --- a/lib/mentat_web/live/provider_live/form_component.ex +++ b/lib/mentat_web/live/provider_live/form_component.ex @@ -72,7 +72,11 @@ defmodule MentatWeb.ProviderLive.FormComponent do end defp save_provider(socket, :new, provider_params) do - case Integrations.create_provider(provider_params) do + case Integrations.create_provider( + Map.merge(provider_params, %{ + "user_id" => socket.assigns.current_user.id + }) + ) do {:ok, provider} -> notify_parent({:saved, provider}) diff --git a/lib/mentat_web/live/provider_live/index.html.heex b/lib/mentat_web/live/provider_live/index.html.heex index 07ae4c8..59ec2eb 100644 --- a/lib/mentat_web/live/provider_live/index.html.heex +++ b/lib/mentat_web/live/provider_live/index.html.heex @@ -31,7 +31,12 @@ -<.modal :if={@live_action in [:new, :edit]} id="provider-modal" show on_cancel={JS.patch(~p"/providers")}> +<.modal + :if={@live_action in [:new, :edit]} + id="provider-modal" + show + on_cancel={JS.patch(~p"/providers")} +> <.live_component module={MentatWeb.ProviderLive.FormComponent} id={@provider.id || :new} @@ -39,5 +44,6 @@ action={@live_action} provider={@provider} patch={~p"/providers"} + current_user={@current_user} /> diff --git a/lib/mentat_web/router.ex b/lib/mentat_web/router.ex index 795af1c..d9ac0e5 100644 --- a/lib/mentat_web/router.ex +++ b/lib/mentat_web/router.ex @@ -68,6 +68,20 @@ defmodule MentatWeb.Router do on_mount: [{MentatWeb.UserAuth, :ensure_authenticated}] do live "/users/settings", UserSettingsLive, :edit live "/users/settings/confirm_email/:token", UserSettingsLive, :confirm_email + + live "/providers", ProviderLive.Index, :index + live "/providers/new", ProviderLive.Index, :new + live "/providers/:id/edit", ProviderLive.Index, :edit + + live "/providers/:id", ProviderLive.Show, :show + live "/providers/:id/show/edit", ProviderLive.Show, :edit + + live "/activity_records", ActivityRecordLive.Index, :index + live "/activity_records/new", ActivityRecordLive.Index, :new + live "/activity_records/:id/edit", ActivityRecordLive.Index, :edit + + live "/activity_records/:id", ActivityRecordLive.Show, :show + live "/activity_records/:id/show/edit", ActivityRecordLive.Show, :edit end end diff --git a/priv/repo/migrations/20240807135812_create_activity_records.exs b/priv/repo/migrations/20240807135812_create_activity_records.exs new file mode 100644 index 0000000..1fd9126 --- /dev/null +++ b/priv/repo/migrations/20240807135812_create_activity_records.exs @@ -0,0 +1,23 @@ +defmodule Mentat.Repo.Migrations.CreateActivityRecords do + use Ecto.Migration + + def change do + create table(:activity_records, primary_key: false) do + add :id, :binary_id, primary_key: true + add :start_time, :utc_datetime, null: false + add :end_time, :utc_datetime, null: false + add :value, :decimal, null: false + add :details, :map + add :tags, {:array, :string} + add :measuring_scale, :integer, null: false + add :user_id, references(:users, on_delete: :delete_all, type: :binary_id) + add :provider_id, references(:providers, on_delete: :nothing, type: :binary_id) + + timestamps(type: :utc_datetime) + end + + create index(:activity_records, [:user_id]) + create index(:activity_records, [:provider_id]) + create index(:activity_records, [:measuring_scale]) + end +end diff --git a/test/mentat/activities_test.exs b/test/mentat/activities_test.exs new file mode 100644 index 0000000..93ccbe5 --- /dev/null +++ b/test/mentat/activities_test.exs @@ -0,0 +1,69 @@ +defmodule Mentat.ActivitiesTest do + use Mentat.DataCase + + alias Mentat.Activities + + describe "activity_records" do + alias Mentat.Activities.ActivityRecord + + import Mentat.ActivitiesFixtures + + @invalid_attrs %{value: nil, details: nil, start_time: nil, end_time: nil, tags: nil, measuring_scale: nil} + + test "list_activity_records/0 returns all activity_records" do + activity_record = activity_record_fixture() + assert Activities.list_activity_records() == [activity_record] + end + + test "get_activity_record!/1 returns the activity_record with given id" do + activity_record = activity_record_fixture() + assert Activities.get_activity_record!(activity_record.id) == activity_record + end + + test "create_activity_record/1 with valid data creates a activity_record" do + valid_attrs = %{value: "120.5", details: %{}, start_time: ~U[2024-08-06 13:58:00Z], end_time: ~U[2024-08-06 13:58:00Z], tags: ["option1", "option2"], measuring_scale: :duration} + + assert {:ok, %ActivityRecord{} = activity_record} = Activities.create_activity_record(valid_attrs) + assert activity_record.value == Decimal.new("120.5") + assert activity_record.details == %{} + assert activity_record.start_time == ~U[2024-08-06 13:58:00Z] + assert activity_record.end_time == ~U[2024-08-06 13:58:00Z] + assert activity_record.tags == ["option1", "option2"] + assert activity_record.measuring_scale == :duration + end + + test "create_activity_record/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Activities.create_activity_record(@invalid_attrs) + end + + test "update_activity_record/2 with valid data updates the activity_record" do + activity_record = activity_record_fixture() + update_attrs = %{value: "456.7", details: %{}, start_time: ~U[2024-08-07 13:58:00Z], end_time: ~U[2024-08-07 13:58:00Z], tags: ["option1"], measuring_scale: :duration} + + assert {:ok, %ActivityRecord{} = activity_record} = Activities.update_activity_record(activity_record, update_attrs) + assert activity_record.value == Decimal.new("456.7") + assert activity_record.details == %{} + assert activity_record.start_time == ~U[2024-08-07 13:58:00Z] + assert activity_record.end_time == ~U[2024-08-07 13:58:00Z] + assert activity_record.tags == ["option1"] + assert activity_record.measuring_scale == :duration + end + + test "update_activity_record/2 with invalid data returns error changeset" do + activity_record = activity_record_fixture() + assert {:error, %Ecto.Changeset{}} = Activities.update_activity_record(activity_record, @invalid_attrs) + assert activity_record == Activities.get_activity_record!(activity_record.id) + end + + test "delete_activity_record/1 deletes the activity_record" do + activity_record = activity_record_fixture() + assert {:ok, %ActivityRecord{}} = Activities.delete_activity_record(activity_record) + assert_raise Ecto.NoResultsError, fn -> Activities.get_activity_record!(activity_record.id) end + end + + test "change_activity_record/1 returns a activity_record changeset" do + activity_record = activity_record_fixture() + assert %Ecto.Changeset{} = Activities.change_activity_record(activity_record) + end + end +end diff --git a/test/mentat_web/live/activity_record_live_test.exs b/test/mentat_web/live/activity_record_live_test.exs new file mode 100644 index 0000000..7106f4f --- /dev/null +++ b/test/mentat_web/live/activity_record_live_test.exs @@ -0,0 +1,108 @@ +defmodule MentatWeb.ActivityRecordLiveTest do + use MentatWeb.ConnCase + + import Phoenix.LiveViewTest + import Mentat.ActivitiesFixtures + + @create_attrs %{value: "120.5", details: %{}, start_time: "2024-08-06T13:58:00Z", end_time: "2024-08-06T13:58:00Z", tags: ["option1", "option2"], measuring_scale: :duration} + @update_attrs %{value: "456.7", details: %{}, start_time: "2024-08-07T13:58:00Z", end_time: "2024-08-07T13:58:00Z", tags: ["option1"], measuring_scale: :duration} + @invalid_attrs %{value: nil, details: nil, start_time: nil, end_time: nil, tags: [], measuring_scale: nil} + + defp create_activity_record(_) do + activity_record = activity_record_fixture() + %{activity_record: activity_record} + end + + describe "Index" do + setup [:create_activity_record] + + test "lists all activity_records", %{conn: conn} do + {:ok, _index_live, html} = live(conn, ~p"/activity_records") + + assert html =~ "Listing Activity records" + end + + test "saves new activity_record", %{conn: conn} do + {:ok, index_live, _html} = live(conn, ~p"/activity_records") + + assert index_live |> element("a", "New Activity record") |> render_click() =~ + "New Activity record" + + assert_patch(index_live, ~p"/activity_records/new") + + assert index_live + |> form("#activity_record-form", activity_record: @invalid_attrs) + |> render_change() =~ "can't be blank" + + assert index_live + |> form("#activity_record-form", activity_record: @create_attrs) + |> render_submit() + + assert_patch(index_live, ~p"/activity_records") + + html = render(index_live) + assert html =~ "Activity record created successfully" + end + + test "updates activity_record in listing", %{conn: conn, activity_record: activity_record} do + {:ok, index_live, _html} = live(conn, ~p"/activity_records") + + assert index_live |> element("#activity_records-#{activity_record.id} a", "Edit") |> render_click() =~ + "Edit Activity record" + + assert_patch(index_live, ~p"/activity_records/#{activity_record}/edit") + + assert index_live + |> form("#activity_record-form", activity_record: @invalid_attrs) + |> render_change() =~ "can't be blank" + + assert index_live + |> form("#activity_record-form", activity_record: @update_attrs) + |> render_submit() + + assert_patch(index_live, ~p"/activity_records") + + html = render(index_live) + assert html =~ "Activity record updated successfully" + end + + test "deletes activity_record in listing", %{conn: conn, activity_record: activity_record} do + {:ok, index_live, _html} = live(conn, ~p"/activity_records") + + assert index_live |> element("#activity_records-#{activity_record.id} a", "Delete") |> render_click() + refute has_element?(index_live, "#activity_records-#{activity_record.id}") + end + end + + describe "Show" do + setup [:create_activity_record] + + test "displays activity_record", %{conn: conn, activity_record: activity_record} do + {:ok, _show_live, html} = live(conn, ~p"/activity_records/#{activity_record}") + + assert html =~ "Show Activity record" + end + + test "updates activity_record within modal", %{conn: conn, activity_record: activity_record} do + {:ok, show_live, _html} = live(conn, ~p"/activity_records/#{activity_record}") + + assert show_live |> element("a", "Edit") |> render_click() =~ + "Edit Activity record" + + assert_patch(show_live, ~p"/activity_records/#{activity_record}/show/edit") + + assert show_live + |> form("#activity_record-form", activity_record: @invalid_attrs) + |> render_change() =~ "can't be blank" + + assert show_live + |> form("#activity_record-form", activity_record: @update_attrs) + |> render_submit() + + assert_patch(show_live, ~p"/activity_records/#{activity_record}") + + html = render(show_live) + assert html =~ "Activity record updated successfully" + end + end +end diff --git a/test/support/fixtures/activities_fixtures.ex b/test/support/fixtures/activities_fixtures.ex new file mode 100644 index 0000000..b42c8d9 --- /dev/null +++ b/test/support/fixtures/activities_fixtures.ex @@ -0,0 +1,25 @@ +defmodule Mentat.ActivitiesFixtures do + @moduledoc """ + This module defines test helpers for creating + entities via the `Mentat.Activities` context. + """ + + @doc """ + Generate a activity_record. + """ + def activity_record_fixture(attrs \\ %{}) do + {:ok, activity_record} = + attrs + |> Enum.into(%{ + details: %{}, + end_time: ~U[2024-08-06 13:58:00Z], + measuring_scale: :duration, + start_time: ~U[2024-08-06 13:58:00Z], + tags: ["option1", "option2"], + value: "120.5" + }) + |> Mentat.Activities.create_activity_record() + + activity_record + end +end