flipper 0.10.2 → 0.11.0.beta1
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 +4 -4
- data/.rubocop.yml +42 -0
- data/.rubocop_todo.yml +188 -0
- data/Changelog.md +10 -0
- data/Gemfile +6 -3
- data/README.md +4 -3
- data/Rakefile +13 -13
- data/docs/Adapters.md +2 -1
- data/docs/DockerCompose.md +6 -3
- data/docs/Gates.md +25 -3
- data/docs/Optimization.md +27 -5
- data/docs/api/README.md +73 -32
- data/docs/http/README.md +34 -0
- data/docs/read-only/README.md +22 -0
- data/examples/percentage_of_actors_group.rb +49 -0
- data/flipper.gemspec +15 -15
- data/lib/flipper.rb +2 -5
- data/lib/flipper/adapter.rb +10 -0
- data/lib/flipper/adapters/http.rb +147 -0
- data/lib/flipper/adapters/http/client.rb +83 -0
- data/lib/flipper/adapters/http/error.rb +14 -0
- data/lib/flipper/adapters/instrumented.rb +36 -36
- data/lib/flipper/adapters/memoizable.rb +2 -6
- data/lib/flipper/adapters/memory.rb +10 -9
- data/lib/flipper/adapters/operation_logger.rb +1 -1
- data/lib/flipper/adapters/pstore.rb +12 -11
- data/lib/flipper/adapters/read_only.rb +6 -6
- data/lib/flipper/dsl.rb +1 -3
- data/lib/flipper/feature.rb +11 -16
- data/lib/flipper/gate.rb +3 -3
- data/lib/flipper/gate_values.rb +6 -6
- data/lib/flipper/gates/group.rb +2 -2
- data/lib/flipper/gates/percentage_of_actors.rb +2 -2
- data/lib/flipper/instrumentation/log_subscriber.rb +2 -4
- data/lib/flipper/instrumentation/metriks.rb +1 -1
- data/lib/flipper/instrumentation/statsd.rb +1 -1
- data/lib/flipper/instrumentation/statsd_subscriber.rb +1 -3
- data/lib/flipper/instrumentation/subscriber.rb +11 -10
- data/lib/flipper/instrumenters/memory.rb +1 -5
- data/lib/flipper/instrumenters/noop.rb +1 -1
- data/lib/flipper/middleware/memoizer.rb +11 -27
- data/lib/flipper/middleware/setup_env.rb +44 -0
- data/lib/flipper/registry.rb +8 -10
- data/lib/flipper/spec/shared_adapter_specs.rb +45 -67
- data/lib/flipper/test/shared_adapter_test.rb +25 -31
- data/lib/flipper/typecast.rb +2 -2
- data/lib/flipper/types/actor.rb +2 -4
- data/lib/flipper/types/group.rb +1 -1
- data/lib/flipper/types/percentage.rb +2 -1
- data/lib/flipper/version.rb +1 -1
- data/spec/fixtures/feature.json +31 -0
- data/spec/flipper/adapters/http_spec.rb +148 -0
- data/spec/flipper/adapters/instrumented_spec.rb +20 -20
- data/spec/flipper/adapters/memoizable_spec.rb +59 -59
- data/spec/flipper/adapters/operation_logger_spec.rb +16 -16
- data/spec/flipper/adapters/pstore_spec.rb +6 -6
- data/spec/flipper/adapters/read_only_spec.rb +28 -34
- data/spec/flipper/dsl_spec.rb +73 -84
- data/spec/flipper/feature_check_context_spec.rb +27 -27
- data/spec/flipper/feature_spec.rb +186 -196
- data/spec/flipper/gate_spec.rb +11 -11
- data/spec/flipper/gate_values_spec.rb +46 -45
- data/spec/flipper/gates/actor_spec.rb +2 -2
- data/spec/flipper/gates/boolean_spec.rb +24 -23
- data/spec/flipper/gates/group_spec.rb +19 -19
- data/spec/flipper/gates/percentage_of_actors_spec.rb +10 -10
- data/spec/flipper/gates/percentage_of_time_spec.rb +2 -2
- data/spec/flipper/instrumentation/log_subscriber_spec.rb +20 -20
- data/spec/flipper/instrumentation/metriks_subscriber_spec.rb +20 -20
- data/spec/flipper/instrumentation/statsd_subscriber_spec.rb +11 -11
- data/spec/flipper/instrumenters/memory_spec.rb +5 -5
- data/spec/flipper/instrumenters/noop_spec.rb +6 -6
- data/spec/flipper/middleware/memoizer_spec.rb +83 -100
- data/spec/flipper/middleware/setup_env_spec.rb +76 -0
- data/spec/flipper/registry_spec.rb +35 -39
- data/spec/flipper/typecast_spec.rb +18 -18
- data/spec/flipper/types/actor_spec.rb +30 -29
- data/spec/flipper/types/boolean_spec.rb +8 -8
- data/spec/flipper/types/group_spec.rb +28 -28
- data/spec/flipper/types/percentage_spec.rb +14 -14
- data/spec/flipper_spec.rb +61 -54
- data/spec/helper.rb +26 -21
- data/spec/integration_spec.rb +121 -113
- data/spec/support/fake_udp_socket.rb +1 -1
- data/spec/support/spec_helpers.rb +32 -4
- data/test/adapters/pstore_test.rb +3 -3
- data/test/test_helper.rb +1 -1
- metadata +20 -5
| @@ -0,0 +1,76 @@ | |
| 1 | 
            +
            require 'helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Flipper::Middleware::SetupEnv do
         | 
