Skip to content

fix(flags): Update relative date op names #37

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

Merged
merged 1 commit into from
Jan 26, 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
2 changes: 1 addition & 1 deletion lib/posthog/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ def add_local_person_and_group_properties(distinct_id, groups, person_properties
symbolize_keys! value
end

all_person_properties = { "$current_distinct_id" => distinct_id }.merge(person_properties)
all_person_properties = { "distinct_id" => distinct_id }.merge(person_properties)

all_group_properties = {}
if groups
Expand Down
18 changes: 9 additions & 9 deletions lib/posthog/feature_flags.rb
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ def self.compare(lhs, rhs, operator)
end

def self.relative_date_parse_for_feature_flag_matching(value)
match = /^([0-9]+)([a-z])$/.match(value)
match = /^-?([0-9]+)([a-z])$/.match(value)
parsed_dt = DateTime.now.new_offset(0)
if match
number = match[1].to_i
Expand Down Expand Up @@ -310,20 +310,20 @@ def self.match_property(property, property_values)
else
self.compare(override_value.to_s, value.to_s, operator)
end
when 'is_date_before', 'is_date_after', 'is_relative_date_before', 'is_relative_date_after'
if operator == 'is_relative_date_before' || operator == 'is_relative_date_after'
parsed_date = self.relative_date_parse_for_feature_flag_matching(value.to_s)
override_date = PostHog::Utils.convert_to_datetime(override_value.to_s)
else
when 'is_date_before', 'is_date_after'
override_date = PostHog::Utils.convert_to_datetime(override_value.to_s)
parsed_date = self.relative_date_parse_for_feature_flag_matching(value.to_s)

if parsed_date.nil?
parsed_date = PostHog::Utils.convert_to_datetime(value.to_s)
override_date = PostHog::Utils.convert_to_datetime(override_value.to_s)
end

if !parsed_date
raise InconclusiveMatchError.new("Invalid date format")
end
if operator == 'is_date_before' or operator == 'is_relative_date_before'
if operator == 'is_date_before'
return override_date < parsed_date
elsif operator == 'is_date_after' or operator == 'is_relative_date_after'
elsif operator == 'is_date_after'
return override_date > parsed_date
end
else
Expand Down
14 changes: 7 additions & 7 deletions spec/posthog/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -567,42 +567,42 @@ def run
body: {"distinct_id": "some_id", "groups": {"company": "id:5", "instance": "app.posthog.com"}, "group_properties": {
"company": {"$group_key": "id:5", "x": "y"},
"instance": {"$group_key": "app.posthog.com"}
}, "person_properties": {"$current_distinct_id": "some_id", "x1": "y1"}, "token": "testsecret"})
}, "person_properties": {"distinct_id": "some_id", "x1": "y1"}, "token": "testsecret"})

WebMock.reset_executed_requests!

client.get_feature_flag('random_key', 'some_id', groups: {"company" => "id:5", "instance" => "app.posthog.com"}, person_properties: {"$current_distinct_id" => "override" }, group_properties: {"company" => {"$group_key" => "group_override"}})
client.get_feature_flag('random_key', 'some_id', groups: {"company" => "id:5", "instance" => "app.posthog.com"}, person_properties: {"distinct_id" => "override" }, group_properties: {"company" => {"$group_key" => "group_override"}})
assert_requested :post, decide_endpoint, times: 1
expect(WebMock).to have_requested(:post, decide_endpoint).with(
body: {"distinct_id": "some_id", "groups": {"company": "id:5", "instance": "app.posthog.com"}, "group_properties": {
"company": {"$group_key": "group_override"},
"instance": {"$group_key": "app.posthog.com"}
}, "person_properties": {"$current_distinct_id": "override"}, "token": "testsecret"})
}, "person_properties": {"distinct_id": "override"}, "token": "testsecret"})
WebMock.reset_executed_requests!

