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.
- checksums.yaml +5 -5
- data/.codeclimate.yml +1 -0
- data/.github/FUNDING.yml +1 -0
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ci.yml +110 -0
- data/.github/workflows/examples.yml +105 -0
- data/.github/workflows/release.yml +54 -0
- data/.rspec +1 -0
- data/CLAUDE.md +87 -0
- data/Changelog.md +2 -215
- data/Dockerfile +1 -1
- data/Gemfile +28 -20
- data/README.md +72 -62
- data/Rakefile +13 -3
- data/benchmark/enabled_ips.rb +10 -0
- data/benchmark/enabled_multiple_actors_ips.rb +20 -0
- data/benchmark/enabled_profile.rb +20 -0
- data/benchmark/instrumentation_ips.rb +21 -0
- data/benchmark/typecast_ips.rb +27 -0
- data/docker-compose.yml +37 -34
- data/docs/DockerCompose.md +0 -1
- data/docs/README.md +1 -0
- data/docs/images/banner.jpg +0 -0
- data/docs/images/flipper_cloud.png +0 -0
- data/examples/api/basic.ru +18 -0
- data/examples/api/custom_memoized.ru +36 -0
- data/examples/api/memoized.ru +42 -0
- data/examples/basic.rb +1 -12
- data/examples/cloud/app.ru +12 -0
- data/examples/cloud/backoff_policy.rb +13 -0
- data/examples/cloud/basic.rb +22 -0
- data/examples/cloud/cloud_setup.rb +20 -0
- data/examples/cloud/forked.rb +36 -0
- data/examples/cloud/import.rb +17 -0
- data/examples/cloud/poll_interval/README.md +111 -0
- data/examples/cloud/poll_interval/client.rb +108 -0
- data/examples/cloud/poll_interval/server.rb +98 -0
- data/examples/cloud/threaded.rb +33 -0
- data/examples/configuring_default.rb +2 -5
- data/examples/dsl.rb +10 -35
- data/examples/enabled_for_actor.rb +10 -15
- data/examples/expressions.rb +237 -0
- data/examples/group.rb +3 -6
- data/examples/group_dynamic_lookup.rb +5 -19
- data/examples/group_with_members.rb +4 -14
- data/examples/importing.rb +1 -1
- data/examples/individual_actor.rb +2 -5
- data/examples/instrumentation.rb +2 -2
- data/examples/instrumentation_last_accessed_at.rb +38 -0
- data/examples/memoizing.rb +35 -0
- data/examples/mirroring.rb +59 -0
- data/examples/percentage_of_actors.rb +6 -16
- data/examples/percentage_of_actors_enabled_check.rb +7 -10
- data/examples/percentage_of_actors_group.rb +5 -18
- data/examples/percentage_of_time.rb +3 -6
- data/examples/strict.rb +18 -0
- data/exe/flipper +5 -0
- data/flipper-cloud.gemspec +19 -0
- data/flipper.gemspec +10 -7
- data/lib/flipper/actor.rb +10 -3
- data/lib/flipper/adapter.rb +50 -8
- data/lib/flipper/adapter_builder.rb +44 -0
- data/lib/flipper/adapters/actor_limit.rb +54 -0
- data/lib/flipper/adapters/cache_base.rb +161 -0
- data/lib/flipper/adapters/dual_write.rb +63 -0
- data/lib/flipper/adapters/failover.rb +85 -0
- data/lib/flipper/adapters/failsafe.rb +72 -0
- data/lib/flipper/adapters/http/client.rb +64 -7
- data/lib/flipper/adapters/http/error.rb +19 -1
- data/lib/flipper/adapters/http.rb +97 -43
- data/lib/flipper/adapters/instrumented.rb +47 -26
- data/lib/flipper/adapters/memoizable.rb +44 -40
- data/lib/flipper/adapters/memory.rb +75 -111
- data/lib/flipper/adapters/operation_logger.rb +22 -78
- data/lib/flipper/adapters/poll/poller.rb +2 -0
- data/lib/flipper/adapters/poll.rb +52 -0
- data/lib/flipper/adapters/pstore.rb +27 -17
- data/lib/flipper/adapters/read_only.rb +8 -41
- data/lib/flipper/adapters/strict.rb +45 -0
- data/lib/flipper/adapters/sync/feature_synchronizer.rb +14 -1
- data/lib/flipper/adapters/sync/interval_synchronizer.rb +2 -7
- data/lib/flipper/adapters/sync/synchronizer.rb +13 -6
- data/lib/flipper/adapters/sync.rb +23 -29
- data/lib/flipper/adapters/wrapper.rb +54 -0
- data/lib/flipper/cli.rb +314 -0
- data/lib/flipper/cloud/configuration.rb +271 -0
- data/lib/flipper/cloud/dsl.rb +27 -0
- data/lib/flipper/cloud/message_verifier.rb +95 -0
- data/lib/flipper/cloud/middleware.rb +63 -0
- data/lib/flipper/cloud/migrate.rb +71 -0
- data/lib/flipper/cloud/routes.rb +14 -0
- data/lib/flipper/cloud/telemetry/backoff_policy.rb +96 -0
- data/lib/flipper/cloud/telemetry/instrumenter.rb +22 -0
- data/lib/flipper/cloud/telemetry/metric.rb +39 -0
- data/lib/flipper/cloud/telemetry/metric_storage.rb +30 -0
- data/lib/flipper/cloud/telemetry/submitter.rb +100 -0
- data/lib/flipper/cloud/telemetry.rb +191 -0
- data/lib/flipper/cloud.rb +54 -0
- data/lib/flipper/configuration.rb +54 -7
- data/lib/flipper/dsl.rb +58 -47
- data/lib/flipper/engine.rb +102 -0
- data/lib/flipper/errors.rb +3 -21
- data/lib/flipper/export.rb +24 -0
- data/lib/flipper/exporter.rb +17 -0
- data/lib/flipper/exporters/json/export.rb +32 -0
- data/lib/flipper/exporters/json/v1.rb +33 -0
- data/lib/flipper/expression/builder.rb +73 -0
- data/lib/flipper/expression/constant.rb +25 -0
- data/lib/flipper/expression.rb +71 -0
- data/lib/flipper/expressions/all.rb +9 -0
- data/lib/flipper/expressions/any.rb +9 -0
- data/lib/flipper/expressions/boolean.rb +9 -0
- data/lib/flipper/expressions/comparable.rb +13 -0
- data/lib/flipper/expressions/equal.rb +9 -0
- data/lib/flipper/expressions/feature_enabled.rb +34 -0
- data/lib/flipper/expressions/greater_than.rb +9 -0
- data/lib/flipper/expressions/greater_than_or_equal_to.rb +9 -0
- data/lib/flipper/expressions/less_than.rb +9 -0
- data/lib/flipper/expressions/less_than_or_equal_to.rb +9 -0
- data/lib/flipper/expressions/not_equal.rb +9 -0
- data/lib/flipper/expressions/now.rb +9 -0
- data/lib/flipper/expressions/number.rb +9 -0
- data/lib/flipper/expressions/percentage.rb +9 -0
- data/lib/flipper/expressions/percentage_of_actors.rb +12 -0
- data/lib/flipper/expressions/property.rb +9 -0
- data/lib/flipper/expressions/random.rb +9 -0
- data/lib/flipper/expressions/string.rb +9 -0
- data/lib/flipper/expressions/time.rb +16 -0
- data/lib/flipper/feature.rb +95 -28
- data/lib/flipper/feature_check_context.rb +10 -6
- data/lib/flipper/gate.rb +13 -11
- data/lib/flipper/gate_values.rb +5 -18
- data/lib/flipper/gates/actor.rb +10 -17
- data/lib/flipper/gates/boolean.rb +1 -1
- data/lib/flipper/gates/expression.rb +75 -0
- data/lib/flipper/gates/group.rb +5 -7
- data/lib/flipper/gates/percentage_of_actors.rb +10 -13
- data/lib/flipper/gates/percentage_of_time.rb +1 -2
- data/lib/flipper/identifier.rb +17 -0
- data/lib/flipper/instrumentation/log_subscriber.rb +35 -8
- data/lib/flipper/instrumentation/statsd.rb +4 -2
- data/lib/flipper/instrumentation/statsd_subscriber.rb +2 -4
- data/lib/flipper/instrumentation/subscriber.rb +8 -5
- data/lib/flipper/instrumenters/memory.rb +6 -2
- data/lib/flipper/metadata.rb +8 -1
- data/lib/flipper/middleware/memoizer.rb +46 -27
- data/lib/flipper/middleware/setup_env.rb +13 -3
- data/lib/flipper/model/active_record.rb +23 -0
- data/lib/flipper/poller.rb +157 -0
- data/lib/flipper/serializers/gzip.rb +22 -0
- data/lib/flipper/serializers/json.rb +17 -0
- data/lib/flipper/spec/shared_adapter_specs.rb +122 -56
- data/lib/flipper/test/shared_adapter_test.rb +120 -52
- data/lib/flipper/test_help.rb +43 -0
- data/lib/flipper/typecast.rb +59 -18
- data/lib/flipper/types/actor.rb +19 -13
- data/lib/flipper/types/group.rb +12 -5
- data/lib/flipper/types/percentage.rb +1 -1
- data/lib/flipper/version.rb +11 -1
- data/lib/flipper.rb +71 -12
- data/lib/generators/flipper/setup_generator.rb +68 -0
- data/lib/generators/flipper/templates/initializer.rb +45 -0
- data/lib/generators/flipper/templates/update/migrations/01_create_flipper_tables.rb.erb +22 -0
- data/lib/generators/flipper/templates/update/migrations/02_change_flipper_gates_value_to_text.rb.erb +18 -0
- data/lib/generators/flipper/update_generator.rb +35 -0
- data/package-lock.json +41 -0
- data/package.json +10 -0
- data/spec/fixtures/environment.rb +1 -0
- data/spec/fixtures/flipper_pstore_1679087600.json +46 -0
- data/spec/flipper/actor_spec.rb +10 -2
- data/spec/flipper/adapter_builder_spec.rb +72 -0
- data/spec/flipper/adapter_spec.rb +52 -6
- data/spec/flipper/adapters/actor_limit_spec.rb +75 -0
- data/spec/flipper/adapters/dual_write_spec.rb +82 -0
- data/spec/flipper/adapters/failover_spec.rb +141 -0
- data/spec/flipper/adapters/failsafe_spec.rb +58 -0
- data/spec/flipper/adapters/http/client_spec.rb +61 -0
- data/spec/flipper/adapters/http_spec.rb +402 -65
- data/spec/flipper/adapters/instrumented_spec.rb +31 -13
- data/spec/flipper/adapters/memoizable_spec.rb +51 -33
- data/spec/flipper/adapters/memory_spec.rb +33 -5
- data/spec/flipper/adapters/operation_logger_spec.rb +38 -12
- data/spec/flipper/adapters/poll_spec.rb +41 -0
- data/spec/flipper/adapters/pstore_spec.rb +0 -2
- data/spec/flipper/adapters/read_only_spec.rb +32 -18
- data/spec/flipper/adapters/strict_spec.rb +64 -0
- data/spec/flipper/adapters/sync/feature_synchronizer_spec.rb +39 -1
- data/spec/flipper/adapters/sync/interval_synchronizer_spec.rb +4 -5
- data/spec/flipper/adapters/sync/synchronizer_spec.rb +87 -1
- data/spec/flipper/adapters/sync_spec.rb +17 -6
- data/spec/flipper/cli_spec.rb +217 -0
- data/spec/flipper/cloud/configuration_spec.rb +257 -0
- data/spec/flipper/cloud/dsl_spec.rb +90 -0
- data/spec/flipper/cloud/message_verifier_spec.rb +104 -0
- data/spec/flipper/cloud/middleware_spec.rb +307 -0
- data/spec/flipper/cloud/migrate_spec.rb +160 -0
- data/spec/flipper/cloud/telemetry/backoff_policy_spec.rb +107 -0
- data/spec/flipper/cloud/telemetry/metric_spec.rb +87 -0
- data/spec/flipper/cloud/telemetry/metric_storage_spec.rb +58 -0
- data/spec/flipper/cloud/telemetry/submitter_spec.rb +145 -0
- data/spec/flipper/cloud/telemetry_spec.rb +208 -0
- data/spec/flipper/cloud_spec.rb +186 -0
- data/spec/flipper/configuration_spec.rb +37 -3
- data/spec/flipper/dsl_spec.rb +67 -80
- data/spec/flipper/engine_spec.rb +374 -0
- data/spec/flipper/export_spec.rb +13 -0
- data/spec/flipper/exporter_spec.rb +16 -0
- data/spec/flipper/exporters/json/export_spec.rb +60 -0
- data/spec/flipper/exporters/json/v1_spec.rb +33 -0
- data/spec/flipper/expression/builder_spec.rb +248 -0
- data/spec/flipper/expression_spec.rb +188 -0
- data/spec/flipper/expressions/all_spec.rb +15 -0
- data/spec/flipper/expressions/any_spec.rb +15 -0
- data/spec/flipper/expressions/boolean_spec.rb +15 -0
- data/spec/flipper/expressions/equal_spec.rb +24 -0
- data/spec/flipper/expressions/greater_than_or_equal_to_spec.rb +28 -0
- data/spec/flipper/expressions/greater_than_spec.rb +28 -0
- data/spec/flipper/expressions/less_than_or_equal_to_spec.rb +28 -0
- data/spec/flipper/expressions/less_than_spec.rb +32 -0
- data/spec/flipper/expressions/not_equal_spec.rb +15 -0
- data/spec/flipper/expressions/now_spec.rb +11 -0
- data/spec/flipper/expressions/number_spec.rb +21 -0
- data/spec/flipper/expressions/percentage_of_actors_spec.rb +20 -0
- data/spec/flipper/expressions/percentage_spec.rb +15 -0
- data/spec/flipper/expressions/property_spec.rb +13 -0
- data/spec/flipper/expressions/random_spec.rb +9 -0
- data/spec/flipper/expressions/string_spec.rb +11 -0
- data/spec/flipper/expressions/time_spec.rb +29 -0
- data/spec/flipper/feature_check_context_spec.rb +18 -20
- data/spec/flipper/feature_spec.rb +461 -48
- data/spec/flipper/gate_spec.rb +0 -2
- data/spec/flipper/gate_values_spec.rb +2 -34
- data/spec/flipper/gates/actor_spec.rb +0 -2
- data/spec/flipper/gates/boolean_spec.rb +1 -3
- data/spec/flipper/gates/expression_spec.rb +190 -0
- data/spec/flipper/gates/group_spec.rb +2 -5
- data/spec/flipper/gates/percentage_of_actors_spec.rb +61 -7
- data/spec/flipper/gates/percentage_of_time_spec.rb +2 -4
- data/spec/flipper/identifier_spec.rb +12 -0
- data/spec/flipper/instrumentation/log_subscriber_spec.rb +24 -7
- data/spec/flipper/instrumentation/statsd_subscriber_spec.rb +26 -3
- data/spec/flipper/instrumenters/memory_spec.rb +18 -1
- data/spec/flipper/instrumenters/noop_spec.rb +14 -8
- data/spec/flipper/middleware/memoizer_spec.rb +199 -62
- data/spec/flipper/middleware/setup_env_spec.rb +23 -5
- data/spec/flipper/model/active_record_spec.rb +72 -0
- data/spec/flipper/poller_spec.rb +390 -0
- data/spec/flipper/registry_spec.rb +0 -1
- data/spec/flipper/serializers/gzip_spec.rb +13 -0
- data/spec/flipper/serializers/json_spec.rb +13 -0
- data/spec/flipper/typecast_spec.rb +121 -7
- data/spec/flipper/types/actor_spec.rb +63 -47
- data/spec/flipper/types/boolean_spec.rb +0 -1
- data/spec/flipper/types/group_spec.rb +24 -3
- data/spec/flipper/types/percentage_of_actors_spec.rb +0 -1
- data/spec/flipper/types/percentage_of_time_spec.rb +0 -1
- data/spec/flipper/types/percentage_spec.rb +0 -1
- data/spec/{integration_spec.rb → flipper_integration_spec.rb} +301 -59
- data/spec/flipper_spec.rb +123 -29
- data/spec/{helper.rb → spec_helper.rb} +23 -21
- data/spec/support/actor_names.yml +1 -0
- data/spec/support/descriptions.yml +1 -0
- data/spec/support/fail_on_output.rb +8 -0
- data/spec/support/fake_backoff_policy.rb +15 -0
- data/spec/support/skippable.rb +18 -0
- data/spec/support/spec_helpers.rb +53 -6
- data/test/adapters/actor_limit_test.rb +20 -0
- data/test/test_helper.rb +2 -1
- data/test_rails/generators/flipper/setup_generator_test.rb +69 -0
- data/test_rails/generators/flipper/update_generator_test.rb +96 -0
- data/test_rails/helper.rb +31 -0
- data/test_rails/system/test_help_test.rb +52 -0
- metadata +200 -82
- data/.rubocop.yml +0 -54
- data/.rubocop_todo.yml +0 -199
- data/docs/Adapters.md +0 -124
- data/docs/Caveats.md +0 -4
- data/docs/Gates.md +0 -167
- data/docs/Instrumentation.md +0 -27
- data/docs/Optimization.md +0 -114
- data/docs/api/README.md +0 -849
- data/docs/http/README.md +0 -35
- data/docs/read-only/README.md +0 -21
- data/examples/example_setup.rb +0 -8
- data/test/helper.rb +0 -11
data/spec/flipper_spec.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'flipper/cloud'
|
|
2
2
|
|
|
3
3
|
RSpec.describe Flipper do
|
|
4
4
|
describe '.new' do
|
|
@@ -64,7 +64,12 @@ RSpec.describe Flipper do
|
|
|
64
64
|
|
|
65
65
|
describe "delegation to instance" do
|
|
66
66
|
let(:group) { Flipper::Types::Group.new(:admins) }
|
|
67
|
-
let(:actor) {
|
|
67
|
+
let(:actor) {
|
|
68
|
+
Flipper::Actor.new("1", {
|
|
69
|
+
"plan" => "basic",
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
let(:expression) { Flipper.property(:plan).eq("basic") }
|
|
68
73
|
|
|
69
74
|
before do
|
|
70
75
|
described_class.configure do |config|
|
|
@@ -88,12 +93,35 @@ RSpec.describe Flipper do
|
|
|
88
93
|
expect(described_class.instance.enabled?(:search)).to be(false)
|
|
89
94
|
end
|
|
90
95
|
|
|
91
|
-
it 'delegates
|
|
92
|
-
expect(described_class.
|
|
96
|
+
it 'delegates expression to instance' do
|
|
97
|
+
expect(described_class.expression(:search)).to be(nil)
|
|
98
|
+
|
|
99
|
+
expression = Flipper.property(:plan).eq("basic")
|
|
100
|
+
Flipper.instance.enable_expression :search, expression
|
|
101
|
+
|
|
102
|
+
expect(described_class.expression(:search)).to eq(expression)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it 'delegates enable_expression to instance' do
|
|
106
|
+
described_class.enable_expression(:search, expression)
|
|
107
|
+
expect(described_class.instance.enabled?(:search, actor)).to be(true)
|
|
93
108
|
end
|
|
94
109
|
|
|
95
|
-
it 'delegates
|
|
96
|
-
|
|
110
|
+
it 'delegates disable_expression to instance' do
|
|
111
|
+
described_class.disable_expression(:search)
|
|
112
|
+
expect(described_class.instance.enabled?(:search, actor)).to be(false)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it 'delegates add_expression to instance' do
|
|
116
|
+
described_class.add_expression(:search, expression)
|
|
117
|
+
expect(described_class.instance.enabled?(:search, actor)).to be(true)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'delegates remove_expression to instance' do
|
|
121
|
+
described_class.enable_expression(:search, Flipper.any(expression))
|
|
122
|
+
expect(described_class.instance.enabled?(:search, actor)).to be(true)
|
|
123
|
+
described_class.remove_expression(:search, expression)
|
|
124
|
+
expect(described_class.instance.enabled?(:search, actor)).to be(false)
|
|
97
125
|
end
|
|
98
126
|
|
|
99
127
|
it 'delegates enable_actor to instance' do
|
|
@@ -106,10 +134,6 @@ RSpec.describe Flipper do
|
|
|
106
134
|
expect(described_class.instance.enabled?(:search, actor)).to be(false)
|
|
107
135
|
end
|
|
108
136
|
|
|
109
|
-
it 'delegates actor to instance' do
|
|
110
|
-
expect(described_class.actor(actor)).to eq(described_class.instance.actor(actor))
|
|
111
|
-
end
|
|
112
|
-
|
|
113
137
|
it 'delegates enable_group to instance' do
|
|
114
138
|
described_class.enable_group(:search, group)
|
|
115
139
|
expect(described_class.instance[:search].enabled_groups).to include(group)
|
|
@@ -130,15 +154,6 @@ RSpec.describe Flipper do
|
|
|
130
154
|
expect(described_class.instance[:search].percentage_of_actors_value).to be(0)
|
|
131
155
|
end
|
|
132
156
|
|
|
133
|
-
it 'delegates actors to instance' do
|
|
134
|
-
expect(described_class.actors(5)).to eq(described_class.instance.actors(5))
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
it 'delegates percentage_of_actors to instance' do
|
|
138
|
-
expected = described_class.instance.percentage_of_actors(5)
|
|
139
|
-
expect(described_class.percentage_of_actors(5)).to eq(expected)
|
|
140
|
-
end
|
|
141
|
-
|
|
142
157
|
it 'delegates enable_percentage_of_time to instance' do
|
|
143
158
|
described_class.enable_percentage_of_time(:search, 5)
|
|
144
159
|
expect(described_class.instance[:search].percentage_of_time_value).to be(5)
|
|
@@ -149,15 +164,6 @@ RSpec.describe Flipper do
|
|
|
149
164
|
expect(described_class.instance[:search].percentage_of_time_value).to be(0)
|
|
150
165
|
end
|
|
151
166
|
|
|
152
|
-
it 'delegates time to instance' do
|
|
153
|
-
expect(described_class.time(56)).to eq(described_class.instance.time(56))
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
it 'delegates percentage_of_time to instance' do
|
|
157
|
-
expected = described_class.instance.percentage_of_time(56)
|
|
158
|
-
expect(described_class.percentage_of_time(56)).to eq(expected)
|
|
159
|
-
end
|
|
160
|
-
|
|
161
167
|
it 'delegates features to instance' do
|
|
162
168
|
described_class.instance.add(:search)
|
|
163
169
|
expect(described_class.features).to eq(described_class.instance.features)
|
|
@@ -202,10 +208,21 @@ RSpec.describe Flipper do
|
|
|
202
208
|
expect(described_class.enabled?(:search)).to be(true)
|
|
203
209
|
end
|
|
204
210
|
|
|
211
|
+
it 'delegates export to instance' do
|
|
212
|
+
described_class.enable(:search)
|
|
213
|
+
expect(described_class.export).to eq(described_class.adapter.export)
|
|
214
|
+
expect(described_class.export(format: :json)).to eq(described_class.adapter.export(format: :json))
|
|
215
|
+
end
|
|
216
|
+
|
|
205
217
|
it 'delegates adapter to instance' do
|
|
206
218
|
expect(described_class.adapter).to eq(described_class.instance.adapter)
|
|
207
219
|
end
|
|
208
220
|
|
|
221
|
+
it 'delegates adapter_stack to instance' do
|
|
222
|
+
expect(described_class.adapter_stack).to eq(described_class.instance.adapter_stack)
|
|
223
|
+
expect(described_class.adapter_stack).to eq("memoizable -> memory")
|
|
224
|
+
end
|
|
225
|
+
|
|
209
226
|
it 'delegates memoize= to instance' do
|
|
210
227
|
expect(described_class.adapter.memoizing?).to be(false)
|
|
211
228
|
described_class.memoize = true
|
|
@@ -215,6 +232,35 @@ RSpec.describe Flipper do
|
|
|
215
232
|
it 'delegates memoizing? to instance' do
|
|
216
233
|
expect(described_class.memoizing?).to eq(described_class.adapter.memoizing?)
|
|
217
234
|
end
|
|
235
|
+
|
|
236
|
+
it 'delegates read_only? to instance' do
|
|
237
|
+
expect(described_class.read_only?).to eq(described_class.adapter.read_only?)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
it 'delegates sync stuff to instance and does nothing' do
|
|
241
|
+
expect(described_class.sync).to be(nil)
|
|
242
|
+
expect(described_class.sync_secret).to be(nil)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
it 'delegates sync stuff to instance for Flipper::Cloud' do
|
|
246
|
+
stub = stub_request(:get, "https://www.flippercloud.io/adapter/features?exclude_gate_names=true").
|
|
247
|
+
with({
|
|
248
|
+
headers: {
|
|
249
|
+
'flipper-cloud-token'=>'asdf',
|
|
250
|
+
},
|
|
251
|
+
}).to_return(status: 200, body: '{"features": {}}', headers: {})
|
|
252
|
+
cloud_configuration = Flipper::Cloud::Configuration.new({
|
|
253
|
+
token: "asdf",
|
|
254
|
+
sync_secret: "tasty",
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
described_class.configure do |config|
|
|
258
|
+
config.default { Flipper::Cloud::DSL.new(cloud_configuration) }
|
|
259
|
+
end
|
|
260
|
+
described_class.sync
|
|
261
|
+
expect(described_class.sync_secret).to eq("tasty")
|
|
262
|
+
expect(stub).to have_been_made.at_least_once
|
|
263
|
+
end
|
|
218
264
|
end
|
|
219
265
|
|
|
220
266
|
describe '.register' do
|
|
@@ -272,7 +318,7 @@ RSpec.describe Flipper do
|
|
|
272
318
|
|
|
273
319
|
describe '.group_exists' do
|
|
274
320
|
it 'returns true if the group is already created' do
|
|
275
|
-
|
|
321
|
+
described_class.register('admins', &:admin?)
|
|
276
322
|
expect(described_class.group_exists?(:admins)).to eq(true)
|
|
277
323
|
end
|
|
278
324
|
|
|
@@ -325,4 +371,52 @@ RSpec.describe Flipper do
|
|
|
325
371
|
expect(described_class.instance_variable_get('@groups_registry')).to eq(registry)
|
|
326
372
|
end
|
|
327
373
|
end
|
|
374
|
+
|
|
375
|
+
describe ".constant" do
|
|
376
|
+
it "returns Flipper::Expression::Constant instance" do
|
|
377
|
+
expect(described_class.constant(false)).to eq(Flipper::Expression::Constant.new(false))
|
|
378
|
+
expect(described_class.constant("string")).to eq(Flipper::Expression::Constant.new("string"))
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
describe ".property" do
|
|
383
|
+
it "returns Flipper::Expressions::Property expression" do
|
|
384
|
+
expect(Flipper.property("name")).to eq(Flipper::Expression.build(Property: "name"))
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
describe ".boolean" do
|
|
389
|
+
it "returns Flipper::Expressions::Boolean expression" do
|
|
390
|
+
expect(described_class.boolean(true)).to eq(Flipper::Expression.build(Boolean: true))
|
|
391
|
+
expect(described_class.boolean(false)).to eq(Flipper::Expression.build(Boolean: false))
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
describe ".random" do
|
|
396
|
+
it "returns Flipper::Expressions::Random expression" do
|
|
397
|
+
expect(Flipper.random(100)).to eq(Flipper::Expression.build(Random: 100))
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
describe ".any" do
|
|
402
|
+
let(:age_expression) { Flipper.property(:age).gte(21) }
|
|
403
|
+
let(:plan_expression) { Flipper.property(:plan).eq("basic") }
|
|
404
|
+
|
|
405
|
+
it "returns Flipper::Expressions::Any instance" do
|
|
406
|
+
expect(Flipper.any(age_expression, plan_expression)).to eq(
|
|
407
|
+
Flipper::Expression.build({Any: [age_expression, plan_expression]})
|
|
408
|
+
)
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
describe ".all" do
|
|
413
|
+
let(:age_expression) { Flipper.property(:age).gte(21) }
|
|
414
|
+
let(:plan_expression) { Flipper.property(:plan).eq("basic") }
|
|
415
|
+
|
|
416
|
+
it "returns Flipper::Expressions::All instance" do
|
|
417
|
+
expect(Flipper.all(age_expression, plan_expression)).to eq(
|
|
418
|
+
Flipper::Expression.build({All: [age_expression, plan_expression]})
|
|
419
|
+
)
|
|
420
|
+
end
|
|
421
|
+
end
|
|
328
422
|
end
|
|
@@ -2,25 +2,39 @@ $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
|
|
|
2
2
|
|
|
3
3
|
require 'pp'
|
|
4
4
|
require 'pathname'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
require 'rubygems'
|
|
8
|
-
require 'bundler'
|
|
5
|
+
require 'bundler/setup'
|
|
9
6
|
|
|
10
|
-
|
|
7
|
+
require 'warning'
|
|
8
|
+
Warning.ignore(/lib\/statsd/)
|
|
9
|
+
Warning.ignore(/lib\/debug\//)
|
|
10
|
+
Warning.ignore(/lib\/ice_age\//)
|
|
11
|
+
Warning.ignore(/lib\/moneta\//)
|
|
12
|
+
Warning.ignore(/lib\/mongo\//)
|
|
11
13
|
|
|
12
|
-
require '
|
|
14
|
+
require 'debug'
|
|
15
|
+
require 'statsd'
|
|
13
16
|
require 'webmock/rspec'
|
|
14
17
|
WebMock.disable_net_connect!(allow_localhost: true)
|
|
15
18
|
|
|
16
19
|
require 'flipper'
|
|
17
|
-
require 'flipper
|
|
18
|
-
require 'flipper
|
|
20
|
+
require 'flipper/api'
|
|
21
|
+
require 'flipper/spec/shared_adapter_specs'
|
|
22
|
+
require 'flipper/ui'
|
|
23
|
+
require 'flipper/test_help'
|
|
24
|
+
|
|
25
|
+
FlipperRoot = Pathname(__FILE__).dirname.join('..').expand_path
|
|
26
|
+
Dir[FlipperRoot.join('spec/support/**/*.rb')].sort.each { |f| require f }
|
|
19
27
|
|
|
20
|
-
|
|
28
|
+
# Disable telemetry logging in specs.
|
|
29
|
+
ENV["FLIPPER_CLOUD_LOGGING_ENABLED"] = "false"
|
|
21
30
|
|
|
22
31
|
RSpec.configure do |config|
|
|
23
32
|
config.before(:example) do
|
|
33
|
+
# default stub for telemetry
|
|
34
|
+
stub_request(:post, "https://www.flippercloud.io/adapter/telemetry").
|
|
35
|
+
to_return(status: 200, body: "", headers: {})
|
|
36
|
+
Flipper::Cloud::Telemetry.reset if defined?(Flipper::Cloud::Telemetry) && Flipper::Cloud::Telemetry.respond_to?(:reset)
|
|
37
|
+
Flipper::Poller.reset if defined?(Flipper::Poller)
|
|
24
38
|
Flipper.unregister_groups
|
|
25
39
|
Flipper.configuration = nil
|
|
26
40
|
end
|
|
@@ -89,15 +103,3 @@ RSpec.shared_examples_for 'a DSL feature' do
|
|
|
89
103
|
end.to raise_error(ArgumentError, /must be a String or Symbol/)
|
|
90
104
|
end
|
|
91
105
|
end
|
|
92
|
-
|
|
93
|
-
RSpec.shared_examples_for 'a DSL boolean method' do
|
|
94
|
-
it 'returns boolean with value set' do
|
|
95
|
-
result = subject.send(method_name, true)
|
|
96
|
-
expect(result).to be_instance_of(Flipper::Types::Boolean)
|
|
97
|
-
expect(result.value).to be(true)
|
|
98
|
-
|
|
99
|
-
result = subject.send(method_name, false)
|
|
100
|
-
expect(result).to be_instance_of(Flipper::Types::Boolean)
|
|
101
|
-
expect(result.value).to be(false)
|
|
102
|
-
end
|
|
103
|
-
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
actor_name_1: 'Actor #1'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
some_awesome_feature: 'Awesome feature description'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
RSpec.configure do |config|
|
|
2
|
+
config.before(:all) do
|
|
3
|
+
$skip = false
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def skip_on_error(error, message, &block)
|
|
7
|
+
# Premptively skip if we've already skipped
|
|
8
|
+
skip(message) if $skip
|
|
9
|
+
block.call
|
|
10
|
+
rescue error
|
|
11
|
+
if ENV["CI"]
|
|
12
|
+
raise
|
|
13
|
+
else
|
|
14
|
+
$skip = true
|
|
15
|
+
skip(message)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
require 'ice_age'
|
|
1
2
|
require 'json'
|
|
2
3
|
require 'rack/test'
|
|
4
|
+
require 'rack/session'
|
|
3
5
|
|
|
4
6
|
module SpecHelpers
|
|
7
|
+
extend self
|
|
8
|
+
|
|
5
9
|
def self.included(base)
|
|
6
10
|
base.let(:flipper) { build_flipper }
|
|
7
11
|
base.let(:app) { build_app(flipper) }
|
|
@@ -9,7 +13,7 @@ module SpecHelpers
|
|
|
9
13
|
|
|
10
14
|
def build_app(flipper, options = {})
|
|
11
15
|
Flipper::UI.app(flipper, options) do |builder|
|
|
12
|
-
builder.use Rack::Session::Cookie, secret: 'test'
|
|
16
|
+
builder.use Rack::Session::Cookie, secret: 'test' * 16 # Rack 3+ wants a 64-character secret
|
|
13
17
|
end
|
|
14
18
|
end
|
|
15
19
|
|
|
@@ -26,11 +30,15 @@ module SpecHelpers
|
|
|
26
30
|
end
|
|
27
31
|
|
|
28
32
|
def json_response
|
|
29
|
-
|
|
33
|
+
body = last_response.body
|
|
34
|
+
if last_response["content-encoding"] == 'gzip'
|
|
35
|
+
body = Flipper::Typecast.from_gzip(body)
|
|
36
|
+
end
|
|
37
|
+
JSON.parse(body)
|
|
30
38
|
end
|
|
31
39
|
|
|
32
40
|
def api_error_code_reference_url
|
|
33
|
-
'https://
|
|
41
|
+
'https://flippercloud.io/docs/api#error-code-reference'
|
|
34
42
|
end
|
|
35
43
|
|
|
36
44
|
def api_not_found_response
|
|
@@ -41,6 +49,14 @@ module SpecHelpers
|
|
|
41
49
|
}
|
|
42
50
|
end
|
|
43
51
|
|
|
52
|
+
def api_positive_percentage_error_response
|
|
53
|
+
{
|
|
54
|
+
'code' => 3,
|
|
55
|
+
'message' => 'Percentage must be a positive number less than or equal to 100.',
|
|
56
|
+
'more_info' => api_error_code_reference_url,
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
|
|
44
60
|
def api_flipper_id_is_missing_response
|
|
45
61
|
{
|
|
46
62
|
'code' => 4,
|
|
@@ -49,16 +65,47 @@ module SpecHelpers
|
|
|
49
65
|
}
|
|
50
66
|
end
|
|
51
67
|
|
|
52
|
-
def
|
|
68
|
+
def api_expression_invalid_response
|
|
53
69
|
{
|
|
54
|
-
'code' =>
|
|
55
|
-
'message' => '
|
|
70
|
+
'code' => 7,
|
|
71
|
+
'message' => 'The provided expression was not valid.',
|
|
56
72
|
'more_info' => api_error_code_reference_url,
|
|
57
73
|
}
|
|
58
74
|
end
|
|
75
|
+
|
|
76
|
+
def silence
|
|
77
|
+
# Store the original stderr and stdout in order to restore them later
|
|
78
|
+
original_stderr = $stderr
|
|
79
|
+
original_stdout = $stdout
|
|
80
|
+
|
|
81
|
+
# Redirect stderr and stdout
|
|
82
|
+
$stderr = $stdout = StringIO.new
|
|
83
|
+
|
|
84
|
+
yield
|
|
85
|
+
ensure
|
|
86
|
+
$stderr = original_stderr
|
|
87
|
+
$stdout = original_stdout
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def capture_output
|
|
91
|
+
original_stderr = $stderr
|
|
92
|
+
original_stdout = $stdout
|
|
93
|
+
|
|
94
|
+
output = $stdout = $stderr = StringIO.new
|
|
95
|
+
|
|
96
|
+
yield
|
|
97
|
+
|
|
98
|
+
output.string
|
|
99
|
+
ensure
|
|
100
|
+
$stderr = original_stderr
|
|
101
|
+
$stdout = original_stdout
|
|
102
|
+
end
|
|
59
103
|
end
|
|
60
104
|
|
|
61
105
|
RSpec.configure do |config|
|
|
106
|
+
config.order = :random
|
|
107
|
+
Kernel.srand config.seed
|
|
108
|
+
|
|
62
109
|
config.include Rack::Test::Methods
|
|
63
110
|
config.include SpecHelpers
|
|
64
111
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "flipper/test/shared_adapter_test"
|
|
3
|
+
require "flipper/adapters/actor_limit"
|
|
4
|
+
|
|
5
|
+
class Flipper::Adapters::ActorLimitTest < MiniTest::Test
|
|
6
|
+
prepend Flipper::Test::SharedAdapterTests
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@memory = Flipper::Adapters::Memory.new
|
|
10
|
+
@adapter = Flipper::Adapters::ActorLimit.new(@memory, 5)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def test_enable_fails_when_limit_exceeded
|
|
14
|
+
5.times { |i| @feature.enable Flipper::Actor.new("User;#{i}") }
|
|
15
|
+
|
|
16
|
+
assert_raises Flipper::Adapters::ActorLimit::LimitExceeded do
|
|
17
|
+
@feature.enable Flipper::Actor.new("User;6")
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/test/test_helper.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
require 'bundler/setup'
|
|
1
2
|
require 'flipper'
|
|
2
3
|
require 'minitest/autorun'
|
|
3
4
|
require 'minitest/unit'
|
|
4
|
-
Dir['./lib/flipper/test/*.rb'].each { |f| require(f) }
|
|
5
|
+
Dir['./lib/flipper/test/*.rb'].sort.each { |f| require(f) }
|
|
5
6
|
|
|
6
7
|
FlipperRoot = Pathname(__FILE__).dirname.join('..').expand_path
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require "helper"
|
|
2
|
+
require "generators/flipper/setup_generator"
|
|
3
|
+
|
|
4
|
+
class SetupGeneratorTest < Rails::Generators::TestCase
|
|
5
|
+
tests Flipper::Generators::SetupGenerator
|
|
6
|
+
ROOT = File.expand_path("../../../tmp/generators", __dir__)
|
|
7
|
+
destination ROOT
|
|
8
|
+
setup :prepare_destination
|
|
9
|
+
|
|
10
|
+
test "invokes flipper:active_record generator if ActiveRecord adapter defined" do
|
|
11
|
+
begin
|
|
12
|
+
load 'flipper/adapters/active_record.rb'
|
|
13
|
+
run_generator
|
|
14
|
+
assert_migration "db/migrate/create_flipper_tables.rb"
|
|
15
|
+
ensure
|
|
16
|
+
Flipper::Adapters.send(:remove_const, :ActiveRecord)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
test "generates an initializer" do
|
|
21
|
+
run_generator
|
|
22
|
+
assert_file 'config/initializers/flipper.rb', /Flipper\.configure/
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
test "does not invoke flipper:active_record generator if ActiveRecord adapter not defined" do
|
|
26
|
+
# Ensure adapter not defined
|
|
27
|
+
Flipper::Adapters.send(:remove_const, :ActiveRecord) rescue nil
|
|
28
|
+
|
|
29
|
+
run_generator
|
|
30
|
+
assert_no_migration "db/migrate/create_flipper_tables.rb"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
%w(.env.development .env.local .env).each do |file|
|
|
34
|
+
test "configures Flipper Cloud token in #{file} if it exists" do
|
|
35
|
+
File.write("#{ROOT}/#{file}", "")
|
|
36
|
+
run_generator %w(--token abc123)
|
|
37
|
+
assert_file file, /^FLIPPER_CLOUD_TOKEN=abc123$/m
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
test "configures Flipper Cloud token in .env.development before .env" do
|
|
42
|
+
File.write("#{ROOT}/.env.development", "")
|
|
43
|
+
File.write("#{ROOT}/.env", "")
|
|
44
|
+
|
|
45
|
+
run_generator %w(--token abc123)
|
|
46
|
+
assert_file ".env.development", /^FLIPPER_CLOUD_TOKEN=abc123$/m
|
|
47
|
+
assert_file ".env", ""
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
test "does not write to .env if no token provided" do
|
|
51
|
+
File.write("#{ROOT}/.env", "")
|
|
52
|
+
run_generator
|
|
53
|
+
assert_file ".env", ""
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
test "configures Flipper Cloud token in config/credentials.yml.enc if credentials.yml.enc exist" do
|
|
57
|
+
Dir.chdir(ROOT) do
|
|
58
|
+
FileUtils.mkdir_p("config")
|
|
59
|
+
ENV["RAILS_MASTER_KEY"] = "a" * 32
|
|
60
|
+
Rails.application = Class.new(Rails::Application)
|
|
61
|
+
Rails.application.credentials.write("")
|
|
62
|
+
|
|
63
|
+
run_generator %w(--token abc123)
|
|
64
|
+
assert_file "config/credentials.yml.enc"
|
|
65
|
+
expected_config = { flipper: { cloud_token: "abc123" } }
|
|
66
|
+
assert_equal expected_config, Rails.application.credentials.config
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require "helper"
|
|
2
|
+
require "generators/flipper/update_generator"
|
|
3
|
+
|
|
4
|
+
class UpdateGeneratorTest < Rails::Generators::TestCase
|
|
5
|
+
tests Flipper::Generators::UpdateGenerator
|
|
6
|
+
ROOT = File.expand_path("../../../../tmp/generators", __FILE__)
|
|
7
|
+
destination ROOT
|
|
8
|
+
setup :prepare_destination
|
|
9
|
+
|
|
10
|
+
setup do
|
|
11
|
+
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
teardown do
|
|
15
|
+
ActiveRecord::Base.connection.close
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
test "generates migrations" do
|
|
19
|
+
run_generator
|
|
20
|
+
|
|
21
|
+
assert_migration "db/migrate/create_flipper_tables.rb" do |migration|
|
|
22
|
+
assert_method :up, migration do |up|
|
|
23
|
+
assert_match(/create_table :flipper_features/, up)
|
|
24
|
+
assert_match(/create_table :flipper_gates/, up)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
assert_method :down, migration do |down|
|
|
28
|
+
assert_match(/drop_table :flipper_features/, down)
|
|
29
|
+
assert_match(/drop_table :flipper_gates/, down)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
assert_migration "db/migrate/change_flipper_gates_value_to_text.rb" do |migration|
|
|
34
|
+
[:up, :down].each do |dir|
|
|
35
|
+
assert_method :up, migration do |method|
|
|
36
|
+
assert_match(/change_column/, method)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
require_migrations
|
|
42
|
+
|
|
43
|
+
silence { CreateFlipperTables.migrate(:up) }
|
|
44
|
+
assert ActiveRecord::Base.connection.table_exists?(:flipper_features)
|
|
45
|
+
assert ActiveRecord::Base.connection.table_exists?(:flipper_gates)
|
|
46
|
+
|
|
47
|
+
assert ActiveRecord::Base.connection.column_exists?(:flipper_gates, :value, :string)
|
|
48
|
+
silence { ChangeFlipperGatesValueToText.migrate(:up) }
|
|
49
|
+
assert ActiveRecord::Base.connection.column_exists?(:flipper_gates, :value, :text)
|
|
50
|
+
|
|
51
|
+
silence { ChangeFlipperGatesValueToText.migrate(:down) }
|
|
52
|
+
assert ActiveRecord::Base.connection.column_exists?(:flipper_gates, :value, :string)
|
|
53
|
+
|
|
54
|
+
silence { CreateFlipperTables.migrate(:down) }
|
|
55
|
+
refute ActiveRecord::Base.connection.table_exists?(:flipper_features)
|
|
56
|
+
refute ActiveRecord::Base.connection.table_exists?(:flipper_gates)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
test "ChangeFlipperGatesValueToText is a noop if value is already text" do
|
|
60
|
+
self.class.generator_class = Flipper::Generators::ActiveRecordGenerator
|
|
61
|
+
run_generator
|
|
62
|
+
|
|
63
|
+
self.class.generator_class = Flipper::Generators::UpdateGenerator
|
|
64
|
+
run_generator
|
|
65
|
+
|
|
66
|
+
assert_migration "db/migrate/create_flipper_tables.rb" do |migration|
|
|
67
|
+
assert_method :up, migration do |up|
|
|
68
|
+
assert_match(/text :value/, up)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
assert_migration "db/migrate/change_flipper_gates_value_to_text.rb"
|
|
73
|
+
|
|
74
|
+
require_migrations
|
|
75
|
+
|
|
76
|
+
silence { CreateFlipperTables.migrate(:up) }
|
|
77
|
+
assert ActiveRecord::Base.connection.column_exists?(:flipper_gates, :value, :text)
|
|
78
|
+
|
|
79
|
+
assert_nothing_raised do
|
|
80
|
+
silence { ChangeFlipperGatesValueToText.migrate(:up) }
|
|
81
|
+
end
|
|
82
|
+
assert ActiveRecord::Base.connection.column_exists?(:flipper_gates, :value, :text)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def require_migrations
|
|
86
|
+
# If these are not reloaded, then test order can cause failures
|
|
87
|
+
Object.send(:remove_const, :CreateFlipperTables) if defined?(::CreateFlipperTables)
|
|
88
|
+
Object.send(:remove_const, :ChangeFlipperGatesValueToText) if defined?(::ChangeFlipperGatesValueToText)
|
|
89
|
+
|
|
90
|
+
Dir.glob("#{ROOT}/db/migrate/*.rb").each do |file|
|
|
91
|
+
assert_nothing_raised do
|
|
92
|
+
load file
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
require 'minitest/autorun'
|
|
4
|
+
require 'rails'
|
|
5
|
+
require 'rails/test_help'
|
|
6
|
+
|
|
7
|
+
require 'warning'
|
|
8
|
+
Warning.ignore(/lib\/capybara\//)
|
|
9
|
+
|
|
10
|
+
begin
|
|
11
|
+
ActiveSupport::TestCase.test_order = :random
|
|
12
|
+
rescue NoMethodError
|
|
13
|
+
# no biggie, means we are on older version of AS that doesn't have this option
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def silence
|
|
17
|
+
# Store the original stderr and stdout in order to restore them later
|
|
18
|
+
original_stderr = $stderr
|
|
19
|
+
original_stdout = $stdout
|
|
20
|
+
|
|
21
|
+
# Redirect stderr and stdout
|
|
22
|
+
output = $stderr = $stdout = StringIO.new
|
|
23
|
+
|
|
24
|
+
yield
|
|
25
|
+
|
|
26
|
+
$stderr = original_stderr
|
|
27
|
+
$stdout = original_stdout
|
|
28
|
+
|
|
29
|
+
# Return output
|
|
30
|
+
output.string
|
|
31
|
+
end
|