kagu 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/kagu.gemspec +1 -2
- metadata +3 -23
- data/.gitignore +0 -7
- data/.rspec +0 -2
- data/Gemfile +0 -3
- data/Rakefile +0 -10
- data/spec/kagu/error_spec.rb +0 -40
- data/spec/kagu/finder_spec.rb +0 -314
- data/spec/kagu/library_spec.rb +0 -57
- data/spec/kagu/playlist_spec.rb +0 -74
- data/spec/kagu/playlists_spec.rb +0 -47
- data/spec/kagu/track_spec.rb +0 -303
- data/spec/kagu/tracks_spec.rb +0 -66
- data/spec/spec_helper.rb +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f2eb7f1dc5e7068bb9aac193c238d9692dabdbf
|
4
|
+
data.tar.gz: 8b6a3dbbdaaa42c74da8060d61b30be3843c594b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a22628b4870b924f88a3db00d910667a1d66286d2112c8d44f1bef072ef872c106134da2fa8d2e32ed8bfd40450b5ffefbb91f40a27250d22d4f9c7bf427a42
|
7
|
+
data.tar.gz: 3b3903a0ded1b34a2e35cd2509964e3779e0ce311cd731c8b9b3b2a360404fa3e0940e826728a94511ab3f2e239633a2e8f29baa2fb32344a0f5cfc97009b3c8
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.2.
|
1
|
+
1.2.1
|
data/kagu.gemspec
CHANGED
@@ -9,8 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.description = 'API to manage iTunes tracks and playlists'
|
10
10
|
s.license = 'MIT'
|
11
11
|
|
12
|
-
s.files = `git ls-files`.split("\n")
|
13
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
12
|
+
s.files = `git ls-files | grep -vE '^(spec/|test/|\\.|Gemfile|Rakefile)'`.split("\n")
|
14
13
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
15
14
|
s.require_paths = ['lib']
|
16
15
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kagu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexis Toulotte
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-05-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -136,12 +136,8 @@ executables: []
|
|
136
136
|
extensions: []
|
137
137
|
extra_rdoc_files: []
|
138
138
|
files:
|
139
|
-
- .gitignore
|
140
|
-
- .rspec
|
141
|
-
- Gemfile
|
142
139
|
- MIT-LICENSE
|
143
140
|
- README.mdown
|
144
|
-
- Rakefile
|
145
141
|
- VERSION
|
146
142
|
- kagu.gemspec
|
147
143
|
- lib/kagu.rb
|
@@ -153,14 +149,6 @@ files:
|
|
153
149
|
- lib/kagu/playlists.rb
|
154
150
|
- lib/kagu/track.rb
|
155
151
|
- lib/kagu/tracks.rb
|
156
|
-
- spec/kagu/error_spec.rb
|
157
|
-
- spec/kagu/finder_spec.rb
|
158
|
-
- spec/kagu/library_spec.rb
|
159
|
-
- spec/kagu/playlist_spec.rb
|
160
|
-
- spec/kagu/playlists_spec.rb
|
161
|
-
- spec/kagu/track_spec.rb
|
162
|
-
- spec/kagu/tracks_spec.rb
|
163
|
-
- spec/spec_helper.rb
|
164
152
|
homepage: https://github.com/alexistoulotte/kagu
|
165
153
|
licenses:
|
166
154
|
- MIT
|
@@ -185,12 +173,4 @@ rubygems_version: 2.0.14.1
|
|
185
173
|
signing_key:
|
186
174
|
specification_version: 4
|
187
175
|
summary: API for iTunes
|
188
|
-
test_files:
|
189
|
-
- spec/kagu/error_spec.rb
|
190
|
-
- spec/kagu/finder_spec.rb
|
191
|
-
- spec/kagu/library_spec.rb
|
192
|
-
- spec/kagu/playlist_spec.rb
|
193
|
-
- spec/kagu/playlists_spec.rb
|
194
|
-
- spec/kagu/track_spec.rb
|
195
|
-
- spec/kagu/tracks_spec.rb
|
196
|
-
- spec/spec_helper.rb
|
176
|
+
test_files: []
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
data/spec/kagu/error_spec.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Kagu::Error do
|
4
|
-
|
5
|
-
let(:error) { Kagu::Error.new('BAM!') }
|
6
|
-
let(:original) { StandardError.new('BIM!') }
|
7
|
-
|
8
|
-
describe '#message' do
|
9
|
-
|
10
|
-
it 'is message set at initialization' do
|
11
|
-
expect(error.message).to eq('BAM!')
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'message is squished' do
|
15
|
-
expect(Kagu::Error.new(" hello \n world").message).to eq('hello world')
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'default one if blank' do
|
19
|
-
expect(Kagu::Error.new(" ").message).to eq('Kagu::Error')
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
describe '#original' do
|
25
|
-
|
26
|
-
it 'is nil by default' do
|
27
|
-
expect(error.original).to be_nil
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'is exception given at initialization' do
|
31
|
-
expect(Kagu::Error.new(original).original).to be(original)
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'sets message from original' do
|
35
|
-
expect(Kagu::Error.new(original).message).to eq('BIM!')
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
data/spec/kagu/finder_spec.rb
DELETED
@@ -1,314 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Kagu::Finder do
|
4
|
-
|
5
|
-
let(:finder) { Kagu::Finder.new(library) }
|
6
|
-
let(:library) { Kagu::Library.new }
|
7
|
-
|
8
|
-
describe '.replace' do
|
9
|
-
|
10
|
-
it 'replace given value with replacements' do
|
11
|
-
expect(Kagu::Finder.replace('Hello World!', 'World' => 'John', 'Hello' => 'Bye')).to eq('Bye John!')
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'is case sensitive' do
|
15
|
-
expect(Kagu::Finder.replace('Hello World!', 'world' => 'John', 'Hello' => 'Bye')).to eq('Bye World!')
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'replace given value with some regexp' do
|
19
|
-
expect(Kagu::Finder.replace('Hello World!', 'World' => 'John', /l+/ => 'i')).to eq('Heio John!')
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'returns nil if blank' do
|
23
|
-
expect(Kagu::Finder.replace(' ', 'world' => 'John', 'Hello' => 'Bye')).to be_nil
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'accepts arrays as replacements' do
|
27
|
-
expect(Kagu::Finder.replace('Hello World!', [['World', 'John'], ['Hello', 'Bye']])).to eq('Bye John!')
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
describe '.transliterate' do
|
33
|
-
|
34
|
-
it 'removes accents' do
|
35
|
-
expect(Kagu::Finder.transliterate('éàlôrs')).to eq('ealors')
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'removes consecutive white spaces' do
|
39
|
-
expect(Kagu::Finder.transliterate(" hello \t world\n ")).to eq('hello world')
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'converts value to lower case' do
|
43
|
-
expect(Kagu::Finder.transliterate('Hello World')).to eq('hello world')
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'removes nil if blank' do
|
47
|
-
expect(Kagu::Finder.transliterate(' ')).to be_nil
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
|
52
|
-
describe '#find' do
|
53
|
-
|
54
|
-
it 'returns some tracks' do
|
55
|
-
tracks = finder.find(artist: 'korn', title: 'blind')
|
56
|
-
expect(tracks).to be_an(Array)
|
57
|
-
expect(tracks.first).to be_a(Kagu::Track)
|
58
|
-
expect(tracks.first.title).to match(/blind/i)
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'returns nothing if artist is blank' do
|
62
|
-
expect(finder.find(title: 'blind')).to be_empty
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'returns nothing if title is blank' do
|
66
|
-
expect(finder.find(artist: 'korn')).to be_empty
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'returns nothing if artist match an artist and a track' do
|
70
|
-
expect(finder.find(artist: 'korn blind')).to be_empty
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'artist and title can be specified as string' do
|
74
|
-
expect(finder.find('artist' => 'KoRn', 'title' => 'Ball Tongue').first).to be_a(Kagu::Track)
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'returns an array of array of tracks if there is some replacements' do
|
78
|
-
finder.reload(replacements: { 'ball tongue' => 'blind' })
|
79
|
-
results = finder.find(artist: 'korn', title: 'blind')
|
80
|
-
expect(results.size).to eq(2)
|
81
|
-
expect(results.first).to be_an(Array)
|
82
|
-
expect(results.first.first.title).to match(/blind/i)
|
83
|
-
expect(results.second.first.title).to match(/ball tongue/i)
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'replacements are working with given attributes' do
|
87
|
-
finder.reload(replacements: { 'hello world' => 'blind' })
|
88
|
-
results = finder.find(artist: 'korn', title: 'hello world')
|
89
|
-
expect(results.size).to eq(1)
|
90
|
-
expect(results.first.first).to be_a(Kagu::Track)
|
91
|
-
expect(results.first.first.title).to match(/blind/i)
|
92
|
-
end
|
93
|
-
|
94
|
-
it 'put at first position the exact matches from given attributes' do
|
95
|
-
finder.reload(replacements: { 'ball tongue' => 'blind' })
|
96
|
-
results = finder.find(artist: 'korn', title: 'ball tongue')
|
97
|
-
expect(results.size).to eq(2)
|
98
|
-
|
99
|
-
expect(results.first).not_to be_empty
|
100
|
-
results.first.each do |track|
|
101
|
-
expect(track.title).to match(/ball tongue/i)
|
102
|
-
end
|
103
|
-
|
104
|
-
expect(results.second).not_to be_empty
|
105
|
-
results.second.each do |track|
|
106
|
-
expect(track.title).to match(/blind/i)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
it 'does not include ignored tracks' do
|
111
|
-
expect {
|
112
|
-
finder.reload(ignored: 'korn blind')
|
113
|
-
}.to change { finder.find(artist: 'korn', title: 'blind').size }.to(0)
|
114
|
-
expect(finder.find(artist: 'korn', title: 'ball tongue')).not_to be_empty
|
115
|
-
end
|
116
|
-
|
117
|
-
it 'does not include ignored tracks for each digest' do
|
118
|
-
finder.reload(replacements: { 'blind' => 'foo' })
|
119
|
-
expect {
|
120
|
-
finder.reload(ignored: 'korn foo', replacements: { 'blind' => 'foo' })
|
121
|
-
}.to change { finder.find(artist: 'korn', title: 'blind').size }.to(0)
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'finds for some tracks with replacements as regexp' do
|
125
|
-
finder.reload(replacements: { /subsonik (\d+)/ => "subsonik podcast \\1" })
|
126
|
-
results = finder.find(artist: 'subsonik', title: '002')
|
127
|
-
expect(results.size).to eq(1)
|
128
|
-
expect(results.first.first.title).to match(/podcast 002/i)
|
129
|
-
end
|
130
|
-
|
131
|
-
it 'does not fails if it does not match last replacements' do
|
132
|
-
finder.reload(replacements: [{ /subsonik (\d+)/ => "subsonik podcast \\1" }, { /\s+/ => '' }])
|
133
|
-
results = finder.find(artist: 'subsonik', title: '002')
|
134
|
-
expect(results.size).to eq(1)
|
135
|
-
expect(results.first.first.title).to match(/podcast 002/i)
|
136
|
-
end
|
137
|
-
|
138
|
-
end
|
139
|
-
|
140
|
-
describe '#ignored' do
|
141
|
-
|
142
|
-
it 'can be set as an array of string' do
|
143
|
-
expect {
|
144
|
-
finder.reload(ignored: ['test', 'foo'])
|
145
|
-
}.to change { finder.ignored }.from([]).to(['test', 'foo'])
|
146
|
-
end
|
147
|
-
|
148
|
-
it 'can be set as a simple string' do
|
149
|
-
expect {
|
150
|
-
finder.reload(ignored: 'test')
|
151
|
-
}.to change { finder.ignored }.from([]).to(['test'])
|
152
|
-
end
|
153
|
-
|
154
|
-
it 'is transliterated' do
|
155
|
-
expect {
|
156
|
-
finder.reload(ignored: ['testé HeLLo World', 'foo'])
|
157
|
-
}.to change { finder.ignored }.from([]).to(['teste hello world', 'foo'])
|
158
|
-
end
|
159
|
-
|
160
|
-
it 'can be set from a track' do
|
161
|
-
expect {
|
162
|
-
finder.reload(ignored: [finder.find(artist: 'KoRn', title: 'Blind').first])
|
163
|
-
}.to change { finder.ignored }.from([]).to(['korn blind'])
|
164
|
-
end
|
165
|
-
|
166
|
-
it 'can be set from an hash (as string keys)' do
|
167
|
-
expect {
|
168
|
-
finder.reload(ignored: { 'artist' => 'KoRn', 'title' => 'Blind' })
|
169
|
-
}.to change { finder.ignored }.from([]).to(['korn blind'])
|
170
|
-
end
|
171
|
-
|
172
|
-
it 'can be set from an hash (with symbol keys)' do
|
173
|
-
expect {
|
174
|
-
finder.reload(ignored: { artist: 'KoRn', title: 'Blind' })
|
175
|
-
}.to change { finder.ignored }.from([]).to(['korn blind'])
|
176
|
-
end
|
177
|
-
|
178
|
-
it 'removes duplicates' do
|
179
|
-
expect {
|
180
|
-
finder.reload(ignored: ['test', 'Foo ', 'foo', 'TEST'])
|
181
|
-
}.to change { finder.ignored }.from([]).to(['test', 'foo'])
|
182
|
-
end
|
183
|
-
|
184
|
-
end
|
185
|
-
|
186
|
-
describe '#ignored?' do
|
187
|
-
|
188
|
-
it 'is false if nil is given' do
|
189
|
-
expect(finder.ignored?(nil)).to be(false)
|
190
|
-
end
|
191
|
-
|
192
|
-
it 'is true if at least one digest is ignored' do
|
193
|
-
finder.reload(replacements: { 'hello' => 'world' }, ignored: 'korn world')
|
194
|
-
expect(finder.ignored?(double(artist: 'korn', title: 'blind'))).to be(false)
|
195
|
-
expect(finder.ignored?(double(artist: 'korn', title: 'hello'))).to be(true)
|
196
|
-
expect(finder.ignored?(double(artist: 'korn', title: 'world'))).to be(true)
|
197
|
-
expect(finder.ignored?(double(artist: 'korn', title: 'hellow'))).to be(false)
|
198
|
-
end
|
199
|
-
|
200
|
-
end
|
201
|
-
|
202
|
-
describe '#library' do
|
203
|
-
|
204
|
-
it 'is library given at initialization' do
|
205
|
-
expect(finder.library).to be(library)
|
206
|
-
end
|
207
|
-
|
208
|
-
it 'raise an error if library is nil' do
|
209
|
-
expect {
|
210
|
-
Kagu::Finder.new(nil)
|
211
|
-
}.to raise_error(ArgumentError, 'Kagu::Finder#library must be a library, nil given')
|
212
|
-
end
|
213
|
-
|
214
|
-
end
|
215
|
-
|
216
|
-
describe '#reload' do
|
217
|
-
|
218
|
-
it 'sets replacements' do
|
219
|
-
expect {
|
220
|
-
finder.reload(replacements: { 'foo' => 'bar' })
|
221
|
-
}.to change { finder.replacements }.from([]).to([{ 'foo' => 'bar' }])
|
222
|
-
end
|
223
|
-
|
224
|
-
it 'removes replacements' do
|
225
|
-
finder.reload(replacements: { 'foo' => 'bar' })
|
226
|
-
expect {
|
227
|
-
finder.reload
|
228
|
-
}.to change { finder.replacements }.to([])
|
229
|
-
end
|
230
|
-
|
231
|
-
it 'removes ignored' do
|
232
|
-
finder.reload(ignored: 'foo')
|
233
|
-
expect {
|
234
|
-
finder.reload
|
235
|
-
}.to change { finder.ignored }.to([])
|
236
|
-
end
|
237
|
-
|
238
|
-
it 'returns finder' do
|
239
|
-
expect(finder.reload).to be(finder)
|
240
|
-
end
|
241
|
-
|
242
|
-
it 'reload tracks' do
|
243
|
-
expect {
|
244
|
-
finder.reload(replacements: { /\./ => '' })
|
245
|
-
}.to change { finder.find(artist: 'korn', title: 'adidas').present? }.from(false).to(true)
|
246
|
-
end
|
247
|
-
|
248
|
-
it 'returns finder' do
|
249
|
-
expect(finder.reload).to be(finder)
|
250
|
-
end
|
251
|
-
|
252
|
-
end
|
253
|
-
|
254
|
-
describe '#reload!' do
|
255
|
-
|
256
|
-
it 'invokes reload' do
|
257
|
-
expect(finder).to receive(:reload).with('foo' => 'bar')
|
258
|
-
finder.reload!('foo' => 'bar')
|
259
|
-
end
|
260
|
-
|
261
|
-
it 'removes tracks cache' do
|
262
|
-
finder.find(artist: 'korn', title: 'blind')
|
263
|
-
expect {
|
264
|
-
finder.reload!
|
265
|
-
}.to change { finder.instance_variable_get(:@tracks) }.to(nil)
|
266
|
-
end
|
267
|
-
|
268
|
-
it 'returns finder' do
|
269
|
-
expect(finder.reload!).to be(finder)
|
270
|
-
end
|
271
|
-
|
272
|
-
end
|
273
|
-
|
274
|
-
describe '#replacements' do
|
275
|
-
|
276
|
-
it 'can be ommited' do
|
277
|
-
expect(finder.reload.replacements).to eq([])
|
278
|
-
end
|
279
|
-
|
280
|
-
it 'can be specified as regexp' do
|
281
|
-
expect(finder.reload(replacements: { /bar/ => 'foo' }).replacements).to eq([/bar/ => 'foo'])
|
282
|
-
end
|
283
|
-
|
284
|
-
it 'can be specified with a string as key' do
|
285
|
-
expect(finder.reload('replacements' => { 'foo' => 'bar' }).replacements).to eq([{ 'foo' => 'bar' }])
|
286
|
-
end
|
287
|
-
|
288
|
-
it 'can be specified as hash' do
|
289
|
-
expect(finder.reload(replacements: { 'foo' => 'bar' }).replacements).to eq([{ 'foo' => 'bar' }])
|
290
|
-
end
|
291
|
-
|
292
|
-
it 'can be specified as array of hashes' do
|
293
|
-
expect(finder.reload(replacements: [{ 'foo' => 'bar' }, { 'titi' => 'toto' }]).replacements).to eq([{ 'foo' => 'bar' }, { 'titi' => 'toto' }])
|
294
|
-
end
|
295
|
-
|
296
|
-
it 'can be specified as array of array' do
|
297
|
-
expect(finder.reload(replacements: [['foo', 'bar' ], ['titi' => 'toto']]).replacements).to eq([['foo', 'bar' ], ['titi' => 'toto']])
|
298
|
-
end
|
299
|
-
|
300
|
-
it 'raise an error if a string is given' do
|
301
|
-
expect {
|
302
|
-
finder.reload(replacements: 'foo')
|
303
|
-
}.to raise_error('Replacements must be an array or a hash, "foo" given')
|
304
|
-
end
|
305
|
-
|
306
|
-
it 'raise an error if it contains something else than an hash or array' do
|
307
|
-
expect {
|
308
|
-
finder.reload(replacements: [{ 'foo' => 'bar' }, 'titi'])
|
309
|
-
}.to raise_error('Replacements must contain only hashes or arrays')
|
310
|
-
end
|
311
|
-
|
312
|
-
end
|
313
|
-
|
314
|
-
end
|
data/spec/kagu/library_spec.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Kagu::Library do
|
4
|
-
|
5
|
-
let(:library) { Kagu::Library.new }
|
6
|
-
|
7
|
-
describe '#initialize' do
|
8
|
-
|
9
|
-
it 'is correct by default' do
|
10
|
-
expect(library.path).to eq("#{ENV['HOME']}/Music/iTunes/iTunes Music Library.xml")
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'raise an error if directory' do
|
14
|
-
expect {
|
15
|
-
Kagu::Library.new('/tmp')
|
16
|
-
}.to raise_error(Kagu::Error, 'No such file: "/tmp"')
|
17
|
-
end
|
18
|
-
|
19
|
-
it "raise an error if file can't be found" do
|
20
|
-
expect {
|
21
|
-
Kagu::Library.new('/tmp/bar.foo.baz')
|
22
|
-
}.to raise_error(Kagu::Error, 'No such file: "/tmp/bar.foo.baz"')
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
describe '#finder' do
|
28
|
-
|
29
|
-
it 'returns a Kagu::Finder instance' do
|
30
|
-
expect(library.finder).to be_a(Kagu::Finder)
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'options can be specified' do
|
34
|
-
expect(library.finder(replacements: { 'foo' => 'bar' }).replacements).to eq([{ 'foo' => 'bar' }])
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
describe '#playlists' do
|
40
|
-
|
41
|
-
it 'returns a Playlists object' do
|
42
|
-
expect(library.playlists).to be_a(Kagu::Playlists)
|
43
|
-
expect(library.playlists.library).to be(library)
|
44
|
-
end
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
describe '#tracks' do
|
49
|
-
|
50
|
-
it 'returns a Tracks object' do
|
51
|
-
expect(library.tracks).to be_a(Kagu::Tracks)
|
52
|
-
expect(library.tracks.library).to be(library)
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
data/spec/kagu/playlist_spec.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Kagu::Playlist do
|
4
|
-
|
5
|
-
let(:library) { Kagu::Library.new }
|
6
|
-
let(:playlist) { Kagu::Playlist.new(name: 'Best tracks', tracks: tracks) }
|
7
|
-
let(:tracks) { library.tracks.take(15) }
|
8
|
-
|
9
|
-
describe '#each' do
|
10
|
-
|
11
|
-
it 'is delegated to tracks' do
|
12
|
-
track = nil
|
13
|
-
playlist.each do |t|
|
14
|
-
track = t
|
15
|
-
break
|
16
|
-
end
|
17
|
-
expect(track).to be_a(Kagu::Track)
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
describe '#itunes_name=' do
|
23
|
-
|
24
|
-
it 'set name and convert entities' do
|
25
|
-
expect {
|
26
|
-
playlist.send(:itunes_name=, 'Hello & World')
|
27
|
-
}.to change { playlist.name }.from('Best tracks').to('Hello & World')
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
describe '#name' do
|
33
|
-
|
34
|
-
it 'is set at initialization' do
|
35
|
-
expect(Kagu::Playlist.new(name: 'Best tracks').name).to eq('Best tracks')
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'is squished' do
|
39
|
-
expect(Kagu::Playlist.new(name: "Best \t tracks\n").name).to eq('Best tracks')
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'is mandatory' do
|
43
|
-
expect {
|
44
|
-
Kagu::Playlist.new(name: ' ')
|
45
|
-
}.to raise_error(Kagu::Error, 'Kagu::Playlist#name is mandatory')
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
|
50
|
-
describe '#to_s' do
|
51
|
-
|
52
|
-
it 'is name' do
|
53
|
-
expect(Kagu::Playlist.new(name: 'Best tracks').to_s).to eq('Best tracks')
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
describe '#tracks' do
|
59
|
-
|
60
|
-
it 'is an empty array by default' do
|
61
|
-
expect(Kagu::Playlist.new(name: 'Test').tracks).to eq([])
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'is tracks given at initialization' do
|
65
|
-
expect(Kagu::Playlist.new(name: 'Test', tracks: tracks).tracks).to eq(tracks)
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'removes invalid tracks' do
|
69
|
-
expect(Kagu::Playlist.new(name: 'Test', tracks: ['bar', [tracks.first], 'foo']).tracks).to eq([tracks.first])
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
data/spec/kagu/playlists_spec.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Kagu::Playlists do
|
4
|
-
|
5
|
-
let(:library) { Kagu::Library.new }
|
6
|
-
let(:playlists) { Kagu::Playlists.new(library) }
|
7
|
-
|
8
|
-
describe '#each' do
|
9
|
-
|
10
|
-
it 'playlists must contains at least 1 song and a name' do
|
11
|
-
expect(playlists.count).to be > 5
|
12
|
-
playlists.each do |playlist|
|
13
|
-
expect(playlist.name).not_to eq('Bibliothèque')
|
14
|
-
expect(playlist.name).not_to match(/\&#\d+;/)
|
15
|
-
expect(playlist.name).to be_a(String)
|
16
|
-
expect(playlist.name).to be_present
|
17
|
-
expect(playlist.tracks.size).to be > 0
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'does not fails if block is not given' do
|
22
|
-
expect {
|
23
|
-
expect(playlists.each).to be_nil
|
24
|
-
}.not_to raise_error
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'returns nil' do
|
28
|
-
expect(playlists.each {}).to be_nil
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
describe '#library' do
|
34
|
-
|
35
|
-
it 'is library given at initialization' do
|
36
|
-
expect(playlists.library).to be(library)
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'raise an error if library is nil' do
|
40
|
-
expect {
|
41
|
-
Kagu::Playlists.new(nil)
|
42
|
-
}.to raise_error(ArgumentError, 'Kagu::Playlists#library must be a library, nil given')
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
data/spec/kagu/track_spec.rb
DELETED
@@ -1,303 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Kagu::Track do
|
4
|
-
|
5
|
-
let(:attributes) { { added_at: track.added_at, album: track.album, artist: track.artist, id: track.id, length: track.length, path: track.path, title: track.title } }
|
6
|
-
let(:library) { Kagu::Library.new }
|
7
|
-
let(:track) { library.tracks.first }
|
8
|
-
|
9
|
-
describe '#==' do
|
10
|
-
|
11
|
-
let(:other) { track.dup }
|
12
|
-
|
13
|
-
it 'is false if not a track' do
|
14
|
-
expect(track == 'foo').to be(false)
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'is false if artist differs' do
|
18
|
-
expect {
|
19
|
-
allow(other).to receive(:artist).and_return('Foo')
|
20
|
-
}.to change { track == other }.from(true).to(false)
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'is false if title differs' do
|
24
|
-
expect {
|
25
|
-
allow(other).to receive(:title).and_return('Bar')
|
26
|
-
}.to change { track == other }.from(true).to(false)
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'is false if length differs' do
|
30
|
-
expect {
|
31
|
-
allow(other).to receive(:length).and_return(track.length - 5)
|
32
|
-
}.to change { track == other }.from(true).to(false)
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'is true if length differs just a little' do
|
36
|
-
expect {
|
37
|
-
allow(other).to receive(:length).and_return(track.length - 2)
|
38
|
-
}.not_to change { track == other }
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'is true if album differs' do
|
42
|
-
expect {
|
43
|
-
allow(other).to receive(:album).and_return('Baz')
|
44
|
-
}.not_to change { track == other }
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
describe '#<=>' do
|
50
|
-
|
51
|
-
let(:other) { track.dup }
|
52
|
-
|
53
|
-
it 'compares tracks lengths' do
|
54
|
-
expect {
|
55
|
-
allow(other).to receive(:added_at).and_return(1.day.from_now)
|
56
|
-
}.to change { track <=> other }.from(0).to(-1)
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'is nil if added_at is nil' do
|
60
|
-
allow(track).to receive(:added_at).and_return(nil)
|
61
|
-
expect(track <=> other).to be_nil
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'is nil if other track added_at is nil' do
|
65
|
-
allow(other).to receive(:added_at).and_return(nil)
|
66
|
-
expect(track <=> other).to be_nil
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'is nil if other is not a track' do
|
70
|
-
expect(track <=> '').to be_nil
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
describe '#added_at' do
|
76
|
-
|
77
|
-
it 'returns a time' do
|
78
|
-
expect(track.added_at).to be_a(Time)
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'return a time in utc' do
|
82
|
-
expect(track.added_at.zone).to eq('UTC')
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'raise an error if not specified' do
|
86
|
-
expect {
|
87
|
-
Kagu::Track.new(attributes.except(:added_at))
|
88
|
-
}.to raise_error(Kagu::Error, 'Kagu::Track#added_at is mandatory')
|
89
|
-
end
|
90
|
-
|
91
|
-
end
|
92
|
-
|
93
|
-
describe '#album' do
|
94
|
-
|
95
|
-
it 'is is squished' do
|
96
|
-
track.send(:album=, " Life Is \r Peachy \n")
|
97
|
-
expect(track.album).to eq('Life Is Peachy')
|
98
|
-
end
|
99
|
-
|
100
|
-
end
|
101
|
-
|
102
|
-
describe '#artist' do
|
103
|
-
|
104
|
-
it 'is is squished' do
|
105
|
-
track.send(:artist=, " Benny \r Page \n")
|
106
|
-
expect(track.artist).to eq('Benny Page')
|
107
|
-
end
|
108
|
-
|
109
|
-
end
|
110
|
-
|
111
|
-
describe '#bpm' do
|
112
|
-
|
113
|
-
it 'is nil if invalid' do
|
114
|
-
track.send(:bpm=, "42a")
|
115
|
-
expect(track.bpm).to be_nil
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'is an integer' do
|
119
|
-
track.send(:bpm=, '143')
|
120
|
-
expect(track.bpm).to be(143)
|
121
|
-
end
|
122
|
-
|
123
|
-
end
|
124
|
-
|
125
|
-
describe '#eql?' do
|
126
|
-
|
127
|
-
it 'is true for same object' do
|
128
|
-
expect(track.eql?(track)).to be(true)
|
129
|
-
end
|
130
|
-
|
131
|
-
it 'is true if == returns true' do
|
132
|
-
other = track.dup
|
133
|
-
expect {
|
134
|
-
allow(track).to receive(:==).and_return(false)
|
135
|
-
}.to change { track.eql?(other) }.from(true).to(false)
|
136
|
-
end
|
137
|
-
|
138
|
-
end
|
139
|
-
|
140
|
-
describe '#exists?' do
|
141
|
-
|
142
|
-
it 'is true if path is a file' do
|
143
|
-
expect {
|
144
|
-
allow(track).to receive(:path).and_return('/tmp/foo.mp3')
|
145
|
-
}.to change { track.exists? }.from(true).to(false)
|
146
|
-
end
|
147
|
-
|
148
|
-
it 'is false if path is a directory' do
|
149
|
-
expect {
|
150
|
-
allow(track).to receive(:path).and_return('/tmp')
|
151
|
-
}.to change { track.exists? }.from(true).to(false)
|
152
|
-
end
|
153
|
-
|
154
|
-
end
|
155
|
-
|
156
|
-
describe '#genre' do
|
157
|
-
|
158
|
-
it 'is correct' do
|
159
|
-
expect(track.genre).to be_a(String)
|
160
|
-
expect(track.genre).to be_present
|
161
|
-
end
|
162
|
-
|
163
|
-
end
|
164
|
-
|
165
|
-
describe '#id' do
|
166
|
-
|
167
|
-
it 'is correct' do
|
168
|
-
expect(track.id).to be_an(Integer)
|
169
|
-
expect(track.id).to be > 0
|
170
|
-
end
|
171
|
-
|
172
|
-
it 'raise an error if not specified' do
|
173
|
-
expect {
|
174
|
-
Kagu::Track.new(attributes.except(:id))
|
175
|
-
}.to raise_error(Kagu::Error, 'Kagu::Track#id is mandatory')
|
176
|
-
end
|
177
|
-
|
178
|
-
end
|
179
|
-
|
180
|
-
describe '#itunes_name=' do
|
181
|
-
|
182
|
-
it 'sets title with entities decoded' do
|
183
|
-
expect {
|
184
|
-
track.send(:itunes_name=, 'Racing & Green')
|
185
|
-
}.to change { track.title }.to('Racing & Green')
|
186
|
-
end
|
187
|
-
|
188
|
-
end
|
189
|
-
|
190
|
-
describe '#length' do
|
191
|
-
|
192
|
-
it 'is correct' do
|
193
|
-
expect(track.length).to be_an(Integer)
|
194
|
-
expect(track.length).to be > 0
|
195
|
-
end
|
196
|
-
|
197
|
-
it 'raise an error if not specified' do
|
198
|
-
expect {
|
199
|
-
Kagu::Track.new(attributes.except(:length))
|
200
|
-
}.to raise_error(Kagu::Error, 'Kagu::Track#length is mandatory')
|
201
|
-
end
|
202
|
-
|
203
|
-
end
|
204
|
-
|
205
|
-
describe '#path' do
|
206
|
-
|
207
|
-
it 'is correct' do
|
208
|
-
expect(track.path).to be_a(String)
|
209
|
-
expect(File.file?(track.path)).to be(true)
|
210
|
-
end
|
211
|
-
|
212
|
-
it 'raise an error if not specified' do
|
213
|
-
expect {
|
214
|
-
Kagu::Track.new(attributes.except(:path))
|
215
|
-
}.to raise_error(Kagu::Error, 'Kagu::Track#path is mandatory')
|
216
|
-
end
|
217
|
-
|
218
|
-
it 'does not raise an error if not found' do
|
219
|
-
expect {
|
220
|
-
Kagu::Track.new(attributes.merge(path: '/tmp/bar.mp3'))
|
221
|
-
}.not_to raise_error
|
222
|
-
end
|
223
|
-
|
224
|
-
it 'logs an error if not exist' do
|
225
|
-
expect(Kagu.logger).to receive(:error)
|
226
|
-
Kagu::Track.new(attributes.merge(path: '/tmp/bar.mp3'))
|
227
|
-
end
|
228
|
-
|
229
|
-
it 'raise an error if exists but not a file' do
|
230
|
-
expect {
|
231
|
-
Kagu::Track.new(attributes.merge(path: '/tmp'))
|
232
|
-
}.to raise_error(Kagu::Error, 'No such file: "/tmp"')
|
233
|
-
end
|
234
|
-
|
235
|
-
end
|
236
|
-
|
237
|
-
describe '#relative_path' do
|
238
|
-
|
239
|
-
it 'is correct' do
|
240
|
-
expect(track.relative_path(ENV['HOME'])).to eq(track.path.gsub("#{ENV['HOME']}/", ''))
|
241
|
-
end
|
242
|
-
|
243
|
-
it 'is full path if not starting with given path' do
|
244
|
-
expect(track.relative_path('/Users/john')).to eq(track.path)
|
245
|
-
end
|
246
|
-
|
247
|
-
end
|
248
|
-
|
249
|
-
describe '#title' do
|
250
|
-
|
251
|
-
it 'is is squished' do
|
252
|
-
track.send(:title=, " Racing \r Green \n")
|
253
|
-
expect(track.title).to eq('Racing Green')
|
254
|
-
end
|
255
|
-
|
256
|
-
end
|
257
|
-
|
258
|
-
describe '#to_s' do
|
259
|
-
|
260
|
-
it 'is "artist - title"' do
|
261
|
-
expect(track.to_s).to eq("#{track.artist} - #{track.title}")
|
262
|
-
end
|
263
|
-
|
264
|
-
end
|
265
|
-
|
266
|
-
describe '#year' do
|
267
|
-
|
268
|
-
it 'is an integer' do
|
269
|
-
expect(track.year).to be_an(Integer)
|
270
|
-
end
|
271
|
-
|
272
|
-
it 'is correct' do
|
273
|
-
expect(track.year.to_s).to match(/\A\d{4}\z/)
|
274
|
-
end
|
275
|
-
|
276
|
-
it 'is nil if negative' do
|
277
|
-
track.send(:year=, -1)
|
278
|
-
expect(track.year).to be_nil
|
279
|
-
end
|
280
|
-
|
281
|
-
it 'is nil if invalid' do
|
282
|
-
track.send(:year=, 20434)
|
283
|
-
expect(track.year).to be_nil
|
284
|
-
end
|
285
|
-
|
286
|
-
it 'can be < 1000' do
|
287
|
-
track.send(:year=, 942)
|
288
|
-
expect(track.year).to be(942)
|
289
|
-
end
|
290
|
-
|
291
|
-
it 'can be set as string' do
|
292
|
-
track.send(:year=, '1984')
|
293
|
-
expect(track.year).to be(1984)
|
294
|
-
end
|
295
|
-
|
296
|
-
it 'is nil if string is invalid' do
|
297
|
-
track.send(:year=, '1984 ')
|
298
|
-
expect(track.year).to be_nil
|
299
|
-
end
|
300
|
-
|
301
|
-
end
|
302
|
-
|
303
|
-
end
|
data/spec/kagu/tracks_spec.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Kagu::Tracks do
|
4
|
-
|
5
|
-
let(:library) { Kagu::Library.new }
|
6
|
-
let(:tracks) { Kagu::Tracks.new(library) }
|
7
|
-
|
8
|
-
describe '#each' do
|
9
|
-
|
10
|
-
it 'most of tracks must be correct path must be a file' do
|
11
|
-
tracks.take(100).each do |track|
|
12
|
-
expect(File.file?(track.path)).to be(true)
|
13
|
-
expect(track).to be_a(Kagu::Track)
|
14
|
-
expect(track.added_at).to be_a(Time)
|
15
|
-
expect(track.album).to be_a(String)
|
16
|
-
expect(track.album).to be_present
|
17
|
-
expect(track.artist).to be_a(String)
|
18
|
-
expect(track.artist).to be_present
|
19
|
-
expect(track.exists?).to be(true)
|
20
|
-
expect(track.genre).to be_a(String)
|
21
|
-
expect(track.genre).to be_present
|
22
|
-
expect(track.id).to be_an(Integer)
|
23
|
-
expect(track.length).to be_an(Integer)
|
24
|
-
expect(track.path).not_to include('file://')
|
25
|
-
expect(track.path).to include('Music')
|
26
|
-
expect(track.title).to be_a(String)
|
27
|
-
expect(track.title).to be_present
|
28
|
-
expect(track.year).to be_an(Integer)
|
29
|
-
expect(track.year.to_s).to match(/\A\d{4}\z/)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'does not fails if block is not given' do
|
34
|
-
expect {
|
35
|
-
expect(tracks.each).to be_nil
|
36
|
-
}.not_to raise_error
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'returns nil' do
|
40
|
-
expect(tracks.each {}).to be_nil
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'all tracks must exists and path should not include UTF-8-MAC charset' do
|
44
|
-
library.tracks.each do |track|
|
45
|
-
expect(track.path).not_to include("\u{65}\u{301}")
|
46
|
-
expect(track.exists?).to be(true)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
|
52
|
-
describe '#library' do
|
53
|
-
|
54
|
-
it 'is library given at initialization' do
|
55
|
-
expect(tracks.library).to be(library)
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'raise an error if library is nil' do
|
59
|
-
expect {
|
60
|
-
Kagu::Tracks.new(nil)
|
61
|
-
}.to raise_error(ArgumentError, 'Kagu::Tracks#library must be a library, nil given')
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
end
|