1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
module GeneratorSpec
module Matcher
# Taken (with permission) from beard by Yahuda Katz
# https://github.com/carlhuda/beard
class File
def description
'file attributes and content'
end
def initialize(name, &block)
@contents = []
@name = name
@negative_contents = []
if block_given?
instance_eval(&block)
end
end
def contains(text)
@contents << text
end
def does_not_contain(text)
@negative_contents << text
end
def matches?(root)
unless root.join(@name).exist?
throw :failure, root.join(@name)
end
check_contents(root.join(@name))
end
protected
def check_contents(file)
contents = ::File.read(file)
@contents.each do |string|
unless contents.include?(string)
throw :failure, [file, string, contents]
end
end
@negative_contents.each do |string|
if contents.include?(string)
throw :failure, [:not, file, string, contents]
end
end
end
end
class Migration < File
def description
'valid migration file'
end
def matches?(root)
file_name = migration_file_name(root, @name)
unless file_name && file_name.exist?
throw :failure, @name
end
check_contents(file_name)
end
protected
def migration_file_name(root, name) #:nodoc:
directory, file_name = ::File.dirname(root.join(name)), ::File.basename(name).sub(/\.rb$/, '')
migration = Dir.glob("#{directory}/[0-9]*_*.rb").grep(/\d+_#{file_name}.rb$/).first
Pathname.new(migration) if migration
end
end
class Directory
attr_reader :tree
def description
'has directory structure'
end
def initialize(root = nil, &block)
@tree = {}
@negative_tree = []
@root = root
instance_eval(&block) if block_given?
end
def directory(name, &block)
@tree[name] = block_given? && Directory.new(location(name), &block)
end
def file(name, &block)
@tree[name] = File.new(location(name), &block)
end
def no_file(name)
@negative_tree << name
end
def location(name)
[@root, name].compact.join("/")
end
def migration(name, &block)
@tree[name] = Migration.new(location(name), &block)
end
def matches?(root)
@tree.each do |file, value|
unless value
unless root.join(location(file)).exist?
throw :failure, "#{root}/#{location(file)}"
end
else
value.matches?(root)
end
end
@negative_tree.each do |file|
if root.join(location(file)).exist?
throw :failure, [:not, "unexpected #{root}/#{location(file)}"]
end
end
nil
end
end
class Root < Directory
def description
'have specified directory structure'
end
def failure_message
if @failure.is_a?(Array) && @failure[0] == :not
if @failure.length > 2
"Structure should have #{@failure[1]} without #{@failure[2]}. It had:\n#{@failure[3]}"
else
"Structure should not have had #{@failure[1]}, but it did"
end
elsif @failure.is_a?(Array)
"Structure should have #{@failure[0]} with #{@failure[1]}. It had:\n#{@failure[2]}"
else
"Structure should have #{@failure}, but it didn't"
end
end
def matches?(root)
root = Pathname.new(root) unless root.is_a?(Pathname)
@failure = catch :failure do
super
end
!@failure
end
end
def have_structure(&block)
error = 'You must pass a block to have_structure (Use {} instead of do/end!)'
raise RuntimeError, error unless block_given?
Root.new(&block)
end
end
end
|