| 4 | 
            +
              context 'with flipper instance' do
         | 
| 5 | 
            +
                let(:app) do
         | 
| 6 | 
            +
                  app = lambda do |env|
         | 
| 7 | 
            +
                    [200, { 'Content-Type' => 'text/html' }, [env['flipper'].object_id.to_s]]
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
                  builder = Rack::Builder.new
         | 
| 10 | 
            +
                  builder.use described_class, flipper
         | 
| 11 | 
            +
                  builder.run app
         | 
| 12 | 
            +
                  builder
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                it 'sets flipper in env' do
         | 
| 16 | 
            +
                  get '/'
         | 
| 17 | 
            +
                  expect(last_response.body).to eq(flipper.object_id.to_s)
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              context 'with block that returns flipper instance' do
         | 
| 22 | 
            +
                let(:flipper_block) do
         | 
| 23 | 
            +
                  -> { flipper }
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
                let(:app) do
         | 
| 26 | 
            +
                  app = lambda do |env|
         | 
| 27 | 
            +
                    [200, { 'Content-Type' => 'text/html' }, [env['flipper'].object_id.to_s]]
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                  builder = Rack::Builder.new
         | 
| 30 | 
            +
                  builder.use described_class, flipper_block
         | 
| 31 | 
            +
                  builder.run app
         | 
| 32 | 
            +
                  builder
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                it 'sets flipper in env' do
         | 
| 36 | 
            +
                  get '/'
         | 
| 37 | 
            +
                  expect(last_response.body).to eq(flipper.object_id.to_s)
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              context 'when env already has flipper setup' do
         | 
| 42 | 
            +
                let(:app) do
         | 
| 43 | 
            +
                  app = lambda do |env|
         | 
| 44 | 
            +
                    [200, { 'Content-Type' => 'text/html' }, [env['flipper'].object_id.to_s]]
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                  builder = Rack::Builder.new
         | 
| 47 | 
            +
                  builder.use described_class, flipper
         | 
| 48 | 
            +
                  builder.run app
         | 
| 49 | 
            +
                  builder
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                it 'leaves env flipper alone' do
         | 
| 53 | 
            +
                  env_flipper = build_flipper
         | 
