lopata 0.1.9 → 0.1.14
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/README.md +25 -25
 - data/exe/lopata +11 -11
 - data/lib/lopata.rb +74 -74
 - data/lib/lopata/active_record.rb +135 -135
 - data/lib/lopata/condition.rb +30 -28
 - data/lib/lopata/configuration.rb +125 -125
 - data/lib/lopata/environment.rb +35 -35
 - data/lib/lopata/factory_bot.rb +72 -72
 - data/lib/lopata/generators/app.rb +42 -42
 - data/lib/lopata/generators/templates/Gemfile +7 -7
 - data/lib/lopata/generators/templates/Lopatafile +20 -20
 - data/lib/lopata/generators/templates/config/environments/qa.yml +7 -7
 - data/lib/lopata/generators/templates/config/initializers/capybara.rb +1 -1
 - data/lib/lopata/id.rb +22 -22
 - data/lib/lopata/loader.rb +31 -27
 - data/lib/lopata/observers.rb +4 -4
 - data/lib/lopata/observers/backtrace_formatter.rb +103 -103
 - data/lib/lopata/observers/base_observer.rb +33 -33
 - data/lib/lopata/observers/console_output_observer.rb +100 -100
 - data/lib/lopata/observers/web_logger.rb +130 -130
 - data/lib/lopata/role.rb +109 -90
 - data/lib/lopata/runner.rb +67 -67
 - data/lib/lopata/scenario.rb +136 -136
 - data/lib/lopata/scenario_builder.rb +497 -495
 - data/lib/lopata/shared_step.rb +38 -38
 - data/lib/lopata/step.rb +191 -191
 - data/lib/lopata/version.rb +6 -6
 - data/lib/lopata/world.rb +24 -24
 - metadata +6 -6
 
    
        data/lib/lopata/role.rb
    CHANGED
    
    | 
         @@ -1,91 +1,110 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module Lopata
         
     | 
| 
       2 
     | 
    
         
            -
              # Adds ability to run scenarios by given user roles
         
     | 
| 
       3 
     | 
    
         
            -
              #
         
     | 
| 
       4 
     | 
    
         
            -
              # @example Usage
         
     | 
| 
       5 
     | 
    
         
            -
              #     require 'lopata/role'
         
     | 
| 
       6 
     | 
    
         
            -
              #     Lopata.configure do |c|
         
     | 
| 
       7 
     | 
    
         
            -
              #       c.role_descriptions = {
         
     | 
| 
       8 
     | 
    
         
            -
              #         user: 'User',
         
     | 
| 
       9 
     | 
    
         
            -
              #         admin: 'Admin'
         
     | 
| 
       10 
     | 
    
         
            -
              #       }
         
     | 
| 
       11 
     | 
    
         
            -
              #       c.default_role = :user
         
     | 
| 
       12 
     | 
    
         
            -
              #       c.before_scenaro 'setup user'
         
     | 
| 
       13 
     | 
    
         
            -
              #     end
         
     | 
| 
       14 
     | 
    
         
            -
              #     Lopata.shared_step 'setup user' do
         
     | 
| 
       15 
     | 
    
         
            -
              #       setup { @user = User.create(role: current_role) if current_role }
         
     | 
| 
       16 
     | 
    
         
            -
              #       cleanup :user
         
     | 
| 
       17 
     | 
    
         
            -
              #     end
         
     | 
| 
       18 
     | 
    
         
            -
              #     Lopata.define 'login' do
         
     | 
| 
       19 
     | 
    
         
            -
              #       # will generate 2 scenarios, one for :user and one for :admin
         
     | 
| 
       20 
     | 
    
         
            -
              #       as :user, :admin
         
     | 
| 
       21 
     | 
    
         
            -
              #       action 'login'
         
     | 
| 
       22 
     | 
    
         
            -
              #       # verify the user is logged in
         
     | 
| 
       23 
     | 
    
         
            -
              #     end
         
     | 
| 
       24 
     | 
    
         
            -
              #
         
     | 
| 
       25 
     | 
    
         
            -
              # @see Lopata::Configuration#role_descriptions
         
     | 
| 
       26 
     | 
    
         
            -
              # @see Lopata::Configuration#default_role
         
     | 
| 
       27 
     | 
    
         
            -
              module Role
         
     | 
| 
       28 
     | 
    
         
            -
                # To be included in Lopata::Scenario
         
     | 
| 
       29 
     | 
    
         
            -
                module Methods
         
     | 
| 
       30 
     | 
    
         
            -
                  # @return [Symbol, nil] user role for current scenario or nil, if scenario is running without user.
         
     | 
| 
       31 
     | 
    
         
            -
                  def current_role
         
     | 
| 
       32 
     | 
    
         
            -
                    metadata[:as]
         
     | 
| 
       33 
     | 
    
         
            -
                  end
         
     | 
| 
       34 
     | 
    
         
            -
                end
         
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
                # To be included in Lopata::ScenarioBuilder
         
     | 
| 
       37 
     | 
    
         
            -
                module DSL
         
     | 
| 
       38 
     | 
    
         
            -
                  # Enumerate the roles the scenario to be runned under.
         
     | 
