flipper 0.16.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +1 -0
  3. data/.github/FUNDING.yml +1 -0
  4. data/.github/dependabot.yml +6 -0
  5. data/.github/workflows/ci.yml +110 -0
  6. data/.github/workflows/examples.yml +105 -0
  7. data/.github/workflows/release.yml +54 -0
  8. data/.rspec +1 -0
  9. data/CLAUDE.md +87 -0
  10. data/Changelog.md +2 -215
  11. data/Dockerfile +1 -1
  12. data/Gemfile +28 -20
  13. data/README.md +72 -62
  14. data/Rakefile +13 -3
  15. data/benchmark/enabled_ips.rb +10 -0
  16. data/benchmark/enabled_multiple_actors_ips.rb +20 -0
  17. data/benchmark/enabled_profile.rb +20 -0
  18. data/benchmark/instrumentation_ips.rb +21 -0
  19. data/benchmark/typecast_ips.rb +27 -0
  20. data/docker-compose.yml +37 -34
  21. data/docs/DockerCompose.md +0 -1
  22. data/docs/README.md +1 -0
  23. data/docs/images/banner.jpg +0 -0
  24. data/docs/images/flipper_cloud.png +0 -0
  25. data/examples/api/basic.ru +18 -0
  26. data/examples/api/custom_memoized.ru +36 -0
  27. data/examples/api/memoized.ru +42 -0
  28. data/examples/basic.rb +1 -12
  29. data/examples/cloud/app.ru +12 -0
  30. data/examples/cloud/backoff_policy.rb +13 -0
  31. data/examples/cloud/basic.rb +22 -0
  32. data/examples/cloud/cloud_setup.rb +20 -0
  33. data/examples/cloud/forked.rb +36 -0
  34. data/examples/cloud/import.rb +17 -0
  35. data/examples/cloud/poll_interval/README.md +111 -0
  36. data/examples/cloud/poll_interval/client.rb +108 -0
  37. data/examples/cloud/poll_interval/server.rb +98 -0
  38. data/examples/cloud/threaded.rb +33 -0
  39. data/examples/configuring_default.rb +2 -5
  40. data/examples/dsl.rb +10 -35
  41. data/examples/enabled_for_actor.rb +10 -15
  42. data/examples/expressions.rb +237 -0
  43. data/examples/group.rb +3 -6
  44. data/examples/group_dynamic_lookup.rb +5 -19
  45. data/examples/group_with_members.rb +4 -14
  46. data/examples/importing.rb +1 -1
  47. data/examples/individual_actor.rb +2 -5
  48. data/examples/instrumentation.rb +2 -2
  49. data/examples/instrumentation_last_accessed_at.rb +38 -0
  50. data/examples/memoizing.rb +35 -0
  51. data/examples/mirroring.rb +59 -0
  52. data/examples/percentage_of_actors.rb +6 -16
  53. data/examples/percentage_of_actors_enabled_check.rb +7 -10
  54. data/examples/percentage_of_actors_group.rb +5 -18
  55. data/examples/percentage_of_time.rb +3 -6
  56. data/examples/strict.rb +18 -0
  57. data/exe/flipper +5 -0
  58. data/flipper-cloud.gemspec +19 -0
  59. data/flipper.gemspec +10 -7
  60. data/lib/flipper/actor.rb +10 -3
  61. data/lib/flipper/adapter.rb +50 -8
  62. data/lib/flipper/adapter_builder.rb +44 -0
  63. data/lib/flipper/adapters/actor_limit.rb +54 -0
  64. data/lib/flipper/adapters/cache_base.rb +161 -0
  65. data/lib/flipper/adapters/dual_write.rb +63 -0
  66. data/lib/flipper/adapters/failover.rb +85 -0
  67. data/lib/flipper/adapters/failsafe.rb +72 -0
  68. data/lib/flipper/adapters/http/client.rb +64 -7
  69. data/lib/flipper/adapters/http/error.rb +19 -1
  70. data/lib/flipper/adapters/http.rb +97 -43
  71. data/lib/flipper/adapters/instrumented.rb +47 -26
  72. data/lib/flipper/adapters/memoizable.rb +44 -40
  73. data/lib/flipper/adapters/memory.rb +75 -111
  74. data/lib/flipper/adapters/operation_logger.rb +22 -78
  75. data/lib/flipper/adapters/poll/poller.rb +2 -0
  76. data/lib/flipper/adapters/poll.rb +52 -0
  77. data/lib/flipper/adapters/pstore.rb +27 -17
  78. data/lib/flipper/adapters/read_only.rb +8 -41
  79. data/lib/flipper/adapters/strict.rb +45 -0
  80. data/lib/flipper/adapters/sync/feature_synchronizer.rb +14 -1
  81. data/lib/flipper/adapters/sync/interval_synchronizer.rb +2 -7
  82. data/lib/flipper/adapters/sync/synchronizer.rb +13 -6
  83. data/lib/flipper/adapters/sync.rb +23 -29
  84. data/lib/flipper/adapters/wrapper.rb +54 -0
  85. data/lib/flipper/cli.rb +314 -0
  86. data/lib/flipper/cloud/configuration.rb +271 -0
  87. data/lib/flipper/cloud/dsl.rb +27 -0
  88. data/lib/flipper/cloud/message_verifier.rb +95 -0
  89. data/lib/flipper/cloud/middleware.rb +63 -0
  90. data/lib/flipper/cloud/migrate.rb +71 -0
  91. data/lib/flipper/cloud/routes.rb +14 -0
  92. data/lib/flipper/cloud/telemetry/backoff_policy.rb +96 -0
  93. data/lib/flipper/cloud/telemetry/instrumenter.rb +22 -0
  94. data/lib/flipper/cloud/telemetry/metric.rb +39 -0
  95. data/lib/flipper/cloud/telemetry/metric_storage.rb +30 -0
  96. data/lib/flipper/cloud/telemetry/submitter.rb +100 -0
  97. data/lib/flipper/cloud/telemetry.rb +191 -0
  98. data/lib/flipper/cloud.rb +54 -0
  99. data/lib/flipper/configuration.rb +54 -7
  100. data/lib/flipper/dsl.rb +58 -47
  101. data/lib/flipper/engine.rb +102 -0
  102. data/lib/flipper/errors.rb +3 -21
  103. data/lib/flipper/export.rb +24 -0
  104. data/lib/flipper/exporter.rb +17 -0
  105. data/lib/flipper/exporters/json/export.rb +32 -0
  106. data/lib/flipper/exporters/json/v1.rb +33 -0
  107. data/lib/flipper/expression/builder.rb +73 -0
  108. data/lib/flipper/expression/constant.rb +25 -0
  109. data/lib/flipper/expression.rb +71 -0
  110. data/lib/flipper/expressions/all.rb +9 -0
  111. data/lib/flipper/expressions/any.rb +9 -0
  112. data/lib/flipper/expressions/boolean.rb +9 -0
  113. data/lib/flipper/expressions/comparable.rb +13 -0
  114. data/lib/flipper/expressions/equal.rb +9 -0
  115. data/lib/flipper/expressions/feature_enabled.rb +34 -0
  116. data/lib/flipper/expressions/greater_than.rb +9 -0
  117. data/lib/flipper/expressions/greater_than_or_equal_to.rb +9 -0
  118. data/lib/flipper/expressions/less_than.rb +9 -0
  119. data/lib/flipper/expressions/less_than_or_equal_to.rb +9 -0
  120. data/lib/flipper/expressions/not_equal.rb +9 -0
  121. data/lib/flipper/expressions/now.rb +9 -0
  122. data/lib/flipper/expressions/number.rb +9 -0
  123. data/lib/flipper/expressions/percentage.rb +9 -0
  124. data/lib/flipper/expressions/percentage_of_actors.rb +12 -0
  125. data/lib/flipper/expressions/property.rb +9 -0
  126. data/lib/flipper/expressions/random.rb +9 -0
  127. data/lib/flipper/expressions/string.rb +9 -0
  128. data/lib/flipper/expressions/time.rb +16 -0
  129. data/lib/flipper/feature.rb +95 -28
  130. data/lib/flipper/feature_check_context.rb +10 -6
  131. data/lib/flipper/gate.rb +13 -11
  132. data/lib/flipper/gate_values.rb +5 -18
  133. data/lib/flipper/gates/actor.rb +10 -17
  134. data/lib/flipper/gates/boolean.rb +1 -1
  135. data/lib/flipper/gates/expression.rb +75 -0
  136. data/lib/flipper/gates/group.rb +5 -7
  137. data/lib/flipper/gates/percentage_of_actors.rb +10 -13
  138. data/lib/flipper/gates/percentage_of_time.rb +1 -2
  139. data/lib/flipper/identifier.rb +17 -0
  140. data/lib/flipper/instrumentation/log_subscriber.rb +35 -8
  141. data/lib/flipper/instrumentation/statsd.rb +4 -2
  142. data/lib/flipper/instrumentation/statsd_subscriber.rb +2 -4
  143. data/lib/flipper/instrumentation/subscriber.rb +8 -5
  144. data/lib/flipper/instrumenters/memory.rb +6 -2
  145. data/lib/flipper/metadata.rb +8 -1
  146. data/lib/flipper/middleware/memoizer.rb +46 -27
  147. data/lib/flipper/middleware/setup_env.rb +13 -3
  148. data/lib/flipper/model/active_record.rb +23 -0
  149. data/lib/flipper/poller.rb +157 -0
  150. data/lib/flipper/serializers/gzip.rb +22 -0
  151. data/lib/flipper/serializers/json.rb +17 -0
  152. data/lib/flipper/spec/shared_adapter_specs.rb +122 -56
  153. data/lib/flipper/test/shared_adapter_test.rb +120 -52
  154. data/lib/flipper/test_help.rb +43 -0
  155. data/lib/flipper/typecast.rb +59 -18
  156. data/lib/flipper/types/actor.rb +19 -13
  157. data/lib/flipper/types/group.rb +12 -5
  158. data/lib/flipper/types/percentage.rb +1 -1
  159. data/lib/flipper/version.rb +11 -1
  160. data/lib/flipper.rb +71 -12
  161. data/lib/generators/flipper/setup_generator.rb +68 -0
  162. data/lib/generators/flipper/templates/initializer.rb +45 -0
  163. data/lib/generators/flipper/templates/update/migrations/01_create_flipper_tables.rb.erb +22 -0
  164. data/lib/generators/flipper/templates/update/migrations/02_change_flipper_gates_value_to_text.rb.erb +18 -0
  165. data/lib/generators/flipper/update_generator.rb +35 -0
  166. data/package-lock.json +41 -0
  167. data/package.json +10 -0
  168. data/spec/fixtures/environment.rb +1 -0
  169. data/spec/fixtures/flipper_pstore_1679087600.json +46 -0
  170. data/spec/flipper/actor_spec.rb +10 -2
  171. data/spec/flipper/adapter_builder_spec.rb +72 -0
  172. data/spec/flipper/adapter_spec.rb +52 -6
  173. data/spec/flipper/adapters/actor_limit_spec.rb +75 -0
  174. data/spec/flipper/adapters/dual_write_spec.rb +82 -0
  175. data/spec/flipper/adapters/failover_spec.rb +141 -0
  176. data/spec/flipper/adapters/failsafe_spec.rb +58 -0
  177. data/spec/flipper/adapters/http/client_spec.rb +61 -0
  178. data/spec/flipper/adapters/http_spec.rb +402 -65
  179. data/spec/flipper/adapters/instrumented_spec.rb +31 -13
  180. data/spec/flipper/adapters/memoizable_spec.rb +51 -33
  181. data/spec/flipper/adapters/memory_spec.rb +33 -5
  182. data/spec/flipper/adapters/operation_logger_spec.rb +38 -12
  183. data/spec/flipper/adapters/poll_spec.rb +41 -0
  184. data/spec/flipper/adapters/pstore_spec.rb +0 -2
  185. data/spec/flipper/adapters/read_only_spec.rb +32 -18
  186. data/spec/flipper/adapters/strict_spec.rb +64 -0
  187. data/spec/flipper/adapters/sync/feature_synchronizer_spec.rb +39 -1
  188. data/spec/flipper/adapters/sync/interval_synchronizer_spec.rb +4 -5
  189. data/spec/flipper/adapters/sync/synchronizer_spec.rb +87 -1
  190. data/spec/flipper/adapters/sync_spec.rb +17 -6
  191. data/spec/flipper/cli_spec.rb +217 -0
  192. data/spec/flipper/cloud/configuration_spec.rb +257 -0
  193. data/spec/flipper/cloud/dsl_spec.rb +90 -0
  194. data/spec/flipper/cloud/message_verifier_spec.rb +104 -0
  195. data/spec/flipper/cloud/middleware_spec.rb +307 -0
  196. data/spec/flipper/cloud/migrate_spec.rb +160 -0
  197. data/spec/flipper/cloud/telemetry/backoff_policy_spec.rb +107 -0
  198. data/spec/flipper/cloud/telemetry/metric_spec.rb +87 -0
  199. data/spec/flipper/cloud/telemetry/metric_storage_spec.rb +58 -0
  200. data/spec/flipper/cloud/telemetry/submitter_spec.rb +145 -0
  201. data/spec/flipper/cloud/telemetry_spec.rb +208 -0
  202. data/spec/flipper/cloud_spec.rb +186 -0
  203. data/spec/flipper/configuration_spec.rb +37 -3
  204. data/spec/flipper/dsl_spec.rb +67 -80
  205. data/spec/flipper/engine_spec.rb +374 -0
  206. data/spec/flipper/export_spec.rb +13 -0
  207. data/spec/flipper/exporter_spec.rb +16 -0
  208. data/spec/flipper/exporters/json/export_spec.rb +60 -0
  209. data/spec/flipper/exporters/json/v1_spec.rb +33 -0
  210. data/spec/flipper/expression/builder_spec.rb +248 -0
  211. data/spec/flipper/expression_spec.rb +188 -0
  212. data/spec/flipper/expressions/all_spec.rb +15 -0
  213. data/spec/flipper/expressions/any_spec.rb +15 -0
  214. data/spec/flipper/expressions/boolean_spec.rb +15 -0
  215. data/spec/flipper/expressions/equal_spec.rb +24 -0
  216. data/spec/flipper/expressions/greater_than_or_equal_to_spec.rb +28 -0
  217. data/spec/flipper/expressions/greater_than_spec.rb +28 -0
  218. data/spec/flipper/expressions/less_than_or_equal_to_spec.rb +28 -0
  219. data/spec/flipper/expressions/less_than_spec.rb +32 -0
  220. data/spec/flipper/expressions/not_equal_spec.rb +15 -0
  221. data/spec/flipper/expressions/now_spec.rb +11 -0
  222. data/spec/flipper/expressions/number_spec.rb +21 -0
  223. data/spec/flipper/expressions/percentage_of_actors_spec.rb +20 -0
  224. data/spec/flipper/expressions/percentage_spec.rb +15 -0
  225. data/spec/flipper/expressions/property_spec.rb +13 -0
  226. data/spec/flipper/expressions/random_spec.rb +9 -0
  227. data/spec/flipper/expressions/string_spec.rb +11 -0
  228. data/spec/flipper/expressions/time_spec.rb +29 -0
  229. data/spec/flipper/feature_check_context_spec.rb +18 -20
  230. data/spec/flipper/feature_spec.rb +461 -48
  231. data/spec/flipper/gate_spec.rb +0 -2
  232. data/spec/flipper/gate_values_spec.rb +2 -34
  233. data/spec/flipper/gates/actor_spec.rb +0 -2
  234. data/spec/flipper/gates/boolean_spec.rb +1 -3
  235. data/spec/flipper/gates/expression_spec.rb +190 -0
  236. data/spec/flipper/gates/group_spec.rb +2 -5
  237. data/spec/flipper/gates/percentage_of_actors_spec.rb +61 -7
  238. data/spec/flipper/gates/percentage_of_time_spec.rb +2 -4
  239. data/spec/flipper/identifier_spec.rb +12 -0
  240. data/spec/flipper/instrumentation/log_subscriber_spec.rb +24 -7
  241. data/spec/flipper/instrumentation/statsd_subscriber_spec.rb +26 -3
  242. data/spec/flipper/instrumenters/memory_spec.rb +18 -1
  243. data/spec/flipper/instrumenters/noop_spec.rb +14 -8
  244. data/spec/flipper/middleware/memoizer_spec.rb +199 -62
  245. data/spec/flipper/middleware/setup_env_spec.rb +23 -5
  246. data/spec/flipper/model/active_record_spec.rb +72 -0
  247. data/spec/flipper/poller_spec.rb +390 -0
  248. data/spec/flipper/registry_spec.rb +0 -1
  249. data/spec/flipper/serializers/gzip_spec.rb +13 -0
  250. data/spec/flipper/serializers/json_spec.rb +13 -0
  251. data/spec/flipper/typecast_spec.rb +121 -7
  252. data/spec/flipper/types/actor_spec.rb +63 -47
  253. data/spec/flipper/types/boolean_spec.rb +0 -1
  254. data/spec/flipper/types/group_spec.rb +24 -3
  255. data/spec/flipper/types/percentage_of_actors_spec.rb +0 -1
  256. data/spec/flipper/types/percentage_of_time_spec.rb +0 -1
  257. data/spec/flipper/types/percentage_spec.rb +0 -1
  258. data/spec/{integration_spec.rb → flipper_integration_spec.rb} +301 -59
  259. data/spec/flipper_spec.rb +123 -29
  260. data/spec/{helper.rb → spec_helper.rb} +23 -21
  261. data/spec/support/actor_names.yml +1 -0
  262. data/spec/support/descriptions.yml +1 -0
  263. data/spec/support/fail_on_output.rb +8 -0
  264. data/spec/support/fake_backoff_policy.rb +15 -0
  265. data/spec/support/skippable.rb +18 -0
  266. data/spec/support/spec_helpers.rb +53 -6
  267. data/test/adapters/actor_limit_test.rb +20 -0
  268. data/test/test_helper.rb +2 -1
  269. data/test_rails/generators/flipper/setup_generator_test.rb +69 -0
  270. data/test_rails/generators/flipper/update_generator_test.rb +96 -0
  271. data/test_rails/helper.rb +31 -0
  272. data/test_rails/system/test_help_test.rb +52 -0
  273. metadata +200 -82
  274. data/.rubocop.yml +0 -54
  275. data/.rubocop_todo.yml +0 -199
  276. data/docs/Adapters.md +0 -124
  277. data/docs/Caveats.md +0 -4
  278. data/docs/Gates.md +0 -167
  279. data/docs/Instrumentation.md +0 -27
  280. data/docs/Optimization.md +0 -114
  281. data/docs/api/README.md +0 -849
  282. data/docs/http/README.md +0 -35
  283. data/docs/read-only/README.md +0 -21
  284. data/examples/example_setup.rb +0 -8
  285. data/test/helper.rb +0 -11
