flipper-ui 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/flipper-ui.gemspec +12 -12
- data/lib/flipper/ui.rb +6 -4
- data/lib/flipper/ui/action.rb +22 -21
- data/lib/flipper/ui/action_collection.rb +2 -2
- data/lib/flipper/ui/actions/actors_gate.rb +7 -7
- data/lib/flipper/ui/actions/add_feature.rb +6 -6
- data/lib/flipper/ui/actions/boolean_gate.rb +2 -2
- data/lib/flipper/ui/actions/feature.rb +5 -6
- data/lib/flipper/ui/actions/features.rb +9 -10
- data/lib/flipper/ui/actions/file.rb +0 -1
- data/lib/flipper/ui/actions/gate.rb +5 -2
- data/lib/flipper/ui/actions/groups_gate.rb +16 -14
- data/lib/flipper/ui/actions/home.rb +1 -2
- data/lib/flipper/ui/actions/percentage_of_actors_gate.rb +2 -2
- data/lib/flipper/ui/actions/percentage_of_time_gate.rb +2 -2
- data/lib/flipper/ui/decorators/feature.rb +9 -9
- data/lib/flipper/ui/decorators/gate.rb +7 -6
- data/lib/flipper/ui/middleware.rb +2 -27
- data/lib/flipper/ui/util.rb +2 -2
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/ui/action_spec.rb +22 -22
- data/spec/flipper/ui/actions/actors_gate_spec.rb +49 -45
- data/spec/flipper/ui/actions/add_feature_spec.rb +9 -9
- data/spec/flipper/ui/actions/boolean_gate_spec.rb +22 -22
- data/spec/flipper/ui/actions/feature_spec.rb +34 -34
- data/spec/flipper/ui/actions/features_spec.rb +44 -40
- data/spec/flipper/ui/actions/file_spec.rb +8 -8
- data/spec/flipper/ui/actions/gate_spec.rb +17 -15
- data/spec/flipper/ui/actions/groups_gate_spec.rb +57 -50
- data/spec/flipper/ui/actions/home_spec.rb +4 -4
- data/spec/flipper/ui/actions/percentage_of_actors_gate_spec.rb +24 -22
- data/spec/flipper/ui/actions/percentage_of_time_gate_spec.rb +24 -22
- data/spec/flipper/ui/decorators/feature_spec.rb +27 -27
- data/spec/flipper/ui/decorators/gate_spec.rb +10 -10
- data/spec/flipper/ui/util_spec.rb +4 -4
- data/spec/flipper/ui_spec.rb +58 -59
- metadata +7 -7
| @@ -23,20 +23,20 @@ module Flipper | |
| 23 23 | 
             
                        'id' => name.to_s,
         | 
| 24 24 | 
             
                        'name' => pretty_name,
         | 
| 25 25 | 
             
                        'state' => state.to_s,
         | 
| 26 | 
            -
                        'gates' => gates.map  | 
| 26 | 
            +
                        'gates' => gates.map do |gate|
         | 
| 27 27 | 
             
                          Decorators::Gate.new(gate, gate_values[gate.key]).as_json
         | 
| 28 | 
            -
                         | 
| 28 | 
            +
                        end,
         | 
| 29 29 | 
             
                      }
         | 
| 30 30 | 
             
                    end
         | 
| 31 31 |  | 
| 32 32 | 
             
                    def color_class
         | 
| 33 33 | 
             
                      case feature.state
         | 
| 34 34 | 
             
                      when :on
         | 
| 35 | 
            -
                         | 
| 35 | 
            +
                        'text-open'
         | 
| 36 36 | 
             
                      when :off
         | 
| 37 | 
            -
                         | 
| 37 | 
            +
                        'text-closed'
         | 
| 38 38 | 
             
                      when :conditional
         | 
| 39 | 
            -
                         | 
| 39 | 
            +
                        'text-pending'
         | 
| 40 40 | 
             
                      end
         | 
