Skip to content

Commit

Permalink
Convert Alchemy::PictureView into ViewComponent
Browse files Browse the repository at this point in the history
  • Loading branch information
tvdeyen committed May 4, 2023
1 parent 25bac6b commit 2766040
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@

module Alchemy
# Renders a picture ingredient view
class PictureView
include ActionView::Helpers::AssetTagHelper
include ActionView::Helpers::UrlHelper
include Rails.application.routes.url_helpers

class PictureView < ViewComponent::Base
attr_reader :ingredient, :html_options, :options, :picture

DEFAULT_OPTIONS = {
Expand All @@ -16,14 +12,14 @@ class PictureView
sizes: []
}.with_indifferent_access

def initialize(ingredient, options = {}, html_options = {})
def initialize(ingredient, options: {}, html_options: {})
@ingredient = ingredient
@options = DEFAULT_OPTIONS.merge(ingredient.settings).merge(options || {})
@html_options = html_options || {}
@picture = ingredient.picture
end

def render
def call
return if picture.blank?

output = caption ? img_tag + caption : img_tag
Expand All @@ -43,6 +39,8 @@ def render
end
end

private

def caption
return unless show_caption?

Expand Down
7 changes: 3 additions & 4 deletions app/views/alchemy/ingredients/_picture_view.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<%= Alchemy::PictureView.new(
<%= render Alchemy::PictureView.new(
picture_view,
local_assigns[:options],
local_assigns[:html_options]
).render %>
**local_assigns.slice(:options, :html_options)
) -%>
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

require "rails_helper"

RSpec.describe Alchemy::PictureView do
include Capybara::RSpecMatchers

RSpec.describe Alchemy::PictureView, type: :component do
let(:image) do
File.new(File.expand_path("../../fixtures/image.png", __dir__))
end
Expand Down Expand Up @@ -52,22 +50,24 @@
{}
end

subject(:view) do
described_class.new(ingredient, options, html_options).render
subject(:render_view) do
render_inline described_class.new(ingredient, options: options, html_options: html_options)
end

it "should enclose the image in a <figure> element" do
expect(view).to have_selector("figure img")
render_view
expect(page).to have_selector("figure img")
end

it "should show the caption" do
expect(view).to have_selector("figure figcaption")
expect(view).to have_content("This is a cute cat")
render_view
expect(page).to have_selector("figure figcaption")
expect(page).to have_content("This is a cute cat")
end

it "does not pass default options to picture url" do
expect(ingredient).to receive(:picture_url).with({}) { picture_url }
view
render_view
end

context "but disabled in the options" do
Expand All @@ -76,72 +76,77 @@
end

it "should not enclose the image in a <figure> element" do
expect(view).to_not have_selector("figure img")
render_view
expect(page).to_not have_selector("figure img")
end

it "should not show the caption" do
expect(view).to_not have_selector("figure figcaption")
expect(view).to_not have_content("This is a cute cat")
render_view
expect(page).to_not have_selector("figure figcaption")
expect(page).to_not have_content("This is a cute cat")
end
end

context "but disabled in the ingredient settings" do
before do
allow(ingredient).to receive(:settings).and_return({show_caption: false})
render_view
end

it "should not enclose the image in a <figure> element" do
expect(view).to_not have_selector("figure img")
expect(page).to_not have_selector("figure img")
end

it "should not show the caption" do
expect(view).to_not have_selector("figure figcaption")
expect(view).to_not have_content("This is a cute cat")
expect(page).to_not have_selector("figure figcaption")
expect(page).to_not have_content("This is a cute cat")
end

context "but enabled in the options hash" do
let(:options) { {show_caption: true} }

it "should enclose the image in a <figure> element" do
expect(view).to have_selector("figure img")
expect(page).to have_selector("figure img")
end

it "should show the caption" do
expect(view).to have_selector("figure figcaption")
expect(view).to have_content("This is a cute cat")
expect(page).to have_selector("figure figcaption")
expect(page).to have_content("This is a cute cat")
end
end
end

context "and ingredient with css class" do
before do
ingredient.css_class = "left"
render_view
end

it "should have the class on the <figure> element" do
expect(view).to have_selector("figure.left img")
expect(page).to have_selector("figure.left img")
end

it "should not have the class on the <img> element" do
expect(view).not_to have_selector("figure img.left")
expect(page).not_to have_selector("figure img.left")
end
end

context "and css class in the html_options" do
before do
html_options[:class] = "right"
render_view
end

it "should have the class from the html_options on the <figure> element" do
expect(view).to have_selector("figure.right img")
expect(page).to have_selector("figure.right img")
end

it "should not have the class from the ingredient on the <figure> element" do
expect(view).not_to have_selector("figure.left img")
expect(page).not_to have_selector("figure.left img")
end

it "should not have the class from the html_options on the <img> element" do
expect(view).not_to have_selector("figure img.right")
expect(page).not_to have_selector("figure img.right")
end
end
end
Expand All @@ -151,22 +156,24 @@
{}
end

subject(:view) do
subject(:render_view) do
ingredient.link = "/home"
described_class.new(ingredient, options).render
render_inline described_class.new(ingredient, options: options)
end