@@ -1,15 +1,15 @@
1
1
  # Requires the following methods:
2
2
  # * subject - The instance of the adapter
3
- # rubocop:disable Metrics/BlockLength
4
3
  RSpec.shared_examples_for 'a flipper adapter' do
5
4
  let(:flipper) { Flipper.new(subject) }
6
5
  let(:feature) { flipper[:stats] }
7
6
 
8
- let(:boolean_gate) { feature.gate(:boolean) }
9
- let(:group_gate) { feature.gate(:group) }
10
- let(:actor_gate) { feature.gate(:actor) }
11
- let(:actors_gate) { feature.gate(:percentage_of_actors) }
12
- let(:time_gate) { feature.gate(:percentage_of_time) }
7
+ let(:boolean_gate) { feature.gate(:boolean) }
8
+ let(:expression_gate) { feature.gate(:expression) }
9
+ let(:group_gate) { feature.gate(:group) }
10
+ let(:actor_gate) { feature.gate(:actor) }
11
+ let(:actors_gate) { feature.gate(:percentage_of_actors) }
12
+ let(:time_gate) { feature.gate(:percentage_of_time) }
13
13
 
14
14
  before do
15
15
  Flipper.register(:admins) do |actor|
@@ -34,17 +34,25 @@ RSpec.shared_examples_for 'a flipper adapter' do
34
34
  expect(subject.class.ancestors).to include(Flipper::Adapter)
