test_assistant 0.0.4 → 0.1.0
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 +155 -71
- data/lib/test_assistant/configuration.rb +5 -0
- data/lib/test_assistant/email/expectation.rb +153 -46
- data/lib/test_assistant/json/expectation.rb +57 -20
- data/lib/test_assistant/version.rb +1 -1
- data/spec/email_expectation_spec.rb +369 -0
- data/spec/eql_json_spec.rb +58 -0
- data/spec/support/email_mock.rb +27 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b1c5794fb9961343ed9b9c926125a1e7f4128bb
|
4
|
+
data.tar.gz: 8dfad5f30319bffaac95db75a76c99228bbe3fad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e8db6c937c7895f188fc16c03f2fbf2344cfbd0e8621ccd42521cc380819ac259a05eac1e869e5036e9e1ec2f4ee1e57bf23ad13098ef32496abacd0adea298
|
7
|
+
data.tar.gz: f841a64f96693ebc1fd9422c931c8f626531f74e38935049bfc2851a3d0de7cae8250c84f5b84be276943f883a6eb12efa102297ef16b0f3ac19dcd751072c5e
|
data/README.md
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
# TestAssistant
|
2
2
|
|
3
|
-
|
3
|
+
RSpec toolbox for writing and diagnosing Ruby on Rails tests, faster - especially emails and JSON APIs.
|
4
4
|
|
5
|
-
##
|
6
|
-
|
7
|
-
TestAssistant is in its infancy and should be considered unstable. The API and behaviour is likely to change.
|
5
|
+
## Features
|
8
6
|
|
7
|
+
* Light-weight, scoped, lazily executed and composable tool-box, so you only include the features you want to use, when you want to use them with no unnecessary overhead
|
8
|
+
* JSON assertion that gives noise-free reports on complex nested structures, so you can find out exactly what has changed with your JSON API without having to manually diff large objects
|
9
|
+
* Expressive email assertions that let you succinctly describe when emails should and should not sent
|
10
|
+
* Automatic reporting of the context around failing tests, so you don't have to re-run them with additional logging or a debugger
|
9
11
|
|
10
12
|
## Installation
|
11
13
|
|
@@ -19,10 +21,6 @@ And then execute:
|
|
19
21
|
|
20
22
|
$ bundle
|
21
23
|
|
22
|
-
Or install it yourself as:
|
23
|
-
|
24
|
-
$ gem install test_assistant
|
25
|
-
|
26
24
|
## Usage
|
27
25
|
|
28
26
|
Test assistant requires access to the RSpec configuration object, so add the following to either `rails_helper.rb` or `spec_helper.rb`:
|
@@ -30,131 +28,217 @@ Test assistant requires access to the RSpec configuration object, so add the fol
|
|
30
28
|
```ruby
|
31
29
|
RSpec.configure do |config|
|
32
30
|
# other rspec configuration
|
33
|
-
|
31
|
+
|
34
32
|
TestAssistant.configure(config) do |ta_config|
|
35
33
|
# test assistant configuration here
|
36
34
|
end
|
37
35
|
end
|
38
36
|
```
|
39
37
|
|
40
|
-
|
38
|
+
## JSON expectations
|
39
|
+
|
40
|
+
Test Assistant lets you include helpers in your controller and request specs to get succinct declarative methods for defining the expected results for JSON responses.
|
41
41
|
|
42
|
-
|
42
|
+
### Setup
|
43
43
|
|
44
44
|
```ruby
|
45
45
|
TestAssistant.configure(config) do |ta_config|
|
46
|
-
ta_config.
|
46
|
+
ta_config.include_json_helpers type: :request
|
47
47
|
end
|
48
48
|
```
|
49
49
|
|
50
|
+
### Asserting JSON responses
|
51
|
+
|
52
|
+
Among the helpers provided are `json_response`, which automatically parses the last response object as json, and a custom assertion `eql_json` that reports failures in a format that is much clearer than anything provided by RSpec.
|
53
|
+
|
54
|
+
The full `expected` and `actual` values are still reported, but below is a separate report that only includes the paths to the failed nested values and their differences, removing the need to manually compare the two complete objects to find the difference.
|
55
|
+
|
50
56
|
```ruby
|
51
57
|
RSpec.describe 'making some valid request', type: :request do
|
52
58
|
context 'some important context' do
|
53
|
-
it 'should return
|
54
|
-
|
59
|
+
it 'should return some complicated JSON' do
|
60
|
+
|
61
|
+
perform_request
|
62
|
+
|
63
|
+
expect(json_response).to eql_json([
|
64
|
+
{
|
65
|
+
"a" => [
|
66
|
+
1, 2, 3
|
67
|
+
],
|
68
|
+
"c" => { "d" => "d'"}
|
69
|
+
},
|
70
|
+
{
|
71
|
+
"b" => [
|
72
|
+
1, 2, 3
|
73
|
+
],
|
74
|
+
"c" => { "d" => "d'"}
|
75
|
+
}
|
76
|
+
])
|
55
77
|
end
|
56
78
|
end
|
57
79
|
end
|
58
80
|
```
|
59
81
|
|
60
|
-
|
61
|
-
|
62
|
-
It's possible to invoke a debugger (`pry` is default, but fallback is to `byebug` and then `debugger`) if a test fails. This gives you access to some of the scope that the failing test ran in, allowing you to inspect objects and test variations of the failing assertion.
|
82
|
+
## Email expectations
|
63
83
|
|
64
|
-
|
84
|
+
Test Assistant provides a declarative API for describing when emails should be sent and their characteristics.
|
65
85
|
|
66
|
-
|
67
|
-
* `type: :<spec_type>` (default: nil - matches all test types) options.
|
86
|
+
### Setup
|
68
87
|
|
69
88
|
```ruby
|
70
89
|
TestAssistant.configure(config) do |ta_config|
|
71
|
-
|
90
|
+
ta_config.include_email_helpers type: :request
|
91
|
+
end
|
92
|
+
```
|
72
93
|
|
73
|
-
|
74
|
-
|
94
|
+
### Clearing emails
|
95
|
+
|
96
|
+
Emails can be cleared at any point by calling `clear_emails` in your tests. This is helpful when you are testing a user workflow that may trigger multiple emails.
|
97
|
+
|
98
|
+
Emails are automatically cleared between each request spec.
|
99
|
+
|
100
|
+
### Email receiver address
|
101
|
+
|
102
|
+
It's possible to assert an email was sent to one or more or more addresses using the following format:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
expect(email).to have_been_sent.to('user@email.com')
|
75
106
|
```
|
76
107
|
|
108
|
+
### Email sender address
|
109
|
+
|
110
|
+
Similarly, you can assert an email was sent from an address:
|
111
|
+
|
77
112
|
```ruby
|
78
|
-
|
79
|
-
context 'some important context' do
|
80
|
-
it 'should return a correct result', debugger: true do
|
81
|
-
# failing assertions
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
113
|
+
expect(email).to have_been_sent.from('user@email.com')
|
85
114
|
```
|
86
115
|
|
87
|
-
|
116
|
+
### Email subject
|
117
|
+
|
118
|
+
You can assert an email's subject:
|
88
119
|
|
89
|
-
|
90
|
-
|
120
|
+
```ruby
|
121
|
+
expect(email).to have_been_sent.with_subject('Welcome!')
|
122
|
+
```
|
91
123
|
|
92
|
-
|
124
|
+
|
125
|
+
### Email body
|
126
|
+
|
127
|
+
You can assert the body of an email by text:
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
expect(email).to have_been_sent.with_text('Welcome, user@email.com')
|
131
|
+
```
|
132
|
+
|
133
|
+
Or using a selector on the email's HTML:
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
expect(email).to have_been_sent.with_selector('#password')
|
137
|
+
```
|
138
|
+
|
139
|
+
Or look for links:
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
expect(email).to have_been_sent.with_link('www.site.com/onboarding/1')
|
143
|
+
```
|
144
|
+
|
145
|
+
Or images:
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
expect(email).to have_been_sent.with_image('www.site.com/assets/images/welcome.png')
|
149
|
+
```
|
150
|
+
|
151
|
+
### Chaining assertions
|
152
|
+
|
153
|
+
You can chain any combination of the above that you want for ultra specific assertions:
|
154
|
+
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
expect(email).to have_been_sent
|
158
|
+
.to('user@email.com')
|
159
|
+
.from('admin@site.com')
|
160
|
+
.with_subject('Welcome!')
|
161
|
+
.with_text('Welcome, user@email.com')
|
162
|
+
.with_selector('#password').and('#username')
|
163
|
+
.with_link('www.site.com/onboarding/1')
|
164
|
+
.with_image('www.site.com/assets/images/welcome.png')
|
165
|
+
|
166
|
+
```
|
167
|
+
|
168
|
+
You can also chain multiple assertions of the the same type with the `and` method:
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
expect(email).to have_been_sent
|
172
|
+
.with_text('Welcome, user@email.com').and('Thanks for signing up')
|
173
|
+
```
|
174
|
+
|
175
|
+
### Asserting emails are NOT sent
|
176
|
+
|
177
|
+
The `have_sent_email` assertion works with the negative case as well:
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
expect(email).to_not have_been_sent.with_text('Secret token')
|
181
|
+
```
|
182
|
+
|
183
|
+
## Failure Reporting
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
### Rendering a response context when a test fails
|
188
|
+
|
189
|
+
Test Assistant can automatically render the server response in your browser when a test fails and you have applied a nominated tag.
|
93
190
|
|
94
191
|
```ruby
|
95
192
|
TestAssistant.configure(config) do |ta_config|
|
96
|
-
ta_config.
|
193
|
+
ta_config.render_failed_responses tag: :focus, type: :request
|
97
194
|
end
|
98
195
|
```
|
99
196
|
|
100
197
|
```ruby
|
101
198
|
RSpec.describe 'making some valid request', type: :request do
|
102
199
|
context 'some important context' do
|
103
|
-
it 'should return
|
104
|
-
|
105
|
-
perform_request
|
106
|
-
|
107
|
-
expect(json_response).to eql_json([
|
108
|
-
{
|
109
|
-
"a" => [
|
110
|
-
1, 2, 3
|
111
|
-
],
|
112
|
-
"c" => { "d" => "d'"}
|
113
|
-
},
|
114
|
-
{
|
115
|
-
"b" => [
|
116
|
-
1, 2, 3
|
117
|
-
],
|
118
|
-
"c" => { "d" => "d'"}
|
119
|
-
}
|
120
|
-
])
|
200
|
+
it 'should return a correct result', focus: true do
|
201
|
+
# failing assertions
|
121
202
|
end
|
122
203
|
end
|
123
204
|
end
|
124
205
|
```
|
125
206
|
|
126
|
-
|
207
|
+
### Invoking a debugger when a test fails
|
127
208
|
|
209
|
+
It's possible to invoke a debugger (`pry` is default, but fallback is to `byebug` and then `debugger`) if a test fails. This gives you access to some of the scope that the failing test ran in, allowing you to inspect objects and test variations of the failing assertion.
|
210
|
+
|
211
|
+
The `debug_failed_responses` accepts a the following options:
|
212
|
+
|
213
|
+
* `tag: :<tag_name>` (default is `:debugger`)
|
214
|
+
* `type: :<spec_type>` (default: nil - matches all test types) options.
|
128
215
|
|
129
216
|
```ruby
|
130
217
|
TestAssistant.configure(config) do |ta_config|
|
131
|
-
|
132
|
-
|
218
|
+
ta_config.include_json_helpers type: :request
|
219
|
+
|
220
|
+
ta_config.debug_failed_responses tag: :debugger
|
221
|
+
end
|
133
222
|
```
|
134
223
|
|
135
224
|
```ruby
|
136
225
|
RSpec.describe 'making some valid request', type: :request do
|
137
226
|
context 'some important context' do
|
138
|
-
it 'should
|
139
|
-
|
140
|
-
.to('user@email.com')
|
141
|
-
.from('admin@site.com')
|
142
|
-
.with_subject('Welcome!')
|
143
|
-
.with_text('Welcome, user@email.com').and('Thanks for signing up')
|
144
|
-
.with_selector('#password').and('#username')
|
145
|
-
.with_link('www.site.com/onboarding/1')
|
146
|
-
.with_image('www.site.com/assets/images/welcome.png')
|
147
|
-
|
148
|
-
clear_emails
|
149
|
-
|
150
|
-
# further actions
|
151
|
-
|
152
|
-
expect(email).to have_been_sent.to('user@email.com')
|
227
|
+
it 'should return a correct result', debugger: true do
|
228
|
+
# failing assertions
|
153
229
|
end
|
154
230
|
end
|
155
231
|
end
|
156
232
|
```
|
157
233
|
|
234
|
+
## Test suite
|
235
|
+
|
236
|
+
TestAssistant comes with close to complete test coverage. You can run the test suite as follows:
|
237
|
+
|
238
|
+
```bash
|
239
|
+
rspec
|
240
|
+
```
|
241
|
+
|
158
242
|
## Contributing
|
159
243
|
|
160
244
|
1. Fork it ( https://github.com/greena13/test_assistant/fork )
|
@@ -14,6 +14,11 @@ module TestAssistant
|
|
14
14
|
|
15
15
|
def include_email_helpers(options = {})
|
16
16
|
@rspec_config.include Email::Helpers, options
|
17
|
+
|
18
|
+
@rspec_config.after :each, type: :request do
|
19
|
+
# clear emails after every request spec
|
20
|
+
ActionMailer::Base.deliveries = []
|
21
|
+
end
|
17
22
|
end
|
18
23
|
|
19
24
|
def render_failed_responses(options = {})
|
@@ -2,6 +2,7 @@ require 'capybara/rspec'
|
|
2
2
|
|
3
3
|
module TestAssistant::Email
|
4
4
|
class Expectation
|
5
|
+
|
5
6
|
def initialize
|
6
7
|
@expectations = {}
|
7
8
|
@failure_message = 'Expected email to be sent'
|
@@ -16,7 +17,7 @@ module TestAssistant::Email
|
|
16
17
|
match: ->(_, email, value){ value.all?{|text| email.has_content?(text) }},
|
17
18
|
actual: ->(_, email){ email.text}
|
18
19
|
},
|
19
|
-
|
20
|
+
matching_selector: {
|
20
21
|
match: ->(_, email, value){ value.all?{|text| email.has_selector?(text) }},
|
21
22
|
actual: ->(_, email){ email.native },
|
22
23
|
actual_name: :with_body
|
@@ -55,11 +56,10 @@ module TestAssistant::Email
|
|
55
56
|
end
|
56
57
|
|
57
58
|
def from(email_address)
|
58
|
-
if
|
59
|
-
|
59
|
+
if @expectations[:from]
|
60
|
+
raise ArgumentError('An email can only have one from address, but you tried to assert the presence of 2 or more values')
|
60
61
|
else
|
61
|
-
@expectations[:from]
|
62
|
-
@expectations[:from] << email_address
|
62
|
+
@expectations[:from] = email_address
|
63
63
|
end
|
64
64
|
|
65
65
|
@and_scope = :from
|
@@ -74,6 +74,8 @@ module TestAssistant::Email
|
|
74
74
|
@expectations[:with_subject] = subject
|
75
75
|
end
|
76
76
|
|
77
|
+
@and_scope = :with_subject
|
78
|
+
|
77
79
|
self
|
78
80
|
end
|
79
81
|
|
@@ -85,11 +87,11 @@ module TestAssistant::Email
|
|
85
87
|
self
|
86
88
|
end
|
87
89
|
|
88
|
-
def
|
89
|
-
@expectations[:
|
90
|
-
@expectations[:
|
90
|
+
def matching_selector(selector)
|
91
|
+
@expectations[:matching_selector] ||= []
|
92
|
+
@expectations[:matching_selector].push(selector)
|
91
93
|
|
92
|
-
@and_scope = :
|
94
|
+
@and_scope = :matching_selector
|
93
95
|
self
|
94
96
|
end
|
95
97
|
|
@@ -118,70 +120,169 @@ module TestAssistant::Email
|
|
118
120
|
|
119
121
|
matching_emails = @emails
|
120
122
|
|
121
|
-
@expectations.
|
122
|
-
|
123
|
-
matching_emails =
|
124
|
-
matching_emails.select do |email|
|
125
|
-
email_matches?(email, MATCHERS[attribute], expected)
|
126
|
-
end
|
127
|
-
|
128
|
-
if matching_emails.empty?
|
123
|
+
if @expectations.any?
|
124
|
+
@expectations.each do |attribute, expected|
|
129
125
|
@failed_attribute = attribute
|
130
126
|
@failed_expected = expected
|
131
|
-
|
127
|
+
|
128
|
+
matching_emails =
|
129
|
+
matching_emails.select do |email|
|
130
|
+
email_matches?(email, MATCHERS[attribute], expected)
|
131
|
+
end
|
132
|
+
|
133
|
+
if matching_emails.empty?
|
134
|
+
return false
|
135
|
+
end
|
132
136
|
end
|
133
|
-
end
|
134
137
|
|
135
|
-
|
138
|
+
true
|
139
|
+
else
|
140
|
+
@emails.any?
|
141
|
+
end
|
136
142
|
end
|
137
143
|
|
138
144
|
def failure_message
|
139
|
-
|
140
|
-
|
141
|
-
case @failed_expected
|
142
|
-
when String
|
143
|
-
"'#{@failed_expected}'"
|
144
|
-
when Array
|
145
|
-
@failed_expected.map{|val| "'#{val}'"}.to_sentence
|
146
|
-
else
|
147
|
-
@failed_expected
|
148
|
-
end
|
145
|
+
field_descs = attribute_descriptions
|
146
|
+
value_descs = value_descriptions
|
149
147
|
|
150
|
-
base_clause =
|
148
|
+
base_clause = expectation_description(
|
149
|
+
'Expected an email to be sent',
|
150
|
+
field_descs,
|
151
|
+
value_descs
|
152
|
+
)
|
151
153
|
|
152
154
|
if @emails.length == 0
|
153
|
-
base_clause
|
155
|
+
"#{base_clause} However, no emails were sent."
|
154
156
|
else
|
155
|
-
|
157
|
+
email_values = sent_email_values
|
158
|
+
|
159
|
+
if email_values.any?
|
160
|
+
base_clause + " However, #{email_pluralisation(@emails)} sent #{result_description(field_descs, [to_sentence(email_values)])}."
|
161
|
+
else
|
162
|
+
base_clause
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def result_description(field_descriptions, values)
|
168
|
+
to_sentence(
|
169
|
+
field_descriptions.map.with_index do |field_description, index|
|
170
|
+
value = values[index]
|
171
|
+
|
172
|
+
if [ 'matching selector', 'with link', 'with image' ].include?(field_description)
|
173
|
+
"with body #{value}"
|
174
|
+
else
|
175
|
+
"#{field_description} #{value}"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
)
|
179
|
+
end
|
180
|
+
|
181
|
+
def failure_message_when_negated
|
182
|
+
field_descs = attribute_descriptions(negated: true)
|
183
|
+
value_descs = value_descriptions(negated: true)
|
184
|
+
|
185
|
+
expectation_description(
|
186
|
+
'Expected no emails to be sent',
|
187
|
+
field_descs,
|
188
|
+
value_descs
|
189
|
+
)
|
190
|
+
end
|
191
|
+
|
192
|
+
private
|
193
|
+
|
194
|
+
def sent_email_values
|
195
|
+
@emails.inject([]) do |memo, email|
|
156
196
|
|
157
|
-
|
197
|
+
if [ :matching_selector, :with_link, :with_image ].include?(@failed_attribute)
|
198
|
+
memo << email_body(email)
|
199
|
+
else
|
158
200
|
matcher = MATCHERS[@failed_attribute]
|
159
201
|
|
160
202
|
value =
|
161
203
|
case matcher
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
204
|
+
when String, Symbol
|
205
|
+
email.send(matcher)
|
206
|
+
when Hash
|
207
|
+
field_description = matcher[:actual_name] if matcher[:actual_name]
|
208
|
+
matcher[:actual].(email, parsed_emails(email))
|
167
209
|
end
|
168
210
|
|
169
211
|
value = value.kind_of?(String) ? "'#{value}'" : value
|
170
212
|
memo << value
|
213
|
+
end
|
214
|
+
|
215
|
+
memo
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def expectation_description(base_clause, field_descriptions, value_descriptions)
|
220
|
+
description = base_clause
|
171
221
|
|
172
|
-
|
222
|
+
additional_clauses = []
|
223
|
+
|
224
|
+
field_descriptions.each.with_index do |field_description, index|
|
225
|
+
clause = ''
|
226
|
+
clause += " #{field_description}" if field_description.length > 0
|
227
|
+
|
228
|
+
if (value_description = value_descriptions[index])
|
229
|
+
clause += " #{value_description}"
|
173
230
|
end
|
174
231
|
|
232
|
+
additional_clauses.push(clause) if clause.length > 0
|
233
|
+
end
|
175
234
|
|
176
|
-
|
177
|
-
|
235
|
+
description + additional_clauses.join('') + '.'
|
236
|
+
end
|
237
|
+
|
238
|
+
def attribute_descriptions(negated: false)
|
239
|
+
attributes_to_describe =
|
240
|
+
if negated
|
241
|
+
@expectations.keys
|
242
|
+
else
|
243
|
+
[ @failed_attribute ]
|
244
|
+
end
|
245
|
+
|
246
|
+
attributes_to_describe.map do |attribute|
|
247
|
+
attribute.to_s.gsub('_', ' ')
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def value_descriptions(negated: false)
|
252
|
+
values_to_describe =
|
253
|
+
if negated
|
254
|
+
@expectations.values
|
255
|
+
else
|
256
|
+
[ @failed_expected ]
|
257
|
+
end
|
258
|
+
|
259
|
+
values_to_describe.map do |value|
|
260
|
+
case value
|
261
|
+
when String
|
262
|
+
"'#{value}'"
|
263
|
+
when Array
|
264
|
+
to_sentence(value.map{|val| "'#{val}'"})
|
178
265
|
else
|
179
|
-
|
266
|
+
value
|
180
267
|
end
|
181
268
|
end
|
269
|
+
|
182
270
|
end
|
183
271
|
|
184
|
-
|
272
|
+
def email_pluralisation(emails)
|
273
|
+
emails.length > 2 ? "#{emails.length} were": "1 was"
|
274
|
+
end
|
275
|
+
|
276
|
+
def to_sentence(items)
|
277
|
+
case items.length
|
278
|
+
when 0, 1
|
279
|
+
items.join('')
|
280
|
+
when 2
|
281
|
+
items.join(' and ')
|
282
|
+
else
|
283
|
+
items[0..(items.length-3)].join(', ') + items[(items.length-3)..items.length-1].join(' and ')
|
284
|
+
end
|
285
|
+
end
|
185
286
|
|
186
287
|
def parsed_emails(email)
|
187
288
|
@parsed_emails ||= {}
|
@@ -190,13 +291,19 @@ module TestAssistant::Email
|
|
190
291
|
end
|
191
292
|
|
192
293
|
def parser(email)
|
193
|
-
Capybara::Node::Simple.new(email
|
294
|
+
Capybara::Node::Simple.new(email_body(email))
|
295
|
+
end
|
296
|
+
|
297
|
+
def email_body(email)
|
298
|
+
email.parts.first.body.decoded
|
194
299
|
end
|
195
300
|
|
196
301
|
def email_matches?(email, assertion, expected)
|
197
302
|
case assertion
|
303
|
+
when :to
|
304
|
+
expected.include?(email.send(assertion))
|
198
305
|
when String, Symbol
|
199
|
-
email.send(assertion)
|
306
|
+
expected == email.send(assertion)
|
200
307
|
when Hash
|
201
308
|
assertion[:match].(email, parsed_emails(email), expected)
|
202
309
|
else
|
@@ -5,6 +5,8 @@ module TestAssistant::Json
|
|
5
5
|
class Expectation
|
6
6
|
def initialize(expected)
|
7
7
|
@expected = expected
|
8
|
+
@message = ''
|
9
|
+
@reported_differences = {}
|
8
10
|
end
|
9
11
|
|
10
12
|
def diffable?
|
@@ -12,9 +14,6 @@ module TestAssistant::Json
|
|
12
14
|
end
|
13
15
|
|
14
16
|
def matches?(actual)
|
15
|
-
@message = ''
|
16
|
-
@reported_differences = {}
|
17
|
-
|
18
17
|
@actual = actual
|
19
18
|
@expected.eql?(@actual)
|
20
19
|
end
|
@@ -24,36 +23,71 @@ module TestAssistant::Json
|
|
24
23
|
@message += "Actual: #{@actual}\n\n"
|
25
24
|
@message += "Differences\n\n"
|
26
25
|
|
27
|
-
|
26
|
+
add_diff_to_message(@actual, @expected)
|
28
27
|
|
29
|
-
|
30
|
-
|
28
|
+
@message
|
29
|
+
end
|
31
30
|
|
32
|
-
|
33
|
-
when '-'
|
34
|
-
attribute, value = operands
|
31
|
+
private
|
35
32
|
|
36
|
-
|
37
|
-
|
33
|
+
def add_diff_to_message(original_actual, original_expected, parent_prefix = '')
|
34
|
+
differences = HashDiff
|
35
|
+
.diff(original_actual, original_expected)
|
36
|
+
.sort{|diff1, diff2| diff1[1] <=> diff2[1]}
|
38
37
|
|
39
|
-
|
40
|
-
|
38
|
+
grouped_differences =
|
39
|
+
differences.inject({}) do |memo, diff|
|
40
|
+
operator, name, value = diff
|
41
|
+
memo[name] ||= {}
|
42
|
+
memo[name][operator] = value
|
43
|
+
memo
|
44
|
+
end
|
41
45
|
|
42
|
-
|
46
|
+
grouped_differences.each do |name, difference|
|
47
|
+
removed_value = difference['-']
|
48
|
+
added_value = difference['+']
|
49
|
+
swapped_value = difference['~']
|
43
50
|
|
44
|
-
|
51
|
+
full_name = parent_prefix.length > 0 ? "#{parent_prefix}.#{name}" : name
|
45
52
|
|
46
|
-
|
47
|
-
|
53
|
+
if non_empty_hash?(removed_value) && non_empty_hash?(added_value)
|
54
|
+
add_diff_to_message(removed_value, added_value, full_name)
|
55
|
+
|
56
|
+
elsif non_empty_array?(removed_value) && non_empty_array?(added_value)
|
48
57
|
|
49
|
-
|
58
|
+
[removed_value.length, added_value.length].max.times do |i|
|
59
|
+
add_diff_to_message(removed_value[i], added_value[i], full_name)
|
60
|
+
end
|
61
|
+
else
|
62
|
+
if difference.has_key?('~')
|
63
|
+
add_diff_description(full_name,
|
64
|
+
format_diff(
|
65
|
+
full_name,
|
66
|
+
attribute_value(original_expected, name),
|
67
|
+
swapped_value
|
68
|
+
)
|
69
|
+
)
|
70
|
+
else
|
71
|
+
add_diff_description(full_name,
|
72
|
+
format_diff(
|
73
|
+
full_name,
|
74
|
+
added_value || attribute_value(original_expected, name),
|
75
|
+
removed_value || attribute_value(original_actual, name)
|
76
|
+
)
|
77
|
+
)
|
78
|
+
end
|
50
79
|
end
|
80
|
+
|
51
81
|
end
|
82
|
+
end
|
52
83
|
|
53
|
-
|
84
|
+
def non_empty_hash?(target)
|
85
|
+
target.kind_of?(Hash) && target.any?
|
54
86
|
end
|
55
87
|
|
56
|
-
|
88
|
+
def non_empty_array?(target)
|
89
|
+
target.kind_of?(Array) && target.any?
|
90
|
+
end
|
57
91
|
|
58
92
|
def add_diff_description(attribute, difference_description)
|
59
93
|
unless already_reported_difference?(attribute)
|
@@ -79,10 +113,13 @@ module TestAssistant::Json
|
|
79
113
|
|
80
114
|
result = target
|
81
115
|
|
116
|
+
|
82
117
|
keys.each do |key|
|
118
|
+
|
83
119
|
unless key == ''
|
84
120
|
result = result[key]
|
85
121
|
end
|
122
|
+
|
86
123
|
end
|
87
124
|
|
88
125
|
result
|
@@ -0,0 +1,369 @@
|
|
1
|
+
require 'test_assistant/email/helpers'
|
2
|
+
require_relative './support/email_mock'
|
3
|
+
|
4
|
+
RSpec.describe 'have_sent_email' do
|
5
|
+
include TestAssistant::Email::Helpers
|
6
|
+
|
7
|
+
context "when no emails have been sent" do
|
8
|
+
subject { [] }
|
9
|
+
|
10
|
+
it "then the positive assertion fails" do
|
11
|
+
expect {
|
12
|
+
expect(subject).to have_been_sent
|
13
|
+
}.to raise_error.with_message('Expected an email to be sent. However, no emails were sent.')
|
14
|
+
end
|
15
|
+
|
16
|
+
it "then the negative assertion passes" do
|
17
|
+
expect {
|
18
|
+
expect(subject).to_not have_been_sent
|
19
|
+
}.to_not raise_error
|
20
|
+
end
|
21
|
+
|
22
|
+
it "then a non-matching 'to' assertion fails" do
|
23
|
+
expect {
|
24
|
+
expect(subject).to have_been_sent.to('test@email.com')
|
25
|
+
}.to raise_error.with_message('Expected an email to be sent to \'test@email.com\'. However, no emails were sent.')
|
26
|
+
end
|
27
|
+
|
28
|
+
it "then a non-matching 'from' assertion fails" do
|
29
|
+
expect {
|
30
|
+
expect(subject).to have_been_sent.from('test@email.com')
|
31
|
+
}.to raise_error.with_message('Expected an email to be sent from \'test@email.com\'. However, no emails were sent.')
|
32
|
+
end
|
33
|
+
|
34
|
+
it "then a non-matching 'with_subject' assertion fails" do
|
35
|
+
expect {
|
36
|
+
expect(subject).to have_been_sent.with_subject('Subject')
|
37
|
+
}.to raise_error.with_message('Expected an email to be sent with subject \'Subject\'. However, no emails were sent.')
|
38
|
+
end
|
39
|
+
|
40
|
+
it "then a non-matching 'with_text' assertion fails" do
|
41
|
+
expect {
|
42
|
+
expect(subject).to have_been_sent.with_text('Text')
|
43
|
+
}.to raise_error.with_message('Expected an email to be sent with text \'Text\'. However, no emails were sent.')
|
44
|
+
end
|
45
|
+
|
46
|
+
it "then a non-matching 'matching_selector' assertion fails" do
|
47
|
+
expect {
|
48
|
+
expect(subject).to have_been_sent.matching_selector('h1')
|
49
|
+
}.to raise_error.with_message('Expected an email to be sent matching selector \'h1\'. However, no emails were sent.')
|
50
|
+
end
|
51
|
+
|
52
|
+
it "then a non-matching 'with_link' assertion fails" do
|
53
|
+
expect {
|
54
|
+
expect(subject).to have_been_sent.with_link('www.example.com')
|
55
|
+
}.to raise_error.with_message('Expected an email to be sent with link \'www.example.com\'. However, no emails were sent.')
|
56
|
+
end
|
57
|
+
|
58
|
+
it "then a non-matching 'with_image' assertion fails" do
|
59
|
+
expect {
|
60
|
+
expect(subject).to have_been_sent.with_image('www.example.com')
|
61
|
+
}.to raise_error.with_message('Expected an email to be sent with image \'www.example.com\'. However, no emails were sent.')
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
context "when an email has been sent" do
|
67
|
+
subject { [ EmailMock.new ] }
|
68
|
+
|
69
|
+
it "then the unqualified assertion passes" do
|
70
|
+
expect {
|
71
|
+
expect(subject).to have_been_sent
|
72
|
+
}.to_not raise_error
|
73
|
+
end
|
74
|
+
|
75
|
+
it "then the unqualified negative assertion fails" do
|
76
|
+
expect {
|
77
|
+
expect(subject).to_not have_been_sent
|
78
|
+
}.to raise_error("Expected no emails to be sent.")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "when a matching email has been sent" do
|
83
|
+
subject { [ EmailMock.new ] }
|
84
|
+
|
85
|
+
it "then a positive 'to' assertion passes" do
|
86
|
+
expect {
|
87
|
+
expect(subject).to have_been_sent.to(subject[0].to)
|
88
|
+
}.to_not raise_error
|
89
|
+
end
|
90
|
+
|
91
|
+
it "then a negative 'to' assertion fails" do
|
92
|
+
expect {
|
93
|
+
expect(subject).to_not have_been_sent.to(subject[0].to)
|
94
|
+
}.to raise_error.with_message("Expected no emails to be sent to '#{subject[0].to}'.")
|
95
|
+
end
|
96
|
+
|
97
|
+
it "then a positive 'from' assertion passes" do
|
98
|
+
expect {
|
99
|
+
expect(subject).to have_been_sent.from(subject[0].from)
|
100
|
+
}.to_not raise_error
|
101
|
+
end
|
102
|
+
|
103
|
+
it "then a negative 'from' assertion fails" do
|
104
|
+
expect {
|
105
|
+
expect(subject).to_not have_been_sent.from(subject[0].from)
|
106
|
+
}.to raise_error.with_message("Expected no emails to be sent from '#{subject[0].from}'.")
|
107
|
+
end
|
108
|
+
|
109
|
+
it "then a positive 'with_subject' assertion passes" do
|
110
|
+
expect {
|
111
|
+
expect(subject).to have_been_sent.with_subject(subject[0].subject)
|
112
|
+
}.to_not raise_error
|
113
|
+
end
|
114
|
+
|
115
|
+
it "then a negative 'with_subject' assertion fails" do
|
116
|
+
expect {
|
117
|
+
expect(subject).to_not have_been_sent.with_subject(subject[0].subject)
|
118
|
+
}.to raise_error.with_message("Expected no emails to be sent with subject '#{subject[0].subject}'.")
|
119
|
+
end
|
120
|
+
|
121
|
+
it "then a positive 'with_text' assertion passes" do
|
122
|
+
expect {
|
123
|
+
expect(subject).to have_been_sent.with_text(subject[0].text)
|
124
|
+
}.to_not raise_error
|
125
|
+
end
|
126
|
+
|
127
|
+
it "then a negative 'with_text' assertion fails" do
|
128
|
+
expect {
|
129
|
+
expect(subject).to_not have_been_sent.with_text(subject[0].text)
|
130
|
+
}.to raise_error.with_message("Expected no emails to be sent with text '#{subject[0].text}'.")
|
131
|
+
end
|
132
|
+
|
133
|
+
it "then a positive 'matching_selector' assertion passes" do
|
134
|
+
expect {
|
135
|
+
expect(subject).to have_been_sent.matching_selector('h1')
|
136
|
+
}.to_not raise_error
|
137
|
+
end
|
138
|
+
|
139
|
+
it "then a negative 'matching_selector' assertion fails" do
|
140
|
+
expect {
|
141
|
+
expect(subject).to_not have_been_sent.matching_selector('h1')
|
142
|
+
}.to raise_error.with_message("Expected no emails to be sent matching selector 'h1'.")
|
143
|
+
end
|
144
|
+
|
145
|
+
it "then a positive 'with_link' assertion passes" do
|
146
|
+
expect {
|
147
|
+
expect(subject).to have_been_sent.with_link('www.test.com')
|
148
|
+
}.to_not raise_error
|
149
|
+
end
|
150
|
+
|
151
|
+
it "then a negative 'with_link' assertion fails" do
|
152
|
+
expect {
|
153
|
+
expect(subject).to_not have_been_sent.with_link('www.test.com')
|
154
|
+
}.to raise_error.with_message("Expected no emails to be sent with link 'www.test.com'.")
|
155
|
+
end
|
156
|
+
|
157
|
+
it "then a positive 'with_image' assertion passes" do
|
158
|
+
expect {
|
159
|
+
expect(subject).to have_been_sent.with_image('www.test.com')
|
160
|
+
}.to_not raise_error
|
161
|
+
end
|
162
|
+
|
163
|
+
it "then a negative 'with_image' assertion fails" do
|
164
|
+
expect {
|
165
|
+
expect(subject).to_not have_been_sent.with_image('www.test.com')
|
166
|
+
}.to raise_error.with_message("Expected no emails to be sent with image 'www.test.com'.")
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context "when a non-matching email has been sent" do
|
171
|
+
subject { [ EmailMock.new ] }
|
172
|
+
|
173
|
+
it "then a positive 'to' assertion fails" do
|
174
|
+
expect {
|
175
|
+
expect(subject).to have_been_sent.to('other@email.com')
|
176
|
+
}.to raise_error.with_message("Expected an email to be sent to 'other@email.com'. However, 1 was sent to '#{subject[0].to}'.")
|
177
|
+
end
|
178
|
+
|
179
|
+
it "then a negative 'to' assertion passes" do
|
180
|
+
expect {
|
181
|
+
expect(subject).to_not have_been_sent.to('other@email.com')
|
182
|
+
}.to_not raise_error
|
183
|
+
end
|
184
|
+
|
185
|
+
it "then a positive 'from' assertion fails" do
|
186
|
+
expect {
|
187
|
+
expect(subject).to have_been_sent.from('other@email.com')
|
188
|
+
}.to raise_error.with_message("Expected an email to be sent from 'other@email.com'. However, 1 was sent from '#{subject[0].from}'.")
|
189
|
+
end
|
190
|
+
|
191
|
+
it "then a negative 'from' assertion passes" do
|
192
|
+
expect {
|
193
|
+
expect(subject).to_not have_been_sent.from('other@email.com')
|
194
|
+
}.to_not raise_error
|
195
|
+
end
|
196
|
+
|
197
|
+
it "then a positive 'with_subject' assertion fails" do
|
198
|
+
expect {
|
199
|
+
expect(subject).to have_been_sent.with_subject('Other Subject')
|
200
|
+
}.to raise_error.with_message("Expected an email to be sent with subject 'Other Subject'. However, 1 was sent with subject '#{subject[0].subject}'.")
|
201
|
+
end
|
202
|
+
|
203
|
+
it "then a negative 'with_subject' assertion passes" do
|
204
|
+
expect {
|
205
|
+
expect(subject).to_not have_been_sent.with_subject('Other Subject')
|
206
|
+
}.to_not raise_error
|
207
|
+
end
|
208
|
+
|
209
|
+
it "then a positive 'with_text' assertion fails" do
|
210
|
+
expect {
|
211
|
+
expect(subject).to have_been_sent.with_text('Other text')
|
212
|
+
}.to raise_error.with_message("Expected an email to be sent with text 'Other text'. However, 1 was sent with text '#{subject[0].text}'.")
|
213
|
+
end
|
214
|
+
|
215
|
+
it "then a negative 'with_text' assertion passes" do
|
216
|
+
expect {
|
217
|
+
expect(subject).to_not have_been_sent.with_text('Other text')
|
218
|
+
}.to_not raise_error
|
219
|
+
end
|
220
|
+
|
221
|
+
it "then a positive 'matching_selector' assertion fails" do
|
222
|
+
expect {
|
223
|
+
expect(subject).to have_been_sent.matching_selector('.other')
|
224
|
+
}.to raise_error.with_message("Expected an email to be sent matching selector '.other'. However, 1 was sent with body #{subject[0].body}.")
|
225
|
+
end
|
226
|
+
|
227
|
+
it "then a negative 'matching_selector' assertion passes" do
|
228
|
+
expect {
|
229
|
+
expect(subject).to_not have_been_sent.matching_selector('.other')
|
230
|
+
}.to_not raise_error
|
231
|
+
end
|
232
|
+
|
233
|
+
it "then a positive 'with_link' assertion fails"do
|
234
|
+
expect {
|
235
|
+
expect(subject).to have_been_sent.with_link('www.other.com')
|
236
|
+
}.to raise_error.with_message("Expected an email to be sent with link 'www.other.com'. However, 1 was sent with body #{subject[0].body}.")
|
237
|
+
end
|
238
|
+
|
239
|
+
it "then a negative 'with_link' assertion passes" do
|
240
|
+
expect {
|
241
|
+
expect(subject).to_not have_been_sent.with_link('www.other.com')
|
242
|
+
}.to_not raise_error
|
243
|
+
end
|
244
|
+
|
245
|
+
it "then a positive 'with_image' assertion fails" do
|
246
|
+
expect {
|
247
|
+
expect(subject).to have_been_sent.with_image('www.other.com')
|
248
|
+
}.to raise_error.with_message("Expected an email to be sent with image 'www.other.com'. However, 1 was sent with body #{subject[0].body}.")
|
249
|
+
end
|
250
|
+
|
251
|
+
it "then a negative 'with_image' assertion passes" do
|
252
|
+
expect {
|
253
|
+
expect(subject).to_not have_been_sent.with_image('www.other.com')
|
254
|
+
}.to_not raise_error
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
context "when multiple emails have been sent" do
|
259
|
+
subject { [ EmailMock.new, EmailMock.new(to: 'other@email.com') ] }
|
260
|
+
|
261
|
+
it "then a positive assertion matching the first email passes" do
|
262
|
+
expect {
|
263
|
+
expect(subject).to have_been_sent.to(subject[0].to)
|
264
|
+
}.to_not raise_error
|
265
|
+
end
|
266
|
+
|
267
|
+
it "then a negative assertion matching the first email fails" do
|
268
|
+
expect {
|
269
|
+
expect(subject).to_not have_been_sent.to(subject[0].to)
|
270
|
+
}.to raise_error.with_message("Expected no emails to be sent to '#{subject[0].to}'.")
|
271
|
+
end
|
272
|
+
|
273
|
+
it "then a positive assertion matching the second email passes" do
|
274
|
+
expect {
|
275
|
+
expect(subject).to have_been_sent.to(subject[1].to)
|
276
|
+
}.to_not raise_error
|
277
|
+
end
|
278
|
+
|
279
|
+
it "then a negative assertion matching the second email fails" do
|
280
|
+
expect {
|
281
|
+
expect(subject).to_not have_been_sent.to(subject[1].to)
|
282
|
+
}.to raise_error.with_message("Expected no emails to be sent to '#{subject[1].to}'.")
|
283
|
+
end
|
284
|
+
|
285
|
+
end
|
286
|
+
|
287
|
+
context "when using multiple qualifiers" do
|
288
|
+
subject { [ EmailMock.new ] }
|
289
|
+
|
290
|
+
it "then a positive assertions correctly matches a matching email" do
|
291
|
+
expect {
|
292
|
+
expect(subject).to have_been_sent.to(subject[0].to).from(subject[0].from)
|
293
|
+
}.to_not raise_error
|
294
|
+
end
|
295
|
+
|
296
|
+
it "then a positive assertions don't match an email if the first qualifier isn't satisfied" do
|
297
|
+
expect {
|
298
|
+
expect(subject).to have_been_sent.to('other@email.com').from(subject[0].from)
|
299
|
+
}.to raise_error.with_message("Expected an email to be sent to 'other@email.com'. However, 1 was sent to '#{subject[0].to}'.")
|
300
|
+
end
|
301
|
+
|
302
|
+
it "then a positive assertions don't match an email if the last qualifier isn't satisfied" do
|
303
|
+
expect {
|
304
|
+
expect(subject).to have_been_sent.to(subject[0].to).from('other@email.com')
|
305
|
+
}.to raise_error.with_message("Expected an email to be sent from 'other@email.com'. However, 1 was sent from '#{subject[0].from}'.")
|
306
|
+
end
|
307
|
+
|
308
|
+
it "then a negative assertions correctly matches a matching email" do
|
309
|
+
expect {
|
310
|
+
expect(subject).to_not have_been_sent.to(subject[0].to).from(subject[0].from)
|
311
|
+
}.to raise_error.with_message("Expected no emails to be sent to '#{subject[0].to}' from '#{subject[0].from}'.")
|
312
|
+
end
|
313
|
+
|
314
|
+
it "then a negative assertions don't match an email if the first qualifier isn't satisfied" do
|
315
|
+
expect {
|
316
|
+
expect(subject).to_not have_been_sent.to('other@email.com').from(subject[0].from)
|
317
|
+
}.to_not raise_error
|
318
|
+
end
|
319
|
+
|
320
|
+
it "then a negative assertions don't match an email if the last qualifier isn't satisfied" do
|
321
|
+
expect {
|
322
|
+
expect(subject).to_not have_been_sent.to(subject[0].to).from('other@email.com')
|
323
|
+
}.to_not raise_error
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
context "when using the and method" do
|
328
|
+
subject { [ EmailMock.new ] }
|
329
|
+
|
330
|
+
it "then a positive assertion will fail if the first qualifier is not satisfied" do
|
331
|
+
expect {
|
332
|
+
expect(subject).to have_been_sent.with_text('Other').and('Email')
|
333
|
+
}.to raise_error.with_message("Expected an email to be sent with text 'Other' and 'Email'. However, 1 was sent with text '#{subject[0].text}'.")
|
334
|
+
end
|
335
|
+
|
336
|
+
it "then a positive assertion will fail if the second qualifier is not satisfied" do
|
337
|
+
expect {
|
338
|
+
expect(subject).to have_been_sent.with_text('Test').and('Other')
|
339
|
+
}.to raise_error.with_message("Expected an email to be sent with text 'Test' and 'Other'. However, 1 was sent with text '#{subject[0].text}'.")
|
340
|
+
end
|
341
|
+
|
342
|
+
it "then a positive assertion will pass if both qualifiers are satisfied" do
|
343
|
+
expect {
|
344
|
+
expect(subject).to have_been_sent.with_text('Test').and('Email')
|
345
|
+
}.to_not raise_error
|
346
|
+
end
|
347
|
+
|
348
|
+
it "then a negative assertion will pass if the first qualifier is not satisfied" do
|
349
|
+
expect {
|
350
|
+
expect(subject).to_not have_been_sent.with_text('Other').and('Email')
|
351
|
+
}.to_not raise_error
|
352
|
+
end
|
353
|
+
|
354
|
+
it "then a negative assertion will pass if the second qualifier is not satisfied" do
|
355
|
+
expect {
|
356
|
+
expect(subject).to_not have_been_sent.with_text('Test').and('Other')
|
357
|
+
}.to_not raise_error
|
358
|
+
end
|
359
|
+
|
360
|
+
it "then a negative assertion will fail if both qualifiers are satisfied" do
|
361
|
+
expect {
|
362
|
+
expect(subject).to_not have_been_sent.with_text('Test').and('Email')
|
363
|
+
}.to raise_error.with_message('Expected no emails to be sent with text \'Test\' and \'Email\'.')
|
364
|
+
end
|
365
|
+
|
366
|
+
end
|
367
|
+
|
368
|
+
|
369
|
+
end
|
data/spec/eql_json_spec.rb
CHANGED
@@ -104,6 +104,64 @@ RSpec.describe "eql_json" do
|
|
104
104
|
|
105
105
|
end
|
106
106
|
|
107
|
+
context "when comparing arrays of objects" do
|
108
|
+
let(:expected) {
|
109
|
+
{
|
110
|
+
'alpha' => 'alpha',
|
111
|
+
'beta' => [ 1, 2, 3],
|
112
|
+
'gamma' => [
|
113
|
+
{ 'i' => 'a', 'j' => 'b' },
|
114
|
+
{ 'i' => 'c', 'j' => 'd' },
|
115
|
+
{ 'i' => 'e', 'j' => 'f' },
|
116
|
+
]
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
let(:actual) {
|
121
|
+
{
|
122
|
+
'alpha' => 'alpha',
|
123
|
+
'beta' => [ 1, 2, 3],
|
124
|
+
'gamma' => [
|
125
|
+
{ 'j' => 'b' },
|
126
|
+
{ 'i' => 'c', 'j' => 'D' },
|
127
|
+
{ 'i' => 'e', 'j' => 'f', 'k' => 'k' },
|
128
|
+
]
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
it "then correctly reports the elements that have changed" do
|
133
|
+
|
134
|
+
expect(actual).to eql(actual)
|
135
|
+
|
136
|
+
expect(actual).to_not eql(expected)
|
137
|
+
|
138
|
+
begin
|
139
|
+
expect(actual).to eql_json(expected)
|
140
|
+
rescue RSpec::Expectations::ExpectationNotMetError => e
|
141
|
+
|
142
|
+
expect(e.message).to eql(error_message(expected, actual, {
|
143
|
+
|
144
|
+
'gamma[0].i' => {
|
145
|
+
expected: "'a'",
|
146
|
+
actual: ''
|
147
|
+
},
|
148
|
+
'gamma[1].j' => {
|
149
|
+
expected: "'d'",
|
150
|
+
actual: "'D'"
|
151
|
+
},
|
152
|
+
'gamma[2].k' => {
|
153
|
+
expected: '',
|
154
|
+
actual: "'k'"
|
155
|
+
}
|
156
|
+
|
157
|
+
}))
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
107
165
|
context "when comparing objects" do
|
108
166
|
let(:expected) { {
|
109
167
|
'a' => 'a',
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class EmailMock
|
2
|
+
attr_reader :to, :from, :subject, :text, :body
|
3
|
+
|
4
|
+
def initialize(to: 'receiver@email.com', from: 'sender@email.com', subject: 'Subject', text: 'Test Email', body: "<body><h1>Test Email</h1><a href='www.test.com' /><img src='www.test.com' /></body>")
|
5
|
+
@to, @from, @subject, @text, @body = to, from, subject, text, body
|
6
|
+
end
|
7
|
+
|
8
|
+
def parts
|
9
|
+
[
|
10
|
+
EmailBodyMock.new(@body)
|
11
|
+
]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class EmailBodyMock
|
16
|
+
def initialize(text)
|
17
|
+
@text = text
|
18
|
+
end
|
19
|
+
|
20
|
+
def body
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def decoded
|
25
|
+
@text
|
26
|
+
end
|
27
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: test_assistant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aleck Greenham
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-07-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capybara
|
@@ -137,8 +137,10 @@ files:
|
|
137
137
|
- lib/test_assistant/json/expectation.rb
|
138
138
|
- lib/test_assistant/json/helpers.rb
|
139
139
|
- lib/test_assistant/version.rb
|
140
|
+
- spec/email_expectation_spec.rb
|
140
141
|
- spec/eql_json_spec.rb
|
141
142
|
- spec/spec_helper.rb
|
143
|
+
- spec/support/email_mock.rb
|
142
144
|
- test_assistant.gemspec
|
143
145
|
homepage: https://github.com/greena13/test_assistant
|
144
146
|
licenses:
|
@@ -160,10 +162,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
160
162
|
version: '0'
|
161
163
|
requirements: []
|
162
164
|
rubyforge_project:
|
163
|
-
rubygems_version: 2.
|
165
|
+
rubygems_version: 2.5.1
|
164
166
|
signing_key:
|
165
167
|
specification_version: 4
|
166
168
|
summary: A toolbox for increased testing efficiency with RSpec
|
167
169
|
test_files:
|
170
|
+
- spec/email_expectation_spec.rb
|
168
171
|
- spec/eql_json_spec.rb
|
169
172
|
- spec/spec_helper.rb
|
173
|
+
- spec/support/email_mock.rb
|