| 
       39 
     | 
    
         
            -
                  # If not invoked the default role only will be used.
         
     | 
| 
       40 
     | 
    
         
            -
                  #
         
     | 
| 
       41 
     | 
    
         
            -
                  # The scenario should be set to use the role via before_scenario step using #current_role param.
         
     | 
| 
       42 
     | 
    
         
            -
                  #
         
     | 
| 
       43 
     | 
    
         
            -
                  # @param args [Array<Symbol>] list of roles the scenario to be runned with.
         
     | 
| 
       44 
     | 
    
         
            -
                  # @param block [Block] the block to calculate role from scenario metadata.
         
     | 
| 
       45 
     | 
    
         
            -
                  def as(*args, &block)
         
     | 
| 
       46 
     | 
    
         
            -
                    @roles = args.flatten
         
     | 
| 
       47 
     | 
    
         
            -
                    @roles << Lopata::ScenarioBuilder::CalculatedValue.new(&block) if block_given?
         
     | 
| 
       48 
     | 
    
         
            -
                    @ 
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
                   
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
                   
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
                  #  
     | 
| 
       57 
     | 
    
         
            -
                  #
         
     | 
| 
       58 
     | 
    
         
            -
                  # 
     | 
| 
       59 
     | 
    
         
            -
                  # 
     | 
| 
       60 
     | 
    
         
            -
                  # 
     | 
| 
       61 
     | 
    
         
            -
                  # 
     | 
| 
       62 
     | 
    
         
            -
                  # 
     | 
| 
       63 
     | 
    
         
            -
                   
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
                    @ 
     | 
| 
       67 
     | 
    
         
            -
                  end
         
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
                  # @private
         
     | 
| 
       70 
     | 
    
         
            -
                  def  
     | 
| 
       71 
     | 
    
         
            -
                     
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
                  # 
     | 
| 
       76 
     | 
    
         
            -
                   
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
                   
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
                  # 
     | 
| 
       82 
     | 
    
         
            -
                   
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            module Lopata
         
     | 
| 
      
 2 
     | 
    
         
            +
              # Adds ability to run scenarios by given user roles
         
     | 
| 
      
 3 
     | 
    
         
            +
              #
         
     | 
| 
      
 4 
     | 
    
         
            +
              # @example Usage
         
     | 
| 
      
 5 
     | 
    
         
            +
              #     require 'lopata/role'
         
     | 
| 
      
 6 
     | 
    
         
            +
              #     Lopata.configure do |c|
         
     | 
| 
      
 7 
     | 
    
         
            +
              #       c.role_descriptions = {
         
     | 
| 
      
 8 
     | 
    
         
            +
              #         user: 'User',
         
     | 
| 
      
 9 
     | 
    
         
            +
              #         admin: 'Admin'
         
     | 
| 
      
 10 
     | 
    
         
            +
              #       }
         
     | 
| 
      
 11 
     | 
    
         
            +
              #       c.default_role = :user
         
     | 
| 
      
 12 
     | 
    
         
            +
              #       c.before_scenaro 'setup user'
         
     | 
| 
      
 13 
     | 
    
         
            +
              #     end
         
     | 
| 
      
 14 
     | 
    
         
            +
              #     Lopata.shared_step 'setup user' do
         
     | 
| 
      
 15 
     | 
    
         
            +
              #       setup { @user = User.create(role: current_role) if current_role }
         
     | 
| 
      
 16 
     | 
    
         
            +
              #       cleanup :user
         
     | 
| 
      
 17 
     | 
    
         
            +
              #     end
         
     | 
| 
      
 18 
     | 
    
         
            +
              #     Lopata.define 'login' do
         
     | 
| 
      
 19 
     | 
    
         
            +
              #       # will generate 2 scenarios, one for :user and one for :admin
         
     | 
| 
      
 20 
     | 
    
         
            +
              #       as :user, :admin
         
     | 
| 
      
 21 
     | 
    
         
            +
              #       action 'login'
         
     | 
| 
      
 22 
     | 
    
         
            +
              #       # verify the user is logged in
         
     | 
| 
      
 23 
     | 
    
         
            +
              #     end
         
     | 
| 
      
 24 
     | 
    
         
            +
              #
         
     | 
| 
      
 25 
     | 
    
         
            +
              # @see Lopata::Configuration#role_descriptions
         
     | 
| 
      
 26 
     | 
    
         
            +
              # @see Lopata::Configuration#default_role
         
     | 
| 
      
 27 
     | 
    
         
            +
              module Role
         
     | 
| 
      
 28 
     | 
    
         
            +
                # To be included in Lopata::Scenario
         
     | 
| 
      
 29 
     | 
    
         
            +
                module Methods
         
     | 
| 
      
 30 
     | 
    
         
            +
                  # @return [Symbol, nil] user role for current scenario or nil, if scenario is running without user.
         
     | 
| 
      
 31 
     | 
    
         
            +
                  def current_role
         
     | 
| 
      
 32 
     | 
    
         
            +
                    metadata[:as]
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                # To be included in Lopata::ScenarioBuilder
         
     | 
