test_assistant 0.0.1 → 0.0.2
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 +31 -1
- data/lib/test_assistant/configuration.rb +5 -0
- data/lib/test_assistant/email/expectation.rb +209 -0
- data/lib/test_assistant/email/helpers.rb +13 -0
- data/lib/test_assistant/version.rb +1 -1
- data/test_assistant.gemspec +1 -0
- metadata +24 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fd9da0b295791c6249e94172857509c44b58b7ac
|
4
|
+
data.tar.gz: ffb211e31de33220bfeea704961e844738597308
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c98c15b60558a8615edfdfc7336e307848eb481f8167574a7208d559d48220b1f6686b454b38e9c6f9932329158d5fbac98b40f470b71e89e956b62cb6f34db
|
7
|
+
data.tar.gz: 3d0500451574c4b9bffd61a05b5a8380a9fc5a8eeac1bc555b5e38348945c3d7f7b8bf931fb832fc6faf419b20fcf8ee98792ccd8a754c0de5668481e9b3f804
|
data/README.md
CHANGED
@@ -84,10 +84,40 @@ RSpec.describe 'making some valid request', type: :request do
|
|
84
84
|
end
|
85
85
|
```
|
86
86
|
|
87
|
+
## Email expectations
|
88
|
+
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
TestAssistant.configure(config) do |ta_config|
|
92
|
+
ta_config.include_email_helpers type: :request
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
RSpec.describe 'making some valid request', type: :request do
|
98
|
+
context 'some important context' do
|
99
|
+
it 'should send an email' do
|
100
|
+
expect(email).to have_been_sent
|
101
|
+
.to('user@email.com')
|
102
|
+
.from('admin@site.com')
|
103
|
+
.with_subject('Welcome!')
|
104
|
+
.with_text('Welcome, user@email.com').and('Thanks for signing up')
|
105
|
+
.with_selector('#password').and('#username')
|
106
|
+
.with_link('www.site.com/onboarding/1')
|
107
|
+
.with_image('www.site.com/assets/images/welcome.png')
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
```
|
112
|
+
|
87
113
|
## Contributing
|
88
114
|
|
89
|
-
1. Fork it ( https://github.com/
|
115
|
+
1. Fork it ( https://github.com/greena13/test_assistant/fork )
|
90
116
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
91
117
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
92
118
|
4. Push to the branch (`git push origin my-new-feature`)
|
93
119
|
5. Create a new Pull Request
|
120
|
+
|
121
|
+
## Inspirations
|
122
|
+
|
123
|
+
* [CapybaraEmail](https://github.com/DockYard/capybara-email)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module TestAssistant
|
2
2
|
autoload :JSONHelpers, 'test_assistant/json_helpers'
|
3
|
+
autoload :Email, 'test_assistant/email/helpers'
|
3
4
|
autoload :FailureReporter, 'test_assistant/failure_reporter'
|
4
5
|
|
5
6
|
class Configuration
|
@@ -11,6 +12,10 @@ module TestAssistant
|
|
11
12
|
@rspec_config.include JSONHelpers, options
|
12
13
|
end
|
13
14
|
|
15
|
+
def include_email_helpers(options = {})
|
16
|
+
@rspec_config.include Email::Helpers, options
|
17
|
+
end
|
18
|
+
|
14
19
|
def render_failed_responses(options = {})
|
15
20
|
tag_filter = options[:tag]
|
16
21
|
no_tag_filter = !tag_filter
|
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'capybara/rspec'
|
2
|
+
|
3
|
+
module TestAssistant::Email
|
4
|
+
class Expectation
|
5
|
+
def initialize
|
6
|
+
@expectations = {}
|
7
|
+
@failure_message = 'Expected email to be sent'
|
8
|
+
@and_scope = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
MATCHERS = {
|
12
|
+
to: :to,
|
13
|
+
from: :from,
|
14
|
+
with_subject: :subject,
|
15
|
+
with_text: {
|
16
|
+
match: ->(_, email, value){ value.all?{|text| email.has_content?(text) }},
|
17
|
+
actual: ->(_, email){ email.text}
|
18
|
+
},
|
19
|
+
with_selector: {
|
20
|
+
match: ->(_, email, value){ value.all?{|text| email.has_selector?(text) }},
|
21
|
+
actual: ->(_, email){ email.native },
|
22
|
+
actual_name: :with_body
|
23
|
+
},
|
24
|
+
with_link: {
|
25
|
+
match: ->(_, email, value){ value.all?{|value| email.has_selector?("a[href='#{value}']") }},
|
26
|
+
actual: ->(_, email){ email.native },
|
27
|
+
actual_name: :with_body
|
28
|
+
},
|
29
|
+
with_image: {
|
30
|
+
match: ->(_, email, value){ value.all?{|value| email.has_selector?("img[src='#{value}']") }},
|
31
|
+
actual: ->(_, email){ email.native },
|
32
|
+
actual_name: :with_body
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
def and(*arguments)
|
37
|
+
if @and_scope
|
38
|
+
self.send(@and_scope, *arguments)
|
39
|
+
else
|
40
|
+
ArugmentError.new("Cannot use and without a proceeding assertion.")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def to(email_address)
|
45
|
+
if email_address.kind_of?(Array)
|
46
|
+
@expectations[:to] = email_address
|
47
|
+
else
|
48
|
+
@expectations[:to] ||= []
|
49
|
+
@expectations[:to] << email_address
|
50
|
+
end
|
51
|
+
|
52
|
+
@and_scope = :to
|
53
|
+
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def from(email_address)
|
58
|
+
if email_address.kind_of?(Array)
|
59
|
+
@expectations[:from] = email_address
|
60
|
+
else
|
61
|
+
@expectations[:from] ||= []
|
62
|
+
@expectations[:from] << email_address
|
63
|
+
end
|
64
|
+
|
65
|
+
@and_scope = :from
|
66
|
+
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
def with_subject(subject)
|
71
|
+
if @expectations[:with_subject]
|
72
|
+
raise ArgumentError('An email can only have one subject, but you tried to assert the presence of 2 or more values')
|
73
|
+
else
|
74
|
+
@expectations[:with_subject] = subject
|
75
|
+
end
|
76
|
+
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
def with_text(text)
|
81
|
+
@expectations[:with_text] ||= []
|
82
|
+
@expectations[:with_text].push(text)
|
83
|
+
|
84
|
+
@and_scope = :with_text
|
85
|
+
self
|
86
|
+
end
|
87
|
+
|
88
|
+
def with_selector(selector)
|
89
|
+
@expectations[:with_selector] ||= []
|
90
|
+
@expectations[:with_selector].push(selector)
|
91
|
+
|
92
|
+
@and_scope = :with_selector
|
93
|
+
self
|
94
|
+
end
|
95
|
+
|
96
|
+
def with_link(href)
|
97
|
+
@expectations[:with_link] ||= []
|
98
|
+
@expectations[:with_link].push(href)
|
99
|
+
|
100
|
+
@and_scope = :with_link
|
101
|
+
self
|
102
|
+
end
|
103
|
+
|
104
|
+
def with_image(src)
|
105
|
+
@expectations[:with_image] ||= []
|
106
|
+
@expectations[:with_image].push(src)
|
107
|
+
|
108
|
+
@and_scope = :with_image
|
109
|
+
self
|
110
|
+
end
|
111
|
+
|
112
|
+
def diffable?
|
113
|
+
false
|
114
|
+
end
|
115
|
+
|
116
|
+
def matches?(emails)
|
117
|
+
@emails = emails
|
118
|
+
|
119
|
+
matching_emails = @emails
|
120
|
+
|
121
|
+
@expectations.each do |attribute, expected|
|
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?
|
129
|
+
@failed_attribute = attribute
|
130
|
+
@failed_expected = expected
|
131
|
+
return false
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
true
|
136
|
+
end
|
137
|
+
|
138
|
+
def failure_message
|
139
|
+
field_description = @failed_attribute.to_s.gsub('_', ' ')
|
140
|
+
value_description =
|
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
|
149
|
+
|
150
|
+
base_clause = "Expected an email to be sent #{field_description} #{value_description}."
|
151
|
+
|
152
|
+
if @emails.length == 0
|
153
|
+
base_clause + ' However, no emails were sent.'
|
154
|
+
else
|
155
|
+
pluralisation = @emails.length == 1 ? 'email' : 'emails'
|
156
|
+
|
157
|
+
email_values = @emails.inject([]) do |memo, email|
|
158
|
+
matcher = MATCHERS[@failed_attribute]
|
159
|
+
|
160
|
+
value =
|
161
|
+
case matcher
|
162
|
+
when String, Symbol
|
163
|
+
email.send(matcher)
|
164
|
+
when Hash
|
165
|
+
field_description = matcher[:actual_name] if matcher[:actual_name]
|
166
|
+
matcher[:actual].(email, parsed_emails(email))
|
167
|
+
end
|
168
|
+
|
169
|
+
value = value.kind_of?(String) ? "'#{value}'" : value
|
170
|
+
memo << value
|
171
|
+
|
172
|
+
memo
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
if email_values.any?
|
177
|
+
base_clause + " However, #{pluralisation} were sent #{field_description} #{email_values.to_sentence}"
|
178
|
+
else
|
179
|
+
base_clause
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
def parsed_emails(email)
|
187
|
+
@parsed_emails ||= {}
|
188
|
+
@parsed_emails[email] ||= parser(email)
|
189
|
+
@parsed_emails[email]
|
190
|
+
end
|
191
|
+
|
192
|
+
def parser(email)
|
193
|
+
Capybara::Node::Simple.new(email.parts.first.body.decoded)
|
194
|
+
end
|
195
|
+
|
196
|
+
def email_matches?(email, assertion, expected)
|
197
|
+
case assertion
|
198
|
+
when String, Symbol
|
199
|
+
email.send(assertion) == expected
|
200
|
+
when Hash
|
201
|
+
assertion[:match].(email, parsed_emails(email), expected)
|
202
|
+
else
|
203
|
+
raise RuntimeError.new(
|
204
|
+
"Unsupported assertion mapping '#{assertion_match}' of type #{assertion_match.class.name}"
|
205
|
+
)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
data/test_assistant.gemspec
CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency "rspec-rails", "~> 3.0"
|
22
|
+
spec.add_dependency 'capybara', '~> 2.5', '>= 2.5.0'
|
22
23
|
spec.add_development_dependency "bundler", "~> 1.6"
|
23
24
|
spec.add_development_dependency "rake", "~> 0"
|
24
25
|
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.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aleck Greenham
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-06-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-rails
|
@@ -24,6 +24,26 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: capybara
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.5'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 2.5.0
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '2.5'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.5.0
|
27
47
|
- !ruby/object:Gem::Dependency
|
28
48
|
name: bundler
|
29
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,6 +87,8 @@ files:
|
|
67
87
|
- Rakefile
|
68
88
|
- lib/test_assistant.rb
|
69
89
|
- lib/test_assistant/configuration.rb
|
90
|
+
- lib/test_assistant/email/expectation.rb
|
91
|
+
- lib/test_assistant/email/helpers.rb
|
70
92
|
- lib/test_assistant/failure_reporter.rb
|
71
93
|
- lib/test_assistant/json_helpers.rb
|
72
94
|
- lib/test_assistant/version.rb
|