yt 0.0.1 → 0.4.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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +24 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +10 -0
  5. data/.yardopts +1 -0
  6. data/Gemfile +9 -0
  7. data/Gemfile.lock +78 -0
  8. data/HISTORY.md +37 -0
  9. data/MIT-LICENSE +20 -0
  10. data/README.md +325 -0
  11. data/Rakefile +1 -0
  12. data/TODO.md +11 -0
  13. data/bin/yt +31 -0
  14. data/lib/yt.rb +2 -0
  15. data/lib/yt/actions/delete.rb +27 -0
  16. data/lib/yt/actions/delete_all.rb +28 -0
  17. data/lib/yt/actions/insert.rb +29 -0
  18. data/lib/yt/actions/list.rb +65 -0
  19. data/lib/yt/actions/update.rb +25 -0
  20. data/lib/yt/associations.rb +33 -0
  21. data/lib/yt/associations/annotations.rb +15 -0
  22. data/lib/yt/associations/channels.rb +20 -0
  23. data/lib/yt/associations/details_sets.rb +20 -0
  24. data/lib/yt/associations/playlist_items.rb +26 -0
  25. data/lib/yt/associations/playlists.rb +22 -0
  26. data/lib/yt/associations/ratings.rb +39 -0
  27. data/lib/yt/associations/snippets.rb +20 -0
  28. data/lib/yt/associations/statuses.rb +14 -0
  29. data/lib/yt/associations/subscriptions.rb +38 -0
  30. data/lib/yt/associations/user_infos.rb +21 -0
  31. data/lib/yt/associations/videos.rb +14 -0
  32. data/lib/yt/collections/annotations.rb +43 -0
  33. data/lib/yt/collections/base.rb +13 -0
  34. data/lib/yt/collections/channels.rb +32 -0
  35. data/lib/yt/collections/details_sets.rb +32 -0
  36. data/lib/yt/collections/playlist_items.rb +50 -0
  37. data/lib/yt/collections/playlists.rb +56 -0
  38. data/lib/yt/collections/ratings.rb +32 -0
  39. data/lib/yt/collections/snippets.rb +38 -0
  40. data/lib/yt/collections/subscriptions.rb +67 -0
  41. data/lib/yt/collections/user_infos.rb +41 -0
  42. data/lib/yt/collections/videos.rb +32 -0
  43. data/lib/yt/config.rb +55 -0
  44. data/lib/yt/models/account.rb +68 -0
  45. data/lib/yt/models/annotation.rb +137 -0
  46. data/lib/yt/models/base.rb +11 -0
  47. data/lib/yt/models/channel.rb +17 -0
  48. data/lib/yt/models/configuration.rb +29 -0
  49. data/lib/yt/models/description.rb +98 -0
  50. data/lib/yt/models/details_set.rb +31 -0
  51. data/lib/yt/models/playlist.rb +65 -0
  52. data/lib/yt/models/playlist_item.rb +42 -0
  53. data/lib/yt/models/rating.rb +28 -0
  54. data/lib/yt/models/snippet.rb +48 -0
  55. data/lib/yt/models/status.rb +26 -0
  56. data/lib/yt/models/subscription.rb +35 -0
  57. data/lib/yt/models/user_info.rb +66 -0
  58. data/lib/yt/models/video.rb +16 -0
  59. data/lib/yt/utils/request.rb +85 -0
  60. data/lib/yt/version.rb +3 -0
  61. data/spec/associations/device_auth/channels_spec.rb +10 -0
  62. data/spec/associations/device_auth/details_sets_spec.rb +19 -0
  63. data/spec/associations/device_auth/playlist_items_spec.rb +42 -0
  64. data/spec/associations/device_auth/playlists_spec.rb +42 -0
  65. data/spec/associations/device_auth/ratings_spec.rb +30 -0
  66. data/spec/associations/device_auth/snippets_spec.rb +30 -0
  67. data/spec/associations/device_auth/subscriptions_spec.rb +27 -0
  68. data/spec/associations/device_auth/user_infos_spec.rb +10 -0
  69. data/spec/associations/device_auth/videos_spec.rb +22 -0
  70. data/spec/associations/no_auth/annotations_spec.rb +15 -0
  71. data/spec/associations/server_auth/channels_spec.rb +2 -0
  72. data/spec/associations/server_auth/details_sets_spec.rb +18 -0
  73. data/spec/associations/server_auth/playlist_items_spec.rb +17 -0
  74. data/spec/associations/server_auth/playlists_spec.rb +17 -0
  75. data/spec/associations/server_auth/ratings_spec.rb +2 -0
  76. data/spec/associations/server_auth/snippets_spec.rb +28 -0
  77. data/spec/associations/server_auth/subscriptions_spec.rb +2 -0
  78. data/spec/associations/server_auth/user_infos_spec.rb +2 -0
  79. data/spec/associations/server_auth/videos_spec.rb +20 -0
  80. data/spec/collections/annotations_spec.rb +6 -0
  81. data/spec/collections/channels_spec.rb +6 -0
  82. data/spec/collections/details_sets_spec.rb +6 -0
  83. data/spec/collections/playlist_items_spec.rb +23 -0
  84. data/spec/collections/playlists_spec.rb +26 -0
  85. data/spec/collections/ratings_spec.rb +6 -0
  86. data/spec/collections/snippets_spec.rb +6 -0
  87. data/spec/collections/subscriptions_spec.rb +30 -0
  88. data/spec/collections/user_infos_spec.rb +6 -0
  89. data/spec/collections/videos_spec.rb +6 -0
  90. data/spec/models/annotation_spec.rb +131 -0
  91. data/spec/models/channel_spec.rb +13 -0
  92. data/spec/models/description_spec.rb +94 -0
  93. data/spec/models/details_set_spec.rb +23 -0
  94. data/spec/models/playlist_item_spec.rb +32 -0
  95. data/spec/models/playlist_spec.rb +52 -0
  96. data/spec/models/rating_spec.rb +13 -0
  97. data/spec/models/snippet_spec.rb +66 -0
  98. data/spec/models/status_spec.rb +42 -0
  99. data/spec/models/subscription_spec.rb +37 -0
  100. data/spec/models/user_info_spec.rb +69 -0
  101. data/spec/models/video_spec.rb +13 -0
  102. data/spec/spec_helper.rb +15 -0
  103. data/spec/support/device_app.rb +16 -0
  104. data/spec/support/server_app.rb +10 -0
  105. data/yt.gemspec +30 -0
  106. metadata +209 -17
