Skip to content
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
2 changes: 2 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import Config

config :kickplan, :base_url, "https://demo-control.fly.dev/api"

if File.exists?("config/config.secret.exs") do
import_config "config.secret.exs"
end
22 changes: 22 additions & 0 deletions lib/kickplan/requests/metrics/set.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
defmodule Kickplan.Requests.Metrics.Set do
@moduledoc """
TODO
"""

@options NimbleOptions.new!(
key: [
type: :string,
required: true
],
value: [
type: {:or, [:float, :integer]},
required: true
],
account_key: [type: :string],
idempotency_key: [type: :string],
time: [type: :any]
)

@doc false
def options, do: @options
end
30 changes: 30 additions & 0 deletions lib/kickplan/resource/metrics.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
defmodule Kickplan.Metrics do
@moduledoc """
TODO
"""

alias Kickplan.{Client, Requests}

@doc """
TODO
"""
def flush do
with {:ok, resp} <- Client.post("metrics/flush") do
{:ok, resp.success?}
end
end

@doc """
TODO
"""
def set(opts \\ %{}) do
with {:ok, params} <- validate(opts, Requests.Metrics.Set),
{:ok, resp} <- Client.post("metrics/set", params) do
{:ok, resp.success?}
end
end

defp validate(opts, request) do
NimbleOptions.validate(opts, request.options())
end
end
2 changes: 2 additions & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ defmodule Kickplan.MixProject do