| 41 41 | 
             
                    end
         | 
| 42 42 |  | 
| @@ -45,10 +45,10 @@ module Flipper | |
| 45 45 | 
             
                    end
         | 
| 46 46 |  | 
| 47 47 | 
             
                    StateSortMap = {
         | 
| 48 | 
            -
                      : | 
| 49 | 
            -
                      : | 
| 50 | 
            -
                      : | 
| 51 | 
            -
                    }
         | 
| 48 | 
            +
                      on: 1,
         | 
| 49 | 
            +
                      conditional: 2,
         | 
| 50 | 
            +
                      off: 3,
         | 
| 51 | 
            +
                    }.freeze
         | 
| 52 52 |  | 
| 53 53 | 
             
                    def <=>(other)
         | 
| 54 54 | 
             
                      if state == other.state
         | 
| @@ -17,12 +17,13 @@ module Flipper | |
| 17 17 |  | 
| 18 18 | 
             
                    # Public: Returns instance as hash that is ready to be json dumped.
         | 
| 19 19 | 
             
                    def as_json
         | 
| 20 | 
            -
                      value_as_json = | 
| 21 | 
            -
             | 
| 22 | 
            -
                         | 
| 23 | 
            -
             | 
| 24 | 
            -
                         | 
| 25 | 
            -
             | 
| 20 | 
            +
                      value_as_json =
         | 
| 21 | 
            +
                        case data_type
         | 
| 22 | 
            +
                        when :set
         | 
| 23 | 
            +
                          value.to_a # json doesn't like sets
         | 
| 24 | 
            +
                        else
         | 
| 25 | 
            +
                          value
         | 
| 26 | 
            +
                        end
         | 
