rivendell-import 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/.gitignore +21 -0
  2. data/Gemfile +11 -0
  3. data/Guardfile +14 -0
  4. data/LICENSE +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +4 -0
  7. data/bin/rivendell-import +6 -0
  8. data/db/migrate/20120920712200_create_tasks.rb +21 -0
  9. data/db/migrate/20120927194300_create_notifiers.rb +14 -0
  10. data/db/migrate/20120927203600_create_notifications.rb +14 -0
  11. data/examples/.gitignore +2 -0
  12. data/examples/config.rb +31 -0
  13. data/features/manage_cart_attributes.feature +20 -0
  14. data/features/manage_file_matching.feature +44 -0
  15. data/features/step_definitions/import_steps.rb +38 -0
  16. data/features/support/env.rb +19 -0
  17. data/features/support/mock_xport.rb +34 -0
  18. data/lib/rivendell/import.rb +48 -0
  19. data/lib/rivendell/import/base.rb +57 -0
  20. data/lib/rivendell/import/cart.rb +67 -0
  21. data/lib/rivendell/import/carts_cache.rb +58 -0
  22. data/lib/rivendell/import/cli.rb +90 -0
  23. data/lib/rivendell/import/config.rb +13 -0
  24. data/lib/rivendell/import/context.rb +28 -0
  25. data/lib/rivendell/import/cut.rb +33 -0
  26. data/lib/rivendell/import/file.rb +57 -0
  27. data/lib/rivendell/import/notification.rb +16 -0
  28. data/lib/rivendell/import/notifier/base.rb +89 -0
  29. data/lib/rivendell/import/notifier/mail-body.erb +8 -0
  30. data/lib/rivendell/import/notifier/mail-subject.erb +11 -0
  31. data/lib/rivendell/import/notifier/mail.rb +104 -0
  32. data/lib/rivendell/import/notifiers.rb +24 -0
  33. data/lib/rivendell/import/task.rb +80 -0
  34. data/lib/rivendell/import/tasking/cart.rb +25 -0
  35. data/lib/rivendell/import/tasking/destination.rb +28 -0
  36. data/lib/rivendell/import/tasking/file.rb +20 -0
  37. data/lib/rivendell/import/tasking/status.rb +29 -0
  38. data/lib/rivendell/import/tasking/tags.rb +27 -0
  39. data/lib/rivendell/import/tasks.rb +23 -0
  40. data/lib/rivendell/import/version.rb +5 -0
  41. data/lib/rivendell/import/worker.rb +34 -0
  42. data/rivendell-import.gemspec +37 -0
  43. data/spec/fixtures/mail-body.erb +5 -0
  44. data/spec/rivendell/import/base_spec.rb +125 -0
  45. data/spec/rivendell/import/cart_spec.rb +132 -0
  46. data/spec/rivendell/import/carts_cache_spec.rb +110 -0
  47. data/spec/rivendell/import/cli_spec.rb +149 -0
  48. data/spec/rivendell/import/config_spec.rb +16 -0
  49. data/spec/rivendell/import/context_spec.rb +19 -0
  50. data/spec/rivendell/import/file_spec.rb +63 -0
  51. data/spec/rivendell/import/notifier/base_spec.rb +63 -0
  52. data/spec/rivendell/import/notifier/mail_spec.rb +110 -0
  53. data/spec/rivendell/import/task_spec.rb +217 -0
  54. data/spec/rivendell/import/tasks_spec.rb +30 -0
  55. data/spec/rivendell/import/worker_spec.rb +25 -0
  56. data/spec/rivendell/import_spec.rb +32 -0
  57. data/spec/spec_helper.rb +15 -0
  58. data/spec/support/database_cleaner.rb +17 -0
  59. data/spec/support/fixtures.rb +3 -0
  60. data/spec/support/mail.rb +3 -0
  61. data/spec/support/test_notifier.rb +15 -0
  62. data/tasks/ci.rake +2 -0
  63. data/tasks/cucumber.rake +4 -0
  64. data/tasks/database.rake +11 -0
  65. data/tasks/rdoc.rake +16 -0
  66. data/tasks/rspec.rake +2 -0
  67. metadata +399 -0
@@ -0,0 +1,5 @@
1
+ <% if tasks.count > 1 %>
2
+ <%= tasks.count %> tasks have been processed
3
+ <% else %>
4
+ A task is processed
5
+ <% end %>
@@ -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