promise.rb 0.6.1 → 0.7.0.rc1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b98cd2e53ffcbfb4c387c41a85c9699b8c050f5e
4
+ data.tar.gz: 22cf6c2bd54e4490470520aca42aa9f15abb24b4
5
+ SHA512:
6
+ metadata.gz: 990eedfbc0cfb55355f2ca0bc963e0cec24d3668b7a22e8e97fb643bb6abd71da10dec39c9e4846f243bc3bad51b5e6a544a270d04a600f7fbca2b3d060e7f96
7
+ data.tar.gz: dffd4ca2bd12d3ee92acb2dc4c719a7aacbe20a4563da016b21ad63d2909c1f22a5c68947b9369f3792b1440edf5e2b37f4b13d8b4e8aa4d14c0d4795ee83e25
data/.travis.yml CHANGED
@@ -1,18 +1,14 @@
1
+ sudo: false
1
2
  language: ruby
2
3
  rvm:
3
- - 1.9.3
4
- - 2.0.0
5
- - 2.1.0
4
+ - 1.9
5
+ - 2.0
6
+ - 2.1
7
+ - 2.2
6
8
  - jruby
7
- - rbx
8
- - ruby-head
9
- - jruby-head
9
+ - rbx-3.14
10
10
  matrix:
11
- allow_failures:
12
- - rvm: 2.1.0 # https://github.com/dkubb/adamantium/issues/30
13
- - rvm: ruby-head
14
- - rvm: jruby-head
15
11
  fast_finish: true
16
- script: bundle exec rake -t metrics:coverage ci
17
12
  before_install:
18
- - gem install bundler -v '= 1.5.1'
13
+ - gem install bundler
14
+ script: bundle exec rake -t
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # promise.rb changelog
2
2
 