35
35
  end
36
36
 
37
+ it 'knows how to get adapter from source' do
38
+ adapter = Flipper::Adapters::Memory.new
39
+ flipper = Flipper.new(adapter)
40
+ expect(subject.class.from(adapter).class.ancestors).to include(Flipper::Adapter)
41
+ expect(subject.class.from(flipper).class.ancestors).to include(Flipper::Adapter)
42
+ end
43
+
37
44
  it 'returns correct default values for the gates if none are enabled' do
45
+ expect(subject.get(feature)).to eq(subject.class.default_config)
38
46
  expect(subject.get(feature)).to eq(subject.default_config)
39
47
  end
40
48
 
41
49
  it 'can enable, disable and get value for boolean gate' do
42
- expect(subject.enable(feature, boolean_gate, flipper.boolean)).to eq(true)
50
+ expect(subject.enable(feature, boolean_gate, Flipper::Types::Boolean.new)).to eq(true)
43
51
 
44
52
  result = subject.get(feature)
45
53
  expect(result[:boolean]).to eq('true')
46
54
 
47
- expect(subject.disable(feature, boolean_gate, flipper.boolean(false))).to eq(true)
55
+ expect(subject.disable(feature, boolean_gate, Flipper::Types::Boolean.new(false))).to eq(true)
48
56
 