# test nones
client.get_all_flags_and_payloads('some_id', groups: {}, person_properties: nil, group_properties: nil)
assert_requested :post, decide_endpoint, times: 1
expect(WebMock).to have_requested(:post, decide_endpoint).with(
body: {"distinct_id": "some_id", "groups": {}, "group_properties": {}, "person_properties": {"$current_distinct_id": "some_id"}, "token": "testsecret"})
body: {"distinct_id": "some_id", "groups": {}, "group_properties": {}, "person_properties": {"distinct_id": "some_id"}, "token": "testsecret"})
WebMock.reset_executed_requests!

client.get_all_flags('some_id', groups: {"company" => "id:5"}, person_properties: nil, group_properties: nil)
assert_requested :post, decide_endpoint, times: 1
expect(WebMock).to have_requested(:post, decide_endpoint).with(
body: {"distinct_id": "some_id", "groups": {"company": "id:5"}, "group_properties": {"company": {"$group_key": "id:5"}}, "person_properties": {"$current_distinct_id": "some_id"}, "token": "testsecret"})
body: {"distinct_id": "some_id", "groups": {"company": "id:5"}, "group_properties": {"company": {"$group_key": "id:5"}}, "person_properties": {"distinct_id": "some_id"}, "token": "testsecret"})
WebMock.reset_executed_requests!

client.get_feature_flag_payload('random_key', 'some_id', groups: {}, person_properties: nil, group_properties: nil)
assert_requested :post, decide_endpoint, times: 1
expect(WebMock).to have_requested(:post, decide_endpoint).with(
body: {"distinct_id": "some_id", "groups": {}, "group_properties": {}, "person_properties": {"$current_distinct_id": "some_id"}, "token": "testsecret"})
body: {"distinct_id": "some_id", "groups": {}, "group_properties": {}, "person_properties": {"distinct_id": "some_id"}, "token": "testsecret"})
WebMock.reset_executed_requests!

client.is_feature_enabled('random_key', 'some_id', groups: {}, person_properties: nil, group_properties: nil)
assert_requested :post, decide_endpoint, times: 1
expect(WebMock).to have_requested(:post, decide_endpoint).with(
body: {"distinct_id": "some_id", "groups": {}, "group_properties": {}, "person_properties": {"$current_distinct_id": "some_id"}, "token": "testsecret"})
body: {"distinct_id": "some_id", "groups": {}, "group_properties": {}, "person_properties": {"distinct_id": "some_id"}, "token": "testsecret"})
WebMock.reset_executed_requests!
end

Expand Down
36 changes: 18 additions & 18 deletions spec/posthog/feature_flag_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ class PostHog
expect(c.get_feature_flag("complex-flag", "some-distinct-id_outside_rollout?", person_properties: {"region" => "USA", "email" => "[email protected]"})).to eq("decide-fallback-value")
assert_requested :post, decide_endpoint, times: 1
expect(WebMock).to have_requested(:post, decide_endpoint).with(
body: {"distinct_id": "some-distinct-id_outside_rollout?", "groups": {}, "group_properties": {}, "person_properties": {"$current_distinct_id": "some-distinct-id_outside_rollout?", "region" => "USA", "email" => "[email protected]"}, "token": "testsecret"})
body: {"distinct_id": "some-distinct-id_outside_rollout?", "groups": {}, "group_properties": {}, "person_properties": {"distinct_id": "some-distinct-id_outside_rollout?", "region" => "USA", "email" => "[email protected]"}, "token": "testsecret"})

WebMock.reset_executed_requests!

Expand All @@ -243,7 +243,7 @@ class PostHog
assert_requested :post, decide_endpoint, times: 1

expect(WebMock).to have_requested(:post, decide_endpoint).with(
body: {"distinct_id": "some-distinct-id", "groups": {}, "group_properties": {}, "person_properties": {"$current_distinct_id": "some-distinct-id", "doesnt_matter" => "1"}, "token": "testsecret"})
body: {"distinct_id": "some-distinct-id", "groups": {}, "group_properties": {}, "person_properties": {"distinct_id": "some-distinct-id", "doesnt_matter" => "1"}, "token": "testsecret"})

WebMock.reset_executed_requests!