3
+ ## 0.7.0.rc1 (February 9, 2016)
4
+
5
+ ### Bug Fixes
6
+
7
+ * Return instances of the custom promise class from its methods (pull #10)
8
+
9
+ ### Features
10
+
11
+ * Add Promise.resolve utility method (pull #8)
12
+ * Add Promise.all utility method (pull #9)
13
+
3
14
  ## 0.6.1 (January 14, 2014)
4
15
 
5
16
  * The rejection reason now defaults to Promise::Error.
data/Gemfile CHANGED
@@ -4,15 +4,18 @@ source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
6
 
7
- gem 'devtools', git: 'https://github.com/rom-rb/devtools.git'
8
- gem 'fuubar', git: 'https://github.com/lgierth/fuubar.git',
9
- ref: 'static-percentage'
7
+ if Gem.ruby_version >= Gem::Version.new('2.1')
8
+ gem 'devtools', '~> 0.1.4'
9
+ end
10
+ gem 'fuubar', '~> 2.0.0'
10
11
  gem 'awesome_print'
11
12
 
13
+ gem 'rake'
14
+ gem 'rspec', '~> 3.4.0'
15
+ gem 'rspec-its'
16
+ gem 'coveralls', '~> 0.8.9'
17
+
12
18
  platform :rbx do
13
19
  gem 'rubysl', '~> 2.0'
14
20
  gem 'rubinius', '~> 2.0'
15
21
  end
16
-
17
- # Added by devtools
18
- eval_gemfile 'Gemfile.devtools'
data/README.md CHANGED
@@ -1,11 +1,12 @@
1
1
  # promise.rb [![Build Status](https://travis-ci.org/lgierth/promise.rb.png?branch=master)](https://travis-ci.org/lgierth/promise.rb) [![Code Climate](https://codeclimate.com/github/lgierth/promise.rb.png)](https://codeclimate.com/github/lgierth/promise.rb) [![Coverage Status](https://coveralls.io/repos/lgierth/promise.rb/badge.png?branch=master)](https://coveralls.io/r/lgierth/promise.rb?branch=master)
2
2
 
3
3
  Ruby implementation of the [Promises/A+ spec](http://promisesaplus.com/).
4
- 100% [mutation coverage](https://github.com/mbj/mutant), tested on 1.9, 2.0, Rubinius, and JRuby.
4
+ 100% [mutation coverage](https://github.com/mbj/mutant),
5
+ tested on MRI 1.9, 2.0, 2.1, 2.2, Rubinius, and JRuby.
5
6
 
6
7
  Similar projects:
7
8
 
8
- - [concurrent-ruby](https://github.com/jdantonio/concurrent-ruby/blob/master/md/promise.md), Promises/A(+) implementation, thread based
9
+ - [concurrent-ruby](https://github.com/jdantonio/concurrent-ruby), Promises/A(+) implementation, thread based
9
10
  - [ruby-thread](https://github.com/meh/ruby-thread), thread/mutex/condition variable based, thread safe
10
11
  - [promise](https://github.com/bhuga/promising-future), a.k.a. promising-future, classic promises and futures, thread based
11
12
  - [celluloid-promise](https://github.com/cotag/celluloid-promise), inspired by Q, backed by a Celluloid actor
@@ -64,8 +65,10 @@ def nonblocking_stuff
64
65
  promise
65
66
  end
66
67
 
67
- nonblocking_stuff.then { |value| p value }
68
- nonblocking_stuff.then(proc { |value| p value })
68
+ EM.run do
69
+ nonblocking_stuff.then { |value| p value }
70
+ nonblocking_stuff.then(proc { |value| p value })
71
+ end
69
72
  ```
70
73
 
71
74
  Rejection works similarly:
@@ -77,7 +80,9 @@ def failing_stuff
77
80
  promise
78
81
  end
79
82
 
80
- failing_stuff.then(proc { |value| }, proc { |reason| p reason })
83
+ EM.run do
84
+ failing_stuff.then(proc { |value| }, proc { |reason| p reason })
85
+ end
81
86
  ```
82
87
 
83
88
  ### Waiting for fulfillment/rejection
@@ -88,6 +93,7 @@ re-raises the reason. Using `#sync` requires you to implement `#wait`. You could
88
93
  for example cooperatively schedule fibers waiting for different promises:
89
94
 
90
95
  ```ruby
96
+ require 'fiber'
91
97
  require 'promise'
92
98
  require 'eventmachine'
93
99
 
@@ -107,25 +113,29 @@ class MyPromise < Promise
107
113
  end
108
114
  end
109
115
 
110
- promise = MyPromise.new
111
- Fiber.new { p promise.sync }.resume
112
- promise.fulfill
116
+ EM.run do
117
+ promise = MyPromise.new
118
+ Fiber.new { p promise.sync }.resume
119
+ promise.fulfill
120
+ end
113
121
  ```
114
122
 
115
123
  Or have the rejection reason re-raised from `#sync`:
116
124
 
117
125
  ```ruby
118
- promise = MyPromise.new
126
+ EM.run do
127
+ promise = MyPromise.new
119
128
 
120
- Fiber.new do
121
- begin
122
- promise.sync
123
- rescue MyError
124
- p $!
125
- end
126
- end.resume
129
+ Fiber.new do
130
+ begin
131
+ promise.sync
132
+ rescue
133
+ p $!
134
+ end
135
+ end.resume
127
136
 
128
- promise.reject(MyError.new)
137
+ promise.reject('reason')
138
+ end
129
139
  ```
130
140
 
131
141
  ### Chaining promises
data/Rakefile CHANGED
@@ -1,7 +1,21 @@
1
1
  # encoding: utf-8
2
2
 
3
- task :default => 'ci:metrics'
3
+ if Gem.ruby_version >= Gem::Version.new('2.1')
4
+ require 'devtools'
5
+ Devtools.init_rake_tasks
4
6
 
5
- # Added by devtools
6
- require 'devtools'
7
- Devtools.init_rake_tasks
7
+ tasks = %w[
8
+ metrics:coverage
9
+ metrics:yardstick:verify
10
+ metrics:rubocop
11
+ metrics:flog
12
+ metrics:reek
13
+ spec:integration
14
+ ]
15
+ tasks << 'metrics:mutant' if RUBY_ENGINE == 'ruby'
16
+ task :default => tasks
17
+ else
18
+ require 'rspec/core/rake_task'
19
+ RSpec::Core::RakeTask.new(:spec)
20
+ task :default => :spec
21
+ end
data/config/devtools.yml CHANGED
@@ -1,2 +1,2 @@
1
1
  ---
2
- unit_test_timeout: 0.1
2
+ unit_test_timeout: 5.0
data/config/flay.yml CHANGED
@@ -1,3 +1,3 @@
1
1
  ---
2
- threshold: 10
3
- total_score: 44
2
+ threshold: 9
3
+ total_score: 43
data/config/reek.yml CHANGED
@@ -12,6 +12,7 @@ ControlParameter:
12
12
  enabled: true
13
13
  exclude:
14
14
  - "Promise#reject"
15
+ - "Promise#dispatch"
15
16
  DataClump:
16
17
  enabled: true
17
18
  exclude: []
@@ -63,8 +64,9 @@ TooManyMethods:
63
64
  TooManyStatements:
64
65
  enabled: true
65
66
  exclude:
67
+ - initialize
66
68
  - each
67
- max_statements: 4
69
+ max_statements: 5
68
70
  UncommunicativeMethodName:
69
71
  enabled: true
70
72
  exclude: []
data/config/rubocop.yml CHANGED
@@ -1,17 +1,20 @@
1
1
  AllCops:
2
- Includes:
2
+ Include:
3
3
  - '**/*.rake'
4
4
  - 'Gemfile'
5
5
  - 'Gemfile.devtools'
6
- Excludes:
6
+ Exclude:
7
7
  - '**/vendor/**'
8
8
  - '**/benchmarks/**'
9
9
 
10
10
  # Avoid parameter lists longer than five parameters.
11
11
  ParameterLists:
12
- Max: 3
12
+ Max: 4
13
13
  CountKeywordArgs: true
14
- Enabled: false
14
+
15
+ MethodLength:
16
+ CountComments: false
17
+ Max: 10
15
18
 
16
19
  # Avoid more than `Max` levels of nesting.
17
20
  BlockNesting:
@@ -25,6 +28,15 @@ CollectionMethods:
25
28
  find: 'detect'
26
29
  find_all: 'select'
27
30
 
31
+ # Do not force public/protected/private keyword to be indented at the same
32
+ # level as the def keyword. My personal preference is to outdent these keywords
33
+ # because I think when scanning code it makes it easier to identify the
34
+ # sections of code and visually separate them. When the keyword is at the same
35
+ # level I think it sort of blends in with the def keywords and makes it harder
36
+ # to scan the code and see where the sections are.
37
+ AccessModifierIndentation:
38
+ Enabled: false
39
+
28
40
  # Limit line length
29
41
  LineLength:
30
42
  Max: 79
@@ -52,3 +64,35 @@ TrivialAccessors:
52
64
  SignalException:
53
65
  # Valid values are: semantic, only_raise and only_fail
54
66
  EnforcedStyle: only_raise
67
+
68
+ # Do not prefer do/end over {} for multiline blocks
69
+ BlockDelimiters:
70
+ Enabled: false
71
+
72
+ # Allow empty lines around body
73
+ EmptyLinesAroundBlockBody:
74
+ Enabled: false
75
+
76
+ # Prefer String#% over Kernel#sprintf
77
+ FormatString:
78
+ Enabled: false
79
+
80
+ # Use square brackets for literal Array objects
81
+ PercentLiteralDelimiters:
82
+ PreferredDelimiters:
83
+ '%': ()
84
+ '%i': '[]'
85
+ '%q': ()
86
+ '%Q': ()
87
+ '%r': '{}'
88
+ '%s': ()
89
+ '%w': '[]'
90
+ '%W': '[]'
91
+ '%x': ()
92
+
93
+ # buggy in rubocop-0.21.0, fixed in 0.23.0
94
+ LineEndConcatenation:
95
+ Enabled: false
96
+
97
+ GuardClause:
98
+ Enabled: false
data/lib/promise.rb CHANGED
@@ -4,6 +4,7 @@ require 'promise/version'
4
4
 
5
5
  require 'promise/callback'
6
6
  require 'promise/progress'
7
+ require 'promise/group'
7
8
 
8
9
  class Promise
9
10
  Error = Class.new(RuntimeError)
@@ -12,26 +13,35 @@ class Promise
12
13
 
13
14
  attr_reader :state, :value, :reason, :backtrace
14
15
 
16
+ def self.resolve(obj)
17
+ return obj if obj.instance_of?(self)
18
+ new.tap { |promise| promise.fulfill(obj) }
19
+ end
20
+
21
+ def self.all(enumerable)
22
+ Group.new(new, enumerable).promise
23
+ end
24
+
15
25
  def initialize
16
26
  @state = :pending
17
27
  @callbacks = []
18
28
  end
19
29
 
20
30
  def pending?
21
- @state == :pending
31
+ state.equal?(:pending)
22
32
  end
23
33
 
24
34
  def fulfilled?
25
- @state == :fulfilled
35
+ state.equal?(:fulfilled)
26
36
  end
27
37
 
28
38
  def rejected?
29
- @state == :rejected
39
+ state.equal?(:rejected)
30
40
  end
31
41
 
32
42
  def then(on_fulfill = nil, on_reject = nil, &block)
33
43
  on_fulfill ||= block
34
- next_promise = Promise.new
44
+ next_promise = self.class.new
35
45
 
36
46
  add_callback { Callback.new(self, on_fulfill, on_reject, next_promise) }
37
47
  next_promise
@@ -4,7 +4,8 @@ class Promise
4
4
  class Callback
5
5
  def initialize(promise, on_fulfill, on_reject, next_promise)
6
6
  @promise = promise
7
- @on_fulfill, @on_reject = on_fulfill, on_reject
7
+ @on_fulfill = on_fulfill
8
+ @on_reject = on_reject
8
9
  @next_promise = next_promise
9
10
  end
10
11
 
@@ -0,0 +1,51 @@
1
+ class Promise
2
+ class Group
3
+ attr_reader :promise
4
+
5
+ def initialize(result_promise, inputs)
6
+ @promise = result_promise
7
+ @inputs = inputs
8
+ @remaining = count_promises
9
+ if @remaining.zero?
10
+ promise.fulfill(inputs)
11
+ else
12
+ chain_inputs
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def chain_inputs
19
+ on_fulfill = method(:on_fulfill)
20
+ on_reject = promise.method(:reject)
21
+ each_promise do |input_promise|
22
+ input_promise.then(on_fulfill, on_reject)
23
+ end
24
+ end
25
+
26
+ def on_fulfill(_result)
27
+ @remaining -= 1
28
+ if @remaining.zero?
29
+ result = @inputs.map { |obj| promise?(obj) ? obj.value : obj }
30
+ promise.fulfill(result)
31
+ end
32
+ end
33
+
34
+ def promise?(obj)
35
+ obj.instance_of?(Promise)
36
+ end
37
+
38
+ def count_promises
39
+ count = 0
40
+ each_promise { count += 1 }
41
+ count
42
+ end
43
+
44
+ def each_promise
45
+ @inputs.each do |obj|
46
+ yield obj if promise?(obj)
47
+ end
48
+ end
49
+ end
50
+ private_constant :Group
51
+ end
@@ -3,9 +3,9 @@
3
3
  class Promise
4
4
  module Progress
5
5
  def on_progress(&block)
6
- @on_progress ||= []
7
- @on_progress << block if block_given?
8
- @on_progress
6
+ (@on_progress ||= []).tap do |callbacks|
7
+ callbacks << block if block_given?
8
+ end
9
9
  end
10
10
 
11
11
  def progress(status)
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  class Promise
4
- VERSION = '0.6.1'
4
+ VERSION = '0.7.0.rc1'
5
5
  end
data/spec/spec_helper.rb CHANGED
@@ -18,6 +18,8 @@ if ENV['COVERAGE'] == 'true'
18
18
  end
19
19
 
20
20
  require 'promise'
21
+ require_relative 'support/delayed_promise'
21
22
 
22
23
  require 'awesome_print'
23
- require 'devtools/spec_helper'
24
+ require 'devtools/spec_helper' if Gem.ruby_version >= Gem::Version.new('2.1')
25
+ require 'rspec/its'
@@ -0,0 +1,22 @@
1
+ class DelayedPromise < Promise
2
+ BrokenPromise = Class.new(StandardError)
3
+
4
+ class << self
5
+ def deferred
6
+ @deferred ||= []
7
+ end
8
+
9
+ def call_deferred
10
+ deferred.shift.call until deferred.empty?
11
+ end
12
+ end
13
+
14
+ def wait
15
+ DelayedPromise.call_deferred
16
+ raise BrokenPromise if pending?
17
+ end
18
+
19
+ def defer(&block)
20
+ DelayedPromise.deferred << block
21
+ end
22
+ end
@@ -44,7 +44,7 @@ describe Promise do
44
44
  end
45
45
 
46
46
  it 'freezes the value' do
47
- pending 'Dropped in 74da6e9'
47
+ skip 'Dropped in 74da6e9'
48
48
  end
49
49
  end
50
50
 
@@ -64,7 +64,7 @@ describe Promise do
64
64
  end
65
65
 
66
66
  it 'freezes the reason' do
67
- pending 'Dropped in 74da6e9'
67
+ skip 'Dropped in 74da6e9'
68
68
  end
69
69
  end
70
70
 
@@ -170,7 +170,16 @@ describe Promise do
170
170
 
171
171
  describe '3.2.4' do
172
172
  it 'returns before on_fulfill or on_reject is called' do
173
- pending 'To be implemented by application code'
173
+ called = false
174
+ p1 = DelayedPromise.new
175
+ p2 = p1.then { called = true }
176
+
177
+ p1.fulfill(42)
178
+
179
+ expect(called).to eq(false)
180
+ DelayedPromise.call_deferred
181
+ expect(called).to eq(true)
182
+ expect(p2).to be_fulfilled
174
183
  end
175
184
  end
176
185
 
@@ -328,83 +337,161 @@ describe Promise do
328
337
  end
329
338
  end
330
339
 
331
- describe '#progress' do
332
- let(:status) { double('status') }
340
+ describe 'extras' do
341
+ describe '#progress' do
342
+ let(:status) { double('status') }
333
343
 
334
- it 'calls the callbacks in the order of calls to #on_progress' do
335
- order = []
336
- block = proc do |i, stat|
337
- order << i
338
- expect(stat).to eq(status)
344
+ it 'calls the callbacks in the order of calls to #on_progress' do
345
+ order = []
346
+ block = proc do |i, stat|
347
+ order << i
348
+ expect(stat).to eq(status)
349
+ end
350
+
351
+ subject.on_progress(&block.curry[1])
352
+ subject.on_progress(&block.curry[2])
353
+ subject.on_progress(&block.curry[3])
354
+ subject.progress(status)
355
+
356
+ expect(order).to eq([1, 2, 3])
339
357
  end
340
358
 
341
- subject.on_progress(&block.curry[1])
342
- subject.on_progress(&block.curry[2])
343
- subject.on_progress(&block.curry[3])
344
- subject.progress(status)
359
+ it 'does not call back unless pending' do
360
+ called = false
361
+ subject.on_progress { |_| called = true }
362
+ subject.fulfill(value)
345
363
 
346
- expect(order).to eq([1, 2, 3])
364
+ subject.progress(status)
365
+ expect(called).to eq(false)
366
+ end
347
367
  end
348
368
 
349
- it 'does not call back unless pending' do
350
- called = false
351
- subject.on_progress { |_| called = true }
352
- subject.fulfill(value)
369
+ describe '#fulfill' do
370
+ it 'does not return anything' do
371
+ expect(subject.fulfill(nil)).to eq(nil)
372
+ end
353
373
 
354
- subject.progress(status)
355
- expect(called).to eq(false)
356
- end
357
- end
374
+ it 'does not require a value' do
375
+ subject.fulfill
376
+ expect(subject.value).to be(nil)
377
+ end
358
378
 
359
- describe '#fulfill' do
360
- it 'does not return anything' do
361
- expect(subject.fulfill(nil)).to eq(nil)
379
+ it 'sets the backtrace' do
380
+ subject.fulfill
381
+ expect(subject.backtrace.join)
382
+ .to include(__FILE__ + ':' + (__LINE__ - 2).to_s)
383
+ end
362
384
  end
363
385
 
364
- it 'does not require a value' do
365
- subject.fulfill
366
- expect(subject.value).to be(nil)
367
- end
386
+ describe '#reject' do
387
+ it 'does not return anything' do
388
+ expect(subject.reject(nil)).to eq(nil)
389
+ end
368
390
 
369
- it 'sets the backtrace' do
370
- subject.fulfill
371
- expect(subject.backtrace.join)
372
- .to include(__FILE__ + ':' + (__LINE__ - 2).to_s)
373
- end
374
- end
391
+ it 'does not require a reason' do
392
+ subject.reject
393
+ expect(subject.reason).to be(Promise::Error)
394
+ end
375
395
 
376
- describe '#reject' do
377
- it 'does not return anything' do
378
- expect(subject.reject(nil)).to eq(nil)
396
+ it 'sets the backtrace' do
397
+ subject.reject
398
+ expect(subject.backtrace.join)
399
+ .to include(__FILE__ + ':' + (__LINE__ - 2).to_s)
400
+ end
379
401
  end
380
402
 
381
- it 'does not require a reason' do
382
- subject.reject
383
- expect(subject.reason).to be(Promise::Error)
384
- end
403
+ describe '#sync' do
404
+ it 'waits for fulfillment' do
405
+ allow(subject).to receive(:wait) { subject.fulfill(value) }
406
+ expect(subject.sync).to be(value)
407
+ end
385
408
 
386
- it 'sets the backtrace' do
387
- subject.reject
388
- expect(subject.backtrace.join)
389
- .to include(__FILE__ + ':' + (__LINE__ - 2).to_s)
390
- end
391
- end
409
+ it 'waits for rejection' do
410
+ allow(subject).to receive(:wait) { subject.reject(reason) }
411
+ expect { subject.sync }.to raise_error(reason)
412
+ end
392
413
 
393
- describe '#sync' do
394
- it 'waits for fulfillment' do
395
- allow(subject).to receive(:wait) { subject.fulfill(value) }
396
- expect(subject.sync).to be(value)
414
+ it 'waits if pending' do
415
+ subject.fulfill(value)
416
+ expect(subject).not_to receive(:wait)
417
+ expect(subject.sync).to be(value)
418
+ end
397
419
  end
398
420
 
399
- it 'waits for rejection' do
400
- allow(subject).to receive(:wait) { subject.reject(reason) }
401
- expect { subject.sync }.to raise_error(reason)
421
+ describe '.resolve' do
422
+ it 'returns a fulfilled promise from a non-promise' do
423
+ promise = Promise.resolve(123)
424
+ expect(promise.fulfilled?).to eq(true)
425
+ expect(promise.value).to eq(123)
426
+ end
427
+
428
+ it 'assumes the state of a given promise' do
429
+ promise = Promise.new
430
+ new_promise = Promise.resolve(promise)
431
+ expect(new_promise.pending?).to eq(true)
432
+ promise.fulfill(42)
433
+ expect(new_promise.fulfilled?).to eq(true)
434
+ expect(new_promise.value).to eq(42)
435
+ end
402
436
  end
403
437
 
404
- it 'waits if pending' do
405
- subject.fulfill(value)
406
- expect(subject).not_to receive(:wait)
407
- expect(subject.sync).to be(value)
438
+ describe '.all' do
439
+ it 'returns a fulfilled promise for an array with no promises' do
440
+ obj = Object.new
441
+ promise = Promise.all([1, 'b', obj])
442
+ expect(promise.fulfilled?).to eq(true)
443
+ expect(promise.value).to eq([1, 'b', obj])
444
+ end
445
+
446
+ it 'fulfills the result when all args are fulfilled' do
447
+ p1 = Promise.new
448
+ p2 = Promise.new
449
+
450
+ result = Promise.all([p1, p2, 3])
451
+
452
+ expect(result).to be_pending
453
+ p2.fulfill('b')
454
+ expect(result).to be_pending
455
+ p1.fulfill(:a)
456
+ expect(result).to be_fulfilled
457
+ expect(result.value).to eq([:a, 'b', 3])
458
+ end
459
+
460
+ it 'leaves result pending if only the first input arg is fulfilled' do
461
+ p1 = Promise.new
462
+ p1.fulfill('a')
463
+ p2 = Promise.new
464
+
465
+ result = Promise.all([p1, p2])
466
+
467
+ expect(result).to be_pending
468
+ p2.fulfill(:b)
469
+ expect(result).to be_fulfilled
470
+ expect(result.value).to eq(['a', :b])
471
+ end
472
+
473
+ it 'rejects the result when any args is rejected' do
474
+ p1 = Promise.new
475
+ p2 = Promise.new
476
+ reason = RuntimeError.new('p1 failed')
477
+
478
+ result = Promise.all([p1, p2])
479
+
480
+ expect(result).to be_pending
481
+ p1.reject(reason)
482
+ expect(result).to be_rejected
483
+ expect(result.reason).to eq(reason)
484
+ end
485
+
486
+ it 'returns an instance of the class it is called on' do
487
+ p1 = Promise.new
488
+
489
+ result = DelayedPromise.all([p1, 2])
490
+
491
+ expect(result).to be_an_instance_of(DelayedPromise)
492
+ p1.fulfill(1.0)
493
+ expect(result.sync).to eq([1.0, 2])
494
+ end
408
495
  end
409
496
  end
410
497
  end
metadata CHANGED
@@ -1,30 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: promise.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
5
- prerelease:
4
+ version: 0.7.0.rc1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Lars Gierth
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-01-14 00:00:00.000000000 Z
11
+ date: 2016-02-09 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rspec
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  description: Promises/A+ for Ruby
@@ -34,12 +31,11 @@ executables: []
34
31
  extensions: []
35
32
  extra_rdoc_files: []
36
33
  files:
37
- - .gitignore
38
- - .rspec
39
- - .travis.yml
34
+ - ".gitignore"
35
+ - ".rspec"
36
+ - ".travis.yml"
40
37
  - CHANGELOG.md
41
38
  - Gemfile
42
- - Gemfile.devtools
43
39
  - README.md
44
40
  - Rakefile
45
41
  - UNLICENSE
@@ -52,37 +48,39 @@ files:
52
48
  - config/yardstick.yml
53
49
  - lib/promise.rb
54
50
  - lib/promise/callback.rb
51
+ - lib/promise/group.rb
55
52
  - lib/promise/progress.rb
56
53
  - lib/promise/version.rb
57
54
  - promise.rb.gemspec
58
- - spec/promise_spec.rb
59
55
  - spec/spec_helper.rb
56
+ - spec/support/delayed_promise.rb
57
+ - spec/unit/promise_spec.rb
60
58
  homepage: https://github.com/lgierth/promise
61
59
  licenses:
62
60
  - Public Domain
61
+ metadata: {}
63
62
  post_install_message:
64
63
  rdoc_options: []
65
64
  require_paths:
66
65
  - lib
67
66
  required_ruby_version: !ruby/object:Gem::Requirement
68
- none: false
69
67
  requirements:
70
- - - ! '>='
68
+ - - ">="
71
69
  - !ruby/object:Gem::Version
72
70
  version: '0'
73
71
  required_rubygems_version: !ruby/object:Gem::Requirement
74
- none: false
75
72
  requirements:
76
- - - ! '>='
73
+ - - ">"
77
74
  - !ruby/object:Gem::Version
78
- version: '0'
75
+ version: 1.3.1
79
76
  requirements: []
80
77
  rubyforge_project:
81
- rubygems_version: 1.8.23
78
+ rubygems_version: 2.2.5
82
79
  signing_key:
83
- specification_version: 3
80
+ specification_version: 4
84
81
  summary: Ruby implementation of the Promises/A+ spec
85
82
  test_files:
86
- - spec/promise_spec.rb
87
83
  - spec/spec_helper.rb
84
+ - spec/support/delayed_promise.rb
85
+ - spec/unit/promise_spec.rb
88
86
  has_rdoc:
data/Gemfile.devtools DELETED
@@ -1,69 +0,0 @@
1
- # encoding: utf-8
2
-
3
- group :development do
4
- gem 'rake', '~> 10.1.0'
5
- gem 'rspec', '~> 2.14.1'
6
- gem 'yard', '~> 0.8.7'
7
-
8
- platform :rbx do
9
- gem 'rubysl-singleton', '~> 2.0.0'
10
- end
11
- end
12
-
13
- group :yard do
14
- gem 'kramdown', '~> 1.3.0'
15
- end
16
-
17
- group :guard do
18
- gem 'guard', '~> 2.2.4'
19
- gem 'guard-bundler', '~> 2.0.0'
20
- gem 'guard-rspec', '~> 4.2.0'
21
- gem 'guard-rubocop', '~> 1.0.0'
22
-
23
- # file system change event handling
24
- gem 'listen', '~> 2.4.0'
25
- gem 'rb-fchange', '~> 0.0.6', require: false
26
- gem 'rb-fsevent', '~> 0.9.3', require: false
27
- gem 'rb-inotify', '~> 0.9.0', require: false
28
-
29
- # notification handling
30
- gem 'libnotify', '~> 0.8.0', require: false
31
- gem 'rb-notifu', '~> 0.0.4', require: false
32
- gem 'terminal-notifier-guard', '~> 1.5.3', require: false
33
- end
34
-
35
- group :metrics do
36
- gem 'coveralls', '~> 0.7.0'
37
- gem 'flay', '~> 2.4.0'
38
- gem 'flog', '~> 4.2.0'
39
- gem 'reek', '~> 1.3.2'
40
- gem 'rubocop', '~> 0.16.0'
41
- gem 'simplecov', '~> 0.8.2'
42
- gem 'yardstick', '~> 0.9.7', git: 'https://github.com/dkubb/yardstick.git'
43
-
44
- platforms :mri do
45
- gem 'mutant', '~> 0.3.4'
46
- end
47
-
48
- platforms :ruby_19, :ruby_20 do
49
- gem 'yard-spellcheck', '~> 0.1.5'
50
- end
51
-
52
- platform :rbx do
53
- gem 'json', '~> 1.8.1'
54
- gem 'racc', '~> 1.4.10'
55
- gem 'rubysl-logger', '~> 2.0.0'
56
- gem 'rubysl-open-uri', '~> 2.0.0'
57
- gem 'rubysl-prettyprint', '~> 2.0.2'
58
- end
59
- end
60
-
61
- group :benchmarks do
62
- gem 'rbench', '~> 0.2.3'
63
- end
64
-
65
- platform :jruby do
66
- group :jruby do
67
- gem 'jruby-openssl', '~> 0.8.5'
68
- end
69
- end