49
57
  result = subject.get(feature)
50
58
  expect(result[:boolean]).to eq(nil)
@@ -52,17 +60,34 @@ RSpec.shared_examples_for 'a flipper adapter' do
52
60
 
53
61
  it 'fully disables all enabled things when boolean gate disabled' do
54
62
  actor22 = Flipper::Actor.new('22')
55
- expect(subject.enable(feature, boolean_gate, flipper.boolean)).to eq(true)
63
+ expect(subject.enable(feature, boolean_gate, Flipper::Types::Boolean.new)).to eq(true)
56
64
  expect(subject.enable(feature, group_gate, flipper.group(:admins))).to eq(true)
57
- expect(subject.enable(feature, actor_gate, flipper.actor(actor22))).to eq(true)
58
- expect(subject.enable(feature, actors_gate, flipper.actors(25))).to eq(true)
59
- expect(subject.enable(feature, time_gate, flipper.time(45))).to eq(true)
60
-
61
- expect(subject.disable(feature, boolean_gate, flipper.boolean(false))).to eq(true)
65
+ expect(subject.enable(feature, actor_gate, Flipper::Types::Actor.new(actor22))).to eq(true)
66
+ expect(subject.enable(feature, actors_gate, Flipper::Types::PercentageOfActors.new(25))).to eq(true)
67
+ expect(subject.enable(feature, time_gate, Flipper::Types::PercentageOfTime.new(45))).to eq(true)
62
68
 
69
+ expect(subject.disable(feature, boolean_gate, Flipper::Types::Boolean.new(false))).to eq(true)
63
70
  expect(subject.get(feature)).to eq(subject.default_config)
64
71
  end
65
72
 
73
+ it 'can enable, disable and get value for expression gate' do
74
+ basic_expression = Flipper.property(:plan).eq("basic")
75
+ age_expression = Flipper.property(:age).gte(21)
76
+ any_expression = Flipper.any(basic_expression, age_expression)
77
+
78
+ expect(subject.enable(feature, expression_gate, any_expression)).to eq(true)
79
+ result = subject.get(feature)
80
+ expect(result[:expression]).to eq(any_expression.value)
81
+
82
+ expect(subject.enable(feature, expression_gate, basic_expression)).to eq(true)
83
+ result = subject.get(feature)
84
+ expect(result[:expression]).to eq(basic_expression.value)
85
+
86
+ expect(subject.disable(feature, expression_gate, basic_expression)).to eq(true)
87
+ result = subject.get(feature)
88
+ expect(result[:expression]).to be(nil)
89
+ end
90
+
66
91
  it 'can enable, disable and get value for group gate' do
67
92
  expect(subject.enable(feature, group_gate, flipper.group(:admins))).to eq(true)
68
93
  expect(subject.enable(feature, group_gate, flipper.group(:early_access))).to eq(true)
@@ -83,34 +108,34 @@ RSpec.shared_examples_for 'a flipper adapter' do
83
108
  actor22 = Flipper::Actor.new('22')
84
109
  actor_asdf = Flipper::Actor.new('asdf')
85
110
 
86
- expect(subject.enable(feature, actor_gate, flipper.actor(actor22))).to eq(true)
87
- expect(subject.enable(feature, actor_gate, flipper.actor(actor_asdf))).to eq(true)
111
+ expect(feature.enable(actor22)).to be(true)
112
+ expect(feature.enable(actor_asdf)).to be(true)
88
113
 
89
- result = subject.get(feature)
90
- expect(result[:actors]).to eq(Set['22', 'asdf'])
114
+ expect(feature).to be_enabled(actor22)
115
+ expect(feature).to be_enabled(actor_asdf)
91
116
 
92
- expect(subject.disable(feature, actor_gate, flipper.actor(actor22))).to eq(true)
93
- result = subject.get(feature)
94
- expect(result[:actors]).to eq(Set['asdf'])
117
+ expect(feature.disable(actor22)).to be(true)
118
+ expect(feature).not_to be_enabled(actor22)
119
+ expect(feature).to be_enabled(actor_asdf)
95
120
 
96
- expect(subject.disable(feature, actor_gate, flipper.actor(actor_asdf))).to eq(true)
97
- result = subject.get(feature)
98
- expect(result[:actors]).to eq(Set.new)
121
+ expect(feature.disable(actor_asdf)).to eq(true)
122
+ expect(feature).not_to be_enabled(actor22)
123
+ expect(feature).not_to be_enabled(actor_asdf)
99
124
  end
100
125
 
101
126
  it 'can enable, disable and get value for percentage of actors gate' do
102
- expect(subject.enable(feature, actors_gate, flipper.actors(15))).to eq(true)
127
+ expect(subject.enable(feature, actors_gate, Flipper::Types::PercentageOfActors.new(15))).to eq(true)
103
128
  result = subject.get(feature)
104
129
  expect(result[:percentage_of_actors]).to eq('15')
105
130
 
106
- expect(subject.disable(feature, actors_gate, flipper.actors(0))).to eq(true)
131
+ expect(subject.disable(feature, actors_gate, Flipper::Types::PercentageOfActors.new(0))).to eq(true)
107
132
  result = subject.get(feature)
108
133
  expect(result[:percentage_of_actors]).to eq('0')
109
134
  end
110
135
 
111
136
  it 'can enable percentage of actors gate many times and consistently return values' do
112
137
  (1..100).each do |percentage|
113
- expect(subject.enable(feature, actors_gate, flipper.actors(percentage))).to eq(true)
138
+ expect(subject.enable(feature, actors_gate, Flipper::Types::PercentageOfActors.new(percentage))).to eq(true)
114
139
  result = subject.get(feature)
115
140
  expect(result[:percentage_of_actors]).to eq(percentage.to_s)
116
141
  end
@@ -118,25 +143,25 @@ RSpec.shared_examples_for 'a flipper adapter' do
118
143
 
119
144
  it 'can disable percentage of actors gate many times and consistently return values' do
120
145
  (1..100).each do |percentage|
121
- expect(subject.disable(feature, actors_gate, flipper.actors(percentage))).to eq(true)
146
+ expect(subject.disable(feature, actors_gate, Flipper::Types::PercentageOfActors.new(percentage))).to eq(true)
122
147
  result = subject.get(feature)
123
148
  expect(result[:percentage_of_actors]).to eq(percentage.to_s)
124
149
  end
125
150
  end
126
151
 
127
152
  it 'can enable, disable and get value for percentage of time gate' do
128
- expect(subject.enable(feature, time_gate, flipper.time(10))).to eq(true)
153
+ expect(subject.enable(feature, time_gate, Flipper::Types::PercentageOfTime.new(10))).to eq(true)
129
154
  result = subject.get(feature)
130
155
  expect(result[:percentage_of_time]).to eq('10')
131
156
 
