smart_rspec 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +0 -15
- data/lib/smart_rspec/macros.rb +2 -3
- data/lib/smart_rspec/matchers/be_matchers.rb +0 -6
- data/lib/smart_rspec/matchers/json_api_matchers.rb +43 -0
- data/lib/smart_rspec/matchers/other_matchers.rb +0 -1
- data/lib/smart_rspec/matchers.rb +3 -1
- data/lib/smart_rspec/support/controller/response.rb +47 -0
- data/lib/smart_rspec/support/model/assertions.rb +112 -0
- data/lib/smart_rspec/support/model/expectations.rb +43 -0
- data/lib/smart_rspec/version.rb +1 -1
- data/lib/smart_rspec.rb +2 -3
- data/spec/fixtures/response.rb +11 -0
- data/spec/{factories → fixtures}/user.rb +31 -16
- data/spec/fixtures/users.json +81 -0
- data/spec/smart_rspec/macros_spec.rb +13 -12
- data/spec/smart_rspec/matchers_spec.rb +182 -121
- data/spec/spec_helper.rb +3 -3
- metadata +13 -7
- data/lib/smart_rspec/support/assertions.rb +0 -119
- data/lib/smart_rspec/support/expectations.rb +0 -42
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 7b6913c78ea542aba3c5bb09a26bbb2b5aaa8767
         | 
| 4 | 
            +
              data.tar.gz: 7a94b954a2e829efa220e487f94f3eb94894bdc1
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 57e4f5b9b6cb2b9d55aa42c8d6e4cbdace08b94c0ae36cbcd311d74f8569dc0c88b842e42be6b362bcf087e2a9e486ab2b944d9b29bdda5ecb79774d7ada7c65
         | 
| 7 | 
            +
              data.tar.gz: ebc06947e17c4c84aa5c0ba1f788dcc4f77ab6e3f09804b210694fda390f0667b627bd25ab47a130d458c5c6d58f727161ade7abeef039694d81ed8a121294f4
         | 
    
        data/README.md
    CHANGED
    
    | @@ -51,7 +51,6 @@ end | |
