Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add validation for ignores_time_zone field in FieldContent struct #13

Merged
merged 2 commits into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions lib/structs/field_content.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ defmodule ExPass.Structs.FieldContent do
* "PKDateStyleMedium"
* "PKDateStyleLong"
* "PKDateStyleFull"

- `ignores_time_zone`: A Boolean value that controls the time zone for the time and date to display in the field.
The default value is false, which displays the time and date using the current device's time zone.
If set to true, the time and date appear in the time zone associated with the date and time of value.
This key doesn't affect the pass relevance calculation.
"""

use TypedStruct
Expand Down Expand Up @@ -101,13 +106,14 @@ defmodule ExPass.Structs.FieldContent do
field :currency_code, String.t(), default: nil
field :data_detector_types, data_detector_types(), default: nil
field :date_style, date_style(), default: nil
field :ignores_time_zone, boolean(), default: nil
end

@doc """
Creates a new FieldContent struct.

This function initializes a new FieldContent struct with the given attributes.
It validates the `attributed_value`, `change_message`, `currency_code`, `data_detector_types`, and `date_style`.
It validates the `attributed_value`, `change_message`, `currency_code`, `data_detector_types`, `date_style`, and `ignores_time_zone`.

## Parameters

Expand All @@ -124,22 +130,22 @@ defmodule ExPass.Structs.FieldContent do
## Examples

iex> FieldContent.new(%{attributed_value: "Hello, World!"})
%FieldContent{attributed_value: "Hello, World!", change_message: nil, currency_code: nil, data_detector_types: nil, date_style: nil}
%FieldContent{attributed_value: "Hello, World!", change_message: nil, currency_code: nil, data_detector_types: nil, date_style: nil, ignores_time_zone: nil}

iex> FieldContent.new(%{attributed_value: 42, data_detector_types: ["PKDataDetectorTypePhoneNumber"], date_style: "PKDateStyleShort"})
%FieldContent{attributed_value: 42, change_message: nil, currency_code: nil, data_detector_types: ["PKDataDetectorTypePhoneNumber"], date_style: "PKDateStyleShort"}
iex> FieldContent.new(%{attributed_value: 42, data_detector_types: ["PKDataDetectorTypePhoneNumber"], date_style: "PKDateStyleShort", ignores_time_zone: true})
%FieldContent{attributed_value: 42, change_message: nil, currency_code: nil, data_detector_types: ["PKDataDetectorTypePhoneNumber"], date_style: "PKDateStyleShort", ignores_time_zone: true}

iex> datetime = DateTime.utc_now()
iex> field_content = FieldContent.new(%{attributed_value: datetime, currency_code: "USD", date_style: "PKDateStyleLong"})
iex> %FieldContent{attributed_value: ^datetime, currency_code: "USD", date_style: "PKDateStyleLong"} = field_content
iex> datetime = ~U[2023-04-15 14:30:00Z]
iex> field_content = FieldContent.new(%{attributed_value: datetime, currency_code: "USD", date_style: "PKDateStyleLong", ignores_time_zone: true})
iex> %FieldContent{attributed_value: ^datetime, currency_code: "USD", date_style: "PKDateStyleLong", ignores_time_zone: true} = field_content
iex> field_content.change_message
nil

iex> FieldContent.new(%{attributed_value: "<a href='http://example.com'>Click here</a>", data_detector_types: ["PKDataDetectorTypeLink"], date_style: "PKDateStyleFull"})
%FieldContent{attributed_value: "<a href='http://example.com'>Click here</a>", change_message: nil, currency_code: nil, data_detector_types: ["PKDataDetectorTypeLink"], date_style: "PKDateStyleFull"}
%FieldContent{attributed_value: "<a href='http://example.com'>Click here</a>", change_message: nil, currency_code: nil, data_detector_types: ["PKDataDetectorTypeLink"], date_style: "PKDateStyleFull", ignores_time_zone: nil}