132
- expect(subject.disable(feature, time_gate, flipper.time(0))).to eq(true)
157
+ expect(subject.disable(feature, time_gate, Flipper::Types::PercentageOfTime.new(0))).to eq(true)
133
158
  result = subject.get(feature)
134
159
  expect(result[:percentage_of_time]).to eq('0')
135
160
  end
136
161
 
137
162
  it 'can enable percentage of time gate many times and consistently return values' do
138
163
  (1..100).each do |percentage|
139
- expect(subject.enable(feature, time_gate, flipper.time(percentage))).to eq(true)
164
+ expect(subject.enable(feature, time_gate, Flipper::Types::PercentageOfTime.new(percentage))).to eq(true)
140
165
  result = subject.get(feature)
141
166
  expect(result[:percentage_of_time]).to eq(percentage.to_s)
142
167
  end
@@ -144,22 +169,23 @@ RSpec.shared_examples_for 'a flipper adapter' do
144
169
 
145
170
  it 'can disable percentage of time gate many times and consistently return values' do
146
171
  (1..100).each do |percentage|
147
- expect(subject.disable(feature, time_gate, flipper.time(percentage))).to eq(true)
172
+ expect(subject.disable(feature, time_gate, Flipper::Types::PercentageOfTime.new(percentage))).to eq(true)
148
173
  result = subject.get(feature)
149
174
  expect(result[:percentage_of_time]).to eq(percentage.to_s)
150
175
  end
151
176
  end
152
177
 
153
178
  it 'converts boolean value to a string' do
154
- expect(subject.enable(feature, boolean_gate, flipper.boolean)).to eq(true)
179
+ expect(subject.enable(feature, boolean_gate, Flipper::Types::Boolean.new)).to eq(true)
155
180
  result = subject.get(feature)
156
181
  expect(result[:boolean]).to eq('true')
157
182
  end
158
183
 
159
184
  it 'converts the actor value to a string' do
160
- expect(subject.enable(feature, actor_gate, flipper.actor(Flipper::Actor.new(22)))).to eq(true)
161
- result = subject.get(feature)
162
- expect(result[:actors]).to eq(Set['22'])
185
+ actor = Flipper::Actor.new(22)
186
+ expect(feature).not_to be_enabled(actor)
187
+ feature.enable_actor actor
188
+ expect(feature).to be_enabled(actor)
163
189
  end
164
190
 
165
191
  it 'converts group value to a string' do
@@ -169,13 +195,13 @@ RSpec.shared_examples_for 'a flipper adapter' do
169
195
  end
170
196
 
171
197
  it 'converts percentage of time integer value to a string' do
172
- expect(subject.enable(feature, time_gate, flipper.time(10))).to eq(true)
198
+ expect(subject.enable(feature, time_gate, Flipper::Types::PercentageOfTime.new(10))).to eq(true)
173
199
  result = subject.get(feature)
174
200
  expect(result[:percentage_of_time]).to eq('10')
175
201
  end
176
202
 
177
203
  it 'converts percentage of actors integer value to a string' do
178
- expect(subject.enable(feature, actors_gate, flipper.actors(10))).to eq(true)
204
+ expect(subject.enable(feature, actors_gate, Flipper::Types::PercentageOfActors.new(10))).to eq(true)
179
205
  result = subject.get(feature)
180
206
  expect(result[:percentage_of_actors]).to eq('10')
181
207
  end
@@ -198,11 +224,11 @@ RSpec.shared_examples_for 'a flipper adapter' do
198
224
 
199
225
  it 'clears all the gate values for the feature on remove' do
200
226
  actor22 = Flipper::Actor.new('22')
201
- expect(subject.enable(feature, boolean_gate, flipper.boolean)).to eq(true)
227
+ expect(subject.enable(feature, boolean_gate, Flipper::Types::Boolean.new)).to eq(true)
202
228
  expect(subject.enable(feature, group_gate, flipper.group(:admins))).to eq(true)
203
- expect(subject.enable(feature, actor_gate, flipper.actor(actor22))).to eq(true)
204
- expect(subject.enable(feature, actors_gate, flipper.actors(25))).to eq(true)
205
- expect(subject.enable(feature, time_gate, flipper.time(45))).to eq(true)
229
+ expect(subject.enable(feature, actor_gate, Flipper::Types::Actor.new(actor22))).to eq(true)
230
+ expect(subject.enable(feature, actors_gate, Flipper::Types::PercentageOfActors.new(25))).to eq(true)
231
+ expect(subject.enable(feature, time_gate, Flipper::Types::PercentageOfTime.new(45))).to eq(true)
206
232
 
207
233
  expect(subject.remove(feature)).to eq(true)
208
234
 
@@ -214,11 +240,11 @@ RSpec.shared_examples_for 'a flipper adapter' do
214
240
  subject.add(feature)
215
241
  expect(subject.features).to include(feature.key)
216
242
 
217
- expect(subject.enable(feature, boolean_gate, flipper.boolean)).to eq(true)
243
+ expect(subject.enable(feature, boolean_gate, Flipper::Types::Boolean.new)).to eq(true)
218
244
  expect(subject.enable(feature, group_gate, flipper.group(:admins))).to eq(true)
219
- expect(subject.enable(feature, actor_gate, flipper.actor(actor22))).to eq(true)
220
- expect(subject.enable(feature, actors_gate, flipper.actors(25))).to eq(true)
221
- expect(subject.enable(feature, time_gate, flipper.time(45))).to eq(true)
245
+ expect(subject.enable(feature, actor_gate, Flipper::Types::Actor.new(actor22))).to eq(true)
246
+ expect(subject.enable(feature, actors_gate, Flipper::Types::PercentageOfActors.new(25))).to eq(true)
247
+ expect(subject.enable(feature, time_gate, Flipper::Types::PercentageOfTime.new(45))).to eq(true)
222
248
 
223
249
  expect(subject.clear(feature)).to eq(true)
224
250
  expect(subject.features).to include(feature.key)
@@ -231,7 +257,7 @@ RSpec.shared_examples_for 'a flipper adapter' do
231
257
 
232
258
  it 'can get multiple features' do
233
259
  expect(subject.add(flipper[:stats])).to eq(true)
234
- expect(subject.enable(flipper[:stats], boolean_gate, flipper.boolean)).to eq(true)
260
+ expect(subject.enable(flipper[:stats], boolean_gate, Flipper::Types::Boolean.new)).to eq(true)
235
261
  expect(subject.add(flipper[:search])).to eq(true)
236
262
 
237
263
  result = subject.get_multi([flipper[:stats], flipper[:search], flipper[:other]])
@@ -247,16 +273,16 @@ RSpec.shared_examples_for 'a flipper adapter' do
247
273
 
248
274
  it 'can get all features' do
249
275
  expect(subject.add(flipper[:stats])).to eq(true)
250
- expect(subject.enable(flipper[:stats], boolean_gate, flipper.boolean)).to eq(true)
276
+ expect(subject.enable(flipper[:stats], boolean_gate, Flipper::Types::Boolean.new)).to eq(true)
251
277
  expect(subject.add(flipper[:search])).to eq(true)
278
+ flipper.enable :analytics, Flipper.property(:plan).eq("pro")
252
279
 
253
280
  result = subject.get_all