| 
      
 37 
     | 
    
         
            +
                module DSL
         
     | 
| 
      
 38 
     | 
    
         
            +
                  # Enumerate the roles the scenario to be runned under.
         
     | 
| 
      
 39 
     | 
    
         
            +
                  # If not invoked the default role only will be used.
         
     | 
| 
      
 40 
     | 
    
         
            +
                  #
         
     | 
| 
      
 41 
     | 
    
         
            +
                  # The scenario should be set to use the role via before_scenario step using #current_role param.
         
     | 
| 
      
 42 
     | 
    
         
            +
                  #
         
     | 
| 
      
 43 
     | 
    
         
            +
                  # @param args [Array<Symbol>] list of roles the scenario to be runned with.
         
     | 
| 
      
 44 
     | 
    
         
            +
                  # @param block [Block] the block to calculate role from scenario metadata.
         
     | 
| 
      
 45 
     | 
    
         
            +
                  def as(*args, &block)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    @roles = args.flatten
         
     | 
| 
      
 47 
     | 
    
         
            +
                    @roles << Lopata::ScenarioBuilder::CalculatedValue.new(&block) if block_given?
         
     | 
| 
      
 48 
     | 
    
         
            +
                    @use_all_roles = true
         
     | 
| 
      
 49 
     | 
    
         
            +
                    @role_options = nil
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  # Enumerate the roles the scenario can be run.
         
     | 
| 
      
 53 
     | 
    
         
            +
                  #
         
     | 
| 
      
 54 
     | 
    
         
            +
                  # The scenario should be set to use the role via before_scenario step using #current_role param.
         
     | 
| 
      
 55 
     | 
    
         
            +
                  #
         
     | 
| 
      
 56 
     | 
    
         
            +
                  # Only first role will be used if scenario has no options or diagonales. Some first roles will be used if
         
     | 
| 
      
 57 
     | 
    
         
            +
                  # options or diagonales are declared, in order of appearence.
         
     | 
| 
      
 58 
     | 
    
         
            +
                  #
         
     | 
| 
      
 59 
     | 
    
         
            +
                  # Use this to describe possible roles, but not needed to run scenario with all of them in order to save time
         
     | 
| 
      
 60 
     | 
    
         
            +
                  # of running.
         
     | 
| 
      
 61 
     | 
    
         
            +
                  #
         
     | 
| 
      
 62 
     | 
    
         
            +
                  # @param args [Array<Symbol>] list of roles the scenario to be runned with.
         
     | 
| 
      
 63 
     | 
    
         
            +
                  def as_first(*args, &block)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    @roles = args.flatten
         
     | 
| 
      
 65 
     | 
    
         
            +
                    @use_all_roles = false
         
     | 
| 
      
 66 
     | 
    
         
            +
                    @role_options = nil
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                  # @private
         
     | 
| 
      
 70 
     | 
    
         
            +
                  def role_options
         
     | 
| 
      
 71 
     | 
    
         
            +
                    @role_options ||= build_role_options
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                  # Marks scenario to be runned without user.
         
     | 
| 
      
 75 
     | 
    
         
            +
                  #
         
     | 
| 
      
 76 
     | 
    
         
            +
                  # @example
         
     | 
| 
      
 77 
     | 
    
         
            +
                  #     Lopata.define 'scenario withou user' do
         
     | 
| 
      
 78 
     | 
    
         
            +
                  #       without_user
         
     | 
| 
      
 79 
     | 
    
         
            +
                  #       it 'does not define the user' do
         
     | 
| 
      
 80 
     | 
    
         
            +
                  #         expect(current_role).to be_nil
         
     | 
| 
      
 81 
     | 
    
         
            +
                  #       end
         
     | 
| 
      
 82 
     | 
    
         
            +
                  #     end
         
     | 
| 
      
 83 
     | 
    
         
            +
                  def without_user
         
     | 
| 
      
 84 
     | 
    
         
            +
                    @without_user = true
         
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  # @private
         
     | 
| 
      
 88 
     | 
    
         
            +
                  def build_role_options
         
     | 
| 
      
 89 
     | 
    
         
            +
                    return [] unless roles
         
     | 
| 
      
 90 
     | 
    
         
            +
                    role_variants = roles.map { |r| [Lopata.configuration.role_descriptions[r], r] }
         
     | 
| 
      
 91 
     | 
    
         
            +
                    [Lopata::ScenarioBuilder::Diagonal.new(:as, role_variants, @use_all_roles)]
         
     | 
| 
      
 92 
     | 
    
         
            +
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                  # @private
         
     | 
| 
      
 95 
     | 
    
         
            +
                  def roles
         
     | 
| 
      
 96 
     | 
    
         
            +
                    return false if @without_user
         
     | 
| 
      
 97 
     | 
    
         
            +
                    @roles ||= [Lopata.configuration.default_role].compact
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                  # @private
         
     | 
| 
      
 101 
     | 
    
         
            +
                  def diagonals
         
     | 
| 
      
 102 
     | 
    
         
            +
                    super + role_options
         
     | 
| 
      
 103 
     | 
    
         
            +
                  end
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
              end
         
     | 
