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.
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