lax 0.2.1 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,30 +1,65 @@
1
1
  lax
2
2
  ===
3
- Lax is an insouciant smidgen of a testing framework that tries to be an invisible wrapper around your ideas about how your code should work.
3
+ Lax is an insouciant smidgen of a testing framework that tries hard to be an invisible wrapper around your ideas about how your code works.
4
4
  ```ruby
5
- Lax.assert do
6
- let number: 1,
7
- string: 'Hi There',
8
- regexp: defer{ /the/ } # lazy evaluation
9
-
10
- number + 1 == 2
11
- string.downcase =~ regexp
5
+ Lax.scope do
6
+ let number: 1, # let defines targets that are appropriately scoped and
7
+ string: 'Hi There', # re-instantiated for each assertion block.
8
+ regexp: lazy{ /the/ } # <- lazy evaluation
12
9
 
13
10
  assert do
14
- let number: 2
15
- number - 1 == 1
11
+ that number + 1 == 2, # these assertions can pass or fail independently
12
+ string.downcase =~ regexp
13
+
14
+ that(regexp.hash).satisfies {|obj| obj.is_a? Fixnum} # you can also easily define your own conditions
16
15
  end
17
- end
18
16
 
19
- Lax::Run[ Lax ] #=> pass, pass, pass
17
+ string { upcase.strip == 'HI THERE' } # you can also make assertions like this
18
+
19
+ before { puts "hiii. i am a callback. i will be run once for each assertion block in my scope." }
20
+
21
+ scope do
22
+ before { puts "i will be run after the before callback in my enclosing scope." }
23
+ before { @this_ivar = 'is visible in assertion blocks' }
24
+ after { puts 'after callbacks also are a thing' }
25
+
26
+
27
+ def self.number_is_even # rspec-like 'shared examples' can be defined like this.
28
+ number { even? }
29
+ end
30
+
31
+ let number: 2,
32
+ nothing: regexp.match('ffff') # compound target
33
+ bool: true
34
+
35
+ number_is_even
36
+
37
+ assert 'documented tests' do # docstrings can optionally be attached to assertion groups.
38
+ that number - 1 == 1,
39
+ string.upcase == 'HI THERE', # string is still in scope
40
+ nothing == nil
41
+ end
42
+ end
43
+
44
+ scope do
45
+ let lax: self,
46
+ open_file: fix(read: "data\nof\nimmediate\ninterest ") # fixtures are also a thing
47
+ assert do
48
+ that lax.respond_to?(:bool) == false, # bool is out of scope
49
+ open_file.read.lines.map(&:strip).size == 4
50
+ end
51
+ end
52
+ end
20
53
 
54
+ Lax::Run[ Lax ] #=> green dots aww yeah
21
55
  ```
22
56
  how come lax is neat
23
57
  --------------------
24
- * Minimal bullshit legalese.
25
- * Easy-to-define custom matchers and hooks.
26
- * Hackable with a tiny code footprint (< 300 SLOC).
27
- * Does not pollute your toplevel namespace or infect the entire Ruby object hierarchy with its code.
58
+ * Minimal legalese.
59
+ * Easy-to-define custom matchers.
60
+ * Built-in Rake task generator for quick setup.
61
+ * Small & hackable is a design goal (< 150 SLOC with plenty of hooks for your code)
62
+ * Does not work by infecting the entire object system with its code - neighbourly!
28
63
 
29
64
  how to make it do it
30
65
  --------------------
@@ -32,7 +67,7 @@ how to make it do it
32
67
  gem install lax
33
68
  cd my/project/root
34
69
  echo "require 'lax/rake_task'; Lax::RakeTask.new" >> Rakefile
35
- # write yr tests in the test directory (default test)
70
+ # write tests in yr test directory (defaults to 'test')
36
71
  rake lax