| 54 | 
            +
                  get '/', {}, 'flipper' => env_flipper
         | 
| 55 | 
            +
                  expect(last_response.body).to eq(env_flipper.object_id.to_s)
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              context 'when flipper instance is nil' do
         | 
| 60 | 
            +
                let(:app) do
         | 
| 61 | 
            +
                  app = lambda do |env|
         | 
| 62 | 
            +
                    [200, { 'Content-Type' => 'text/html' }, [env['flipper'].object_id.to_s]]
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
                  builder = Rack::Builder.new
         | 
| 65 | 
            +
                  builder.use described_class, nil
         | 
| 66 | 
            +
                  builder.run app
         | 
| 67 | 
            +
                  builder
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                it 'leaves env flipper alone' do
         | 
| 71 | 
            +
                  env_flipper = build_flipper
         | 
| 72 | 
            +
                  get '/', {}, 'flipper' => env_flipper
         | 
| 73 | 
            +
                  expect(last_response.body).to eq(env_flipper.object_id.to_s)
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
            end
         | 
| @@ -2,123 +2,119 @@ require 'helper' | |
| 2 2 | 
             
            require 'flipper/registry'
         | 
| 3 3 |  | 
| 4 4 | 
             
            RSpec.describe Flipper::Registry do
         | 
| 5 | 
            -
              subject {  | 
| 5 | 
            +
              subject { described_class.new(source) }
         | 
| 6 6 |  | 
| 7 7 | 
             
              let(:source) { {} }
         | 
| 8 8 |  | 
| 9 | 
            -
              describe  | 
| 10 | 
            -
                it  | 
| 9 | 
            +
              describe '#add' do
         | 
| 10 | 
            +
                it 'adds to source' do
         | 
| 11 11 | 
             
                  value = 'thing'
         | 
| 12 12 | 
             
                  subject.add(:admins, value)
         | 
| 13 13 | 
             
                  expect(source[:admins]).to eq(value)
         | 
| 14 14 | 
             
                end
         | 
| 15 15 |  | 
| 16 | 
            -
                it  | 
| 16 | 
            +
                it 'converts key to symbol' do
         | 
| 17 17 | 
             
                  value = 'thing'
         | 
| 18 18 | 
             
                  subject.add('admins', value)
         | 
| 19 19 | 
             
                  expect(source[:admins]).to eq(value)
         | 
| 20 20 | 
             
                end
         | 
| 21 21 |  | 
| 22 | 
            -
                it  | 
| 22 | 
            +
                it 'raises exception if key already registered' do
         | 
| 23 23 | 
             
                  subject.add(:admins, 'thing')
         | 
| 24 24 |  | 
| 25 | 
            -
                  expect  | 
| 25 | 
            +
                  expect do
         | 
| 26 26 | 
             
                    subject.add('admins', 'again')
         | 
| 27 | 
            -
                   | 
| 27 | 
            +
                  end.to raise_error(Flipper::Registry::DuplicateKey)
         | 
| 28 28 | 
             
                end
         | 
| 29 29 | 
             
              end
         | 
| 30 30 |  | 
| 31 | 
            -
              describe  | 
| 32 | 
            -
                context  | 
| 31 | 
            +
              describe '#get' do
         | 
| 32 | 
            +
                context 'key registered' do
         | 
| 33 33 | 
             
                  before do
         | 
| 34 34 | 
             
                    source[:admins] = 'thing'
         | 
| 35 35 | 
             
                  end
         | 
| 36 36 |  | 
| 37 | 
            -
                  it  | 
| 37 | 
            +
                  it 'returns value' do
         | 
| 38 38 | 
             
                    expect(subject.get(:admins)).to eq('thing')
         | 
| 39 39 | 
             
                  end
         | 
| 40 40 |  | 
| 41 | 
            -
                  it  | 
| 41 | 
            +
                  it 'returns value if given string key' do
         | 
| 42 42 | 
             
                    expect(subject.get('admins')).to eq('thing')
         | 
| 43 43 | 
             
                  end
         | 
| 44 44 | 
             
                end
         | 
| 45 45 |  | 
| 46 | 
            -
                context  | 
| 47 | 
            -
                  it  | 
| 48 | 
            -
                    expect  | 
| 49 | 
            -
                      subject.get(:admins)
         | 
| 50 | 
            -
                    }.to raise_error(Flipper::Registry::KeyNotFound)
         | 
