smart_rspec 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ff36ef01dd0d51c6bab2614a6613201973dd7c7
4
- data.tar.gz: cdf57909342d77f99b5ccf3b0fe3766343da5591
3
+ metadata.gz: 7b6913c78ea542aba3c5bb09a26bbb2b5aaa8767
4
+ data.tar.gz: 7a94b954a2e829efa220e487f94f3eb94894bdc1
5
5
  SHA512:
6
- metadata.gz: 8e1f3afcc473a3fb8b25a21da76bbc6a4cbfd09d7e93746f15b3e224f8b4f24f438f42266906e99e4389e9ffde7f07311790d16133d2e892117f11efc22f3e72
7
- data.tar.gz: ec5b1078402f12aa22cd125eceef70a1ea96ce4d639186c20505733dc7045d9a9e2be90b5f9abc4571c78ec54480a42bbd12e32994084596948835f13a4a7fbe
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
@@ -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
@@ -13,4 +13,3 @@ module SmartRspec
13
13
  end
14
14
  end
15
15
  end
16
-
@@ -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
@@ -1,3 +1,3 @@
1
1
  module SmartRspec
2
- VERSION = '0.1.3'
2
+ VERSION = '0.1.4'
3
3
  end
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
-
@@ -0,0 +1,11 @@
1
+ module Fixtures
2
+ class Response
3
+ def initialize
4
+ @file = File.read('spec/fixtures/users.json')
5
+ end
6
+
7
+ def body
8
+ @file
9
+ end
10
+ end
11
+ end
@@ -1,6 +1,6 @@
1
1
  require 'smart_rspec/support/regexes'
2
2
 