Expand Down Expand Up @@ -1235,9 +1235,9 @@ class PostHog

end

it 'with relative date operators - is_relative_date_before' do
it 'with relative date operators - is_date_before' do
Timecop.freeze(Time.gm(2022, 5, 1)) do
property_a = { 'key' => 'key', 'value' => '6h', 'operator' => 'is_relative_date_before'}
property_a = { 'key' => 'key', 'value' => '-6h', 'operator' => 'is_date_before'}
expect(FeatureFlagsPoller.match_property(property_a, { 'key' => '2022-03-01' })).to be true
expect(FeatureFlagsPoller.match_property(property_a, { 'key' => '2022-04-30' })).to be true
expect(FeatureFlagsPoller.match_property(property_a, { 'key' => DateTime.new(2022, 4, 30, 1, 2, 3) })).to be true
Expand All @@ -1259,9 +1259,9 @@ class PostHog
end
end

it 'with relative date operators - is_relative_date_after' do
it 'with relative date operators - is_date_after' do
Timecop.freeze(Time.gm(2022, 5, 1)) do
property_b = { 'key' => 'key', 'value' => '1h', 'operator' => 'is_relative_date_after'}
property_b = { 'key' => 'key', 'value' => '1h', 'operator' => 'is_date_after'}
expect(FeatureFlagsPoller.match_property(property_b, { 'key' => '2022-05-02' })).to be true
expect(FeatureFlagsPoller.match_property(property_b, { 'key' => '2022-05-30' })).to be true
expect(FeatureFlagsPoller.match_property(property_b, { 'key' => DateTime.new(2022, 5, 30) })).to be true
Expand All @@ -1271,15 +1271,15 @@ class PostHog
# can't be invalid string
expect{ FeatureFlagsPoller.match_property(property_b, { 'key' => 'abcdef'}) }.to raise_error(InconclusiveMatchError)
# invalid flag property
property_c = { 'key' => 'key', 'value' => 1234, 'operator' => 'is_relative_date_after'}
property_c = { 'key' => 'key', 'value' => 1234, 'operator' => 'is_date_after'}
expect{ FeatureFlagsPoller.match_property(property_c, { 'key' => 1}) }.to raise_error(InconclusiveMatchError)
expect{ FeatureFlagsPoller.match_property(property_c, { 'key' => '2022-05-30'}) }.to raise_error(InconclusiveMatchError)
end
end

it 'with relative date operators - all possible relative dates' do
Timecop.freeze(Time.gm(2022, 5, 1)) do
property_d = { 'key' => 'key', 'value' => '12d', 'operator' => 'is_relative_date_before'}
property_d = { 'key' => 'key', 'value' => '-12d', 'operator' => 'is_date_before'}
expect(FeatureFlagsPoller.match_property(property_d, { 'key' => '2022-05-30' })).to be false

expect(FeatureFlagsPoller.match_property(property_d, { 'key' => '2022-03-30' })).to be true
Expand All @@ -1288,45 +1288,45 @@ class PostHog
expect(FeatureFlagsPoller.match_property(property_d, { 'key' => '2022-04-19 02:00:01+02:00' })).to be false

# Try all possible relative dates
property_e = { 'key' => 'key', 'value' => '1h', 'operator' => 'is_relative_date_before'}
property_e = { 'key' => 'key', 'value' => '1h', 'operator' => 'is_date_before'}
expect(FeatureFlagsPoller.match_property(property_e, { 'key' => '2022-05-01 00:00:00' })).to be false
expect(FeatureFlagsPoller.match_property(property_e, { 'key' => '2022-04-30 22:00:00' })).to be true

property_f = { 'key' => 'key', 'value' => '1d', 'operator' => 'is_relative_date_before'}
property_f = { 'key' => 'key', 'value' => '1d', 'operator' => 'is_date_before'}
expect(FeatureFlagsPoller.match_property(property_f, { 'key' => '2022-04-29 23:59:00' })).to be true
expect(FeatureFlagsPoller.match_property(property_f, { 'key' => '2022-04-30 00:00:01' })).to be false