defp deps do
[
{:exvcr, "~> 0.11", only: :test},
{:finch, "~> 0.6", optional: true},
{:hackney, "~> 1.9", optional: true},
{:jason, "~> 1.0", optional: true},
Expand All @@ -36,6 +37,7 @@ defmodule Kickplan.MixProject do
{:ex_doc, ">= 0.0.0", only: [:dev], runtime: false},
{:gettext, ">= 0.0.0", only: [:dev], runtime: false},
{:mix_audit, ">= 0.0.0", only: [:dev], runtime: false},
{:nimble_options, "~> 1.1.0"},
{:sobelow, ">= 0.0.0", only: [:dev], runtime: false}
]
end
Expand Down
5 changes: 5 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,21 @@
"ex_check": {:hex, :ex_check, "0.14.0", "d6fbe0bcc51cf38fea276f5bc2af0c9ae0a2bb059f602f8de88709421dae4f0e", [:mix], [], "hexpm", "8a602e98c66e6a4be3a639321f1f545292042f290f91fa942a285888c6868af0"},
"ex_doc": {:hex, :ex_doc, "0.34.2", "13eedf3844ccdce25cfd837b99bea9ad92c4e511233199440488d217c92571e8", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "5ce5f16b41208a50106afed3de6a2ed34f4acfd65715b82a0b84b49d995f95c1"},
"expo": {:hex, :expo, "1.0.0", "647639267e088717232f4d4451526e7a9de31a3402af7fcbda09b27e9a10395a", [:mix], [], "hexpm", "18d2093d344d97678e8a331ca0391e85d29816f9664a25653fd7e6166827827c"},
"exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], [], "hexpm", "1222419f706e01bfa1095aec9acf6421367dcfab798a6f67c54cf784733cd6b5"},
"exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm", "32e95820a97cffea67830e91514a2ad53b888850442d6d395f53a1ac60c82e07"},
"exvcr": {:hex, :exvcr, "0.15.1", "772db4d065f5136c6a984c302799a79e4ade3e52701c95425fa2229dd6426886", [:mix], [{:exactor, "~> 2.2", [hex: :exactor, repo: "hexpm", optional: false]}, {:exjsx, "~> 4.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:finch, "~> 0.16", [hex: :finch, repo: "hexpm", optional: true]}, {:httpoison, "~> 1.0 or ~> 2.0", [hex: :httpoison, repo: "hexpm", optional: true]}, {:httpotion, "~> 3.1", [hex: :httpotion, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:meck, "~> 0.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "de4fc18b1d672d9b72bc7468735e19779aa50ea963a1f859ef82cd9e294b13e3"},
"file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"},
"finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"},
"gettext": {:hex, :gettext, "0.26.1", "38e14ea5dcf962d1fc9f361b63ea07c0ce715a8ef1f9e82d3dfb8e67e0416715", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "01ce56f188b9dc28780a52783d6529ad2bc7124f9744e571e1ee4ea88bf08734"},
"hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
"hpax": {:hex, :hpax, "0.2.0", "5a58219adcb75977b2edce5eb22051de9362f08236220c9e859a47111c194ff5", [:mix], [], "hexpm", "bea06558cdae85bed075e6c036993d43cd54d447f76d8190a8db0dc5893fa2f1"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
"jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm", "fc3499fed7a726995aa659143a248534adc754ebd16ccd437cd93b649a95091f"},
"makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"},
"makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"},
"meck": {:hex, :meck, "0.9.2", "85ccbab053f1db86c7ca240e9fc718170ee5bda03810a6292b5306bf31bae5f5", [:rebar3], [], "hexpm", "81344f561357dc40a8344afa53767c32669153355b626ea9fcbc8da6b3045826"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
"mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"},
Expand Down
34 changes: 34 additions & 0 deletions test/cassettes/features/resolve-all.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[
{
"request": {
"options": {
"with_body": "true"
},
"body": "{}",
"url": "https://demo-control.fly.dev/api/features/",
"headers": {
"Authorization": "***",
"Content-Type": "application/json",
"User-Agent": "Kickplan/0.1.0 (sdk-elixir)"
},
"method": "post",
"request_body": ""
},
"response": {
"binary": false,
"type": "ok",
"body": "[{\"value\":false,\"key\":\"upload-contacts\"},{\"value\":false,\"key\":\"ai-llm-generation\"},{\"value\":false,\"key\":\"fancy\"},{\"value\":\"{\\n \\\"Currency\\\": \\\"US Dollar (USD)\\\",\\n \\\"Allowed Payment Gateways\\\": [\\\"PayPal\\\", \\\"Stripe\\\", \\\"Square\\\"]\\n }\",\"key\":\"payment-configuration\"},{\"value\":0,\"key\":\"contact-limit\"}]",
"headers": {
"cache-control": "max-age=0, private, must-revalidate",
"content-length": "308",
"content-type": "application/json; charset=utf-8",
"date": "Thu, 22 Aug 2024 19:19:14 GMT",
"server": "Fly/5e55b43a7 (2024-08-21)",
"x-request-id": "F-4jJk91UgTYSXkAAAyB",
"via": "1.1 fly.io",
"fly-request-id": "01J5XREQJRTKHBC3Y5CJQAPDYK-sea"
},
"status_code": 200
}
}
]
34 changes: 34 additions & 0 deletions test/cassettes/features/resolve.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[
{
"request": {
"options": {
"with_body": "true"
},
"body": "{}",
"url": "https://demo-control.fly.dev/api/features/contact-limit",
"headers": {
"Authorization": "***",
"Content-Type": "application/json",
"User-Agent": "Kickplan/0.1.0 (sdk-elixir)"
},
"method": "post",
"request_body": ""
},
"response": {
"binary": false,
"type": "ok",
"body": "{\"value\":0,\"key\":\"contact-limit\"}",
"headers": {
"cache-control": "max-age=0, private, must-revalidate",
"content-length": "33",
"content-type": "application/json; charset=utf-8",
"date": "Thu, 22 Aug 2024 19:43:57 GMT",
"server": "Fly/5e55b43a7 (2024-08-21)",
"x-request-id": "F-4kf6KMXpujMxwAAAyx",
"via": "1.1 fly.io",
"fly-request-id": "01J5XSVZZEBDC5XTBGR0QKYXXJ-sea"
},
"status_code": 200
}
}
]
33 changes: 33 additions & 0 deletions test/cassettes/metrics/flush.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[
{
"request": {
"options": {
"with_body": "true"
},
"body": "{}",
"url": "https://demo-control.fly.dev/api/metrics/flush",
"headers": {
"Authorization": "***",
"Content-Type": "application/json",
"User-Agent": "Kickplan/0.1.0 (sdk-elixir)"
},
"method": "post",
"request_body": ""
},
"response": {
"binary": false,
"type": "ok",
"body": "",
"headers": {
"cache-control": "max-age=0, private, must-revalidate",
"date": "Thu, 22 Aug 2024 22:37:26 GMT",
"server": "Fly/5e55b43a7 (2024-08-21)",
"x-request-id": "F-4t9xPC0bL6wOQAAA0B",
"via": "1.1 fly.io",
"fly-request-id": "01J5Y3SMMC67WZPQJYTVY1ZVP0-sea",
"content-length": "0"
},
"status_code": 202
}
}
]
33 changes: 33 additions & 0 deletions test/cassettes/metrics/set.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[
{
"request": {
"options": {
"with_body": "true"
},
"body": "{\"value\":3,\"time\":\"2024-08-22T21:40:19.923716Z\",\"key\":\"sdk_elixir_test\",\"account_key\":\"9a592f57-6da0-408e-99e7-8918b48a7dbe\",\"idempotency_key\":\"004b7f07-71fd-4ea5-a43c-dcde2516305b\"}",
"url": "https://demo-control.fly.dev/api/metrics/set",
"headers": {
"Authorization": "***",
"Content-Type": "application/json",
"User-Agent": "Kickplan/0.1.0 (sdk-elixir)"
},
"method": "post",
"request_body": ""
},
"response": {
"binary": false,
"type": "ok",
"body": "",
"headers": {
"cache-control": "max-age=0, private, must-revalidate",
"date": "Thu, 22 Aug 2024 21:40:19 GMT",
"server": "Fly/5e55b43a7 (2024-08-21)",
"x-request-id": "F-4q2U-SUX7DPj0AAAzx",
"via": "1.1 fly.io",
"fly-request-id": "01J5Y0H2HYJAJ2PJVFS2D0TM7A-sea",
"content-length": "0"
},
"status_code": 202
}
}
]
28 changes: 28 additions & 0 deletions test/kickplan/resource/features_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
defmodule Kickplan.FeaturesTest do
use Kickplan.VCRCase, async: true

