activestorage_legacy 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +7 -0
  2. data/.babelrc +5 -0
  3. data/.codeclimate.yml +7 -0
  4. data/.eslintrc +19 -0
  5. data/.github/workflows/gem-push.yml +29 -0
  6. data/.github/workflows/ruby-tests.yml +37 -0
  7. data/.gitignore +9 -0
  8. data/.rubocop.yml +125 -0
  9. data/.travis.yml +25 -0
  10. data/Gemfile +33 -0
  11. data/Gemfile.lock +271 -0
  12. data/MIT-LICENSE +20 -0
  13. data/README.md +160 -0
  14. data/Rakefile +12 -0
  15. data/activestorage.gemspec +27 -0
  16. data/app/assets/javascripts/activestorage.js +1 -0
  17. data/app/controllers/active_storage/blobs_controller.rb +22 -0
  18. data/app/controllers/active_storage/direct_uploads_controller.rb +21 -0
  19. data/app/controllers/active_storage/disk_controller.rb +52 -0
  20. data/app/controllers/active_storage/variants_controller.rb +28 -0
  21. data/app/helpers/active_storage/file_field_with_direct_upload_helper.rb +18 -0
  22. data/app/javascript/activestorage/blob_record.js +54 -0
  23. data/app/javascript/activestorage/blob_upload.js +34 -0
  24. data/app/javascript/activestorage/direct_upload.js +42 -0
  25. data/app/javascript/activestorage/direct_upload_controller.js +67 -0
  26. data/app/javascript/activestorage/direct_uploads_controller.js +50 -0
  27. data/app/javascript/activestorage/file_checksum.js +53 -0
  28. data/app/javascript/activestorage/helpers.js +42 -0
  29. data/app/javascript/activestorage/index.js +11 -0
  30. data/app/javascript/activestorage/ujs.js +74 -0
  31. data/app/jobs/active_storage/purge_attachment_worker.rb +9 -0
  32. data/app/jobs/active_storage/purge_blob_worker.rb +9 -0
  33. data/app/models/active_storage/attachment.rb +33 -0
  34. data/app/models/active_storage/blob.rb +198 -0
  35. data/app/models/active_storage/filename.rb +49 -0
  36. data/app/models/active_storage/variant.rb +82 -0
  37. data/app/models/active_storage/variation.rb +53 -0
  38. data/config/routes.rb +9 -0
  39. data/config/storage_services.yml +34 -0
  40. data/lib/active_storage/attached/macros.rb +86 -0
  41. data/lib/active_storage/attached/many.rb +51 -0
  42. data/lib/active_storage/attached/one.rb +56 -0
  43. data/lib/active_storage/attached.rb +38 -0
  44. data/lib/active_storage/engine.rb +81 -0
  45. data/lib/active_storage/gem_version.rb +15 -0
  46. data/lib/active_storage/log_subscriber.rb +48 -0
  47. data/lib/active_storage/messages_metadata.rb +64 -0
  48. data/lib/active_storage/migration.rb +27 -0
  49. data/lib/active_storage/patches/active_record.rb +19 -0
  50. data/lib/active_storage/patches/delegation.rb +98 -0
  51. data/lib/active_storage/patches/secure_random.rb +26 -0
  52. data/lib/active_storage/patches.rb +4 -0
  53. data/lib/active_storage/service/azure_service.rb +115 -0
  54. data/lib/active_storage/service/configurator.rb +28 -0
  55. data/lib/active_storage/service/disk_service.rb +124 -0
  56. data/lib/active_storage/service/gcs_service.rb +79 -0
  57. data/lib/active_storage/service/mirror_service.rb +46 -0
  58. data/lib/active_storage/service/s3_service.rb +96 -0
  59. data/lib/active_storage/service.rb +113 -0
  60. data/lib/active_storage/verifier.rb +113 -0
  61. data/lib/active_storage/version.rb +8 -0
  62. data/lib/active_storage.rb +34 -0
  63. data/lib/tasks/activestorage.rake +20 -0
  64. data/package.json +33 -0
  65. data/test/controllers/direct_uploads_controller_test.rb +123 -0
  66. data/test/controllers/disk_controller_test.rb +57 -0
  67. data/test/controllers/variants_controller_test.rb +21 -0
  68. data/test/database/create_users_migration.rb +7 -0
  69. data/test/database/setup.rb +6 -0
  70. data/test/dummy/Rakefile +3 -0
  71. data/test/dummy/app/assets/config/manifest.js +5 -0
  72. data/test/dummy/app/assets/images/.keep +0 -0
  73. data/test/dummy/app/assets/javascripts/application.js +13 -0
  74. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  75. data/test/dummy/app/controllers/application_controller.rb +3 -0
  76. data/test/dummy/app/controllers/concerns/.keep +0 -0
  77. data/test/dummy/app/helpers/application_helper.rb +2 -0
  78. data/test/dummy/app/jobs/application_job.rb +2 -0
  79. data/test/dummy/app/models/application_record.rb +3 -0
  80. data/test/dummy/app/models/concerns/.keep +0 -0
  81. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  82. data/test/dummy/bin/bundle +3 -0
  83. data/test/dummy/bin/rails +4 -0
  84. data/test/dummy/bin/rake +4 -0
  85. data/test/dummy/bin/yarn +11 -0
  86. data/test/dummy/config/application.rb +22 -0
  87. data/test/dummy/config/boot.rb +5 -0
  88. data/test/dummy/config/database.yml +25 -0
  89. data/test/dummy/config/environment.rb +5 -0
  90. data/test/dummy/config/environments/development.rb +49 -0
  91. data/test/dummy/config/environments/production.rb +82 -0
  92. data/test/dummy/config/environments/test.rb +33 -0
  93. data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
  94. data/test/dummy/config/initializers/assets.rb +14 -0
  95. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  96. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  97. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  98. data/test/dummy/config/initializers/inflections.rb +16 -0
  99. data/test/dummy/config/initializers/mime_types.rb +4 -0
  100. data/test/dummy/config/initializers/secret_key.rb +3 -0
  101. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  102. data/test/dummy/config/routes.rb +2 -0
  103. data/test/dummy/config/secrets.yml +32 -0
  104. data/test/dummy/config/spring.rb +6 -0
  105. data/test/dummy/config/storage_services.yml +3 -0
  106. data/test/dummy/config.ru +5 -0
  107. data/test/dummy/db/.keep +0 -0
  108. data/test/dummy/lib/assets/.keep +0 -0
  109. data/test/dummy/log/.keep +0 -0
  110. data/test/dummy/package.json +5 -0
  111. data/test/dummy/public/404.html +67 -0
  112. data/test/dummy/public/422.html +67 -0
  113. data/test/dummy/public/500.html +66 -0
  114. data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
  115. data/test/dummy/public/apple-touch-icon.png +0 -0
  116. data/test/dummy/public/favicon.ico +0 -0
  117. data/test/filename_test.rb +36 -0
  118. data/test/fixtures/files/racecar.jpg +0 -0
  119. data/test/models/attachments_test.rb +122 -0
  120. data/test/models/blob_test.rb +47 -0
  121. data/test/models/variant_test.rb +27 -0
  122. data/test/service/.gitignore +1 -0
  123. data/test/service/azure_service_test.rb +14 -0
  124. data/test/service/configurations-example.yml +31 -0
  125. data/test/service/configurator_test.rb +14 -0
  126. data/test/service/disk_service_test.rb +12 -0
  127. data/test/service/gcs_service_test.rb +42 -0
  128. data/test/service/mirror_service_test.rb +62 -0
  129. data/test/service/s3_service_test.rb +52 -0
  130. data/test/service/shared_service_tests.rb +66 -0
  131. data/test/sidekiq/minitest_support.rb +6 -0
  132. data/test/support/assertions.rb +20 -0
  133. data/test/test_helper.rb +69 -0
  134. data/webpack.config.js +27 -0
  135. data/yarn.lock +3164 -0
  136. metadata +330 -0
