MacCracken/watir-performance

View on GitHub
lib/watir-performance.rb

Summary

Maintainability
A
2 hrs
Test Coverage
require 'ostruct'

module Watir
  # Adds helper for window.performance to Watir::Browser.
  # @see http://dev.w3.org/2006/webapi/WebTiming/
  class PerformanceHelper
    def initialize(data)
      @data = data
      @hash = {}
    end

    def munge
      OpenStruct.new(summarized_hash(data_to_hash))
    end

    def data_to_hash
      @data.each_key do |key|
        next if key == '__fxdriver_unwrapped'
        @hash[key.to_sym] = {}
        next unless @data[key].respond_to? :each
        @data[key].each do |k, v|
          next if k == '__fxdriver_unwrapped'
          @hash[key.to_sym][underscored(k).to_sym] = v
        end
      end
      @hash
    end

    def summarized_hash(hash)
      hash[:summary] = {}
      timing = hash[:timing]
      hash[:summary][:redirect] = redirect_timer(timing)
      hash[:summary][:app_cache] = app_cache(timing)
      hash[:summary][:dns] = hash[:timing][:domain_lookup_end] -
        hash[:timing][:domain_lookup_start] if hash[:timing][:domain_lookup_start] > 0
      hash[:summary][:tcp_connection] = hash[:timing][:connect_end] -
        hash[:timing][:connect_start] if hash[:timing][:connect_start] > 0
      hash[:summary][:tcp_connection_secure] = hash[:timing][:connect_end] -
        hash[:timing][:secure_connection_start] if
          ((hash[:timing][:secure_connection_start] != nil) and
           (hash[:timing][:secure_connection_start] > 0))
      hash[:summary][:request] = hash[:timing][:response_start] -
        hash[:timing][:request_start] if hash[:timing][:request_start] > 0
      hash[:summary][:response] = hash[:timing][:response_end] -
        hash[:timing][:response_start] if hash[:timing][:response_start] > 0
      hash[:summary][:dom_processing] = hash[:timing][:dom_content_loaded_event_start] -
        hash[:timing][:dom_loading] if hash[:timing][:dom_loading] > 0
      hash[:summary][:time_to_first_byte] = hash[:timing][:response_start] -
        hash[:timing][:domain_lookup_start] if hash[:timing][:domain_lookup_start] > 0
      hash[:summary][:time_to_last_byte] = hash[:timing][:response_end] -
        hash[:timing][:domain_lookup_start] if hash[:timing][:domain_lookup_start] > 0
      hash[:summary][:response_time] = latest_timestamp(hash) - earliest_timestamp(hash)
      hash
    end

    private

    def underscored(camel_cased_word)
      word = camel_cased_word.to_s.dup
      word.gsub!(/::/, '/')
      word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
      word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
      word.tr!('-', '_')
      word.downcase!
      word
    end

    def timer_checks(timers, hash)
      timers.each do |timer|
        return hash[:timing][timer] if hash[:timing][timer] > 0
      end
    end

    def timer_summerize(t_start, t_end, standard, hash)
      case standard
      when true
        hash[t_end] - hash[t_start] if hash[t_end] > 0
      else
        hash[t_end] - hash[t_start] if hash[t_start] > 0
      end
    end

    def redirect_timer(hash)
      hash[:redirect_end] - hash[:redirect_start] if hash[:redirect_end] > 0
    end

    def app_cache(hash)
      hash[:domain_lookup_start] - hash[:fetch_start] if hash[:fetch_start] > 0
    end

    def earliest_timestamp(hash)
      timers = %i[navigation_start redirect_start redirect_end fetch_start]
      timer_checks(timers, hash)
    end

    def latest_timestamp(hash)
      timers = %i[load_event_end load_event_start dom_complete
                  dom_content_loaded_event_end dom_content_loaded_event_start
                  dom_interactive response_end]
      timer_checks(timers, hash)
    end
  end

  PERFORMS = 'return window.performance || window.webkitPerformance || '\
             'window.mozPerformance || window.msPerformance;'.freeze
  ERRORMESSAGE = 'Could not collect performance metrics from your current ' \
                'browser. Please ensure the browser you are using supports ' \
                'collecting performance metrics.'.freeze

  # Extending Watir Browser
  # See Documentation Here
  # https://www.rubydoc.info/gems/watir/
  class Browser
    def performance
      data = case driver.browser
             when :internet_explorer
               script = 'return JSON.stringify(window.performance.toJSON());'
               cmd = driver.execute_script(script)
               ::Object::JSON.parse(cmd)
             else
               driver.execute_script(PERFORMS)
             end
      raise ERRORMESSAGE if data.nil?

      PerformanceHelper.new(data).munge
    end

    def performance_supported?
      driver.execute_script(PERFORMS)
    end
    alias performance_data performance_supported?

    def with_performance
      yield PerformanceHelper.new(performance_data).munge if performance_supported?
    end
  end
end