alias Kickplan.Features
alias Kickplan.Schema.Resolution

describe "resolve/2" do
test "success: resolves all features" do
use_cassette "features/resolve-all" do
{:ok, resolutions} = Features.resolve()

assert length(resolutions) == 5

assert Enum.all?(resolutions, fn resolution ->
%Resolution{} = resolution
end)
end
end

test "success: resolves a single feature" do
use_cassette "features/resolve" do
{:ok, resolution} = Features.resolve("contact-limit")

assert %Resolution{key: "contact-limit"} = resolution
end
end
end
end
33 changes: 33 additions & 0 deletions test/kickplan/resource/metrics_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
defmodule Kickplan.MetricsTest do
use Kickplan.VCRCase, async: true

alias Kickplan.Metrics

describe "flush/0" do
test "success: flushes the metrics" do
use_cassette "metrics/flush" do
assert {:ok, true} = Metrics.flush()
end
end
end

describe "set/1" do
test "success: resolves a single feature" do
use_cassette "metrics/set" do
assert {:ok, true} =
Metrics.set(
key: "sdk_elixir_test",
value: 3,
account_key: "9a592f57-6da0-408e-99e7-8918b48a7dbe",
time: DateTime.utc_now(),
idempotency_key: "004b7f07-71fd-4ea5-a43c-dcde2516305b"
)
end
end

test "failure: request has invalid params" do
assert {:error, %NimbleOptions.ValidationError{}} =
Metrics.set(key: "sdk_elixir_test")
end
end
end
18 changes: 18 additions & 0 deletions test/support/vcr_case.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defmodule Kickplan.VCRCase do
@moduledoc false

use ExUnit.CaseTemplate

using do
quote do
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
end
end

setup do
ExVCR.Config.cassette_library_dir("test/cassettes")
ExVCR.Config.filter_request_headers("Authorization")

:ok
end
end
Loading