it "should enclose the image in a link tag" do
expect(view).to have_selector('a[href="/home"] img')
render_view
expect(page).to have_selector('a[href="/home"] img')
end

context "but disabled link option" do
before do
options[:disable_link] = true
render_view
end

it "should not enclose the image in a link tag" do
expect(view).not_to have_selector("a img")
expect(page).not_to have_selector("a img")
end
end
end
Expand All @@ -177,11 +184,11 @@
end

subject(:picture_view) do
described_class.new(ingredient, options)
described_class.new(ingredient, options: options)
end

it "does not overwrite DEFAULT_OPTIONS" do
described_class.new(ingredient, {my_custom_option: true})
described_class.new(ingredient, options: {my_custom_option: true})
expect(picture_view.options).to_not have_key(:my_custom_option)
end
end
Expand All @@ -193,8 +200,8 @@
end
end

subject(:view) do
described_class.new(ingredient).render
subject(:render_view) do
render_inline described_class.new(ingredient)
end

let(:srcset) do
Expand All @@ -203,7 +210,7 @@

it "does not pass srcset option to picture_url" do
expect(ingredient).to receive(:picture_url).with({}) { picture_url }
view
render_view
end

context "when only width or width and height are set" do
Expand All @@ -214,8 +221,8 @@
it "adds srcset attribute including image url and width for each size" do
url1 = ingredient.picture_url(size: "1024x768")
url2 = ingredient.picture_url(size: "800x")

expect(view).to have_selector("img[srcset=\"#{url1} 1024w, #{url2} 800w\"]")
render_view
expect(page).to have_selector("img[srcset=\"#{url1} 1024w, #{url2} 800w\"]")
end
end

Expand All @@ -227,19 +234,19 @@
it "adds srcset attribute including image url and height for each size" do
url1 = ingredient.picture_url(size: "x768")
url2 = ingredient.picture_url(size: "x600")

expect(view).to have_selector("img[srcset=\"#{url1} 768h, #{url2} 600h\"]")
render_view
expect(page).to have_selector("img[srcset=\"#{url1} 768h, #{url2} 600h\"]")
end
end
end

context "with no srcset ingredient setting" do
subject(:view) do
described_class.new(ingredient).render
subject!(:render_view) do
render_inline described_class.new(ingredient)
end

it "image tag has no srcset attribute" do
expect(view).not_to have_selector("img[srcset]")
expect(page).not_to have_selector("img[srcset]")
end
end

Expand All @@ -250,8 +257,8 @@
end
end

subject(:view) do
described_class.new(ingredient).render
subject(:render_view) do
render_inline described_class.new(ingredient)
end

let(:sizes) do
Expand All @@ -263,27 +270,28 @@

it "does not pass sizes option to picture_url" do
expect(ingredient).to receive(:picture_url).with({}) { picture_url }
view
render_view
end

it "adds sizes attribute for each size" do
expect(view).to have_selector("img[sizes=\"#{sizes[0]}, #{sizes[1]}\"]")
render_view
expect(page).to have_selector("img[sizes=\"#{sizes[0]}, #{sizes[1]}\"]")
end
end

context "with no sizes ingredient setting" do
subject(:view) do
described_class.new(ingredient).render
subject!(:render_view) do
render_inline described_class.new(ingredient)
end

it "image tag has no sizes attribute" do
expect(view).not_to have_selector("img[sizes]")
expect(page).not_to have_selector("img[sizes]")
end
end

describe "alt text" do
subject(:view) do
described_class.new(ingredient, {}, html_options).render
subject!(:render_view) do
render_inline described_class.new(ingredient, html_options: html_options)
end

let(:html_options) { {} }
Expand All @@ -296,7 +304,7 @@
end

it "uses this as image alt text" do
expect(view).to have_selector('img[alt="A cute cat"]')
expect(page).to have_selector('img[alt="A cute cat"]')
end
end

Expand All @@ -305,7 +313,7 @@
let(:html_options) { {alt: "Cute kittens"} }

it "uses this as image alt text" do
expect(view).to have_selector('img[alt="Cute kittens"]')
expect(page).to have_selector('img[alt="Cute kittens"]')
end
end

Expand All @@ -319,13 +327,13 @@
end

it "uses a humanized picture name as alt text" do
expect(view).to have_selector('img[alt="Cute kitty-cat"]')
expect(page).to have_selector('img[alt="Cute kitty-cat"]')
end
end

context "and no name on the picture" do
it "has no alt text" do
expect(view).to_not have_selector("img[alt]")
expect(page).to_not have_selector("img[alt]")
end
end
end
Expand Down
8 changes: 2 additions & 6 deletions spec/views/alchemy/ingredients/picture_view_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,8 @@
)
end

before do
expect_any_instance_of(Alchemy::PictureView).to receive(:render).and_call_original
end

it "renders an image tag" do
it "renders Alchemy::PictureView" do
expect_any_instance_of(Alchemy::PictureView).to receive(:call)
render ingredient
expect(rendered).to have_css("img")
end
end

0 comments on commit 2766040

Please sign in to comment.