37
72
  ```
38
73
 
data/lib/lax.rb CHANGED
@@ -1,4 +1,138 @@
1
- Object::Lax = Class.new(Array)
2
- Lax::SOURCE = File.new(File.expand_path('../lax/source.rb', __FILE__)).read
3
- Lax.class_eval Lax::SOURCE
1
+ class Lax < Array
2
+ VERSION = '0.2.3'
3
+
4
+ Lazy = Class.new Proc
5
+ Run = ->(lax=Lax, fin=->(n){n}) do
6
+ fin.call lax.select {|l| l.included_modules.include? AssertionGroup}.map(&:new).flatten
7
+ end
8
+ Assertion = Struct.new(:pass, :source, :doc, :exception)
9
+
10
+ @lings = []
11
+ extend Enumerable
12
+ def self.inherited(ling)
13
+ @lings << ling
14
+ ling.lings = []
15
+ end
16
+
17
+ class << self
18
+ attr_accessor :lings, :src, :doc
19
+
20
+ def each(&b)
21
+ yield self
22
+ lings.each {|c| c.each(&b)}
23
+ end
24
+
25
+ def let(h)
26
+ h.each do |key, value|
27
+ val = (Lazy===value) ? value : lazy{value}
28
+ define_singleton_method(key) do |&b|
29
+ b ? assert { that val.call.instance_exec(&b) } : val.call
30
+ end
31
+ define_method(key) do
32
+ (@_memo||={}).has_key?(key)? @_memo[key] : @_memo[key] = val.call
33
+ end
34
+ end
35
+ end
36
+
37
+ def lazy
38
+ Lazy.new
39
+ end
40
+
41
+ def fix(hash)
42
+ Struct.new(*hash.keys).new *hash.values
43
+ end
44
+
45
+ def before(&bef)
46
+ ->(m) { define_method(:before) do |*a|
47
+ m.bind(self).call *a
48
+ instance_exec(*a, &bef)
49
+ end }.call instance_method :before
50
+ end
51
+
52
+ def assert(doc=nil,&spec)
53
+ scope do
54
+ @doc, @src = doc, spec.source_location
55
+ include AssertionGroup
56
+ before(&spec)
57
+ end
58
+ end
59
+
60
+ def scope(&b)
61
+ Class.new(self, &b)
62
+ end
63
+
64
+ def after(&aft)
65
+ ->(m) { define_method(:after) do |*a|
66
+ instance_exec(*a, &aft)
67
+ m.bind(self).call *a
68
+ end }.call instance_method :after
69
+ end
70
+
71
+ def matcher(sym,&p)
72
+ define_method(sym) { satisfies &p}
73
+ end
74
+ end
75
+
76
+ def before(*a); end
77
+ def after(*a); end
78
+
79
+ module AssertionGroup
80
+ def fix(hash)
81
+ self.class.fix hash
82
+ end
83
+
84
+ def that(*as)
85
+ concat as.map {|a| assert a}
86
+ end
87
+
88
+ def satisfies
89
+ push assert yield pop
90
+ end
91
+
92
+ def assert(v,x=nil)
93
+ Assertion.new !!v, self.class.src, self.class.doc, x
94
+ end
95
+
96
+ def initialize
97
+ before
98
+ rescue => e
99
+ push assert(false, e)
100
+ ensure
101
+ after self
102
+ end
103
+ end
104
+
105
+ module RakeTask
106
+ def self.new(opts = {})
107
+ require 'rake'
108
+ extend Rake::DSL
109
+ o = {dir: :test, name: :lax}.merge(opts)
110
+ namespace o[:name] do
111
+ task(:load) { Dir["./#{o[:dir]}/**/*.rb"].each {|f| load f} }
112
+ task(:run) do
113
+ Lax.after &Output::DOTS
114
+ Run[ Lax, ->(n){Output::FAILURES[n]; Output::SUMMARY[n]} ]
115
+ end
116
+ end
117
+ task o[:name] => ["#{o[:name]}:load", "#{o[:name]}:run"]
118
+ end
119
+ end
120
+
121
+ module Output
122
+ DOTS = ->(tc) {
123
+ tc.each {|c| print c.pass ? "\x1b[32m.\x1b[0m" : "\x1b[31mX\x1b[0m"}
124
+ }
125
+
126
+ SUMMARY = ->(cs) {
127
+ puts "pass: #{cs.select(&:pass).size}\nfail: #{cs.reject(&:pass).size}"
128
+ }
129
+ FAILURES = ->(cs) {
130
+ puts
131
+ cs.reject(&:pass).each do |f|
132
+ puts " failure in #{f.doc || 'an undocumended node'} at #{f.source*?:}"
133
+ puts " raised #{f.exception.class} : #{f.exception.message}" if f.exception
134
+ end
135
+ }
136
+ end
137
+ end
4
138
 
@@ -2,25 +2,42 @@ require 'spec_helper'
2
2
 
3
3
  describe Lax do
4
4
 
5
- let :simple_case do
6
- Lax.assert do
7
- let number: 19,
8
- string: 'asdf',
9
- symbol: :symbol
5
+ context 'a simple case' do
6
+ let :simple_case do
7
+ Lax.scope do
8
+ let number: 19,
9
+ string: 'asdf',
10
+ symbol: :symbol
10
11
 
11
- number.odd? == true
12
- number == 19
13
- string == 'asdf'
14
- number == 20
15
- string.upcase == 'ASDF'
16
- symbol.to_s == 'symbol'
12
+ assert do
13
+ that number.odd? == true,
14
+ number == 19,
15
+ string == 'asdf',
16
+ number == 20,
17
+ string.upcase == 'ASDF',
18
+ symbol.to_s == 'symbol'
19
+ end
20
+ end
17
21
  end
22
+
23
+ subject { simple_case.lings.last.new }
24
+ it { should have(6).things }
25
+ specify { subject.select(&:pass).should have(5).things }
26
+ specify { subject.reject(&:pass).should have(1).things }
18
27
  end
19
28
 
20
- subject { simple_case.new }
21
- it { should have(6).things }
22
- specify { subject.select(&:pass?).should have(5).things }
23
- specify { subject.reject(&:pass?).should have(1).things }
29
+ context 'compound targets' do
30
+ let :comp do
31
+ Lax.scope do
32
+ let number: 21
33
+ let thirty: number + 9
34
+ assert { that thirty == 30 }
35
+ end
36
+ end
37
+ subject { comp.lings.last.new }
38
+ it { should have(1).thing }
39
+ specify { subject.first.pass.should == true }
40
+ end
24
41
 
25
42
  end
26
43
 
data/spec/spec_helper.rb CHANGED
@@ -6,5 +6,4 @@ RSpec.configure do |config|
6
6
  config.color_enabled = true
7
7
  end
8
8
 
9
- Lax.config.run.hooks.after = Lax::Hook.noop # suppress output
10
9
 
@@ -1,20 +1,38 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Lax do
4
- subject { Lax }
4
+ let(:lax) { Class.new(Lax) }
5
5
 
6
6
  describe '::let' do
7
- before do
8
- Lax.let number: 1
9
- Lax.number == 1
10
- end
11
- subject { Lax.instance_methods - Lax.superclass.instance_methods }
12
- it { should have(1).thing }
7
+ before { lax.let number: 1 }
8
+ specify { lax.methods.should include :number }
9
+ specify { lax.instance_methods.should include :number }
10
+ specify { lax.number.should == 1 }
11
+ specify { lax.new.number.should == 1 }
13
12
  end
14
13
 
15
14
  describe '#initialize' do
16
- subject { Lax.reboot.new }
15
+ subject { lax.new }
17
16
  it { should be_empty }
18
17
  end
18
+
19
+ describe '::scope' do
20
+ subject { Lax.scope }
21
+ specify { Lax.lings.should include subject }
22
+ its(:superclass) { should == Lax }
23
+ its(:new) { should be_empty }
24
+ end
25
+
26
+ describe '::assert' do
27
+ subject do
28
+ Lax.scope do
29
+ let number: 22
30
+ assert('hahawow') { that number == 22 }
31
+ end.lings.last
32
+ end
33
+ specify { subject.superclass.superclass.should be Lax }
34
+ its(:doc) { should == 'hahawow' }
35
+ its(:new) { should have(1).thing }
36
+ end
19
37
  end
20
38
 
data/test/control.rb CHANGED
@@ -1,28 +1,77 @@
1
- Lax.assert do
1
+ Lax.scope do
2
2
  let number: 1,
3
- string: 'asdf',
4
- symbol: :a_sym,
5
- regexp: _{/asd/}
3
+ string: 'asdf',
4
+ symbol: :a_sym,
5
+ regexp: lazy{/asd/}
6
6
 
7
- assert do
8
- number == 1
9
- assert do
7
+ scope do
8
+ assert { that number == 1 }
9
+ scope do
10
10
  let number: 2
11
- number == 2
12
-
13
- string.upcase.downcase == 'asdf'
14
- string =~ regexp
11
+ assert do
12
+ that number == 2,
13
+ number.even?,
14
+ string.upcase.downcase == 'asdf',
15
+ string =~ regexp
16
+ end
15
17
  end
16
18
  end
17
19
  end
18
- Lax.assert do
20
+
21
+ Lax.scope do
19
22
  let number: 1,
20
- string: 'Hi There',
21
- regexp: defer{ /the/ }
22
- number + 1 == 2
23
- string.downcase =~ regexp
23
+ string: 'Hi There',
24
+ regexp: lazy{ /the/ } # lazy evaluation
25
+
26
+ string {upcase == 'HI THERE'}
27
+
24
28
  assert do
25
- let number: 2
26
- number - 1 == 1
29
+ that number + 1 == 2,
30
+ string.downcase =~ regexp
31
+ end
32
+
33
+ # before { puts "i will be run once for each assert block in my scope" }
34
+ # after { puts "are stackable" }
35
+
36
+ scope do
37
+
38
+ def self.number_is_even
39
+ number { even? }
40
+ end
41
+
42
+ let number: 2,
43
+ nothing: regexp.match('ffff'),
44
+ bool: true
45
+ before { @qqq=9}
46
+
47
+ number_is_even
48
+
49
+ assert 'documented tests' do
50
+ that number + @qqq == 11,
51
+ number - 1 == 1,
52
+ string.upcase == 'HI THERE', # string is in scope
53
+ nothing == nil
54
+ end
55
+ end
56
+
57
+ scope do
58
+ let lax: self,
59
+ open_file: fix(read: "data\nof\nimmediate\ninterest ") # fixtures
60
+ assert do
61
+ that lax.respond_to?(:bool) == false # bool is out of scope
62
+ that open_file.read.lines.map(&:strip).size == 4
63
+ end
27
64
  end
28
65
  end
66
+
67
+ Lax.scope do
68
+ let lax: Lax
69
+ assert do
70
+ group = lax.scope do
71
+ let altitude: 10000
72
+ assert { that altitude > 1000 }
73
+ end.lings.first.new
74
+ that group.size==1
75
+ end
76
+ end
77
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lax
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-22 00:00:00.000000000 Z
12
+ date: 2012-12-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -35,17 +35,12 @@ extra_rdoc_files: []
35
35
  files:
36
36
  - lax.gemspec
37
37
  - lib/lax.rb
38
- - lib/lax/rake_task.rb
39
- - lib/lax/source.rb
40
38
  - README.md
41
39
  - LICENSE
42
40
  - test/control.rb
43
41
  - spec/spec_helper.rb
44
42
  - spec/acceptance/acceptance_spec.rb
45
- - spec/unit/hook_spec.rb
46
- - spec/unit/target_spec.rb
47
43
  - spec/unit/lax_spec.rb
48
- - spec/unit/fixture/hashable_spec.rb
49
44
  homepage: http://github.com/gwentacle/lax
50
45
  licenses:
51
46
  - MIT/X11
@@ -75,7 +70,4 @@ test_files:
75
70
  - test/control.rb
76
71
  - spec/spec_helper.rb
77
72
  - spec/acceptance/acceptance_spec.rb
78
- - spec/unit/hook_spec.rb
79
- - spec/unit/target_spec.rb
80
73
  - spec/unit/lax_spec.rb
81
- - spec/unit/fixture/hashable_spec.rb
data/lib/lax/rake_task.rb DELETED
@@ -1,20 +0,0 @@
1
- require 'rake'
2
- require 'lax'
3
- class Lax
4
- module RakeTask
5
- class << self
6
- include Rake::DSL
7
- def new(opts = {})
8
- o = Lax.config.task.merge opts
9
- namespace o[:name] do
10
- task(:load) { Dir["./#{o[:dir]}/**/*.rb"].each {|f| load f} }
11
- task(:run) do
12
- Lax::Run[ Lax ]
13
- end
14
- end
15
- task o[:name] => ["#{o[:name]}:load", "#{o[:name]}:run"]
16
- end
17
- end
18
- end
19
- end
20
-
data/lib/lax/source.rb DELETED
@@ -1,288 +0,0 @@
1
- VERSION = '0.2.1'
2
-
3
- class Assertion < Struct.new :name, :subject, :condition, :src, :matcher, :args, :hooks
4
- def pass?
5
- memoize(:pass) { condition.call value }
6
- end
7
-
8
- def value
9
- memoize(:value) { subject.call }
10
- end
11
-
12
- def validate
13
- memoize(:validate) do
14
- hooks.before.call self
15
- pass?
16
- self.tap { hooks.after.call self }
17
- end
18
- end
19
-
20
- private
21
- def memoize(key)
22
- @memo ||= {}
23
- @memo.has_key?(key) ? @memo[key] : @memo[key] = yield
24
- end
25
-
26
- class Xptn < Struct.new :assertion, :exception
27
- attr_accessor :name, :src, :matcher, :args
28
-
29
- def pass?
30
- false
31
- end
32
-
33
- def value
34
- nil
35
- end
36
-
37
- def initialize(a, x)
38
- super
39
- %w{name src matcher args}.each {|m| send "#{m}=", a.send(m)}
40
- end
41
- end
42
- end
43
-
44
- module Fixture
45
- def self.new(hash)
46
- klass = Struct.new(*hash.keys)
47
- klass.send :include, self
48
- klass.new *hash.values
49
- end
50
-
51
- module Hashable
52
- def self.new(hashable)
53
- hash = hashable.to_hash
54
- klass = Struct.new(*hash.keys)
55
- klass.send :include, self, Fixture
56
- klass.new(*hash.values.map do |val|
57
- (Hash===val) ? new(val) : val
58
- end)
59
- end
60
-
61
- def to_hash
62
- Hash[
63
- members.zip entries.map {|e| e.kind_of?(Hashable) ? e.to_hash : e }
64
- ]
65
- end
66
-
67
- def merge(hashable)
68
- Hashable.new to_hash.merge hashable
69
- end
70
- end
71
- end
72
-
73
- class Target < BasicObject
74
- def self.define_matcher(sym, &p)
75
- define_method(sym) do |*a,&b|
76
- p ?
77
- satisfies(sym) do |o|
78
- p[*a.map {|v| resolve v},&b][o]
79
- end :
80
- satisfies(sym,*a) do |o|
81
- o.__send__ sym,*a.map {|v| resolve v},&b
82
- end
83
- end
84
- end
85
-
86
- def self.define_predicate(sym)
87
- if sym =~ /(.*)(\?|_?p)$/
88
- define_method($1) { satisfies($1) {|o| o.__send__ sym} }
89
- else
90
- raise ArgumentError, "#{sym} does not appear to be a predicate"
91
- end
92
- end
93
-
94
- %w{== === != =~ !~ < > <= >=}.each {|m| define_matcher m}
95
- %w{odd? even? is_a? kind_of? include?}.each {|m| define_predicate m}
96
-
97
- def initialize(node, subj, name, src)
98
- @node, @subj, @name, @src = node, subj, name, src
99
- end
100
-
101
- def satisfies(matcher=nil, *args, &cond)
102
- assert!(cond, *[ matcher, args ])
103
- end
104
-
105
- def method_missing(sym, *args, &blk)
106
- Target.new @node, ->{@subj.call.__send__(sym, *args, &blk)}, @name, @src
107
- end
108
-
109
- def __val__
110
- @subj.call
111
- end
112
-
113
- private
114
- def assert!(cond, matcher=nil, args=nil)
115
- name, subj, src, hooks = @name, @subj, @src, @node.hooks
116
- ord = @node.instance_methods.size.to_s
117
- @node.send(:include, ::Module.new do
118
- define_method(ord) do
119
- ::Lax::Assertion.new name, subj, cond, src, matcher, args, hooks
120
- end
121
- end)
122
- end
123
-
124
- def resolve(v)
125
- ::Lax::Target === v ? v.__val__ : v
126
- end
127
-
128
- end
129
-
130
- module Run
131
- def self.[](lax)
132
- hook = lax.config.run.hooks
133
- hook.start[ as = lax.map(&:new).flatten ]
134
- as.map do |assertion|
135
- hook.before[ assertion ]
136
- validate_protect(assertion).tap {|v| hook.after[v]}
137
- end.tap {|vs| hook.finish[vs]}
138
- end
139
-
140
- private
141
- def self.validate_protect(a)
142
- begin
143
- a.validate
144
- rescue => e
145
- Assertion::Xptn.new(a, e)
146
- end
147
- end
148
- end
149
-
150
- class Hook < Proc
151
- class << self
152
- def _resolve(hook)
153
- if hook.is_a? Hook
154
- hook
155
- elsif hook.is_a? Proc
156
- new &hook
157
- elsif hook.is_a?(Symbol) and self.respond_to?(hook)
158
- send hook
159
- else
160
- raise NameError, "Unable to resolve hook `#{hook}'"
161
- end
162
- end
163
-
164
- def noop
165
- new {|*a|}
166
- end
167
-
168
- def output
169
- new {|tc| print tc.pass? ? "\x1b[32m.\x1b[0m" : "\x1b[31mX\x1b[0m"}
170
- end
171
-
172
- # Returns a hook for generating terminal output from test cases.
173
- def summary
174
- new {|cs| puts "\nFinished #{cs.size} tests with #{cs.reject(&:pass?).size} failures"}
175
- end
176
-
177
- # Returns a hook for generating terminal output from test cases.
178
- def failures
179
- new do |cs|
180
- cs.reject(&:pass?).each do |f|
181
- puts " #{f.src}\n " <<
182
- "#{f.exception ?
183
- "(raised an unhandled #{f.exception.class})" :
184
- "(got #{f.subject})"}"
185
- end
186
- end
187
- end
188
-
189
- def define(sym, &p)
190
- define_singleton_method(sym) {new &p}
191
- end
192
- end
193
-
194
- def <<(hook)
195
- Hook.new {|*a,&b| call(Hook._resolve(hook)[*a,&b])}
196
- end
197
-
198
- def +(hook)
199
- Hook.new {|*a,&b| call(*a,&b); Hook._resolve(hook)[*a,&b]}
200
- end
201
- end
202
-
203
- CONFIG = Fixture::Hashable.new(
204
- task: { dir: :test, name: :lax },
205
- node: {
206
- hooks: {
207
- before: Hook.noop,
208
- after: Hook.noop
209
- }
210
- },
211
- run: {
212
- hooks: {
213
- start: Hook.noop,
214
- before: Hook.noop,
215
- after: Hook.output,
216
- finish: Hook.summary
217
- }
218
- }
219
- )
220
-
221
- @hooks = CONFIG.node.hooks
222
- @children = []
223
-
224
- def self.inherited(child)
225
- @children << child
226
- child.hooks = @hooks.dup
227
- child.children = []
228
- end
229
-
230
- extend Enumerable
231
-
232
- class << self
233
- attr_accessor :hooks, :children
234
-
235
- def reboot(suppress_warning = true)
236
- (stderr, $stderr = $stderr, StringIO.new) if suppress_warning
237
- Object.const_set :Lax, Class.new(Array)
238
- Lax.const_set :SOURCE, SOURCE
239
- Lax.class_eval SOURCE
240
- ($stderr = stderr) if suppress_warning
241
- Lax
242
- end
243
-
244
- def config
245
- block_given? ? yield(CONFIG) : CONFIG
246
- end
247
-
248
- def matcher(sym, &b)
249
- Target.define_matcher(sym, &b)
250
- end
251
-
252
- def hook(sym, &b)
253
- Hook.define(sym, &b)
254
- end
255
-
256
- def each(&b)
257
- yield self
258
- children.each {|c| c.each(&b)}
259
- end
260
-
261
- def let(h)
262
- h.each do |key, value|
263
- val = value.is_a?(Hook) ? value : ->{value}
264
- define_singleton_method(key) do
265
- Target.new(self, val, key, caller[0])
266
- end
267
- end
268
- end
269
-
270
- def defer(&v)
271
- Hook.new(&v)
272
- end
273
- alias _ defer
274
-
275
- def fix(hash)
276
- Fixture.new(hash)
277
- end
278
-
279
- def assert(*vals, &b)
280
- Class.new(self).tap {|node| node.class_eval(&b)}
281
- end
282
- end
283
-
284
- def initialize
285
- ks = methods - self.class.superclass.instance_methods
286
- ks.map {|k| send k}.each {|k| self << k}
287
- end
288
-
@@ -1,27 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Lax::Fixture::Hashable do
4
- let(:hash) { { name: 'phyllis', fears: { mild: ['spiders'], severe: ['manatees'] } } }
5
- let(:config) { Lax::Fixture::Hashable.new hash }
6
-
7
- describe '::new' do
8
- specify { ->{Lax::Fixture::Hashable.new}.should raise_error ArgumentError }
9
- specify { [:name, :fears].each {|msg| config.should respond_to msg } }
10
- specify { config.name.should == 'phyllis' }
11
- specify { config.fears.should be_a_kind_of Lax::Fixture::Hashable }
12
- end
13
-
14
- describe '#merge' do
15
- subject { config.merge manners: 'impeccable' }
16
- it { should be_a_kind_of Lax::Fixture::Hashable }
17
- specify { subject.name.should == 'phyllis' }
18
- specify { subject.manners.should == 'impeccable' }
19
- specify { subject.fears.should be_a_kind_of Lax::Fixture::Hashable }
20
- end
21
-
22
- describe '#to_hash' do
23
- subject { config.to_hash }
24
- it { should == hash }
25
- end
26
- end
27
-
@@ -1,40 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Lax::Hook do
4
- let(:one) { Lax::Hook.new {1} }
5
- specify { one.should be_a_kind_of Proc }
6
-
7
- describe '#<<' do
8
- let(:doubler) { Lax::Hook.new {|n| 2*n} }
9
- subject { doubler << one }
10
- its(:call) { should == 2 }
11
- end
12
-
13
- describe '#+' do
14
- let(:thing) { Object.new }
15
- let(:hash) { Lax::Hook.new { thing.hash } }
16
- subject { hash + one }
17
- its(:call) { should == 1 }
18
- specify do
19
- thing.should_receive :hash
20
- subject.call
21
- end
22
- end
23
-
24
- describe '::_resolve' do
25
- let(:resolve) { Lax::Hook.method :_resolve }
26
- context 'given a hook' do
27
- let(:hook) { Lax::Hook.new {:surprise!} }
28
- subject { resolve[hook] }
29
- it { should == hook }
30
- end
31
-
32
- context 'given a symbol' do
33
- let(:a_hook) { :noop }
34
- let(:random_sym) { :asdfqwer }
35
- specify { resolve[a_hook].call.should == nil }
36
- specify { -> {resolve[random_sym]}.should raise_error NameError }
37
- end
38
- end
39
- end
40
-
@@ -1,25 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Lax::Target do
4
- let(:node) { Lax.assert { let num: 1 } }
5
-
6
- describe 'establishing a target' do
7
- subject { node.num }
8
- specify { (Lax::Target === subject).should == true }
9
- specify { subject.__val__.should == 1 }
10
- end
11
-
12
- context 'when specifying a condition' do
13
- before { node.num == 1234 }
14
- specify { node.new.should have(1).thing }
15
- describe 'the entailed assertion' do
16
- subject { node.new.first }
17
- it { should be_an_instance_of Lax::Assertion }
18
- its(:subject) { should be_an_instance_of Proc }
19
- its(:name) { should == :num }
20
- its(:matcher) { should == '==' }
21
- its(:pass?) { should == false }
22
- end
23
- end
24
- end
25
-