mr_darcy 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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