@@ -0,0 +1,47 @@
1
+ require "test_helper"
2
+ require "database/setup"
3
+
4
+ class ActiveStorage::BlobTest < ActiveSupport::TestCase
5
+ test "create after upload sets byte size and checksum" do
6
+ data = "Hello world!"
7
+ blob = create_blob data: data
8
+
9
+ assert_equal data, blob.download
10
+ assert_equal data.length, blob.byte_size
11
+ assert_equal Digest::MD5.base64digest(data), blob.checksum
12
+ end
13
+
14
+ test "text?" do
15
+ blob = create_blob data: "Hello world!"
16
+ assert blob.text?
17
+ assert_not blob.audio?
18
+ end
19
+
20
+ test "download yields chunks" do
21
+ blob = create_blob data: "a" * 75.kilobytes
22
+ chunks = []
23
+
24
+ blob.download do |chunk|
25
+ chunks << chunk
26
+ end
27
+
28
+ assert_equal 2, chunks.size
29
+ assert_equal "a" * 64.kilobytes, chunks.first
30
+ assert_equal "a" * 11.kilobytes, chunks.second
31
+ end
32
+
33
+ test "urls expiring in 5 minutes" do
34
+ blob = create_blob
35
+
36
+ freeze_time do
37
+ assert_equal expected_url_for(blob), blob.service_url
38
+ assert_equal expected_url_for(blob, disposition: :attachment), blob.service_url(disposition: :attachment)
39
+ end
40
+ end
41
+
42
+ private
43
+ def expected_url_for(blob, disposition: :inline)
44
+ query_string = { content_type: blob.content_type, disposition: disposition }.to_param
45
+ "/rails/active_storage/disk/#{ActiveStorage.verifier.generate(blob.key, expires_in: 5.minutes, purpose: :blob_key)}/#{blob.filename}?#{query_string}"
46
+ end
47
+ end
@@ -0,0 +1,27 @@
1
+ require "test_helper"
2
+ require "database/setup"
3
+
4
+ class ActiveStorage::VariantTest < ActiveSupport::TestCase
5
+ setup do
6
+ @blob = create_image_blob filename: "racecar.jpg"
7
+ end
8
+
9
+ test "resized variation" do
10
+ variant = @blob.variant(resize: "100x100").processed
11
+ assert_match /racecar.jpg/, variant.service_url
12
+
13
+ image = read_image_variant(variant)
14
+ assert_equal 100, image.width
15
+ assert_equal 67, image.height
16
+ end
17
+
18
+ test "resized and monochrome variation" do
19
+ variant = @blob.variant(resize: "100x100", monochrome: true).processed
20
+ assert_match /racecar.jpg/, variant.service_url
21
+
22
+ image = read_image_variant(variant)
23
+ assert_equal 100, image.width
24
+ assert_equal 67, image.height
25
+ assert_match /Gray/, image.colorspace
26
+ end
27
+ end
@@ -0,0 +1 @@
1
+ configurations.yml
@@ -0,0 +1,14 @@
1
+ require "service/shared_service_tests"
2
+ require "httparty"
3
+ require "uri"
4
+
5
+ if SERVICE_CONFIGURATIONS[:azure]
6
+ class ActiveStorage::Service::AzureServiceTest < ActiveSupport::TestCase
7
+ SERVICE = ActiveStorage::Service.configure(:azure, SERVICE_CONFIGURATIONS)
8
+
9
+ include ActiveStorage::Service::SharedServiceTests
10
+ end
11
+
12
+ else
13
+ puts "Skipping Azure Storage Service tests because no Azure configuration was supplied"
14
+ end
@@ -0,0 +1,31 @@
1
+ # Copy this file to configurations.yml and edit the credentials to match your IAM test account and bucket
2
+ s3:
3
+ service: S3
4
+ access_key_id:
5
+ secret_access_key:
6
+ region:
7
+ bucket:
8
+
9
+ gcs:
10
+ service: GCS
11
+ keyfile: {
12
+ type: "service_account",
13
+ project_id: "",
14
+ private_key_id: "",
15
+ private_key: "",
16
+ client_email: "",
17
+ client_id: "",
18
+ auth_uri: "https://accounts.google.com/o/oauth2/auth",
19
+ token_uri: "https://accounts.google.com/o/oauth2/token",
20
+ auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs",
21
+ client_x509_cert_url: ""
22
+ }
23
+ project:
24
+ bucket:
25
+
26
+ azure:
27
+ service: Azure
28
+ path: ""
29
+ storage_account_name: ""
30
+ storage_access_key: ""
31
+ container: ""
@@ -0,0 +1,14 @@
1
+ require "service/shared_service_tests"
2
+
3
+ class ActiveStorage::Service::ConfiguratorTest < ActiveSupport::TestCase
4
+ test "builds correct service instance based on service name" do
5
+ service = ActiveStorage::Service::Configurator.build(:foo, foo: { service: "Disk", root: "path" })
6
+ assert_instance_of ActiveStorage::Service::DiskService, service
7
+ end
8
+
9
+ test "raises error when passing non-existent service name" do
10
+ assert_raise RuntimeError do
11
+ ActiveStorage::Service::Configurator.build(:bigfoot, {})
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ require "service/shared_service_tests"
2
+
3
+ class ActiveStorage::Service::DiskServiceTest < ActiveSupport::TestCase
4
+ SERVICE = ActiveStorage::Service::DiskService.new(root: File.join(Dir.tmpdir, "active_storage"))
5
+
6
+ include ActiveStorage::Service::SharedServiceTests
7
+
8
+ test "url generation" do
9
+ assert_match /rails\/active_storage\/disk\/.*\/avatar\.png\?.+disposition=inline/,
10
+ @service.url(FIXTURE_KEY, expires_in: 5.minutes, disposition: :inline, filename: "avatar.png", content_type: "image/png")
11
+ end
12
+ end
@@ -0,0 +1,42 @@
1
+ require "service/shared_service_tests"
2
+ require "httparty"
3
+
4
+ if SERVICE_CONFIGURATIONS[:gcs]
5
+ class ActiveStorage::Service::GCSServiceTest < ActiveSupport::TestCase
6
+ SERVICE = ActiveStorage::Service.configure(:gcs, SERVICE_CONFIGURATIONS)
7
+
8
+ include ActiveStorage::Service::SharedServiceTests
9
+
10
+ test "direct upload" do
11
+ begin
12
+ key = SecureRandom.base58(24)
13
+ data = "Something else entirely!"
14
+ checksum = Digest::MD5.base64digest(data)
15
+ url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum)
16
+
17
+ HTTParty.put(
18
+ url,
19
+ body: data,
20
+ headers: { "Content-Type" => "text/plain", "Content-MD5" => checksum },
21
+ debug_output: STDOUT
22
+ )
23
+
24
+ assert_equal data, @service.download(key)
25
+ ensure
26
+ @service.delete key
27
+ end
28
+ end
29
+
30
+ test "signed URL generation" do
31
+ freeze_time do
32
+ url = SERVICE.bucket.signed_url(FIXTURE_KEY, expires: 120) +
33
+ "&response-content-disposition=inline%3B+filename%3D%22test.txt%22" +
34
+ "&response-content-type=text%2Fplain"
35
+
36
+ assert_equal url, @service.url(FIXTURE_KEY, expires_in: 2.minutes, disposition: :inline, filename: "test.txt", content_type: "text/plain")
37
+ end
38
+ end
39
+ end
40
+ else
41
+ puts "Skipping GCS Service tests because no GCS configuration was supplied"
42
+ end
@@ -0,0 +1,62 @@
1
+ require "service/shared_service_tests"
2
+
3
+ class ActiveStorage::Service::MirrorServiceTest < ActiveSupport::TestCase
4
+ mirror_config = (1..3).map do |i|
5
+ [ "mirror_#{i}",
6
+ service: "Disk",
7
+ root: Dir.mktmpdir("active_storage_tests_mirror_#{i}") ]
8
+ end.to_h
9
+
10
+ config = mirror_config.merge \
11
+ mirror: { service: "Mirror", primary: "primary", mirrors: mirror_config.keys },
12
+ primary: { service: "Disk", root: Dir.mktmpdir("active_storage_tests_primary") }
13
+
14
+ SERVICE = ActiveStorage::Service.configure :mirror, config
15
+
16
+ include ActiveStorage::Service::SharedServiceTests
17
+
18
+ test "uploading to all services" do
19
+ begin
20
+ data = "Something else entirely!"
21
+ key = upload(data, to: @service)
22
+
23
+ assert_equal data, SERVICE.primary.download(key)
24
+ SERVICE.mirrors.each do |mirror|
25
+ assert_equal data, mirror.download(key)
26
+ end
27
+ ensure
28
+ @service.delete key
29
+ end
30
+ end
31
+
32
+ test "downloading from primary service" do
33
+ data = "Something else entirely!"
34
+ key = upload(data, to: SERVICE.primary)
35
+
36
+ assert_equal data, @service.download(key)
37
+ end
38
+
39
+ test "deleting from all services" do
40
+ @service.delete FIXTURE_KEY
41
+ assert_not SERVICE.primary.exist?(FIXTURE_KEY)
42
+ SERVICE.mirrors.each do |mirror|
43
+ assert_not mirror.exist?(FIXTURE_KEY)
44
+ end
45
+ end
46
+
47
+ test "URL generation in primary service" do
48
+ freeze_time do
49
+ assert_equal SERVICE.primary.url(FIXTURE_KEY, expires_in: 2.minutes, disposition: :inline, filename: "test.txt", content_type: "text/plain"),
50
+ @service.url(FIXTURE_KEY, expires_in: 2.minutes, disposition: :inline, filename: "test.txt", content_type: "text/plain")
51
+ end
52
+ end
53
+
54
+ private
55
+ def upload(data, to:)
56
+ SecureRandom.base58(24).tap do |key|
57
+ io = StringIO.new(data).tap(&:read)
58
+ @service.upload key, io, checksum: Digest::MD5.base64digest(data)
59
+ assert io.eof?
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,52 @@
1
+ require "service/shared_service_tests"
2
+ require "httparty"
3
+
4
+ if SERVICE_CONFIGURATIONS[:s3]
5
+ class ActiveStorage::Service::S3ServiceTest < ActiveSupport::TestCase
6
+ SERVICE = ActiveStorage::Service.configure(:s3, SERVICE_CONFIGURATIONS)
7
+
8
+ include ActiveStorage::Service::SharedServiceTests
9
+
10
+ test "direct upload" do
11
+ begin
12
+ key = SecureRandom.base58(24)
13
+ data = "Something else entirely!"
14
+ checksum = Digest::MD5.base64digest(data)
15
+ url = @service.url_for_direct_upload(key, expires_in: 5.minutes, content_type: "text/plain", content_length: data.size, checksum: checksum)
16
+
17
+ HTTParty.put(
18
+ url,
19
+ body: data,
20
+ headers: { "Content-Type" => "text/plain", "Content-MD5" => checksum },
21
+ debug_output: STDOUT
22
+ )
23
+
24
+ assert_equal data, @service.download(key)
25
+ ensure
26
+ @service.delete key
27
+ end
28
+ end
29
+
30
+ test "signed URL generation" do
31
+ assert_match /#{SERVICE_CONFIGURATIONS[:s3][:bucket]}\.s3.(\S+)?amazonaws.com.*response-content-disposition=inline.*avatar\.png.*response-content-type=image%2Fpng/,
32
+ @service.url(FIXTURE_KEY, expires_in: 5.minutes, disposition: :inline, filename: "avatar.png", content_type: "image/png")
33
+ end
34
+
35
+ test "uploading with server-side encryption" do
36
+ config = SERVICE_CONFIGURATIONS.deep_merge(s3: { upload: { server_side_encryption: "AES256" }})
37
+ service = ActiveStorage::Service.configure(:s3, config)
38
+
39
+ begin
40
+ key = SecureRandom.base58(24)
41
+ data = "Something else entirely!"
42
+ service.upload key, StringIO.new(data), checksum: Digest::MD5.base64digest(data)
43
+
44
+ assert_equal "AES256", service.bucket.object(key).server_side_encryption
45
+ ensure
46
+ service.delete key
47
+ end
48
+ end
49
+ end
50
+ else
51
+ puts "Skipping S3 Service tests because no S3 configuration was supplied"
52
+ end
@@ -0,0 +1,66 @@
1
+ require "test_helper"
2
+
3
+ module ActiveStorage::Service::SharedServiceTests
4
+ extend ActiveSupport::Concern
5
+
6
+ FIXTURE_KEY = SecureRandom.base58(24)
7
+ FIXTURE_DATA = "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\000\020\000\000\000\020\001\003\000\000\000%=m\"\000\000\000\006PLTE\000\000\000\377\377\377\245\331\237\335\000\000\0003IDATx\234c\370\377\237\341\377_\206\377\237\031\016\2603\334?\314p\1772\303\315\315\f7\215\031\356\024\203\320\275\317\f\367\201R\314\f\017\300\350\377\177\000Q\206\027(\316]\233P\000\000\000\000IEND\256B`\202".force_encoding(Encoding::BINARY)
8
+
9
+ included do
10
+ setup do
11
+ @service = self.class.const_get(:SERVICE)
12
+ @service.upload FIXTURE_KEY, StringIO.new(FIXTURE_DATA)
13
+ end
14
+
15
+ teardown do
16
+ @service.delete FIXTURE_KEY
17
+ end
18
+
19
+ test "uploading with integrity" do
20
+ begin
21
+ key = SecureRandom.base58(24)
22
+ data = "Something else entirely!"
23
+ @service.upload(key, StringIO.new(data), checksum: Digest::MD5.base64digest(data))
24
+
25
+ assert_equal data, @service.download(key)
26
+ ensure
27
+ @service.delete key
28
+ end
29
+ end
30
+
31
+ test "uploading without integrity" do
32
+ begin
33
+ key = SecureRandom.base58(24)
34
+ data = "Something else entirely!"
35
+
36
+ assert_raises(ActiveStorage::IntegrityError) do
37
+ @service.upload(key, StringIO.new(data), checksum: Digest::MD5.base64digest("bad data"))
38
+ end
39
+
40
+ assert_not @service.exist?(key)
41
+ ensure
42
+ @service.delete key
43
+ end
44
+ end
45
+
46
+ test "downloading" do
47
+ assert_equal FIXTURE_DATA, @service.download(FIXTURE_KEY)
48
+ end
49
+
50
+ test "existing" do
51
+ assert @service.exist?(FIXTURE_KEY)
52
+ assert_not @service.exist?(FIXTURE_KEY + "nonsense")
53
+ end
54
+
55
+ test "deleting" do
56
+ @service.delete FIXTURE_KEY
57
+ assert_not @service.exist?(FIXTURE_KEY)
58
+ end
59
+
60
+ test "deleting nonexistent key" do
61
+ assert_nothing_raised do
62
+ @service.delete SecureRandom.base58(24)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,6 @@
1
+ module SidekiqMinitestSupport
2
+ def after_teardown
3
+ Sidekiq::Worker.clear_all
4
+ super
5
+ end
6
+ end
@@ -0,0 +1,20 @@
1
+ require 'minitest/mock'
2
+
3
+ module Assertions
4
+ def assert_not(object, message = nil)
5
+ message ||= "Expected #{object} to be nil or false"
6
+ assert !object, message
7
+ end
8
+
9
+ def freeze_time(&block)
10
+ if block
11
+ reference_date = Time.now
12
+
13
+ Time.stub :now, reference_date do
14
+ block.call
15
+ end
16
+ else
17
+ block.call
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,69 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter %r{^/test/}
4
+ end
5
+
6
+ require File.expand_path("../../test/dummy/config/environment.rb", __FILE__)
7
+
8
+ require "bundler/setup"
9
+
10
+ require "test/unit/active_support"
11
+
12
+ require "active_support"
13
+ require "active_support/test_case"
14
+
15
+ require "byebug"
16
+ require "sidekiq"
17
+ require 'sidekiq/testing'
18
+ require "sidekiq/minitest_support"
19
+
20
+ require "active_storage"
21
+
22
+ require "yaml"
23
+ SERVICE_CONFIGURATIONS = begin
24
+ YAML.load_file(File.expand_path("../service/configurations.yml", __FILE__)).deep_symbolize_keys
25
+ rescue Errno::ENOENT
26
+ puts "Missing service configuration file in test/service/configurations.yml"
27
+ {}
28
+ end
29
+
30
+ require "tmpdir"
31
+ require 'active_storage/service/disk_service'
32
+ require 'support/assertions'
33
+
34
+ ActiveStorage::Blob.service = ActiveStorage::Service::DiskService.new(root: Dir.mktmpdir("active_storage_tests"))
35
+ ActiveStorage::Service.logger = ::Logger.new(STDOUT)
36
+
37
+ ActiveStorage.verifier = ActiveStorage::Verifier.new('Testing')
38
+
39
+ class ActiveSupport::TestCase
40
+ include Assertions
41
+ include SidekiqMinitestSupport
42
+
43
+ private
44
+ def create_blob(data: "Hello world!", filename: "hello.txt", content_type: "text/plain")
45
+ ActiveStorage::Blob.create_after_upload! io: StringIO.new(data), filename: filename, content_type: content_type
46
+ end
47
+
48
+ def create_image_blob(filename: "racecar.jpg", content_type: "image/jpeg")
49
+ ActiveStorage::Blob.create_after_upload! \
50
+ io: file_fixture(filename).open,
51
+ filename: filename, content_type: content_type
52
+ end
53
+
54
+ def create_blob_before_direct_upload(filename: "hello.txt", byte_size:, checksum:, content_type: "text/plain")
55
+ ActiveStorage::Blob.create_before_direct_upload! filename: filename, byte_size: byte_size, checksum: checksum, content_type: content_type
56
+ end
57
+
58
+ def read_image_variant(variant)
59
+ MiniMagick::Image.open variant.service.send(:path_for, variant.key)
60
+ end
61
+
62
+ def file_fixture(filename)
63
+ Pathname(File.join(file_fixture_path, filename))
64
+ end
65
+
66
+ def file_fixture_path
67
+ File.expand_path("../fixtures/files", __FILE__)
68
+ end
69
+ end
data/webpack.config.js ADDED
@@ -0,0 +1,27 @@
1
+ const webpack = require("webpack")
2
+ const path = require("path")
3
+
4
+ module.exports = {
5
+ entry: {
6
+ "activestorage": path.resolve(__dirname, "app/javascript/activestorage/index.js"),
7
+ },
8
+
9
+ output: {
10
+ filename: "[name].js",
11
+ path: path.resolve(__dirname, "app/assets/javascripts"),
12
+ library: "ActiveStorage",
13
+ libraryTarget: "umd"
14
+ },
15
+
16
+ module: {
17
+ rules: [
18
+ {
19
+ test: /\.js$/,
20
+ exclude: /node_modules/,
21
+ use: {
22
+ loader: "babel-loader"
23
+ }
24
+ }
25
+ ]
26
+ }
27
+ }