| 
      
 106 
     | 
    
         
            +
            end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
            Lopata::Scenario.include Lopata::Role::Methods
         
     | 
| 
      
 109 
     | 
    
         
            +
            # Prepend the module to overload #diagonals method
         
     | 
| 
       91 
110 
     | 
    
         
             
            Lopata::ScenarioBuilder.prepend Lopata::Role::DSL
         
     | 
    
        data/lib/lopata/runner.rb
    CHANGED
    
    | 
         @@ -1,67 +1,67 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'thor'
         
     | 
| 
       2 
     | 
    
         
            -
            require_relative 'generators/app'
         
     | 
| 
       3 
     | 
    
         
            -
            require_relative 'world'
         
     | 
| 
       4 
     | 
    
         
            -
            require_relative 'loader'
         
     | 
| 
       5 
     | 
    
         
            -
            require_relative '../lopata'
         
     | 
| 
       6 
     | 
    
         
            -
            require_relative 'observers'
         
     | 
| 
       7 
     | 
    
         
            -
            require_relative 'condition'
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
            module Lopata
         
     | 
| 
       10 
     | 
    
         
            -
              # @private
         
     | 
| 
       11 
     | 
    
         
            -
              class Runner < Thor
         
     | 
| 
       12 
     | 
    
         
            -
                desc 'test', 'Run tests'
         
     | 
| 
       13 
     | 
    
         
            -
                option :env, default: :qa, aliases: 'e'
         
     | 
| 
       14 
     | 
    
         
            -
                option :rerun, type: :boolean, aliases: 'r'
         
     | 
| 
       15 
     | 
    
         
            -
                option :keep, type: :boolean, aliases: 'k'
         
     | 
| 
       16 
     | 
    
         
            -
                option :text, aliases: 't'
         
     | 
| 
       17 
     | 
    
         
            -
                def test(*args)
         
     | 
| 
       18 
     | 
    
         
            -
                  trap_interrupt
         
     | 
| 
       19 
     | 
    
         
            -
                  configure_from_options
         
     | 
| 
       20 
     | 
    
         
            -
                  Lopata::Loader.load_shared_steps
         
     | 
| 
       21 
     | 
    
         
            -
                  Lopata::Loader.load_scenarios(*args)
         
     | 
| 
       22 
     | 
    
         
            -
                  world = Lopata.world
         
     | 
| 
       23 
     | 
    
         
            -
                  world.notify_observers(:started, world)
         
     | 
| 
       24 
     | 
    
         
            -
                  world.scenarios.each { |s| s.run }
         
     | 
| 
       25 
     | 
    
         
            -
                  world.notify_observers(:finished, world)
         
     | 
| 
       26 
     | 
    
         
            -
                end
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
                default_task :test
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
                register Generators::App, :new, 'lopata new project-name', 'Init new lopata projects'
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                def self.exit_on_failure?
         
     | 
| 
       33 
     | 
    
         
            -
                  true
         
     | 
| 
       34 
     | 
    
         
            -
                end
         
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
                no_commands do
         
     | 
| 
       37 
     | 
    
         
            -
                  def configure_from_options
         
     | 
| 
       38 
     | 
    
         
            -
                    Lopata.configure do |c|
         
     | 
| 
       39 
     | 
    
         
            -
                      c.env = options[:env].to_sym
         
     | 
| 
       40 
     | 
    
         
            -
                      c.keep = options[:keep]
         
     | 
| 
       41 
     | 
    
         
            -
                      c.load_environment
         
     | 
| 
       42 
     | 
    
         
            -
                      c.run_before_start_hooks
         
     | 
| 
       43 
     | 
    
         
            -
                    end
         
     | 
| 
       44 
     | 
    
         
            -
                    add_text_filter(options[:text]) if options[:text]
         
     | 
| 
       45 
     | 
    
         
            -
                    add_rerun_filter if options[:rerun]
         
     | 
| 
       46 
     | 
    
         
            -
                  end
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
                  def add_text_filter(text)
         
     | 
| 
       49 
     | 
    
         
            -
                    Lopata.configuration.filters << -> (scenario) { scenario.title.include?(text) }
         
     | 
| 
       50 
     | 
    
         
            -
                  end
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
                  def add_rerun_filter
         
     | 
| 
       53 
     | 
    
         
            -
                    to_rerun = Lopata::Client.new.to_rerun
         
     | 
| 
       54 
     | 
    
         
            -
                    Lopata.configuration.filters << -> (scenario) { to_rerun.include?(scenario.title) }
         
     | 
| 
       55 
     | 
    
         
            -
                  end
         
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
                  def trap_interrupt
         
     | 
| 
       58 
     | 
    
         
            -
                    trap('INT') { exit!(1) }
         
     | 
| 
       59 
     | 
    
         
            -
                  end
         
     | 
| 
       60 
     | 
    
         
            -
                end
         
     | 
| 
       61 
     | 
    
         
            -
              end
         
     | 
| 
       62 
     | 
    
         
            -
            end
         
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
            unless ARGV.first == 'new'
         
     | 
| 
       65 
     | 
    
         
            -
              eval File.binread('./Lopatafile') if File.exists?('./Lopatafile')
         
     | 