| 51 51 | 
             
                * [be_a_list_of](#be_a_list_of)
         | 
| 52 52 | 
             
                * [be_ascending](#be_ascending)
         | 
| 53 53 | 
             
                * [be_descending](#be_descending)
         | 
| 54 | 
            -
                * [be_a_bad_request](#be_a_bad_request)
         | 
| 55 54 | 
             
              * ["Have" matchers](#have-matchers)
         | 
| 56 55 | 
             
                * [have](#have)
         | 
| 57 56 | 
             
                * [have_at_least](#have_at_least)
         | 
| @@ -180,20 +179,6 @@ it { expect([4, 3, 2, 1]).to be_descending } | |
| 180 179 | 
             
            it { expect([1, 2, 3, 4]).not_to be_descending }
         | 
| 181 180 | 
             
            ```
         | 
| 182 181 |  | 
| 183 | 
            -
            ##### be_a_bad_request
         | 
| 184 | 
            -
            ``` ruby
         | 
| 185 | 
            -
            context 'unauthenticated' do
         | 
| 186 | 
            -
              subject { get :profile }
         | 
| 187 | 
            -
              it { is_expected.to be_a_bad_request }
         | 
| 188 | 
            -
            end
         | 
| 189 | 
            -
             | 
| 190 | 
            -
            context 'authenticated' do
         | 
| 191 | 
            -
              before { sign_in user }
         | 
| 192 | 
            -
              subject { get :profile }
         | 
| 193 | 
            -
              it { is_expected.to_not be_a_bad_request }
         | 
| 194 | 
            -
            end
         | 
| 195 | 
            -
            ```
         | 
| 196 | 
            -
             | 
| 197 182 | 
             
            #### Have matchers
         | 
| 198 183 |  | 
| 199 184 | 
             
            ##### have(x).items
         | 
    
        data/lib/smart_rspec/macros.rb
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 | 
            -
            require 'smart_rspec/support/assertions'
         | 
| 1 | 
            +
            require 'smart_rspec/support/model/assertions'
         | 
| 2 2 |  | 
| 3 3 | 
             
            module SmartRspec::Macros
         | 
| 4 | 
            -
              include SmartRspec::Support::Assertions
         | 
| 4 | 
            +
              include SmartRspec::Support::Model::Assertions
         | 
| 5 5 |  | 
| 6 6 | 
             
              def belongs_to(*associations)
         | 
| 7 7 | 
             
                assert_association :belongs_to, associations
         | 
| @@ -31,4 +31,3 @@ module SmartRspec::Macros | |
| 31 31 | 
             
                end
         | 
| 32 32 | 
             
              end
         | 
| 33 33 | 
             
            end
         | 
| 34 | 
            -
             | 
| @@ -7,12 +7,6 @@ module SmartRspec | |
| 7 7 | 
             
                    match { |actual| actual == actual.sort  }
         | 
| 8 8 | 
             
                  end
         | 
| 9 9 |  | 
| 10 | 
            -
                  matcher :be_a_bad_request do
         | 
| 11 | 
            -
                    match do |response|
         | 
| 12 | 
            -
                      response.code.to_s =~ /^4/
         | 
| 13 | 
            -
                    end
         | 
| 14 | 
            -
                  end
         | 
| 15 | 
            -
             | 
| 16 10 | 
             
                  matcher :be_a_list_of do |klass|
         | 
| 17 11 | 
             
                    match do |collection|
         | 
| 18 12 | 
             
                      collection.all? { |e| e.is_a?(klass) }
         | 
| @@ -0,0 +1,43 @@ | |
| 1 | 
            +
            module SmartRspec
         | 
| 2 | 
            +
              module Matchers
         | 
| 3 | 
            +
                module JsonApiMatchers
         | 
| 4 | 
            +
                  extend RSpec::Matchers::DSL
         | 
| 5 | 
            +
                  include SmartRspec::Support::Controller::Response
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  matcher :have_primary_data do |expected|
         | 
| 8 | 
            +
                    match do |response|
         | 
| 9 | 
            +
                      json(response).collection.all? do |record|
         | 
| 10 | 
            +
                        !record['id'].to_s.empty? && record['type'] == expected
         | 
| 11 | 
            +
                      end
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  matcher :have_data_attributes do |fields|
         | 
| 16 | 
            +
                    match do |response|
         | 
| 17 | 
            +
                      json(response).check_keys_in('attributes', fields)
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  matcher :have_relationships do |relationships|
         | 
| 22 | 
            +
                    match do |response|
         | 
| 23 | 
            +
                      json(response).check_keys_in('relationships', relationships)
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  matcher :have_included_relationships do
         | 
| 28 | 
            +
                    match do |response|
         | 
| 29 | 
            +
                      json(response)
         | 
| 30 | 
            +
                      return false if included_data.empty? || relationship_data.empty?
         | 
| 31 | 
            +
                      included_data.size == relationship_data.size &&
         | 
| 32 | 
            +
                        (included_data - relationship_data).empty?
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  matcher :have_meta_record_count do |count|
         | 
| 37 | 
            +
                    match do |response|
         | 
| 38 | 
            +
                      json(response).meta_record_count == count
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
            end
         | 
    
        data/lib/smart_rspec/matchers.rb
    CHANGED
    
    | @@ -1,12 +1,14 @@ | |
| 1 1 | 
             
            require 'smart_rspec/support/regexes'
         | 
| 2 | 
            +
            require 'smart_rspec/support/controller/response'
         | 
| 2 3 | 
             
            require 'smart_rspec/matchers/be_matchers'
         | 
| 4 | 
            +
            require 'smart_rspec/matchers/json_api_matchers'
         | 
| 3 5 | 
             
            require 'smart_rspec/matchers/other_matchers'
         | 
| 4 6 |  | 
| 5 7 | 
             
            module SmartRspec
         | 
| 6 8 | 
             
              module Matchers
         | 
| 7 9 | 
             
                include SmartRspec::Support::Regexes
         | 
| 8 10 | 
             
                include SmartRspec::Matchers::BeMatchers
         | 
| 11 | 
            +
                include SmartRspec::Matchers::JsonApiMatchers
         | 
| 9 12 | 
             
                include SmartRspec::Matchers::OtherMatchers
         | 
| 10 13 | 
             
              end
         | 
| 11 14 | 
             
            end
         | 
| 12 | 
            -
             | 
| @@ -0,0 +1,47 @@ | |
| 1 | 
            +
            require 'json'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module SmartRspec
         | 
| 4 | 
            +
              module Support
         | 
| 5 | 
            +
                module Controller
         | 
| 6 | 
            +
                  module Response
         | 
| 7 | 
            +
                    def json(response)
         | 
| 8 | 
            +
                      @json ||= JSON.parse(response.body)
         | 
| 9 | 
            +
                      self
         | 
| 10 | 
            +
                    end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    def error
         | 
| 13 | 
            +
                      @error ||= @json['errors'].first
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    def collection
         | 
| 17 | 
            +
                      @collection ||= [@json['data']].flatten
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def meta_record_count
         | 
| 21 | 
            +
                      @json['meta']['record_count']
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    def relationship_data
         | 
| 25 | 
            +
                      @relationship_data ||= collection.flat_map do |record|
         | 
| 26 | 
            +
                        record['relationships'].flat_map do |_, relation|
         | 
| 27 | 
            +
                          [relation['data']].flatten.map { |data| data.slice('type', 'id') }
         | 
| 28 | 
            +
                        end.compact
         | 
| 29 | 
            +
                      end
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                    def included_data
         | 
| 33 | 
            +
                      return [] if @json['included'].nil?
         | 
| 34 | 
            +
                      @included_data ||= @json['included'].flat_map do |record|
         | 
| 35 | 
            +
                        record.slice('type', 'id')
         | 
| 36 | 
            +
                      end
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    def check_keys_in(member, keys)
         | 
| 40 | 
            +
                      collection.all? do |record|
         | 
| 41 | 
            +
                        record[member].keys.sort == keys.sort
         | 
| 42 | 
            +
                      end
         | 
| 43 | 
            +
                    end
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
            end
         | 
| @@ -0,0 +1,112 @@ | |
| 1 | 
            +
            module SmartRspec
         | 
| 2 | 
            +
              module Support
         | 
| 3 | 
            +
                module Model
         | 
| 4 | 
            +
                  module Assertions
         | 
| 5 | 
            +
                    def validates_email_of(attr, validation)
         | 
| 6 | 
            +
                      it 'has an invalid format' do
         | 
| 7 | 
            +
                        %w(foobar foobar@ @foobar foo@bar).each do |e|
         | 
| 8 | 
            +
                          be_valid_expectation(attr, e, subject.dup)
         | 
| 9 | 
            +
                        end
         | 
| 10 | 
            +
                      end
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    def validates_exclusion_of(attr, validation)
         | 
| 14 | 
            +
                      it 'has a reserved value' do
         | 
| 15 | 
            +
                        be_valid_expectation(attr, validation[:in].sample)
         | 
| 16 | 
            +
                      end
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    def validates_format_of(attr, validation)
         | 
| 20 | 
            +
                      it 'does not match the required format' do
         | 
| 21 | 
            +
                        mock, with =
         | 
| 22 | 
            +
                          validation.values_at(:mock).first,
         | 
| 23 | 
            +
                          validation.values_at(:with).first
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                        if mock && with && with !~ mock
         | 
| 26 | 
            +
                          be_valid_expectation(attr, mock)
         | 
| 27 | 
            +
                        else
         | 
| 28 | 
            +
                          raise ArgumentError, ':with and :mock are required when using the :format validation'
         | 
| 29 | 
            +
                        end
         | 
| 30 | 
            +
                      end
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    def validates_inclusion_of(attr, validation)
         | 
| 34 | 
            +
                      it 'is out of the scope of possible values' do
         | 
| 35 | 
            +
                        begin
         | 
| 36 | 
            +
                          value = SecureRandom.hex
         | 
| 37 | 
            +
                        end while validation[:in].include?(value)
         | 
| 38 | 
            +
                        be_valid_expectation(attr, value)
         | 
| 39 | 
            +
                      end
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    def validates_length_of(attr, validation)
         | 
| 43 | 
            +
                      validation.each do |key, value|
         | 
| 44 | 
            +
                        next unless [:in, :is, :maximum, :minimum, :within].include?(key)
         | 
| 45 | 
            +
                        txt, n = build_length_validation(key, value)
         | 
| 46 | 
            +
                        it txt do
         | 
| 47 | 
            +
                          be_valid_expectation(attr, 'x' * n)
         | 
| 48 | 
            +
                        end
         | 
| 49 | 
            +
                      end
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    def validates_presence_of(attr, validation)
         | 
| 53 | 
            +
                      it 'is blank' do
         | 
| 54 | 
            +
                        be_valid_expectation(attr, nil, subject.dup)
         | 
| 55 | 
            +
                      end
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                    def validates_uniqueness_of(attr, validation)
         | 
| 59 | 
            +
                      it 'is already in use' do
         | 
| 60 | 
            +
                        if !validation.is_a?(Hash) || !validation.has_key?(:mock)
         | 
| 61 | 
            +
                          raise ArgumentError, 'A "mock" must be set when validating the uniqueness of a record'
         | 
| 62 | 
            +
                        elsif subject.persisted? || subject.save
         | 
| 63 | 
            +
                          mock, scope = validation.values_at(:mock, :scope)
         | 
| 64 | 
            +
                          mock.send("#{scope}=", subject.send(scope)) unless scope.to_s.empty?
         | 
| 65 | 
            +
                          be_valid_expectation(attr, subject.send(attr), mock)
         | 
| 66 | 
            +
                        end
         | 
| 67 | 
            +
                      end
         | 
| 68 | 
            +
                    end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                    def assert_has_attributes(attrs, options) type_str = build_type_str(options)
         | 
| 71 | 
            +
                      attrs.each do |attr|
         | 
| 72 | 
            +
                        it %Q(has an attribute named "#{attr}"#{type_str}) do
         | 
| 73 | 
            +
                          expect(subject).to respond_to(attr)
         | 
| 74 | 
            +
                          has_attributes_expectation(attr, options)
         | 
| 75 | 
            +
                        end
         | 
| 76 | 
            +
                      end
         | 
| 77 | 
            +
                    end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                    def assert_association(type, associations)
         | 
| 80 | 
            +
                      associations.each do |model|
         | 
| 81 | 
            +
                        it "#{type.to_s.gsub('_', ' ')} #{model}" do
         | 
| 82 | 
            +
                          expect(subject).to respond_to(model)
         | 
| 83 | 
            +
                          association_expectation(type, model)
         | 
| 84 | 
            +
                        end
         | 
| 85 | 
            +
                      end
         | 
| 86 | 
            +
                    end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                    def build_length_validation(key, value)
         | 
| 89 | 
            +
                      case key
         | 
| 90 | 
            +
                      when :in, :within then ['is out of the length range', value.max + 1]
         | 
| 91 | 
            +
                      when :is, :minimum then ["is #{key == :is ? 'invalid' : 'too short'}", value - 1]
         | 
| 92 | 
            +
                      when :maximum then ['is too long', value + 1]
         | 
| 93 | 
            +
                      end
         | 
| 94 | 
            +
                    end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                    def build_type_str(options)
         | 
| 97 | 
            +
                      if !options.nil? && options[:type]
         | 
| 98 | 
            +
                        " (%s%s%s)" % [
         | 
| 99 | 
            +
                          ('Enumerated ' if options[:enum]),
         | 
| 100 | 
            +
                          options[:type],
         | 
| 101 | 
            +
                          (", default: #{options[:default]}" if options[:default])
         | 
| 102 | 
            +
                        ]
         | 
| 103 | 
            +
                      end
         | 
| 104 | 
            +
                    end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                    # def scoped_validation?(validation)
         | 
| 107 | 
            +
                    #   validation.is_a?(Hash) && ([:scope, :mock] - validation.keys).empty?
         | 
| 108 | 
            +
                    # end
         | 
| 109 | 
            +
                  end
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
              end
         | 
| 112 | 
            +
            end
         | 
| @@ -0,0 +1,43 @@ | |
| 1 | 
            +
            module SmartRspec
         | 
| 2 | 
            +
              module Support
         | 
| 3 | 
            +
                module Model
         | 
| 4 | 
            +
                  module Expectations
         | 
| 5 | 
            +
                    def be_valid_expectation(attr, value = nil, mock = nil)
         | 
| 6 | 
            +
                      mock ||= subject
         | 
| 7 | 
            +
                      mock.send("#{attr}=", value)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                      expect(mock).not_to be_valid
         | 
| 10 | 
            +
                      expect(mock).to have_error_on(attr)
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    def default_expectation(attr, value)
         | 
| 14 | 
            +
                      expect(subject.send(attr)).to eq(value)
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    def enum_expectation(attr, value)
         | 
| 18 | 
            +
                      expect(value).to include(subject.send(attr).to_sym)
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    def type_expectation(attr, value)
         | 
| 22 | 
            +
                      assert_type = value != :Boolean ? be_kind_of(Kernel.const_get(value)) : be_boolean
         | 
| 23 | 
            +
                      expect(subject.send(attr)).to assert_type
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    def has_attributes_expectation(attr, options) options.each do |key, value|
         | 
| 27 | 
            +
                        send("#{key}_expectation", attr, value)
         | 
| 28 | 
            +
                      end
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    def association_expectation(type, model)
         | 
| 32 | 
            +
                      if type == :has_many
         | 
| 33 | 
            +
                        expect(subject).to respond_to("#{model.to_s.singularize}_ids")
         | 
| 34 | 
            +
                      elsif type == :belongs_to
         | 
| 35 | 
            +
                        %W(#{model}= #{model}_id #{model}_id=).each do |method|
         | 
| 36 | 
            +
                          expect(subject).to respond_to(method)
         | 
| 37 | 
            +
                        end
         | 
| 38 | 
            +
                      end
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
            end
         | 
    
        data/lib/smart_rspec/version.rb
    CHANGED
    
    
    
        data/lib/smart_rspec.rb
    CHANGED
    
    | @@ -2,7 +2,7 @@ require 'active_support/concern' | |
| 2 2 | 
             
            require 'rspec/collection_matchers'
         | 
| 3 3 | 
             
            require 'rspec/matchers'
         | 
| 4 4 |  | 
| 5 | 
            -
            %w(macros matchers support/expectations).each { |f| require "smart_rspec/#{f}" }
         | 
| 5 | 
            +
            %w(macros matchers support/model/expectations).each { |f| require "smart_rspec/#{f}" }
         | 
| 6 6 |  | 
| 7 7 | 
             
            include SmartRspec::Matchers
         | 
| 8 8 |  | 
| @@ -10,11 +10,10 @@ module SmartRspec | |
| 10 10 | 
             
              extend ActiveSupport::Concern
         | 
| 11 11 |  | 
| 12 12 | 
             
              included do
         | 
| 13 | 
            -
                include SmartRspec::Support::Expectations
         | 
| 13 | 
            +
                include SmartRspec::Support::Model::Expectations
         | 
| 14 14 | 
             
              end
         | 
| 15 15 |  | 
| 16 16 | 
             
              module ClassMethods
         | 
| 17 17 | 
             
                include SmartRspec::Macros
         | 
| 18 18 | 
             
              end
         | 
| 19 19 | 
             
            end
         | 
| 20 | 
            -
             | 
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            require 'smart_rspec/support/regexes'
         | 
| 2 2 |  | 
| 3 | 
            -
            module  | 
| 3 | 
            +
            module Fixtures
         | 
| 4 4 | 
             
              class User
         | 
| 5 5 | 
             
                include SmartRspec::Support::Regexes
         | 
| 6 6 |  | 
| @@ -17,30 +17,42 @@ module Factories | |
| 17 17 |  | 
| 18 18 | 
             
                attr_accessor :email, :system, :system_id, :project, :project_id,
         | 
| 19 19 | 
             
                              :name, :username, :is_admin, :score, :admin, :father,
         | 
| 20 | 
            -
                              :mother, :articles, :rates
         | 
| 20 | 
            +
                              :mother, :articles, :rates, :errors
         | 
| 21 21 |  | 
| 22 | 
            -
                attr_reader :id | 
| 22 | 
            +
                attr_reader :id
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                attr_writer :locale
         | 
| 23 25 |  | 
| 24 26 | 
             
                def initialize(attrs = {})
         | 
| 25 27 | 
             
                  attrs.each { |key, value| self.send("#{key}=", value) }
         | 
| 26 28 | 
             
                  set_defaults
         | 
| 27 | 
            -
                  @@collection << self
         | 
| 28 29 | 
             
                end
         | 
| 29 30 |  | 
| 30 31 | 
             
                class << self
         | 
| 31 32 | 
             
                  attr_reader :collection
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  def create(attrs)
         | 
| 35 | 
            +
                    user = User.new(attrs)
         | 
| 36 | 
            +
                    @@collection << user && user
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  def find_by(key, value)
         | 
| 40 | 
            +
                    @@collection.find { |e| e.send(key) == value }
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                def save
         | 
| 45 | 
            +
                  @@collection << self
         | 
| 32 46 | 
             
                end
         | 
| 33 47 |  | 
| 34 48 | 
             
                def locale
         | 
| 35 49 | 
             
                  @locale.to_s unless @locale.nil?
         | 
| 36 50 | 
             
                end
         | 
| 37 51 |  | 
| 38 | 
            -
                def  | 
| 39 | 
            -
                   | 
| 52 | 
            +
                def persisted?
         | 
| 53 | 
            +
                  User.find_by(:id, id)
         | 
| 40 54 | 
             
                end
         | 
| 41 55 |  | 
| 42 | 
            -
                def persisted?; true end
         | 
| 43 | 
            -
             | 
| 44 56 | 
             
                def valid?
         | 
| 45 57 | 
             
                  %w(email father locale name username).each { |e| send("check_#{e}") }
         | 
| 46 58 | 
             
                  @errors.nil?
         | 
| @@ -51,6 +63,8 @@ module Factories | |
| 51 63 | 
             
                def check_email
         | 
| 52 64 | 
             
                  if !email || (email && email !~ build_regex(:email))
         | 
| 53 65 | 
             
                    @errors.merge!({ email: @@error_message[:blank] })
         | 
| 66 | 
            +
                  elsif User.find_by(:email, email)
         | 
| 67 | 
            +
                    @errors.merge!({ email: @@error_message[:uniqueness] })
         | 
| 54 68 | 
             
                  end
         | 
| 55 69 | 
             
                end
         | 
| 56 70 |  | 
| @@ -61,7 +75,7 @@ module Factories | |
| 61 75 | 
             
                end
         | 
| 62 76 |  | 
| 63 77 | 
             
                def check_locale
         | 
| 64 | 
            -
                  unless  | 
| 78 | 
            +
                  unless %w(en pt).include?(locale)
         | 
| 65 79 | 
             
                    @errors.merge!({ locale: @@error_message[:inclusion] })
         | 
| 66 80 | 
             
                  end
         | 
| 67 81 | 
             
                end
         | 
| @@ -73,18 +87,19 @@ module Factories | |
| 73 87 | 
             
                end
         | 
| 74 88 |  | 
| 75 89 | 
             
                def check_username
         | 
| 76 | 
            -
                   | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 90 | 
            +
                  if username.to_s.empty?
         | 
| 91 | 
            +
                    @errors.merge!({ username: @@error_message[:blank] })
         | 
| 92 | 
            +
                  elsif %w(foo bar).include?(username)
         | 
| 93 | 
            +
                    @errors.merge!({ username: @@error_message[:exclusion] })
         | 
| 94 | 
            +
                  elsif User.find_by(:username, username)
         | 
| 95 | 
            +
                    @errors.merge!({ username: @@error_message[:uniqueness] })
         | 
| 79 96 | 
             
                  end
         | 
| 80 97 | 
             
                end
         | 
| 81 98 |  | 
| 82 99 | 
             
                def set_defaults
         | 
| 83 100 | 
             
                  @@last_id = @id = @@last_id + 1
         | 
| 84 | 
            -
                  { errors: {}, is_admin: false, score: 0, locale: :en } | 
| 85 | 
            -
             | 
| 86 | 
            -
                  end
         | 
| 101 | 
            +
                  attrs = { errors: {}, is_admin: false, score: 0, locale: :en }
         | 
| 102 | 
            +
                  attrs.each { |key, value| send("#{key}=", value) }
         | 
| 87 103 | 
             
                end
         | 
| 88 104 | 
             
              end
         | 
| 89 105 | 
             
            end
         | 
| 90 | 
            -
             | 
| @@ -0,0 +1,81 @@ | |
| 1 | 
            +
            {
         | 
| 2 | 
            +
              "data": [
         | 
| 3 | 
            +
                {
         | 
| 4 | 
            +
                  "id": "1",
         | 
| 5 | 
            +
                  "type": "users",
         | 
| 6 | 
            +
                  "links": {
         | 
| 7 | 
            +
                    "self": "http://api.myawesomesite.com/users/1"
         | 
| 8 | 
            +
                  },
         | 
| 9 | 
            +
                  "attributes": {
         | 
| 10 | 
            +
                    "first_name": "Tiago",
         | 
| 11 | 
            +
                    "last_name": "Guedes",
         | 
| 12 | 
            +
                    "full_name": "Tiago Guedes",
         | 
| 13 | 
            +
                    "birthday": "1988-22-12"
         | 
| 14 | 
            +
                  },
         | 
| 15 | 
            +
                  "relationships": {
         | 
| 16 | 
            +
                    "posts": {
         | 
| 17 | 
            +
                      "links": {
         | 
| 18 | 
            +
                        "self": "http://api.myawesomesite.com/users/1/relationships/posts",
         | 
| 19 | 
            +
                        "related": "http://api.myawesomesite.com/users/1/posts"
         | 
| 20 | 
            +
                      },
         | 
| 21 | 
            +
                      "data": [
         | 
| 22 | 
            +
                        {
         | 
| 23 | 
            +
                          "type": "posts",
         | 
| 24 | 
            +
                          "id": "1"
         | 
| 25 | 
            +
                        }
         | 
| 26 | 
            +
                      ]
         | 
| 27 | 
            +
                    }
         | 
| 28 | 
            +
                  }
         | 
| 29 | 
            +
                },
         | 
| 30 | 
            +
                {
         | 
| 31 | 
            +
                  "id": "2",
         | 
| 32 | 
            +
                  "type": "users",
         | 
| 33 | 
            +
                  "links": {
         | 
| 34 | 
            +
                    "self": "http://api.myawesomesite.com/users/2"
         | 
| 35 | 
            +
                  },
         | 
| 36 | 
            +
                  "attributes": {
         | 
| 37 | 
            +
                    "first_name": "Douglas",
         | 
| 38 | 
            +
                    "last_name": "André",
         | 
| 39 | 
            +
                    "full_name": "Douglas André",
         | 
| 40 | 
            +
                    "birthday": null
         | 
| 41 | 
            +
                  },
         | 
| 42 | 
            +
                  "relationships": {
         | 
| 43 | 
            +
                    "posts": {
         | 
| 44 | 
            +
                      "links": {
         | 
| 45 | 
            +
                        "self": "http://api.myawesomesite.com/users/2/relationships/posts",
         | 
| 46 | 
            +
                        "related": "http://api.myawesomesite.com/users/2/posts"
         | 
| 47 | 
            +
                      },
         | 
| 48 | 
            +
                      "data": []
         | 
| 49 | 
            +
                    }
         | 
| 50 | 
            +
                  }
         | 
| 51 | 
            +
                }
         | 
| 52 | 
            +
              ],
         | 
| 53 | 
            +
              "included": [
         | 
| 54 | 
            +
                {
         | 
| 55 | 
            +
                  "id": "1",
         | 
| 56 | 
            +
                  "type": "posts",
         | 
| 57 | 
            +
                  "links": {
         | 
| 58 | 
            +
                    "self": "http://api.myawesomesite.com/posts/1"
         | 
| 59 | 
            +
                  },
         | 
| 60 | 
            +
                  "attributes": {
         | 
| 61 | 
            +
                    "title": "An awesome post",
         | 
| 62 | 
            +
                    "body": "Lorem ipsum dolot sit amet"
         | 
| 63 | 
            +
                  },
         | 
| 64 | 
            +
                  "relationships": {
         | 
| 65 | 
            +
                    "author": {
         | 
| 66 | 
            +
                      "links": {
         | 
| 67 | 
            +
                        "self": "http://api.myawesomesite.com/posts/1/relationships/author",
         | 
| 68 | 
            +
                        "related": "http://api.myawesomesite.com/posts/1/author"
         | 
| 69 | 
            +
                      }
         | 
| 70 | 
            +
                    }
         | 
| 71 | 
            +
                  }
         | 
| 72 | 
            +
                }
         | 
| 73 | 
            +
              ],
         | 
| 74 | 
            +
              "meta": {
         | 
| 75 | 
            +
                "record_count": 2
         | 
| 76 | 
            +
              },
         | 
| 77 | 
            +
              "links": {
         | 
| 78 | 
            +
                "first": "http://api.myawesomesite.com/users?include=posts&page%5Blimit%5D=2&page%5Boffset%5D=0",
         | 
| 79 | 
            +
                "last": "http://api.myawesomesite.com/users?include=posts&page%5Blimit%5D=2&page%5Boffset%5D=0"
         | 
| 80 | 
            +
              }
         | 
| 81 | 
            +
            }
         | 
| @@ -3,17 +3,14 @@ require 'spec_helper' | |
| 3 3 | 
             
            describe SmartRspec::Macros do
         | 
| 4 4 | 
             
              include SmartRspec
         | 
| 5 5 |  | 
| 6 | 
            -
               | 
| 7 | 
            -
                 | 
| 8 | 
            -
                  email: | 
| 9 | 
            -
                  name: | 
| 6 | 
            +
              subject(:user) do
         | 
| 7 | 
            +
                User.create({
         | 
| 8 | 
            +
                  email:    Faker::Internet.email,
         | 
| 9 | 
            +
                  name:     Faker::Name.name,
         | 
| 10 10 | 
             
                  username: Faker::Internet.user_name
         | 
| 11 | 
            -
                }
         | 
| 12 | 
            -
                @user = User.new(attrs)
         | 
| 11 | 
            +
                })
         | 
| 13 12 | 
             
              end
         | 
| 14 13 |  | 
| 15 | 
            -
              subject { @user }
         | 
| 16 | 
            -
             | 
| 17 14 | 
             
              describe '#belongs_to' do
         | 
| 18 15 | 
             
                context 'when it receives a single arg' do
         | 
| 19 16 | 
             
                  belongs_to :system
         | 
| @@ -59,11 +56,16 @@ describe SmartRspec::Macros do | |
| 59 56 |  | 
| 60 57 | 
             
              describe '#fails_validation_of' do
         | 
| 61 58 | 
             
                context 'when it receives a single arg' do
         | 
| 62 | 
            -
                   | 
| 59 | 
            +
                  new_user =
         | 
| 60 | 
            +
                    User.new({
         | 
| 61 | 
            +
                      email:    Faker::Internet.email,
         | 
| 62 | 
            +
                      name:     Faker::Name.name,
         | 
| 63 | 
            +
                      username: Faker::Internet.user_name
         | 
| 64 | 
            +
                    })
         | 
| 63 65 |  | 
| 64 | 
            -
                  fails_validation_of :email, presence: true, email: true, uniqueness:  | 
| 66 | 
            +
                  fails_validation_of :email, presence: true, email: true, uniqueness: { mock: new_user }
         | 
| 65 67 | 
             
                  fails_validation_of :name, length: { maximum: 80 }
         | 
| 66 | 
            -
                  fails_validation_of :username, uniqueness: {  | 
| 68 | 
            +
                  fails_validation_of :username, uniqueness: { mock: new_user }, exclusion: { in: %w(foo bar) }
         | 
| 67 69 | 
             
                  fails_validation_of :locale, inclusion: { in: %w(en pt) }
         | 
| 68 70 | 
             
                  fails_validation_of :father, format: { with: /foo/, mock: 'bar' }
         | 
| 69 71 | 
             
                end
         | 
| @@ -73,4 +75,3 @@ describe SmartRspec::Macros do | |
| 73 75 | 
             
                end
         | 
| 74 76 | 
             
              end
         | 
| 75 77 | 
             
            end
         | 
| 76 | 
            -
             | 
| @@ -1,173 +1,234 @@ | |
| 1 1 | 
             
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 | 
            -
            describe  | 
| 4 | 
            -
              describe  | 
| 5 | 
            -
                 | 
| 6 | 
            -
                   | 
| 7 | 
            -
             | 
| 3 | 
            +
            describe SmartRspec::Matchers do
         | 
| 4 | 
            +
              describe BeMatchers do
         | 
| 5 | 
            +
                describe '#be_ascending' do
         | 
| 6 | 
            +
                  context 'positive assertion' do
         | 
| 7 | 
            +
                    it { expect([1, 2, 3, 4]).to be_ascending }
         | 
| 8 | 
            +
                  end
         | 
| 8 9 |  | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 10 | 
            +
                  context 'negative assertion' do
         | 
| 11 | 
            +
                    it { expect([1, 4, 2, 3]).not_to be_ascending }
         | 
| 12 | 
            +
                  end
         | 
| 11 13 | 
             
                end
         | 
| 12 | 
            -
              end
         | 
| 13 14 |  | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 15 | 
            +
                describe '#be_boolean' do
         | 
| 16 | 
            +
                  context 'positive assertion' do
         | 
| 17 | 
            +
                    it { expect(true).to be_boolean }
         | 
| 18 | 
            +
                    it { expect(false).to be_boolean }
         | 
| 19 | 
            +
                  end
         | 
| 19 20 |  | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 21 | 
            +
                  context 'negative assertion' do
         | 
| 22 | 
            +
                    it { expect('true').not_to be_boolean }
         | 
| 23 | 
            +
                    it { expect(1).not_to be_boolean }
         | 
| 24 | 
            +
                    it { expect(%w(foo bar)).not_to be_boolean }
         | 
| 25 | 
            +
                  end
         | 
| 24 26 | 
             
                end
         | 
| 25 | 
            -
              end
         | 
| 26 27 |  | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 28 | 
            +
                describe '#be_descending' do
         | 
| 29 | 
            +
                  context 'positive assertion' do
         | 
| 30 | 
            +
                    it { expect([4, 3, 2, 1]).to be_descending }
         | 
| 31 | 
            +
                  end
         | 
| 31 32 |  | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 33 | 
            +
                  context 'negative assertion' do
         | 
| 34 | 
            +
                    it { expect([1, 2, 3, 4]).not_to be_descending }
         | 
| 35 | 
            +
                  end
         | 
| 34 36 | 
             
                end
         | 
| 35 | 
            -
              end
         | 
| 36 37 |  | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 38 | 
            +
                describe '#be_email' do
         | 
| 39 | 
            +
                  context 'positive assertion' do
         | 
| 40 | 
            +
                    it { expect(Faker::Internet.email).to be_email }
         | 
| 41 | 
            +
                    it { expect('tiagopog@gmail.com').to be_email }
         | 
| 42 | 
            +
                    it { expect('foo@bar.com.br').to be_email }
         | 
| 43 | 
            +
                  end
         | 
| 43 44 |  | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 45 | 
            +
                  context 'negative assertion' do
         | 
| 46 | 
            +
                    it { expect('foo@bar').not_to be_email }
         | 
| 47 | 
            +
                    it { expect('foo@').not_to be_email }
         | 
| 48 | 
            +
                    it { expect('@bar').not_to be_email }
         | 
| 49 | 
            +
                    it { expect('@bar.com').not_to be_email }
         | 
| 50 | 
            +
                    it { expect('foo bar@bar.com').not_to be_email }
         | 
| 51 | 
            +
                  end
         | 
| 50 52 | 
             
                end
         | 
| 51 | 
            -
              end
         | 
| 52 53 |  | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 54 | 
            +
                describe '#be_url' do
         | 
| 55 | 
            +
                  context 'positive assertion' do
         | 
| 56 | 
            +
                    it { expect(Faker::Internet.url).to be_url }
         | 
| 57 | 
            +
                    it { expect('http://adtangerine.com').to be_url }
         | 
| 58 | 
            +
                    it { expect('http://www.facebook.com').to be_url }
         | 
| 59 | 
            +
                    it { expect('www.twitflink.com').to be_url }
         | 
| 60 | 
            +
                    it { expect('google.com.br').to be_url }
         | 
| 61 | 
            +
                  end
         | 
| 61 62 |  | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 63 | 
            +
                  context 'negative assertion' do
         | 
| 64 | 
            +
                    it { expect('foobar.bar').not_to be_url }
         | 
| 65 | 
            +
                    it { expect('foobar').not_to be_url }
         | 
| 66 | 
            +
                    it { expect('foo bar.com.br').not_to be_url }
         | 
| 67 | 
            +
                  end
         | 
| 66 68 | 
             
                end
         | 
| 67 | 
            -
              end
         | 
| 68 69 |  | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 70 | 
            +
                describe '#be_image_url' do
         | 
| 71 | 
            +
                  context 'positive assertion' do
         | 
| 72 | 
            +
                    it { expect(Faker::Company.logo).to be_image_url }
         | 
| 73 | 
            +
                    it { expect('http://foobar.com/foo.jpg').to be_image_url }
         | 
| 74 | 
            +
                    it { expect('http://foobar.com/foo.jpg').to be_image_url(:jpg) }
         | 
| 75 | 
            +
                    it { expect('http://foobar.com/foo.gif').to be_image_url(:gif) }
         | 
| 76 | 
            +
                    it { expect('http://foobar.com/foo.png').to be_image_url(:png) }
         | 
| 77 | 
            +
                    it { expect('http://foobar.com/foo.png').to be_image_url([:jpg, :png]) }
         | 
| 78 | 
            +
                    it { expect('http://foobar.com/foo/bar?image=foo.jpg').to be_image_url }
         | 
| 79 | 
            +
                  end
         | 
| 79 80 |  | 
| 80 | 
            -
             | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 81 | 
            +
                  context 'negative assertion' do
         | 
| 82 | 
            +
                    it { expect('http://foobar.com').not_to be_image_url }
         | 
| 83 | 
            +
                    it { expect('http://foobar.com/foo.jpg').not_to be_image_url(:gif) }
         | 
| 84 | 
            +
                    it { expect('http://foobar.com/foo.gif').not_to be_image_url(:png) }
         | 
| 85 | 
            +
                    it { expect('http://foobar.com/foo.png').not_to be_image_url(:jpg) }
         | 
| 86 | 
            +
                    it { expect('http://foobar.com/foo.gif').not_to be_image_url([:jpg, :png]) }
         | 
| 87 | 
            +
                  end
         | 
| 86 88 | 
             
                end
         | 
| 87 | 
            -
              end
         | 
| 88 89 |  | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 90 | 
            +
                describe '#be_a_list_of' do
         | 
| 91 | 
            +
                  context 'positive assertion' do
         | 
| 92 | 
            +
                    subject { Array.new(3, User.new) }
         | 
| 93 | 
            +
                    it { is_expected.to be_a_list_of(User) }
         | 
| 94 | 
            +
                  end
         | 
| 94 95 |  | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 96 | 
            +
                  context 'negative assertion' do
         | 
| 97 | 
            +
                    subject { Array.new(3, User.new) << nil }
         | 
| 98 | 
            +
                    it { is_expected.to_not be_a_list_of(User) }
         | 
| 99 | 
            +
                  end
         | 
| 98 100 | 
             
                end
         | 
| 99 101 | 
             
              end
         | 
| 100 102 |  | 
| 101 | 
            -
              describe  | 
| 102 | 
            -
                 | 
| 103 | 
            -
             | 
| 104 | 
            -
                 | 
| 105 | 
            -
             | 
| 103 | 
            +
              describe JsonApiMatchers do
         | 
| 104 | 
            +
                subject(:response) { Fixtures::Response.new }
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                describe '#have_primary_data' do
         | 
| 107 | 
            +
                  context 'positive assertion' do
         | 
| 108 | 
            +
                    it do
         | 
| 109 | 
            +
                      expect(response).to have_primary_data('users')
         | 
| 110 | 
            +
                    end
         | 
| 111 | 
            +
                  end
         | 
| 106 112 |  | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 109 | 
            -
             | 
| 113 | 
            +
                  context 'negative assertion' do
         | 
| 114 | 
            +
                    it do
         | 
| 115 | 
            +
                      expect(response).not_to have_primary_data('foobar')
         | 
| 116 | 
            +
                    end
         | 
| 117 | 
            +
                  end
         | 
| 110 118 | 
             
                end
         | 
| 111 | 
            -
              end
         | 
| 112 119 |  | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 120 | 
            +
                describe '#have_data_attributes' do
         | 
| 121 | 
            +
                  let(:fields) { %w(first_name last_name full_name birthday) }
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                  context 'positive assertion' do
         | 
| 124 | 
            +
                    it do
         | 
| 125 | 
            +
                      expect(response).to have_data_attributes(fields)
         | 
| 126 | 
            +
                    end
         | 
| 127 | 
            +
                  end
         | 
| 115 128 |  | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
                     | 
| 129 | 
            +
                  context 'negative assertion' do
         | 
| 130 | 
            +
                    it do
         | 
| 131 | 
            +
                      expect(response).not_to have_data_attributes(fields + %w(foobar))
         | 
| 132 | 
            +
                    end
         | 
| 120 133 | 
             
                  end
         | 
| 121 134 | 
             
                end
         | 
| 122 135 |  | 
| 123 | 
            -
                 | 
| 124 | 
            -
                   | 
| 125 | 
            -
             | 
| 126 | 
            -
             | 
| 136 | 
            +
                describe '#have_relationships' do
         | 
| 137 | 
            +
                  let(:relationships) { %w(posts) }
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                  context 'positive assertion' do
         | 
| 140 | 
            +
                    it do
         | 
| 141 | 
            +
                      expect(response).to have_relationships(relationships)
         | 
| 142 | 
            +
                    end
         | 
| 143 | 
            +
                  end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                  context 'negative assertion' do
         | 
| 146 | 
            +
                    it do
         | 
| 147 | 
            +
                      expect(response).not_to have_relationships(relationships + %w(foobar))
         | 
| 148 | 
            +
                    end
         | 
| 127 149 | 
             
                  end
         | 
| 128 150 | 
             
                end
         | 
| 129 | 
            -
              end
         | 
| 130 151 |  | 
| 131 | 
            -
             | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 134 | 
            -
                   | 
| 135 | 
            -
             | 
| 152 | 
            +
                describe '#have_included_relationships' do
         | 
| 153 | 
            +
                  let(:relationships) { %w(posts) }
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                  context 'positive assertion' do
         | 
| 156 | 
            +
                    it do
         | 
| 157 | 
            +
                      expect(response).to have_included_relationships
         | 
| 158 | 
            +
                    end
         | 
| 159 | 
            +
                  end
         | 
| 136 160 | 
             
                end
         | 
| 137 161 |  | 
| 138 | 
            -
                 | 
| 139 | 
            -
                   | 
| 162 | 
            +
                describe '#have_meta_record_count' do
         | 
| 163 | 
            +
                  context 'positive assertion' do
         | 
| 164 | 
            +
                    it do
         | 
| 165 | 
            +
                      expect(response).to have_meta_record_count(2)
         | 
| 166 | 
            +
                    end
         | 
| 167 | 
            +
                  end
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                  context 'negative assertion' do
         | 
| 170 | 
            +
                    it do
         | 
| 171 | 
            +
                      expect(response).not_to have_meta_record_count(3)
         | 
| 172 | 
            +
                    end
         | 
| 173 | 
            +
                  end
         | 
| 140 174 | 
             
                end
         | 
| 141 175 | 
             
              end
         | 
| 142 176 |  | 
| 143 | 
            -
              describe  | 
| 144 | 
            -
                 | 
| 145 | 
            -
                  subject {  | 
| 146 | 
            -
             | 
| 177 | 
            +
              describe OtherMatchers do
         | 
| 178 | 
            +
                describe '#have_error_on' do
         | 
| 179 | 
            +
                  subject { User.new(email: nil, name: Faker::Name.name) }
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                  context 'positive assertion' do
         | 
| 182 | 
            +
                    it do
         | 
| 183 | 
            +
                      subject.valid?
         | 
| 184 | 
            +
                      is_expected.to have_error_on(:email)
         | 
| 185 | 
            +
                    end
         | 
| 186 | 
            +
                  end
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                  context 'negative assertion' do
         | 
| 189 | 
            +
                    it do
         | 
| 190 | 
            +
                      subject.valid?
         | 
| 191 | 
            +
                      is_expected.not_to have_error_on(:name)
         | 
| 192 | 
            +
                    end
         | 
| 193 | 
            +
                  end
         | 
| 147 194 | 
             
                end
         | 
| 148 195 |  | 
| 149 | 
            -
                 | 
| 150 | 
            -
                   | 
| 151 | 
            -
             | 
| 196 | 
            +
                describe '#include_items' do
         | 
| 197 | 
            +
                  context 'positive assertion' do
         | 
| 198 | 
            +
                    it { expect(%w(foo bar foobar)).to include_items(%w(foo bar foobar)) }
         | 
| 199 | 
            +
                    it { expect(%w(lorem ipsum)).to include_items('lorem', 'ipsum') }
         | 
| 200 | 
            +
                    it { expect([1, 'foo', ['bar']]).to include_items([1, 'foo', ['bar']]) }
         | 
| 201 | 
            +
                  end
         | 
| 202 | 
            +
             | 
| 203 | 
            +
                  context 'negative assertion' do
         | 
| 204 | 
            +
                    it { expect(%w(foo bar foobar)).not_to include_items(%w(lorem)) }
         | 
| 205 | 
            +
                  end
         | 
| 152 206 | 
             
                end
         | 
| 153 207 | 
             
              end
         | 
| 154 208 |  | 
| 155 | 
            -
              describe  | 
| 156 | 
            -
                 | 
| 209 | 
            +
              describe ::RSpec::CollectionMatchers do
         | 
| 210 | 
            +
                describe '#have' do
         | 
| 211 | 
            +
                  context 'positive assertion' do
         | 
| 212 | 
            +
                    it { expect([1]).to have(1).item }
         | 
| 213 | 
            +
                    it { expect(%w(foo bar)).to have(2).items }
         | 
| 214 | 
            +
                  end
         | 
| 157 215 |  | 
| 158 | 
            -
             | 
| 159 | 
            -
             | 
| 160 | 
            -
             | 
| 216 | 
            +
                  context 'negative assertion' do
         | 
| 217 | 
            +
                    it { expect([1]).not_to have(2).items }
         | 
| 218 | 
            +
                    it { expect(%w(foo bar)).not_to have(1).item }
         | 
| 219 | 
            +
                  end
         | 
| 161 220 | 
             
                end
         | 
| 162 221 |  | 
| 163 | 
            -
                 | 
| 164 | 
            -
                   | 
| 165 | 
            -
             | 
| 222 | 
            +
                describe '#have_at_least' do
         | 
| 223 | 
            +
                  context 'positive assertion' do
         | 
| 224 | 
            +
                    it { expect(%w(foo bar foobar)).to have_at_least(3).items }
         | 
| 225 | 
            +
                  end
         | 
| 166 226 | 
             
                end
         | 
| 167 227 |  | 
| 168 | 
            -
                 | 
| 169 | 
            -
                   | 
| 170 | 
            -
             | 
| 228 | 
            +
                describe '#have_at_most' do
         | 
| 229 | 
            +
                  context 'positive assertion' do
         | 
| 230 | 
            +
                    it { expect(%w(foo bar foobar)).to have_at_most(3).items }
         | 
| 231 | 
            +
                  end
         | 
| 171 232 | 
             
                end
         | 
| 172 233 | 
             
              end
         | 
| 173 234 | 
             
            end
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: smart_rspec
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.4
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Tiago Guedes
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2016-05-10 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: activesupport
         | 
| @@ -119,13 +119,17 @@ files: | |
| 119 119 | 
             
            - lib/smart_rspec/macros.rb
         | 
| 120 120 | 
             
            - lib/smart_rspec/matchers.rb
         | 
| 121 121 | 
             
            - lib/smart_rspec/matchers/be_matchers.rb
         | 
| 122 | 
            +
            - lib/smart_rspec/matchers/json_api_matchers.rb
         | 
| 122 123 | 
             
            - lib/smart_rspec/matchers/other_matchers.rb
         | 
| 123 | 
            -
            - lib/smart_rspec/support/ | 
| 124 | 
            -
            - lib/smart_rspec/support/ | 
| 124 | 
            +
            - lib/smart_rspec/support/controller/response.rb
         | 
| 125 | 
            +
            - lib/smart_rspec/support/model/assertions.rb
         | 
| 126 | 
            +
            - lib/smart_rspec/support/model/expectations.rb
         | 
| 125 127 | 
             
            - lib/smart_rspec/support/regexes.rb
         | 
| 126 128 | 
             
            - lib/smart_rspec/version.rb
         | 
| 127 129 | 
             
            - smart_rspec.gemspec
         | 
| 128 | 
            -
            - spec/ | 
| 130 | 
            +
            - spec/fixtures/response.rb
         | 
| 131 | 
            +
            - spec/fixtures/user.rb
         | 
| 132 | 
            +
            - spec/fixtures/users.json
         | 
| 129 133 | 
             
            - spec/smart_rspec/macros_spec.rb
         | 
| 130 134 | 
             
            - spec/smart_rspec/matchers_spec.rb
         | 
| 131 135 | 
             
            - spec/spec_helper.rb
         | 
| @@ -149,12 +153,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 149 153 | 
             
                  version: '0'
         | 
| 150 154 | 
             
            requirements: []
         | 
| 151 155 | 
             
            rubyforge_project: 
         | 
| 152 | 
            -
            rubygems_version: 2. | 
| 156 | 
            +
            rubygems_version: 2.6.2
         | 
| 153 157 | 
             
            signing_key: 
         | 
| 154 158 | 
             
            specification_version: 4
         | 
| 155 159 | 
             
            summary: Macros and matchers to make your RSpec tests even more amazing.
         | 
| 156 160 | 
             
            test_files:
         | 
| 157 | 
            -
            - spec/ | 
| 161 | 
            +
            - spec/fixtures/response.rb
         | 
| 162 | 
            +
            - spec/fixtures/user.rb
         | 
| 163 | 
            +
            - spec/fixtures/users.json
         | 
| 158 164 | 
             
            - spec/smart_rspec/macros_spec.rb
         | 
| 159 165 | 
             
            - spec/smart_rspec/matchers_spec.rb
         | 
| 160 166 | 
             
            - spec/spec_helper.rb
         | 
| @@ -1,119 +0,0 @@ | |
| 1 | 
            -
            module SmartRspec
         | 
| 2 | 
            -
              module Support
         | 
| 3 | 
            -
                module Assertions
         | 
| 4 | 
            -
                  private_class_method
         | 
| 5 | 
            -
             | 
| 6 | 
            -
                  def validates_email_of(attr, validation)
         | 
| 7 | 
            -
                    it 'has an invalid format' do
         | 
| 8 | 
            -
                      %w(foobar foobar@ @foobar foo@bar).each do |e|
         | 
| 9 | 
            -
                        validation_expectation(attr, e)
         | 
| 10 | 
            -
                      end
         | 
| 11 | 
            -
                    end
         | 
| 12 | 
            -
                  end
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                  def validates_exclusion_of(attr, validation)
         | 
| 15 | 
            -
                    it 'has a reserved value' do
         | 
| 16 | 
            -
                      validation_expectation(attr, validation[:in].sample)
         | 
| 17 | 
            -
                    end
         | 
| 18 | 
            -
                  end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                  def validates_format_of(attr, validation)
         | 
| 21 | 
            -
                    it 'does not match the required format' do
         | 
| 22 | 
            -
                      mock, with =
         | 
| 23 | 
            -
                        validation.values_at(:mock).first,
         | 
| 24 | 
            -
                        validation.values_at(:with).first
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                      if mock && with && with !~ mock
         | 
| 27 | 
            -
                        validation_expectation(attr, mock)
         | 
| 28 | 
            -
                      else
         | 
| 29 | 
            -
                        raise ArgumentError, ':with and :mock are required when using the :format validation'
         | 
| 30 | 
            -
                      end
         | 
| 31 | 
            -
                    end
         | 
| 32 | 
            -
                  end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                  def validates_inclusion_of(attr, validation)
         | 
| 35 | 
            -
                    it 'is out of the scope of possible values' do
         | 
| 36 | 
            -
                      begin
         | 
| 37 | 
            -
                        value = SecureRandom.hex
         | 
| 38 | 
            -
                      end while validation[:in].include?(value)
         | 
| 39 | 
            -
                      validation_expectation(attr, value)
         | 
| 40 | 
            -
                    end
         | 
| 41 | 
            -
                  end
         | 
| 42 | 
            -
             | 
| 43 | 
            -
                  def validates_length_of(attr, validation)
         | 
| 44 | 
            -
                    validation.each do |key, value|
         | 
| 45 | 
            -
                      next unless [:in, :is, :maximum, :minimum, :within].include?(key)
         | 
| 46 | 
            -
                      txt, n = build_length_validation(key, value)
         | 
| 47 | 
            -
                      it txt do
         | 
| 48 | 
            -
                        validation_expectation(attr, 'x' * n)
         | 
| 49 | 
            -
                      end
         | 
| 50 | 
            -
                    end
         | 
| 51 | 
            -
                  end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                  def validates_presence_of(attr, validation)
         | 
| 54 | 
            -
                    it 'is blank' do
         | 
| 55 | 
            -
                      validation_expectation(attr, nil)
         | 
| 56 | 
            -
                    end
         | 
| 57 | 
            -
                  end
         | 
| 58 | 
            -
             | 
| 59 | 
            -
                  def validates_uniqueness_of(attr, validation)
         | 
| 60 | 
            -
                    scoped = scoped_validation?(validation)
         | 
| 61 | 
            -
                    it "is already in use#{" (scope: #{validation[:scope]})" if scoped}" do
         | 
| 62 | 
            -
                      mock =
         | 
| 63 | 
            -
                        if scoped
         | 
| 64 | 
            -
                          copy = subject.send(validation[:scope])
         | 
| 65 | 
            -
                          validation[:mock].send("#{validation[:scope]}=", copy)
         | 
| 66 | 
            -
                          validation[:mock]
         | 
| 67 | 
            -
                        else
         | 
| 68 | 
            -
                          subject.dup
         | 
| 69 | 
            -
                        end
         | 
| 70 | 
            -
                      subject.save unless subject.persisted?
         | 
| 71 | 
            -
                      validation_expectation(attr, subject.send(attr), mock)
         | 
| 72 | 
            -
                    end
         | 
| 73 | 
            -
                  end
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                  def assert_has_attributes(attrs, options)
         | 
| 76 | 
            -
                    type_str = build_type_str(options)
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                    attrs.each do |attr|
         | 
| 79 | 
            -
                      it %Q(has an attribute named "#{attr}"#{type_str}) do
         | 
| 80 | 
            -
                        expect(subject).to respond_to(attr)
         | 
| 81 | 
            -
                        has_attributes_expectation(attr, options)
         | 
| 82 | 
            -
                      end
         | 
| 83 | 
            -
                    end
         | 
| 84 | 
            -
                  end
         | 
| 85 | 
            -
             | 
| 86 | 
            -
                  def assert_association(type, associations)
         | 
| 87 | 
            -
                    associations.each do |model|
         | 
| 88 | 
            -
                      it "#{type.to_s.gsub('_', ' ')} #{model}" do
         | 
| 89 | 
            -
                        expect(subject).to respond_to(model)
         | 
| 90 | 
            -
                        association_expectation(type, model)
         | 
| 91 | 
            -
                      end
         | 
| 92 | 
            -
                    end
         | 
| 93 | 
            -
                  end
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                  def build_length_validation(key, value)
         | 
| 96 | 
            -
                    case key
         | 
| 97 | 
            -
                    when :in, :within then ['is out of the length range', value.max + 1]
         | 
| 98 | 
            -
                    when :is, :minimum then ["is #{key == :is ? 'invalid' : 'too short'}", value - 1]
         | 
| 99 | 
            -
                    when :maximum then ['is too long', value + 1]
         | 
| 100 | 
            -
                    end
         | 
| 101 | 
            -
                  end
         | 
| 102 | 
            -
             | 
| 103 | 
            -
                  def build_type_str(options)
         | 
| 104 | 
            -
                    if !options.nil? && options[:type]
         | 
| 105 | 
            -
                      " (%s%s%s)" % [
         | 
| 106 | 
            -
                        ('Enumerated ' if options[:enum]),
         | 
| 107 | 
            -
                        options[:type],
         | 
| 108 | 
            -
                        (", default: #{options[:default]}" if options[:default])
         | 
| 109 | 
            -
                      ]
         | 
| 110 | 
            -
                    end
         | 
| 111 | 
            -
                  end
         | 
| 112 | 
            -
             | 
| 113 | 
            -
                  def scoped_validation?(validation)
         | 
| 114 | 
            -
                    validation.is_a?(Hash) && ([:scope, :mock] - validation.keys).empty?
         | 
| 115 | 
            -
                  end
         | 
| 116 | 
            -
                end
         | 
| 117 | 
            -
              end
         | 
| 118 | 
            -
            end
         | 
| 119 | 
            -
             | 
| @@ -1,42 +0,0 @@ | |
| 1 | 
            -
            module SmartRspec
         | 
| 2 | 
            -
              module Support
         | 
| 3 | 
            -
                module Expectations
         | 
| 4 | 
            -
                  def validation_expectation(attr, value = nil, mock = nil)
         | 
| 5 | 
            -
                    mock ||= subject
         | 
| 6 | 
            -
                    mock.send("#{attr}=", value)
         | 
| 7 | 
            -
             | 
| 8 | 
            -
                    expect(mock).not_to be_valid
         | 
| 9 | 
            -
                    expect(mock).to have_error_on(attr)
         | 
| 10 | 
            -
                  end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                  def default_expectation(attr, value)
         | 
| 13 | 
            -
                    expect(subject.send(attr)).to eq(value)
         | 
| 14 | 
            -
                  end
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                  def enum_expectation(attr, value)
         | 
| 17 | 
            -
                    expect(value).to include(subject.send(attr).to_sym)
         | 
| 18 | 
            -
                  end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                  def type_expectation(attr, value)
         | 
| 21 | 
            -
                    assert_type = value != :Boolean ? be_kind_of(Kernel.const_get(value)) : be_boolean
         | 
| 22 | 
            -
                    expect(subject.send(attr)).to assert_type
         | 
| 23 | 
            -
                  end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                  def has_attributes_expectation(attr, options) options.each do |key, value|
         | 
| 26 | 
            -
                      send("#{key}_expectation", attr, value)
         | 
| 27 | 
            -
                    end
         | 
| 28 | 
            -
                  end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                  def association_expectation(type, model)
         | 
| 31 | 
            -
                    if type == :has_many
         | 
| 32 | 
            -
                      expect(subject).to respond_to("#{model.to_s.singularize}_ids")
         | 
| 33 | 
            -
                    elsif type == :belongs_to
         | 
| 34 | 
            -
                      %W(#{model}= #{model}_id #{model}_id=).each do |method|
         | 
| 35 | 
            -
                        expect(subject).to respond_to(method)
         | 
| 36 | 
            -
                      end
         | 
| 37 | 
            -
                    end
         | 
| 38 | 
            -
                  end
         | 
| 39 | 
            -
                end
         | 
| 40 | 
            -
              end
         | 
| 41 | 
            -
            end
         | 
| 42 | 
            -
             |