cultome_player 2.0.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.
Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +24 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +7 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +325 -0
  9. data/Rakefile +8 -0
  10. data/bin/cultome_player +39 -0
  11. data/config/environment.yml +28 -0
  12. data/cultome_player.gemspec +35 -0
  13. data/db/001_create_schema.rb +58 -0
  14. data/lib/cultome_player.rb +107 -0
  15. data/lib/cultome_player/command.rb +11 -0
  16. data/lib/cultome_player/command/language.rb +61 -0
  17. data/lib/cultome_player/command/processor.rb +165 -0
  18. data/lib/cultome_player/command/reader.rb +86 -0
  19. data/lib/cultome_player/environment.rb +130 -0
  20. data/lib/cultome_player/events.rb +29 -0
  21. data/lib/cultome_player/media.rb +47 -0
  22. data/lib/cultome_player/objects.rb +15 -0
  23. data/lib/cultome_player/objects/album.rb +21 -0
  24. data/lib/cultome_player/objects/artist.rb +18 -0
  25. data/lib/cultome_player/objects/command.rb +37 -0
  26. data/lib/cultome_player/objects/drive.rb +26 -0
  27. data/lib/cultome_player/objects/genre.rb +16 -0
  28. data/lib/cultome_player/objects/parameter.rb +37 -0
  29. data/lib/cultome_player/objects/response.rb +42 -0
  30. data/lib/cultome_player/objects/song.rb +38 -0
  31. data/lib/cultome_player/player.rb +13 -0
  32. data/lib/cultome_player/player/adapter.rb +14 -0
  33. data/lib/cultome_player/player/adapter/mpg123.rb +143 -0
  34. data/lib/cultome_player/player/interactive.rb +56 -0
  35. data/lib/cultome_player/player/interface.rb +13 -0
  36. data/lib/cultome_player/player/interface/basic.rb +96 -0
  37. data/lib/cultome_player/player/interface/builtin_help.rb +368 -0
  38. data/lib/cultome_player/player/interface/extended.rb +199 -0
  39. data/lib/cultome_player/player/interface/helper.rb +300 -0
  40. data/lib/cultome_player/player/playlist.rb +280 -0
  41. data/lib/cultome_player/plugins.rb +23 -0
  42. data/lib/cultome_player/plugins/help.rb +58 -0
  43. data/lib/cultome_player/state_checker.rb +74 -0
  44. data/lib/cultome_player/utils.rb +95 -0
  45. data/lib/cultome_player/version.rb +3 -0
  46. data/spec/config.yml +0 -0
  47. data/spec/cultome_player/command/processor_spec.rb +168 -0
  48. data/spec/cultome_player/command/reader_spec.rb +45 -0
  49. data/spec/cultome_player/cultome_player_spec.rb +17 -0
  50. data/spec/cultome_player/environment_spec.rb +65 -0
  51. data/spec/cultome_player/events_spec.rb +22 -0
  52. data/spec/cultome_player/media_spec.rb +41 -0
  53. data/spec/cultome_player/player/adapter/mpg123_spec.rb +82 -0
  54. data/spec/cultome_player/player/interface/basic_spec.rb +168 -0
  55. data/spec/cultome_player/player/interface/extended/connect_spec.rb +117 -0
  56. data/spec/cultome_player/player/interface/extended/search_spec.rb +90 -0
  57. data/spec/cultome_player/player/interface/extended/show_spec.rb +36 -0
  58. data/spec/cultome_player/player/interface/extended/shuffle_spec.rb +26 -0
  59. data/spec/cultome_player/player/interface/extended_spec.rb +136 -0
  60. data/spec/cultome_player/player/interface/helper_spec.rb +63 -0
  61. data/spec/cultome_player/player/interface_spec.rb +17 -0
  62. data/spec/cultome_player/player/playlist_spec.rb +301 -0
  63. data/spec/cultome_player/plugins/help_spec.rb +21 -0
  64. data/spec/cultome_player/plugins_spec.rb +19 -0
  65. data/spec/cultome_player/utils_spec.rb +15 -0
  66. data/spec/spec_helper.rb +108 -0
  67. data/spec/test/uno/dos/dos.mp3 +0 -0
  68. data/spec/test/uno/dos/tres/tres.mp3 +0 -0
  69. data/spec/test/uno/uno.mp3 +0 -0
  70. data/tasks/console.rake +19 -0
  71. data/tasks/db.rake +19 -0
  72. data/tasks/run.rake +7 -0
  73. metadata +322 -0