| 
       66 
     | 
    
         
            -
            end
         
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            require 'thor'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require_relative 'generators/app'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative 'world'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative 'loader'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require_relative '../lopata'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require_relative 'observers'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require_relative 'condition'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            module Lopata
         
     | 
| 
      
 10 
     | 
    
         
            +
              # @private
         
     | 
| 
      
 11 
     | 
    
         
            +
              class Runner < Thor
         
     | 
| 
      
 12 
     | 
    
         
            +
                desc 'test', 'Run tests'
         
     | 
| 
      
 13 
     | 
    
         
            +
                option :env, default: :qa, aliases: 'e'
         
     | 
| 
      
 14 
     | 
    
         
            +
                option :rerun, type: :boolean, aliases: 'r'
         
     | 
| 
      
 15 
     | 
    
         
            +
                option :keep, type: :boolean, aliases: 'k'
         
     | 
| 
      
 16 
     | 
    
         
            +
                option :text, aliases: 't'
         
     | 
| 
      
 17 
     | 
    
         
            +
                def test(*args)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  trap_interrupt
         
     | 
| 
      
 19 
     | 
    
         
            +
                  configure_from_options
         
     | 
| 
      
 20 
     | 
    
         
            +
                  Lopata::Loader.load_shared_steps
         
     | 
| 
      
 21 
     | 
    
         
            +
                  Lopata::Loader.load_scenarios(*args)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  world = Lopata.world
         
     | 
| 
      
 23 
     | 
    
         
            +
                  world.notify_observers(:started, world)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  world.scenarios.each { |s| s.run }
         
     | 
| 
      
 25 
     | 
    
         
            +
                  world.notify_observers(:finished, world)
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                default_task :test
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                register Generators::App, :new, 'lopata new project-name', 'Init new lopata projects'
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def self.exit_on_failure?
         
     | 
| 
      
 33 
     | 
    
         
            +
                  true
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                no_commands do
         
     | 
| 
      
 37 
     | 
    
         
            +
                  def configure_from_options
         
     | 
| 
      
 38 
     | 
    
         
            +
                    Lopata.configure do |c|
         
     | 
| 
      
 39 
     | 
    
         
            +
                      c.env = options[:env].to_sym
         
     | 
| 
      
 40 
     | 
    
         
            +
                      c.keep = options[:keep]
         
     | 
| 
      
 41 
     | 
    
         
            +
                      c.load_environment
         
     | 
| 
      
 42 
     | 
    
         
            +
                      c.run_before_start_hooks
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    add_text_filter(options[:text]) if options[:text]
         
     | 
| 
      
 45 
     | 
    
         
            +
                    add_rerun_filter if options[:rerun]
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  def add_text_filter(text)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    Lopata.configuration.filters << -> (scenario) { scenario.title.include?(text) }
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  def add_rerun_filter
         
     | 
| 
      
 53 
     | 
    
         
            +
                    to_rerun = Lopata::Client.new.to_rerun
         
     | 
| 
      
 54 
     | 
    
         
            +
                    Lopata.configuration.filters << -> (scenario) { to_rerun.include?(scenario.title) }
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  def trap_interrupt
         
     | 
| 
      
 58 
     | 
    
         
            +
                    trap('INT') { exit!(1) }
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
            end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            unless ARGV.first == 'new'
         
     | 
| 
      
 65 
     | 
    
         
            +
              eval File.binread('./Lopatafile') if File.exists?('./Lopatafile')
         
     | 
| 
      
 66 
     | 
    
         
            +
            end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
    
        data/lib/lopata/scenario.rb
    CHANGED
    
    | 
         @@ -1,136 +1,136 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'rspec/expectations'
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            # Scenario runtime class.
         
     | 
| 
       4 
     | 
    
         
            -
            #
         
     | 
| 
       5 
     | 
    
         
            -
            # All the scenarios are running in context of separate Lopata::Scenario object.
         
     | 
| 
       6 
     | 
    
         
            -
            #
         
     | 
| 
       7 
     | 
    
         
            -
            class Lopata::Scenario
         
     | 
| 
       8 
     | 
    
         
            -
              include RSpec::Matchers
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
              # @private
         
     | 
| 
       11 
     | 
    
         
            -
              attr_reader :execution
         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
              # @private
         
     | 
| 
       14 
     | 
    
         
            -
              def initialize(execution)
         
     | 
| 
       15 
     | 
    
         
            -
                @execution = execution
         
     | 
| 
       16 
     | 
    
         
            -
              end
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
              # Marks current step as pending
         
     | 
| 
       19 
     | 
    
         
            -
              # @example
         
     | 
| 
       20 
     | 
    
         
            -
              #     it 'pending step' do
         
     | 
| 
       21 
     | 
    
         
            -
              #       pending
         
     | 
| 
       22 
     | 
    
         
            -
              #       expect(1).to eq 2
         
     | 
| 
       23 
     | 
    
         
            -
              #     end
         
     | 
| 
       24 
     | 
    
         
            -
              #
         
     | 
| 
       25 
     | 
    
         
            -
              # Pending steps wont be failed
         
     | 