254
- expect(result).to be_instance_of(Hash)
255
281
 
256
- stats = result["stats"]
257
- search = result["search"]
258
- expect(stats).to eq(subject.default_config.merge(boolean: 'true'))
259
- expect(search).to eq(subject.default_config)
282
+ expect(result).to be_instance_of(Hash)
283
+ expect(result["stats"]).to eq(subject.default_config.merge(boolean: 'true'))
284
+ expect(result["search"]).to eq(subject.default_config)
285
+ expect(result["analytics"]).to eq(subject.default_config.merge(expression: {"Equal"=>[{"Property"=>["plan"]}, "pro"]}))
260
286
  end
261
287
 
262
288
  it 'includes explicitly disabled features when getting all features' do
@@ -270,9 +296,9 @@ RSpec.shared_examples_for 'a flipper adapter' do
270
296
 
271
297
  it 'can double enable an actor without error' do
272
298
  actor = Flipper::Actor.new('Flipper::Actor;22')
273
- expect(subject.enable(feature, actor_gate, flipper.actor(actor))).to eq(true)
274
- expect(subject.enable(feature, actor_gate, flipper.actor(actor))).to eq(true)
275
- expect(subject.get(feature).fetch(:actors)).to eq(Set['Flipper::Actor;22'])
299
+ expect(feature.enable(actor)).to be(true)
300
+ expect(feature.enable(actor)).to be(true)
301
+ expect(feature).to be_enabled(actor)
276
302
  end
277
303
 
278
304
  it 'can double enable a group without error' do
@@ -280,4 +306,44 @@ RSpec.shared_examples_for 'a flipper adapter' do
280
306
  expect(subject.enable(feature, group_gate, flipper.group(:admins))).to eq(true)
281
307
  expect(subject.get(feature).fetch(:groups)).to eq(Set['admins'])
282
308
  end
309
+
310
+ it 'can double enable percentage without error' do
311
+ expect(subject.enable(feature, actors_gate, Flipper::Types::PercentageOfActors.new(25))).to eq(true)
312
+ expect(subject.enable(feature, actors_gate, Flipper::Types::PercentageOfActors.new(25))).to eq(true)
313
+ end
314
+
315
+ it 'can double enable without error' do
316
+ expect(subject.enable(feature, boolean_gate, Flipper::Types::Boolean.new)).to eq(true)
317
+ expect(subject.enable(feature, boolean_gate, Flipper::Types::Boolean.new)).to eq(true)
318
+ end
319
+
320
+ it 'can get_all features when there are none' do
321
+ expect(subject.features).to eq(Set.new)
322
+ expect(subject.get_all).to eq({})
323
+ end
324
+
325
+ it 'clears other gate values on enable' do
326
+ actor = Flipper::Actor.new('Flipper::Actor;22')
327
+ subject.enable(feature, actors_gate, Flipper::Types::PercentageOfActors.new(25))
328
+ subject.enable(feature, time_gate, Flipper::Types::PercentageOfTime.new(25))
329
+ subject.enable(feature, group_gate, flipper.group(:admins))
330
+ subject.enable(feature, actor_gate, Flipper::Types::Actor.new(actor))
331
+ subject.enable(feature, boolean_gate, Flipper::Types::Boolean.new(true))
332
+ expect(subject.get(feature)).to eq(subject.default_config.merge(boolean: "true"))
333
+ end
334
+
335
+ it 'can import and export' do
336
+ adapter = Flipper::Adapters::Memory.new
337
+ source_flipper = Flipper.new(adapter)
338
+ source_flipper.enable(:stats)
339
+ export = adapter.export
340
+
341
+ # some adapters cannot import so if they return false lets assert it
342
+ # didn't happen
343
+ if subject.import(export)
344
+ expect(flipper[:stats]).to be_enabled
345
+ else
346
+ expect(flipper[:stats]).not_to be_enabled
347
+ end
348
+ end
283
349
  end
@@ -1,4 +1,3 @@
1
- # rubocop:disable Metrics/ModuleLength
2
1
  module Flipper
3
2
  module Test
4
3
  module SharedAdapterTests
@@ -8,6 +7,7 @@ module Flipper
8
7
  @feature = @flipper[:stats]
9
8
  @boolean_gate = @feature.gate(:boolean)
10
9
  @group_gate = @feature.gate(:group)
10
+ @expression_gate = @feature.gate(:expression)
11
11
  @actor_gate = @feature.gate(:actor)
12
12
  @actors_gate = @feature.gate(:percentage_of_actors)
13
13
  @time_gate = @feature.gate(:percentage_of_time)
@@ -35,28 +35,55 @@ module Flipper
35
35
  assert_includes @adapter.class.ancestors, Flipper::Adapter
36
36
  end
37
37
 
38
+ def test_knows_how_to_get_adapter_from_source
39
+ adapter = Flipper::Adapters::Memory.new
40
+ flipper = Flipper.new(adapter)
41
+
42
+ assert_includes adapter.class.from(adapter).class.ancestors, Flipper::Adapter
43
+ assert_includes adapter.class.from(flipper).class.ancestors, Flipper::Adapter
44
+ end
45
+
38
46
  def test_returns_correct_default_values_for_gates_if_none_are_enabled
47
+ assert_equal @adapter.class.default_config, @adapter.get(@feature)
39
48
  assert_equal @adapter.default_config, @adapter.get(@feature)
40
49
  end
41
50
 
42
51
  def test_can_enable_disable_and_get_value_for_boolean_gate
43
- assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
52
+ assert_equal true, @adapter.enable(@feature, @boolean_gate, Flipper::Types::Boolean.new)
44
53
  assert_equal 'true', @adapter.get(@feature)[:boolean]
45
- assert_equal true, @adapter.disable(@feature, @boolean_gate, @flipper.boolean(false))
46
- assert_equal nil, @adapter.get(@feature)[:boolean]
54
+ assert_equal true, @adapter.disable(@feature, @boolean_gate, Flipper::Types::Boolean.new(false))
55
+ assert_nil @adapter.get(@feature)[:boolean]
47
56
  end
48
57
 
49
58
  def test_fully_disables_all_enabled_things_when_boolean_gate_disabled
50
59
  actor22 = Flipper::Actor.new('22')
51
- assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
60
+ assert_equal true, @adapter.enable(@feature, @boolean_gate, Flipper::Types::Boolean.new)
52
61
  assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
53
- assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor22))
54
- assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(25))
55
- assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(45))
56
- assert_equal true, @adapter.disable(@feature, @boolean_gate, @flipper.boolean(false))
62
+ assert_equal true, @adapter.enable(@feature, @actor_gate, Flipper::Types::Actor.new(actor22))
63
+ assert_equal true, @adapter.enable(@feature, @actors_gate, Flipper::Types::PercentageOfActors.new(25))
64
+ assert_equal true, @adapter.enable(@feature, @time_gate, Flipper::Types::PercentageOfTime.new(45))
65
+ assert_equal true, @adapter.disable(@feature, @boolean_gate, Flipper::Types::Boolean.new(false))
57
66
  assert_equal @adapter.default_config, @adapter.get(@feature)
58
67
  end
59
68
 
