audiothority 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+
6
+ module Audiothority
7
+ describe Society do
8
+ let :society do
9
+ described_class.new(location, fileutils)
10
+ end
11
+
12
+ let :location do
13
+ 'society'
14
+ end
15
+
16
+ let :fileutils do
17
+ double(:fileutils, move: 0)
18
+ end
19
+
20
+ describe '#transfer' do
21
+ it 'moves the enforced entity to society location' do
22
+ society.transfer('enforced')
23
+ expect(fileutils).to have_received(:move).with('enforced', Pathname.new('society'))
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+
6
+ module Audiothority
7
+ describe Tracker do
8
+ let :tracker do
9
+ described_class.new
10
+ end
11
+
12
+ let :violations do
13
+ [double(:violation)]
14
+ end
15
+
16
+ describe '#mark' do
17
+ it 'adds path and violations' do
18
+ tracker.mark('path', violations)
19
+ expect(tracker.suspects).to eq({'path' => violations})
20
+ end
21
+ end
22
+
23
+ describe '#suspects' do
24
+ it 'returns marked paths with violations' do
25
+ tracker.mark('path', violations)
26
+ expect(tracker.suspects).to eq({'path' => violations})
27
+ end
28
+
29
+ it 'freezes the returned suspects' do
30
+ expect(tracker.suspects).to be_frozen
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,134 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+
6
+ module Audiothority
7
+ module Validators
8
+ shared_examples_for 'an uniqueness validator' do
9
+ let :validator do
10
+ described_class.new
11
+ end
12
+
13
+ context 'when `field` is unique among given tags' do
14
+ let :tags do
15
+ 3.times.map { |i| OpenStruct.new(field => 'same') }
16
+ end
17
+
18
+ it 'returns a `valid` validation' do
19
+ expect(validator.validate(tags)).to be_valid
20
+ end
21
+ end
22
+
23
+ context 'when `field` is not unique among given tags' do
24
+ let :tags do
25
+ 3.times.map { |i| OpenStruct.new(field => i) }
26
+ end
27
+
28
+ it 'returns an `invalid` validation' do
29
+ expect(validator.validate(tags)).to be_invalid
30
+ end
31
+
32
+ it 'indicates which field it is concerned about' do
33
+ violation = validator.validate(tags)
34
+ expect(violation.field).to eq(field)
35
+ end
36
+
37
+ it 'reports that there are multiple values for field' do
38
+ violation = validator.validate(tags)
39
+ expect(violation.reason).to eq(:multiple)
40
+ end
41
+ end
42
+
43
+ context 'when `field` is not present among given tags' do
44
+ let :tags do
45
+ 3.times.map { |i| OpenStruct.new(field => nil) }
46
+ end
47
+
48
+ it 'returns an `invalid` validation' do
49
+ expect(validator.validate(tags)).to be_invalid
50
+ end
51
+
52
+ it 'indicates which field it is concerned about' do
53
+ violation = validator.validate(tags)
54
+ expect(violation.field).to eq(field)
55
+ end
56
+
57
+ it 'reports that field is missing' do
58
+ violation = validator.validate(tags)
59
+ expect(violation.reason).to eq(:missing)
60
+ end
61
+
62
+ it 'reports an applicable violation' do
63
+ violation = validator.validate(tags)
64
+ expect(violation).to be_applicable
65
+ end
66
+ end
67
+ end
68
+
69
+ describe Artist do
70
+ it_behaves_like 'an uniqueness validator' do
71
+ let :field do
72
+ :artist
73
+ end
74
+ end
75
+ end
76
+
77
+ describe Album do
78
+ it_behaves_like 'an uniqueness validator' do
79
+ let :field do
80
+ :album
81
+ end
82
+ end
83
+ end
84
+
85
+ describe Year do
86
+ it_behaves_like 'an uniqueness validator' do
87
+ let :field do
88
+ :year
89
+ end
90
+ end
91
+ end
92
+
93
+ describe TrackNumber do
94
+ let :validator do
95
+ described_class.new
96
+ end
97
+
98
+ context 'when `track` is present among all tags' do
99
+ let :tags do
100
+ 3.times.map { |i| OpenStruct.new(track: i + 1) }
101
+ end
102
+
103
+ it 'returns a `valid` validation' do
104
+ expect(validator.validate(tags)).to be_valid
105
+ end
106
+ end
107
+
108
+ context 'when `track` of any tag is zero (0)' do
109
+ let :tags do
110
+ 3.times.map { |i| OpenStruct.new(track: i) }
111
+ end
112
+
113
+ it 'returns an `invalid` validation' do
114
+ expect(validator.validate(tags)).to be_invalid
115
+ end
116
+
117
+ it 'indicates which field it is concerned about' do
118
+ violation = validator.validate(tags)
119
+ expect(violation.field).to eq(:track)
120
+ end
121
+
122
+ it 'reports one or more tags are missing track numbers' do
123
+ violation = validator.validate(tags)
124
+ expect(violation.reason).to eq(:missing)
125
+ end
126
+
127
+ it 'reports a non-applicable violation' do
128
+ violation = validator.validate(tags)
129
+ expect(violation).to_not be_applicable
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,91 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+
6
+ describe 'bin/audiothorian enforce <PATH>' do
7
+ include_context 'cli setup'
8
+
9
+ let :argv do
10
+ ['enforce', music_dir]
11
+ end
12
+
13
+ context 'when invoked without any paths' do
14
+ let :argv do
15
+ ['enforce']
16
+ end
17
+
18
+ it 'prints help for the `enforce` command' do
19
+ expect { run }.to output(/^Usage:\n.+ enforce/).to_stdout
20
+ end
21
+ end
22
+
23
+ it 'presents a list of inconsistent albums' do
24
+ expect do
25
+ interactive(%w[n]) { run }
26
+ end.to output(/the-album is inconsistent due to:/).to_stdout
27
+ end
28
+
29
+ context 'when the user answers `y` / `yes` to enforcement' do
30
+ context ', and selects to perform presented changes' do
31
+ it 'corrects inconsistencies' do
32
+ interactive(%w[y P]) { run }
33
+ tags_from(%(#{music_dir}/the-album)) do |tags|
34
+ expect(tags.map(&:artist).uniq).to eq(['the artist'])
35
+ expect(tags.map(&:album).uniq).to eq(['the album'])
36
+ expect(tags.map(&:year).uniq).to eq([2001])
37
+ end
38
+ end
39
+
40
+ context 'and -S / --society option is given' do
41
+ let :society_dir do
42
+ File.join(music_dir, 'society')
43
+ end
44
+
45
+ let :argv do
46
+ ['enforce', music_dir, '-S', society_dir]
47
+ end
48
+
49
+ before do
50
+ Dir.mkdir(society_dir)
51
+ end
52
+
53
+ it 'moves the enforced entity to society' do
54
+ interactive(%w[y P]) { run }
55
+ expect(File.exists?(File.join(society_dir, 'the-album'))).to be true
56
+ tags_from(%(#{society_dir}/the-album)) do |tags|
57
+ expect(tags.map(&:artist).uniq).to eq(['the artist'])
58
+ expect(tags.map(&:album).uniq).to eq(['the album'])
59
+ expect(tags.map(&:year).uniq).to eq([2001])
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ context ', and decides to skip performing changes' do
66
+ it 'does not apply changes' do
67
+ interactive(%w[y S]) do
68
+ expect { run }.to output.to_stdout
69
+ end
70
+ tags_from(%(#{music_dir}/the-album)) do |tags|
71
+ expect(tags.map(&:artist).uniq.size).to be > 1
72
+ expect(tags.map(&:album).uniq.size).to be > 1
73
+ expect(tags.map(&:year).uniq.size).to be > 1
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ context 'when the user answer anything else' do
80
+ it 'terminates and does not change any files' do
81
+ interactive(%w[n]) do
82
+ expect { run }.to output.to_stdout
83
+ end
84
+ tags_from(%(#{music_dir}/the-album)) do |tags|
85
+ expect(tags.map(&:artist).uniq.size).to be > 1
86
+ expect(tags.map(&:album).uniq.size).to be > 1
87
+ expect(tags.map(&:year).uniq.size).to be > 1
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,95 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+
6
+ describe 'bin/audiothorian scan <PATH>' do
7
+ include_context 'cli setup'
8
+
9
+ context 'when invoked without any paths' do
10
+ let :argv do
11
+ ['scan']
12
+ end
13
+
14
+ it 'prints help for the `scan` command' do
15
+ expect { run }.to output(/^Usage:\n.+ scan/).to_stdout
16
+ end
17
+ end
18
+
19
+ context 'when a directory does not contain inconsistencies' do
20
+ let :argv do
21
+ ['scan', empty_dir]
22
+ end
23
+
24
+ let :empty_dir do
25
+ path = File.join(music_dir, 'empty-dir')
26
+ Dir.mkdir(path)
27
+ path
28
+ end
29
+
30
+ it 'prints an `all is good` message' do
31
+ expect { run }.to output(/All is good/).to_stdout
32
+ end
33
+ end
34
+
35
+ context 'when a directory contains directories with inconsistencies' do
36
+ context 'without any options' do
37
+ let :argv do
38
+ ['scan', music_dir]
39
+ end
40
+
41
+ it 'scans a given directory and reports inconsistencies' do
42
+ expect { run }.to output(/the-album is inconsistent due to:/).to_stdout
43
+ end
44
+
45
+ it 'reports inconsistencies in `artist` field' do
46
+ expect { run }.to output(/multiple artists:/).to_stdout
47
+ end
48
+
49
+ it 'reports inconsistencies in `album` field' do
50
+ expect { run }.to output(/multiple albums:/).to_stdout
51
+ end
52
+
53
+ it 'reports inconsistencies in `year` field' do
54
+ expect { run }.to output(/multiple years:/).to_stdout
55
+ end
56
+ end
57
+
58
+ context 'with --paths-only' do
59
+ let :argv do
60
+ ['scan', music_dir, '--paths-only']
61
+ end
62
+
63
+ it 'prints paths to inconsistent albums' do
64
+ expect { run }.to output(/\/the-album$/).to_stdout
65
+ end
66
+ end
67
+
68
+ context 'with -C / --custody' do
69
+ let :custody do
70
+ File.join(music_dir, 'custody')
71
+ end
72
+
73
+ context ', and custody exists' do
74
+ before do
75
+ Dir.mkdir(custody)
76
+ end
77
+
78
+ before do
79
+ run_audiothorian(['scan', music_dir, '-C', custody])
80
+ end
81
+
82
+ it 'moves suspects into custody' do
83
+ expect(File.exists?(File.join(music_dir, 'custody', 'the-album'))).to be true
84
+ expect(Dir[%(#{custody}/**/*.mp3)].size).to eq(3)
85
+ end
86
+ end
87
+
88
+ context ', and custody does not exist' do
89
+ it 'raises an error' do
90
+ expect { run_audiothorian(['scan', music_dir, '-C', custody]) }.to raise_error(Audiothority::CustodyTorchedError)
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ require 'tmpdir'
4
+ require 'ostruct'
5
+ require 'support/cli_setup'
6
+ require 'support/interactive'
7
+ require 'coveralls'
8
+ require 'simplecov'
9
+
10
+ if ENV.include?('TRAVIS')
11
+ Coveralls.wear!
12
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
13
+ end
14
+
15
+ SimpleCov.start do
16
+ add_group 'Source', 'lib'
17
+ add_group 'Unit tests', 'spec/audiothority'
18
+ add_group 'Integration tests', 'spec/integration'
19
+ end
20
+
21
+ require 'audiothority'
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+
3
+ require 'fileutils'
4
+
5
+
6
+ shared_context 'cli setup' do
7
+ let :run do
8
+ run_audiothorian(argv)
9
+ end
10
+
11
+ def run_audiothorian(*argv)
12
+ Audiothority::Cli.start(*argv)
13
+ end
14
+
15
+ def copy_resources(dir)
16
+ Dir[resources_glob].each do |path|
17
+ path = Pathname.new(path)
18
+ FileUtils.copy_entry(path.to_s, %(#{dir}/#{path.basename}))
19
+ end
20
+ end
21
+
22
+ def resources_glob
23
+ %(#{resources_dir}/the-album)
24
+ end
25
+
26
+ def resources_dir
27
+ @resources_dir ||= File.expand_path('../../resources', __FILE__)
28
+ end
29
+
30
+ def music_dir
31
+ @music_dir
32
+ end
33
+
34
+ def set_music_dir(dir)
35
+ @music_dir = dir
36
+ end
37
+
38
+ around do |example|
39
+ Dir.mktmpdir do |dir|
40
+ Dir.chdir(dir) do
41
+ copy_resources(dir)
42
+ set_music_dir(dir)
43
+ example.call
44
+ end
45
+ end
46
+ end
47
+ end