iex> FieldContent.new(%{attributed_value: "No detectors", data_detector_types: []})
%FieldContent{attributed_value: "No detectors", change_message: nil, currency_code: nil, data_detector_types: [], date_style: nil}
iex> FieldContent.new(%{attributed_value: "No detectors", data_detector_types: [], change_message: "Updated to %@", ignores_time_zone: true})
%FieldContent{attributed_value: "No detectors", change_message: "Updated to %@", currency_code: nil, data_detector_types: [], date_style: nil, ignores_time_zone: true}
"""
@spec new(map()) :: %__MODULE__{}
def new(attrs \\ %{}) do
Expand All @@ -151,6 +157,7 @@ defmodule ExPass.Structs.FieldContent do
|> validate(:currency_code, &Validators.validate_currency_code/1)
|> validate(:data_detector_types, &Validators.validate_data_detector_types/1)
|> validate(:date_style, &Validators.validate_date_style/1)
|> validate(:ignores_time_zone, &Validators.validate_ignores_timezone/1)

struct!(__MODULE__, attrs)
end
Expand Down Expand Up @@ -186,6 +193,9 @@ defmodule ExPass.Structs.FieldContent do
:date_style ->
"Supported values are: PKDateStyleNone, PKDateStyleShort, PKDateStyleMedium, PKDateStyleLong, PKDateStyleFull"

:ignores_time_zone ->
"ignores_time_zone must be a boolean value (true or false)"

_ ->
""
end
Expand Down
30 changes: 30 additions & 0 deletions lib/utils/validators.ex
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,36 @@ defmodule ExPass.Utils.Validators do

def validate_date_style(_), do: {:error, "date_style must be a string"}

@doc """
Validates the ignores_time_zone field.

The ignores_time_zone must be a boolean value.

## Returns

* `:ok` if the value is a valid boolean or nil.
* `{:error, reason}` if the value is not valid, where reason is a string explaining the error.

## Examples

iex> validate_ignores_timezone(true)
:ok

iex> validate_ignores_timezone(false)
:ok

iex> validate_ignores_timezone(nil)
:ok

iex> validate_ignores_timezone("true")
{:error, "ignores_time_zone must be a boolean"}

"""
@spec validate_ignores_timezone(boolean() | nil) :: :ok | {:error, String.t()}
def validate_ignores_timezone(nil), do: :ok
def validate_ignores_timezone(value) when is_boolean(value), do: :ok
def validate_ignores_timezone(_), do: {:error, "ignores_time_zone must be a boolean"}

defp contains_unsupported_html_tags?(string) do
# Remove all valid anchor tags
string_without_anchors = String.replace(string, ~r{<a\s[^>]*>.*?</a>|<a\s[^>]*/>}, "")
Expand Down
29 changes: 29 additions & 0 deletions test/structs/field_content_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,33 @@ defmodule ExPass.Structs.FieldContentTest do
end
end
end

describe "ignores_time_zone" do
test "new/1 creates a valid FieldContent struct with ignores_time_zone set to true" do
result = FieldContent.new(%{ignores_time_zone: true})

assert %FieldContent{ignores_time_zone: true} = result
assert Jason.encode!(result) == ~s({"ignoresTimeZone":true})
end

test "new/1 creates a valid FieldContent struct with ignores_time_zone set to false" do
result = FieldContent.new(%{ignores_time_zone: false})

assert %FieldContent{ignores_time_zone: false} = result
assert Jason.encode!(result) == ~s({"ignoresTimeZone":false})
end

test "new/1 defaults to nil when ignores_time_zone is not provided" do
result = FieldContent.new(%{})

assert %FieldContent{ignores_time_zone: nil} = result
assert Jason.encode!(result) == ~s({})
end

test "new/1 raises ArgumentError when ignores_time_zone is not a boolean" do
assert_raise ArgumentError, ~r/ignores_time_zone must be a boolean/, fn ->
FieldContent.new(%{ignores_time_zone: "true"})
end
end
end
end