From f457235b75932e87bb146717687a0eb32035da27 Mon Sep 17 00:00:00 2001 From: Kieran Eglin Date: Wed, 14 Aug 2024 13:53:17 -0700 Subject: [PATCH] Added validation for min/max amounts --- lib/pinchflat/sources/source.ex | 12 ++++++++ .../sources/source_html/source_form.html.heex | 2 ++ test/pinchflat/sources_test.exs | 28 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/lib/pinchflat/sources/source.ex b/lib/pinchflat/sources/source.ex index 1e0dfee..99ff2d4 100644 --- a/lib/pinchflat/sources/source.ex +++ b/lib/pinchflat/sources/source.ex @@ -123,6 +123,7 @@ defmodule Pinchflat.Sources.Source do |> dynamic_default(:uuid, fn _ -> Ecto.UUID.generate() end) |> validate_required(required_fields) |> validate_title_regex() + |> validate_min_and_max_durations() |> validate_number(:retention_period_days, greater_than_or_equal_to: 0) # Ensures it ends with `.{{ ext }}` or `.%(ext)s` or similar (with a little wiggle room) |> validate_format(:output_path_template_override, MediaProfile.ext_regex(), message: "must end with .{{ ext }}") @@ -169,6 +170,17 @@ defmodule Pinchflat.Sources.Source do defp validate_title_regex(changeset), do: changeset + defp validate_min_and_max_durations(changeset) do + min_duration = get_change(changeset, :min_duration_seconds) + max_duration = get_change(changeset, :max_duration_seconds) + + case {min_duration, max_duration} do + {min, max} when is_nil(min) or is_nil(max) -> changeset + {min, max} when min >= max -> add_error(changeset, :max_duration_seconds, "must be greater than minumum duration") + _ -> changeset + end + end + defimpl Jason.Encoder, for: Source do def encode(value, opts) do value diff --git a/lib/pinchflat_web/controllers/sources/source_html/source_form.html.heex b/lib/pinchflat_web/controllers/sources/source_html/source_form.html.heex index 759d92b..a530fe6 100644 --- a/lib/pinchflat_web/controllers/sources/source_html/source_form.html.heex +++ b/lib/pinchflat_web/controllers/sources/source_html/source_form.html.heex @@ -125,6 +125,7 @@ field={f[:min_duration_seconds]} type="number" label="Minimum Duration (seconds)" + min="0" help="Minimum duration of the media to be downloaded. Can be blank" /> @@ -132,6 +133,7 @@ field={f[:max_duration_seconds]} type="number" label="Maximum Duration (seconds)" + min="0" help="Maximum duration of the media to be downloaded. Can be blank" /> diff --git a/test/pinchflat/sources_test.exs b/test/pinchflat/sources_test.exs index 662d697..cc8a63e 100644 --- a/test/pinchflat/sources_test.exs +++ b/test/pinchflat/sources_test.exs @@ -681,6 +681,34 @@ defmodule Pinchflat.SourcesTest do end end + describe "change_source/3 when testing min/max duration validations" do + test "succeeds if min and max are nil" do + source = source_fixture() + + assert %{errors: []} = Sources.change_source(source, %{min_duration_seconds: nil, max_duration_seconds: nil}) + end + + test "succeeds if either min or max is nil" do + source = source_fixture() + + assert %{errors: []} = Sources.change_source(source, %{min_duration_seconds: nil, max_duration_seconds: 100}) + assert %{errors: []} = Sources.change_source(source, %{min_duration_seconds: 100, max_duration_seconds: nil}) + end + + test "succeeds if min is less than max" do + source = source_fixture() + + assert %{errors: []} = Sources.change_source(source, %{min_duration_seconds: 100, max_duration_seconds: 200}) + end + + test "fails if min is greater than or equal to max" do + source = source_fixture() + + assert %{errors: [_]} = Sources.change_source(source, %{min_duration_seconds: 200, max_duration_seconds: 100}) + assert %{errors: [_]} = Sources.change_source(source, %{min_duration_seconds: 100, max_duration_seconds: 100}) + end + end + describe "change_source/3 when testing original_url validation" do test "succeeds when an original URL is valid" do source = source_fixture()