rivendell-import 0.0.1
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.
- data/.gitignore +21 -0
- data/Gemfile +11 -0
- data/Guardfile +14 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +4 -0
- data/bin/rivendell-import +6 -0
- data/db/migrate/20120920712200_create_tasks.rb +21 -0
- data/db/migrate/20120927194300_create_notifiers.rb +14 -0
- data/db/migrate/20120927203600_create_notifications.rb +14 -0
- data/examples/.gitignore +2 -0
- data/examples/config.rb +31 -0
- data/features/manage_cart_attributes.feature +20 -0
- data/features/manage_file_matching.feature +44 -0
- data/features/step_definitions/import_steps.rb +38 -0
- data/features/support/env.rb +19 -0
- data/features/support/mock_xport.rb +34 -0
- data/lib/rivendell/import.rb +48 -0
- data/lib/rivendell/import/base.rb +57 -0
- data/lib/rivendell/import/cart.rb +67 -0
- data/lib/rivendell/import/carts_cache.rb +58 -0
- data/lib/rivendell/import/cli.rb +90 -0
- data/lib/rivendell/import/config.rb +13 -0
- data/lib/rivendell/import/context.rb +28 -0
- data/lib/rivendell/import/cut.rb +33 -0
- data/lib/rivendell/import/file.rb +57 -0
- data/lib/rivendell/import/notification.rb +16 -0
- data/lib/rivendell/import/notifier/base.rb +89 -0
- data/lib/rivendell/import/notifier/mail-body.erb +8 -0
- data/lib/rivendell/import/notifier/mail-subject.erb +11 -0
- data/lib/rivendell/import/notifier/mail.rb +104 -0
- data/lib/rivendell/import/notifiers.rb +24 -0
- data/lib/rivendell/import/task.rb +80 -0
- data/lib/rivendell/import/tasking/cart.rb +25 -0
- data/lib/rivendell/import/tasking/destination.rb +28 -0
- data/lib/rivendell/import/tasking/file.rb +20 -0
- data/lib/rivendell/import/tasking/status.rb +29 -0
- data/lib/rivendell/import/tasking/tags.rb +27 -0
- data/lib/rivendell/import/tasks.rb +23 -0
- data/lib/rivendell/import/version.rb +5 -0
- data/lib/rivendell/import/worker.rb +34 -0
- data/rivendell-import.gemspec +37 -0
- data/spec/fixtures/mail-body.erb +5 -0
- data/spec/rivendell/import/base_spec.rb +125 -0
- data/spec/rivendell/import/cart_spec.rb +132 -0
- data/spec/rivendell/import/carts_cache_spec.rb +110 -0
- data/spec/rivendell/import/cli_spec.rb +149 -0
- data/spec/rivendell/import/config_spec.rb +16 -0
- data/spec/rivendell/import/context_spec.rb +19 -0
- data/spec/rivendell/import/file_spec.rb +63 -0
- data/spec/rivendell/import/notifier/base_spec.rb +63 -0
- data/spec/rivendell/import/notifier/mail_spec.rb +110 -0
- data/spec/rivendell/import/task_spec.rb +217 -0
- data/spec/rivendell/import/tasks_spec.rb +30 -0
- data/spec/rivendell/import/worker_spec.rb +25 -0
- data/spec/rivendell/import_spec.rb +32 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/database_cleaner.rb +17 -0
- data/spec/support/fixtures.rb +3 -0
- data/spec/support/mail.rb +3 -0
- data/spec/support/test_notifier.rb +15 -0
- data/tasks/ci.rake +2 -0
- data/tasks/cucumber.rake +4 -0
- data/tasks/database.rake +11 -0
- data/tasks/rdoc.rake +16 -0
- data/tasks/rspec.rake +2 -0
- metadata +399 -0
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rivendell::Import::Base do
|
4
|
+
|
5
|
+
describe "#prepare_task" do
|
6
|
+
|
7
|
+
let(:task) { mock }
|
8
|
+
|
9
|
+
it "should prepare task with to_prepare block" do
|
10
|
+
subject.to_prepare = Proc.new {}
|
11
|
+
task.should_receive :prepare
|
12
|
+
subject.prepare_task task
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#create_task" do
|
18
|
+
|
19
|
+
let(:file) { Rivendell::Import::File.new "dummy.wav" }
|
20
|
+
|
21
|
+
it "should create a task with given file" do
|
22
|
+
Rivendell::Import::Task.should_receive(:create).with({:file => file}, {})
|
23
|
+
subject.create_task file
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should prepare task" do
|
27
|
+
subject.should_receive(:prepare_task)
|
28
|
+
subject.create_task file
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#file" do
|
34
|
+
|
35
|
+
let(:file) { Rivendell::Import::File.new("dummy.wav") }
|
36
|
+
|
37
|
+
it "should create a File with given path and base_directory" do
|
38
|
+
Rivendell::Import::File.should_receive(:new).with("path", :base_directory => "base_directory")
|
39
|
+
subject.file "path", "base_directory"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should create a File with given path and base_directory" do
|
43
|
+
Rivendell::Import::File.stub :new=> file
|
44
|
+
subject.should_receive(:create_task).with(file)
|
45
|
+
subject.file "path", "base_directory"
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#directory" do
|
51
|
+
|
52
|
+
it "should look for files in given directory" do
|
53
|
+
Dir.mktmpdir do |directory|
|
54
|
+
FileUtils.mkdir "#{directory}/subdirectory"
|
55
|
+
|
56
|
+
file = "#{directory}/subdirectory/dummy.wav"
|
57
|
+
FileUtils.touch file
|
58
|
+
|
59
|
+
subject.should_receive(:file).with(file, directory)
|
60
|
+
subject.directory directory
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#process" do
|
67
|
+
|
68
|
+
it "should use file method when path isn't a directory" do
|
69
|
+
File.stub :directory? => false
|
70
|
+
subject.should_receive(:file).with("dummy")
|
71
|
+
subject.process("dummy")
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should use directory method when path is a directory" do
|
75
|
+
File.stub :directory? => true
|
76
|
+
subject.should_receive(:directory).with("dummy")
|
77
|
+
subject.process("dummy")
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#listen" do
|
83
|
+
|
84
|
+
before(:each) do
|
85
|
+
Listen.stub :to => true
|
86
|
+
end
|
87
|
+
|
88
|
+
let(:directory) { "directory" }
|
89
|
+
let(:worker) { mock }
|
90
|
+
|
91
|
+
before(:each) do
|
92
|
+
worker.stub :start => worker
|
93
|
+
Rivendell::Import::Worker.stub :new => worker
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should create a Worker" do
|
97
|
+
Rivendell::Import::Worker.should_receive(:new).with(subject).and_return(worker)
|
98
|
+
subject.listen directory
|
99
|
+
subject.workers.should == [ worker ]
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should start Worker" do
|
103
|
+
worker.should_receive(:start).and_return(worker)
|
104
|
+
subject.listen directory
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should not create Worker with dry_run option" do
|
108
|
+
subject.listen directory, :dry_run => true
|
109
|
+
subject.workers.should be_empty
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should invoke Listen.to with given directory" do
|
113
|
+
Listen.should_receive(:to).with(directory)
|
114
|
+
subject.listen directory
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should invoke file with added files" do
|
118
|
+
Listen.stub(:to).and_yield(nil,%w{file},nil)
|
119
|
+
subject.should_receive(:file).with("file", directory)
|
120
|
+
subject.listen directory
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rivendell::Import::Cart do
|
4
|
+
|
5
|
+
let(:task) { mock }
|
6
|
+
subject { Rivendell::Import::Cart.new task }
|
7
|
+
|
8
|
+
describe "initialization" do
|
9
|
+
|
10
|
+
it "should use the given task" do
|
11
|
+
Rivendell::Import::Cart.new(task).task.should == task
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#xport" do
|
17
|
+
|
18
|
+
before(:each) do
|
19
|
+
task.stub :xport => mock
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should be task xport" do
|
23
|
+
subject.xport.should == subject.task.xport
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#create" do
|
29
|
+
|
30
|
+
before(:each) do
|
31
|
+
subject.stub :xport => mock
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should use Xport#add_cart with Cart group" do
|
35
|
+
subject.group = "dummy"
|
36
|
+
subject.xport.should_receive(:add_cart).with(:group => subject.group).and_return(mock(:number => 123))
|
37
|
+
subject.create
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should use the number returned by Xport#add_cart" do
|
41
|
+
subject.xport.stub(:add_cart).and_return(mock(:number => 123))
|
42
|
+
subject.group = "dummy"
|
43
|
+
subject.create
|
44
|
+
subject.number.should == 123
|
45
|
+
end
|
46
|
+
|
47
|
+
context "when number is already defined" do
|
48
|
+
|
49
|
+
before(:each) do
|
50
|
+
subject.number = 666
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should not invoke Xport#add_cart" do
|
54
|
+
subject.xport.stub(:add_cart).and_return(mock(:number => 123))
|
55
|
+
subject.create
|
56
|
+
subject.number.should == 666
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when group isn't defined" do
|
62
|
+
|
63
|
+
it "should raise an error" do
|
64
|
+
subject.group = nil
|
65
|
+
lambda { subject.create }.should raise_error
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#cut" do
|
73
|
+
|
74
|
+
it "should return a Cut associated to this Cart" do
|
75
|
+
subject.cut.cart.should == subject
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#import" do
|
81
|
+
|
82
|
+
let(:file) { mock :path => "dummy", :exists? => true }
|
83
|
+
|
84
|
+
before(:each) do
|
85
|
+
subject.number = 123
|
86
|
+
subject.stub :xport => mock(:import => true)
|
87
|
+
subject.cut.stub :create => true, :number => 1, :update => true
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should create Cut" do
|
91
|
+
subject.cut.should_receive :create
|
92
|
+
subject.import file
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should import file via xport with Cart and Cut numbers" do
|
96
|
+
subject.xport.should_receive(:import).with(subject.number, subject.cut.number, file.path)
|
97
|
+
subject.import file
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should update Cut" do
|
101
|
+
subject.cut.should_receive :update
|
102
|
+
subject.import file
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#find_by_title" do
|
108
|
+
|
109
|
+
let(:cart) { mock :title => "The Title of the Cart", :number => 123 }
|
110
|
+
|
111
|
+
before(:each) do
|
112
|
+
subject.stub_chain("xport.list_carts").and_return([cart])
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should find an exact title" do
|
116
|
+
subject.find_by_title(cart.title)
|
117
|
+
subject.number.should == cart.number
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should find with a 'matching' filename ('the-title_of_the Cart' for 'The Title of the Cart')" do
|
121
|
+
subject.find_by_title("the-title_of_the Cart")
|
122
|
+
subject.number.should == cart.number
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should use specified options to find carts" do
|
126
|
+
subject.xport.should_receive(:list_carts).with(:group => "TEST").and_return([cart])
|
127
|
+
subject.find_by_title("dummy", :group => "TEST")
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rivendell::Import::CartsCache do
|
4
|
+
|
5
|
+
let(:carts_cache) { Rivendell::Import::CartsCache.new(xport) }
|
6
|
+
subject { carts_cache }
|
7
|
+
|
8
|
+
let(:cart) { mock :title => "dummy" }
|
9
|
+
let(:carts) { [ cart ] }
|
10
|
+
|
11
|
+
let(:xport) { mock }
|
12
|
+
|
13
|
+
before do
|
14
|
+
subject.stub :xport => xport
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#find_all_by_title" do
|
18
|
+
|
19
|
+
let(:options) { Hash.new }
|
20
|
+
|
21
|
+
before do
|
22
|
+
subject.stub(:carts).and_return(carts)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should use carts with given options" do
|
26
|
+
subject.should_receive(:carts).with(options).and_return(carts)
|
27
|
+
subject.find_all_by_title("dummy", options)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should select with given title" do
|
31
|
+
subject.find_all_by_title(cart.title).should == [ cart ]
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should use the given normalizer" do
|
35
|
+
normalizer = Proc.new { |s| s.downcase }
|
36
|
+
cart.stub :title => "the Title"
|
37
|
+
subject.find_all_by_title("The TITLE", :normalizer => normalizer).should == [ cart ]
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#default_normalizer" do
|
43
|
+
|
44
|
+
subject { carts_cache.default_normalizer }
|
45
|
+
|
46
|
+
it "should downcase string" do
|
47
|
+
subject.call("ABC").should == "abc"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should replace no alphanumeric characters by space" do
|
51
|
+
subject.call("a'b-c").should == "a b c"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should remove double spaces" do
|
55
|
+
subject.call("a b c").should == "a b c"
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "#carts" do
|
61
|
+
|
62
|
+
before do
|
63
|
+
subject.xport.stub :list_carts => carts
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should return Xport#list_carts result" do
|
67
|
+
subject.carts.should == carts
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should cache the result" do
|
71
|
+
subject.xport.should_receive(:list_carts).once.and_return(carts)
|
72
|
+
2.times { subject.carts }
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should reset cache after delay defined by cache_time_to_live" do
|
76
|
+
subject.carts # fill cache
|
77
|
+
subject.purged_at = Time.now - subject.time_to_live - 1
|
78
|
+
|
79
|
+
subject.xport.should_receive(:list_carts).and_return(carts)
|
80
|
+
subject.carts
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#find_by_title" do
|
86
|
+
|
87
|
+
before do
|
88
|
+
subject.stub(:carts).and_return(carts)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should try an exact match" do
|
92
|
+
subject.find_by_title(cart.title).should == cart
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should try a match with default normalizer" do
|
96
|
+
subject.find_by_title(cart.title.upcase).should == cart
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should return nil when no cart matchs" do
|
100
|
+
subject.find_by_title("nothing").should be_nil
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should return nil when several carts match" do
|
104
|
+
carts << cart
|
105
|
+
subject.find_by_title(cart.title).should be_nil
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'rivendell/import/cli'
|
4
|
+
|
5
|
+
describe Rivendell::Import::CLI do
|
6
|
+
|
7
|
+
describe "#config_file" do
|
8
|
+
|
9
|
+
it "should return file specified with --config" do
|
10
|
+
subject.arguments << "--config" << "dummy"
|
11
|
+
subject.config_file.should == "dummy"
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "listen_mode?" do
|
17
|
+
|
18
|
+
it "should return true when --listen is specified" do
|
19
|
+
subject.arguments << "--listen"
|
20
|
+
subject.should be_listen_mode
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "dry_run?" do
|
26
|
+
|
27
|
+
it "should return true when --dry-run is specified" do
|
28
|
+
subject.arguments << "--dry-run"
|
29
|
+
subject.should be_dry_run
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "debug?" do
|
35
|
+
|
36
|
+
it "should return true when --debug is specified" do
|
37
|
+
subject.arguments << "--debug"
|
38
|
+
subject.should be_debug
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#import" do
|
44
|
+
|
45
|
+
it "should return a Rivendell::Import::Base instance" do
|
46
|
+
subject.import.should be_instance_of(Rivendell::Import::Base)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#paths" do
|
52
|
+
|
53
|
+
it "should return arguments after options" do
|
54
|
+
subject.arguments << "--listen"
|
55
|
+
subject.arguments << "file1" << "file2"
|
56
|
+
subject.paths.should == %w{file1 file2}
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#database" do
|
62
|
+
|
63
|
+
it "should return file specified with --dabase" do
|
64
|
+
subject.arguments << "--database" << "tasks.sqlite3"
|
65
|
+
subject.database.should == "tasks.sqlite3"
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#run" do
|
71
|
+
|
72
|
+
before(:each) do
|
73
|
+
subject.stub :paths => %w{file1 file2}
|
74
|
+
subject.import.tasks.stub :run => true
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should load config_file" do
|
78
|
+
subject.stub :config_file => "dummy.rb"
|
79
|
+
subject.should_receive(:load).with(subject.config_file)
|
80
|
+
|
81
|
+
subject.run
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should establish_connection with specified database" do
|
85
|
+
subject.stub :database => "tasks.sqlite3"
|
86
|
+
Rivendell::Import.should_receive(:establish_connection).with("tasks.sqlite3")
|
87
|
+
|
88
|
+
subject.run
|
89
|
+
end
|
90
|
+
|
91
|
+
context "in listen_mode" do
|
92
|
+
|
93
|
+
let(:directory) { "directory" }
|
94
|
+
|
95
|
+
before(:each) do
|
96
|
+
subject.stub :listen_mode? => true
|
97
|
+
subject.stub :paths => [directory]
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should use listen import" do
|
101
|
+
subject.import.should_receive(:listen).with(directory, {})
|
102
|
+
subject.run
|
103
|
+
end
|
104
|
+
|
105
|
+
context "when dry_run" do
|
106
|
+
before(:each) do
|
107
|
+
subject.stub :dry_run? => true
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should use dry_run listen option" do
|
111
|
+
subject.import.should_receive(:listen).with(anything, hash_including(:dry_run => true))
|
112
|
+
subject.run
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
context "without listen_mode" do
|
119
|
+
|
120
|
+
before(:each) do
|
121
|
+
subject.stub :listen_mode? => false
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should use process import" do
|
125
|
+
subject.import.should_receive(:process).with(subject.paths)
|
126
|
+
subject.run
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should run tasks" do
|
130
|
+
subject.import.tasks.should_receive(:run)
|
131
|
+
subject.run
|
132
|
+
end
|
133
|
+
|
134
|
+
context "when dry_run" do
|
135
|
+
before(:each) do
|
136
|
+
subject.stub :dry_run? => true
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should not run tasks" do
|
140
|
+
subject.import.tasks.should_not_receive(:run)
|
141
|
+
subject.run
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|