lib/teaspoon/configuration.rb
require "singleton"
require "teaspoon/driver"
require "teaspoon/formatter"
module Teaspoon
class Configuration
include Singleton
# CONTRIBUTORS:
# If you add a configuration option you should do the following before it will be considered for merging.
# - think about if it should be a suite, coverage, or global configuration
# - write specs for it, and add it to existing specs in spec/teaspoon/configuration_spec.rb
# - add it to the readme so it's documented
# - add it to the command_line.rb if appropriate (_only_ if it's appropriate)
# - add it to ENV_OVERRIDES if it can be overridden from ENV
# - add it to the initializers in /lib/generators/install/templates so it's documented there as well
cattr_accessor :mount_at, :root, :asset_paths, :fixture_paths, :asset_manifest
@@mount_at = "/teaspoon"
@@root = nil # will default to Rails.root
@@asset_paths = ["spec/javascripts", "spec/javascripts/stylesheets",
"test/javascripts", "test/javascripts/stylesheets"]
@@fixture_paths = ["spec/javascripts/fixtures", "test/javascripts/fixtures"]
@@asset_manifest = ["teaspoon.css", "teaspoon-filterer.js", "support/*.js"]
# console runner specific
cattr_accessor :driver, :driver_options, :driver_timeout, :server, :server_host, :server_port, :server_timeout, :fail_fast,
:formatters, :color, :suppress_log,
:use_coverage
@@driver = Teaspoon::Driver.default
@@driver_options = nil
@@driver_timeout = 180
@@server = nil
@@server_host = nil
@@server_port = nil
@@server_timeout = 20
@@fail_fast = true
@@formatters = [Teaspoon::Formatter.default]
@@color = true
@@suppress_log = false
@@use_coverage = nil
# options that can be specified in the ENV
ENV_OVERRIDES = {
boolean: %w(FAIL_FAST SUPPRESS_LOG COLOR),
integer: %w(DRIVER_TIMEOUT SERVER_TIMEOUT),
string: %w(DRIVER DRIVER_OPTIONS SERVER SERVER_PORT FORMATTERS USE_COVERAGE)
}
# suite configurations
cattr_accessor :suite_configs
@@suite_configs = { "default" => { block: proc { } } }
def self.suite(name = :default, &block)
@@suite_configs[name.to_s] = { block: block, instance: Suite.new(name, &block) }
end
class Suite
attr_accessor :matcher, :helper, :javascripts, :javascript_packs, :stylesheets,
:boot_partial, :body_partial,
:hooks, :expand_assets, :js_extensions
def initialize(name = nil)
@matcher = "{spec/javascripts,app/assets}/**/*_spec.{js,js.coffee,coffee,es6,js.es6}"
@helper = "spec_helper"
@javascripts = []
@stylesheets = ["teaspoon"]
@javascript_packs = []
@boot_partial = "boot"
@body_partial = "body"
@hooks = Hash.new { |h, k| h[k] = [] }
@expand_assets = true
@js_extensions = [/(\.js)?\.coffee/, /(\.js)?\.es6/, ".es6.js"]
default = Teaspoon.configuration.suite_configs["default"]
instance_eval(&default[:block]) if default
if block_given?
yield self
raise Teaspoon::UnspecifiedFramework.new(name: name) if @javascripts.length == 0
end
end
def use_framework(name, version = nil)
framework = Teaspoon::Framework.fetch(name)
framework.modify_config(self)
@javascripts = framework.javascripts_for(version)
return if @javascripts
raise Teaspoon::UnknownFrameworkVersion.new(name: name, version: version)
end
def hook(group = :default, &block)
@hooks[group.to_s] << block
end
end
# coverage configurations
cattr_accessor :coverage_configs
@@coverage_configs = { "default" => { block: proc { } } }
def self.coverage(name = :default, &block)
@@coverage_configs[name.to_s] = { block: block, instance: Coverage.new(&block) }
end
class Coverage
attr_accessor :reports, :output_path, :ignore,
:statements, :functions, :branches, :lines
def initialize
@reports = ["text-summary"]
@output_path = "coverage"
@ignore = [%r{/.rvm/gems/}, %r{/lib/ruby/gems/}, %r{/vendor/assets/}, %r{/support/}, %r{/(.+)_helper.}]
@statements = nil
@functions = nil
@branches = nil
@lines = nil
default = Teaspoon.configuration.coverage_configs["default"]
instance_eval(&default[:block]) if default
yield self if block_given?
end
end
# custom getters / setters
def self.root=(path)
@@root = Pathname.new(path.to_s) if path.present?
end
def self.formatters
return ["dot"] if @@formatters.blank?
return @@formatters if @@formatters.is_a?(Array)
@@formatters.to_s.split(/,\s?/)
end
# override from env or options
def self.override_from_options(options)
options.each { |k, v| override(k, v) }
end
def self.override_from_env(env)
ENV_OVERRIDES[:boolean].each { |o| override(o, env[o] == "true") if env[o].present? }
ENV_OVERRIDES[:integer].each { |o| override(o, env[o].to_i) if env[o].present? }
ENV_OVERRIDES[:string].each { |o| override(o, env[o]) if env[o].present? }
end
def self.override(config, value)
setter = "#{config.to_s.downcase}="
send(setter, value) if respond_to?(setter)
end
end
mattr_accessor :configured, :configuration
@@configured = false
@@configuration = Configuration
def self.configure
yield @@configuration
@@configured = true
@@configuration.override_from_env(ENV)
end
end