From 2b9ce8f64f2b1430e8f87d743f5dd36ae324d207 Mon Sep 17 00:00:00 2001 From: Leszek Witkowicz Date: Mon, 15 Jun 2020 15:15:46 +0200 Subject: [PATCH 1/6] first tries of property-based testing APIv3 --- mix.exs | 3 +- mix.lock | 1 + .../api_v3_notification_controller_test.exs | 54 +++++++++++++++ test/support/requests_generator.ex | 69 +++++++++++++++++++ 4 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 test/support/requests_generator.ex diff --git a/mix.exs b/mix.exs index 5834f6a2..d2dcab62 100644 --- a/mix.exs +++ b/mix.exs @@ -61,7 +61,8 @@ defmodule MongoosePush.Mixfile do {:telemetry, "~>0.4.1"}, {:telemetry_metrics, "~> 0.4.2"}, {:telemetry_metrics_prometheus_core, "~> 0.3"}, - {:logfmt, "~>3.3"} + {:logfmt, "~>3.3"}, + {:stream_data, "~> 0.5", only: [:test, :dev]} ] end diff --git a/mix.lock b/mix.lock index c1d28162..8ca59ee1 100644 --- a/mix.lock +++ b/mix.lock @@ -50,6 +50,7 @@ "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"}, "sparrow": {:git, "https://github.com/esl/sparrow.git", "b1896ca4fb0ca18369dd62de3d4c82f14f5bc66e", [ref: "b1896ca"]}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm", "13104d7897e38ed7f044c4de953a6c28597d1c952075eb2e328bc6d6f2bfc496"}, + "stream_data": {:hex, :stream_data, "0.5.0", "b27641e58941685c75b353577dc602c9d2c12292dd84babf506c2033cd97893e", [:mix], [], "hexpm", "012bd2eec069ada4db3411f9115ccafa38540a3c78c4c0349f151fc761b9e271"}, "telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm", "4738382e36a0a9a2b6e25d67c960e40e1a2c95560b9f936d8e29de8cd858480f"}, "telemetry_metrics": {:hex, :telemetry_metrics, "0.4.2", "1de986fad9aa6bf81f8a33ddfd16e5d8ab0dec6272e624eb517c1a92a44d41a9", [:mix], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e56ffed2dbe293ab6cf7c94980faeb368cb360662c1927f54fc634a4ca55362e"}, "telemetry_metrics_prometheus_core": {:hex, :telemetry_metrics_prometheus_core, "0.3.1", "742631c7c378973f01b4d321da2a44d69099a4b07a873913d8c39c67c0526ae6", [:mix], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.4", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "ecc05af84856f663ed3e5b8f56a8ad065745f1d185a731ca0f84b758fcca2f50"}, diff --git a/test/mongoose_push_web/controllers/api_v3_notification_controller_test.exs b/test/mongoose_push_web/controllers/api_v3_notification_controller_test.exs index 2f7869e6..99489bbe 100644 --- a/test/mongoose_push_web/controllers/api_v3_notification_controller_test.exs +++ b/test/mongoose_push_web/controllers/api_v3_notification_controller_test.exs @@ -1,7 +1,9 @@ defmodule MongoosePushWeb.APIv3NotificationControllerTest do alias MongoosePushWeb.Support.ControllersHelper + use ExUnitProperties use MongoosePushWeb.ConnCase, async: true import Mox + import RequestsGenerator setup :verify_on_exit! @@ -838,6 +840,19 @@ defmodule MongoosePushWeb.APIv3NotificationControllerTest do post_and_assert(conn, device_id, expected_device_id, request, expected_request) end + property "APIv3 notification decoder property-based test", %{conn: conn} do + check all( + mandatory <- mandatory_fields(), + optionals <- optional_fields(), + device_id <- nonempty_string() + ) do + request = Map.merge(mandatory, optionals, fn _k, v1, v2 -> Map.merge(v1, v2) end) + expected_device_id = device_id + expected_request = create_expected_request(request) + post_and_assert(conn, device_id, expected_device_id, request, expected_request) + end + end + defp post_and_assert(conn, device_id, expected_device_id, request, expected_request) do expect(MongoosePush.Notification.MockImpl, :push, fn device_id, request -> assert request == expected_request @@ -860,4 +875,43 @@ defmodule MongoosePushWeb.APIv3NotificationControllerTest do assert json_response(conn, number) == %{"reason" => to_string(error_reason)} end + + defp create_expected_request(request) do + %{ + alert: fetch_alert(request["alert"]), + data: request["data"], + mode: fetch_enum_field(request["mode"]), + service: fetch_enum_field(request["service"]), + priority: fetch_enum_field(request["priority"]), + mutable_content: fetch_mutable_content(request["mutable_content"]), + tags: request["tags"], + topic: request["topic"], + time_to_live: request["time_to_live"] + } + |> drop_nil_values() + end + + defp fetch_alert(alert) do + %{ + body: alert["body"], + title: alert["title"], + badge: alert["badge"], + click_action: alert["click_action"], + tag: alert["tag"], + sound: alert["sound"] + } + |> drop_nil_values() + end + + defp fetch_enum_field(nil), do: nil + defp fetch_enum_field(string), do: String.to_existing_atom(string) + + defp fetch_mutable_content(nil), do: false + defp fetch_mutable_content(val), do: val + + defp drop_nil_values(map) do + map + |> Enum.filter(fn {_, v} -> v != nil end) + |> Map.new() + end end diff --git a/test/support/requests_generator.ex b/test/support/requests_generator.ex new file mode 100644 index 00000000..18899a67 --- /dev/null +++ b/test/support/requests_generator.ex @@ -0,0 +1,69 @@ +defmodule RequestsGenerator do + # basic types + def nonempty_string() do + StreamData.string(:alphanumeric) |> StreamData.filter(fn x -> String.length(x) > 0 end) + end + + def positive_integer() do + StreamData.positive_integer() + end + + def boolean() do + StreamData.one_of([false, true]) + end + + def tags_type() do + StreamData.list_of(nonempty_string(), min_length: 1, max_length: 5) + end + + def priority_type() do + one_of_strings([:normal, :high]) + end + + def service_type() do + one_of_strings([:apns, :fcm]) + end + + def mode_type() do + one_of_strings([:prod, :dev]) + end + + def data_type() do + StreamData.map_of(StreamData.string(:ascii), StreamData.string(:ascii)) + end + + # requests creation + def mandatory_fields() do + StreamData.fixed_map(%{ + "alert" => + StreamData.fixed_map(%{ + "title" => nonempty_string(), + "body" => nonempty_string() + }), + "service" => one_of_strings([:apns, :fcm]) + }) + end + + def optional_fields() do + StreamData.optional_map(%{ + "alert" => + StreamData.optional_map(%{ + "badge" => positive_integer(), + "click_action" => nonempty_string(), + "tag" => nonempty_string(), + "sound" => nonempty_string() + }), + "data" => data_type(), + "mode" => mode_type(), + "priority" => priority_type(), + "mutable_content" => boolean(), + "tags" => tags_type(), + "topic" => nonempty_string(), + "time_to_live" => positive_integer() + }) + end + + defp one_of_strings(list) do + StreamData.map(StreamData.one_of(list), &Kernel.to_string/1) + end +end From fa41ada27a4e68b1173e689688545585e4de9ae1 Mon Sep 17 00:00:00 2001 From: Leszek Witkowicz Date: Mon, 15 Jun 2020 17:27:04 +0200 Subject: [PATCH 2/6] improve requests handling in CastAndValidate plug --- lib/mongoose_push_web/plugs/cast_and_validate.ex | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/mongoose_push_web/plugs/cast_and_validate.ex b/lib/mongoose_push_web/plugs/cast_and_validate.ex index c94bd889..f8b9b918 100644 --- a/lib/mongoose_push_web/plugs/cast_and_validate.ex +++ b/lib/mongoose_push_web/plugs/cast_and_validate.ex @@ -34,6 +34,19 @@ defmodule MongoosePushWeb.Plug.CastAndValidate do # "Failed to cast value to one of: [] (no schemas provided)", instead of something more meaningful. # Here we avoid it by manual modification of the pattern the request is matched against, # so the framework can serve us as expected. + defp update_schema_and_do_call( + conn = %{params: %{"alert" => _, "data" => _}}, + opts = %{operation_id: operation_id} + ) do + new_schema = %OpenApiSpex.Reference{ + "$ref": "#/components/schemas/Request.SendNotification.Deep.MixedNotification" + } + + conn + |> update_schema(operation_id, new_schema) + |> OpenApiSpex.Plug.CastAndValidate.call(opts) + end + defp update_schema_and_do_call( conn = %{params: %{"data" => _}}, opts = %{operation_id: operation_id} From 9b96db4071c0cd61cfd4e1b86c4bfd9dd58feb2f Mon Sep 17 00:00:00 2001 From: Leszek Witkowicz Date: Mon, 15 Jun 2020 17:41:40 +0200 Subject: [PATCH 3/6] cover missing field scenario; upgrade missing field response stub --- .../api_v1_notification_controller_test.exs | 4 +-- .../api_v2_notification_controller_test.exs | 12 +++---- .../api_v3_notification_controller_test.exs | 35 +++++++++++++++---- test/support/controllers_helper.ex | 14 +++++++- test/support/requests_generator.ex | 4 +++ 5 files changed, 54 insertions(+), 15 deletions(-) diff --git a/test/mongoose_push_web/controllers/api_v1_notification_controller_test.exs b/test/mongoose_push_web/controllers/api_v1_notification_controller_test.exs index 8456e56e..573ff471 100644 --- a/test/mongoose_push_web/controllers/api_v1_notification_controller_test.exs +++ b/test/mongoose_push_web/controllers/api_v1_notification_controller_test.exs @@ -27,7 +27,7 @@ defmodule MongoosePushWeb.APIv1NotificationControllerTest do Jason.encode!(Map.drop(ControllersHelper.flat_request(), ["service"])) ) - assert json_response(conn, 422) == ControllersHelper.missing_field_response("service") + assert json_response(conn, 422) == ControllersHelper.missing_field_response(:v1, "service") end test "Request.SendNotification.FlatNotification schema without required body field", %{ @@ -40,7 +40,7 @@ defmodule MongoosePushWeb.APIv1NotificationControllerTest do Jason.encode!(Map.drop(ControllersHelper.flat_request(), ["body"])) ) - assert json_response(conn, 422) == ControllersHelper.missing_field_response("body") + assert json_response(conn, 422) == ControllersHelper.missing_field_response(:v1, "body") end test "Request.SendNotification.FlatNotification schema with incorrect badge value", %{ diff --git a/test/mongoose_push_web/controllers/api_v2_notification_controller_test.exs b/test/mongoose_push_web/controllers/api_v2_notification_controller_test.exs index d83a2016..dbf1f1e9 100644 --- a/test/mongoose_push_web/controllers/api_v2_notification_controller_test.exs +++ b/test/mongoose_push_web/controllers/api_v2_notification_controller_test.exs @@ -27,7 +27,7 @@ defmodule MongoosePushWeb.APIv2NotificationControllerTest do Jason.encode!(Map.drop(ControllersHelper.alert_request(), ["service"])) ) - assert json_response(conn, 422) == ControllersHelper.missing_field_response("service") + assert json_response(conn, 422) == ControllersHelper.missing_field_response(:v2, "service") end test "Request.SendNotification.Deep.AlertNotification schema without required alert field", %{ @@ -40,7 +40,7 @@ defmodule MongoosePushWeb.APIv2NotificationControllerTest do Jason.encode!(Map.drop(ControllersHelper.alert_request(), ["alert"])) ) - assert json_response(conn, 422) == ControllersHelper.missing_field_response("alert") + assert json_response(conn, 422) == ControllersHelper.missing_field_response(:v2, "alert") end test "Request.SendNotification.Deep.AlertNotification schema with incorrect priority value", %{ @@ -92,7 +92,7 @@ defmodule MongoosePushWeb.APIv2NotificationControllerTest do Jason.encode!(Map.drop(ControllersHelper.silent_request(), ["service"])) ) - assert json_response(conn, 422) == ControllersHelper.missing_field_response("service") + assert json_response(conn, 422) == ControllersHelper.missing_field_response(:v2, "service") end test "Request.SendNotification.Deep.SilentNotification schema without required data field", %{ @@ -105,7 +105,7 @@ defmodule MongoosePushWeb.APIv2NotificationControllerTest do Jason.encode!(Map.drop(ControllersHelper.silent_request(), ["data"])) ) - assert json_response(conn, 422) == ControllersHelper.missing_field_response("alert") + assert json_response(conn, 422) == ControllersHelper.missing_field_response(:v2, "alert") end test "Request.SendNotification.Deep.SilentNotification schema with incorrect time_to_live value", @@ -148,8 +148,8 @@ defmodule MongoosePushWeb.APIv2NotificationControllerTest do assert json_response(conn, 422) == Map.merge( - ControllersHelper.missing_field_response("service"), - ControllersHelper.missing_field_response("alert"), + ControllersHelper.missing_field_response(:v2, "service"), + ControllersHelper.missing_field_response(:v2, "alert"), fn _k, v1, v2 -> v1 ++ v2 end ) end diff --git a/test/mongoose_push_web/controllers/api_v3_notification_controller_test.exs b/test/mongoose_push_web/controllers/api_v3_notification_controller_test.exs index 99489bbe..19d71741 100644 --- a/test/mongoose_push_web/controllers/api_v3_notification_controller_test.exs +++ b/test/mongoose_push_web/controllers/api_v3_notification_controller_test.exs @@ -29,7 +29,7 @@ defmodule MongoosePushWeb.APIv3NotificationControllerTest do Jason.encode!(Map.drop(ControllersHelper.alert_request(), ["service"])) ) - assert json_response(conn, 422) == ControllersHelper.missing_field_response("service") + assert json_response(conn, 422) == ControllersHelper.missing_field_response(:v3, "service") end test "Request.SendNotification.Deep.AlertNotification schema without required alert field", %{ @@ -42,7 +42,7 @@ defmodule MongoosePushWeb.APIv3NotificationControllerTest do Jason.encode!(Map.drop(ControllersHelper.alert_request(), ["alert"])) ) - assert json_response(conn, 422) == ControllersHelper.missing_field_response("alert") + assert json_response(conn, 422) == ControllersHelper.missing_field_response(:v3, "alert") end test "Request.SendNotification.Deep.AlertNotification schema with incorrect priority value", %{ @@ -94,7 +94,7 @@ defmodule MongoosePushWeb.APIv3NotificationControllerTest do Jason.encode!(Map.drop(ControllersHelper.silent_request(), ["service"])) ) - assert json_response(conn, 422) == ControllersHelper.missing_field_response("service") + assert json_response(conn, 422) == ControllersHelper.missing_field_response(:v3, "service") end test "Request.SendNotification.Deep.SilentNotification schema without required data field", %{ @@ -107,7 +107,7 @@ defmodule MongoosePushWeb.APIv3NotificationControllerTest do Jason.encode!(Map.drop(ControllersHelper.silent_request(), ["data"])) ) - assert json_response(conn, 422) == ControllersHelper.missing_field_response("alert") + assert json_response(conn, 422) == ControllersHelper.missing_field_response(:v3, "alert") end test "Request.SendNotification.Deep.SilentNotification schema with incorrect time_to_live value", @@ -150,8 +150,8 @@ defmodule MongoosePushWeb.APIv3NotificationControllerTest do assert json_response(conn, 422) == Map.merge( - ControllersHelper.missing_field_response("service"), - ControllersHelper.missing_field_response("alert"), + ControllersHelper.missing_field_response(:v3, "service"), + ControllersHelper.missing_field_response(:v3, "alert"), fn _k, v1, v2 -> v1 ++ v2 end ) end @@ -853,6 +853,21 @@ defmodule MongoosePushWeb.APIv3NotificationControllerTest do end end + property "APIv3 notification with dropped mandatory field", %{conn: conn} do + check all( + mandatory <- mandatory_fields(), + optionals <- optional_fields(), + dropped <- mandatory_field() + ) do + request = + Map.merge(mandatory, optionals, fn _k, v1, v2 -> Map.merge(v1, v2) end) + |> drop_field(dropped) + + conn = post(conn, "/v3/notification/123456", Jason.encode!(request)) + assert json_response(conn, 422) == ControllersHelper.missing_field_response(:v3, dropped) + end + end + defp post_and_assert(conn, device_id, expected_device_id, request, expected_request) do expect(MongoosePush.Notification.MockImpl, :push, fn device_id, request -> assert request == expected_request @@ -914,4 +929,12 @@ defmodule MongoosePushWeb.APIv3NotificationControllerTest do |> Enum.filter(fn {_, v} -> v != nil end) |> Map.new() end + + defp drop_field(map, field) when field in ["body", "title"] do + Kernel.update_in(map, ["alert"], fn _ -> Map.drop(map["alert"], [field]) end) + end + + defp drop_field(map, field) do + Map.drop(map, [field]) + end end diff --git a/test/support/controllers_helper.ex b/test/support/controllers_helper.ex index efe8a2c6..28f28134 100644 --- a/test/support/controllers_helper.ex +++ b/test/support/controllers_helper.ex @@ -66,7 +66,19 @@ defmodule MongoosePushWeb.Support.ControllersHelper do } end - def missing_field_response(field) do + def missing_field_response(api, field) when api in [:v2, :v3] and field in ["body", "title"] do + %{ + "errors" => [ + %{ + "message" => "Missing field: #{field}", + "source" => %{"pointer" => "/alert/#{field}"}, + "title" => "Invalid value" + } + ] + } + end + + def missing_field_response(_api, field) do %{ "errors" => [ %{ diff --git a/test/support/requests_generator.ex b/test/support/requests_generator.ex index 18899a67..17872370 100644 --- a/test/support/requests_generator.ex +++ b/test/support/requests_generator.ex @@ -44,6 +44,10 @@ defmodule RequestsGenerator do }) end + def mandatory_field() do + one_of_strings([:service, :title, :body]) + end + def optional_fields() do StreamData.optional_map(%{ "alert" => From aa548edf124b3c5a0aec98c7e1beafea0c128042 Mon Sep 17 00:00:00 2001 From: Leszek Witkowicz Date: Tue, 16 Jun 2020 13:02:46 +0200 Subject: [PATCH 4/6] refactor RequestsGenerator; remove stream_data dep from dev --- mix.exs | 2 +- .../api_v3_notification_controller_test.exs | 19 ++-- test/support/requests_generator.ex | 96 ++++++++++--------- 3 files changed, 61 insertions(+), 56 deletions(-) diff --git a/mix.exs b/mix.exs index d2dcab62..de5d176d 100644 --- a/mix.exs +++ b/mix.exs @@ -62,7 +62,7 @@ defmodule MongoosePush.Mixfile do {:telemetry_metrics, "~> 0.4.2"}, {:telemetry_metrics_prometheus_core, "~> 0.3"}, {:logfmt, "~>3.3"}, - {:stream_data, "~> 0.5", only: [:test, :dev]} + {:stream_data, "~> 0.5", only: :test} ] end diff --git a/test/mongoose_push_web/controllers/api_v3_notification_controller_test.exs b/test/mongoose_push_web/controllers/api_v3_notification_controller_test.exs index 19d71741..3b6e7fe9 100644 --- a/test/mongoose_push_web/controllers/api_v3_notification_controller_test.exs +++ b/test/mongoose_push_web/controllers/api_v3_notification_controller_test.exs @@ -1,9 +1,9 @@ defmodule MongoosePushWeb.APIv3NotificationControllerTest do alias MongoosePushWeb.Support.ControllersHelper + alias MongoosePushWeb.Support.RequestsGenerator use ExUnitProperties use MongoosePushWeb.ConnCase, async: true import Mox - import RequestsGenerator setup :verify_on_exit! @@ -842,9 +842,9 @@ defmodule MongoosePushWeb.APIv3NotificationControllerTest do property "APIv3 notification decoder property-based test", %{conn: conn} do check all( - mandatory <- mandatory_fields(), - optionals <- optional_fields(), - device_id <- nonempty_string() + mandatory <- RequestsGenerator.mandatory_fields(), + optionals <- RequestsGenerator.optional_fields(), + device_id <- RequestsGenerator.device_id() ) do request = Map.merge(mandatory, optionals, fn _k, v1, v2 -> Map.merge(v1, v2) end) expected_device_id = device_id @@ -853,17 +853,18 @@ defmodule MongoosePushWeb.APIv3NotificationControllerTest do end end - property "APIv3 notification with dropped mandatory field", %{conn: conn} do + property "APIv3 notification with dropped one mandatory field", %{conn: conn} do check all( - mandatory <- mandatory_fields(), - optionals <- optional_fields(), - dropped <- mandatory_field() + mandatory <- RequestsGenerator.mandatory_fields(), + optionals <- RequestsGenerator.optional_fields(), + device_id <- RequestsGenerator.device_id(), + dropped <- RequestsGenerator.mandatory_field() ) do request = Map.merge(mandatory, optionals, fn _k, v1, v2 -> Map.merge(v1, v2) end) |> drop_field(dropped) - conn = post(conn, "/v3/notification/123456", Jason.encode!(request)) + conn = post(conn, "/v3/notification/#{device_id}", Jason.encode!(request)) assert json_response(conn, 422) == ControllersHelper.missing_field_response(:v3, dropped) end end diff --git a/test/support/requests_generator.ex b/test/support/requests_generator.ex index 17872370..c6ecbb60 100644 --- a/test/support/requests_generator.ex +++ b/test/support/requests_generator.ex @@ -1,38 +1,5 @@ -defmodule RequestsGenerator do - # basic types - def nonempty_string() do - StreamData.string(:alphanumeric) |> StreamData.filter(fn x -> String.length(x) > 0 end) - end - - def positive_integer() do - StreamData.positive_integer() - end - - def boolean() do - StreamData.one_of([false, true]) - end - - def tags_type() do - StreamData.list_of(nonempty_string(), min_length: 1, max_length: 5) - end - - def priority_type() do - one_of_strings([:normal, :high]) - end - - def service_type() do - one_of_strings([:apns, :fcm]) - end - - def mode_type() do - one_of_strings([:prod, :dev]) - end - - def data_type() do - StreamData.map_of(StreamData.string(:ascii), StreamData.string(:ascii)) - end - - # requests creation +defmodule MongoosePushWeb.Support.RequestsGenerator do + # APIv2/3 requests def mandatory_fields() do StreamData.fixed_map(%{ "alert" => @@ -40,14 +7,10 @@ defmodule RequestsGenerator do "title" => nonempty_string(), "body" => nonempty_string() }), - "service" => one_of_strings([:apns, :fcm]) + "service" => service() }) end - def mandatory_field() do - one_of_strings([:service, :title, :body]) - end - def optional_fields() do StreamData.optional_map(%{ "alert" => @@ -57,17 +20,58 @@ defmodule RequestsGenerator do "tag" => nonempty_string(), "sound" => nonempty_string() }), - "data" => data_type(), - "mode" => mode_type(), - "priority" => priority_type(), + "data" => data(), + "mode" => mode(), + "priority" => priority(), "mutable_content" => boolean(), - "tags" => tags_type(), + "tags" => tags(), "topic" => nonempty_string(), "time_to_live" => positive_integer() }) end - defp one_of_strings(list) do - StreamData.map(StreamData.one_of(list), &Kernel.to_string/1) + def device_id() do + nonempty_string() + end + + def mandatory_field() do + one_of_strings([:service, :title, :body]) + end + + # basic types + defp nonempty_string() do + StreamData.string(:alphanumeric) |> StreamData.filter(fn x -> String.length(x) > 0 end) + end + + defp positive_integer() do + StreamData.positive_integer() + end + + defp boolean() do + StreamData.one_of([false, true]) + end + + defp tags() do + StreamData.list_of(nonempty_string(), min_length: 1, max_length: 5) + end + + defp priority() do + one_of_strings([:normal, :high]) + end + + defp service() do + one_of_strings([:apns, :fcm]) + end + + defp mode() do + one_of_strings([:prod, :dev]) + end + + defp data() do + StreamData.map_of(StreamData.string(:ascii), StreamData.string(:ascii)) + end + + defp one_of_strings(list_of_atoms) do + StreamData.map(StreamData.one_of(list_of_atoms), &Kernel.to_string/1) end end From 9dc7815001357924e706a8a5cf9043024863ca11 Mon Sep 17 00:00:00 2001 From: Leszek Witkowicz Date: Fri, 19 Jun 2020 18:01:14 +0200 Subject: [PATCH 5/6] ignore StreamData by dialyzer; #makeCircleCIGreenAgain --- .dialyzer_ignore.exs | 1 + 1 file changed, 1 insertion(+) diff --git a/.dialyzer_ignore.exs b/.dialyzer_ignore.exs index 22c16706..15db899e 100644 --- a/.dialyzer_ignore.exs +++ b/.dialyzer_ignore.exs @@ -7,5 +7,6 @@ ~r/Function :asn1ct.compile\/2 does not exist/, ~r/lib\/mix\//, ~r/test\/support\/mix\//, + ~r/test\/support\/requests_generator\.ex/, {"test/support/api.ex"} ] From 739325122cb1c8957baf0f6d87030f7787ab3f29 Mon Sep 17 00:00:00 2001 From: Leszek Witkowicz Date: Fri, 19 Jun 2020 18:10:54 +0200 Subject: [PATCH 6/6] apply PR remarks --- test/support/requests_generator.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/support/requests_generator.ex b/test/support/requests_generator.ex index c6ecbb60..d16c3254 100644 --- a/test/support/requests_generator.ex +++ b/test/support/requests_generator.ex @@ -40,7 +40,7 @@ defmodule MongoosePushWeb.Support.RequestsGenerator do # basic types defp nonempty_string() do - StreamData.string(:alphanumeric) |> StreamData.filter(fn x -> String.length(x) > 0 end) + StreamData.string(:alphanumeric, min_length: 1) end defp positive_integer() do