digital_opera 0.0.10 → 0.0.12

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