diff --git a/Gemfile.lock b/Gemfile.lock index a2d9b25..57f3fa8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,107 +2,125 @@ PATH remote: . specs: next_gen_images (1.1.1) - rails (>= 3.1) - webp-ffi (~> 0.3.1) + rails (>= 7.1) + webp-ffi (~> 0.4.0) GEM remote: https://rubygems.org/ specs: - actioncable (7.0.4) - actionpack (= 7.0.4) - activesupport (= 7.0.4) + actioncable (7.1.4) + actionpack (= 7.1.4) + activesupport (= 7.1.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (7.0.4) - actionpack (= 7.0.4) - activejob (= 7.0.4) - activerecord (= 7.0.4) - activestorage (= 7.0.4) - activesupport (= 7.0.4) + zeitwerk (~> 2.6) + actionmailbox (7.1.4) + actionpack (= 7.1.4) + activejob (= 7.1.4) + activerecord (= 7.1.4) + activestorage (= 7.1.4) + activesupport (= 7.1.4) mail (>= 2.7.1) net-imap net-pop net-smtp - actionmailer (7.0.4) - actionpack (= 7.0.4) - actionview (= 7.0.4) - activejob (= 7.0.4) - activesupport (= 7.0.4) + actionmailer (7.1.4) + actionpack (= 7.1.4) + actionview (= 7.1.4) + activejob (= 7.1.4) + activesupport (= 7.1.4) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp - rails-dom-testing (~> 2.0) - actionpack (7.0.4) - actionview (= 7.0.4) - activesupport (= 7.0.4) - rack (~> 2.0, >= 2.2.0) + rails-dom-testing (~> 2.2) + actionpack (7.1.4) + actionview (= 7.1.4) + activesupport (= 7.1.4) + nokogiri (>= 1.8.5) + racc + rack (>= 2.2.4) + rack-session (>= 1.0.1) rack-test (>= 0.6.3) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (7.0.4) - actionpack (= 7.0.4) - activerecord (= 7.0.4) - activestorage (= 7.0.4) - activesupport (= 7.0.4) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + actiontext (7.1.4) + actionpack (= 7.1.4) + activerecord (= 7.1.4) + activestorage (= 7.1.4) + activesupport (= 7.1.4) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.0.4) - activesupport (= 7.0.4) + actionview (7.1.4) + activesupport (= 7.1.4) builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (7.0.4) - activesupport (= 7.0.4) + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + activejob (7.1.4) + activesupport (= 7.1.4) globalid (>= 0.3.6) - activemodel (7.0.4) - activesupport (= 7.0.4) - activerecord (7.0.4) - activemodel (= 7.0.4) - activesupport (= 7.0.4) - activestorage (7.0.4) - actionpack (= 7.0.4) - activejob (= 7.0.4) - activerecord (= 7.0.4) - activesupport (= 7.0.4) + activemodel (7.1.4) + activesupport (= 7.1.4) + activerecord (7.1.4) + activemodel (= 7.1.4) + activesupport (= 7.1.4) + timeout (>= 0.4.0) + activestorage (7.1.4) + actionpack (= 7.1.4) + activejob (= 7.1.4) + activerecord (= 7.1.4) + activesupport (= 7.1.4) marcel (~> 1.0) - mini_mime (>= 1.1.0) - activesupport (7.0.4) + activesupport (7.1.4) + base64 + bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb i18n (>= 1.6, < 2) minitest (>= 5.1) + mutex_m tzinfo (~> 2.0) - addressable (2.8.4) - public_suffix (>= 2.0.2, < 6.0) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) ast (2.4.2) - builder (3.2.4) - carrierwave (2.2.3) - activemodel (>= 5.0.0) - activesupport (>= 5.0.0) + base64 (0.2.0) + bigdecimal (3.1.8) + builder (3.3.0) + carrierwave (3.0.7) + activemodel (>= 6.0.0) + activesupport (>= 6.0.0) addressable (~> 2.6) image_processing (~> 1.1) marcel (~> 1.0.0) - mini_mime (>= 0.1.3) ssrf_filter (~> 1.0) - concurrent-ruby (1.1.10) + concurrent-ruby (1.3.4) + connection_pool (2.4.1) crass (1.0.6) - date (3.3.3) - diff-lcs (1.5.0) - erubi (1.12.0) - ffi (1.15.5) - ffi-compiler (1.0.1) - ffi (>= 1.0.0) + date (3.3.4) + diff-lcs (1.5.1) + drb (2.2.1) + erubi (1.13.0) + ffi (1.17.0) + ffi-compiler (1.3.2) + ffi (>= 1.15.5) rake - globalid (1.1.0) - activesupport (>= 5.0) - i18n (1.12.0) + globalid (1.2.1) + activesupport (>= 6.1) + i18n (1.14.5) concurrent-ruby (~> 1.0) - image_processing (1.12.2) + image_processing (1.13.0) mini_magick (>= 4.9.5, < 5) ruby-vips (>= 2.0.17, < 3) - json (2.6.2) - loofah (2.21.3) + io-console (0.7.2) + irb (1.14.0) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + json (2.7.2) + language_server-protocol (3.17.0.3) + logger (1.6.1) + loofah (2.22.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) @@ -110,104 +128,123 @@ GEM net-imap net-pop net-smtp - marcel (1.0.2) - method_source (1.0.0) - mini_magick (4.12.0) - mini_mime (1.1.2) - minitest (5.16.3) - net-imap (0.3.4) + marcel (1.0.4) + mini_magick (4.13.2) + mini_mime (1.1.5) + minitest (5.25.1) + mutex_m (0.2.0) + net-imap (0.4.16) date net-protocol net-pop (0.1.2) net-protocol - net-protocol (0.2.1) + net-protocol (0.2.2) timeout - net-smtp (0.3.3) + net-smtp (0.5.0) net-protocol - nio4r (2.5.9) - nokogiri (1.15.2-arm64-darwin) + nio4r (2.7.3) + nokogiri (1.16.7-arm64-darwin) racc (~> 1.4) - parallel (1.22.1) - parser (3.1.2.1) + nokogiri (1.16.7-x86_64-linux) + racc (~> 1.4) + parallel (1.26.3) + parser (3.3.5.0) ast (~> 2.4.1) - public_suffix (5.0.1) - racc (1.6.2) - rack (2.2.7) + racc + psych (5.1.2) + stringio + public_suffix (6.0.1) + racc (1.8.1) + rack (3.1.7) + rack-session (2.0.0) + rack (>= 3.0.0) rack-test (2.1.0) rack (>= 1.3) - rails (7.0.4) - actioncable (= 7.0.4) - actionmailbox (= 7.0.4) - actionmailer (= 7.0.4) - actionpack (= 7.0.4) - actiontext (= 7.0.4) - actionview (= 7.0.4) - activejob (= 7.0.4) - activemodel (= 7.0.4) - activerecord (= 7.0.4) - activestorage (= 7.0.4) - activesupport (= 7.0.4) + rackup (2.1.0) + rack (>= 3) + webrick (~> 1.8) + rails (7.1.4) + actioncable (= 7.1.4) + actionmailbox (= 7.1.4) + actionmailer (= 7.1.4) + actionpack (= 7.1.4) + actiontext (= 7.1.4) + actionview (= 7.1.4) + activejob (= 7.1.4) + activemodel (= 7.1.4) + activerecord (= 7.1.4) + activestorage (= 7.1.4) + activesupport (= 7.1.4) bundler (>= 1.15.0) - railties (= 7.0.4) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) + railties (= 7.1.4) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.5.0) - loofah (~> 2.19, >= 2.19.1) - railties (7.0.4) - actionpack (= 7.0.4) - activesupport (= 7.0.4) - method_source + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) + railties (7.1.4) + actionpack (= 7.1.4) + activesupport (= 7.1.4) + irb + rackup (>= 1.0.0) rake (>= 12.2) - thor (~> 1.0) - zeitwerk (~> 2.5) + thor (~> 1.0, >= 1.2.2) + zeitwerk (~> 2.6) rainbow (3.1.1) - rake (13.0.6) - regexp_parser (2.6.0) - rexml (3.2.5) - rspec (3.12.0) - rspec-core (~> 3.12.0) - rspec-expectations (~> 3.12.0) - rspec-mocks (~> 3.12.0) - rspec-core (3.12.0) - rspec-support (~> 3.12.0) - rspec-expectations (3.12.0) + rake (13.2.1) + rdoc (6.7.0) + psych (>= 4.0.0) + regexp_parser (2.9.2) + reline (0.5.10) + io-console (~> 0.5) + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.1) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.3) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) - rspec-mocks (3.12.0) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) - rspec-support (3.12.0) - rubocop (1.38.0) + rspec-support (~> 3.13.0) + rspec-support (3.13.1) + rubocop (1.66.1) json (~> 2.3) + language_server-protocol (>= 3.17.0) parallel (~> 1.10) - parser (>= 3.1.2.1) + parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.23.0, < 2.0) + regexp_parser (>= 2.4, < 3.0) + rubocop-ast (>= 1.32.2, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.23.0) - parser (>= 3.1.1.0) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.32.3) + parser (>= 3.3.1.0) rubocop-rspec (2.17.1) rubocop (~> 1.33) - ruby-progressbar (1.11.0) - ruby-vips (2.1.4) + ruby-progressbar (1.13.0) + ruby-vips (2.2.2) ffi (~> 1.12) - ssrf_filter (1.1.1) - thor (1.2.2) - timeout (0.3.2) - tzinfo (2.0.5) + logger + ssrf_filter (1.1.2) + stringio (3.1.1) + thor (1.3.2) + timeout (0.4.1) + tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicode-display_width (2.3.0) - webp-ffi (0.3.1) + unicode-display_width (2.5.0) + webp-ffi (0.4.0) ffi (>= 1.9.0) ffi-compiler (>= 0.1.2) - websocket-driver (0.7.5) + webrick (1.8.1) + websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - zeitwerk (2.6.8) + zeitwerk (2.6.18) PLATFORMS arm64-darwin-21 diff --git a/README.md b/README.md index d6df81e..c11582e 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,11 @@ ## Motivation -Currently Rails does not provide a `picture` HTML tag helper. An HTML `picture` tag provides [several advantages](https://blog.bitsrc.io/why-you-should-use-picture-tag-instead-of-img-tag-b9841e86bf8b) over an image tag, like fallback image support, resolution switching and art direction. -Also, most of a website assets are still JPEG or PNG images, and we don't want to convert our assets manually to WebP, we want this to happen automatically if it's needed. +*Update:* +Since Rails 7.1 and this [PR](https://github.com/rails/rails/pull/48100), Rails has a `picture` HTML tag helper. -This gem brings next gen image formats to Ruby on Rails. A `picture_tag` view helper is provided along several utilities to automatically convert them. Currently, it supports `WebP` images. A Carrierwave module with some utility methods is provided. +This gem provides helpers to simplify the transition to using WebP images in Ruby on Rails. +A Carrierwave module with some utility methods is provided. ## Installation @@ -23,93 +24,44 @@ Or add it to your application's Gemfile ```ruby gem 'next_gen_images' ``` -and then run +and then run ```bash bundle install ``` ## Usage -### View Helpers +### Asset conversion to public/assets for production usage -This gem adds support for a `picture_tag` helper. Syntax is the following: -``` -picture_tag SOURCE, PICTURE_TAG_OPTIONS, image: IMAGE_TAG_OPTIONS -``` - -This will output something like this: -```html - - - ... - - -``` - -Depending on your needs, you can use the `picture_tag` in 3 different ways: +A rake task called `next_gen_images:precompile` that precompiles all of your images to WebP is provided. You can enable it so it runs automatically when you do an `assets:precompile` via an initializer like this: -1. You can pass your existing image as the source, and add the `add_webp: true` option to automatically infer the `webp` image from the PNG/JPEG and add fallback image support. ```ruby -picture_tag 'satellite.png', image: { alt: 'satellite image', class: 'mt-0' }, add_webp: true -``` -This will create the following HTML: -```html - - - - satellite image - -``` - -2. If you want to manually specify your sources, you can pass an array of images to the `picture_tag`. This is extremely useful for dynamically generated images (that a user uploaded for example). -```ruby -picture_tag [post.cover_image.webp.medium.url, post.cover_image.medium.url], image: { alt: 'post image', class: 'rounded' } +NextGenImages.configure do |config| + config.run_on_precompile = true +end ``` -This will create the following HTML: -```html - - - - post image - +If you want to manually convert your images, you can run: +```bash +rake next_gen_images:precompile ``` +Assets will be compiled to `public/assets/` or the path that you specifed in `Rails.application.config.assets.prefix`. +The file names of the generated image assets will be in the format:`OLD_IMAGE.OLD_EXTENSION.webp` -3. The last option is to provide a block that will be inserted directly into the picture tag. This can be extremely useful for art direction. +### Asset conversion of /app/assets/images directory -```ruby -= picture_tag 'city.png', image: { alt: 'city image' } do - = source_tag srcset: "#{image_path('city_small.png')}.webp", type: 'image/webp', media: '(max-width: 1728px)' - = source_tag srcset: "#{image_path('city_big.png')}.webp", type: 'image/webp' - = source_tag srcset: image_path('city_small.png'), type: 'image/png', media: '(max-width: 1728px)' - = source_tag srcset: image_path('city_big.png'), type: 'image/png' -``` -Which will create the following HTML: -```html - - - - - - city image - -``` +In addition to the `next_gen_images:precompile` task, there's also a task to convert images in the `app/assets/images` directory to WebP. It leaves the original images untouched: -### Asset conversion - -A rake task called `assets:webp` that converts all of your images to WebP is provided. When you run the `assets:precompile` task, the `assets:webp` task will also run (via an `enhance` to the `assets:precompile` task) and automatically convert your images to WebP. -If you want to manually convert your images, you can run: ```bash -rake assets:webp +rake next_gen_images:convert_app_images ``` -Assets will be compiled to `public/assets/` or the path that you specifed in `Rails.application.config.assets.prefix`. -The file names of the generated image assets will be in the format:`OLD_IMAGE.OLD_EXTENSION.webp` +The file names of the generated image assets will be in the format `OLD_IMAGE.webp` and will be placed in the `app/assets/images` directory. ### ActiveStorage integration If you are using ActiveStorage you will need to first enable the `image_processing` gem. Usually, uncommenting this from your Gemfile: ``` -gem "image_processing", "~> 1.2" +gem "image_processing" ``` Then, you will need to install the VIPS image processing library binaries. Check the [VIPS Ruby wrapper gem](https://github.com/libvips/ruby-vips) for installation instructions for your OS. @@ -141,7 +93,6 @@ class User < ApplicationRecord end ``` - ### Carrierwave integration A `convert_to_webp` method that converts images to WebP is provided. You can send any encoding option available to [webp-ffi](https://github.com/le0pard/webp-ffi#encode-webp-image). diff --git a/lib/next_gen_images.rb b/lib/next_gen_images.rb index 31ec3d8..bb20850 100644 --- a/lib/next_gen_images.rb +++ b/lib/next_gen_images.rb @@ -3,7 +3,7 @@ require 'webp-ffi' require_relative 'next_gen_images/version' +require_relative 'next_gen_images/config' require_relative 'next_gen_images/railtie' if defined?(Rails) require_relative 'next_gen_images/engine' -require_relative 'next_gen_images/view_helpers' require_relative 'next_gen_images/carrierwave_helpers' diff --git a/lib/next_gen_images/config.rb b/lib/next_gen_images/config.rb new file mode 100644 index 0000000..88da8d0 --- /dev/null +++ b/lib/next_gen_images/config.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module NextGenImages + class << self + def configure + yield(config) + end + + def config + @config ||= Config.new + end + end + + class Config + attr_accessor :run_on_precompile + + def initialize + @run_on_precompile = false + end + end +end diff --git a/lib/next_gen_images/tasks/assets/webp.rake b/lib/next_gen_images/tasks/assets/webp.rake index 1362e76..6be896c 100644 --- a/lib/next_gen_images/tasks/assets/webp.rake +++ b/lib/next_gen_images/tasks/assets/webp.rake @@ -2,9 +2,9 @@ require 'webp-ffi' -namespace :assets do +namespace :next_gen_images do # rubocop:disable Metrics/BlockLength desc 'Create .webp versions of assets' - task webp: :environment do + task precompile: :environment do image_types = /\.(?:png|jpe?g)$/ public_assets = File.join( @@ -31,9 +31,26 @@ namespace :assets do end end - # Hook into existing assets:precompile task - Rake::Task['assets:precompile'].enhance do - # TODO: if defined?(NextGenImages) && NextGenImages.config.run_on_precompile - Rake::Task['assets:webp'].invoke + desc 'Convert JPEG/PNG images in app/assets/images to WebP' + task convert_app_images: :environment do + source_dir = Rails.root.join('app', 'assets', 'images') + + Dir.glob(File.join(source_dir, '**', '*.{jpg,jpeg,png}')).each do |image_path| + webp_path = image_path.sub(/\.(jpg|jpeg|png)$/i, '.webp') + + begin + WebP.encode(image_path, webp_path, lossless: 0, quality: 80, method: 6) + puts "Converted: #{image_path} -> #{webp_path}" + rescue StandardError => e + puts "Error converting #{image_path}: #{e.message}" + end + end + + puts 'Conversion complete. WebP images are in the same directories as the original images.' end end + +# Hook into existing assets:precompile task +Rake::Task['assets:precompile'].enhance do + Rake::Task['next_gen_images:precompile'].invoke if defined?(NextGenImages) && NextGenImages.config.run_on_precompile +end diff --git a/lib/next_gen_images/version.rb b/lib/next_gen_images/version.rb index 31e2a5f..f68ec18 100644 --- a/lib/next_gen_images/version.rb +++ b/lib/next_gen_images/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module NextGenImages - VERSION = '1.1.1' + VERSION = '1.2.0' end diff --git a/lib/next_gen_images/view_helpers.rb b/lib/next_gen_images/view_helpers.rb deleted file mode 100644 index b77d27d..0000000 --- a/lib/next_gen_images/view_helpers.rb +++ /dev/null @@ -1,87 +0,0 @@ -# frozen_string_literal: true - -require 'action_view' - -module NextGenImages - module ViewHelpers - def self.included(klass) - klass.class_eval do - include ActionView::Context - end - end - - def picture_tag(source, options = {}, &block) - picture_options = options.except(:image) - - content_tag :picture, picture_options do - build_picture_content(source, options, block) - end - end - - def source_tag(options = {}) - tag :source, options - end - - private - - def build_picture_content(source, options, block) - image_options = options.fetch(:image, {}) - image_options[:src] = build_img_src(source) - add_webp = options.fetch(:add_webp, false) - - content = ''.html_safe - if block.present? - content << capture(&block).html_safe - else - [source].flatten.each do |img_src| - content << build_source_from_img(image_path(img_src), add_webp) - end - end - content << tag('img', image_options) - end - - def build_img_src(source) - case source - when String - image_path(source) - when Array - image_path(source.last) - else - '' - end - end - - def build_source_from_img(img_path, add_webp) - source_tags = ''.html_safe - webp_path = "#{img_path}.webp" - # order of source tags matters - if add_webp && file_exist_in_public_path?(webp_path) - source_tags << source_tag(srcset: webp_path, type: 'image/webp') - end - source_tags + source_tag( - srcset: img_path, - type: image_type(img_path) - ) - end - - def image_type(image_path) - extension = File.extname(image_path) - Rack::Mime::MIME_TYPES.merge!({ - '.webp' => 'image/webp' - }) - Rack::Mime.mime_type(extension).to_s - end - - def file_exist_in_public_path?(path) - # for performance reasons, we assume production contains the asset - return true if ::Rails.env.production? - - public_path = File.join( - ::Rails.root, - 'public', - path - ) - File.exist?(public_path) - end - end -end diff --git a/next_gen_images.gemspec b/next_gen_images.gemspec index d71318f..33a656a 100644 --- a/next_gen_images.gemspec +++ b/next_gen_images.gemspec @@ -31,8 +31,8 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } spec.require_paths = ['lib'] - spec.add_runtime_dependency 'rails', '>= 3.1' - spec.add_runtime_dependency 'webp-ffi', '~> 0.3.1' + spec.add_dependency 'rails', '>= 7.1' + spec.add_dependency 'webp-ffi', '~> 0.4.0' spec.add_development_dependency 'bundler' spec.add_development_dependency 'carrierwave', '>= 2.0' spec.add_development_dependency 'rspec', '~> 3.12.0' diff --git a/spec/next_gen_images/config_spec.rb b/spec/next_gen_images/config_spec.rb new file mode 100644 index 0000000..1153a53 --- /dev/null +++ b/spec/next_gen_images/config_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'next_gen_images/config' + +RSpec.describe NextGenImages::Config do + describe '.configure' do + it 'yields the config object' do + expect { |b| NextGenImages.configure(&b) }.to yield_with_args(NextGenImages.config) + end + + it 'allows setting configuration options' do + NextGenImages.configure do |config| + config.run_on_precompile = true + end + + expect(NextGenImages.config.run_on_precompile).to be true + end + end + + describe '.config' do + it 'returns a Config instance' do + expect(NextGenImages.config).to be_an_instance_of(described_class) + end + end + + describe NextGenImages::Config do + describe '#initialize' do + it 'sets default values' do + config = described_class.new + expect(config.run_on_precompile).to be false + end + end + + describe '#run_on_precompile' do + it 'can be set and retrieved' do + config = described_class.new + config.run_on_precompile = true + expect(config.run_on_precompile).to be true + end + end + end +end diff --git a/spec/next_gen_images/view_helpers_spec.rb b/spec/next_gen_images/view_helpers_spec.rb deleted file mode 100644 index 31cc892..0000000 --- a/spec/next_gen_images/view_helpers_spec.rb +++ /dev/null @@ -1,142 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe NextGenImages::ViewHelpers, type: :helper do - # For Rack::Mime usage - include ::Rack - include described_class - include ActionView::Helpers - include ActionView::Helpers::TagHelper - - it 'has a version number' do - expect(NextGenImages::VERSION).not_to be_nil - end - - describe '#picture_tag' do - let(:source) { 'example.png' } - let(:options) { {} } - let(:result) { picture_tag(source, options) } - - it 'wraps everything in a picture tag' do - expect(result).to match(Regexp.new('\\A.*?\\z')) - end - - it 'adds an img tag at the end' do - expect(result).to match(Regexp.new('.*')) - end - - context 'when passing image options' do - let(:options) { { image: { alt: 'laptop', class: 'position-absolute' } } } - - it 'passes image options to the img tag' do - expect(result).to include( - "\"laptop\"') - end - end - - describe '#file_exist_in_public_path?' do - let(:path) { 'test_file.txt' } - - context 'when environment is production' do - before do - allow(::Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('production')) - end - - it 'returns true' do - expect(file_exist_in_public_path?(path)).to be(true) - end - end - - context 'when environment is not production' do - before do - allow(::Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('development')) - allow(::Rails).to receive(:root).and_return('/tmp') - end - - context 'when file exists in public path' do - before do - allow(File).to receive(:exist?).and_return(true) - end - - it 'returns true' do - expect(file_exist_in_public_path?(path)).to be(true) - end - end - - context 'when file does not exist in public path' do - before do - allow(File).to receive(:exist?).and_return(false) - end - - it 'returns false' do - expect(file_exist_in_public_path?(path)).to be(false) - end - end - end - end -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c83a9da..c4b314b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true +require 'active_support' require 'next_gen_images' -require 'rails' RSpec.configure do |config| # Enable flags like --only-failures and --next-failure