convio/watirmark

View on GitHub
lib/watirmark/configuration.rb

Summary

Maintainability
A
2 hrs
Test Coverage
require 'singleton'
require 'logger'
require 'yaml'

module Watirmark

  class Configuration
    include Singleton

    def initialize
      @settings         = {}
      @runtime_defaults = {}
      reload
    end

    def defaults
      {
        :configfile         => nil,
        :hostname           => nil,
        :email              => 'devnull',
        :closebrowseronexit => false,
        :loglevel           => Logger::INFO,
        :uuid               => nil,
        :webdriver          => :firefox,
        :headless           => false,
        :always_locate      => true,
        :prefer_css         => false,
        :watir_timeout      => 30,
        :http_timeout       => 60,
        :firebug            => false,
        # database
        :dbhostname         => nil,
        :dbusername         => nil,
        :dbpassword         => nil,
        :dbsid              => nil,
        :dbport             => nil,
        # snapshots
        :snapshotwidth      => 1000,
        :snapshotheight     => 1000,
        :projectpath        => nil,
        :sauce_username     => nil,
        :sauce_access_key   => nil,
        :dbi_url            => nil,

        #to deprecate
        :profile            => Hash.new { |h, k| h[k] = Hash.new },
        :profile_name       => :undefined,

      }.merge @runtime_defaults
    end

    def defaults=(x)
      @runtime_defaults.merge! x
      reload
    end

    def update(values)
      values.each_pair { |k, v|
        v = Logger.const_get(v.upcase) if k.to_s == "loglevel" && v.class == String
        self[k] = v
      }
    end

    def inspect
      @settings.inspect
    end

    def reset
      @settings.each_key { |key| @settings.delete key }
    end

    def [](key)
      @settings[key.to_sym]
    end

    def []=(key, value)
      override_method = "#{key}_value".to_sym
      if respond_to? override_method
        @settings[key.to_sym] = self.send override_method, value
      else
        @settings[key.to_sym] = value
      end
    end

    def method_missing(sym, *args)
      if sym.to_s =~ /(.+)=$/
        self[$1] = args.first
      else
        self[sym]
      end
    end

    def db
      @db = nil if (@db && @db.respond_to?(:dbh) && @db.dbh.handle == nil)
      @db ||= WatirmarkDB::DB.new(self.hostname, self.dbhostname, self.dbusername, self.dbpassword, self.dbsid, self.dbport)
    end


    # This will read in ANY variable set in a configuration file
    def read_from_file
      return unless File.exists?(configfile.to_s)
      filename = File.expand_path(configfile)
      case File.extname filename
        when ".txt", ".hudson"
          parse_text_file filename
        when ".yml"
          parse_yaml_file filename
        else
          Watirmark.logger.warn "Unsure how to handle configuration file #{configfile}. Assuming .txt"
          parse_text_file filename
      end
    end

    alias :read :read_from_file

    # The variable needs to be set as a default here or in the
    # library to be read from the environment
    def read_from_environment
      @settings.each_key do |var|
        next if var.to_s.upcase == "USERNAME"
        next if var.to_s.upcase == "HOSTNAME" && self.hostname
        env = ENV[var.to_s.upcase]
        if var == :webdriver
          ENV['JOB_NAME']=~ /WEBDRIVER=(\w+)/
          env ||= $1
        end
        update_key var, env if env
      end
    end

    def reload
      update(defaults)
      read_from_file
      read_from_environment
      initialize_logger
    end

    def logger
      @logger ||= begin
        log = Logger.new STDOUT
        log.formatter = proc {|severity, datetime, progname, msg| "[#{datetime}] #{msg}\n"}
        log
      end
    end

    def loglevel=(x)
      logger.level = x
    end

    private

    def update_key key, value
      case value
        when 'true'
          update key.to_sym => true
        when 'false'
          update key.to_sym => false
        when /^:(.+)/
          update key.to_sym => $1.to_sym
        when /^\d+\s*$/
          update key.to_sym => value.to_i
        when /^(\d*\.\d+)\s*$/
          update key.to_sym => value.to_f
        else
          update key.to_sym => value
      end
    end

    def update_profile key
      return unless key =~ /^profile\[:(.+)\]\[:(.+)\]/
      logger.warn "profiles are going to be deprecated. Please use YAML and salesforce_sites"
      if self[:profile][$1.to_sym] == nil
        self[:profile] = ({$1.to_sym => {$2.to_sym => value.to_s}})
      else
        self[:profile][$1.to_sym].merge!({$2.to_sym => value.to_s})
      end
    end

    def update_profile_yaml
      if self[:salesforce_sites] && self[:salesforce_sites]["active"]
        site = self[:salesforce_sites]["active"]
        self[:salesforce_sites][site].each do |key, value|
          self[key.to_sym] = value
        end
      end
    end

    def parse_yaml_file filename
      YAML.load_file(filename).each_pair { |key, value| update_key key, value }
      update_profile_yaml
    end

    # This is the old-style method of using a config.txt
    def parse_text_file filename
      Watirmark.logger.warn "Warning: Deprecated use of config.txt. Please use config.yml instead"
      IO.readlines(filename).each do |line|
        line.strip!                 # Remove all extraneous whitespace
        line.sub!(/#.*$/, "")       # Remove comments
        next unless line.length > 0 # Anything left?
        (key, value) = line.split(/\s*=\s*/, 2)
        update_profile key
        update_key key, value
      end
    end
  end

  def self.logger
    Configuration.instance.logger ||= Logger.new(STDOUT)
  end

end