frappuccino 0.0.1 → 0.2.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.
@@ -0,0 +1,18 @@
1
+ module Frappuccino
2
+ class Drop < Stream
3
+ def initialize(source, n)
4
+ source.add_observer(self)
5
+
6
+ @dropped = 0
7
+ @n = n
8
+ end
9
+
10
+ def update(event)
11
+ @dropped += 1
12
+
13
+ if @dropped > @n
14
+ occur(event)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ module Frappuccino
2
+ class Map < Stream
3
+ def initialize(source, &blk)
4
+ @block = blk
5
+ source.add_observer(self)
6
+ end
7
+
8
+ def update(event)
9
+ occur(@block.call(event))
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ module Frappuccino
2
+ class Scan < Stream
3
+ def initialize(source, zero, &blk)
4
+ @last = zero
5
+ @block = blk
6
+
7
+ source.add_observer(self)
8
+ end
9
+
10
+ def update(value)
11
+ @last = @block.call(@last, value)
12
+ occur(@last)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ module Frappuccino
2
+ class Select < Stream
3
+ def initialize(source, &blk)
4
+ @block = blk
5
+ source.add_observer(self)
6
+ end
7
+
8
+ def update(event)
9
+ if @block.call(event)
10
+ occur(event)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ module Frappuccino
2
+ class Take < Stream
3
+ def initialize(source, n)
4
+ @n = n
5
+ @length = 0
6
+ source.add_observer(self)
7
+ end
8
+
9
+ def update(value)
10
+ if @length < @n
11
+ occur(value)
12
+ @length += 1
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,26 @@
1
+ module Frappuccino
2
+ class Zip < Stream
3
+ def initialize(left, right)
4
+ @left_buffer = []
5
+ @right_buffer = []
6
+ left.add_observer(self, :left_update)
7
+ right.add_observer(self, :right_update)
8
+ end
9
+
10
+ def left_update(event)
11
+ if @right_buffer.length > 0
12
+ occur([event, @right_buffer.shift])
13
+ else
14
+ @left_buffer << event
15
+ end
16
+ end
17
+
18
+ def right_update(event)
19
+ if @left_buffer.length > 0
20
+ occur([@left_buffer.shift, event])
21
+ else
22
+ @right_buffer << event
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module Frappuccino
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,13 @@
1
+ require 'test_helper'
2
+
3
+ describe "drop" do
4
+ it "ignores the first n events" do
5
+ button = CounterButton.new
6
+ stream = Frappuccino::Stream.new(button)
7
+ dropped_stream = to_array(stream.drop(3))
8
+
9
+ 5.times { button.push }
10
+ assert_equal 2, dropped_stream.length
11
+ assert_equal [3, 4], dropped_stream
12
+ end
13
+ end
@@ -0,0 +1,80 @@
1
+ require 'test_helper'
2
+
3
+ describe "map" do
4
+ it "can take callbacks" do
5
+ button = Button.new
6
+
7
+ stream = Frappuccino::Stream.new(button)
8
+
9
+ filtered_stream = stream
10
+ .map{|event| 1 }
11
+
12
+ count = 0
13
+
14
+ filtered_stream.on_value do |event|
15
+ count += event
16
+ end
17
+
18
+ button.push
19
+ button.push
20
+ button.push
21
+
22
+ assert_equal 3, count
23
+ end
24
+
25
+ it "maps events to values" do
26
+ plus_button = PlusOneButton.new
27
+ minus_button = MinusOneButton.new
28
+
29
+ stream_one = Frappuccino::Stream.new(plus_button)
30
+ stream_two = Frappuccino::Stream.new(minus_button)
31
+
32
+ merged_stream = Frappuccino::Stream.merge(stream_one, stream_two)
33
+ mapped_stream = to_array(merged_stream.map(:+ => 1, :- => -1, :default => 0))
34
+
35
+ assert_equal [], mapped_stream
36
+
37
+ plus_button.push
38
+ assert_equal [1], mapped_stream
39
+
40
+ minus_button.push
41
+ assert_equal [1, -1], mapped_stream
42
+ end
43
+
44
+ it "respects the default value of the hash" do
45
+ plus_button = PlusOneButton.new
46
+ minus_button = MinusOneButton.new
47
+
48
+ stream_one = Frappuccino::Stream.new(plus_button)
49
+ stream_two = Frappuccino::Stream.new(minus_button)
50
+
51
+ merged_stream = Frappuccino::Stream.merge(stream_one, stream_two)
52
+ mapped_stream = to_array(merged_stream.map(:default => 1))
53
+
54
+ assert_equal [], mapped_stream
55
+
56
+ plus_button.push
57
+ minus_button.push
58
+ assert_equal [1, 1], mapped_stream
59
+ end
60
+ end
61
+
62
+ describe "collect" do
63
+ it "is a synonym for #map" do
64
+ stream = Frappuccino::Stream.new(nil)
65
+
66
+ map = stream.collect{|event| 1 }
67
+
68
+ assert_kind_of Frappuccino::Map, map
69
+ end
70
+ end
71
+
72
+ describe "#map_stream" do
73
+ it "is a synonym for #map" do
74
+ stream = Frappuccino::Stream.new(nil)
75
+
76
+ map = stream.map_stream(:default => 1)
77
+
78
+ assert_kind_of Frappuccino::Map, map
79
+ end
80
+ end
@@ -0,0 +1,53 @@
1
+ require 'test_helper'
2
+
3
+ describe "merging steams" do
4
+ it "produces one stream with both sets of events" do
5
+ button_one = Button.new
6
+ button_two = Button.new
7
+
8
+ stream_one = Frappuccino::Stream.new(button_one)
9
+ stream_two = Frappuccino::Stream.new(button_two)
10
+ merged_stream = to_array(Frappuccino::Stream.merge(stream_one, stream_two))
11
+
12
+ button_one.push
13
+ button_two.push
14
+
15
+ assert_equal 2, merged_stream.length
16
+ end
17
+
18
+ it "+1/-1" do
19
+ plus_button = PlusOneButton.new
20
+ minus_button = MinusOneButton.new
21
+
22
+ stream_one = Frappuccino::Stream.new(plus_button)
23
+ stream_two = Frappuccino::Stream.new(minus_button)
24
+
25
+ merged_stream = Frappuccino::Stream.merge(stream_one, stream_two)
26
+ counter = merged_stream
27
+ .map do |event|
28
+ case event
29
+ when :+
30
+ 1
31
+ when :-
32
+ -1
33
+ else
34
+ 0
35
+ end
36
+ end
37
+ .inject(0) {|sum, n| sum + n }
38
+
39
+ assert_equal 0, counter.now
40
+
41
+ plus_button.push
42
+ assert_equal 1, counter.now
43
+
44
+ minus_button.push
45
+ assert_equal 0, counter.now
46
+
47
+ 2.times { minus_button.push }
48
+ assert_equal(-2, counter.now)
49
+
50
+ 4.times { plus_button.push }
51
+ assert_equal 2, counter.now
52
+ end
53
+ end
@@ -0,0 +1,22 @@
1
+ require 'test_helper'
2
+
3
+ require 'frappuccino'
4
+
5
+ describe "MVP interaction" do
6
+ it "can subscribe to an event stream" do
7
+ button = Button.new
8
+ stream = Frappuccino::Stream.new(button)
9
+
10
+ counter = stream
11
+ .map {|event| event == :pushed ? 1 : 0 }
12
+ .inject(0) {|sum, n| sum + n }
13
+
14
+ assert_equal 0, counter.now
15
+
16
+ 3.times { button.push }
17
+ assert_equal 3, counter.now
18
+
19
+ button.push
20
+ assert_equal 4, counter.now
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ require 'test_helper'
2
+
3
+ describe "not implemented methods" do
4
+ [:all?,
5
+ :any?,
6
+ :chunk,
7
+ :cycle,
8
+ :find,
9
+ :detect,
10
+ ].each do |m|
11
+ it "#{m} is not implemented because it's nonsensical" do
12
+ assert_raises(NotImplementedError) do
13
+ stream = Frappuccino::Stream.new(nil)
14
+ stream.send(m)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,75 @@
1
+ require 'test_helper'
2
+
3
+ describe "#on_value" do
4
+ it "calls the block on a value" do
5
+ button = Button.new
6
+ stream = Frappuccino::Stream.new(button)
7
+
8
+ event = false
9
+
10
+ stream.on_value do |value|
11
+ event = value
12
+ end
13
+
14
+ button.push
15
+
16
+ assert_equal :pushed, event, "#on_value did not call back."
17
+ end
18
+
19
+ it "allows for multiple callbacks per Stream" do
20
+ button = Button.new
21
+ stream = Frappuccino::Stream.new(button)
22
+
23
+ callback1 = false
24
+ callback2 = false
25
+
26
+ stream.on_value do |value|
27
+ callback1 = value
28
+ end
29
+
30
+ stream.on_value do |value|
31
+ callback2 = value
32
+ end
33
+
34
+ button.push
35
+
36
+ assert_equal :pushed, callback1, "#on_value did not call first callback"
37
+ assert_equal :pushed, callback2, "#on_value did not call second callback"
38
+ end
39
+
40
+ it "works with mapped Streams" do
41
+ button = Button.new
42
+ stream = Frappuccino::Stream.new(button)
43
+
44
+ callback = false
45
+
46
+ stream.map { |val| :true }.on_value do |val|
47
+ callback = val
48
+ end
49
+
50
+ button.push
51
+
52
+ assert_equal :true, callback, "#on_value did not call back."
53
+ end
54
+
55
+ it "works with filtered Streams" do
56
+ button = Button.new
57
+ stream = Frappuccino::Stream.new(button)
58
+
59
+ callback = false
60
+ should = true
61
+
62
+ stream.select { |val| should }.on_value do |val|
63
+ callback = val
64
+ end
65
+
66
+ button.push
67
+ assert_equal :pushed, callback, "#on_value did not call back."
68
+
69
+ should = false
70
+ callback = :didnot
71
+ button.push
72
+
73
+ assert_equal :didnot, callback, "#on_value did call back."
74
+ end
75
+ end
@@ -0,0 +1,22 @@
1
+ require 'test_helper'
2
+
3
+ describe "Property" do
4
+ describe "#now" do
5
+ it "returns the current 'last' value of the Stream" do
6
+ button = Button.new
7
+ stream = Frappuccino::Stream.new(button)
8
+ stepper = Frappuccino::Property.new(:not_pushed, stream)
9
+
10
+ button.push
11
+ assert_equal :pushed, stepper.now
12
+ end
13
+
14
+ describe "when the input Stream is empty" do
15
+ it "returns the zero value" do
16
+ stream = Frappuccino::Stream.new(Object.new)
17
+ stepper = Frappuccino::Property.new("zero", stream)
18
+ assert_equal "zero", stepper.now
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ require 'test_helper'
2
+
3
+ describe "scan" do
4
+ it "returns a stream where every element is the result of the passed block applied to the last result and the current element" do
5
+ button = Button.new
6
+ stream = Frappuccino::Stream.new(button)
7
+ count_stream = to_array(stream.scan(0) { |last, current|
8
+ last + 1
9
+ })
10
+
11
+ 5.times { button.push }
12
+ assert_equal [1,2,3,4,5], count_stream
13
+ end
14
+ end
@@ -0,0 +1,40 @@
1
+ require 'test_helper'
2
+
3
+ describe "#select" do
4
+ it "properly filters events from the stream" do
5
+ points = Points.new
6
+ button = Button.new
7
+
8
+ stream = Frappuccino::Stream.new(points, button)
9
+
10
+ filtered_stream = to_array(stream.select{|event| event == :POINTS! })
11
+
12
+ 9.times { points.POINTS! }
13
+ 9.times { button.push }
14
+
15
+ assert_equal 9, filtered_stream.length
16
+ assert_equal true, filtered_stream.all? { |event| event == :POINTS! }
17
+ end
18
+
19
+ it "has #on_value" do
20
+ points = Points.new
21
+ button = Button.new
22
+
23
+ stream = Frappuccino::Stream.new(points, button)
24
+
25
+ filtered_stream = stream
26
+ .select{|event| event == :POINTS! }
27
+
28
+ count = 0
29
+
30
+ filtered_stream.on_value do |event|
31
+ count += 1
32
+ end
33
+
34
+ points.POINTS!
35
+ points.POINTS!
36
+ button.push
37
+
38
+ assert_equal 2, count
39
+ end
40
+ end