Class: FixtureTree

Inherits:
Object
  • Object
show all
Defined in:
lib/fixture_tree.rb,
lib/fixture_tree/rspec_support.rb

Overview

Helper for creating directory hierarchies to use with tests.

You’ll typically create trees with ‘FixtureTree.create`. If you’re using RSpec, put this inside one of your specs:

around do |example|
  FixtureTree.create do |tree|
    @tree = tree
    example.run
  end
end

Now put some data into your tree:

before do
  @tree.merge({
    'one' => 'two', # keys can be either strings...
    three: 'four',  # ...or symbols
    five: {         # create nested directories by using a hash
      six: 'seven'
    }
  })
end

And test against it:

it "has a file named 'one' whose contents are 'two'" do
  expect(@tree.path.join('one').open.read).to eq('two') # FixtureTree#path returns a Pathname object
end

it "has a nested directory named 'five' with a file named 'six' whose contents are 'seven'" do
  expect(@tree.path.join('five/six').open.read).to eq('seven')
end

You can add additional files if a test calls for them:

it 'lets me add additional files and keeps existing ones around' do
  @tree.merge({
    'eight.txt' => 'nine'
  })
  expect(@tree.path.join('eight.txt').open.read).to eq('nine')
  expect(@tree.path.join('one').open.read).to eq('two')
end

Or you can replace the entire tree:

it 'lets me replace the entire tree' do
  @tree.replace({
    ten: 'eleven'
  })
  expect(@tree.path.join('ten').open.read).to eq('eleven')
  expect(@tree.path.join('one').exist?).to be(false)
end

The tree will be automatically deleted when your ‘FixtureTree#create` block exits.

Defined Under Namespace

Modules: RSpecSupport

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ FixtureTree

Wrap the specified ‘Pathname` instance with a `FixtureTree` that can be used to modify it. No special cleanup will be undertaken after you’re done testing if you create a ‘FixtureTree` this way, so you’ll need to make sure to delete it after you’re done with it.



61
62
63
# File 'lib/fixture_tree.rb', line 61

def initialize(path)
  @path = path
end

Instance Attribute Details

#pathObject (readonly)

Returns the value of attribute path.



56
57
58
# File 'lib/fixture_tree.rb', line 56

def path
  @path
end

Class Method Details

.createObject

Create an ephemeral ‘FixtureTree`.

If a block is given, the tree will be yielded to the block, and the tree’s data (including any modifications made to it during the course of testing) will be deleted when the block exits. If not, ‘[dir, tree]` will be returned, where `dir` is a Pathname object pointing to a temporary directory containing the tree and `tree` is the ephemeral `FixtureTree` object. The tree’s contents can be cleaned up by deleting ‘dir` after testing is complete.



71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/fixture_tree.rb', line 71

def self.create
  temp_dir = Pathname.new(Dir.mktmpdir('fixture_tree'))
  tree = FixtureTree.new(temp_dir.join('fixture'))

  if block_given?
    begin
      yield FixtureTree.new(temp_dir.join('fixture'))
    ensure
      temp_dir.rmtree if temp_dir.exist?
    end
  else
    [temp_dir, tree]
  end
end

Instance Method Details

#deleteObject

Deletes this ‘FixtureTree`, if it exists. If this tree is currently a directory, it will be removed along with its children. If this tree is currently a file, the file will be deleted.

‘merge` or `replace` can later be called to recreate this `FixtureTree`.



121
122
123
124
125
126
127
128
129
# File 'lib/fixture_tree.rb', line 121

def delete
  if @path.directory?
    @path.rmtree
  elsif @path.exist?
    @path.delete
  end

  self
end

#join(path) ⇒ Object

Return a ‘FixtureTree` offering a view on a nested path of this `FixtureTree`. This can be used like:

some_tree.join('foo/bar').merge({'baz' => 'qux'})

to get the same effect as:

some_tree.merge({'foo' => {'bar' => {'baz' => 'qux'}}})


138
139
140
# File 'lib/fixture_tree.rb', line 138

def join(path)
  FixtureTree.new(@path.join(path))
end

#merge(data) ⇒ Object

Merge the given directory hierarchy or file into this ‘FixtureTree`.

‘data` can be either a string or a hash. If it’s a hash, this ‘FixtureTree` will be created as a directory if it’s not already one and a file or directory created for each entry in the hash. Values can themselves be strings or hashes to create nested files or directories, respectively. If it’s a string, this ‘FixtureTree` will be created as a file whose contents are the specified string.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/fixture_tree.rb', line 92

def merge(data)
  if data.is_a?(Hash)
    delete unless @path.directory?
    @path.mkpath

    data.each do |name, contents|
      join(name.to_s).merge(contents)
    end
  else
    delete
    @path.write(data)
  end

  self
end

#replace(data) ⇒ Object

Replace this ‘FixtureTree` with the specified directory hierarchy or file. This is equivalent to calling `delete` followed by `merge(data)`.



110
111
112
113
114
115
# File 'lib/fixture_tree.rb', line 110

def replace(data)
  delete
  merge(data)

  self
end