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

Introducing first Reform matcher validate_presence_of #4

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
/pkg/
/spec/reports/
/tmp/
.rubocop-https*
.byebug_history
/log/
5 changes: 5 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
AllCops:
TargetRubyVersion: '2.3'

inherit_from:
- https://raw.githubusercontent.com/trailblazer/meta/master/rubocop.yml
36 changes: 34 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,36 @@
language: ruby
cache: bundler
before_install:
- gem update --system
- gem install bundler
rvm:
- 2.2.3
before_install: gem install bundler -v 1.10.6
- 2.4.6
- 2.5.5
- 2.6.3
env:
- "RAILS_VERSION=6.0.0"
- "RAILS_VERSION=5.2.0"
- "RAILS_VERSION=5.1.0"
- "RAILS_VERSION=5.0.0"
- "RAILS_VERSION=4.2.0"
- "RAILS_VERSION=4.1.0"
- "RAILS_VERSION=4.0.0"
matrix:
fast_finish: true
exclude:
- rvm: 2.4.6
env: "RAILS_VERSION=4.0.0"
- rvm: 2.4.6
env: "RAILS_VERSION=4.1.0"
- rvm: 2.4.6
env: "RAILS_VERSION=6.0.0"

- rvm: 2.5.5
env: "RAILS_VERSION=4.0.0"
- rvm: 2.5.5
env: "RAILS_VERSION=4.1.0"

- rvm: 2.6.3
env: "RAILS_VERSION=4.0.0"
- rvm: 2.6.3
env: "RAILS_VERSION=4.1.0"
18 changes: 17 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
source 'https://rubygems.org'
source "https://rubygems.org"

# Specify your gem's dependencies in rspec-trailblazer.gemspec
gemspec

gem "pry"
gem "dry-validation", "< 1.0"
gem "reform", "2.3.0.rc1"
gem "reform-rails", "0.2.0.rc2"

rails_version = ENV.fetch("RAILS_VERSION", "5.2.0")

gem "activerecord", "~> #{rails_version}"
gem "railties", "~> #{rails_version}"
if rails_version.include?("6.0")
gem "sqlite3", "~> 1.4"
else
gem "sqlite3", "~> 1.3", "< 1.4"
end
puts "Rails version #{rails_version}"
4 changes: 4 additions & 0 deletions lib/rspec/trailblazer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ module Trailblazer
module Operation
end

module Reform
end

Operation.autoload :Matchers, 'rspec/trailblazer/operation/matchers'
Reform.autoload :Matchers, 'rspec/trailblazer/reform/matchers'
end
end
35 changes: 35 additions & 0 deletions lib/rspec/trailblazer/reform/matchers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
require "rspec/trailblazer/support/reform"

module RSpec::Trailblazer::Reform
module Matchers
extend ::RSpec::Matchers::DSL
include Support::Reform

VALID_OPTIONS = %i[nested_property nested_collection].freeze

matcher :validate_presence_of do |column, options = {}|
match do |form|
invalid_options = options.keys - VALID_OPTIONS
raise "Incorrect options passed #{invalid_options.join(" - ")}" if invalid_options.any?

@_column = column
@_form = form
@_options = options
@_params = _params
@_validate = _validate(@_form, @_params)
@_error_keys = _find_error_key

@_validate == false && @_error_keys.empty?
end

failure_message do |form|
msg = "expected #{form.class.name} to validate presence of #{column}"
msg += " in #{_nested_option}" if _nested_option
msg += " using as params #{@_params}"
msg += " but validations didn't fail" if @_validate
msg += " but #{@_error_keys} were not found in the error message" if @_error_keys.any? && !@_validate
msg
end
end
end
end
32 changes: 32 additions & 0 deletions lib/rspec/trailblazer/support/reform.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module Support
module Reform
def _validate(form, params)
form.validate(params)
end

def _params
params = Hash[Array(@_column).map { |x| [x, nil] }]

