Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add have rich text matcher #1263

Merged
merged 1 commit into from
Jan 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Appraisals
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ if Gem::Requirement.new('>= 2.5.0').satisfied_by?(Gem::Version.new(RUBY_VERSION)
gem 'selenium-webdriver'
gem 'webdrivers'

# Other dependencies
gem 'actiontext', '~> 6.0.2.1'

# Database adapters
gem 'pg', '>= 0.18', '< 2.0'
gem 'sqlite3', '~> 1.4'
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,8 @@ about any of them, make sure to [consult the documentation][rubydocs]!
tests your `has_one` associations.
* **[have_readonly_attribute](lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb)**
tests usage of the `attr_readonly` macro.
* **[have_rich_text](lib/shoulda/matchers/active_record/have_rich_text_matcher.rb)**
tests your `has_rich_text` associations.
* **[serialize](lib/shoulda/matchers/active_record/serialize_matcher.rb)** tests
usage of the `serialize` macro.
* **[validate_uniqueness_of](lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb)**
Expand Down
1 change: 1 addition & 0 deletions gemfiles/rails_6_0.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ gem "listen", ">= 3.0.5", "< 3.2"
gem "spring-watcher-listen", "~> 2.0.0"
gem "selenium-webdriver"
gem "webdrivers"
gem "actiontext", "~> 6.0.2.1"
gem "pg", ">= 0.18", "< 2.0"
gem "sqlite3", "~> 1.4"
1 change: 1 addition & 0 deletions gemfiles/rails_6_0.gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ PLATFORMS
ruby

DEPENDENCIES
actiontext (~> 6.0.2.1)
appraisal (= 2.2.0)
bcrypt (~> 3.1.7)
bootsnap (>= 1.4.2)
Expand Down
1 change: 1 addition & 0 deletions lib/shoulda/matchers/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
require "shoulda/matchers/active_record/have_db_column_matcher"
require "shoulda/matchers/active_record/have_db_index_matcher"
require "shoulda/matchers/active_record/have_readonly_attribute_matcher"
require "shoulda/matchers/active_record/have_rich_text_matcher"
require "shoulda/matchers/active_record/have_secure_token_matcher"
require "shoulda/matchers/active_record/serialize_matcher"
require "shoulda/matchers/active_record/accept_nested_attributes_for_matcher"
Expand Down
79 changes: 79 additions & 0 deletions lib/shoulda/matchers/active_record/have_rich_text_matcher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
module Shoulda
module Matchers
module ActiveRecord
# The `have_rich_text` matcher tests usage of the
# `has_rich_text` macro.
#
# #### Example
#
# class Post < ActiveRecord
# has_rich_text :content
# end
#
# # RSpec
# RSpec.describe Post, type: :model do
# it { is_expected.to have_rich_text(:content) }
# end
#
# # Minitest (Shoulda)
# class PostTest < ActiveSupport::TestCase
# should have_rich_text(:content)
# end
#
# @return [HaveRichText]
#
def have_rich_text(rich_text_attribute)
HaveRichText.new(rich_text_attribute)
end

# @private
class HaveRichText
def initialize(rich_text_attribute)
@rich_text_attribute = rich_text_attribute
end

def description
"have configured :#{rich_text_attribute} as a ActionText::RichText association"
end

def failure_message
"Expected #{subject.class} to #{error_description}"
end

def failure_message_when_negated
"Did not expect #{subject.class} to have ActionText::RichText :#{rich_text_attribute}"
end

def matches?(subject)
@subject = subject
@error = run_checks
vsppedro marked this conversation as resolved.
Show resolved Hide resolved
@error.nil?
end

private

attr_reader :error, :rich_text_attribute, :subject

def run_checks
if !has_attribute?
":#{rich_text_attribute} does not exist"
elsif !has_expected_action_text?
:default
end
end

def has_attribute?
@subject.respond_to?(rich_text_attribute.to_s)
end

def has_expected_action_text?
@subject.send(rich_text_attribute).class.name == 'ActionText::RichText'
end

def error_description
error == :default ? description : "#{description} but #{error}"
end
end
end
end
end
11 changes: 11 additions & 0 deletions spec/support/unit/rails_application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ def create

def load
load_environment

if rails_version > 5 && bundle.includes?('actiontext')
add_action_text_migration
end

run_migrations
end

Expand Down Expand Up @@ -165,6 +170,12 @@ class DevelopmentRecord < ActiveRecord::Base
TEXT
end

def add_action_text_migration
fs.within_project do
run_command! 'bundle exec rake action_text:install:migrations'
end
end

def add_initializer_for_time_zone_aware_types
path = 'config/initializers/configure_time_zone_aware_types.rb'
fs.write(path, <<-TEXT)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
require 'unit_spec_helper'

describe Shoulda::Matchers::ActiveRecord::HaveRichText, type: :model do
def self.rich_text_is_defined?
defined?(ActionText::RichText)
end

context '#description' do
it 'returns the message including the name of the provided association' do
matcher = have_rich_text(:content)
expect(matcher.description).
to eq('have configured :content as a ActionText::RichText association')
end
end

if rich_text_is_defined?
context 'when the model has a RichText association' do
it 'matches when the subject configures has_rich_text' do
valid_record = new_post(is_rich_text_association: true)

expected_message = 'Did not expect Post to have ActionText::RichText :content'

expect { have_rich_text(:content) }.
to match_against(valid_record).
or_fail_with(expected_message)
end
end

context 'when the model does not have a RichText association' do
it 'does not match when provided with a model attribute that exist' do
invalid_record = new_post(has_invalid_content: true)
expected_message = 'Expected Post to have configured :invalid_content as a ' \
vsppedro marked this conversation as resolved.
Show resolved Hide resolved
'ActionText::RichText association'

expect { have_rich_text(:invalid_content) }.
not_to match_against(invalid_record).
and_fail_with(expected_message)
end

it 'does not match when provided with a model attribute that does not exist' do
invalid_record = new_post
expected_message = 'Expected Post to have configured :invalid_attribute as a ' \
'ActionText::RichText association but :invalid_attribute does not exist'

expect { have_rich_text(:invalid_attribute) }.
not_to match_against(invalid_record).
and_fail_with(expected_message)
end
end
else
it 'does not match when provided with a model attribute that exist' do
invalid_record = new_post(has_invalid_content: true)
expected_message = 'Expected Post to have configured :invalid_content as a ' \
'ActionText::RichText association'

expect { have_rich_text(:invalid_content) }.
not_to match_against(invalid_record).
and_fail_with(expected_message)
end

it 'does not match when provided with a model attribute that does not exist' do
invalid_record = new_post
expected_message = 'Expected Post to have configured :invalid_attribute as a ' \
'ActionText::RichText association but :invalid_attribute does not exist'

expect { have_rich_text(:invalid_attribute) }.
not_to match_against(invalid_record).
and_fail_with(expected_message)
end
end

def new_post(has_invalid_content: false, is_rich_text_association: false)
columns = {}

if has_invalid_content
columns[:invalid_content] = :string
end

define_model 'Post', columns do
if is_rich_text_association
has_rich_text :content
end
end.new
end
end