3
- module Factories
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, :errors
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 locale=(locale)
39
- [:en, :pt].include?(locale) && @locale = locale
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 [:en, :pt].include?(locale)
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
- other_user = @@collection.select { |e| e.name == name && e.username == username && e.id != id }.first
77
- if username && (other_user || %w(foo bar).include?(username))
78
- @errors.merge!({ username: @@error_message[other_user ? :uniqueness : :exclusion] })
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 }.each do |key, value|
85
- eval "@#{key} ||= #{value.inspect}"
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
- before(:all) do
7
- attrs = {
8
- email: Faker::Internet.email,
9
- name: Faker::Name.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
- user = User.new(email: Faker::Internet.email)
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: true
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: { scope: :name, mock: user }, exclusion: { in: %w(foo bar) }
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 'SmartRspec Matchers' do
4
- describe '#be_ascending' do
5
- context 'when valid' do
6
- it { expect([1, 2, 3, 4]).to be_ascending }
7
- end
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
- context 'when invalid' do
10
- it { expect([1, 4, 2, 3]).not_to be_ascending }
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
- describe '#be_boolean' do
15
- context 'when valid' do
16
- it { expect(true).to be_boolean }
17
- it { expect(false).to be_boolean }
18
- end
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
- context 'when invalid' do
21
- it { expect('true').not_to be_boolean }
22
- it { expect(1).not_to be_boolean }
23
- it { expect(%w(foo bar)).not_to be_boolean }
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
- describe '#be_descending' do
28
- context 'when valid' do
29
- it { expect([4, 3, 2, 1]).to be_descending }
30
- end
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
- context 'when invalid' do
33
- it { expect([1, 2, 3, 4]).not_to be_descending }
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
- describe '#be_email' do
38
- context 'when valid' do
39
- it { expect(Faker::Internet.email).to be_email }
40
- it { expect('tiagopog@gmail.com').to be_email }
41
- it { expect('foo@bar.com.br').to be_email }
42
- end
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
- context 'when invalid' do
45
- it { expect('foo@bar').not_to be_email }
46
- it { expect('foo@').not_to be_email }
47
- it { expect('@bar').not_to be_email }
48
- it { expect('@bar.com').not_to be_email }
49
- it { expect('foo bar@bar.com').not_to be_email }
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
- describe '#be_url' do
54
- context 'when valid' do
55
- it { expect(Faker::Internet.url).to be_url }
56
- it { expect('http://adtangerine.com').to be_url }
57
- it { expect('http://www.facebook.com').to be_url }
58
- it { expect('www.twitflink.com').to be_url }
59
- it { expect('google.com.br').to be_url }
60
- end
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
- context 'when invalid' do
63
- it { expect('foobar.bar').not_to be_url }
64
- it { expect('foobar').not_to be_url }
65
- it { expect('foo bar.com.br').not_to be_url }
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
- describe '#be_image_url' do
70
- context 'when valid' do
71
- it { expect(Faker::Company.logo).to be_image_url }
72
- it { expect('http://foobar.com/foo.jpg').to be_image_url }
73
- it { expect('http://foobar.com/foo.jpg').to be_image_url(:jpg) }
74
- it { expect('http://foobar.com/foo.gif').to be_image_url(:gif) }
75
- it { expect('http://foobar.com/foo.png').to be_image_url(:png) }
76
- it { expect('http://foobar.com/foo.png').to be_image_url([:jpg, :png]) }
77
- it { expect('http://foobar.com/foo/bar?image=foo.jpg').to be_image_url }
78
- end
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
- context 'when invalid' do
81
- it { expect('http://foobar.com').not_to be_image_url }
82
- it { expect('http://foobar.com/foo.jpg').not_to be_image_url(:gif) }
83
- it { expect('http://foobar.com/foo.gif').not_to be_image_url(:png) }
84
- it { expect('http://foobar.com/foo.png').not_to be_image_url(:jpg) }
85
- it { expect('http://foobar.com/foo.gif').not_to be_image_url([:jpg, :png]) }
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
- describe '#have' do
90
- context 'when valid' do
91
- it { expect([1]).to have(1).item }
92
- it { expect(%w(foo bar)).to have(2).items }
93
- end
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
- context 'when invalid' do
96
- it { expect([1]).not_to have(2).items }
97
- it { expect(%w(foo bar)).not_to have(1).item }
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 '#have_at_least' do
102
- context 'when valid' do
103
- it { expect(%w(foo bar foobar)).to have_at_least(3).items }
104
- end
105
- end
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
- describe '#have_at_most' do
108
- context 'when valid' do
109
- it { expect(%w(foo bar foobar)).to have_at_most(3).items }
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
- describe '#have_error_on' do
114
- subject { User.new(email: nil, name: Faker::Name.name) }
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
- context 'when valid' do
117
- it do
118
- subject.valid?
119
- is_expected.to have_error_on(:email)
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
- context 'when invalid' do
124
- it do
125
- subject.valid?
126
- is_expected.not_to have_error_on(:name)
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
- describe '#include_items' do
132
- context 'when valid' do
133
- it { expect(%w(foo bar foobar)).to include_items(%w(foo bar foobar)) }
134
- it { expect(%w(lorem ipsum)).to include_items('lorem', 'ipsum') }
135
- it { expect([1, 'foo', ['bar']]).to include_items([1, 'foo', ['bar']]) }
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
- context 'when invalid' do
139
- it { expect(%w(foo bar foobar)).not_to include_items(%w(lorem)) }
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 '#be_a_list_of' do
144
- context 'when valid' do
145
- subject { Array.new(3, User.new) }
146
- it { is_expected.to be_a_list_of(User) }
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
- context 'when invalid' do
150
- subject { Array.new(3, User.new) << nil }
151
- it { is_expected.to_not be_a_list_of(User) }
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 '#be_a_bad_request' do
156
- let(:response) { double('http response') }
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
- context 'ok' do
159
- before { allow(response).to receive(:code).and_return(200) }
160
- it { expect(response).to_not be_a_bad_request }
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
- context 'not found' do
164
- before { allow(response).to receive(:code).and_return(404) }
165
- it { expect(response).to be_a_bad_request }
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
- context 'unauthorized' do
169
- before { allow(response).to receive(:code).and_return(401) }
170
- it { expect(response).to be_a_bad_request }
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
@@ -2,7 +2,7 @@ require 'bundler/setup'
2
2
  require 'rubygems'
3
3
  require 'smart_rspec'
4
4
  require 'faker'
5
- require 'factories/user'
6
-
7
- include Factories
5
+ require 'fixtures/user'
6
+ require 'fixtures/response'
8
7
 
8
+ include Fixtures
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.3
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: 2015-06-13 00:00:00.000000000 Z
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/assertions.rb
124
- - lib/smart_rspec/support/expectations.rb
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/factories/user.rb
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.4.6
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/factories/user.rb
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
-