digital_opera 0.0.10 → 0.0.12

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 (87) hide show
  1. data/.gitignore +4 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +14 -0
  4. data/Gemfile.lock +186 -0
  5. data/Guardfile +15 -0
  6. data/README.md +35 -0
  7. data/Rakefile +6 -3
  8. data/app/helpers/digital_opera/s3_helper.rb +14 -0
  9. data/digital_opera.gemspec +37 -0
  10. data/lib/digital_opera/banker.rb +1 -1
  11. data/lib/digital_opera/builders/s3_form_builder.rb +118 -0
  12. data/lib/digital_opera/document/base.rb +0 -0
  13. data/lib/digital_opera/document/fields/standard.rb +185 -0
  14. data/lib/digital_opera/document.rb +167 -0
  15. data/lib/digital_opera/engine.rb +9 -0
  16. data/lib/digital_opera/form_object/base.rb +115 -0
  17. data/lib/digital_opera/form_object.rb +13 -0
  18. data/lib/digital_opera/presenter/base.rb +6 -0
  19. data/lib/digital_opera/presenter/concerns/json_serialization.rb +30 -0
  20. data/lib/digital_opera/presenter.rb +9 -0
  21. data/lib/digital_opera/services/s3.rb +148 -0
  22. data/lib/digital_opera/version.rb +1 -1
  23. data/lib/digital_opera.rb +8 -1
  24. data/spec/dummy/README.rdoc +28 -0
  25. data/spec/dummy/Rakefile +8 -0
  26. data/spec/dummy/app/assets/images/.keep +0 -0
  27. data/spec/dummy/app/assets/javascripts/application.js +2 -0
  28. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  29. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  30. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  31. data/spec/dummy/app/mailers/.keep +0 -0
  32. data/spec/dummy/app/models/.keep +0 -0
  33. data/spec/dummy/app/models/concerns/.keep +0 -0
  34. data/spec/dummy/app/views/application/show.html.erb +0 -0
  35. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  36. data/spec/dummy/bin/bundle +3 -0
  37. data/spec/dummy/bin/rails +4 -0
  38. data/spec/dummy/bin/rake +4 -0
  39. data/spec/dummy/config/application.rb +23 -0
  40. data/spec/dummy/config/boot.rb +5 -0
  41. data/spec/dummy/config/database.yml +25 -0
  42. data/spec/dummy/config/environment.rb +5 -0
  43. data/spec/dummy/config/environments/development.rb +29 -0
  44. data/spec/dummy/config/environments/production.rb +80 -0
  45. data/spec/dummy/config/environments/test.rb +36 -0
  46. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  47. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  48. data/spec/dummy/config/initializers/inflections.rb +16 -0
  49. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  50. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  51. data/spec/dummy/config/initializers/session_store.rb +3 -0
  52. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  53. data/spec/dummy/config/locales/en.yml +23 -0
  54. data/spec/dummy/config/routes.rb +3 -0
  55. data/spec/dummy/config.ru +4 -0
  56. data/spec/dummy/db/development.sqlite3 +0 -0
  57. data/spec/dummy/db/schema.rb +16 -0
  58. data/spec/dummy/db/test.sqlite3 +0 -0
  59. data/spec/dummy/lib/assets/.keep +0 -0
  60. data/spec/dummy/public/404.html +58 -0
  61. data/spec/dummy/public/422.html +58 -0
  62. data/spec/dummy/public/500.html +57 -0
  63. data/spec/dummy/public/favicon.ico +0 -0
  64. data/spec/dummy/spec/javascripts/helpers/.gitkeep +0 -0
  65. data/spec/dummy/spec/javascripts/support/jasmine.yml +116 -0
  66. data/spec/dummy/spec/javascripts/support/jasmine_helper.rb +10 -0
  67. data/spec/javascripts/spec/ellipsis_spec.js +10 -28
  68. data/spec/javascripts/spec/events_spec.js +15 -40
  69. data/spec/javascripts/spec/preload_images_spec.js +20 -32
  70. data/spec/javascripts/spec/tables_spec.js +3 -3
  71. data/spec/{banker_spec.rb → lib/digital_opera/banker_spec.rb} +4 -4
  72. data/spec/{base_extensions → lib/digital_opera/base_extensions}/object_spec.rb +0 -0
  73. data/spec/{presenter → lib/digital_opera/presenter}/base_spec.rb +0 -3
  74. data/spec/lib/digital_opera/services/s3_spec.rb +203 -0
  75. data/spec/{token_spec.rb → lib/digital_opera/token_spec.rb} +0 -0
  76. data/spec/spec_helper.rb +11 -5
  77. data/spec/support/aws.rb +5 -0
  78. data/spec/support/document.rb +10 -0
  79. data/tasks/spec.rake +5 -0
  80. data/tmp/rspec_guard_result +1 -0
  81. metadata +268 -46
  82. data/spec/javascripts/SpecRunner.html +0 -62
  83. data/spec/javascripts/lib/jasmine-1.3.1/MIT.LICENSE +0 -20
  84. data/spec/javascripts/lib/jasmine-1.3.1/jasmine-html.js +0 -681
  85. data/spec/javascripts/lib/jasmine-1.3.1/jasmine.css +0 -82
  86. data/spec/javascripts/lib/jasmine-1.3.1/jasmine.js +0 -2600
  87. data/spec/javascripts/src/digital_opera.js +0 -149
