Sha256: c8244b3253cb98f1cb781916a956f36491a13ec281c8865ee7fd1293e545b926

Contents?: true

Size: 1.58 KB

Versions: 1

Compression:

Stored size: 1.58 KB

Contents

require 'set'
require 'yaml'

module TestFileFinder
  class Mapping
    attr_reader :pattern_matchers

    def self.load(mapping_file = nil)
      return default_rails_mapping unless mapping_file

      content = File.read(mapping_file)
      maps = YAML.load(content)['mapping']

      validate(maps)

      new do |mapping|
        maps.each do |map|
          source = map['source']
          test = map['test']
          mapping.relate(source, test)
        end
      end
    end

    def self.validate(maps)
      raise InvalidMappingFileError, 'missing `mapping` in test mapping file' if maps.nil?
      raise InvalidMappingFileError, 'missing `source` or `test` in test mapping file' if maps.any? { |map| incomplete?(map) }
    end

    def self.incomplete?(map)
      map['source'].nil? || map['test'].nil?
    end

    def self.default_rails_mapping
      new do |mapping|
        mapping.relate(%r{^app/(.+)\.rb$}, 'spec/%s_spec.rb')
        mapping.relate(%r{^lib/(.+)\.rb$}, 'spec/lib/%s_spec.rb')
        mapping.relate(%r{^spec/(.+)_spec.rb$}, 'spec/%s_spec.rb')
      end
    end

    def initialize
      @pattern_matchers = Hash.new { |h, k| h[k] = [] }

      yield self if block_given?
    end

    def relate(source, test)
      @pattern_matchers[source] << test
    end

    def match(file)
      @pattern_matchers.each_with_object(Set.new) do |(source, tests), result|
        regexp = %r{^#{source}$}

        if (match = regexp.match(file))
          test_files = tests.flat_map { |test| test % match.captures }
          result.merge(Array(test_files))
        end
      end.to_a
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
test_file_finder-0.1.0 lib/test_file_finder/mapping.rb