a-ruby-promise 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,156 @@
1
+ # encoding: UTF-8
2
+ require_relative "../spec_helper"
3
+ require_relative "../promises_aplus"
4
+
5
+ dummy = { dummy: "dummy" } # we fulfill or reject with this when we don't intend to test against it
6
+ sentinel = { sentinel: "sentinel" } # a sentinel fulfillment value to test for with strict equality
7
+
8
+ describe "2.2.2: If `onFulfilled` is a function," do
9
+ include PromisesAplus
10
+
11
+ describe "2.2.2.1: it must be called after `promise` is fulfilled, with `promise`’s fulfillment value as its first argument." do
12
+ PromisesAplus.test_fulfilled(self, sentinel) do |promise, done|
13
+ promise.then ->(value) {
14
+ value.must_equal sentinel
15
+ done.call
16
+ }
17
+ end
18
+ end
19
+
20
+ describe "2.2.2.2: it must not be called before `promise` is fulfilled" do
21
+
22
+ it "fulfilled after a delay" do
23
+ d = deferred
24
+ is_fulfilled = false
25
+ d.promise.then ->(v) {
26
+ assert_equal true, is_fulfilled
27
+ done!
28
+ }
29
+
30
+ Thread.new do
31
+ short_sleep
32
+ # Notice: flipped statements since we don't have delayed execution
33
+ is_fulfilled = true
34
+ d.resolve(dummy)
35
+ end
36
+ end
37
+
38
+ it "never fulfilled" do
39
+ d = deferred
40
+ on_fulfilled_called = false
41
+
42
+ d.promise.then ->(v) {
43
+ on_fulfilled_called = true
44
+ done!
45
+ }
46
+
47
+ done = method(:done!)
48
+ Thread.new do
49
+ 3.times { short_sleep }
50
+ assert_equal false, on_fulfilled_called
51
+ done.call
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "2.2.2.3: it must not be called more than once." do
57
+ it "already-fulfilled" do
58
+ times_called = 0
59
+
60
+ resolved(dummy).then(->(v) {
61
+ (times_called += 1).must_equal 1
62
+ done!
63
+ })
64
+ end
65
+
66
+ it "trying to fulfill a pending promise more than once, immediately" do
67
+ d = deferred
68
+ times_called = 0
69
+
70
+ d.promise.then(->(v) {
71
+ (times_called += 1).must_equal 1
72
+ done!
73
+ })
74
+
75
+ d.resolve(dummy)
76
+ d.resolve(dummy)
77
+ end
78
+
79
+ it "trying to fulfill a pending promise more than once, delayed" do
80
+ d = deferred
81
+ times_called = 0
82
+
83
+ d.promise.then(->(v) {
84
+ assert_equal 1, (times_called += 1)
85
+ done!
86
+ })
87
+
88
+ Thread.new do
89
+ short_sleep
90
+ d.resolve(dummy)
91
+ d.resolve(dummy)
92
+ end
93
+ end
94
+
95
+ it "trying to fulfill a pending promise more than once, immediately then delayed" do
96
+ d = deferred
97
+ times_called = 0
98
+
99
+ d.promise.then(->(v) {
100
+ (times_called += 1).must_equal 1
101
+ done!
102
+ })
103
+
104
+ d.resolve(dummy)
105
+ Thread.new do
106
+ short_sleep
107
+ d.resolve(dummy)
108
+ end
109
+ end
110
+
111
+ it "when multiple `then` calls are made, spaced apart in time" do
112
+ d = deferred
113
+ times_called = [0, 0, 0]
114
+
115
+ d.promise.then(->(v) {
116
+ assert_equal 1, (times_called[0] += 1)
117
+ })
118
+
119
+ Thread.new do
120
+ short_sleep
121
+ d.promise.then(->(v) {
122
+ assert_equal 1, (times_called[1] += 1)
123
+ })
124
+ end
125
+
126
+ Thread.new do
127
+ 2.times { short_sleep }
128
+ d.promise.then(->(v) {
129
+ assert_equal 1, (times_called[2] += 1)
130
+ done!
131
+ })
132
+ end
133
+
134
+ Thread.new do
135
+ 3.times { short_sleep }
136
+ d.resolve(dummy)
137
+ end
138
+ end
139
+
140
+ it "when `then` is interleaved with fulfillment" do
141
+ d = deferred
142
+ times_called = [0, 0]
143
+
144
+ d.promise.then(->(v) {
145
+ (times_called[0] += 1).must_equal 1
146
+ })
147
+
148
+ d.resolve(dummy)
149
+
150
+ d.promise.then(->(v) {
151
+ (times_called[1] += 1).must_equal 1
152
+ done!
153
+ })
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,142 @@
1
+ # encoding: UTF-8
2
+ require_relative "../spec_helper"
3
+ require_relative "../promises_aplus"
4
+
5
+ dummy = { dummy: "dummy" }
6
+ sentinel = { sentinel: "sentinel" }
7
+
8
+ describe "2.2.3: If `onRejected` is a function," do
9
+ include PromisesAplus
10
+
11
+ describe "2.2.3.1: it must be called after `promise` is rejected, with `promise`’s rejection reason as its first argument." do
12
+ PromisesAplus.test_rejected(self, sentinel) do |promise, done|
13
+ promise.then nil, ->(reason) {
14
+ reason.must_equal sentinel
15
+ done.call
16
+ }
17
+ end
18
+ end
19
+
20
+ describe "2.2.3.2: it must not be called before `promise` is rejected" do
21
+
22
+ it "rejected after a delay" do
23
+ d = deferred
24
+ is_rejected = false
25
+ d.promise.then(nil, ->(r) {
26
+ is_rejected.must_equal true
27
+ done!
28
+ })
29
+
30
+ sleep 0.050
31
+ is_rejected = true
32
+ d.reject(dummy)
33
+ end
34
+
35
+ it "never rejected" do
36
+ d = deferred
37
+ on_rejected_called = false
38
+
39
+ d.promise.then(nil, ->(r) {
40
+ on_rejected_called = true
41
+ done!
42
+ })
43
+
44
+ sleep 0.150
45
+ on_rejected_called.must_equal false
46
+ done!
47
+ end
48
+ end
49
+
50
+ describe "2.2.3.3: it must not be called more than once." do
51
+ it "already-rejected" do
52
+ times_called = 0
53
+
54
+ rejected(dummy).then(nil, ->(r) {
55
+ (times_called += 1).must_equal 1
56
+ done!
57
+ })
58
+ end
59
+
60
+ it "trying to reject a pending promise more than once, immediately" do
61
+ d = deferred
62
+ times_called = 0
63
+
64
+ d.promise.then(nil, ->(r) {
65
+ (times_called += 1).must_equal 1
66
+ done!
67
+ })
68
+
69
+ d.reject(dummy)
70
+ d.reject(dummy)
71
+ end
72
+
73
+ it "trying to reject a pending promise more than once, delayed" do
74
+ d = deferred
75
+ times_called = 0
76
+
77
+ d.promise.then(nil, ->(r) {
78
+ (times_called += 1).must_equal 1
79
+ done!
80
+ })
81
+
82
+ sleep 0.050
83
+ d.reject(dummy)
84
+ d.reject(dummy)
85
+ end
86
+
87
+ it "trying to reject a pending promise more than once, immediately then delayed" do
88
+ d = deferred
89
+ times_called = 0
90
+
91
+ d.promise.then(nil, ->(r) {
92
+ (times_called += 1).must_equal 1
93
+ done!
94
+ })
95
+
96
+ d.reject(dummy)
97
+
98
+ sleep 0.050
99
+ d.reject(dummy)
100
+ end
101
+
102
+ it "when multiple `then` calls are made, spaced apart in time" do
103
+ d = deferred
104
+ times_called = [0, 0, 0]
105
+
106
+ d.promise.then(nil, ->(r) {
107
+ (times_called[0] += 1).must_equal 1
108
+ })
109
+
110
+ sleep 0.050
111
+ d.promise.then(nil, ->(r) {
112
+ (times_called[1] += 1).must_equal 1
113
+ })
114
+
115
+ sleep 0.050
116
+ d.promise.then(nil, ->(r) {
117
+ (times_called[2] += 1).must_equal 1
118
+ done!
119
+ })
120
+
121
+ sleep 0.050
122
+ d.reject(dummy)
123
+ end
124
+
125
+ it "when `then` is interleaved with rejection" do
126
+ d = deferred
127
+
128
+ times_called = [0, 0]
129
+
130
+ d.promise.then(nil, ->(r) {
131
+ (times_called[0] += 1).must_equal 1
132
+ })
133
+
134
+ d.reject(dummy)
135
+
136
+ d.promise.then(nil, ->(r) {
137
+ (times_called[1] += 1).must_equal 1
138
+ done!
139
+ })
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,188 @@
1
+ # encoding: UTF-8
2
+ require_relative "../spec_helper"
3
+ require_relative "../promises_aplus"
4
+
5
+ dummy = { dummy: "dummy" }
6
+ sentinel = { sentinel: "sentinel" }
7
+
8
+ describe "2.2.4: `onFulfilled` or `onRejected` must not be called until the execution context stack contains only platform code." do
9
+ include PromisesAplus
10
+
11
+ describe "`then` returns before the promise becomes fulfilled or rejected" do
12
+ before { done! and skip "don't know how to delay execution yet" }
13
+
14
+ PromisesAplus.test_fulfilled(self, sentinel) do |promise, done|
15
+ thenHasReturned = false
16
+
17
+ promise.then ->(v) {
18
+ thenHasReturned.must_equal true
19
+ done.call
20
+ }
21
+
22
+ thenHasReturned = true
23
+ end
24
+
25
+ PromisesAplus.test_rejected(self, dummy) do |promise, done|
26
+ thenHasReturned = false
27
+
28
+ promise.then nil, ->(r) {
29
+ thenHasReturned.must_equal true
30
+ done.call
31
+ }
32
+
33
+ thenHasReturned = true
34
+ end
35
+ end
36
+
37
+ describe "Clean-stack execution ordering tests (fulfillment case)" do
38
+ before { done! and skip "don't know how to delay execution yet" }
39
+
40
+ it "when `onFulfilled` is added immediately before the promise is fulfilled" do
41
+ d = deferred()
42
+ onFulfilledCalled = false
43
+
44
+ d.promise.then ->(v) do
45
+ onFulfilledCalled = true
46
+ end
47
+
48
+ d.resolve(dummy)
49
+
50
+ onFulfilledCalled.must_equal false
51
+ done!
52
+ end
53
+
54
+ it "when `onFulfilled` is added immediately after the promise is fulfilled" do
55
+ d = deferred()
56
+ onFulfilledCalled = false
57
+
58
+ d.resolve(dummy)
59
+
60
+ d.promise.then ->(v) do
61
+ onFulfilledCalled = true
62
+ end
63
+
64
+ onFulfilledCalled.must_equal false
65
+ done!
66
+ end
67
+
68
+ it "when one `onFulfilled` is added inside another `onFulfilled`" do
69
+ promise = resolved()
70
+ firstOnFulfilledFinished = false
71
+
72
+ promise.then ->(v) do
73
+ promise.then ->(v) do
74
+ firstOnFulfilledFinished.must_equal true
75
+ done!
76
+ end
77
+ firstOnFulfilledFinished = true
78
+ end
79
+ end
80
+
81
+ it "when `onFulfilled` is added inside an `onRejected`" do
82
+ promise = rejected()
83
+ promise2 = resolved()
84
+ firstOnRejectedFinished = false
85
+
86
+ promise.then nil, ->(r) do
87
+ promise2.then ->(v) do
88
+ firstOnRejectedFinished.must_equal true
89
+ done!
90
+ end
91
+ firstOnRejectedFinished = true
92
+ end
93
+ end
94
+
95
+ it "when the promise is fulfilled asynchronously" do
96
+ d = deferred()
97
+ firstStackFinished = false
98
+
99
+ f = Fiber.new do
100
+ d.resolve(dummy)
101
+ firstStackFinished = true
102
+ end
103
+
104
+ d.promise.then ->(v) do
105
+ firstStackFinished.must_equal true
106
+ done!
107
+ end
108
+
109
+ f.resume
110
+ end
111
+ end
112
+
113
+ describe "Clean-stack execution ordering tests (rejection case)" do
114
+ before { done! and skip "don't know how to delay execution yet" }
115
+
116
+ it "when `onRejected` is added immediately before the promise is rejected" do
117
+ d = deferred()
118
+ onRejectedCalled = false
119
+
120
+ d.promise.then nil, ->(r) do
121
+ onRejectedCalled = true
122
+ end
123
+
124
+ d.reject(dummy)
125
+
126
+ onRejectedCalled.must_equal false
127
+ done!
128
+ end
129
+
130
+ it "when `onRejected` is added immediately after the promise is rejected" do
131
+ d = deferred()
132
+ onRejectedCalled = false
133
+
134
+ d.reject(dummy)
135
+
136
+ d.promise.then nil, ->(r) do
137
+ onRejectedCalled = true
138
+ end
139
+
140
+ onRejectedCalled.must_equal false
141
+ done!
142
+ end
143
+
144
+ it "when `onRejected` is added inside an `onFulfilled`" do
145
+ promise = resolved()
146
+ promise2 = rejected()
147
+ firstOnFulfilledFinished = false
148
+
149
+ promise.then ->(v) do
150
+ promise2.then nil, ->(r) do
151
+ firstOnFulfilledFinished.must_equal true
152
+ done!
153
+ end
154
+ firstOnFulfilledFinished = true
155
+ end
156
+ end
157
+
158
+ it "when one `onRejected` is added inside another `onRejected`" do
159
+ promise = rejected()
160
+ firstOnRejectedFinished = false
161
+
162
+ promise.then nil, ->(r) do
163
+ promise.then nil, ->(r) do
164
+ firstOnRejectedFinished.must_equal true
165
+ done!
166
+ end
167
+ firstOnRejectedFinished = true
168
+ end
169
+ end
170
+
171
+ it "when the promise is rejected asynchronously" do
172
+ d = deferred()
173
+ firstStackFinished = false
174
+
175
+ f = Fiber.new do
176
+ d.reject(dummy)
177
+ firstStackFinished = true
178
+ end
179
+
180
+ d.promise.then nil, ->(r) do
181
+ firstStackFinished.must_equal true
182
+ done!
183
+ end
184
+
185
+ f.resume
186
+ end
187
+ end
188
+ end