@@ -0,0 +1,3 @@
1
+ module Yt
2
+ VERSION = '0.4.0'
3
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'yt/associations/channels'
3
+
4
+ describe Yt::Associations::Channels, scenario: :device_app do
5
+ let(:account) { Yt.configuration.account }
6
+
7
+ describe '#channel' do
8
+ it { require 'pry'; binding.pry; true; expect(account.channel).to be_a Yt::Channel }
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+ require 'yt/associations/details_sets'
3
+
4
+ describe Yt::Associations::DetailsSets, scenario: :device_app do
5
+ let(:account) { Yt.configuration.account }
6
+ let(:video) { Yt::Video.new id: 'fsdfsfsdMESycYJytkU', auth: account.auth }
7
+
8
+ describe '#details_set' do
9
+ context 'given an existing video' do
10
+ let(:video) { Yt::Video.new id: 'MESycYJytkU', auth: account }
11
+ it { expect(video.details_set).to be_a Yt::DetailsSet }
12
+ end
13
+
14
+ context 'given an unknown video' do
15
+ let(:video) { Yt::Video.new id: 'not-a-video-id', auth: account }
16
+ it { expect(video.details_set).to be_nil }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'yt/associations/playlist_items'
3
+
4
+ describe Yt::Associations::PlaylistItems, scenario: :device_app do
5
+ before :all do
6
+ account = Yt.configuration.account
7
+ @playlist = account.create_playlist title: "Yt Test Playlist Items"
8
+ end
9
+ after(:all) { @playlist.delete }
10
+
11
+ describe '#playlist_items' do
12
+ let(:video_id) { 'MESycYJytkU' }
13
+ before { @playlist.add_video video_id }
14
+ # TODO: after, delete playlist item
15
+
16
+ it { expect(@playlist.playlist_items.count).to be > 0 }
17
+ it { require 'pry'; binding.pry; true; expect(@playlist.playlist_items.first).to be_a Yt::PlaylistItem }
18
+ end
19
+
20
+ describe '#add_video' do
21
+ let(:video_id) { 'MESycYJytkU' }
22
+ # TODO: after, delete playlist item
23
+ it { expect(@playlist.add_video video_id).to be_a Yt::PlaylistItem }
24
+ it { expect{@playlist.add_video video_id}.to change{@playlist.playlist_items.count}.by(1) }
25
+ end
26
+
27
+ describe '#add_videos' do
28
+ let(:video_ids) { ['MESycYJytkU'] * 2 }
29
+ # TODO: after, delete playlist items
30
+ it { expect(@playlist.add_videos video_ids).to have(2).items }
31
+ it { expect{@playlist.add_videos video_ids}.to change{@playlist.playlist_items.count}.by(2) }
32
+ end
33
+
34
+
35
+ describe '#delete_playlist_items' do
36
+ let(:video_id) { 'MESycYJytkU' }
37
+ before { @playlist.add_video video_id }
38
+
39
+ it { expect(@playlist.delete_playlist_items).to eq [true] }
40
+ it { expect{@playlist.delete_playlist_items}.to change{@playlist.playlist_items.count}.by(-1) }
41
+ end
42
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'yt/associations/playlists'
3
+
4
+ describe Yt::Associations::Playlists, scenario: :device_app do
5
+ let(:account) { Yt.configuration.account }
6
+
7
+ describe '#playlists' do
8
+ let(:params) { {title: "Yt Test Playlists" } }
9
+ before { account.create_playlist params }
10
+ after { account.delete_playlists params }
11
+
12
+ it { expect(account.playlists.count).to be > 0 }
13
+ it { expect(account.playlists.first).to be_a Yt::Playlist }
14
+ end
15
+
16
+ describe '#create_playlist' do
17
+ let(:params) { {title: "Yt Test Create Playlist" } }
18
+ after { account.delete_playlists params }
19
+
20
+ it { expect(account.create_playlist params).to be_a Yt::Playlist }
21
+ it { expect{account.create_playlist params}.to change{account.playlists.count}.by(1) }
22
+ end
23
+
24
+ describe '#delete_playlists' do
25
+ let(:params) { {title: "Yt Test Delete Playlist #{rand}" } }
26
+ before { account.create_playlist params }
27
+
28
+ it { expect(account.delete_playlists params).to eq [true] }
29
+ it { expect{account.delete_playlists params}.to change{account.playlists.count}.by(-1) }
30
+ end
31
+
32
+ describe 'update a playlist' do
33
+ let(:old_title) { "Yt Test Before Update Playlist" }
34
+ let(:new_title) { "Yt Test After Update Playlist" }
35
+ before { @playlist = account.create_playlist title: old_title }
36
+ after { @playlist.delete }
37
+
38
+ it { expect(@playlist.update title: new_title).to eq true }
39
+ it { expect{@playlist.update title: new_title}.to change{@playlist.title} }
40
+ it { expect{@playlist.update privacy_status: 'unlisted'}.to change{@playlist.privacy_status} }
41
+ end
42
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ require 'yt/models/video'
3
+
4
+ describe Yt::Associations::Ratings, scenario: :device_app do
5
+ let(:account) { Yt.configuration.account }
6
+
7
+ describe '#rating' do
8
+ context 'given an existing video' do
9
+ let(:video) { Yt::Video.new id: 'MESycYJytkU', auth: account }
10
+
11
+ context 'that I like' do
12
+ before { video.like }
13
+ it { expect(video).to be_liked }
14
+ it { expect(video.dislike).to be_true }
15
+ end
16
+
17
+ context 'that I dislike' do
18
+ before { video.dislike }
19
+ it { expect(video).not_to be_liked }
20
+ it { expect(video.like).to be_true }
21
+ end
22
+
23
+ context 'that I am indifferent to' do
24
+ before { video.unlike }
25
+ it { expect(video).not_to be_liked }
26
+ it { expect(video.like).to be_true }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ require 'yt/associations/snippets'
3
+ require 'yt/models/channel'
4
+ require 'yt/models/video'
5
+
6
+ describe Yt::Associations::Snippets, scenario: :device_app do
7
+ let(:account) { Yt.configuration.account }
8
+
9
+ describe '#snippet' do
10
+ context 'given an existing video resource' do
11
+ let(:video) { Yt::Video.new id: 'MESycYJytkU', auth: account }
12
+ it { expect(video.snippet).to be_a Yt::Snippet }
13
+ end
14
+
15
+ context 'given an unknown video resource' do
16
+ let(:video) { Yt::Video.new id: 'not-a-video-id', auth: account }
17
+ it { expect(video.snippet).to be_nil }
18
+ end
19
+
20
+ context 'given an existing channel resource' do
21
+ let(:channel) { Yt::Channel.new id: 'UCxO1tY8h1AhOz0T4ENwmpow', auth: account }
22
+ it { expect(channel.snippet).to be_a Yt::Snippet }
23
+ end
24
+
25
+ context 'given an unknown channel resource' do
26
+ let(:channel) { Yt::Channel.new id: 'not-a-channel-id', auth: account }
27
+ it { expect(channel.snippet).to be_nil }
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+ require 'yt/models/channel'
3
+
4
+ # NOTE: This test is slow because we *must* wait for some seconds between
5
+ # subscribing and unsubscribing to a channel, otherwise YouTube will show
6
+ # wrong (cached) data, such as a user is subscribed when he is not.
7
+ describe Yt::Associations::Subscriptions, scenario: :device_app do
8
+ let(:account) { Yt.configuration.account }
9
+
10
+ describe '#subscription' do
11
+ context 'given an existing channel' do
12
+ let(:channel) { Yt::Channel.new id: 'UCxO1tY8h1AhOz0T4ENwmpow', auth: account }
13
+
14
+ context 'that I am not subscribed to' do
15
+ before { channel.unsubscribe }
16
+ it { expect(channel.subscribed?).to be_false }
17
+ it { expect(channel.subscribe!).to be_true }
18
+ end
19
+
20
+ context 'that I am subscribed to' do
21
+ before { channel.subscribe }
22
+ it { expect(channel.subscribed?).to be_true }
23
+ it { expect(channel.unsubscribe!).to be_true }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'yt/associations/user_infos'
3
+
4
+ describe Yt::Associations::UserInfos, scenario: :device_app do
5
+ let(:account) { Yt.configuration.account }
6
+
7
+ describe '#user_info' do
8
+ it { expect(account.user_info).to be_a Yt::UserInfo }
9
+ end
10
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ require 'yt/associations/videos'
3
+
4
+ describe Yt::Associations::Videos, scenario: :device_app do
5
+ let(:account) { Yt.configuration.account }
6
+
7
+ describe '#videos' do
8
+ context 'given a channel with videos' do
9
+ let(:channel) { Yt::Channel.new id: 'UCxO1tY8h1AhOz0T4ENwmpow', auth: account }
10
+ it { expect(channel.videos.count).to be > 0 }
11
+ it { expect(channel.videos.first).to be_a Yt::Video }
12
+ end
13
+
14
+ # NOTE: with an unknown channel id, YouTube behaves weirdly: if the
15
+ # wrong channel ID starts with "UC" then it returns 0 results, otherwise
16
+ # it ignores the channel filter and returns 100,000 results.
17
+ context 'given an unknown channel starting with UC' do
18
+ let(:channel) { Yt::Channel.new id: 'UC-not-a-channel', auth: account }
19
+ it { expect(channel.videos.count).to be 0 }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+ require 'yt/associations/annotations'
3
+ require 'yt/models/video'
4
+
5
+ describe Yt::Associations::Annotations do
6
+ subject(:annotations) { video.annotations }
7
+
8
+ describe '#annotations' do
9
+ context 'given an existing video with annotations' do
10
+ let(:video) { Yt::Video.new id: 'MESycYJytkU' }
11
+ it { expect(annotations.count).to be > 0 }
12
+ it { expect(annotations.first).to be_a Yt::Annotation }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,2 @@
1
+ # Channels cannot be tested with a server app because
2
+ # only authenticated clients can have channels
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+ require 'yt/associations/details_sets'
3
+
4
+ describe Yt::Associations::DetailsSets, scenario: :server_app do
5
+ let(:video) { Yt::Video.new id: 'fsdfsfsdMESycYJytkU' }
6
+
7
+ describe '#details_set' do
8
+ context 'given an existing video' do
9
+ let(:video) { Yt::Video.new id: 'MESycYJytkU' }
10
+ it { expect(video.details_set).to be_a Yt::DetailsSet }
11
+ end
12
+
13
+ context 'given an unknown video' do
14
+ let(:video) { Yt::Video.new id: 'not-a-video-id' }
15
+ it { expect(video.details_set).to be_nil }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+ require 'yt/models/playlist'
3
+ require 'yt/models/playlist_item'
4
+
5
+ describe Yt::Associations::PlaylistItems, scenario: :server_app do
6
+ describe '#playlist_items' do
7
+ subject(:playlist_items) { playlist.playlist_items }
8
+
9
+ context 'given an existing playlist with items' do
10
+ let(:playlist) { Yt::Playlist.new id: 'PLSWYkYzOrPMRCK6j0UgryI8E0NHhoVdRc' }
11
+ it { expect(playlist_items.first).to be_a Yt::PlaylistItem }
12
+ end
13
+ end
14
+
15
+ # Creating and deleting playlist items cannot be tested with a server
16
+ # app because only authenticated clients can perform those actions
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+ require 'yt/models/channel'
3
+ require 'yt/models/playlist'
4
+
5
+ describe Yt::Associations::Playlists, scenario: :server_app do
6
+ describe '#playlists' do
7
+ subject(:playlists) { channel.playlists }
8
+
9
+ context 'given an existing channel with playlists' do
10
+ let(:channel) { Yt::Channel.new id: 'UCxO1tY8h1AhOz0T4ENwmpow' }
11
+ it { expect(playlists.first).to be_a Yt::Playlist }
12
+ end
13
+ end
14
+
15
+ # Creating and deleting playlist cannot be tested with a server app because
16
+ # only authenticated clients can perform those actions
17
+ end
@@ -0,0 +1,2 @@
1
+ # Ratings cannot be tested with a server app because
2
+ # only authenticated clients can like and unlike videos
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ require 'yt/associations/snippets'
3
+ require 'yt/models/channel'
4
+ require 'yt/models/video'
5
+
6
+ describe Yt::Associations::Snippets, scenario: :server_app do
7
+ describe '#snippet' do
8
+ context 'given an existing video resource' do
9
+ let(:video) { Yt::Video.new id: 'MESycYJytkU' }
10
+ it { expect(video.snippet).to be_a Yt::Snippet }
11
+ end
12
+
13
+ context 'given an unknown video resource' do
14
+ let(:video) { Yt::Video.new id: 'not-a-video-id' }
15
+ it { expect(video.snippet).to be_nil }
16
+ end
17
+
18
+ context 'given an existing channel resource' do
19
+ let(:channel) { Yt::Channel.new id: 'UCxO1tY8h1AhOz0T4ENwmpow' }
20
+ it { expect(channel.snippet).to be_a Yt::Snippet }
21
+ end
22
+
23
+ context 'given an unknown channel resource' do
24
+ let(:channel) { Yt::Channel.new id: 'not-a-channel-id' }
25
+ it { expect(channel.snippet).to be_nil }
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,2 @@
1
+ # Subscriptions cannot be tested with a server app because
2
+ # only authenticated clients can subscribe and unsubscribe
@@ -0,0 +1,2 @@
1
+ # User infos cannot be tested with a server app because
2
+ # only authenticated clients can like and unlike videos
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'yt/associations/videos'
3
+
4
+ describe Yt::Associations::Videos, scenario: :server_app do
5
+ describe '#videos' do
6
+ context 'given a channel with videos' do
7
+ let(:channel) { Yt::Channel.new id: 'UCxO1tY8h1AhOz0T4ENwmpow' }
8
+ it { expect(channel.videos.count).to be > 0 }
9
+ it { expect(channel.videos.first).to be_a Yt::Video }
10
+ end
11
+
12
+ # NOTE: with an unknown channel id, YouTube behaves weirdly: if the
13
+ # wrong channel ID starts with "UC" then it returns 0 results, otherwise
14
+ # it ignores the channel filter and returns 100,000 results.
15
+ context 'given an unknown channel starting with UC' do
16
+ let(:channel) { Yt::Channel.new id: 'UC-not-a-channel' }
17
+ it { expect(channel.videos.count).to be 0 }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'yt/collections/annotations'
3
+
4
+ describe Yt::Collections::Annotations do
5
+ # Nothing to test
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'yt/collections/channels'
3
+
4
+ describe Yt::Collections::Channels do
5
+ # Nothing to test
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'yt/collections/details_sets'
3
+
4
+ describe Yt::Collections::DetailsSets do
5
+ # Nothing to test
6
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+ require 'yt/models/playlist'
3
+ require 'yt/collections/playlist_items'
4
+
5
+ describe Yt::Collections::PlaylistItems do
6
+ subject(:collection) { Yt::Collections::PlaylistItems.new playlist: playlist }
7
+ let(:playlist) { Yt::Playlist.new }
8
+
9
+ describe '#insert' do
10
+ let(:playlist_item) { Yt::PlaylistItem.new }
11
+ # TODO: separate stubs to show options translate into do_insert params
12
+ before { collection.stub(:do_insert).and_return playlist_item }
13
+
14
+ it { expect(collection.insert).to eq playlist_item }
15
+ end
16
+
17
+
18
+ describe '#delete_all' do
19
+ before { collection.stub(:do_delete_all).and_return [true] }
20
+
21
+ it { expect(collection.delete_all).to eq [true] }
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ require 'yt/collections/playlists'
3
+
4
+ describe Yt::Collections::Playlists do
5
+ subject(:collection) { Yt::Collections::Playlists.new }
6
+
7
+ describe '#insert' do
8
+ let(:playlist) { Yt::Playlist.new }
9
+ # TODO: separate stubs to show options translate into do_insert params
10
+ before { collection.stub(:do_insert).and_return playlist }
11
+
12
+ it { expect(collection.insert).to eq playlist }
13
+ end
14
+
15
+ describe '#delete_all' do
16
+ before { collection.stub(:do_delete_all).and_return [true] }
17
+
18
+ it { expect(collection.delete_all).to eq [true] }
19
+ end
20
+
21
+ describe '#delete_all' do
22
+ before { collection.stub(:do_delete_all).and_return [true] }
23
+
24
+ it { expect(collection.delete_all).to eq [true] }
25
+ end
26
+ end