@@ -0,0 +1,168 @@
1
+ require 'spec_helper'
2
+
3
+ describe CultomePlayer::Player::Interface::Basic do
4
+ let(:t){ TestClass.new }
5
+
6
+ describe '#pause' do
7
+ it 'calls the underliying player' do
8
+ t.should_receive(:pause_in_player)
9
+ t.execute "pause on"
10
+ end
11
+
12
+ it 'respond to description_help' do
13
+ t.should respond_to(:description_help)
14
+ end
15
+
16
+ it 'respond to usage_help' do
17
+ t.should respond_to(:usage_help)
18
+ end
19
+
20
+ it 'respond with Response object' do
21
+ t.execute("pause on").should be_instance_of Response
22
+ end
23
+ end
24
+
25
+ describe '#stop' do
26
+ before :each do
27
+ t.execute "connect '#{test_folder}' => test"
28
+ end
29
+
30
+ it 'calls the underliying player' do
31
+ t.should_receive(:stop_in_player)
32
+ t.execute "play"
33
+ t.execute "stop"
34
+ end
35
+
36
+ it 'respond to description_stop' do
37
+ t.should respond_to(:description_stop)
38
+ end
39
+
40
+ it 'respond to usage_stop' do
41
+ t.should respond_to(:usage_stop)
42
+ end
43
+
44
+ it 'respond with Response object' do
45
+ t.execute("stop").should be_instance_of Response
46
+ end
47
+ end
48
+
49
+ describe '#play' do
50
+
51
+ it 'respond to description_play' do
52
+ t.should respond_to(:description_play)
53
+ end
54
+
55
+ it 'respond to usage_play' do
56
+ t.should respond_to(:usage_play)
57
+ end
58
+
59
+ it 'respond with Response object' do
60
+ t.execute("play").should be_instance_of Response
61
+ end
62
+
63
+ context 'without music connected' do
64
+ it 'advise to connect music first if no music is connected' do
65
+ r = t.execute("play")
66
+ r.message.should eq "No music connected! You should try 'connect /home/yoo/music => main' first"
67
+ end
68
+ end
69
+
70
+ context 'with music connected' do
71
+ before :each do
72
+ t.execute "connect '#{test_folder}' => test"
73
+ end
74
+
75
+ it 'calls the underliying player to play' do
76
+ t.should_receive(:play_in_player)
77
+ t.execute 'play'
78
+ end
79
+
80
+ it 'calls the underliying player to resume playback' do
81
+ t.should_receive(:resume_in_player)
82
+ t.execute 'play'
83
+ t.execute "pause on"
84
+ t.execute 'play'
85
+ end
86
+
87
+ context 'without parameters' do
88
+ it 'in clean state should play all the library' do
89
+ r = t.execute 'play'
90
+ r.playlist.should have(3).items
91
+ r.should respond_to(:now_playing)
92
+ r.should respond_to(:playlist)
93
+ t.current_playlist.to_a.should have(3).items
94
+ t.current_song.should_not be_nil
95
+ end
96
+
97
+ it 'if paused should resume playback' do
98
+ t.execute "pause on"
99
+ t.should be_paused
100
+ t.execute 'play'
101
+ t.should_not be_paused
102
+ end
103
+
104
+ it 'if stopped should resume last playback from the begin' do
105
+ t.execute "play"
106
+ my_song = t.current_song
107
+ t.execute "stop"
108
+ t.should be_stopped
109
+ t.execute 'play'
110
+ t.should be_playing
111
+ my_song.should eq t.current_song
112
+ end
113
+
114
+ it 'get an error message if playing' do
115
+ t.execute 'play'
116
+ r = t.execute 'play'
117
+ r.message.should eq 'What you mean? Im already playing!'
118
+ end
119
+ end
120
+
121
+ context 'with number parameter' do
122
+ it 'play the nth element in focus list without altering the current playlist' do
123
+ t.execute 'search a'
124
+ t.execute 'play 2'
125
+ t.current_song.name.should eq t.playlists[:focus].at(1).name
126
+ end
127
+ end
128
+
129
+ context 'with criteria parameter' do
130
+ it 'different criterias create an AND filter' do
131
+ t.execute "play t:a"
132
+ t.current_playlist.should have(2).songs
133
+ t.execute "play t:a a:m"
134
+ t.current_playlist.should have(1).songs
135
+ end
136
+
137
+ it 'same criterias create an OR filter' do
138
+ t.execute "play t:a"
139
+ t.current_playlist.should have(2).songs
140
+ t.execute "play t:a t:d"
141
+ t.current_playlist.should have(3).songs
142
+ end
143
+ end
144
+
145
+ context 'with object parameter' do
146
+ it 'replace the current playlist with the object content' do
147
+ t.execute 'play'
148
+ t.current_playlist.should have(3).songs
149
+ t.execute 'next'
150
+ t.execute 'next'
151
+ t.execute 'play @history'
152
+ t.current_playlist.should have(2).songs
153
+ end
154
+ end
155
+
156
+ context 'with literal parameter' do
157
+ it 'create an OR filter with the fields trackname, artist and album' do
158
+ t.execute 'play way'
159
+ t.current_playlist.should have(1).songs
160
+ t.execute 'play sing'
161
+ t.current_playlist.should have(1).songs
162
+ t.execute 'play sing way'
163
+ t.current_playlist.should have(2).songs
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,117 @@
1
+ require 'spec_helper'
2
+
3
+ include CultomePlayer::Objects
4
+
5
+ describe CultomePlayer::Player::Interface::Extended do
6
+ let(:t){ TestClass.new }
7
+
8
+ before :each do
9
+ Song.create!(id: 1, name: "song_uno", artist_id: 1, album_id: 1, drive_id: 1, relative_path: "uno/uno.mp3")
10
+ Song.create!(id: 2, name: "song_dos", artist_id: 1, album_id: 1, drive_id: 1, relative_path: "uno/dos/dos.mp3")
11
+
12
+ Artist.create!(id: 1, name: "artist_uno")
13
+
14
+ Album.create!(id: 1, name: "album_uno")
15
+ end
16
+
17
+ it 'detect all the files in the subdirectories' do
18
+ r = t.execute "connect '#{test_folder}' => test"
19
+ r.files_detected.should eq 3
20
+ end
21
+
22
+ it 'import the files not imported before and update the rest' do
23
+ r = t.execute "connect '#{test_folder}' => test"
24
+ r.files_detected.should eq 3
25
+ r.files_updated.should eq 2
26
+ r.files_imported.should eq 1
27
+ end
28
+
29
+ context 'with only a literal parameter' do
30
+ it 'connect the named drive if exist' do
31
+ Drive.create!(name: "test", path: test_folder, connected: false)
32
+ Drive.find_by(name: 'test').should_not be_connected
33
+ r = t.execute "connect test"
34
+ Drive.find_by(name: 'test').should be_connected
35
+ end
36
+
37
+ it 'raise an error if drive not exists' do
38
+ r = t.execute("connect ghost")
39
+ r.message.should eq 'invalid name'
40
+ r.details.should eq 'the named drive doesnt exists'
41
+ end
42
+ end
43
+
44
+ context 'with a path and a literal' do
45
+ it 'create the drive if not exists' do
46
+ Drive.find_by(name: 'new').should be_nil
47
+ r = t.execute "connect '#{test_folder}' => new"
48
+ Drive.find_by(name: 'new').should_not be_nil
49
+ r.drive_updated.should be_false
50
+ end
51
+
52
+ it 'update the drive if exists' do
53
+ Drive.create!(name: "test", path: test_folder)
54
+ r = t.execute "connect '#{test_folder}' => test"
55
+ r.drive_updated.should be_true
56
+ end
57
+
58
+ it 'raise an error if path is invalid' do
59
+ r = t.execute('connect /invalid => ghost')
60
+ r.message.should eq 'invalid path'
61
+ r.details.should eq 'the directory is invalid'
62
+ end
63
+ end
64
+
65
+ describe 'with mp3 files' do
66
+ let(:t2){ TestClass.new }
67
+
68
+ before :each do
69
+ Drive.create!(name: "library", path: test_folder)
70
+ end
71
+
72
+ describe 'create information from file' do
73
+ it 'create the song' do
74
+ expect{ t2.execute "connect '#{test_folder}' => test" }.to change{ Song.all.count }.by(1)
75
+ end
76
+
77
+ it 'create the artist' do
78
+ expect{ t2.execute "connect '#{test_folder}' => test" }.to change{ Artist.all.count }.by(2) # una de las rolas no tiene artist
79
+ end
80
+
81
+ it 'create the album' do
82
+ expect{ t2.execute "connect '#{test_folder}' => test" }.to change{ Album.all.count }.by(2) # una de las rolas no tiene album
83
+ end
84
+
85
+ context 'already imported into library' do
86
+ before :each do
87
+ DatabaseCleaner.clean_with(:truncation)
88
+ r = t2.execute "connect '#{test_folder}/uno/dos/tres' => test"
89
+ r.files_imported.should eq 1
90
+ r.files_updated.should eq 0
91
+ @track = Song.all.first
92
+ end
93
+
94
+ it 'insert the correct song information' do
95
+ @track.name.should eq "Sing For Absolution"
96
+ @track.year.should eq 2003
97
+ @track.track.should eq 4
98
+ @track.duration.should eq 295
99
+ @track.relative_path.should eq "tres.mp3"
100
+ # dependencias
101
+ @track.artist_id.should eq 1
102
+ @track.album_id.should eq 1
103
+ @track.drive_id.should eq 1
104
+ end
105
+
106
+ it 'insert the correct artist information' do
107
+ @track.artist.name.should eq "Muse"
108
+ end
109
+
110
+ it 'insert the correct album information' do
111
+ @track.album.name.should eq "Absolution"
112
+ @track.album.artists.first.name.should eq "Muse"
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ include CultomePlayer::Objects
4
+
5
+ describe CultomePlayer::Player::Interface::Extended do
6
+ let(:t){ TestClass.new }
7
+
8
+ before :each do
9
+ Drive.create!(id: 1, name: 'test', path: '/patito', connected: true)
10
+ Song.create!(id: 1, name: "song_uno", artist_id: 1, album_id: 1, drive_id: 1, relative_path: "uno/uno.mp3")
11
+ Song.create!(id: 2, name: "song_dos", artist_id: 1, album_id: 2, drive_id: 1, relative_path: "uno/dos/dos.mp3")
12
+ Song.create!(id: 3, name: "song_tres", artist_id: 1, album_id: 2, drive_id: 1, relative_path: "uno/dos/tres/tres.mp3")
13
+ Song.create!(id: 4, name: "song_cuatro", artist_id: 2, album_id: 3, drive_id: 1, relative_path: "fake/cuatro.mp3")
14
+ Song.create!(id: 5, name: "song_cinco", artist_id: 3, album_id: 4, drive_id: 1, relative_path: "fake/cinco.mp3")
15
+
16
+ Artist.create!(id: 1, name: "artist_uno")
17
+ Artist.create!(id: 2, name: "artist_dos")
18
+ Artist.create!(id: 3, name: "artist_tres")
19
+ Artist.create!(id: 4, name: "artist_cuatro")
20
+
21
+ Album.create!(id: 1, name: "album_uno")
22
+ Album.create!(id: 2, name: "album_dos")
23
+ Album.create!(id: 3, name: "album_tres")
24
+ Album.create!(id: 4, name: "album_cuatro")
25
+ end
26
+
27
+ it 'return a Response object' do
28
+ t.execute('search a:artist_uno').should be_instance_of Response
29
+ end
30
+
31
+ it 'respond success when there are results' do
32
+ r = t.execute('search a:artist_uno')
33
+ r.should be_success
34
+ r.should respond_to :songs
35
+ end
36
+
37
+ it 'respond failure when there are not results' do
38
+ r = t.execute('search a:nothing')
39
+ r.should be_failure
40
+ r.should respond_to :message
41
+ end
42
+
43
+ context 'with criteria parameters' do
44
+ it 'different criterias create an AND filter' do
45
+ r = t.execute 'search a:artist_uno b:album_dos'
46
+ songs = r.send(r.response_type)
47
+ songs.should have(2).items
48
+ songs.each{|s| s.artist.name.should match /uno/ }
49
+ songs.each{|s| s.album.name.should match /dos/ }
50
+ end
51
+
52
+ it 'same criterias create an OR filter' do
53
+ r = t.execute 'search a:artist_dos a:artist_tres'
54
+ songs = r.send(r.response_type)
55
+ songs.should have(2).songs
56
+ songs.each{|s| s.artist.name.should match /(dos|tres)/ }
57
+ end
58
+ end
59
+
60
+ context 'with object parameters' do
61
+ it 'search using an object as criteria' do
62
+ r = t.execute 'search @artist'
63
+ songs = r.send(r.response_type)
64
+ songs.should have(3).item
65
+ songs.each{|s| s.artist.name.should eq t.current_artist.name }
66
+ end
67
+
68
+ it 'create and OR filter more than one object' do
69
+ t.execute('search @artist @album').should have(4).songs
70
+ end
71
+ end
72
+
73
+ context 'with literal parameters' do
74
+ it 'create an OR filter with the fields trackname, artist and album' do
75
+ t.execute('search song_cuatro song_cinco').should have(2).songs
76
+ t.execute('search song_uno song_dos').should have(2).songs
77
+ t.execute('search album_dos cinco').should have(3).songs
78
+ t.execute('search cinco').should have(1).songs
79
+ end
80
+ end
81
+
82
+ context 'with mixed parameters' do
83
+ it 'create an OR filter between each type' do
84
+ t.execute('search t:song_tres artist_tres @album').should have(3).songs
85
+ t.execute('search t:song_cuatro t:song_dos @album').should have(2).songs
86
+ t.execute('search song_dos song_uno').should have(2).songs
87
+ t.execute('search @artist song_tres').should have(3).songs
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe CultomePlayer::Player::Interface::Extended do
4
+ let(:t){ TestClass.new }
5
+ context 'when no playlist is active and no parameters' do
6
+ it 'shows a message saying so, and giving instructions to play' do
7
+ r = t.execute 'show'
8
+ r.message.should eq "Nothing to show yet. Try with 'play' first."
9
+ end
10
+ end
11
+
12
+ context 'with and active playlist and playback' do
13
+ before :each do
14
+ t.execute "connect '#{test_folder}' => test"
15
+ t.execute 'play'
16
+ end
17
+
18
+ it 'without parameters shows the current song' do
19
+ r = t.execute 'show'
20
+ r.message.should match /^:::: Song: .+? (\\ Artist: .+? \\ Album: .+? )?::::$/
21
+ r.message.should match /[\d]{2}:[\d]{2} \|[#_]+?\| [\d]{2}:[\d]{2}/
22
+ end
23
+
24
+ context 'with object parameter' do
25
+ it 'library' do
26
+ r = t.execute 'show @library'
27
+ r.list.should_not be_empty
28
+ end
29
+
30
+ it 'song' do
31
+ r = t.execute 'show @song'
32
+ r.message.should match /:::: Song: .+? (\\ Artist: .+? )?(\\ Album: .+? )?::::\n?/
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe CultomePlayer::Player::Interface::Extended do
4
+ let(:t){ TestClass.new }
5
+
6
+ context '#shuffle' do
7
+ it 'check shuffle status' do
8
+ r = t.execute('shuffle')
9
+ r.message.should eq "No shuffling"
10
+ r.shuffling.should be_false
11
+ end
12
+
13
+ it 'turn on the shuffle' do
14
+ t.should_not be_shuffling
15
+ t.execute('shuffle on')
16
+ t.should be_shuffling
17
+ end
18
+
19
+ it 'turn off shuffle' do
20
+ t.execute('shuffle on')
21
+ t.should be_shuffling
22
+ t.execute('shuffle off')
23
+ t.should_not be_shuffling
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,136 @@
1
+ require 'spec_helper'
2
+
3
+ describe CultomePlayer::Player::Interface::Extended do
4
+ let(:t){ TestClass.new }
5
+
6
+ it 'repeats a song from the beginning' do
7
+ t.should_receive(:send_to_player).with(/^jump 0$/)
8
+ t.repeat(nil)
9
+ end
10
+
11
+ describe 'search' do
12
+ it 'respond to description_search' do
13
+ t.should respond_to(:description_search)
14
+ end
15
+
16
+ it 'respond to usage_search' do
17
+ t.should respond_to(:usage_search)
18
+ end
19
+
20
+ it 'respond with Response object' do
21
+ t.execute("search on").should be_instance_of Response
22
+ end
23
+ end
24
+
25
+ describe 'show' do
26
+ it 'respond to description_show' do
27
+ t.should respond_to(:description_show)
28
+ end
29
+
30
+ it 'respond to usage_show' do
31
+ t.should respond_to(:usage_show)
32
+ end
33
+
34
+ it 'respond with Response object' do
35
+ t.execute("show").should be_instance_of Response
36
+ end
37
+ end
38
+
39
+ describe 'enqueue' do
40
+ it 'respond to description_enqueue' do
41
+ t.should respond_to(:description_enqueue)
42
+ end
43
+
44
+ it 'respond to usage_enqueue' do
45
+ t.should respond_to(:usage_enqueue)
46
+ end
47
+
48
+ it 'respond with Response object' do
49
+ t.execute("enqueue on").should be_instance_of Response
50
+ end
51
+ end
52
+
53
+ describe 'shuffle' do
54
+ it 'respond to description_shuffle' do
55
+ t.should respond_to(:description_shuffle)
56
+ end
57
+
58
+ it 'respond to usage_shuffle' do
59
+ t.should respond_to(:usage_shuffle)
60
+ end
61
+
62
+ it 'respond with Response object' do
63
+ t.execute("shuffle on").should be_instance_of Response
64
+ end
65
+ end
66
+
67
+ describe 'connect' do
68
+ it 'respond to description_connect' do
69
+ t.should respond_to(:description_connect)
70
+ end
71
+
72
+ it 'respond to usage_connect' do
73
+ t.should respond_to(:usage_connect)
74
+ end
75
+
76
+ it 'respond with Response object' do
77
+ t.execute("connect drive").should be_instance_of Response
78
+ end
79
+ end
80
+
81
+ describe 'disconnect' do
82
+ it 'respond to description_disconnect' do
83
+ t.should respond_to(:description_disconnect)
84
+ end
85
+
86
+ it 'respond to usage_disconnect' do
87
+ t.should respond_to(:usage_disconnect)
88
+ end
89
+
90
+ it 'respond with Response object' do
91
+ t.execute("disconnect drive").should be_instance_of Response
92
+ end
93
+ end
94
+
95
+ describe 'ff' do
96
+ it 'respond to description_ff' do
97
+ t.should respond_to(:description_ff)
98
+ end
99
+
100
+ it 'respond to usage_ff' do
101
+ t.should respond_to(:usage_ff)
102
+ end
103
+
104
+ it 'respond with Response object' do
105
+ t.execute("ff").should be_instance_of Response
106
+ end
107
+ end
108
+
109
+ describe 'fb' do
110
+ it 'respond to description_fb' do
111
+ t.should respond_to(:description_fb)
112
+ end
113
+
114
+ it 'respond to usage_fb' do
115
+ t.should respond_to(:usage_fb)
116
+ end
117
+
118
+ it 'respond with Response object' do
119
+ t.execute("fb").should be_instance_of Response
120
+ end
121
+ end
122
+
123
+ describe 'repeat' do
124
+ it 'respond to description_repeat' do
125
+ t.should respond_to(:description_repeat)
126
+ end
127
+
128
+ it 'respond to usage_repeat' do
129
+ t.should respond_to(:usage_repeat)
130
+ end
131
+
132
+ it 'respond with Response object' do
133
+ t.execute("repeat").should be_instance_of Response
134
+ end
135
+ end
136
+ end