reacto 0.0.0 → 0.0.1
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 +4 -4
- data/.gitignore +1 -0
- data/lib/reacto/operations/flat_map.rb +7 -1
- data/lib/reacto/operations/flat_map_latest.rb +37 -0
- data/lib/reacto/operations.rb +1 -0
- data/lib/reacto/subscriptions/composite_subscription.rb +4 -0
- data/lib/reacto/subscriptions/subscription_wrapper.rb +2 -0
- data/lib/reacto/trackable.rb +4 -0
- data/lib/reacto/version.rb +1 -1
- data/spec/reacto/create_trackable_spec.rb +0 -9
- data/spec/reacto/trackable/class_level/never_spec.rb +11 -0
- data/spec/reacto/trackable/concat_spec.rb +34 -0
- data/spec/reacto/trackable/diff_spec.rb +42 -0
- data/spec/reacto/trackable/drop_errors_spec.rb +15 -0
- data/spec/reacto/trackable/flat_map_latest_spec.rb +18 -0
- data/spec/reacto/trackable/flat_map_spec.rb +18 -0
- data/spec/reacto/trackable/flatten_spec.rb +15 -0
- data/spec/reacto/trackable/inject_spec.rb +59 -0
- data/spec/reacto/trackable/merge_spec.rb +40 -0
- data/spec/reacto/trackable/positional_filtering_spec.rb +96 -0
- data/spec/reacto/trackable/throttle_spec.rb +0 -1
- data/spec/reacto/trackable/uniq_spec.rb +15 -0
- data/spec/reacto/trackable_spec.rb +0 -366
- data/spec/support/helpers.rb +9 -0
- metadata +26 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c3be32892f6d090d99fad277060c0a6594eff2f
|
4
|
+
data.tar.gz: 8cf5362fb0e3a1de7d6a7ab8c30fa6afd78cba97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60e81798750a652579e0834810f80352c0c6fb3418c35f062ee82efd26f2ec44f9211e149324ec5da9b6e4547aaca700bac123aef4333725ee2a19eb3c63812e
|
7
|
+
data.tar.gz: bc7528738e9e26c73eb513075c6ebea36870eb9c0d396672391130abfdf1862ed0a44dd1b7db751e1fcf9617ad6d432a5c558fe825e996c36535cdd207ea386a
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
@@ -16,8 +16,14 @@ module Reacto
|
|
16
16
|
trackable.do_track subscription.subscription!
|
17
17
|
end
|
18
18
|
|
19
|
+
close = lambda do
|
20
|
+
return unless subscription.closed?
|
21
|
+
|
22
|
+
tracker.on_close
|
23
|
+
end
|
24
|
+
|
19
25
|
Subscriptions::OperationSubscription.new(
|
20
|
-
tracker, value: value
|
26
|
+
tracker, value: value, close: close
|
21
27
|
)
|
22
28
|
end
|
23
29
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class FlatMapLatest
|
6
|
+
def initialize(transform)
|
7
|
+
@transform = transform
|
8
|
+
@last_active = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(tracker)
|
12
|
+
subscription = Subscriptions::FlatMapSubscription.new(tracker)
|
13
|
+
value = lambda do |v|
|
14
|
+
trackable = @transform.call(v)
|
15
|
+
|
16
|
+
sub = subscription.subscription!
|
17
|
+
|
18
|
+
@last_active.unsubscribe if @last_active
|
19
|
+
trackable.do_track sub
|
20
|
+
@last_active = sub
|
21
|
+
end
|
22
|
+
|
23
|
+
close = lambda do
|
24
|
+
return unless subscription.closed?
|
25
|
+
|
26
|
+
tracker.on_close
|
27
|
+
end
|
28
|
+
|
29
|
+
Subscriptions::OperationSubscription.new(
|
30
|
+
tracker, value: value, close: close
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
data/lib/reacto/operations.rb
CHANGED
data/lib/reacto/trackable.rb
CHANGED
@@ -204,6 +204,10 @@ module Reacto
|
|
204
204
|
lift(Operations::FlatMap.new(block_given? ? block : transform))
|
205
205
|
end
|
206
206
|
|
207
|
+
def flat_map_latest(transform = nil, &block)
|
208
|
+
lift(Operations::FlatMapLatest.new(block_given? ? block : transform))
|
209
|
+
end
|
210
|
+
|
207
211
|
def map(mapping = nil, error: nil, close: nil, &block)
|
208
212
|
lift(Operations::Map.new(
|
209
213
|
block_given? ? block : mapping, error: error, close: close
|
data/lib/reacto/version.rb
CHANGED
@@ -1,15 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
context Reacto::Trackable do
|
4
|
-
|
5
|
-
context '.never' do
|
6
|
-
it 'creates a new trackable, which won\'t send any notifications' do
|
7
|
-
attach_test_trackers described_class.never
|
8
|
-
|
9
|
-
expect(test_data).to be_empty
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
4
|
context '.error' do
|
14
5
|
it 'creates a new trackable emitting only the error passed' do
|
15
6
|
err = StandardError.new('Errrr')
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context '#concat' do
|
5
|
+
it 'starts emitting the values from the concatenated after emitting the ' \
|
6
|
+
'values from the source, then emits a `close` notification' do
|
7
|
+
trackable = source.concat(described_class.enumerable((6..10)))
|
8
|
+
trackable.on(value: test_on_value, close: test_on_close)
|
9
|
+
|
10
|
+
expect(test_data).to be == (5..10).to_a + ['|']
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'can be chained' do
|
14
|
+
trackable = source
|
15
|
+
.concat(described_class.enumerable((6..8)))
|
16
|
+
.concat(described_class.enumerable((9..10)))
|
17
|
+
trackable.on(value: test_on_value, close: test_on_close)
|
18
|
+
|
19
|
+
expect(test_data).to be == (5..10).to_a + ['|']
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'closes on error' do
|
23
|
+
err = StandardError.new('Hey')
|
24
|
+
trackable = source
|
25
|
+
.concat(described_class.error(err))
|
26
|
+
.concat(described_class.enumerable((9..10)))
|
27
|
+
trackable.on(
|
28
|
+
value: test_on_value, close: test_on_close, error: test_on_error
|
29
|
+
)
|
30
|
+
|
31
|
+
expect(test_data).to be == [5, err]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context '#diff' do
|
5
|
+
it 'by default emits arrays with two values the - previous and current ' \
|
6
|
+
'element' do
|
7
|
+
source = described_class.enumerable((1..10))
|
8
|
+
trackable = source.diff
|
9
|
+
trackable.on(value: test_on_value, error: test_on_error)
|
10
|
+
|
11
|
+
expect(test_data).to be == [
|
12
|
+
[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9], [9, 10
|
13
|
+
]]
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'can be passed a diff function to calculate the difference between ' \
|
17
|
+
'the previously emitted value and the current and to emit it' do
|
18
|
+
source = described_class.enumerable((1..10))
|
19
|
+
trackable = source.diff(Reacto::NO_VALUE, -> (p, c) { c - p })
|
20
|
+
trackable.on(value: test_on_value, error: test_on_error)
|
21
|
+
|
22
|
+
expect(test_data).to be == [1] * 9
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'can be passed a diff block to calculate the difference between ' \
|
26
|
+
'the previously emitted value and the current and to emit it' do
|
27
|
+
source = described_class.enumerable((1..10))
|
28
|
+
trackable = source.diff { |p, c| c - p }
|
29
|
+
trackable.on(value: test_on_value, error: test_on_error)
|
30
|
+
|
31
|
+
expect(test_data).to be == [1] * 9
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'can receive initial value to be used as seed - the first value' do
|
35
|
+
source = described_class.enumerable((1..10))
|
36
|
+
trackable = source.diff(-5) { |p, c| c - p }
|
37
|
+
trackable.on(value: test_on_value, error: test_on_error)
|
38
|
+
|
39
|
+
expect(test_data).to be == [6] + ([1] * 9)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context '#drop_errors' do
|
5
|
+
it 'drops all the errors from the source and continues' do
|
6
|
+
described_class.enumerable((1..5)).concat(
|
7
|
+
described_class.error(StandardError.new)
|
8
|
+
).concat(described_class.enumerable(6..10)).drop_errors.on(
|
9
|
+
value: test_on_value, error: test_on_error, close: test_on_close
|
10
|
+
)
|
11
|
+
|
12
|
+
expect(test_data).to be == (1..10).to_a + ['|']
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context 'flat_map_latest' do
|
5
|
+
it 'TODO' do
|
6
|
+
trackable = described_class.interval(1).take(3).flat_map_latest do |val|
|
7
|
+
Reacto::Trackable.interval(0.3, (val..7).to_enum)
|
8
|
+
end
|
9
|
+
|
10
|
+
subscription = trackable.on(
|
11
|
+
value: test_on_value, close: test_on_close, error: test_on_error
|
12
|
+
)
|
13
|
+
|
14
|
+
trackable.await(subscription)
|
15
|
+
expect(test_data).to be == [0, 1, 2, 1, 2, 3, 2, 3, 4, 5, 6, 7, '|']
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context 'flat_map' do
|
5
|
+
it 'flattens the notification of the Trackable objects produced by ' \
|
6
|
+
'the passed transformation function and turns them to one stream of ' \
|
7
|
+
'notifications' do
|
8
|
+
trackable = described_class.enumerable((1..5)).flat_map do |val|
|
9
|
+
Reacto::Trackable.enumerable([val, val + 1])
|
10
|
+
end
|
11
|
+
|
12
|
+
trackable.on(
|
13
|
+
value: test_on_value, close: test_on_close, error: test_on_error
|
14
|
+
)
|
15
|
+
expect(test_data).to be == [1, 2, 2, 3, 3, 4, 4, 5, 5, 6, '|']
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context 'flatten' do
|
5
|
+
it 'sends the members of array values as values' do
|
6
|
+
trackable =
|
7
|
+
described_class.enumerable([[1, 2, 3], [4, 3], [2, 1, 5]]).flatten
|
8
|
+
|
9
|
+
trackable.on(
|
10
|
+
value: test_on_value, close: test_on_close, error: test_on_error
|
11
|
+
)
|
12
|
+
expect(test_data).to be == [1, 2, 3, 4, 3, 2, 1, 5, '|']
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context '#inject' do
|
5
|
+
let(:test_behaviour) do
|
6
|
+
lambda do |tracker_subscription|
|
7
|
+
[16, 7, 2014].each do |value|
|
8
|
+
tracker_subscription.on_value(value)
|
9
|
+
end
|
10
|
+
|
11
|
+
tracker_subscription.on_close
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'sends the values created by applying the `inject` operation on the ' \
|
16
|
+
'last value and current value, using for first value the initial one' do
|
17
|
+
trackable = source.inject(0) do |prev, v|
|
18
|
+
prev + v
|
19
|
+
end
|
20
|
+
trackable.on(value: test_on_value)
|
21
|
+
|
22
|
+
expect(test_data.size).to be(3)
|
23
|
+
expect(test_data).to be == [16, 23, 2037]
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'sends the values created by applying the `inject` operation on the ' \
|
27
|
+
'last value and current value, using for first value ' \
|
28
|
+
'the first emitted by the source if no initial value provided' do
|
29
|
+
trackable = source.inject do |prev, v|
|
30
|
+
prev + v
|
31
|
+
end
|
32
|
+
trackable.on(value: test_on_value)
|
33
|
+
|
34
|
+
expect(test_data.size).to be(3)
|
35
|
+
expect(test_data).to be == [16, 23, 2037]
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'sends the initial value if no value is emitted' do
|
39
|
+
source = described_class.new(-> (t) { t.on_close })
|
40
|
+
trackable = source.inject(0) do |prev, v|
|
41
|
+
prev + v
|
42
|
+
end
|
43
|
+
trackable.on(value: test_on_value)
|
44
|
+
|
45
|
+
expect(test_data.size).to be(1)
|
46
|
+
expect(test_data).to be == [0]
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'sends nothing if no initial value and no value emitted' do
|
50
|
+
source = described_class.new(-> (t) { t.on_close })
|
51
|
+
trackable = source.inject do |prev, v|
|
52
|
+
prev + v
|
53
|
+
end
|
54
|
+
trackable.on(value: test_on_value)
|
55
|
+
|
56
|
+
expect(test_data.size).to be(0)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context '#merge' do
|
5
|
+
it 'merges the passed trackable\'s emitions with the source ones' do
|
6
|
+
trackable =
|
7
|
+
described_class.interval(0.2).map { |v| v.to_s + 'a'}.take(5)
|
8
|
+
to_be_merged =
|
9
|
+
described_class.interval(0.35).map { |v| v.to_s + 'b'}.take(4)
|
10
|
+
subscription = trackable.merge(to_be_merged).on(
|
11
|
+
value: test_on_value, close: test_on_close, error: test_on_error
|
12
|
+
)
|
13
|
+
trackable.await(subscription)
|
14
|
+
|
15
|
+
expect(test_data).to be ==
|
16
|
+
["0a", "0b", "1a", "2a", "1b", "3a", "4a", "2b", "3b", "|"]
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'finishes with the error if `delay_error` is true' do
|
20
|
+
err = StandardError.new('Hey')
|
21
|
+
trackable = described_class.interval(0.2).map do |v|
|
22
|
+
raise err if v == 3
|
23
|
+
v.to_s + 'a'
|
24
|
+
end.take(5)
|
25
|
+
|
26
|
+
to_be_merged =
|
27
|
+
described_class.interval(0.35).map { |v| v.to_s + 'b'}.take(4)
|
28
|
+
|
29
|
+
trackable = trackable.merge(to_be_merged, delay_error: true)
|
30
|
+
subscription = trackable.on(
|
31
|
+
value: test_on_value, close: test_on_close, error: test_on_error
|
32
|
+
)
|
33
|
+
trackable.await(subscription, 2)
|
34
|
+
|
35
|
+
expect(test_data).to be ==
|
36
|
+
["0a", "0b", "1a", "2a", "1b", "2b", "3b", err]
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context '#drop, #take, #last, #first, #[]' do
|
5
|
+
let(:test_behaviour) do
|
6
|
+
lambda do |tracker_subscription|
|
7
|
+
(1..15).each do |value|
|
8
|
+
tracker_subscription.on_value(value)
|
9
|
+
end
|
10
|
+
|
11
|
+
tracker_subscription.on_close
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context('#drop') do
|
16
|
+
it 'drops the first `n` values sent by the source' do
|
17
|
+
source.drop(6).on(value: test_on_value)
|
18
|
+
|
19
|
+
expect(test_data.size).to be(9)
|
20
|
+
expect(test_data).to be == (7..15).to_a
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context('#take') do
|
25
|
+
it 'sents only the first `n` values sent by the source' do
|
26
|
+
source.take(6).on(value: test_on_value)
|
27
|
+
|
28
|
+
expect(test_data.size).to be(6)
|
29
|
+
expect(test_data).to be == (1..6).to_a
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context('#last') do
|
34
|
+
it 'emits only the last value of the source and the closing ' \
|
35
|
+
'notification' do
|
36
|
+
source.last.on(value: test_on_value, close: test_on_close)
|
37
|
+
|
38
|
+
expect(test_data).to be == [15, '|']
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'only closes if no value was emitted by the source' do
|
42
|
+
described_class.close.last.on(
|
43
|
+
value: test_on_value, close: test_on_close
|
44
|
+
)
|
45
|
+
|
46
|
+
expect(test_data).to be == ['|']
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'emits the last value before the error and the error when error ' \
|
50
|
+
'notification is received from the source' do
|
51
|
+
err = StandardError.new('Hey!')
|
52
|
+
source.concat(described_class.error(err)).last.on(
|
53
|
+
value: test_on_value, close: test_on_close, error: test_on_error
|
54
|
+
)
|
55
|
+
|
56
|
+
expect(test_data).to be == [15, err]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context('#first') do
|
61
|
+
it 'emits only the first value of the source and closes' do
|
62
|
+
source.first.on(
|
63
|
+
value: test_on_value, close: test_on_close
|
64
|
+
)
|
65
|
+
|
66
|
+
expect(test_data).to be == [1, '|']
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'only closes if no value was emitted by the source' do
|
70
|
+
described_class.close.first.on(
|
71
|
+
value: test_on_value, close: test_on_close
|
72
|
+
)
|
73
|
+
|
74
|
+
expect(test_data).to be == ['|']
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context('#[]') do
|
79
|
+
it 'emits only the n-th value of the source and closes' do
|
80
|
+
source[4].on(
|
81
|
+
value: test_on_value, close: test_on_close
|
82
|
+
)
|
83
|
+
|
84
|
+
expect(test_data).to be == [5, '|']
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'just closes if no value was emitted by the source' do
|
88
|
+
described_class.close[3].on(
|
89
|
+
value: test_on_value, close: test_on_close
|
90
|
+
)
|
91
|
+
|
92
|
+
expect(test_data).to be == ['|']
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context 'uniq' do
|
5
|
+
it 'sends only uniq values, dropping the repeating ones' do
|
6
|
+
trackable =
|
7
|
+
described_class.enumerable([1, 2, 3, 2, 4, 3, 2, 1, 5]).uniq
|
8
|
+
|
9
|
+
trackable.on(
|
10
|
+
value: test_on_value, close: test_on_close, error: test_on_error
|
11
|
+
)
|
12
|
+
expect(test_data).to be == [1, 2, 3, 4, 5, '|']
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,20 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
context Reacto::Trackable do
|
4
|
-
let(:test_data) { [] }
|
5
|
-
let(:test_on_value) { -> (v) { test_data << v }}
|
6
|
-
let(:test_on_error) { -> (e) { test_data << e }}
|
7
|
-
let(:test_on_close) { -> () { test_data << '|' }}
|
8
|
-
|
9
|
-
let(:test_behaviour) do
|
10
|
-
lambda do |tracker_subscription|
|
11
|
-
tracker_subscription.on_value(5)
|
12
|
-
tracker_subscription.on_close
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
let(:source) { described_class.new(test_behaviour) }
|
17
|
-
|
18
4
|
context '.new' do
|
19
5
|
it 'supports behavior invoked on tracking, passed as block' do
|
20
6
|
trackable = described_class.new do |tracker_subscription|
|
@@ -62,356 +48,4 @@ context Reacto::Trackable do
|
|
62
48
|
expect(test_data[0]).to be(25)
|
63
49
|
end
|
64
50
|
end
|
65
|
-
|
66
|
-
context '#map' do
|
67
|
-
it 'transforms the value of the source Trackable using the passed ' \
|
68
|
-
'transformation' do
|
69
|
-
trackable = source.map do |v|
|
70
|
-
v * v * v
|
71
|
-
end
|
72
|
-
|
73
|
-
trackable.on(value: test_on_value)
|
74
|
-
|
75
|
-
expect(test_data.size).to be(1)
|
76
|
-
expect(test_data[0]).to be(125)
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'transforms errors, if error transformation is passed' do
|
80
|
-
source = described_class.make do |subscriber|
|
81
|
-
subscriber.on_value(4)
|
82
|
-
subscriber.on_error(StandardError.new('error'))
|
83
|
-
end
|
84
|
-
trackable = source.map(-> (v) { v }, error: -> (e) { 5 })
|
85
|
-
|
86
|
-
trackable.on(value: test_on_value, error: test_on_error)
|
87
|
-
|
88
|
-
expect(test_data.size).to be(2)
|
89
|
-
expect(test_data).to be == [4, 5]
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'emits what is produced by the passed `close` function before close' do
|
93
|
-
trackable =
|
94
|
-
described_class.enumerable((1..5)).map(close: ->() { 10 }) do |v|
|
95
|
-
v
|
96
|
-
end
|
97
|
-
|
98
|
-
trackable.on(value: test_on_value, close: test_on_close)
|
99
|
-
expect(test_data).to be == (1..5).to_a + [10, '|']
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
context '#select' do
|
104
|
-
it 'doesn\'t notify with values not passing the filter block' do
|
105
|
-
trackable = source.select do |v|
|
106
|
-
v % 2 == 0
|
107
|
-
end
|
108
|
-
|
109
|
-
trackable.on(value: test_on_value)
|
110
|
-
|
111
|
-
expect(test_data.size).to be(0)
|
112
|
-
end
|
113
|
-
|
114
|
-
it 'notifies with values passing the filter block' do
|
115
|
-
trackable = source.select do |v|
|
116
|
-
v % 2 == 1
|
117
|
-
end
|
118
|
-
|
119
|
-
trackable.on(value: test_on_value)
|
120
|
-
|
121
|
-
expect(test_data.size).to be(1)
|
122
|
-
expect(test_data[0]).to be(5)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
context '#inject' do
|
127
|
-
let(:test_behaviour) do
|
128
|
-
lambda do |tracker_subscription|
|
129
|
-
[16, 7, 2014].each do |value|
|
130
|
-
tracker_subscription.on_value(value)
|
131
|
-
end
|
132
|
-
|
133
|
-
tracker_subscription.on_close
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
it 'sends the values created by applying the `inject` operation on the ' \
|
138
|
-
'last value and current value, using for first value the initial one' do
|
139
|
-
trackable = source.inject(0) do |prev, v|
|
140
|
-
prev + v
|
141
|
-
end
|
142
|
-
trackable.on(value: test_on_value)
|
143
|
-
|
144
|
-
expect(test_data.size).to be(3)
|
145
|
-
expect(test_data).to be == [16, 23, 2037]
|
146
|
-
end
|
147
|
-
|
148
|
-
it 'sends the values created by applying the `inject` operation on the ' \
|
149
|
-
'last value and current value, using for first value ' \
|
150
|
-
'the first emitted by the source if no initial value provided' do
|
151
|
-
trackable = source.inject do |prev, v|
|
152
|
-
prev + v
|
153
|
-
end
|
154
|
-
trackable.on(value: test_on_value)
|
155
|
-
|
156
|
-
expect(test_data.size).to be(3)
|
157
|
-
expect(test_data).to be == [16, 23, 2037]
|
158
|
-
end
|
159
|
-
|
160
|
-
it 'sends the initial value if no value is emitted' do
|
161
|
-
source = described_class.new(-> (t) { t.on_close })
|
162
|
-
trackable = source.inject(0) do |prev, v|
|
163
|
-
prev + v
|
164
|
-
end
|
165
|
-
trackable.on(value: test_on_value)
|
166
|
-
|
167
|
-
expect(test_data.size).to be(1)
|
168
|
-
expect(test_data).to be == [0]
|
169
|
-
end
|
170
|
-
|
171
|
-
it 'sends nothing if no initial value and no value emitted' do
|
172
|
-
source = described_class.new(-> (t) { t.on_close })
|
173
|
-
trackable = source.inject do |prev, v|
|
174
|
-
prev + v
|
175
|
-
end
|
176
|
-
trackable.on(value: test_on_value)
|
177
|
-
|
178
|
-
expect(test_data.size).to be(0)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
context '#diff' do
|
183
|
-
it 'by default emits arrays with two values the - previous and current ' \
|
184
|
-
'element' do
|
185
|
-
source = described_class.enumerable((1..10))
|
186
|
-
trackable = source.diff
|
187
|
-
trackable.on(value: test_on_value, error: test_on_error)
|
188
|
-
|
189
|
-
expect(test_data).to be == [
|
190
|
-
[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9], [9, 10
|
191
|
-
]]
|
192
|
-
end
|
193
|
-
|
194
|
-
it 'can be passed a diff function to calculate the difference between ' \
|
195
|
-
'the previously emitted value and the current and to emit it' do
|
196
|
-
source = described_class.enumerable((1..10))
|
197
|
-
trackable = source.diff(Reacto::NO_VALUE, -> (p, c) { c - p })
|
198
|
-
trackable.on(value: test_on_value, error: test_on_error)
|
199
|
-
|
200
|
-
expect(test_data).to be == [1] * 9
|
201
|
-
end
|
202
|
-
|
203
|
-
it 'can be passed a diff block to calculate the difference between ' \
|
204
|
-
'the previously emitted value and the current and to emit it' do
|
205
|
-
source = described_class.enumerable((1..10))
|
206
|
-
trackable = source.diff { |p, c| c - p }
|
207
|
-
trackable.on(value: test_on_value, error: test_on_error)
|
208
|
-
|
209
|
-
expect(test_data).to be == [1] * 9
|
210
|
-
end
|
211
|
-
|
212
|
-
it 'can receive initial value to be used as seed - the first value' do
|
213
|
-
source = described_class.enumerable((1..10))
|
214
|
-
trackable = source.diff(-5) { |p, c| c - p }
|
215
|
-
trackable.on(value: test_on_value, error: test_on_error)
|
216
|
-
|
217
|
-
expect(test_data).to be == [6] + ([1] * 9)
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
context '#prepend' do
|
222
|
-
it 'emits the passed enumerable before the values, emited by the caller' do
|
223
|
-
source = described_class.enumerable((1..5))
|
224
|
-
trackable = source.prepend((-5..0))
|
225
|
-
|
226
|
-
trackable.on(value: test_on_value)
|
227
|
-
|
228
|
-
expect(test_data.size).to be(11)
|
229
|
-
expect(test_data).to be == (-5..5).to_a
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
context '#drop_errors' do
|
234
|
-
it 'drops all the errors from the source and continues' do
|
235
|
-
described_class.enumerable((1..5)).concat(
|
236
|
-
described_class.error(StandardError.new)
|
237
|
-
).concat(described_class.enumerable(6..10)).drop_errors.on(
|
238
|
-
value: test_on_value, error: test_on_error, close: test_on_close
|
239
|
-
)
|
240
|
-
|
241
|
-
expect(test_data).to be == (1..10).to_a + ['|']
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
context '#drop, #take, #last, #first, #[]' do
|
246
|
-
let(:test_behaviour) do
|
247
|
-
lambda do |tracker_subscription|
|
248
|
-
(1..15).each do |value|
|
249
|
-
tracker_subscription.on_value(value)
|
250
|
-
end
|
251
|
-
|
252
|
-
tracker_subscription.on_close
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
context('#drop') do
|
257
|
-
it 'drops the first `n` values sent by the source' do
|
258
|
-
source.drop(6).on(value: test_on_value)
|
259
|
-
|
260
|
-
expect(test_data.size).to be(9)
|
261
|
-
expect(test_data).to be == (7..15).to_a
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
context('#take') do
|
266
|
-
it 'sents only the first `n` values sent by the source' do
|
267
|
-
source.take(6).on(value: test_on_value)
|
268
|
-
|
269
|
-
expect(test_data.size).to be(6)
|
270
|
-
expect(test_data).to be == (1..6).to_a
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
context('#last') do
|
275
|
-
it 'emits only the last value of the source and the closing ' \
|
276
|
-
'notification' do
|
277
|
-
source.last.on(value: test_on_value, close: test_on_close)
|
278
|
-
|
279
|
-
expect(test_data).to be == [15, '|']
|
280
|
-
end
|
281
|
-
|
282
|
-
it 'only closes if no value was emitted by the source' do
|
283
|
-
described_class.close.last.on(
|
284
|
-
value: test_on_value, close: test_on_close
|
285
|
-
)
|
286
|
-
|
287
|
-
expect(test_data).to be == ['|']
|
288
|
-
end
|
289
|
-
|
290
|
-
it 'emits the last value before the error and the error when error ' \
|
291
|
-
'notification is received from the source' do
|
292
|
-
err = StandardError.new('Hey!')
|
293
|
-
source.concat(described_class.error(err)).last.on(
|
294
|
-
value: test_on_value, close: test_on_close, error: test_on_error
|
295
|
-
)
|
296
|
-
|
297
|
-
expect(test_data).to be == [15, err]
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
context('#first') do
|
302
|
-
it 'emits only the first value of the source and closes' do
|
303
|
-
source.first.on(
|
304
|
-
value: test_on_value, close: test_on_close
|
305
|
-
)
|
306
|
-
|
307
|
-
expect(test_data).to be == [1, '|']
|
308
|
-
end
|
309
|
-
|
310
|
-
it 'only closes if no value was emitted by the source' do
|
311
|
-
described_class.close.first.on(
|
312
|
-
value: test_on_value, close: test_on_close
|
313
|
-
)
|
314
|
-
|
315
|
-
expect(test_data).to be == ['|']
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
context('#[]') do
|
320
|
-
it 'emits only the n-th value of the source and closes' do
|
321
|
-
source[4].on(
|
322
|
-
value: test_on_value, close: test_on_close
|
323
|
-
)
|
324
|
-
|
325
|
-
expect(test_data).to be == [5, '|']
|
326
|
-
end
|
327
|
-
|
328
|
-
it 'just closes if no value was emitted by the source' do
|
329
|
-
described_class.close[3].on(
|
330
|
-
value: test_on_value, close: test_on_close
|
331
|
-
)
|
332
|
-
|
333
|
-
expect(test_data).to be == ['|']
|
334
|
-
end
|
335
|
-
end
|
336
|
-
end
|
337
|
-
|
338
|
-
context '#concat' do
|
339
|
-
it 'starts emitting the values from the concatenated after emitting the ' \
|
340
|
-
'values from the source, then emits a `close` notification' do
|
341
|
-
trackable = source.concat(described_class.enumerable((6..10)))
|
342
|
-
trackable.on(value: test_on_value, close: test_on_close)
|
343
|
-
|
344
|
-
expect(test_data).to be == (5..10).to_a + ['|']
|
345
|
-
end
|
346
|
-
|
347
|
-
it 'can be chained' do
|
348
|
-
trackable = source
|
349
|
-
.concat(described_class.enumerable((6..8)))
|
350
|
-
.concat(described_class.enumerable((9..10)))
|
351
|
-
trackable.on(value: test_on_value, close: test_on_close)
|
352
|
-
|
353
|
-
expect(test_data).to be == (5..10).to_a + ['|']
|
354
|
-
end
|
355
|
-
|
356
|
-
it 'closes on error' do
|
357
|
-
err = StandardError.new('Hey')
|
358
|
-
trackable = source
|
359
|
-
.concat(described_class.error(err))
|
360
|
-
.concat(described_class.enumerable((9..10)))
|
361
|
-
trackable.on(
|
362
|
-
value: test_on_value, close: test_on_close, error: test_on_error
|
363
|
-
)
|
364
|
-
|
365
|
-
expect(test_data).to be == [5, err]
|
366
|
-
end
|
367
|
-
|
368
|
-
context '#merge' do
|
369
|
-
it 'merges the passed trackable\'s emitions with the source ones' do
|
370
|
-
trackable =
|
371
|
-
described_class.interval(0.2).map { |v| v.to_s + 'a'}.take(5)
|
372
|
-
to_be_merged =
|
373
|
-
described_class.interval(0.35).map { |v| v.to_s + 'b'}.take(4)
|
374
|
-
subscription = trackable.merge(to_be_merged).on(
|
375
|
-
value: test_on_value, close: test_on_close, error: test_on_error
|
376
|
-
)
|
377
|
-
trackable.await(subscription)
|
378
|
-
|
379
|
-
expect(test_data).to be ==
|
380
|
-
["0a", "0b", "1a", "2a", "1b", "3a", "4a", "2b", "3b", "|"]
|
381
|
-
end
|
382
|
-
|
383
|
-
it 'finishes with the error if `delay_error` is true' do
|
384
|
-
err = StandardError.new('Hey')
|
385
|
-
trackable = described_class.interval(0.2).map do |v|
|
386
|
-
raise err if v == 3
|
387
|
-
v.to_s + 'a'
|
388
|
-
end.take(5)
|
389
|
-
|
390
|
-
to_be_merged =
|
391
|
-
described_class.interval(0.35).map { |v| v.to_s + 'b'}.take(4)
|
392
|
-
|
393
|
-
trackable = trackable.merge(to_be_merged, delay_error: true)
|
394
|
-
subscription = trackable.on(
|
395
|
-
value: test_on_value, close: test_on_close, error: test_on_error
|
396
|
-
)
|
397
|
-
trackable.await(subscription, 2)
|
398
|
-
|
399
|
-
expect(test_data).to be ==
|
400
|
-
["0a", "0b", "1a", "2a", "1b", "2b", "3b", err]
|
401
|
-
|
402
|
-
end
|
403
|
-
end
|
404
|
-
|
405
|
-
context 'uniq' do
|
406
|
-
it 'sends only uniq values, dropping the repeating ones' do
|
407
|
-
trackable =
|
408
|
-
described_class.enumerable([1, 2, 3, 2, 4, 3, 2, 1, 5]).uniq
|
409
|
-
|
410
|
-
trackable.on(
|
411
|
-
value: test_on_value, close: test_on_close, error: test_on_error
|
412
|
-
)
|
413
|
-
expect(test_data).to be == [1, 2, 3, 4, 5, '|']
|
414
|
-
end
|
415
|
-
end
|
416
|
-
end
|
417
51
|
end
|
data/spec/support/helpers.rb
CHANGED
@@ -6,6 +6,15 @@ module Helpers
|
|
6
6
|
let(:test_on_close) { -> () { test_data << '|' }}
|
7
7
|
let(:test_on_error) { -> (e) { test_data << e }}
|
8
8
|
|
9
|
+
let(:test_behaviour) do
|
10
|
+
lambda do |tracker_subscription|
|
11
|
+
tracker_subscription.on_value(5)
|
12
|
+
tracker_subscription.on_close
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:source) { described_class.new(test_behaviour) }
|
17
|
+
|
9
18
|
def attach_test_trackers(trackable)
|
10
19
|
trackable.on(
|
11
20
|
value: test_on_value,
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reacto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nickolay Tzvetinov - Meddle
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -59,6 +59,7 @@ executables: []
|
|
59
59
|
extensions: []
|
60
60
|
extra_rdoc_files: []
|
61
61
|
files:
|
62
|
+
- .gitignore
|
62
63
|
- .rspec
|
63
64
|
- Gemfile
|
64
65
|
- Gemfile.lock
|
@@ -74,6 +75,7 @@ files:
|
|
74
75
|
- lib/reacto/operations/drop.rb
|
75
76
|
- lib/reacto/operations/drop_errors.rb
|
76
77
|
- lib/reacto/operations/flat_map.rb
|
78
|
+
- lib/reacto/operations/flat_map_latest.rb
|
77
79
|
- lib/reacto/operations/flatten.rb
|
78
80
|
- lib/reacto/operations/inject.rb
|
79
81
|
- lib/reacto/operations/last.rb
|
@@ -109,7 +111,18 @@ files:
|
|
109
111
|
- spec/reacto/executors_and_trackable_spec.rb
|
110
112
|
- spec/reacto/operations/track_on_spec.rb
|
111
113
|
- spec/reacto/trackable/buffer_spec.rb
|
114
|
+
- spec/reacto/trackable/class_level/never_spec.rb
|
115
|
+
- spec/reacto/trackable/concat_spec.rb
|
116
|
+
- spec/reacto/trackable/diff_spec.rb
|
117
|
+
- spec/reacto/trackable/drop_errors_spec.rb
|
118
|
+
- spec/reacto/trackable/flat_map_latest_spec.rb
|
119
|
+
- spec/reacto/trackable/flat_map_spec.rb
|
120
|
+
- spec/reacto/trackable/flatten_spec.rb
|
121
|
+
- spec/reacto/trackable/inject_spec.rb
|
122
|
+
- spec/reacto/trackable/merge_spec.rb
|
123
|
+
- spec/reacto/trackable/positional_filtering_spec.rb
|
112
124
|
- spec/reacto/trackable/throttle_spec.rb
|
125
|
+
- spec/reacto/trackable/uniq_spec.rb
|
113
126
|
- spec/reacto/trackable/zip_spec.rb
|
114
127
|
- spec/reacto/trackable_spec.rb
|
115
128
|
- spec/spec_helper.rb
|
@@ -143,7 +156,18 @@ test_files:
|
|
143
156
|
- spec/reacto/executors_and_trackable_spec.rb
|
144
157
|
- spec/reacto/operations/track_on_spec.rb
|
145
158
|
- spec/reacto/trackable/buffer_spec.rb
|
159
|
+
- spec/reacto/trackable/class_level/never_spec.rb
|
160
|
+
- spec/reacto/trackable/concat_spec.rb
|
161
|
+
- spec/reacto/trackable/diff_spec.rb
|
162
|
+
- spec/reacto/trackable/drop_errors_spec.rb
|
163
|
+
- spec/reacto/trackable/flat_map_latest_spec.rb
|
164
|
+
- spec/reacto/trackable/flat_map_spec.rb
|
165
|
+
- spec/reacto/trackable/flatten_spec.rb
|
166
|
+
- spec/reacto/trackable/inject_spec.rb
|
167
|
+
- spec/reacto/trackable/merge_spec.rb
|
168
|
+
- spec/reacto/trackable/positional_filtering_spec.rb
|
146
169
|
- spec/reacto/trackable/throttle_spec.rb
|
170
|
+
- spec/reacto/trackable/uniq_spec.rb
|
147
171
|
- spec/reacto/trackable/zip_spec.rb
|
148
172
|
- spec/reacto/trackable_spec.rb
|
149
173
|
- spec/spec_helper.rb
|