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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7c14c4c6d990513adb024b4571090c7fc85dca59
4
- data.tar.gz: 1ab16e504b25feca6a2d2ab443684d4512e4a67e
3
+ metadata.gz: fd9da0b295791c6249e94172857509c44b58b7ac
4
+ data.tar.gz: ffb211e31de33220bfeea704961e844738597308
5
5
  SHA512:
6
- metadata.gz: 8361c96e295b176daf5c9aba592217be43174ba39876094fc5f7423e9f2ddfe14db46fc8e7b424b8ede85c8035c8f5b78074222f10a6be8631aea60a74e59577
7
- data.tar.gz: 33107a1cc37d9ffd6d645b02206699c0d8f6afdb392fbf76b1e2a72cbc1fb7d0efa49294c010f58a6a8da415b72962bb72d6f9a74a5126ceff09c95fb30c2fcf
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/[my-github-username]/test_assistant/fork )
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
@@ -0,0 +1,13 @@
1
+ require 'test_assistant/email/expectation'
2
+
3
+ module TestAssistant::Email
4
+ module Helpers
5
+ def email
6
+ ActionMailer::Base.deliveries
7
+ end
8
+
9
+ def have_been_sent
10
+ TestAssistant::Email::Expectation.new
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module TestAssistant
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -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.1
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-05-30 00:00:00.000000000 Z
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