rivendell-import 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|