| 
       26 
     | 
    
         
            -
              def pending(message = nil)
         
     | 
| 
       27 
     | 
    
         
            -
                execution.current_step.pending!(message)
         
     | 
| 
       28 
     | 
    
         
            -
              end
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
              # @return [Hash] metadata available for current step
         
     | 
| 
       31 
     | 
    
         
            -
              # @note The metadata keys also availalbe as methods (via method_missing)
         
     | 
| 
       32 
     | 
    
         
            -
              def metadata
         
     | 
| 
       33 
     | 
    
         
            -
                execution.metadata
         
     | 
| 
       34 
     | 
    
         
            -
              end
         
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
              private
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
              # @private
         
     | 
| 
       39 
     | 
    
         
            -
              def method_missing(method, *args, &block)
         
     | 
| 
       40 
     | 
    
         
            -
                if execution.let_methods.include?(method)
         
     | 
| 
       41 
     | 
    
         
            -
                  instance_exec(*args, &execution.let_methods[method])
         
     | 
| 
       42 
     | 
    
         
            -
                elsif metadata.keys.include?(method)
         
     | 
| 
       43 
     | 
    
         
            -
                  metadata[method]
         
     | 
| 
       44 
     | 
    
         
            -
                else
         
     | 
| 
       45 
     | 
    
         
            -
                  super
         
     | 
| 
       46 
     | 
    
         
            -
                end
         
     | 
| 
       47 
     | 
    
         
            -
              end
         
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
              # @private
         
     | 
| 
       50 
     | 
    
         
            -
              def respond_to_missing?(method, *)
         
     | 
| 
       51 
     | 
    
         
            -
                execution.let_methods.include?(method) or metadata.keys.include?(method) or super
         
     | 
| 
       52 
     | 
    
         
            -
              end
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
              # @private
         
     | 
| 
       55 
     | 
    
         
            -
              # Scenario execution and live-cycle information
         
     | 
| 
       56 
     | 
    
         
            -
              class Execution
         
     | 
| 
       57 
     | 
    
         
            -
                attr_reader :scenario, :status, :steps, :title, :current_step
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
                def initialize(title, options_title, metadata = {})
         
     | 
| 
       60 
     | 
    
         
            -
                  @title = [title, options_title].compact.reject(&:empty?).join(' ')
         
     | 
| 
       61 
     | 
    
         
            -
                  @metadata = metadata
         
     | 
| 
       62 
     | 
    
         
            -
                  @let_methods = {}
         
     | 
| 
       63 
     | 
    
         
            -
                  @status = :not_runned
         
     | 
| 
       64 
     | 
    
         
            -
                  @steps = []
         
     | 
| 
       65 
     | 
    
         
            -
                  @scenario = Lopata::Scenario.new(self)
         
     | 
| 
       66 
     | 
    
         
            -
                end
         
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
                def run
         
     | 
| 
       69 
     | 
    
         
            -
                  @status = :running
         
     | 
| 
       70 
     | 
    
         
            -
                  sort_steps
         
     | 
| 
       71 
     | 
    
         
            -
                  world.notify_observers(:scenario_started, self)
         
     | 
| 
       72 
     | 
    
         
            -
                  steps.each(&method(:run_step))
         
     | 
| 
       73 
     | 
    
         
            -
                  @status = steps.any?(&:failed?) ? :failed : :passed
         
     | 
| 
       74 
     | 
    
         
            -
                  world.notify_observers(:scenario_finished, self)
         
     | 
| 
       75 
     | 
    
         
            -
                  cleanup
         
     | 
| 
       76 
     | 
    
         
            -
                end
         
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
                def run_step(step)
         
     | 
| 
       79 
     | 
    
         
            -
                  return if step.skipped?
         
     | 
| 
       80 
     | 
    
         
            -
                  @current_step = step
         
     | 
| 
       81 
     | 
    
         
            -
                  step.run(scenario)
         
     | 
| 
       82 
     | 
    
         
            -
                  skip_rest if step.failed? && step.skip_rest_on_failure?
         
     | 
| 
       83 
     | 
    
         
            -
                  @current_step = nil
         
     | 
| 
       84 
     | 
    
         
            -
                end
         
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
                def world
         
     | 
| 
       87 
     | 
    
         
            -
                  Lopata.world
         
     | 
| 
       88 
     | 
    
         
            -
                end
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
                def failed?
         
     | 
| 
       91 
     | 
    
         
            -
                  status == :failed
         
     | 
| 
       92 
     | 
    
         
            -
                end
         
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
     | 
    
         
            -
                def sort_steps
         
     | 
| 
       95 
     | 
    
         
            -
                  @steps = steps.reject(&:teardown_group?) + steps.select(&:teardown_group?)
         
     | 
| 
       96 
     | 
    
         
            -
                end
         
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
                def skip_rest
         
     | 
| 
       99 
     | 
    
         
            -
                  steps.select { |s| s.status == :not_runned && !s.teardown? }.each(&:skip!)
         
     | 
| 
       100 
     | 
    
         
            -
                end
         
     | 
| 
       101 
     | 
    
         
            -
             
     | 
