mr_darcy 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +7 -0
  4. data/Gemfile +6 -0
  5. data/Gemfile.lock +95 -0
  6. data/Guardfile +14 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +267 -0
  9. data/Rakefile +6 -0
  10. data/lib/mr_darcy/context.rb +71 -0
  11. data/lib/mr_darcy/deferred.rb +25 -0
  12. data/lib/mr_darcy/drivers/celluloid.rb +23 -0
  13. data/lib/mr_darcy/drivers/synchronous.rb +15 -0
  14. data/lib/mr_darcy/drivers/thread.rb +22 -0
  15. data/lib/mr_darcy/drivers.rb +13 -0
  16. data/lib/mr_darcy/promise/base.rb +117 -0
  17. data/lib/mr_darcy/promise/celluloid.rb +52 -0
  18. data/lib/mr_darcy/promise/child_promise.rb +83 -0
  19. data/lib/mr_darcy/promise/dsl.rb +29 -0
  20. data/lib/mr_darcy/promise/em.rb +29 -0
  21. data/lib/mr_darcy/promise/state/base.rb +43 -0
  22. data/lib/mr_darcy/promise/state/rejected.rb +11 -0
  23. data/lib/mr_darcy/promise/state/resolved.rb +11 -0
  24. data/lib/mr_darcy/promise/state/unresolved.rb +19 -0
  25. data/lib/mr_darcy/promise/state.rb +25 -0
  26. data/lib/mr_darcy/promise/synchronous.rb +27 -0
  27. data/lib/mr_darcy/promise/thread.rb +64 -0
  28. data/lib/mr_darcy/promise.rb +31 -0
  29. data/lib/mr_darcy/role.rb +45 -0
  30. data/lib/mr_darcy/version.rb +3 -0
  31. data/lib/mr_darcy.rb +26 -0
  32. data/mr_darcy.gemspec +29 -0
  33. data/spec/acceptance/dci_bank_transfer_spec.rb +62 -0
  34. data/spec/acceptance/em_http_request_spec.rb +22 -0
  35. data/spec/acceptance/open-uri_http_request_spec.rb +21 -0
  36. data/spec/acceptance/simple_promise_spec.rb +25 -0
  37. data/spec/acceptance/simple_promise_with_chained_fail.rb +25 -0
  38. data/spec/acceptance/simple_promise_with_fail_spec.rb +25 -0
  39. data/spec/acceptance/simple_promise_with_then_spec.rb +25 -0
  40. data/spec/lib/mr_darcy/context_spec.rb +22 -0
  41. data/spec/lib/mr_darcy/promise/base_spec.rb +197 -0
  42. data/spec/lib/mr_darcy/promise/child_promise_spec.rb +169 -0
  43. data/spec/lib/mr_darcy/promise/dsl_spec.rb +43 -0
  44. data/spec/lib/mr_darcy/promise/state/base_spec.rb +24 -0
  45. data/spec/lib/mr_darcy/promise/state/rejected_spec.rb +12 -0
  46. data/spec/lib/mr_darcy/promise/state/resolved_spec.rb +12 -0
  47. data/spec/lib/mr_darcy/promise/state/unresolved_spec.rb +22 -0
  48. data/spec/lib/mr_darcy/promise/state_spec.rb +30 -0
  49. data/spec/lib/mr_darcy/promise/synchronous_spec.rb +21 -0
  50. data/spec/lib/mr_darcy/promise_spec.rb +72 -0
  51. data/spec/lib/mr_darcy/role_spec.rb +89 -0
  52. data/spec/lib/mr_darcy_spec.rb +19 -0
  53. data/spec/spec_helper.rb +10 -0
  54. data/spec/support/context_helpers.rb +19 -0
  55. data/spec/support/shared_examples_for_promise.rb +47 -0
  56. data/spec/support/shared_examples_for_thennable.rb +10 -0
  57. metadata +279 -0
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ class BankTransfer < MrDarcy::Context
4
+ role :money_source do
5
+ def has_available_funds? amount
6
+ available_balance >= amount
7
+ end
8
+
9
+ def subtract_funds amount
10
+ self.available_balance = available_balance - amount
11
+ end
12
+ end
13
+
14
+ role :money_destination do
15
+ def receive_funds amount
16
+ self.available_balance = available_balance + amount
17
+ end
18
+ end
19
+
20
+ action :transfer do |amount|
21
+ if money_source.has_available_funds? amount
22
+ money_source.subtract_funds amount
23
+ money_destination.receive_funds amount
24
+ else
25
+ raise "insufficient funds"
26
+ end
27
+ amount
28
+ end
29
+ end
30
+
31
+ Account = Struct.new(:available_balance)
32
+
33
+ describe 'DCI Bank Transfer' do
34
+ let(:money_source) { Account.new source_balance }
35
+ let(:money_destination) { Account.new destination_balance }
36
+
37
+ MrDarcy.all_drivers.each do |driver|
38
+ if driver == :synchronous
39
+ describe "Driver #{driver}" do
40
+ let(:context) { BankTransfer.new money_source: money_source, money_destination: money_destination, driver: driver }
41
+
42
+ When 'the source balance is 10' do
43
+ let(:source_balance) { 10 }
44
+
45
+ And 'the destination balance is 5' do
46
+ let(:destination_balance) { 5 }
47
+
48
+ When 'I transfer 8' do
49
+ subject { context.transfer(8).final }
50
+
51
+ its('money_source.available_balance') { should eq 2 }
52
+ its('money_destination.available_balance') { should eq 13 }
53
+ its(:result) { should be_nil }
54
+ end
55
+ end
56
+ end
57
+ end
58
+ else
59
+ pending "not working with driver #{driver} :("
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ require 'eventmachine'
3
+ require 'em-http-request'
4
+
5
+ describe "Wrapping em-http-request" do
6
+ let(:promise) do
7
+ MrDarcy::Promise.new driver: :em do |p|
8
+ http = EM::HttpRequest.new('http://camp.ruby.org.nz/').get
9
+ http.errback do
10
+ p.reject http.error
11
+ end
12
+ http.callback do
13
+ p.resolve http.response
14
+ end
15
+ end
16
+ end
17
+
18
+ subject { promise }
19
+
20
+ it_should_behave_like 'a resolved promise'
21
+ its(:result) { should match /Rails Camp NZ/i }
22
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+ require 'open-uri'
3
+
4
+ describe "Wrapping OpenURI" do
5
+ MrDarcy.all_drivers.each do |driver|
6
+ describe "driver #{driver}" do
7
+ let(:promise) do
8
+ MrDarcy::Promise.new driver: driver do |p|
9
+ open('http://camp.ruby.org.nz') do |f|
10
+ p.resolve f.read
11
+ end
12
+ end
13
+ end
14
+
15
+ subject { promise }
16
+
17
+ it_should_behave_like 'a resolved promise'
18
+ its(:result) { should match /Rails Camp NZ/i }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Simple promise" do
4
+
5
+ MrDarcy.all_drivers.each do |driver|
6
+ describe "with driver #{driver}" do
7
+ let(:promise) { MrDarcy::Promise.new(driver: driver, &promise_block) }
8
+ subject { promise }
9
+
10
+ When 'the promise resolves' do
11
+ let(:promise_block) { proc { |p| p.resolve 1 } }
12
+
13
+ it_should_behave_like 'a resolved promise'
14
+ its(:result) { should eq 1 }
15
+ end
16
+
17
+ When 'the promise rejects' do
18
+ let(:promise_block) { proc { |p| p.reject 1 } }
19
+
20
+ it_should_behave_like 'a rejected promise'
21
+ its(:result) { should eq 1 }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Promise with then and fail" do
4
+
5
+ MrDarcy.all_drivers.each do |driver|
6
+ describe "with driver #{driver}" do
7
+ let(:promise) { MrDarcy::Promise.new(driver: driver, &promise_block).then {}.fail { |v| v+1 } }
8
+ subject { promise }
9
+
10
+ When 'the promise resolves' do
11
+ let(:promise_block) { proc { |p| p.resolve 1 } }
12
+
13
+ it_should_behave_like 'a resolved promise'
14
+ its(:result) { should be_nil }
15
+ end
16
+
17
+ When 'the promise rejects' do
18
+ let(:promise_block) { proc { |p| p.reject 1 } }
19
+
20
+ it_should_behave_like 'a rejected promise'
21
+ its(:result) { should eq 2 }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Promise with fail" do
4
+
5
+ MrDarcy.all_drivers.each do |driver|
6
+ describe "with driver #{driver}" do
7
+ let(:promise) { MrDarcy::Promise.new(driver: driver, &promise_block).fail { |v| v+1 } }
8
+ subject { promise }
9
+
10
+ When 'the promise resolves' do
11
+ let(:promise_block) { proc { |p| p.resolve 1 } }
12
+
13
+ it_should_behave_like 'a resolved promise'
14
+ its(:result) { should eq 1 }
15
+ end
16
+
17
+ When 'the promise rejects' do
18
+ let(:promise_block) { proc { |p| p.reject 1 } }
19
+
20
+ it_should_behave_like 'a resolved promise'
21
+ its(:result) { should eq 2 }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Promise with then" do
4
+
5
+ MrDarcy.all_drivers.each do |driver|
6
+ describe "with driver #{driver}" do
7
+ let(:promise) { MrDarcy::Promise.new(driver: driver, &promise_block).then { |v| v+1 } }
8
+ subject { promise }
9
+
10
+ When 'the promise resolves' do
11
+ let(:promise_block) { proc { |p| p.resolve 1 } }
12
+
13
+ it_should_behave_like 'a resolved promise'
14
+ its(:result) { should eq 2 }
15
+ end
16
+
17
+ When 'the promise rejects' do
18
+ let(:promise_block) { proc { |p| p.reject 1 } }
19
+
20
+ it_should_behave_like 'a rejected promise'
21
+ its(:result) { should eq 1 }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe MrDarcy::Context do
4
+ context 'class methods' do
5
+ subject { described_class }
6
+ it { should respond_to :role }
7
+ it { should respond_to :action }
8
+
9
+ describe '.role' do
10
+ subject { described_class.role :test_name }
11
+
12
+ it { should be_a MrDarcy::Role }
13
+ its(:name) { should eq :test_name }
14
+ end
15
+
16
+ describe '.action' do
17
+ subject { -> { described_class.action :action_name, &->{} } }
18
+
19
+ it { should change { described_class.instance_methods.member? :action_name }.from(false).to(true) }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,197 @@
1
+ require 'spec_helper'
2
+
3
+ describe MrDarcy::Promise::Base do
4
+ let(:promise_block) { proc {} }
5
+ let(:mock_promise) do
6
+ Class.new(MrDarcy::Promise::Base) do
7
+ def schedule_promise
8
+ yield
9
+ end
10
+
11
+ def generate_child_promise
12
+ MrDarcy::Promise::ChildPromise.new driver: :synchronous
13
+ end
14
+ end.new(promise_block)
15
+ end
16
+ subject { mock_promise }
17
+
18
+ it_behaves_like :thenable
19
+
20
+ describe '#then' do
21
+ let(:then_block) { proc {} }
22
+ subject { mock_promise.then &then_block }
23
+
24
+ it_behaves_like :thenable
25
+
26
+ When 'the promise is already resolved' do
27
+ before { mock_promise.resolve :good }
28
+ it_behaves_like 'a resolved promise'
29
+
30
+ it 'calls the then block with the result' do
31
+ expect { |b| mock_promise.then(&b) }.to yield_with_args(:good)
32
+ end
33
+
34
+ it 'calls the then block only once' do
35
+ expect { |b| mock_promise.then(&b) }.to yield_control.once
36
+ end
37
+ end
38
+
39
+ When 'the promise is already rejected' do
40
+ before { mock_promise.reject :bad }
41
+ it_behaves_like 'a rejected promise'
42
+
43
+ it 'does not call the then block' do
44
+ expect { |b| mock_promise.then(&b) }.not_to yield_control
45
+ end
46
+ end
47
+
48
+ Otherwise do
49
+ it_behaves_like 'an unresolved promise'
50
+
51
+ it 'does not call the then block' do
52
+ expect { |b| mock_promise.then(&b) }.not_to yield_control
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '#fail' do
58
+ let(:fail_block) { proc {} }
59
+ subject { mock_promise.fail &fail_block }
60
+
61
+ it_behaves_like :thenable
62
+
63
+ When 'the promise is already resolved' do
64
+ before { mock_promise.resolve :good }
65
+ it_behaves_like 'a resolved promise'
66
+
67
+ it 'does not call the fail block' do
68
+ expect { |b| mock_promise.fail(&b) }.not_to yield_control
69
+ end
70
+ end
71
+
72
+ When 'the promise is already rejected' do
73
+ before { mock_promise.reject :bad }
74
+
75
+ When 'the fail block re-fails' do
76
+ let(:fail_block) { proc { raise :bad } }
77
+
78
+ it_behaves_like 'a rejected promise'
79
+ end
80
+
81
+ Otherwise do
82
+ it_behaves_like 'a resolved promise'
83
+ end
84
+
85
+ it 'calls the fail block with the result' do
86
+ expect { |b| mock_promise.fail(&b) }.to yield_with_args(:bad)
87
+ end
88
+
89
+ it 'calls the fail block only once' do
90
+ expect { |b| mock_promise.fail(&b) }.to yield_control.once
91
+ end
92
+ end
93
+
94
+ Otherwise do
95
+ it_behaves_like 'an unresolved promise'
96
+
97
+ it 'does not call the fail block' do
98
+ expect { |b| mock_promise.fail(&b) }.not_to yield_control
99
+ end
100
+ end
101
+ end
102
+
103
+ describe '#result' do
104
+ subject { -> { mock_promise.result } }
105
+ it { should raise_error }
106
+ end
107
+
108
+ describe '#final' do
109
+ subject { -> { mock_promise.final } }
110
+ it { should raise_error }
111
+ end
112
+
113
+ describe '#raise' do
114
+ before { mock_promise.stub result: :foo }
115
+ subject { -> { mock_promise.raise } }
116
+
117
+ When 'the promise is resolved' do
118
+ before { mock_promise.resolve :good }
119
+
120
+ it { should_not raise_error }
121
+ end
122
+
123
+ When 'the promise is rejected' do
124
+ before { mock_promise.reject :bad }
125
+
126
+ it { should raise_error }
127
+ end
128
+
129
+ When 'the promise is unresolved' do
130
+ it { should_not raise_error }
131
+ end
132
+ end
133
+
134
+ describe '#resolve' do
135
+ let(:resolve_value) { :good }
136
+ subject { mock_promise.resolve resolve_value }
137
+
138
+ When 'the promise is already resolved' do
139
+ before { mock_promise.resolve :previous }
140
+
141
+ specify { expect { subject }.to raise_error }
142
+ end
143
+
144
+ When 'the promise is already rejected' do
145
+ before { mock_promise.reject :previous }
146
+
147
+ specify { expect { subject }.to raise_error }
148
+ end
149
+
150
+ Otherwise do
151
+ specify { expect { subject }.to change{ mock_promise.resolved? }.from(false).to(true) }
152
+ specify { expect { subject }.to change{ mock_promise.unresolved? }.from(true).to(false) }
153
+
154
+ When 'there is a child promise' do
155
+ let(:then_block) { proc {} }
156
+ before { mock_promise.then(&then_block) }
157
+
158
+ it 'calls the then block' do
159
+ expect(then_block).to receive(:call).with(:good).once
160
+ subject
161
+ end
162
+ end
163
+ end
164
+ end
165
+
166
+ describe '#reject' do
167
+ let(:reject_value) { :bad }
168
+ subject { mock_promise.reject reject_value }
169
+
170
+ When 'the promise is already resolved' do
171
+ before { mock_promise.resolve :previous }
172
+
173
+ specify { expect { subject }.to raise_error }
174
+ end
175
+
176
+ When 'the promise is already rejected' do
177
+ before { mock_promise.reject :previous }
178
+
179
+ specify { expect { subject }.to raise_error }
180
+ end
181
+
182
+ Otherwise do
183
+ specify { expect { subject }.to change{ mock_promise.rejected? }.from(false).to(true) }
184
+ specify { expect { subject }.to change{ mock_promise.unresolved? }.from(true).to(false) }
185
+
186
+ When 'there is a child promise' do
187
+ let(:fail_block) { proc {} }
188
+ before { mock_promise.fail(&fail_block) }
189
+
190
+ it 'calls the fail block' do
191
+ expect(fail_block).to receive(:call).with(:bad).once
192
+ subject
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,169 @@
1
+ require 'spec_helper'
2
+
3
+ describe MrDarcy::Promise::ChildPromise do
4
+ let(:child_promise) { MrDarcy::Promise::ChildPromise.new driver: :Synchronous }
5
+ subject { child_promise }
6
+
7
+ it { should be_a MrDarcy::Deferred }
8
+
9
+ it { should respond_to :resolve_block }
10
+ it { should respond_to :reject_block }
11
+
12
+ describe '#parent_resolved' do
13
+ let(:resolve_value) { :good }
14
+ subject { child_promise.parent_resolved resolve_value }
15
+
16
+ When 'it handles success' do
17
+ let(:resolve_block) { proc {} }
18
+ before { child_promise.resolve_block = resolve_block }
19
+
20
+ it 'calls the resolve block' do
21
+ expect(resolve_block).to receive(:call).with(resolve_value)
22
+ subject
23
+ end
24
+
25
+ When 'the resolve block returns a value' do
26
+ let(:resolve_block) { proc { :new_value } }
27
+
28
+ it 'resolves' do
29
+ expect { subject }.to change { child_promise.resolved? }.from(false).to(true)
30
+ end
31
+
32
+ it 'sets the new value' do
33
+ expect { subject }.to change { child_promise.result }.to(:new_value)
34
+ end
35
+ end
36
+
37
+ When 'the resolve block returns a new promise' do
38
+ let(:promise_block) { proc {} }
39
+ let(:promise) { MrDarcy::Promise::Synchronous.new promise_block }
40
+ let(:resolve_block) { proc { promise } }
41
+
42
+ it 'doesn\'t resolve' do
43
+ expect { subject }.not_to change { child_promise.resolved? }
44
+ end
45
+
46
+ it 'doesn\'t set the value' do
47
+ expect { subject }.not_to change { child_promise.result }
48
+ end
49
+
50
+ When 'the promise eventually resolves' do
51
+ before { child_promise.parent_resolved resolve_value }
52
+ subject { promise.resolve :mr_good_stuff }
53
+
54
+ it 'resolves' do
55
+ expect { subject }.to change{ child_promise.resolved? }.from(false).to(true)
56
+ end
57
+
58
+ it 'has the new value' do
59
+ expect { subject }.to change { child_promise.result }.to(:mr_good_stuff)
60
+ end
61
+ end
62
+
63
+ When 'the promise eventually rejects' do
64
+ before { child_promise.parent_resolved resolve_value }
65
+ subject { promise.reject :mr_bad_stuff }
66
+
67
+ it 'rejects' do
68
+ expect { subject }.to change{ child_promise.rejected? }.from(false).to(true)
69
+ end
70
+
71
+ it 'has the new value' do
72
+ expect { subject }.to change { child_promise.result }.to(:mr_bad_stuff)
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ Otherwise do
79
+ it 'is resolved' do
80
+ subject
81
+ expect(child_promise).to be_resolved
82
+ end
83
+
84
+ it 'is resolved with the supplied value' do
85
+ subject
86
+ expect(child_promise.result).to eq(resolve_value)
87
+ end
88
+ end
89
+ end
90
+
91
+ describe '#parent_rejected' do
92
+ let(:reject_value) { :bad }
93
+ subject { child_promise.parent_rejected reject_value }
94
+
95
+ When 'it handles success' do
96
+ let(:reject_block) { proc {} }
97
+ before { child_promise.reject_block = reject_block }
98
+
99
+ it 'calls the reject block' do
100
+ expect(reject_block).to receive(:call).with(reject_value)
101
+ subject
102
+ end
103
+
104
+ When 'the reject block returns a value' do
105
+ let(:reject_block) { proc { :new_value } }
106
+
107
+ it 'resolves' do
108
+ expect { subject }.to change { child_promise.resolved? }.from(false).to(true)
109
+ end
110
+
111
+ it 'sets the new value' do
112
+ expect { subject }.to change { child_promise.result }.to(:new_value)
113
+ end
114
+ end
115
+
116
+ When 'the reject block returns a new promise' do
117
+ let(:promise_block) { proc {} }
118
+ let(:promise) { MrDarcy::Promise::Synchronous.new promise_block }
119
+ let(:reject_block) { proc { promise } }
120
+
121
+ it 'doesn\'t reject' do
122
+ expect { subject }.not_to change { child_promise.rejected? }
123
+ end
124
+
125
+ it 'doesn\'t set the value' do
126
+ expect { subject }.not_to change { child_promise.result }
127
+ end
128
+
129
+ When 'the promise eventually resolves' do
130
+ before { child_promise.parent_rejected reject_value }
131
+ subject { promise.resolve :mr_good_stuff }
132
+
133
+ it 'resolves' do
134
+ expect { subject }.to change{ child_promise.resolved? }.from(false).to(true)
135
+ end
136
+
137
+ it 'has the new value' do
138
+ expect { subject }.to change { child_promise.result }.to(:mr_good_stuff)
139
+ end
140
+ end
141
+
142
+ When 'the promise eventually rejects' do
143
+ before { child_promise.parent_rejected reject_value }
144
+ subject { promise.reject :mr_bad_stuff }
145
+
146
+ it 'rejects' do
147
+ expect { subject }.to change{ child_promise.rejected? }.from(false).to(true)
148
+ end
149
+
150
+ it 'has the new value' do
151
+ expect { subject }.to change { child_promise.result }.to(:mr_bad_stuff)
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ Otherwise do
158
+ it 'is rejected' do
159
+ subject
160
+ expect(child_promise).to be_rejected
161
+ end
162
+
163
+ it 'is rejected with the supplied value' do
164
+ subject
165
+ expect(child_promise.result).to eq(reject_value)
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe MrDarcy::Promise::DSL do
4
+
5
+ let(:promise) { double :promise }
6
+ let(:dsl) { described_class.new(promise) }
7
+ subject { dsl }
8
+
9
+ it { should respond_to :resolve }
10
+ it { should respond_to :reject }
11
+ it { should respond_to :unresolved? }
12
+ it { should respond_to :resolved? }
13
+ it { should respond_to :rejected? }
14
+ it { should respond_to :then }
15
+ it { should respond_to :fail }
16
+ it { should respond_to :result }
17
+ it { should respond_to :final }
18
+
19
+ describe '.new' do
20
+ its(:promise) { should eq promise }
21
+ end
22
+
23
+ describe '#resolve' do
24
+ subject { dsl.resolve :resolved_value }
25
+ before { promise.stub :value= => nil, resolve: nil }
26
+
27
+ it 'resolves the promise' do
28
+ promise.should_receive(:resolve).with(:resolved_value)
29
+ subject
30
+ end
31
+ end
32
+
33
+ describe '#reject' do
34
+ subject { dsl.reject :exception }
35
+ before { promise.stub :value= => nil, reject: nil }
36
+
37
+ it 'rejects the promise' do
38
+ promise.should_receive(:reject).with(:exception)
39
+ subject
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe MrDarcy::Promise::State::Base do
4
+ let(:initial_state) { 'unresolved'}
5
+ let(:stateful) { Struct.new(:state).new initial_state }
6
+ let(:state) { described_class.new stateful }
7
+ subject { state }
8
+
9
+ it { should respond_to :stateful }
10
+ it { should respond_to :stateful= }
11
+ it { should respond_to :unresolved? }
12
+ it { should respond_to :resolved? }
13
+ it { should respond_to :rejected? }
14
+
15
+ describe '#resolve' do
16
+ subject { -> { state.resolve } }
17
+ it { should raise_error }
18
+ end
19
+
20
+ describe '#reject' do
21
+ subject { -> { state.reject } }
22
+ it { should raise_error }
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe MrDarcy::Promise::State::Rejected do
4
+ let(:initial_state) { :unresolved }
5
+ let(:stateful) { Struct.new(:state).new initial_state }
6
+ let(:state) { described_class.new stateful }
7
+
8
+ subject { state }
9
+
10
+ it { should be_a MrDarcy::Promise::State::Base }
11
+ its(:rejected?) { should be_true }
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe MrDarcy::Promise::State::Resolved do
4
+ let(:initial_state) { :unresolved }
5
+ let(:stateful) { Struct.new(:state).new initial_state }
6
+ let(:state) { described_class.new stateful }
7
+
8
+ subject { state }
9
+
10
+ it { should be_a MrDarcy::Promise::State::Base }
11
+ its(:resolved?) { should be_true }
12
+ end