hallon 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -0
- data/{CHANGELOG → CHANGELOG.md} +82 -27
- data/Gemfile +1 -0
- data/README.markdown +1 -1
- data/Rakefile +8 -6
- data/examples/adding_tracks_to_playlist.rb +3 -0
- data/examples/logging_in.rb +3 -0
- data/examples/playing_audio.rb +130 -0
- data/examples/printing_link_information.rb +3 -0
- data/examples/show_published_playlists_of_user.rb +5 -13
- data/hallon.gemspec +2 -2
- data/lib/hallon.rb +15 -0
- data/lib/hallon/album.rb +1 -1
- data/lib/hallon/album_browse.rb +4 -3
- data/lib/hallon/artist.rb +1 -1
- data/lib/hallon/artist_browse.rb +5 -4
- data/lib/hallon/base.rb +7 -2
- data/lib/hallon/error.rb +1 -1
- data/lib/hallon/ext/spotify.rb +26 -42
- data/lib/hallon/image.rb +7 -8
- data/lib/hallon/observable.rb +134 -62
- data/lib/hallon/observable/album_browse.rb +30 -0
- data/lib/hallon/observable/artist_browse.rb +31 -0
- data/lib/hallon/observable/image.rb +31 -0
- data/lib/hallon/observable/player.rb +13 -0
- data/lib/hallon/observable/playlist.rb +194 -0
- data/lib/hallon/observable/playlist_container.rb +74 -0
- data/lib/hallon/observable/post.rb +30 -0
- data/lib/hallon/observable/search.rb +29 -0
- data/lib/hallon/observable/session.rb +236 -0
- data/lib/hallon/observable/toplist.rb +30 -0
- data/lib/hallon/player.rb +8 -17
- data/lib/hallon/playlist.rb +11 -7
- data/lib/hallon/playlist_container.rb +11 -4
- data/lib/hallon/queue.rb +71 -0
- data/lib/hallon/search.rb +10 -7
- data/lib/hallon/session.rb +18 -21
- data/lib/hallon/toplist.rb +4 -3
- data/lib/hallon/user.rb +5 -5
- data/lib/hallon/version.rb +1 -1
- data/spec/hallon/album_browse_spec.rb +4 -0
- data/spec/hallon/artist_browse_spec.rb +4 -0
- data/spec/hallon/base_spec.rb +26 -9
- data/spec/hallon/hallon_spec.rb +0 -18
- data/spec/hallon/image_spec.rb +0 -1
- data/spec/hallon/link_spec.rb +14 -0
- data/spec/hallon/observable/album_browse_spec.rb +7 -0
- data/spec/hallon/observable/artist_browse_spec.rb +7 -0
- data/spec/hallon/observable/image_spec.rb +8 -0
- data/spec/hallon/observable/playlist_container_spec.rb +21 -0
- data/spec/hallon/observable/playlist_spec.rb +85 -0
- data/spec/hallon/observable/post_spec.rb +8 -0
- data/spec/hallon/observable/search_spec.rb +7 -0
- data/spec/hallon/observable/session_spec.rb +143 -0
- data/spec/hallon/observable/toplist_spec.rb +7 -0
- data/spec/hallon/observable_spec.rb +134 -65
- data/spec/hallon/playlist_container_spec.rb +24 -18
- data/spec/hallon/playlist_spec.rb +2 -0
- data/spec/hallon/queue_spec.rb +35 -0
- data/spec/hallon/session_spec.rb +4 -4
- data/spec/hallon/spotify_spec.rb +35 -9
- data/spec/mockspotify.rb +2 -3
- data/spec/spec_helper.rb +0 -1
- data/spec/support/common_objects.rb +27 -15
- data/spec/support/enumerable_comparison.rb +9 -0
- data/spec/support/shared_for_callbacks.rb +60 -0
- data/spec/support/shared_for_linkable_objects.rb +1 -1
- metadata +56 -20
data/spec/hallon/hallon_spec.rb
CHANGED
@@ -18,22 +18,4 @@ describe Hallon do
|
|
18
18
|
it { should match uri }
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
22
|
-
describe "object callbacks" do
|
23
|
-
pending <<-REASON
|
24
|
-
|
25
|
-
Once callbacks are implemented in libmockspotify, we should also
|
26
|
-
test them on the following objects:
|
27
|
-
|
28
|
-
- Session
|
29
|
-
- Image
|
30
|
-
- AlbumBrowse
|
31
|
-
- ArtistBrowse
|
32
|
-
- Search
|
33
|
-
- Playlist
|
34
|
-
- PlaylistContainer
|
35
|
-
- Toplist
|
36
|
-
- Inbox
|
37
|
-
REASON
|
38
|
-
end
|
39
21
|
end
|
data/spec/hallon/image_spec.rb
CHANGED
data/spec/hallon/link_spec.rb
CHANGED
@@ -101,4 +101,18 @@ describe Hallon::Link do
|
|
101
101
|
subject.should eq object
|
102
102
|
end
|
103
103
|
end
|
104
|
+
|
105
|
+
describe "#pointer" do
|
106
|
+
it "should raise an error if the expected type is not the same as requested" do
|
107
|
+
expect { Hallon::Link.new("spotify:user:burgestrand:starred").pointer(:profile) }.to raise_error(ArgumentError)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should not raise an error if the expected type is :playlist but real type is starred" do
|
111
|
+
expect { Hallon::Link.new("spotify:user:burgestrand:starred").pointer(:playlist) }.to_not raise_error
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should not raise an error if the expected type and type matches" do
|
115
|
+
expect { Hallon::Link.new("spotify:user:burgestrand").pointer(:profile) }.to_not raise_error
|
116
|
+
end
|
117
|
+
end
|
104
118
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
describe Hallon::Observable::PlaylistContainer do
|
2
|
+
specification_for_callback "playlist_added" do
|
3
|
+
let(:input) { [a_pointer, mock_playlist_raw, 3, :userdata] }
|
4
|
+
let(:output) { [Hallon::Playlist.new(mock_playlist), 3, subject] }
|
5
|
+
end
|
6
|
+
|
7
|
+
specification_for_callback "playlist_removed" do
|
8
|
+
let(:input) { [a_pointer, mock_playlist_raw, 3, :userdata] }
|
9
|
+
let(:output) { [Hallon::Playlist.new(mock_playlist), 3, subject] }
|
10
|
+
end
|
11
|
+
|
12
|
+
specification_for_callback "playlist_moved" do
|
13
|
+
let(:input) { [a_pointer, mock_playlist_raw, 3, 8, :userdata] }
|
14
|
+
let(:output) { [Hallon::Playlist.new(mock_playlist), 3, 8, subject] }
|
15
|
+
end
|
16
|
+
|
17
|
+
specification_for_callback "container_loaded" do
|
18
|
+
let(:input) { [a_pointer, :userdata] }
|
19
|
+
let(:output) { [subject] }
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
describe Hallon::Observable::Playlist do
|
2
|
+
let(:trackpointers_size) { 2 }
|
3
|
+
let(:trackpointers) do
|
4
|
+
tracks = FFI::MemoryPointer.new(:pointer, 2)
|
5
|
+
tracks.write_array_of_pointer([mock_track, mock_track_two])
|
6
|
+
tracks
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:tracks) do
|
10
|
+
instantiate(Hallon::Track, mock_track, mock_track_two)
|
11
|
+
end
|
12
|
+
|
13
|
+
specification_for_callback "tracks_added" do
|
14
|
+
let(:input) { [a_pointer, trackpointers, trackpointers_size, 0, :userdata] }
|
15
|
+
let(:output) { [tracks, 0, subject] }
|
16
|
+
end
|
17
|
+
|
18
|
+
specification_for_callback "tracks_removed" do
|
19
|
+
let(:input) { [a_pointer, trackpointers, trackpointers_size, :userdata] }
|
20
|
+
let(:output) { [tracks, subject] }
|
21
|
+
end
|
22
|
+
|
23
|
+
specification_for_callback "tracks_moved" do
|
24
|
+
let(:input) { [a_pointer, trackpointers, trackpointers_size, 7, :userdata] }
|
25
|
+
let(:output) { [tracks, 7, subject] }
|
26
|
+
end
|
27
|
+
|
28
|
+
specification_for_callback "playlist_renamed" do
|
29
|
+
let(:input) { [a_pointer, :userdata] }
|
30
|
+
let(:output) { [subject] }
|
31
|
+
end
|
32
|
+
|
33
|
+
specification_for_callback "playlist_state_changed" do
|
34
|
+
let(:input) { [a_pointer, :userdata] }
|
35
|
+
let(:output) { [subject] }
|
36
|
+
end
|
37
|
+
|
38
|
+
specification_for_callback "playlist_update_in_progress" do
|
39
|
+
let(:input) { [a_pointer, true, :userdata] }
|
40
|
+
let(:output) { [true, subject] }
|
41
|
+
end
|
42
|
+
|
43
|
+
specification_for_callback "playlist_metadata_updated" do
|
44
|
+
let(:input) { [a_pointer, :userdata] }
|
45
|
+
let(:output) { [subject] }
|
46
|
+
end
|
47
|
+
|
48
|
+
specification_for_callback "track_created_changed" do
|
49
|
+
let(:input) { [a_pointer, 7, mock_user_raw, 15, :userdata] }
|
50
|
+
let(:output) { [7, Hallon::User.new(mock_user), Time.at(15), subject] }
|
51
|
+
end
|
52
|
+
|
53
|
+
specification_for_callback "track_seen_changed" do
|
54
|
+
let(:input) { [a_pointer, 0, true, :userdata] }
|
55
|
+
let(:output) { [0, true, subject] }
|
56
|
+
end
|
57
|
+
|
58
|
+
specification_for_callback "track_message_changed" do
|
59
|
+
let(:input) { [a_pointer, 13, "I LUFF JOO!", :userdata] }
|
60
|
+
let(:output) { [13, "I LUFF JOO!", subject] }
|
61
|
+
end
|
62
|
+
|
63
|
+
specification_for_callback "description_changed" do
|
64
|
+
let(:input) { [a_pointer, "Merily merily merily bong", :userdata] }
|
65
|
+
let(:output) { ["Merily merily merily bong", subject] }
|
66
|
+
end
|
67
|
+
|
68
|
+
specification_for_callback "image_changed" do
|
69
|
+
before { Hallon::Session.stub!(:instance => session) }
|
70
|
+
let(:input) { [a_pointer, mock_image_id, :userdata] }
|
71
|
+
let(:output) { [Hallon::Image.new(mock_image), subject] }
|
72
|
+
|
73
|
+
it "should not fail if the image has been *removed*" do
|
74
|
+
block = proc { |image| }
|
75
|
+
block.should_receive(:call).with(nil, subject)
|
76
|
+
subject.on(:image_changed, &block)
|
77
|
+
subject_callback.call(a_pointer, null_pointer, :userdata)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
specification_for_callback "subscribers_changed" do
|
82
|
+
let(:input) { [a_pointer, :userdata] }
|
83
|
+
let(:output) { [subject] }
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
describe Hallon::Observable::Session do
|
3
|
+
let(:klass) { Class.new { include described_class } }
|
4
|
+
let(:object) { klass.new }
|
5
|
+
|
6
|
+
specification_for_callback "logged_in" do
|
7
|
+
let(:input) { [a_pointer, :ok] }
|
8
|
+
let(:output) { [:ok, subject] }
|
9
|
+
end
|
10
|
+
|
11
|
+
specification_for_callback "logged_out" do
|
12
|
+
let(:input) { [a_pointer] }
|
13
|
+
let(:output) { [subject] }
|
14
|
+
end
|
15
|
+
|
16
|
+
specification_for_callback "metadata_updated" do
|
17
|
+
let(:input) { [a_pointer] }
|
18
|
+
let(:output) { [subject] }
|
19
|
+
end
|
20
|
+
|
21
|
+
specification_for_callback "connection_error" do
|
22
|
+
let(:input) { [a_pointer, :ok] }
|
23
|
+
let(:output) { [:ok, subject] }
|
24
|
+
end
|
25
|
+
|
26
|
+
specification_for_callback "message_to_user" do
|
27
|
+
let(:input) { [a_pointer, "ALL UR BASE"] }
|
28
|
+
let(:output) { ["ALL UR BASE", subject] }
|
29
|
+
end
|
30
|
+
|
31
|
+
specification_for_callback "notify_main_thread" do
|
32
|
+
let(:input) { [a_pointer] }
|
33
|
+
let(:output) { [subject] }
|
34
|
+
end
|
35
|
+
|
36
|
+
specification_for_callback "music_delivery" do
|
37
|
+
let(:num_frames) do
|
38
|
+
data.size / 2
|
39
|
+
end
|
40
|
+
|
41
|
+
let(:data) do
|
42
|
+
(0...100).zip((0...100).to_a.reverse).flatten # [0, 99, 1, 98 …]
|
43
|
+
end
|
44
|
+
|
45
|
+
let(:frames) do
|
46
|
+
channels = 2
|
47
|
+
frames = FFI::MemoryPointer.new(:int16, num_frames * channels)
|
48
|
+
frames.write_array_of_int16(data.flatten)
|
49
|
+
frames
|
50
|
+
end
|
51
|
+
|
52
|
+
let(:format) do
|
53
|
+
struct = Spotify::AudioFormat.new
|
54
|
+
struct[:sample_type] = :int16
|
55
|
+
struct[:sample_rate] = 44100 # 44.1khz
|
56
|
+
struct[:channels] = 2
|
57
|
+
struct.pointer
|
58
|
+
end
|
59
|
+
|
60
|
+
let(:input) { [a_pointer, format, frames, num_frames] }
|
61
|
+
let(:output) { [{rate: 44100, type: :int16, channels: 2}, data.each_slice(2), subject] }
|
62
|
+
|
63
|
+
it "should return the resulting value" do
|
64
|
+
subject.on(:music_delivery) { 7 }
|
65
|
+
subject_callback.call(*input).should eq 7
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should ensure the resulting value is an integer" do
|
69
|
+
subject_callback.call(*input).should eq 0
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
specification_for_callback "play_token_lost" do
|
74
|
+
let(:input) { [a_pointer] }
|
75
|
+
let(:output) { [subject] }
|
76
|
+
end
|
77
|
+
|
78
|
+
specification_for_callback "end_of_track" do
|
79
|
+
let(:input) { [a_pointer] }
|
80
|
+
let(:output) { [subject] }
|
81
|
+
end
|
82
|
+
|
83
|
+
specification_for_callback "start_playback" do
|
84
|
+
let(:input) { [a_pointer] }
|
85
|
+
let(:output) { [subject] }
|
86
|
+
end
|
87
|
+
|
88
|
+
specification_for_callback "stop_playback" do
|
89
|
+
let(:input) { [a_pointer] }
|
90
|
+
let(:output) { [subject] }
|
91
|
+
end
|
92
|
+
|
93
|
+
specification_for_callback "get_audio_buffer_stats" do
|
94
|
+
let(:input) { [a_pointer, Spotify::AudioBufferStats.new.pointer] }
|
95
|
+
let(:output) { [subject] }
|
96
|
+
|
97
|
+
it "should return the resulting audio buffer stats" do
|
98
|
+
stats = Spotify::AudioBufferStats.new
|
99
|
+
subject.on(:get_audio_buffer_stats) { [5, 7] }
|
100
|
+
|
101
|
+
stats[:samples].should eq 0
|
102
|
+
stats[:stutter].should eq 0
|
103
|
+
subject_callback.call(a_pointer, stats.pointer)
|
104
|
+
stats[:samples].should eq 5
|
105
|
+
stats[:stutter].should eq 7
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should report zeroes if there’s no callback" do
|
109
|
+
stats = Spotify::AudioBufferStats.new
|
110
|
+
|
111
|
+
stats[:samples].should eq 0
|
112
|
+
stats[:stutter].should eq 0
|
113
|
+
subject_callback.call(a_pointer, stats.pointer)
|
114
|
+
stats[:samples].should eq 0
|
115
|
+
stats[:stutter].should eq 0
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
specification_for_callback "streaming_error" do
|
120
|
+
let(:input) { [a_pointer, :ok] }
|
121
|
+
let(:output) { [:ok, subject] }
|
122
|
+
end
|
123
|
+
|
124
|
+
specification_for_callback "userinfo_updated" do
|
125
|
+
let(:input) { [a_pointer] }
|
126
|
+
let(:output) { [subject] }
|
127
|
+
end
|
128
|
+
|
129
|
+
specification_for_callback "log_message" do
|
130
|
+
let(:input) { [a_pointer, "WATCHING U!"] }
|
131
|
+
let(:output) { ["WATCHING U!", subject] }
|
132
|
+
end
|
133
|
+
|
134
|
+
specification_for_callback "offline_status_updated" do
|
135
|
+
let(:input) { [a_pointer] }
|
136
|
+
let(:output) { [subject] }
|
137
|
+
end
|
138
|
+
|
139
|
+
specification_for_callback "offline_error" do
|
140
|
+
let(:input) { [a_pointer, :ok] }
|
141
|
+
let(:output) { [:ok, subject] }
|
142
|
+
end
|
143
|
+
end
|
@@ -1,80 +1,155 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
describe Hallon::Observable do
|
2
|
-
|
3
|
-
Class.new
|
3
|
+
let(:klass) do
|
4
|
+
Class.new do
|
5
|
+
class << self
|
6
|
+
def initialize_callbacks
|
7
|
+
%w[testing testing_string testing_symbol testing_arguments].map do |m|
|
8
|
+
callback_for(m)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def testing_callback(pointer)
|
13
|
+
trigger(pointer, :testing)
|
14
|
+
end
|
15
|
+
|
16
|
+
def testing_string_callback(pointer)
|
17
|
+
trigger(pointer, "testing_string")
|
18
|
+
end
|
19
|
+
|
20
|
+
def testing_symbol_callback(pointer)
|
21
|
+
trigger(pointer, :testing_symbol)
|
22
|
+
end
|
23
|
+
|
24
|
+
def testing_arguments_callback(pointer, x, y)
|
25
|
+
trigger(pointer, :testing_arguments, x * 2, y * 4)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
include Hallon::Observable
|
30
|
+
|
31
|
+
attr_reader :callbacks
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
subscribe_for_callbacks do |callbacks|
|
35
|
+
@callbacks = callbacks
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def fire!(name, *args, &block)
|
40
|
+
ptr = FFI::Pointer.new(pointer)
|
41
|
+
cb = self.class.send(:callback_for, name)
|
42
|
+
cb.call(ptr, *args)
|
43
|
+
end
|
44
|
+
|
45
|
+
def pointer
|
46
|
+
FFI::Pointer.new(0xDEADBEEF)
|
47
|
+
end
|
48
|
+
end
|
4
49
|
end
|
5
50
|
|
6
|
-
describe "
|
7
|
-
|
8
|
-
|
51
|
+
describe "ClassMethods" do
|
52
|
+
subject { klass }
|
53
|
+
|
54
|
+
describe ".subscribers_for" do
|
55
|
+
around { |test| Ref::Mock.use(&test) }
|
56
|
+
|
57
|
+
it "should contain a list of weak references to subscribers" do
|
58
|
+
ptr = FFI::Pointer.new(0xDEADBEEF)
|
59
|
+
|
60
|
+
objA = klass.new
|
61
|
+
subject.subscribers_for(ptr).should eq [objA]
|
62
|
+
|
63
|
+
objB = klass.new
|
64
|
+
subject.subscribers_for(ptr).should eq [objA, objB]
|
65
|
+
|
66
|
+
Ref::Mock.gc(objA)
|
67
|
+
subject.subscribers_for(ptr).should eq [objB]
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should return an empty array if there are no subscribers" do
|
71
|
+
subject.subscribers_for(null_pointer).should be_empty
|
72
|
+
end
|
73
|
+
end
|
9
74
|
end
|
10
75
|
|
76
|
+
subject { klass.new }
|
77
|
+
|
11
78
|
describe "#on" do
|
12
|
-
it "should
|
13
|
-
|
14
|
-
|
15
|
-
|
79
|
+
it "should take both a symbol and a string" do
|
80
|
+
string = false
|
81
|
+
symbol = false
|
82
|
+
|
83
|
+
subject.on("testing_string") { string = true }
|
84
|
+
subject.on(:testing_symbol) { symbol = true }
|
85
|
+
|
86
|
+
subject.fire!(:testing_string)
|
87
|
+
subject.fire!("testing_symbol")
|
16
88
|
|
17
|
-
|
18
|
-
|
19
|
-
subject.trigger(:c).should eq "yay"
|
89
|
+
string.should be_true
|
90
|
+
symbol.should be_true
|
20
91
|
end
|
21
92
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
93
|
+
it "should receive the callback after it’s been processed" do
|
94
|
+
x = nil
|
95
|
+
y = nil
|
96
|
+
|
97
|
+
subject.on(:testing_arguments) do |a, b|
|
98
|
+
x = a
|
99
|
+
y = b
|
100
|
+
end
|
101
|
+
|
102
|
+
subject.fire!(:testing_arguments, 10, "Hi")
|
103
|
+
|
104
|
+
x.should eq 20
|
105
|
+
y.should eq "HiHiHiHi"
|
26
106
|
end
|
27
107
|
|
28
|
-
|
29
|
-
|
30
|
-
|
108
|
+
it "should replace the previous callback if there was one" do
|
109
|
+
x = 0
|
110
|
+
|
111
|
+
subject.on(:testing) { x += 1 }
|
112
|
+
subject.fire!(:testing)
|
113
|
+
x.should eq 1
|
114
|
+
|
115
|
+
subject.on(:testing) { x -= 1 }
|
116
|
+
subject.fire!(:testing)
|
117
|
+
x.should eq 0
|
31
118
|
end
|
32
119
|
|
33
|
-
it "should
|
34
|
-
subject.on("
|
35
|
-
expect { subject.trigger(:a) }.to raise_error("hell")
|
120
|
+
it "should raise an error trying to bind to a non-existing callback" do
|
121
|
+
expect { subject.on("nonexisting") {} }.to raise_error(NameError)
|
36
122
|
end
|
37
|
-
end
|
38
123
|
|
39
|
-
|
40
|
-
|
41
|
-
called = false
|
42
|
-
subject.on(:a) { called = true }
|
43
|
-
subject.trigger(:a)
|
44
|
-
called.should be_true
|
124
|
+
it "should raise an error when not given a block" do
|
125
|
+
expect { subject.on(:testing) }.to raise_error(ArgumentError)
|
45
126
|
end
|
127
|
+
end
|
46
128
|
|
47
|
-
|
48
|
-
|
49
|
-
subject.
|
50
|
-
subject.trigger(:a, :b, :c)
|
51
|
-
passed_args.should eq [:b, :c]
|
129
|
+
describe "#subscribe_for_callbacks" do
|
130
|
+
it "should yield indiscriminetly" do
|
131
|
+
expect { subject.send(:subscribe_for_callbacks) }.to raise_error(LocalJumpError)
|
52
132
|
end
|
53
133
|
|
54
|
-
it "should
|
55
|
-
|
134
|
+
it "should raise an error if the same object tries to subscribe twice" do
|
135
|
+
# we already subscribed for callbacks in initialize
|
136
|
+
expect { subject.send(:subscribe_for_callbacks) {} }.to raise_error(ArgumentError)
|
56
137
|
end
|
57
138
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
subject.on(:a) { triggered << :a }
|
62
|
-
subject.on(:a) { triggered << :b }
|
63
|
-
subject.trigger(:a)
|
64
|
-
triggered.should eq [:a, :b]
|
65
|
-
end
|
139
|
+
it "should always yield the *same* object" do
|
140
|
+
a = klass.new
|
141
|
+
b = klass.new
|
66
142
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
subject.trigger(:a).should eq :second
|
71
|
-
end
|
143
|
+
a.callbacks.should eq b.callbacks
|
144
|
+
end
|
145
|
+
end
|
72
146
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
147
|
+
describe "#trigger" do
|
148
|
+
it "should always append self to the arguments" do
|
149
|
+
block = proc {}
|
150
|
+
subject.on(:testing, &block)
|
151
|
+
block.should_receive(:call).with(subject)
|
152
|
+
subject.send(:trigger, :testing)
|
78
153
|
end
|
79
154
|
end
|
80
155
|
|
@@ -86,21 +161,15 @@ describe Hallon::Observable do
|
|
86
161
|
end
|
87
162
|
|
88
163
|
it "should restore previous handlers on return" do
|
89
|
-
subject.on(:
|
164
|
+
subject.on(:testing) { "before" }
|
90
165
|
|
91
166
|
subject.protecting_handlers do
|
92
|
-
subject.
|
93
|
-
subject.on(:
|
94
|
-
subject.
|
167
|
+
subject.fire!(:testing).should eq "before"
|
168
|
+
subject.on(:testing) { "after" }
|
169
|
+
subject.fire!(:testing).should eq "after"
|
95
170
|
end
|
96
171
|
|
97
|
-
subject.
|
98
|
-
end
|
99
|
-
|
100
|
-
it "should still allow #trigger to work on non-defined events" do
|
101
|
-
subject.protecting_handlers {}
|
102
|
-
expect { subject.trigger(:does_not_exist) }.to_not raise_error
|
172
|
+
subject.fire!(:testing).should eq "before"
|
103
173
|
end
|
104
174
|
end
|
105
|
-
|
106
175
|
end
|