class CLIntegracon::FileTreeSpec

FileTreeSpec represents a single specification, which is mirrored on the file system in the spec directory by a direct children. It contains a before directory (before_path) and an after directory (after_path) or if it is initialized with a base_spec, the before directory of this spec is used. The before directory contents in the spec_path of the child spec, can contain further files, which overwrite, if given, the inherited contents.

Attributes

base_spec_name[R]

@return [String|NilClass]

The name of an optional #base_spec.
context[R]

@return [FileTreeSpecContext]

The context, which configures path and file behaviors
spec_folder[R]

@return [String]

The concrete spec folder

Public Class Methods

new(context, spec_folder, based_on: nil) click to toggle source

Init a spec with a given context

@param [FileTreeSpecContext] context

The context, which configures path and file behaviors

@param [String] spec_folder

The concrete spec folder

@param [String] based_on

@see #base_spec_name
# File lib/CLIntegracon/file_tree_spec.rb, line 90
def initialize(context, spec_folder, based_on: nil)
  @context = context
  @spec_folder = spec_folder
  @base_spec_name = based_on
end

Public Instance Methods

after_path() click to toggle source

@return [Pathname]

The concrete after directory for this spec
# File lib/CLIntegracon/file_tree_spec.rb, line 38
def after_path
  spec_path + context.after_dir
end
base_spec() click to toggle source

@return [FileTreeSpec|NilClass]

The spec on whose #after_path will be used as #before_path
for this spec.
# File lib/CLIntegracon/file_tree_spec.rb, line 75
def base_spec
  has_base? ? context.spec(base_spec_name) : nil
end
before_path() click to toggle source

@return [Pathname]

The concrete before directory for this spec
# File lib/CLIntegracon/file_tree_spec.rb, line 32
def before_path
  spec_path + context.before_dir
end
check_unexpected_files(&block) click to toggle source

Compares the expected and produced directory by using the rules defined in the context for unexpected files.

This is separate because you probably don't want to define an extra test case for each file, which wasn't expected at all. So you can keep your test cases consistent.

@param [Block<(Array)->()>] diff_block

The block, where you will likely define a test that no unexpected files exists.
It will receive an Array.
# File lib/CLIntegracon/file_tree_spec.rb, line 151
def check_unexpected_files(&block)
  expected_files = glob_all after_path
  produced_files = glob_all
  unexpected_files = produced_files - expected_files

  # Select only files
  unexpected_files.select! { |path| path.file? }

  # Filter ignored paths
  unexpected_files.reject! { |path| context.ignores?(path) }

  block.call unexpected_files
end
compare(&diff_block) click to toggle source

Compares the expected and produced directory by using the rules defined in the context

@param [Block<(Diff)->()>] diff_block

The block, where you will likely define a test for each file to compare.
It will receive a Diff of each of the expected and produced files.
# File lib/CLIntegracon/file_tree_spec.rb, line 121
def compare(&diff_block)
  # Get a copy of the outputs before any transformations are applied
  FileUtils.cp_r("#{temp_transformed_path}/.", temp_raw_path)

  transform_paths!

  glob_all(after_path).each do |relative_path|
    expected = after_path + relative_path

    next unless expected.file?
    next if context.ignores?(relative_path)

    block = context.preprocessors_for(relative_path).first
    diff = diff_files(expected, relative_path, &block)

    diff_block.call diff
  end
end
formatter() click to toggle source

Return a Formatter

@return [Formatter]

# File lib/CLIntegracon/file_tree_spec.rb, line 169
def formatter
  @formatter ||= Formatter.new(self)
end
has_base?() click to toggle source

Return whether this spec is based on another spec.

@return [Bool]

# File lib/CLIntegracon/file_tree_spec.rb, line 68
def has_base?
  !base_spec_name.nil?
end
run(&block) click to toggle source

Run this spec

@param [Block<(FileTreeSpec)->()>] block

The block, which will be executed after chdir into the created temporary
directory. In this block you will likely run your modifications to the
file system and use the received FileTreeSpec instance to make asserts
with the test framework of your choice.
# File lib/CLIntegracon/file_tree_spec.rb, line 104
def run(&block)
  prepare!

  copy_files!

  Dir.chdir(temp_transformed_path) do
    block.call self
  end
end
spec_path() click to toggle source

@return [Pathname]

The concrete spec path
# File lib/CLIntegracon/file_tree_spec.rb, line 26
def spec_path
  context.spec_path + spec_folder
end
temp_path() click to toggle source

@return [Pathname]

The concrete temp directory for this spec
# File lib/CLIntegracon/file_tree_spec.rb, line 44
def temp_path
  context.temp_path + spec_folder
end
temp_raw_path() click to toggle source

@return [Pathname]

The concrete temp raw directory for this spec
# File lib/CLIntegracon/file_tree_spec.rb, line 50
def temp_raw_path
  temp_path + 'raw'
end
temp_transformed_path() click to toggle source

@return [Pathname]

The concrete transformed temp directory for this spec
# File lib/CLIntegracon/file_tree_spec.rb, line 56
def temp_transformed_path
  temp_path + 'transformed'
end

Protected Instance Methods

copy_files!() click to toggle source

Copies the before subdirectory of the given tests folder in the raw directory.

# File lib/CLIntegracon/file_tree_spec.rb, line 189
def copy_files!
  destination = temp_transformed_path

  if has_base?
    FileUtils.cp_r("#{base_spec.temp_raw_path}/.", destination)
  end

  begin
    FileUtils.cp_r("#{before_path}/.", destination)
  rescue Errno::ENOENT => e
    raise e unless has_base?
  end
end
diff_files(expected, relative_path, &block) click to toggle source

Compares two files to check if they are identical and produces a clear diff to highlight the differences.

@param [Pathname] expected

The file in the after directory

@param [Pathname] relative_path

The file in the temp directory

@param [Block<(Pathname)->(to_s)>] block

the block, which transforms the files in a better comparable form

@return [Diff]

An object holding a diff
# File lib/CLIntegracon/file_tree_spec.rb, line 245
def diff_files(expected, relative_path, &block)
  produced = temp_transformed_path + relative_path
  Diff.new(expected, produced, relative_path, &block)
end
glob_all(path=nil) click to toggle source

Searches recursively for all files and take care for including hidden files if this is configured in the context.

@param [String] path

The relative or absolute path to search in (optional)

@return [Array<Pathname>]

# File lib/CLIntegracon/file_tree_spec.rb, line 222
def glob_all(path=nil)
  Dir.chdir path || '.' do
    Pathname.glob("**/*", context.include_hidden_files? ? File::FNM_DOTMATCH : 0).sort.reject do |p|
      %w(. ..).include?(p.basename.to_s)
    end
  end
end
prepare!() click to toggle source

Prepare the temporary directory

# File lib/CLIntegracon/file_tree_spec.rb, line 177
def prepare!
  context.prepare!

  temp_path.rmtree if temp_path.exist?
  temp_path.mkdir
  temp_raw_path.mkdir
  temp_transformed_path.mkdir
end
transform_paths!() click to toggle source

Applies the in the context configured transformations.

# File lib/CLIntegracon/file_tree_spec.rb, line 205
def transform_paths!
  glob_all.each do |path|
    context.transformers_for(path).each do |transformer|
      transformer.call(path) if path.exist?
    end
    path.rmtree if context.ignores?(path) && path.exist?
  end
end