| 46 | 
            +
                context 'key not registered' do
         | 
| 47 | 
            +
                  it 'returns nil' do
         | 
| 48 | 
            +
                    expect(subject.get(:admins)).to be(nil)
         | 
| 51 49 | 
             
                  end
         | 
| 52 50 | 
             
                end
         | 
| 53 51 | 
             
              end
         | 
| 54 52 |  | 
| 55 | 
            -
              describe  | 
| 53 | 
            +
              describe '#key?' do
         | 
| 56 54 | 
             
                before do
         | 
| 57 | 
            -
                  source[:admins] =  | 
| 55 | 
            +
                  source[:admins] = 'admins'
         | 
| 58 56 | 
             
                end
         | 
| 59 57 |  | 
| 60 | 
            -
                it  | 
| 58 | 
            +
                it 'returns true if the key exists' do
         | 
| 61 59 | 
             
                  expect(subject.key?(:admins)).to eq true
         | 
| 62 60 | 
             
                end
         | 
| 63 61 |  | 
| 64 | 
            -
                it  | 
| 62 | 
            +
                it 'returns false if the key does not exists' do
         | 
| 65 63 | 
             
                  expect(subject.key?(:unknown_key)).to eq false
         | 
| 66 64 | 
             
                end
         | 
| 67 65 | 
             
              end
         | 
| 68 66 |  | 
| 69 | 
            -
              describe  | 
| 67 | 
            +
              describe '#each' do
         | 
| 70 68 | 
             
                before do
         | 
| 71 69 | 
             
                  source[:admins] = 'admins'
         | 
| 72 70 | 
             
                  source[:devs] = 'devs'
         | 
| 73 71 | 
             
                end
         | 
| 74 72 |  | 
| 75 | 
            -
                it  | 
| 73 | 
            +
                it 'iterates source keys and values' do
         | 
| 76 74 | 
             
                  results = {}
         | 
| 77 75 | 
             
                  subject.each do |key, value|
         | 
| 78 76 | 
             
                    results[key] = value
         | 
| 79 77 | 
             
                  end
         | 
| 80 | 
            -
                  expect(results).to eq( | 
| 81 | 
            -
             | 
| 82 | 
            -
                          :devs => 'devs',
         | 
| 83 | 
            -
                        })
         | 
| 78 | 
            +
                  expect(results).to eq(admins: 'admins',
         | 
| 79 | 
            +
                                        devs: 'devs')
         | 
| 84 80 | 
             
                end
         | 
| 85 81 | 
             
              end
         | 
| 86 82 |  | 
| 87 | 
            -
              describe  | 
| 83 | 
            +
              describe '#keys' do
         | 
| 88 84 | 
             
                before do
         | 
| 89 85 | 
             
                  source[:admins] = 'admins'
         | 
| 90 86 | 
             
                  source[:devs] = 'devs'
         | 
| 91 87 | 
             
                end
         | 
| 92 88 |  | 
| 93 | 
            -
                it  | 