| 
       102 
     | 
    
         
            -
                def metadata
         
     | 
| 
       103 
     | 
    
         
            -
                  if current_step
         
     | 
| 
       104 
     | 
    
         
            -
                    @metadata.merge(current_step.metadata)
         
     | 
| 
       105 
     | 
    
         
            -
                  else
         
     | 
| 
       106 
     | 
    
         
            -
                    @metadata
         
     | 
| 
       107 
     | 
    
         
            -
                  end
         
     | 
| 
       108 
     | 
    
         
            -
                end
         
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
                def let_methods
         
     | 
| 
       111 
     | 
    
         
            -
                  if current_step
         
     | 
| 
       112 
     | 
    
         
            -
                    @let_methods.merge(current_step.let_methods)
         
     | 
| 
       113 
     | 
    
         
            -
                  else
         
     | 
| 
       114 
     | 
    
         
            -
                    @let_methods
         
     | 
| 
       115 
     | 
    
         
            -
                  end
         
     | 
| 
       116 
     | 
    
         
            -
                end
         
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
                def let(method_name, &block)
         
     | 
| 
       119 
     | 
    
         
            -
                  # define_singleton_method method_name, &block
         
     | 
| 
       120 
     | 
    
         
            -
                  base =
         
     | 
| 
       121 
     | 
    
         
            -
                    if current_step && !current_step.groups.empty?
         
     | 
| 
       122 
     | 
    
         
            -
                      current_step.groups.last.let_methods
         
     | 
| 
       123 
     | 
    
         
            -
                    else
         
     | 
| 
       124 
     | 
    
         
            -
                      @let_methods
         
     | 
| 
       125 
     | 
    
         
            -
                    end
         
     | 
| 
       126 
     | 
    
         
            -
                  base[method_name] = block
         
     | 
| 
       127 
     | 
    
         
            -
                end
         
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
       129 
     | 
    
         
            -
                def cleanup
         
     | 
| 
       130 
     | 
    
         
            -
                  @title = nil
         
     | 
| 
       131 
     | 
    
         
            -
                  @metadata = nil
         
     | 
| 
       132 
     | 
    
         
            -
                  @steps = nil
         
     | 
| 
       133 
     | 
    
         
            -
                  @scenario = nil
         
     | 
| 
       134 
     | 
    
         
            -
                end
         
     | 
| 
       135 
     | 
    
         
            -
              end
         
     | 
| 
       136 
     | 
    
         
            -
            end
         
     | 
| 
      
 1 
     | 
    
         
            +
            require 'rspec/expectations'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # Scenario runtime class.
         
     | 
| 
      
 4 
     | 
    
         
            +
            #
         
     | 
| 
      
 5 
     | 
    
         
            +
            # All the scenarios are running in context of separate Lopata::Scenario object.
         
     | 
| 
      
 6 
     | 
    
         
            +
            #
         
     | 
| 
      
 7 
     | 
    
         
            +
            class Lopata::Scenario
         
     | 
| 
      
 8 
     | 
    
         
            +
              include RSpec::Matchers
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              # @private
         
     | 
| 
      
 11 
     | 
    
         
            +
              attr_reader :execution
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              # @private
         
     | 
| 
      
 14 
     | 
    
         
            +
              def initialize(execution)
         
     | 
| 
      
 15 
     | 
    
         
            +
                @execution = execution
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              # Marks current step as pending
         
     | 
| 
      
 19 
     | 
    
         
            +
              # @example
         
     | 
| 
      
 20 
     | 
    
         
            +
              #     it 'pending step' do
         
     | 
| 
      
 21 
     | 
    
         
            +
              #       pending
         
     | 
| 
      
 22 
     | 
    
         
            +
              #       expect(1).to eq 2
         
     | 
| 
      
 23 
     | 
    
         
            +
              #     end
         
     | 
| 
      
 24 
     | 
    
         
            +
              #
         
     | 
| 
      
 25 
     | 
    
         
            +
              # Pending steps wont be failed
         
     | 
| 
      
 26 
     | 
    
         
            +
              def pending(message = nil)
         
     | 
| 
      
 27 
     | 
    
         
            +
                execution.current_step.pending!(message)
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              # @return [Hash] metadata available for current step
         
     | 
| 
      
 31 
     | 
    
         
            +
              # @note The metadata keys also availalbe as methods (via method_missing)
         
     | 
| 
      
 32 
     | 
    
         
            +
              def metadata
         
     | 
| 
      
 33 
     | 
    
         
            +
                execution.metadata
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              private
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              # @private
         
     | 
| 
      
 39 
     | 
    
         
            +
              def method_missing(method, *args, &block)
         
     | 
| 
      
 40 
     | 
    
         
            +
                if execution.let_methods.include?(method)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  instance_exec(*args, &execution.let_methods[method])
         
     | 
| 
      
 42 
     | 
    
         
            +
                elsif metadata.keys.include?(method)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  metadata[method]
         
     | 
| 
      
 44 
     | 
    
         
            +
                else
         
     | 
| 
      
 45 
     | 
    
         
            +
                  super
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              # @private
         
     | 