@@ -18,22 +18,15 @@ describe("events", function() {
18
18
  it("should return true", function() {
19
19
  var loggedEvent;
20
20
 
21
- runs(function(){
22
- first.on('click', function(e){
23
- loggedEvent = e;
24
- });
25
- setTimeout(function(){
26
- first.click();
27
- });
21
+ first.on('click', function(e){
22
+ loggedEvent = e;
28
23
  });
29
24
 
30
- waitsFor(function(){
31
- return typeof loggedEvent !== 'undefined';
32
- }, 'waiting for click', 1000)
25
+ first.click();
33
26
 
34
- runs(function(){
35
- expect(window.digitalOpera.isClickOutsideElement(loggedEvent, second)).toBe(true);
36
- });
27
+ jasmine.clock().tick(1000);
28
+
29
+ expect(window.digitalOpera.isClickOutsideElement(loggedEvent, second)).toBe(true);
37
30
  });
38
31
  });
39
32
 
@@ -41,43 +34,25 @@ describe("events", function() {
41
34
  it("should return false if click is on element inside", function() {
42
35
  var loggedEvent;
43
36
 
44
- runs(function(){
45
- second.on('click', function(e){
46
- loggedEvent = e;
47
- });
48
- setTimeout(function(){
49
- second.click();
50
- });
37
+ second.on('click', function(e){
38
+ loggedEvent = e;
51
39
  });
40
+ second.click();
52
41
 
53
- waitsFor(function(){
54
- return typeof loggedEvent !== 'undefined';
55
- }, 'waiting for click', 1000)
42
+ jasmine.clock().tick(1000);
56
43
 
57
- runs(function(){
58
- expect(window.digitalOpera.isClickOutsideElement(loggedEvent, first)).toBe(false);
59
- });
44
+ expect(window.digitalOpera.isClickOutsideElement(loggedEvent, first)).toBe(false);
60
45
  });
61
46
 
62
47
  it("should return false if click was on element", function() {
63
48
  var loggedEvent;
64
49
 
65
- runs(function(){
66
- second.on('click', function(e){
67
- loggedEvent = e;
68
- });
69
- setTimeout(function(){
70
- second.click();
71
- });
50
+ second.on('click', function(e){
51
+ loggedEvent = e;
72
52
  });
53
+ second.click();
73
54
 
74
- waitsFor(function(){
75
- return typeof loggedEvent !== 'undefined';
76
- }, 'waiting for click', 1000)
77
-
78
- runs(function(){
79
- expect(window.digitalOpera.isClickOutsideElement(loggedEvent, second)).toBe(false);
80
- });
55
+ expect(window.digitalOpera.isClickOutsideElement(loggedEvent, second)).toBe(false);
81
56
  });
82
57
  });
83
58
  });
@@ -12,65 +12,53 @@ describe("preload_images", function() {
12
12
  expect(function(){window.digitalOpera.preloadImages([google])}).not.toThrow();
13
13
  });
14
14
 
15
- it('should callback once a single image loaded', function(){
16
- var images,
17
- callbackCalled = false;
15
+ describe('single image', function(){
16
+ var images, callbackCalled = false;
18
17
 
19
- runs(function(){
18
+ beforeEach(function(done) {
20
19
  images = window.digitalOpera.preloadImages(google, function(){
21
- callbackCalled = true;
20
+ done();
22
21
  });
23
22
  });
24
23
 
25
- waitsFor(function(){
26
- return callbackCalled == true;
27
- }, 'callback should have been called', 5000);
28
-
29
- runs(function(){
24
+ it('should callback once a single image loaded', function(done){
30
25
  expect(images[0].complete).toBe(true);
26
+ done();
31
27
  });
32
28
 
33
29
  });
34
30
 
35
- it('should callback once all images are loaded', function(){
36
- var images,
37
- callbackCalled = false;
31
+ describe('multiple image', function(){
32
+ var images, callbackCalled = false;
38
33
 
39
- runs(function(){
34
+ beforeEach(function(done) {
40
35
  images = window.digitalOpera.preloadImages([google, yahoo], function(){
41
- callbackCalled = true;
36
+ done();
42
37
  });
43
38
  });
44
39
 
45
- waitsFor(function(){
46
- return callbackCalled == true;
47
- }, 'callback should have been called', 5000);
48
-
49
- runs(function(){
40
+ it('should callback once all images are loaded', function(done){
50
41
  expect(images[0].complete).toBe(true);
51
42
  expect(images[1].complete).toBe(true);
43
+ done();
52
44
  });
53
45
 
54
46
  });
55
47
 
56
- it('should callback if there was an error', function(){
57
- var images,
58
- callbackCalled = false;
48
+ describe('bad image', function(){
49
+ var images, callbackCalled = false;
59
50
 
60
- runs(function(){
61
- images = window.digitalOpera.preloadImages(bad, function(){
62
- callbackCalled = true;
51
+ beforeEach(function(done) {
52
+ images = window.digitalOpera.preloadImages([google, yahoo], function(){
53
+ done();
63
54
  });
64
55
  });
65
56
 
66
- waitsFor(function(){
67
- return callbackCalled == true;
68
- }, 'callback should have been called', 5000);
69
-
70
- runs(function(){
57
+ it('should callback if there was an error', function(done){
71
58
  expect(images[0].complete).toBe(true);
59
+ done();
72
60
  });
73
- });
74
61
 
62
+ });
75
63
  });
76
64
  });
@@ -19,7 +19,7 @@ describe("tables", function() {
19
19
  });
20
20
 
21
21
  it('should open new window if has data-does="open-window"', function(){
22
- spyOn(window, 'open').andReturn(focusObject);
22
+ spyOn(window, 'open').and.returnValue(focusObject);
23
23
  table.find('tr:first').attr('data-does', 'open-window');
24
24
  table.find('tr:first').click();
25
25
  expect(window.open).toHaveBeenCalled();
@@ -28,7 +28,7 @@ describe("tables", function() {
28
28
  it('should not follow link if click is within the anchor', function(){
29
29
  var anchor = $('<a href="http://bing.com">my link</a>')
30
30
  table.find('tr:first td:first').append(anchor);
31
- spyOn(window, 'open').andReturn(focusObject);
31
+ spyOn(window, 'open').and.returnValue(focusObject);
32
32
  spyOn(window.digitalOpera.forTestingPurposes, 'getWindowLocation');
33
33
  anchor.click();
34
34
  expect(window.open).not.toHaveBeenCalled();
@@ -38,7 +38,7 @@ describe("tables", function() {
38
38
  it('should not follow link if click is within a span within the anchor', function(){
39
39
  var anchor = $('<a href="http://bing.com"><span>my link</span></a>')
40
40
  table.find('tr:first td:first').append(anchor);
41
- spyOn(window, 'open').andReturn(focusObject);
41
+ spyOn(window, 'open').and.returnValue(focusObject);
42
42
  spyOn(window.digitalOpera.forTestingPurposes, 'getWindowLocation');
43
43
  anchor.find('span').click();
44
44
  expect(window.open).not.toHaveBeenCalled();
@@ -11,13 +11,13 @@ describe DigitalOpera::Banker do
11
11
 
12
12
  context 'from string' do
13
13
  it 'should convert to cents' do
14
- subject.money_in_account = '15.31'
15
- subject.money_in_account_in_cents.should eq 1531
14
+ subject.money_in_account = '16.31'
15
+ subject.money_in_account_in_cents.should eq 1631
16
16
  end
17
17
 
18
18
  it 'should convert to cents' do
19
- subject.money_in_account_in_cents = '1531'
20
- subject.money_in_account.should eq '15.31'
19
+ subject.money_in_account_in_cents = '1631'
20
+ subject.money_in_account.should eq '16.31'
21
21
  end
22
22
  end
23
23
 
@@ -1,7 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'support/user'
3
- require 'support/base_presenter'
4
- require 'action_controller'
5
2
 
6
3
  describe DigitalOpera::Presenter::Base do
7
4
  let(:user) { User.new }
@@ -0,0 +1,203 @@
1
+ require 'spec_helper'
2
+ require_relative "../../../../lib/digital_opera/services/s3"
3
+
4
+ describe DigitalOpera::Services::S3 do
5
+ let(:document){ Document.new s3_key: "documents/#{doc_name}" }
6
+ let(:doc_name){ 'test.png' }
7
+ let(:service){ DigitalOpera::Services::S3.new document }
8
+
9
+ before(:each) do
10
+ ENV["S3_BUCKET_NAME"] = 'testbuketname'
11
+ ENV["S3_ACCESS_KEY"] = 'testaccesskey'
12
+ ENV["S3_SECRET_ACCESS_KEY"] = 'testsecredaccesskey'
13
+ end
14
+
15
+ context 'when AWS is defined' do
16
+ before(:each) do
17
+ AWS.stub!
18
+ end
19
+
20
+ it 'should have a document' do
21
+ service.document.should eq document
22
+ end
23
+
24
+ it 'should have default options' do
25
+ service.instance_variable_get(:@options)[:acl].should eq 'authenticated-read'
26
+ end
27
+
28
+ it 'should be able to override options' do
29
+ service = DigitalOpera::Services::S3.new document, {acl: 'public-read'}
30
+ service.instance_variable_get(:@options)[:acl].should eq 'public-read'
31
+ end
32
+
33
+ it 'should have a base_url' do
34
+ service.base_url.should eq "https://#{ENV["S3_BUCKET_NAME"]}.s3.amazonaws.com/"
35
+ end
36
+
37
+ it 'should have a bucket' do
38
+ service.bucket.class.should eq AWS::S3::Bucket
39
+ end
40
+
41
+ it 'bucket_name should return a string' do
42
+ service.bucket_name.should eq ENV["S3_BUCKET_NAME"]
43
+ end
44
+
45
+ it 'access_key should return a string' do
46
+ service.access_key.should eq ENV["S3_ACCESS_KEY"]
47
+ end
48
+
49
+ it 'secret_access_key should return a key' do
50
+ service.secret_access_key.should eq ENV["S3_SECRET_ACCESS_KEY"]
51
+ end
52
+
53
+ it 'should have upload_key' do
54
+ service.upload_key.should eq 'documents/${filename}'
55
+ end
56
+
57
+ describe '#document_name' do
58
+ it 'should return name' do
59
+ service.document_name.should eq doc_name
60
+ end
61
+
62
+ it 'should return nil if key is nil' do
63
+ service = DigitalOpera::Services::S3.new Document.new({})
64
+ service.document_name.should be_nil
65
+ end
66
+ end
67
+
68
+
69
+ describe '#key' do
70
+ it 'should return a s3 key string if only key is supplied' do
71
+ service = DigitalOpera::Services::S3.new 'accounts/10/example.jpg'
72
+ service.key.should eq 'accounts/10/example.jpg'
73
+ end
74
+
75
+ it 'should return a s3 key string if only key is supplied with forward slash' do
76
+ service = DigitalOpera::Services::S3.new '/accounts/10/example.jpg'
77
+ service.key.should eq 'accounts/10/example.jpg'
78
+ end
79
+
80
+ it 'should return a s3 key string if full url is supplied' do
81
+ service = DigitalOpera::Services::S3.new "https://#{ENV["S3_BUCKET_NAME"]}.s3.amazonaws.com/accounts/10/example.jpg"
82
+ service.key.should eq 'accounts/10/example.jpg'
83
+ end
84
+
85
+ it 'should return nil if no s3_key is present' do
86
+ service = DigitalOpera::Services::S3.new Document.new({})
87
+ service.key.should be_nil
88
+ end
89
+ end
90
+
91
+ describe '#public_url' do
92
+ it 'calls S3s public_url' do
93
+ service.public_url.should eq service.base_url + service.key
94
+ end
95
+
96
+ it 'should return nil if s3_object is blank' do
97
+ service = DigitalOpera::Services::S3.new Document.new({})
98
+ service.public_url.should be_nil
99
+ end
100
+ end
101
+
102
+ describe '#private_url' do
103
+ it 'calls S3s url_for' do
104
+ disposition = "attachment; filename=#{doc_name.parameterize}"
105
+ service.s3_object.expects(:url_for).with(:read, :expires => service.expiration(10.minutes), :response_content_disposition => disposition)
106
+
107
+ service.private_url
108
+ end
109
+
110
+ it 'should return nil if s3_object is blank' do
111
+ service.stubs(:s3_object).returns(nil)
112
+ service.private_url.should be_nil
113
+ end
114
+
115
+ it 'should create disposition from document' do
116
+ service = DigitalOpera::Services::S3.new Document.new({s3_key: 'testname.exx'})
117
+
118
+ disposition = "attachment; filename=#{'testname.exx'.parameterize}"
119
+ service.s3_object.expects(:url_for).with(:read, :expires => service.expiration(10.minutes), :response_content_disposition => disposition)
120
+
121
+ service.private_url
122
+ end
123
+
124
+ it 'should create disposition from key if @document is string' do
125
+ disposition = "attachment; filename=#{doc_name.parameterize}"
126
+ service.s3_object.expects(:url_for).with(:read, :expires => service.expiration(10.minutes), :response_content_disposition => disposition)
127
+
128
+ service.private_url
129
+ end
130
+ end
131
+
132
+ describe '#expiration' do
133
+ it 'should return an iso time' do
134
+ Time.any_instance.expects(:iso8601).returns('2013-09-19T09:38:45Z')
135
+
136
+ service.expiration.should eq '2013-09-19T09:38:45Z'
137
+ end
138
+
139
+ it 'should return a time in the future' do
140
+ DateTime.parse(service.expiration).should > DateTime.now
141
+ end
142
+
143
+ it 'should return an adjusted time supplied based on param supplied' do
144
+ service.expiration(5.minutes).should eq 5.minutes.from_now.to_time.iso8601
145
+ service.expiration(2.hours).should eq 2.hours.from_now.to_time.iso8601
146
+ end
147
+ end
148
+
149
+ describe '#delete' do
150
+ it 'should call S3s delete' do
151
+ service.s3_object.expects(:delete)
152
+
153
+ service.delete
154
+ end
155
+ end
156
+
157
+ describe '#s3_object' do
158
+ it 'should call s3 object' do
159
+ hash = { objects: {} }
160
+ hash[:objects][service.key] = 'test_object'
161
+ hash = Confstruct::Configuration.new hash
162
+ service.stubs(:bucket).returns(hash)
163
+
164
+ service.s3_object.should eq 'test_object'
165
+ end
166
+
167
+ it 'should return nil if key is blank' do
168
+ service.stubs(:key).returns(nil)
169
+ service.s3_object.should be_nil
170
+ end
171
+
172
+ it 'should be memoized' do
173
+ hash = { objects: {} }
174
+ hash[:objects][service.key] = 'test_object'
175
+ h = Confstruct::Configuration.new hash
176
+ service.stubs(:bucket).returns(h)
177
+
178
+ service.s3_object.should eq 'test_object'
179
+
180
+ hash[:objects][service.key] = 'boo'
181
+ h = Confstruct::Configuration.new hash
182
+ service.stubs(:bucket).returns(h)
183
+
184
+ service.s3_object.should eq 'test_object'
185
+ end
186
+ end
187
+ end
188
+
189
+ context 'when AWS is not defined' do
190
+ before(:each) do
191
+ @tmp = AWS
192
+ end
193
+
194
+ after(:each) do
195
+ AWS = @tmp
196
+ end
197
+
198
+ it 'should throw error on init' do
199
+ AWS = nil
200
+ expect{service}.to raise_error
201
+ end
202
+ end
203
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,23 +1,29 @@
1
+ ENV["RAILS_ENV"] ||= 'test'
2
+
1
3
  require 'rubygems'
2
4
  require 'spork'
3
- require 'active_support'
4
- require 'digital_opera'
5
5
 
6
6
  Spork.prefork do
7
- ENV["RAILS_ENV"] ||= 'test'
8
- require 'rspec'
7
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
8
+ require 'rspec/rails'
9
9
  require 'rspec/autorun'
10
10
  require 'mocha/api'
11
11
 
12
+ require 'confstruct'
13
+ require 'aws'
14
+
15
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
16
+
12
17
  # Configure RSpec ---------------------------------------
13
18
  RSpec.configure do |config|
14
- config.mock_with :mocha
19
+ config.mock_framework = :mocha
15
20
 
16
21
  # Run specs in random order to surface order dependencies. If you find an
17
22
  # order dependency and want to debug it, you can fix the order by providing
18
23
  # the seed, which is printed after each run.
19
24
  # --seed 1234
20
25
  config.order = "random"
26
+ # config.order = 63206
21
27
  end
22
28
  end
23
29
 
@@ -0,0 +1,5 @@
1
+ AWS.config({
2
+ :access_key_id => 'ACCESS_KEY_ID',
3
+ :secret_access_key => 'SECRET_ACCESS_KEY',
4
+ :region => 'us-east-1',
5
+ })
@@ -0,0 +1,10 @@
1
+ class Document
2
+ # simulate fields
3
+ attr_accessor :s3_key
4
+
5
+ def initialize(opts)
6
+ opts.each do |key, val|
7
+ self.send "#{key}=", val if self.respond_to? "#{key}="
8
+ end
9
+ end
10
+ end
data/tasks/spec.rake ADDED
@@ -0,0 +1,5 @@
1
+ namespace :spec do
2
+ task :js do
3
+ system("cd spec/dummy && bundle exec rake jasmine:ci") or exit!(1)
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+