if _nested_option
nested_params = {}
nested_params[_nested_option] = (@_options[:nested_collection] ? [params] : params)
params = nested_params
end
params
end

def _find_error_key
keys = Array(@_column).map { |key| [_nested_option, key].compact.join(".").to_sym }

keys - _errors_keys
end

def _errors_keys
@_form.errors.messages.keys
end

def _nested_option
@_options[:nested_property] || @_options[:nested_collection]
end
end
end
3 changes: 2 additions & 1 deletion rspec-trailblazer.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
spec.require_paths = ["lib"]

spec.add_dependency "rspec"
spec.add_development_dependency "bundler", "~> 1.10"
spec.add_development_dependency "bundler"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rubocop"
end
47 changes: 45 additions & 2 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,45 @@
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
require 'rspec/trailblazer'
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
require "rspec/trailblazer"

include RSpec::Trailblazer::Reform::Matchers

# Load the rails application
require "active_model/railtie"

Bundler.require

module Dummy
class Application < Rails::Application
config.eager_load = false
config.active_support.deprecation = :stderr
end
end

# Initialize the rails application
Dummy::Application.initialize!

require "active_record"
class Artist < ActiveRecord::Base
end

class Song < ActiveRecord::Base
belongs_to :artist
end

class Album < ActiveRecord::Base
has_many :songs
end

ActiveRecord::Base.establish_connection :adapter => "sqlite3",
:database => ":memory:"
ActiveRecord::Schema.verbose = false
load "#{File.dirname(__FILE__)}/support/schema.rb"

require "reform/form/dry"
class DryVForm < Reform::Form
feature Reform::Form::Dry
end

class RailsForm < Reform::Form
feature ActiveModel::Validations
end
22 changes: 22 additions & 0 deletions spec/support/schema.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
ActiveRecord::Schema.define(version: 1) do
create_table "songs" do |t|
t.string "title"
t.date "release_date"
t.integer "artist_id"
t.integer "album_id"
t.datetime "created_at"
t.datetime "updated_at"
end

create_table "artists" do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end

create_table "albums" do |t|
t.string "title"
t.datetime "created_at"
t.datetime "updated_at"
end
end
95 changes: 95 additions & 0 deletions spec/trailblazer/reform_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
require "spec_helper"

describe RSpec::Trailblazer::Reform do
shared_examples "#validate_presence_of" do
it { expect(album_form).to validate_presence_of(:title) }
it { expect(album_form).to validate_presence_of(%i[title release_date], nested_collection: :songs) }
it { expect(song_form).to validate_presence_of(:name, nested_property: :artist) }

it "raise an error if passing the wrong option" do
expect {
expect(album_form).to validate_presence_of(%i[title release_date], something: :songs)
}.to raise_error(RuntimeError, "Incorrect options passed something")
end
end

context "AR validations" do
class AlbumForm < RailsForm
model :album

property :title
validates :title, presence: true

collection :songs, populate_if_empty: Song do
property :title
property :release_date

validates :title, :release_date, presence: true

property :artist, populate_if_empty: Artist do
property :name

validates :name, presence: true
end
end
end

class SongForm < RailsForm
model :song

property :artist, populate_if_empty: Artist do
property :name

validates :name, presence: true
end
end

let(:album_form) { AlbumForm.new(Album.new) }
let(:song_form) { SongForm.new(Song.new) }

it_behaves_like "#validate_presence_of"
end

context "dry-v" do
class DryAlbumForm < DryVForm
property :title

validation do
required(:title).filled
end

collection :songs, populate_if_empty: Song do
property :title
property :release_date

validation do
required(:title).filled
required(:release_date).filled
end

property :artist, populate_if_empty: Artist do
property :name

validation do
required(:name).filled
end
end
end
end

class DrySongForm < DryVForm
property :artist, populate_if_empty: Artist do
property :name

validation do
required(:name).filled
end
end
end

let(:album_form) { DryAlbumForm.new(Album.new) }
let(:song_form) { DrySongForm.new(Song.new) }

it_behaves_like "#validate_presence_of"
end
end