| 
      
 50 
     | 
    
         
            +
              def respond_to_missing?(method, *)
         
     | 
| 
      
 51 
     | 
    
         
            +
                execution.let_methods.include?(method) or metadata.keys.include?(method) or super
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
              # @private
         
     | 
| 
      
 55 
     | 
    
         
            +
              # Scenario execution and live-cycle information
         
     | 
| 
      
 56 
     | 
    
         
            +
              class Execution
         
     | 
| 
      
 57 
     | 
    
         
            +
                attr_reader :scenario, :status, :steps, :title, :current_step
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                def initialize(title, options_title, metadata = {})
         
     | 
| 
      
 60 
     | 
    
         
            +
                  @title = [title, options_title].compact.reject(&:empty?).join(' ')
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @metadata = metadata
         
     | 
| 
      
 62 
     | 
    
         
            +
                  @let_methods = {}
         
     | 
| 
      
 63 
     | 
    
         
            +
                  @status = :not_runned
         
     | 
| 
      
 64 
     | 
    
         
            +
                  @steps = []
         
     | 
| 
      
 65 
     | 
    
         
            +
                  @scenario = Lopata::Scenario.new(self)
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                def run
         
     | 
| 
      
 69 
     | 
    
         
            +
                  @status = :running
         
     | 
| 
      
 70 
     | 
    
         
            +
                  sort_steps
         
     | 
| 
      
 71 
     | 
    
         
            +
                  world.notify_observers(:scenario_started, self)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  steps.each(&method(:run_step))
         
     | 
| 
      
 73 
     | 
    
         
            +
                  @status = steps.any?(&:failed?) ? :failed : :passed
         
     | 
| 
      
 74 
     | 
    
         
            +
                  world.notify_observers(:scenario_finished, self)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  cleanup
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                def run_step(step)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  return if step.skipped?
         
     | 
| 
      
 80 
     | 
    
         
            +
                  @current_step = step
         
     | 
| 
      
 81 
     | 
    
         
            +
                  step.run(scenario)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  skip_rest if step.failed? && step.skip_rest_on_failure?
         
     | 
| 
      
 83 
     | 
    
         
            +
                  @current_step = nil
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                def world
         
     | 
| 
      
 87 
     | 
    
         
            +
                  Lopata.world
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                def failed?
         
     | 
| 
      
 91 
     | 
    
         
            +
                  status == :failed
         
     | 
| 
      
 92 
     | 
    
         
            +
                end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                def sort_steps
         
     | 
| 
      
 95 
     | 
    
         
            +
                  @steps = steps.reject(&:teardown_group?) + steps.select(&:teardown_group?)
         
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                def skip_rest
         
     | 
| 
      
 99 
     | 
    
         
            +
                  steps.select { |s| s.status == :not_runned && !s.teardown? }.each(&:skip!)
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                def metadata
         
     | 
| 
      
 103 
     | 
    
         
            +
                  if current_step
         
     | 
| 
      
 104 
     | 
    
         
            +
                    @metadata.merge(current_step.metadata)
         
     | 
| 
      
 105 
     | 
    
         
            +
                  else
         
     | 
| 
      
 106 
     | 
    
         
            +
                    @metadata
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                def let_methods
         
     | 
| 
      
 111 
     | 
    
         
            +
                  if current_step
         
     | 
| 
      
 112 
     | 
    
         
            +
                    @let_methods.merge(current_step.let_methods)
         
     | 
| 
      
 113 
     | 
    
         
            +
                  else
         
     | 
| 
      
 114 
     | 
    
         
            +
                    @let_methods
         
     | 
| 
      
 115 
     | 
    
         
            +
                  end
         
     | 
| 
      
 116 
     | 
    
         
            +
                end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                def let(method_name, &block)
         
     | 
| 
      
 119 
     | 
    
         
            +
                  # define_singleton_method method_name, &block
         
     | 
| 
      
 120 
     | 
    
         
            +
                  base =
         
     | 
| 
      
 121 
     | 
    
         
            +
                    if current_step && !current_step.groups.empty?
         
     | 
| 
      
 122 
     | 
    
         
            +
                      current_step.groups.last.let_methods
         
     | 
| 
      
 123 
     | 
    
         
            +
                    else
         
     | 
| 
      
 124 
     | 
    
         
            +
                      @let_methods
         
     | 
| 
      
 125 
     | 
    
         
            +
                    end
         
     | 
| 
      
 126 
     | 
    
         
            +
                  base[method_name] = block
         
     | 
| 
      
 127 
     | 
    
         
            +
                end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                def cleanup
         
     | 
| 
      
 130 
     | 
    
         
            +
                  @title = nil
         
     | 
| 
      
 131 
     | 
    
         
            +
                  @metadata = nil
         
     | 
| 
      
 132 
     | 
    
         
            +
                  @steps = nil
         
     | 
| 
      
 133 
     | 
    
         
            +
                  @scenario = nil
         
     | 
| 
      
 134 
     | 
    
         
            +
                end
         
     | 
| 
      
 135 
     | 
    
         
            +
              end
         
     | 
| 
      
 136 
     | 
    
         
            +
            end
         
     |