audiothority 0.1.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.
@@ -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