property_g = { 'key' => 'key', 'value' => '1w', 'operator' => 'is_relative_date_before'}
property_g = { 'key' => 'key', 'value' => '1w', 'operator' => 'is_date_before'}
expect(FeatureFlagsPoller.match_property(property_g, { 'key' => '2022-04-23 00:00:00' })).to be true
expect(FeatureFlagsPoller.match_property(property_g, { 'key' => '2022-04-24 00:00:00' })).to be false
expect(FeatureFlagsPoller.match_property(property_g, { 'key' => '2022-04-24 00:00:01' })).to be false

property_h = { 'key' => 'key', 'value' => '1m', 'operator' => 'is_relative_date_before'}
property_h = { 'key' => 'key', 'value' => '1m', 'operator' => 'is_date_before'}
expect(FeatureFlagsPoller.match_property(property_h, { 'key' => '2022-03-01 00:00:00' })).to be true
expect(FeatureFlagsPoller.match_property(property_h, { 'key' => '2022-04-05 00:00:00' })).to be false

property_i = { 'key' => 'key', 'value' => '1y', 'operator' => 'is_relative_date_before'}
property_i = { 'key' => 'key', 'value' => '1y', 'operator' => 'is_date_before'}
expect(FeatureFlagsPoller.match_property(property_i, { 'key' => '2021-04-28 00:00:00' })).to be true
expect(FeatureFlagsPoller.match_property(property_i, { 'key' => '2021-05-01 00:00:01' })).to be false

property_j = { 'key' => 'key', 'value' => '122h', 'operator' => 'is_relative_date_after'}
property_j = { 'key' => 'key', 'value' => '122h', 'operator' => 'is_date_after'}
expect(FeatureFlagsPoller.match_property(property_j, { 'key' => '2022-05-01 00:00:00' })).to be true
expect(FeatureFlagsPoller.match_property(property_j, { 'key' => '2022-04-23 01:00:00' })).to be false

property_k = { 'key' => 'key', 'value' => '2d', 'operator' => 'is_relative_date_after'}
property_k = { 'key' => 'key', 'value' => '-2d', 'operator' => 'is_date_after'}
expect(FeatureFlagsPoller.match_property(property_k, { 'key' => '2022-05-01 00:00:00' })).to be true
expect(FeatureFlagsPoller.match_property(property_k, { 'key' => '2022-04-29 00:00:01' })).to be true
expect(FeatureFlagsPoller.match_property(property_k, { 'key' => '2022-04-29 00:00:00' })).to be false

property_l = { 'key' => 'key', 'value' => '02w', 'operator' => 'is_relative_date_after'}
property_l = { 'key' => 'key', 'value' => '02w', 'operator' => 'is_date_after'}
expect(FeatureFlagsPoller.match_property(property_l, { 'key' => '2022-05-01 00:00:00' })).to be true
expect(FeatureFlagsPoller.match_property(property_l, { 'key' => '2022-04-16 00:00:00' })).to be false

property_m = { 'key' => 'key', 'value' => '1m', 'operator' => 'is_relative_date_after'}
property_m = { 'key' => 'key', 'value' => '1m', 'operator' => 'is_date_after'}
expect(FeatureFlagsPoller.match_property(property_m, { 'key' => '2022-04-01 00:00:01' })).to be true
expect(FeatureFlagsPoller.match_property(property_m, { 'key' => '2022-04-01 00:00:00' })).to be false

property_n = { 'key' => 'key', 'value' => '1y', 'operator' => 'is_relative_date_after'}
property_n = { 'key' => 'key', 'value' => '1y', 'operator' => 'is_date_after'}
expect(FeatureFlagsPoller.match_property(property_n, { 'key' => '2022-05-01 00:00:00' })).to be true
expect(FeatureFlagsPoller.match_property(property_n, { 'key' => '2021-05-01 00:00:01' })).to be true
expect(FeatureFlagsPoller.match_property(property_n, { 'key' => '2021-05-01 00:00:00' })).to be false
Expand Down