69
+ def test_can_enable_disable_and_get_value_for_expression_gate
70
+ basic_expression = Flipper.property(:plan).eq("basic")
71
+ age_expression = Flipper.property(:age).gte(21)
72
+ any_expression = Flipper.any(basic_expression, age_expression)
73
+
74
+ assert_equal true, @adapter.enable(@feature, @expression_gate, any_expression)
75
+ result = @adapter.get(@feature)
76
+ assert_equal any_expression.value, result[:expression]
77
+
78
+ assert_equal true, @adapter.enable(@feature, @expression_gate, basic_expression)
79
+ result = @adapter.get(@feature)
80
+ assert_equal basic_expression.value, result[:expression]
81
+
82
+ assert_equal true, @adapter.disable(@feature, @expression_gate, basic_expression)
83
+ result = @adapter.get(@feature)
84
+ assert_nil result[:expression]
85
+ end
86
+
60
87
  def test_can_enable_disable_get_value_for_group_gate
61
88
  assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
62
89
  assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:early_access))
@@ -77,34 +104,34 @@ module Flipper
77
104
  actor22 = Flipper::Actor.new('22')
78
105
  actor_asdf = Flipper::Actor.new('asdf')
79
106
 
80
- assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor22))
81
- assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor_asdf))
107
+ assert_equal true, @feature.enable(actor22)
108
+ assert_equal true, @feature.enable(actor_asdf)
82
109
 
83
- result = @adapter.get(@feature)
84
- assert_equal Set['22', 'asdf'], result[:actors]
110
+ assert @feature.enabled?(actor22)
111
+ assert @feature.enabled?(actor_asdf)
85
112
 
86
- assert true, @adapter.disable(@feature, @actor_gate, @flipper.actor(actor22))
87
- result = @adapter.get(@feature)
88
- assert_equal Set['asdf'], result[:actors]
113
+ assert_equal true, @feature.disable(actor22)
114
+ refute @feature.enabled?(actor22)
115
+ assert @feature.enabled?(actor_asdf)
89
116
 
90
- assert_equal true, @adapter.disable(@feature, @actor_gate, @flipper.actor(actor_asdf))
91
- result = @adapter.get(@feature)
92
- assert_equal Set.new, result[:actors]
117
+ assert_equal true, @feature.disable(actor_asdf)
118
+ refute @feature.enabled?(actor22)
119
+ refute @feature.enabled?(actor_asdf)
93
120
  end
94
121
 
95
122
  def test_can_enable_disable_get_value_for_percentage_of_actors_gate
96
- assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(15))
123
+ assert_equal true, @adapter.enable(@feature, @actors_gate, Flipper::Types::PercentageOfActors.new(15))
97
124
  result = @adapter.get(@feature)
98
125
  assert_equal '15', result[:percentage_of_actors]
99
126
 
100
- assert_equal true, @adapter.disable(@feature, @actors_gate, @flipper.actors(0))
127
+ assert_equal true, @adapter.disable(@feature, @actors_gate, Flipper::Types::PercentageOfActors.new(0))
101
128
  result = @adapter.get(@feature)
102
129
  assert_equal '0', result[:percentage_of_actors]
103
130
  end
104
131
 
105
132
  def test_can_enable_percentage_of_actors_gate_many_times_and_consistently_return_values
106
133
  (1..100).each do |percentage|
107
- assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(percentage))
134
+ assert_equal true, @adapter.enable(@feature, @actors_gate, Flipper::Types::PercentageOfActors.new(percentage))
108
135
  result = @adapter.get(@feature)
109
136
  assert_equal percentage.to_s, result[:percentage_of_actors]
110
137
  end
@@ -112,25 +139,25 @@ module Flipper
112
139
 
113
140
  def test_can_disable_percentage_of_actors_gate_many_times_and_consistently_return_values
114
141
  (1..100).each do |percentage|
115
- assert_equal true, @adapter.disable(@feature, @actors_gate, @flipper.actors(percentage))
142
+ assert_equal true, @adapter.disable(@feature, @actors_gate, Flipper::Types::PercentageOfActors.new(percentage))
116
143
  result = @adapter.get(@feature)
117
144
  assert_equal percentage.to_s, result[:percentage_of_actors]
118
145
  end
119
146
  end
120
147
 
121
148
  def test_can_enable_disable_and_get_value_for_percentage_of_time_gate
122
- assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(10))
149
+ assert_equal true, @adapter.enable(@feature, @time_gate, Flipper::Types::PercentageOfTime.new(10))
123
150
  result = @adapter.get(@feature)
124
151
  assert_equal '10', result[:percentage_of_time]
125
152
 
126
- assert_equal true, @adapter.disable(@feature, @time_gate, @flipper.time(0))
153
+ assert_equal true, @adapter.disable(@feature, @time_gate, Flipper::Types::PercentageOfTime.new(0))
127
154
  result = @adapter.get(@feature)
128
155
  assert_equal '0', result[:percentage_of_time]
129
156
  end
130
157
 
131
158
  def test_can_enable_percentage_of_time_gate_many_times_and_consistently_return_values
132
159
  (1..100).each do |percentage|
133
- assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(percentage))
160
+ assert_equal true, @adapter.enable(@feature, @time_gate, Flipper::Types::PercentageOfTime.new(percentage))
134
161
  result = @adapter.get(@feature)
135
162
  assert_equal percentage.to_s, result[:percentage_of_time]
136
163
  end
@@ -138,23 +165,23 @@ module Flipper
138
165
 
139
166
  def test_can_disable_percentage_of_time_gate_many_times_and_consistently_return_values
140
167
  (1..100).each do |percentage|
141
- assert_equal true, @adapter.disable(@feature, @time_gate, @flipper.time(percentage))
168
+ assert_equal true, @adapter.disable(@feature, @time_gate, Flipper::Types::PercentageOfTime.new(percentage))
142
169
  result = @adapter.get(@feature)
143
170
  assert_equal percentage.to_s, result[:percentage_of_time]
144
171
  end
145
172
  end
146
173
 
147
174
  def test_converts_boolean_value_to_a_string
148
- assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
175
+ assert_equal true, @adapter.enable(@feature, @boolean_gate, Flipper::Types::Boolean.new)
149
176
  result = @adapter.get(@feature)
150
177
  assert_equal 'true', result[:boolean]
151
178
  end
152
179
 
153
180
  def test_converts_the_actor_value_to_a_string
154
- assert_equal true,
155
- @adapter.enable(@feature, @actor_gate, @flipper.actor(Flipper::Actor.new(22)))
156
- result = @adapter.get(@feature)
157
- assert_equal Set['22'], result[:actors]
181
+ actor = Flipper::Actor.new(22)
182
+ refute @feature.enabled?(actor)
183
+ @feature.enable_actor actor
184
+ assert @feature.enabled?(actor)
158
185
  end
159
186
 
160
187
  def test_converts_group_value_to_a_string
@@ -164,13 +191,13 @@ module Flipper
164
191
  end
165
192
 
166
193
  def test_converts_percentage_of_time_integer_value_to_a_string
167
- assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(10))
194
+ assert_equal true, @adapter.enable(@feature, @time_gate, Flipper::Types::PercentageOfTime.new(10))
168
195
  result = @adapter.get(@feature)
