module TestProf::LetItBe

Just like `let`, but persist the result for the whole group. NOTE: Experimental and magical, for more control use `before_all`.

Constants

FROZEN_ERROR_HINT
PREFIX

Use uniq prefix for instance variables to avoid collisions We want to use the power of Ruby's unicode support) And we love cats!)

Public Class Methods

config() click to toggle source
# File lib/test_prof/recipes/rspec/let_it_be.rb, line 32
def config
  @config ||= Configuration.new
end
configure() { |config| ... } click to toggle source
# File lib/test_prof/recipes/rspec/let_it_be.rb, line 36
def configure
  yield config
end
define_let_it_be_alias(name, **default_args) click to toggle source
# File lib/test_prof/recipes/rspec/let_it_be.rb, line 82
def self.define_let_it_be_alias(name, **default_args)
  define_method(name) do |identifier, **options, &blk|
    let_it_be(identifier, **default_args.merge(options), &blk)
  end
end
modifiers() click to toggle source
# File lib/test_prof/recipes/rspec/let_it_be.rb, line 40
def modifiers
  @modifiers ||= {}
end
module_for(group) click to toggle source
# File lib/test_prof/recipes/rspec/let_it_be.rb, line 57
def module_for(group)
  modules[group] ||= Module.new.tap { |mod| group.prepend(mod) }
end
wrap_with_modifiers(mods, &block) click to toggle source
# File lib/test_prof/recipes/rspec/let_it_be.rb, line 44
def wrap_with_modifiers(mods, &block)
  return block if mods.empty?

  validate_modifiers! mods

  -> {
    record = instance_eval(&block)
    mods.inject(record) do |rec, (k, v)|
      LetItBe.modifiers.fetch(k).call(rec, v)
    end
  }
end

Private Class Methods

modules() click to toggle source
# File lib/test_prof/recipes/rspec/let_it_be.rb, line 63
def modules
  @modules ||= {}
end
validate_modifiers!(mods) click to toggle source
# File lib/test_prof/recipes/rspec/let_it_be.rb, line 67
def validate_modifiers!(mods)
  unknown = mods.keys - modifiers.keys
  return if unknown.empty?

  raise ArgumentError, "Unknown let_it_be modifiers were used: #{unknown.join(", ")}. " \
                       "Available modifiers are: #{modifiers.keys.join(", ")}"
end

Public Instance Methods

let_it_be(identifier, **options, &block) click to toggle source
Calls superclass method
# File lib/test_prof/recipes/rspec/let_it_be.rb, line 88
def let_it_be(identifier, **options, &block)
  initializer = proc do
    instance_variable_set(:"#{TestProf::LetItBe::PREFIX}#{identifier}", instance_exec(&block))
  rescue FrozenError => e
    raise e.exception("#{e.message}#{TestProf::LetItBe::FROZEN_ERROR_HINT}")
  end

  default_options = LetItBe.config.default_modifiers.dup
  default_options.merge!(metadata[:let_it_be_modifiers]) if metadata[:let_it_be_modifiers]

  options = default_options.merge(options)

  before_all(&initializer)

  let_accessor = LetItBe.wrap_with_modifiers(options) do
    instance_variable_get(:"#{PREFIX}#{identifier}")
  end

  LetItBe.module_for(self).module_eval do
    define_method(identifier) do
      # Trying to detect the context
      # Based on https://github.com/rspec/rspec-rails/commit/7cb796db064f58da7790a92e73ab906ef50b1f34
      if /(before|after)\(:context\)/.match?(@__inspect_output) || @__inspect_output.include?("before_all")
        instance_variable_get(:"#{PREFIX}#{identifier}")
      else
        # Fallback to let definition
        super()
      end
    end
  end

  let(identifier, &let_accessor)
end