email_spectacular 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/.rubocop.yml +40 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/Gemfile +5 -0
- data/Guardfile +37 -0
- data/LICENSE.txt +22 -0
- data/README.md +166 -0
- data/Rakefile +3 -0
- data/email_spectacular.gemspec +32 -0
- data/lib/email_spectacular.rb +11 -0
- data/lib/email_spectacular/dsl.rb +178 -0
- data/lib/email_spectacular/email_filter.rb +13 -0
- data/lib/email_spectacular/expectation.rb +88 -0
- data/lib/email_spectacular/failure_descriptions.rb +149 -0
- data/lib/email_spectacular/matchers.rb +66 -0
- data/lib/email_spectacular/parser.rb +26 -0
- data/lib/email_spectacular/rspec.rb +39 -0
- data/lib/email_spectacular/version.rb +5 -0
- data/spec/email_expectation_spec.rb +429 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/support/email_mock.rb +45 -0
- metadata +175 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0f37914ebc9f8c1fba4ef39afba24d808dce2557
|
4
|
+
data.tar.gz: 59dd333158d579bd98ba60c68eb795e9a88d380f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 17185632819ec97f045453a508ad419d4ea9bbb8f669415d070ccb249a118fcdaa7656ef7eea29d26062f5895396fba2cc91e65a8a3af396b2721f90cb96cd25
|
7
|
+
data.tar.gz: 1168413e77f916258af5a793dda207dfa0d98c4cda0e055c7e95e944393807faf175618eca0511e0d4083ec459b9ec54a110e886355479d62beaedd7c5f06b97
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.5
|
3
|
+
|
4
|
+
Metrics/LineLength:
|
5
|
+
Max: 120
|
6
|
+
|
7
|
+
Metrics/AbcSize:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
Style/Documentation:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Style/ClassAndModuleChildren:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Style/RescueModifier:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Layout/MultilineOperationIndentation:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Layout/TrailingWhitespace:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Metrics/PerceivedComplexity:
|
26
|
+
Max: 20
|
27
|
+
|
28
|
+
Metrics/CyclomaticComplexity:
|
29
|
+
Max: 20
|
30
|
+
|
31
|
+
Metrics/MethodLength:
|
32
|
+
CountComments: false
|
33
|
+
Max: 20
|
34
|
+
|
35
|
+
Metrics/BlockLength:
|
36
|
+
ExcludedMethods:
|
37
|
+
- describe
|
38
|
+
- context
|
39
|
+
- class_eval
|
40
|
+
|
data/.travis.yml
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
- README LICENSE
|
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
4
|
+
require 'guard/rspec/dsl'
|
5
|
+
|
6
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
7
|
+
|
8
|
+
last_run_spec = nil
|
9
|
+
|
10
|
+
watch(%r{^lib/(.+)\.rb$}) do |match|
|
11
|
+
file_path =
|
12
|
+
if match[1] == 'lib'
|
13
|
+
"spec/lib/#{match[2]}_spec.rb"
|
14
|
+
else
|
15
|
+
"spec/#{match[2]}_spec.rb"
|
16
|
+
end
|
17
|
+
|
18
|
+
if File.exist?(file_path)
|
19
|
+
file_path
|
20
|
+
else
|
21
|
+
last_run_spec
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# RSpec files
|
26
|
+
rspec = dsl.rspec
|
27
|
+
|
28
|
+
# noinspection RubyResolve
|
29
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
30
|
+
# noinspection RubyResolve
|
31
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
32
|
+
# noinspection RubyResolve
|
33
|
+
watch(rspec.spec_files) do |spec|
|
34
|
+
# noinspection RubyUnusedLocalVariable
|
35
|
+
last_run_spec = spec[0]
|
36
|
+
end
|
37
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2019 Aleck Greenham
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
# EmailSpectacular
|
2
|
+
|
3
|
+
[![Gem](https://img.shields.io/gem/dt/email_spectacular.svg)]()
|
4
|
+
[![Build Status](https://travis-ci.org/greena13/email_spectacular.svg)](https://travis-ci.org/greena13/email_spectacular)
|
5
|
+
[![GitHub license](https://img.shields.io/github/license/greena13/email_spectacular.svg)](https://github.com/greena13/email_spectacular/blob/master/LICENSE)
|
6
|
+
|
7
|
+
High-level email spec helpers for acceptance, feature and request tests.
|
8
|
+
|
9
|
+
## What EmailSpectacular is
|
10
|
+
|
11
|
+
Expressive email assertions that let you succinctly describe when emails should and should not be sent.
|
12
|
+
|
13
|
+
### What EmailSpectacular is NOT
|
14
|
+
|
15
|
+
A library for low-level or unit-testing of ActionMailers.
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
Add this line to your application's Gemfile:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
group :test do
|
23
|
+
gem 'email_spectacular', require: false
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
Add `email_spectacular` to your `spec/rails_helper.rb`
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
|
31
|
+
require 'email_spectacular'
|
32
|
+
|
33
|
+
# ...
|
34
|
+
|
35
|
+
RSpec.configure do |config|
|
36
|
+
# ...
|
37
|
+
|
38
|
+
email_spectacular_spec_types = %i[acceptance feature request]
|
39
|
+
|
40
|
+
config.after(:each, type: email_spectacular_spec_types) do
|
41
|
+
# Clear emails between specs
|
42
|
+
clear_emails
|
43
|
+
end
|
44
|
+
|
45
|
+
email_spectacular_spec_types.each do |spec_type|
|
46
|
+
# Include email spectacular syntax in rspec tests
|
47
|
+
config.include EmailSpectacular::RSpec, type: spec_type
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
And then execute:
|
53
|
+
|
54
|
+
```bash
|
55
|
+
bundle install
|
56
|
+
```
|
57
|
+
|
58
|
+
## Usage
|
59
|
+
|
60
|
+
### Email receiver address
|
61
|
+
|
62
|
+
It's possible to assert an email was sent to one or more or more addresses using the following format:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
expect(email).to have_been_sent.to('user@email.com')
|
66
|
+
```
|
67
|
+
|
68
|
+
### Email sender address
|
69
|
+
|
70
|
+
Similarly, you can assert an email was sent from an address:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
expect(email).to have_been_sent.from('user@email.com')
|
74
|
+
```
|
75
|
+
|
76
|
+
### Email subject
|
77
|
+
|
78
|
+
You can assert an email's subject:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
expect(email).to have_been_sent.with_subject('Welcome!')
|
82
|
+
```
|
83
|
+
|
84
|
+
### Email body
|
85
|
+
|
86
|
+
You can assert the body of an email by text:
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
expect(email).to have_been_sent.with_text('Welcome, user@email.com')
|
90
|
+
```
|
91
|
+
|
92
|
+
Or using a selector on the email's HTML:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
expect(email).to have_been_sent.with_selector('#password')
|
96
|
+
```
|
97
|
+
|
98
|
+
Or look for links:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
expect(email).to have_been_sent.with_link('www.site.com/onboarding/1')
|
102
|
+
```
|
103
|
+
|
104
|
+
Or images:
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
expect(email).to have_been_sent.with_image('www.site.com/assets/images/welcome.png')
|
108
|
+
```
|
109
|
+
|
110
|
+
### Chaining assertions
|
111
|
+
|
112
|
+
You can chain any combination of the above that you want for ultra specific assertions:
|
113
|
+
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
expect(email).to have_been_sent
|
117
|
+
.to('user@email.com')
|
118
|
+
.from('admin@site.com')
|
119
|
+
.with_subject('Welcome!')
|
120
|
+
.with_text('Welcome, user@email.com')
|
121
|
+
.with_selector('#password').and('#username')
|
122
|
+
.with_link('www.site.com/onboarding/1')
|
123
|
+
.with_image('www.site.com/assets/images/welcome.png')
|
124
|
+
|
125
|
+
```
|
126
|
+
|
127
|
+
You can also chain multiple assertions of the the same type with the `and` method:
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
expect(email).to have_been_sent
|
131
|
+
.with_text('Welcome, user@email.com').and('Thanks for signing up')
|
132
|
+
```
|
133
|
+
|
134
|
+
### Asserting emails are NOT sent
|
135
|
+
|
136
|
+
The `have_sent_email` assertion works with the negative case as well:
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
expect(email).to_not have_been_sent.with_text('Secret token')
|
140
|
+
```
|
141
|
+
|
142
|
+
### Clearing emails
|
143
|
+
|
144
|
+
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.
|
145
|
+
|
146
|
+
If you followed in installation steps above, emails will automatically be cleared between each spec.
|
147
|
+
|
148
|
+
## Test suite
|
149
|
+
|
150
|
+
`email_spectacular` comes with close-to-complete test coverage. You can run the test suite as follows:
|
151
|
+
|
152
|
+
```bash
|
153
|
+
rspec
|
154
|
+
```
|
155
|
+
|
156
|
+
## Contributing
|
157
|
+
|
158
|
+
1. Fork it ( https://github.com/greena13/email_spectacular/fork )
|
159
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
160
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
161
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
162
|
+
5. Create a new Pull Request
|
163
|
+
|
164
|
+
## Inspirations
|
165
|
+
|
166
|
+
* [CapybaraEmail](https://github.com/DockYard/capybara-email)
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'email_spectacular/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'email_spectacular'
|
9
|
+
spec.version = EmailSpectacular::VERSION
|
10
|
+
spec.authors = ['Aleck Greenham']
|
11
|
+
spec.email = ['greenhama13@gmail.com']
|
12
|
+
spec.summary = 'High-level email spec helpers for acceptance, feature and request ' \
|
13
|
+
'tests'
|
14
|
+
spec.description = 'Expressive email assertions that let you succinctly describe when ' \
|
15
|
+
'emails should and should not be sent'
|
16
|
+
spec.homepage = 'https://github.com/greena13/email_spectacular'
|
17
|
+
spec.license = 'MIT'
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0")
|
20
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
+
spec.test_files = spec.files.grep(%r{^(spec)/})
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
|
24
|
+
spec.add_dependency 'actionmailer', '>= 0'
|
25
|
+
spec.add_dependency 'capybara', '~> 2.5', '>= 2.5.0'
|
26
|
+
|
27
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
28
|
+
spec.add_development_dependency 'guard', '~> 2.1'
|
29
|
+
spec.add_development_dependency 'guard-rspec', '~> 4.7'
|
30
|
+
spec.add_development_dependency 'rake', '~> 0'
|
31
|
+
spec.add_development_dependency 'rspec', '>= 3.5.0'
|
32
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'email_spectacular/version'
|
4
|
+
|
5
|
+
# High-level email spec helpers for acceptance, feature and request tests.
|
6
|
+
#
|
7
|
+
# @author Aleck Greenham
|
8
|
+
#
|
9
|
+
# @see https://github.com/greena13/email_spectacular EmailSpectacular Github page
|
10
|
+
module EmailSpectacular
|
11
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EmailSpectacular
|
4
|
+
# Module containing the domain-specific language for expressing expectations of emails
|
5
|
+
#
|
6
|
+
# @author Aleck Greenham
|
7
|
+
module DSL
|
8
|
+
def self.included(base) # rubocop:disable Metrics/MethodLength
|
9
|
+
base.class_eval do
|
10
|
+
def initialize
|
11
|
+
@scopes = {}
|
12
|
+
@and_scope = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
# Allows chaining two assertions on the same email attribute together without
|
16
|
+
# having to repeat the same method. Intended as syntactical sugar only and is
|
17
|
+
# functionally equivalent to repeating the method.
|
18
|
+
#
|
19
|
+
# @example Asserting an email was sent to two email addresses
|
20
|
+
# expect(email).to have_been_sent.to('user1@email.com').and('user2@email.com')
|
21
|
+
#
|
22
|
+
# @param [Array<String>] arguments parameters to pass to whatever assertion is
|
23
|
+
# being extended.
|
24
|
+
# @return [self] reference to self, to allow for further method chaining
|
25
|
+
def and(*arguments)
|
26
|
+
if @and_scope
|
27
|
+
send(@and_scope, *arguments)
|
28
|
+
else
|
29
|
+
ArgumentError.new('Cannot use an and modifier without a proceeding assertion.')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# For constructing an assertion that at least one email was sent to a
|
34
|
+
# <tt>email_address</tt>
|
35
|
+
#
|
36
|
+
# @example Asserting an email was sent to user@email.com
|
37
|
+
# expect(email).to have_been_sent.to('user@email.com')
|
38
|
+
#
|
39
|
+
# @param [String, Array<String>] email_address address email is expected to be
|
40
|
+
# sent to. If an array of email addresses, the email is expected to have been
|
41
|
+
# sent to all of them.
|
42
|
+
# @return [self] reference to self, to allow for further method chaining
|
43
|
+
def to(email_address)
|
44
|
+
@scopes[:to] ||= []
|
45
|
+
|
46
|
+
if email_address.is_a?(Array)
|
47
|
+
@scopes[:to] = @scopes[:to].concat(email_address)
|
48
|
+
else
|
49
|
+
@scopes[:to] ||= []
|
50
|
+
@scopes[:to] << email_address
|
51
|
+
end
|
52
|
+
|
53
|
+
@and_scope = :to
|
54
|
+
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
# For constructing an assertion that at least one email was sent from
|
59
|
+
# <tt>email_address</tt>.
|
60
|
+
#
|
61
|
+
# @example Asserting an email was sent from admin@site.com
|
62
|
+
# expect(email).to have_been_sent.from('admin@site.com')
|
63
|
+
#
|
64
|
+
# @param [String] email_address Address email is expected to be sent from.
|
65
|
+
# @raise ArgumentError when {#from} is called more than once on the same
|
66
|
+
# expectation, as an email can only ben sent from a single sender.
|
67
|
+
# @return [self] reference to self, to allow for further method chaining
|
68
|
+
def from(email_address)
|
69
|
+
if @scopes[:from]
|
70
|
+
raise ArgumentError(
|
71
|
+
'An email can only have one from address, but you tried to assert the ' \
|
72
|
+
'presence of 2 or more values.'
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
@scopes[:from] = email_address
|
77
|
+
@and_scope = :from
|
78
|
+
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
# For constructing an assertion that at least one email was sent with a
|
83
|
+
# particular subject line
|
84
|
+
#
|
85
|
+
# @example Asserting an email was sent with subject line 'Hello'
|
86
|
+
# expect(email).to have_been_sent.with_subject('Hello')
|
87
|
+
#
|
88
|
+
# @param [String] subject Subject line an email is expected to have been sent
|
89
|
+
# with
|
90
|
+
# @raise ArgumentError when {#with_subject} is called more than once on the
|
91
|
+
# same expectation, as an email can only have one subject line.
|
92
|
+
# @return [self] reference to self, to allow for further method chaining
|
93
|
+
def with_subject(subject)
|
94
|
+
if @scopes[:with_subject]
|
95
|
+
raise ArgumentError(
|
96
|
+
'An email can only have one subject, but you tried to assert the presence ' \
|
97
|
+
'of 2 or more values.'
|
98
|
+
)
|
99
|
+
end
|
100
|
+
|
101
|
+
@scopes[:with_subject] = subject
|
102
|
+
|
103
|
+
@and_scope = :with_subject
|
104
|
+
|
105
|
+
self
|
106
|
+
end
|
107
|
+
|
108
|
+
# For constructing an assertion that at least one email was sent with a particular
|
109
|
+
# string in the body of the email.
|
110
|
+
#
|
111
|
+
# @example Asserting an email was sent with the text 'User 1'
|
112
|
+
# expect(email).to have_been_sent.with_text('User 1')
|
113
|
+
#
|
114
|
+
# @param [String] text Text an email is expected to have been sent with in the
|
115
|
+
# body
|
116
|
+
# @return [self] reference to self, to allow for further method chaining
|
117
|
+
def with_text(text)
|
118
|
+
@scopes[:with_text] ||= []
|
119
|
+
@scopes[:with_text].push(text)
|
120
|
+
|
121
|
+
@and_scope = :with_text
|
122
|
+
self
|
123
|
+
end
|
124
|
+
|
125
|
+
# For constructing an assertion that at least one email was sent with a body that
|
126
|
+
# matches a particular CSS selector.
|
127
|
+
#
|
128
|
+
# @example Asserting an email was sent with a body matching selector '#imporant-div'
|
129
|
+
# expect(email).to have_been_sent.matching_selector('#imporant-div')
|
130
|
+
#
|
131
|
+
# @param [String] selector CSS selector that should match at least one sent
|
132
|
+
# email's body
|
133
|
+
# @return [EmailSpectacular::Expectation] reference to self, to allow for
|
134
|
+
# further method chaining
|
135
|
+
def matching_selector(selector)
|
136
|
+
@scopes[:matching_selector] ||= []
|
137
|
+
@scopes[:matching_selector].push(selector)
|
138
|
+
|
139
|
+
@and_scope = :matching_selector
|
140
|
+
self
|
141
|
+
end
|
142
|
+
|
143
|
+
# For constructing an assertion that at least one email was sent with a link to
|
144
|
+
# a particular URL in the body.
|
145
|
+
#
|
146
|
+
# @example Asserting an email was sent with a link to http://www.example.com
|
147
|
+
# expect(email).to have_been_sent.with_link('http://www.example.com')
|
148
|
+
#
|
149
|
+
# @param [String] href URL that should appear in at least one sent email's body
|
150
|
+
# @return [self] reference to self, to allow for further method chaining
|
151
|
+
def with_link(href)
|
152
|
+
@scopes[:with_link] ||= []
|
153
|
+
@scopes[:with_link].push(href)
|
154
|
+
|
155
|
+
@and_scope = :with_link
|
156
|
+
self
|
157
|
+
end
|
158
|
+
|
159
|
+
# For constructing an assertion that at least one email was sent with an image
|
160
|
+
# hosted at a particular URL
|
161
|
+
#
|
162
|
+
# @example Asserting an email was sent with the image http://www.example.com/image.png
|
163
|
+
# expect(email).to have_been_sent.with_link('http://www.example.com/image.png')
|
164
|
+
#
|
165
|
+
# @param [String] src URL of the image that should appear in at least one sent
|
166
|
+
# email's body
|
167
|
+
# @return [self] reference to self, to allow for further method chaining
|
168
|
+
def with_image(src)
|
169
|
+
@scopes[:with_image] ||= []
|
170
|
+
@scopes[:with_image].push(src)
|
171
|
+
|
172
|
+
@and_scope = :with_image
|
173
|
+
self
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|