| 94 | 
            -
                  expect(subject.keys.map(&:to_s).sort).to eq( | 
| 89 | 
            +
                it 'returns the keys' do
         | 
| 90 | 
            +
                  expect(subject.keys.map(&:to_s).sort).to eq(%w(admins devs))
         | 
| 95 91 | 
             
                end
         | 
| 96 92 |  | 
| 97 | 
            -
                it  | 
| 93 | 
            +
                it 'returns the keys as symbols' do
         | 
| 98 94 | 
             
                  subject.keys.each do |key|
         | 
| 99 95 | 
             
                    expect(key).to be_instance_of(Symbol)
         | 
| 100 96 | 
             
                  end
         | 
| 101 97 | 
             
                end
         | 
| 102 98 | 
             
              end
         | 
| 103 99 |  | 
| 104 | 
            -
              describe  | 
| 100 | 
            +
              describe '#values' do
         | 
| 105 101 | 
             
                before do
         | 
| 106 102 | 
             
                  source[:admins] = 'admins'
         | 
| 107 103 | 
             
                  source[:devs] = 'devs'
         | 
| 108 104 | 
             
                end
         | 
| 109 105 |  | 
| 110 | 
            -
                it  | 
| 111 | 
            -
                  expect(subject.values.map(&:to_s).sort).to eq( | 
| 106 | 
            +
                it 'returns the values' do
         | 
| 107 | 
            +
                  expect(subject.values.map(&:to_s).sort).to eq(%w(admins devs))
         | 
| 112 108 | 
             
                end
         | 
| 113 109 | 
             
              end
         | 
| 114 110 |  | 
| 115 | 
            -
              describe  | 
| 111 | 
            +
              describe 'enumeration' do
         | 
| 116 112 | 
             
                before do
         | 
| 117 113 | 
             
                  source[:admins] = 'admins'
         | 
| 118 114 | 
             
                  source[:devs] = 'devs'
         | 
| 119 115 | 
             
                end
         | 
| 120 116 |  | 
| 121 | 
            -
                it  | 
| 117 | 
            +
                it 'works' do
         | 
| 122 118 | 
             
                  keys = []
         | 
| 123 119 | 
             
                  values = []
         | 
| 124 120 |  | 
| @@ -127,17 +123,17 @@ RSpec.describe Flipper::Registry do | |
| 127 123 | 
             
                    values << value
         | 
| 128 124 | 
             
                  end
         | 
| 129 125 |  | 
| 130 | 
            -
                  expect(keys.map(&:to_s).sort).to eq( | 
| 131 | 
            -
                  expect(values.sort).to eq( | 
| 126 | 
            +
                  expect(keys.map(&:to_s).sort).to eq(%w(admins devs))
         | 
| 127 | 
            +
                  expect(values.sort).to eq(%w(admins devs))
         | 
| 132 128 | 
             
                end
         | 
| 133 129 | 
             
              end
         | 
| 134 130 |  | 
| 135 | 
            -
              describe  | 
| 131 | 
            +
              describe '#clear' do
         | 
| 136 132 | 
             
                before do
         | 
| 137 133 | 
             
                  source[:admins] = 'admins'
         | 
| 138 134 | 
             
                end
         | 
| 139 135 |  | 
| 140 | 
            -
                it  | 
| 136 | 
            +
                it 'clears the source' do
         | 
| 141 137 | 
             
                  subject.clear
         | 
| 142 138 | 
             
                  expect(source).to be_empty
         | 
| 143 139 | 
             
                end
         | 
| @@ -4,15 +4,15 @@ require 'flipper/typecast' | |
| 4 4 | 
             
            RSpec.describe Flipper::Typecast do
         | 
| 5 5 | 
             
              {
         | 
| 6 6 | 
             
                nil => false,
         | 
| 7 | 
            -
                 | 
| 7 | 
            +
                '' => false,
         | 
| 8 8 | 
             
                0 => false,
         | 
| 9 9 | 
             
                1 => true,
         | 
| 10 | 
            -
                 | 
| 11 | 
            -
                 | 
| 10 | 
            +
                '0' => false,
         | 
| 11 | 
            +
                '1' => true,
         | 
| 12 12 | 
             
                true => true,
         | 
| 13 13 | 
             
                false => false,
         | 
| 14 | 
            -
                 | 
| 15 | 
            -
                 | 
| 14 | 
            +
                'true' => true,
         | 
| 15 | 
            +
                'false' => false,
         | 
| 16 16 | 
             
              }.each do |value, expected|
         | 
| 17 17 | 
             
                context "#to_boolean for #{value.inspect}" do
         | 
| 18 18 | 
             
                  it "returns #{expected}" do
         | 
| @@ -23,11 +23,11 @@ RSpec.describe Flipper::Typecast do | |
| 23 23 |  | 
| 24 24 | 
             
              {
         | 
| 25 25 | 
             
                nil => 0,
         | 
| 26 | 
            -
                 | 
| 26 | 
            +
                '' => 0,
         | 
| 27 27 | 
             
                0 => 0,
         | 
| 28 28 | 
             
                1 => 1,
         | 
| 29 | 
            -
                 | 
| 30 | 
            -
                 | 
| 29 | 
            +
                '1' => 1,
         | 
| 30 | 
            +
                '99' => 99,
         | 
| 31 31 | 
             
              }.each do |value, expected|
         | 
| 32 32 | 
             
                context "#to_integer for #{value.inspect}" do
         | 
| 33 33 | 
             
                  it "returns #{expected}" do
         | 
| @@ -38,9 +38,9 @@ RSpec.describe Flipper::Typecast do | |
| 38 38 |  | 
| 39 39 | 
             
              {
         | 
| 40 40 | 
             
                nil => Set.new,
         | 
| 41 | 
            -
                 | 
| 41 | 
            +
                '' => Set.new,
         | 
| 42 42 | 
             
                Set.new([1, 2]) => Set.new([1, 2]),
         | 
| 43 | 
            -
                [1, 2] => Set.new([1, 2])
         | 
| 43 | 
            +
                [1, 2] => Set.new([1, 2]),
         | 
| 44 44 | 
             
              }.each do |value, expected|
         | 
| 45 45 | 
             
                context "#to_set for #{value.inspect}" do
         | 
| 46 46 | 
             
                  it "returns #{expected}" do
         | 
| @@ -49,15 +49,15 @@ RSpec.describe Flipper::Typecast do | |
| 49 49 | 
             
                end
         | 
| 50 50 | 
             
              end
         | 
| 51 51 |  | 
| 52 | 
            -
              it  | 
| 53 | 
            -
                expect  | 
| 54 | 
            -
                  described_class.to_integer([ | 
| 55 | 
            -
                 | 
| 52 | 
            +
              it 'raises argument error for integer value that cannot be converted to an integer' do
         | 
| 53 | 
            +
                expect do
         | 
| 54 | 
            +
                  described_class.to_integer(['asdf'])
         | 
| 55 | 
            +
                end.to raise_error(ArgumentError, %(["asdf"] cannot be converted to an integer))
         | 
| 56 56 | 
             
              end
         | 
| 57 57 |  | 
| 58 | 
            -
              it  | 
| 59 | 
            -
                expect  | 
| 60 | 
            -
                  described_class.to_set( | 
| 61 | 
            -
                 | 
| 58 | 
            +
              it 'raises argument error for set value that cannot be converted to a set' do
         | 
| 59 | 
            +
                expect do
         | 
| 60 | 
            +
                  described_class.to_set('asdf')
         | 
| 61 | 
            +
                end.to raise_error(ArgumentError, %("asdf" cannot be converted to a set))
         | 
| 62 62 | 
             
              end
         | 
| 63 63 | 
             
            end
         | 
| @@ -2,13 +2,13 @@ require 'helper' | |
| 2 2 | 
             
            require 'flipper/types/actor'
         | 
| 3 3 |  | 
| 4 4 | 
             
            RSpec.describe Flipper::Types::Actor do
         | 
| 5 | 
            -
              subject  | 
| 5 | 
            +
              subject do
         | 
| 6 6 | 
             
                thing = thing_class.new('2')
         | 
| 7 7 | 
             
                described_class.new(thing)
         | 
| 8 | 
            -
               | 
| 8 | 
            +
              end
         | 
| 9 9 |  | 
| 10 | 
            -
              let(:thing_class)  | 
| 11 | 
            -
                Class.new  | 
| 10 | 
            +
              let(:thing_class) do
         | 
| 11 | 
            +
                Class.new do
         | 
| 12 12 | 
             
                  attr_reader :flipper_id
         | 
| 13 13 |  | 
| 14 14 | 
             
                  def initialize(flipper_id)
         | 
| @@ -18,37 +18,37 @@ RSpec.describe Flipper::Types::Actor do | |
| 18 18 | 
             
                  def admin?
         | 
| 19 19 | 
             
                    true
         | 
| 20 20 | 
             
                  end
         | 
| 21 | 
            -
                 | 
| 22 | 
            -
               | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 23 |  | 
| 24 | 
            -
              describe  | 
| 25 | 
            -
                it  | 
| 24 | 
            +
              describe '.wrappable?' do
         | 
| 25 | 
            +
                it 'returns true if actor' do
         | 
| 26 26 | 
             
                  thing = thing_class.new('1')
         | 
| 27 27 | 
             
                  actor = described_class.new(thing)
         | 
| 28 28 | 
             
                  expect(described_class.wrappable?(actor)).to eq(true)
         | 
| 29 29 | 
             
                end
         | 
| 30 30 |  | 
| 31 | 
            -
                it  | 
| 31 | 
            +
                it 'returns true if responds to flipper_id' do
         | 
| 32 32 | 
             
                  thing = thing_class.new(10)
         | 
| 33 33 | 
             
                  expect(described_class.wrappable?(thing)).to eq(true)
         | 
| 34 34 | 
             
                end
         | 
| 35 35 |  | 
| 36 | 
            -
                it  | 
| 36 | 
            +
                it 'returns false if nil' do
         | 
| 37 37 | 
             
                  expect(described_class.wrappable?(nil)).to be(false)
         | 
| 38 38 | 
             
                end
         | 
| 39 39 | 
             
              end
         | 
| 40 40 |  | 
| 41 | 
            -
              describe  | 
| 42 | 
            -
                context  | 
| 43 | 
            -
                  it  | 
| 41 | 
            +
              describe '.wrap' do
         | 
| 42 | 
            +
                context 'for actor' do
         | 
| 43 | 
            +
                  it 'returns actor' do
         | 
| 44 44 | 
             
                    actor = described_class.wrap(subject)
         | 
| 45 45 | 
             
                    expect(actor).to be_instance_of(described_class)
         | 
| 46 46 | 
             
                    expect(actor).to be(subject)
         | 
| 47 47 | 
             
                  end
         | 
| 48 48 | 
             
                end
         | 
| 49 49 |  | 
| 50 | 
            -
                context  | 
| 51 | 
            -
                  it  | 
| 50 | 
            +
                context 'for other thing' do
         | 
| 51 | 
            +
                  it 'returns actor' do
         | 
| 52 52 | 
             
                    thing = thing_class.new('1')
         | 
| 53 53 | 
             
                    actor = described_class.wrap(thing)
         | 
| 54 54 | 
             
                    expect(actor).to be_instance_of(described_class)
         | 
| @@ -56,57 +56,58 @@ RSpec.describe Flipper::Types::Actor do | |
| 56 56 | 
             
                end
         | 
| 57 57 | 
             
              end
         | 
| 58 58 |  | 
| 59 | 
            -
              it  | 
| 59 | 
            +
              it 'initializes with thing that responds to id' do
         | 
| 60 60 | 
             
                thing = thing_class.new('1')
         | 
| 61 61 | 
             
                actor = described_class.new(thing)
         | 
| 62 62 | 
             
                expect(actor.value).to eq('1')
         | 
| 63 63 | 
             
              end
         | 
| 64 64 |  | 
| 65 | 
            -
              it  | 
| 66 | 
            -
                expect  | 
| 65 | 
            +
              it 'raises error when initialized with nil' do
         | 
| 66 | 
            +
                expect do
         | 
| 67 67 | 
             
                  described_class.new(nil)
         | 
| 68 | 
            -
                 | 
| 68 | 
            +
                end.to raise_error(ArgumentError)
         | 
| 69 69 | 
             
              end
         | 
| 70 70 |  | 
| 71 | 
            -
              it  | 
| 71 | 
            +
              it 'raises error when initalized with non-wrappable object' do
         | 
| 72 72 | 
             
                unwrappable_thing = Struct.new(:id).new(1)
         | 
| 73 | 
            -
                expect  | 
| 73 | 
            +
                expect do
         | 
| 74 74 | 
             
                  described_class.new(unwrappable_thing)
         | 
| 75 | 
            -
                 | 
| 75 | 
            +
                end.to raise_error(ArgumentError,
         | 
| 76 | 
            +
                                   "#{unwrappable_thing.inspect} must respond to flipper_id, but does not")
         | 
| 76 77 | 
             
              end
         | 
| 77 78 |  | 
| 78 | 
            -
              it  | 
| 79 | 
            +
              it 'converts id to string' do
         | 
| 79 80 | 
             
                thing = thing_class.new(2)
         | 
| 80 81 | 
             
                actor = described_class.new(thing)
         | 
| 81 82 | 
             
                expect(actor.value).to eq('2')
         | 
| 82 83 | 
             
              end
         | 
| 83 84 |  | 
| 84 | 
            -
              it  | 
| 85 | 
            +
              it 'proxies everything to thing' do
         | 
| 85 86 | 
             
                thing = thing_class.new(10)
         | 
| 86 87 | 
             
                actor = described_class.new(thing)
         | 
| 87 88 | 
             
                expect(actor.admin?).to eq(true)
         | 
| 88 89 | 
             
              end
         | 
| 89 90 |  | 
| 90 | 
            -
              it  | 
| 91 | 
            +
              it 'exposes thing' do
         | 
| 91 92 | 
             
                thing = thing_class.new(10)
         | 
| 92 93 | 
             
                actor = described_class.new(thing)
         | 
| 93 94 | 
             
                expect(actor.thing).to be(thing)
         | 
| 94 95 | 
             
              end
         | 
| 95 96 |  | 
| 96 | 
            -
              describe  | 
| 97 | 
            -
                it  | 
| 97 | 
            +
              describe '#respond_to?' do
         | 
| 98 | 
            +
                it 'returns true if responds to method' do
         | 
| 98 99 | 
             
                  thing = thing_class.new('1')
         | 
| 99 100 | 
             
                  actor = described_class.new(thing)
         | 
| 100 101 | 
             
                  expect(actor.respond_to?(:value)).to eq(true)
         | 
| 101 102 | 
             
                end
         | 
| 102 103 |  | 
| 103 | 
            -
                it  | 
| 104 | 
            +
                it 'returns true if thing responds to method' do
         | 
| 104 105 | 
             
                  thing = thing_class.new(10)
         | 
| 105 106 | 
             
                  actor = described_class.new(thing)
         | 
| 106 107 | 
             
                  expect(actor.respond_to?(:admin?)).to eq(true)
         | 
| 107 108 | 
             
                end
         | 
| 108 109 |  | 
| 109 | 
            -
                it  | 
| 110 | 
            +
                it 'returns false if does not respond to method and thing does not respond to method' do
         | 
| 110 111 | 
             
                  thing = thing_class.new(10)
         | 
| 111 112 | 
             
                  actor = described_class.new(thing)
         | 
| 112 113 | 
             
                  expect(actor.respond_to?(:frankenstein)).to eq(false)
         |