| 26 27 |  | 
| 27 28 | 
             
                      {
         | 
| 28 29 | 
             
                        'key' => gate.key.to_s,
         | 
| @@ -9,31 +9,9 @@ end | |
| 9 9 | 
             
            module Flipper
         | 
| 10 10 | 
             
              module UI
         | 
| 11 11 | 
             
                class Middleware
         | 
| 12 | 
            -
                   | 
| 13 | 
            -
                  #
         | 
| 14 | 
            -
                  # app - The app this middleware is included in.
         | 
| 15 | 
            -
                  # flipper_or_block - The Flipper::DSL instance or a block that yields a
         | 
| 16 | 
            -
                  #                    Flipper::DSL instance to use for all operations.
         | 
| 17 | 
            -
                  #
         | 
| 18 | 
            -
                  # Examples
         | 
| 19 | 
            -
                  #
         | 
| 20 | 
            -
                  #   flipper = Flipper.new(...)
         | 
| 21 | 
            -
                  #
         | 
| 22 | 
            -
                  #   # using with a normal flipper instance
         | 
| 23 | 
            -
                  #   use Flipper::UI::Middleware, flipper
         | 
| 24 | 
            -
                  #
         | 
| 25 | 
            -
                  #   # using with a block that yields a flipper instance
         | 
| 26 | 
            -
                  #   use Flipper::UI::Middleware, lambda { Flipper.new(...) }
         | 
| 27 | 
            -
                  #
         | 
| 28 | 
            -
                  def initialize(app, flipper_or_block)
         | 
| 12 | 
            +
                  def initialize(app)
         | 
| 29 13 | 
             
                    @app = app
         | 
| 30 14 |  | 
| 31 | 
            -
                    if flipper_or_block.respond_to?(:call)
         | 
| 32 | 
            -
                      @flipper_block = flipper_or_block
         | 
| 33 | 
            -
                    else
         | 
| 34 | 
            -
                      @flipper = flipper_or_block
         | 
| 35 | 
            -
                    end
         | 
| 36 | 
            -
             | 
| 37 15 | 
             
                    @action_collection = ActionCollection.new
         | 
| 38 16 |  | 
| 39 17 | 
             
                    # UI
         | 
| @@ -54,10 +32,6 @@ module Flipper | |
| 54 32 | 
             
                    @action_collection.add UI::Actions::Home
         | 
| 55 33 | 
             
                  end
         | 
| 56 34 |  | 
| 57 | 
            -
                  def flipper
         | 
| 58 | 
            -
                    @flipper ||= @flipper_block.call
         | 
| 59 | 
            -
                  end
         | 
| 60 | 
            -
             | 
| 61 35 | 
             
                  def call(env)
         | 
| 62 36 | 
             
                    dup.call!(env)
         | 
| 63 37 | 
             
                  end
         | 
| @@ -69,6 +43,7 @@ module Flipper | |
| 69 43 | 
             
                    if action_class.nil?
         | 
| 70 44 | 
             
                      @app.call(env)
         | 
| 71 45 | 
             
                    else
         | 
| 46 | 
            +
                      flipper = env.fetch('flipper')
         | 
| 72 47 | 
             
                      action_class.run(flipper, request)
         | 
| 73 48 | 
             
                    end
         | 
| 74 49 | 
             
                  end
         | 
    
        data/lib/flipper/ui/util.rb
    CHANGED
    
    | @@ -2,14 +2,14 @@ module Flipper | |
| 2 2 | 
             
              module UI
         | 
| 3 3 | 
             
                module Util
         | 
| 4 4 | 
             
                  # Private: 0x3000: fullwidth whitespace
         | 
| 5 | 
            -
                  NON_WHITESPACE_REGEXP =  | 
| 5 | 
            +
                  NON_WHITESPACE_REGEXP = /[^\s#{[0x3000].pack("U")}]/
         | 
| 6 6 |  | 
| 7 7 | 
             
                  def self.blank?(str)
         | 
| 8 8 | 
             
                    str.to_s !~ NON_WHITESPACE_REGEXP
         | 
| 9 9 | 
             
                  end
         | 
| 10 10 |  | 
| 11 11 | 
             
                  def self.titleize(str)
         | 
| 12 | 
            -
                    str.to_s.split( | 
| 12 | 
            +
                    str.to_s.split('_').map(&:capitalize).join(' ')
         | 
| 13 13 | 
             
                  end
         | 
| 14 14 | 
             
                end
         | 
| 15 15 | 
             
              end
         | 
    
        data/lib/flipper/version.rb
    CHANGED
    
    
| @@ -1,59 +1,59 @@ | |
| 1 1 | 
             
            require 'helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            RSpec.describe Flipper::UI::Action do
         | 
| 4 | 
            -
              let(:action_subclass)  | 
| 4 | 
            +
              let(:action_subclass) do
         | 
| 5 5 | 
             
                Class.new(described_class) do
         | 
| 6 6 | 
             
                  def noooope
         | 
| 7 | 
            -
                    raise  | 
| 7 | 
            +
                    raise 'should never run this'
         | 
| 8 8 | 
             
                  end
         | 
| 9 9 |  | 
| 10 10 | 
             
                  def get
         | 
| 11 | 
            -
                    [200, {},  | 
| 11 | 
            +
                    [200, {}, 'get']
         | 
| 12 12 | 
             
                  end
         | 
| 13 13 |  | 
| 14 14 | 
             
                  def post
         | 
| 15 | 
            -
                    [200, {},  | 
| 15 | 
            +
                    [200, {}, 'post']
         | 
| 16 16 | 
             
                  end
         | 
| 17 17 |  | 
| 18 18 | 
             
                  def put
         | 
| 19 | 
            -
                    [200, {},  | 
| 19 | 
            +
                    [200, {}, 'put']
         | 
| 20 20 | 
             
                  end
         | 
| 21 21 |  | 
| 22 22 | 
             
                  def delete
         | 
| 23 | 
            -
                    [200, {},  | 
| 23 | 
            +
                    [200, {}, 'delete']
         | 
| 24 24 | 
             
                  end
         | 
| 25 25 | 
             
                end
         | 
| 26 | 
            -
               | 
| 26 | 
            +
              end
         | 
| 27 27 |  | 
| 28 28 | 
             
              it "won't run method that isn't whitelisted" do
         | 
| 29 | 
            -
                fake_request = Struct.new(:request_method, :env, :session).new( | 
| 29 | 
            +
                fake_request = Struct.new(:request_method, :env, :session).new('NOOOOPE', {}, {})
         | 
| 30 30 | 
             
                action = action_subclass.new(flipper, fake_request)
         | 
| 31 | 
            -
                expect  | 
| 31 | 
            +
                expect do
         | 
| 32 32 | 
             
                  action.run
         | 
| 33 | 
            -
                 | 
| 33 | 
            +
                end.to raise_error(Flipper::UI::RequestMethodNotSupported)
         | 
| 34 34 | 
             
              end
         | 
| 35 35 |  | 
| 36 | 
            -
              it  | 
| 37 | 
            -
                fake_request = Struct.new(:request_method, :env, :session).new( | 
| 36 | 
            +
              it 'will run get' do
         | 
| 37 | 
            +
                fake_request = Struct.new(:request_method, :env, :session).new('GET', {}, {})
         | 
| 38 38 | 
             
                action = action_subclass.new(flipper, fake_request)
         | 
| 39 | 
            -
                expect(action.run).to eq([200, {},  | 
| 39 | 
            +
                expect(action.run).to eq([200, {}, 'get'])
         | 
| 40 40 | 
             
              end
         | 
| 41 41 |  | 
| 42 | 
            -
              it  | 
| 43 | 
            -
                fake_request = Struct.new(:request_method, :env, :session).new( | 
| 42 | 
            +
              it 'will run post' do
         | 
| 43 | 
            +
                fake_request = Struct.new(:request_method, :env, :session).new('POST', {}, {})
         | 
| 44 44 | 
             
                action = action_subclass.new(flipper, fake_request)
         | 
| 45 | 
            -
                expect(action.run).to eq([200, {},  | 
| 45 | 
            +
                expect(action.run).to eq([200, {}, 'post'])
         | 
| 46 46 | 
             
              end
         | 
| 47 47 |  | 
| 48 | 
            -
              it  | 
| 49 | 
            -
                fake_request = Struct.new(:request_method, :env, :session).new( | 
| 48 | 
            +
              it 'will run put' do
         | 
| 49 | 
            +
                fake_request = Struct.new(:request_method, :env, :session).new('PUT', {}, {})
         | 
| 50 50 | 
             
                action = action_subclass.new(flipper, fake_request)
         | 
| 51 | 
            -
                expect(action.run).to eq([200, {},  | 
| 51 | 
            +
                expect(action.run).to eq([200, {}, 'put'])
         | 
| 52 52 | 
             
              end
         | 
| 53 53 |  | 
| 54 | 
            -
              it  | 
| 55 | 
            -
                fake_request = Struct.new(:request_method, :env, :session).new( | 
| 54 | 
            +
              it 'will run delete' do
         | 
| 55 | 
            +
                fake_request = Struct.new(:request_method, :env, :session).new('DELETE', {}, {})
         | 
| 56 56 | 
             
                action = action_subclass.new(flipper, fake_request)
         | 
| 57 | 
            -
                expect(action.run).to eq([200, {},  | 
| 57 | 
            +
                expect(action.run).to eq([200, {}, 'delete'])
         | 
| 58 58 | 
             
              end
         | 
| 59 59 | 
             
            end
         | 
| @@ -1,107 +1,111 @@ | |
| 1 1 | 
             
            require 'helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            RSpec.describe Flipper::UI::Actions::ActorsGate do
         | 
| 4 | 
            -
              let(:token)  | 
| 4 | 
            +
              let(:token) do
         | 
| 5 5 | 
             
                if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
         | 
| 6 6 | 
             
                  Rack::Protection::AuthenticityToken.random_token
         | 
| 7 7 | 
             
                else
         | 
| 8 | 
            -
                   | 
| 8 | 
            +
                  'a'
         | 
| 9 9 | 
             
                end
         | 
| 10 | 
            -
               | 
| 11 | 
            -
              let(:session)  | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
              let(:session) do
         | 
| 12 12 | 
             
                if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
         | 
| 13 | 
            -
                  {: | 
| 13 | 
            +
                  { csrf: token }
         | 
| 14 14 | 
             
                else
         | 
| 15 | 
            -
                  { | 
| 15 | 
            +
                  { '_csrf_token' => token }
         | 
| 16 16 | 
             
                end
         | 
| 17 | 
            -
               | 
| 17 | 
            +
              end
         | 
| 18 18 |  | 
| 19 | 
            -
              describe  | 
| 19 | 
            +
              describe 'GET /features/:feature/actors' do
         | 
| 20 20 | 
             
                before do
         | 
| 21 | 
            -
                  get  | 
| 21 | 
            +
                  get 'features/search/actors'
         | 
| 22 22 | 
             
                end
         | 
| 23 23 |  | 
| 24 | 
            -
                it  | 
| 24 | 
            +
                it 'responds with success' do
         | 
| 25 25 | 
             
                  expect(last_response.status).to be(200)
         | 
| 26 26 | 
             
                end
         | 
| 27 27 |  | 
| 28 | 
            -
                it  | 
| 28 | 
            +
                it 'renders add new actor form' do
         | 
| 29 29 | 
             
                  expect(last_response.body).to include('<form action="/features/search/actors" method="post">')
         | 
| 30 30 | 
             
                end
         | 
| 31 31 | 
             
              end
         | 
| 32 32 |  | 
| 33 | 
            -
              describe  | 
| 34 | 
            -
                context  | 
| 35 | 
            -
                  let(:value) {  | 
| 33 | 
            +
              describe 'POST /features/:feature/actors' do
         | 
| 34 | 
            +
                context 'enabling an actor' do
         | 
| 35 | 
            +
                  let(:value) { 'User:6' }
         | 
| 36 36 |  | 
| 37 37 | 
             
                  before do
         | 
| 38 | 
            -
                    post  | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 38 | 
            +
                    post 'features/search/actors',
         | 
| 39 | 
            +
                         { 'value' => value, 'operation' => 'enable', 'authenticity_token' => token },
         | 
| 40 | 
            +
                         'rack.session' => session
         | 
| 41 41 | 
             
                  end
         | 
| 42 42 |  | 
| 43 | 
            -
                  it  | 
| 44 | 
            -
                    expect(flipper[:search].actors_value).to include( | 
| 43 | 
            +
                  it 'adds item to members' do
         | 
| 44 | 
            +
                    expect(flipper[:search].actors_value).to include('User:6')
         | 
| 45 45 | 
             
                  end
         | 
| 46 46 |  | 
| 47 | 
            -
                  it  | 
| 47 | 
            +
                  it 'redirects back to feature' do
         | 
| 48 48 | 
             
                    expect(last_response.status).to be(302)
         | 
| 49 | 
            -
                    expect(last_response.headers[ | 
| 49 | 
            +
                    expect(last_response.headers['Location']).to eq('/features/search')
         | 
| 50 50 | 
             
                  end
         | 
| 51 51 |  | 
| 52 52 | 
             
                  context 'value contains whitespace' do
         | 
| 53 | 
            -
                    let(:value) {  | 
| 53 | 
            +
                    let(:value) { '  User:6  ' }
         | 
| 54 54 |  | 
| 55 | 
            -
                    it  | 
| 56 | 
            -
                      expect(flipper[:search].actors_value).to include( | 
| 55 | 
            +
                    it 'adds item without whitespace' do
         | 
| 56 | 
            +
                      expect(flipper[:search].actors_value).to include('User:6')
         | 
| 57 57 | 
             
                    end
         | 
| 58 58 | 
             
                  end
         | 
| 59 59 |  | 
| 60 | 
            -
                  context  | 
| 61 | 
            -
                    context  | 
| 62 | 
            -
                      let(:value) {  | 
| 60 | 
            +
                  context 'for an invalid actor value' do
         | 
| 61 | 
            +
                    context 'empty value' do
         | 
| 62 | 
            +
                      let(:value) { '' }
         | 
| 63 63 |  | 
| 64 | 
            -
                       | 
| 64 | 
            +
                      # rubocop:disable Metrics/LineLength
         | 
| 65 | 
            +
                      it 'redirects back to feature' do
         | 
| 65 66 | 
             
                        expect(last_response.status).to be(302)
         | 
| 66 | 
            -
                        expect(last_response.headers[ | 
| 67 | 
            +
                        expect(last_response.headers['Location']).to eq('/features/search/actors?error=%22%22+is+not+a+valid+actor+value.')
         | 
| 67 68 | 
             
                      end
         | 
| 69 | 
            +
                      # rubocop:enable Metrics/LineLength
         | 
| 68 70 | 
             
                    end
         | 
| 69 71 |  | 
| 70 | 
            -
                    context  | 
| 72 | 
            +
                    context 'nil value' do
         | 
| 71 73 | 
             
                      let(:value) { nil }
         | 
| 72 74 |  | 
| 73 | 
            -
                       | 
| 75 | 
            +
                      # rubocop:disable Metrics/LineLength
         | 
| 76 | 
            +
                      it 'redirects back to feature' do
         | 
| 74 77 | 
             
                        expect(last_response.status).to be(302)
         | 
| 75 | 
            -
                        expect(last_response.headers[ | 
| 78 | 
            +
                        expect(last_response.headers['Location']).to eq('/features/search/actors?error=%22%22+is+not+a+valid+actor+value.')
         | 
| 76 79 | 
             
                      end
         | 
| 80 | 
            +
                      # rubocop:enable Metrics/LineLength
         | 
| 77 81 | 
             
                    end
         | 
| 78 82 | 
             
                  end
         | 
| 79 83 | 
             
                end
         | 
| 80 84 |  | 
| 81 | 
            -
                context  | 
| 82 | 
            -
                  let(:value) {  | 
| 85 | 
            +
                context 'disabling an actor' do
         | 
| 86 | 
            +
                  let(:value) { 'User:6' }
         | 
| 83 87 |  | 
| 84 88 | 
             
                  before do
         | 
| 85 | 
            -
                    flipper[:search].enable_actor Flipper::UI::Actor.new( | 
| 86 | 
            -
                    post  | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            +
                    flipper[:search].enable_actor Flipper::UI::Actor.new('User:6')
         | 
| 90 | 
            +
                    post 'features/search/actors',
         | 
| 91 | 
            +
                         { 'value' => value, 'operation' => 'disable', 'authenticity_token' => token },
         | 
| 92 | 
            +
                         'rack.session' => session
         | 
| 89 93 | 
             
                  end
         | 
| 90 94 |  | 
| 91 | 
            -
                  it  | 
| 92 | 
            -
                    expect(flipper[:search].actors_value).not_to include( | 
| 95 | 
            +
                  it 'removes item from members' do
         | 
| 96 | 
            +
                    expect(flipper[:search].actors_value).not_to include('User:6')
         | 
| 93 97 | 
             
                  end
         | 
| 94 98 |  | 
| 95 | 
            -
                  it  | 
| 99 | 
            +
                  it 'redirects back to feature' do
         | 
| 96 100 | 
             
                    expect(last_response.status).to be(302)
         | 
| 97 | 
            -
                    expect(last_response.headers[ | 
| 101 | 
            +
                    expect(last_response.headers['Location']).to eq('/features/search')
         | 
| 98 102 | 
             
                  end
         | 
| 99 103 |  | 
| 100 104 | 
             
                  context 'value contains whitespace' do
         | 
| 101 | 
            -
                    let(:value) {  | 
| 105 | 
            +
                    let(:value) { '  User:6  ' }
         | 
| 102 106 |  | 
| 103 | 
            -
                    it  | 
| 104 | 
            -
                      expect(flipper[:search].actors_value).not_to include( | 
| 107 | 
            +
                    it 'removes item whitout whitespace' do
         | 
| 108 | 
            +
                      expect(flipper[:search].actors_value).not_to include('User:6')
         | 
| 105 109 | 
             
                    end
         | 
| 106 110 | 
             
                  end
         | 
| 107 111 | 
             
                end
         | 
| @@ -1,43 +1,43 @@ | |
| 1 1 | 
             
            require 'helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            RSpec.describe Flipper::UI::Actions::AddFeature do
         | 
| 4 | 
            -
              describe  | 
| 4 | 
            +
              describe 'GET /features/new with feature_creation_enabled set to true' do
         | 
| 5 5 | 
             
                before do
         | 
| 6 6 | 
             
                  @original_feature_creation_enabled = Flipper::UI.feature_creation_enabled
         | 
| 7 7 | 
             
                  Flipper::UI.feature_creation_enabled = true
         | 
| 8 | 
            -
                  get  | 
| 8 | 
            +
                  get '/features/new'
         | 
| 9 9 | 
             
                end
         | 
| 10 10 |  | 
| 11 11 | 
             
                after do
         | 
| 12 12 | 
             
                  Flipper::UI.feature_creation_enabled = @original_feature_creation_enabled
         | 
| 13 13 | 
             
                end
         | 
| 14 14 |  | 
| 15 | 
            -
                it  | 
| 15 | 
            +
                it 'responds with success' do
         | 
| 16 16 | 
             
                  expect(last_response.status).to be(200)
         | 
| 17 17 | 
             
                end
         | 
| 18 18 |  | 
| 19 | 
            -
                it  | 
| 19 | 
            +
                it 'renders template' do
         | 
| 20 20 | 
             
                  expect(last_response.body).to include('<form action="/features" method="post">')
         | 
| 21 21 | 
             
                end
         | 
| 22 22 | 
             
              end
         | 
| 23 23 |  | 
| 24 | 
            -
              describe  | 
| 24 | 
            +
              describe 'GET /features/new with feature_creation_enabled set to false' do
         | 
| 25 25 | 
             
                before do
         | 
| 26 26 | 
             
                  @original_feature_creation_enabled = Flipper::UI.feature_creation_enabled
         | 
| 27 27 | 
             
                  Flipper::UI.feature_creation_enabled = false
         | 
| 28 | 
            -
                  get  | 
| 28 | 
            +
                  get '/features/new'
         | 
| 29 29 | 
             
                end
         | 
| 30 30 |  | 
| 31 31 | 
             
                after do
         | 
| 32 32 | 
             
                  Flipper::UI.feature_creation_enabled = @original_feature_creation_enabled
         | 
| 33 33 | 
             
                end
         | 
| 34 34 |  | 
| 35 | 
            -
                it  | 
| 35 | 
            +
                it 'returns 403' do
         | 
| 36 36 | 
             
                  expect(last_response.status).to be(403)
         | 
| 37 37 | 
             
                end
         | 
| 38 38 |  | 
| 39 | 
            -
                it  | 
| 40 | 
            -
                  expect(last_response.body).to include( | 
| 39 | 
            +
                it 'renders feature creation disabled template' do
         | 
| 40 | 
            +
                  expect(last_response.body).to include('Feature creation is disabled.')
         | 
| 41 41 | 
             
                end
         | 
| 42 42 | 
             
              end
         | 
| 43 43 | 
             
            end
         | 
| @@ -1,55 +1,55 @@ | |
| 1 1 | 
             
            require 'helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            RSpec.describe Flipper::UI::Actions::BooleanGate do
         | 
| 4 | 
            -
              let(:token)  | 
| 4 | 
            +
              let(:token) do
         | 
| 5 5 | 
             
                if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
         | 
| 6 6 | 
             
                  Rack::Protection::AuthenticityToken.random_token
         | 
| 7 7 | 
             
                else
         | 
| 8 | 
            -
                   | 
| 8 | 
            +
                  'a'
         | 
| 9 9 | 
             
                end
         | 
| 10 | 
            -
               | 
| 11 | 
            -
              let(:session)  | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
              let(:session) do
         | 
| 12 12 | 
             
                if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
         | 
| 13 | 
            -
                  {: | 
| 13 | 
            +
                  { csrf: token }
         | 
| 14 14 | 
             
                else
         | 
| 15 | 
            -
                  { | 
| 15 | 
            +
                  { '_csrf_token' => token }
         | 
| 16 16 | 
             
                end
         | 
| 17 | 
            -
               | 
| 17 | 
            +
              end
         | 
| 18 18 |  | 
| 19 | 
            -
              describe  | 
| 20 | 
            -
                context  | 
| 19 | 
            +
              describe 'POST /features/:feature/boolean' do
         | 
| 20 | 
            +
                context 'with enable' do
         | 
| 21 21 | 
             
                  before do
         | 
| 22 22 | 
             
                    flipper.disable :search
         | 
| 23 | 
            -
                    post  | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 23 | 
            +
                    post 'features/search/boolean',
         | 
| 24 | 
            +
                         { 'action' => 'Enable', 'authenticity_token' => token },
         | 
| 25 | 
            +
                         'rack.session' => session
         | 
| 26 26 | 
             
                  end
         | 
| 27 27 |  | 
| 28 | 
            -
                  it  | 
| 28 | 
            +
                  it 'enables the feature' do
         | 
| 29 29 | 
             
                    expect(flipper.enabled?(:search)).to be(true)
         | 
| 30 30 | 
             
                  end
         | 
| 31 31 |  | 
| 32 | 
            -
                  it  | 
| 32 | 
            +
                  it 'redirects back to feature' do
         | 
| 33 33 | 
             
                    expect(last_response.status).to be(302)
         | 
| 34 | 
            -
                    expect(last_response.headers[ | 
| 34 | 
            +
                    expect(last_response.headers['Location']).to eq('/features/search')
         | 
| 35 35 | 
             
                  end
         | 
| 36 36 | 
             
                end
         | 
| 37 37 |  | 
| 38 | 
            -
                context  | 
| 38 | 
            +
                context 'with disable' do
         | 
| 39 39 | 
             
                  before do
         | 
| 40 40 | 
             
                    flipper.enable :search
         | 
| 41 | 
            -
                    post  | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 41 | 
            +
                    post 'features/search/boolean',
         | 
| 42 | 
            +
                         { 'action' => 'Disable', 'authenticity_token' => token },
         | 
| 43 | 
            +
                         'rack.session' => session
         | 
| 44 44 | 
             
                  end
         | 
| 45 45 |  | 
| 46 | 
            -
                  it  | 
| 46 | 
            +
                  it 'disables the feature' do
         | 
| 47 47 | 
             
                    expect(flipper.enabled?(:search)).to be(false)
         | 
| 48 48 | 
             
                  end
         | 
| 49 49 |  | 
| 50 | 
            -
                  it  | 
| 50 | 
            +
                  it 'redirects back to feature' do
         | 
| 51 51 | 
             
                    expect(last_response.status).to be(302)
         | 
| 52 | 
            -
                    expect(last_response.headers[ | 
| 52 | 
            +
                    expect(last_response.headers['Location']).to eq('/features/search')
         | 
| 53 53 | 
             
                  end
         | 
| 54 54 | 
             
                end
         | 
| 55 55 | 
             
              end
         |