# frozen_string_literal: true
require 'spec_helper'
RSpec.describe SafeFormatHelper, feature_category: :shared do
describe '#safe_format' do
shared_examples 'safe formatting' do
subject { helper.safe_format(format, args) }
it { is_expected.to eq(result) }
it { is_expected.to be_html_safe }
end
it_behaves_like 'safe formatting' do
let(:format) { '' }
let(:args) { {} }
let(:result) { '' }
end
it_behaves_like 'safe formatting' do
let(:format) { 'Foo' }
let(:args) { {} }
let(:result) { 'Foo' }
end
it_behaves_like 'safe formatting' do
let(:format) { 'strong' }
let(:args) { {} }
let(:result) { '<b>strong</b>' }
end
it_behaves_like 'safe formatting' do
let(:format) { '%{open}strong%{close}' }
let(:args) { { open: ''.html_safe, close: ''.html_safe } }
let(:result) { 'strong' }
end
it_behaves_like 'safe formatting' do
let(:format) { '%{open}strong%{close} %{user_input}' }
let(:args) do
{ open: ''.html_safe, close: ''.html_safe,
user_input: 'link' }
end
let(:result) { 'strong <a href="">link</a>' }
end
context 'when format is marked as html_safe' do
it_behaves_like 'safe formatting' do
let(:format) { 'strong'.html_safe }
let(:args) { {} }
let(:result) { '<b>strong</b>' }
end
end
context 'with multiple args' do
it_behaves_like 'safe formatting' do
let(:format) { '%{a}c%{b} %{x}z%{y}' }
let(:args) do
[
{ a: ''.html_safe, b: ''.html_safe },
# Demonstrate shadowing
{ x: ''.html_safe, y: ''.html_safe },
{ x: ''.html_safe, y: ''.html_safe }
]
end
let(:result) { 'c z' }
subject { helper.safe_format(format, *args) }
end
end
context 'with a view component' do
let(:view_component) do
Class.new(ViewComponent::Base) do
include SafeFormatHelper
def call
safe_format('%{value}', value: '
')
end
end
end
it 'safetly formats' do
expect(view_component.new.call)
.to eq('<b><br></b>')
end
end
context 'with format containing escaped entities' do
it_behaves_like 'safe formatting' do
let(:format) { 'In < hour' }
let(:args) { {} }
let(:result) { 'In < hour' }
end
it_behaves_like 'safe formatting' do
let(:format) { '"air"' }
let(:args) { {} }
let(:result) { '"air"' }
end
it_behaves_like 'safe formatting' do
let(:format) { 'Mix & match > all' }
let(:args) { {} }
let(:result) { 'Mix & match > all' }
end
end
end
describe '#tag_pair' do
using RSpec::Parameterized::TableSyntax
let(:tag) { plain_tag.html_safe }
let(:open_name) { :tag_open }
let(:close_name) { :tag_close }
subject(:result) { tag_pair(tag, open_name, close_name) }
where(:plain_tag, :open, :close) do
'' | nil | nil
'a' | nil | nil
'' | nil | nil
'' | nil | nil
'' | nil | nil
'' | '' | ''
'x' | '' | ''
end
with_them do
if params[:open] && params[:close]
it { is_expected.to eq({ open_name => open, close_name => close }) }
specify { expect(result.values).to be_all(&:html_safe?) }
else
it { is_expected.to eq({}) }
end
end
context 'when tag is not html_safe' do
# `to_str` turns a html_safe string into a plain String.
let(:tag) { helper.tag.strong.to_str }
it 'raises an ArgumentError' do
expect { result }.to raise_error ArgumentError, 'Argument `tag` must be `html_safe`!'
end
end
end
end