169
196
  assert_equal '10', result[:percentage_of_time]
170
197
  end
171
198
 
172
199
  def test_converts_percentage_of_actors_integer_value_to_a_string
173
- assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(10))
200
+ assert_equal true, @adapter.enable(@feature, @actors_gate, Flipper::Types::PercentageOfActors.new(10))
174
201
  result = @adapter.get(@feature)
175
202
  assert_equal '10', result[:percentage_of_actors]
176
203
  end
@@ -193,11 +220,11 @@ module Flipper
193
220
 
194
221
  def test_clears_all_the_gate_values_for_the_feature_on_remove
195
222
  actor22 = Flipper::Actor.new('22')
196
- assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
223
+ assert_equal true, @adapter.enable(@feature, @boolean_gate, Flipper::Types::Boolean.new)
197
224
  assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
198
- assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor22))
199
- assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(25))
200
- assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(45))
225
+ assert_equal true, @adapter.enable(@feature, @actor_gate, Flipper::Types::Actor.new(actor22))
226
+ assert_equal true, @adapter.enable(@feature, @actors_gate, Flipper::Types::PercentageOfActors.new(25))
227
+ assert_equal true, @adapter.enable(@feature, @time_gate, Flipper::Types::PercentageOfTime.new(45))
201
228
 
202
229
  assert_equal true, @adapter.remove(@feature)
203
230
 
@@ -209,11 +236,11 @@ module Flipper
209
236
  @adapter.add(@feature)
210
237
  assert_includes @adapter.features, @feature.key
211
238
 
212
- assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
239
+ assert_equal true, @adapter.enable(@feature, @boolean_gate, Flipper::Types::Boolean.new)
213
240
  assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
214
- assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor22))
215
- assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(25))
216
- assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(45))
241
+ assert_equal true, @adapter.enable(@feature, @actor_gate, Flipper::Types::Actor.new(actor22))
242
+ assert_equal true, @adapter.enable(@feature, @actors_gate, Flipper::Types::PercentageOfActors.new(25))
243
+ assert_equal true, @adapter.enable(@feature, @time_gate, Flipper::Types::PercentageOfTime.new(45))
217
244
 
218
245
  assert_equal true, @adapter.clear(@feature)
219
246
  assert_includes @adapter.features, @feature.key
@@ -226,7 +253,7 @@ module Flipper
226
253
 
227
254
  def test_can_get_multiple_features
228
255
  assert @adapter.add(@flipper[:stats])
229
- assert @adapter.enable(@flipper[:stats], @boolean_gate, @flipper.boolean)
256
+ assert @adapter.enable(@flipper[:stats], @boolean_gate, Flipper::Types::Boolean.new)
230
257
  assert @adapter.add(@flipper[:search])
231
258
 
232
259
  result = @adapter.get_multi([@flipper[:stats], @flipper[:search], @flipper[:other]])
@@ -242,16 +269,16 @@ module Flipper
242
269
 
243
270
  def test_can_get_all_features
244
271
  assert @adapter.add(@flipper[:stats])
245
- assert @adapter.enable(@flipper[:stats], @boolean_gate, @flipper.boolean)
272
+ assert @adapter.enable(@flipper[:stats], @boolean_gate, Flipper::Types::Boolean.new)
246
273
  assert @adapter.add(@flipper[:search])
274
+ @flipper.enable :analytics, Flipper.property(:plan).eq("pro")
247
275
 
248
276
  result = @adapter.get_all
249
- assert_instance_of Hash, result
250
277
 
251
- stats = result["stats"]
252
- search = result["search"]
253
- assert_equal @adapter.default_config.merge(boolean: 'true'), stats
254
- assert_equal @adapter.default_config, search
278
+ assert_instance_of Hash, result
279
+ assert_equal @adapter.default_config.merge(boolean: 'true'), result["stats"]
280
+ assert_equal @adapter.default_config, result["search"]
281
+ assert_equal @adapter.default_config.merge(expression: {"Equal"=>[{"Property"=>["plan"]}, "pro"]}), result["analytics"]
255
282
  end
256
283
 
257
284
  def test_includes_explicitly_disabled_features_when_getting_all_features
@@ -265,9 +292,9 @@ module Flipper
265
292
 
266
293
  def test_can_double_enable_an_actor_without_error
267
294
  actor = Flipper::Actor.new('Flipper::Actor;22')
268
- assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor))
269
- assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor))
270
- assert_equal Set['Flipper::Actor;22'], @adapter.get(@feature).fetch(:actors)
295
+ assert_equal true, @feature.enable(actor)
296
+ assert_equal true, @feature.enable(actor)
297
+ assert @feature.enabled?(actor)
271
298
  end
272
299
 
273
300
  def test_can_double_enable_a_group_without_error
@@ -275,6 +302,47 @@ module Flipper
275
302
  assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
276
303
  assert_equal Set['admins'], @adapter.get(@feature).fetch(:groups)
277
304
  end
305
+
306
+ def test_can_double_enable_percentage_without_error
307
+ assert_equal true, @adapter.enable(@feature, @actors_gate, Flipper::Types::PercentageOfActors.new(25))
308
+ assert_equal true, @adapter.enable(@feature, @actors_gate, Flipper::Types::PercentageOfActors.new(25))
309
+ end
310
+
311
+ def test_can_double_enable_without_error
312
+ assert_equal true, @adapter.enable(@feature, @boolean_gate, Flipper::Types::Boolean.new)
313
+ assert_equal true, @adapter.enable(@feature, @boolean_gate, Flipper::Types::Boolean.new)
314
+ end
315
+
316
+ def test_can_get_all_features_when_there_are_none
317
+ expected = {}
318
+ assert_equal Set.new, @adapter.features
319
+ assert_equal expected, @adapter.get_all
320
+ end
321
+
322
+ def test_clears_other_gate_values_on_enable
323
+ actor = Flipper::Actor.new('Flipper::Actor;22')
324
+ assert_equal true, @adapter.enable(@feature, @actors_gate, Flipper::Types::PercentageOfActors.new(25))
325
+ assert_equal true, @adapter.enable(@feature, @time_gate, Flipper::Types::PercentageOfTime.new(25))
326
+ assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
327
+ assert_equal true, @adapter.enable(@feature, @actor_gate, Flipper::Types::Actor.new(actor))
328
+ assert_equal true, @adapter.enable(@feature, @boolean_gate, Flipper::Types::Boolean.new(true))
329
+ assert_equal @adapter.default_config.merge(boolean: "true"), @adapter.get(@feature)
330
+ end
331
+
332
+ def test_can_import_and_export
333
+ adapter = Flipper::Adapters::Memory.new
334
+ source_flipper = Flipper.new(adapter)
335
+ source_flipper.enable(:stats)
336
+ export = adapter.export
337
+
338
+ # some adapters cannot import so if they return false lets assert it
339
+ # didn't happen
340
+ if @adapter.import(export)
341
+ assert @flipper[:stats].enabled?
342
+ else
343
+ refute @flipper[:stats].enabled?
344
+ end
345
+ end
278
346
  end
279
347
  end
280
348
  end