Constant Stubbing in RSpec 2.11
Myron Marston
Jun 29, 2012In the 2.11 release, rspec-mocks is gaining a significant new -capability that, as far as I know, isn't provided by any other -ruby mocking library: constant stubbing1.
+capability that, as far as I know, isn’t provided by any other +ruby mocking library: constant stubbing[^foot_1]. -Let's look at the API, and then talk a bit about some of +
Let’s look at the API, and then talk a bit about some of the use cases for it.
-The API
+The API
The main API is stub_const:
describe "stub_const" do
it "changes the constant value for the duration of the example" do
stub_const("Foo::SIZE", 10)
@@ -29,7 +28,6 @@ The API
Note that constant names must be fully qualified; the current
module nesting is not considered:
-
module MyGem
class SomeClass; end
end
@@ -52,18 +50,16 @@ The API
stub_const also supports a :transfer_nested_constants option.
Consider a case where you have nested constants:
-
class CardDeck
SUITS = [:spades, :diamonds, :clubs, :hearts]
NUM_CARDS = 52
end
-stub_const("CardDeck", fake_class) cuts off access to the
+
stub_const("CardDeck", fake_class) cuts off access to the
nested constants (CardDeck::SUITS and CardDeck::NUM_CARDS),
unless you manually assign fake_class::SUITS and
fake_class::NUM_CARDS. The :transfer_nested_constants
option is provided to take care of this for you:
-
# Default behavior:
fake_class = Class.new
stub_const("CardDeck", fake_class)
@@ -81,38 +77,32 @@ The API
CardDeck::SUITS # => [:spades, :diamonds, :clubs, :hearts]
CardDeck::NUM_CARDS # => raises uninitialized constant error
-Use Cases
+Use Cases
-I've found this useful in a few different situations:
+I’ve found this useful in a few different situations:
- - It provides a simple way to change a class setting expressed as
-a constant for one test. In the past, I've often defined static
+
- It provides a simple way to change a class setting expressed as
+a constant for one test. In the past, I’ve often defined static
class methods just so they could be stubbed, even though it
made more sense to use a constant. Now you can just use a constant!
- - It makes dependency injection easy when the class-under-test
-depends on a collaborator's class method (e.g. when the collaborator
-is stateless). You can easily stub the collaborator's class constant
+
- It makes dependency injection easy when the class-under-test
+depends on a collaborator’s class method (e.g. when the collaborator
+is stateless). You can easily stub the collaborator’s class constant
with a test double.
- - It makes stubbing unloaded dependencies dead-simple. Gary
+
- It makes stubbing unloaded dependencies dead-simple. Gary
Bernhardt discussed this situation at length in Destroy all
Software #46.
He mentioned mutating constants as a possible way of stubbing unloaded
dependencies, but recommended against it because of the complexity
-of safely managing this. Now that rspec-mocks can do it for you, it's
+of safely managing this. Now that rspec-mocks can do it for you, it’s
far less complex, and much, much safer.
-If you're curious how it all works, check out the source on
+If you’re curious how it all works, check out the source on
github.
-
-
- -
-
Actually, this has been available in rspec-fire for a good four months or so. But it's not really a full mocking library…it builds on top of rspec-mocks, and now this functionality has been ported over to rspec-mocks. ↩
-
-
-
+[^foot_1]: Actually, this has been available in rspec-fire for a good four months or so. But it’s not really a full mocking library…it builds on top of rspec-mocks, and now this functionality has been ported over to rspec-mocks.
\ No newline at end of file
diff --git a/docs/blog/feed.xml b/docs/blog/feed.xml
index 642fe1117..4238675fd 100644
--- a/docs/blog/feed.xml
+++ b/docs/blog/feed.xml
@@ -18,7 +18,7 @@
Jon Rowe
- <h1 id="the-short-version">The short version</h1>
+ <h1>The short version</h1>
<p>RSpec repositories will deprecate the use of <code>master</code> for the default branch
name. We will wait for a consensus on the new name for the default branch,
@@ -29,9 +29,9 @@ renamed <code>main</code>. At that point all development effort will
the new branch name, and use of <code>master</code> will illicit a warning on install
/ usage. All open PRs will be rebased.</p>
-<h1 id="the-long-version">The long version</h1>
+<h1>The long version</h1>
-<p>RSpec's source code is hosted on Github. By default git, and thus Github has
+<p>RSpec’s source code is hosted on Github. By default git, and thus Github has
historically used <code>master</code> as the name of the default, or main branch. This
term has sat uneasily on the minds of the team and with the recent community
led moves to eliminate this terminology from our technology stacks, we are going
@@ -52,7 +52,7 @@ lots of things, but the term has its origins in the dominance of one person
over another, in particular in slavery and this change is about being
inclusive to all people.</p>
-<h2 id="implications">Implications</h2>
+<h2>Implications</h2>
<p>We have always encouraged the use of our main branch for getting pre-release
features before we release them as a group of gems, this means there are likely
@@ -62,14 +62,14 @@ people using the <code>master</code> branch via their Gemfiles. We w
become stale and not be updated further. Additionally we will look at
using branch protection rules preventing PRs against <code>master</code> from that date.</p>
-<h2 id="steps-we-intend-to-take">Steps we intend to take</h2>
+<h2>Steps we intend to take</h2>
<ol>
- <li>Push <code>master</code> to <code>main</code> (or other new branch name).</li>
- <li>Rebase all open PRs and update our builds.</li>
- <li>Set the default to <code>main</code> (etc) for all RSpec repositories.</li>
- <li>Push change deprecating <code>master</code> to <code>master</code>.</li>
- <li>In the future (possibly when releasing RSpec 4) remove <code>master</code>.</li>
+<li>Push <code>master</code> to <code>main</code> (or other new branch name).</li>
+<li>Rebase all open PRs and update our builds.</li>
+<li>Set the default to <code>main</code> (etc) for all RSpec repositories.</li>
+<li>Push change deprecating <code>master</code> to <code>master</code>.</li>
+<li>In the future (possibly when releasing RSpec 4) remove <code>master</code>.</li>
</ol>
@@ -84,11 +84,11 @@ using branch protection rules preventing PRs against <code>master</code
<p>RSpec Rails 4.0 has been released! Given our commitment to
<a href="http://semver.org/">semantic versioning</a>, this is a major release and as such
-contains breaking changes. The major change is that we've dropped support for
+contains breaking changes. The major change is that we’ve dropped support for
Rails below 5, with only soft support for Rails 4.2.</p>
<p>As usual, if you notice any newly introduced bugs, please let us know,
-and we'll release a fix for it ASAP.</p>
+and we’ll release a fix for it ASAP.</p>
<p>RSpec continues to be a community-driven project with contributors
from all over the world. This release includes 258 commits and 56
@@ -96,11 +96,11 @@ merged pull requests from 27 different contributors!</p>
<p>Thank you to everyone who helped make this release happen!</p>
-<h2 id="notable-changes">Notable Changes</h2>
+<h2>Notable Changes</h2>
<p>Support for Rails 6, including support for testing ActionCable, ActiveMailbox.</p>
-<h3 id="breaking-changes">Breaking changes</h3>
+<h3>Breaking changes</h3>
<p>RSpec Rails 4 only supports Rails 5 and 6. This is in line with our
new versioning policy which keeps major versions of RSpec Rails in
@@ -110,34 +110,33 @@ lockstep with supported versions of Rails.</p>
in line with the versions of Ruby supported by Rails 5.</p>
<p>We have restricted the version of Rails for this version to 4.2 to
-allows a "soft support" for Rails 4.2 during this interim
+allows a “soft support” for Rails 4.2 during this interim
period but we strongly urge you to upgrade Rails to use 4.0.0.</p>
-<h3 id="removed-version-lock-with-rspec-gems">Removed version lock with RSpec gems</h3>
+<h3>Removed version lock with RSpec gems</h3>
<p>The <code>rspec-rails</code> gem is no longer locked with the versioning of the other
RSpec gems, we will now be releasing <code>rspec-rails</code> with each new Rails
release, keeping in lockstep with their supported major versions.</p>
-<h3 id="improved-jruby-support">Improved JRuby support</h3>
+<h3>Improved JRuby support</h3>
<p>We have improved JRuby support and RSpec Rails 4 fully supports JRuby on Rails 5 and 6.</p>
-<h3 id="support-for-action-cable">Support for Action Cable</h3>
+<h3>Support for Action Cable</h3>
<p>We now support <a href="https://relishapp.com/rspec/rspec-rails/v/4-0/docs/channel-specs">channel specs</a> in order to easily test your Action Cable channels.
A <code>channel spec</code> pulls in <code>ActionCable::Channel::TestCase</code>, including all of the
-behavior and assertions that it provides, in addition to RSpec's own behavior and
+behavior and assertions that it provides, in addition to RSpec’s own behavior and
expectations.</p>
-<h3 id="support-for-action-mailbox">Support for Action Mailbox</h3>
+<h3>Support for Action Mailbox</h3>
<p>Rails 6 adds <a href="https://guides.rubyonrails.org/action_mailbox_basics.html">Action Mailbox</a> for dealing with inbound emails.
RSpec Rails 4 adds support for <a href="https://relishapp.com/rspec/rspec-rails/docs/mailbox-specs/action-mailbox-spec">mailbox specs</a> using the Rails
test helpers for mailboxes.</p>
<p>For example using the Rails test helper, <code>process</code> and the <code>have_been_delivered</code> matcher:</p>
-
<div class="highlight"><pre class="highlight ruby"><code><span class="no">RSpec</span><span class="p">.</span><span class="nf">describe</span> <span class="no">InboxMailbox</span><span class="p">,</span> <span class="ss">type: :mailbox</span> <span class="k">do</span>
<span class="n">it</span> <span class="s2">"marks email as delivered when number tag in subject is valid"</span> <span class="k">do</span>
<span class="n">mail</span> <span class="o">=</span> <span class="no">Mail</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span>
@@ -150,27 +149,26 @@ test helpers for mailboxes.</p>
<span class="k">end</span>
<span class="k">end</span>
</code></pre></div>
-<h3 id="improvements-to-generators">Improvements to generators</h3>
+<h3>Improvements to generators</h3>
<p>If you use generators, there are some improvements:
- The default hash syntax is now the Ruby 1.9 style in generated files to match Rails conventions
- Request specs are generated instead of controller specs by default
-- New <a href="https://relishapp.com/rspec/rspec-rails/v/4-0/docs/generators">generators</a> available (channel, generator, mailbox…)</p>
+- New <a href="https://relishapp.com/rspec/rspec-rails/v/4-0/docs/generators">generators</a> available (channel, generator, mailbox…)</p>
-<h3 id="allow-configuring-active-job-queueadapter-in-system-specs">Allow configuring Active Job <code>queue_adapter</code> in system specs</h3>
+<h3>Allow configuring Active Job <code>queue_adapter</code> in system specs</h3>
<p>Some people want to run Active Job with a specific queue adapter. In system
specs you can now choose your desired queue adapter:</p>
-
<div class="highlight"><pre class="highlight ruby"><code><span class="n">before</span> <span class="k">do</span>
<span class="no">ActiveJob</span><span class="o">::</span><span class="no">Base</span><span class="p">.</span><span class="nf">queue_adapter</span> <span class="o">=</span> <span class="ss">:inline</span>
<span class="k">end</span>
</code></pre></div>
-<h3 id="silence-log-output-with-puma">Silence log output with Puma</h3>
+<h3>Silence log output with Puma</h3>
<p>By default, Puma will no longer print logs when running system specs.</p>
-<h3 id="ability-to-manually-turn-off-active-record-support">Ability to manually turn off Active Record support</h3>
+<h3>Ability to manually turn off Active Record support</h3>
<p>When using Rails without ActiveRecord or using an alternative ORM
or a database of choice, e.g. Sequel, ROM, Mongoid etc. We can
@@ -179,114 +177,115 @@ autoloading the constants, we now support manually turning off
Active Record support when not configured with:
<code>config.use_active_record = false</code></p>
-<h2 id="stats">Stats:</h2>
+<h2>Stats:</h2>
<ul>
- <li><strong>Total Commits</strong>: 285</li>
- <li><strong>Merged pull requests</strong>: 63</li>
- <li><strong>31 contributors</strong>: Andrew White, Anton Rieder, Benoit Tigeot, Jon Rowe,
+<li><strong>Total Commits</strong>: 285</li>
+<li><strong>Merged pull requests</strong>: 63</li>
+<li><strong>31 contributors</strong>: Andrew White, Anton Rieder, Benoit Tigeot, Jon Rowe,
David Revelo, Giovanni Kock Bonetti, Ignatius Reza, James Dabbs, Joel AZEMAR,
-John Hawthorn, Jonathan Rochkind, Kieran O'Grady, Marc-André Lafortune,
+John Hawthorn, Jonathan Rochkind, Kieran O'Grady, Marc-André Lafortune,
Moshe Kamensky, OKURA Masafumi, Olle Jonsson, Pedro Paiva, Penelope Phippen,
Phil Pirozhkov, Piotr W, Seb Jacobs, Tanbir Hasan, Viacheslav Bobrov,
Vladimir Dementyev, Xavier Shay, alpaca-tc, pavel, ta1kt0me, yalab</li>
</ul>
-<h2 id="docs">Docs</h2>
+<h2>Docs</h2>
-<h3 id="api-docs">API Docs</h3>
+<h3>API Docs</h3>
<ul>
- <li><a href="/documentation/4.0/rspec-rails/">rspec-rails</a></li>
+<li><a href="/documentation/4.0/rspec-rails/">rspec-rails</a></li>
</ul>
-<h3 id="cucumber-features">Cucumber Features</h3>
+<h3>Cucumber Features</h3>
<ul>
- <li><a href="https://relishapp.com/rspec/rspec-rails/v/4-0/">rspec-rails</a></li>
+<li><a href="https://relishapp.com/rspec/rspec-rails/v/4-0/">rspec-rails</a></li>
</ul>
-<h2 id="release-notes">Release Notes</h2>
+<h2>Release Notes</h2>
+
+<h3>4.0.1 / 2020-05-16</h3>
-<h3 id="section">4.0.1 / 2020-05-16</h3>
<p><a href="https://github.com/rspec/rspec-rails/compare/v4.0.0...v4.0.1">Full Changelog</a></p>
<p>Bug Fixes:</p>
<ul>
- <li>Remove warning when calling <code>driven_by</code> in system specs. (Aubin Lorieux, #2302)</li>
- <li>Fix comparison of times for <code>#at</code> in job matchers. (Jon Rowe, Markus Doits, #2304)</li>
- <li>Allow <code>have_enqueued_mail</code> to match when a sub class of <code>ActionMailer::DeliveryJob</code>
+<li>Remove warning when calling <code>driven_by</code> in system specs. (Aubin Lorieux, #2302)</li>
+<li>Fix comparison of times for <code>#at</code> in job matchers. (Jon Rowe, Markus Doits, #2304)</li>
+<li>Allow <code>have_enqueued_mail</code> to match when a sub class of <code>ActionMailer::DeliveryJob</code>
is set using <code><Class>.delivery_job=</code>. (Atsushi Yoshida #2305)</li>
- <li>Restore Ruby 2.2.x compatibility. (Jon Rowe, #2332)</li>
- <li>Add <code>required_ruby_version</code> to gem spec. (Marc-André Lafortune, #2319, #2338)</li>
+<li>Restore Ruby 2.2.x compatibility. (Jon Rowe, #2332)</li>
+<li>Add <code>required_ruby_version</code> to gem spec. (Marc-André Lafortune, #2319, #2338)</li>
</ul>
-<h3 id="section-1">4.0.0 / 2020-03-24</h3>
+<h3>4.0.0 / 2020-03-24</h3>
+
<p><a href="https://github.com/rspec/rspec-rails/compare/v3.9.1...v4.0.0">Full Changelog</a></p>
<p>Enhancements:</p>
<ul>
- <li>Adds support for Rails 6. (Penelope Phippen, Benoit Tigeot, Jon Rowe, #2071)</li>
- <li>Adds support for JRuby on Rails 5.2 and 6</li>
- <li>Add support for parameterised mailers (Ignatius Reza, #2125)</li>
- <li>Add ActionMailbox spec helpers and test type (James Dabbs, #2119)</li>
- <li>Add ActionCable spec helpers and test type (Vladimir Dementyev, #2113)</li>
- <li>Add support for partial args when using <code>have_enqueued_mail</code>
+<li>Adds support for Rails 6. (Penelope Phippen, Benoit Tigeot, Jon Rowe, #2071)</li>
+<li>Adds support for JRuby on Rails 5.2 and 6</li>
+<li>Add support for parameterised mailers (Ignatius Reza, #2125)</li>
+<li>Add ActionMailbox spec helpers and test type (James Dabbs, #2119)</li>
+<li>Add ActionCable spec helpers and test type (Vladimir Dementyev, #2113)</li>
+<li>Add support for partial args when using <code>have_enqueued_mail</code>
(Ignatius Reza, #2118, #2125)</li>
- <li>Add support for time arguments for <code>have_enqueued_job</code> (@alpaca-tc, #2157)</li>
- <li>Improve path parsing in view specs render options. (John Hawthorn, #2115)</li>
- <li>Add routing spec template as an option for generating controller specs.
+<li>Add support for time arguments for <code>have_enqueued_job</code> (@alpaca-tc, #2157)</li>
+<li>Improve path parsing in view specs render options. (John Hawthorn, #2115)</li>
+<li>Add routing spec template as an option for generating controller specs.
(David Revelo, #2134)</li>
- <li>Add argument matcher support to <code>have_enqueued_*</code> matchers. (Phil Pirozhkov, #2206)</li>
- <li>Switch generated templates to use ruby 1.9 hash keys. (Tanbir Hasan, #2224)</li>
- <li>Add <code>have_been_performed</code>/<code>have_performed_job</code>/<code>perform_job</code> ActiveJob
+<li>Add argument matcher support to <code>have_enqueued_*</code> matchers. (Phil Pirozhkov, #2206)</li>
+<li>Switch generated templates to use ruby 1.9 hash keys. (Tanbir Hasan, #2224)</li>
+<li>Add <code>have_been_performed</code>/<code>have_performed_job</code>/<code>perform_job</code> ActiveJob
matchers (Isaac Seymour, #1785)</li>
- <li>Default to generating request specs rather than controller specs when
+<li>Default to generating request specs rather than controller specs when
generating a controller (Luka Lüdicke, #2222)</li>
- <li>Allow <code>ActiveJob</code> matchers <code>#on_queue</code> modifier to take symbolic queue names. (Nils Sommer, #2283)</li>
- <li>The scaffold generator now generates request specs in preference to controller specs.
+<li>Allow <code>ActiveJob</code> matchers <code>#on_queue</code> modifier to take symbolic queue names. (Nils Sommer, #2283)</li>
+<li>The scaffold generator now generates request specs in preference to controller specs.
(Luka Lüdicke, #2288)</li>
- <li>Add configuration option to disable ActiveRecord. (Jon Rowe, Phil Pirozhkov, Hermann Mayer, #2266)</li>
- <li>Set <code>ActionDispatch::SystemTesting::Server.silence_puma = true</code> when running system specs.
- (ta1kt0me, Benoit Tigeot, #2289)</li>
+<li>Add configuration option to disable ActiveRecord. (Jon Rowe, Phil Pirozhkov, Hermann Mayer, #2266)</li>
+<li> Set <code>ActionDispatch::SystemTesting::Server.silence_puma = true</code> when running system specs.
+(ta1kt0me, Benoit Tigeot, #2289)</li>
</ul>
<p>Bug Fixes:</p>
<ul>
- <li><code>EmptyTemplateHandler.call</code> now needs to support an additional argument in
+<li><code>EmptyTemplateHandler.call</code> now needs to support an additional argument in
Rails 6. (Pavel Rosický, #2089)</li>
- <li>Suppress warning from <code>SQLite3Adapter.represent_boolean_as_integer</code> which is
+<li>Suppress warning from <code>SQLite3Adapter.represent_boolean_as_integer</code> which is
deprecated. (Pavel Rosický, #2092)</li>
- <li><code>ActionView::Template#formats</code> has been deprecated and replaced by
+<li><code>ActionView::Template#formats</code> has been deprecated and replaced by
<code>ActionView::Template#format</code>(Seb Jacobs, #2100)</li>
- <li>Replace <code>before_teardown</code> as well as <code>after_teardown</code> to ensure screenshots
+<li>Replace <code>before_teardown</code> as well as <code>after_teardown</code> to ensure screenshots
are generated correctly. (Jon Rowe, #2164)</li>
- <li><code>ActionView::FixtureResolver#hash</code> has been renamed to <code>ActionView::FixtureResolver#data</code>.
+<li><code>ActionView::FixtureResolver#hash</code> has been renamed to <code>ActionView::FixtureResolver#data</code>.
(Penelope Phippen, #2076)</li>
- <li>Prevent <code>driven_by(:selenium)</code> being called due to hook precedence.
+<li>Prevent <code>driven_by(:selenium)</code> being called due to hook precedence.
(Takumi Shotoku, #2188)</li>
- <li>Prevent a <code>WrongScopeError</code> being thrown during loading fixtures on Rails
+<li>Prevent a <code>WrongScopeError</code> being thrown during loading fixtures on Rails
6.1 development version. (Edouard Chin, #2215)</li>
- <li>Fix Mocha mocking support with <code>should</code>. (Phil Pirozhkov, #2256)</li>
- <li>Restore previous conditional check for setting <code>default_url_options</code> in feature
+<li>Fix Mocha mocking support with <code>should</code>. (Phil Pirozhkov, #2256)</li>
+<li>Restore previous conditional check for setting <code>default_url_options</code> in feature
specs, prevents a <code>NoMethodError</code> in some scenarios. (Eugene Kenny, #2277)</li>
- <li>Allow changing <code>ActiveJob::Base.queue_adapter</code> inside a system spec.
+<li>Allow changing <code>ActiveJob::Base.queue_adapter</code> inside a system spec.
(Jonathan Rochkind, #2242)</li>
- <li><code>rails generate generator</code> command now creates related spec file (Joel Azemar, #2217)</li>
- <li>Relax upper <code>capybara</code> version constraint to allow for Capybara 3.x (Phil Pirozhkov, #2281)</li>
- <li>Clear ActionMailer test mailbox after each example (Benoit Tigeot, #2293)</li>
+<li><code>rails generate generator</code> command now creates related spec file (Joel Azemar, #2217)</li>
+<li>Relax upper <code>capybara</code> version constraint to allow for Capybara 3.x (Phil Pirozhkov, #2281)</li>
+<li>Clear ActionMailer test mailbox after each example (Benoit Tigeot, #2293)</li>
</ul>
<p>Breaking Changes:</p>
<ul>
- <li>Drops support for Rails below 5.0</li>
- <li>Drops support for Ruby below 2.2</li>
+<li>Drops support for Rails below 5.0</li>
+<li>Drops support for Ruby below 2.2</li>
</ul>
-
@@ -301,10 +300,10 @@ specs, prevents a <code>NoMethodError</code> in some scenarios. (Eug
<p>RSpec 3.9 has just been released! As the RSpec project follows
<a href="http://semver.org/">semantic versioning</a>, anyone already using RSpec 3
should be able to upgrade to this version seemlessly, but if we have
-introduced a regression please let us know, and we'll get a patch
+introduced a regression please let us know, and we’ll get a patch
release out to sort it out as soon as possible.</p>
-<p>We're sad to announce that <a href="https://github.com/samphippen">Penelope Phippen</a> has
+<p>We’re sad to announce that <a href="https://github.com/samphippen">Penelope Phippen</a> has
retired from the project, leaving myself, <a href="https://github.com/jonrowe">Jon Rowe</a> as
the sole lead maintainer going forward, but its not all bad news, we welcome our
newest core team member <a href="https://github.com/pirj`">Phil Pirozhkov</a>.</p>
@@ -313,7 +312,7 @@ newest core team member <a href="https://github.com/pirj`">Phil Pirozhkov&
<p>This is the last release in which the RSpec gems, <code>rspec</code>, <code>rspec-core</code>,
<code>rspec-expectations</code> and <code>rspec-mocks</code> will be in sync with <code>rspec-rails</code>.
-We'll be launched <code>rspec-rails</code> 4 soon which will be classed as an extension
+We’ll be launched <code>rspec-rails</code> 4 soon which will be classed as an extension
gem and not kept in sync version wise with the core gems, which will allow
us to keep <code>rspec-rails</code> in sync with Rails versions, more on that soon.</p>
@@ -321,73 +320,73 @@ us to keep <code>rspec-rails</code> in sync with Rails versions, mor
369 commits and 98 merged pull requests from 52 different contributors
who helped make this release happen. Thank you all :)</p>
-<h2 id="notable-changes">Notable Changes</h2>
+<h2>Notable Changes</h2>
-<h3 id="core-improved-error-handling">Core: Improved error handling</h3>
+<h3>Core: Improved error handling</h3>
<p>If RSpec encounters an error whilst loading support files, it will now
skip loading specs files removing later confusing errors due to the earlier
error(s). Additionally when available <code>did_you_mean</code> suggestions will be
shown for any <code>LoadError</code>s that are encountered.</p>
-<h3 id="core-command-line-interface-improvement---example-matches">Core: Command Line Interface improvement, <code>--example-matches</code></h3>
+<h3>Core: Command Line Interface improvement, <code>--example-matches</code></h3>
<p>With the release of 3.9 you can now use <code>--example-matches</code> to filter your
examples via a regular expression, useful if you only know part of an example
name or have specs with a common theme across a number of different files.</p>
-<h3 id="core-new-formatter">Core: New Formatter</h3>
+<h3>Core: New Formatter</h3>
<p>In 3.9 you will find a new built in formatter option, the failure list formatter,
which can be used via the command line as <code>--format f</code> or <code>--format failure_list</code>,
or via the <code>RSpec::Configuration#formatter</code> method. This new formatter produces
-output in a more minimalist "quick fix" style output.</p>
+output in a more minimalist “quick fix” style output.</p>
-<h3 id="expectations-respondtonew">Expectations: respond_to(:new)</h3>
+<h3>Expectations: respond_to(:new)</h3>
<p>The <code>respond_to</code> matcher now special cases <code>:new</code> and checks <code>:initialize</code>
if its a standard class method.</p>
-<h3 id="expectations-empty-diff-warning">Expectations: Empty diff warning</h3>
+<h3>Expectations: Empty diff warning</h3>
<p>Prior to 3.9 when you had matchers that failed but the items under test
-produced the same inspect output you'd get a confusing diff were both
+produced the same inspect output you’d get a confusing diff were both
sides look the same, we now detect this scenario and issue a warning.</p>
-<h3 id="mocks-improved-thread-safety">Mocks: Improved thread safety</h3>
+<h3>Mocks: Improved thread safety</h3>
<p>A bonus for people running parralleised specs, 3.9 brings some improvements
to our threaded behaviour by adding mutexes to avoid deadlocking errors.</p>
-<h3 id="rails-railshelperrb-improvements">Rails: <code>rails_helper.rb</code> improvements</h3>
+<h3>Rails: <code>rails_helper.rb</code> improvements</h3>
<p>A minor tweak in 3.9 brining the generated <code>rails_helper.rb</code> inline
with Ruby semantics and using <code>__dir__</code> rather than <code>__FILE__</code> on
newer Rubies.</p>
-<h3 id="rails-new-email-matchers">Rails: New email matchers</h3>
+<h3>Rails: New email matchers</h3>
<p>Add a new <code>have_enqueued_mail</code> matcher for making it easier to assert
on mailer specific active jobs.</p>
-<h3 id="rails-new-generators">Rails: New generators</h3>
+<h3>Rails: New generators</h3>
<p>Version 3.9 brings a couple of new generator scaffolds, you can now
generate system specs on Rails 5.1 and above, generate specs for generators
and add routes when generating controller specs.</p>
-<h2 id="stats">Stats:</h2>
+<h2>Stats:</h2>
-<h3 id="combined">Combined:</h3>
+<h3>Combined:</h3>
<ul>
- <li><strong>Total Commits</strong>: 322</li>
- <li><strong>Merged pull requests</strong>: 59</li>
- <li><strong>54 contributors</strong>: Aaron Kromer, Alex Haynes, Alireza Bashiri, Andy Waite,
+<li><strong>Total Commits</strong>: 322</li>
+<li><strong>Merged pull requests</strong>: 59</li>
+<li><strong>54 contributors</strong>: Aaron Kromer, Alex Haynes, Alireza Bashiri, Andy Waite,
Benoit Tigeot, Bobby McDonald, Chris, Christophe Bliard, ConSou, David Rodríguez,
Douglas Lovell, Eito Katagiri, Emric, Fred Snyder, Giovanni Kock Bonetti, Grey
Baker, Jack Wink, Jamie English, Joel Lubrano, Jon Rowe, Juanito Fatas, Keiji,
-Kevin, Kevin Kuchta, Kieran O'Grady, Kohei Sugi, Laura Paakkinen, Manuel
+Kevin, Kevin Kuchta, Kieran O'Grady, Kohei Sugi, Laura Paakkinen, Manuel
Schnitzer, Matijs van Zuijlen, Michel Ocon, Myron Marston, Nazar Matus, Nick
LaMuro, OKURA Masafumi, Olle Jonsson, Orien Madgwick, Patrick Boatner, Penelope
Phippen, Pete Johns, Phil Pirozhkov, Philippe Hardardt, Rafe Rosen, Romain Tartière,
@@ -395,90 +394,91 @@ Ryan Lue, Sam Joseph, Samuel Williams, Taichi Ishitani, Takumi Kaji,
Thomas Walpole, Tom Grimley, Viktor Fonic, Yoshimi, aymeric-ledorze, 三上大河</li>
</ul>
-<h3 id="rspec-core">rspec-core:</h3>
+<h3>rspec-core:</h3>
<ul>
- <li><strong>Total Commits</strong>: 92</li>
- <li><strong>Merged pull requests</strong>: 13</li>
- <li><strong>22 contributors</strong>: Alex Haynes, Andy Waite, Benoit Tigeot, Chris, Christophe
+<li><strong>Total Commits</strong>: 92</li>
+<li><strong>Merged pull requests</strong>: 13</li>
+<li><strong>22 contributors</strong>: Alex Haynes, Andy Waite, Benoit Tigeot, Chris, Christophe
Bliard, David Rodríguez, Jon Rowe, Juanito Fatas, Keiji, Matijs van Zuijlen,
Myron Marston, Nick LaMuro, Olle Jonsson, Orien Madgwick, Pete Johns,
Phil Pirozhkov, Philippe Hardardt, Romain Tartière, Sam Joseph, Samuel Williams,
Viktor Fonic, Yoshimi</li>
</ul>
-<h3 id="rspec-expectations">rspec-expectations:</h3>
+<h3>rspec-expectations:</h3>
<ul>
- <li><strong>Total Commits</strong>: 60</li>
- <li><strong>Merged pull requests</strong>: 7</li>
- <li><strong>15 contributors</strong>: Benoit Tigeot, Eito Katagiri, Fred Snyder, Jack Wink,
+<li><strong>Total Commits</strong>: 60</li>
+<li><strong>Merged pull requests</strong>: 7</li>
+<li><strong>15 contributors</strong>: Benoit Tigeot, Eito Katagiri, Fred Snyder, Jack Wink,
Jamie English, Jon Rowe, Juanito Fatas, Matijs van Zuijlen, Myron Marston,
Nazar Matus, Olle Jonsson, Orien Madgwick, Pete Johns, Phil Pirozhkov,
Taichi Ishitani</li>
</ul>
-<h3 id="rspec-mocks">rspec-mocks:</h3>
+<h3>rspec-mocks:</h3>
<ul>
- <li><strong>Total Commits</strong>: 38</li>
- <li><strong>Merged pull requests</strong>: 2</li>
- <li><strong>10 contributors</strong>: Alireza Bashiri, Benoit Tigeot, Jon Rowe, Juanito Fatas,
+<li><strong>Total Commits</strong>: 38</li>
+<li><strong>Merged pull requests</strong>: 2</li>
+<li><strong>10 contributors</strong>: Alireza Bashiri, Benoit Tigeot, Jon Rowe, Juanito Fatas,
Kevin, Matijs van Zuijlen, Myron Marston, Olle Jonsson, Orien Madgwick,
Patrick Boatner</li>
</ul>
-<h3 id="rspec-rails">rspec-rails:</h3>
+<h3>rspec-rails:</h3>
<ul>
- <li><strong>Total Commits</strong>: 103</li>
- <li><strong>Merged pull requests</strong>: 17</li>
- <li><strong>27 contributors</strong>: Aaron Kromer, Benoit Tigeot, Bobby McDonald, ConSou,
+<li><strong>Total Commits</strong>: 103</li>
+<li><strong>Merged pull requests</strong>: 17</li>
+<li><strong>27 contributors</strong>: Aaron Kromer, Benoit Tigeot, Bobby McDonald, ConSou,
Douglas Lovell, Emric, Giovanni Kock Bonetti, Grey Baker, Joel Lubrano, Jon Rowe,
-Kevin Kuchta, Kieran O'Grady, Kohei Sugi, Laura Paakkinen, Manuel Schnitzer,
+Kevin Kuchta, Kieran O'Grady, Kohei Sugi, Laura Paakkinen, Manuel Schnitzer,
Michel Ocon, Myron Marston, OKURA Masafumi, Olle Jonsson, Orien Madgwick,
Penelope Phippen, Rafe Rosen, Ryan Lue, Takumi Kaji, Thomas Walpole, Tom Grimley,
aymeric-ledorze</li>
</ul>
-<h3 id="rspec-support">rspec-support:</h3>
+<h3>rspec-support:</h3>
<ul>
- <li><strong>Total Commits</strong>: 29</li>
- <li><strong>Merged pull requests</strong>: 20</li>
- <li><strong>4 contributors</strong>: Benoit Tigeot, Jon Rowe, Myron Marston, 三上大河</li>
+<li><strong>Total Commits</strong>: 29</li>
+<li><strong>Merged pull requests</strong>: 20</li>
+<li><strong>4 contributors</strong>: Benoit Tigeot, Jon Rowe, Myron Marston, 三上大河</li>
</ul>
-<h2 id="docs">Docs</h2>
+<h2>Docs</h2>
-<h3 id="api-docs">API Docs</h3>
+<h3>API Docs</h3>
<ul>
- <li><a href="/documentation/3.9/rspec-core/">rspec-core</a></li>
- <li><a href="/documentation/3.9/rspec-expectations/">rspec-expectations</a></li>
- <li><a href="/documentation/3.9/rspec-mocks/">rspec-mocks</a></li>
- <li><a href="/documentation/3.9/rspec-rails/">rspec-rails</a></li>
+<li><a href="/documentation/3.9/rspec-core/">rspec-core</a></li>
+<li><a href="/documentation/3.9/rspec-expectations/">rspec-expectations</a></li>
+<li><a href="/documentation/3.9/rspec-mocks/">rspec-mocks</a></li>
+<li><a href="/documentation/3.9/rspec-rails/">rspec-rails</a></li>
</ul>
-<h3 id="cucumber-features">Cucumber Features</h3>
+<h3>Cucumber Features</h3>
<ul>
- <li><a href="http://relishapp.com/rspec/rspec-core">rspec-core</a></li>
- <li><a href="http://relishapp.com/rspec/rspec-expectations">rspec-expectations</a></li>
- <li><a href="http://relishapp.com/rspec/rspec-mocks">rspec-mocks</a></li>
- <li><a href="http://relishapp.com/rspec/rspec-rails">rspec-rails</a></li>
+<li><a href="http://relishapp.com/rspec/rspec-core">rspec-core</a></li>
+<li><a href="http://relishapp.com/rspec/rspec-expectations">rspec-expectations</a></li>
+<li><a href="http://relishapp.com/rspec/rspec-mocks">rspec-mocks</a></li>
+<li><a href="http://relishapp.com/rspec/rspec-rails">rspec-rails</a></li>
</ul>
-<h2 id="release-notes">Release Notes</h2>
+<h2>Release Notes</h2>
+
+<h3>rspec-core-3.9.0</h3>
-<h3 id="rspec-core-390">rspec-core-3.9.0</h3>
<p><a href="http://github.com/rspec/rspec-core/compare/v3.8.2...v3.9.0">Full Changelog</a></p>
<p>Enhancements:
* Improve the handling of errors during loading support files, if a file
errors before loading specs, RSpec will now skip loading the specs.
(David Rodríguez, #2568)
-* Add support for –example-matches to run examples by regular expression.
+* Add support for –example-matches to run examples by regular expression.
(Sam Joseph, Matt Rider, @okothkongo1, #2586)
* Add <code>did_you_mean</code> suggestions for file names encountering a <code>LoadError</code>
outside of examples. (@obromios, #2601)
@@ -493,55 +493,58 @@ aymeric-ledorze</li>
* Indent messages by there example group / example in the documentation formatter.
(Samuel Williams, #2649)</p>
-<h3 id="rspec-expectations-390">rspec-expectations-3.9.0</h3>
+<h3>rspec-expectations-3.9.0</h3>
+
<p><a href="http://github.com/rspec/rspec-expectations/compare/v3.8.5...v3.9.0">Full Changelog</a></p>
<p>Enhancements:</p>
<ul>
- <li>The <code>respond_to</code> matcher now uses the signature from <code>initialize</code> to validate checks
+<li>The <code>respond_to</code> matcher now uses the signature from <code>initialize</code> to validate checks
for <code>new</code> (unless <code>new</code> is non standard). (Jon Rowe, #1072)</li>
- <li>Generated descriptions for matchers now use <code>is expected to</code> rather than <code>should</code> in
+<li>Generated descriptions for matchers now use <code>is expected to</code> rather than <code>should</code> in
line with our preferred DSL. (Pete Johns, #1080, rspec/rspec-core#2572)</li>
- <li>Add the ability to re-raise expectation errors when matching
+<li>Add the ability to re-raise expectation errors when matching
with <code>match_when_negated</code> blocks. (Jon Rowe, #1130)</li>
- <li>Add a warning when an empty diff is produce due to identical inspect output.
+<li>Add a warning when an empty diff is produce due to identical inspect output.
(Benoit Tigeot, #1126)</li>
</ul>
-<h3 id="rspec-mocks-390">rspec-mocks-3.9.0</h3>
+<h3>rspec-mocks-3.9.0</h3>
+
<p><a href="http://github.com/rspec/rspec-mocks/compare/v3.8.2...v3.9.0">Full Changelog</a></p>
<p>Enhancements:</p>
<ul>
- <li>Improve thread safety of message expectations by using Mutex to prevent
+<li>Improve thread safety of message expectations by using Mutex to prevent
deadlocking errors. (Ry Biesemeyer, #1236)</li>
- <li>Add the ability to use <code>time</code> as an alias for <code>times</code>. For example:
+<li>Add the ability to use <code>time</code> as an alias for <code>times</code>. For example:
<code>expect(Class).to receive(:method).exactly(1).time</code>.
(Pistos, Benoit Tigeot, #1271)</li>
</ul>
-<h3 id="rspec-rails-390">rspec-rails-3.9.0</h3>
+<h3>rspec-rails-3.9.0</h3>
+
<p><a href="http://github.com/rspec/rspec-rails/compare/v3.8.2...v3.9.0">Full Changelog</a></p>
<p>Enhancements</p>
<ul>
- <li>Use <code>__dir__</code> instead of <code>__FILE__</code> in generated <code>rails_helper.rb</code> where
+<li>Use <code>__dir__</code> instead of <code>__FILE__</code> in generated <code>rails_helper.rb</code> where
supported. (OKURA Masafumi, #2048)</li>
- <li>Add <code>have_enqueued</code> matcher as a "super" matcher to the <code>ActiveJob</code> matchers
+<li>Add <code>have_enqueued</code> matcher as a “super” matcher to the <code>ActiveJob</code> matchers
making it easier to match on <code>ActiveJob</code> delivered emails. (Joel Lubrano, #2047)</li>
- <li>Add generator for system specs on Rails 5.1 and above. (Andrzej Sliwa, #1933)</li>
- <li>Add generator for generator specs. (@ConSou, #2085)</li>
- <li>Add option to generate routes when generating controller specs. (David Revelo, #2134)</li>
+<li>Add generator for system specs on Rails 5.1 and above. (Andrzej Sliwa, #1933)</li>
+<li>Add generator for generator specs. (@ConSou, #2085)</li>
+<li>Add option to generate routes when generating controller specs. (David Revelo, #2134)</li>
</ul>
<p>Bug Fixes:</p>
<ul>
- <li>Make the <code>ActiveJob</code> matchers fail when multiple jobs are queued for negated
-matches. e.g. `expect { job; job; }.to_not have_enqueued_job.
+<li>Make the <code>ActiveJob</code> matchers fail when multiple jobs are queued for negated
+matches. e.g. `expect { job; job; }.to<em>not have</em>enqueued_job.
(Emric Istanful, #2069)</li>
</ul>
@@ -557,38 +560,38 @@ matches. e.g. `expect { job; job; }.to_not have_enqueued_job.
<p>My <a href="https://github.com/rspec/rspec-core/commit/cbd5a8a26885106e0483d189e9d39d80d58f7f77">first contribution to
RSpec</a>
-happened over 8 years ago, and I've <a href="http://blog.davidchelimsky.net/blog/2012/11/28/myron-marston-and-andy-lindeman-are-rspecs-new-project-leads/">lead the project for nearly 6
+happened over 8 years ago, and I’ve <a href="http://blog.davidchelimsky.net/blog/2012/11/28/myron-marston-and-andy-lindeman-are-rspecs-new-project-leads/">lead the project for nearly 6
years</a>.
In that time, a lot has been accomplished:</p>
<ul>
- <li>We shipped a dozen major or minor feature releases (plus
+<li>We shipped a dozen major or minor feature releases (plus
<a href="https://rubygems.org/gems/rspec-core/versions">many</a>,
<a href="https://rubygems.org/gems/rspec-expectations/versions">many</a>
<a href="https://rubygems.org/gems/rspec-mocks/versions">patch</a>
<a href="https://rubygems.org/gems/rspec-rails/versions">releases</a>)</li>
- <li>We added some of RSpec's most popular features (like <a href="/blog/2014/01/new-in-rspec-3-composable-matchers/">composable
+<li>We added some of RSpec’s most popular features (like <a href="/blog/2014/01/new-in-rspec-3-composable-matchers/">composable
matchers</a>,
<a href="https://rhnh.net/2013/12/10/new-in-rspec-3-verifying-doubles/">verifying doubles</a>, and
<a href="/blog/2015/06/rspec-3-3-has-been-released/#core-bisect"><code>--bisect</code></a>)</li>
- <li>I co-authored <a href="https://pragprog.com/book/rspec3/effective-testing-with-rspec-3">a book about using RSpec
+<li>I co-authored <a href="https://pragprog.com/book/rspec3/effective-testing-with-rspec-3">a book about using RSpec
effectively</a></li>
- <li>RSpec became <a href="https://rubygems.org/stats">the most popular Ruby gem</a> with over 300 million downloads</li>
+<li>RSpec became <a href="https://rubygems.org/stats">the most popular Ruby gem</a> with over 300 million downloads</li>
</ul>
<p>During that time, my life has also changed significantly:</p>
<ul>
- <li>I changed employers from <a href="https://moz.com/">Moz</a> to <a href="https://squareup.com/">Square</a> last year</li>
- <li>I stopped using Ruby as my primary language about 3 years ago (at Moz we switched to
+<li>I changed employers from <a href="https://moz.com/">Moz</a> to <a href="https://squareup.com/">Square</a> last year</li>
+<li>I stopped using Ruby as my primary language about 3 years ago (at Moz we switched to
<a href="https://elixir-lang.org/">Elixir</a> and my team at Square is using Java)</li>
- <li>I have 3 kids now (when I started working on RSpec I didn't have any!)</li>
- <li>I no longer have the kind of time I used to to work on open source</li>
+<li>I have 3 kids now (when I started working on RSpec I didn’t have any!)</li>
+<li>I no longer have the kind of time I used to to work on open source</li>
</ul>
<p>As much as I have enjoyed working on RSpec for the better part of a decade, I
-rarely have the time anymore, and when I do have the time, I often don't enjoy it.
-I'm also no longer a regular user of RSpec.</p>
+rarely have the time anymore, and when I do have the time, I often don’t enjoy it.
+I’m also no longer a regular user of RSpec.</p>
<p>In short, the time has come for me to take a step back from the project.
Effective immediately, Jon Rowe and Sam Phippen are the new co-leads of
@@ -611,12 +614,12 @@ project!</p>
<p>RSpec 3.8 has just been released! Given our commitment to
<a href="http://semver.org/">semantic versioning</a>, this should be an easy
upgrade for anyone already using RSpec 3, but if we did introduce
-any regressions, please let us know, and we'll get a patch release
+any regressions, please let us know, and we’ll get a patch release
out with a fix ASAP.</p>
-<p>We're also happy to announce that <a href="https://github.com/benoittgt">Benoit Tigeot</a>
+<p>We’re also happy to announce that <a href="https://github.com/benoittgt">Benoit Tigeot</a>
has joined the RSpec team since the last release. Welcome to the team, Benoit!
-We know you'll do great things :).</p>
+We know you’ll do great things :).</p>
<p>RSpec continues to be a community-driven project with contributors
from all over the world. This release includes 369 commits and 98
@@ -624,14 +627,14 @@ merged pull requests from 52 different contributors!</p>
<p>Thank you to everyone who helped make this release happen!</p>
-<h2 id="notable-changes">Notable Changes</h2>
+<h2>Notable Changes</h2>
-<h3 id="core-performance-of---bisect-has-been-significantly-improved">Core: Performance of –bisect has been significantly improved</h3>
+<h3>Core: Performance of –bisect has been significantly improved</h3>
<p>RSpec has supported a <code>--bisect</code> feature since
<a href="/blog/2015/06/rspec-3-3-has-been-released/#core-bisect">RSpec 3.3</a>.
This feature is useful when your test suite has an ordering
-dependency–that is, the suite only fails when the tests are run
+dependency–that is, the suite only fails when the tests are run
in a specific order. <code>--bisect</code> will repeatedly run smaller and
smaller subsets of your suite in order to narrow it down to the
minimal set of specs needed to reproduce the failures.</p>
@@ -646,29 +649,29 @@ to 30+ seconds on a large Rails app. In extreme cases, the runtime of
<code>--bisect</code> can be dominated by the time it takes to boot your application
environment over and over and over.</p>
-<p>In RSpec 3.8, we've improved bisect's performance by using forking
+<p>In RSpec 3.8, we’ve improved bisect’s performance by using forking
on platforms that support it rather than shelling out. That way, we
can boot your application environment <em>once</em>, and then fork a subprocess
in which to run each subset of the test suite, avoiding the need to boot
your application many times.</p>
-<p>The actual improvement you'll see in practice will vary widely, but
+<p>The actual improvement you’ll see in practice will vary widely, but
in our <a href="https://github.com/rspec/rspec-core/pull/2511">limited testing</a>
it improved the runtime of <code>--bisect</code> by 33% in one case and an
order-of-magnitude (108.9 seconds down to 11.7 seconds) in another.</p>
-<p>If you're looking to maximize the benefit of this change, you may
+<p>If you’re looking to maximize the benefit of this change, you may
want to pass some additional <code>--require</code> options when running a
bisection in order to pre-load as much of your application environment
as possible.</p>
-<h3 id="core-support-the-xdg-base-directory-spec-for-configuration">Core: Support the XDG base directory spec for configuration</h3>
+<h3>Core: Support the XDG base directory spec for configuration</h3>
<p>RSpec, like many command line tools, supports the use of options
files, which can live at <code>.rspec</code> (for team project options)
<code>~/.rspec</code> (for global personal options) or at <code>.rspec-local</code>
-(for personal project options – this file should not be under
-source control). In RSpec 3.8, we've expanded this feature to
+(for personal project options – this file should not be under
+source control). In RSpec 3.8, we’ve expanded this feature to
support the <a href="https://specifications.freedesktop.org/basedir-spec/latest/">XDG Base Directory
Specification</a>,
which defines a standard way for tools to locate the global personal
@@ -684,14 +687,13 @@ request</a>.</p>
<p>Thanks to Magnus Bergmark for implementing this feature!</p>
-<h3 id="expectations-formatted-output-length-is-now-configurable">Expectations: Formatted output length is now configurable</h3>
+<h3>Expectations: Formatted output length is now configurable</h3>
<p>When setting expectations on large objects their string representations can become
rather unwieldy and can clutter the console output. In RSpec 3.6, we started
truncating these objects to address this issue, but did not make it easily configurable.</p>
<p>In RSpec 3.8, you can now configure it:</p>
-
<div class="highlight"><pre class="highlight ruby"><code><span class="no">RSpec</span><span class="p">.</span><span class="nf">configure</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
<span class="n">config</span><span class="p">.</span><span class="nf">expect_with</span> <span class="ss">:rspec</span> <span class="k">do</span> <span class="o">|</span><span class="n">expectations</span><span class="o">|</span>
<span class="n">expectations</span><span class="p">.</span><span class="nf">max_formatted_output_length</span> <span class="o">=</span> <span class="mi">200</span>
@@ -700,31 +702,31 @@ truncating these objects to address this issue, but did not make it easily confi
</code></pre></div>
<p>You can also disable the truncation entirely by setting the config option to <code>nil</code>.</p>
-<h3 id="rails--havehttpstatus-matcher-upgraded-to-support-rails-52">Rails: <code>have_http_status</code> matcher upgraded to support Rails 5.2</h3>
+<h3>Rails: <code>have_http_status</code> matcher upgraded to support Rails 5.2</h3>
-<p>A change in Rails 5.2 caused RSpec's <code>have_http_status</code> matcher to issue deprecation
+<p>A change in Rails 5.2 caused RSpec’s <code>have_http_status</code> matcher to issue deprecation
warnings. In RSpec 3.8, these warnings have been removed.</p>
-<h3 id="rails-view-specs-stubtemplate-performance-improved">Rails: View specs <code>stub_template</code> performance improved.</h3>
+<h3>Rails: View specs <code>stub_template</code> performance improved.</h3>
<p>Thanks to Simon Coffey for implementing caching for <code>stub_template</code>
that prevents unnecessary recreation of templates. This improves performance
by reducing the amount of allocation and setup performed.</p>
-<h3 id="rails-railshelperrb-improvements">Rails: <code>rails_helper.rb</code> improvements</h3>
+<h3>Rails: <code>rails_helper.rb</code> improvements</h3>
<p>Thank you to Koichi ITO and Alessandro Rodi for improving our generated
<code>rails_helper.rb</code> with improved messages when migrations are pending,
and bringing us in line with Rails standards.</p>
-<h2 id="stats">Stats:</h2>
+<h2>Stats:</h2>
-<h3 id="combined">Combined:</h3>
+<h3>Combined:</h3>
<ul>
- <li><strong>Total Commits</strong>: 369</li>
- <li><strong>Merged pull requests</strong>: 98</li>
- <li><strong>52 contributors</strong>: Ace Dimasuhid, Alessandro Rodi, Alexander
+<li><strong>Total Commits</strong>: 369</li>
+<li><strong>Merged pull requests</strong>: 98</li>
+<li><strong>52 contributors</strong>: Ace Dimasuhid, Alessandro Rodi, Alexander
Panasyuk, Alyssa Ross, Andrew, Andrew Vit, Benoit Tigeot, Brad Charna,
Brian Kephart, Christophe Bliard, Craig J. Bass, Daniel Colson, Douglas
Lovell, Eric Hayes, Garett Arrowood, Gary Bernhardt, Gustav Munkby,
@@ -737,43 +739,43 @@ Systho, Szijjártó-Nagy Misu, Tom Chen, Xavier Shay, Yuji Nakayama,
arjan0307, joker1007, lsarni, n.epifanov, pavel</li>
</ul>
-<h3 id="rspec-core">rspec-core:</h3>
+<h3>rspec-core:</h3>
<ul>
- <li><strong>Total Commits</strong>: 94</li>
- <li><strong>Merged pull requests</strong>: 24</li>
- <li><strong>17 contributors</strong>: Alyssa Ross, Andrew Vit, Benoit Tigeot, Garett
+<li><strong>Total Commits</strong>: 94</li>
+<li><strong>Merged pull requests</strong>: 24</li>
+<li><strong>17 contributors</strong>: Alyssa Ross, Andrew Vit, Benoit Tigeot, Garett
Arrowood, Gary Bernhardt, Jon Rowe, Kenichi Kamiya, Koichi ITO, Magnus
Bergmark, Myron Marston, Oleg Pudeyev, Olle Jonsson, Sam Phippen, Sorah
Fukumori, Systho, Xavier Shay, arjan0307</li>
</ul>
-<h3 id="rspec-expectations">rspec-expectations:</h3>
+<h3>rspec-expectations:</h3>
<ul>
- <li><strong>Total Commits</strong>: 52</li>
- <li><strong>Merged pull requests</strong>: 15</li>
- <li><strong>13 contributors</strong>: Ace Dimasuhid, Alyssa Ross, Benoit Tigeot, James
+<li><strong>Total Commits</strong>: 52</li>
+<li><strong>Merged pull requests</strong>: 15</li>
+<li><strong>13 contributors</strong>: Ace Dimasuhid, Alyssa Ross, Benoit Tigeot, James
Crisp, Jon Rowe, Kenichi Kamiya, Myron Marston, Pablo Brasero, Sam
Phippen, Xavier Shay, Yuji Nakayama, joker1007, n.epifanov</li>
</ul>
-<h3 id="rspec-mocks">rspec-mocks:</h3>
+<h3>rspec-mocks:</h3>
<ul>
- <li><strong>Total Commits</strong>: 47</li>
- <li><strong>Merged pull requests</strong>: 16</li>
- <li><strong>13 contributors</strong>: Alexander Panasyuk, Alyssa Ross, Andrew, Benoit
+<li><strong>Total Commits</strong>: 47</li>
+<li><strong>Merged pull requests</strong>: 16</li>
+<li><strong>13 contributors</strong>: Alexander Panasyuk, Alyssa Ross, Andrew, Benoit
Tigeot, James Crisp, Jon Rowe, Kenichi Kamiya, Maxim Krizhanovsky, Myron
Marston, Olle Jonsson, Sam Phippen, Sergiy Yarinovskiy, Xavier Shay</li>
</ul>
-<h3 id="rspec-rails">rspec-rails:</h3>
+<h3>rspec-rails:</h3>
<ul>
- <li><strong>Total Commits</strong>: 132</li>
- <li><strong>Merged pull requests</strong>: 27</li>
- <li><strong>29 contributors</strong>: Alessandro Rodi, Benoit Tigeot, Brad Charna,
+<li><strong>Total Commits</strong>: 132</li>
+<li><strong>Merged pull requests</strong>: 27</li>
+<li><strong>29 contributors</strong>: Alessandro Rodi, Benoit Tigeot, Brad Charna,
Brian Kephart, Christophe Bliard, Daniel Colson, Douglas Lovell, Eric
Hayes, Joel Taylor, Jon Rowe, Kenichi Kamiya, Koichi ITO, Lairan, Laura
Paakkinen, Laurent Cobos, Matt Brictson, Myron Marston, Nikola Đuza,
@@ -781,149 +783,153 @@ Olivier Lacan, Paul McMahon, Regan Chan, Sam Phippen, Shane Cavanaugh,
Shia, Simon Coffey, Szijjártó-Nagy Misu, Tom Chen, lsarni, pavel</li>
</ul>
-<h3 id="rspec-support">rspec-support:</h3>
+<h3>rspec-support:</h3>
<ul>
- <li><strong>Total Commits</strong>: 44</li>
- <li><strong>Merged pull requests</strong>: 16</li>
- <li><strong>10 contributors</strong>: Alyssa Ross, Benoit Tigeot, Craig J. Bass, Gustav
+<li><strong>Total Commits</strong>: 44</li>
+<li><strong>Merged pull requests</strong>: 16</li>
+<li><strong>10 contributors</strong>: Alyssa Ross, Benoit Tigeot, Craig J. Bass, Gustav
Munkby, James Crisp, Jon Rowe, Kenichi Kamiya, Myron Marston, Sam
Phippen, Xavier Shay</li>
</ul>
-<h2 id="docs">Docs</h2>
+<h2>Docs</h2>
-<h3 id="api-docs">API Docs</h3>
+<h3>API Docs</h3>
<ul>
- <li><a href="/documentation/3.8/rspec-core/">rspec-core</a></li>
- <li><a href="/documentation/3.8/rspec-expectations/">rspec-expectations</a></li>
- <li><a href="/documentation/3.8/rspec-mocks/">rspec-mocks</a></li>
- <li><a href="/documentation/3.8/rspec-rails/">rspec-rails</a></li>
+<li><a href="/documentation/3.8/rspec-core/">rspec-core</a></li>
+<li><a href="/documentation/3.8/rspec-expectations/">rspec-expectations</a></li>
+<li><a href="/documentation/3.8/rspec-mocks/">rspec-mocks</a></li>
+<li><a href="/documentation/3.8/rspec-rails/">rspec-rails</a></li>
</ul>
-<h3 id="cucumber-features">Cucumber Features</h3>
+<h3>Cucumber Features</h3>
<ul>
- <li><a href="http://relishapp.com/rspec/rspec-core">rspec-core</a></li>
- <li><a href="http://relishapp.com/rspec/rspec-expectations">rspec-expectations</a></li>
- <li><a href="http://relishapp.com/rspec/rspec-mocks">rspec-mocks</a></li>
- <li><a href="http://relishapp.com/rspec/rspec-rails">rspec-rails</a></li>
+<li><a href="http://relishapp.com/rspec/rspec-core">rspec-core</a></li>
+<li><a href="http://relishapp.com/rspec/rspec-expectations">rspec-expectations</a></li>
+<li><a href="http://relishapp.com/rspec/rspec-mocks">rspec-mocks</a></li>
+<li><a href="http://relishapp.com/rspec/rspec-rails">rspec-rails</a></li>
</ul>
-<h2 id="release-notes">Release Notes</h2>
+<h2>Release Notes</h2>
+
+<h3>rspec-core-3.8.0</h3>
-<h3 id="rspec-core-380">rspec-core-3.8.0</h3>
<p><a href="http://github.com/rspec/rspec-core/compare/v3.7.1...v3.8.0">Full Changelog</a></p>
<p>Enhancements:</p>
<ul>
- <li>Improve shell escaping used by <code>RSpec::Core::RakeTask</code> and <code>--bisect</code> so
+<li>Improve shell escaping used by <code>RSpec::Core::RakeTask</code> and <code>--bisect</code> so
that it works on <code>Pathname</code> objects. (Andrew Vit, #2479)</li>
- <li>Nicely format errors encountered while loading files specified
+<li>Nicely format errors encountered while loading files specified
by <code>--require</code> option. (Myron Marston, #2504)</li>
- <li>Significantly improve the performance of <code>--bisect</code> on platforms that
+<li>Significantly improve the performance of <code>--bisect</code> on platforms that
support forking by replacing the shell-based runner with one that uses
forking so that RSpec and the application environment can be booted only
once, instead of once per spec run. (Myron Marston, #2511)</li>
- <li>Provide a configuration API to pick which bisect runner is used for
+<li>Provide a configuration API to pick which bisect runner is used for
<code>--bisect</code>. Pick a runner via <code>config.bisect_runner = :shell</code> or
<code>config.bisect_runner = :fork</code> in a file loaded by a <code>--require</code>
option passed at the command line or set in <code>.rspec</code>. (Myron Marston, #2511)</li>
- <li>Support the <a href="https://specifications.freedesktop.org/basedir-spec/latest/">XDG Base Directory
+<li>Support the <a href="https://specifications.freedesktop.org/basedir-spec/latest/">XDG Base Directory
Specification</a>
for the global options file. <code>~/.rspec</code> is still supported when no
options file is found in <code>$XDG_CONFIG_HOME/rspec/options</code> (Magnus Bergmark, #2538)</li>
- <li>Extract <code>RSpec.world.prepare_example_filtering</code> that sets up the
+<li>Extract <code>RSpec.world.prepare_example_filtering</code> that sets up the
example filtering for custom RSpec runners. (Oleg Pudeyev, #2552)</li>
</ul>
<p>Bug Fixes:</p>
<ul>
- <li>Prevent an <code>ArgumentError</code> when truncating backtraces with two identical
+<li>Prevent an <code>ArgumentError</code> when truncating backtraces with two identical
backtraces. (Systho, #2515, Benoit Tigeot, #2539)</li>
</ul>
-<h3 id="rspec-expectations-380">rspec-expectations-3.8.0</h3>
+<h3>rspec-expectations-3.8.0</h3>
+
<p><a href="http://github.com/rspec/rspec-expectations/compare/v3.7.0...v3.8.0">Full Changelog</a></p>
<p>Enhancements:</p>
<ul>
- <li>Improve failure message of <code>change(receiver, :message)</code> by including the
+<li>Improve failure message of <code>change(receiver, :message)</code> by including the
receiver as <code>SomeClass#some_message</code>. (Tomohiro Hashidate, #1005)</li>
- <li>Improve <code>change</code> matcher so that it can correctly detect changes in
+<li>Improve <code>change</code> matcher so that it can correctly detect changes in
deeply nested mutable objects (such as arrays-of-hashes-of-arrays).
The improved logic uses the before/after <code>hash</code> value to see if the
object has been mutated, rather than shallow duping the object.
(Myron Marston, #1034)</li>
- <li>Improve <code>include</code> matcher so that pseudo-hash objects (e.g. objects
+<li>Improve <code>include</code> matcher so that pseudo-hash objects (e.g. objects
that decorate a hash using a <code>SimpleDelegator</code> or similar) are treated
as a hash, as long as they implement <code>to_hash</code>. (Pablo Brasero, #1012)</li>
- <li>Add <code>max_formatted_output_length=</code> to configuration, allowing changing
+<li>Add <code>max_formatted_output_length=</code> to configuration, allowing changing
the length at which we truncate large output strings.
(Sam Phippen #951, Benoit Tigeot #1056)</li>
- <li>Improve error message when passing a matcher that doesn't support block
+<li>Improve error message when passing a matcher that doesn’t support block
expectations to a block based <code>expect</code>. (@nicktime, #1066)</li>
</ul>
-<h3 id="rspec-mocks-380">rspec-mocks-3.8.0</h3>
+<h3>rspec-mocks-3.8.0</h3>
+
<p><a href="http://github.com/rspec/rspec-mocks/compare/v3.7.0...v3.8.0">Full Changelog</a></p>
<p>Bug Fixes:</p>
<ul>
- <li>Issue error when encountering invalid "counted" negative message expectations.
+<li>Issue error when encountering invalid “counted” negative message expectations.
(Sergiy Yarinovskiy, #1212)</li>
- <li>Ensure <code>allow_any_instance_of</code> and <code>expect_any_instance_of</code> can be temporarily
+<li>Ensure <code>allow_any_instance_of</code> and <code>expect_any_instance_of</code> can be temporarily
supressed. (Jon Rowe, #1228)</li>
- <li>Ensure <code>expect_any_instance_of(double).to_not have_received(:some_method)</code>
+<li>Ensure <code>expect_any_instance_of(double).to_not have_received(:some_method)</code>
fails gracefully (as its not supported) rather than issuing a <code>NoMethodError</code>.
(Maxim Krizhanovsky, #1231)</li>
</ul>
-<h3 id="rspec-rails-380">rspec-rails-3.8.0</h3>
+<h3>rspec-rails-3.8.0</h3>
+
<p><a href="http://github.com/rspec/rspec-rails/compare/v3.7.2...v3.8.0">Full Changelog</a></p>
<p>Enhancements:</p>
<ul>
- <li>Improved message when migrations are pending in the default <code>rails_helper.rb</code>
+<li>Improved message when migrations are pending in the default <code>rails_helper.rb</code>
(Koichi ITO, #1924)</li>
- <li><code>have_http_status</code> matcher now supports Rails 5.2 style response symbols
+<li><code>have_http_status</code> matcher now supports Rails 5.2 style response symbols
(Douglas Lovell, #1951)</li>
- <li>Change generated Rails helper to match Rails standards for Rails.root
+<li>Change generated Rails helper to match Rails standards for Rails.root
(Alessandro Rodi, #1960)</li>
- <li>At support for asserting enqueued jobs have no wait period attached.
+<li>At support for asserting enqueued jobs have no wait period attached.
(Brad Charna, #1977)</li>
- <li>Cache instances of <code>ActionView::Template</code> used in <code>stub_template</code> resulting
+<li>Cache instances of <code>ActionView::Template</code> used in <code>stub_template</code> resulting
in increased performance due to less allocations and setup. (Simon Coffey, #1979)</li>
- <li>Rails scaffold generator now respects longer namespaces (e.g. api/v1/<thing>).
+<li>Rails scaffold generator now respects longer namespaces (e.g. api/v1/<thing>).
(Laura Paakkinen, #1958)</li>
</ul>
<p>Bug Fixes:</p>
<ul>
- <li>Escape quotation characters when producing method names for system spec
+<li>Escape quotation characters when producing method names for system spec
screenshots. (Shane Cavanaugh, #1955)</li>
- <li>Use relative path for resolving fixtures when <code>fixture_path</code> is not set.
+<li>Use relative path for resolving fixtures when <code>fixture_path</code> is not set.
(Laurent Cobos, #1943)</li>
- <li>Allow custom template resolvers in view specs. (@ahorek, #1941)</li>
+<li>Allow custom template resolvers in view specs. (@ahorek, #1941)</li>
</ul>
-<h3 id="rspec-support-380">rspec-support-3.8.0</h3>
+<h3>rspec-support-3.8.0</h3>
+
<p><a href="http://github.com/rspec/rspec-support/compare/v3.7.1...v3.8.0">Full Changelog</a></p>
<p>Bug Fixes:</p>
<ul>
- <li>Order hash keys before diffing to improve diff accuracy when using mocked calls.
+<li>Order hash keys before diffing to improve diff accuracy when using mocked calls.
(James Crisp, #334)</li>
</ul>
-
@@ -938,21 +944,21 @@ screenshots. (Shane Cavanaugh, #1955)</li>
<p>RSpec 3.7 has just been released! Given our commitment to
<a href="http://semver.org/">semantic versioning</a>, this should be an easy
upgrade for anyone already using RSpec 3, but if we did introduce
-any regressions, please let us know, and we'll get a patch release
+any regressions, please let us know, and we’ll get a patch release
out with a fix ASAP.</p>
<p>RSpec continues to be a community-driven project with contributors
from all over the world. This release includes over 127 commits and 31
merged pull requests from 27 different contributors!</p>
-<p>It's worth noting: this is a smaller release than usual, as we wanted to get our
+<p>It’s worth noting: this is a smaller release than usual, as we wanted to get our
Rails System Testing integration to you as quickly as possible.</p>
<p>Thank you to everyone who helped make this release happen!</p>
-<h2 id="notable-changes">Notable Changes</h2>
+<h2>Notable Changes</h2>
-<h3 id="rails-actiondispatchsystemtest-integration-system-specs">Rails: <code>ActionDispatch::SystemTest</code> integration (System specs)</h3>
+<h3>Rails: <code>ActionDispatch::SystemTest</code> integration (System specs)</h3>
<p>In Rails 5.1, a new kind of test was added, called system test. These tests wrap
capybara and Rails to allow for a full stack testing experience from frontend
@@ -963,16 +969,16 @@ which provide a smiliar integration. There are a few important differences
between feature specs and system specs that are worth enumerating:</p>
<ol>
- <li>If you use a javascript enabled driver (like selenium or poltergeist) with
+<li>If you use a javascript enabled driver (like selenium or poltergeist) with
feature specs your tests run in a different <strong>process</strong> than your Rails app.
This means that your tests and your code under test cannot share a database
-transaction, and so you cannot use RSpec's built in mechanism to roll back
+transaction, and so you cannot use RSpec’s built in mechanism to roll back
database changes, instead requiring a gem like <a href="https://github.com/DatabaseCleaner/database_cleaner">database
cleaner</a>. With system
tests, the Rails team has done the hard work to ensure that this is not the
-case, and so you can safely use RSpec's mechanism, without needing an extra
+case, and so you can safely use RSpec’s mechanism, without needing an extra
gem.</li>
- <li>RSpec's feature specs defaults to using the <code>Rack::Test</code> capybara driver. If
+<li>RSpec’s feature specs defaults to using the <code>Rack::Test</code> capybara driver. If
you want to use a javascript enabled test browser, it is on you to manage the
capybara configuration. For a long time this has proven to be something that
is tricky to get correct with more advanced integrations like selenium.
@@ -982,166 +988,171 @@ your behalf.</li>
</ol>
<p>As such, we are recommending that users on Rails 5.1 prefer writing system specs
-over feature specs for full application integration testing. We'd like to give a
+over feature specs for full application integration testing. We’d like to give a
special thanks to <a href="https://twitter.com/eileencodes">Eileen Uchitelle</a> who lead
the implementation of this feature in Rails.</p>
-<h2 id="stats">Stats:</h2>
+<h2>Stats:</h2>
-<h3 id="combined">Combined:</h3>
+<h3>Combined:</h3>
<ul>
- <li><strong>Total Commits</strong>: 127</li>
- <li><strong>Merged pull requests</strong>: 31</li>
- <li><strong>27 contributors</strong>: Aaron Rosenberg, Alex Shi, Alyssa Ross, Britni Alexander, Dave Woodall, Devon Estes, Hisashi Kamezawa, Ian Ker-Seymer, James Adam, Jim Kingdon, Jon Rowe, Levi Robertson, Myron Marston, Pat Allan, RustyNail, Ryan Lue, Sam Phippen, Samuel Cochran, Sergei Trofimovich, Takeshi Arabiki, Thomas Hart, Tobias Pfeiffer, Wojciech Wnętrzak, Xavier Shay, Yuji Nakayama, Zhong Zheng, oh_rusty_nail</li>
+<li><strong>Total Commits</strong>: 127</li>
+<li><strong>Merged pull requests</strong>: 31</li>
+<li><strong>27 contributors</strong>: Aaron Rosenberg, Alex Shi, Alyssa Ross, Britni Alexander, Dave Woodall, Devon Estes, Hisashi Kamezawa, Ian Ker-Seymer, James Adam, Jim Kingdon, Jon Rowe, Levi Robertson, Myron Marston, Pat Allan, RustyNail, Ryan Lue, Sam Phippen, Samuel Cochran, Sergei Trofimovich, Takeshi Arabiki, Thomas Hart, Tobias Pfeiffer, Wojciech Wnętrzak, Xavier Shay, Yuji Nakayama, Zhong Zheng, oh<em>rusty</em>nail</li>
</ul>
-<h3 id="rspec-core">rspec-core:</h3>
+<h3>rspec-core:</h3>
<ul>
- <li><strong>Total Commits</strong>: 40</li>
- <li><strong>Merged pull requests</strong>: 10</li>
- <li><strong>11 contributors</strong>: Devon Estes, Ian Ker-Seymer, Jon Rowe, Levi Robertson, Myron Marston, Pat Allan, Sam Phippen, Takeshi Arabiki, Thomas Hart, Tobias Pfeiffer, Yuji Nakayama</li>
+<li><strong>Total Commits</strong>: 40</li>
+<li><strong>Merged pull requests</strong>: 10</li>
+<li><strong>11 contributors</strong>: Devon Estes, Ian Ker-Seymer, Jon Rowe, Levi Robertson, Myron Marston, Pat Allan, Sam Phippen, Takeshi Arabiki, Thomas Hart, Tobias Pfeiffer, Yuji Nakayama</li>
</ul>
-<h3 id="rspec-expectations">rspec-expectations:</h3>
+<h3>rspec-expectations:</h3>
<ul>
- <li><strong>Total Commits</strong>: 13</li>
- <li><strong>Merged pull requests</strong>: 2</li>
- <li><strong>5 contributors</strong>: Jim Kingdon, Myron Marston, Pat Allan, Sam Phippen, Yuji Nakayama</li>
+<li><strong>Total Commits</strong>: 13</li>
+<li><strong>Merged pull requests</strong>: 2</li>
+<li><strong>5 contributors</strong>: Jim Kingdon, Myron Marston, Pat Allan, Sam Phippen, Yuji Nakayama</li>
</ul>
-<h3 id="rspec-mocks">rspec-mocks:</h3>
+<h3>rspec-mocks:</h3>
<ul>
- <li><strong>Total Commits</strong>: 14</li>
- <li><strong>Merged pull requests</strong>: 2</li>
- <li><strong>6 contributors</strong>: Aaron Rosenberg, Myron Marston, Pat Allan, Sam Phippen, Yuji Nakayama, Zhong Zheng</li>
+<li><strong>Total Commits</strong>: 14</li>
+<li><strong>Merged pull requests</strong>: 2</li>
+<li><strong>6 contributors</strong>: Aaron Rosenberg, Myron Marston, Pat Allan, Sam Phippen, Yuji Nakayama, Zhong Zheng</li>
</ul>
-<h3 id="rspec-rails">rspec-rails:</h3>
+<h3>rspec-rails:</h3>
<ul>
- <li><strong>Total Commits</strong>: 38</li>
- <li><strong>Merged pull requests</strong>: 9</li>
- <li><strong>16 contributors</strong>: Alex Shi, Alyssa Ross, Britni Alexander, Dave Woodall, Hisashi Kamezawa, James Adam, Jon Rowe, Myron Marston, RustyNail, Ryan Lue, Sam Phippen, Samuel Cochran, Wojciech Wnętrzak, Xavier Shay, Yuji Nakayama, oh_rusty_nail</li>
+<li><strong>Total Commits</strong>: 38</li>
+<li><strong>Merged pull requests</strong>: 9</li>
+<li><strong>16 contributors</strong>: Alex Shi, Alyssa Ross, Britni Alexander, Dave Woodall, Hisashi Kamezawa, James Adam, Jon Rowe, Myron Marston, RustyNail, Ryan Lue, Sam Phippen, Samuel Cochran, Wojciech Wnętrzak, Xavier Shay, Yuji Nakayama, oh<em>rusty</em>nail</li>
</ul>
-<h3 id="rspec-support">rspec-support:</h3>
+<h3>rspec-support:</h3>
<ul>
- <li><strong>Total Commits</strong>: 22</li>
- <li><strong>Merged pull requests</strong>: 8</li>
- <li><strong>6 contributors</strong>: Jon Rowe, Myron Marston, Pat Allan, Sam Phippen, Sergei Trofimovich, Yuji Nakayama</li>
+<li><strong>Total Commits</strong>: 22</li>
+<li><strong>Merged pull requests</strong>: 8</li>
+<li><strong>6 contributors</strong>: Jon Rowe, Myron Marston, Pat Allan, Sam Phippen, Sergei Trofimovich, Yuji Nakayama</li>
</ul>
-<h2 id="docs">Docs</h2>
+<h2>Docs</h2>
-<h3 id="api-docs">API Docs</h3>
+<h3>API Docs</h3>
<ul>
- <li><a href="/documentation/3.7/rspec-core/">rspec-core</a></li>
- <li><a href="/documentation/3.7/rspec-expectations/">rspec-expectations</a></li>
- <li><a href="/documentation/3.7/rspec-mocks/">rspec-mocks</a></li>
- <li><a href="/documentation/3.7/rspec-rails/">rspec-rails</a></li>
+<li><a href="/documentation/3.7/rspec-core/">rspec-core</a></li>
+<li><a href="/documentation/3.7/rspec-expectations/">rspec-expectations</a></li>
+<li><a href="/documentation/3.7/rspec-mocks/">rspec-mocks</a></li>
+<li><a href="/documentation/3.7/rspec-rails/">rspec-rails</a></li>
</ul>
-<h3 id="cucumber-features">Cucumber Features</h3>
+<h3>Cucumber Features</h3>
<ul>
- <li><a href="http://relishapp.com/rspec/rspec-core">rspec-core</a></li>
- <li><a href="http://relishapp.com/rspec/rspec-expectations">rspec-expectations</a></li>
- <li><a href="http://relishapp.com/rspec/rspec-mocks">rspec-mocks</a></li>
- <li><a href="http://relishapp.com/rspec/rspec-rails">rspec-rails</a></li>
+<li><a href="http://relishapp.com/rspec/rspec-core">rspec-core</a></li>
+<li><a href="http://relishapp.com/rspec/rspec-expectations">rspec-expectations</a></li>
+<li><a href="http://relishapp.com/rspec/rspec-mocks">rspec-mocks</a></li>
+<li><a href="http://relishapp.com/rspec/rspec-rails">rspec-rails</a></li>
</ul>
-<h2 id="release-notes">Release notes:</h2>
+<h2>Release notes:</h2>
+
+<h3>RSpec Core</h3>
-<h3 id="rspec-core-1">RSpec Core</h3>
<p><a href="http://github.com/rspec/rspec-core/compare/v3.6.0...v3.7.0">Full Changelog</a></p>
<p>Enhancements:</p>
<ul>
- <li>Add <code>-n</code> alias for <code>--next-failure</code>. (Ian Ker-Seymer, #2434)</li>
- <li>Improve compatibility with <code>--enable-frozen-string-literal</code> option
+<li>Add <code>-n</code> alias for <code>--next-failure</code>. (Ian Ker-Seymer, #2434)</li>
+<li>Improve compatibility with <code>--enable-frozen-string-literal</code> option
on Ruby 2.3+. (Pat Allan, #2425, #2427, #2437)</li>
- <li>Do not run <code>:context</code> hooks for example groups that have been skipped.
+<li>Do not run <code>:context</code> hooks for example groups that have been skipped.
(Devon Estes, #2442)</li>
- <li>Add <code>errors_outside_of_examples_count</code> to the JSON formatter.
+<li>Add <code>errors_outside_of_examples_count</code> to the JSON formatter.
(Takeshi Arabiki, #2448)</li>
</ul>
<p>Bug Fixes:</p>
<ul>
- <li>Improve compatibility with frozen string literal flag. (#2425, Pat Allan)</li>
+<li>Improve compatibility with frozen string literal flag. (#2425, Pat Allan)</li>
</ul>
-<h3 id="rspec-expectations-1">RSpec Expectations</h3>
+<h3>RSpec Expectations</h3>
+
<p><a href="http://github.com/rspec/rspec-expectations/compare/v3.6.0...v3.7.0">Full Changelog</a></p>
<p>Enhancements:</p>
<ul>
- <li>Improve compatibility with <code>--enable-frozen-string-literal</code> option
+<li>Improve compatibility with <code>--enable-frozen-string-literal</code> option
on Ruby 2.3+. (Pat Allan, #997)</li>
</ul>
-<h2 id="rspec-mocks-1">RSpec Mocks</h2>
+<h2>RSpec Mocks</h2>
+
<p><a href="http://github.com/rspec/rspec-mocks/compare/v3.6.0...v3.7.0">Full Changelog</a></p>
<p>Enhancements:</p>
<ul>
- <li>Improve compatibility with <code>--enable-frozen-string-literal</code> option
+<li>Improve compatibility with <code>--enable-frozen-string-literal</code> option
on Ruby 2.3+. (Pat Allan, #1165)</li>
</ul>
<p>Bug Fixes:</p>
<ul>
- <li>Fix <code>hash_including</code> and <code>hash_excluding</code> so that they work against
+<li>Fix <code>hash_including</code> and <code>hash_excluding</code> so that they work against
subclasses of <code>Hash</code>. (Aaron Rosenberg, #1167)</li>
</ul>
-<h2 id="rspec-rails-1">RSpec Rails</h2>
+<h2>RSpec Rails</h2>
+
<p><a href="http://github.com/rspec/rspec-rails/compare/v3.6.0...v3.7.0">Full Changelog</a></p>
<p>Bug Fixes:</p>
<ul>
- <li>Prevent "template not rendered" log message from erroring in threaded
+<li>Prevent “template not rendered” log message from erroring in threaded
environments. (Samuel Cochran, #1831)</li>
- <li>Correctly generate job name in error message. (Wojciech Wnętrzak, #1814)</li>
+<li>Correctly generate job name in error message. (Wojciech Wnętrzak, #1814)</li>
</ul>
<p>Enhancements:</p>
<ul>
- <li>Allow <code>be_a_new(...).with(...)</code> matcher to accept matchers for
+<li>Allow <code>be_a_new(...).with(...)</code> matcher to accept matchers for
attribute values. (Britni Alexander, #1811)</li>
- <li>Only configure RSpec Mocks if it is fully loaded. (James Adam, #1856)</li>
- <li>Integrate with <code>ActionDispatch::SystemTestCase</code>. (Sam Phippen, #1813)</li>
+<li>Only configure RSpec Mocks if it is fully loaded. (James Adam, #1856)</li>
+<li>Integrate with <code>ActionDispatch::SystemTestCase</code>. (Sam Phippen, #1813)</li>
</ul>
-<h2 id="rspec-support-1">RSpec Support</h2>
+<h2>RSpec Support</h2>
+
<p><a href="http://github.com/rspec/rspec-support/compare/v3.6.0...v3.7.0">Full Changelog</a></p>
<p>Enhancements:</p>
<ul>
- <li>Improve compatibility with <code>--enable-frozen-string-literal</code> option
+<li>Improve compatibility with <code>--enable-frozen-string-literal</code> option
on Ruby 2.3+. (Pat Allan, #320)</li>
- <li>Add <code>Support.class_of</code> for extracting class of any object.
+<li>Add <code>Support.class_of</code> for extracting class of any object.
(Yuji Nakayama, #325)</li>
</ul>
<p>Bug Fixes:</p>
<ul>
- <li>Fix recursive const support to not blow up when given buggy classes
+<li>Fix recursive const support to not blow up when given buggy classes
that raise odd errors from <code>#to_str</code>. (Myron Marston, #317)</li>
</ul>
diff --git a/docs/documentation/index.html b/docs/documentation/index.html
index 9b4f0ba77..7dc4ef438 100644
--- a/docs/documentation/index.html
+++ b/docs/documentation/index.html
@@ -2,23 +2,24 @@
-RSpec documentation API Documentation
The API documentation contains details about all public APIs supported by RSpec.
+
RSpec documentation Documentation
Gem RDoc Examples (Relish / Gherkin) rspec-core 3.12 3.12 rspec-expectations 3.12 3.12 rspec-mocks 3.12 3.12 rspec-rails 6.0 6.0
RSpec is composed of multiple libraries, which are designed to work together, or
+can be used independently with other testing tools like Cucumber
+or Minitest.
The parts of RSpec are:
- rspec-core: The spec runner, providing a rich command line program, flexible and customizable reporting, and an API to organize your code examples.
+
- rspec-expectations: Provides a readable API to express expected outcomes of a code example.
+
- rspec-mocks: Test double framework, providing multiple types of fake objects to allow you to tightly control the environment in which your specs run.
+
- rspec-rails: Supports using RSpec to test Ruby on Rails applications in place of Rails' built-in test framework.
The API documentation contains details about all public APIs supported by RSpec.
We consider these the primary docs and will treat these APIs according to the
policies of Semantic Versioning. We encourage you
to use only public APIs as private APIs may change in any release without warning.
If you have a use case not supported by the existing public APIs, please ask
-and we'll be glad to add an API for you or make an existing private API public.
RSpec is composed of multiple libraries, which are designed to work together, or
-can be used independently with other testing tools like Cucumber
-or Minitest. The parts of RSpec are:
- rspec-core: The spec runner, providing a rich command line program, flexible and customizable reporting, and an API to organize your code examples.
- Versions:
- rspec-expectations: Provides a readable API to express expected outcomes of a code example.
- Versions:
- rspec-mocks: Test double framework, providing multiple types of fake objects to allow you to tightly control the environment in which your specs run.
- Versions:
- rspec-rails: Supports using RSpec to test Ruby on Rails applications in place of Rails' built-in test framework. Versions:
Relish / Gherkin
RSpec is also documented through executable examples written in Gherkin.
+and we'll be glad to add an API for you or make an existing private API public.
Gherkin Examples (e.g. RelishApp)
RSpec is also documented through executable examples written in Gherkin.
The examples are written in an "end-to-end" style demonstrating the use of
various RSpec features in the context of executable spec files. They are
a good resource for getting a survey of what RSpec is capable of and seeing
how the pieces can be used together, but for detailed documentation about a
-particular API or feature, we recommend the API docs.
Previously these gherkin examples could be read on
+particular API or feature, we recommend the API docs.
These feature files are executed via Cucumber in our CI process to ensure they
+are always up-to-date with the current code base.
Previously our gherkin examples could be read on
RelishApp but currently
-this service is unavailable, you can find the raw files in our Github
-repositories whilst we work on a replacement.
These feature files are executed via Cucumber in our CI process to ensure they
-are always up-to-date with the current code base.
\ No newline at end of file
+this service is unavailable. We thank Matt Wynne for his contribution
+hosting these over the years, and we now host these ourselves via the
+table above.
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/.nav b/docs/features/3-12/rspec-core/.nav
new file mode 100644
index 000000000..e2065bd3b
--- /dev/null
+++ b/docs/features/3-12/rspec-core/.nav
@@ -0,0 +1,60 @@
+- example-groups:
+ - basic-structure.feature
+ - shared-examples.feature
+ - shared-context.feature
+- command-line:
+ - example-name-option.feature
+ - format-option.feature
+ - tag.feature
+ - line-number-appended-to-path.feature
+ - exit-status.feature
+ - order.md (`--order` option)
+ - rake-task.feature
+- pending-and-skipped-examples:
+ - pending-examples.feature
+- hooks:
+ - before-and-after-hooks.feature
+ - around-hooks.feature
+ - filtering.feature
+ - when-first-matching-example-defined.feature
+- subject:
+ - implicit-subject.feature
+ - explicit-subject.feature
+ - one-liner-syntax.feature
+- helper-methods:
+ - let.feature
+ - arbitrary-methods.feature
+ - modules.feature
+- metadata:
+ - current-example.feature
+ - described-class.feature
+ - user-defined.feature
+- filtering:
+ - inclusion-filters.feature
+ - exclusion-filters.feature
+ - if-and-unless.feature
+ - filter-run-when-matching.feature
+- configuration:
+ - read-options-from-file.feature
+ - color.feature
+ - fail-fast.feature
+ - fail-if-no-examples.feature
+ - custom-settings.feature
+ - alias-example-to.feature
+ - default-path.feature
+- expectation-framework-integration:
+ - configure-expectation-framework.feature
+ - aggregating-failures.feature
+- mock-framework-integration:
+ - use-rspec.feature
+ - use-flexmock.feature
+ - use-mocha.feature
+ - use-rr.feature
+ - use-any-framework.feature
+- formatters:
+ - configurable-colors.feature
+ - json-formatter.feature
+ - custom-formatter.feature
+- spec-files:
+ - arbitrary-file-suffix.feature
+- core-standalone.feature
diff --git a/docs/features/3-12/rspec-core/clear-examples/index.html b/docs/features/3-12/rspec-core/clear-examples/index.html
new file mode 100644
index 000000000..058931f77
--- /dev/null
+++ b/docs/features/3-12/rspec-core/clear-examples/index.html
@@ -0,0 +1,104 @@
+
+
+
+
+Running specs multiple times with different runner options in the same process
+
+Use clear_examples command to clear all example groups between different
+ runs in the same process. It:
+
+
+- clears all example groups
+- restores inclusion and exclusion filters set by configuration
+- clears inclusion and exclusion filters set by previous spec run (via runner)
+- resets all time counters (start time, load time, duration, etc.)
+- resets different counts of examples (all examples, pending and failed)
+
+ require "spec_helper"
+
+ RSpec::Core::Runner.run([... some parameters ...])
+
+ RSpec.clear_examples
+
+ RSpec::Core::Runner.run([... different parameters ...])
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.filter_run_when_matching :focus => true
+ config.filter_run_excluding :slow => true
+end
+
+Given a file named “spec/truth_spec.rb” with:
+require 'spec_helper'
+
+RSpec.describe "truth" do
+ describe true do
+ it "is truthy" do
+ expect(true).to be_truthy
+ end
+
+ it "is not falsy" do
+ expect(true).not_to be_falsy
+ end
+ end
+
+ describe false do
+ it "is falsy" do
+ expect(false).to be_falsy
+ end
+
+ it "is truthy" do
+ expect(false).not_to be_truthy
+ end
+ end
+end
+
+Running specs multiple times in the same process
+
+Given a file named “scripts/multiple_runs.rb” with:
+require 'rspec/core'
+
+RSpec::Core::Runner.run(['spec'])
+RSpec.clear_examples
+RSpec::Core::Runner.run(['spec'])
+
+When I run ruby scripts/multiple_runs.rb
+
+Then the output should match:
+4 examples, 0 failures
+.*
+4 examples, 0 failures
+
+Running specs multiple times in the same process with different parameters
+
+Given a file named “spec/bar_spec.rb” with:
+require 'spec_helper'
+
+RSpec.describe 'bar' do
+ subject(:bar) { :focused }
+
+ it 'is focused', :focus do
+ expect(bar).to be(:focused)
+ end
+end
+
+Given a file named “scripts/different_parameters.rb” with:
+require 'rspec/core'
+
+RSpec::Core::Runner.run(['spec'])
+RSpec.clear_examples
+RSpec::Core::Runner.run(['spec/truth_spec.rb:4'])
+RSpec.clear_examples
+RSpec::Core::Runner.run(['spec', '-e', 'fals'])
+
+When I run ruby scripts/different_parameters.rb
+
+Then the output should match:
+1 example, 0 failures
+.*
+2 examples, 0 failures
+.*
+3 examples, 0 failures
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/bisect/index.html b/docs/features/3-12/rspec-core/command-line/bisect/index.html
new file mode 100644
index 000000000..2ad33cfd5
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/bisect/index.html
@@ -0,0 +1,186 @@
+
+
+
+
+Bisect
+
+RSpec’s --order random and --seed options help surface flickering examples that only fail when one or more other examples are executed first. It can be very difficult to isolate the exact combination of examples that triggers the failure. The --bisect flag helps solve that problem.
+
+Pass the --bisect option (in addition to --seed and any other options) and RSpec will repeatedly run subsets of your suite in order to isolate the minimal set of examples that reproduce the same failures.
+
+At any point during the bisect run, you can hit ctrl-c to abort and it will provide you with the most minimal reproduction command it has discovered so far.
+
+To get more detailed output (particularly useful if you want to report a bug with bisect), use --bisect=verbose.
+
+Background
+
+Given a file named “lib/calculator.rb” with:
+class Calculator
+ def self.add(x, y)
+ x + y
+ end
+end
+
+And a file named “spec/calculator1spec.rb” with:
+require 'calculator'
+
+RSpec.describe "Calculator" do
+ it 'adds numbers' do
+ expect(Calculator.add(1, 2)).to eq(3)
+ end
+end
+
+And files “spec/calculator2spec.rb” through “spec/calculator9spec.rb” with an unrelated passing spec in each file
+
+And a file named “spec/calculator10spec.rb” with:
+require 'calculator'
+
+RSpec.describe "Monkey patched Calculator" do
+ it 'does screwy math' do
+ # monkey patching `Calculator` affects examples that are
+ # executed after this one!
+ def Calculator.add(x, y)
+ x - y
+ end
+
+ expect(Calculator.add(5, 10)).to eq(-5)
+ end
+end
+
+Use --bisect flag to create a minimal repro case for the ordering dependency
+
+When I run rspec --seed 1234
+
+Then the output should contain “10 examples, 1 failure”
+
+When I run rspec --seed 1234 --bisect
+
+Then bisect should succeed with output like:
+Bisect started using options: "--seed 1234"
+Running suite to find failures... (0.16755 seconds)
+Starting bisect with 1 failing example and 9 non-failing examples.
+Checking that failure(s) are order-dependent... failure appears to be order-dependent
+
+Round 1: bisecting over non-failing examples 1-9 .. ignoring examples 6-9 (0.30166 seconds)
+Round 2: bisecting over non-failing examples 1-5 .. ignoring examples 4-5 (0.30306 seconds)
+Round 3: bisecting over non-failing examples 1-3 .. ignoring example 3 (0.33292 seconds)
+Round 4: bisecting over non-failing examples 1-2 . ignoring example 1 (0.16476 seconds)
+Bisect complete! Reduced necessary non-failing examples from 9 to 1 in 1.26 seconds.
+
+The minimal reproduction command is:
+ rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] --seed 1234
+
+When I run rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] --seed 1234
+
+Then the output should contain “2 examples, 1 failure”.
+
+Ctrl-C can be used to abort the bisect early and get the most minimal command it has discovered so far
+
+When I run rspec --seed 1234 --bisect and abort in the middle with ctrl-c
+
+Then bisect should fail with output like:
+Bisect started using options: "--seed 1234"
+Running suite to find failures... (0.17102 seconds)
+Starting bisect with 1 failing example and 9 non-failing examples.
+Checking that failure(s) are order-dependent... failure appears to be order-dependent
+
+Round 1: bisecting over non-failing examples 1-9 .. ignoring examples 6-9 (0.32943 seconds)
+Round 2: bisecting over non-failing examples 1-5 .. ignoring examples 4-5 (0.3154 seconds)
+Round 3: bisecting over non-failing examples 1-3 .. ignoring example 3 (0.2175 seconds)
+
+Bisect aborted!
+
+The most minimal reproduction command discovered so far is:
+ rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_3_spec.rb[1:1] --seed 1234
+
+When I run rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_3_spec.rb[1:1] --seed 1234
+
+Then the output should contain “3 examples, 1 failure”.
+
+Use --bisect=verbose to enable verbose debug mode for more detail
+
+When I run rspec --seed 1234 --bisect=verbose
+
+Then bisect should succeed with output like:
+Bisect started using options: "--seed 1234" and bisect runner: :fork
+Running suite to find failures... (0.16528 seconds)
+ - Failing examples (1):
+ - ./spec/calculator_1_spec.rb[1:1]
+ - Non-failing examples (9):
+ - ./spec/calculator_10_spec.rb[1:1]
+ - ./spec/calculator_2_spec.rb[1:1]
+ - ./spec/calculator_3_spec.rb[1:1]
+ - ./spec/calculator_4_spec.rb[1:1]
+ - ./spec/calculator_5_spec.rb[1:1]
+ - ./spec/calculator_6_spec.rb[1:1]
+ - ./spec/calculator_7_spec.rb[1:1]
+ - ./spec/calculator_8_spec.rb[1:1]
+ - ./spec/calculator_9_spec.rb[1:1]
+Checking that failure(s) are order-dependent..
+ - Running: rspec ./spec/calculator_1_spec.rb[1:1] --seed 1234 (n.nnnn seconds)
+ - Failure appears to be order-dependent
+Round 1: bisecting over non-failing examples 1-9
+ - Running: rspec ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_6_spec.rb[1:1] ./spec/calculator_7_spec.rb[1:1] ./spec/calculator_8_spec.rb[1:1] ./spec/calculator_9_spec.rb[1:1] --seed 1234 (0.15302 seconds)
+ - Running: rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_2_spec.rb[1:1] ./spec/calculator_3_spec.rb[1:1] ./spec/calculator_4_spec.rb[1:1] ./spec/calculator_5_spec.rb[1:1] --seed 1234 (0.19708 seconds)
+ - Examples we can safely ignore (4):
+ - ./spec/calculator_6_spec.rb[1:1]
+ - ./spec/calculator_7_spec.rb[1:1]
+ - ./spec/calculator_8_spec.rb[1:1]
+ - ./spec/calculator_9_spec.rb[1:1]
+ - Remaining non-failing examples (5):
+ - ./spec/calculator_10_spec.rb[1:1]
+ - ./spec/calculator_2_spec.rb[1:1]
+ - ./spec/calculator_3_spec.rb[1:1]
+ - ./spec/calculator_4_spec.rb[1:1]
+ - ./spec/calculator_5_spec.rb[1:1]
+Round 2: bisecting over non-failing examples 1-5
+ - Running: rspec ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_4_spec.rb[1:1] ./spec/calculator_5_spec.rb[1:1] --seed 1234 (0.15836 seconds)
+ - Running: rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_2_spec.rb[1:1] ./spec/calculator_3_spec.rb[1:1] --seed 1234 (0.19065 seconds)
+ - Examples we can safely ignore (2):
+ - ./spec/calculator_4_spec.rb[1:1]
+ - ./spec/calculator_5_spec.rb[1:1]
+ - Remaining non-failing examples (3):
+ - ./spec/calculator_10_spec.rb[1:1]
+ - ./spec/calculator_2_spec.rb[1:1]
+ - ./spec/calculator_3_spec.rb[1:1]
+Round 3: bisecting over non-failing examples 1-3
+ - Running: rspec ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_2_spec.rb[1:1] --seed 1234 (0.21028 seconds)
+ - Running: rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] ./spec/calculator_3_spec.rb[1:1] --seed 1234 (0.1975 seconds)
+ - Examples we can safely ignore (1):
+ - ./spec/calculator_2_spec.rb[1:1]
+ - Remaining non-failing examples (2):
+ - ./spec/calculator_10_spec.rb[1:1]
+ - ./spec/calculator_3_spec.rb[1:1]
+Round 4: bisecting over non-failing examples 1-2
+ - Running: rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] --seed 1234 (0.17173 seconds)
+ - Examples we can safely ignore (1):
+ - ./spec/calculator_3_spec.rb[1:1]
+ - Remaining non-failing examples (1):
+ - ./spec/calculator_10_spec.rb[1:1]
+Bisect complete! Reduced necessary non-failing examples from 9 to 1 in 1.47 seconds.
+
+The minimal reproduction command is:
+ rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] --seed 1234
+
+When I run rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] --seed 1234
+
+Then the output should contain “2 examples, 1 failure”.
+
+Pick a bisect runner via a config option
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |c|
+ c.bisect_runner = :shell
+end
+
+And a file named “.rspec” with:
+--require spec_helper
+
+When I run rspec --seed 1234 --bisect=verbose
+
+Then bisect should succeed with output like:
+Bisect started using options: "--seed 1234" and bisect runner: :shell
+# ...
+The minimal reproduction command is:
+ rspec ./spec/calculator_10_spec.rb[1:1] ./spec/calculator_1_spec.rb[1:1] --seed 1234
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/dry-run/index.html b/docs/features/3-12/rspec-core/command-line/dry-run/index.html
new file mode 100644
index 000000000..39681bb5c
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/dry-run/index.html
@@ -0,0 +1,37 @@
+
+
+
+
+--dry-run option
+
+Use the --dry-run option to have RSpec print your suite’s formatter output
+ without running any examples or hooks.
+
+Using --dry-run
+
+Given a file named “spec/dryrunspec.rb” with:
+RSpec.configure do |c|
+ c.before(:suite) { puts "before suite" }
+ c.after(:suite) { puts "after suite" }
+end
+
+RSpec.describe "dry run" do
+ before(:context) { fail }
+ before(:example) { fail }
+
+ it "fails in example" do
+ fail
+ end
+
+ after(:example) { fail }
+ after(:context) { fail }
+end
+
+When I run rspec --dry-run
+
+Then the output should contain “1 example, 0 failures”
+
+And the output should not contain “before suite”
+
+And the output should not contain “after suite”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/example-matches-name-option/index.html b/docs/features/3-12/rspec-core/command-line/example-matches-name-option/index.html
new file mode 100644
index 000000000..ed2866ffa
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/example-matches-name-option/index.html
@@ -0,0 +1,249 @@
+
+
+
+
+--example-matches option
+
+Use the --example-matches (or -E) option to filter examples by name using REGEX.
+
+The argument is matched against the full description of the example, which is
+ the concatenation of descriptions of the group (including any nested groups)
+ and the example.
+
+This allows you to run a single uniquely named example, all examples with
+ similar names, all the examples in a uniquely named group, etc, etc.
+
+You can also use the option more than once to specify multiple example
+ matches.
+
+Note: description-less examples that have generated descriptions (typical when using the one-liner syntax) cannot be directly filtered with this option, because it is necessary to execute the example to generate the description, so RSpec is unable to use the not-yet-generated description to decide whether or not to execute an example. You can, of course, pass part of a group’s description to select all examples defined in the group (including those that have no description).
+
+Background
+
+Given a file named “first_spec.rb” with:
+RSpec.describe "first group" do
+ it "first" do; end
+ it "first example in first group" do; end
+ it "second example in first group" do; end
+end
+
+And a file named “second_spec.rb” with:
+RSpec.describe "second group" do
+ it "first example in second group" do; end
+ it "second example in second group" do; end
+end
+
+And a file named “third_spec.rb” with:
+RSpec.describe "third group" do
+ it "first example in third group" do; end
+ context "group of nest" do
+ it "first example in nested group" do; end
+ it "second example in nested group" do; end
+ it "third example in nested_group with underscore" do; end
+ end
+end
+
+And a file named “fourth_spec.rb” with:
+RSpec.describe Array do
+ describe "#length" do
+ it "is the number of items" do
+ expect(Array.new([1,2,3]).length).to eq 3
+ end
+ end
+end
+
+No matches
+
+When I run rspec . --example-matches nothing_like_this
+
+Then the process should succeed even though no examples were run.
+
+Match on one word
+
+When I run rspec . --example-matches example
+
+Then the examples should all pass.
+
+One match in each context
+
+When I run rspec . --example-matches 'first example'
+
+Then the examples should all pass.
+
+One match in one file using just the example name
+
+When I run rspec . --example-matches 'first example in first group'
+
+Then the examples should all pass.
+
+One match in one file using the example name and the group name
+
+When I run rspec . --example-matches 'first group first example in first group'
+
+Then the examples should all pass.
+
+All examples in one group
+
+When I run rspec . --example-matches 'first group'
+
+Then the examples should all pass.
+
+One match in one file with group name
+
+When I run rspec . --example-matches 'second group first example'
+
+Then the examples should all pass.
+
+All examples in one group including examples in nested groups
+
+When I run rspec . --example-matches 'third group'
+
+Then the examples should all pass.
+
+Match using ClassName#method_name form
+
+When I run rspec . --example-matches 'Array#length'
+
+Then the examples should all pass.
+
+Match only matching regex
+
+When I run rspec . --example-matches "first$" --format d
+
+Then the examples should all pass
+
+And the output should contain all of these:
+
+
+
+
+
+
+
+first
+
+
+
+And the output should not contain any of these:
+
+
+
+
+
+
+
+first example in first group
+
+
+second example in first group
+
+
+first example in second group
+
+
+second example in second group
+
+
+first example in third group
+
+
+nested group first example in nested group
+
+
+nested group second example in nested group
+
+
+
+Match only matching regex with word boundaries
+
+When I run rspec . --example-matches "nested[^_]" --format d
+
+Then the examples should all pass
+
+And the output should contain all of these:
+
+
+
+
+
+
+
+first example in nested group
+
+
+second example in nested group
+
+
+
+And the output should not contain any of these:
+
+
+
+
+
+
+
+first example in first group
+
+
+second example in first group
+
+
+first example in second group
+
+
+second example in second group
+
+
+first example in third group
+
+
+third example in nested_group
+
+
+
+Multiple applications of example name option
+
+When I run rspec . --example-matches 'first group' --example-matches 'second group' --format d
+
+Then the examples should all pass
+
+And the output should contain all of these:
+
+
+
+
+
+
+
+first example in first group
+
+
+second example in first group
+
+
+first example in second group
+
+
+second example in second group
+
+
+
+And the output should not contain any of these:
+
+
+
+
+
+
+
+first example in third group
+
+
+nested group first example in nested group
+
+
+nested group second example in nested group
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/example-name-option/index.html b/docs/features/3-12/rspec-core/command-line/example-name-option/index.html
new file mode 100644
index 000000000..a5acacb64
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/example-name-option/index.html
@@ -0,0 +1,151 @@
+
+
+
+
+--example option
+
+Use the --example (or -e) option to filter examples by name.
+
+The argument is matched against the full description of the example, which is
+ the concatenation of descriptions of the group (including any nested groups)
+ and the example.
+
+This allows you to run a single uniquely named example, all examples with
+ similar names, all the examples in a uniquely named group, etc, etc.
+
+You can also use the option more than once to specify multiple example
+ matches.
+
+Note: description-less examples that have generated descriptions (typical when using the one-liner syntax) cannot be directly filtered with this option, because it is necessary to execute the example to generate the description, so RSpec is unable to use the not-yet-generated description to decide whether or not to execute an example. You can, of course, pass part of a group’s description to select all examples defined in the group (including those that have no description).
+
+Background
+
+Given a file named “first_spec.rb” with:
+RSpec.describe "first group" do
+ it "first example in first group" do; end
+ it "second example in first group" do; end
+end
+
+And a file named “second_spec.rb” with:
+RSpec.describe "second group" do
+ it "first example in second group" do; end
+ it "second example in second group" do; end
+end
+
+And a file named “third_spec.rb” with:
+RSpec.describe "third group" do
+ it "first example in third group" do; end
+ context "nested group" do
+ it "first example in nested group" do; end
+ it "second example in nested group" do; end
+ end
+end
+
+And a file named “fourth_spec.rb” with:
+RSpec.describe Array do
+ describe "#length" do
+ it "is the number of items" do
+ expect(Array.new([1,2,3]).length).to eq 3
+ end
+ end
+end
+
+No matches
+
+When I run rspec . --example nothing_like_this
+
+Then the process should succeed even though no examples were run.
+
+Match on one word
+
+When I run rspec . --example example
+
+Then the examples should all pass.
+
+One match in each context
+
+When I run rspec . --example 'first example'
+
+Then the examples should all pass.
+
+One match in one file using just the example name
+
+When I run rspec . --example 'first example in first group'
+
+Then the examples should all pass.
+
+One match in one file using the example name and the group name
+
+When I run rspec . --example 'first group first example in first group'
+
+Then the examples should all pass.
+
+All examples in one group
+
+When I run rspec . --example 'first group'
+
+Then the examples should all pass.
+
+One match in one file with group name
+
+When I run rspec . --example 'second group first example'
+
+Then the examples should all pass.
+
+All examples in one group including examples in nested groups
+
+When I run rspec . --example 'third group'
+
+Then the examples should all pass.
+
+Match using ClassName#method_name form
+
+When I run rspec . --example 'Array#length'
+
+Then the examples should all pass.
+
+Multiple applications of example name option
+
+When I run rspec . --example 'first group' --example 'second group' --format d
+
+Then the examples should all pass
+
+And the output should contain all of these:
+
+
+
+
+
+
+
+first example in first group
+
+
+second example in first group
+
+
+first example in second group
+
+
+second example in second group
+
+
+
+And the output should not contain any of these:
+
+
+
+
+
+
+
+first example in third group
+
+
+nested group first example in nested group
+
+
+nested group second example in nested group
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/exit-status/index.html b/docs/features/3-12/rspec-core/command-line/exit-status/index.html
new file mode 100644
index 000000000..1564748c9
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/exit-status/index.html
@@ -0,0 +1,82 @@
+
+
+
+
+--failure-exit-code option (exit status)
+
+The rspec command exits with an exit status of 0 if all examples pass, and 1
+ if any examples fail. The failure exit code can be overridden using the
+ --failure-exit-code option.
+
+A passing spec with the default exit code
+
+Given a file named “ok_spec.rb” with:
+RSpec.describe "ok" do
+ it "passes" do
+ end
+end
+
+When I run rspec ok_spec.rb
+
+Then the exit status should be 0
+
+And the examples should all pass.
+
+A failing spec with the default exit code
+
+Given a file named “ko_spec.rb” with:
+RSpec.describe "KO" do
+ it "fails" do
+ raise "KO"
+ end
+end
+
+When I run rspec ko_spec.rb
+
+Then the exit status should be 1
+
+And the output should contain “1 example, 1 failure”.
+
+A nested failing spec with the default exit code
+
+Given a file named “nestedkospec.rb” with:
+RSpec.describe "KO" do
+ describe "nested" do
+ it "fails" do
+ raise "KO"
+ end
+ end
+end
+
+When I run rspec nested_ko_spec.rb
+
+Then the exit status should be 1
+
+And the output should contain “1 example, 1 failure”.
+
+Exit with 0 when no examples are run
+
+Given a file named “anoexamples_spec.rb” with:
+
+
+When I run rspec a_no_examples_spec.rb
+
+Then the exit status should be 0
+
+And the output should contain “0 examples”.
+
+A failing spec and --failure-exit-code is 42
+
+Given a file named “ko_spec.rb” with:
+RSpec.describe "KO" do
+ it "fails" do
+ raise "KO"
+ end
+end
+
+When I run rspec --failure-exit-code 42 ko_spec.rb
+
+Then the exit status should be 42
+
+And the output should contain “1 example, 1 failure”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/fail-fast/index.html b/docs/features/3-12/rspec-core/command-line/fail-fast/index.html
new file mode 100644
index 000000000..559a010f4
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/fail-fast/index.html
@@ -0,0 +1,56 @@
+
+
+
+
+--fail-fast option
+
+Use the --fail-fast option to tell RSpec to stop running the test suite on
+ the first failed test.
+
+You may add a parameter to tell RSpec to stop running the test suite after N
+ failed tests, for example: --fail-fast=3.
+
+You can also specify --no-fail-fast to turn it off (default behaviour).
+
+Background
+
+Given a file named “failfastspec.rb” with:
+RSpec.describe "fail fast" do
+ it "passing test" do; end
+ it "1st failing test" do
+ fail
+ end
+ it "2nd failing test" do
+ fail
+ end
+ it "3rd failing test" do
+ fail
+ end
+ it "4th failing test" do
+ fail
+ end
+ it "passing test" do; end
+end
+
+Using --fail-fast
+
+When I run rspec . --fail-fast
+
+Then the output should contain “.F”
+
+Then the output should not contain “.F.”.
+
+Using --fail-fast=3
+
+When I run rspec . --fail-fast=3
+
+Then the output should contain “.FFF”
+
+Then the output should not contain “.FFFF.”.
+
+Using --no-fail-fast
+
+When I run rspec . --no-fail-fast
+
+Then the output should contain “.FFFF.”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/format-option/index.html b/docs/features/3-12/rspec-core/command-line/format-option/index.html
new file mode 100644
index 000000000..de8405c0b
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/format-option/index.html
@@ -0,0 +1,86 @@
+
+
+
+
+--format option
+
+Use the --format option to tell RSpec how to format the output.
+
+RSpec ships with several formatters built in. By default, it uses the progress
+ formatter, which generates output like this:
+ ....F.....*.....
+
+A ‘.’ represents a passing example, ‘F’ is failing, and ‘*’ is pending.
+
+Use the documentation formatter to see the documentation strings passed to
+ describe, it, and their aliases:
+ $ rspec spec --format documentation
+
+You can also specify an output target ($stdout by default) with an --out
+ option immediately following the --format option:
+ $ rspec spec --format documentation --out rspec.txt
+
+Run rspec --help to see a listing of available formatters.
+
+Background
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "something" do
+ it "does something that passes" do
+ expect(5).to eq(5)
+ end
+
+ it "does something that fails" do
+ expect(5).to eq(4)
+ end
+
+ it "does something that is pending", :pending => true do
+ expect(5).to be < 3
+ end
+
+ it "does something that is skipped", :skip => true do
+ expect(5).to be < 3
+ end
+end
+
+Progress bar format (default)
+
+When I run rspec --format progress example_spec.rb
+
+Then the output should contain “.F**”.
+
+Documentation format
+
+When I run rspec example_spec.rb --format documentation
+
+Then the output should contain:
+something
+ does something that passes
+ does something that fails (FAILED - 1)
+ does something that is pending (PENDING: No reason given)
+ does something that is skipped (PENDING: No reason given)
+
+Documentation format saved to a file
+
+When I run rspec example_spec.rb --format documentation --out rspec.txt
+
+Then the file “rspec.txt” should contain:
+something
+ does something that passes
+ does something that fails (FAILED - 1)
+ does something that is pending (PENDING: No reason given)
+ does something that is skipped (PENDING: No reason given)
+
+Multiple formats and output targets
+
+When I run rspec example_spec.rb --format progress --format documentation --out rspec.txt
+
+Then the output should contain “.F**”
+
+And the file “rspec.txt” should contain:
+something
+ does something that passes
+ does something that fails (FAILED - 1)
+ does something that is pending (PENDING: No reason given)
+ does something that is skipped (PENDING: No reason given)
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/index.html b/docs/features/3-12/rspec-core/command-line/index.html
new file mode 100644
index 000000000..cfbe08df5
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/index.html
@@ -0,0 +1,29 @@
+
+
+
+
+Command line options
+
+The rspec command comes with several options you can use to customize RSpec’s
+behavior, including output formats, filtering examples, etc.
+
+For a full list of options, run the rspec command with the --help flag:
+$ rspec --help
+
+Run with ruby
+
+Generally, life is simpler if you just use the rspec command. If you must use
+the ruby command, however, you’ll need to require rspec/autorun. You can
+either pass a -rrspec/autorun CLI option when invoking ruby, or add a
+require 'rspec/autorun' to one or more of your spec files.
+
+It is conventional to put configuration in and require assorted support files
+from spec/spec_helper.rb. It is also conventional to require that file from
+the spec files using require 'spec_helper'. This works because RSpec
+implicitly adds the spec directory to the LOAD_PATH. It also adds lib, so
+your implementation files will be on the LOAD_PATH as well.
+
+If you’re using the ruby command, you’ll need to do this yourself (with the
+-I option). Putting these together, your command might be something like this:
+$ ruby -Ilib -Ispec -rrspec/autorun path/to/spec.rb
+
Topics
- `--example` option
- `--format` option
- `--tag` option
- `<file>:<line_number>` (line number appended to file path)
- `--failure-exit-code` option (exit status)
- `--order` option
- Creating a rake task
- Using the `--order` option
- Run with `ruby` command
- `--warnings` option (run with warnings enabled)
- `--init` option
- `--example-matches` option
- Bisect
- Using the `--only-failures` option
- `--fail-fast` option
- `--dry-run` option
- Randomization can be reproduced across test runs
- `--pattern` option
- `--require` option
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/init/index.html b/docs/features/3-12/rspec-core/command-line/init/index.html
new file mode 100644
index 000000000..27f0eab3d
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/init/index.html
@@ -0,0 +1,73 @@
+
+
+
+
+--init option
+
+Use the --init option on the command line to generate conventional files for
+ an RSpec project. It generates a .rspec and spec/spec_helper.rb with some
+ example settings to get you started.
+
+These settings treat the case where you run an individual spec file
+ differently, using the documentation formatter if no formatter has been
+ explicitly set.
+
+Generate .rspec
+
+When I run rspec --init
+
+Then the following files should exist:
+
+
+
+
+
+
+
+.rspec
+
+
+
+And the output should contain “create .rspec”.
+
+.rspec file already exists
+
+Given a file named “.rspec” with:
+--force-color
+
+When I run rspec --init
+
+Then the output should contain “exist .rspec”.
+
+Accept and use the recommended settings in spec_helper (which are initially commented out)
+
+Given I have a brand new project with no files
+
+And I have run rspec --init
+
+When I accept the recommended settings by removing =begin and =end from spec_helper.rb
+
+And I create “spec/addition_spec.rb” with the following content:
+RSpec.describe "Addition" do
+ it "works" do
+ expect(1 + 1).to eq(2)
+ end
+end
+
+And I create “spec/subtraction_spec.rb” with the following content:
+RSpec.describe "Subtraction" do
+ it "works" do
+ expect(1 - 1).to eq(0)
+ end
+end
+
+Then the output from rspec should not be in documentation format
+
+But the output from rspec spec/addition_spec.rb should be in documentation format
+
+But the output from rspec spec/addition_spec.rb --format progress should not be in documentation format
+
+And the output from rspec --pattern 'spec/*ction_spec.rb' should indicate it ran only the subtraction file
+
+And the output from rspec --exclude-pattern 'spec/*dition_spec.rb' should indicate it ran only the subtraction file.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/line-number-appended-to-path/index.html b/docs/features/3-12/rspec-core/command-line/line-number-appended-to-path/index.html
new file mode 100644
index 000000000..8ea4dc121
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/line-number-appended-to-path/index.html
@@ -0,0 +1,236 @@
+
+
+
+
+<file>:<line_number> (line number appended to file path)
+
+To run one or more examples or groups, you can append the line number to the
+ path, e.g.
+ $ rspec path/to/example_spec.rb:37
+
+Background
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "outer group" do
+
+ it "first example in outer group" do
+
+ end
+
+ it "second example in outer group" do
+
+ end
+
+ describe "nested group" do
+
+ it "example in nested group" do
+
+ end
+
+ end
+
+end
+
+And a file named “example2_spec.rb” with:
+RSpec.describe "yet another group" do
+ it "first example in second file" do
+ end
+ it "second example in second file" do
+ end
+end
+
+And a file named “onelinerspec.rb” with:
+RSpec.describe 9 do
+
+ it { is_expected.to be > 8 }
+
+ it { is_expected.to be < 10 }
+
+end
+
+Nested groups - outer group on declaration line
+
+When I run rspec example_spec.rb:1 --format doc
+
+Then the examples should all pass
+
+And the output should contain “second example in outer group”
+
+And the output should contain “first example in outer group”
+
+And the output should contain “example in nested group”.
+
+Nested groups - outer group inside block before example
+
+When I run rspec example_spec.rb:2 --format doc
+
+Then the examples should all pass
+
+And the output should contain “second example in outer group”
+
+And the output should contain “first example in outer group”
+
+And the output should contain “example in nested group”.
+
+Nested groups - inner group on declaration line
+
+When I run rspec example_spec.rb:11 --format doc
+
+Then the examples should all pass
+
+And the output should contain “example in nested group”
+
+And the output should not contain “second example in outer group”
+
+And the output should not contain “first example in outer group”.
+
+Nested groups - inner group inside block before example
+
+When I run rspec example_spec.rb:12 --format doc
+
+Then the examples should all pass
+
+And the output should contain “example in nested group”
+
+And the output should not contain “second example in outer group”
+
+And the output should not contain “first example in outer group”.
+
+Two examples - first example on declaration line
+
+When I run rspec example_spec.rb:3 --format doc
+
+Then the examples should all pass
+
+And the output should contain “first example in outer group”
+
+But the output should not contain “second example in outer group”
+
+And the output should not contain “example in nested group”.
+
+Two examples - first example inside block
+
+When I run rspec example_spec.rb:4 --format doc
+
+Then the examples should all pass
+
+And the output should contain “first example in outer group”
+
+But the output should not contain “second example in outer group”
+
+And the output should not contain “example in nested group”.
+
+Two examples - first example on end
+
+When I run rspec example_spec.rb:5 --format doc
+
+Then the examples should all pass
+
+And the output should contain “first example in outer group”
+
+But the output should not contain “second example in outer group”
+
+And the output should not contain “example in nested group”.
+
+Two examples - first example after end but before next example
+
+When I run rspec example_spec.rb:6 --format doc
+
+Then the examples should all pass
+
+And the output should contain “first example in outer group”
+
+But the output should not contain “second example in outer group”
+
+And the output should not contain “example in nested group”.
+
+Two examples - second example on declaration line
+
+When I run rspec example_spec.rb:7 --format doc
+
+Then the examples should all pass
+
+And the output should contain “second example in outer group”
+
+But the output should not contain “first example in outer group”
+
+And the output should not contain “example in nested group”.
+
+Two examples - second example inside block
+
+When I run rspec example_spec.rb:7 --format doc
+
+Then the examples should all pass
+
+And the output should contain “second example in outer group”
+
+But the output should not contain “first example in outer group”
+
+And the output should not contain “example in nested group”.
+
+Two examples - second example on end
+
+When I run rspec example_spec.rb:7 --format doc
+
+Then the examples should all pass
+
+And the output should contain “second example in outer group”
+
+But the output should not contain “first example in outer group”
+
+And the output should not contain “example in nested group”.
+
+Specified multiple times for different files
+
+When I run rspec example_spec.rb:7 example2_spec.rb:4 --format doc
+
+Then the examples should all pass
+
+And the output should contain “second example in outer group”
+
+And the output should contain “second example in second file”
+
+But the output should not contain “first example in outer group”
+
+And the output should not contain “nested group”
+
+And the output should not contain “first example in second file”.
+
+Specified multiple times for the same file with multiple arguments
+
+When I run rspec example_spec.rb:7 example_spec.rb:11 --format doc
+
+Then the examples should all pass
+
+And the output should contain “second example in outer group”
+
+And the output should contain “nested group”
+
+But the output should not contain “first example in outer group”
+
+And the output should not contain “second file”.
+
+Specified multiple times for the same file with a single argument
+
+When I run rspec example_spec.rb:7:11 --format doc
+
+Then the examples should all pass
+
+And the output should contain “second example in outer group”
+
+And the output should contain “nested group”
+
+But the output should not contain “first example in outer group”
+
+And the output should not contain “second file”.
+
+Matching one-liners
+
+When I run rspec one_liner_spec.rb:3 --format doc
+
+Then the examples should all pass
+
+Then the output should contain “is expected to be > 8”
+
+But the output should not contain “is expected to be < 10”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/only-failures/index.html b/docs/features/3-12/rspec-core/command-line/only-failures/index.html
new file mode 100644
index 000000000..4acab2ec6
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/only-failures/index.html
@@ -0,0 +1,141 @@
+
+
+
+
+Using the --only-failures option
+
+The --only-failures option filters what examples are run so that only those that failed the last time they ran are executed. To use this option, you first have to configure config.example_status_persistence_file_path, which RSpec will use to store the status of each example the last time it ran.
+
+There’s also a --next-failure option, which is shorthand for --only-failures --fail-fast --order defined. It allows you to repeatedly focus on just one of the currently failing examples, then move on to the next failure, etc.
+
+Either of these options can be combined with another a directory or file name; RSpec will run just the failures from the set of loaded examples.
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |c|
+ c.example_status_persistence_file_path = "examples.txt"
+end
+
+And a file named “.rspec” with:
+--require spec_helper
+--order random
+--format documentation
+
+And a file named “spec/array_spec.rb” with:
+RSpec.describe 'Array' do
+ it "checks for inclusion of 1" do
+ expect([1, 2]).to include(1)
+ end
+
+ it "checks for inclusion of 2" do
+ expect([1, 2]).to include(2)
+ end
+
+ it "checks for inclusion of 3" do
+ expect([1, 2]).to include(3) # failure
+ end
+end
+
+And a file named “spec/string_spec.rb” with:
+RSpec.describe 'String' do
+ it "checks for inclusion of 'foo'" do
+ expect("food").to include('foo')
+ end
+
+ it "checks for inclusion of 'bar'" do
+ expect("food").to include('bar') # failure
+ end
+
+ it "checks for inclusion of 'baz'" do
+ expect("bazzy").to include('baz')
+ end
+
+ it "checks for inclusion of 'foobar'" do
+ expect("food").to include('foobar') # failure
+ end
+end
+
+And a file named “spec/passing_spec.rb” with:
+puts "Loading passing_spec.rb"
+
+RSpec.describe "A passing spec" do
+ it "passes" do
+ expect(1).to eq(1)
+ end
+end
+
+And I have run rspec once, resulting in “8 examples, 3 failures”.
+
+Running rspec --only-failures loads only spec files with failures and runs only the failures
+
+When I run rspec --only-failures
+
+Then the output from “rspec –only-failures” should contain “3 examples, 3 failures”
+
+And the output from “rspec –only-failures” should not contain “Loading passing_spec.rb”.
+
+Combine --only-failures with a file name
+
+When I run rspec spec/array_spec.rb --only-failures
+
+Then the output should contain “1 example, 1 failure”
+
+When I run rspec spec/string_spec.rb --only-failures
+
+Then the output should contain “2 examples, 2 failures”.
+
+Use --next-failure to repeatedly run a single failure
+
+When I run rspec --next-failure
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should contain “checks for inclusion of 3”
+
+When I fix “spec/arrayspec.rb” by replacing “to include(3)” with “notto include(3)”
+
+And I run rspec --next-failure
+
+Then the output should contain “2 examples, 1 failure”
+
+And the output should contain “checks for inclusion of 3”
+
+And the output should contain “checks for inclusion of ‘bar’”
+
+When I fix “spec/stringspec.rb” by replacing “to include(‘bar’)” with “notto include(‘bar’)”
+
+And I run rspec --next-failure
+
+Then the output should contain “2 examples, 1 failure”
+
+And the output should contain “checks for inclusion of ‘bar’”
+
+And the output should contain “checks for inclusion of ‘foobar’”
+
+When I fix “spec/stringspec.rb” by replacing “to include(‘foobar’)” with “notto include(‘foobar’)”
+
+And I run rspec --next-failure
+
+Then the output should contain “1 example, 0 failures”
+
+And the output should contain “checks for inclusion of ‘foobar’”
+
+When I run rspec --next-failure
+
+Then the output should contain “All examples were filtered out”.
+
+Running rspec --only-failures with spec files that pass doesn’t run anything
+
+When I run rspec spec/passing_spec.rb --only-failures
+
+Then it should pass with “0 examples, 0 failures”.
+
+Clear error given when using --only-failures without configuring example_status_persistence_file_path
+
+Given I have not configured example_status_persistence_file_path
+
+When I run rspec --only-failures
+
+Then it should fail with “To use --only-failures, you must first set config.example_status_persistence_file_path.”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/order/index.html b/docs/features/3-12/rspec-core/command-line/order/index.html
new file mode 100644
index 000000000..1bf7efa35
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/order/index.html
@@ -0,0 +1,37 @@
+
+
+
+
+Using the --order option
+
+Use the --order option to tell RSpec how to order the files, groups, and
+examples. The available ordering schemes are defined and rand.
+
+defined is the default, which executes groups and examples in the order they
+are defined as the spec files are loaded, with the caveat that each group
+runs its examples before running its nested example groups, even if the
+nested groups are defined before the examples.
+
+Use rand to randomize the order of groups and examples within the groups.
+Nested groups are always run from top-level to bottom-level in order to avoid
+executing before(:context) and after(:context) hooks more than once, but the
+order of groups at each level is randomized.
+
+With rand you can also specify a seed.
+
+Use recently-modified to run the most recently modified files first. You can
+combine it with --only-failures to find the most recent failing specs. Note
+that recently-modified and rand are mutually exclusive.
+
+Example usage
+
+The defined option is only necessary when you have --order rand stored in a
+config file (e.g. .rspec) and you want to override it from the command line.
+
+--order defined
+--order rand
+--order rand:123
+--seed 123 # same as --order rand:123
+--order recently-modified
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/pattern-option/index.html b/docs/features/3-12/rspec-core/command-line/pattern-option/index.html
new file mode 100644
index 000000000..d99c39543
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/pattern-option/index.html
@@ -0,0 +1,55 @@
+
+
+
+
+--pattern option
+
+When you run RSpec without giving it specific file names, it determines which
+ files to load by applying a pattern to the provided directory arguments or
+ spec (if no directories are provided). By default, RSpec uses the following
+ pattern:
+ "**{,/*/**}/*_spec.rb"
+
+Use the --pattern option to declare a different pattern.
+
+Background
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.describe "two specs" do
+ it "passes" do
+ end
+
+ it "passes too" do
+ end
+end
+
+And a file named “spec/example_test.rb” with:
+RSpec.describe "one spec" do
+ it "passes" do
+ end
+end
+
+By default, RSpec runs matching spec files
+
+When I run rspec
+
+Then the output should contain “2 examples, 0 failures”.
+
+The --pattern flag makes RSpec run files matching the specified pattern and ignore the default pattern
+
+When I run rspec -P "**/*_test.rb"
+
+Then the output should contain “1 example, 0 failures”.
+
+The --pattern flag can be used to pass in multiple patterns, separated by commas
+
+When I run rspec -P "**/*_test.rb,**/*_spec.rb"
+
+Then the output should contain “3 examples, 0 failures”.
+
+The --pattern flag accepts shell style glob unions
+
+When I run rspec -P "**/*_{test,spec}.rb"
+
+Then the output should contain “3 examples, 0 failures”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/rake-task/index.html b/docs/features/3-12/rspec-core/command-line/rake-task/index.html
new file mode 100644
index 000000000..baa568ffc
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/rake-task/index.html
@@ -0,0 +1,157 @@
+
+
+
+
+Creating a rake task
+
+RSpec ships with a rake task with a number of useful options.
+
+We recommend you wrap this in a rescue clause so that you can
+ use your Rakefile in an environment where RSpec is unavailable
+ (for example on a production server). e.g:
+ begin
+ require 'rspec/core/rake_task'
+ RSpec::Core::RakeTask.new(:spec)
+ rescue LoadError
+ end
+
+Default options with passing spec (prints command and exit status is 0)
+
+Given a file named “Rakefile” with:
+
+begin
+ require 'rspec/core/rake_task'
+
+ RSpec::Core::RakeTask.new(:spec)
+
+ task :default => :spec
+rescue LoadError
+ # no rspec available
+end
+
+And a file named “spec/thing_spec.rb” with:
+RSpec.describe "something" do
+ it "does something" do
+ # pass
+ end
+end
+
+When I run rake
+
+Then the output should match:
+(ruby(\d\.\d(.\d)?)?|rbx) -I\S+ [\/\S]+\/exe\/rspec
+
+Then the exit status should be 0.
+
+Default options with failing spec (exit status is 1)
+
+Given a file named “Rakefile” with:
+begin
+ require 'rspec/core/rake_task'
+
+ RSpec::Core::RakeTask.new(:spec)
+
+ task :default => :spec
+rescue LoadError
+ # no rspec available
+end
+
+And a file named “spec/thing_spec.rb” with:
+RSpec.describe "something" do
+ it "does something" do
+ fail
+ end
+end
+
+When I run rake
+
+Then the exit status should be 1.
+
+Setting fail_on_error = false with failing spec (exit status is 0)
+
+Given a file named “Rakefile” with:
+begin
+ require 'rspec/core/rake_task'
+
+ RSpec::Core::RakeTask.new(:spec) do |t|
+ t.fail_on_error = false
+ end
+
+ task :default => :spec
+rescue LoadError
+ # no rspec available
+end
+
+And a file named “spec/thing_spec.rb” with:
+RSpec.describe "something" do
+ it "does something" do
+ fail
+ end
+end
+
+When I run rake
+
+Then the exit status should be 0.
+
+Passing arguments to the rspec command using rspec_opts
+
+Given a file named “Rakefile” with:
+begin
+ require 'rspec/core/rake_task'
+
+ RSpec::Core::RakeTask.new(:spec) do |t|
+ t.rspec_opts = "--tag fast"
+ end
+rescue LoadError
+ # no rspec available
+end
+
+And a file named “spec/thing_spec.rb” with:
+RSpec.describe "something" do
+ it "has a tag", :fast => true do
+ # pass
+ end
+
+ it "does not have a tag" do
+ fail
+ end
+end
+
+When I run rake spec
+
+Then the exit status should be 0
+
+Then the output should match:
+(ruby(\d\.\d(.\d)?)?|rbx) -I\S+ [\/\S]+\/exe\/rspec --pattern spec[\/\\*{,}]+_spec.rb --tag fast
+
+Passing rake task arguments to the rspec command via rspec_opts
+
+Given a file named “Rakefile” with:
+begin
+ require 'rspec/core/rake_task'
+
+ RSpec::Core::RakeTask.new(:spec, :tag) do |t, task_args|
+ t.rspec_opts = "--tag #{task_args[:tag]}"
+ end
+rescue LoadError
+ # no rspec available
+end
+
+And a file named “spec/thing_spec.rb” with:
+RSpec.describe "something" do
+ it "has a tag", :fast => true do
+ # pass
+ end
+
+ it "does not have a tag" do
+ fail
+ end
+end
+
+When I run rake spec[fast]
+
+Then the exit status should be 0
+
+Then the output should match:
+(ruby(\d\.\d(.\d)?)?|rbx) -I\S+ [\/\S]+\/exe\/rspec --pattern spec[\/\\*{,}]+_spec.rb --tag fast
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/randomization/index.html b/docs/features/3-12/rspec-core/command-line/randomization/index.html
new file mode 100644
index 000000000..9e76211fc
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/randomization/index.html
@@ -0,0 +1,68 @@
+
+
+
+
+Randomization can be reproduced across test runs
+
+In Ruby, randomness is seeded by calling srand and passing it the seed that
+ you want to use. By doing this, subsequent calls to rand, shuffle,
+ sample, etc. will all be randomized the same way given the same seed is
+ passed to srand.
+
+RSpec takes care not to seed randomization directly when taking action that
+ involves randomness (such as random ordering of examples).
+
+Since RSpec does not ever invoke srand, this means that you are free to
+ choose which, if any, mechanism is used to seed randomization.
+
+There is an example below of how to use RSpec’s seed for this purpose if you
+ wish to do so.
+
+If you would like to manage seeding randomization without any help from RSpec,
+ please keep the following things in mind:
+* The seed should never be hard-coded.
+
+ The first example below only does this to show that seeding randomization
+ with a seed other than the one used by RSpec will correctly seed
+ randomization.
+
+* Report the seed that was chosen.
+
+ The randomization that was used for a given test run can not be reproduced
+ if no one knows what seed was used to begin with.
+
+* Provide a mechanism to feed the seed into the tests.
+
+ Without this, the call to `srand` will have to be hard-coded any time it
+ is necessary to replicate a given test run's randomness.
+
+Background
+
+Given a file named “.rspec” with:
+--require spec_helper
+
+Given a file named “spec/random_spec.rb” with:
+RSpec.describe 'randomized example' do
+ it 'prints random numbers' do
+ puts 5.times.map { rand(99) }.join("-")
+ end
+end
+
+Specifying a seed using srand provides predictable randomization
+
+Given a file named “spec/spec_helper.rb” with:
+srand 123
+
+When I run rspec
+
+Then the output should contain “66-92-98-17-83”.
+
+Passing the RSpec seed to srand provides predictable randomization
+
+Given a file named “spec/spec_helper.rb” with:
+srand RSpec.configuration.seed
+
+When I run rspec --seed 123
+
+Then the output should contain “66-92-98-17-83”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/require-option/index.html b/docs/features/3-12/rspec-core/command-line/require-option/index.html
new file mode 100644
index 000000000..0ca503ff8
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/require-option/index.html
@@ -0,0 +1,52 @@
+
+
+
+
+--require option
+
+Use the --require (or -r) option to specify a file to require before
+ running specs.
+
+Using the --require option
+
+Given a file named “logging_formatter.rb” with:
+require "rspec/core/formatters/base_text_formatter"
+require 'delegate'
+
+class LoggingFormatter < RSpec::Core::Formatters::BaseTextFormatter
+ RSpec::Core::Formatters.register self, :dump_summary
+
+ def initialize(output)
+ super LoggingIO.new(output)
+ end
+
+ class LoggingIO < SimpleDelegator
+ def initialize(output)
+ @file = File.new('rspec.log', 'w')
+ super
+ end
+
+ def puts(*args)
+ [@file, __getobj__].each { |out| out.puts(*args) }
+ end
+
+ def close
+ @file.close
+ end
+ end
+end
+
+And a file named “spec/example_spec.rb” with:
+RSpec.describe "an embarrassing situation" do
+ it "happens to everyone" do
+ end
+end
+
+When I run rspec --require ./logging_formatter.rb --format LoggingFormatter
+
+Then the output should contain “1 example, 0 failures”
+
+And the file “rspec.log” should contain “1 example, 0 failures”
+
+And the exit status should be 0.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/ruby/index.html b/docs/features/3-12/rspec-core/command-line/ruby/index.html
new file mode 100644
index 000000000..c86fcd24f
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/ruby/index.html
@@ -0,0 +1,34 @@
+
+
+
+
+Run with ruby command
+
+You can use the ruby command to run specs. You just need to require
+ rspec/autorun.
+
+Generally speaking, you’re better off using the rspec command, which avoids
+ the complexity of rspec/autorun (e.g. no at_exit hook needed!), but some
+ tools only work with the ruby command.
+
+Require rspec/autorun from a spec file
+
+Given a file named “example_spec.rb” with:
+require 'rspec/autorun'
+
+RSpec.describe 1 do
+ it "is < 2" do
+ expect(1).to be < 2
+ end
+
+ it "has an intentional failure" do
+ expect(1).to be > 2
+ end
+end
+
+When I run ruby example_spec.rb
+
+Then the output should contain “2 examples, 1 failure”
+
+And the output should contain “expect(1).to be > 2”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/tag/index.html b/docs/features/3-12/rspec-core/command-line/tag/index.html
new file mode 100644
index 000000000..18c51ebfe
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/tag/index.html
@@ -0,0 +1,145 @@
+
+
+
+
+--tag option
+
+Use the --tag (or -t) option to run examples that match a specified tag.
+ The tag can be a simple name or a name:value pair.
+
+If a simple name is supplied, only examples with :name => true will run.
+ If a name:value pair is given, examples with name => value will run,
+ where value is always a string. In both cases, name is converted to a symbol.
+
+Tags can also be used to exclude examples by adding a ~ before the tag. For
+ example, ~tag will exclude all examples marked with :tag => true and
+ ~tag:value will exclude all examples marked with :tag => value.
+
+Filtering by tag uses a hash internally, which means that you can’t specify
+ multiple filters for the same key. For instance, if you try to exclude
+ :name => 'foo' and :name => 'bar', you will only end up excluding
+ :name => 'bar'.
+
+To be compatible with the Cucumber syntax, tags can optionally start with an
+ @ symbol, which will be ignored as part of the tag, e.g. --tag @focus is
+ treated the same as --tag focus and is expanded to :focus => true.
+
+Background
+
+Given a file named “tagged_spec.rb” with:
+RSpec.describe "group with tagged specs" do
+ it "example I'm working now", :focus => true do; end
+ it "special example with string", :type => 'special' do; end
+ it "special example with symbol", :type => :special do; end
+ it "slow example", :skip => true do; end
+ it "ordinary example", :speed => 'slow' do; end
+ it "untagged example" do; end
+end
+
+Filter examples with non-existent tag
+
+When I run rspec . --tag mytag
+
+Then the process should succeed even though no examples were run.
+
+Filter examples with a simple tag
+
+When I run rspec . --tag focus
+
+Then the output should contain “include {:focus=>true}”
+
+And the examples should all pass.
+
+Filter examples with a simple tag and @
+
+When I run rspec . --tag @focus
+
+Then the output should contain “include {:focus=>true}”
+
+Then the examples should all pass.
+
+Filter examples with a name:value tag
+
+When I run rspec . --tag type:special
+
+Then the output should contain:
+include {:type=>"special"}
+
+And the output should contain “2 examples”
+
+And the examples should all pass.
+
+Filter examples with a name:value tag and @
+
+When I run rspec . --tag @type:special
+
+Then the output should contain:
+include {:type=>"special"}
+
+And the examples should all pass.
+
+Exclude examples with a simple tag
+
+When I run rspec . --tag ~skip
+
+Then the output should contain “exclude {:skip=>true}”
+
+Then the examples should all pass.
+
+Exclude examples with a simple tag and @
+
+When I run rspec . --tag ~@skip
+
+Then the output should contain “exclude {:skip=>true}”
+
+Then the examples should all pass.
+
+Exclude examples with a name:value tag
+
+When I run rspec . --tag ~speed:slow
+
+Then the output should contain:
+exclude {:speed=>"slow"}
+
+Then the examples should all pass.
+
+Exclude examples with a name:value tag and @
+
+When I run rspec . --tag ~@speed:slow
+
+Then the output should contain:
+exclude {:speed=>"slow"}
+
+Then the examples should all pass.
+
+Filter examples with a simple tag, exclude examples with another tag
+
+When I run rspec . --tag focus --tag ~skip
+
+Then the output should contain “include {:focus=>true}”
+
+And the output should contain “exclude {:skip=>true}”
+
+And the examples should all pass.
+
+Exclude examples with multiple tags
+
+When I run rspec . --tag ~skip --tag ~speed:slow
+
+Then the output should contain one of the following:
+
+
+
+
+
+
+
+exclude {:skip=>true, :speed=>“slow”}
+
+
+exclude {:speed=>“slow”, :skip=>true}
+
+
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/command-line/warnings-option/index.html b/docs/features/3-12/rspec-core/command-line/warnings-option/index.html
new file mode 100644
index 000000000..b677dab42
--- /dev/null
+++ b/docs/features/3-12/rspec-core/command-line/warnings-option/index.html
@@ -0,0 +1,45 @@
+
+
+
+
+--warnings option (run with warnings enabled)
+
+Use the --warnings option to run specs with warnings enabled.
+
+Given a file named “example_spec.rb” with:
+RSpec.describe do
+ it 'generates warning' do
+ $undefined
+ end
+end
+
+When I run rspec --warnings example_spec.rb
+
+Then the output should contain “warning”.
+
+Given a file named “example_spec.rb” with:
+def foo(**kwargs)
+ kwargs
+end
+
+RSpec.describe do
+ it "should warn about keyword arguments with 'rspec -w'" do
+ expect(foo({a: 1})).to eq({a: 1})
+ end
+end
+
+When I run rspec -w example_spec.rb
+
+Then the output should contain “warning”.
+
+Given a file named “example_spec.rb” with:
+RSpec.describe do
+ it 'generates warning' do
+ $undefined
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should not contain “warning”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/alias-example-to/index.html b/docs/features/3-12/rspec-core/configuration/alias-example-to/index.html
new file mode 100644
index 000000000..e0a89d29e
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/alias-example-to/index.html
@@ -0,0 +1,67 @@
+
+
+
+
+Create example aliases
+
+Use config.alias_example_to to create new example group methods that define
+ examples with the configured metadata. You can also specify metadata using
+ only symbols.
+
+Use alias_example_to to define a custom example name
+
+Given a file named “aliasexampleto_spec.rb” with:
+RSpec.configure do |c|
+ c.alias_example_to :task
+end
+
+RSpec.describe "a task example group" do
+ task "does something" do
+ expect(5).to eq(5)
+ end
+end
+
+When I run rspec alias_example_to_spec.rb --format doc
+
+Then the output should contain “does something”
+
+And the examples should all pass.
+
+Use alias_example_to to define a pending example
+
+Given a file named “aliasexampletopendingspec.rb” with:
+RSpec.configure do |c|
+ c.alias_example_to :pit, :pending => "Pit alias used"
+end
+
+RSpec.describe "an example group" do
+ pit "does something later on" do
+ fail "not implemented yet"
+ end
+end
+
+When I run rspec alias_example_to_pending_spec.rb --format doc
+
+Then the output should contain “does something later on (PENDING: Pit alias used)”
+
+And the output should contain “0 failures”.
+
+Use symbols as metadata
+
+Given a file named “usesymbolsasmetadataspec.rb” with:
+RSpec.configure do |c|
+ c.alias_example_to :pit, :pending
+end
+
+RSpec.describe "an example group" do
+ pit "does something later on" do
+ fail "not implemented yet"
+ end
+end
+
+When I run rspec use_symbols_as_metadata_spec.rb --format doc
+
+Then the output should contain “does something later on (PENDING: No reason given)”
+
+And the output should contain “0 failures”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/backtrace-exclusion-patterns/index.html b/docs/features/3-12/rspec-core/configuration/backtrace-exclusion-patterns/index.html
new file mode 100644
index 000000000..7ac8f166a
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/backtrace-exclusion-patterns/index.html
@@ -0,0 +1,156 @@
+
+
+
+
+Excluding lines from the backtrace
+
+To reduce the noise when diagnosing failures, RSpec can exclude lines belonging to certain gems or matching given patterns.
+
+If you want to filter out backtrace lines belonging to specific gems, you can use config.filter_gems_from_backtrace like so:
+ config.filter_gems_from_backtrace "ignored_gem", "another_ignored_gem",
+
+For more control over which lines to ignore, you can use the the backtrace_exclusion_patterns option to either replace the default exclusion patterns, or append your own, e.g.
+ config.backtrace_exclusion_patterns = [/first pattern/, /second pattern/]
+ config.backtrace_exclusion_patterns << /another pattern/
+
+The default exclusion patterns are:
+ /\/lib\d*\/ruby\//,
+ /org\/jruby\//,
+ /bin\//,
+ /lib\/rspec\/(core|expectations|matchers|mocks)/
+
+Additionally, rspec can be run with the --backtrace option to skip backtrace cleaning entirely.
+
+Using default backtrace_exclusion_patterns
+
+Given a file named “spec/failing_spec.rb” with:
+RSpec.describe "2 + 2" do
+ it "is 5" do
+ expect(2+2).to eq(5)
+ end
+end
+
+When I run rspec
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should not contain “lib/rspec/expectations”.
+
+Replacing backtrace_exclusion_patterns
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.backtrace_exclusion_patterns = [
+ /spec_helper/
+ ]
+end
+
+And a file named “spec/example_spec.rb” with:
+require 'spec_helper'
+RSpec.describe "foo" do
+ it "returns baz" do
+ expect("foo").to eq("baz")
+ end
+end
+
+When I run rspec
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should contain “lib/rspec/expectations”.
+
+Appending to backtrace_exclusion_patterns
+
+Given a file named “spec/support/assert_baz.rb” with:
+require "support/really_assert_baz"
+
+def assert_baz(arg)
+ really_assert_baz(arg)
+end
+
+And a file named “spec/support/reallyassertbaz.rb” with:
+def really_assert_baz(arg)
+ expect(arg).to eq("baz")
+end
+
+And a file named “spec/example_spec.rb” with:
+require "support/assert_baz"
+RSpec.configure do |config|
+ config.backtrace_exclusion_patterns << /really/
+end
+
+RSpec.describe "bar" do
+ it "is baz" do
+ assert_baz("bar")
+ end
+end
+
+When I run rspec
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should contain “assert_baz”
+
+But the output should not contain “reallyassertbaz”
+
+And the output should not contain “lib/rspec/expectations”.
+
+Running rspec with --backtrace prints unfiltered backtraces
+
+Given a file named “spec/support/custom_helper.rb” with:
+def assert_baz(arg)
+ expect(arg).to eq("baz")
+end
+
+And a file named “spec/example_spec.rb” with:
+require "support/custom_helper"
+
+RSpec.configure do |config|
+ config.backtrace_exclusion_patterns << /custom_helper/
+end
+
+RSpec.describe "bar" do
+ it "is baz" do
+ assert_baz("bar")
+ end
+end
+
+When I run rspec --backtrace
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should contain “spec/support/customhelper.rb:2:in `assertbaz’”
+
+And the output should contain “lib/rspec/expectations”
+
+And the output should contain “lib/rspec/core”.
+
+Using filter_gems_from_backtrace to filter the named gem
+
+Given a vendored gem named “mygem” containing a file named “lib/mygem.rb” with:
+class MyGem
+ def self.do_amazing_things!
+ # intentional bug to trigger an exception
+ impossible_math = 10 / 0
+ "10 div 0 is: #{impossible_math}"
+ end
+end
+
+And a file named “spec/usemygem_spec.rb” with:
+require 'my_gem'
+
+RSpec.describe "Using my_gem" do
+ it 'does amazing things' do
+ expect(MyGem.do_amazing_things!).to include("10 div 0 is")
+ end
+end
+
+And a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.filter_gems_from_backtrace "my_gem"
+end
+
+Then the output from rspec should contain “vendor/mygem-1.2.3/lib/mygem.rb:4:in `doamazingthings!‘”
+
+But the output from rspec --require spec_helper should not contain “vendor/mygem-1.2.3/lib/mygem.rb:4:in `doamazingthings!’”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/color/index.html b/docs/features/3-12/rspec-core/configuration/color/index.html
new file mode 100644
index 000000000..7c4b2a35a
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/color/index.html
@@ -0,0 +1,26 @@
+
+
+
+
+Windows may require additional solutions to display color
+
+The output uses ANSI escape codes to show text in color. Windows
+ systems (shells) often don’t interpret those codes at all.
+
+If you’re on Windows and you see ANSI escape codes in the output
+ (something like [1m [31m ) and your text isn’t in different colors,
+ you may need to install a utility so that your Windows shell will
+ interpret those codes correctly and show the colors. Here are some
+ popular solutions:
+* [ANSICON](https://github.com/adoxa/ansicon): ANSICON runs 'on top of' cmd or powershell. This is a very
+ popular solution. You can set it up so that it's always used whenever
+ you use cmd or powershell, or use it only at specific times.
+
+* Alternatives to cmd.exe or powershell: [ConEmu](http://conemu.github.io/), [Console2](http://sourceforge.net/projects/console/),
+ [ConsoleZ](https://github.com/cbucher/console)
+
+* Unix-like shells and utilities: [cygwin](https://www.cygwin.com/), [babun](http://babun.github.io/index.html),
+ [MinGW](http://www.mingw.org/) (Minimalist GNU for Windows)
+
+To find out more, search for information about those solutions.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/custom-settings/index.html b/docs/features/3-12/rspec-core/configuration/custom-settings/index.html
new file mode 100644
index 000000000..7ac704d0c
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/custom-settings/index.html
@@ -0,0 +1,87 @@
+
+
+
+
+Custom settings
+
+Extensions like rspec-rails can add their own configuration settings.
+
+Simple setting (with defaults)
+
+Given a file named “additionalsettingspec.rb” with:
+RSpec.configure do |c|
+ c.add_setting :custom_setting
+end
+
+RSpec.describe "custom setting" do
+ it "is nil by default" do
+ expect(RSpec.configuration.custom_setting).to be_nil
+ end
+
+ it "is exposed as a predicate" do
+ expect(RSpec.configuration.custom_setting?).to be(false)
+ end
+
+ it "can be overridden" do
+ RSpec.configuration.custom_setting = true
+ expect(RSpec.configuration.custom_setting).to be(true)
+ expect(RSpec.configuration.custom_setting?).to be(true)
+ end
+end
+
+When I run rspec ./additional_setting_spec.rb
+
+Then the examples should all pass.
+
+Default to true
+
+Given a file named “additionalsettingspec.rb” with:
+RSpec.configure do |c|
+ c.add_setting :custom_setting, :default => true
+end
+
+RSpec.describe "custom setting" do
+ it "is true by default" do
+ expect(RSpec.configuration.custom_setting).to be(true)
+ end
+
+ it "is exposed as a predicate" do
+ expect(RSpec.configuration.custom_setting?).to be(true)
+ end
+
+ it "can be overridden" do
+ RSpec.configuration.custom_setting = false
+ expect(RSpec.configuration.custom_setting).to be(false)
+ expect(RSpec.configuration.custom_setting?).to be(false)
+ end
+end
+
+When I run rspec ./additional_setting_spec.rb
+
+Then the examples should all pass.
+
+Overridden in a subsequent RSpec.configure block
+
+Given a file named “additionalsettingspec.rb” with:
+RSpec.configure do |c|
+ c.add_setting :custom_setting
+end
+
+RSpec.configure do |c|
+ c.custom_setting = true
+end
+
+RSpec.describe "custom setting" do
+ it "returns the value set in the last configure block to get eval'd" do
+ expect(RSpec.configuration.custom_setting).to be(true)
+ end
+
+ it "is exposed as a predicate" do
+ expect(RSpec.configuration.custom_setting?).to be(true)
+ end
+end
+
+When I run rspec ./additional_setting_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/default-path/index.html b/docs/features/3-12/rspec-core/configuration/default-path/index.html
new file mode 100644
index 000000000..a8dae9687
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/default-path/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+Setting the default spec path
+
+You can just type rspec to run all specs that live in the spec directory.
+
+This is supported by a --default-path option, which is set to spec by
+ default. If you prefer to keep your specs in a different directory, or assign
+ an individual file to --default-path, you can do so on the command line or
+ in a configuration file (for example .rspec).
+
+NOTE: this option is not supported on RSpec.configuration, as it needs to be
+ set before spec files are loaded.
+
+Run rspec with default default-path (spec directory)
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.describe "an example" do
+ it "passes" do
+ end
+end
+
+When I run rspec
+
+Then the output should contain “1 example, 0 failures”.
+
+Run rspec with customized default-path
+
+Given a file named “.rspec” with:
+--default-path behavior
+
+Given a file named “behavior/example_spec.rb” with:
+RSpec.describe "an example" do
+ it "passes" do
+ end
+end
+
+When I run rspec
+
+Then the output should contain “1 example, 0 failures”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/deprecation-stream/index.html b/docs/features/3-12/rspec-core/configuration/deprecation-stream/index.html
new file mode 100644
index 000000000..d2a5120e2
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/deprecation-stream/index.html
@@ -0,0 +1,95 @@
+
+
+
+
+Custom deprecation stream
+
+Define a custom output stream for warning about deprecations (default
+ $stderr).
+ RSpec.configure do |c|
+ c.deprecation_stream = File.open('deprecations.txt', 'w')
+ end
+
+or
+ RSpec.configure { |c| c.deprecation_stream = 'deprecations.txt' }
+
+or pass --deprecation-out
+
+Background
+
+Given a file named “lib/foo.rb” with:
+class Foo
+ def bar
+ RSpec.deprecate "Foo#bar"
+ end
+end
+
+Default - print deprecations to $stderr
+
+Given a file named “spec/example_spec.rb” with:
+require "foo"
+
+RSpec.describe "calling a deprecated method" do
+ example { Foo.new.bar }
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the output should contain “Deprecation Warnings:\n\nFoo#bar is deprecated”.
+
+Configure using the path to a file
+
+Given a file named “spec/example_spec.rb” with:
+require "foo"
+
+RSpec.configure {|c| c.deprecation_stream = 'deprecations.txt' }
+
+RSpec.describe "calling a deprecated method" do
+ example { Foo.new.bar }
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the output should not contain “Deprecation Warnings:”
+
+But the output should contain “1 deprecation logged to deprecations.txt”
+
+And the file “deprecations.txt” should contain “Foo#bar is deprecated”.
+
+Configure using a File object
+
+Given a file named “spec/example_spec.rb” with:
+require "foo"
+
+RSpec.configure do |c|
+ c.deprecation_stream = File.open('deprecations.txt', 'w')
+end
+
+RSpec.describe "calling a deprecated method" do
+ example { Foo.new.bar }
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the output should not contain “Deprecation Warnings:”
+
+But the output should contain “1 deprecation logged to deprecations.txt”
+
+And the file “deprecations.txt” should contain “Foo#bar is deprecated”.
+
+Configure using the CLI --deprecation-out option
+
+Given a file named “spec/example_spec.rb” with:
+require "foo"
+RSpec.describe "calling a deprecated method" do
+ example { Foo.new.bar }
+end
+
+When I run rspec spec/example_spec.rb --deprecation-out deprecations.txt
+
+Then the output should not contain “Deprecation Warnings:”
+
+But the output should contain “1 deprecation logged to deprecations.txt”
+
+And the file “deprecations.txt” should contain “Foo#bar is deprecated”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/enable-global-dsl/index.html b/docs/features/3-12/rspec-core/configuration/enable-global-dsl/index.html
new file mode 100644
index 000000000..eb07a41cf
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/enable-global-dsl/index.html
@@ -0,0 +1,78 @@
+
+
+
+
+Global namespace DSL
+
+RSpec has a few top-level constructs that allow you to begin describing
+ behaviour:
+
+
+RSpec.describe: Define a named context for a group of examples.
+RSpec.shared_examples: Define a set of shared examples that can later be
+included in an example group.
+RSpec.shared_context: define some common context (using before, let,
+helper methods, etc) that can later be included in an example group.
+
+
+Historically, these constructs have been available directly off of the main
+ object, so that you could use these at the start of a file without the
+ RSpec. prefix. They have also been available off of any class or module so
+ that you can scope your examples within a particular constant namespace.
+
+RSpec 3 now provides an option to disable this global monkey patching:
+ config.expose_dsl_globally = false
+
+For backwards compatibility it defaults to true.
+
+By default RSpec allows the DSL to be used globally
+
+Given a file named “spec/example_spec.rb” with:
+describe "specs here" do
+ it "passes" do
+ end
+end
+
+When I run rspec
+
+Then the output should contain “1 example, 0 failures”.
+
+By default rspec/autorun allows the DSL to be used globally
+
+Given a file named “spec/example_spec.rb” with:
+require 'rspec/autorun'
+describe "specs here" do
+ it "passes" do
+ end
+end
+
+When I run ruby spec/example_spec.rb
+
+Then the output should contain “1 example, 0 failures”.
+
+When exposing globally is disabled the top level DSL no longer works
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.configure { |c| c.expose_dsl_globally = false }
+describe "specs here" do
+ it "passes" do
+ end
+end
+
+When I run rspec
+
+Then the output should contain “undefined method `describe’”.
+
+Regardless of setting
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.configure { |c| c.expose_dsl_globally = true }
+RSpec.describe "specs here" do
+ it "passes" do
+ end
+end
+
+When I run rspec
+
+Then the output should contain “1 example, 0 failures”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/error-exit-code/index.html b/docs/features/3-12/rspec-core/configuration/error-exit-code/index.html
new file mode 100644
index 000000000..345023640
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/error-exit-code/index.html
@@ -0,0 +1,55 @@
+
+
+
+
+Setting an error exit code
+
+Use the error_exit_code option to set a custom exit code when RSpec fails outside an example.
+ RSpec.configure { |c| c.error_exit_code = 42 }
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure { |c| c.error_exit_code = 42 }
+
+A erroring spec with the default exit code
+
+Given a file named “spec/typo_spec.rb” with:
+RSpec.escribe "something" do # intentional typo
+ it "works" do
+ true
+ end
+end
+
+When I run rspec spec/typo_spec.rb
+
+Then the exit status should be 1.
+
+A erroring spec with a custom exit code
+
+Given a file named “spec/typo_spec.rb” with:
+require 'spec_helper'
+RSpec.escribe "something" do # intentional typo
+ it "works" do
+ true
+ end
+end
+
+When I run rspec spec/typo_spec.rb
+
+And the exit status should be 42.
+
+Success running specs spec with a custom error exit code defined
+
+Given a file named “spec/example_spec.rb” with:
+require 'spec_helper'
+RSpec.describe "something" do
+ it "works" do
+ true
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the exit status should be 0.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/exclude-pattern/index.html b/docs/features/3-12/rspec-core/configuration/exclude-pattern/index.html
new file mode 100644
index 000000000..6fdb3c74e
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/exclude-pattern/index.html
@@ -0,0 +1,56 @@
+
+
+
+
+Using the --exclude_pattern option
+
+Use the --exclude-pattern option to tell RSpec to skip looking for specs in files
+ that match the pattern specified.
+
+Background
+
+Given a file named “spec/models/model_spec.rb” with:
+RSpec.describe "two specs here" do
+ it "passes" do
+ end
+
+ it "passes too" do
+ end
+end
+
+And a file named “spec/features/feature_spec.rb” with:
+RSpec.describe "only one spec" do
+ it "passes" do
+ end
+end
+
+By default, RSpec runs files that match "**/*_spec.rb"
+
+When I run rspec
+
+Then the output should contain “3 examples, 0 failures”.
+
+The --exclude-pattern flag makes RSpec skip matching files
+
+When I run rspec --exclude-pattern "**/models/*_spec.rb"
+
+Then the output should contain “1 example, 0 failures”.
+
+The --exclude-pattern flag can be used to pass in multiple patterns, separated by comma
+
+When I run rspec --exclude-pattern "**/models/*_spec.rb, **/features/*_spec.rb"
+
+Then the output should contain “0 examples, 0 failures”.
+
+The --exclude-pattern flag accepts shell style glob unions
+
+When I run rspec --exclude-pattern "**/{models,features}/*_spec.rb"
+
+Then the output should contain “0 examples, 0 failures”.
+
+The --exclude-pattern flag can be used with the --pattern flag
+
+When I run rspec --pattern "spec/**/*_spec.rb" --exclude-pattern "spec/models/*_spec.rb"
+
+Then the output should contain “1 example, 0 failures”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/fail-fast/index.html b/docs/features/3-12/rspec-core/configuration/fail-fast/index.html
new file mode 100644
index 000000000..b7f9f4020
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/fail-fast/index.html
@@ -0,0 +1,112 @@
+
+
+
+
+Setting the fail_fast option
+
+Use the fail_fast option to tell RSpec to abort the run after N failures:
+
+fail_fast with no failures (runs all examples)
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure {|c| c.fail_fast = 1}
+
+And a file named “spec/example_spec.rb” with:
+RSpec.describe "something" do
+ it "passes" do
+ end
+
+ it "passes too" do
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the examples should all pass.
+
+fail_fast with first example failing (only runs the one example)
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure {|c| c.fail_fast = 1}
+
+And a file named “spec/example_spec.rb” with:
+require "spec_helper"
+RSpec.describe "something" do
+ it "fails" do
+ fail
+ end
+
+ it "passes" do
+ end
+end
+
+When I run rspec spec/example_spec.rb -fd
+
+Then the output should contain “1 example, 1 failure”.
+
+fail_fast with multiple files, second example failing (only runs the first two examples)
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure {|c| c.fail_fast = 1}
+
+And a file named “spec/example1spec.rb” with:
+require "spec_helper"
+RSpec.describe "something" do
+ it "passes" do
+ end
+
+ it "fails" do
+ fail
+ end
+end
+
+RSpec.describe "something else" do
+ it "fails" do
+ fail
+ end
+end
+
+And a file named “spec/example2spec.rb” with:
+require "spec_helper"
+RSpec.describe "something" do
+ it "passes" do
+ end
+end
+
+RSpec.describe "something else" do
+ it "fails" do
+ fail
+ end
+end
+
+When I run rspec spec
+
+Then the output should contain “2 examples, 1 failure”.
+
+fail_fast 2 with 1st and 3rd examples failing (only runs the first 3 examples)
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure {|c| c.fail_fast = 2}
+
+And a file named “spec/example_spec.rb” with:
+require "spec_helper"
+RSpec.describe "something" do
+ it "fails once" do
+ fail
+ end
+
+ it "passes once" do
+ end
+
+ it "fails twice" do
+ fail
+ end
+
+ it "passes" do
+ end
+end
+
+When I run rspec spec/example_spec.rb -fd
+
+Then the output should contain “3 examples, 2 failures”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/fail-if-no-examples/index.html b/docs/features/3-12/rspec-core/configuration/fail-if-no-examples/index.html
new file mode 100644
index 000000000..22d0c2c26
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/fail-if-no-examples/index.html
@@ -0,0 +1,37 @@
+
+
+
+
+Setting the fail_if_no_examples option
+
+Use the fail_if_no_examples option to make RSpec exit with a failure status (by default 1) if there are no examples. Using this option, it is recommended to add a --require spec_helper option to .rspec file to ensure the fail_if_no_examples option is set even if no spec files are loaded.
+
+This option may be particularly useful when you happen to not run RSpec tests locally, but rely on CI to do this. This prevents from false positive builds, when you expected some RSpec examples to be run, but none were run. Such a situation may be caused by your misconfiguration or regression/major changes in RSpec.
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure { |c| c.fail_if_no_examples = true }
+
+Given a file named “.rspec” with:
+--require spec_helper
+
+Given a file named “spec/some.spec.rb” with:
+RSpec.describe 'something' do
+ it 'succeeds' do
+ true
+ end
+end
+
+Examples file name is not matched by RSpec pattern, thus there are no examples run
+
+When I run rspec
+
+Then it should fail with “0 examples, 0 failures”.
+
+Examples file name is matched by RSpec pattern, 1 example is run
+
+When I run rspec --pattern spec/**/*.spec.rb
+
+Then it should pass with “1 example, 0 failures”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/failure-exit-code/index.html b/docs/features/3-12/rspec-core/configuration/failure-exit-code/index.html
new file mode 100644
index 000000000..5991ccf54
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/failure-exit-code/index.html
@@ -0,0 +1,85 @@
+
+
+
+
+Setting a failure exit code
+
+Use the failure_exit_code option to set a custom exit code when RSpec fails.
+ RSpec.configure { |c| c.failure_exit_code = 42 }
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure { |c| c.failure_exit_code = 42 }
+
+A failing spec with the default exit code
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.describe "something" do
+ it "fails" do
+ fail
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the exit status should be 1.
+
+A failing spec with a custom exit code
+
+Given a file named “spec/example_spec.rb” with:
+require 'spec_helper'
+RSpec.describe "something" do
+ it "fails" do
+ fail
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the exit status should be 42.
+
+An error running specs spec with a custom exit code
+
+Given a file named “spec/typo_spec.rb” with:
+require 'spec_helper'
+RSpec.escribe "something" do # intentional typo
+ it "works" do
+ true
+ end
+end
+
+When I run rspec spec/typo_spec.rb
+
+Then the exit status should be 42.
+
+Success running specs spec with a custom exit code defined
+
+Given a file named “spec/example_spec.rb” with:
+require 'spec_helper'
+RSpec.describe "something" do
+ it "works" do
+ true
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the exit status should be 0.
+
+Exit with the default exit code when an at_exit hook is added upstream
+
+Given a file named “exitatspec.rb” with:
+require 'rspec/autorun'
+at_exit { exit(0) }
+
+RSpec.describe "exit 0 at_exit ignored" do
+ it "does not interfere with the default exit code" do
+ fail
+ end
+end
+
+When I run ruby exit_at_spec.rb
+
+Then the exit status should be 1.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/index.html b/docs/features/3-12/rspec-core/configuration/index.html
new file mode 100644
index 000000000..de247c58e
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Configuration
Topics
- Reading command line configuration options from files
- Windows may require additional solutions to display color
- Setting the `fail_fast` option
- Setting the `fail_if_no_examples` option
- Custom settings
- Create example aliases
- Setting the default spec path
- Using the `--pattern` option
- Using `run_all_when_everything_filtered`
- Overriding global ordering
- Profiling examples (`--profile`)
- Setting an error exit code
- Setting a failure exit code
- Setting the `--order` and/or `--seed`
- Using the `--exclude_pattern` option
- Global namespace DSL
- Custom deprecation stream
- Custom output stream
- Excluding lines from the backtrace
- Zero monkey patching mode
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/order-and-seed/index.html b/docs/features/3-12/rspec-core/configuration/order-and-seed/index.html
new file mode 100644
index 000000000..34372222b
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/order-and-seed/index.html
@@ -0,0 +1,10 @@
+
+
+
+
+Setting the --order and/or --seed
+
+You can set the order to run specs and specify a seed if you are running the
+ specs using the ‘random’ ordering. See the documentation on the --order
+ command line option for more on this.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/output-stream/index.html b/docs/features/3-12/rspec-core/configuration/output-stream/index.html
new file mode 100644
index 000000000..f031d66de
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/output-stream/index.html
@@ -0,0 +1,29 @@
+
+
+
+
+Custom output stream
+
+Define a custom output stream (default $stdout). Aliases: :output,
+ :out.
+ RSpec.configure { |c| c.output_stream = File.open('saved_output', 'w') }
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure { |c| c.output_stream = File.open('saved_output', 'w') }
+
+Redirecting output
+
+Given a file named “spec/example_spec.rb” with:
+require 'spec_helper'
+RSpec.describe "an example" do
+ it "passes" do
+ true
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the file “saved_output” should contain “1 example, 0 failures”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/overriding-global-ordering/index.html b/docs/features/3-12/rspec-core/configuration/overriding-global-ordering/index.html
new file mode 100644
index 000000000..4ce890767
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/overriding-global-ordering/index.html
@@ -0,0 +1,96 @@
+
+
+
+
+Overriding global ordering
+
+You can customize how RSpec orders examples and example groups. For an
+ individual group, you can control it by tagging it with :order metadata:
+* `:defined` runs the examples (and sub groups) in defined order
+* `:random` runs them in random order
+
+If you have more specialized needs, you can register your own ordering using
+ the register_ordering configuration option. If you register an ordering as
+ :global, it will be the global default, used by all groups that do not have
+ :order metadata (and by RSpec to order the top-level groups).
+
+Running a specific example group in order
+
+Given a file named “orderdependentspec.rb” with:
+RSpec.describe "examples only pass when they are run in order", :order => :defined do
+ before(:context) { @list = [] }
+
+ it "passes when run first" do
+ @list << 1
+ expect(@list).to eq([1])
+ end
+
+ it "passes when run second" do
+ @list << 2
+ expect(@list).to eq([1, 2])
+ end
+
+ it "passes when run third" do
+ @list << 3
+ expect(@list).to eq([1, 2, 3])
+ end
+end
+
+When I run rspec order_dependent_spec.rb --order random:1
+
+Then the examples should all pass.
+
+Registering a custom ordering
+
+Given a file named “registercustomordering_spec.rb” with:
+RSpec.configure do |rspec|
+ rspec.register_ordering(:reverse) do |items|
+ items.reverse
+ end
+end
+
+RSpec.describe "A group that must run in reverse order", :order => :reverse do
+ before(:context) { @list = [] }
+
+ it "passes when run second" do
+ @list << 2
+ expect(@list).to eq([1, 2])
+ end
+
+ it "passes when run first" do
+ @list << 1
+ expect(@list).to eq([1])
+ end
+end
+
+When I run rspec register_custom_ordering_spec.rb
+
+Then the examples should all pass.
+
+Using a custom global ordering
+
+Given a file named “registerglobalordering_spec.rb” with:
+RSpec.configure do |rspec|
+ rspec.register_ordering(:global) do |items|
+ items.reverse
+ end
+end
+
+RSpec.describe "A group without :order metadata" do
+ before(:context) { @list = [] }
+
+ it "passes when run second" do
+ @list << 2
+ expect(@list).to eq([1, 2])
+ end
+
+ it "passes when run first" do
+ @list << 1
+ expect(@list).to eq([1])
+ end
+end
+
+When I run rspec register_global_ordering_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/pattern/index.html b/docs/features/3-12/rspec-core/configuration/pattern/index.html
new file mode 100644
index 000000000..6123548e7
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/pattern/index.html
@@ -0,0 +1,63 @@
+
+
+
+
+Using the --pattern option
+
+Use the pattern option to configure RSpec to look for specs in files that match
+ a pattern instead of the default "**/*_spec.rb".
+ RSpec.configure { |c| c.pattern = '**/*.spec' }
+
+Rather than using require 'spec_helper' at the top of each spec file,
+ ensure that you have --require spec_helper in .rspec. That will always
+ load before the pattern is resolved. With the pattern thus configured,
+ only those spec files that match the pattern will then be loaded.
+
+Background
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.describe "two specs" do
+ it "passes" do
+ end
+
+ it "passes too" do
+ end
+end
+
+Override the default pattern in configuration
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.pattern = '**/*.spec'
+end
+
+And a file named “spec/one_example.spec” with:
+RSpec.describe "something" do
+ it "passes" do
+ end
+end
+
+When I run rspec -rspec_helper
+
+Then the output should contain “1 example, 0 failures”.
+
+Append to the default pattern in configuration
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.pattern += ',**/*.spec'
+end
+
+And a file named “spec/two_examples.spec” with:
+RSpec.describe "something" do
+ it "passes" do
+ end
+
+ it "passes again" do
+ end
+end
+
+When I run rspec -rspec_helper
+
+Then the output should contain “4 examples, 0 failures”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/profile/index.html b/docs/features/3-12/rspec-core/configuration/profile/index.html
new file mode 100644
index 000000000..b0a0ddcc5
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/profile/index.html
@@ -0,0 +1,334 @@
+
+
+
+
+Profiling examples (--profile)
+
+The --profile command line option (available from RSpec.configure as
+ #profile_examples), when set, will cause RSpec to dump out a list of your
+ slowest examples. By default, it prints the 10 slowest examples, but you can
+ set it to a different value to have it print more or fewer slow examples. If
+ --fail-fast option is used together with --profile and there is a failure,
+ slow examples are not shown.
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+
+
+And a file named “spec/example_spec.rb” with:
+require "spec_helper"
+
+RSpec.describe "something" do
+ it "sleeps for 0.1 seconds (example 1)" do
+ sleep 0.1
+ expect(1).to eq(1)
+ end
+
+ it "sleeps for 0 seconds (example 2)" do
+ expect(2).to eq(2)
+ end
+
+ it "sleeps for 0.15 seconds (example 3)" do
+ sleep 0.15
+ expect(3).to eq(3)
+ end
+
+ it "sleeps for 0.05 seconds (example 4)" do
+ sleep 0.05
+ expect(4).to eq(4)
+ end
+
+ it "sleeps for 0.05 seconds (example 5)" do
+ sleep 0.05
+ expect(5).to eq(5)
+ end
+
+ it "sleeps for 0.05 seconds (example 6)" do
+ sleep 0.05
+ expect(6).to eq(6)
+ end
+
+ it "sleeps for 0.05 seconds (example 7)" do
+ sleep 0.05
+ expect(7).to eq(7)
+ end
+
+ it "sleeps for 0.05 seconds (example 8)" do
+ sleep 0.05
+ expect(8).to eq(8)
+ end
+
+ it "sleeps for 0.05 seconds (example 9)" do
+ sleep 0.05
+ expect(9).to eq(9)
+ end
+
+ it "sleeps for 0.05 seconds (example 10)" do
+ sleep 0.05
+ expect(10).to eq(10)
+ end
+
+ it "sleeps for 0.05 seconds (example 11)" do
+ sleep 0.05
+ expect(11).to eq(11)
+ end
+end
+
+By default does not show profile
+
+When I run rspec spec
+
+Then the examples should all pass
+
+And the output should not contain “example 1”
+
+And the output should not contain “example 2”
+
+And the output should not contain “example 3”
+
+And the output should not contain “example 4”
+
+And the output should not contain “example 5”
+
+And the output should not contain “example 6”
+
+And the output should not contain “example 7”
+
+And the output should not contain “example 8”
+
+And the output should not contain “example 9”
+
+And the output should not contain “example 10”
+
+And the output should not contain “example 11”.
+
+Setting profile_examples to true shows 10 examples
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure { |c| c.profile_examples = true }
+
+When I run rspec spec
+
+Then the examples should all pass
+
+And the output should contain “Top 10 slowest examples”
+
+And the output should contain “example 1”
+
+And the output should not contain “example 2”
+
+And the output should contain “example 3”
+
+And the output should contain “example 4”
+
+And the output should contain “example 5”
+
+And the output should contain “example 6”
+
+And the output should contain “example 7”
+
+And the output should contain “example 8”
+
+And the output should contain “example 9”
+
+And the output should contain “example 10”
+
+And the output should contain “example 11”.
+
+Setting profile_examples to 2 shows 2 examples
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure { |c| c.profile_examples = 2 }
+
+When I run rspec spec
+
+Then the examples should all pass
+
+And the output should contain “Top 2 slowest examples”
+
+And the output should contain “example 1”
+
+And the output should not contain “example 2”
+
+And the output should contain “example 3”
+
+And the output should not contain “example 4”
+
+And the output should not contain “example 5”
+
+And the output should not contain “example 6”
+
+And the output should not contain “example 7”
+
+And the output should not contain “example 8”
+
+And the output should not contain “example 9”
+
+And the output should not contain “example 10”
+
+And the output should not contain “example 11”.
+
+Setting profile examples through CLI using --profile
+
+When I run rspec spec --profile 2
+
+Then the examples should all pass
+
+And the output should contain “Top 2 slowest examples”
+
+And the output should contain “example 1”
+
+And the output should not contain “example 2”
+
+And the output should contain “example 3”
+
+And the output should not contain “example 4”
+
+And the output should not contain “example 5”
+
+And the output should not contain “example 6”
+
+And the output should not contain “example 7”
+
+And the output should not contain “example 8”
+
+And the output should not contain “example 9”
+
+And the output should not contain “example 10”
+
+And the output should not contain “example 11”.
+
+Using --no-profile overrules config options
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure { |c| c.profile_examples = true }
+
+When I run rspec spec --no-profile
+
+Then the examples should all pass
+
+And the output should not contain “example 1”
+
+And the output should not contain “example 2”
+
+And the output should not contain “example 3”
+
+And the output should not contain “example 4”
+
+And the output should not contain “example 5”
+
+And the output should not contain “example 6”
+
+And the output should not contain “example 7”
+
+And the output should not contain “example 8”
+
+And the output should not contain “example 9”
+
+And the output should not contain “example 10”
+
+And the output should not contain “example 11”.
+
+Using --profile with --fail-fast shows slow examples if everything passes
+
+When I run rspec spec --fail-fast --profile
+
+Then the examples should all pass
+
+And the output should contain “Top 10 slowest examples”
+
+And the output should contain “example 1”
+
+And the output should not contain “example 2”
+
+And the output should contain “example 3”
+
+And the output should contain “example 4”
+
+And the output should contain “example 5”
+
+And the output should contain “example 6”
+
+And the output should contain “example 7”
+
+And the output should contain “example 8”
+
+And the output should contain “example 9”
+
+And the output should contain “example 10”
+
+And the output should contain “example 11”.
+
+Using --profile shows slow examples even in case of failures
+
+Given a file named “spec/example_spec.rb” with:
+require "spec_helper"
+
+RSpec.describe "something" do
+ it "sleeps for 0.1 seconds (example 1)" do
+ sleep 0.1
+ expect(1).to eq(1)
+ end
+
+ it "fails" do
+ fail
+ end
+end
+
+When I run rspec spec --profile
+
+Then the output should contain “2 examples, 1 failure”
+
+And the output should contain “Top 2 slowest examples”
+
+And the output should contain “example 1”.
+
+Using --profile with --fail-fast doesn’t show slow examples in case of failures
+
+Given a file named “spec/example_spec.rb” with:
+require "spec_helper"
+
+RSpec.describe "something" do
+ it "sleeps for 0.1 seconds (example 1)" do
+ sleep 0.1
+ expect(1).to eq(1)
+ end
+
+ it "fails" do
+ fail
+ end
+end
+
+When I run rspec spec --fail-fast --profile
+
+Then the output should not contain “Top 2 slowest examples”
+
+And the output should not contain “example 1”.
+
+Using --profile with slow before hooks includes hook execution time
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.describe "slow before context hook" do
+ before(:context) do
+ sleep 0.2
+ end
+
+ context "nested" do
+ it "example" do
+ expect(10).to eq(10)
+ end
+ end
+end
+
+RSpec.describe "slow example" do
+ it "slow example" do
+ sleep 0.1
+ expect(10).to eq(10)
+ end
+end
+
+When I run rspec spec --profile 1
+
+Then the output should report “slow before context hook” as the slowest example group.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/read-options-from-file/index.html b/docs/features/3-12/rspec-core/configuration/read-options-from-file/index.html
new file mode 100644
index 000000000..61b8cfe40
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/read-options-from-file/index.html
@@ -0,0 +1,104 @@
+
+
+
+
+Reading command line configuration options from files
+
+RSpec reads command line configuration options from several different files,
+ all conforming to a specific level of specificity. Options from a higher
+ specificity will override conflicting options from lower specificity files.
+
+The locations are:
+* **Global options:** First file from the following list (i.e. the user's
+ personal global options)
+
+ * `$XDG_CONFIG_HOME/rspec/options` ([XDG Base Directory
+ Specification](https://specifications.freedesktop.org/basedir-spec/latest/)
+ config)
+ * `~/.rspec`
+
+* **Project options:** `./.rspec` (i.e. in the project's root directory, usually
+ checked into the project)
+
+* **Local:** `./.rspec-local` (i.e. in the project's root directory, can be
+ gitignored)
+
+Options specified at the command-line has even higher specificity, as does
+ the SPEC_OPTS environment variable. That means that a command-line option
+ would overwrite a project-specific option, which overrides the global value
+ of that option.
+
+The default options files can all be ignored using the --options
+ command-line argument, which selects a custom file to load options from.
+
+Color set in .rspec
+
+Given a file named “.rspec” with:
+--force-color
+
+And a file named “spec/example_spec.rb” with:
+RSpec.describe "color_enabled?" do
+ context "when set with RSpec.configure" do
+ it "is true" do
+ expect(RSpec.configuration).to be_color_enabled
+ end
+ end
+end
+
+When I run rspec ./spec/example_spec.rb
+
+Then the examples should all pass.
+
+Custom options file
+
+Given a file named “my.options” with:
+--format documentation
+
+And a file named “spec/example_spec.rb” with:
+RSpec.describe "formatter set in custom options file" do
+ it "sets formatter" do
+ expect(RSpec.configuration.formatters.first).
+ to be_a(RSpec::Core::Formatters::DocumentationFormatter)
+ end
+end
+
+When I run rspec spec/example_spec.rb --options my.options
+
+Then the examples should all pass.
+
+RSpec ignores ./.rspec when custom options file is used
+
+Given a file named “my.options” with:
+--format documentation
+
+And a file named “.rspec” with:
+--no-color
+
+And a file named “spec/example_spec.rb” with:
+RSpec.describe "custom options file" do
+ it "causes .rspec to be ignored" do
+ expect(RSpec.configuration.color_mode).to eq(:automatic)
+ end
+end
+
+When I run rspec spec/example_spec.rb --options my.options
+
+Then the examples should all pass.
+
+Using ERB in .rspec
+
+Given a file named “.rspec” with:
+--format <%= true ? 'documentation' : 'progress' %>
+
+And a file named “spec/example_spec.rb” with:
+RSpec.describe "formatter" do
+ it "is set to documentation" do
+ expect(RSpec.configuration.formatters.first).
+ to be_an(RSpec::Core::Formatters::DocumentationFormatter)
+ end
+end
+
+When I run rspec ./spec/example_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/run-all-when-everything-filtered/index.html b/docs/features/3-12/rspec-core/configuration/run-all-when-everything-filtered/index.html
new file mode 100644
index 000000000..214e5553b
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/run-all-when-everything-filtered/index.html
@@ -0,0 +1,88 @@
+
+
+
+
+Using run_all_when_everything_filtered
+
+Note: this feature has been superseded by
+ filter_run_when_matching and will be
+ removed in a future version of RSpec.
+
+Use the run_all_when_everything_filtered option to tell RSpec to run all the
+ specs in the case where you try to run a filtered list of specs but no specs
+ match that filter. This works well when paired with an inclusion filter like
+ :focus => true, as it will run all the examples when none match the
+ inclusion filter.
+ RSpec.configure { |c| c.run_all_when_everything_filtered = true }
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure {|c| c.run_all_when_everything_filtered = true}
+
+By default, no specs are run if they are all filtered out by an inclusion tag
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.describe "examples" do
+ it "with no tag" do
+ end
+
+ it "with no tag as well" do
+ end
+end
+
+When I run rspec spec/example_spec.rb --tag some_tag
+
+Then the output should contain “0 examples, 0 failures”.
+
+Specs are still run if they are filtered out by an exclusion tag
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.describe "examples" do
+ it "with no tag" do
+ end
+
+ it "with no tag as well" do
+ end
+end
+
+When I run rspec spec/example_spec.rb --tag ~some_tag
+
+Then the output should contain “2 examples, 0 failures”.
+
+When the run_all_when_everything_filtered option is turned on, if there are any matches for the filtering tag, only those features are run
+
+Given a file named “spec/example_spec.rb” with:
+require "spec_helper"
+RSpec.describe "examples" do
+ it "with no tag", :some_tag => true do
+ end
+
+ it "with no tag as well" do
+ end
+end
+
+When I run rspec spec/example_spec.rb --tag some_tag
+
+Then the output should contain “1 example, 0 failures”
+
+And the output should contain “Run options: include {:some_tag=>true}”.
+
+When the run_all_when_everything_filtered option is turned on, all the specs are run when the tag has no matches
+
+Given a file named “spec/example_spec.rb” with:
+require "spec_helper"
+RSpec.describe "examples" do
+ it "with no tag" do
+ end
+
+ it "with no tag as well" do
+ end
+end
+
+When I run rspec spec/example_spec.rb --tag some_tag
+
+Then the output should contain “2 examples, 0 failures”
+
+And the output should contain “All examples were filtered out; ignoring {:some_tag=>true}”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/configuration/zero-monkey-patching-mode/index.html b/docs/features/3-12/rspec-core/configuration/zero-monkey-patching-mode/index.html
new file mode 100644
index 000000000..9be5f6272
--- /dev/null
+++ b/docs/features/3-12/rspec-core/configuration/zero-monkey-patching-mode/index.html
@@ -0,0 +1,122 @@
+
+
+
+
+Zero monkey patching mode
+
+Use the disable_monkey_patching! configuration option to
+ disable all monkey patching done by RSpec:
+
+
+- stops exposing DSL globally
+- disables
should and should_not syntax for rspec-expectations
+- disables
stub, should_receive, and should_not_receive syntax for
+rspec-mocks
+
+ RSpec.configure { |c| c.disable_monkey_patching! }
+
+Background
+
+Given a file named “spec/exampledescribespec.rb” with:
+require 'spec_helper'
+
+describe "specs here" do
+ it "passes" do
+ end
+end
+
+Given a file named “spec/exampleshouldspec.rb” with:
+require 'spec_helper'
+
+RSpec.describe "another specs here" do
+ it "passes with monkey patched expectations" do
+ x = 25
+ x.should eq 25
+ x.should_not be > 30
+ end
+
+ it "passes with monkey patched mocks" do
+ x = double("thing")
+ x.stub(:hello => [:world])
+ x.should_receive(:count).and_return(4)
+ x.should_not_receive(:all)
+ (x.hello * x.count).should eq([:world, :world, :world, :world])
+ end
+end
+
+Given a file named “spec/exampleexpectspec.rb” with:
+require 'spec_helper'
+
+RSpec.describe "specs here too" do
+ it "passes in zero monkey patching mode" do
+ x = double("thing")
+ allow(x).to receive(:hello).and_return([:world])
+ expect(x).to receive(:count).and_return(4)
+ expect(x).not_to receive(:all)
+ expect(x.hello * x.count).to eq([:world, :world, :world, :world])
+ end
+
+ it "passes in zero monkey patching mode" do
+ x = 25
+ expect(x).to eq(25)
+ expect(x).not_to be > 30
+ end
+end
+
+By default RSpec allows monkey patching
+
+Given a file named “spec/spec_helper.rb” with:
+# Empty spec_helper
+
+When I run rspec
+
+Then the examples should all pass.
+
+Monkey patched methods are undefined with disable_monkey_patching!
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.disable_monkey_patching!
+end
+
+When I run rspec spec/example_should_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+undefined method `should’
+
+
+unexpected message :stub
+
+
+
+When I run rspec spec/example_describe_spec.rb
+
+Then the output should contain “undefined method `describe’”.
+
+allow and expect syntax works with monkey patching
+
+Given a file named “spec/spec_helper.rb” with:
+# Empty spec_helper
+
+When I run rspec spec/example_expect_spec.rb
+
+Then the examples should all pass.
+
+allow and expect syntax works without monkey patching
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.disable_monkey_patching!
+end
+
+When I run rspec spec/example_expect_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/core-standalone/index.html b/docs/features/3-12/rspec-core/core-standalone/index.html
new file mode 100644
index 000000000..019d04fc2
--- /dev/null
+++ b/docs/features/3-12/rspec-core/core-standalone/index.html
@@ -0,0 +1,30 @@
+
+
+
+
+Use rspec-core without rspec-mocks or rspec-expectations
+
+It is most common to use rspec-core with rspec-mocks and rspec-expectations,
+ and rspec-core will take care of loading those libraries automatically if
+ available, but rspec-core can be used just fine without either of those
+ gems installed.
+
+Use only rspec-core when only it is installed
+
+Given only rspec-core is installed
+
+And a file named “coreonlyspec.rb” with:
+RSpec.describe "Only rspec-core is available" do
+ it "it fails when an rspec-mocks API is used" do
+ dbl = double("MyDouble")
+ end
+
+ it "it fails when an rspec-expectations API is used" do
+ expect(1).to eq(1)
+ end
+end
+
+When I run rspec core_only_spec.rb
+
+Then the output should contain “2 examples, 2 failures”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/example-groups/aliasing/index.html b/docs/features/3-12/rspec-core/example-groups/aliasing/index.html
new file mode 100644
index 000000000..f9865b418
--- /dev/null
+++ b/docs/features/3-12/rspec-core/example-groups/aliasing/index.html
@@ -0,0 +1,50 @@
+
+
+
+
+Aliasing
+
+describe and context are the default aliases for example_group. You can
+ define your own aliases for example_group and give those custom aliases
+ default metadata.
+
+RSpec provides a few built-in aliases:
+* `xdescribe` and `xcontext` add `:skip` metadata to the example group in
+ order to temporarily disable the examples.
+* `fdescribe` and `fcontext` add `:focus` metadata to the example group in
+ order to make it easy to temporarily focus the example group (when
+ combined with `config.filter_run :focus`.)
+
+Custom example group aliases with metadata
+
+Given a file named “nestedexamplegroupaliasesspec.rb” with:
+RSpec.configure do |c|
+ c.alias_example_group_to :detail, :detailed => true
+end
+
+RSpec.detail "a detail" do
+ it "can do some less important stuff" do
+ end
+end
+
+RSpec.describe "a thing" do
+ describe "in broad strokes" do
+ it "can do things" do
+ end
+ end
+
+ detail "something less important" do
+ it "can do an unimportant thing" do
+ end
+ end
+end
+
+When I run rspec nested_example_group_aliases_spec.rb --tag detailed -fdoc
+
+Then the output should contain:
+a detail
+ can do some less important stuff
+
+a thing
+ something less important
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/example-groups/basic-structure/index.html b/docs/features/3-12/rspec-core/example-groups/basic-structure/index.html
new file mode 100644
index 000000000..0fd99776d
--- /dev/null
+++ b/docs/features/3-12/rspec-core/example-groups/basic-structure/index.html
@@ -0,0 +1,58 @@
+
+
+
+
+The basic structure (describe/it)
+
+RSpec is a DSL for creating executable examples of how code is expected to
+ behave, organized in groups. It uses the words “describe” and “it” so we can
+ express concepts like a conversation:
+ "Describe an account when it is first opened."
+ "It has a balance of zero."
+
+The describe method creates an example group. Within the block passed to
+ describe you can declare nested groups using the describe or context
+ methods, or you can declare examples using the it or specify methods.
+
+Under the hood, an example group is a class in which the block passed to
+ describe or context is evaluated. The blocks passed to it are evaluated
+ in the context of an instance of that class.
+
+One group, one example
+
+Given a file named “sample_spec.rb” with:
+RSpec.describe "something" do
+ it "does something" do
+ end
+end
+
+When I run rspec sample_spec.rb -fdoc
+
+Then the output should contain:
+something
+ does something
+
+Nested example groups (using context)
+
+Given a file named “nestedexamplegroups_spec.rb” with:
+RSpec.describe "something" do
+ context "in one context" do
+ it "does one thing" do
+ end
+ end
+
+ context "in another context" do
+ it "does another thing" do
+ end
+ end
+end
+
+When I run rspec nested_example_groups_spec.rb -fdoc
+
+Then the output should contain:
+something
+ in one context
+ does one thing
+ in another context
+ does another thing
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/example-groups/index.html b/docs/features/3-12/rspec-core/example-groups/index.html
new file mode 100644
index 000000000..c6d1d91f4
--- /dev/null
+++ b/docs/features/3-12/rspec-core/example-groups/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Example groups
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/example-groups/shared-context/index.html b/docs/features/3-12/rspec-core/example-groups/shared-context/index.html
new file mode 100644
index 000000000..a30d07b5f
--- /dev/null
+++ b/docs/features/3-12/rspec-core/example-groups/shared-context/index.html
@@ -0,0 +1,150 @@
+
+
+
+
+Using shared_context
+
+Use shared_context to define a block that will be evaluated in the context of example groups either locally, using include_context in an example group, or globally using config.include_context.
+
+When implicitly including shared contexts via matching metadata, the normal way is to define matching metadata on an example group, in which case the context is included in the entire group. However, you also have the option to include it in an individual example instead. RSpec treats every example as having a singleton example group (analogous to Ruby’s singleton classes) containing just the one example.
+
+Background
+
+Given a file named “shared_stuff.rb” with:
+RSpec.configure do |rspec|
+ # This config option will be enabled by default on RSpec 4,
+ # but for reasons of backwards compatibility, you have to
+ # set it on RSpec 3.
+ #
+ # It causes the host group and examples to inherit metadata
+ # from the shared context.
+ rspec.shared_context_metadata_behavior = :apply_to_host_groups
+end
+
+RSpec.shared_context "shared stuff", :shared_context => :metadata do
+ before { @some_var = :some_value }
+ def shared_method
+ "it works"
+ end
+ let(:shared_let) { {'arbitrary' => 'object'} }
+ subject do
+ 'this is the subject'
+ end
+end
+
+RSpec.configure do |rspec|
+ rspec.include_context "shared stuff", :include_shared => true
+end
+
+Declare a shared context and include it with include_context
+
+Given a file named “sharedcontextexample.rb” with:
+require "./shared_stuff.rb"
+
+RSpec.describe "group that includes a shared context using 'include_context'" do
+ include_context "shared stuff"
+
+ it "has access to methods defined in shared context" do
+ expect(shared_method).to eq("it works")
+ end
+
+ it "has access to methods defined with let in shared context" do
+ expect(shared_let['arbitrary']).to eq('object')
+ end
+
+ it "runs the before hooks defined in the shared context" do
+ expect(@some_var).to be(:some_value)
+ end
+
+ it "accesses the subject defined in the shared context" do
+ expect(subject).to eq('this is the subject')
+ end
+
+ group = self
+
+ it "inherits metadata from the included context" do |ex|
+ expect(group.metadata).to include(:shared_context => :metadata)
+ expect(ex.metadata).to include(:shared_context => :metadata)
+ end
+end
+
+When I run rspec shared_context_example.rb
+
+Then the examples should all pass.
+
+Declare a shared context, include it with include_context and extend it with an additional block
+
+Given a file named “sharedcontextexample.rb” with:
+require "./shared_stuff.rb"
+
+RSpec.describe "including shared context using 'include_context' and a block" do
+ include_context "shared stuff" do
+ let(:shared_let) { {'in_a' => 'block'} }
+ end
+
+ it "evaluates the block in the shared context" do
+ expect(shared_let['in_a']).to eq('block')
+ end
+end
+
+When I run rspec shared_context_example.rb
+
+Then the examples should all pass.
+
+Declare a shared context and include it with metadata
+
+Given a file named “sharedcontextexample.rb” with:
+require "./shared_stuff.rb"
+
+RSpec.describe "group that includes a shared context using metadata", :include_shared => true do
+ it "has access to methods defined in shared context" do
+ expect(shared_method).to eq("it works")
+ end
+
+ it "has access to methods defined with let in shared context" do
+ expect(shared_let['arbitrary']).to eq('object')
+ end
+
+ it "runs the before hooks defined in the shared context" do
+ expect(@some_var).to be(:some_value)
+ end
+
+ it "accesses the subject defined in the shared context" do
+ expect(subject).to eq('this is the subject')
+ end
+
+ group = self
+
+ it "inherits metadata from the included context" do |ex|
+ expect(group.metadata).to include(:shared_context => :metadata)
+ expect(ex.metadata).to include(:shared_context => :metadata)
+ end
+end
+
+When I run rspec shared_context_example.rb
+
+Then the examples should all pass.
+
+Declare a shared context and include it with metadata of an individual example
+
+Given a file named “sharedcontextexample.rb” with:
+require "./shared_stuff.rb"
+
+RSpec.describe "group that does not include the shared context" do
+ it "does not have access to shared methods normally" do
+ expect(self).not_to respond_to(:shared_method)
+ end
+
+ it "has access to shared methods from examples with matching metadata", :include_shared => true do
+ expect(shared_method).to eq("it works")
+ end
+
+ it "inherits metadata from the included context due to the matching metadata", :include_shared => true do |ex|
+ expect(ex.metadata).to include(:shared_context => :metadata)
+ end
+end
+
+When I run rspec shared_context_example.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/example-groups/shared-examples/index.html b/docs/features/3-12/rspec-core/example-groups/shared-examples/index.html
new file mode 100644
index 000000000..eea4630b3
--- /dev/null
+++ b/docs/features/3-12/rspec-core/example-groups/shared-examples/index.html
@@ -0,0 +1,328 @@
+
+
+
+
+Using shared examples
+
+Shared examples let you describe behaviour of classes or modules. When declared,
+ a shared group’s content is stored. It is only realized in the context of
+ another example group, which provides any context the shared group needs to
+ run.
+
+A shared group is included in another group using any of:
+ include_examples "name" # include the examples in the current context
+ it_behaves_like "name" # include the examples in a nested context
+ it_should_behave_like "name" # include the examples in a nested context
+ matching metadata # include the examples in the current context
+
+WARNING: Files containing shared groups must be loaded before the files that
+ use them. While there are conventions to handle this, RSpec does not do
+ anything special (like autoload). Doing so would require a strict naming
+ convention for files that would break existing suites.
+
+WARNING: When you include parameterized examples in the current context multiple
+ times, you may override previous method definitions and last declaration wins.
+ So if you have this kind of shared example (or shared context)
+ RSpec.shared_examples "some example" do |parameter|
+ \# Same behavior is triggered also with either `def something; 'some value'; end`
+ \# or `define_method(:something) { 'some value' }`
+ let(:something) { parameter }
+ it "uses the given parameter" do
+ expect(something).to eq(parameter)
+ end
+ end
+
+ RSpec.describe SomeClass do
+ include_examples "some example", "parameter1"
+ include_examples "some example", "parameter2"
+ end
+
+You’re actually doing this (notice that first example will fail):
+ RSpec.describe SomeClass do
+ \# Reordered code for better understanding of what is happening
+ let(:something) { "parameter1" }
+ let(:something) { "parameter2" }
+
+ it "uses the given parameter" do
+ \# This example will fail because last let "wins"
+ expect(something).to eq("parameter1")
+ end
+
+ it "uses the given parameter" do
+ expect(something).to eq("parameter2")
+ end
+ end
+
+To prevent this kind of subtle error a warning is emitted if you declare multiple
+ methods with the same name in the same context. Should you get this warning
+ the simplest solution is to replace include_examples with it_behaves_like, in this
+ way method overriding is avoided because of the nested context created by it_behaves_like
+
+Conventions:
+
+
+
+
+The simplest approach is to require files with shared examples explicitly
+ from the files that use them. Keep in mind that RSpec adds the spec
+ directory to the LOAD_PATH, so you can say require
+ 'shared_examples_for_widgets' to require a file at
+ #{PROJECT_ROOT}/spec/shared_examples_for_widgets.rb.
+One convention is to put files containing shared examples in spec/support/
+ and require files in that directory from spec/spec_helper.rb:
+ Dir["./spec/support/**/*.rb"].sort.each { |f| require f }
+
+Historically, this was included in the generated spec/spec_helper.rb file in
+ rspec-rails. However, in order to keep your test suite boot time down,
+ it’s a good idea to not autorequire all files in a directory like this.
+ When running only one spec file, loading unneeded dependencies or performing
+ unneeded setup can have a significant, noticeable effect on how long it takes
+ before the first example runs.
+When all of the groups that include the shared group reside in the same file,
+ just declare the shared group in that file.
+
+
+Shared examples group included in two groups in one file
+
+Given a file named “collection_spec.rb” with:
+require "set"
+
+RSpec.shared_examples "a collection" do
+ let(:collection) { described_class.new([7, 2, 4]) }
+
+ context "initialized with 3 items" do
+ it "says it has three items" do
+ expect(collection.size).to eq(3)
+ end
+ end
+
+ describe "#include?" do
+ context "with an item that is in the collection" do
+ it "returns true" do
+ expect(collection.include?(7)).to be(true)
+ end
+ end
+
+ context "with an item that is not in the collection" do
+ it "returns false" do
+ expect(collection.include?(9)).to be(false)
+ end
+ end
+ end
+end
+
+RSpec.describe Array do
+ it_behaves_like "a collection"
+end
+
+RSpec.describe Set do
+ it_behaves_like "a collection"
+end
+
+When I run rspec collection_spec.rb --format documentation
+
+Then the examples should all pass
+
+And the output should contain:
+Array
+ behaves like a collection
+ initialized with 3 items
+ says it has three items
+ #include?
+ with an item that is in the collection
+ returns true
+ with an item that is not in the collection
+ returns false
+
+Set
+ behaves like a collection
+ initialized with 3 items
+ says it has three items
+ #include?
+ with an item that is in the collection
+ returns true
+ with an item that is not in the collection
+ returns false
+
+Providing context to a shared group using a block
+
+Given a file named “sharedexamplegroup_spec.rb” with:
+require "set"
+
+RSpec.shared_examples "a collection object" do
+ describe "<<" do
+ it "adds objects to the end of the collection" do
+ collection << 1
+ collection << 2
+ expect(collection.to_a).to match_array([1, 2])
+ end
+ end
+end
+
+RSpec.describe Array do
+ it_behaves_like "a collection object" do
+ let(:collection) { Array.new }
+ end
+end
+
+RSpec.describe Set do
+ it_behaves_like "a collection object" do
+ let(:collection) { Set.new }
+ end
+end
+
+When I run rspec shared_example_group_spec.rb --format documentation
+
+Then the examples should all pass
+
+And the output should contain:
+Array
+ behaves like a collection object
+ <<
+ adds objects to the end of the collection
+
+Set
+ behaves like a collection object
+ <<
+ adds objects to the end of the collection
+
+Passing parameters to a shared example group
+
+Given a file named “sharedexamplegroupparamsspec.rb” with:
+RSpec.shared_examples "a measurable object" do |measurement, measurement_methods|
+ measurement_methods.each do |measurement_method|
+ it "should return #{measurement} from ##{measurement_method}" do
+ expect(subject.send(measurement_method)).to eq(measurement)
+ end
+ end
+end
+
+RSpec.describe Array, "with 3 items" do
+ subject { [1, 2, 3] }
+ it_should_behave_like "a measurable object", 3, [:size, :length]
+end
+
+RSpec.describe String, "of 6 characters" do
+ subject { "FooBar" }
+ it_should_behave_like "a measurable object", 6, [:size, :length]
+end
+
+When I run rspec shared_example_group_params_spec.rb --format documentation
+
+Then the examples should all pass
+
+And the output should contain:
+Array with 3 items
+ it should behave like a measurable object
+ should return 3 from #size
+ should return 3 from #length
+
+String of 6 characters
+ it should behave like a measurable object
+ should return 6 from #size
+ should return 6 from #length
+
+Aliasing it_should_behave_like to it_has_behavior
+
+Given a file named “sharedexamplegroup_spec.rb” with:
+RSpec.configure do |c|
+ c.alias_it_should_behave_like_to :it_has_behavior, 'has behavior:'
+end
+
+RSpec.shared_examples 'sortability' do
+ it 'responds to <=>' do
+ expect(sortable).to respond_to(:<=>)
+ end
+end
+
+RSpec.describe String do
+ it_has_behavior 'sortability' do
+ let(:sortable) { 'sample string' }
+ end
+end
+
+When I run rspec shared_example_group_spec.rb --format documentation
+
+Then the examples should all pass
+
+And the output should contain:
+String
+ has behavior: sortability
+ responds to <=>
+
+Sharing metadata automatically includes shared example groups
+
+Given a file named “sharedexamplemetadata_spec.rb” with:
+RSpec.shared_examples "shared stuff", :a => :b do
+ it 'runs wherever the metadata is shared' do
+ end
+end
+
+RSpec.describe String, :a => :b do
+end
+
+When I run rspec shared_example_metadata_spec.rb
+
+Then the output should contain:
+1 example, 0 failures
+
+Shared examples are nestable by context
+
+Given a file named “contextspecificexamples_spec.rb” with:
+RSpec.describe "shared examples" do
+ context "per context" do
+
+ shared_examples "shared examples are nestable" do
+ specify { expect(true).to eq true }
+ end
+
+ it_behaves_like "shared examples are nestable"
+ end
+end
+
+When I run rspec context_specific_examples_spec.rb
+
+Then the output should contain:
+1 example, 0 failures
+
+Shared examples are accessible from offspring contexts
+
+Given a file named “contextspecificexamples_spec.rb” with:
+RSpec.describe "shared examples" do
+ shared_examples "shared examples are nestable" do
+ specify { expect(true).to eq true }
+ end
+
+ context "per context" do
+ it_behaves_like "shared examples are nestable"
+ end
+end
+
+When I run rspec context_specific_examples_spec.rb
+
+Then the output should contain:
+1 example, 0 failures
+
+And the output should not contain:
+Accessing shared_examples defined across contexts is deprecated
+
+Shared examples are isolated per context
+
+Given a file named “isolatedsharedexamples_spec.rb” with:
+RSpec.describe "shared examples" do
+ context do
+ shared_examples "shared examples are isolated" do
+ specify { expect(true).to eq true }
+ end
+ end
+
+ context do
+ it_behaves_like "shared examples are isolated"
+ end
+end
+
+When I run rspec isolated_shared_examples_spec.rb
+
+Then the output should contain:
+Could not find shared examples \"shared examples are isolated\"
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/expectation-framework-integration/aggregating-failures/index.html b/docs/features/3-12/rspec-core/expectation-framework-integration/aggregating-failures/index.html
new file mode 100644
index 000000000..13ceee3f1
--- /dev/null
+++ b/docs/features/3-12/rspec-core/expectation-framework-integration/aggregating-failures/index.html
@@ -0,0 +1,587 @@
+
+
+
+
+Aggregating Failures
+
+RSpec::Expectations provides aggregate_failures, an API that allows you to group a set of expectations and see all the failures at once, rather than it aborting on the first failure. RSpec::Core improves on this feature in a couple of ways:
+* RSpec::Core provides much better failure output, adding code snippets and backtraces to the sub-failures, just like it does for any normal failure.
+* RSpec::Core provides [metadata](../metadata/user-defined-metadata) integration for this feature. Each example that is tagged with `:aggregate_failures` will be wrapped in an `aggregate_failures` block. You can also use `config.define_derived_metadata` to apply this to every example automatically.
+
+The metadata form is quite convenient, but may not work well for end-to-end tests that have multiple distinct steps. For example, consider a spec for an HTTP client workflow that (1) makes a request, (2) expects a redirect, (3) follows the redirect, and (4) expects a particular response. You probably want the expect(response.status).to be_between(300, 399) expectation to immediately abort if it fails, because you can’t perform the next step (following the redirect) if that is not satisfied. For these situations, we encourage you to use the aggregate_failures block form to wrap each set of expectations that represents a distinct step in the test workflow.
+
+Background
+
+Given a file named “lib/client.rb” with:
+Response = Struct.new(:status, :headers, :body)
+
+class Client
+ def self.make_request(url='/')
+ Response.new(404, { "Content-Type" => "text/plain" }, "Not Found")
+ end
+end
+
+Use aggregate_failures block form
+
+Given a file named “spec/useblockform_spec.rb” with:
+require 'client'
+
+RSpec.describe Client do
+ after do
+ # this should be appended to failure list
+ expect(false).to be(true), "after hook failure"
+ end
+
+ around do |ex|
+ ex.run
+ # this should also be appended to failure list
+ expect(false).to be(true), "around hook failure"
+ end
+
+ it "returns a successful response" do
+ response = Client.make_request
+
+ aggregate_failures "testing response" do
+ expect(response.status).to eq(200)
+ expect(response.headers).to include("Content-Type" => "application/json")
+ expect(response.body).to eq('{"message":"Success"}')
+ end
+ end
+end
+
+When I run rspec spec/use_block_form_spec.rb
+
+Then it should fail and list all the failures:
+Failures:
+
+ 1) Client returns a successful response
+ Got 3 failures:
+
+ 1.1) Got 3 failures from failure aggregation block "testing response".
+ # ./spec/use_block_form_spec.rb:18
+ # ./spec/use_block_form_spec.rb:10
+
+ 1.1.1) Failure/Error: expect(response.status).to eq(200)
+
+ expected: 200
+ got: 404
+
+ (compared using ==)
+ # ./spec/use_block_form_spec.rb:19
+
+ 1.1.2) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json")
+ expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"}
+ Diff:
+ @@ -1 +1 @@
+ -"Content-Type" => "application/json",
+ +"Content-Type" => "text/plain",
+ # ./spec/use_block_form_spec.rb:20
+
+ 1.1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}')
+
+ expected: "{\"message\":\"Success\"}"
+ got: "Not Found"
+
+ (compared using ==)
+ # ./spec/use_block_form_spec.rb:21
+
+ 1.2) Failure/Error: expect(false).to be(true), "after hook failure"
+ after hook failure
+ # ./spec/use_block_form_spec.rb:6
+ # ./spec/use_block_form_spec.rb:10
+
+ 1.3) Failure/Error: expect(false).to be(true), "around hook failure"
+ around hook failure
+ # ./spec/use_block_form_spec.rb:12
+
+Use aggregate_failures block form
+
+Given a file named “spec/useblockform_spec.rb” with:
+require 'client'
+
+RSpec.describe Client do
+ after do
+ # this should be appended to failure list
+ expect(false).to be(true), "after hook failure"
+ end
+
+ around do |ex|
+ ex.run
+ # this should also be appended to failure list
+ expect(false).to be(true), "around hook failure"
+ end
+
+ it "returns a successful response" do
+ response = Client.make_request
+
+ aggregate_failures "testing response" do
+ expect(response.status).to eq(200)
+ expect(response.headers).to include("Content-Type" => "application/json")
+ expect(response.body).to eq('{"message":"Success"}')
+ end
+ end
+end
+
+When I run rspec spec/use_block_form_spec.rb
+
+Then it should fail and list all the failures:
+Failures:
+
+ 1) Client returns a successful response
+ Got 3 failures:
+
+ 1.1) Got 3 failures from failure aggregation block "testing response".
+ # ./spec/use_block_form_spec.rb:18
+ # ./spec/use_block_form_spec.rb:10
+
+ 1.1.1) Failure/Error: expect(response.status).to eq(200)
+
+ expected: 200
+ got: 404
+
+ (compared using ==)
+ # ./spec/use_block_form_spec.rb:19
+
+ 1.1.2) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json")
+ expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"}
+ Diff:
+ @@ -1,2 +1,2 @@
+ -"Content-Type" => "application/json",
+ +"Content-Type" => "text/plain",
+ # ./spec/use_block_form_spec.rb:20
+
+ 1.1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}')
+
+ expected: "{\"message\":\"Success\"}"
+ got: "Not Found"
+
+ (compared using ==)
+ # ./spec/use_block_form_spec.rb:21
+
+ 1.2) Failure/Error: expect(false).to be(true), "after hook failure"
+ after hook failure
+ # ./spec/use_block_form_spec.rb:6
+ # ./spec/use_block_form_spec.rb:10
+
+ 1.3) Failure/Error: expect(false).to be(true), "around hook failure"
+ around hook failure
+ # ./spec/use_block_form_spec.rb:12
+
+Use :aggregate_failures metadata
+
+Given a file named “spec/usemetadataspec.rb” with:
+require 'client'
+
+RSpec.describe Client do
+ it "follows a redirect", :aggregate_failures do
+ response = Client.make_request
+
+ expect(response.status).to eq(302)
+ expect(response.body).to eq('{"message":"Redirect"}')
+
+ redirect_response = Client.make_request(response.headers.fetch('Location'))
+
+ expect(redirect_response.status).to eq(200)
+ expect(redirect_response.body).to eq('{"message":"OK"}')
+ end
+end
+
+When I run rspec spec/use_metadata_spec.rb
+
+Then it should fail and list all the failures:
+Failures:
+
+ 1) Client follows a redirect
+ Got 2 failures and 1 other error:
+
+ 1.1) Failure/Error: expect(response.status).to eq(302)
+
+ expected: 302
+ got: 404
+
+ (compared using ==)
+ # ./spec/use_metadata_spec.rb:7
+
+ 1.2) Failure/Error: expect(response.body).to eq('{"message":"Redirect"}')
+
+ expected: "{\"message\":\"Redirect\"}"
+ got: "Not Found"
+
+ (compared using ==)
+ # ./spec/use_metadata_spec.rb:8
+
+ 1.3) Failure/Error: redirect_response = Client.make_request(response.headers.fetch('Location'))
+ KeyError:
+ key not found: "Location"
+ # ./spec/use_metadata_spec.rb:10
+ # ./spec/use_metadata_spec.rb:10
+
+Enable failure aggregation globally using define_derived_metadata
+
+Given a file named “spec/enablegloballyspec.rb” with:
+require 'client'
+
+RSpec.configure do |c|
+ c.define_derived_metadata do |meta|
+ meta[:aggregate_failures] = true
+ end
+end
+
+RSpec.describe Client do
+ it "returns a successful response" do
+ response = Client.make_request
+
+ expect(response.status).to eq(200)
+ expect(response.headers).to include("Content-Type" => "application/json")
+ expect(response.body).to eq('{"message":"Success"}')
+ end
+end
+
+When I run rspec spec/enable_globally_spec.rb
+
+Then it should fail and list all the failures:
+Failures:
+
+ 1) Client returns a successful response
+ Got 3 failures:
+
+ 1.1) Failure/Error: expect(response.status).to eq(200)
+
+ expected: 200
+ got: 404
+
+ (compared using ==)
+ # ./spec/enable_globally_spec.rb:13
+
+ 1.2) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json")
+ expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"}
+ Diff:
+ @@ -1 +1 @@
+ -"Content-Type" => "application/json",
+ +"Content-Type" => "text/plain",
+ # ./spec/enable_globally_spec.rb:14
+
+ 1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}')
+
+ expected: "{\"message\":\"Success\"}"
+ got: "Not Found"
+
+ (compared using ==)
+ # ./spec/enable_globally_spec.rb:15
+
+Enable failure aggregation globally using define_derived_metadata
+
+Given a file named “spec/enablegloballyspec.rb” with:
+require 'client'
+
+RSpec.configure do |c|
+ c.define_derived_metadata do |meta|
+ meta[:aggregate_failures] = true
+ end
+end
+
+RSpec.describe Client do
+ it "returns a successful response" do
+ response = Client.make_request
+
+ expect(response.status).to eq(200)
+ expect(response.headers).to include("Content-Type" => "application/json")
+ expect(response.body).to eq('{"message":"Success"}')
+ end
+end
+
+When I run rspec spec/enable_globally_spec.rb
+
+Then it should fail and list all the failures:
+Failures:
+
+ 1) Client returns a successful response
+ Got 3 failures:
+
+ 1.1) Failure/Error: expect(response.status).to eq(200)
+
+ expected: 200
+ got: 404
+
+ (compared using ==)
+ # ./spec/enable_globally_spec.rb:13
+
+ 1.2) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json")
+ expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"}
+ Diff:
+ @@ -1,2 +1,2 @@
+ -"Content-Type" => "application/json",
+ +"Content-Type" => "text/plain",
+ # ./spec/enable_globally_spec.rb:14
+
+ 1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}')
+
+ expected: "{\"message\":\"Success\"}"
+ got: "Not Found"
+
+ (compared using ==)
+ # ./spec/enable_globally_spec.rb:15
+
+Nested failure aggregation works
+
+Given a file named “spec/nestedfailureaggregation_spec.rb” with:
+require 'client'
+
+RSpec.describe Client do
+ it "returns a successful response", :aggregate_failures do
+ response = Client.make_request
+
+ expect(response.status).to eq(200)
+
+ aggregate_failures "testing headers" do
+ expect(response.headers).to include("Content-Type" => "application/json")
+ expect(response.headers).to include("Content-Length" => "21")
+ end
+
+ expect(response.body).to eq('{"message":"Success"}')
+ end
+end
+
+When I run rspec spec/nested_failure_aggregation_spec.rb
+
+Then it should fail and list all the failures:
+Failures:
+
+ 1) Client returns a successful response
+ Got 3 failures:
+
+ 1.1) Failure/Error: expect(response.status).to eq(200)
+
+ expected: 200
+ got: 404
+
+ (compared using ==)
+ # ./spec/nested_failure_aggregation_spec.rb:7
+
+ 1.2) Got 2 failures from failure aggregation block "testing headers".
+ # ./spec/nested_failure_aggregation_spec.rb:9
+
+ 1.2.1) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json")
+ expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"}
+ Diff:
+ @@ -1 +1 @@
+ -"Content-Type" => "application/json",
+ +"Content-Type" => "text/plain",
+ # ./spec/nested_failure_aggregation_spec.rb:10
+
+ 1.2.2) Failure/Error: expect(response.headers).to include("Content-Length" => "21")
+ expected {"Content-Type" => "text/plain"} to include {"Content-Length" => "21"}
+ Diff:
+ @@ -1 +1 @@
+ -"Content-Length" => "21",
+ +"Content-Type" => "text/plain",
+ # ./spec/nested_failure_aggregation_spec.rb:11
+
+ 1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}')
+
+ expected: "{\"message\":\"Success\"}"
+ got: "Not Found"
+
+ (compared using ==)
+ # ./spec/nested_failure_aggregation_spec.rb:14
+
+Nested failure aggregation works
+
+Given a file named “spec/nestedfailureaggregation_spec.rb” with:
+require 'client'
+
+RSpec.describe Client do
+ it "returns a successful response", :aggregate_failures do
+ response = Client.make_request
+
+ expect(response.status).to eq(200)
+
+ aggregate_failures "testing headers" do
+ expect(response.headers).to include("Content-Type" => "application/json")
+ expect(response.headers).to include("Content-Length" => "21")
+ end
+
+ expect(response.body).to eq('{"message":"Success"}')
+ end
+end
+
+When I run rspec spec/nested_failure_aggregation_spec.rb
+
+Then it should fail and list all the failures:
+Failures:
+
+ 1) Client returns a successful response
+ Got 3 failures:
+
+ 1.1) Failure/Error: expect(response.status).to eq(200)
+
+ expected: 200
+ got: 404
+
+ (compared using ==)
+ # ./spec/nested_failure_aggregation_spec.rb:7
+
+ 1.2) Got 2 failures from failure aggregation block "testing headers".
+ # ./spec/nested_failure_aggregation_spec.rb:9
+
+ 1.2.1) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json")
+ expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"}
+ Diff:
+ @@ -1,2 +1,2 @@
+ -"Content-Type" => "application/json",
+ +"Content-Type" => "text/plain",
+ # ./spec/nested_failure_aggregation_spec.rb:10
+
+ 1.2.2) Failure/Error: expect(response.headers).to include("Content-Length" => "21")
+ expected {"Content-Type" => "text/plain"} to include {"Content-Length" => "21"}
+ Diff:
+ @@ -1,2 +1,2 @@
+ -"Content-Length" => "21",
+ +"Content-Type" => "text/plain",
+ # ./spec/nested_failure_aggregation_spec.rb:11
+
+ 1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}')
+
+ expected: "{\"message\":\"Success\"}"
+ got: "Not Found"
+
+ (compared using ==)
+ # ./spec/nested_failure_aggregation_spec.rb:14
+
+Mock expectation failures are aggregated as well
+
+Given a file named “spec/mockexpectationfailure_spec.rb” with:
+require 'client'
+
+RSpec.describe "Aggregating Failures", :aggregate_failures do
+ it "has a normal expectation failure and a message expectation failure" do
+ client = double("Client")
+ expect(client).to receive(:put).with("updated data")
+ allow(client).to receive(:get).and_return(Response.new(404, {}, "Not Found"))
+
+ response = client.get
+ expect(response.status).to eq(200)
+ end
+end
+
+When I run rspec spec/mock_expectation_failure_spec.rb
+
+Then it should fail and list all the failures:
+Failures:
+
+ 1) Aggregating Failures has a normal expectation failure and a message expectation failure
+ Got 2 failures:
+
+ 1.1) Failure/Error: expect(response.status).to eq(200)
+
+ expected: 200
+ got: 404
+
+ (compared using ==)
+ # ./spec/mock_expectation_failure_spec.rb:10
+
+ 1.2) Failure/Error: expect(client).to receive(:put).with("updated data")
+ (Double "Client").put("updated data")
+ expected: 1 time with arguments: ("updated data")
+ received: 0 times
+ # ./spec/mock_expectation_failure_spec.rb:6
+
+
+Pending integrates properly with aggregated failures
+
+Given a file named “spec/pending_spec.rb” with:
+require 'client'
+
+RSpec.describe Client do
+ it "returns a successful response", :aggregate_failures do
+ pending "Not yet ready"
+ response = Client.make_request
+
+ expect(response.status).to eq(200)
+ expect(response.headers).to include("Content-Type" => "application/json")
+ expect(response.body).to eq('{"message":"Success"}')
+ end
+end
+
+When I run rspec spec/pending_spec.rb
+
+Then it should pass and list all the pending examples:
+Pending: (Failures listed here are expected and do not affect your suite's status)
+
+ 1) Client returns a successful response
+ # Not yet ready
+ Got 3 failures:
+
+ 1.1) Failure/Error: expect(response.status).to eq(200)
+
+ expected: 200
+ got: 404
+
+ (compared using ==)
+ # ./spec/pending_spec.rb:8
+
+ 1.2) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json")
+ expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"}
+ Diff:
+ @@ -1 +1 @@
+ -"Content-Type" => "application/json",
+ +"Content-Type" => "text/plain",
+ # ./spec/pending_spec.rb:9
+
+ 1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}')
+
+ expected: "{\"message\":\"Success\"}"
+ got: "Not Found"
+
+ (compared using ==)
+ # ./spec/pending_spec.rb:10
+
+Pending integrates properly with aggregated failures
+
+Given a file named “spec/pending_spec.rb” with:
+require 'client'
+
+RSpec.describe Client do
+ it "returns a successful response", :aggregate_failures do
+ pending "Not yet ready"
+ response = Client.make_request
+
+ expect(response.status).to eq(200)
+ expect(response.headers).to include("Content-Type" => "application/json")
+ expect(response.body).to eq('{"message":"Success"}')
+ end
+end
+
+When I run rspec spec/pending_spec.rb
+
+Then it should pass and list all the pending examples:
+Pending: (Failures listed here are expected and do not affect your suite's status)
+
+ 1) Client returns a successful response
+ # Not yet ready
+ Got 3 failures:
+
+ 1.1) Failure/Error: expect(response.status).to eq(200)
+
+ expected: 200
+ got: 404
+
+ (compared using ==)
+ # ./spec/pending_spec.rb:8
+
+ 1.2) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json")
+ expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"}
+ Diff:
+ @@ -1,2 +1,2 @@
+ -"Content-Type" => "application/json",
+ +"Content-Type" => "text/plain",
+ # ./spec/pending_spec.rb:9
+
+ 1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}')
+
+ expected: "{\"message\":\"Success\"}"
+ got: "Not Found"
+
+ (compared using ==)
+ # ./spec/pending_spec.rb:10
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/expectation-framework-integration/configure-expectation-framework/index.html b/docs/features/3-12/rspec-core/expectation-framework-integration/configure-expectation-framework/index.html
new file mode 100644
index 000000000..d7dc4c266
--- /dev/null
+++ b/docs/features/3-12/rspec-core/expectation-framework-integration/configure-expectation-framework/index.html
@@ -0,0 +1,190 @@
+
+
+
+
+Configuring an expectation framework
+
+By default, RSpec is configured to include rspec-expectations for expressing
+ desired outcomes. You can also configure RSpec to use:
+
+
+- rspec/expectations (explicitly)
+- test/unit assertions
+- minitest assertions
+- any combination of the above libraries
+
+
+Note that when you do not use rspec-expectations, you must explicitly provide
+ a description to every example. You cannot rely on the generated descriptions
+ provided by rspec-expectations.
+
+Default configuration uses rspec-expectations
+
+Given a file named “example_spec.rb” with:
+RSpec::Matchers.define :be_a_multiple_of do |factor|
+ match do |actual|
+ actual % factor == 0
+ end
+end
+
+RSpec.describe 6 do
+ it { is_expected.to be_a_multiple_of 3 }
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
+Configure rspec-expectations (explicitly)
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.expect_with :rspec
+end
+
+RSpec.describe 5 do
+ it "is greater than 4" do
+ expect(5).to be > 4
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
+Configure test/unit assertions
+
+Given rspec-expectations is not installed
+
+And a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.expect_with :test_unit
+end
+
+RSpec.describe [1] do
+ it "is equal to [1]" do
+ assert_equal [1], [1], "expected [1] to equal [1]"
+ end
+
+ specify { assert_not_equal [1], [] }
+
+ it "is equal to [2] (intentional failure)" do
+ assert [1] == [2], "errantly expected [2] to equal [1]"
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should match:
+ (Test::Unit::AssertionFailedError|Mini(T|t)est::Assertion):
+ errantly expected \[2\] to equal \[1\]
+
+And the output should contain “3 examples, 1 failure”.
+
+Configure minitest assertions
+
+Given rspec-expectations is not installed
+
+And a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.expect_with :minitest
+end
+
+RSpec.describe "Object identity" do
+ it "the an object is the same as itself" do
+ x = [1]
+ assert_same x, x, "expected x to be the same x"
+ end
+
+ specify { refute_same [1], [1] }
+
+ it "is empty (intentional failure)" do
+ assert_empty [1], "errantly expected [1] to be empty"
+ end
+
+ it "marks pending for skip method" do
+ skip "intentionally"
+ end
+end
+
+When I run rspec -b example_spec.rb
+
+Then the output should match:
+ MiniT|test::Assertion:
+ errantly expected \[1\] to be empty
+
+And the output should contain “4 examples, 1 failure, 1 pending”
+
+And the output should not contain “Warning: you should require ‘minitest/autorun’ instead.”.
+
+Configure rspec/expectations AND test/unit assertions
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.expect_with :rspec, :test_unit
+end
+
+RSpec.describe [1] do
+ it "is equal to [1]" do
+ assert_equal [1], [1], "expected [1] to equal [1]"
+ end
+
+ it "matches array [1]" do
+ is_expected.to match_array([1])
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
+Configure rspec/expectations AND minitest assertions
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.expect_with :rspec, :minitest
+end
+
+RSpec.describe "Object identity" do
+ it "two arrays are not the same object" do
+ refute_same [1], [1]
+ end
+
+ it "an array is itself" do
+ array = [1]
+ expect(array).to be array
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
+Configure test/unit and minitest assertions
+
+Given rspec-expectations is not installed
+
+And a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.expect_with :test_unit, :minitest
+end
+
+RSpec.describe [1] do
+ it "is equal to [1]" do
+ assert_equal [1], [1], "expected [1] to equal [1]"
+ end
+
+ specify { assert_not_equal [1], [] }
+
+ it "the an object is the same as itself" do
+ x = [1]
+ assert_same x, x, "expected x to be the same x"
+ end
+
+ specify { refute_same [1], [1] }
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/expectation-framework-integration/index.html b/docs/features/3-12/rspec-core/expectation-framework-integration/index.html
new file mode 100644
index 000000000..58f902f29
--- /dev/null
+++ b/docs/features/3-12/rspec-core/expectation-framework-integration/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Expectation framework integration
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/filtering/exclusion-filters/index.html b/docs/features/3-12/rspec-core/filtering/exclusion-filters/index.html
new file mode 100644
index 000000000..2e67643cf
--- /dev/null
+++ b/docs/features/3-12/rspec-core/filtering/exclusion-filters/index.html
@@ -0,0 +1,154 @@
+
+
+
+
+Exclusion filters
+
+You can exclude examples from a run by declaring an exclusion filter and then
+ tagging examples, or entire groups, with that filter. You can also specify
+ metadata using only symbols.
+
+Exclude an example
+
+Given a file named “spec/sample_spec.rb” with:
+RSpec.configure do |c|
+ # declare an exclusion filter
+ c.filter_run_excluding :broken => true
+end
+
+RSpec.describe "something" do
+ it "does one thing" do
+ end
+
+ # tag example for exclusion by adding metadata
+ it "does another thing", :broken => true do
+ end
+end
+
+When I run rspec ./spec/sample_spec.rb --format doc
+
+Then the output should contain “does one thing”
+
+And the output should not contain “does another thing”.
+
+Exclude a group
+
+Given a file named “spec/sample_spec.rb” with:
+RSpec.configure do |c|
+ c.filter_run_excluding :broken => true
+end
+
+RSpec.describe "group 1", :broken => true do
+ it "group 1 example 1" do
+ end
+
+ it "group 1 example 2" do
+ end
+end
+
+RSpec.describe "group 2" do
+ it "group 2 example 1" do
+ end
+end
+
+When I run rspec ./spec/sample_spec.rb --format doc
+
+Then the output should contain “group 2 example 1”
+
+And the output should not contain “group 1 example 1”
+
+And the output should not contain “group 1 example 2”.
+
+Exclude multiple groups
+
+Given a file named “spec/sample_spec.rb” with:
+RSpec.configure do |c|
+ c.filter_run_excluding :broken => true
+end
+
+RSpec.describe "group 1", :broken => true do
+ before(:context) do
+ raise "you should not see me"
+ end
+
+ it "group 1 example 1" do
+ end
+
+ it "group 1 example 2" do
+ end
+end
+
+RSpec.describe "group 2", :broken => true do
+ before(:example) do
+ raise "you should not see me"
+ end
+
+ it "group 2 example 1" do
+ end
+end
+
+When I run rspec ./spec/sample_spec.rb --format doc
+
+Then the process should succeed even though no examples were run
+
+And the output should not contain “group 1”
+
+And the output should not contain “group 2”.
+
+before/after(:context) hooks in excluded example group are not run
+
+Given a file named “spec/beforeaftercontextexclusionfilter_spec.rb” with:
+RSpec.configure do |c|
+ c.filter_run_excluding :broken => true
+end
+
+RSpec.describe "group 1" do
+ before(:context) { puts "before context in included group" }
+ after(:context) { puts "after context in included group" }
+
+ it "group 1 example" do
+ end
+end
+
+RSpec.describe "group 2", :broken => true do
+ before(:context) { puts "before context in excluded group" }
+ after(:context) { puts "after context in excluded group" }
+
+ context "context 1" do
+ it "group 2 context 1 example 1" do
+ end
+ end
+end
+
+When I run rspec ./spec/before_after_context_exclusion_filter_spec.rb
+
+Then the output should contain “before context in included group”
+
+And the output should contain “after context in included group”
+
+And the output should not contain “before context in excluded group”
+
+And the output should not contain “after context in excluded group”.
+
+Use symbols as metadata
+
+Given a file named “symbolsasmetadata_spec.rb” with:
+RSpec.configure do |c|
+ c.filter_run_excluding :broken
+end
+
+RSpec.describe "something" do
+ it "does one thing" do
+ end
+
+ # tag example for exclusion by adding metadata
+ it "does another thing", :broken do
+ end
+end
+
+When I run rspec symbols_as_metadata_spec.rb --format doc
+
+Then the output should contain “does one thing”
+
+And the output should not contain “does another thing”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/filtering/filter-run-when-matching/index.html b/docs/features/3-12/rspec-core/filtering/filter-run-when-matching/index.html
new file mode 100644
index 000000000..7471d737f
--- /dev/null
+++ b/docs/features/3-12/rspec-core/filtering/filter-run-when-matching/index.html
@@ -0,0 +1,79 @@
+
+
+
+
+Using filter_run_when_matching
+
+You can configure a conditional filter that only applies if there are any matching
+ examples using config.filter_run_when_matching. This is commonly used for focus
+ filtering:
+ RSpec.configure do |c|
+ c.filter_run_when_matching :focus
+ end
+
+This configuration allows you to filter to specific examples or groups by tagging
+ them with :focus metadata. When no example or groups are focused (which should be
+ the norm since it’s intended to be a temporary change), the filter will be ignored.
+
+RSpec also provides aliases–fit, fdescribe and fcontext–as a shorthand for
+ it, describe and context with :focus metadata, making it easy to temporarily
+ focus an example or group by prefixing an f.
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |c|
+ c.filter_run_when_matching :focus
+end
+
+And a file named “.rspec” with:
+--require spec_helper
+
+And a file named “spec/example_spec.rb” with:
+RSpec.describe "A group" do
+ it "has a passing example" do
+ end
+
+ context "a nested group" do
+ it "also has a passing example" do
+ end
+ end
+end
+
+The filter is ignored when nothing is focused
+
+When I run rspec --format doc
+
+Then it should pass with “2 examples, 0 failures”
+
+And the output should contain:
+A group
+ has a passing example
+ a nested group
+ also has a passing example
+
+Examples can be focused with fit
+
+Given I have changed it "has a passing example" to fit "has a passing example" in “spec/example_spec.rb”
+
+When I run rspec --format doc
+
+Then it should pass with “1 example, 0 failures”
+
+And the output should contain:
+A group
+ has a passing example
+
+Groups can be focused with fdescribe or fcontext
+
+Given I have changed context to fcontext in “spec/example_spec.rb”
+
+When I run rspec --format doc
+
+Then it should pass with “1 example, 0 failures”
+
+And the output should contain:
+A group
+ a nested group
+ also has a passing example
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/filtering/if-and-unless/index.html b/docs/features/3-12/rspec-core/filtering/if-and-unless/index.html
new file mode 100644
index 000000000..d29e02e74
--- /dev/null
+++ b/docs/features/3-12/rspec-core/filtering/if-and-unless/index.html
@@ -0,0 +1,318 @@
+
+
+
+
+Conditional Filters
+
+The :if and :unless metadata keys can be used to filter examples without
+ needing to configure an exclusion filter.
+
+Implicit :if filter
+
+Given a file named “implicitiffilter_spec.rb” with:
+RSpec.describe ":if => true group", :if => true do
+ it(":if => true group :if => true example", :if => true) { }
+ it(":if => true group :if => false example", :if => false) { }
+ it(":if => true group no :if example") { }
+end
+
+RSpec.describe ":if => false group", :if => false do
+ it(":if => false group :if => true example", :if => true) { }
+ it(":if => false group :if => false example", :if => false) { }
+ it(":if => false group no :if example") { }
+end
+
+RSpec.describe "no :if group" do
+ it("no :if group :if => true example", :if => true) { }
+ it("no :if group :if => false example", :if => false) { }
+ it("no :if group no :if example") { }
+end
+
+When I run rspec implicit_if_filter_spec.rb --format doc
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+:if => true group :if => true example
+
+
+:if => true group no :if example
+
+
+:if => false group :if => true example
+
+
+no :if group :if => true example
+
+
+no :if group no :if example
+
+
+
+And the output should not contain any of these:
+
+
+
+
+
+
+
+:if => true group :if => false example
+
+
+:if => false group :if => false example
+
+
+:if => false group no :if example
+
+
+no :if group :if => false example
+
+
+
+Implicit :unless filter
+
+Given a file named “implicitunlessfilter_spec.rb” with:
+RSpec.describe ":unless => true group", :unless => true do
+ it(":unless => true group :unless => true example", :unless => true) { }
+ it(":unless => true group :unless => false example", :unless => false) { }
+ it(":unless => true group no :unless example") { }
+end
+
+RSpec.describe ":unless => false group", :unless => false do
+ it(":unless => false group :unless => true example", :unless => true) { }
+ it(":unless => false group :unless => false example", :unless => false) { }
+ it(":unless => false group no :unless example") { }
+end
+
+RSpec.describe "no :unless group" do
+ it("no :unless group :unless => true example", :unless => true) { }
+ it("no :unless group :unless => false example", :unless => false) { }
+ it("no :unless group no :unless example") { }
+end
+
+When I run rspec implicit_unless_filter_spec.rb --format doc
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+:unless => true group :unless => false example
+
+
+:unless => false group :unless => false example
+
+
+:unless => false group no :unless example
+
+
+no :unless group :unless => false example
+
+
+no :unless group no :unless example
+
+
+
+And the output should not contain any of these:
+
+
+
+
+
+
+
+:unless => true group :unless => true example
+
+
+:unless => true group no :unless example
+
+
+:unless => false group :unless => true example
+
+
+no :unless group :unless => true example
+
+
+
+Combining implicit filter with explicit inclusion filter
+
+Given a file named “explicitinclusionfilter_spec.rb” with:
+RSpec.configure do |c|
+ c.filter_run :focus => true
+end
+
+RSpec.describe "group with :focus", :focus => true do
+ it("focused example") { }
+ it("focused :if => true example", :if => true) { }
+ it("focused :if => false example", :if => false) { }
+ it("focused :unless => true example", :unless => true) { }
+ it("focused :unless => false example", :unless => false) { }
+end
+
+RSpec.describe "group without :focus" do
+ it("unfocused example") { }
+ it("unfocused :if => true example", :if => true) { }
+ it("unfocused :if => false example", :if => false) { }
+ it("unfocused :unless => true example", :unless => true) { }
+ it("unfocused :unless => false example", :unless => false) { }
+end
+
+When I run rspec explicit_inclusion_filter_spec.rb --format doc
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+focused example
+
+
+focused :if => true example
+
+
+focused :unless => false example
+
+
+
+And the output should not contain any of these:
+
+
+
+
+
+
+
+focused :if => false example
+
+
+focused :unless => true example
+
+
+unfocused
+
+
+
+Combining implicit filter with explicit exclusion filter
+
+Given a file named “explicitexclusionfilter_spec.rb” with:
+RSpec.configure do |c|
+ c.filter_run_excluding :broken => true
+end
+
+RSpec.describe "unbroken group" do
+ it("included example") { }
+ it("included :if => true example", :if => true) { }
+ it("included :if => false example", :if => false) { }
+ it("included :unless => true example", :unless => true) { }
+ it("included :unless => false example", :unless => false) { }
+end
+
+RSpec.describe "broken group", :broken => true do
+ it("excluded example") { }
+ it("excluded :if => true example", :if => true) { }
+ it("excluded :if => false example", :if => false) { }
+ it("excluded :unless => true example", :unless => true) { }
+ it("excluded :unless => false example", :unless => false) { }
+end
+
+When I run rspec explicit_exclusion_filter_spec.rb --format doc
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+included example
+
+
+included :if => true example
+
+
+included :unless => false example
+
+
+
+And the output should not contain any of these:
+
+
+
+
+
+
+
+included :if => false example
+
+
+included :unless => true example
+
+
+excluded
+
+
+
+The :if and :unless exclusions stay in effect when there are explicit inclusions
+
+Given a file named “ifandunless_spec.rb” with:
+RSpec.describe "Using inclusions" do
+ context "inclusion target" do
+ it "is filtered out by :if", :if => false do
+ end
+
+ it 'is filtered out by :unless', :unless => true do
+ end
+
+ it 'is still run according to :if', :if => true do
+ end
+
+ it 'is still run according to :unless', :unless => false do
+ end
+ end
+end
+
+When I run rspec if_and_unless_spec.rb --format doc -e 'inclusion target'
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+is still run according to :if
+
+
+is still run according to :unless
+
+
+
+And the output should not contain any of these:
+
+
+
+
+
+
+
+is filtered out by :if
+
+
+is filtered out by :unless
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/filtering/inclusion-filters/index.html b/docs/features/3-12/rspec-core/filtering/inclusion-filters/index.html
new file mode 100644
index 000000000..fb2bad236
--- /dev/null
+++ b/docs/features/3-12/rspec-core/filtering/inclusion-filters/index.html
@@ -0,0 +1,116 @@
+
+
+
+
+Inclusion filters
+
+You can constrain which examples are run by declaring an inclusion filter.
+ The most common use case is to focus on a subset of examples as you’re focused
+ on a particular problem. You can also specify metadata using only symbols.
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |c|
+ c.filter_run_including :focus => true
+end
+
+Focus on an example
+
+Given a file named “spec/sample_spec.rb” with:
+require "spec_helper"
+
+RSpec.describe "something" do
+ it "does one thing" do
+ end
+
+ it "does another thing", :focus => true do
+ end
+end
+
+When I run rspec spec/sample_spec.rb --format doc
+
+Then the output should contain “does another thing”
+
+And the output should not contain “does one thing”.
+
+Focus on a group
+
+Given a file named “spec/sample_spec.rb” with:
+require "spec_helper"
+
+RSpec.describe "group 1", :focus => true do
+ it "group 1 example 1" do
+ end
+
+ it "group 1 example 2" do
+ end
+end
+
+RSpec.describe "group 2" do
+ it "group 2 example 1" do
+ end
+end
+
+When I run rspec spec/sample_spec.rb --format doc
+
+Then the output should contain “group 1 example 1”
+
+And the output should contain “group 1 example 2”
+
+And the output should not contain “group 2 example 1”.
+
+before/after(:context) hooks in unmatched example group are not run
+
+Given a file named “spec/beforeafterallinclusionfilter_spec.rb” with:
+require "spec_helper"
+
+RSpec.describe "group 1", :focus => true do
+ before(:context) { puts "before all in focused group" }
+ after(:context) { puts "after all in focused group" }
+
+ it "group 1 example" do
+ end
+end
+
+RSpec.describe "group 2" do
+ before(:context) { puts "before all in unfocused group" }
+ after(:context) { puts "after all in unfocused group" }
+
+ context "context 1" do
+ it "group 2 context 1 example 1" do
+ end
+ end
+end
+
+When I run rspec ./spec/before_after_all_inclusion_filter_spec.rb
+
+Then the output should contain “before all in focused group”
+
+And the output should contain “after all in focused group”
+
+And the output should not contain “before all in unfocused group”
+
+And the output should not contain “after all in unfocused group”.
+
+Use symbols as metadata
+
+Given a file named “symbolsasmetadata_spec.rb” with:
+RSpec.configure do |c|
+ c.filter_run :current_example
+end
+
+RSpec.describe "something" do
+ it "does one thing" do
+ end
+
+ it "does another thing", :current_example do
+ end
+end
+
+When I run rspec symbols_as_metadata_spec.rb --format doc
+
+Then the output should contain “does another thing”
+
+And the output should not contain “does one thing”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/filtering/index.html b/docs/features/3-12/rspec-core/filtering/index.html
new file mode 100644
index 000000000..77c4e45fc
--- /dev/null
+++ b/docs/features/3-12/rspec-core/filtering/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Filtering
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/formatters/configurable-colors/index.html b/docs/features/3-12/rspec-core/formatters/configurable-colors/index.html
new file mode 100644
index 000000000..4d21ddad2
--- /dev/null
+++ b/docs/features/3-12/rspec-core/formatters/configurable-colors/index.html
@@ -0,0 +1,58 @@
+
+
+
+
+Configurable colors
+
+RSpec allows you to configure the terminal colors used in the text formatters.
+
+
+failure_color: Color used when tests fail (default: :red)
+success_color: Color used when tests pass (default: :green)
+pending_color: Color used when tests are pending (default: :yellow)
+fixed_color: Color used when a pending block inside an example passes, but
+was expected to fail (default: :blue)
+detail_color: Color used for miscellaneous test details (default: :cyan)
+
+
+Colors are specified as symbols. Options are :black, :red, :green,
+ :yellow, :blue, :magenta, :cyan, :white, :bold_black, :bold_red,
+ :bold_green, :bold_yellow, :bold_blue, :bold_magenta, :bold_cyan,
+ and :bold_white,
+
+Customizing the failure color
+
+Given a file named “customfailurecolor_spec.rb” with:
+RSpec.configure do |config|
+ config.failure_color = :magenta
+ config.color_mode = :on
+end
+
+RSpec.describe "failure" do
+ it "fails and uses the custom color" do
+ expect(2).to eq(4)
+ end
+end
+
+When I run rspec custom_failure_color_spec.rb --format progress
+
+Then the failing example is printed in magenta.
+
+Customizing the failure color with a custom console code
+
+Given a file named “customfailurecolor_spec.rb” with:
+RSpec.configure do |config|
+ config.failure_color = "1;32"
+ config.color_mode = :on
+end
+
+RSpec.describe "failure" do
+ it "fails and uses the custom color" do
+ expect(2).to eq(4)
+ end
+end
+
+When I run rspec custom_failure_color_spec.rb --format progress
+
+Then the failing example is printed wrapped in “1;32”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/formatters/custom-formatter/index.html b/docs/features/3-12/rspec-core/formatters/custom-formatter/index.html
new file mode 100644
index 000000000..bdb06a1c2
--- /dev/null
+++ b/docs/features/3-12/rspec-core/formatters/custom-formatter/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+Custom formatters
+
+RSpec ships with general purpose output formatters. You can tell RSpec which
+ one to use using the --format command line option.
+
+When RSpec’s built-in output formatters don’t, however, give you everything
+ you need, you can write your own custom formatter and tell RSpec to use that
+ one instead. The simplest way is to subclass RSpec’s BaseTextFormatter, and
+ then override just the methods that you want to modify.
+
+Custom formatter
+
+Given a file named “custom_formatter.rb” with:
+class CustomFormatter
+ # This registers the notifications this formatter supports, and tells
+ # us that this was written against the RSpec 3.x formatter API.
+ RSpec::Core::Formatters.register self, :example_started
+
+ def initialize(output)
+ @output = output
+ end
+
+ def example_started(notification)
+ @output << "example: " << notification.example.description
+ end
+end
+
+And a file named “example_spec.rb” with:
+RSpec.describe "my group" do
+ specify "my example" do
+ end
+end
+
+When I run rspec example_spec.rb --require ./custom_formatter.rb --format CustomFormatter
+
+Then the output should contain “example: my example”
+
+And the exit status should be 0.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/formatters/index.html b/docs/features/3-12/rspec-core/formatters/index.html
new file mode 100644
index 000000000..dc22c9cea
--- /dev/null
+++ b/docs/features/3-12/rspec-core/formatters/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Formatters
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/formatters/json-formatter/index.html b/docs/features/3-12/rspec-core/formatters/json-formatter/index.html
new file mode 100644
index 000000000..a4d4f6ccd
--- /dev/null
+++ b/docs/features/3-12/rspec-core/formatters/json-formatter/index.html
@@ -0,0 +1,61 @@
+
+
+
+
+The JSON formatter
+
+Formatting example names for retry
+
+Given a file named “various_spec.rb” with:
+RSpec.describe "Various" do
+ it "fails" do
+ expect("fail").to eq("succeed")
+ end
+
+ it "succeeds" do
+ expect("succeed").to eq("succeed")
+ end
+
+ it "pends"
+end
+
+When I run rspec various_spec.rb --format j
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+“summary_line”:“3 examples, 1 failure, 1 pending”
+
+
+“examples”:[
+
+
+“description”:“fails”
+
+
+“full_description”:“Various fails”
+
+
+“status”:“failed”
+
+
+“filepath”:“./variousspec.rb”
+
+
+“line_number”:2
+
+
+“exception”:{
+
+
+“class”:“RSpec::Expectations::ExpectationNotMetError”
+
+
+
+And the exit status should be 1.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/helper-methods/arbitrary-methods/index.html b/docs/features/3-12/rspec-core/helper-methods/arbitrary-methods/index.html
new file mode 100644
index 000000000..68e50dbaa
--- /dev/null
+++ b/docs/features/3-12/rspec-core/helper-methods/arbitrary-methods/index.html
@@ -0,0 +1,47 @@
+
+
+
+
+Defining arbitrary helper methods
+
+You can define methods in any example group using Ruby’s def keyword or
+ define_method method. These helper methods are exposed to examples in the
+ group in which they are defined and groups nested within that group, but not
+ parent or sibling groups.
+
+Use a method defined in the same group
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "an example" do
+ def help
+ :available
+ end
+
+ it "has access to methods defined in its group" do
+ expect(help).to be(:available)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
+Use a method defined in a parent group
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "an example" do
+ def help
+ :available
+ end
+
+ describe "in a nested group" do
+ it "has access to methods defined in its parent group" do
+ expect(help).to be(:available)
+ end
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/helper-methods/index.html b/docs/features/3-12/rspec-core/helper-methods/index.html
new file mode 100644
index 000000000..b1fb730b1
--- /dev/null
+++ b/docs/features/3-12/rspec-core/helper-methods/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Helper methods
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/helper-methods/let/index.html b/docs/features/3-12/rspec-core/helper-methods/let/index.html
new file mode 100644
index 000000000..6ba4342f1
--- /dev/null
+++ b/docs/features/3-12/rspec-core/helper-methods/let/index.html
@@ -0,0 +1,60 @@
+
+
+
+
+let and let!
+
+Use let to define a memoized helper method. The value will be cached across
+ multiple calls in the same example but not across examples.
+
+Note that let is lazy-evaluated: it is not evaluated until the first time
+ the method it defines is invoked. You can use let! to force the method’s
+ invocation before each example.
+
+By default, let is threadsafe, but you can configure it not to be
+ by disabling config.threadsafe, which makes let perform a bit faster.
+
+Use let to define memoized helper method
+
+Given a file named “let_spec.rb” with:
+$count = 0
+RSpec.describe "let" do
+ let(:count) { $count += 1 }
+
+ it "memoizes the value" do
+ expect(count).to eq(1)
+ expect(count).to eq(1)
+ end
+
+ it "is not cached across examples" do
+ expect(count).to eq(2)
+ end
+end
+
+When I run rspec let_spec.rb
+
+Then the examples should all pass.
+
+Use let! to define a memoized helper method that is called in a before hook
+
+Given a file named “letbangspec.rb” with:
+$count = 0
+RSpec.describe "let!" do
+ invocation_order = []
+
+ let!(:count) do
+ invocation_order << :let!
+ $count += 1
+ end
+
+ it "calls the helper method in a before hook" do
+ invocation_order << :example
+ expect(invocation_order).to eq([:let!, :example])
+ expect(count).to eq(1)
+ end
+end
+
+When I run rspec let_bang_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/helper-methods/modules/index.html b/docs/features/3-12/rspec-core/helper-methods/modules/index.html
new file mode 100644
index 000000000..9ab7caaa5
--- /dev/null
+++ b/docs/features/3-12/rspec-core/helper-methods/modules/index.html
@@ -0,0 +1,166 @@
+
+
+
+
+Define helper methods in a module
+
+You can define helper methods in a module and include it in your example
+ groups using the config.include configuration option. config.extend can be
+ used to extend the module onto your example groups so that the methods in the
+ module are available in the example groups themselves (but not in the actual
+ examples).
+
+You can also include or extend the module onto only certain example groups
+ by passing a metadata hash as the last argument. Only groups that match the
+ given metadata will include or extend the module. You can also specify
+ metadata using only symbols.
+
+Note that examples that match a config.include module’s metadata will also have the module included. RSpec treats every example as having a singleton example group (analogous to Ruby’s singleton classes) containing just the one example.
+
+Background
+
+Given a file named “helpers.rb” with:
+module Helpers
+ def help
+ :available
+ end
+end
+
+Include a module in all example groups
+
+Given a file named “includemodulespec.rb” with:
+require './helpers'
+
+RSpec.configure do |c|
+ c.include Helpers
+end
+
+RSpec.describe "an example group" do
+ it "has access to the helper methods defined in the module" do
+ expect(help).to be(:available)
+ end
+end
+
+When I run rspec include_module_spec.rb
+
+Then the examples should all pass.
+
+Extend a module in all example groups
+
+Given a file named “extendmodulespec.rb” with:
+require './helpers'
+
+RSpec.configure do |c|
+ c.extend Helpers
+end
+
+RSpec.describe "an example group" do
+ puts "Help is #{help}"
+
+ it "does not have access to the helper methods defined in the module" do
+ expect { help }.to raise_error(NameError)
+ end
+end
+
+When I run rspec extend_module_spec.rb
+
+Then the examples should all pass
+
+And the output should contain “Help is available”.
+
+Include a module in only some example groups
+
+Given a file named “includemoduleinsomegroups_spec.rb” with:
+require './helpers'
+
+RSpec.configure do |c|
+ c.include Helpers, :foo => :bar
+end
+
+RSpec.describe "an example group with matching metadata", :foo => :bar do
+ it "has access to the helper methods defined in the module" do
+ expect(help).to be(:available)
+ end
+end
+
+RSpec.describe "an example group without matching metadata" do
+ it "does not have access to the helper methods defined in the module" do
+ expect { help }.to raise_error(NameError)
+ end
+
+ it "does have access when the example has matching metadata", :foo => :bar do
+ expect(help).to be(:available)
+ end
+end
+
+When I run rspec include_module_in_some_groups_spec.rb
+
+Then the examples should all pass.
+
+Extend a module in only some example groups
+
+Given a file named “extendmoduleinonlysomegroupsspec.rb” with:
+require './helpers'
+
+RSpec.configure do |c|
+ c.extend Helpers, :foo => :bar
+end
+
+RSpec.describe "an example group with matching metadata", :foo => :bar do
+ puts "In a matching group, help is #{help}"
+
+ it "does not have access to the helper methods defined in the module" do
+ expect { help }.to raise_error(NameError)
+ end
+end
+
+RSpec.describe "an example group without matching metadata" do
+ puts "In a non-matching group, help is #{help rescue 'not available'}"
+
+ it "does not have access to the helper methods defined in the module" do
+ expect { help }.to raise_error(NameError)
+ end
+end
+
+When I run rspec extend_module_in_only_some_groups_spec.rb
+
+Then the examples should all pass
+
+And the output should contain “In a matching group, help is available”
+
+And the output should contain “In a non-matching group, help is not available”.
+
+Use symbols as metadata
+
+Given a file named “symbolsasmetadata_spec.rb” with:
+require './helpers'
+
+RSpec.configure do |c|
+ c.include Helpers, :include_helpers
+ c.extend Helpers, :extend_helpers
+end
+
+RSpec.describe "an example group with matching include metadata", :include_helpers do
+ puts "In a group not matching the extend filter, help is #{help rescue 'not available'}"
+
+ it "has access to the helper methods defined in the module" do
+ expect(help).to be(:available)
+ end
+end
+
+RSpec.describe "an example group with matching extend metadata", :extend_helpers do
+ puts "In a group matching the extend filter, help is #{help}"
+
+ it "does not have access to the helper methods defined in the module" do
+ expect { help }.to raise_error(NameError)
+ end
+end
+
+When I run rspec symbols_as_metadata_spec.rb
+
+Then the examples should all pass
+
+And the output should contain “In a group not matching the extend filter, help is not available”
+
+And the output should contain “In a group matching the extend filter, help is available”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/hooks/around-hooks/index.html b/docs/features/3-12/rspec-core/hooks/around-hooks/index.html
new file mode 100644
index 000000000..e8b37fe1c
--- /dev/null
+++ b/docs/features/3-12/rspec-core/hooks/around-hooks/index.html
@@ -0,0 +1,376 @@
+
+
+
+
+around hooks
+
+around hooks receive the example as a block argument, extended to behave as
+ a proc. This lets you define code that should be executed before and after the
+ example. Of course, you can do the same thing with before and after hooks;
+ and it’s often cleaner to do so.
+
+Where around hooks shine is when you want to run an example within a block.
+ For instance, if your database library offers a transaction method that
+ receives a block, you can use an around to cleanly open and close the
+ transaction around the example.
+
+WARNING: around hooks do not share state with the example the way
+ before and after hooks do. This means that you cannot share instance
+ variables between around hooks and examples.
+
+WARNING: Mock frameworks are set up and torn down within the context of
+ running the example. You cannot interact with them directly in around hooks.
+
+WARNING: around hooks will execute before any before hooks, and after
+ any after hooks regardless of the context they were defined in.
+
+Use the example as a proc within the block passed to around()
+
+Given a file named “example_spec.rb” with:
+class Database
+ def self.transaction
+ puts "open transaction"
+ yield
+ puts "close transaction"
+ end
+end
+
+RSpec.describe "around filter" do
+ around(:example) do |example|
+ Database.transaction(&example)
+ end
+
+ it "gets run in order" do
+ puts "run the example"
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain:
+open transaction
+run the example
+close transaction
+
+Invoke the example using run()
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "around hook" do
+ around(:example) do |example|
+ puts "around example before"
+ example.run
+ puts "around example after"
+ end
+
+ it "gets run in order" do
+ puts "in the example"
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain:
+around example before
+in the example
+around example after
+
+Access the example metadata
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "something" do
+ around(:example) do |example|
+ puts example.metadata[:foo]
+ example.run
+ end
+
+ it "does something", :foo => "this should show up in the output" do
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “this should show up in the output”.
+
+An around hook continues to run even if the example throws an exception
+
+Given a file named “example_spec.rb” with:
+ RSpec.describe "something" do
+ around(:example) do |example|
+ puts "around example setup"
+ example.run
+ puts "around example cleanup"
+ end
+
+ it "still executes the entire around hook" do
+ fail "the example blows up"
+ end
+ end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should contain:
+around example setup
+around example cleanup
+
+Define a global around hook
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |c|
+ c.around(:example) do |example|
+ puts "around example before"
+ example.run
+ puts "around example after"
+ end
+end
+
+RSpec.describe "around filter" do
+ it "gets run in order" do
+ puts "in the example"
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain:
+around example before
+in the example
+around example after
+
+Per example hooks are wrapped by the around hook
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "around filter" do
+ around(:example) do |example|
+ puts "around example before"
+ example.run
+ puts "around example after"
+ end
+
+ before(:example) do
+ puts "before example"
+ end
+
+ after(:example) do
+ puts "after example"
+ end
+
+ it "gets run in order" do
+ puts "in the example"
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain:
+around example before
+before example
+in the example
+after example
+around example after
+
+Context hooks are NOT wrapped by the around hook
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "around filter" do
+ around(:example) do |example|
+ puts "around example before"
+ example.run
+ puts "around example after"
+ end
+
+ before(:context) do
+ puts "before context"
+ end
+
+ after(:context) do
+ puts "after context"
+ end
+
+ it "gets run in order" do
+ puts "in the example"
+ end
+end
+
+When I run rspec --format progress example_spec.rb
+
+Then the output should contain:
+before context
+around example before
+in the example
+around example after
+.after context
+
+Examples run by an around block are run in the configured context
+
+Given a file named “example_spec.rb” with:
+module IncludedInConfigureBlock
+ def included_in_configure_block; true; end
+end
+
+RSpec.configure do |c|
+ c.include IncludedInConfigureBlock
+end
+
+RSpec.describe "around filter" do
+ around(:example) do |example|
+ example.run
+ end
+
+ it "runs the example in the correct context" do
+ expect(included_in_configure_block).to be(true)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “1 example, 0 failure”.
+
+Implicitly pending examples are detected as Not yet implemented
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "implicit pending example" do
+ around(:example) do |example|
+ example.run
+ end
+
+ it "should be detected as Not yet implemented"
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “1 example, 0 failures, 1 pending”
+
+And the output should contain:
+Pending: (Failures listed here are expected and do not affect your suite's status)
+
+ 1) implicit pending example should be detected as Not yet implemented
+ # Not yet implemented
+ # ./example_spec.rb:6
+
+Explicitly pending examples are detected as pending
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "explicit pending example" do
+ around(:example) do |example|
+ example.run
+ end
+
+ it "should be detected as pending" do
+ pending
+ fail
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “1 example, 0 failures, 1 pending”
+
+And the output should contain:
+Pending: (Failures listed here are expected and do not affect your suite's status)
+
+ 1) explicit pending example should be detected as pending
+ # No reason given
+
+Multiple around hooks in the same scope
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "if there are multiple around hooks in the same scope" do
+ around(:example) do |example|
+ puts "first around hook before"
+ example.run
+ puts "first around hook after"
+ end
+
+ around(:example) do |example|
+ puts "second around hook before"
+ example.run
+ puts "second around hook after"
+ end
+
+ it "they should all be run" do
+ puts "in the example"
+ expect(1).to eq(1)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “1 example, 0 failure”
+
+And the output should contain:
+first around hook before
+second around hook before
+in the example
+second around hook after
+first around hook after
+
+around hooks in multiple scopes
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "if there are around hooks in an outer scope" do
+ around(:example) do |example|
+ puts "first outermost around hook before"
+ example.run
+ puts "first outermost around hook after"
+ end
+
+ around(:example) do |example|
+ puts "second outermost around hook before"
+ example.run
+ puts "second outermost around hook after"
+ end
+
+ describe "outer scope" do
+ around(:example) do |example|
+ puts "first outer around hook before"
+ example.run
+ puts "first outer around hook after"
+ end
+
+ around(:example) do |example|
+ puts "second outer around hook before"
+ example.run
+ puts "second outer around hook after"
+ end
+
+ describe "inner scope" do
+ around(:example) do |example|
+ puts "first inner around hook before"
+ example.run
+ puts "first inner around hook after"
+ end
+
+ around(:example) do |example|
+ puts "second inner around hook before"
+ example.run
+ puts "second inner around hook after"
+ end
+
+ it "they should all be run" do
+ puts "in the example"
+ end
+ end
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “1 example, 0 failure”
+
+And the output should contain:
+first outermost around hook before
+second outermost around hook before
+first outer around hook before
+second outer around hook before
+first inner around hook before
+second inner around hook before
+in the example
+second inner around hook after
+first inner around hook after
+second outer around hook after
+first outer around hook after
+second outermost around hook after
+first outermost around hook after
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/hooks/before-and-after-hooks/index.html b/docs/features/3-12/rspec-core/hooks/before-and-after-hooks/index.html
new file mode 100644
index 000000000..f4e52a39c
--- /dev/null
+++ b/docs/features/3-12/rspec-core/hooks/before-and-after-hooks/index.html
@@ -0,0 +1,479 @@
+
+
+
+
+before and after hooks
+
+Use before and after hooks to execute arbitrary code before and/or after
+ the body of an example is run:
+ before(:example) # run before each example
+ before(:context) # run one time only, before all of the examples in a group
+
+ after(:example) # run after each example
+ after(:context) # run one time only, after all of the examples in a group
+
+before and after blocks are called in the following order:
+ before :suite
+ before :context
+ before :example
+ after :example
+ after :context
+ after :suite
+
+A bare before or after hook defaults to the :example scope.
+
+before and after hooks can be defined directly in the example groups they
+ should run in, or in a global RSpec.configure block. Note that the status of
+ the example does not affect the hooks.
+
+WARNING: Setting instance variables are not supported in before(:suite).
+
+WARNING: Mocks are only supported in before(:example).
+
+WARNING: around hooks will execute before any before hooks, and after
+ any after hooks regardless of the context they were defined in.
+
+Note: the :example and :context scopes are also available as :each and
+ :all, respectively. Use whichever you prefer.
+
+Define before(:example) block
+
+Given a file named “beforeexamplespec.rb” with:
+require "rspec/expectations"
+
+class Thing
+ def widgets
+ @widgets ||= []
+ end
+end
+
+RSpec.describe Thing do
+ before(:example) do
+ @thing = Thing.new
+ end
+
+ describe "initialized in before(:example)" do
+ it "has 0 widgets" do
+ expect(@thing.widgets.count).to eq(0)
+ end
+
+ it "can accept new widgets" do
+ @thing.widgets << Object.new
+ end
+
+ it "does not share state across examples" do
+ expect(@thing.widgets.count).to eq(0)
+ end
+ end
+end
+
+When I run rspec before_example_spec.rb
+
+Then the examples should all pass.
+
+Define before(:context) block in example group
+
+Given a file named “beforecontextspec.rb” with:
+require "rspec/expectations"
+
+class Thing
+ def widgets
+ @widgets ||= []
+ end
+end
+
+RSpec.describe Thing do
+ before(:context) do
+ @thing = Thing.new
+ end
+
+ describe "initialized in before(:context)" do
+ it "has 0 widgets" do
+ expect(@thing.widgets.count).to eq(0)
+ end
+
+ it "can accept new widgets" do
+ @thing.widgets << Object.new
+ end
+
+ it "shares state across examples" do
+ expect(@thing.widgets.count).to eq(1)
+ end
+ end
+end
+
+When I run rspec before_context_spec.rb
+
+Then the examples should all pass
+
+When I run rspec before_context_spec.rb:15
+
+Then the examples should all pass.
+
+Failure in before(:context) block
+
+Given a file named “beforecontextspec.rb” with:
+RSpec.describe "an error in before(:context)" do
+ before(:context) do
+ raise "oops"
+ end
+
+ it "fails this example" do
+ end
+
+ it "fails this example, too" do
+ end
+
+ after(:context) do
+ puts "after context ran"
+ end
+
+ describe "nested group" do
+ it "fails this third example" do
+ end
+
+ it "fails this fourth example" do
+ end
+
+ describe "yet another level deep" do
+ it "fails this last example" do
+ end
+ end
+ end
+end
+
+When I run rspec before_context_spec.rb --format documentation
+
+Then the output should contain “5 examples, 5 failures”
+
+And the output should contain:
+an error in before(:context)
+ fails this example (FAILED - 1)
+ fails this example, too (FAILED - 2)
+ nested group
+ fails this third example (FAILED - 3)
+ fails this fourth example (FAILED - 4)
+ yet another level deep
+ fails this last example (FAILED - 5)
+after context ran
+
+When I run rspec before_context_spec.rb:9 --format documentation
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should contain:
+an error in before(:context)
+ fails this example, too (FAILED - 1)
+
+Failure in after(:context) block
+
+Given a file named “aftercontextspec.rb” with:
+RSpec.describe "an error in after(:context)" do
+ after(:context) do
+ raise StandardError.new("Boom!")
+ end
+
+ it "passes this example" do
+ end
+
+ it "passes this example, too" do
+ end
+end
+
+When I run rspec after_context_spec.rb
+
+Then it should fail with:
+An error occurred in an `after(:context)` hook.
+Failure/Error: raise StandardError.new("Boom!")
+
+StandardError:
+ Boom!
+# ./after_context_spec.rb:3
+
+A failure in an example does not affect hooks
+
+Given a file named “failureinexample_spec.rb” with:
+RSpec.describe "a failing example does not affect hooks" do
+ before(:context) { puts "before context runs" }
+ before(:example) { puts "before example runs" }
+ after(:example) { puts "after example runs" }
+ after(:context) { puts "after context runs" }
+
+ it "fails the example but runs the hooks" do
+ raise "An Error"
+ end
+end
+
+When I run rspec failure_in_example_spec.rb
+
+Then it should fail with:
+before context runs
+before example runs
+after example runs
+Fafter context runs
+
+Define before and after blocks in configuration
+
+Given a file named “beforesinconfiguration_spec.rb” with:
+require "rspec/expectations"
+
+RSpec.configure do |config|
+ config.before(:example) do
+ @before_example = "before example"
+ end
+ config.before(:context) do
+ @before_context = "before context"
+ end
+end
+
+RSpec.describe "stuff in before blocks" do
+ describe "with :context" do
+ it "should be available in the example" do
+ expect(@before_context).to eq("before context")
+ end
+ end
+ describe "with :example" do
+ it "should be available in the example" do
+ expect(@before_example).to eq("before example")
+ end
+ end
+end
+
+When I run rspec befores_in_configuration_spec.rb
+
+Then the examples should all pass.
+
+before/after blocks are run in order
+
+Given a file named “ensureblockorder_spec.rb” with:
+require "rspec/expectations"
+
+RSpec.describe "before and after callbacks" do
+ before(:context) do
+ puts "before context"
+ end
+
+ before(:example) do
+ puts "before example"
+ end
+
+ before do
+ puts "also before example but by default"
+ end
+
+ after(:example) do
+ puts "after example"
+ end
+
+ after do
+ puts "also after example but by default"
+ end
+
+ after(:context) do
+ puts "after context"
+ end
+
+ it "gets run in order" do
+
+ end
+end
+
+When I run rspec --format progress ensure_block_order_spec.rb
+
+Then the output should contain:
+before context
+before example
+also before example but by default
+also after example but by default
+after example
+.after context
+
+before/after blocks defined in configuration are run in order
+
+Given a file named “configuration_spec.rb” with:
+require "rspec/expectations"
+
+RSpec.configure do |config|
+ config.before(:suite) do
+ puts "before suite"
+ end
+
+ config.before(:context) do
+ puts "before context"
+ end
+
+ config.before(:example) do
+ puts "before example"
+ end
+
+ config.after(:example) do
+ puts "after example"
+ end
+
+ config.after(:context) do
+ puts "after context"
+ end
+
+ config.after(:suite) do
+ puts "after suite"
+ end
+end
+
+RSpec.describe "ignore" do
+ example "ignore" do
+ end
+end
+
+When I run rspec --format progress configuration_spec.rb
+
+Then the output should contain:
+before suite
+before context
+before example
+after example
+.after context
+after suite
+
+before/after context blocks are run once
+
+Given a file named “beforeandaftercontextspec.rb” with:
+RSpec.describe "before and after callbacks" do
+ before(:context) do
+ puts "outer before context"
+ end
+
+ example "in outer group" do
+ end
+
+ after(:context) do
+ puts "outer after context"
+ end
+
+ describe "nested group" do
+ before(:context) do
+ puts "inner before context"
+ end
+
+ example "in nested group" do
+ end
+
+ after(:context) do
+ puts "inner after context"
+ end
+ end
+
+end
+
+When I run rspec --format progress before_and_after_context_spec.rb
+
+Then the examples should all pass
+
+And the output should contain:
+outer before context
+.inner before context
+.inner after context
+outer after context
+
+When I run rspec --format progress before_and_after_context_spec.rb:14
+
+Then the examples should all pass
+
+And the output should contain:
+outer before context
+inner before context
+.inner after context
+outer after context
+
+When I run rspec --format progress before_and_after_context_spec.rb:6
+
+Then the examples should all pass
+
+And the output should contain:
+outer before context
+.outer after context
+
+Nested examples have access to state set in outer before(:context)
+
+Given a file named “beforecontextspec.rb” with:
+RSpec.describe "something" do
+ before :context do
+ @value = 123
+ end
+
+ describe "nested" do
+ it "access state set in before(:context)" do
+ expect(@value).to eq(123)
+ end
+
+ describe "nested more deeply" do
+ it "access state set in before(:context)" do
+ expect(@value).to eq(123)
+ end
+ end
+ end
+
+ describe "nested in parallel" do
+ it "access state set in before(:context)" do
+ expect(@value).to eq(123)
+ end
+ end
+end
+
+When I run rspec before_context_spec.rb
+
+Then the examples should all pass.
+
+before/after context blocks have access to state
+
+Given a file named “beforeandaftercontextspec.rb” with:
+RSpec.describe "before and after callbacks" do
+ before(:context) do
+ @outer_state = "set in outer before context"
+ end
+
+ example "in outer group" do
+ expect(@outer_state).to eq("set in outer before context")
+ end
+
+ describe "nested group" do
+ before(:context) do
+ @inner_state = "set in inner before context"
+ end
+
+ example "in nested group" do
+ expect(@outer_state).to eq("set in outer before context")
+ expect(@inner_state).to eq("set in inner before context")
+ end
+
+ after(:context) do
+ expect(@inner_state).to eq("set in inner before context")
+ end
+ end
+
+ after(:context) do
+ expect(@outer_state).to eq("set in outer before context")
+ end
+end
+
+When I run rspec before_and_after_context_spec.rb
+
+Then the examples should all pass.
+
+Exception in before(:example) is captured and reported as failure
+
+Given a file named “errorinbeforeexamplespec.rb” with:
+RSpec.describe "error in before(:example)" do
+ before(:example) do
+ raise "this error"
+ end
+
+ it "is reported as failure" do
+ end
+end
+
+When I run rspec error_in_before_example_spec.rb
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should contain “this error”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/hooks/filtering/index.html b/docs/features/3-12/rspec-core/hooks/filtering/index.html
new file mode 100644
index 000000000..ec831cfc9
--- /dev/null
+++ b/docs/features/3-12/rspec-core/hooks/filtering/index.html
@@ -0,0 +1,440 @@
+
+
+
+
+Filtering
+
+before, after, and around hooks defined in the block passed to
+ RSpec.configure can be constrained to specific examples and/or groups using
+ metadata as a filter.
+ RSpec.configure do |c|
+ c.before(:example, :type => :model) do
+ end
+ end
+
+ RSpec.describe "something", :type => :model do
+ end
+
+Note that filtered :context hooks will still be applied to individual examples with matching metadata – in effect, every example has a singleton example group containing just the one example (analogous to Ruby’s singleton classes).
+
+You can also specify metadata using only symbols.
+
+Filter before(:example) hooks using arbitrary metadata
+
+Given a file named “filterbeforeexamplehooksspec.rb” with:
+RSpec.configure do |config|
+ config.before(:example, :foo => :bar) do
+ invoked_hooks << :before_example_foo_bar
+ end
+end
+
+RSpec.describe "a filtered before :example hook" do
+ let(:invoked_hooks) { [] }
+
+ describe "group without matching metadata" do
+ it "does not run the hook" do
+ expect(invoked_hooks).to be_empty
+ end
+
+ it "runs the hook for an example with matching metadata", :foo => :bar do
+ expect(invoked_hooks).to eq([:before_example_foo_bar])
+ end
+ end
+
+ describe "group with matching metadata", :foo => :bar do
+ it "runs the hook" do
+ expect(invoked_hooks).to eq([:before_example_foo_bar])
+ end
+ end
+end
+
+When I run rspec filter_before_example_hooks_spec.rb
+
+Then the examples should all pass.
+
+Filter after(:example) hooks using arbitrary metadata
+
+Given a file named “filterafterexamplehooksspec.rb” with:
+RSpec.configure do |config|
+ config.after(:example, :foo => :bar) do
+ raise "boom!"
+ end
+end
+
+RSpec.describe "a filtered after :example hook" do
+ describe "group without matching metadata" do
+ it "does not run the hook" do
+ # should pass
+ end
+
+ it "runs the hook for an example with matching metadata", :foo => :bar do
+ # should fail
+ end
+ end
+
+ describe "group with matching metadata", :foo => :bar do
+ it "runs the hook" do
+ # should fail
+ end
+ end
+end
+
+When I run rspec filter_after_example_hooks_spec.rb
+
+Then the output should contain “3 examples, 2 failures”.
+
+Filter around(:example) hooks using arbitrary metadata
+
+Given a file named “filteraroundexamplehooksspec.rb” with:
+RSpec.configure do |config|
+ config.around(:example, :foo => :bar) do |example|
+ order << :before_around_example_foo_bar
+ example.run
+ expect(order).to eq([:before_around_example_foo_bar, :example])
+ end
+end
+
+RSpec.describe "a filtered around(:example) hook" do
+ let(:order) { [] }
+
+ describe "a group without matching metadata" do
+ it "does not run the hook" do
+ expect(order).to be_empty
+ end
+
+ it "runs the hook for an example with matching metadata", :foo => :bar do
+ expect(order).to eq([:before_around_example_foo_bar])
+ order << :example
+ end
+ end
+
+ describe "a group with matching metadata", :foo => :bar do
+ it "runs the hook for an example with matching metadata", :foo => :bar do
+ expect(order).to eq([:before_around_example_foo_bar])
+ order << :example
+ end
+ end
+end
+
+When I run rspec filter_around_example_hooks_spec.rb
+
+Then the examples should all pass.
+
+Filter before(:context) hooks using arbitrary metadata
+
+Given a file named “filterbeforecontexthooksspec.rb” with:
+RSpec.configure do |config|
+ config.before(:context, :foo => :bar) { @hook = :before_context_foo_bar }
+end
+
+RSpec.describe "a filtered before(:context) hook" do
+ describe "a group without matching metadata" do
+ it "does not run the hook" do
+ expect(@hook).to be_nil
+ end
+
+ it "runs the hook for a single example with matching metadata", :foo => :bar do
+ expect(@hook).to eq(:before_context_foo_bar)
+ end
+
+ describe "a nested subgroup with matching metadata", :foo => :bar do
+ it "runs the hook" do
+ expect(@hook).to eq(:before_context_foo_bar)
+ end
+ end
+ end
+
+ describe "a group with matching metadata", :foo => :bar do
+ it "runs the hook" do
+ expect(@hook).to eq(:before_context_foo_bar)
+ end
+
+ describe "a nested subgroup" do
+ it "runs the hook" do
+ expect(@hook).to eq(:before_context_foo_bar)
+ end
+ end
+ end
+end
+
+When I run rspec filter_before_context_hooks_spec.rb
+
+Then the examples should all pass.
+
+Filter after(:context) hooks using arbitrary metadata
+
+Given a file named “filteraftercontexthooksspec.rb” with:
+example_msgs = []
+
+RSpec.configure do |config|
+ config.after(:context, :foo => :bar) do
+ puts "after :context"
+ end
+end
+
+RSpec.describe "a filtered after(:context) hook" do
+ describe "a group without matching metadata" do
+ it "does not run the hook" do
+ puts "unfiltered"
+ end
+
+ it "runs the hook for a single example with matching metadata", :foo => :bar do
+ puts "filtered 1"
+ end
+ end
+
+ describe "a group with matching metadata", :foo => :bar do
+ it "runs the hook" do
+ puts "filtered 2"
+ end
+ end
+
+ describe "another group without matching metadata" do
+ describe "a nested subgroup with matching metadata", :foo => :bar do
+ it "runs the hook" do
+ puts "filtered 3"
+ end
+ end
+ end
+end
+
+When I run rspec --format progress filter_after_context_hooks_spec.rb --order defined
+
+Then the examples should all pass
+
+And the output should contain:
+unfiltered
+.filtered 1
+after :context
+.filtered 2
+.after :context
+filtered 3
+.after :context
+
+Use symbols as metadata
+
+Given a file named “lessverbosemetadata_filter.rb” with:
+RSpec.configure do |c|
+ c.before(:example, :before_example) { puts "before example" }
+ c.after(:example, :after_example) { puts "after example" }
+ c.around(:example, :around_example) do |example|
+ puts "around example (before)"
+ example.run
+ puts "around example (after)"
+ end
+ c.before(:context, :before_context) { puts "before context" }
+ c.after(:context, :after_context) { puts "after context" }
+end
+
+RSpec.describe "group 1", :before_context, :after_context do
+ it("") { puts "example 1" }
+ it("", :before_example) { puts "example 2" }
+ it("", :after_example) { puts "example 3" }
+ it("", :around_example) { puts "example 4" }
+end
+
+When I run rspec --format progress less_verbose_metadata_filter.rb
+
+Then the examples should all pass
+
+And the output should contain:
+before context
+example 1
+.before example
+example 2
+.example 3
+after example
+.around example (before)
+example 4
+around example (after)
+.after context
+
+Filtering hooks using symbols
+
+Given a file named “filterexamplehookswithsymbol_spec.rb” with:
+RSpec.configure do |config|
+ config.before(:example, :foo) do
+ invoked_hooks << :before_example_foo_bar
+ end
+end
+
+RSpec.describe "a filtered before :example hook" do
+ let(:invoked_hooks) { [] }
+
+ describe "group without a matching metadata key" do
+ it "does not run the hook" do
+ expect(invoked_hooks).to be_empty
+ end
+
+ it "does not run the hook for an example with metadata hash containing the key with a falsey value", :foo => nil do
+ expect(invoked_hooks).to be_empty
+ end
+
+ it "runs the hook for an example with metadata hash containing the key with a truthy value", :foo => :bar do
+ expect(invoked_hooks).to eq([:before_example_foo_bar])
+ end
+
+ it "runs the hook for an example with only the key defined", :foo do
+ expect(invoked_hooks).to eq([:before_example_foo_bar])
+ end
+ end
+
+ describe "group with matching metadata key", :foo do
+ it "runs the hook" do
+ expect(invoked_hooks).to eq([:before_example_foo_bar])
+ end
+ end
+end
+
+When I run rspec filter_example_hooks_with_symbol_spec.rb
+
+Then the examples should all pass.
+
+Filtering hooks using a hash
+
+Given a file named “filterexamplehookswithhash_spec.rb” with:
+RSpec.configure do |config|
+ config.before(:example, :foo => { :bar => :baz, :slow => true }) do
+ invoked_hooks << :before_example_foo_bar
+ end
+end
+
+RSpec.describe "a filtered before :example hook" do
+ let(:invoked_hooks) { [] }
+
+ describe "group without matching metadata" do
+ it "does not run the hook" do
+ expect(invoked_hooks).to be_empty
+ end
+
+ it "does not run the hook for an example if only part of the filter matches", :foo => { :bar => :baz } do
+ expect(invoked_hooks).to be_empty
+ end
+
+ it "runs the hook for an example if the metadata contains all key value pairs from the filter", :foo => { :bar => :baz, :slow => true, :extra => :pair } do
+ expect(invoked_hooks).to eq([:before_example_foo_bar])
+ end
+ end
+
+ describe "group with matching metadata", :foo => { :bar => :baz, :slow => true } do
+ it "runs the hook" do
+ expect(invoked_hooks).to eq([:before_example_foo_bar])
+ end
+ end
+end
+
+When I run rspec filter_example_hooks_with_hash_spec.rb
+
+Then the examples should all pass.
+
+Filtering hooks using a Proc
+
+Given a file named “filterexamplehookswithproc_spec.rb” with:
+RSpec.configure do |config|
+ config.before(:example, :foo => Proc.new { |value| value.is_a?(String) } ) do
+ invoked_hooks << :before_example_foo_bar
+ end
+end
+
+RSpec.describe "a filtered before :example hook" do
+ let(:invoked_hooks) { [] }
+
+ describe "group without matching metadata" do
+ it "does not run the hook" do
+ expect(invoked_hooks).to be_empty
+ end
+
+ it "does not run the hook if the proc returns false", :foo => :bar do
+ expect(invoked_hooks).to be_empty
+ end
+
+ it "runs the hook if the proc returns true", :foo => 'bar' do
+ expect(invoked_hooks).to eq([:before_example_foo_bar])
+ end
+ end
+
+ describe "group with matching metadata", :foo => 'bar' do
+ it "runs the hook" do
+ expect(invoked_hooks).to eq([:before_example_foo_bar])
+ end
+ end
+end
+
+When I run rspec filter_example_hooks_with_proc_spec.rb
+
+Then the examples should all pass.
+
+Filtering hooks using a regular expression
+
+Given a file named “filterexamplehookswithregexp_spec.rb” with:
+RSpec.configure do |config|
+ config.before(:example, :foo => /bar/ ) do
+ invoked_hooks << :before_example_foo_bar
+ end
+end
+
+RSpec.describe "a filtered before :example hook" do
+ let(:invoked_hooks) { [] }
+
+ describe "group without matching metadata" do
+ it "does not run the hook" do
+ expect(invoked_hooks).to be_empty
+ end
+
+ it "does not run the hook if the value does not match", :foo => 'baz' do
+ expect(invoked_hooks).to be_empty
+ end
+
+ it "runs the hook if the value matches", :foo => 'bar' do
+ expect(invoked_hooks).to eq([:before_example_foo_bar])
+ end
+ end
+
+ describe "group with matching metadata", :foo => 'bar' do
+ it "runs the hook" do
+ expect(invoked_hooks).to eq([:before_example_foo_bar])
+ end
+ end
+end
+
+When I run rspec filter_example_hooks_with_regexp_spec.rb
+
+Then the examples should all pass.
+
+Filtering hooks using string comparison
+
+Given a file named “filterexamplehookswithstrcmp_spec.rb” with:
+RSpec.configure do |config|
+ config.before(:example, :foo => :bar ) do
+ invoked_hooks << :before_example_foo_bar
+ end
+end
+
+RSpec.describe "a filtered before :example hook" do
+ let(:invoked_hooks) { [] }
+
+ describe "group without matching metadata" do
+ it "does not run the hook" do
+ expect(invoked_hooks).to be_empty
+ end
+
+ it "does not run the hook if the coerced values do not match", :foo => 'baz' do
+ expect(invoked_hooks).to be_empty
+ end
+
+ it "runs the hook if the coerced values match", :foo => 'bar' do
+ expect(invoked_hooks).to eq([:before_example_foo_bar])
+ end
+ end
+
+ describe "group with matching metadata", :foo => 'bar' do
+ it "runs the hook" do
+ expect(invoked_hooks).to eq([:before_example_foo_bar])
+ end
+ end
+end
+
+When I run rspec filter_example_hooks_with_strcmp_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/hooks/index.html b/docs/features/3-12/rspec-core/hooks/index.html
new file mode 100644
index 000000000..27e0aaef8
--- /dev/null
+++ b/docs/features/3-12/rspec-core/hooks/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Hooks
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/hooks/when-first-matching-example-defined/index.html b/docs/features/3-12/rspec-core/hooks/when-first-matching-example-defined/index.html
new file mode 100644
index 000000000..c69ecc02d
--- /dev/null
+++ b/docs/features/3-12/rspec-core/hooks/when-first-matching-example-defined/index.html
@@ -0,0 +1,73 @@
+
+
+
+
+Using when_first_matching_example_defined hook
+
+In large projects that use RSpec, it’s common to have some expensive setup logic
+ that is only needed when certain kinds of specs have been loaded. If that kind of
+ spec has not been loaded, you’d prefer to avoid the cost of doing the setup.
+
+The when_first_matching_example_defined hook makes it easy to conditionally
+ perform some logic when the first example is defined with matching metadata,
+ allowing you to ensure the necessary setup is performed only when needed.
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.when_first_matching_example_defined(:db) do
+ require "support/db"
+ end
+end
+
+And a file named “spec/support/db.rb” with:
+RSpec.configure do |config|
+ config.before(:suite) do
+ puts "Bootstrapped the DB."
+ end
+
+ config.around(:example, :db) do |example|
+ puts "Starting a DB transaction."
+ example.run
+ puts "Rolling back a DB transaction."
+ end
+end
+
+And a file named “.rspec” with:
+--require spec_helper
+
+And a file named “spec/unit_spec.rb” with:
+RSpec.describe "A unit spec" do
+ it "does not require a database" do
+ puts "in unit example"
+ end
+end
+
+And a file named “spec/integration_spec.rb” with:
+RSpec.describe "An integration spec", :db do
+ it "requires a database" do
+ puts "in integration example"
+ end
+end
+
+Running the entire suite loads the DB setup
+
+When I run rspec
+
+Then it should pass with:
+Bootstrapped the DB.
+Starting a DB transaction.
+in integration example
+Rolling back a DB transaction.
+.in unit example
+.
+
+Running just the unit spec does not load the DB setup
+
+When I run rspec spec/unit_spec.rb
+
+Then the examples should all pass
+
+And the output should not contain “DB”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/index.html b/docs/features/3-12/rspec-core/index.html
new file mode 100644
index 000000000..0cd984bcf
--- /dev/null
+++ b/docs/features/3-12/rspec-core/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+RSpec Core
+
+rspec-core provides the structure for RSpec code examples:
+RSpec.describe Account do
+ it "has a balance of zero when first opened" do
+ # example code goes here - for more on the
+ # code inside the examples, see rspec-expectations
+ # and rspec-mocks
+ end
+end
+
+Issues
+
+This documentation is open source, and a work in progress. If you find it incomplete or confusing, please submit an issue, or, better yet, a pull request.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/metadata/current-example/index.html b/docs/features/3-12/rspec-core/metadata/current-example/index.html
new file mode 100644
index 000000000..937e659b3
--- /dev/null
+++ b/docs/features/3-12/rspec-core/metadata/current-example/index.html
@@ -0,0 +1,62 @@
+
+
+
+
+Using the current example
+
+You can reference the example object, and access its metadata, using the block
+ argument provided to: it, subject, let, and the before, after, and
+ around hooks.
+
+Access the example object from within an example
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.describe "example as block arg to it, before, and after" do
+ before do |example|
+ expect(example.description).to eq("is the example object")
+ end
+
+ after do |example|
+ expect(example.description).to eq("is the example object")
+ end
+
+ it "is the example object" do |example|
+ expect(example.description).to eq("is the example object")
+ end
+end
+
+RSpec.describe "example as block arg to let" do
+ let(:the_description) do |example|
+ example.description
+ end
+
+ it "is the example object" do |example|
+ expect(the_description).to eq("is the example object")
+ end
+end
+
+RSpec.describe "example as block arg to subject" do
+ subject do |example|
+ example.description
+ end
+
+ it "is the example object" do |example|
+ expect(subject).to eq("is the example object")
+ end
+end
+
+RSpec.describe "example as block arg to subject with a name" do
+ subject(:the_subject) do |example|
+ example.description
+ end
+
+ it "is the example object" do |example|
+ expect(the_subject).to eq("is the example object")
+ expect(subject).to eq("is the example object")
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/metadata/current-scope/index.html b/docs/features/3-12/rspec-core/metadata/current-scope/index.html
new file mode 100644
index 000000000..7cb2f4133
--- /dev/null
+++ b/docs/features/3-12/rspec-core/metadata/current-scope/index.html
@@ -0,0 +1,93 @@
+
+
+
+
+RSpec provides the current scope as RSpec.current_scope
+
+You can detect which rspec scope your helper methods or library code is executing in.
+ This is useful if for example, your method only makes sense to call in a certain context.
+
+Detecting the current scope
+
+Given a file named “currentscopespec.rb” with:
+# Outside of the test lifecycle, the current scope is `:suite`
+exit(1) unless RSpec.current_scope == :suite
+
+at_exit do
+ exit(1) unless RSpec.current_scope == :suite
+end
+
+RSpec.configure do |c|
+ c.before :suite do
+ expect(RSpec.current_scope).to eq(:before_suite_hook)
+ end
+
+ c.before :context do
+ expect(RSpec.current_scope).to eq(:before_context_hook)
+ end
+
+ c.before :example do
+ expect(RSpec.current_scope).to eq(:before_example_hook)
+ end
+
+ c.around :example do |ex|
+ expect(RSpec.current_scope).to eq(:before_example_hook)
+ ex.run
+ expect(RSpec.current_scope).to eq(:after_example_hook)
+ end
+
+ c.after :example do
+ expect(RSpec.current_scope).to eq(:after_example_hook)
+ end
+
+ c.after :context do
+ expect(RSpec.current_scope).to eq(:after_context_hook)
+ end
+
+ c.after :suite do
+ expect(RSpec.current_scope).to eq(:after_suite_hook)
+ end
+end
+
+RSpec.describe "RSpec.current_scope" do
+ before :context do
+ expect(RSpec.current_scope).to eq(:before_context_hook)
+ end
+
+ before :example do
+ expect(RSpec.current_scope).to eq(:before_example_hook)
+ end
+
+ around :example do |ex|
+ expect(RSpec.current_scope).to eq(:before_example_hook)
+ ex.run
+ expect(RSpec.current_scope).to eq(:after_example_hook)
+ end
+
+ after :example do
+ expect(RSpec.current_scope).to eq(:after_example_hook)
+ end
+
+ after :context do
+ expect(RSpec.current_scope).to eq(:after_context_hook)
+ end
+
+ it "is :example in an example" do
+ expect(RSpec.current_scope).to eq(:example)
+ end
+
+ it "works for multiple examples" do
+ expect(RSpec.current_scope).to eq(:example)
+ end
+
+ describe "in nested describe blocks" do
+ it "still works" do
+ expect(RSpec.current_scope).to eq(:example)
+ end
+ end
+end
+
+When I run rspec current_scope_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/metadata/described-class/index.html b/docs/features/3-12/rspec-core/metadata/described-class/index.html
new file mode 100644
index 000000000..6793b72db
--- /dev/null
+++ b/docs/features/3-12/rspec-core/metadata/described-class/index.html
@@ -0,0 +1,30 @@
+
+
+
+
+Using described_class
+
+If the first argument to an example group is a class, the class is exposed to
+ each example in that example group via the described_class() method.
+
+Access the described class from the example
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.describe Symbol do
+ it "is available as described_class" do
+ expect(described_class).to eq(Symbol)
+ end
+
+ describe 'inner' do
+ describe String do
+ it "is available as described_class" do
+ expect(described_class).to eq(String)
+ end
+ end
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/metadata/index.html b/docs/features/3-12/rspec-core/metadata/index.html
new file mode 100644
index 000000000..2bb911172
--- /dev/null
+++ b/docs/features/3-12/rspec-core/metadata/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Metadata
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/metadata/user-defined/index.html b/docs/features/3-12/rspec-core/metadata/user-defined/index.html
new file mode 100644
index 000000000..06e31053a
--- /dev/null
+++ b/docs/features/3-12/rspec-core/metadata/user-defined/index.html
@@ -0,0 +1,109 @@
+
+
+
+
+User-defined metadata
+
+You can attach user-defined metadata to any example group or example. Pass a
+ hash as the last argument (before the block) to describe, context or it.
+ RSpec supports many configuration options that apply only to certain examples
+ or groups based on the metadata.
+
+Metadata defined on an example group is available (and can be overridden) by
+ any sub-group or from any example in that group or a sub-group.
+
+In addition, you can specify metadata using just symbols. Each symbol passed
+ as an argument to describe, context or it will be a key in the metadata
+ hash, with a corresponding value of true.
+
+Define group metadata using a hash
+
+Given a file named “definegroupmetadatawithhash_spec.rb” with:
+RSpec.describe "a group with user-defined metadata", :foo => 17 do
+ it 'has access to the metadata in the example' do |example|
+ expect(example.metadata[:foo]).to eq(17)
+ end
+
+ it 'does not have access to metadata defined on sub-groups' do |example|
+ expect(example.metadata).not_to include(:bar)
+ end
+
+ describe 'a sub-group with user-defined metadata', :bar => 12 do
+ it 'has access to the sub-group metadata' do |example|
+ expect(example.metadata[:bar]).to eq(12)
+ end
+
+ it 'also has access to metadata defined on parent groups' do |example|
+ expect(example.metadata[:foo]).to eq(17)
+ end
+ end
+end
+
+When I run rspec define_group_metadata_with_hash_spec.rb
+
+Then the examples should all pass.
+
+Define example metadata using a hash
+
+Given a file named “defineexamplemetadatawithhash_spec.rb” with:
+RSpec.describe "a group with no user-defined metadata" do
+ it 'has an example with metadata', :foo => 17 do |example|
+ expect(example.metadata[:foo]).to eq(17)
+ expect(example.metadata).not_to include(:bar)
+ end
+
+ it 'has another example with metadata', :bar => 12, :bazz => 33 do |example|
+ expect(example.metadata[:bar]).to eq(12)
+ expect(example.metadata[:bazz]).to eq(33)
+ expect(example.metadata).not_to include(:foo)
+ end
+end
+
+When I run rspec define_example_metadata_with_hash_spec.rb
+
+Then the examples should all pass.
+
+Override user-defined metadata
+
+Given a file named “overridemetadataspec.rb” with:
+RSpec.describe "a group with user-defined metadata", :foo => 'bar' do
+ it 'can be overridden by an example', :foo => 'bazz' do |example|
+ expect(example.metadata[:foo]).to eq('bazz')
+ end
+
+ describe "a sub-group with an override", :foo => 'goo' do
+ it 'can be overridden by a sub-group' do |example|
+ expect(example.metadata[:foo]).to eq('goo')
+ end
+ end
+end
+
+When I run rspec override_metadata_spec.rb
+
+Then the examples should all pass.
+
+Less verbose metadata
+
+Given a file named “lessverbosemetadata_spec.rb” with:
+RSpec.describe "a group with simple metadata", :fast, :simple, :bug => 73 do
+ it 'has `:fast => true` metadata' do |example|
+ expect(example.metadata[:fast]).to eq(true)
+ end
+
+ it 'has `:simple => true` metadata' do |example|
+ expect(example.metadata[:simple]).to eq(true)
+ end
+
+ it 'can still use a hash for metadata' do |example|
+ expect(example.metadata[:bug]).to eq(73)
+ end
+
+ it 'can define simple metadata on an example', :special do |example|
+ expect(example.metadata[:special]).to eq(true)
+ end
+end
+
+When I run rspec less_verbose_metadata_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/mock-framework-integration/index.html b/docs/features/3-12/rspec-core/mock-framework-integration/index.html
new file mode 100644
index 000000000..2d26f9690
--- /dev/null
+++ b/docs/features/3-12/rspec-core/mock-framework-integration/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Mock framework integration
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/mock-framework-integration/use-any-framework/index.html b/docs/features/3-12/rspec-core/mock-framework-integration/use-any-framework/index.html
new file mode 100644
index 000000000..7efa6b4c3
--- /dev/null
+++ b/docs/features/3-12/rspec-core/mock-framework-integration/use-any-framework/index.html
@@ -0,0 +1,123 @@
+
+
+
+
+Mocking with an alternative framework
+
+In addition to rspec, mocha, flexmock, and RR, you can choose an alternate
+ framework as the mocking framework. You (or the framework authors) just needs
+ to provide an adapter that hooks RSpec’s events into those of the framework.
+
+A mock framework adapter must expose three methods:
+
+
+setup_mocks_for_rspec
+
+
+- called before each example is run
+
+verify_mocks_for_rspec
+
+
+- called after each example is run
+- this is where message expectation failures should result in an error with
+the appropriate failure message
+
+teardown_mocks_for_rspec
+
+
+- called after
verify_mocks_for_rspec
+- use this to clean up resources, restore objects to earlier state, etc
+- guaranteed to run even if there are failures
+
+
+
+Mock with alternate framework
+
+Given a file named “expector.rb” with:
+class Expector
+ class << self
+ def expectors
+ @expectors ||= []
+ end
+
+ def clear_expectors
+ expectors.clear
+ end
+
+ def verify_expectors
+ expectors.each {|d| d.verify}
+ end
+ end
+
+ def initialize
+ self.class.expectors << self
+ end
+
+ def expectations
+ @expectations ||= []
+ end
+
+ def expect(message)
+ expectations << message.to_s
+ end
+
+ def verify
+ unless expectations.empty?
+ raise expectations.map {|e|
+ "expected #{e}, but it was never received"
+ }.join("\n")
+ end
+ end
+
+private
+
+ def method_missing(name, *args, &block)
+ expectations.delete(name.to_s)
+ end
+
+public
+
+ module RSpecAdapter
+ def setup_mocks_for_rspec
+ # no setup necessary
+ end
+
+ def verify_mocks_for_rspec
+ Expector.verify_expectors
+ end
+
+ def teardown_mocks_for_rspec
+ Expector.clear_expectors
+ end
+ end
+end
+
+Given a file named “example_spec.rb” with:
+require File.expand_path("../expector", __FILE__)
+
+RSpec.configure do |config|
+ config.mock_with Expector::RSpecAdapter
+end
+
+RSpec.describe Expector do
+ it "passes when message is received" do
+ expector = Expector.new
+ expector.expect(:foo)
+ expector.foo
+ end
+
+ it "fails when message is received" do
+ expector = Expector.new
+ expector.expect(:foo)
+ end
+end
+
+When I run rspec example_spec.rb --format doc
+
+Then the exit status should be 1
+
+And the output should contain “2 examples, 1 failure”
+
+And the output should contain “fails when message is received (FAILED - 1)”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/mock-framework-integration/use-flexmock/index.html b/docs/features/3-12/rspec-core/mock-framework-integration/use-flexmock/index.html
new file mode 100644
index 000000000..6befe43a2
--- /dev/null
+++ b/docs/features/3-12/rspec-core/mock-framework-integration/use-flexmock/index.html
@@ -0,0 +1,107 @@
+
+
+
+
+Mocking with flexmock
+
+Configure RSpec to use flexmock as shown in the scenarios below.
+
+Passing message expectation
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :flexmock
+end
+
+RSpec.describe "mocking with Flexmock" do
+ it "passes when it should" do
+ receiver = flexmock('receiver')
+ receiver.should_receive(:message).once
+ receiver.message
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
+Failing message expectation
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :flexmock
+end
+
+RSpec.describe "mocking with Flexmock" do
+ it "fails when it should" do
+ receiver = flexmock('receiver')
+ receiver.should_receive(:message).once
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “1 example, 1 failure”.
+
+Failing message expectation in pending example (remains pending)
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :flexmock
+end
+
+RSpec.describe "failed message expectation in a pending example" do
+ it "is listed as pending" do
+ pending
+ receiver = flexmock('receiver')
+ receiver.should_receive(:message).once
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “1 example, 0 failures, 1 pending”
+
+And the exit status should be 0.
+
+Passing message expectation in pending example (fails)
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :flexmock
+end
+
+RSpec.describe "passing message expectation in a pending example" do
+ it "fails with FIXED" do
+ pending
+ receiver = flexmock('receiver')
+ receiver.should_receive(:message).once
+ receiver.message
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “FIXED”
+
+Then the output should contain “1 example, 1 failure”
+
+And the exit status should be 1.
+
+Accessing RSpec.configuration.mock_framework.framework_name
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :flexmock
+end
+
+RSpec.describe "RSpec.configuration.mock_framework.framework_name" do
+ it "returns :flexmock" do
+ expect(RSpec.configuration.mock_framework.framework_name).to eq(:flexmock)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/mock-framework-integration/use-mocha/index.html b/docs/features/3-12/rspec-core/mock-framework-integration/use-mocha/index.html
new file mode 100644
index 000000000..cfcc05464
--- /dev/null
+++ b/docs/features/3-12/rspec-core/mock-framework-integration/use-mocha/index.html
@@ -0,0 +1,107 @@
+
+
+
+
+Mocking with mocha
+
+Configure RSpec to use mocha as shown in the scenarios below.
+
+Passing message expectation
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :mocha
+end
+
+RSpec.describe "mocking with RSpec" do
+ it "passes when it should" do
+ receiver = mock('receiver')
+ receiver.expects(:message).once
+ receiver.message
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
+Failing message expectation
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :mocha
+end
+
+RSpec.describe "mocking with RSpec" do
+ it "fails when it should" do
+ receiver = mock('receiver')
+ receiver.expects(:message).once
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “1 example, 1 failure”.
+
+Failing message expectation in pending example (remains pending)
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :mocha
+end
+
+RSpec.describe "failed message expectation in a pending example" do
+ it "is listed as pending" do
+ pending
+ receiver = mock('receiver')
+ receiver.expects(:message).once
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “1 example, 0 failures, 1 pending”
+
+And the exit status should be 0.
+
+Passing message expectation in pending example (fails)
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :mocha
+end
+
+RSpec.describe "passing message expectation in a pending example" do
+ it "fails with FIXED" do
+ pending
+ receiver = mock('receiver')
+ receiver.expects(:message).once
+ receiver.message
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “FIXED”
+
+Then the output should contain “1 example, 1 failure”
+
+And the exit status should be 1.
+
+Accessing RSpec.configuration.mock_framework.framework_name
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :mocha
+end
+
+RSpec.describe "RSpec.configuration.mock_framework.framework_name" do
+ it "returns :mocha" do
+ expect(RSpec.configuration.mock_framework.framework_name).to eq(:mocha)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/mock-framework-integration/use-rr/index.html b/docs/features/3-12/rspec-core/mock-framework-integration/use-rr/index.html
new file mode 100644
index 000000000..de2c2fbba
--- /dev/null
+++ b/docs/features/3-12/rspec-core/mock-framework-integration/use-rr/index.html
@@ -0,0 +1,107 @@
+
+
+
+
+Mocking with rr
+
+Configure RSpec to use rr as shown in the scenarios below.
+
+Passing message expectation
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rr
+end
+
+RSpec.describe "mocking with RSpec" do
+ it "passes when it should" do
+ receiver = Object.new
+ mock(receiver).message
+ receiver.message
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
+Failing message expectation
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rr
+end
+
+RSpec.describe "mocking with RSpec" do
+ it "fails when it should" do
+ receiver = Object.new
+ mock(receiver).message
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “1 example, 1 failure”.
+
+Failing message expectation in pending example (remains pending)
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rr
+end
+
+RSpec.describe "failed message expectation in a pending example" do
+ it "is listed as pending" do
+ pending
+ receiver = Object.new
+ mock(receiver).message
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “1 example, 0 failures, 1 pending”
+
+And the exit status should be 0.
+
+Passing message expectation in pending example (fails)
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rr
+end
+
+RSpec.describe "passing message expectation in a pending example" do
+ it "fails with FIXED" do
+ pending
+ receiver = Object.new
+ mock(receiver).message
+ receiver.message
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “FIXED”
+
+Then the output should contain “1 example, 1 failure”
+
+And the exit status should be 1.
+
+Accessing RSpec.configuration.mock_framework.framework_name
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rr
+end
+
+RSpec.describe "RSpec.configuration.mock_framework.framework_name" do
+ it "returns :rr" do
+ expect(RSpec.configuration.mock_framework.framework_name).to eq(:rr)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/mock-framework-integration/use-rspec/index.html b/docs/features/3-12/rspec-core/mock-framework-integration/use-rspec/index.html
new file mode 100644
index 000000000..59c53b5f6
--- /dev/null
+++ b/docs/features/3-12/rspec-core/mock-framework-integration/use-rspec/index.html
@@ -0,0 +1,127 @@
+
+
+
+
+Mocking with rspec
+
+RSpec uses its own mocking framework by default. You can also configure it
+ explicitly if you wish.
+
+Passing message expectation
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rspec
+end
+
+RSpec.describe "mocking with RSpec" do
+ it "passes when it should" do
+ receiver = double('receiver')
+ expect(receiver).to receive(:message)
+ receiver.message
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
+Failing message expectation
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rspec
+end
+
+RSpec.describe "mocking with RSpec" do
+ it "fails when it should" do
+ receiver = double('receiver')
+ expect(receiver).to receive(:message)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “1 example, 1 failure”.
+
+Failing message expectation in pending example (remains pending)
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rspec
+end
+
+RSpec.describe "failed message expectation in a pending example" do
+ it "is listed as pending" do
+ pending
+ receiver = double('receiver')
+ expect(receiver).to receive(:message)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “1 example, 0 failures, 1 pending”
+
+And the exit status should be 0.
+
+Passing message expectation in pending example (fails)
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rspec
+end
+
+RSpec.describe "passing message expectation in a pending example" do
+ it "fails with FIXED" do
+ pending
+ receiver = double('receiver')
+ expect(receiver).to receive(:message)
+ receiver.message
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain “FIXED”
+
+Then the output should contain “1 example, 1 failure”
+
+And the exit status should be 1.
+
+Accessing RSpec.configuration.mock_framework.framework_name
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rspec
+end
+
+RSpec.describe "RSpec.configuration.mock_framework.framework_name" do
+ it "returns :rspec" do
+ expect(RSpec.configuration.mock_framework.framework_name).to eq(:rspec)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
+Doubles may be used in generated descriptions
+
+Given a file named “example_spec.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rspec
+end
+
+RSpec.describe "Testing" do
+ # Examples with no descriptions will default to RSpec-generated descriptions
+ it do
+ foo = double("Test")
+ expect(foo).to be foo
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/pending-and-skipped-examples/index.html b/docs/features/3-12/rspec-core/pending-and-skipped-examples/index.html
new file mode 100644
index 000000000..b058d049a
--- /dev/null
+++ b/docs/features/3-12/rspec-core/pending-and-skipped-examples/index.html
@@ -0,0 +1,10 @@
+
+
+
+
+Pending and Skipped examples
+
+Sometimes you will have a failing example that can not be fixed, but is useful to keep around. For instance, the fix could depend on an upstream patch being merged, or the example is not supported on JRuby. RSpec provides two features for dealing with this scenario.
+
+An example can either be marked as skipped, in which is it not executed, or pending in which it is executed but failure will not cause a failure of the entire suite. When a pending example passes (i.e. the underlying reasons for it being marked pending is no longer present) it will be marked as failed in order to communicate to you that it should no longer be marked as pending.
+Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/pending-and-skipped-examples/pending-examples/index.html b/docs/features/3-12/rspec-core/pending-and-skipped-examples/pending-examples/index.html
new file mode 100644
index 000000000..72a01cd76
--- /dev/null
+++ b/docs/features/3-12/rspec-core/pending-and-skipped-examples/pending-examples/index.html
@@ -0,0 +1,95 @@
+
+
+
+
+Using pending with examples
+
+RSpec offers a number of different ways to indicate that an example is
+ disabled pending some action.
+
+pending any arbitrary reason with a failing example
+
+Given a file named “pendingwithoutblock_spec.rb” with:
+RSpec.describe "an example" do
+ it "is implemented but waiting" do
+ pending("something else getting finished")
+ fail
+ end
+end
+
+When I run rspec pending_without_block_spec.rb
+
+Then the exit status should be 0
+
+And the output should contain “1 example, 0 failures, 1 pending”
+
+And the output should contain:
+Pending: (Failures listed here are expected and do not affect your suite's status)
+
+ 1) an example is implemented but waiting
+ # something else getting finished
+
+pending any arbitrary reason with a passing example
+
+Given a file named “pendingwithpassingexamplespec.rb” with:
+RSpec.describe "an example" do
+ it "is implemented but waiting" do
+ pending("something else getting finished")
+ expect(1).to be(1)
+ end
+end
+
+When I run rspec pending_with_passing_example_spec.rb
+
+Then the exit status should not be 0
+
+And the output should contain “1 example, 1 failure”
+
+And the output should contain “FIXED”
+
+And the output should contain “Expected pending ‘something else getting finished’ to fail. No error was raised.”
+
+And the output should contain “pendingwithpassingexamplespec.rb:2”.
+
+pending for an example that is currently passing
+
+Given a file named “pendingwithpassingblockspec.rb” with:
+RSpec.describe "an example" do
+ pending("something else getting finished") do
+ expect(1).to eq(1)
+ end
+end
+
+When I run rspec pending_with_passing_block_spec.rb
+
+Then the exit status should not be 0
+
+And the output should contain “1 example, 1 failure”
+
+And the output should contain “FIXED”
+
+And the output should contain “Expected pending ‘No reason given’ to fail. No error was raised.”
+
+And the output should contain “pendingwithpassingblockspec.rb:2”.
+
+pending for an example that is currently passing with a reason
+
+Given a file named “pendingwithpassingblockspec.rb” with:
+RSpec.describe "an example" do
+ example("something else getting finished", :pending => 'unimplemented') do
+ expect(1).to eq(1)
+ end
+end
+
+When I run rspec pending_with_passing_block_spec.rb
+
+Then the exit status should not be 0
+
+And the output should contain “1 example, 1 failure”
+
+And the output should contain “FIXED”
+
+And the output should contain “Expected pending ‘unimplemented’ to fail. No error was raised.”
+
+And the output should contain “pendingwithpassingblockspec.rb:2”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/pending-and-skipped-examples/skipped-examples/index.html b/docs/features/3-12/rspec-core/pending-and-skipped-examples/skipped-examples/index.html
new file mode 100644
index 000000000..ac9efb68b
--- /dev/null
+++ b/docs/features/3-12/rspec-core/pending-and-skipped-examples/skipped-examples/index.html
@@ -0,0 +1,147 @@
+
+
+
+
+Using skip with examples
+
+RSpec offers a number of ways to indicate that an example should be skipped
+ and not executed.
+
+No implementation provided
+
+Given a file named “examplewithoutblock_spec.rb” with:
+RSpec.describe "an example" do
+ it "is a skipped example"
+end
+
+When I run rspec example_without_block_spec.rb
+
+Then the exit status should be 0
+
+And the output should contain “1 example, 0 failures, 1 pending”
+
+And the output should contain “Not yet implemented”
+
+And the output should contain “examplewithoutblock_spec.rb:2”.
+
+Skipping using skip
+
+Given a file named “skipped_spec.rb” with:
+RSpec.describe "an example" do
+ skip "is skipped" do
+ end
+end
+
+When I run rspec skipped_spec.rb
+
+Then the exit status should be 0
+
+And the output should contain “1 example, 0 failures, 1 pending”
+
+And the output should contain:
+Pending: (Failures listed here are expected and do not affect your suite's status)
+
+ 1) an example is skipped
+ # No reason given
+ # ./skipped_spec.rb:2
+
+Skipping using skip inside an example
+
+Given a file named “skipped_spec.rb” with:
+RSpec.describe "an example" do
+ it "is skipped" do
+ skip
+ end
+end
+
+When I run rspec skipped_spec.rb
+
+Then the exit status should be 0
+
+And the output should contain “1 example, 0 failures, 1 pending”
+
+And the output should contain:
+Pending: (Failures listed here are expected and do not affect your suite's status)
+
+ 1) an example is skipped
+ # No reason given
+ # ./skipped_spec.rb:2
+
+Temporarily skipping by prefixing it, specify, or example with an x
+
+Given a file named “temporarilyskippedspec.rb” with:
+RSpec.describe "an example" do
+ xit "is skipped using xit" do
+ end
+
+ xspecify "is skipped using xspecify" do
+ end
+
+ xexample "is skipped using xexample" do
+ end
+end
+
+When I run rspec temporarily_skipped_spec.rb
+
+Then the exit status should be 0
+
+And the output should contain “3 examples, 0 failures, 3 pending”
+
+And the output should contain:
+Pending: (Failures listed here are expected and do not affect your suite's status)
+
+ 1) an example is skipped using xit
+ # Temporarily skipped with xit
+ # ./temporarily_skipped_spec.rb:2
+
+ 2) an example is skipped using xspecify
+ # Temporarily skipped with xspecify
+ # ./temporarily_skipped_spec.rb:5
+
+ 3) an example is skipped using xexample
+ # Temporarily skipped with xexample
+ # ./temporarily_skipped_spec.rb:8
+
+Skipping using metadata
+
+Given a file named “skipped_spec.rb” with:
+RSpec.describe "an example" do
+ example "is skipped", :skip => true do
+ end
+end
+
+When I run rspec skipped_spec.rb
+
+Then the exit status should be 0
+
+And the output should contain “1 example, 0 failures, 1 pending”
+
+And the output should contain:
+Pending: (Failures listed here are expected and do not affect your suite's status)
+
+ 1) an example is skipped
+ # No reason given
+ # ./skipped_spec.rb:2
+
+Skipping using metadata with a reason
+
+Given a file named “skippedwithreason_spec.rb” with:
+RSpec.describe "an example" do
+ example "is skipped", :skip => "waiting for planets to align" do
+ raise "this line is never executed"
+ end
+end
+
+When I run rspec skipped_with_reason_spec.rb
+
+Then the exit status should be 0
+
+And the output should contain “1 example, 0 failures, 1 pending”
+
+And the output should contain:
+Pending: (Failures listed here are expected and do not affect your suite's status)
+
+ 1) an example is skipped
+ # waiting for planets to align
+ # ./skipped_with_reason_spec.rb:2
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/spec-files/arbitrary-file-suffix/index.html b/docs/features/3-12/rspec-core/spec-files/arbitrary-file-suffix/index.html
new file mode 100644
index 000000000..7a96a1bb3
--- /dev/null
+++ b/docs/features/3-12/rspec-core/spec-files/arbitrary-file-suffix/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+Using an arbitrary file suffix
+
+.spec
+
+Given a file named “a.spec” with:
+RSpec.describe "something" do
+ it "does something" do
+ expect(3).to eq(3)
+ end
+end
+
+When I run rspec a.spec
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/spec-files/index.html b/docs/features/3-12/rspec-core/spec-files/index.html
new file mode 100644
index 000000000..a030ed09f
--- /dev/null
+++ b/docs/features/3-12/rspec-core/spec-files/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Spec files
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/subject/explicit-subject/index.html b/docs/features/3-12/rspec-core/subject/explicit-subject/index.html
new file mode 100644
index 000000000..7978a827d
--- /dev/null
+++ b/docs/features/3-12/rspec-core/subject/explicit-subject/index.html
@@ -0,0 +1,202 @@
+
+
+
+
+Explicit Subject
+
+Use subject in the group scope to explicitly define the value that is returned by the
+ subject method in the example scope.
+
+Note that while the examples below demonstrate how the subject helper can be used
+ as a user-facing concept, we recommend that you reserve it for support of custom
+ matchers and/or extension libraries that hide its use from examples.
+
+A named subject improves on the explicit subject by assigning it a contextually
+ semantic name. Since a named subject is an explicit subject, it still defines the value
+ that is returned by the subject method in the example scope. However, it defines an
+ additional helper method with the provided name. This helper method is memoized.
+ The value is cached across multiple calls in the same example but not across examples.
+
+We recommend using the named helper method over subject in examples.
+
+For more information about declaring a subject see the API docs.
+
+A subject can be defined and used in the top level group scope
+
+Given a file named “toplevelsubject_spec.rb” with:
+RSpec.describe Array, "with some elements" do
+ subject { [1, 2, 3] }
+
+ it "has the prescribed elements" do
+ expect(subject).to eq([1, 2, 3])
+ end
+end
+
+When I run rspec top_level_subject_spec.rb
+
+Then the examples should all pass.
+
+The subject defined in an outer group is available to inner groups
+
+Given a file named “nestedsubjectspec.rb” with:
+RSpec.describe Array do
+ subject { [1, 2, 3] }
+
+ describe "has some elements" do
+ it "which are the prescribed elements" do
+ expect(subject).to eq([1, 2, 3])
+ end
+ end
+end
+
+When I run rspec nested_subject_spec.rb
+
+Then the examples should all pass.
+
+The subject is memoized within an example but not across examples
+
+Note: This scenario shows mutation being performed in a subject definition block. This
+ behavior is generally discouraged as it makes it more difficult to understand the specs.
+ This is technique is used simply as a tool to demonstrate how the memoization occurs.
+
+Given a file named “memoizedsubjectspec.rb” with:
+RSpec.describe Array do
+ # This uses a context local variable. As you can see from the
+ # specs, it can mutate across examples. Use with caution.
+ element_list = [1, 2, 3]
+
+ subject { element_list.pop }
+
+ it "is memoized across calls (i.e. the block is invoked once)" do
+ expect {
+ 3.times { subject }
+ }.to change{ element_list }.from([1, 2, 3]).to([1, 2])
+ expect(subject).to eq(3)
+ end
+
+ it "is not memoized across examples" do
+ expect{ subject }.to change{ element_list }.from([1, 2]).to([1])
+ expect(subject).to eq(2)
+ end
+end
+
+When I run rspec memoized_subject_spec.rb
+
+Then the examples should all pass.
+
+The subject is available in before hooks
+
+Given a file named “beforehooksubject_spec.rb” with:
+RSpec.describe Array, "with some elements" do
+ subject { [] }
+
+ before { subject.push(1, 2, 3) }
+
+ it "has the prescribed elements" do
+ expect(subject).to eq([1, 2, 3])
+ end
+end
+
+When I run rspec before_hook_subject_spec.rb
+
+Then the examples should all pass.
+
+Helper methods can be invoked from a subject definition block
+
+Given a file named “helpersubjectspec.rb” with:
+RSpec.describe Array, "with some elements" do
+ def prepared_array
+ [1, 2, 3]
+ end
+
+ subject { prepared_array }
+
+ it "has the prescribed elements" do
+ expect(subject).to eq([1, 2, 3])
+ end
+end
+
+When I run rspec helper_subject_spec.rb
+
+Then the examples should all pass.
+
+Use the subject! bang method to call the definition block before the example
+
+Given a file named “subjectbangspec.rb” with:
+RSpec.describe "eager loading with subject!" do
+ subject! { element_list.push(99) }
+
+ let(:element_list) { [1, 2, 3] }
+
+ it "calls the definition block before the example" do
+ element_list.push(5)
+ expect(element_list).to eq([1, 2, 3, 99, 5])
+ end
+end
+
+When I run rspec subject_bang_spec.rb
+
+Then the examples should all pass.
+
+Use subject(:name) to define a memoized helper method
+
+Note: While a global variable is used in the examples below, this behavior is strongly
+ discouraged in actual specs. It is used here simply to demonstrate the value will be
+ cached across multiple calls in the same example but not across examples.
+
+Given a file named “namedsubjectspec.rb” with:
+$count = 0
+
+RSpec.describe "named subject" do
+ subject(:global_count) { $count += 1 }
+
+ it "is memoized across calls (i.e. the block is invoked once)" do
+ expect {
+ 2.times { global_count }
+ }.not_to change{ global_count }.from(1)
+ end
+
+ it "is not cached across examples" do
+ expect(global_count).to eq(2)
+ end
+
+ it "is still available using the subject method" do
+ expect(subject).to eq(3)
+ end
+
+ it "works with the one-liner syntax" do
+ is_expected.to eq(4)
+ end
+
+ it "the subject and named helpers return the same object" do
+ expect(global_count).to be(subject)
+ end
+
+ it "is set to the block return value (i.e. the global $count)" do
+ expect(global_count).to be($count)
+ end
+end
+
+When I run rspec named_subject_spec.rb
+
+Then the examples should all pass.
+
+Use subject!(:name) to define a helper method called before the example
+
+Given a file named “namedsubjectbang_spec.rb” with:
+RSpec.describe "eager loading using a named subject!" do
+ subject!(:updated_list) { element_list.push(99) }
+
+ let(:element_list) { [1, 2, 3] }
+
+ it "calls the definition block before the example" do
+ element_list.push(5)
+ expect(element_list).to eq([1, 2, 3, 99, 5])
+ expect(updated_list).to be(element_list)
+ end
+end
+
+When I run rspec named_subject_bang_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/subject/implicit-subject/index.html b/docs/features/3-12/rspec-core/subject/implicit-subject/index.html
new file mode 100644
index 000000000..820b39cf1
--- /dev/null
+++ b/docs/features/3-12/rspec-core/subject/implicit-subject/index.html
@@ -0,0 +1,66 @@
+
+
+
+
+Implicitly defined subject
+
+If the first argument to an example group is a class, an instance of that
+ class is exposed to each example in that example group via the subject
+ method.
+
+While the examples below demonstrate how subject can be used as a
+ user-facing concept, we recommend that you reserve it for support of custom
+ matchers and/or extension libraries that hide its use from examples.
+
+subject exposed in top level group
+
+Given a file named “toplevelsubject_spec.rb” with:
+RSpec.describe Array do
+ it "should be empty when first created" do
+ expect(subject).to be_empty
+ end
+end
+
+When I run rspec ./top_level_subject_spec.rb
+
+Then the examples should all pass.
+
+subject in a nested group
+
+Given a file named “nestedsubjectspec.rb” with:
+RSpec.describe Array do
+ describe "when first created" do
+ it "should be empty" do
+ expect(subject).to be_empty
+ end
+ end
+end
+
+When I run rspec nested_subject_spec.rb
+
+Then the examples should all pass.
+
+subject in a nested group with a different class (innermost wins)
+
+Given a file named “nestedsubjectspec.rb” with:
+class ArrayWithOneElement < Array
+ def initialize(*)
+ super
+ unshift "first element"
+ end
+end
+
+RSpec.describe Array do
+ describe ArrayWithOneElement do
+ context "referenced as subject" do
+ it "contains one element" do
+ expect(subject).to include("first element")
+ end
+ end
+ end
+end
+
+When I run rspec nested_subject_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/subject/index.html b/docs/features/3-12/rspec-core/subject/index.html
new file mode 100644
index 000000000..ff096ba67
--- /dev/null
+++ b/docs/features/3-12/rspec-core/subject/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Subject
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-core/subject/one-liner-syntax/index.html b/docs/features/3-12/rspec-core/subject/one-liner-syntax/index.html
new file mode 100644
index 000000000..572dc39b1
--- /dev/null
+++ b/docs/features/3-12/rspec-core/subject/one-liner-syntax/index.html
@@ -0,0 +1,75 @@
+
+
+
+
+One-liner syntax
+
+RSpec supports a one-liner syntax for setting an expectation on the
+ subject. RSpec will give the examples a doc string that is auto-
+ generated from the matcher used in the example. This is designed specifically
+ to help avoid duplication in situations where the doc string and the matcher
+ used in the example mirror each other exactly. When used excessively, it can
+ produce documentation output that does not read well or contribute to
+ understanding the object you are describing.
+
+This comes in two flavors:
+* `is_expected` is defined simply as `expect(subject)` and is designed for
+ when you are using rspec-expectations with its newer expect-based syntax.
+* `should` was designed back when rspec-expectations only had a should-based
+ syntax. However, it continues to be available and work even if the
+ `:should` syntax is disabled (since that merely removes `Object#should`
+ but this is `RSpec::Core::ExampleGroup#should`).
+
+Notes:
+* This feature is only available when using rspec-expectations.
+* Examples defined using this one-liner syntax cannot be directly selected from the command line using the [`--example` option](../command-line/example-option).
+* The one-liner syntax only works with non-block expectations (e.g. `expect(obj).to eq`, etc) and it cannot be used with block expectations (e.g. `expect { object }`).
+
+Implicit subject
+
+Given a file named “example_spec.rb” with:
+RSpec.describe Array do
+ describe "when first created" do
+ # Rather than:
+ # it "should be empty" do
+ # subject.should be_empty
+ # end
+
+ it { should be_empty }
+ # or
+ it { is_expected.to be_empty }
+ end
+end
+
+When I run rspec example_spec.rb --format doc
+
+Then the examples should all pass
+
+And the output should contain:
+Array
+ when first created
+ is expected to be empty
+ is expected to be empty
+
+Explicit subject
+
+Given a file named “example_spec.rb” with:
+RSpec.describe Array do
+ describe "with 3 items" do
+ subject { [1,2,3] }
+ it { should_not be_empty }
+ # or
+ it { is_expected.not_to be_empty }
+ end
+end
+
+When I run rspec example_spec.rb --format doc
+
+Then the examples should all pass
+
+And the output should contain:
+Array
+ with 3 items
+ is expected not to be empty
+ is expected not to be empty
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/.nav b/docs/features/3-12/rspec-expectations/.nav
new file mode 100644
index 000000000..3500b4c91
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/.nav
@@ -0,0 +1,42 @@
+- built-in-matchers:
+ - equality.feature
+ - comparisons.feature
+ - predicates.feature
+ - types.feature
+ - all.feature
+ - be.feature
+ - be-within.feature
+ - exist.feature
+ - change.feature
+ - contain-exactly.feature
+ - cover.feature
+ - end-with.feature
+ - exist.feature
+ - have.feature
+ - have-attributes.feature
+ - include.feature
+ - match.feature
+ - operators.feature
+ - raise-error.feature
+ - respond-to.feature
+ - satisfy.feature
+ - start-with.feature
+ - throw-symbol.feature
+ - yield.feature
+- custom-matchers:
+ - define-matcher.feature
+ - define-diffable-matcher.feature
+ - define-matcher-with-fluent-interface.feature
+ - access-running-example.feature
+ - define-matcher-outside-rspec.feature
+- aggregating-failures.feature
+- composing-matchers.feature
+- compound-expectations.feature
+- define-negated-matcher.feature
+- customized-message.feature
+- diffing.feature
+- implicit-docstrings.feature
+- syntax-configuration.feature
+- test-frameworks:
+ - test-unit.feature
+- Changelog.md
diff --git a/docs/features/3-12/rspec-expectations/aggregating-failures/index.html b/docs/features/3-12/rspec-expectations/aggregating-failures/index.html
new file mode 100644
index 000000000..5deb128fe
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/aggregating-failures/index.html
@@ -0,0 +1,60 @@
+
+
+
+
+Aggregating Failures
+
+Normally, an expectation failure causes the example to immediately abort. When you have multiple independent expectations, it’s nice to be able to see all of the failures rather than just the first. One solution is to split off a separate example for each expectation, but if the setup for the examples is slow, that’s going to take extra time and slow things down. aggregate_failures provides an alternate solution. It wraps a set of expectations with a block. Within the block, expectation failures will not immediatly abort like normal; instead, the failures will be aggregated into a single exception that is raised at the end of the block, allowing you to see all expectations that failed.
+
+aggregate_failures takes an optional string argument that will be used in the aggregated failure message as a label.
+
+RSpec::Core expands this feature a bit; see the rspec-core docs for more detail.
+
+Note: The implementation of aggregate_failures uses a thread-local variable, which means that if you have an expectation failure in another thread, it’ll abort like normal.
+
+Multiple expectation failures within aggregate_failures are all reported
+
+Given a file named “spec/aggregatedfailurespec.rb” with:
+require 'rspec/expectations'
+include RSpec::Matchers
+
+Response = Struct.new(:status, :headers, :body)
+response = Response.new(404, { "Content-Type" => "text/plain" }, "Not Found")
+
+begin
+ aggregate_failures "testing response" do
+ expect(response.status).to eq(200)
+ expect(response.headers["Content-Type"]).to eq("application/json")
+ expect(response.body).to eq('{"message":"Success"}')
+ end
+rescue RSpec::Expectations::MultipleExpectationsNotMetError => e
+ puts e.message.gsub(/(:in).+/, '')
+ exit(1)
+end
+
+When I run ruby spec/aggregated_failure_spec.rb
+
+Then it should fail with:
+Got 3 failures from failure aggregation block "testing response":
+
+ 1) expected: 200
+ got: 404
+
+ (compared using ==)
+
+ spec/aggregated_failure_spec.rb:9
+
+ 2) expected: "application/json"
+ got: "text/plain"
+
+ (compared using ==)
+
+ spec/aggregated_failure_spec.rb:10
+
+ 3) expected: "{"message":"Success"}"
+ got: "Not Found"
+
+ (compared using ==)
+
+ spec/aggregated_failure_spec.rb:11
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/all/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/all/index.html
new file mode 100644
index 000000000..d4b656c97
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/all/index.html
@@ -0,0 +1,96 @@
+
+
+
+
+all matcher
+
+Use the all matcher to specify that a collection’s objects all pass an expected matcher. This works on any enumerable object.
+```ruby
+expect([1, 3, 5]).to all( be_odd )
+expect([1, 3, 5]).to all( be_an(Integer) )
+expect([1, 3, 5]).to all( be < 10 )
+expect([1, 3, 4]).to all( be_odd ) # fails
+```
+
+The matcher also supports compound matchers:
+```ruby
+expect([1, 3, 5]).to all( be_odd.and be < 10 )
+expect([1, 4, 21]).to all( be_odd.or be < 10 )
+```
+
+If you are looking for “any” member of a collection that passes an expectation, look at the include-matcher.
+
+Array usage
+
+Given a file named “arrayallmatcher_spec.rb” with:
+RSpec.describe [1, 3, 5] do
+ it { is_expected.to all( be_odd ) }
+ it { is_expected.to all( be_an(Integer) ) }
+ it { is_expected.to all( be < 10 ) }
+
+ # deliberate failures
+ it { is_expected.to all( be_even ) }
+ it { is_expected.to all( be_a(String) ) }
+ it { is_expected.to all( be > 2 ) }
+end
+
+When I run rspec array_all_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+6 examples, 3 failures
+
+
+expected [1, 3, 5] to all be even
+
+
+expected [1, 3, 5] to all be a kind of String
+
+
+expected [1, 3, 5] to all be > 2
+
+
+
+Compound matcher usage
+
+Given a file named “compoundallmatcher_spec.rb” with:
+RSpec.describe ['anything', 'everything', 'something'] do
+ it { is_expected.to all( be_a(String).and include("thing") ) }
+ it { is_expected.to all( be_a(String).and end_with("g") ) }
+ it { is_expected.to all( start_with("s").or include("y") ) }
+
+ # deliberate failures
+ it { is_expected.to all( include("foo").and include("bar") ) }
+ it { is_expected.to all( be_a(String).and start_with("a") ) }
+ it { is_expected.to all( start_with("a").or include("z") ) }
+end
+
+When I run rspec compound_all_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+6 examples, 3 failures
+
+
+expected [“anything”, “everything”, “something”] to all include “foo” and include “bar”
+
+
+expected [“anything”, “everything”, “something”] to all be a kind of String and start with “a”
+
+
+expected [“anything”, “everything”, “something”] to all start with “a” or include “z”
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/be-within/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/be-within/index.html
new file mode 100644
index 000000000..42a674582
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/be-within/index.html
@@ -0,0 +1,69 @@
+
+
+
+
+be_within matcher
+
+Normal equality expectations do not work well for floating point values.
+ Consider this irb session:
+ > radius = 3
+ => 3
+ > area_of_circle = radius * radius * Math::PI
+ => 28.2743338823081
+ > area_of_circle == 28.2743338823081
+ => false
+
+Instead, you should use the be_within matcher to check that the value is within a delta of
+ your expected value:
+```ruby
+expect(area_of_circle).to be_within(0.1).of(28.3)
+```
+
+Note that the difference between the actual and expected values must be smaller than your
+ delta; if it is equal, the matcher will fail.
+
+Basic usage
+
+Given a file named “bewithinmatcher_spec.rb” with:
+RSpec.describe 27.5 do
+ it { is_expected.to be_within(0.5).of(27.9) }
+ it { is_expected.to be_within(0.5).of(28.0) }
+ it { is_expected.to be_within(0.5).of(27.1) }
+ it { is_expected.to be_within(0.5).of(27.0) }
+
+ it { is_expected.not_to be_within(0.5).of(28.1) }
+ it { is_expected.not_to be_within(0.5).of(26.9) }
+
+ # deliberate failures
+ it { is_expected.not_to be_within(0.5).of(28) }
+ it { is_expected.not_to be_within(0.5).of(27) }
+ it { is_expected.to be_within(0.5).of(28.1) }
+ it { is_expected.to be_within(0.5).of(26.9) }
+end
+
+When I run rspec be_within_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+10 examples, 4 failures
+
+
+expected 27.5 not to be within 0.5 of 28
+
+
+expected 27.5 not to be within 0.5 of 27
+
+
+expected 27.5 to be within 0.5 of 28.1
+
+
+expected 27.5 to be within 0.5 of 26.9
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/be/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/be/index.html
new file mode 100644
index 000000000..894c8a085
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/be/index.html
@@ -0,0 +1,187 @@
+
+
+
+
+be matchers
+
+There are several related “be” matchers:
+```ruby
+expect(obj).to be_truthy # passes if obj is truthy (not nil or false)
+expect(obj).to be_falsey # passes if obj is falsy (nil or false)
+expect(obj).to be_nil # passes if obj is nil
+expect(obj).to be # passes if obj is truthy (not nil or false)
+```
+
+The be_truthy matcher
+
+Given a file named “betruthyspec.rb” with:
+RSpec.describe "be_truthy matcher" do
+ specify { expect(true).to be_truthy }
+ specify { expect(7).to be_truthy }
+ specify { expect("foo").to be_truthy }
+ specify { expect(nil).not_to be_truthy }
+ specify { expect(false).not_to be_truthy }
+
+ # deliberate failures
+ specify { expect(true).not_to be_truthy }
+ specify { expect(7).not_to be_truthy }
+ specify { expect("foo").not_to be_truthy }
+ specify { expect(nil).to be_truthy }
+ specify { expect(false).to be_truthy }
+end
+
+When I run rspec be_truthy_spec.rb
+
+Then the output should contain “10 examples, 5 failures”
+
+And the output should contain:
+ expected: falsey value
+ got: true
+
+And the output should contain:
+ expected: falsey value
+ got: 7
+
+And the output should contain:
+ expected: falsey value
+ got: "foo"
+
+And the output should contain:
+ expected: truthy value
+ got: nil
+
+And the output should contain:
+ expected: truthy value
+ got: false
+
+The be_falsey matcher
+
+Given a file named “befalseyspec.rb” with:
+RSpec.describe "be_falsey matcher" do
+ specify { expect(nil).to be_falsey }
+ specify { expect(false).to be_falsey }
+ specify { expect(true).not_to be_falsey }
+ specify { expect(7).not_to be_falsey }
+ specify { expect("foo").not_to be_falsey }
+
+ # deliberate failures
+ specify { expect(nil).not_to be_falsey }
+ specify { expect(false).not_to be_falsey }
+ specify { expect(true).to be_falsey }
+ specify { expect(7).to be_falsey }
+ specify { expect("foo").to be_falsey }
+end
+
+When I run rspec be_falsey_spec.rb
+
+Then the output should contain “10 examples, 5 failures”
+
+And the output should contain:
+ expected: truthy value
+ got: nil
+
+And the output should contain:
+ expected: truthy value
+ got: false
+
+And the output should contain:
+ expected: falsey value
+ got: true
+
+And the output should contain:
+ expected: falsey value
+ got: 7
+
+And the output should contain:
+ expected: falsey value
+ got: "foo"
+
+The be_nil matcher
+
+Given a file named “benilspec.rb” with:
+RSpec.describe "be_nil matcher" do
+ specify { expect(nil).to be_nil }
+ specify { expect(false).not_to be_nil }
+ specify { expect(true).not_to be_nil }
+ specify { expect(7).not_to be_nil }
+ specify { expect("foo").not_to be_nil }
+
+ # deliberate failures
+ specify { expect(nil).not_to be_nil }
+ specify { expect(false).to be_nil }
+ specify { expect(true).to be_nil }
+ specify { expect(7).to be_nil }
+ specify { expect("foo").to be_nil }
+end
+
+When I run rspec be_nil_spec.rb
+
+Then the output should contain “10 examples, 5 failures”
+
+And the output should contain:
+ expected: not nil
+ got: nil
+
+And the output should contain:
+ expected: nil
+ got: false
+
+And the output should contain:
+ expected: nil
+ got: true
+
+And the output should contain:
+ expected: nil
+ got: 7
+
+And the output should contain:
+ expected: nil
+ got: "foo"
+
+The be matcher
+
+Given a file named “be_spec.rb” with:
+RSpec.describe "be_matcher" do
+ specify { expect(true).to be }
+ specify { expect(7).to be }
+ specify { expect("foo").to be }
+ specify { expect(nil).not_to be }
+ specify { expect(false).not_to be }
+
+ # deliberate failures
+ specify { expect(true).not_to be }
+ specify { expect(7).not_to be }
+ specify { expect("foo").not_to be }
+ specify { expect(nil).to be }
+ specify { expect(false).to be }
+end
+
+When I run rspec be_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+10 examples, 5 failures
+
+
+expected true to evaluate to false
+
+
+expected 7 to evaluate to false
+
+
+expected “foo” to evaluate to false
+
+
+expected nil to evaluate to true
+
+
+expected false to evaluate to true
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/change/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/change/index.html
new file mode 100644
index 000000000..39f90552b
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/change/index.html
@@ -0,0 +1,76 @@
+
+
+
+
+change matcher
+
+The change matcher is used to specify that a block of code changes some mutable state.
+ You can specify what will change using either of two forms:
+
+
+expect { do_something }.to change(object, :attribute)
+expect { do_something }.to change { object.attribute }
+
+
+You can further qualify the change by chaining from and/or to or one of by, by_at_most,
+ by_at_least.
+
+Background
+
+Given a file named “lib/counter.rb” with:
+class Counter
+ class << self
+ def increment
+ @count ||= 0
+ @count += 1
+ end
+
+ def count
+ @count ||= 0
+ end
+ end
+end
+
+Expect change
+
+Given a file named “spec/example_spec.rb” with:
+require "counter"
+
+RSpec.describe Counter, "#increment" do
+ it "should increment the count" do
+ expect { Counter.increment }.to change { Counter.count }.from(0).to(1)
+ end
+
+ # deliberate failure
+ it "should increment the count by 2" do
+ expect { Counter.increment }.to change { Counter.count }.by(2)
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the output should contain “1 failure”
+
+Then the output should contain “expected Counter.count to have changed by 2, but was changed by 1”.
+
+Expect no change
+
+Given a file named “spec/example_spec.rb” with:
+require "counter"
+
+RSpec.describe Counter, "#increment" do
+ it "should not increment the count by 1 (using not_to)" do
+ expect { Counter.increment }.not_to change { Counter.count }
+ end
+
+ it "should not increment the count by 1 (using to_not)" do
+ expect { Counter.increment }.to_not change { Counter.count }
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the output should contain “2 failures”
+
+Then the output should contain “expected Counter.count not to have changed, but did change from 1 to 2”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/comparisons/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/comparisons/index.html
new file mode 100644
index 000000000..a83f85677
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/comparisons/index.html
@@ -0,0 +1,123 @@
+
+
+
+
+Comparison matchers
+
+RSpec provides a number of matchers that are based on Ruby’s built-in operators. These
+ can be used for generalized comparison of values. E.g.
+```ruby
+expect(9).to be > 6
+expect(3).to be <= 3
+expect(1).to be < 6
+expect('a').to be < 'b'
+```
+
+Numeric operator matchers
+
+Given a file named “numericoperatormatchers_spec.rb” with:
+RSpec.describe 18 do
+ it { is_expected.to be < 20 }
+ it { is_expected.to be > 15 }
+ it { is_expected.to be <= 19 }
+ it { is_expected.to be >= 17 }
+
+ # deliberate failures
+ it { is_expected.to be < 15 }
+ it { is_expected.to be > 20 }
+ it { is_expected.to be <= 17 }
+ it { is_expected.to be >= 19 }
+ it { is_expected.to be < 'a' }
+end
+
+RSpec.describe 'a' do
+ it { is_expected.to be < 'b' }
+
+ # deliberate failures
+ it { is_expected.to be < 18 }
+end
+
+When I run rspec numeric_operator_matchers_spec.rb
+
+Then the output should contain “11 examples, 6 failures”
+
+And the output should contain:
+ Failure/Error: it { is_expected.to be < 15 }
+
+ expected: < 15
+ got: 18
+
+And the output should contain:
+ Failure/Error: it { is_expected.to be > 20 }
+
+ expected: > 20
+ got: 18
+
+And the output should contain:
+ Failure/Error: it { is_expected.to be <= 17 }
+
+ expected: <= 17
+ got: 18
+
+And the output should contain:
+ Failure/Error: it { is_expected.to be >= 19 }
+
+ expected: >= 19
+ got: 18
+
+And the output should contain:
+ Failure/Error: it { is_expected.to be < 'a' }
+
+ expected: < "a"
+ got: 18
+
+And the output should contain:
+ Failure/Error: it { is_expected.to be < 18 }
+
+ expected: < 18
+ got: "a"
+
+String operator matchers
+
+Given a file named “stringoperatormatchers_spec.rb” with:
+RSpec.describe "Strawberry" do
+ it { is_expected.to be < "Tomato" }
+ it { is_expected.to be > "Apple" }
+ it { is_expected.to be <= "Turnip" }
+ it { is_expected.to be >= "Banana" }
+
+ # deliberate failures
+ it { is_expected.to be < "Cranberry" }
+ it { is_expected.to be > "Zuchini" }
+ it { is_expected.to be <= "Potato" }
+ it { is_expected.to be >= "Tomato" }
+end
+
+When I run rspec string_operator_matchers_spec.rb
+
+Then the output should contain “8 examples, 4 failures”
+
+And the output should contain:
+ Failure/Error: it { is_expected.to be < "Cranberry" }
+
+ expected: < "Cranberry"
+ got: "Strawberry"
+
+And the output should contain:
+ Failure/Error: it { is_expected.to be > "Zuchini" }
+
+ expected: > "Zuchini"
+ got: "Strawberry"
+
+And the output should contain:
+ Failure/Error: it { is_expected.to be <= "Potato" }
+
+ expected: <= "Potato"
+ got: "Strawberry"
+
+And the output should contain:
+ Failure/Error: it { is_expected.to be >= "Tomato" }
+
+ expected: >= "Tomato"
+ got: "Strawberry"
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/contain-exactly/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/contain-exactly/index.html
new file mode 100644
index 000000000..9073257a8
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/contain-exactly/index.html
@@ -0,0 +1,68 @@
+
+
+
+
+contain_exactly matcher
+
+The contain_exactly matcher provides a way to test arrays against each other in a way
+ that disregards differences in the ordering between the actual and expected array.
+ For example:
+```ruby
+expect([1, 2, 3]).to contain_exactly(2, 3, 1) # pass
+expect([:a, :c, :b]).to contain_exactly(:a, :c ) # fail
+```
+
+This matcher is also available as match_array, which expects the expected array to be
+ given as a single array argument rather than as individual splatted elements. The above
+ could also be written as:
+```ruby
+expect([1, 2, 3]).to match_array [2, 3, 1] # pass
+expect([:a, :c, :b]).to match_array [:a, :c] # fail
+```
+
+Array is expected to contain every value
+
+Given a file named “containexactlymatcher_spec.rb” with:
+RSpec.describe [1, 2, 3] do
+ it { is_expected.to contain_exactly(1, 2, 3) }
+ it { is_expected.to contain_exactly(1, 3, 2) }
+ it { is_expected.to contain_exactly(2, 1, 3) }
+ it { is_expected.to contain_exactly(2, 3, 1) }
+ it { is_expected.to contain_exactly(3, 1, 2) }
+ it { is_expected.to contain_exactly(3, 2, 1) }
+
+ # deliberate failures
+ it { is_expected.to contain_exactly(1, 2, 1) }
+end
+
+When I run rspec contain_exactly_matcher_spec.rb
+
+Then the output should contain “7 examples, 1 failure”
+
+And the output should contain:
+ Failure/Error: it { is_expected.to contain_exactly(1, 2, 1) }
+
+ expected collection contained: [1, 1, 2]
+ actual collection contained: [1, 2, 3]
+ the missing elements were: [1]
+ the extra elements were: [3]
+
+Array is not expected to contain every value
+
+Given a file named “containexactlymatcher_spec.rb” with:
+RSpec.describe [1, 2, 3] do
+ it { is_expected.to_not contain_exactly(1, 2, 3, 4) }
+ it { is_expected.to_not contain_exactly(1, 2) }
+
+ # deliberate failures
+ it { is_expected.to_not contain_exactly(1, 3, 2) }
+end
+
+When I run rspec contain_exactly_matcher_spec.rb
+
+Then the output should contain “3 examples, 1 failure”
+
+And the output should contain:
+ Failure/Error: it { is_expected.to_not contain_exactly(1, 3, 2) }
+ expected [1, 2, 3] not to contain exactly 1, 3, and 2
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/cover/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/cover/index.html
new file mode 100644
index 000000000..eaa14bafc
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/cover/index.html
@@ -0,0 +1,74 @@
+
+
+
+
+cover matcher
+
+Use the cover matcher to specify that a range covers one or more
+ expected objects. This works on any object that responds to #cover?
+ (such as a Range):
+```ruby
+expect(1..10).to cover(5)
+expect(1..10).to cover(4, 6)
+expect(1..10).not_to cover(11)
+```
+
+Range usage
+
+Given a file named “rangecovermatcher_spec.rb” with:
+RSpec.describe (1..10) do
+ it { is_expected.to cover(4) }
+ it { is_expected.to cover(6) }
+ it { is_expected.to cover(8) }
+ it { is_expected.to cover(4, 6) }
+ it { is_expected.to cover(4, 6, 8) }
+ it { is_expected.not_to cover(11) }
+ it { is_expected.not_to cover(11, 12) }
+
+ # deliberate failures
+ it { is_expected.to cover(11) }
+ it { is_expected.not_to cover(4) }
+ it { is_expected.not_to cover(6) }
+ it { is_expected.not_to cover(8) }
+ it { is_expected.not_to cover(4, 6, 8) }
+
+ # both of these should fail since it covers 5 but not 11
+ it { is_expected.to cover(5, 11) }
+ it { is_expected.not_to cover(5, 11) }
+end
+
+When I run rspec range_cover_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+14 examples, 7 failures
+
+
+expected 1..10 to cover 11
+
+
+expected 1..10 not to cover 4
+
+
+expected 1..10 not to cover 6
+
+
+expected 1..10 not to cover 8
+
+
+expected 1..10 not to cover 4, 6, and 8
+
+
+expected 1..10 to cover 5 and 11
+
+
+expected 1..10 not to cover 5 and 11
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/end-with/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/end-with/index.html
new file mode 100644
index 000000000..a461669d3
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/end-with/index.html
@@ -0,0 +1,80 @@
+
+
+
+
+end_with matcher
+
+Use the end_with matcher to specify that a string or array ends with the expected
+ characters or elements.
+```ruby
+expect("this string").to end_with "string"
+expect("this string").not_to end_with "stringy"
+expect([0, 1, 2]).to end_with 1, 2
+```
+
+String usage
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "this string" do
+ it { is_expected.to end_with "string" }
+ it { is_expected.not_to end_with "stringy" }
+
+ # deliberate failures
+ it { is_expected.not_to end_with "string" }
+ it { is_expected.to end_with "stringy" }
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+4 examples, 2 failures
+
+
+expected “this string” not to end with “string”
+
+
+expected “this string” to end with “stringy”
+
+
+
+Array usage
+
+Given a file named “example_spec.rb” with:
+RSpec.describe [0, 1, 2, 3, 4] do
+ it { is_expected.to end_with 4 }
+ it { is_expected.to end_with 3, 4 }
+ it { is_expected.not_to end_with 3 }
+ it { is_expected.not_to end_with 0, 1, 2, 3, 4, 5 }
+
+ # deliberate failures
+ it { is_expected.not_to end_with 4 }
+ it { is_expected.to end_with 3 }
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+6 examples, 2 failures
+
+
+expected [0, 1, 2, 3, 4] not to end with 4
+
+
+expected [0, 1, 2, 3, 4] to end with 3
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/equality/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/equality/index.html
new file mode 100644
index 000000000..90a4383f0
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/equality/index.html
@@ -0,0 +1,141 @@
+
+
+
+
+Equality matchers
+
+Ruby exposes several different methods for handling equality:
+ a.equal?(b) # object identity - a and b refer to the same object
+ a.eql?(b) # object equivalence - a and b have the same value
+ a == b # object equivalence - a and b have the same value with type conversions
+
+Note that these descriptions are guidelines but are not forced by the language. Any object
+ can implement any of these methods with its own semantics.
+
+rspec-expectations ships with matchers that align with each of these methods:
+```ruby
+expect(a).to equal(b) # passes if a.equal?(b)
+expect(a).to eql(b) # passes if a.eql?(b)
+expect(a).to be == b # passes if a == b
+```
+
+It also ships with two matchers that have more of a DSL feel to them:
+```ruby
+expect(a).to be(b) # passes if a.equal?(b)
+expect(a).to eq(b) # passes if a == b
+```
+
+Compare using eq (==)
+
+Given a file named “compareusingeq.rb” with:
+RSpec.describe "a string" do
+ it "is equal to another string of the same value" do
+ expect("this string").to eq("this string")
+ end
+
+ it "is not equal to another string of a different value" do
+ expect("this string").not_to eq("a different string")
+ end
+end
+
+RSpec.describe "an integer" do
+ it "is equal to a float of the same value" do
+ expect(5).to eq(5.0)
+ end
+end
+
+When I run rspec compare_using_eq.rb
+
+Then the output should contain “3 examples, 0 failures”.
+
+Compare using ==
+
+Given a file named “compareusing==.rb” with:
+RSpec.describe "a string" do
+ it "is equal to another string of the same value" do
+ expect("this string").to be == "this string"
+ end
+
+ it "is not equal to another string of a different value" do
+ expect("this string").not_to be == "a different string"
+ end
+end
+
+RSpec.describe "an integer" do
+ it "is equal to a float of the same value" do
+ expect(5).to be == 5.0
+ end
+end
+
+When I run rspec compare_using_==.rb
+
+Then the output should contain “3 examples, 0 failures”.
+
+Compare using eql (eql?)
+
+Given a file named “compareusingeql.rb” with:
+RSpec.describe "an integer" do
+ it "is equal to another integer of the same value" do
+ expect(5).to eql(5)
+ end
+
+ it "is not equal to another integer of a different value" do
+ expect(5).not_to eql(6)
+ end
+
+ it "is not equal to a float of the same value" do
+ expect(5).not_to eql(5.0)
+ end
+
+end
+
+When I run rspec compare_using_eql.rb
+
+Then the output should contain “3 examples, 0 failures”.
+
+Compare using equal (equal?)
+
+Given a file named “compareusingequal.rb” with:
+RSpec.describe "a string" do
+ it "is equal to itself" do
+ string = "this string"
+ expect(string).to equal(string)
+ end
+
+ it "is not equal to another string of the same value" do
+ expect("this string").not_to equal("this string")
+ end
+
+ it "is not equal to another string of a different value" do
+ expect("this string").not_to equal("a different string")
+ end
+
+end
+
+When I run rspec compare_using_equal.rb
+
+Then the output should contain “3 examples, 0 failures”.
+
+Compare using be (equal?)
+
+Given a file named “compareusingbe.rb” with:
+RSpec.describe "a string" do
+ it "is equal to itself" do
+ string = "this string"
+ expect(string).to be(string)
+ end
+
+ it "is not equal to another string of the same value" do
+ expect("this string").not_to be("this string")
+ end
+
+ it "is not equal to another string of a different value" do
+ expect("this string").not_to be("a different string")
+ end
+
+end
+
+When I run rspec compare_using_be.rb
+
+Then the output should contain “3 examples, 0 failures”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/exist/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/exist/index.html
new file mode 100644
index 000000000..98f2b749d
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/exist/index.html
@@ -0,0 +1,62 @@
+
+
+
+
+exist matcher
+
+The exist matcher is used to specify that something exists (as indicated by #exist? or #exists?):
+```ruby
+expect(obj).to exist # passes if obj.exist? or obj.exists?
+```
+
+Basic usage
+
+Given a file named “existmatcherspec.rb” with:
+class Planet
+ attr_reader :name
+
+ def initialize(name)
+ @name = name
+ end
+
+ def inspect
+ "<Planet: #{name}>"
+ end
+
+ def exist? # also works with exists?
+ %w[Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune].include?(name)
+ end
+end
+
+RSpec.describe "Earth" do
+ let(:earth) { Planet.new("Earth") }
+ specify { expect(earth).to exist }
+ specify { expect(earth).not_to exist } # deliberate failure
+end
+
+RSpec.describe "Tatooine" do
+ let(:tatooine) { Planet.new("Tatooine") }
+ specify { expect(tatooine).to exist } # deliberate failure
+ specify { expect(tatooine).not_to exist }
+end
+
+When I run rspec exist_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+4 examples, 2 failures
+
+
+expected not to exist
+
+
+expected to exist
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/have-attributes/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/have-attributes/index.html
new file mode 100644
index 000000000..84fa67d88
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/have-attributes/index.html
@@ -0,0 +1,50 @@
+
+
+
+
+have_attributes matcher
+
+Use the have_attributes matcher to specify that an object’s attributes match the expected attributes:
+```ruby
+Person = Struct.new(:name, :age)
+person = Person.new("Jim", 32)
+
+expect(person).to have_attributes(:name => "Jim", :age => 32)
+expect(person).to have_attributes(:name => a_string_starting_with("J"), :age => (a_value > 30) )
+```
+
+The matcher will fail if actual doesn’t respond to any of the expected attributes:
+```ruby
+expect(person).to have_attributes(:name => "Jim", :color => 'red')
+```
+
+Basic usage
+
+Given a file named “basichaveattributesmatcherspec.rb” with:
+Person = Struct.new(:name, :age)
+
+RSpec.describe Person.new("Jim", 32) do
+ it { is_expected.to have_attributes(:name => "Jim") }
+ it { is_expected.to have_attributes(:name => a_string_starting_with("J") ) }
+ it { is_expected.to have_attributes(:age => 32) }
+ it { is_expected.to have_attributes(:age => (a_value > 30) ) }
+ it { is_expected.to have_attributes(:name => "Jim", :age => 32) }
+ it { is_expected.to have_attributes(:name => a_string_starting_with("J"), :age => (a_value > 30) ) }
+ it { is_expected.not_to have_attributes(:name => "Bob") }
+ it { is_expected.not_to have_attributes(:age => 10) }
+ it { is_expected.not_to have_attributes(:age => (a_value < 30) ) }
+
+ # deliberate failures
+ it { is_expected.to have_attributes(:name => "Bob") }
+ it { is_expected.to have_attributes(:age => 10) }
+
+ # fails if any of the attributes don't match
+ it { is_expected.to have_attributes(:name => "Bob", :age => 32) }
+ it { is_expected.to have_attributes(:name => "Jim", :age => 10) }
+ it { is_expected.to have_attributes(:name => "Bob", :age => 10) }
+end
+
+When I run rspec basic_have_attributes_matcher_spec.rb
+
+Then the output should contain “14 examples, 5 failures”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/include/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/include/index.html
new file mode 100644
index 000000000..c7dfa9af9
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/include/index.html
@@ -0,0 +1,285 @@
+
+
+
+
+include matcher
+
+Use the include matcher to specify that a collection includes one or more expected objects. It succeeds if any object of the given collection passes the specified matcher. This works on any object that responds to #include? (such as a string or array):
+```ruby
+expect("a string").to include("a")
+expect("a string").to include(/a|str/).twice
+expect("a string").to include("str", "g")
+expect("a string").not_to include("foo")
+
+expect([1, 2]).to include(1)
+expect([1, 2]).to include(1, 2)
+expect([1, 2]).to include(a_kind_of(Integer))
+expect([1, 2]).to include(be_odd.and be < 10 )
+expect([1, 2]).to include(be_odd)
+expect([1, 2]).to include(be < 10).at_least(2).times
+expect([1, 2]).not_to include(17)
+```
+
+The matcher also provides flexible handling for hashes:
+```ruby
+expect(:a => 1, :b => 2).to include(:a)
+expect(:a => 1, :b => 2).to include(:a, :b)
+expect(:a => 1, :b => 2).to include(:a => 1)
+expect(:a => 1, :b => 2).to include(:b => 2, :a => 1)
+expect(:a => 1, :b => 2).to include(match(/b/) => 2)
+expect(:a => 1, :b => 2).to include(match(/b/) => be_even)
+expect(:a => 1, :b => 2).not_to include(:c)
+expect(:a => 1, :b => 2).not_to include(:a => 2)
+expect(:a => 1, :b => 2).not_to include(:c => 3)
+```
+
+Array usage
+
+Given a file named “arrayincludematcher_spec.rb” with:
+RSpec.describe [1, 3, 7] do
+ it { is_expected.to include(1) }
+ it { is_expected.to include(3) }
+ it { is_expected.to include(7) }
+ it { is_expected.to include(1, 7) }
+ it { is_expected.to include(1, 3, 7) }
+ it { is_expected.to include(a_kind_of(Integer)) }
+ it { is_expected.to include(be_odd.and be < 10) }
+ it { is_expected.to include(be_odd).at_least(:twice) }
+ it { is_expected.not_to include(be_even) }
+ it { is_expected.not_to include(17) }
+ it { is_expected.not_to include(43, 100) }
+
+ # deliberate failures
+ it { is_expected.to include(4) }
+ it { is_expected.to include(be_even) }
+ it { is_expected.to include(be_odd).at_most(2).times }
+ it { is_expected.not_to include(1) }
+ it { is_expected.not_to include(3) }
+ it { is_expected.not_to include(7) }
+ it { is_expected.not_to include(1, 3, 7) }
+
+ # both of these should fail since it includes 1 but not 9
+ it { is_expected.to include(1, 9) }
+ it { is_expected.not_to include(1, 9) }
+end
+
+When I run rspec array_include_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+20 examples, 9 failures
+
+
+expected [1, 3, 7] to include 4
+
+
+expected [1, 3, 7] to include (be even)
+
+
+expected [1, 3, 7] to include (be odd) at most twice but it is included 3 times
+
+
+expected [1, 3, 7] not to include 1
+
+
+expected [1, 3, 7] not to include 3
+
+
+expected [1, 3, 7] not to include 7
+
+
+expected [1, 3, 7] not to include 1, 3, and 7
+
+
+expected [1, 3, 7] to include 9
+
+
+expected [1, 3, 7] not to include 1
+
+
+
+String usage
+
+Given a file named “stringincludematcher_spec.rb” with:
+RSpec.describe "a string" do
+ it { is_expected.to include("str") }
+ it { is_expected.to include("a", "str", "ng") }
+ it { is_expected.to include(/a|str/).twice }
+ it { is_expected.not_to include("foo") }
+ it { is_expected.not_to include("foo", "bar") }
+
+ # deliberate failures
+ it { is_expected.to include("foo") }
+ it { is_expected.not_to include("str") }
+ it { is_expected.to include("str").at_least(:twice) }
+ it { is_expected.to include("str", "foo") }
+ it { is_expected.not_to include("str", "foo") }
+end
+
+When I run rspec string_include_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+10 examples, 5 failures
+
+
+expected “a string” to include “foo”
+
+
+expected “a string” not to include “str”
+
+
+expected “a string” to include “str” at least twice but it is included once
+
+
+expected “a string” to include “foo”
+
+
+expected “a string” not to include “str”
+
+
+
+Hash usage
+
+Given a file named “hashincludematcher_spec.rb” with:
+RSpec.describe :a => 7, :b => 5 do
+ it { is_expected.to include(:a) }
+ it { is_expected.to include(:b, :a) }
+ it { is_expected.to include(:a => 7) }
+ it { is_expected.to include(:b => 5, :a => 7) }
+ it { is_expected.not_to include(:c) }
+ it { is_expected.not_to include(:c, :d) }
+ it { is_expected.not_to include(:d => 2) }
+ it { is_expected.not_to include(:a => 5) }
+ it { is_expected.not_to include(:b => 7, :a => 5) }
+
+ # deliberate failures
+ it { is_expected.not_to include(:a) }
+ it { is_expected.not_to include(:b, :a) }
+ it { is_expected.not_to include(:a => 7) }
+ it { is_expected.not_to include(:a => 7, :b => 5) }
+ it { is_expected.to include(:c) }
+ it { is_expected.to include(:c, :d) }
+ it { is_expected.to include(:d => 2) }
+ it { is_expected.to include(:a => 5) }
+ it { is_expected.to include(:a => 5, :b => 7) }
+
+ # Mixed cases--the hash includes one but not the other.
+ # All 4 of these cases should fail.
+ it { is_expected.to include(:a, :d) }
+ it { is_expected.not_to include(:a, :d) }
+ it { is_expected.to include(:a => 7, :d => 3) }
+ it { is_expected.not_to include(:a => 7, :d => 3) }
+end
+
+When I run rspec hash_include_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+22 examples, 13 failures
+
+
+expected {:a => 7, :b => 5} not to include :a
+
+
+expected {:a => 7, :b => 5} not to include :b and :a
+
+
+expected {:a => 7, :b => 5} not to include {:a => 7}
+
+
+expected {:a => 7, :b => 5} not to include {:a => 7, :b => 5}
+
+
+expected {:a => 7, :b => 5} to include :c
+
+
+expected {:a => 7, :b => 5} to include :c and :d
+
+
+expected {:a => 7, :b => 5} to include {:d => 2}
+
+
+expected {:a => 7, :b => 5} to include {:a => 5}
+
+
+expected {:a => 7, :b => 5} to include {:a => 5, :b => 7}
+
+
+expected {:a => 7, :b => 5} to include :d
+
+
+expected {:a => 7, :b => 5} not to include :a
+
+
+expected {:a => 7, :b => 5} to include {:d => 3}
+
+
+expected {:a => 7, :b => 5} not to include {:a => 7}
+
+
+
+Counts usage
+
+Given a file named “includematcherwithcountsspec.rb” with:
+ RSpec.describe [{:c => 7}, {:a => 1}, {:b => 2}, {:c => 1}, {:a => 3}, {:c => 7}] do
+ it { is_expected.to include(:b => 2).exactly(1).times }
+ it { is_expected.to include(:b => 2).once }
+ it { is_expected.to include(have_key(:a)).twice }
+ it { is_expected.to include(have_key(:c)).at_least(2).times }
+ it { is_expected.to include(have_key(:a)).at_least(:once) }
+ it { is_expected.to include(have_key(:c)).at_least(:twice) }
+ it { is_expected.to include(have_key(:d)).at_most(:once) }
+ it { is_expected.to include(have_key(:b)).at_most(:twice) }
+
+ # deliberate failures
+ it { is_expected.not_to include(have_key(:b)).once }
+ it { is_expected.not_to include(have_key(:a)).twice }
+ it { is_expected.not_to include(have_key(:c)).at_least(2).times }
+ it { is_expected.not_to include(have_key(:d)).at_most(:once) }
+ end
+
+When I run rspec include_matcher_with_counts_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+12 examples, 4 failures
+
+
+expected [{:c => 7}, {:a => 1}, {:b => 2}, {:c => 1}, {:a => 3}, {:c => 7}] not to include (have key :b) once
+
+
+expected [{:c => 7}, {:a => 1}, {:b => 2}, {:c => 1}, {:a => 3}, {:c => 7}] not to include (have key :a) twice
+
+
+expected [{:c => 7}, {:a => 1}, {:b => 2}, {:c => 1}, {:a => 3}, {:c => 7}] not to include (have key :c) at least twice
+
+
+expected [{:c => 7}, {:a => 1}, {:b => 2}, {:c => 1}, {:a => 3}, {:c => 7}] not to include (have key :d) at most once
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/index.html
new file mode 100644
index 000000000..30556b3fb
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/index.html
@@ -0,0 +1,124 @@
+
+
+
+
+Built in matchers
+
+rspec-expectations ships with a number of built-in matchers. Each matcher can be used
+with expect(..).to or expect(..).not_to to define positive and negative expectations
+respectively on an object. Most matchers can also be accessed using the (...).should and
+(...).should_not syntax; see using should syntax for why we recommend using expect.
+
+e.g.
+expect(result).to eq(3)
+expect(list).not_to be_empty
+pi.should be > 3
+
+Object identity
+expect(actual).to be(expected) # passes if actual.equal?(expected)
+
+Object equivalence
+expect(actual).to eq(expected) # passes if actual == expected
+
+Optional APIs for identity/equivalence
+expect(actual).to eql(expected) # passes if actual.eql?(expected)
+expect(actual).to equal(expected) # passes if actual.equal?(expected)
+
+# NOTE: `expect` does not support `==` matcher.
+
+Comparisons
+expect(actual).to be > expected
+expect(actual).to be >= expected
+expect(actual).to be <= expected
+expect(actual).to be < expected
+expect(actual).to be_between(minimum, maximum).inclusive
+expect(actual).to be_between(minimum, maximum).exclusive
+expect(actual).to match(/expression/)
+expect(actual).to be_within(delta).of(expected)
+expect(actual).to start_with expected
+expect(actual).to end_with expected
+
+# NOTE: `expect` does not support `=~` matcher.
+
+Types/classes/response
+expect(actual).to be_instance_of(expected)
+expect(actual).to be_kind_of(expected)
+expect(actual).to respond_to(expected)
+
+Truthiness and existentialism
+expect(actual).to be_truthy # passes if actual is truthy (not nil or false)
+expect(actual).to be true # passes if actual == true
+expect(actual).to be_falsey # passes if actual is falsy (nil or false)
+expect(actual).to be false # passes if actual == false
+expect(actual).to be_nil # passes if actual is nil
+expect(actual).to exist # passes if actual.exist? and/or actual.exists? are truthy
+expect(actual).to exist(*args) # passes if actual.exist?(*args) and/or actual.exists?(*args) are truthy
+
+Expecting errors
+expect { ... }.to raise_error
+expect { ... }.to raise_error(ErrorClass)
+expect { ... }.to raise_error("message")
+expect { ... }.to raise_error(ErrorClass, "message")
+
+Expecting throws
+expect { ... }.to throw_symbol
+expect { ... }.to throw_symbol(:symbol)
+expect { ... }.to throw_symbol(:symbol, 'value')
+
+Predicate matchers
+expect(actual).to be_xxx # passes if actual.xxx?
+expect(actual).to have_xxx(:arg) # passes if actual.has_xxx?(:arg)
+
+Examples
+expect([]).to be_empty
+expect(:a => 1).to have_key(:a)
+
+Collection membership
+expect(actual).to include(expected)
+expect(array).to match_array(expected_array)
+# ...which is the same as:
+expect(array).to contain_exactly(individual, elements)
+
+Examples
+expect([1, 2, 3]).to include(1)
+expect([1, 2, 3]).to include(1, 2)
+expect(:a => 'b').to include(:a => 'b')
+expect("this string").to include("is str")
+expect([1, 2, 3]).to contain_exactly(2, 1, 3)
+expect([1, 2, 3]).to match_array([3, 2, 1])
+
+Ranges (1.9+ only)
+expect(1..10).to cover(3)
+
+Change observation
+expect { object.action }.to change(object, :value).from(old).to(new)
+expect { object.action }.to change(object, :value).by(delta)
+expect { object.action }.to change(object, :value).by_at_least(minimum_delta)
+expect { object.action }.to change(object, :value).by_at_most(maximum_delta)
+
+Examples
+expect { a += 1 }.to change { a }.by(1)
+expect { a += 3 }.to change { a }.from(2)
+expect { a += 3 }.to change { a }.by_at_least(2)
+
+Satisfy
+expect(actual).to satisfy { |value| value == expected }
+
+Output capture
+expect { actual }.to output("some output").to_stdout
+expect { actual }.to output("some error").to_stderr
+
+Block expectation
+expect { |b| object.action(&b) }.to yield_control
+expect { |b| object.action(&b) }.to yield_with_no_args # only matches no args
+expect { |b| object.action(&b) }.to yield_with_args # matches any args
+expect { |b| object.action(&b) }.to yield_successive_args(*args) # matches args against multiple yields
+
+Examples
+expect { |b| User.transaction(&b) }.to yield_control
+expect { |b| User.transaction(&b) }.to yield_with_no_args
+expect { |b| 5.tap(&b) }.not_to yield_with_no_args # because it yields with `5`
+expect { |b| 5.tap(&b) }.to yield_with_args(5) # because 5 == 5
+expect { |b| 5.tap(&b) }.to yield_with_args(Integer) # because Integer === 5
+expect { |b| [1, 2, 3].each(&b) }.to yield_successive_args(1, 2, 3)
+
Topics
- Equality matchers
- Comparison matchers
- Predicate matchers
- Type matchers
- `all` matcher
- `be` matchers
- `be_within` matcher
- `exist` matcher
- `change` matcher
- `contain_exactly` matcher
- `cover` matcher
- `end_with` matcher
- `exist` matcher
- `have_attributes` matcher
- `include` matcher
- `match` matcher
- `raise_error` matcher
- `respond_to` matcher
- `satisfy` matcher
- `start_with` matcher
- `throw_symbol` matcher
- `yield` matchers
- `output` matcher
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/match/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/match/index.html
new file mode 100644
index 000000000..cf0801fa5
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/match/index.html
@@ -0,0 +1,81 @@
+
+
+
+
+match matcher
+
+The match matcher calls #match on the object, passing if #match returns a truthy (not
+ false or nil) value. Regexp and String both provide a #match method.
+```ruby
+expect("a string").to match(/str/) # passes
+expect("a string").to match(/foo/) # fails
+expect(/foo/).to match("food") # passes
+expect(/foo/).to match("drinks") # fails
+```
+
+You can also use this matcher to match nested data structures when composing matchers.
+
+String usage
+
+Given a file named “stringmatchspec.rb” with:
+RSpec.describe "a string" do
+ it { is_expected.to match(/str/) }
+ it { is_expected.not_to match(/foo/) }
+
+ # deliberate failures
+ it { is_expected.not_to match(/str/) }
+ it { is_expected.to match(/foo/) }
+end
+
+When I run rspec string_match_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+4 examples, 2 failures
+
+
+expected “a string” not to match /str/
+
+
+expected “a string” to match /foo/
+
+
+
+Regular expression usage
+
+Given a file named “regexpmatchspec.rb” with:
+RSpec.describe /foo/ do
+ it { is_expected.to match("food") }
+ it { is_expected.not_to match("drinks") }
+
+ # deliberate failures
+ it { is_expected.not_to match("food") }
+ it { is_expected.to match("drinks") }
+end
+
+When I run rspec regexp_match_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+4 examples, 2 failures
+
+
+expected /foo/ not to match “food”
+
+
+expected /foo/ to match “drinks”
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/output/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/output/index.html
new file mode 100644
index 000000000..33c45b5e3
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/output/index.html
@@ -0,0 +1,228 @@
+
+
+
+
+output matcher
+
+The output matcher provides a way to assert that the block has emitted content to either
+ $stdout or $stderr.
+
+With no arg, passes if the block outputs to_stdout or to_stderr. With a string, passes
+ if the blocks outputs that specific string to_stdout or to_stderr. With a regexp or
+ matcher, passes if the blocks outputs a string to_stdout or to_stderr that matches.
+
+Note: to_stdout and to_stderr work by temporarily replacing $stdout or $stderr, so
+ they’re not able to intercept stream output that explicitly uses STDOUT/STDERR or that
+ uses a reference to $stdout/$stderr that was stored before the matcher is used.
+
+To capture output from any spawned subprocess as well, use to_stdout_from_any_process
+ or to_stderr_from_any_process. Output from any process that inherits the main process’s
+ corresponding standard stream will be captured.
+
+Note: to_stdout_from_any_process and to_stderr_from_any_process use tempfiles to
+ capture output, and are thus significantly (~30x) slower than to_stdout and to_stderr.
+
+Using the output_to_stdout matcher
+
+Given a file named “outputtostdout_spec.rb” with:
+RSpec.describe "output.to_stdout matcher" do
+ specify { expect { print('foo') }.to output.to_stdout }
+ specify { expect { print('foo') }.to output('foo').to_stdout }
+ specify { expect { print('foo') }.to output(/foo/).to_stdout }
+ specify { expect { }.to_not output.to_stdout }
+ specify { expect { print('foo') }.to_not output('bar').to_stdout }
+ specify { expect { print('foo') }.to_not output(/bar/).to_stdout }
+
+ # deliberate failures
+ specify { expect { }.to output.to_stdout }
+ specify { expect { }.to output('foo').to_stdout }
+ specify { expect { print('foo') }.to_not output.to_stdout }
+ specify { expect { print('foo') }.to output('bar').to_stdout }
+ specify { expect { print('foo') }.to output(/bar/).to_stdout }
+end
+
+When I run rspec output_to_stdout_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+11 examples, 5 failures
+
+
+expected block to output to stdout, but did not
+
+
+expected block to not output to stdout, but output “foo”
+
+
+expected block to output “bar” to stdout, but output “foo”
+
+
+expected block to output “foo” to stdout, but output nothing
+
+
+expected block to output /bar/ to stdout, but output “foo”
+
+
+
+Using the output_to_stderr matcher
+
+Given a file named “outputtostderr.rb” with:
+RSpec.describe "output_to_stderr matcher" do
+ specify { expect { warn('foo') }.to output.to_stderr }
+ specify { expect { warn('foo') }.to output("foo\n").to_stderr }
+ specify { expect { warn('foo') }.to output(/foo/).to_stderr }
+ specify { expect { }.to_not output.to_stderr }
+ specify { expect { warn('foo') }.to_not output('bar').to_stderr }
+ specify { expect { warn('foo') }.to_not output(/bar/).to_stderr }
+
+ # deliberate failures
+ specify { expect { }.to output.to_stderr }
+ specify { expect { }.to output('foo').to_stderr }
+ specify { expect { warn('foo') }.to_not output.to_stderr }
+ specify { expect { warn('foo') }.to output('bar').to_stderr }
+ specify { expect { warn('foo') }.to output(/bar/).to_stderr }
+end
+
+When I run rspec output_to_stderr.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+11 examples, 5 failures
+
+
+expected block to output to stderr, but did not
+
+
+expected block to not output to stderr, but output “foo
+
+
+expected block to output "bar” to stderr, but output “foo
+
+
+”
+
+
+
+
+
+————————————————————–
+
+
+expected block to output “foo” to stderr, but output nothing
+
+
+expected block to output /bar/ to stderr, but output “foo
+
+
+”
+
+
+
+Using the output_to_stdout_from_any_process matcher
+
+Given a file named “outputtostdoutfromanyprocessspec.rb” with:
+RSpec.describe "output.to_stdout_from_any_process matcher" do
+ specify { expect { system('printf foo') }.to output.to_stdout_from_any_process }
+ specify { expect { system('printf foo') }.to output("foo").to_stdout_from_any_process }
+ specify { expect { system('printf foo') }.to output(/foo/).to_stdout_from_any_process }
+ specify { expect { }.to_not output.to_stdout_from_any_process }
+ specify { expect { system('printf foo') }.to_not output("bar").to_stdout_from_any_process }
+ specify { expect { system('printf foo') }.to_not output(/bar/).to_stdout_from_any_process }
+
+ # deliberate failures
+ specify { expect { }.to output.to_stdout_from_any_process }
+ specify { expect { }.to output('foo').to_stdout_from_any_process }
+ specify { expect { system('printf foo') }.to_not output.to_stdout_from_any_process }
+ specify { expect { system('printf foo') }.to output('bar').to_stdout_from_any_process }
+ specify { expect { system('printf foo') }.to output(/bar/).to_stdout_from_any_process }
+end
+
+When I run rspec output_to_stdout_from_any_process_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+11 examples, 5 failures
+
+
+expected block to output to stdout, but did not
+
+
+expected block to not output to stdout, but output “foo”
+
+
+expected block to output “bar” to stdout, but output “foo”
+
+
+expected block to output “foo” to stdout, but output nothing
+
+
+expected block to output /bar/ to stdout, but output “foo”
+
+
+
+Using the output_to_stderr_from_any_process matcher
+
+Given a file named “outputtostderrfromanyprocessspec.rb” with:
+RSpec.describe "output.to_stderr_from_any_process matcher" do
+ specify { expect { system('printf foo 1>&2') }.to output.to_stderr_from_any_process }
+ specify { expect { system('printf foo 1>&2') }.to output("foo").to_stderr_from_any_process }
+ specify { expect { system('printf foo 1>&2') }.to output(/foo/).to_stderr_from_any_process }
+ specify { expect { }.to_not output.to_stderr_from_any_process }
+ specify { expect { system('printf foo 1>&2') }.to_not output("bar").to_stderr_from_any_process }
+ specify { expect { system('printf foo 1>&2') }.to_not output(/bar/).to_stderr_from_any_process }
+
+ # deliberate failures
+ specify { expect { }.to output.to_stderr_from_any_process }
+ specify { expect { }.to output('foo').to_stderr_from_any_process }
+ specify { expect { system('printf foo 1>&2') }.to_not output.to_stderr_from_any_process }
+ specify { expect { system('printf foo 1>&2') }.to output('bar').to_stderr_from_any_process }
+ specify { expect { system('printf foo 1>&2') }.to output(/bar/).to_stderr_from_any_process }
+end
+
+When I run rspec output_to_stderr_from_any_process_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+11 examples, 5 failures
+
+
+expected block to output to stderr, but did not
+
+
+expected block to not output to stderr, but output “foo”
+
+
+expected block to output “bar” to stderr, but output “foo”
+
+
+expected block to output “foo” to stderr, but output nothing
+
+
+expected block to output /bar/ to stderr, but output “foo”
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/predicates/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/predicates/index.html
new file mode 100644
index 000000000..386d12b9f
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/predicates/index.html
@@ -0,0 +1,234 @@
+
+
+
+
+Predicate matchers
+
+Ruby objects commonly provide predicate methods:
+```ruby
+7.zero? # => false
+0.zero? # => true
+[1].empty? # => false
+[].empty? # => true
+{ :a => 5 }.has_key?(:b) # => false
+{ :b => 5 }.has_key?(:b) # => true
+```
+
+You could use a basic equality matcher to set expectations on these:
+```ruby
+expect(7.zero?).to eq true # fails with "expected true, got false (using ==)"
+```
+
+…but RSpec provides dynamic predicate matchers that are more readable and provide
+ better failure output.
+
+For any predicate method, RSpec gives you a corresponding matcher. Simply prefix the
+ method with be_ and remove the question mark. Examples:
+```ruby
+expect(7).not_to be_zero # calls 7.zero?
+expect([]).to be_empty # calls [].empty?
+expect(x).to be_multiple_of(3) # calls x.multiple_of?(3)
+```
+
+Alternately, for a predicate method that begins with has_ like Hash#has_key?, RSpec allows
+ you to use an alternate form since be_has_key makes no sense.
+```ruby
+expect(hash).to have_key(:foo) # calls hash.has_key?(:foo)
+expect(array).not_to have_odd_values # calls array.has_odd_values?
+```
+
+In either case, RSpec provides nice, clear error messages, such as:
+`expected zero? to be truthy, got false`
+
+Calling private methods will also fail:
+`expected private_method? to return true but it's a private method`
+
+Any arguments passed to the matcher will be passed on to the predicate method.
+
+Expecting subject to be_zero (based on Integer#zero?)
+
+Given a file named “shouldbezero_spec.rb” with:
+RSpec.describe 0 do
+ it { is_expected.to be_zero }
+end
+
+RSpec.describe 7 do
+ it { is_expected.to be_zero } # deliberate failure
+end
+
+When I run rspec should_be_zero_spec.rb
+
+Then the output should contain “2 examples, 1 failure”
+
+And the output should contain “expected 7.zero? to be truthy, got false”.
+
+Expecting subject to not be_empty (based on Array#empty?)
+
+Given a file named “shouldnotbeemptyspec.rb” with:
+RSpec.describe [1, 2, 3] do
+ it { is_expected.not_to be_empty }
+end
+
+RSpec.describe [] do
+ it { is_expected.not_to be_empty } # deliberate failure
+end
+
+When I run rspec should_not_be_empty_spec.rb
+
+Then the output should contain “2 examples, 1 failure”
+
+And the output should contain “expected [].empty? to be falsey, got true”.
+
+Expecting subject to have_key (based on Hash#has_key?)
+
+Given a file named “shouldhavekey_spec.rb” with:
+RSpec.describe Hash do
+ subject { { :foo => 7 } }
+ it { is_expected.to have_key(:foo) }
+ it { is_expected.to have_key(:bar) } # deliberate failure
+end
+
+When I run rspec should_have_key_spec.rb
+
+Then the output should contain “2 examples, 1 failure”
+
+And the output should contain “expected {:foo=>7}.has_key?(:bar) to be truthy, got false”.
+
+Expecting subject to have all decimals (based on custom has_decimals? method)
+
+Given a file named “shouldnothaveallstringkeysspec.rb” with:
+class Float
+ def has_decimals?
+ round != self
+ end
+end
+
+RSpec.describe Float do
+ context 'with decimals' do
+ subject { 4.2 }
+
+ it { is_expected.to have_decimals }
+ end
+
+ context 'with no decimals' do
+ subject { 42.0 }
+ it { is_expected.to have_decimals } # deliberate failure
+ end
+end
+
+When I run rspec should_not_have_all_string_keys_spec.rb
+
+Then the output should contain “2 examples, 1 failure”
+
+And the output should contain “expected 42.0.has_decimals? to be truthy, got false”.
+
+Matcher arguments are passed on to the predicate method
+
+Given a file named “predicatematcherargument_spec.rb” with:
+class Integer
+ def multiple_of?(x)
+ (self % x).zero?
+ end
+end
+
+RSpec.describe 12 do
+ it { is_expected.to be_multiple_of(3) }
+ it { is_expected.not_to be_multiple_of(7) }
+
+ # deliberate failures
+ it { is_expected.not_to be_multiple_of(4) }
+ it { is_expected.to be_multiple_of(5) }
+end
+
+When I run rspec predicate_matcher_argument_spec.rb
+
+Then the output should contain “4 examples, 2 failures”
+
+And the output should contain “expected 12.multiple_of?(4) to be falsey, got true”
+
+And the output should contain “expected 12.multiple_of?(5) to be truthy, got false”.
+
+The config strict_predicate_matchers impacts matching of results other than true and false
+
+Given a file named “strictornot.rb” with:
+class StrangeResult
+ def has_strange_result?
+ 42
+ end
+end
+
+RSpec.describe StrangeResult do
+ subject { StrangeResult.new }
+
+ before do
+ RSpec.configure do |config|
+ config.expect_with :rspec do |expectations|
+ expectations.strict_predicate_matchers = strict
+ end
+ end
+ end
+
+ context 'with non-strict matchers (default)' do
+ let(:strict) { false }
+ it { is_expected.to have_strange_result }
+ end
+
+ context 'with strict matchers' do
+ let(:strict) { true }
+ # deliberate failure
+ it { is_expected.to have_strange_result }
+ end
+end
+
+When I run rspec strict_or_not.rb
+
+Then the output should contain “2 examples, 1 failure”
+
+And the output should contain “hasstrangeresult?` to return true, got 42”.
+
+Calling private method with be_predicate causes error
+
+Given a file named “attemptingtomatchprivatemethod_spec.rb” with:
+class WithPrivateMethods
+ def secret?
+ true
+ end
+ private :secret?
+end
+
+RSpec.describe 'private methods' do
+ subject { WithPrivateMethods.new }
+
+ # deliberate failure
+ it { is_expected.to be_secret }
+end
+
+When I run rspec attempting_to_match_private_method_spec.rb
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should contain “secret? is a private method”.
+
+Calling private method with have_predicate causes error
+
+Given a file named “attemptingtomatchprivatemethod_spec.rb” with:
+class WithPrivateMethods
+ def has_secret?
+ true
+ end
+ private :has_secret?
+end
+
+RSpec.describe 'private methods' do
+ subject { WithPrivateMethods.new }
+
+ # deliberate failure
+ it { is_expected.to have_secret }
+end
+
+When I run rspec attempting_to_match_private_method_spec.rb
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should contain “has_secret? is a private method”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/raise-error/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/raise-error/index.html
new file mode 100644
index 000000000..024a25e81
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/raise-error/index.html
@@ -0,0 +1,170 @@
+
+
+
+
+raise_error matcher
+
+Use the raise_error matcher to specify that a block of code raises an error. The most
+ basic form passes if any error is thrown:
+```ruby
+expect { raise StandardError }.to raise_error
+```
+
+You can use raise_exception instead if you prefer that wording:
+```ruby
+expect { 3 / 0 }.to raise_exception
+```
+
+raise_error and raise_exception are functionally interchangeable, so use the one that
+ makes the most sense to you in any given context.
+
+In addition to the basic form, above, there are a number of ways to specify details of an
+ error/exception:
+```ruby
+expect { raise "oops" }.to raise_error
+expect { raise "oops" }.to raise_error(RuntimeError)
+expect { raise "oops" }.to raise_error("oops")
+expect { raise "oops" }.to raise_error(/op/)
+expect { raise "oops" }.to raise_error(RuntimeError, "oops")
+expect { raise "oops" }.to raise_error(RuntimeError, /op/)
+expect { raise "oops" }.to raise_error(an_instance_of(RuntimeError).and having_attributes(message: "oops"))
+```
+
+Expecting any error
+
+Given a file named “example_spec” with:
+RSpec.describe "calling a missing method" do
+ it "raises" do
+ expect { Object.new.foo }.to raise_error
+ end
+end
+
+When I run rspec example_spec
+
+Then the example should pass.
+
+Expecting a specific error
+
+Given a file named “example_spec” with:
+RSpec.describe "calling a missing method" do
+ it "raises" do
+ expect { Object.new.foo }.to raise_error(NameError)
+ end
+end
+
+When I run rspec example_spec
+
+Then the example should pass.
+
+Matching a message with a string
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "matching error message with string" do
+ it "matches the error message" do
+ expect { raise StandardError, 'this message exactly'}.
+ to raise_error('this message exactly')
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the example should pass.
+
+Matching a message with a regexp
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "matching error message with regex" do
+ it "matches the error message" do
+ expect { raise StandardError, "my message" }.
+ to raise_error(/my mess/)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the example should pass.
+
+Matching a message with with_message
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "matching error message with regex" do
+ it "matches the error message" do
+ expect { raise StandardError, "my message" }.
+ to raise_error.with_message(/my mess/)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the example should pass.
+
+Matching a class + message with string
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "matching error message with string" do
+ it "matches the error message" do
+ expect { raise StandardError, 'this message exactly'}.
+ to raise_error(StandardError, 'this message exactly')
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the example should pass.
+
+Matching a class + message with regexp
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "matching error message with regex" do
+ it "matches the error message" do
+ expect { raise StandardError, "my message" }.
+ to raise_error(StandardError, /my mess/)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the example should pass.
+
+Setting expectations on error object passed to block
+
+Given a file named “example_spec” with:
+RSpec.describe "#foo" do
+ it "raises NameError" do
+ expect { Object.new.foo }.to raise_error { |error|
+ expect(error).to be_a(NameError)
+ }
+ end
+end
+
+When I run rspec example_spec
+
+Then the example should pass.
+
+Setting expectations on an error object with chained matchers
+
+Given a file named “example_spec” with:
+RSpec.describe "composing matchers" do
+ it "raises StandardError" do
+ expect { raise StandardError, "my message" }.
+ to raise_error(an_instance_of(StandardError).and having_attributes({"message" => "my message"}))
+ end
+end
+
+When I run rspec example_spec
+
+Then the example should pass.
+
+Expecting no error at all
+
+Given a file named “example_spec” with:
+RSpec.describe "#to_s" do
+ it "does not raise" do
+ expect { Object.new.to_s }.not_to raise_error
+ end
+end
+
+When I run rspec example_spec
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/respond-to/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/respond-to/index.html
new file mode 100644
index 000000000..48cf1faa9
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/respond-to/index.html
@@ -0,0 +1,395 @@
+
+
+
+
+respond_to matcher
+
+Use the respond_to matcher to specify details of an object’s interface. In its most basic form:
+```ruby
+expect(obj).to respond_to(:foo) # pass if obj.respond_to?(:foo)
+```
+
+You can specify that an object responds to multiple messages in a single statement with
+ multiple arguments passed to the matcher:
+```ruby
+expect(obj).to respond_to(:foo, :bar) # passes if obj.respond_to?(:foo) && obj.respond_to?(:bar)
+```
+
+If the number of arguments accepted by the method is important to you, you can specify
+ that as well:
+```ruby
+expect(obj).to respond_to(:foo).with(1).argument
+expect(obj).to respond_to(:bar).with(2).arguments
+expect(obj).to respond_to(:baz).with(1..2).arguments
+expect(obj).to respond_to(:xyz).with_unlimited_arguments
+```
+
+If your Ruby version supports keyword arguments, you can specify a list of keywords accepted
+ by the method.
+```ruby
+expect(obj).to respond_to(:foo).with_keywords(:ichi, :ni)
+expect(obj).to respond_to(:bar).with(2).arguments.and_keywords(:san, :yon)
+expect(obj).to respond_to(:baz).with_arbitrary_keywords
+```
+
+Note that this matcher relies entirely upon #respond_to?. If an object dynamically responds
+ to a message via #method_missing, but does not indicate this via #respond_to?, then this
+ matcher will give you false results.
+
+Basic usage
+
+Given a file named “respondtomatcher_spec.rb” with:
+RSpec.describe "a string" do
+ it { is_expected.to respond_to(:length) }
+ it { is_expected.to respond_to(:hash, :class, :to_s) }
+ it { is_expected.not_to respond_to(:to_model) }
+ it { is_expected.not_to respond_to(:compact, :flatten) }
+
+ # deliberate failures
+ it { is_expected.to respond_to(:to_model) }
+ it { is_expected.to respond_to(:compact, :flatten) }
+ it { is_expected.not_to respond_to(:length) }
+ it { is_expected.not_to respond_to(:hash, :class, :to_s) }
+
+ # mixed examples--String responds to :length but not :flatten
+ # both specs should fail
+ it { is_expected.to respond_to(:length, :flatten) }
+ it { is_expected.not_to respond_to(:length, :flatten) }
+end
+
+When I run rspec respond_to_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+10 examples, 6 failures
+
+
+expected “a string” to respond to :to_model
+
+
+expected “a string” to respond to :compact, :flatten
+
+
+expected “a string” not to respond to :length
+
+
+expected “a string” not to respond to :hash, :class, :to_s
+
+
+expected “a string” to respond to :flatten
+
+
+expected “a string” not to respond to :length
+
+
+
+Specify arguments
+
+Given a file named “respondtomatcherargumentchecking_spec.rb” with:
+RSpec.describe 7 do
+ it { is_expected.to respond_to(:zero?).with(0).arguments }
+ it { is_expected.not_to respond_to(:zero?).with(1).argument }
+
+ it { is_expected.to respond_to(:between?).with(2).arguments }
+ it { is_expected.not_to respond_to(:between?).with(7).arguments }
+
+ # deliberate failures
+ it { is_expected.to respond_to(:zero?).with(1).argument }
+ it { is_expected.not_to respond_to(:zero?).with(0).arguments }
+
+ it { is_expected.to respond_to(:between?).with(7).arguments }
+ it { is_expected.not_to respond_to(:between?).with(2).arguments }
+end
+
+When I run rspec respond_to_matcher_argument_checking_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+8 examples, 4 failures
+
+
+expected 7 to respond to :zero? with 1 argument
+
+
+expected 7 not to respond to :zero? with 0 arguments
+
+
+expected 7 to respond to :between? with 7 arguments
+
+
+expected 7 not to respond to :between? with 2 arguments
+
+
+
+Specify arguments range
+
+Given a file named “respondtomatcherargumentrangecheckingspec.rb” with:
+class MyClass
+ def build(name, options = {})
+ end
+
+ def inspect
+ 'my_object'
+ end
+end
+
+RSpec.describe MyClass do
+ it { is_expected.to respond_to(:build).with(1..2).arguments }
+ it { is_expected.not_to respond_to(:build).with(0..1).arguments }
+ it { is_expected.not_to respond_to(:build).with(2..3).arguments }
+ it { is_expected.not_to respond_to(:build).with(0..3).arguments }
+
+ # deliberate failures
+ it { is_expected.not_to respond_to(:build).with(1..2).arguments }
+ it { is_expected.to respond_to(:build).with(0..1).arguments }
+ it { is_expected.to respond_to(:build).with(2..3).arguments }
+ it { is_expected.to respond_to(:build).with(0..3).arguments }
+end
+
+When I run rspec respond_to_matcher_argument_range_checking_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+8 examples, 4 failures
+
+
+expected my_object not to respond to :build with 1..2 arguments
+
+
+expected my_object to respond to :build with 0..1 arguments
+
+
+expected my_object to respond to :build with 2..3 arguments
+
+
+expected my_object to respond to :build with 0..3 arguments
+
+
+
+Specify unlimited arguments
+
+Given a file named “respondtomatcherunlimitedargumentcheckingspec.rb” with:
+class MyClass
+ def greet(message = 'Hello', *people)
+ end
+
+ def hail(person)
+ end
+
+ def inspect
+ 'my_object'
+ end
+end
+
+RSpec.describe MyClass do
+ it { is_expected.to respond_to(:greet).with_unlimited_arguments }
+ it { is_expected.to respond_to(:greet).with(1).argument.and_unlimited_arguments }
+ it { is_expected.not_to respond_to(:hail).with_unlimited_arguments }
+ it { is_expected.not_to respond_to(:hail).with(1).argument.and_unlimited_arguments }
+
+ # deliberate failures
+ it { is_expected.not_to respond_to(:greet).with_unlimited_arguments }
+ it { is_expected.not_to respond_to(:greet).with(1).argument.and_unlimited_arguments }
+ it { is_expected.to respond_to(:hail).with_unlimited_arguments }
+ it { is_expected.to respond_to(:hail).with(1).argument.and_unlimited_arguments }
+end
+
+When I run rspec respond_to_matcher_unlimited_argument_checking_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+8 examples, 4 failures
+
+
+expected my_object not to respond to :greet with unlimited arguments
+
+
+expected my_object not to respond to :greet with 1 argument and unlimited arguments
+
+
+expected my_object to respond to :hail with unlimited arguments
+
+
+expected my_object to respond to :hail with 1 argument and unlimited arguments
+
+
+
+Specify keywords
+
+Given a file named “respondtomatcherkeywordchecking_spec.rb” with:
+class MyClass
+ def find(name = 'id', limit: 1_000, offset: 0)
+ []
+ end
+
+ def inspect
+ 'my_object'
+ end
+end
+
+RSpec.describe MyClass do
+ it { is_expected.to respond_to(:find).with_keywords(:limit, :offset) }
+ it { is_expected.to respond_to(:find).with(1).argument.and_keywords(:limit, :offset) }
+
+ it { is_expected.not_to respond_to(:find).with_keywords(:limit, :offset, :page) }
+ it { is_expected.not_to respond_to(:find).with(1).argument.and_keywords(:limit, :offset, :page) }
+
+ # deliberate failures
+ it { is_expected.to respond_to(:find).with_keywords(:limit, :offset, :page) }
+ it { is_expected.to respond_to(:find).with(1).argument.and_keywords(:limit, :offset, :page) }
+
+ it { is_expected.not_to respond_to(:find).with_keywords(:limit, :offset) }
+ it { is_expected.not_to respond_to(:find).with(1).argument.and_keywords(:limit, :offset) }
+end
+
+When I run rspec respond_to_matcher_keyword_checking_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+8 examples, 4 failures
+
+
+expected my_object to respond to :find with keywords :limit, :offset, and :page
+
+
+expected my_object to respond to :find with 1 argument and keywords :limit, :offset, and :page
+
+
+expected my_object not to respond to :find with keywords :limit and :offset
+
+
+expected my_object not to respond to :find with 1 argument and keywords :limit and :offset
+
+
+
+Specify any keywords
+
+Given a file named “respondtomatcheranykeywordscheckingspec.rb” with:
+class MyClass
+ def build(name: 'object', **opts)
+ end
+
+ def create(name: 'object', type: String)
+ end
+
+ def inspect
+ 'my_object'
+ end
+end
+
+RSpec.describe MyClass do
+ it { is_expected.to respond_to(:build).with_any_keywords }
+ it { is_expected.to respond_to(:build).with_keywords(:name).and_any_keywords }
+ it { is_expected.not_to respond_to(:create).with_any_keywords }
+ it { is_expected.not_to respond_to(:create).with_keywords(:name).and_any_keywords }
+
+ # deliberate failures
+ it { is_expected.not_to respond_to(:build).with_any_keywords }
+ it { is_expected.not_to respond_to(:build).with_keywords(:name).and_any_keywords }
+ it { is_expected.to respond_to(:create).with_any_keywords }
+ it { is_expected.to respond_to(:create).with_keywords(:name).and_any_keywords }
+end
+
+When I run rspec respond_to_matcher_any_keywords_checking_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+8 examples, 4 failures
+
+
+expected my_object not to respond to :build with any keywords
+
+
+expected my_object not to respond to :build with keyword :name and any keywords
+
+
+expected my_object to respond to :create with any keywords
+
+
+expected my_object to respond to :create with keyword :name and any keywords
+
+
+
+Specify required keywords
+
+Given a file named “respondtomatcherrequiredkeywordcheckingspec.rb” with:
+class MyClass
+ def plant(seed:, fertilizer: nil, water: 'daily')
+ []
+ end
+
+ def inspect
+ 'my_object'
+ end
+end
+
+RSpec.describe MyClass do
+ it { is_expected.to respond_to(:plant).with_keywords(:seed) }
+ it { is_expected.to respond_to(:plant).with_keywords(:seed, :fertilizer, :water) }
+ it { is_expected.not_to respond_to(:plant).with_keywords(:fertilizer, :water) }
+
+ # deliberate failures
+ it { is_expected.not_to respond_to(:plant).with_keywords(:seed) }
+ it { is_expected.not_to respond_to(:plant).with_keywords(:seed, :fertilizer, :water) }
+ it { is_expected.to respond_to(:plant).with_keywords(:fertilizer, :water) }
+end
+
+When I run rspec respond_to_matcher_required_keyword_checking_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+6 examples, 3 failures
+
+
+expected my_object not to respond to :plant with keyword :seed
+
+
+expected my_object not to respond to :plant with keywords :seed, :fertilizer, and :water
+
+
+expected my_object to respond to :plant with keywords :fertilizer and :water
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/satisfy/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/satisfy/index.html
new file mode 100644
index 000000000..b9a49e63e
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/satisfy/index.html
@@ -0,0 +1,61 @@
+
+
+
+
+satisfy matcher
+
+The satisfy matcher is extremely flexible and can handle almost anything you want to
+ specify. It passes if the block you provide returns true:
+```ruby
+expect(10).to satisfy { |v| v % 5 == 0 }
+expect(7).not_to satisfy { |v| v % 5 == 0 }
+```
+
+The default failure message (“expected [actual] to satisfy block”) is not very descriptive or helpful.
+ To add clarification, you can provide your own description as an argument:
+```ruby
+expect(10).to satisfy("be a multiple of 5") do |v|
+ v % 5 == 0
+end
+```
+
+Basic usage
+
+Given a file named “satisfymatcherspec.rb” with:
+RSpec.describe 10 do
+ it { is_expected.to satisfy { |v| v > 5 } }
+ it { is_expected.not_to satisfy { |v| v > 15 } }
+
+ # deliberate failures
+ it { is_expected.not_to satisfy { |v| v > 5 } }
+ it { is_expected.to satisfy { |v| v > 15 } }
+ it { is_expected.to_not satisfy("be greater than 5") { |v| v > 5 } }
+ it { is_expected.to satisfy("be greater than 15") { |v| v > 15 } }
+end
+
+When I run rspec satisfy_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+6 examples, 4 failures
+
+
+expected 10 not to satisfy expression v > 5
+
+
+expected 10 to satisfy expression v > 15
+
+
+expected 10 not to be greater than 5
+
+
+expected 10 to be greater than 15
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/start-with/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/start-with/index.html
new file mode 100644
index 000000000..1662b7fd3
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/start-with/index.html
@@ -0,0 +1,80 @@
+
+
+
+
+start_with matcher
+
+Use the start_with matcher to specify that a string or array starts with the expected
+ characters or elements.
+```ruby
+expect("this string").to start_with("this")
+expect("this string").not_to start_with("that")
+expect([0,1,2]).to start_with(0, 1)
+```
+
+With a string
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "this string" do
+ it { is_expected.to start_with "this" }
+ it { is_expected.not_to start_with "that" }
+
+ # deliberate failures
+ it { is_expected.not_to start_with "this" }
+ it { is_expected.to start_with "that" }
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+4 examples, 2 failures
+
+
+expected “this string” not to start with “this”
+
+
+expected “this string” to start with “that”
+
+
+
+With an array
+
+Given a file named “example_spec.rb” with:
+RSpec.describe [0, 1, 2, 3, 4] do
+ it { is_expected.to start_with 0 }
+ it { is_expected.to start_with(0, 1)}
+ it { is_expected.not_to start_with(2) }
+ it { is_expected.not_to start_with(0, 1, 2, 3, 4, 5) }
+
+ # deliberate failures
+ it { is_expected.not_to start_with 0 }
+ it { is_expected.to start_with 3 }
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+6 examples, 2 failures
+
+
+expected [0, 1, 2, 3, 4] not to start with 0
+
+
+expected [0, 1, 2, 3, 4] to start with 3
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/throw-symbol/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/throw-symbol/index.html
new file mode 100644
index 000000000..89b5a38b6
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/throw-symbol/index.html
@@ -0,0 +1,143 @@
+
+
+
+
+throw_symbol matcher
+
+The throw_symbol matcher is used to specify that a block of code throws a symbol. The most
+ basic form passes if any symbol is thrown:
+```ruby
+expect { throw :foo }.to throw_symbol
+```
+
+You’ll often want to specify that a particular symbol is thrown:
+```ruby
+expect { throw :foo }.to throw_symbol(:foo)
+```
+
+If you care about the additional argument given to throw, you can specify that as well:
+```ruby
+expect { throw :foo, 7 }.to throw_symbol(:foo, 7)
+```
+
+Basic usage
+
+Given a file named “throwsymbolmatcher_spec.rb” with:
+RSpec.describe "throw" do
+ specify { expect { throw :foo }.to throw_symbol }
+ specify { expect { throw :bar, 7 }.to throw_symbol }
+ specify { expect { 5 + 5 }.not_to throw_symbol }
+
+ # deliberate failures
+ specify { expect { throw :foo }.not_to throw_symbol }
+ specify { expect { throw :bar, 7 }.not_to throw_symbol }
+ specify { expect { 5 + 5 }.to throw_symbol }
+end
+
+When I run rspec throw_symbol_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+6 examples, 3 failures
+
+
+expected no Symbol to be thrown, got :foo
+
+
+expected no Symbol to be thrown, got :bar
+
+
+expected a Symbol to be thrown, got nothing
+
+
+
+Specify thrown symbol
+
+Given a file named “throwsymbolmatcher_spec.rb” with:
+RSpec.describe "throw symbol" do
+ specify { expect { throw :foo }.to throw_symbol(:foo) }
+ specify { expect { throw :foo, 7 }.to throw_symbol(:foo) }
+ specify { expect { 5 + 5 }.not_to throw_symbol(:foo) }
+ specify { expect { throw :bar }.not_to throw_symbol(:foo) }
+
+ # deliberate failures
+ specify { expect { throw :foo }.not_to throw_symbol(:foo) }
+ specify { expect { throw :foo, 7 }.not_to throw_symbol(:foo) }
+ specify { expect { 5 + 5 }.to throw_symbol(:foo) }
+ specify { expect { throw :bar }.to throw_symbol(:foo) }
+end
+
+When I run rspec throw_symbol_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+8 examples, 4 failures
+
+
+expected :foo not to be thrown, got :foo
+
+
+expected :foo not to be thrown, got :foo with 7
+
+
+expected :foo to be thrown, got nothing
+
+
+expected :foo to be thrown, got :bar
+
+
+
+Specify thrown symbol and argument
+
+Given a file named “throwsymbolargumentmatcherspec.rb” with:
+RSpec.describe "throw symbol with argument" do
+ specify { expect { throw :foo, 7 }.to throw_symbol(:foo, 7) }
+ specify { expect { throw :foo, 8 }.not_to throw_symbol(:foo, 7) }
+ specify { expect { throw :bar, 7 }.not_to throw_symbol(:foo, 7) }
+ specify { expect { throw :foo }.not_to throw_symbol(:foo, 7) }
+
+ # deliberate failures
+ specify { expect { throw :foo, 7 }.not_to throw_symbol(:foo, 7) }
+ specify { expect { throw :foo, 8 }.to throw_symbol(:foo, 7) }
+ specify { expect { throw :bar, 7 }.to throw_symbol(:foo, 7) }
+ specify { expect { throw :foo }.to throw_symbol(:foo, 7) }
+end
+
+When I run rspec throw_symbol_argument_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+8 examples, 4 failures
+
+
+expected :foo with 7 not to be thrown, got :foo with 7
+
+
+expected :foo with 7 to be thrown, got :foo with 8
+
+
+expected :foo with 7 to be thrown, got :bar
+
+
+expected :foo with 7 to be thrown, got :foo with no argument
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/types/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/types/index.html
new file mode 100644
index 000000000..f89327690
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/types/index.html
@@ -0,0 +1,155 @@
+
+
+
+
+Type matchers
+
+rspec-expectations includes two matchers to specify types of objects:
+* `expect(obj).to be_kind_of(type)`: calls `obj.kind_of?(type)`, which returns true if
+ type is in obj's class hierarchy or is a module and is included in a class in obj's
+ class hierarchy.
+* `expect(obj).to be_instance_of(type)`: calls `obj.instance_of?(type)`, which returns
+ true if and only if type if obj's class.
+
+Both of these matchers have aliases:
+```ruby
+expect(obj).to be_a_kind_of(type) # same as expect(obj).to be_kind_of(type)
+expect(obj).to be_a(type) # same as expect(obj).to be_kind_of(type)
+expect(obj).to be_an(type) # same as expect(obj).to be_kind_of(type)
+expect(obj).to be_an_instance_of(type) # same as expect(obj).to be_instance_of(type)
+```
+
+With be_(a_)kind_of matcher
+
+Given a file named “bekindofmatcherspec.rb” with:
+module MyModule; end
+
+class Float
+ include MyModule
+end
+
+RSpec.describe 17.0 do
+ # the actual class
+ it { is_expected.to be_kind_of(Float) }
+ it { is_expected.to be_a_kind_of(Float) }
+ it { is_expected.to be_a(Float) }
+
+ # the superclass
+ it { is_expected.to be_kind_of(Numeric) }
+ it { is_expected.to be_a_kind_of(Numeric) }
+ it { is_expected.to be_an(Numeric) }
+
+ # an included module
+ it { is_expected.to be_kind_of(MyModule) }
+ it { is_expected.to be_a_kind_of(MyModule) }
+ it { is_expected.to be_a(MyModule) }
+
+ # negative passing case
+ it { is_expected.not_to be_kind_of(String) }
+ it { is_expected.not_to be_a_kind_of(String) }
+ it { is_expected.not_to be_a(String) }
+
+ # deliberate failures
+ it { is_expected.not_to be_kind_of(Float) }
+ it { is_expected.not_to be_a_kind_of(Float) }
+ it { is_expected.not_to be_a(Float) }
+ it { is_expected.not_to be_kind_of(Numeric) }
+ it { is_expected.not_to be_a_kind_of(Numeric) }
+ it { is_expected.not_to be_an(Numeric) }
+ it { is_expected.not_to be_kind_of(MyModule) }
+ it { is_expected.not_to be_a_kind_of(MyModule) }
+ it { is_expected.not_to be_a(MyModule) }
+ it { is_expected.to be_kind_of(String) }
+ it { is_expected.to be_a_kind_of(String) }
+ it { is_expected.to be_a(String) }
+end
+
+When I run rspec be_kind_of_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+24 examples, 12 failures
+
+
+expected 17.0 not to be a kind of Float
+
+
+expected 17.0 not to be a kind of Numeric
+
+
+expected 17.0 not to be a kind of MyModule
+
+
+expected 17.0 to be a kind of String
+
+
+
+With be_(an_)instance_of matcher
+
+Given a file named “beinstanceofmatcherspec.rb” with:
+module MyModule; end
+
+class Float
+ include MyModule
+end
+
+RSpec.describe 17.0 do
+ # the actual class
+ it { is_expected.to be_instance_of(Float) }
+ it { is_expected.to be_an_instance_of(Float) }
+
+ # the superclass
+ it { is_expected.not_to be_instance_of(Numeric) }
+ it { is_expected.not_to be_an_instance_of(Numeric) }
+
+ # an included module
+ it { is_expected.not_to be_instance_of(MyModule) }
+ it { is_expected.not_to be_an_instance_of(MyModule) }
+
+ # another class with no relation to the subject's hierarchy
+ it { is_expected.not_to be_instance_of(String) }
+ it { is_expected.not_to be_an_instance_of(String) }
+
+ # deliberate failures
+ it { is_expected.not_to be_instance_of(Float) }
+ it { is_expected.not_to be_an_instance_of(Float) }
+ it { is_expected.to be_instance_of(Numeric) }
+ it { is_expected.to be_an_instance_of(Numeric) }
+ it { is_expected.to be_instance_of(MyModule) }
+ it { is_expected.to be_an_instance_of(MyModule) }
+ it { is_expected.to be_instance_of(String) }
+ it { is_expected.to be_an_instance_of(String) }
+end
+
+When I run rspec be_instance_of_matcher_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+16 examples, 8 failures
+
+
+expected 17.0 not to be an instance of Float
+
+
+expected 17.0 to be an instance of Numeric
+
+
+expected 17.0 to be an instance of MyModule
+
+
+expected 17.0 to be an instance of String
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/built-in-matchers/yield/index.html b/docs/features/3-12/rspec-expectations/built-in-matchers/yield/index.html
new file mode 100644
index 000000000..8bfd4e785
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/built-in-matchers/yield/index.html
@@ -0,0 +1,223 @@
+
+
+
+
+yield matchers
+
+There are four related matchers that allow you to specify whether or not a method yields,
+ how many times it yields, whether or not it yields with arguments, and what those
+ arguments are.
+* `yield_control` matches if the method-under-test yields, regardless of whether or not
+ arguments are yielded.
+* `yield_with_args` matches if the method-under-test yields with arguments. If arguments
+ are provided to this matcher, it will only pass if the actual yielded arguments match the expected ones using `===` or `==`.
+* `yield_with_no_args` matches if the method-under-test yields with no arguments.
+* `yield_successive_args` is designed for iterators, and will match if the method-under-test
+ yields the same number of times as arguments passed to this matcher, and all actual yielded arguments match the expected ones using `===` or `==`.
+
+Note: your expect block must accept an argument that is then passed on to the
+ method-under-test as a block. This acts as a “probe” that allows the matcher to detect
+ whether or not your method yields, and, if so, how many times and what the yielded
+ arguments are.
+
+Background
+
+Given a file named “my_class.rb” with:
+class MyClass
+ def self.yield_once_with(*args)
+ yield *args
+ end
+
+ def self.yield_twice_with(*args)
+ 2.times { yield *args }
+ end
+
+ def self.raw_yield
+ yield
+ end
+
+ def self.dont_yield
+ end
+end
+
+The yield_control matcher
+
+Given a file named “yieldcontrolspec.rb” with:
+require './my_class'
+
+RSpec.describe "yield_control matcher" do
+ specify { expect { |b| MyClass.yield_once_with(1, &b) }.to yield_control }
+ specify { expect { |b| MyClass.dont_yield(&b) }.not_to yield_control }
+ specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.twice }
+ specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.exactly(2).times }
+ specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.at_least(1) }
+ specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.at_most(3).times }
+
+ # deliberate failures
+ specify { expect { |b| MyClass.yield_once_with(1, &b) }.not_to yield_control }
+ specify { expect { |b| MyClass.dont_yield(&b) }.to yield_control }
+ specify { expect { |b| MyClass.yield_once_with(1, &b) }.to yield_control.at_least(2).times }
+ specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.twice }
+ specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.at_least(2).times }
+ specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.at_least(1) }
+ specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.at_most(3).times }
+end
+
+When I run rspec yield_control_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+13 examples, 7 failures
+
+
+expected given block to yield control
+
+
+expected given block not to yield control
+
+
+expected given block not to yield control at least twice
+
+
+expected given block not to yield control at most 3 times
+
+
+
+The yield_with_args matcher
+
+Given a file named “yieldwithargs_spec.rb” with:
+require './my_class'
+
+RSpec.describe "yield_with_args matcher" do
+ specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args }
+ specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args("foo") }
+ specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args(String) }
+ specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args(/oo/) }
+
+ specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args("foo", "bar") }
+ specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args(String, String) }
+ specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args(/fo/, /ar/) }
+
+ specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.not_to yield_with_args(17, "baz") }
+
+ # deliberate failures
+ specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args }
+ specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args("foo") }
+ specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args(String) }
+ specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args(/oo/) }
+ specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.not_to yield_with_args("foo", "bar") }
+ specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args(17, "baz") }
+end
+
+When I run rspec yield_with_args_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+14 examples, 6 failures
+
+
+expected given block not to yield with arguments, but did
+
+
+expected given block not to yield with arguments, but yielded with expected arguments
+
+
+expected given block to yield with arguments, but yielded with unexpected arguments
+
+
+
+The yield_with_no_args matcher
+
+Given a file named “yieldwithnoargsspec.rb” with:
+require './my_class'
+
+RSpec.describe "yield_with_no_args matcher" do
+ specify { expect { |b| MyClass.raw_yield(&b) }.to yield_with_no_args }
+ specify { expect { |b| MyClass.dont_yield(&b) }.not_to yield_with_no_args }
+ specify { expect { |b| MyClass.yield_once_with("a", &b) }.not_to yield_with_no_args }
+
+ # deliberate failures
+ specify { expect { |b| MyClass.raw_yield(&b) }.not_to yield_with_no_args }
+ specify { expect { |b| MyClass.dont_yield(&b) }.to yield_with_no_args }
+ specify { expect { |b| MyClass.yield_once_with("a", &b) }.to yield_with_no_args }
+end
+
+When I run rspec yield_with_no_args_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+6 examples, 3 failures
+
+
+expected given block not to yield with no arguments, but did
+
+
+expected given block to yield with no arguments, but did not yield
+
+
+expected given block to yield with no arguments, but yielded with arguments: [“a”]
+
+
+
+The yield_successive_args matcher
+
+Given a file named “yieldsuccessiveargs_spec.rb” with:
+def array
+ [1, 2, 3]
+end
+
+def array_of_tuples
+ [[:a, :b], [:c, :d]]
+end
+
+RSpec.describe "yield_successive_args matcher" do
+ specify { expect { |b| array.each(&b) }.to yield_successive_args(1, 2, 3) }
+ specify { expect { |b| array_of_tuples.each(&b) }.to yield_successive_args([:a, :b], [:c, :d]) }
+ specify { expect { |b| array.each(&b) }.to yield_successive_args(Integer, Integer, Integer) }
+ specify { expect { |b| array.each(&b) }.not_to yield_successive_args(1, 2) }
+
+ # deliberate failures
+ specify { expect { |b| array.each(&b) }.not_to yield_successive_args(1, 2, 3) }
+ specify { expect { |b| array_of_tuples.each(&b) }.not_to yield_successive_args([:a, :b], [:c, :d]) }
+ specify { expect { |b| array.each(&b) }.not_to yield_successive_args(Integer, Integer, Integer) }
+ specify { expect { |b| array.each(&b) }.to yield_successive_args(1, 2) }
+end
+
+When I run rspec yield_successive_args_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+8 examples, 4 failures
+
+
+expected given block not to yield successively with arguments, but yielded with expected arguments
+
+
+expected given block to yield successively with arguments, but yielded with unexpected arguments
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/composing-matchers/index.html b/docs/features/3-12/rspec-expectations/composing-matchers/index.html
new file mode 100644
index 000000000..261d912dc
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/composing-matchers/index.html
@@ -0,0 +1,260 @@
+
+
+
+
+Composing Matchers
+
+RSpec’s matchers are designed to be composable so that you can combine them to express
+ the exact details of what you expect but nothing more. This can help you avoid writing
+ over-specified brittle specs, by using a matcher in place of an exact value to specify only
+ the essential aspects of what you expect.
+
+The following matchers accept matchers as arguments:
+* `change { }.by(matcher)`
+* `change { }.from(matcher).to(matcher)`
+* `contain_exactly(matcher, matcher, matcher)`
+* `end_with(matcher, matcher)`
+* `include(matcher, matcher)`
+* `include(:key => matcher, :other => matcher)`
+* `match(arbitrary_nested_structure_with_matchers)`
+* `output(matcher).to_stdout`
+* `output(matcher).to_stderr`
+* `raise_error(ErrorClass, matcher)`
+* `start_with(matcher, matcher)`
+* `throw_symbol(:sym, matcher)`
+* `yield_with_args(matcher, matcher)`
+* `yield_successive_args(matcher, matcher)`
+
+Note that many built-in matchers do not accept matcher arguments because they have precise
+ semantics that do not allow for a matcher argument. For example, equal(some_object) is
+ designed to pass only if the actual and expected arguments are references to the same
+ object. It would not make sense to support a matcher argument here.
+
+All of RSpec’s built-in matchers have one or more aliases that allow you to use a noun-phrase
+ rather than verb form since they read better as composed arguments. They also provide
+ customized failure output so that the failure message reads better as well.
+
+A full list of these aliases is out of scope here, but here are some of the aliases used below:
+* `be < 2` => `a_value < 2`
+* `be > 2` => `a_value > 2`
+* `be_an_instance_of` => `an_instance_of`
+* `be_within` => `a_value_within`
+* `contain_exactly` => `a_collection_containing_exactly`
+* `end_with` => `a_string_ending_with`, `ending_with`
+* `match` => `a_string_matching`
+* `start_with` => `a_string_starting_with`
+
+For a full list, see the API docs for the RSpec::Matchers module.
+
+Composing matchers with change
+
+Given a file named “change_spec.rb” with:
+RSpec.describe "Passing matchers to `change`" do
+ specify "you can pass a matcher to `by`" do
+ k = 0
+ expect { k += 1.05 }.to change { k }.
+ by( a_value_within(0.1).of(1.0) )
+ end
+
+ specify "you can pass matchers to `from` and `to`" do
+ s = "food"
+ expect { s = "barn" }.to change { s }.
+ from( a_string_matching(/foo/) ).
+ to( a_string_matching(/bar/) )
+ end
+end
+
+When I run rspec change_spec.rb
+
+Then the examples should all pass.
+
+Composing matchers with contain_exactly
+
+Given a file named “containexactlyspec.rb” with:
+RSpec.describe "Passing matchers to `contain_exactly`" do
+ specify "you can pass matchers in place of exact values" do
+ expect(["barn", 2.45]).to contain_exactly(
+ a_value_within(0.1).of(2.5),
+ a_string_starting_with("bar")
+ )
+ end
+end
+
+When I run rspec contain_exactly_spec.rb
+
+Then the examples should all pass.
+
+Composing matchers with end_with
+
+Given a file named “endwithspec.rb” with:
+RSpec.describe "Passing matchers to `end_with`" do
+ specify "you can pass matchers in place of exact values" do
+ expect(["barn", "food", 2.45]).to end_with(
+ a_string_matching("foo"),
+ a_value > 2
+ )
+ end
+end
+
+When I run rspec end_with_spec.rb
+
+Then the examples should all pass.
+
+Composing matchers with include
+
+Given a file named “include_spec.rb” with:
+RSpec.describe "Passing matchers to `include`" do
+ specify "you can use matchers in place of array values" do
+ expect(["barn", 2.45]).to include( a_string_starting_with("bar") )
+ end
+
+ specify "you can use matchers in place of hash values" do
+ expect(:a => "food", :b => "good").to include(:a => a_string_matching(/foo/))
+ end
+
+ specify "you can use matchers in place of hash keys" do
+ expect("food" => "is good").to include( a_string_matching(/foo/) )
+ end
+end
+
+When I run rspec include_spec.rb
+
+Then the examples should all pass.
+
+Composing matchers with match:
+
+Given a file named “match_spec.rb” with:
+RSpec.describe "Passing matchers to `match`" do
+ specify "you can match nested data structures against matchers" do
+ hash = {
+ :a => {
+ :b => ["foo", 5.0],
+ :c => { :d => 2.05 }
+ }
+ }
+
+ expect(hash).to match(
+ :a => {
+ :b => a_collection_containing_exactly(
+ a_string_starting_with("f"),
+ an_instance_of(Float)
+ ),
+ :c => { :d => (a_value < 3) }
+ }
+ )
+ end
+end
+
+When I run rspec match_spec.rb
+
+Then the examples should all pass.
+
+Composing matchers with output
+
+Given a file named “output_spec.rb” with:
+RSpec.describe "Passing matchers to `output`" do
+ specify "you can pass a matcher in place of the output (to_stdout)" do
+ expect {
+ print 'foo'
+ }.to output(a_string_starting_with('f')).to_stdout
+ end
+ specify "you can pass a matcher in place of the output (to_stderr)" do
+ expect {
+ warn 'foo'
+ }.to output(a_string_starting_with('f')).to_stderr
+ end
+end
+
+When I run rspec output_spec.rb
+
+Then the examples should all pass.
+
+Composing matchers with raise_error
+
+Given a file named “raiseerrorspec.rb” with:
+RSpec.describe "Passing matchers to `raise_error`" do
+ specify "you can pass a matcher in place of the message" do
+ expect {
+ raise RuntimeError, "this goes boom"
+ }.to raise_error(RuntimeError, a_string_ending_with("boom"))
+ end
+end
+
+When I run rspec raise_error_spec.rb
+
+Then the examples should all pass.
+
+Composing matchers with start_with
+
+Given a file named “startwithspec.rb” with:
+RSpec.describe "Passing matchers to `start_with`" do
+ specify "you can pass matchers in place of exact values" do
+ expect(["barn", "food", 2.45]).to start_with(
+ a_string_matching("bar"),
+ a_string_matching("foo")
+ )
+ end
+end
+
+When I run rspec start_with_spec.rb
+
+Then the examples should all pass.
+
+Composing matchers with throw_symbol
+
+Given a file named “throwsymbolspec.rb” with:
+RSpec.describe "Passing matchers to `throw_symbol`" do
+ specify "you can pass a matcher in place of a throw arg" do
+ expect {
+ throw :pi, Math::PI
+ }.to throw_symbol(:pi, a_value_within(0.01).of(3.14))
+ end
+end
+
+When I run rspec throw_symbol_spec.rb
+
+Then the examples should all pass.
+
+Composing matchers with yield_with_args
+
+Given a file named “yieldwithargs_spec.rb” with:
+RSpec.describe "Passing matchers to `yield_with_args`" do
+ specify "you can pass matchers in place of the args" do
+ expect { |probe|
+ "food".tap(&probe)
+ }.to yield_with_args(a_string_matching(/foo/))
+ end
+end
+
+When I run rspec yield_with_args_spec.rb
+
+Then the examples should all pass.
+
+Composing matchers with yield_successive_args
+
+Given a file named “yieldsuccessiveargs_spec.rb” with:
+RSpec.describe "Passing matchers to `yield_successive_args`" do
+ specify "you can pass matchers in place of the args" do
+ expect { |probe|
+ [1, 2, 3].each(&probe)
+ }.to yield_successive_args(a_value < 2, 2, a_value > 2)
+ end
+end
+
+When I run rspec yield_successive_args_spec.rb
+
+Then the examples should all pass.
+
+Composing matchers using a compound and expression
+
+Given a file named “include_spec.rb” with:
+RSpec.describe "Passing a compound matcher expression to `include`" do
+ example do
+ expect(["food", "drink"]).to include( a_string_starting_with("f").and ending_with("d"))
+ end
+end
+
+When I run rspec include_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/compound-expectations/index.html b/docs/features/3-12/rspec-expectations/compound-expectations/index.html
new file mode 100644
index 000000000..2c6f19b42
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/compound-expectations/index.html
@@ -0,0 +1,59 @@
+
+
+
+
+Compound Expectations
+
+Matchers can be composed using and or or to make compound expectations.
+
+Use and to chain expectations
+
+Given a file named “compoundandmatcher_spec.rb” with:
+RSpec.describe "A compound `and` matcher" do
+ let(:string) { "foo bar bazz" }
+
+ it "passes when both are true" do
+ expect(string).to start_with("foo").and end_with("bazz")
+ end
+
+ it "passes when using boolean AND `&` alias" do
+ expect(string).to start_with("foo") & end_with("bazz")
+ end
+
+ it "fails when the first matcher fails" do
+ expect(string).to start_with("bar").and end_with("bazz")
+ end
+
+ it "fails when the second matcher fails" do
+ expect(string).to start_with("foo").and end_with("bar")
+ end
+end
+
+When I run rspec compound_and_matcher_spec.rb
+
+Then the output should contain “4 examples, 2 failures”.
+
+Use or to chain expectations
+
+Given a file named “stoplight_spec.rb” with:
+class StopLight
+ def color
+ %w[ green yellow red ].shuffle.first
+ end
+end
+
+RSpec.describe StopLight, "#color" do
+ let(:light) { StopLight.new }
+ it "is green, yellow or red" do
+ expect(light.color).to eq("green").or eq("yellow").or eq("red")
+ end
+
+ it "passes when using boolean OR `|` alias" do
+ expect(light.color).to eq("green") | eq("yellow") | eq("red")
+ end
+end
+
+When I run rspec stoplight_spec.rb
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/custom-matchers/access-running-example/index.html b/docs/features/3-12/rspec-expectations/custom-matchers/access-running-example/index.html
new file mode 100644
index 000000000..94936b7a4
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/custom-matchers/access-running-example/index.html
@@ -0,0 +1,58 @@
+
+
+
+
+Access the running example
+
+In the context of a custom matcher, you can call helper methods that are available from the
+ current example’s example group. This is used, for example, by rspec-rails in order to wrap
+ rails’ built-in assertions (which depend on helper methods available in the test context).
+
+Call method defined on example from matcher
+
+Given a file named “example_spec.rb” with:
+RSpec::Matchers.define :bar do
+ match do |_|
+ foo == "foo"
+ end
+end
+
+RSpec.describe "something" do
+ def foo
+ "foo"
+ end
+
+ it "does something" do
+ expect("foo").to bar
+ end
+end
+
+When I run rspec ./example_spec.rb
+
+Then the output should contain “1 example, 0 failures”.
+
+Call method not defined on example from matcher
+
+Given a file named “example_spec.rb” with:
+RSpec::Matchers.define :bar do
+ match do |_|
+ foo == "foo"
+ end
+end
+
+RSpec.describe "something" do
+ it "does something" do
+ expect("foo").to bar
+ end
+end
+
+When I run rspec ./example_spec.rb
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should match /undefined.*method/
+
+And the output should contain “RSpec::Matchers::DSL::Matcher”
+
+And the output should not contain “ExampleGroup”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/custom-matchers/define-block-matcher/index.html b/docs/features/3-12/rspec-expectations/custom-matchers/define-block-matcher/index.html
new file mode 100644
index 000000000..299754eff
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/custom-matchers/define-block-matcher/index.html
@@ -0,0 +1,84 @@
+
+
+
+
+Defining a matcher supporting block expectations
+
+When you wish to support block expectations (e.g. expect { ... }.to matcher) with
+ your custom matchers you must specify this. You can do this manually (or determinately
+ based on some logic) by defining a supports_block_expectation? method or by using
+ the DSL’s supports_block_expectations shortcut method.
+
+Define a block matcher manually
+
+Given a file named “blockmatcherspec.rb” with:
+RSpec::Matchers.define :support_blocks do
+ match do |actual|
+ actual.is_a? Proc
+ end
+
+ def supports_block_expectations?
+ true # or some logic
+ end
+end
+
+RSpec.describe "a custom block matcher" do
+ specify { expect { }.to support_blocks }
+end
+
+When I run rspec ./block_matcher_spec.rb
+
+Then the example should pass.
+
+Define a block matcher using shortcut
+
+Given a file named “blockmatcherspec.rb” with:
+RSpec::Matchers.define :support_blocks do
+ match do |actual|
+ actual.is_a? Proc
+ end
+
+ supports_block_expectations
+end
+
+RSpec.describe "a custom block matcher" do
+ specify { expect { }.to support_blocks }
+end
+
+When I run rspec ./block_matcher_spec.rb
+
+Then the example should pass.
+
+Define a block matcher using shortcut
+
+Given a file named “blockmatcherspec.rb” with:
+RSpec::Matchers.define :support_blocks_with_errors do
+ match(:notify_expectation_failures => true) do |actual|
+ actual.call
+ true
+ end
+
+ supports_block_expectations
+end
+
+RSpec.describe "a custom block matcher" do
+ specify do
+ expect {
+ expect(true).to eq false
+ }.to support_blocks_with_errors
+ end
+end
+
+When I run rspec ./block_matcher_spec.rb
+
+Then it should fail with:
+Failures:
+
+ 1) a custom block matcher is expected to support blocks with errors
+ Failure/Error: expect(true).to eq false
+
+ expected: false
+ got: true
+
+ (compared using ==)
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/custom-matchers/define-diffable-matcher/index.html b/docs/features/3-12/rspec-expectations/custom-matchers/define-diffable-matcher/index.html
new file mode 100644
index 000000000..dda02c35b
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/custom-matchers/define-diffable-matcher/index.html
@@ -0,0 +1,135 @@
+
+
+
+
+Defining a diffable matcher
+
+When a matcher is defined as diffable, the output will include a diff of the submitted objects when the objects are more than simple primitives.
+
+Define a diffable matcher (with diff-lcs 1.4)
+
+Given a file named “diffablematcherspec.rb” with:
+RSpec::Matchers.define :be_just_like do |expected|
+ match do |actual|
+ actual == expected
+ end
+
+ diffable
+end
+
+RSpec.describe "two\nlines" do
+ it { is_expected.to be_just_like("three\nlines") }
+end
+
+When I run rspec ./diffable_matcher_spec.rb
+
+Then it should fail with:
+ Diff:
+ @@ -1 +1 @@
+ -three
+ +two
+
+Define a diffable matcher (with diff-lcs 1.3)
+
+Given a file named “diffablematcherspec.rb” with:
+RSpec::Matchers.define :be_just_like do |expected|
+ match do |actual|
+ actual == expected
+ end
+
+ diffable
+end
+
+RSpec.describe "two\nlines" do
+ it { is_expected.to be_just_like("three\nlines") }
+end
+
+When I run rspec ./diffable_matcher_spec.rb
+
+Then it should fail with:
+ Diff:
+ @@ -1,3 +1,3 @@
+ -three
+ +two
+ lines
+
+Redefine actual (with diff-lcs 1.4.4)
+
+Sometimes is necessary to overwrite actual to make diffing work, e.g. if actual is a name of a file you want to read from. For this to work you need to overwrite @actual in your matcher.
+
+Given a file named “redefineactualmatcher_spec.rb” with:
+RSpec::Matchers.define :have_content do |expected|
+ match do |actual|
+ @actual = File.read(actual).chomp
+
+ values_match? expected, @actual
+ end
+
+ diffable
+end
+
+RSpec.describe 'Compare files' do
+ context 'when content is equal' do
+ it { expect('data.txt').to have_content 'Data' }
+ end
+
+ context 'when files are different' do
+ it { expect('data.txt').to have_content "No\nData\nhere" }
+ end
+end
+
+And a file named “data.txt” with:
+Data
+
+When I run rspec ./redefine_actual_matcher_spec.rb --format documentation
+
+Then the exit status should not be 0
+
+And the output should contain:
+2 examples, 1 failure
+
+And the output should contain:
+ @@ -1,4 +1,2 @@
+ -No
+ Data
+ -here
+
+Redefine actual (with diff-lcs 1.3)
+
+Given a file named “redefineactualmatcher_spec.rb” with:
+RSpec::Matchers.define :have_content do |expected|
+ match do |actual|
+ @actual = File.read(actual).chomp
+
+ values_match? expected, @actual
+ end
+
+ diffable
+end
+
+RSpec.describe 'Compare files' do
+ context 'when content is equal' do
+ it { expect('data.txt').to have_content 'Data' }
+ end
+
+ context 'when files are different' do
+ it { expect('data.txt').to have_content "No\nData\nhere" }
+ end
+end
+
+And a file named “data.txt” with:
+Data
+
+When I run rspec ./redefine_actual_matcher_spec.rb --format documentation
+
+Then the exit status should not be 0
+
+And the output should contain:
+2 examples, 1 failure
+
+And the output should contain:
+ @@ -1,4 +1,2 @@
+ -No
+ Data
+ -here
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/custom-matchers/define-matcher-outside-rspec/index.html b/docs/features/3-12/rspec-expectations/custom-matchers/define-matcher-outside-rspec/index.html
new file mode 100644
index 000000000..1987724e8
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/custom-matchers/define-matcher-outside-rspec/index.html
@@ -0,0 +1,40 @@
+
+
+
+
+Defining a matcher outside rspec
+
+You can define custom matchers when using rspec-expectations outside of rspec-core.
+
+Define a matcher with default messages
+
+Given a file named “test_multiples.rb” with:
+require "minitest/autorun"
+require "rspec/expectations/minitest_integration"
+
+RSpec::Matchers.define :be_a_multiple_of do |expected|
+ match do |actual|
+ actual % expected == 0
+ end
+end
+
+class TestMultiples < Minitest::Test
+
+ def test_9_should_be_a_multiple_of_3
+ expect(9).to be_a_multiple_of(3)
+ end
+
+ def test_9_should_be_a_multiple_of_4
+ expect(9).to be_a_multiple_of(4)
+ end
+
+end
+
+When I run ruby test_multiples.rb
+
+Then the exit status should not be 0
+
+And the output should contain “expected 9 to be a multiple of 4”
+
+And the output should contain “2 runs, 2 assertions, 1 failures, 0 errors”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/custom-matchers/define-matcher-with-fluent-interface/index.html b/docs/features/3-12/rspec-expectations/custom-matchers/define-matcher-with-fluent-interface/index.html
new file mode 100644
index 000000000..1dba90fa5
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/custom-matchers/define-matcher-with-fluent-interface/index.html
@@ -0,0 +1,81 @@
+
+
+
+
+Defining a matcher with fluent interface
+
+Use the chain method to define matchers with a fluent interface.
+
+Chained method with argument
+
+Given a file named “between_spec.rb” with:
+RSpec::Matchers.define :be_bigger_than do |first|
+ match do |actual|
+ (actual > first) && (actual < @second)
+ end
+
+ chain :and_smaller_than do |second|
+ @second = second
+ end
+end
+
+RSpec.describe 5 do
+ it { is_expected.to be_bigger_than(4).and_smaller_than(6) }
+end
+
+When I run rspec between_spec.rb --format documentation
+
+Then the output should contain “1 example, 0 failures”
+
+And the output should contain “is expected to be bigger than 4”.
+
+Chained setter
+
+Given a file named “between_spec.rb” with:
+RSpec::Matchers.define :be_bigger_than do |first|
+ match do |actual|
+ (actual > first) && (actual < second)
+ end
+
+ chain :and_smaller_than, :second
+end
+
+RSpec.describe 5 do
+ it { is_expected.to be_bigger_than(4).and_smaller_than(6) }
+end
+
+When I run rspec between_spec.rb --format documentation
+
+Then the output should contain “1 example, 0 failures”
+
+And the output should contain “is expected to be bigger than 4”.
+
+With include_chain_clauses_in_custom_matcher_descriptions configured to true, and chained method with argument
+
+Given a file named “between_spec.rb” with:
+RSpec.configure do |config|
+ config.expect_with :rspec do |c|
+ c.include_chain_clauses_in_custom_matcher_descriptions = true
+ end
+end
+
+RSpec::Matchers.define :be_bigger_than do |first|
+ match do |actual|
+ (actual > first) && (actual < @second)
+ end
+
+ chain :and_smaller_than do |second|
+ @second = second
+ end
+end
+
+RSpec.describe 5 do
+ it { is_expected.to be_bigger_than(4).and_smaller_than(6) }
+end
+
+When I run rspec between_spec.rb --format documentation
+
+Then the output should contain “1 example, 0 failures”
+
+And the output should contain “is expected to be bigger than 4 and smaller than 6”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/custom-matchers/define-matcher/index.html b/docs/features/3-12/rspec-expectations/custom-matchers/define-matcher/index.html
new file mode 100644
index 000000000..479e6de94
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/custom-matchers/define-matcher/index.html
@@ -0,0 +1,582 @@
+
+
+
+
+Defining a custom matcher
+
+rspec-expectations provides a DSL for defining custom matchers. These are often useful for expressing expectations in the domain of your application.
+
+Behind the scenes RSpec::Matchers.define evaluates the define block in the context of a singleton class. If you need to write a more complex matcher and would like to use the Class-approach yourself, please head over to our API-documentation and read the docs about the MatcherProtocol.
+
+Define a matcher with default messages
+
+Given a file named “matcherwithdefaultmessagespec.rb” with:
+require 'rspec/expectations'
+
+RSpec::Matchers.define :be_a_multiple_of do |expected|
+ match do |actual|
+ actual % expected == 0
+ end
+end
+
+RSpec.describe 9 do
+ it { is_expected.to be_a_multiple_of(3) }
+end
+
+RSpec.describe 9 do
+ it { is_expected.not_to be_a_multiple_of(4) }
+end
+
+# fail intentionally to generate expected output
+RSpec.describe 9 do
+ it { is_expected.to be_a_multiple_of(4) }
+end
+
+# fail intentionally to generate expected output
+RSpec.describe 9 do
+ it { is_expected.not_to be_a_multiple_of(3) }
+end
+
+When I run rspec ./matcher_with_default_message_spec.rb --format documentation
+
+Then the exit status should not be 0
+
+And the output should contain “is expected to be a multiple of 3”
+
+And the output should contain “is expected not to be a multiple of 4”
+
+And the output should contain “Failure/Error: it { isexpected.to beamultipleof(4) }”
+
+And the output should contain “Failure/Error: it { isexpected.notto beamultiple_of(3) }”
+
+And the output should contain “4 examples, 2 failures”
+
+And the output should contain “expected 9 to be a multiple of 4”
+
+And the output should contain “expected 9 not to be a multiple of 3”.
+
+Overriding the failure_message
+
+Given a file named “matcherwithfailuremessagespec.rb” with:
+require 'rspec/expectations'
+
+RSpec::Matchers.define :be_a_multiple_of do |expected|
+ match do |actual|
+ actual % expected == 0
+ end
+ failure_message do |actual|
+ "expected that #{actual} would be a multiple of #{expected}"
+ end
+end
+
+# fail intentionally to generate expected output
+RSpec.describe 9 do
+ it { is_expected.to be_a_multiple_of(4) }
+end
+
+When I run rspec ./matcher_with_failure_message_spec.rb
+
+Then the exit status should not be 0
+
+And the stdout should contain “1 example, 1 failure”
+
+And the stdout should contain “expected that 9 would be a multiple of 4”.
+
+Overriding the failuremessagewhen_negated
+
+Given a file named “matcherwithfailureformessage_spec.rb” with:
+require 'rspec/expectations'
+
+RSpec::Matchers.define :be_a_multiple_of do |expected|
+ match do |actual|
+ actual % expected == 0
+ end
+ failure_message_when_negated do |actual|
+ "expected that #{actual} would not be a multiple of #{expected}"
+ end
+end
+
+# fail intentionally to generate expected output
+RSpec.describe 9 do
+ it { is_expected.not_to be_a_multiple_of(3) }
+end
+
+When I run rspec ./matcher_with_failure_for_message_spec.rb
+
+Then the exit status should not be 0
+
+And the stdout should contain “1 example, 1 failure”
+
+And the stdout should contain “expected that 9 would not be a multiple of 3”.
+
+Overriding the description
+
+Given a file named “matcheroverridingdescription_spec.rb” with:
+require 'rspec/expectations'
+
+RSpec::Matchers.define :be_a_multiple_of do |expected|
+ match do |actual|
+ actual % expected == 0
+ end
+ description do
+ "be multiple of #{expected}"
+ end
+end
+
+RSpec.describe 9 do
+ it { is_expected.to be_a_multiple_of(3) }
+end
+
+RSpec.describe 9 do
+ it { is_expected.not_to be_a_multiple_of(4) }
+end
+
+When I run rspec ./matcher_overriding_description_spec.rb --format documentation
+
+Then the exit status should be 0
+
+And the stdout should contain “2 examples, 0 failures”
+
+And the stdout should contain “is expected to be multiple of 3”
+
+And the stdout should contain “is expected not to be multiple of 4”.
+
+With no args
+
+Given a file named “matcherwithnoargsspec.rb” with:
+require 'rspec/expectations'
+
+RSpec::Matchers.define :have_7_fingers do
+ match do |thing|
+ thing.fingers.length == 7
+ end
+end
+
+class Thing
+ def fingers; (1..7).collect {"finger"}; end
+end
+
+RSpec.describe Thing do
+ it { is_expected.to have_7_fingers }
+end
+
+When I run rspec ./matcher_with_no_args_spec.rb --format documentation
+
+Then the exit status should be 0
+
+And the stdout should contain “1 example, 0 failures”
+
+And the stdout should contain “is expected to have 7 fingers”.
+
+With multiple args
+
+Given a file named “matcherwithmultipleargsspec.rb” with:
+require 'rspec/expectations'
+
+RSpec::Matchers.define :be_the_sum_of do |a,b,c,d|
+ match do |sum|
+ a + b + c + d == sum
+ end
+end
+
+RSpec.describe 10 do
+ it { is_expected.to be_the_sum_of(1,2,3,4) }
+end
+
+When I run rspec ./matcher_with_multiple_args_spec.rb --format documentation
+
+Then the exit status should be 0
+
+And the stdout should contain “1 example, 0 failures”
+
+And the stdout should contain “is expected to be the sum of 1, 2, 3, and 4”.
+
+With a block arg
+
+Given a file named “matcherwithblockargspec.rb” with:
+require 'rspec/expectations'
+
+RSpec::Matchers.define :be_lazily_equal_to do
+ match do |obj|
+ obj == block_arg.call
+ end
+
+ description { "be lazily equal to #{block_arg.call}" }
+end
+
+RSpec.describe 10 do
+ it { is_expected.to be_lazily_equal_to { 10 } }
+end
+
+When I run rspec ./matcher_with_block_arg_spec.rb --format documentation
+
+Then the exit status should be 0
+
+And the stdout should contain “1 example, 0 failures”
+
+And the stdout should contain “is expected to be lazily equal to 10”.
+
+With helper methods
+
+Given a file named “matcherwithinternalhelperspec.rb” with:
+require 'rspec/expectations'
+
+RSpec::Matchers.define :have_same_elements_as do |sample|
+ match do |actual|
+ similar?(sample, actual)
+ end
+
+ def similar?(a, b)
+ a.sort == b.sort
+ end
+end
+
+RSpec.describe "these two arrays" do
+ specify "should be similar" do
+ expect([1,2,3]).to have_same_elements_as([2,3,1])
+ end
+end
+
+When I run rspec ./matcher_with_internal_helper_spec.rb
+
+Then the exit status should be 0
+
+And the stdout should contain “1 example, 0 failures”.
+
+Scoped in a module
+
+Given a file named “scopedmatcherspec.rb” with:
+require 'rspec/expectations'
+
+module MyHelpers
+ extend RSpec::Matchers::DSL
+
+ matcher :be_just_like do |expected|
+ match {|actual| actual == expected}
+ end
+end
+
+RSpec.describe "group with MyHelpers" do
+ include MyHelpers
+ it "has access to the defined matcher" do
+ expect(5).to be_just_like(5)
+ end
+end
+
+RSpec.describe "group without MyHelpers" do
+ it "does not have access to the defined matcher" do
+ expect do
+ expect(5).to be_just_like(5)
+ end.to raise_exception
+ end
+end
+
+When I run rspec ./scoped_matcher_spec.rb
+
+Then the stdout should contain “2 examples, 0 failures”.
+
+Scoped in an example group
+
+Given a file named “scopedmatcherspec.rb” with:
+require 'rspec/expectations'
+
+RSpec.describe "group with matcher" do
+ matcher :be_just_like do |expected|
+ match {|actual| actual == expected}
+ end
+
+ it "has access to the defined matcher" do
+ expect(5).to be_just_like(5)
+ end
+
+ describe "nested group" do
+ it "has access to the defined matcher" do
+ expect(5).to be_just_like(5)
+ end
+ end
+end
+
+RSpec.describe "group without matcher" do
+ it "does not have access to the defined matcher" do
+ expect do
+ expect(5).to be_just_like(5)
+ end.to raise_exception
+ end
+end
+
+When I run rspec scoped_matcher_spec.rb
+
+Then the output should contain “3 examples, 0 failures”.
+
+Matcher with separate logic for expect().to and expect().not_to
+
+Given a file named “matcherwithseparateshouldnotlogicspec.rb” with:
+RSpec::Matchers.define :contain do |*expected|
+ match do |actual|
+ expected.all? { |e| actual.include?(e) }
+ end
+
+ match_when_negated do |actual|
+ expected.none? { |e| actual.include?(e) }
+ end
+end
+
+RSpec.describe [1, 2, 3] do
+ it { is_expected.to contain(1, 2) }
+ it { is_expected.not_to contain(4, 5, 6) }
+
+ # deliberate failures
+ it { is_expected.to contain(1, 4) }
+ it { is_expected.not_to contain(1, 4) }
+end
+
+When I run rspec matcher_with_separate_should_not_logic_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+4 examples, 2 failures
+
+
+expected [1, 2, 3] to contain 1 and 4
+
+
+expected [1, 2, 3] not to contain 1 and 4
+
+
+
+Use define_method to create a helper method with access to matcher params
+
+Given a file named “definemethodspec.rb” with:
+RSpec::Matchers.define :be_a_multiple_of do |expected|
+ define_method :is_multiple? do |actual|
+ actual % expected == 0
+ end
+ match { |actual| is_multiple?(actual) }
+end
+
+RSpec.describe 9 do
+ it { is_expected.to be_a_multiple_of(3) }
+ it { is_expected.not_to be_a_multiple_of(4) }
+
+ # deliberate failures
+ it { is_expected.to be_a_multiple_of(2) }
+ it { is_expected.not_to be_a_multiple_of(3) }
+end
+
+When I run rspec define_method_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+4 examples, 2 failures
+
+
+expected 9 to be a multiple of 2
+
+
+expected 9 not to be a multiple of 3
+
+
+
+Include a module with helper methods in the matcher
+
+Given a file named “includemodulespec.rb” with:
+module MatcherHelpers
+ def is_multiple?(actual, expected)
+ actual % expected == 0
+ end
+end
+
+RSpec::Matchers.define :be_a_multiple_of do |expected|
+ include MatcherHelpers
+ match { |actual| is_multiple?(actual, expected) }
+end
+
+RSpec.describe 9 do
+ it { is_expected.to be_a_multiple_of(3) }
+ it { is_expected.not_to be_a_multiple_of(4) }
+
+ # deliberate failures
+ it { is_expected.to be_a_multiple_of(2) }
+ it { is_expected.not_to be_a_multiple_of(3) }
+end
+
+When I run rspec include_module_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+4 examples, 2 failures
+
+
+expected 9 to be a multiple of 2
+
+
+expected 9 not to be a multiple of 3
+
+
+
+Using values_match? to compare values and/or compound matchers.
+
+Given a file named “comparevaluesspec.rb” with:
+RSpec::Matchers.define :have_content do |expected|
+ match do |actual|
+ # The order of arguments is important for `values_match?`, e.g.
+ # especially if your matcher should handle `Regexp`-objects
+ # (`/regex/`): First comes the `expected` value, second the `actual`
+ # one.
+ values_match? expected, actual
+ end
+end
+
+RSpec.describe 'a' do
+ it { is_expected.to have_content 'a' }
+end
+
+RSpec.describe 'a' do
+ it { is_expected.to have_content /a/ }
+end
+
+RSpec.describe 'a' do
+ it { is_expected.to have_content a_string_starting_with('a') }
+end
+
+When I run rspec ./compare_values_spec.rb --format documentation
+
+Then the exit status should be 0.
+
+Error handling
+
+Make sure your matcher returns either true or false. Take care to handle exceptions appropriately in your matcher, e.g. most cases you might want your matcher to return false if an exception - e.g. ArgumentError - occurs, but there might be edge cases where you want to pass the exception to the user.
+You should handle each `StandardError` with care! Do not handle them all in one.
+
+```ruby
+match do |actual|
+ begin
+ '[...] Some code'
+ rescue ArgumentError
+ false
+ end
+end
+```
+
+Given a file named “errorhandlingspec.rb” with:
+class CustomClass; end
+
+RSpec::Matchers.define :is_lower_than do |expected|
+ match do |actual|
+ begin
+ actual < expected
+ rescue ArgumentError
+ false
+ end
+ end
+end
+
+RSpec.describe 1 do
+ it { is_expected.to is_lower_than 2 }
+end
+
+RSpec.describe 1 do
+ it { is_expected.not_to is_lower_than 'a' }
+end
+
+RSpec.describe CustomClass do
+ it { expect { is_expected.not_to is_lower_than 2 }.to raise_error NoMethodError }
+end
+
+
+When I run rspec ./error_handling_spec.rb --format documentation
+
+Then the exit status should be 0.
+
+Define aliases for your matcher
+
+If you want your matcher to be readable in different contexts, you can use the .alias_matcher-method to provide an alias for your matcher.
+
+Given a file named “alias_spec.rb” with:
+RSpec::Matchers.define :be_a_multiple_of do |expected|
+ match do |actual|
+ actual % expected == 0
+ end
+end
+
+RSpec::Matchers.alias_matcher :be_n_of , :be_a_multiple_of
+
+RSpec.describe 9 do
+ it { is_expected.to be_n_of(3) }
+end
+
+When I run rspec ./alias_spec.rb --format documentation
+
+Then the exit status should be 0.
+
+With expectation errors that bubble up
+
+By default the match block will swallow expectation errors (e.g. caused by using an expectation such as expect(1).to eq 2), if you wish to allow these to bubble up, pass in the option :notify_expectation_failures => true.
+
+Given a file named “bubblingexpectationerrors_spec.rb” with:
+RSpec::Matchers.define :be_a_palindrome do
+ match(:notify_expectation_failures => true) do |actual|
+ expect(actual).to be_a(String)
+ expect(actual.reverse).to eq(actual)
+ end
+end
+
+RSpec.describe "a custom matcher that bubbles up expectation errors" do
+ it "bubbles expectation errors" do
+ expect("carriage").to be_a_palindrome
+ end
+end
+
+When I run rspec bubbling_expectation_errors_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+Failures:
+
+
+1) a custom matcher that bubbles up expectation errors bubbles expectation errors
+
+
+Failure/Error: expect(actual.reverse).to eq(actual)
+
+
+expected: “carriage”
+
+
+got: “egairrac”
+
+
+(compared using ==)
+
+
+# ./bubblingexpectationerrors_spec.rb:4
+
+
+# ./bubblingexpectationerrors_spec.rb:10
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/custom-matchers/index.html b/docs/features/3-12/rspec-expectations/custom-matchers/index.html
new file mode 100644
index 000000000..f2fecf935
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/custom-matchers/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Custom matchers
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/customized-message/index.html b/docs/features/3-12/rspec-expectations/customized-message/index.html
new file mode 100644
index 000000000..6a50099d3
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/customized-message/index.html
@@ -0,0 +1,46 @@
+
+
+
+
+Customized message
+
+RSpec tries to provide useful failure messages, but for cases in which you want more
+ specific information, you can define your own message right in the example.This works for
+ any matcher other than the operator matchers.
+
+Customize failure message
+
+Given a file named “example_spec.rb” with:
+RSpec.describe Array do
+ context "when created with `new`" do
+ it "is empty" do
+ array = Array.new
+ array << 1 # trigger a failure to demonstrate the message
+ expect(array).to be_empty, "expected empty array, got #{array.inspect}"
+ end
+ end
+end
+
+
+When I run rspec example_spec.rb --format documentation
+
+Then the output should contain “expected empty array, got [1]”.
+
+Customize failure message with a proc
+
+Given a file named “example_spec.rb” with:
+RSpec.describe Array do
+ context "when created with `new`" do
+ it "is empty" do
+ array = Array.new
+ array << 1 # trigger a failure to demonstrate the message
+ expect(array).to be_empty, lambda { "expected empty array, got #{array.inspect}" }
+ end
+ end
+end
+
+
+When I run rspec example_spec.rb --format documentation
+
+Then the output should contain “expected empty array, got [1]”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/define-negated-matcher/index.html b/docs/features/3-12/rspec-expectations/define-negated-matcher/index.html
new file mode 100644
index 000000000..6085ebe64
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/define-negated-matcher/index.html
@@ -0,0 +1,50 @@
+
+
+
+
+Define negated matcher
+
+You can use RSpec::Matchers.define_negated_matcher to define a negated version of
+ an existing matcher. This is particularly useful in composed matcher expressions.
+
+Composed negated matcher expression
+
+Given a file named “composednegatedexpression_spec.rb” with:
+RSpec::Matchers.define_negated_matcher :an_array_excluding, :include
+
+RSpec.describe "A negated matcher" do
+ let(:list) { 1.upto(10).to_a }
+
+ it "can be used in a composed matcher expression" do
+ expect { list.delete(5) }.to change { list }.to(an_array_excluding 5)
+ end
+
+ it "provides a good failure message based on the name" do
+ # deliberate failure
+ expect { list.delete(1) }.to change { list }.to(an_array_excluding 5)
+ end
+end
+
+When I run rspec composed_negated_expression_spec.rb
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+2 examples, 1 failure
+
+
+1) A negated matcher provides a good failure message based on the name
+
+
+Failure/Error: expect { list.delete(1) }.to change { list }.to(anarrayexcluding 5)
+
+
+expected list to have changed to an array excluding 5, but is now [2, 3, 4, 5, 6, 7, 8, 9, 10]
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/diffing/index.html b/docs/features/3-12/rspec-expectations/diffing/index.html
new file mode 100644
index 000000000..6c0088f6c
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/diffing/index.html
@@ -0,0 +1,115 @@
+
+
+
+
+Diffing
+
+When appropriate, failure messages will automatically include a diff.
+
+Diff for a multiline string
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "a multiline string" do
+ it "is like another string" do
+ expected = <<-EXPECTED
+this is the
+ expected
+ string
+EXPECTED
+ actual = <<-ACTUAL
+this is the
+ actual
+ string
+ACTUAL
+ expect(actual).to eq(expected)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain:
+ Diff:
+ @@ -1,4 +1,4 @@
+ this is the
+ - expected
+ + actual
+ string
+
+Diff for a multiline string and a regexp on diff-lcs 1.4
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "a multiline string" do
+ it "is like another string" do
+ expected = /expected/m
+ actual = <<-ACTUAL
+this is the
+ actual
+ string
+ACTUAL
+ expect(actual).to match expected
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain:
+ Diff:
+ @@ -1,3 +1,5 @@
+ -/expected/m
+ +this is the
+ + actual
+ + string
+
+Diff for a multiline string and a regexp on diff-lcs 1.3
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "a multiline string" do
+ it "is like another string" do
+ expected = /expected/m
+ actual = <<-ACTUAL
+this is the
+ actual
+ string
+ACTUAL
+ expect(actual).to match expected
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should contain:
+ Diff:
+ @@ -1,2 +1,4 @@
+ -/expected/m
+ +this is the
+ + actual
+ + string
+
+No diff for a single line strings
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "a single line string" do
+ it "is like another string" do
+ expected = "this string"
+ actual = "that string"
+ expect(actual).to eq(expected)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should not contain “Diff:”.
+
+No diff for numbers
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "a number" do
+ it "is like another number" do
+ expect(1).to eq(2)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the output should not contain “Diff:”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/implicit-docstrings/index.html b/docs/features/3-12/rspec-expectations/implicit-docstrings/index.html
new file mode 100644
index 000000000..06e3a6eec
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/implicit-docstrings/index.html
@@ -0,0 +1,59 @@
+
+
+
+
+Implicit docstrings
+
+When you use rspec-expectations with rspec-core, RSpec is able to auto-generate the
+ docstrings for examples for you based on the last expectation in the example. This can be
+ handy when the matcher expresses exactly what you would write in your example docstring,
+ but it can also be easily abused. We find that the freeform nature of the docstring provides
+ a lot of value when used well (e.g. to document the “why” of a particular behavior), and you
+ lose that kind of flexibility when you rely on the matcher to generate the docstring for you.
+
+In general, we recommend only using this feature when the matcher aligns exactly with the
+ docstring you would write. Even then, many users prefer the explicitness of the full
+ docstring, so use this feature with care (if at all).
+
+Run passing examples
+
+Given a file named “implicitdocstringsspec.rb” with:
+RSpec.describe "Examples with no docstrings generate their own:" do
+ specify { expect(3).to be < 5 }
+ specify { expect([1,2,3]).to include(2) }
+ specify { expect([1,2,3]).to respond_to(:size) }
+end
+
+When I run rspec ./implicit_docstrings_spec.rb -fdoc
+
+Then the output should contain “is expected to be < 5”
+
+And the output should contain “is expected to include 2”
+
+And the output should contain “is expected to respond to #size”.
+
+Run failing examples
+
+Given a file named “failingimplicitdocstrings_spec.rb” with:
+RSpec.describe "Failing examples with no descriptions" do
+ # description is auto-generated per the last executed expectation
+ specify do
+ expect(3).to equal(2)
+ expect(5).to equal(5)
+ end
+
+ specify { expect(3).to be > 5 }
+ specify { expect([1,2,3]).to include(4) }
+ specify { expect([1,2,3]).not_to respond_to(:size) }
+end
+
+When I run rspec ./failing_implicit_docstrings_spec.rb -fdoc
+
+Then the output should contain “is expected to equal 2”
+
+And the output should contain “is expected to be > 5”
+
+And the output should contain “is expected to include 4”
+
+And the output should contain “is expected not to respond to #size”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/index.html b/docs/features/3-12/rspec-expectations/index.html
new file mode 100644
index 000000000..0e9a0e2c5
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/index.html
@@ -0,0 +1,51 @@
+
+
+
+
+RSpec Expectations
+
+rspec-expectations is used to define expected outcomes.
+RSpec.describe Account do
+ it "has a balance of zero when first created" do
+ expect(Account.new.balance).to eq(Money.new(0))
+ end
+end
+
+Basic structure
+
+The basic structure of an rspec expectation is:
+expect(actual).to matcher(expected)
+expect(actual).not_to matcher(expected)
+
+Note: You can also use expect(..).to_not instead of expect(..).not_to.
+ One is an alias to the other, so you can use whichever reads better to you.
+
+Examples
+expect(5).to eq(5)
+expect(5).not_to eq(4)
+
+What is a matcher?
+
+A matcher is any object that responds to the following methods:
+matches?(actual)
+failure_message
+
+These methods are also part of the matcher protocol, but are optional:
+does_not_match?(actual)
+failure_message_when_negated
+description
+supports_block_expectations?
+
+RSpec ships with a number of built-in matchers and a DSL for writing custom
+matchers.
+
+Issues
+
+The documentation for rspec-expectations is a work in progress. We’ll be adding
+Cucumber features over time, and clarifying existing ones. If you have
+specific features you’d like to see added, find the existing documentation
+incomplete or confusing, or, better yet, wish to write a missing Cucumber
+feature yourself, please submit an
+issue or a pull
+request.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/syntax-configuration/index.html b/docs/features/3-12/rspec-expectations/syntax-configuration/index.html
new file mode 100644
index 000000000..9bb9b6754
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/syntax-configuration/index.html
@@ -0,0 +1,123 @@
+
+
+
+
+Syntax Configuration
+
+The primary syntax provided by rspec-expectations is based on
+ the expect method, which explicitly wraps an object or block
+ of code in order to set an expectation on it.
+
+There’s also an older should-based syntax, which relies upon should being
+ monkey-patched onto every object in the system. However, this syntax can at times lead to
+ some surprising failures, since RSpec does not own every object in the system and cannot
+ guarantee that it will always work consistently.
+
+We recommend you use the expect syntax unless you have a specific reason you prefer the
+ should syntax. We have no plans to ever completely remove the should syntax but starting
+ in RSpec 3, a deprecation warning will be issued if you do not explicitly enable it, with the
+ plan to disable it by default in RSpec 4 (and potentially move it into an external gem).
+
+If you have an old should-based project that you would like to upgrade to the expect,
+ check out transpec, which can perform the conversion automatically for you.
+
+Background
+
+Given a file named “spec/syntaxes_spec.rb” with:
+require 'spec_helper'
+
+RSpec.describe "using the should syntax" do
+ specify { 3.should eq(3) }
+ specify { 3.should_not eq(4) }
+ specify { lambda { raise "boom" }.should raise_error("boom") }
+ specify { lambda { }.should_not raise_error }
+end
+
+RSpec.describe "using the expect syntax" do
+ specify { expect(3).to eq(3) }
+ specify { expect(3).not_to eq(4) }
+ specify { expect { raise "boom" }.to raise_error("boom") }
+ specify { expect { }.not_to raise_error }
+end
+
+Both syntaxes are available by default
+
+Given a file named “spec/spec_helper.rb” with:
+
+
+When I run rspec
+
+Then the examples should all pass
+
+And the output should contain “Using should from rspec-expectations’ old :should syntax without explicitly enabling the syntax is deprecated”.
+
+Disable should syntax
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.expect_with :rspec do |expectations|
+ expectations.syntax = :expect
+ end
+end
+
+When I run rspec
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+8 examples, 4 failures
+
+
+undefined method `should’
+
+
+
+Disable expect syntax
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.expect_with :rspec do |expectations|
+ expectations.syntax = :should
+ end
+ config.mock_with :rspec do |mocks|
+ mocks.syntax = :should
+ end
+end
+
+When I run rspec
+
+Then the output should contain all of these:
+
+
+
+
+
+
+
+8 examples, 4 failures
+
+
+undefined method `expect’
+
+
+
+Explicitly enable both syntaxes
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.expect_with :rspec do |expectations|
+ expectations.syntax = [:should, :expect]
+ end
+end
+
+When I run rspec
+
+Then the examples should all pass
+
+And the output should not contain “deprecated”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/test-frameworks/index.html b/docs/features/3-12/rspec-expectations/test-frameworks/index.html
new file mode 100644
index 000000000..b080cbfdd
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/test-frameworks/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Test frameworks
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-expectations/test-frameworks/minitest/index.html b/docs/features/3-12/rspec-expectations/test-frameworks/minitest/index.html
new file mode 100644
index 000000000..ea8546b1a
--- /dev/null
+++ b/docs/features/3-12/rspec-expectations/test-frameworks/minitest/index.html
@@ -0,0 +1,125 @@
+
+
+
+
+Minitest integration
+
+rspec-expectations is a stand-alone gem that can be used without the rest of RSpec. If you
+ like minitest as your test runner, but prefer RSpec’s approach to expressing expectations,
+ you can have both.
+
+To integrate rspec-expectations with minitest, require rspec/expectations/minitest_integration.
+
+Use rspec/expectations with minitest
+
+Given a file named “rspecexpectationstest.rb” with:
+require 'minitest/autorun'
+require 'rspec/expectations/minitest_integration'
+
+class RSpecExpectationsTest < Minitest::Test
+ RSpec::Matchers.define :be_an_integer do
+ match { |actual| Integer === actual }
+ end
+
+ def be_an_int
+ # This is actually an internal rspec-expectations API, but is used
+ # here to demonstrate that deprecation warnings from within
+ # rspec-expectations work correctly without depending on rspec-core
+ RSpec.deprecate(:be_an_int, :replacement => :be_an_integer)
+ be_an_integer
+ end
+
+ def test_passing_expectation
+ expect(1 + 3).to eq 4
+ end
+
+ def test_failing_expectation
+ expect([1, 2]).to be_empty
+ end
+
+ def test_custom_matcher_with_deprecation_warning
+ expect(1).to be_an_int
+ end
+
+ def test_using_aggregate_failures
+ aggregate_failures do
+ expect(1).to be_even
+ expect(2).to be_odd
+ end
+ end
+end
+
+When I run ruby rspec_expectations_test.rb
+
+Then the output should contain “4 runs, 5 assertions, 2 failures, 0 errors”
+
+And the output should contain “expected [1, 2].empty? to be truthy, got false”
+
+And the output should contain “beanint is deprecated”
+
+And the output should contain “Got 2 failures from failure aggregation block”.
+
+Use rspec/expectations with minitest/spec
+
+Given a file named “rspecexpectationsspec.rb” with:
+require 'minitest/autorun'
+require 'minitest/spec'
+require 'rspec/expectations/minitest_integration'
+
+describe "Using RSpec::Expectations with Minitest::Spec" do
+ RSpec::Matchers.define :be_an_integer do
+ match { |actual| Integer === actual }
+ end
+
+ it 'passes an expectation' do
+ expect(1 + 3).to eq 4
+ end
+
+ it 'fails an expectation' do
+ expect([1, 2]).to be_empty
+ end
+
+ it 'passes a block expectation' do
+ expect { 1 / 0 }.to raise_error(ZeroDivisionError)
+ end
+
+ it 'fails a block expectation' do
+ expect { 1 / 1 }.to raise_error(ZeroDivisionError)
+ end
+
+ it 'passes a negative expectation (using `not_to`)' do
+ expect(1).not_to eq 2
+ end
+
+ it 'fails a negative expectation (using `to_not`)' do
+ expect(1).to_not eq 1
+ end
+
+ it 'fails multiple expectations' do
+ aggregate_failures do
+ expect(1).to be_even
+ expect(2).to be_odd
+ end
+ end
+
+ it 'passes a minitest expectation' do
+ expect(1 + 3).must_equal 4
+ end
+
+ it 'fails a minitest expectation' do
+ expect([1, 2]).must_be :empty?
+ end
+end
+
+When I run ruby rspec_expectations_spec.rb
+
+Then the output should contain “9 runs, 10 assertions, 5 failures, 0 errors”
+
+And the output should contain “expected [1, 2].empty? to be truthy, got false”
+
+And the output should contain “expected ZeroDivisionError but nothing was raised”
+
+And the output should contain “Got 2 failures from failure aggregation block”
+
+And the output should contain “Expected [1, 2] to be empty?”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/.nav b/docs/features/3-12/rspec-mocks/.nav
new file mode 100644
index 000000000..f782108b4
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/.nav
@@ -0,0 +1,45 @@
+- basics:
+ - test-doubles.feature
+ - allowing-messages.feature
+ - expecting-messages.feature
+ - partial-test-doubles.feature
+ - null-object-doubles.feature
+ - spies.feature
+ - scope.feature
+- verifying-doubles:
+ - instance-doubles.feature
+ - class-doubles.feature
+ - object-doubles.feature
+ - dynamic-classes.feature
+ - partial-doubles.feature
+- configuring-responses:
+ - returning-a-value.feature
+ - raising-an-error.feature
+ - throwing.feature
+ - yielding.feature
+ - calling-the-original-implementation.feature
+ - wrapping-the-original-implementation.feature
+ - block-implementation.feature
+- setting-constraints:
+ - matching-arguments.feature
+ - receive-counts.feature
+ - message-order.feature
+- mutating-constants:
+ - stub-defined-constant.feature
+ - stub-undefined-constant.feature
+ - hide-defined-constant.feature
+ - hide-undefined-constant.feature
+- working-with-legacy-code:
+ - any-instance.feature
+ - message-chains.feature
+- old-syntax:
+ - stub.feature
+ - should-receive.feature
+ - any-instance.feature
+ - stub-chain.feature
+ - unstub.feature
+- outside-rspec:
+ - minitest.feature
+ - any-test-framework.feature
+ - standalone.feature
+- Changelog
diff --git a/docs/features/3-12/rspec-mocks/basics/allowing-messages/index.html b/docs/features/3-12/rspec-mocks/basics/allowing-messages/index.html
new file mode 100644
index 000000000..54538807f
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/basics/allowing-messages/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+Allowing messages
+
+Test doubles are “strict” by default – messages that have not been specifically
+ allowed or expected will trigger an error. Use allow(...).to receive(...) to configure
+ which messages the double is allowed to receive. You can also use allow(...).to
+ receive_messages(...) to configure allowed messages (and return values) in bulk.
+
+Allowed messages return nil by default
+
+Given a file named “allowmessagespec.rb” with:
+RSpec.describe "allow" do
+ it "returns nil from allowed messages" do
+ dbl = double("Some Collaborator")
+ allow(dbl).to receive(:foo)
+ expect(dbl.foo).to be_nil
+ end
+end
+
+When I run rspec allow_message_spec.rb
+
+Then the examples should all pass.
+
+Messages can be allowed in bulk using receive_messages
+
+Given a file named “receivemessagesspec.rb” with:
+RSpec.describe "receive_messages" do
+ it "configures return values for the provided messages" do
+ dbl = double("Some Collaborator")
+ allow(dbl).to receive_messages(:foo => 2, :bar => 3)
+ expect(dbl.foo).to eq(2)
+ expect(dbl.bar).to eq(3)
+ end
+end
+
+When I run rspec receive_messages_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/basics/expecting-messages/index.html b/docs/features/3-12/rspec-mocks/basics/expecting-messages/index.html
new file mode 100644
index 000000000..5dfadcdbc
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/basics/expecting-messages/index.html
@@ -0,0 +1,115 @@
+
+
+
+
+Expecting messages
+
+Use expect(...).to receive(...) to expect a message on a test double. Unfulfilled
+ message expectations trigger failures when the example completes. You can also use
+ expect(...).not_to receive(...) to set a negative message expectation.
+
+Failing positive message expectation
+
+Given a file named “unfulfilledmessageexpectation_spec.rb” with:
+RSpec.describe "An unfulfilled positive message expectation" do
+ it "triggers a failure" do
+ dbl = double("Some Collaborator")
+ expect(dbl).to receive(:foo)
+ end
+end
+
+When I run rspec unfulfilled_message_expectation_spec.rb
+
+Then it should fail with:
+ 1) An unfulfilled positive message expectation triggers a failure
+ Failure/Error: expect(dbl).to receive(:foo)
+
+ (Double "Some Collaborator").foo(*(any args))
+ expected: 1 time with any arguments
+ received: 0 times with any arguments
+
+Passing positive message expectation
+
+Given a file named “fulfilledmessageexpectation_spec.rb” with:
+RSpec.describe "A fulfilled positive message expectation" do
+ it "passes" do
+ dbl = double("Some Collaborator")
+ expect(dbl).to receive(:foo)
+ dbl.foo
+ end
+end
+
+When I run rspec fulfilled_message_expectation_spec.rb
+
+Then the examples should all pass.
+
+Failing negative message expectation
+
+Given a file named “negativemessageexpectation_spec.rb” with:
+RSpec.describe "A negative message expectation" do
+ it "fails when the message is received" do
+ dbl = double("Some Collaborator").as_null_object
+ expect(dbl).not_to receive(:foo)
+ dbl.foo
+ end
+end
+
+When I run rspec negative_message_expectation_spec.rb
+
+Then it should fail with:
+ 1) A negative message expectation fails when the message is received
+ Failure/Error: dbl.foo
+
+ (Double "Some Collaborator").foo(no args)
+ expected: 0 times with any arguments
+ received: 1 time
+
+Passing negative message expectation
+
+Given a file named “negativemessageexpectation_spec.rb” with:
+RSpec.describe "A negative message expectation" do
+ it "passes if the message is never received" do
+ dbl = double("Some Collaborator").as_null_object
+ expect(dbl).not_to receive(:foo)
+ end
+end
+
+When I run rspec negative_message_expectation_spec.rb
+
+Then the examples should all pass.
+
+Failing positive message expectation with a custom failure message
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "An unfulfilled positive message expectation" do
+ it "triggers a failure" do
+ dbl = double
+ expect(dbl).to receive(:foo), "dbl never calls :foo"
+ end
+end
+
+When I run rspec example_spec.rb --format documentation
+
+Then the output should contain:
+ 1) An unfulfilled positive message expectation triggers a failure
+ Failure/Error: expect(dbl).to receive(:foo), "dbl never calls :foo"
+ dbl never calls :foo
+
+Failing negative message expectation with a custom failure message
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "A negative message expectation" do
+ it "fails when the message is received" do
+ dbl = double
+ expect(dbl).not_to receive(:foo), "dbl called :foo but is not supposed to"
+ dbl.foo
+ end
+end
+
+When I run rspec example_spec.rb --format documentation
+
+Then the output should contain:
+ 1) A negative message expectation fails when the message is received
+ Failure/Error: dbl.foo
+ dbl called :foo but is not supposed to
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/basics/index.html b/docs/features/3-12/rspec-mocks/basics/index.html
new file mode 100644
index 000000000..a197981d6
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/basics/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Basics
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/basics/null-object-doubles/index.html b/docs/features/3-12/rspec-mocks/basics/null-object-doubles/index.html
new file mode 100644
index 000000000..451b5a358
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/basics/null-object-doubles/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+Null object doubles
+
+Test doubles are strict by default, raising errors when they receive messages that have not
+ been allowed or expected. You can chain as_null_object off of double in order to make
+ the double “loose”. For any message that has not explicitly allowed or expected, the double
+ will return itself. It acts as a black hole null object, allowing arbitrarily deep method chains.
+
+as_null_object allows arbitrarily deep message chains and returns itself
+
+Given a file named “asnullobject_spec.rb” with:
+RSpec.describe "as_null_object" do
+ it "returns itself" do
+ dbl = double("Some Collaborator").as_null_object
+ expect(dbl.foo.bar.bazz).to be(dbl)
+ end
+end
+
+When I run rspec as_null_object_spec.rb
+
+Then the examples should all pass.
+
+Individual methods can still be allowed or expected
+
+Given a file named “asnullobject_spec.rb” with:
+RSpec.describe "as_null_object" do
+ it "can allow individual methods" do
+ dbl = double("Some Collaborator", :foo => 3).as_null_object
+ allow(dbl).to receive(:bar).and_return(4)
+
+ expect(dbl.foo).to eq(3)
+ expect(dbl.bar).to eq(4)
+ end
+end
+
+When I run rspec as_null_object_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/basics/partial-test-doubles/index.html b/docs/features/3-12/rspec-mocks/basics/partial-test-doubles/index.html
new file mode 100644
index 000000000..a5bf1f963
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/basics/partial-test-doubles/index.html
@@ -0,0 +1,71 @@
+
+
+
+
+Partial test doubles
+
+A partial test double is an extension of a real object in a system that is instrumented with
+ test-double like behaviour in the context of a test. This technique is very common in Ruby
+ because we often see class objects acting as global namespaces for methods. For example,
+ in Rails:
+ person = double("person")
+ allow(Person).to receive(:find) { person }
+
+In this case we’re instrumenting Person to return the person object we’ve defined whenever
+ it receives the find message. We can also set a message expectation so that the example
+ fails if find is not called:
+ person = double("person")
+ expect(Person).to receive(:find) { person }
+
+RSpec replaces the method we’re stubbing or mocking with its own test-double like method.
+ At the end of the example, RSpec verifies any message expectations, and then restores the
+ original methods.
+
+Note: we recommend enabling the verify_partial_doubles config option.
+
+Only the specified methods are redefined
+
+Given a file named “partialdoublespec.rb” with:
+RSpec.describe "A partial double" do
+ # Note: stubbing a string like this is a terrible idea.
+ # This is just for demonstration purposes.
+ let(:string) { "a string" }
+ before { allow(string).to receive(:length).and_return(500) }
+
+ it "redefines the specified methods" do
+ expect(string.length).to eq(500)
+ end
+
+ it "does not effect other methods" do
+ expect(string.reverse).to eq("gnirts a")
+ end
+end
+
+When I run rspec partial_double_spec.rb
+
+Then the examples should all pass.
+
+The original method is restored when the example completes
+
+Given a file named “partialdoublespec.rb” with:
+class User
+ def self.find(id)
+ :original_return_value
+ end
+end
+
+RSpec.describe "A partial double" do
+ it "redefines a method" do
+ allow(User).to receive(:find).and_return(:redefined)
+ expect(User.find(3)).to eq(:redefined)
+ end
+
+ it "restores the redefined method after the example completes" do
+ expect(User.find(3)).to eq(:original_return_value)
+ end
+end
+
+When I run rspec partial_double_spec.rb --order defined
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/basics/scope/index.html b/docs/features/3-12/rspec-mocks/basics/scope/index.html
new file mode 100644
index 000000000..408aadc74
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/basics/scope/index.html
@@ -0,0 +1,119 @@
+
+
+
+
+Scope
+
+All rspec-mocks constructs have a per-example lifecycle. Message expectations are verified
+ after each example. Doubles, method stubs, stubbed constants, etc. are all cleaned up after
+ each example. This ensures that each example can be run in isolation, and in any order.
+
+It is perfectly fine to set up doubles, stubs, and message expectations in a
+ before(:example) hook, as that hook is executed in the scope of the example:
+ before(:example) do
+ allow(MyClass).to receive(:foo)
+ end
+
+Since before(:context) runs outside the scope of any individual example, usage of
+ rspec-mocks features is not supported there. You can, however, create a temporary scope in
+ any arbitrary context, including in a before(:context) hook, using
+ RSpec::Mocks.with_temporary_scope { }.
+
+Cannot create doubles in a before(:context) hook
+
+Given a file named “beforecontextspec.rb” with:
+RSpec.describe "Creating a double in a before(:context) hook" do
+ before(:context) do
+ @dbl = double(:foo => 13)
+ end
+
+ it "fails before it gets to the examples" do
+ expect(@dbl.foo).to eq(13)
+ end
+end
+
+When I run rspec before_context_spec.rb
+
+Then it should fail with:
+The use of doubles or partial doubles from rspec-mocks outside of the per-test lifecycle is not supported.
+
+Use with_temporary_scope to create and use a double in a before(:context) hook
+
+Given a file named “withtemporaryscope_spec.rb” with:
+RSpec.describe "Creating a double in a before(:context) hook" do
+ before(:context) do
+ RSpec::Mocks.with_temporary_scope do
+ dbl = double(:foo => 13)
+ @result = dbl.foo
+ end
+ end
+
+ it "allows a double to be created and used from within a with_temporary_scope block" do
+ expect(@result).to eq(13)
+ end
+end
+
+When I run rspec with_temporary_scope_spec.rb
+
+Then the examples should all pass.
+
+Doubles cannot be reused in another example
+
+Given a file named “leaktestdouble_spec.rb” with:
+class Account
+ class << self
+ attr_accessor :logger
+ end
+
+ def initialize
+ @balance = 0
+ end
+
+ attr_reader :balance
+
+ def credit(amount)
+ @balance += amount
+ self.class.logger.log("Credited $#{amount}")
+ end
+end
+
+RSpec.describe Account do
+ it "logs each credit" do
+ Account.logger = logger = double("Logger")
+ expect(logger).to receive(:log).with("Credited $15")
+ account = Account.new
+ account.credit(15)
+ end
+
+ it "keeps track of the balance" do
+ account = Account.new
+ expect { account.credit(10) }.to change { account.balance }.by(10)
+ end
+end
+
+When I run rspec leak_test_double_spec.rb
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+2 examples, 1 failure
+
+
+
+
+
+1) Account keeps track of the balance
+
+
+Failure/Error: self.class.logger.log(“Credited $#{amount}”)
+
+
+# was originally created in one example but has leaked into another example and can no longer be used.
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/basics/spies/index.html b/docs/features/3-12/rspec-mocks/basics/spies/index.html
new file mode 100644
index 000000000..8fb9580e9
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/basics/spies/index.html
@@ -0,0 +1,166 @@
+
+
+
+
+Spies
+
+Message expectations put an example’s expectation at the start, before you’ve invoked the
+ code-under-test. Many developers prefer using an arrange-act-assert (or given-when-then)
+ pattern for structuring tests. Spies are an alternate type of test double that support this
+ pattern by allowing you to expect that a message has been received after the fact, using
+ have_received.
+
+You can use any test double (or partial double) as a spy, but the double must be setup to
+ spy on the messages you care about. Spies automatically spy on all messages,
+ or you can allow a message to spy on it.
+
+have_received supports the same fluent interface for setting constraints that normal message expectations do.
+
+Note: The have_received API shown here will only work if you are using rspec-expectations.
+ Note: have_received(...).with(...) is unable to work properly when passed arguments are mutated after the spy records the received message.
+
+Using a spy
+
+Given a file named “spy_spec.rb” with:
+RSpec.describe "have_received" do
+ it "passes when the message has been received" do
+ invitation = spy('invitation')
+ invitation.deliver
+ expect(invitation).to have_received(:deliver)
+ end
+end
+
+When I run rspec spy_spec.rb
+
+Then the examples should all pass.
+
+Spy on a method on a partial double
+
+Given a file named “partialdoublespy_spec.rb” with:
+class Invitation
+ def self.deliver; end
+end
+
+RSpec.describe "have_received" do
+ it "passes when the expectation is met" do
+ allow(Invitation).to receive(:deliver)
+ Invitation.deliver
+ expect(Invitation).to have_received(:deliver)
+ end
+end
+
+When I run rspec partial_double_spy_spec.rb
+
+Then the examples should all pass.
+
+Failure when the message has not been received
+
+Given a file named “failure_spec.rb” with:
+class Invitation
+ def self.deliver; end
+end
+
+RSpec.describe "failure when the message has not been received" do
+ example "for a spy" do
+ invitation = spy('invitation')
+ expect(invitation).to have_received(:deliver)
+ end
+
+ example "for a partial double" do
+ allow(Invitation).to receive(:deliver)
+ expect(Invitation).to have_received(:deliver)
+ end
+end
+
+When I run rspec failure_spec.rb --order defined
+
+Then it should fail with:
+ 1) failure when the message has not been received for a spy
+ Failure/Error: expect(invitation).to have_received(:deliver)
+
+ (Double "invitation").deliver(*(any args))
+ expected: 1 time with any arguments
+ received: 0 times with any arguments
+
+And it should fail with:
+ 2) failure when the message has not been received for a partial double
+ Failure/Error: expect(Invitation).to have_received(:deliver)
+
+ (Invitation (class)).deliver(*(any args))
+ expected: 1 time with any arguments
+ received: 0 times with any arguments
+
+Set constraints using the fluent interface
+
+Given a file named “settingconstraintsspec.rb” with:
+RSpec.describe "An invitation" do
+ let(:invitation) { spy("invitation") }
+
+ before do
+ invitation.deliver("foo@example.com")
+ invitation.deliver("bar@example.com")
+ end
+
+ it "passes when a count constraint is satisfied" do
+ expect(invitation).to have_received(:deliver).twice
+ end
+
+ it "passes when an order constraint is satisfied" do
+ expect(invitation).to have_received(:deliver).with("foo@example.com").ordered
+ expect(invitation).to have_received(:deliver).with("bar@example.com").ordered
+ end
+
+ it "fails when a count constraint is not satisfied" do
+ expect(invitation).to have_received(:deliver).at_least(3).times
+ end
+
+ it "fails when an order constraint is not satisfied" do
+ expect(invitation).to have_received(:deliver).with("bar@example.com").ordered
+ expect(invitation).to have_received(:deliver).with("foo@example.com").ordered
+ end
+end
+
+When I run rspec setting_constraints_spec.rb --order defined
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+4 examples, 2 failures
+
+
+
+
+
+1) An invitation fails when a count constraint is not satisfied
+
+
+Failure/Error: expect(invitation).to havereceived(:deliver).atleast(3).times
+
+
+(Double “invitation”).deliver(*(any args))
+
+
+expected: at least 3 times with any arguments
+
+
+received: 2 times with any arguments
+
+
+
+
+
+2) An invitation fails when an order constraint is not satisfied
+
+
+Failure/Error: expect(invitation).to have_received(:deliver).with(“foo@example.com”).ordered
+
+
+# received :deliver out of order
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/basics/test-doubles/index.html b/docs/features/3-12/rspec-mocks/basics/test-doubles/index.html
new file mode 100644
index 000000000..b17a4a457
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/basics/test-doubles/index.html
@@ -0,0 +1,46 @@
+
+
+
+
+Test Doubles
+
+Test double is a generic term for any object that stands in for a real object during a test
+ (think “stunt double”). You create one using the double method. Doubles are “strict” by
+ default – any message you have not allowed or expected will trigger an error – but you can
+ switch a double to being “loose”. When creating a double, you can allow messages (and set
+ their return values) by passing a hash.
+
+Once you have a test double, you can allow or expect messages on it.
+
+We recommend you use verifying doubles whenever possible.
+
+Doubles are strict by default
+
+Given a file named “double_spec.rb” with:
+RSpec.describe "A test double" do
+ it "raises errors when messages not allowed or expected are received" do
+ dbl = double("Some Collaborator")
+ dbl.foo
+ end
+end
+
+When I run rspec double_spec.rb
+
+Then it should fail with:
+#<Double "Some Collaborator"> received unexpected message :foo with (no args)
+
+A hash can be used to define allowed messages and return values
+
+Given a file named “double_spec.rb” with:
+RSpec.describe "A test double" do
+ it "returns canned responses from the methods named in the provided hash" do
+ dbl = double("Some Collaborator", :foo => 3, :bar => 4)
+ expect(dbl.foo).to eq(3)
+ expect(dbl.bar).to eq(4)
+ end
+end
+
+When I run rspec double_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/configuring-responses/block-implementation/index.html b/docs/features/3-12/rspec-mocks/configuring-responses/block-implementation/index.html
new file mode 100644
index 000000000..5bb512615
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/configuring-responses/block-implementation/index.html
@@ -0,0 +1,139 @@
+
+
+
+
+Block implementation
+
+When you pass a block, RSpec will use your block as the implementation of the method. Any
+ arguments (or a block) provided by the caller will be yielded to your block implementation.
+ This feature is extremely flexible, and supports many use cases that are not directly
+ supported by the more declarative fluent interface.
+
+You can pass a block to any of the fluent interface methods:
+* `allow(dbl).to receive(:foo) { do_something }`
+* `allow(dbl).to receive(:foo).with("args") { do_something }`
+* `allow(dbl).to receive(:foo).once { do_something }`
+* `allow(dbl).to receive(:foo).ordered { do_something }`
+
+Some of the more common use cases for block implementations are shown below, but this
+ is not an exhaustive list.
+
+Use a block to specify a return value with a terser syntax
+
+Given a file named “returnvaluespec.rb” with:
+RSpec.describe "Specifying a return value using a block" do
+ it "returns the block's return value" do
+ dbl = double
+ allow(dbl).to receive(:foo) { 14 }
+ expect(dbl.foo).to eq(14)
+ end
+end
+
+When I run rspec return_value_spec.rb
+
+Then the examples should all pass.
+
+Use a block to verify arguments
+
+Given a file named “verifyargumentsspec.rb” with:
+RSpec.describe "Verifying arguments using a block" do
+ it "fails when the arguments do not meet the expectations set in the block" do
+ dbl = double
+
+ allow(dbl).to receive(:foo) do |arg|
+ expect(arg).to eq("bar")
+ end
+
+ dbl.foo(nil)
+ end
+end
+
+When I run rspec verify_arguments_spec.rb
+
+Then it should fail with:
+Failure/Error: expect(arg).to eq("bar")
+
+Use a block to perform a calculation
+
+Given a file named “performcalculationspec.rb” with:
+RSpec.describe "Performing a calculation using a block" do
+ it "returns the block's return value" do
+ loan = double("Loan", :amount => 100)
+
+ allow(loan).to receive(:required_payment_for_rate) do |rate|
+ loan.amount * rate
+ end
+
+ expect(loan.required_payment_for_rate(0.05)).to eq(5)
+ expect(loan.required_payment_for_rate(0.1)).to eq(10)
+ end
+end
+
+When I run rspec perform_calculation_spec.rb
+
+Then the examples should all pass.
+
+Yield to the caller’s block
+
+Given a file named “yieldtocaller_spec.rb” with:
+RSpec.describe "When the caller passes a block" do
+ it "can be yielded to from your implementation block" do
+ dbl = double
+ allow(dbl).to receive(:foo) { |&block| block.call(14) }
+ expect { |probe| dbl.foo(&probe) }.to yield_with_args(14)
+ end
+end
+
+When I run rspec yield_to_caller_spec.rb
+
+Then the examples should all pass.
+
+Delegate to partial double’s original implementation within the block
+
+Given a file named “delegatetooriginal_spec.rb” with:
+class Calculator
+ def self.add(x, y)
+ x + y
+ end
+end
+
+RSpec.describe "When using a block implementation on a partial double" do
+ it "supports delegating to the original implementation" do
+ original_add = Calculator.method(:add)
+
+ allow(Calculator).to receive(:add) do |x, y|
+ original_add.call(x, y) * 2
+ end
+
+ expect(Calculator.add(2, 5)).to eq(14)
+ end
+end
+
+When I run rspec delegate_to_original_spec.rb
+
+Then the examples should all pass.
+
+Simulating a transient network failure
+
+Given a file named “simulatetransientnetworkfailurespec.rb” with:
+RSpec.describe "An HTTP API client" do
+ it "can simulate transient network failures" do
+ client = double("MyHTTPClient")
+
+ call_count = 0
+ allow(client).to receive(:fetch_data) do
+ call_count += 1
+ call_count.odd? ? raise("timeout") : { :count => 15 }
+ end
+
+ expect { client.fetch_data }.to raise_error("timeout")
+ expect(client.fetch_data).to eq(:count => 15)
+ expect { client.fetch_data }.to raise_error("timeout")
+ expect(client.fetch_data).to eq(:count => 15)
+ end
+end
+
+When I run rspec simulate_transient_network_failure_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/configuring-responses/calling-the-original-implementation/index.html b/docs/features/3-12/rspec-mocks/configuring-responses/calling-the-original-implementation/index.html
new file mode 100644
index 000000000..8663d4a35
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/configuring-responses/calling-the-original-implementation/index.html
@@ -0,0 +1,58 @@
+
+
+
+
+Calling the original implementation
+
+Use and_call_original to make a partial double response as it normally would. This can
+ be useful when you want to expect a message without interfering with how it responds. You
+ can also use it to configure the default response for most arguments, and then override
+ that for specific arguments using with.
+
+Note: and_call_original is only supported on partial doubles, as normal test doubles do
+ not have an original implementation.
+
+Background
+
+Given a file named “lib/calculator.rb” with:
+class Calculator
+ def self.add(x, y)
+ x + y
+ end
+end
+
+and_call_original makes the partial double respond as it normally would
+
+Given a file named “spec/andcalloriginal_spec.rb” with:
+require 'calculator'
+
+RSpec.describe "and_call_original" do
+ it "responds as it normally would" do
+ expect(Calculator).to receive(:add).and_call_original
+ expect(Calculator.add(2, 3)).to eq(5)
+ end
+end
+
+When I run rspec spec/and_call_original_spec.rb
+
+Then the examples should all pass.
+
+and_call_original can configure a default response that can be overridden for specific args
+
+Given a file named “spec/andcalloriginal_spec.rb” with:
+require 'calculator'
+
+RSpec.describe "and_call_original" do
+ it "can be overridden for specific arguments using #with" do
+ allow(Calculator).to receive(:add).and_call_original
+ allow(Calculator).to receive(:add).with(2, 3).and_return(-5)
+
+ expect(Calculator.add(2, 2)).to eq(4)
+ expect(Calculator.add(2, 3)).to eq(-5)
+ end
+end
+
+When I run rspec spec/and_call_original_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/configuring-responses/index.html b/docs/features/3-12/rspec-mocks/configuring-responses/index.html
new file mode 100644
index 000000000..6883fab77
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/configuring-responses/index.html
@@ -0,0 +1,23 @@
+
+
+
+
+Configuring responses
+
+When allowing or expecting messages, the default response is to return nil. Several
+methods are provided to configure how the test double responds to the message.
+
+
+
+In addition, you can provide a block implementation to respond in any manner you wish.
+
+Note: for simplicity, the examples here use allow rather than expect, but these APIs apply equally to both cases.
+Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/configuring-responses/mixed-responses/index.html b/docs/features/3-12/rspec-mocks/configuring-responses/mixed-responses/index.html
new file mode 100644
index 000000000..7eef73089
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/configuring-responses/mixed-responses/index.html
@@ -0,0 +1,31 @@
+
+
+
+
+Mixed responses
+
+Use and_invoke to invoke a callable when a message is received. Pass and_invoke multiple
+ callables to have different behavior for consecutive calls. The final callable will continue to be
+ called if the message is received additional times.
+
+Note: The invoked callable will be invoked with the calls arguments, so it is recommended to
+ use a lambda or similar with the same arity as your method but you can use a proc if you
+ do not care about arity (e.g. when raising).
+
+Mixed responses
+
+Given a file named “raisesandthen_returns.rb” with:
+RSpec.describe "when the method is called multiple times" do
+ it "raises and then later returns a value" do
+ dbl = double
+ allow(dbl).to receive(:foo).and_invoke(lambda { raise "failure" }, lambda { true })
+
+ expect { dbl.foo }.to raise_error("failure")
+ expect(dbl.foo).to eq(true)
+ end
+end
+
+When I run rspec raises_and_then_returns.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/configuring-responses/raising-an-error/index.html b/docs/features/3-12/rspec-mocks/configuring-responses/raising-an-error/index.html
new file mode 100644
index 000000000..5a026e87d
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/configuring-responses/raising-an-error/index.html
@@ -0,0 +1,32 @@
+
+
+
+
+Raising an error
+
+Use and_raise to make the test double raise an error when it receives the message. Any of the following forms are supported:
+* `and_raise(ExceptionClass)`
+* `and_raise("message")`
+* `and_raise(ExceptionClass, "message")`
+* `and_raise(instance_of_an_exception_class)`
+
+Raising an error
+
+Given a file named “raisesanerror_spec.rb” with:
+RSpec.describe "Making it raise an error" do
+ it "raises the provided exception" do
+ dbl = double
+ allow(dbl).to receive(:foo).and_raise("boom")
+ dbl.foo
+ end
+end
+
+When I run rspec raises_an_error_spec.rb
+
+Then it should fail with:
+ 1) Making it raise an error raises the provided exception
+ Failure/Error: dbl.foo
+
+ RuntimeError:
+ boom
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/configuring-responses/returning-a-value/index.html b/docs/features/3-12/rspec-mocks/configuring-responses/returning-a-value/index.html
new file mode 100644
index 000000000..401a8fc91
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/configuring-responses/returning-a-value/index.html
@@ -0,0 +1,62 @@
+
+
+
+
+Returning a value
+
+Use and_return to specify a return value. Pass and_return multiple values to specify
+ different return values for consecutive calls. The final value will continue to be returned if
+ the message is received additional times.
+
+Note - If you are looking for documentation for configuring responses from allow_any_instance_of, please see the working with legacy code documentation.
+
+Nil is returned by default
+
+Given a file named “returnsnilspec.rb” with:
+RSpec.describe "The default response" do
+ it "returns nil when no response has been configured" do
+ dbl = double
+ allow(dbl).to receive(:foo)
+ expect(dbl.foo).to be_nil
+ end
+end
+
+When I run rspec returns_nil_spec.rb
+
+Then the examples should all pass.
+
+Specify a return value
+
+Given a file named “andreturnspec.rb” with:
+RSpec.describe "Specifying a return value" do
+ it "returns the specified return value" do
+ dbl = double
+ allow(dbl).to receive(:foo).and_return(14)
+ expect(dbl.foo).to eq(14)
+ end
+end
+
+When I run rspec and_return_spec.rb
+
+Then the examples should all pass.
+
+Specify different return values for multiple calls
+
+Given a file named “multiplecallsspec.rb” with:
+RSpec.describe "When the method is called multiple times" do
+ it "returns the specified values in order, then keeps returning the last value" do
+ dbl = double
+ allow(dbl).to receive(:foo).and_return(1, 2, 3)
+
+ expect(dbl.foo).to eq(1)
+ expect(dbl.foo).to eq(2)
+ expect(dbl.foo).to eq(3)
+ expect(dbl.foo).to eq(3) # begins to repeat last value
+ expect(dbl.foo).to eq(3)
+ end
+end
+
+When I run rspec multiple_calls_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/configuring-responses/throwing/index.html b/docs/features/3-12/rspec-mocks/configuring-responses/throwing/index.html
new file mode 100644
index 000000000..241c2d848
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/configuring-responses/throwing/index.html
@@ -0,0 +1,41 @@
+
+
+
+
+Throwing
+
+Use and_throw to make the test double throw the provided symbol, optionally with the provided argument.
+* `and_throw(:symbol)`
+* `and_throw(:symbol, argument)`
+
+Throw a symbol
+
+Given a file named “andthrowspec.rb” with:
+RSpec.describe "Making it throw a symbol" do
+ it "throws the provided symbol" do
+ dbl = double
+ allow(dbl).to receive(:foo).and_throw(:hello)
+
+ catch :hello do
+ dbl.foo
+ fail "should not get here"
+ end
+ end
+
+ it "includes the provided argument when throwing" do
+ dbl = double
+ allow(dbl).to receive(:foo).and_throw(:hello, "world")
+
+ arg = catch :hello do
+ dbl.foo
+ fail "should not get here"
+ end
+
+ expect(arg).to eq("world")
+ end
+end
+
+When I run rspec and_throw_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/configuring-responses/wrapping-the-original-implementation/index.html b/docs/features/3-12/rspec-mocks/configuring-responses/wrapping-the-original-implementation/index.html
new file mode 100644
index 000000000..2b78d4276
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/configuring-responses/wrapping-the-original-implementation/index.html
@@ -0,0 +1,86 @@
+
+
+
+
+Wrapping the original implementation
+
+Use and_wrap_original to modify a partial double’s original response. This can be useful
+ when you want to utilise an external object but mutate its response. For example if an
+ API returns a large amount of data and for test purposes you’d like to trim it down. You can
+ also use it to configure the default response for most arguments, and then override that for
+ specific arguments using with.
+
+Note: and_wrap_original is only supported on partial doubles, as normal test doubles do
+ not have an original implementation.
+
+Background
+
+Given a file named “lib/api.rb” with:
+class API
+ def self.solve_for(x)
+ (1..x).to_a
+ end
+end
+
+and_wrap_original wraps the original partial double response
+
+Given a file named “spec/andwraporiginal_spec.rb” with:
+require 'api'
+
+RSpec.describe "and_wrap_original" do
+ it "responds as it normally would, modified by the block" do
+ expect(API).to receive(:solve_for).and_wrap_original { |m, *args| m.call(*args).first(5) }
+ expect(API.solve_for(100)).to eq [1,2,3,4,5]
+ end
+end
+
+When I run rspec spec/and_wrap_original_spec.rb
+
+Then the examples should all pass.
+
+and_wrap_original can configure a default response that can be overridden for specific args
+
+Given a file named “spec/andwraporiginal_spec.rb” with:
+require 'api'
+
+RSpec.describe "and_wrap_original" do
+ it "can be overridden for specific arguments using #with" do
+ allow(API).to receive(:solve_for).and_wrap_original { |m, *args| m.call(*args).first(5) }
+ allow(API).to receive(:solve_for).with(2).and_return([3])
+
+ expect(API.solve_for(20)).to eq [1,2,3,4,5]
+ expect(API.solve_for(2)).to eq [3]
+ end
+end
+
+When I run rspec spec/and_wrap_original_spec.rb
+
+Then the examples should all pass.
+
+and_wrap_original can configure a default response that can be overridden for specific keyword arguments
+
+Given a file named “lib/kw_api.rb” with:
+class API
+ def self.solve_for(x: 1, y: 2)
+ (x..y).to_a
+ end
+end
+
+Given a file named “spec/andwraporiginal_spec.rb” with:
+require 'kw_api'
+
+RSpec.describe "and_wrap_original" do
+ it "can be overridden for specific arguments using #with" do
+ allow(API).to receive(:solve_for).and_wrap_original { |m, **kwargs| m.call(**kwargs).first(5) }
+ allow(API).to receive(:solve_for).with(x: 3, y: 4).and_return([3])
+
+ expect(API.solve_for(x: 1, y: 20)).to eq [1,2,3,4,5]
+ expect(API.solve_for(y: 20)).to eq [1,2,3,4,5]
+ expect(API.solve_for(x: 3, y: 4)).to eq [3]
+ end
+end
+
+When I run rspec spec/and_wrap_original_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/configuring-responses/yielding/index.html b/docs/features/3-12/rspec-mocks/configuring-responses/yielding/index.html
new file mode 100644
index 000000000..dd268e559
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/configuring-responses/yielding/index.html
@@ -0,0 +1,81 @@
+
+
+
+
+Yielding
+
+Use and_yield to make the test double yield the provided arguments when it receives the
+ message. If the caller does not provide a block, or the caller’s block does not accept the
+ provided arguments, an error will be raised. If you want to yield multiple times, chain
+ multiple and_yield calls together.
+
+Yield an argument
+
+Given a file named “yieldargumentsspec.rb” with:
+RSpec.describe "Making it yield arguments" do
+ it "yields the provided args" do
+ dbl = double
+ allow(dbl).to receive(:foo).and_yield(2, 3)
+
+ x = y = nil
+ dbl.foo { |a, b| x, y = a, b }
+ expect(x).to eq(2)
+ expect(y).to eq(3)
+ end
+end
+
+When I run rspec yield_arguments_spec.rb
+
+Then the examples should all pass.
+
+It fails when the caller does not provide a block
+
+Given a file named “nocallerblock_spec.rb” with:
+RSpec.describe "Making it yield" do
+ it "fails when the caller does not provide a block" do
+ dbl = double
+ allow(dbl).to receive(:foo).and_yield(2, 3)
+ dbl.foo
+ end
+end
+
+When I run rspec no_caller_block_spec.rb
+
+Then it should fail with:
+#<Double (anonymous)> asked to yield |[2, 3]| but no block was passed
+
+It fails when the caller’s block does not accept the provided arguments
+
+Given a file named “argmismatchspec.rb” with:
+RSpec.describe "Making it yield" do
+ it "fails when the caller's block does not accept the provided arguments" do
+ dbl = double
+ allow(dbl).to receive(:foo).and_yield(2, 3)
+ dbl.foo { |x| }
+ end
+end
+
+When I run rspec arg_mismatch_spec.rb
+
+Then it should fail with:
+#<Double (anonymous)> yielded |2, 3| to block with arity of 1
+
+Yield multiple times
+
+Given a file named “yieldmultipletimes_spec.rb” with:
+RSpec.describe "Making it yield multiple times" do
+ it "yields the specified args in succession" do
+ yielded = []
+
+ dbl = double
+ allow(dbl).to receive(:foo).and_yield(1).and_yield(2).and_yield(3)
+ dbl.foo { |x| yielded << x }
+
+ expect(yielded).to eq([1, 2, 3])
+ end
+end
+
+When I run rspec yield_multiple_times_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/index.html b/docs/features/3-12/rspec-mocks/index.html
new file mode 100644
index 000000000..dc5159fcd
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/index.html
@@ -0,0 +1,71 @@
+
+
+
+
+RSpec Mocks
+
+rspec-mocks helps to control the context in a code example by letting you set known return
+values, fake implementations of methods, and even set expectations that specific messages
+are received by an object.
+
+You can do these three things on test doubles that rspec-mocks creates for you on the fly, or
+you can do them on objects that are part of your system.
+
+Messages and Methods
+
+Message and method are metaphors that we use somewhat interchangeably, but they are
+subtly different. In Object Oriented Programming, objects communicate by sending
+messages to one another. When an object receives a message, it invokes a method with the
+same name as the message.
+
+Test Doubles
+
+A test double is an object that stands in for another object in your system during a code
+example. Use the double method, passing in an optional identifier, to create one:
+book = double("book")
+
+Most of the time you will want some confidence that your doubles resemble an existing
+object in your system. Verifying doubles are provided for this purpose. If the existing object
+is available, they will prevent you from adding stubs and expectations for methods that do
+not exist or that have invalid arguments.
+book = instance_double("Book", :pages => 250)
+
+Verifying doubles have some clever tricks to enable you to both test in isolation without your
+dependencies loaded while still being able to validate them against real objects.
+
+Method Stubs
+
+A method stub is an instruction to an object (real or test double) to return a
+known value in response to a message:
+allow(die).to receive(:roll) { 3 }
+
+This tells the die object to return the value 3 when it receives the roll message.
+
+Message Expectations
+
+A message expectation is an expectation that an object should receive a specific message
+during the course of a code example:
+describe Account do
+ context "when closed" do
+ it "logs an 'account closed' message" do
+ logger = double()
+ account = Account.new
+ account.logger = logger
+
+ expect(logger).to receive(:account_closed).with(account)
+
+ account.close
+ end
+ end
+end
+
+This example specifies that the account object sends the logger the account_closed
+message (with itself as an argument) when it receives the close message.
+
+Issues
+
+The documentation for rspec-mocks is a work in progress. We’ll be adding Cucumber
+features over time, and clarifying existing ones. If you have specific features you’d like to see
+added, find the existing documentation incomplete or confusing, or, better yet, wish to write
+a missing Cucumber feature yourself, please submit an issue or a pull request.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/mutating-constants/hide-defined-constant/index.html b/docs/features/3-12/rspec-mocks/mutating-constants/hide-defined-constant/index.html
new file mode 100644
index 000000000..fac7ddab8
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/mutating-constants/hide-defined-constant/index.html
@@ -0,0 +1,72 @@
+
+
+
+
+Hide Defined Constant
+
+Use hide_const to remove a constant for the duration of a test.
+
+Hide top-level constant
+
+Given a file named “hideconstspec.rb” with:
+FOO = 7
+
+RSpec.describe "hiding FOO" do
+ it "can hide FOO" do
+ hide_const("FOO")
+ expect { FOO }.to raise_error(NameError)
+ end
+
+ it "restores the hidden constant when the example completes" do
+ expect(FOO).to eq(7)
+ end
+end
+
+When I run rspec hide_const_spec.rb
+
+Then the examples should all pass.
+
+Hide nested constant
+
+Given a file named “hideconstspec.rb” with:
+module MyGem
+ class SomeClass
+ FOO = 7
+ end
+end
+
+module MyGem
+ RSpec.describe SomeClass do
+ it "hides the nested constant when it is fully qualified" do
+ hide_const("MyGem::SomeClass::FOO")
+ expect { SomeClass::FOO }.to raise_error(NameError)
+ end
+
+ it "restores the hidden constant when the example completes" do
+ expect(MyGem::SomeClass::FOO).to eq(7)
+ end
+ end
+end
+
+When I run rspec hide_const_spec.rb
+
+Then the examples should all pass.
+
+Hiding undefined constant
+
+Given a file named “hideconstspec.rb” with:
+RSpec.describe "hiding UNDEFINED_CONSTANT" do
+ it "has no effect" do
+ hide_const("UNDEFINED_CONSTANT")
+ expect { UNDEFINED_CONSTANT }.to raise_error(NameError)
+ end
+
+ it "is still undefined after the example completes" do
+ expect { UNDEFINED_CONSTANT }.to raise_error(NameError)
+ end
+end
+
+When I run rspec hide_const_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/mutating-constants/hide-undefined-constant/index.html b/docs/features/3-12/rspec-mocks/mutating-constants/hide-undefined-constant/index.html
new file mode 100644
index 000000000..9d63a7ae7
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/mutating-constants/hide-undefined-constant/index.html
@@ -0,0 +1,28 @@
+
+
+
+
+Hide Undefined Constant
+
+Hiding a constant that is already undefined is a no-op. This can be useful when a spec file
+ may run in either an isolated environment (e.g. when running one spec file) or in a full
+ environment with all parts of your code base loaded (e.g. when running your entire suite).
+
+Hiding undefined constant
+
+Given a file named “hideconstspec.rb” with:
+RSpec.describe "hiding UNDEFINED_CONSTANT" do
+ it "has no effect" do
+ hide_const("UNDEFINED_CONSTANT")
+ expect { UNDEFINED_CONSTANT }.to raise_error(NameError)
+ end
+
+ it "is still undefined after the example completes" do
+ expect { UNDEFINED_CONSTANT }.to raise_error(NameError)
+ end
+end
+
+When I run rspec hide_const_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/mutating-constants/index.html b/docs/features/3-12/rspec-mocks/mutating-constants/index.html
new file mode 100644
index 000000000..694ceb0e3
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/mutating-constants/index.html
@@ -0,0 +1,70 @@
+
+
+
+
+Mutating Constants
+
+Stubbing
+
+Support is provided for stubbing constants. Like with method stubs, the stubbed constants
+will be restored to their original state when an example completes.
+stub_const("Foo", fake_foo)
+Foo # => fake_foo
+
+Stubbed constant names must be fully qualified; the current module nesting is not
+considered.
+module MyGem
+ class SomeClass; end
+end
+
+module MyGem
+ describe "Something" do
+ let(:fake_class) { Class.new }
+
+ it "accidentally stubs the wrong constant" do
+ # this stubs ::SomeClass (in the top-level namespace),
+ # not MyGem::SomeClass like you probably mean.
+ stub_const("SomeClass", fake_class)
+ end
+
+ it "stubs the right constant" do
+ stub_const("MyGem::SomeClass", fake_class)
+ end
+ end
+end
+
+When you stub a constant that is a module or a class, nested constants on the original
+module or class are not transferred by default, but you can use the
+:transfer_nested_constants option to tell rspec-mocks to transfer them:
+class CardDeck
+ SUITS = [:Spades, :Diamonds, :Clubs, :Hearts]
+ NUM_CARDS = 52
+end
+
+fake_class = Class.new
+stub_const("CardDeck", fake_class)
+CardDeck # => fake_class
+CardDeck::SUITS # => raises uninitialized constant error
+CardDeck::NUM_CARDS # => raises uninitialized constant error
+
+stub_const("CardDeck", fake_class, :transfer_nested_constants => true)
+CardDeck::SUITS # => [:Spades, :Diamonds, :Clubs, :Hearts]
+CardDeck::NUM_CARDS # => 52
+
+stub_const("CardDeck", fake_class, :transfer_nested_constants => [:SUITS])
+CardDeck::SUITS # => [:Spades, :Diamonds, :Clubs, :Hearts]
+CardDeck::NUM_CARDS # => raises uninitialized constant error
+
+Hiding
+
+Support is also provided for hiding constants. Hiding a constant temporarily removes it; it is
+restored to its original value after the test completes.
+FOO = 42
+hide_const("FOO")
+FOO # => NameError: uninitialized constant FOO
+
+Like stubbed constants, names must be fully qualified.
+
+Hiding constants that are already undefined has no effect.
+hide_const("NO_OP")
+
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/mutating-constants/stub-defined-constant/index.html b/docs/features/3-12/rspec-mocks/mutating-constants/stub-defined-constant/index.html
new file mode 100644
index 000000000..96e0e72cc
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/mutating-constants/stub-defined-constant/index.html
@@ -0,0 +1,85 @@
+
+
+
+
+Stub Defined Constant
+
+Use stub_const to stub constants. When the constant is already defined, the stubbed value
+ will replace the original value for the duration of the example.
+
+Stub top-level constant
+
+Given a file named “stubconstspec.rb” with:
+FOO = 7
+
+RSpec.describe "stubbing FOO" do
+ it "can stub FOO with a different value" do
+ stub_const("FOO", 5)
+ expect(FOO).to eq(5)
+ end
+
+ it "restores the stubbed constant when the example completes" do
+ expect(FOO).to eq(7)
+ end
+end
+
+When I run rspec stub_const_spec.rb
+
+Then the examples should all pass.
+
+Stub nested constant
+
+Given a file named “stubconstspec.rb” with:
+module MyGem
+ class SomeClass
+ FOO = 7
+ end
+end
+
+module MyGem
+ RSpec.describe SomeClass do
+ it "stubs the nested constant when it is fully qualified" do
+ stub_const("MyGem::SomeClass::FOO", 5)
+ expect(SomeClass::FOO).to eq(5)
+ end
+ end
+end
+
+When I run rspec stub_const_spec.rb
+
+Then the examples should all pass.
+
+Transfer nested constants
+
+Given a file named “stubconstspec.rb” with:
+module MyGem
+ class SomeClass
+ FOO = 7
+ end
+end
+
+module MyGem
+ RSpec.describe SomeClass do
+ let(:fake_class) { Class.new }
+
+ it "does not transfer nested constants by default" do
+ stub_const("MyGem::SomeClass", fake_class)
+ expect { SomeClass::FOO }.to raise_error(NameError)
+ end
+
+ it "transfers nested constants when using :transfer_nested_constants => true" do
+ stub_const("MyGem::SomeClass", fake_class, :transfer_nested_constants => true)
+ expect(SomeClass::FOO).to eq(7)
+ end
+
+ it "can specify a list of nested constants to transfer" do
+ stub_const("MyGem::SomeClass", fake_class, :transfer_nested_constants => [:FOO])
+ expect(SomeClass::FOO).to eq(7)
+ end
+ end
+end
+
+When I run rspec stub_const_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/mutating-constants/stub-undefined-constant/index.html b/docs/features/3-12/rspec-mocks/mutating-constants/stub-undefined-constant/index.html
new file mode 100644
index 000000000..f476e2746
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/mutating-constants/stub-undefined-constant/index.html
@@ -0,0 +1,57 @@
+
+
+
+
+Stub Undefined Constant
+
+Use stub_const to stub constants. When the constant is not already defined, all the
+ necessary intermediary modules will be dynamically created. When the example completes,
+ the intermediary module constants will be removed to return the constant state to how it
+ started.
+
+Stub top-level constant
+
+Given a file named “stubconstspec.rb” with:
+RSpec.describe "stubbing FOO" do
+ it "can stub undefined constant FOO" do
+ stub_const("FOO", 5)
+ expect(FOO).to eq(5)
+ end
+
+ it "undefines the constant when the example completes" do
+ expect { FOO }.to raise_error(NameError)
+ end
+end
+
+When I run rspec stub_const_spec.rb
+
+Then the examples should all pass.
+
+Stub nested constant
+
+Given a file named “stubconstspec.rb” with:
+module MyGem
+ class SomeClass
+ end
+end
+
+module MyGem
+ RSpec.describe SomeClass do
+ it "can stub an arbitrarily deep constant that is undefined" do
+ expect(defined?(SomeClass::A)).to be_falsey
+ stub_const("MyGem::SomeClass::A::B::C", 3)
+ expect(SomeClass::A::B::C).to eq(3)
+ expect(SomeClass::A).to be_a(Module)
+ end
+
+ it 'undefines the intermediary constants that were dynamically created' do
+ expect(defined?(SomeClass)).to be_truthy
+ expect(defined?(SomeClass::A)).to be_falsey
+ end
+ end
+end
+
+When I run rspec stub_const_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/old-syntax/any-instance/index.html b/docs/features/3-12/rspec-mocks/old-syntax/any-instance/index.html
new file mode 100644
index 000000000..fc1967611
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/old-syntax/any-instance/index.html
@@ -0,0 +1,123 @@
+
+
+
+
+any_instance
+
+any_instance is the old way to stub or mock any instance of a class but carries the baggage of a global monkey patch on all classes.
+ Note that we generally recommend against using this feature.
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rspec do |mocks|
+ mocks.syntax = :should
+ end
+end
+
+And a file named “.rspec” with:
+--require spec_helper
+
+Stub a method on any instance of a class
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.describe "Stubbing a method with any_instance" do
+ it "returns the specified value on any instance of the class" do
+ Object.any_instance.stub(:foo).and_return(:return_value)
+
+ o = Object.new
+ expect(o.foo).to eq(:return_value)
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the examples should all pass.
+
+Stub multiple methods on any instance of a class
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.describe "Stubbing multiple methods with any_instance" do
+ it "returns the specified values for the given messages" do
+ Object.any_instance.stub(:foo => 'foo', :bar => 'bar')
+
+ o = Object.new
+ expect(o.foo).to eq('foo')
+ expect(o.bar).to eq('bar')
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the examples should all pass.
+
+Stubbing any instance of a class with specific arguments
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.describe "Stubbing any instance with arguments" do
+ it "returns the stubbed value when arguments match" do
+ Object.any_instance.stub(:foo).with(:param_one, :param_two).and_return(:result_one)
+ Object.any_instance.stub(:foo).with(:param_three, :param_four).and_return(:result_two)
+
+ o = Object.new
+ expect(o.foo(:param_one, :param_two)).to eq(:result_one)
+ expect(o.foo(:param_three, :param_four)).to eq(:result_two)
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the examples should all pass.
+
+Block implementation is passed the receiver as first arg
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.describe "Stubbing any instance of a class" do
+ it 'yields the receiver to the block implementation' do
+ String.any_instance.stub(:slice) do |value, start, length|
+ value[start, length]
+ end
+
+ expect('string'.slice(2, 3)).to eq('rin')
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then the examples should all pass.
+
+Expect a message on any instance of a class
+
+Given a file named “spec/example_spec.rb” with:
+RSpec.describe "Expecting a message on any instance of a class" do
+ before do
+ Object.any_instance.should_receive(:foo)
+ end
+
+ it "passes when an instance receives the message" do
+ Object.new.foo
+ end
+
+ it "fails when no instance receives the message" do
+ Object.new.to_s
+ end
+end
+
+When I run rspec spec/example_spec.rb
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+2 examples, 1 failure
+
+
+Exactly one instance should have received the following message(s) but didn’t: foo
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/old-syntax/index.html b/docs/features/3-12/rspec-mocks/old-syntax/index.html
new file mode 100644
index 000000000..d8cf44d52
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/old-syntax/index.html
@@ -0,0 +1,36 @@
+
+
+
+
+Old Syntax
+
+Historically, rspec-mocks has used a monkey-patched syntax to allow you to mock or stub any object:
+obj.stub(:foo).and_return(15)
+obj.should_receive(:bar)
+
+Unfortunately, this is prone to weird, confusing failures when applied to delegate/proxy
+objects. For a method like stub to work properly, it must be defined on every object in the
+system, but RSpec does not own every object in the system and cannot ensure that it always
+works consistently.
+
+For this reason, in RSpec 2.14, we introduced a new syntax that avoids monkey patching
+altogether. It’s the syntax shown in all examples of this documentation outside of this
+directory. As of RSpec 3, we consider this to be the main, recommended syntax of rspec-
+mocks. The old monkey-patched syntax continues to work, but you will get a deprecation
+warning if you use it without explicitly opting-in to it:
+# If you're using rspec-core:
+RSpec.configure do |config|
+ config.mock_with :rspec do |mocks|
+ mocks.syntax = :should
+ end
+end
+
+# Or, if you're using rspec-mocks in another context:
+RSpec::Mocks.configuration.syntax = :should
+
+We have no plans to ever kill the old syntax, but we may extract it into an external gem in
+RSpec 4.
+
+If you have an old project that uses the old syntax and you want to update it to the current
+syntax, checkout transpec.
+Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/old-syntax/should-receive/index.html b/docs/features/3-12/rspec-mocks/old-syntax/should-receive/index.html
new file mode 100644
index 000000000..e559a33eb
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/old-syntax/should-receive/index.html
@@ -0,0 +1,94 @@
+
+
+
+
+should_receive
+
+should_receive is the old way to expect messages but carries the
+ baggage of a global monkey patch on all objects. It supports the
+ same fluent interface for setting constraints and configuring responses.
+
+Similarly, you can use should_not_receive to set a negative message expectation.
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rspec do |mocks|
+ mocks.syntax = :should
+ end
+end
+
+And a file named “.rspec” with:
+--require spec_helper
+
+Failing positive message expectation
+
+Given a file named “spec/unfulfilledmessageexpectation_spec.rb” with:
+RSpec.describe "An unfulfilled message expectation" do
+ it "triggers a failure" do
+ dbl = double("Some Collaborator")
+ dbl.should_receive(:foo)
+ end
+end
+
+When I run rspec spec/unfulfilled_message_expectation_spec.rb
+
+Then it should fail with:
+ 1) An unfulfilled message expectation triggers a failure
+ Failure/Error: dbl.should_receive(:foo)
+
+ (Double "Some Collaborator").foo(*(any args))
+ expected: 1 time with any arguments
+ received: 0 times with any arguments
+
+Passing positive message expectation
+
+Given a file named “spec/fulfilledmessageexpectation_spec.rb” with:
+RSpec.describe "A fulfilled message expectation" do
+ it "passes" do
+ dbl = double("Some Collaborator")
+ dbl.should_receive(:foo)
+ dbl.foo
+ end
+end
+
+When I run rspec spec/fulfilled_message_expectation_spec.rb
+
+Then the examples should all pass.
+
+Failing negative message expectation
+
+Given a file named “spec/negativemessageexpectation_spec.rb” with:
+RSpec.describe "A negative message expectation" do
+ it "fails when the message is received" do
+ dbl = double("Some Collaborator").as_null_object
+ dbl.should_not_receive(:foo)
+ dbl.foo
+ end
+end
+
+When I run rspec spec/negative_message_expectation_spec.rb
+
+Then it should fail with:
+ 1) A negative message expectation fails when the message is received
+ Failure/Error: dbl.foo
+
+ (Double "Some Collaborator").foo(no args)
+ expected: 0 times with any arguments
+ received: 1 time
+
+Passing negative message expectation
+
+Given a file named “spec/negativemessageexpectation_spec.rb” with:
+RSpec.describe "A negative message expectation" do
+ it "passes if the message is never received" do
+ dbl = double("Some Collaborator").as_null_object
+ dbl.should_not_receive(:foo)
+ end
+end
+
+When I run rspec spec/negative_message_expectation_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/old-syntax/stub-chain/index.html b/docs/features/3-12/rspec-mocks/old-syntax/stub-chain/index.html
new file mode 100644
index 000000000..1b20def8f
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/old-syntax/stub-chain/index.html
@@ -0,0 +1,73 @@
+
+
+
+
+stub_chain
+
+stub_chain is the old way to allow a message chain but carries the
+ baggage of a global monkey patch on all objects. As with
+ receive_message_chain, use with care; we recommend treating usage of stub_chain as a
+ code smell.
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rspec do |mocks|
+ mocks.syntax = :should
+ end
+end
+
+And a file named “.rspec” with:
+--require spec_helper
+
+Use stub_chain on a double
+
+Given a file named “spec/stubchainspec.rb” with:
+RSpec.describe "Using stub_chain on a double" do
+ let(:dbl) { double }
+
+ example "using a string and a block" do
+ dbl.stub_chain("foo.bar") { :baz }
+ expect(dbl.foo.bar).to eq(:baz)
+ end
+
+ example "using symbols and a hash" do
+ dbl.stub_chain(:foo, :bar => :baz)
+ expect(dbl.foo.bar).to eq(:baz)
+ end
+
+ example "using symbols and a block" do
+ dbl.stub_chain(:foo, :bar) { :baz }
+ expect(dbl.foo.bar).to eq(:baz)
+ end
+end
+
+When I run rspec spec/stub_chain_spec.rb
+
+Then the examples should all pass.
+
+Use stub_chain on any instance of a class
+
+Given a file named “spec/stubchainspec.rb” with:
+RSpec.describe "Using any_instance.stub_chain" do
+ example "using a string and a block" do
+ Object.any_instance.stub_chain("foo.bar") { :baz }
+ expect(Object.new.foo.bar).to eq(:baz)
+ end
+
+ example "using symbols and a hash" do
+ Object.any_instance.stub_chain(:foo, :bar => :baz)
+ expect(Object.new.foo.bar).to eq(:baz)
+ end
+
+ example "using symbols and a block" do
+ Object.any_instance.stub_chain(:foo, :bar) { :baz }
+ expect(Object.new.foo.bar).to eq(:baz)
+ end
+end
+
+When I run rspec spec/stub_chain_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/old-syntax/stub/index.html b/docs/features/3-12/rspec-mocks/old-syntax/stub/index.html
new file mode 100644
index 000000000..8d49fd918
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/old-syntax/stub/index.html
@@ -0,0 +1,55 @@
+
+
+
+
+stub
+
+stub is the old way to allow messages but carries the baggage of a
+ global monkey patch on all objects. It supports the same fluent
+ interface for setting constraints and configuring responses. You can also pass stub a hash
+ of message/return-value pairs, which acts like allow(obj).to receive_messages(hash),
+ but does not support further customization through the fluent interface.
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rspec do |mocks|
+ mocks.syntax = :should
+ end
+end
+
+And a file named “.rspec” with:
+--require spec_helper
+
+Stub a method
+
+Given a file named “spec/stub_spec.rb” with:
+RSpec.describe "Stubbing a method" do
+ it "configures how the object responds" do
+ dbl = double
+ dbl.stub(:foo).and_return(13)
+ expect(dbl.foo).to eq(13)
+ end
+end
+
+When I run rspec spec/stub_spec.rb
+
+Then the examples should all pass.
+
+Stub multiple methods by passing a hash
+
+Given a file named “spec/stubmultiplemethods_spec.rb” with:
+RSpec.describe "Stubbing multiple methods" do
+ it "stubs each named method with the given return value" do
+ dbl = double
+ dbl.stub(:foo => 13, :bar => 10)
+ expect(dbl.foo).to eq(13)
+ expect(dbl.bar).to eq(10)
+ end
+end
+
+When I run rspec spec/stub_multiple_methods_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/old-syntax/unstub/index.html b/docs/features/3-12/rspec-mocks/old-syntax/unstub/index.html
new file mode 100644
index 000000000..13219ea35
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/old-syntax/unstub/index.html
@@ -0,0 +1,46 @@
+
+
+
+
+Using unstub
+
+unstub removes a method stub, essentially cleaning up the method
+ stub early, rather than waiting for the cleanup that runs at the end
+ of the example. The newer non-monkey-patching syntax does not have a direct
+ equivalent but in most situations you can achieve the same behavior using
+ and_call_original. The difference is that obj.unstub(:foo) completely cleans up the foo
+ method stub, whereas allow(obj).to receive(:foo).and_call_original continues to
+ observe calls to the method (important when you are using spies), which could affect the
+ method’s behavior if it does anything with caller as it will include additional rspec stack
+ frames.
+
+Background
+
+Given a file named “spec/spec_helper.rb” with:
+RSpec.configure do |config|
+ config.mock_with :rspec do |mocks|
+ mocks.syntax = :should
+ end
+end
+
+And a file named “.rspec” with:
+--require spec_helper
+
+Unstub a method
+
+Given a file named “spec/unstub_spec.rb” with:
+RSpec.describe "Unstubbing a method" do
+ it "restores the original behavior" do
+ string = "hello world"
+ string.stub(:reverse) { "hello dlrow" }
+
+ expect {
+ string.unstub(:reverse)
+ }.to change { string.reverse }.from("hello dlrow").to("dlrow olleh")
+ end
+end
+
+When I run rspec spec/unstub_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/outside-rspec/any-test-framework/index.html b/docs/features/3-12/rspec-mocks/outside-rspec/any-test-framework/index.html
new file mode 100644
index 000000000..6852a9e29
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/outside-rspec/any-test-framework/index.html
@@ -0,0 +1,177 @@
+
+
+
+
+Integrating with any test framework
+
+rspec-mocks is a stand-alone gem that can be integrated with any test framework. The
+ example below demonstrates using rspec-mocks with minitest, but these steps
+ would apply when integrating rspec-mocks with any library or framework:
+* Include `RSpec::Mocks::ExampleMethods` in your test context. This provides rspec-mocks' API.
+* Call `RSpec::Mocks.setup` before a test begins.
+* Call `RSpec::Mocks.verify` after a test completes to verify message expectations. Note
+ that this step is optional; rspec-core, for example, skips this when an example has already failed.
+* Call `RSpec::Mocks.teardown` after a test completes (and after `verify`) to cleanup. This
+ _must_ be called, even if an error has occurred, so it generally goes in an `ensure` clause.
+
+Note: if you are using minitest, you’ll probably want to use the built-in minitest integration.
+
+Use rspec-mocks with Minitest
+
+Given a file named “test/test_helper.rb” with:
+require 'minitest/autorun'
+require 'rspec/mocks'
+
+module MinitestRSpecMocksIntegration
+ include ::RSpec::Mocks::ExampleMethods
+
+ def before_setup
+ ::RSpec::Mocks.setup
+ super
+ end
+
+ def after_teardown
+ super
+ ::RSpec::Mocks.verify
+ ensure
+ ::RSpec::Mocks.teardown
+ end
+end
+
+Minitest::Test.send(:include, MinitestRSpecMocksIntegration)
+
+And a file named “test/rspecmockstest.rb” with:
+require 'test_helper'
+
+class RSpecMocksTest < Minitest::Test
+ def test_passing_positive_expectation
+ dbl = double
+ expect(dbl).to receive(:message)
+ dbl.message
+ end
+
+ def test_failing_positive_expectation
+ dbl = double
+ expect(dbl).to receive(:message)
+ end
+
+ def test_passing_negative_expectation
+ dbl = double
+ expect(dbl).to_not receive(:message)
+ end
+
+ def test_failing_negative_expectation
+ dbl = double
+ expect(dbl).to_not receive(:message)
+ dbl.message
+ end
+
+ def test_passing_positive_spy_expectation
+ bond = spy
+ bond.james
+ expect(bond).to have_received(:james)
+ end
+
+ def test_failing_positive_spy_expectation
+ bond = spy
+ expect(bond).to have_received(:james)
+ end
+
+ def test_passing_negative_spy_expectation
+ bond = spy
+ expect(bond).not_to have_received(:james)
+ end
+
+ def test_failing_negative_spy_expectation
+ bond = spy
+ bond.james
+ expect(bond).not_to have_received(:james)
+ end
+end
+
+When I run ruby -Itest test/rspec_mocks_test.rb
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+1) Error:
+
+
+RSpecMocksTest#testfailingnegative_expectation:
+
+
+RSpec::Mocks::MockExpectationError: (Double (anonymous)).message(no args)
+
+
+expected: 0 times with any arguments
+
+
+received: 1 time
+
+
+
+
+
+2) Error:
+
+
+RSpecMocksTest#testfailingpositive_expectation:
+
+
+RSpec::Mocks::MockExpectationError: (Double (anonymous)).message(*(any args))
+
+
+expected: 1 time with any arguments
+
+
+received: 0 times with any arguments
+
+
+
+
+
+3) Error:
+
+
+RSpecMocksTest#testfailingpositivespyexpectation:
+
+
+RSpec::Mocks::MockExpectationError: (Double (anonymous)).james(*(any args))
+
+
+expected: 1 time with any arguments
+
+
+received: 0 times with any arguments
+
+
+
+
+
+4) Error:
+
+
+RSpecMocksTest#testfailingnegativespyexpectation:
+
+
+RSpec::Mocks::MockExpectationError: (Double (anonymous)).james(no args)
+
+
+expected: 0 times with any arguments
+
+
+received: 1 time
+
+
+
+
+
+8 runs, 0 assertions, 0 failures, 4 errors, 0 skips
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/outside-rspec/index.html b/docs/features/3-12/rspec-mocks/outside-rspec/index.html
new file mode 100644
index 000000000..04cf715e0
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/outside-rspec/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Outside rspec
Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/outside-rspec/minitest/index.html b/docs/features/3-12/rspec-mocks/outside-rspec/minitest/index.html
new file mode 100644
index 000000000..f87634de7
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/outside-rspec/minitest/index.html
@@ -0,0 +1,401 @@
+
+
+
+
+Integrating with Minitest
+
+To use rspec-mocks with minitest, simply require rspec/mocks/minitest_integration.
+
+Use rspec-mocks with Minitest::Test
+
+Given a file named “test/rspecmockstest.rb” with:
+require 'minitest/autorun'
+require 'rspec/mocks/minitest_integration'
+
+class RSpecMocksTest < Minitest::Test
+ def test_passing_positive_expectation
+ dbl = double
+ expect(dbl).to receive(:message)
+ dbl.message
+ end
+
+ def test_failing_positive_expectation
+ dbl = double
+ expect(dbl).to receive(:message)
+ end
+
+ def test_passing_negative_expectation
+ dbl = double
+ expect(dbl).to_not receive(:message)
+ end
+
+ def test_failing_negative_expectation
+ dbl = double
+ expect(dbl).to_not receive(:message)
+ dbl.message
+ end
+
+ def test_passing_positive_spy_expectation
+ bond = spy
+ bond.james
+ expect(bond).to have_received(:james)
+ end
+
+ def test_failing_positive_spy_expectation
+ bond = spy
+ expect(bond).to have_received(:james)
+ end
+
+ def test_passing_negative_spy_expectation
+ bond = spy
+ expect(bond).not_to have_received(:james)
+ end
+
+ def test_failing_negative_spy_expectation
+ bond = spy
+ bond.james
+ expect(bond).not_to have_received(:james)
+ end
+end
+
+When I run ruby test/rspec_mocks_test.rb --seed 0
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+1) Failure:
+
+
+RSpecMocksTest#testfailingpositive_expectation
+
+
+(Double (anonymous)).message(*(any args))
+
+
+expected: 1 time with any arguments
+
+
+received: 0 times with any arguments
+
+
+
+
+
+2) Failure:
+
+
+RSpecMocksTest#testfailingnegative_expectation
+
+
+(Double (anonymous)).message(no args)
+
+
+expected: 0 times with any arguments
+
+
+received: 1 time
+
+
+
+
+
+3) Failure:
+
+
+RSpecMocksTest#testfailingpositivespyexpectation
+
+
+(Double (anonymous)).james(*(any args))
+
+
+expected: 1 time with any arguments
+
+
+received: 0 times with any arguments
+
+
+
+
+
+4) Failure:
+
+
+RSpecMocksTest#testfailingnegativespyexpectation
+
+
+(Double (anonymous)).james(no args)
+
+
+expected: 0 times with any arguments
+
+
+received: 1 time
+
+
+
+
+
+8 runs, 0 assertions, 4 failures, 0 errors, 0 skips
+
+
+
+Use rspec-mocks with Minitest::Spec
+
+Given a file named “spec/rspecmocksspec.rb” with:
+require 'minitest/autorun'
+require 'minitest/spec'
+require 'rspec/mocks/minitest_integration'
+
+describe "Minitest Spec integration" do
+ it 'passes a positive expectation' do
+ dbl = double
+ expect(dbl).to receive(:message)
+ dbl.message
+ end
+
+ it 'fails a positive expectation' do
+ dbl = double
+ expect(dbl).to receive(:message)
+ end
+
+ it 'passes a negative expectation (using to_not)' do
+ dbl = double
+ expect(dbl).to_not receive(:message)
+ end
+
+ it 'fails a negative expectation (using not_to)' do
+ dbl = double
+ expect(dbl).not_to receive(:message)
+ dbl.message
+ end
+end
+
+When I run ruby spec/rspec_mocks_spec.rb --seed 0
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+1) Failure:
+
+
+Minitest Spec integration#test0002fails a positive expectation
+
+
+(Double (anonymous)).message(*(any args))
+
+
+expected: 1 time with any arguments
+
+
+received: 0 times with any arguments
+
+
+
+
+
+2) Failure:
+
+
+Minitest Spec integration#test0004fails a negative expectation (using not_to)
+
+
+(Double (anonymous)).message(no args)
+
+
+expected: 0 times with any arguments
+
+
+received: 1 time
+
+
+
+
+
+4 runs, 4 assertions, 2 failures, 0 errors, 0 skips
+
+
+
+Load rspec-mocks before rspec-expectations, with Minitest::Spec
+
+Given a file named “spec/rspecmocksspec.rb” with:
+require 'minitest/autorun'
+require 'minitest/spec'
+require 'rspec/mocks/minitest_integration'
+require 'rspec/expectations/minitest_integration'
+
+describe "Minitest Spec integration" do
+ it 'passes a positive expectation' do
+ dbl = double
+ expect(dbl).to receive(:message)
+ dbl.message
+ end
+
+ it 'fails a positive expectation' do
+ dbl = double
+ expect(dbl).to receive(:message)
+ end
+
+ it 'passes a negative expectation (using to_not)' do
+ dbl = double
+ expect(dbl).to_not receive(:message)
+ end
+
+ it 'fails a negative expectation (using not_to)' do
+ dbl = double
+ expect(dbl).not_to receive(:message)
+ dbl.message
+ end
+
+ it 'can use both minitest and rspec expectations' do
+ expect(1 + 3).must_equal 4
+ expect(1 + 3).to eq 4
+ end
+end
+
+When I run ruby spec/rspec_mocks_spec.rb --seed 0
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+1) Failure:
+
+
+Minitest Spec integration#test0002fails a positive expectation
+
+
+(Double (anonymous)).message(*(any args))
+
+
+expected: 1 time with any arguments
+
+
+received: 0 times with any arguments
+
+
+
+
+
+2) Failure:
+
+
+Minitest Spec integration#test0004fails a negative expectation (using not_to)
+
+
+(Double (anonymous)).message(no args)
+
+
+expected: 0 times with any arguments
+
+
+received: 1 time
+
+
+
+
+
+5 runs, 6 assertions, 2 failures, 0 errors, 0 skips
+
+
+
+Load rspec-mocks after rspec-expectations, with Minitest::Spec
+
+Given a file named “spec/rspecmocksspec.rb” with:
+require 'minitest/autorun'
+require 'minitest/spec'
+require 'rspec/expectations/minitest_integration'
+require 'rspec/mocks/minitest_integration'
+
+describe "Minitest Spec integration" do
+ it 'passes a positive expectation' do
+ dbl = double
+ expect(dbl).to receive(:message)
+ dbl.message
+ end
+
+ it 'fails a positive expectation' do
+ dbl = double
+ expect(dbl).to receive(:message)
+ end
+
+ it 'passes a negative expectation (using to_not)' do
+ dbl = double
+ expect(dbl).to_not receive(:message)
+ end
+
+ it 'fails a negative expectation (using not_to)' do
+ dbl = double
+ expect(dbl).not_to receive(:message)
+ dbl.message
+ end
+
+ it 'can use both minitest and rspec expectations' do
+ expect(1 + 3).must_equal 4
+ expect(1 + 3).to eq 4
+ end
+end
+
+When I run ruby spec/rspec_mocks_spec.rb --seed 0
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+1) Failure:
+
+
+Minitest Spec integration#test0002fails a positive expectation
+
+
+(Double (anonymous)).message(*(any args))
+
+
+expected: 1 time with any arguments
+
+
+received: 0 times with any arguments
+
+
+
+
+
+2) Failure:
+
+
+Minitest Spec integration#test0004fails a negative expectation (using not_to)
+
+
+(Double (anonymous)).message(no args)
+
+
+expected: 0 times with any arguments
+
+
+received: 1 time
+
+
+
+
+
+5 runs, 6 assertions, 2 failures, 0 errors, 0 skips
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/outside-rspec/standalone/index.html b/docs/features/3-12/rspec-mocks/outside-rspec/standalone/index.html
new file mode 100644
index 000000000..82baea982
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/outside-rspec/standalone/index.html
@@ -0,0 +1,55 @@
+
+
+
+
+Using rspec-mocks on its own outside of RSpec (standalone mode)
+
+require "rspec/mocks/standalone" to expose the API at the top level (e.g. main) outside
+ the RSpec environment in a REPL like IRB or in a one-off script.
+
+Allow a message outside RSpec
+
+Given a file named “example.rb” with:
+require "rspec/mocks/standalone"
+
+greeter = double("greeter")
+allow(greeter).to receive(:say_hi) { "Hello!" }
+puts greeter.say_hi
+
+When I run ruby example.rb
+
+Then the output should contain “Hello!”.
+
+Expect a message outside RSpec
+
+Given a file named “example.rb” with:
+require "rspec/mocks/standalone"
+
+greeter = double("greeter")
+expect(greeter).to receive(:say_hi)
+
+RSpec::Mocks.verify
+
+When I run ruby example.rb
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+(Double “greeter”).say_hi(*(any args))
+
+
+RSpec::Mocks::MockExpectationError
+
+
+expected: 1 time with any arguments
+
+
+received: 0 times with any arguments
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/setting-constraints/index.html b/docs/features/3-12/rspec-mocks/setting-constraints/index.html
new file mode 100644
index 000000000..638da3abb
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/setting-constraints/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+Setting Constraints
+
+RSpec provides a fluent interface off of expect(...).to receive(...) that allows you to
+further constrain what you expect: the arguments, the number of times, and the ordering of
+multiple messages.
+
+Although not shown here, this fluent interface is also supported by spies, off of
+have_received(...).
+Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/setting-constraints/matching-arguments/index.html b/docs/features/3-12/rspec-mocks/setting-constraints/matching-arguments/index.html
new file mode 100644
index 000000000..381a7582a
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/setting-constraints/matching-arguments/index.html
@@ -0,0 +1,367 @@
+
+
+
+
+Matching arguments
+
+Use with to specify the expected arguments. A message expectation constrained by with
+ will only be satisfied when called with matching arguments. A canned response for an
+ allowed message will only be used when the arguments match.
+
+
+
+To match…
+…use an expression like:
+…which matches calls like:
+
+
+
+Literal arguments
+with(1, true)
+foo(1, true)
+
+
+Literal arguments where one is a hash
+with(1, {x: 1, y: 2})
+`foo(1, x: 1, y: 2) (where last argument is a hash)
+
+
+Keyword arguments
+with(x: 1, y: 2)
+foo(x: 1, y: 2) (where x and y are keywords)
+
+
+Anything that supports case equality (===)
+with(/bar/)
+foo("barn")
+
+
+Any list of args
+with(any_args)
+foo()
foo(1)
foo(:bar, 2)
+
+
+Any sublist of args (like an arg splat)
+with(1, any_args)
+foo(1)
foo(1, :bar, :bazz)
+
+
+An empty list of args
+with(no_args)
+foo()
+
+
+Anything for a given positional arg
+with(3, anything)
+foo(3, nil)
foo(3, :bar)
+
+
+Against an interface
+with(duck_type(:each))
+foo([])
+
+
+A boolean
+with(3, boolean)
+foo(3, true)
foo(3, false)
+
+
+A subset of a hash
+with(hash_including(:a => 1))
+foo(:a => 1, :b => 2)
+
+
+An excluded subset of a hash
+with(hash_excluding(:a => 1))
+foo(:b => 2)
+
+
+A subset of an array
+with(array_including(:a, :b))
+foo([:a, :b, :c])
+
+
+An excluded subset of an array
+with(array_excluding(:a, :b))
+foo([:c, :d])
+
+
+An instance of a specific class
+with(instance_of(Integer))
+foo(3)
+
+
+An object with a given module in its ancestors list
+with(kind_of(Numeric))
+foo(3)
+
+
+An object with matching attributes
+with(having_attributes(:a => 1))
+foo(:a => 1, :b => 2)
+
+
+Any RSpec matcher
+with(<matcher>)
+foo(<object that matches>)
+
+
+
+Basic example
+
+Given a file named “basicexamplespec.rb” with:
+RSpec.describe "Constraining a message expectation using with" do
+ let(:dbl) { double }
+ before { expect(dbl).to receive(:foo).with(1, anything, /bar/) }
+
+ it "passes when the args match" do
+ dbl.foo(1, nil, "barn")
+ end
+
+ it "fails when the args do not match" do
+ dbl.foo(1, nil, "other")
+ end
+end
+
+When I run rspec basic_example_spec.rb
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+2 examples, 1 failure
+
+
+
+
+
+Failure/Error: dbl.foo(1, nil, “other”)
+
+
+# received :foo with unexpected arguments
+
+
+expected: (1, anything, /bar/)
+
+
+got: (1, nil, “other”)
+
+
+
+Using keyword arguments
+
+Given a file named “keywordexamplespec.rb” with:
+class WithKeywords
+ def foo(bar: "")
+ end
+end
+
+RSpec.describe "Constraining a message expectation using with" do
+ let(:dbl) { instance_double(WithKeywords) }
+ before { expect(dbl).to receive(:foo).with(bar: "baz") }
+
+ it "passes when the args match" do
+ dbl.foo(bar: "baz")
+ end
+
+ it "fails when the args do not match" do
+ dbl.foo(bar: "incorrect")
+ end
+end
+
+When I run rspec keyword_example_spec.rb
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+2 examples, 1 failure
+
+
+
+
+
+Failure/Error: dbl.foo(bar: “incorrect”)
+
+
+# received :foo with unexpected arguments
+
+
+expected: ({:bar=>“baz”})
+
+
+got: ({:bar=>“incorrect”})
+
+
+
+Using keyword arguments on Rubies that differentiate hashes from keyword arguments
+
+Given a file named “keywordexamplespec.rb” with:
+class WithKeywords
+ def foo(bar: "")
+ end
+end
+
+RSpec.describe "Constraining a message expectation using with" do
+ let(:dbl) { instance_double(WithKeywords) }
+ before { expect(dbl).to receive(:foo).with(bar: "baz") }
+
+ it "fails when the args do not match due to a hash" do
+ dbl.foo({bar: "also incorrect"})
+ end
+end
+
+When I run rspec keyword_example_spec.rb
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+1 example, 1 failure
+
+
+
+
+
+Failure/Error: dbl.foo({bar: “also incorrect”})
+
+
+# received :foo with unexpected arguments
+
+
+expected: ({:bar=>“baz”}) (keyword arguments)
+
+
+got: ({:bar=>“also incorrect”}) (options hash)
+
+
+
+Using a RSpec matcher
+
+Given a file named “rspecmatcherspec.rb” with:
+RSpec.describe "Using a RSpec matcher" do
+ let(:dbl) { double }
+ before { expect(dbl).to receive(:foo).with(a_collection_containing_exactly(1, 2)) }
+
+ it "passes when the args match" do
+ dbl.foo([2, 1])
+ end
+
+ it "fails when the args do not match" do
+ dbl.foo([1, 3])
+ end
+end
+
+When I run rspec rspec_matcher_spec.rb
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+2 examples, 1 failure
+
+
+
+
+
+Failure/Error: dbl.foo([1, 3])
+
+
+# received :foo with unexpected arguments
+
+
+expected: (a collection containing exactly 1 and 2)
+
+
+got: ([1, 3])
+
+
+
+Using a custom matcher
+
+Given a file named “custommatcherspec.rb” with:
+RSpec::Matchers.define :a_multiple_of do |x|
+ match { |actual| (actual % x).zero? }
+end
+
+RSpec.describe "Using a custom matcher" do
+ let(:dbl) { double }
+ before { expect(dbl).to receive(:foo).with(a_multiple_of(3)) }
+
+ it "passes when the args match" do
+ dbl.foo(12)
+ end
+
+ it "fails when the args do not match" do
+ dbl.foo(13)
+ end
+end
+
+When I run rspec custom_matcher_spec.rb
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+2 examples, 1 failure
+
+
+
+
+
+Failure/Error: dbl.foo(13)
+
+
+# received :foo with unexpected arguments
+
+
+expected: (a multiple of 3)
+
+
+got: (13)
+
+
+
+Responding differently based on the arguments
+
+Given a file named “respondingdifferentlyspec.rb” with:
+RSpec.describe "Using #with to constrain responses" do
+ specify "its response depends on the arguments" do
+ dbl = double
+
+ # Set a default for any unmatched args
+ allow(dbl).to receive(:foo).and_return(:default)
+
+ allow(dbl).to receive(:foo).with(1).and_return(1)
+ allow(dbl).to receive(:foo).with(2).and_return(2)
+
+ expect(dbl.foo(0)).to eq(:default)
+ expect(dbl.foo(1)).to eq(1)
+ expect(dbl.foo(2)).to eq(2)
+ end
+end
+
+When I run rspec responding_differently_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/setting-constraints/message-order/index.html b/docs/features/3-12/rspec-mocks/setting-constraints/message-order/index.html
new file mode 100644
index 000000000..00776ebbd
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/setting-constraints/message-order/index.html
@@ -0,0 +1,91 @@
+
+
+
+
+Message Order
+
+You can use ordered to constrain the order of multiple message expectations. This is not
+ generally recommended because in most situations the order doesn’t matter and using
+ ordered would make your spec brittle, but it’s occasionally useful. When you use ordered,
+ the example will only pass if the messages are received in the declared order.
+
+Passing example
+
+Given a file named “passingexamplespec.rb” with:
+RSpec.describe "Constraining order" do
+ it "passes when the messages are received in declared order" do
+ collaborator_1 = double("Collaborator 1")
+ collaborator_2 = double("Collaborator 2")
+
+ expect(collaborator_1).to receive(:step_1).ordered
+ expect(collaborator_2).to receive(:step_2).ordered
+ expect(collaborator_1).to receive(:step_3).ordered
+
+ collaborator_1.step_1
+ collaborator_2.step_2
+ collaborator_1.step_3
+ end
+end
+
+When I run rspec passing_example_spec.rb
+
+Then the examples should all pass.
+
+Failing examples
+
+Given a file named “failingexamplesspec.rb” with:
+RSpec.describe "Constraining order" do
+ it "fails when messages are received out of order on one collaborator" do
+ collaborator_1 = double("Collaborator 1")
+
+ expect(collaborator_1).to receive(:step_1).ordered
+ expect(collaborator_1).to receive(:step_2).ordered
+
+ collaborator_1.step_2
+ collaborator_1.step_1
+ end
+
+ it "fails when messages are received out of order between collaborators" do
+ collaborator_1 = double("Collaborator 1")
+ collaborator_2 = double("Collaborator 2")
+
+ expect(collaborator_1).to receive(:step_1).ordered
+ expect(collaborator_2).to receive(:step_2).ordered
+
+ collaborator_2.step_2
+ collaborator_1.step_1
+ end
+end
+
+When I run rspec failing_examples_spec.rb --order defined
+
+Then the examples should all fail, producing the following output:
+
+
+
+
+
+
+
+1) Constraining order fails when messages are received out of order on one collaborator
+
+
+Failure/Error: collaborator1.step2
+
+
+# received :step_2 out of order
+
+
+
+
+
+2) Constraining order fails when messages are received out of order between collaborators
+
+
+Failure/Error: collaborator2.step2
+
+
+# received :step_2 out of order
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/setting-constraints/receive-counts/index.html b/docs/features/3-12/rspec-mocks/setting-constraints/receive-counts/index.html
new file mode 100644
index 000000000..cfcb741c7
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/setting-constraints/receive-counts/index.html
@@ -0,0 +1,271 @@
+
+
+
+
+Receive Counts
+
+When expecting a message, you can specify how many times you expect the message to be
+ received:
+* `expect(...).to receive(...).once`
+* `expect(...).to receive(...).twice`
+* `expect(...).to receive(...).exactly(n).time`
+* `expect(...).to receive(...).exactly(n).times`
+* `expect(...).to receive(...).at_least(:once)`
+* `expect(...).to receive(...).at_least(:twice)`
+* `expect(...).to receive(...).at_least(n).time`
+* `expect(...).to receive(...).at_least(n).times`
+* `expect(...).to receive(...).at_most(:once)`
+* `expect(...).to receive(...).at_most(:twice)`
+* `expect(...).to receive(...).at_most(n).time`
+* `expect(...).to receive(...).at_most(n).times`
+
+If you don’t specify an expected receive count, it defaults to once.
+
+Background
+
+Given a file named “lib/account.rb” with:
+class Account
+ def initialize(logger)
+ @logger = logger
+ end
+
+ def open
+ @logger.account_opened
+ end
+end
+
+Passing examples
+
+Given a file named “spec/account_spec.rb” with:
+require 'account'
+
+RSpec.describe Account do
+ let(:logger) { double("Logger") }
+ let(:account) { Account.new(logger) }
+
+ example "once" do
+ expect(logger).to receive(:account_opened).once
+ account.open
+ end
+
+ example "twice" do
+ expect(logger).to receive(:account_opened).twice
+ account.open
+ account.open
+ end
+
+ example "exactly(n).time" do
+ expect(logger).to receive(:account_opened).exactly(1).time
+ account.open
+ end
+
+ example "exactly(n).times" do
+ expect(logger).to receive(:account_opened).exactly(3).times
+ account.open
+ account.open
+ account.open
+ end
+
+ example "at_least(:once)" do
+ expect(logger).to receive(:account_opened).at_least(:once)
+ account.open
+ account.open
+ end
+
+ example "at_least(:twice)" do
+ expect(logger).to receive(:account_opened).at_least(:twice)
+ account.open
+ account.open
+ account.open
+ end
+
+ example "at_least(n).time" do
+ expect(logger).to receive(:account_opened).at_least(1).time
+ account.open
+ end
+
+ example "at_least(n).times" do
+ expect(logger).to receive(:account_opened).at_least(3).times
+ account.open
+ account.open
+ account.open
+ account.open
+ end
+
+ example "at_most(:once)" do
+ expect(logger).to receive(:account_opened).at_most(:once)
+ end
+
+ example "at_most(:twice)" do
+ expect(logger).to receive(:account_opened).at_most(:twice)
+ account.open
+ end
+
+ example "at_most(n).time" do
+ expect(logger).to receive(:account_opened).at_most(1).time
+ account.open
+ end
+
+ example "at_most(n).times" do
+ expect(logger).to receive(:account_opened).at_most(3).times
+ account.open
+ account.open
+ end
+end
+
+When I run rspec spec/account_spec.rb
+
+Then the examples should all pass.
+
+Failing examples
+
+Given a file named “spec/account_spec.rb” with:
+require 'account'
+
+RSpec.describe Account do
+ let(:logger) { double("Logger") }
+ let(:account) { Account.new(logger) }
+
+ example "once" do
+ expect(logger).to receive(:account_opened).once
+ account.open
+ account.open
+ end
+
+ example "twice" do
+ expect(logger).to receive(:account_opened).twice
+ account.open
+ end
+
+ example "exactly(n).times" do
+ expect(logger).to receive(:account_opened).exactly(3).times
+ account.open
+ account.open
+ end
+
+ example "at_least(:once)" do
+ expect(logger).to receive(:account_opened).at_least(:once)
+ end
+
+ example "at_least(:twice)" do
+ expect(logger).to receive(:account_opened).at_least(:twice)
+ account.open
+ end
+
+ example "at_least(n).times" do
+ expect(logger).to receive(:account_opened).at_least(3).times
+ account.open
+ account.open
+ end
+
+ example "at_most(:once)" do
+ expect(logger).to receive(:account_opened).at_most(:once)
+ account.open
+ account.open
+ end
+
+ example "at_most(:twice)" do
+ expect(logger).to receive(:account_opened).at_most(:twice)
+ account.open
+ account.open
+ account.open
+ end
+
+ example "at_most(n).times" do
+ expect(logger).to receive(:account_opened).at_most(3).times
+ account.open
+ account.open
+ account.open
+ account.open
+ end
+end
+
+When I run rspec spec/account_spec.rb --order defined
+
+Then the examples should all fail, producing the following output:
+
+
+
+
+
+
+
+expected: 1 time with any arguments
+
+
+received: 2 times
+
+
+
+
+
+expected: 2 times with any arguments
+
+
+received: 1 time with any arguments
+
+
+
+
+
+expected: 3 times with any arguments
+
+
+received: 2 times with any arguments
+
+
+
+
+
+expected: at least 1 time with any arguments
+
+
+received: 0 times with any arguments
+
+
+
+
+
+expected: at least 2 times with any arguments
+
+
+received: 1 time with any arguments
+
+
+
+
+
+expected: at least 3 times with any arguments
+
+
+received: 2 times with any arguments
+
+
+
+
+
+expected: at most 1 time with any arguments
+
+
+received: 2 times
+
+
+
+
+
+expected: at most 2 times with any arguments
+
+
+received: 3 times
+
+
+
+
+
+expected: at most 3 times with any arguments
+
+
+received: 4 times
+
+
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/verifying-doubles/class-doubles/index.html b/docs/features/3-12/rspec-mocks/verifying-doubles/class-doubles/index.html
new file mode 100644
index 000000000..e67c04674
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/verifying-doubles/class-doubles/index.html
@@ -0,0 +1,74 @@
+
+
+
+
+Using a class double
+
+class_double is provided as a complement to instance_double with the difference that it
+ verifies class methods on the given class rather than instance methods.
+
+In addition, it also provides a convenience method as_stubbed_const to replace concrete
+ classes with the defined double. See mutating constants for more details.
+
+Note: class_double can be used for modules as well. We chose to stick with the
+ class_double terminology because the methods a class_double verifies against are
+ commonly called “class methods”, not “module methods”, even when working with a module.
+
+Background
+
+Given a file named “lib/user.rb” with:
+class User
+ def suspend!
+ ConsoleNotifier.notify("suspended as")
+ end
+end
+
+Given a file named “lib/console_notifier.rb” with:
+class ConsoleNotifier
+ MAX_WIDTH = 80
+
+ def self.notify(message)
+ puts message
+ end
+end
+
+Given a file named “spec/user_spec.rb” with:
+require 'user'
+require 'console_notifier'
+
+RSpec.describe User, '#suspend!' do
+ it 'notifies the console' do
+ notifier = class_double("ConsoleNotifier").
+ as_stubbed_const(:transfer_nested_constants => true)
+
+ expect(notifier).to receive(:notify).with("suspended as")
+ expect(ConsoleNotifier::MAX_WIDTH).to eq(80)
+
+ user = User.new
+ user.suspend!
+ end
+end
+
+Replacing existing constants
+
+When I run rspec spec/user_spec.rb
+
+Then the examples should all pass.
+
+Renaming ConsoleNotifier.notify to send_notification
+
+Given a file named “lib/console_notifier.rb” with:
+class ConsoleNotifier
+ MAX_WIDTH = 80
+
+ def self.send_notification(message)
+ puts message
+ end
+end
+
+When I run rspec spec/user_spec.rb
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should contain “the ConsoleNotifier class does not implement the class method:”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/verifying-doubles/dynamic-classes/index.html b/docs/features/3-12/rspec-mocks/verifying-doubles/dynamic-classes/index.html
new file mode 100644
index 000000000..44c6b9d14
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/verifying-doubles/dynamic-classes/index.html
@@ -0,0 +1,107 @@
+
+
+
+
+Dynamic classes
+
+Verifying instance doubles do not support methods which the class reports to not exist
+ since an actual instance of the class would be required to verify against. This is commonly
+ the case when method_missing is used.
+
+There are a few ways to work around this. If the object has already been loaded you may
+ consider using an object_double, but that cannot work if you are testing in isolation.
+ Alternatively you could implement the methods directly (calling super to return the method_missing definition).
+
+Some of these classes may have methods to define these methods on the objects at runtime.
+ (For example, ActiveRecord does this to define methods from database columns.) For these
+ cases we provide an API which can be used to customise verifying doubles on creation. We
+ use this ourselves in rspec-rails to set up some niceties for you.
+
+These types of methods are supported at class level (with class_double) however, since
+ respond_to? can be queried directly on the class.
+
+Background
+
+Given a file named “lib/fakeactiverecord.rb” with:
+class FakeActiveRecord
+ COLUMNS = %w[name email]
+
+ def respond_to_missing?(method_name)
+ COLUMNS.include?(method_name.to_s) || super
+ end
+
+ def method_missing(method_name, *args)
+ if respond_to?(method_name)
+ instance_variable_get("@#{method_name}")
+ else
+ super
+ end
+ end
+
+ def self.define_attribute_methods
+ COLUMNS.each do |name|
+ define_method(name) { instance_variable_get("@#{name}") }
+ end
+ end
+end
+
+Given a file named “spec/user_spec.rb” with:
+require 'user'
+
+RSpec.describe User do
+ it 'can be doubled' do
+ instance_double("User", :name => "Don")
+ end
+end
+
+Fails with method missing
+
+Given a file named “lib/user.rb” with:
+require 'fake_active_record'
+
+class User < FakeActiveRecord
+end
+
+When I run rspec spec/user_spec.rb
+
+Then the output should contain “1 example, 1 failure”.
+
+Workaround with explicit definitions
+
+Given a file named “lib/user.rb” with:
+require 'fake_active_record'
+
+class User < FakeActiveRecord
+ def name; super end
+ def email; super end
+end
+
+When I run rspec spec/user_spec.rb
+
+Then the examples should all pass.
+
+Workaround using callback
+
+Given a file named “lib/user.rb” with:
+require 'fake_active_record'
+
+class User < FakeActiveRecord
+end
+
+And a file named “spec/fakerecordhelper.rb” with:
+RSpec.configuration.mock_with(:rspec) do |config|
+ config.before_verifying_doubles do |reference|
+ reference.target.define_attribute_methods
+ end
+end
+#
+# or you can use:
+#
+# RSpec::Mocks.configuration.before_verifying_doubles do |reference|
+# reference.target.define_attribute_methods
+# end
+
+When I run rspec -r fake_record_helper spec/user_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/verifying-doubles/index.html b/docs/features/3-12/rspec-mocks/verifying-doubles/index.html
new file mode 100644
index 000000000..845ab56b6
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/verifying-doubles/index.html
@@ -0,0 +1,20 @@
+
+
+
+
+Verifying doubles
+
+Verifying doubles are a stricter alternative to normal doubles that provide guarantees about
+what is being verified. When using verifying doubles, RSpec will check that the methods
+being stubbed are actually present on the underlying object if it is available. Prefer using
+verifying doubles over normal doubles.
+
+No checking will happen if the underlying object or class is not defined, but when run with
+it present (either as a full spec run or by explicitly preloading collaborators) a failure will be
+triggered if an invalid method is being stubbed or a method is called with an invalid
+number of arguments.
+
+This dual approach allows you to move very quickly and test components in isolation, while
+giving you confidence that your doubles are not a complete fiction. Testing in isolation is
+optional but recommended for classes that do not depend on third-party components.
+Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/verifying-doubles/instance-doubles/index.html b/docs/features/3-12/rspec-mocks/verifying-doubles/instance-doubles/index.html
new file mode 100644
index 000000000..b3e060330
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/verifying-doubles/instance-doubles/index.html
@@ -0,0 +1,107 @@
+
+
+
+
+Using an instance double
+
+An instance_double is the most common type of verifying double. It takes a class name or
+ object as its first argument, then verifies that any methods being stubbed would be present
+ on an instance of that class. In addition, when it receives messages, it verifies that the
+ provided arguments are supported by the method signature, both in terms of arity and
+ allowed or required keyword arguments, if any. The same argument verification happens
+ when you constrain the arguments using with.
+
+For methods handled by method_missing, see dynamic classes.
+
+Background
+
+Given a file named “app/models/user.rb” with:
+class User < Struct.new(:notifier)
+ def suspend!
+ notifier.notify("suspended as")
+ end
+end
+
+Given a file named “spec/unit_helper.rb” with:
+$LOAD_PATH.unshift("app/models")
+
+Given a file named “spec/spec_helper.rb” with:
+require 'unit_helper'
+
+require 'user'
+require 'console_notifier'
+
+RSpec.configure do |config|
+ config.mock_with :rspec do |mocks|
+
+ # This option should be set when all dependencies are being loaded
+ # before a spec run, as is the case in a typical spec helper. It will
+ # cause any verifying double instantiation for a class that does not
+ # exist to raise, protecting against incorrectly spelt names.
+ mocks.verify_doubled_constant_names = true
+
+ end
+end
+
+Given a file named “spec/unit/user_spec.rb” with:
+require 'unit_helper'
+
+require 'user'
+
+RSpec.describe User, '#suspend!' do
+ it 'notifies the console' do
+ notifier = instance_double("ConsoleNotifier")
+
+ expect(notifier).to receive(:notify).with("suspended as")
+
+ user = User.new(notifier)
+ user.suspend!
+ end
+end
+
+Spec passes in isolation
+
+When I run rspec spec/unit/user_spec.rb
+
+Then the examples should all pass.
+
+Spec passes with dependencies loaded and method implemented
+
+Given a file named “app/models/console_notifier.rb” with:
+class ConsoleNotifier
+ def notify(msg)
+ puts message
+ end
+end
+
+When I run rspec -r./spec/spec_helper spec/unit/user_spec.rb
+
+Then the examples should all pass.
+
+Spec fails with dependencies loaded and method unimplemented
+
+Given a file named “app/models/console_notifier.rb” with:
+class ConsoleNotifier
+end
+
+When I run rspec -r./spec/spec_helper spec/unit/user_spec.rb
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should contain “ConsoleNotifier class does not implement the instance method:”.
+
+Spec fails with dependencies loaded and incorrect arity
+
+Given a file named “app/models/console_notifier.rb” with:
+class ConsoleNotifier
+ def notify(msg, color)
+ puts color + message
+ end
+end
+
+When I run rspec -r./spec/spec_helper spec/unit/user_spec.rb
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should contain “Wrong number of arguments.”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/verifying-doubles/object-doubles/index.html b/docs/features/3-12/rspec-mocks/verifying-doubles/object-doubles/index.html
new file mode 100644
index 000000000..21e03eed0
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/verifying-doubles/object-doubles/index.html
@@ -0,0 +1,69 @@
+
+
+
+
+Using an object double
+
+object_double can be used to create a double from an existing “template” object, from
+ which it verifies that any stubbed methods on the double also exist on the template. This is
+ useful for objects that are readily constructable, but may have far-reaching side-effects
+ such as talking to a database or external API. In this case, using a double rather than the
+ real thing allows you to focus on the communication patterns of the object’s interface
+ without having to worry about accidentally causing side-effects. Object doubles can also be
+ used to verify methods defined on an object using method_missing, which is not possible
+ with instance_double.
+
+In addition, object_double can be used with specific constant values, as shown below. This
+ is for niche situations, such as when dealing with singleton objects.
+
+Doubling an existing object
+
+Given a file named “spec/user_spec.rb” with:
+class User
+ # Don't want to accidentally trigger this!
+ def save; sleep 100; end
+end
+
+def save_user(user)
+ "saved!" if user.save
+end
+
+RSpec.describe '#save_user' do
+ it 'renders message on success' do
+ user = object_double(User.new, :save => true)
+ expect(save_user(user)).to eq("saved!")
+ end
+end
+
+When I run rspec spec/user_spec.rb
+
+Then the examples should all pass.
+
+Doubling a constant object
+
+Given a file named “spec/email_spec.rb” with:
+require 'logger'
+
+module MyApp
+ LOGGER = Logger.new("myapp")
+end
+
+class Email
+ def self.send_to(recipient)
+ MyApp::LOGGER.info("Sent to #{recipient}")
+ # other emailing logic
+ end
+end
+
+RSpec.describe Email do
+ it 'logs a message when sending' do
+ logger = object_double("MyApp::LOGGER", :info => nil).as_stubbed_const
+ Email.send_to('hello@foo.com')
+ expect(logger).to have_received(:info).with("Sent to hello@foo.com")
+ end
+end
+
+When I run rspec spec/email_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/verifying-doubles/partial-doubles/index.html b/docs/features/3-12/rspec-mocks/verifying-doubles/partial-doubles/index.html
new file mode 100644
index 000000000..5fe74716b
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/verifying-doubles/partial-doubles/index.html
@@ -0,0 +1,40 @@
+
+
+
+
+Partial doubles
+
+When the verify_partial_doubles configuration option is set, the same argument and
+ method existence checks that are performed for object_double are also performed on
+ partial doubles. You should set this unless you have a good reason not to. It defaults to off
+ only for backwards compatibility.
+
+Doubling an existing object
+
+Given a file named “spec/user_spec.rb” with:
+class User
+ def save; false; end
+end
+
+def save_user(user)
+ "saved!" if user.save
+end
+
+RSpec.configure do |config|
+ config.mock_with :rspec do |mocks|
+ mocks.verify_partial_doubles = true
+ end
+end
+
+RSpec.describe '#save_user' do
+ it 'renders message on success' do
+ user = User.new
+ expect(user).to receive(:wave).and_return(true) # Typo in name
+ expect(save_user(user)).to eq("saved!")
+ end
+end
+
+When I run rspec spec/user_spec.rb
+
+Then the output should contain “1 example, 1 failure”.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/working-with-legacy-code/any-instance/index.html b/docs/features/3-12/rspec-mocks/working-with-legacy-code/any-instance/index.html
new file mode 100644
index 000000000..93e726d94
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/working-with-legacy-code/any-instance/index.html
@@ -0,0 +1,176 @@
+
+
+
+
+Any Instance
+
+rspec-mocks provides two methods, allow_any_instance_of and
+ expect_any_instance_of, that will allow you to stub or mock any instance of a class. They
+ are used in place of allow or expect:
+ allow_any_instance_of(Widget).to receive(:name).and_return("Wibble")
+ expect_any_instance_of(Widget).to receive(:name).and_return("Wobble")
+
+These methods add the appropriate stub or expectation to all instances of Widget.
+
+You can also configure the responses in the same manner.
+
+This feature is sometimes useful when working with legacy code, though in general we
+ discourage its use for a number of reasons:
+
+
+- The
rspec-mocks API is designed for individual object instances, but this feature
+operates on entire classes of objects. As a result there are some semantically confusing
+edge cases. For example, in expect_any_instance_of(Widget).to
+receive(:name).twice it isn’t clear whether a specific instance is expected to
+receive name twice, or if two receives total are expected. (It’s the former.)
+- Using this feature is often a design smell. It may be that your test is trying to do too
+much or that the object under test is too complex.
+- It is the most complicated feature of
rspec-mocks, and has historically received the
+most bug reports. (None of the core team actively use it, which doesn’t help.)
+
+
+Use allow_any_instance_of to stub a method
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "allow_any_instance_of" do
+ it "returns the specified value on any instance of the class" do
+ allow_any_instance_of(Object).to receive(:foo).and_return(:return_value)
+
+ o = Object.new
+ expect(o.foo).to eq(:return_value)
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
+Use allow_any_instance_of to stub multiple methods
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "allow_any_instance_of" do
+ context "with receive_messages" do
+ it "stubs multiple methods" do
+ allow_any_instance_of(Object).to receive_messages(:foo => 'foo', :bar => 'bar')
+
+ o = Object.new
+ expect(o.foo).to eq('foo')
+ expect(o.bar).to eq('bar')
+ end
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
+Stubbing any instance of a class with specific arguments
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "allow_any_instance_of" do
+ context "with arguments" do
+ it "returns the stubbed value when arguments match" do
+ allow_any_instance_of(Object).to receive(:foo).with(:param_one, :param_two).and_return(:result_one)
+ allow_any_instance_of(Object).to receive(:foo).with(:param_three, :param_four).and_return(:result_two)
+
+ o = Object.new
+ expect(o.foo(:param_one, :param_two)).to eq(:result_one)
+ expect(o.foo(:param_three, :param_four)).to eq(:result_two)
+ end
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
+Block implementation is passed the receiver as first arg
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "allow_any_instance_of" do
+ it 'yields the receiver to the block implementation' do
+ allow_any_instance_of(String).to receive(:slice) do |instance, start, length|
+ instance[start, length]
+ end
+
+ expect('string'.slice(2, 3)).to eq('rin')
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then the examples should all pass.
+
+Use expect_any_instance_of to set a message expectation on any instance
+
+Given a file named “example_spec.rb” with:
+RSpec.describe "expect_any_instance_of" do
+ before do
+ expect_any_instance_of(Object).to receive(:foo)
+ end
+
+ it "passes when an instance receives the message" do
+ Object.new.foo
+ end
+
+ it "fails when no instance receives the message" do
+ Object.new.to_s
+ end
+end
+
+When I run rspec example_spec.rb
+
+Then it should fail with the following output:
+
+
+
+
+
+
+
+2 examples, 1 failure
+
+
+Exactly one instance should have received the following message(s) but didn’t: foo
+
+
+
+Specify different return values for multiple calls in combination with allowanyinstance_of
+
+Using the multiple calls feature with allow_any_instance_of results in the behaviour where multiple calls are configured on every instance.
+ Therefore, each individual instance will return the configured return values in the order specified, and then begin to repeat the last value.
+
+Given a file named “multiplecallsspecwithallowanyinstance_of.rb” with:
+class SomeClass
+end
+
+RSpec.describe "When the method is called multiple times on different instances with allow_any_instance_of" do
+ it "demonstrates the mocked behavior on each instance individually" do
+ allow_any_instance_of(SomeClass).to receive(:foo).and_return(1, 2, 3)
+
+ first = SomeClass.new
+ second = SomeClass.new
+ third = SomeClass.new
+
+ expect(first.foo).to eq(1)
+ expect(second.foo).to eq(1)
+
+ expect(first.foo).to eq(2)
+ expect(second.foo).to eq(2)
+
+ expect(first.foo).to eq(3)
+ expect(first.foo).to eq(3) # repeats last value from here
+ expect(second.foo).to eq(3)
+ expect(second.foo).to eq(3) # repeats last value from here
+
+ expect(third.foo).to eq(1)
+ expect(third.foo).to eq(2)
+ expect(third.foo).to eq(3)
+ expect(third.foo).to eq(3) # repeats last value from here
+ end
+end
+
+When I run rspec multiple_calls_spec_with_allow_any_instance_of.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/working-with-legacy-code/index.html b/docs/features/3-12/rspec-mocks/working-with-legacy-code/index.html
new file mode 100644
index 000000000..6e0466290
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/working-with-legacy-code/index.html
@@ -0,0 +1,10 @@
+
+
+
+
+Working with legacy code
+
+RSpec provides a few features that, while not generally recommended, can be useful when
+you are getting legacy code under test (or in similar situations). Usage of these features
+should be considered a code smell.
+Topics
\ No newline at end of file
diff --git a/docs/features/3-12/rspec-mocks/working-with-legacy-code/message-chains/index.html b/docs/features/3-12/rspec-mocks/working-with-legacy-code/message-chains/index.html
new file mode 100644
index 000000000..42b11badf
--- /dev/null
+++ b/docs/features/3-12/rspec-mocks/working-with-legacy-code/message-chains/index.html
@@ -0,0 +1,91 @@
+
+
+
+
+Message Chains
+
+You can use receive_message_chain in place of receive in certain circumstances
+ to stub a chain of messages:
+ allow(double).to receive_message_chain("foo.bar") { :baz }
+ allow(double).to receive_message_chain(:foo, :bar => :baz)
+ allow(double).to receive_message_chain(:foo, :bar) { :baz }
+
+Given any of these three forms:
+ double.foo.bar # => :baz
+
+Common use in Rails/ActiveRecord:
+ allow(Article).to receive_message_chain("recent.published") { [Article.new] }
+
+receive_message_chain is designed to be used with evaluating a response like and_return,
+ and_yield etc. For legacy reasons, parity with stub_chain is supported but its uses are
+ not considered good practice. Support for stub_chain parity may be removed in future versions.
+
+Customisations like exactly (i.e. exactly(2).times) are not supported.
+
+Warning:
+ ========
+
+Chains can be arbitrarily long, which makes it quite painless to violate the Law of Demeter
+ in violent ways, so you should consider any use of receive_message_chain a code smell.
+ Even though not all code smells indicate real problems (think fluent interfaces),
+ receive_message_chain still results in brittle examples. For example, if you write
+ allow(foo).to receive_message_chain(:bar, :baz => 37) in a spec and then the
+ implementation calls foo.baz.bar, the stub will not work.
+
+Chaining with receive_message_chain creates ambiguity in how the chains should
+ be applied and applies design pressure on complex interactions in the implementation
+ code. As such receive_message_chain is not a perfect replacement for receive. (see
+ Issue 921 for a more detailed
+ explanation). Other mocking methods like double and instance_double provide a
+ better way of testing code with these interactions.
+
+Use receive_message_chain on a double
+
+Given a file named “receivemessagechain_spec.rb” with:
+RSpec.describe "Using receive_message_chain on a double" do
+ let(:dbl) { double }
+
+ example "using a string and a block" do
+ allow(dbl).to receive_message_chain("foo.bar") { :baz }
+ expect(dbl.foo.bar).to eq(:baz)
+ end
+
+ example "using symbols and a hash" do
+ allow(dbl).to receive_message_chain(:foo, :bar => :baz)
+ expect(dbl.foo.bar).to eq(:baz)
+ end
+
+ example "using symbols and a block" do
+ allow(dbl).to receive_message_chain(:foo, :bar) { :baz }
+ expect(dbl.foo.bar).to eq(:baz)
+ end
+end
+
+When I run rspec receive_message_chain_spec.rb
+
+Then the examples should all pass.
+
+Use receive_message_chain on any instance of a class
+
+Given a file named “receivemessagechain_spec.rb” with:
+RSpec.describe "Using receive_message_chain on any instance of a class" do
+ example "using a string and a block" do
+ allow_any_instance_of(Object).to receive_message_chain("foo.bar") { :baz }
+ expect(Object.new.foo.bar).to eq(:baz)
+ end
+
+ example "using symbols and a hash" do
+ allow_any_instance_of(Object).to receive_message_chain(:foo, :bar => :baz)
+ expect(Object.new.foo.bar).to eq(:baz)
+ end
+
+ example "using symbols and a block" do
+ allow_any_instance_of(Object).to receive_message_chain(:foo, :bar) { :baz }
+ expect(Object.new.foo.bar).to eq(:baz)
+ end
+end
+
+When I run rspec receive_message_chain_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/.nav b/docs/features/6-0/rspec-rails/.nav
new file mode 100644
index 000000000..b392ea79b
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/.nav
@@ -0,0 +1,39 @@
+- GettingStarted.md (Start from scratch)
+- Generators.md (Generators)
+- Transactions.md
+- directory-structure.feature
+- backtrace-filtering.feature
+- model-specs:
+ - transactional-examples.feature
+- mocks:
+ - mock-model.feature
+ - stub-model.feature
+- controller-specs:
+ - cookies.feature
+ - controller-spec.feature
+ - isolation-from-views.feature
+ - render-views.feature
+ - anonymous-controller.feature
+ - bypass-rescue.feature
+ - engine-routes.feature
+- matchers:
+ - new-record-matcher.feature
+ - render-template-matcher.feature
+ - redirect-to-matcher.feature
+- request-specs:
+ - request-spec.feature
+- feature-specs:
+ - feature-spec.feature
+- view-specs:
+ - view-spec.feature
+ - stub-template.feature
+ - inferred-controller-path.feature
+- helper-specs:
+ - helper-spec.feature
+- mailer-specs:
+ - url-helpers.feature
+- routing-specs:
+ - route-to-matcher.feature
+ - be-routable-matcher.feature
+ - named-routes.feature
+ - engine-routes.feature
diff --git a/docs/features/6-0/rspec-rails/Generators/index.html b/docs/features/6-0/rspec-rails/Generators/index.html
new file mode 100644
index 000000000..d9561c82c
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/Generators/index.html
@@ -0,0 +1,38 @@
+
+
+
+
+Using generators
+
+RSpec spec are normally generated alongside other application components.
+For instance, rails generate model will also generate an RSpec spec file
+for the model.
+
+Note that the generators are there to help you get started, but they are no
+substitute for writing your own examples, and they are only guaranteed to work
+out of the box for with Rails’ defaults.
+
+RSpec generators can also be run independently. For instance,
+rails generate rspec:model widget
+
+will create a new spec file in spec/models/widget_spec.rb.
+
+The same generator pattern is available for all specs:
+
+
+- scaffold
+- model
+- controller
+- helper
+- view
+- mailer
+- integration
+- feature
+- job
+- channel
+- generator
+- mailbox
+- request
+- system
+
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/GettingStarted/index.html b/docs/features/6-0/rspec-rails/GettingStarted/index.html
new file mode 100644
index 000000000..ccddb0694
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/GettingStarted/index.html
@@ -0,0 +1,80 @@
+
+
+
+
+Getting Started
+
+Install Rails 6
+$ gem install rails -v "~> 6.0.0"
+
+Generate an app
+$ rails new example_app
+$ cd example_app
+
+Add rspec-rails to the Gemfile
+$ echo 'gem "rspec-rails", group: [:development, :test]' >> Gemfile
+
+Install the bundle
+$ bundle install
+
+Bootstrap RSpec
+$ rails generate rspec:install
+
+Generate a scaffold
+$ rails generate scaffold Widget name:string
+
+This generates files in the app and spec directories. The files in the
+app directory are generated by Rails, and Rails delegates the generation of
+the files in the spec directory to RSpec.
+
+Run migrations
+$ rails db:migrate && rails db:test:prepare
+
+Run RSpec
+$ rake spec
+
+or
+$ rspec spec --format documentation
+
+If all went well, you should see output ending with:
+29 examples, 0 failures, 2 pending
+
+This output also includes the following controller spec:
+WidgetsController
+ GET index
+ assigns all widgets as @widgets
+ GET show
+ assigns the requested widget as @widget
+ GET new
+ assigns a new widget as @widget
+ GET edit
+ assigns the requested widget as @widget
+ POST create
+ with valid params
+ creates a new Widget
+ assigns a newly created widget as @widget
+ redirects to the created widget
+ with invalid params
+ assigns a newly created but unsaved widget as @widget
+ re-renders the 'new' template
+ PUT update
+ with valid params
+ updates the requested widget
+ assigns the requested widget as @widget
+ redirects to the widget
+ with invalid params
+ assigns the widget as @widget
+ re-renders the 'edit' template
+ DELETE destroy
+ destroys the requested widget
+ redirects to the widgets list
+
+Output like this can help to quickly gain a high level understanding of how an
+object behaves. It also exposes which cases have been specified and which have
+not. Note the balance between the examples for the create and update
+actions. If the redirects to the widget example was missing from one or the
+other, it would be easy to spot.
+
+Take a look at the generated spec/controllers/widgets_controller_spec.rb to
+get a sense of how to organize your specs to generate output like this.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/Transactions/index.html b/docs/features/6-0/rspec-rails/Transactions/index.html
new file mode 100644
index 000000000..d2994533c
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/Transactions/index.html
@@ -0,0 +1,87 @@
+
+
+
+
+Transactions
+
+When you run rails generate rspec:install, the spec/rails_helper.rb file
+includes the following configuration:
+RSpec.configure do |config|
+ config.use_transactional_fixtures = true
+end
+
+The name of this setting is a bit misleading. What it really means in Rails
+is “run every test method within a transaction.” In the context of rspec-rails,
+it means “run every example within a transaction.”
+
+The idea is to start each example with a clean database, create whatever data
+is necessary for that example, and then remove that data by simply rolling back
+the transaction at the end of the example.
+
+Disabling transactions
+
+If you prefer to manage the data yourself, or using another tool like
+database_cleaner to do it for you,
+simply tell RSpec to tell Rails not to manage transactions:
+RSpec.configure do |config|
+ config.use_transactional_fixtures = false
+end
+
+Data created in before(:example) are rolled back
+
+Any data you create in a before(:example) hook will be rolled back at the end of
+the example. This is a good thing because it means that each example is
+isolated from state that would otherwise be left around by the examples that
+already ran. For example:
+describe Widget do
+ before(:example) do
+ @widget = Widget.create
+ end
+
+ it "does something" do
+ expect(@widget).to do_something
+ end
+
+ it "does something else" do
+ expect(@widget).to do_something_else
+ end
+end
+
+The @widget is recreated in each of the two examples above, so each example
+has a different object, and the underlying data is rolled back so the data
+backing the @widget in each example is new.
+
+Data created in before(:context) are not rolled back
+
+before(:context) hooks are invoked before the transaction is opened. You can use
+this to speed things up by creating data once before any example in a group is
+run, however, this introduces a number of complications and you should only do
+this if you have a firm grasp of the implications. Here are a couple of
+guidelines:
+
+
+Be sure to clean up any data in an after(:context) hook:
+before(:context) do
+ @widget = Widget.create!
+end
+
+after(:context) do
+ @widget.destroy
+end
+
+If you don’t do that, you’ll leave data lying around that will eventually
+interfere with other examples.
+Reload the object in a before(:example) hook.
+before(:context) do
+ @widget = Widget.create!
+end
+
+before(:example) do
+ @widget.reload
+end
+
+Even though database updates in each example will be rolled back, the
+ object won’t know about those rollbacks so the object and its backing
+ data can easily get out of sync.
+
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/backtrace-filtering/index.html b/docs/features/6-0/rspec-rails/backtrace-filtering/index.html
new file mode 100644
index 000000000..ee5fc6e0d
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/backtrace-filtering/index.html
@@ -0,0 +1,54 @@
+
+
+
+
+Backtrace filtering
+
+The following configuration setting will filter out lines in backtraces
+ that come from Rails gems in order to reduce the noise in test failure output:
+ RSpec.configure do |config|
+ config.filter_rails_from_backtrace!
+ end
+
+rspec will always show the full backtrace output when run with
+ the --backtrace commandline option.
+
+Background (Using filter_rails_from_backtrace!)
+
+Given a file named “spec/failing_spec.rb” with:
+require "rails_helper"
+
+RSpec.configure do |config|
+ config.filter_rails_from_backtrace!
+end
+
+RSpec.describe "Controller", type: :controller do
+ controller do
+ def index
+ raise "Something went wrong."
+ end
+ end
+
+ describe "GET index" do
+ it "raises an error" do
+ get :index
+ end
+ end
+end
+
+Using the bare rspec command
+
+When I run rspec
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should not contain “activesupport”.
+
+Using rspec --backtrace
+
+When I run rspec --backtrace
+
+Then the output should contain “1 example, 1 failure”
+
+And the output should contain “activesupport”.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/channel-specs/channel-spec/index.html b/docs/features/6-0/rspec-rails/channel-specs/channel-spec/index.html
new file mode 100644
index 000000000..41dda92ad
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/channel-specs/channel-spec/index.html
@@ -0,0 +1,223 @@
+
+
+
+
+Channel specs
+
+Channel specs are marked by type: :channel or if you have set
+ config.infer_spec_type_from_file_location! by placing them in spec/channels.
+
+A channel spec is a thin wrapper for an ActionCable::Channel::TestCase, and includes all
+ of the behavior and assertions that it provides, in addition to RSpec’s own
+ behavior and expectations.
+
+It also includes helpers from ActionCable::Connection::TestCase to make it possible to
+ test connection behavior.
+
+Background
+
+Given action cable testing is available
+
+And a file named “app/channels/chat_channel.rb” with:
+class ChatChannel < ApplicationCable::Channel
+ def subscribed
+ reject unless params[:room_id].present?
+ end
+
+ def speak(data)
+ ActionCable.server.broadcast(
+ "chat_#{params[:room_id]}", text: data['message']
+ )
+ end
+
+ def echo(data)
+ data.delete("action")
+ transmit data
+ end
+end
+
+A simple passing example
+
+Given a file named “spec/channels/chatchannelspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ChatChannel, type: :channel do
+ it "successfully subscribes" do
+ subscribe room_id: 42
+ expect(subscription).to be_confirmed
+ end
+end
+
+When I run rspec spec/channels/chat_channel_spec.rb
+
+Then the example should pass.
+
+Verifying that a subscription is rejected
+
+Given a file named “spec/channels/chatchannelspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ChatChannel, type: :channel do
+ it "rejects subscription" do
+ subscribe room_id: nil
+ expect(subscription).to be_rejected
+ end
+end
+
+When I run rspec spec/channels/chat_channel_spec.rb
+
+Then the example should pass.
+
+Performing actions and checking transmissions
+
+Given a file named “spec/channels/chatchannelspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ChatChannel, type: :channel do
+ it "successfully subscribes" do
+ subscribe room_id: 42
+
+ perform :echo, foo: 'bar'
+ expect(transmissions.last).to eq('foo' => 'bar')
+ end
+end
+
+When I run rspec spec/channels/chat_channel_spec.rb
+
+Then the example should pass.
+
+A successful connection with url params
+
+Given a file named “app/channels/application_cable/connection.rb” with:
+class ApplicationCable::Connection < ActionCable::Connection::Base
+ identified_by :user_id
+
+ def connect
+ self.user_id = request.params[:user_id]
+ reject_unauthorized_connection unless user_id.present?
+ end
+end
+
+And a file named “spec/channels/connection_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe ApplicationCable::Connection, type: :channel do
+ it "successfully connects" do
+ connect "/cable?user_id=323"
+ expect(connection.user_id).to eq "323"
+ end
+end
+
+When I run rspec spec/channels/connection_spec.rb
+
+Then the example should pass.
+
+A successful connection with cookies
+
+Given a file named “app/channels/application_cable/connection.rb” with:
+class ApplicationCable::Connection < ActionCable::Connection::Base
+ identified_by :user_id
+
+ def connect
+ self.user_id = cookies.signed[:user_id]
+ reject_unauthorized_connection unless user_id.present?
+ end
+end
+
+And a file named “spec/channels/connection_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe ApplicationCable::Connection, type: :channel do
+ it "successfully connects" do
+ cookies.signed[:user_id] = "324"
+
+ connect "/cable"
+ expect(connection.user_id).to eq "324"
+ end
+end
+
+When I run rspec spec/channels/connection_spec.rb
+
+Then the example should pass.
+
+A successful connection with headers
+
+Given a file named “app/channels/application_cable/connection.rb” with:
+class ApplicationCable::Connection < ActionCable::Connection::Base
+ identified_by :user_id
+
+ def connect
+ self.user_id = request.headers["x-user-id"]
+ reject_unauthorized_connection unless user_id.present?
+ end
+end
+
+And a file named “spec/channels/connection_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe ApplicationCable::Connection, type: :channel do
+ it "successfully connects" do
+ connect "/cable", headers: { "X-USER-ID" => "325" }
+ expect(connection.user_id).to eq "325"
+ end
+end
+
+When I run rspec spec/channels/connection_spec.rb
+
+Then the example should pass.
+
+A rejected connection
+
+Given a file named “app/channels/application_cable/connection.rb” with:
+class ApplicationCable::Connection < ActionCable::Connection::Base
+ identified_by :user_id
+
+ def connect
+ self.user_id = request.params[:user_id]
+ reject_unauthorized_connection unless user_id.present?
+ end
+end
+
+And a file named “spec/channels/connection_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe ApplicationCable::Connection, type: :channel do
+ it "rejects connection" do
+ expect { connect "/cable?user_id=" }.to have_rejected_connection
+ end
+end
+
+When I run rspec spec/channels/connection_spec.rb
+
+Then the example should pass.
+
+Disconnect a connection
+
+Given a file named “app/channels/application_cable/connection.rb” with:
+class ApplicationCable::Connection < ActionCable::Connection::Base
+ identified_by :user_id
+
+ def connect
+ self.user_id = request.params[:user_id]
+ reject_unauthorized_connection unless user_id.present?
+ end
+
+ def disconnect
+ $stdout.puts "User #{user_id} disconnected"
+ end
+end
+
+And a file named “spec/channels/connection_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe ApplicationCable::Connection, type: :channel do
+ it "disconnects" do
+ connect "/cable?user_id=42"
+ expect { disconnect }.to output(/User 42 disconnected/).to_stdout
+ end
+end
+
+When I run rspec spec/channels/connection_spec.rb
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/channel-specs/index.html b/docs/features/6-0/rspec-rails/channel-specs/index.html
new file mode 100644
index 000000000..4b1b3e0f0
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/channel-specs/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Channel specs
Topics
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/controller-specs/anonymous-controller/index.html b/docs/features/6-0/rspec-rails/controller-specs/anonymous-controller/index.html
new file mode 100644
index 000000000..94a5eb625
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/controller-specs/anonymous-controller/index.html
@@ -0,0 +1,564 @@
+
+
+
+
+Using an anonymous controller
+
+Use the controller method to define an anonymous controller that will
+ inherit from the described class. This is useful for specifying behavior like
+ global error handling.
+
+To specify a different base class you can pass the class explicitly to the
+ controller method:
+ controller(BaseController)
+
+You can also disable base type inference, in which case anonymous controllers
+ will inherit from ApplicationController instead of the described class by
+ default:
+ RSpec.configure do |c|
+ c.infer_base_class_for_anonymous_controllers = false
+ end
+
+ RSpec.describe BaseController, type: :controller do
+ controller do
+ def index; end
+
+ # this normally creates an anonymous `BaseController` subclass,
+ # however since `infer_base_class_for_anonymous_controllers` is
+ # disabled, it creates a subclass of `ApplicationController`
+ end
+ end
+
+Specify error handling in ApplicationController with redirect
+
+Given a file named “spec/controllers/applicationcontrollerspec.rb” with:
+require "rails_helper"
+
+class ApplicationController < ActionController::Base
+ class AccessDenied < StandardError; end
+
+ rescue_from AccessDenied, :with => :access_denied
+
+private
+
+ def access_denied
+ redirect_to "/401.html"
+ end
+end
+
+RSpec.describe ApplicationController, type: :controller do
+ controller do
+ def index
+ raise ApplicationController::AccessDenied
+ end
+ end
+
+ describe "handling AccessDenied exceptions" do
+ it "redirects to the /401.html page" do
+ get :index
+ expect(response).to redirect_to("/401.html")
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Specify error handling in ApplicationController with render
+
+Given a file named “spec/controllers/applicationcontrollerspec.rb” with:
+require "rails_helper"
+
+class ApplicationController < ActionController::Base
+ class AccessDenied < StandardError; end
+
+ rescue_from AccessDenied, :with => :access_denied
+
+private
+
+ def access_denied
+ render "errors/401"
+ end
+end
+
+RSpec.describe ApplicationController, type: :controller do
+ controller do
+ def index
+ raise ApplicationController::AccessDenied
+ end
+ end
+
+ describe "handling AccessDenied exceptions" do
+ it "renders the errors/401 template" do
+ get :index
+ expect(response).to render_template("errors/401")
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Specify error handling in a subclass
+
+Given a file named “spec/controllers/applicationcontrollersubclass_spec.rb” with:
+require "rails_helper"
+
+class ApplicationController < ActionController::Base
+ class AccessDenied < StandardError; end
+end
+
+class FoosController < ApplicationController
+
+ rescue_from ApplicationController::AccessDenied,
+ :with => :access_denied
+
+private
+
+ def access_denied
+ redirect_to "/401.html"
+ end
+end
+
+RSpec.describe FoosController, type: :controller do
+ controller(FoosController) do
+ def index
+ raise ApplicationController::AccessDenied
+ end
+ end
+
+ describe "handling AccessDenied exceptions" do
+ it "redirects to the /401.html page" do
+ get :index
+ expect(response).to redirect_to("/401.html")
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Infer base class from the described class
+
+Given a file named “spec/controllers/baseclasscanbeinferred_spec.rb” with:
+require "rails_helper"
+
+class ApplicationController < ActionController::Base; end
+
+class FoosController < ApplicationController; end
+
+RSpec.describe FoosController, type: :controller do
+ controller do
+ def index
+ render :plain => "Hello World"
+ end
+ end
+
+ it "creates anonymous controller derived from FoosController" do
+ expect(controller).to be_a_kind_of(FoosController)
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Use name and controller_name from the described class
+
+Given a file named “spec/controllers/getnameandcontrollernamefromdescribedclassspec.rb” with:
+require "rails_helper"
+
+class ApplicationController < ActionController::Base; end
+class FoosController < ApplicationController; end
+
+RSpec.describe "Access controller names", type: :controller do
+ controller FoosController do
+ def index
+ @name = self.class.name
+ @controller_name = controller_name
+ render :plain => "Hello World"
+ end
+ end
+
+ before do
+ get :index
+ end
+
+ it "gets the class name as described" do
+ expect(assigns[:name]).to eq('FoosController')
+ end
+
+ it "gets the controller_name as described" do
+ expect(assigns[:controller_name]).to eq('foos')
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Invoke around_filter and around_action in base class
+
+Given a file named “spec/controllers/applicationcontrolleraroundfilterspec.rb” with:
+require "rails_helper"
+
+class ApplicationController < ActionController::Base
+ around_action :an_around_filter
+
+ def an_around_filter
+ @callback_invoked = true
+ yield
+ end
+end
+
+RSpec.describe ApplicationController, type: :controller do
+ controller do
+ def index
+ render :plain => ""
+ end
+ end
+
+ it "invokes the callback" do
+ get :index
+
+ expect(assigns[:callback_invoked]).to be_truthy
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Anonymous controllers only create resource routes
+
+Given a file named “spec/controllers/applicationcontrollerspec.rb” with:
+require "rails_helper"
+
+if defined?(ActionController::UrlGenerationError)
+ ExpectedRoutingError = ActionController::UrlGenerationError
+else
+ ExpectedRoutingError = ActionController::RoutingError
+end
+
+RSpec.describe ApplicationController, type: :controller do
+ controller do
+ def index
+ render :plain => "index called"
+ end
+
+ def create
+ render :plain => "create called"
+ end
+
+ def new
+ render :plain => "new called"
+ end
+
+ def show
+ render :plain => "show called"
+ end
+
+ def edit
+ render :plain => "edit called"
+ end
+
+ def update
+ render :plain => "update called"
+ end
+
+ def destroy
+ render :plain => "destroy called"
+ end
+
+ def willerror
+ render :plain => "will not render"
+ end
+ end
+
+ describe "#index" do
+ it "responds to GET" do
+ get :index
+ expect(response.body).to eq "index called"
+ end
+
+ it "also responds to POST" do
+ post :index
+ expect(response.body).to eq "index called"
+ end
+
+ it "also responds to PUT" do
+ put :index
+ expect(response.body).to eq "index called"
+ end
+
+ it "also responds to DELETE" do
+ delete :index
+ expect(response.body).to eq "index called"
+ end
+ end
+
+ describe "#create" do
+ it "responds to POST" do
+ post :create
+ expect(response.body).to eq "create called"
+ end
+
+ # And the rest...
+ %w{get post put delete}.each do |calltype|
+ it "responds to #{calltype}" do
+ send(calltype, :create)
+ expect(response.body).to eq "create called"
+ end
+ end
+ end
+
+ describe "#new" do
+ it "responds to GET" do
+ get :new
+ expect(response.body).to eq "new called"
+ end
+
+ # And the rest...
+ %w{get post put delete}.each do |calltype|
+ it "responds to #{calltype}" do
+ send(calltype, :new)
+ expect(response.body).to eq "new called"
+ end
+ end
+ end
+
+ describe "#edit" do
+ it "responds to GET" do
+ get :edit, :params => { :id => "anyid" }
+ expect(response.body).to eq "edit called"
+ end
+
+ it "requires the :id parameter" do
+ expect { get :edit }.to raise_error(ExpectedRoutingError)
+ end
+
+ # And the rest...
+ %w{get post put delete}.each do |calltype|
+ it "responds to #{calltype}" do
+ send(calltype, :edit, :params => {:id => "anyid"})
+ expect(response.body).to eq "edit called"
+ end
+ end
+ end
+
+ describe "#show" do
+ it "responds to GET" do
+ get :show, :params => { :id => "anyid" }
+ expect(response.body).to eq "show called"
+ end
+
+ it "requires the :id parameter" do
+ expect { get :show }.to raise_error(ExpectedRoutingError)
+ end
+
+ # And the rest...
+ %w{get post put delete}.each do |calltype|
+ it "responds to #{calltype}" do
+ send(calltype, :show, :params => {:id => "anyid"})
+ expect(response.body).to eq "show called"
+ end
+ end
+ end
+
+ describe "#update" do
+ it "responds to PUT" do
+ put :update, :params => { :id => "anyid" }
+ expect(response.body).to eq "update called"
+ end
+
+ it "requires the :id parameter" do
+ expect { put :update }.to raise_error(ExpectedRoutingError)
+ end
+
+ # And the rest...
+ %w{get post put delete}.each do |calltype|
+ it "responds to #{calltype}" do
+ send(calltype, :update, :params => {:id => "anyid"})
+ expect(response.body).to eq "update called"
+ end
+ end
+ end
+
+ describe "#destroy" do
+ it "responds to DELETE" do
+ delete :destroy, :params => { :id => "anyid" }
+ expect(response.body).to eq "destroy called"
+ end
+
+ it "requires the :id parameter" do
+ expect { delete :destroy }.to raise_error(ExpectedRoutingError)
+ end
+
+ # And the rest...
+ %w{get post put delete}.each do |calltype|
+ it "responds to #{calltype}" do
+ send(calltype, :destroy, :params => {:id => "anyid"})
+ expect(response.body).to eq "destroy called"
+ end
+ end
+ end
+
+ describe "#willerror" do
+ it "cannot be called" do
+ expect { get :willerror }.to raise_error(ExpectedRoutingError)
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Draw custom routes for anonymous controllers
+
+Given a file named “spec/controllers/applicationcontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ApplicationController, type: :controller do
+ controller do
+ def custom
+ render :plain => "custom called"
+ end
+ end
+
+ specify "manually draw the route to request a custom action" do
+ routes.draw { get "custom" => "anonymous#custom" }
+
+ get :custom
+ expect(response.body).to eq "custom called"
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Draw custom routes for anonymous controllers which don’t inherit from application controller
+
+Given a file named “spec/controllers/othercontrollerspec.rb” with:
+require "rails_helper"
+class OtherController < ActionController::Base
+end
+
+RSpec.describe OtherController, type: :controller do
+ controller do
+ def custom
+ render :plain => "custom called"
+ end
+ end
+
+ specify "manually draw the route to request a custom action" do
+ routes.draw { get "custom" => "other#custom" }
+
+ get :custom
+ expect(response.body).to eq "custom called"
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Draw custom routes for defined controllers
+
+Given a file named “spec/controllers/applicationcontrollerspec.rb” with:
+require "rails_helper"
+
+class FoosController < ApplicationController; end
+
+RSpec.describe ApplicationController, type: :controller do
+ controller FoosController do
+ def custom
+ render :plain => "custom called"
+ end
+ end
+
+ specify "manually draw the route to request a custom action" do
+ routes.draw { get "custom" => "foos#custom" }
+
+ get :custom
+ expect(response.body).to eq "custom called"
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Works with namespaced controllers
+
+Given a file named “spec/controllers/namespacedcontrollerspec.rb” with:
+require "rails_helper"
+
+class ApplicationController < ActionController::Base; end
+
+module Outer
+ module Inner
+ class FoosController < ApplicationController; end
+ end
+end
+
+RSpec.describe Outer::Inner::FoosController, type: :controller do
+ controller do
+ def index
+ @name = self.class.name
+ @controller_name = controller_name
+ render :plain => "Hello World"
+ end
+ end
+
+ it "creates anonymous controller derived from the namespace" do
+ expect(controller).to be_a_kind_of(Outer::Inner::FoosController)
+ end
+
+ it "gets the class name as described" do
+ expect{ get :index }.to change{
+ assigns[:name]
+ }.to eq('Outer::Inner::FoosController')
+ end
+
+ it "gets the controller_name as described" do
+ expect{ get :index }.to change{
+ assigns[:controller_name]
+ }.to eq('foos')
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Refer to application routes in the controller under test
+
+Given a file named “spec/controllers/applicationcontrollerspec.rb” with:
+require "rails_helper"
+
+Rails.application.routes.draw do
+ match "/login" => "sessions#new", :as => "login", :via => "get"
+end
+
+RSpec.describe ApplicationController, type: :controller do
+ controller do
+ def index
+ redirect_to login_url
+ end
+ end
+
+ it "redirects to the login page" do
+ get :index
+ expect(response).to redirect_to("/login")
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/controller-specs/bypass-rescue/index.html b/docs/features/6-0/rspec-rails/controller-specs/bypass-rescue/index.html
new file mode 100644
index 000000000..5d29f7efd
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/controller-specs/bypass-rescue/index.html
@@ -0,0 +1,80 @@
+
+
+
+
+Using bypass_rescue
+
+Use bypass_rescue to bypass both Rails’ default handling of errors in
+ controller actions, and any custom handling declared with a rescue_from
+ statement.
+
+This lets you specify details of the exception being raised, regardless of
+ how it might be handled upstream.
+
+Background
+
+Given a file named “spec/controllers/gadgetscontrollerspec_context.rb” with:
+class AccessDenied < StandardError; end
+
+class ApplicationController < ActionController::Base
+ rescue_from AccessDenied, :with => :access_denied
+
+ private
+
+ def access_denied
+ redirect_to "/401.html"
+ end
+end
+
+Standard exception handling using rescue_from
+
+Given a file named “spec/controllers/gadgetscontrollerspec.rb” with:
+require "rails_helper"
+
+require 'controllers/gadgets_controller_spec_context'
+
+RSpec.describe GadgetsController, type: :controller do
+ before do
+ def controller.index
+ raise AccessDenied
+ end
+ end
+
+ describe "index" do
+ it "redirects to the /401.html page" do
+ get :index
+ expect(response).to redirect_to("/401.html")
+ end
+ end
+end
+
+When I run rspec spec/controllers/gadgets_controller_spec.rb
+
+Then the examples should all pass.
+
+Bypass rescue_from handling with bypass_rescue
+
+Given a file named “spec/controllers/gadgetscontrollerspec.rb” with:
+require "rails_helper"
+
+require 'controllers/gadgets_controller_spec_context'
+
+RSpec.describe GadgetsController, type: :controller do
+ before do
+ def controller.index
+ raise AccessDenied
+ end
+ end
+
+ describe "index" do
+ it "raises AccessDenied" do
+ bypass_rescue
+ expect { get :index }.to raise_error(AccessDenied)
+ end
+ end
+end
+
+When I run rspec spec/controllers/gadgets_controller_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/controller-specs/controller-spec/index.html b/docs/features/6-0/rspec-rails/controller-specs/controller-spec/index.html
new file mode 100644
index 000000000..276284cdf
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/controller-specs/controller-spec/index.html
@@ -0,0 +1,88 @@
+
+
+
+
+Controller specs
+
+A simple passing example
+
+Given a file named “spec/controllers/widgetscontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe WidgetsController, type: :controller do
+ describe "GET index" do
+ it "has a 200 status code" do
+ get :index
+ expect(response.status).to eq(200)
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the example should pass.
+
+A controller is exposed to global before hooks
+
+Given a file named “spec/controllers/widgetscontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.configure {|c| c.before { expect(controller).not_to be_nil }}
+
+RSpec.describe WidgetsController, type: :controller do
+ describe "GET index" do
+ it "doesn't matter" do
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the example should pass.
+
+Setting a different content type for example json (request type)
+
+Given a file named “spec/controllers/widgetscontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe WidgetsController, type: :controller do
+ describe "responds to" do
+ it "responds to html by default" do
+ post :create, :params => { :widget => { :name => "Any Name" } }
+ expect(response.content_type).to eq "text/html; charset=utf-8"
+ end
+
+ it "responds to custom formats when provided in the params" do
+ post :create, :params => { :widget => { :name => "Any Name" }, :format => :json }
+ expect(response.content_type).to eq "application/json; charset=utf-8"
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the example should pass.
+
+Setting a different media type for example json (request type)
+
+Given a file named “spec/controllers/widgetscontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe WidgetsController, type: :controller do
+ describe "responds to" do
+ it "responds to html by default" do
+ post :create, :params => { :widget => { :name => "Any Name" } }
+ expect(response.media_type).to eq "text/html"
+ end
+
+ it "responds to custom formats when provided in the params" do
+ post :create, :params => { :widget => { :name => "Any Name" }, :format => :json }
+ expect(response.media_type).to eq "application/json"
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/controller-specs/cookies/index.html b/docs/features/6-0/rspec-rails/controller-specs/cookies/index.html
new file mode 100644
index 000000000..a40658d08
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/controller-specs/cookies/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+Cookies
+
+There are different ways to make assertions on cookies from controller specs,
+ but we recommend using the cookies method as set out below.
+
+You can use strings or symbols to fetch or set your cookies because the cookies
+ method supports indifferent access.
+
+Testing cookie’s value cleared in controller
+
+Given a file named “spec/controllers/applicationcontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ApplicationController, type: :controller do
+ controller do
+ def clear_cookie
+ cookies.delete(:user_name)
+ head :ok
+ end
+ end
+
+ before do
+ routes.draw { get "clear_cookie" => "anonymous#clear_cookie" }
+ end
+
+ it "clear cookie's value 'user_name'" do
+ cookies[:user_name] = "Sam"
+
+ get :clear_cookie
+
+ expect(cookies[:user_name]).to eq nil
+ end
+end
+
+When I run rspec spec
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/controller-specs/engine-routes/index.html b/docs/features/6-0/rspec-rails/controller-specs/engine-routes/index.html
new file mode 100644
index 000000000..3c76d5b06
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/controller-specs/engine-routes/index.html
@@ -0,0 +1,56 @@
+
+
+
+
+Engine routes for controllers
+
+Controller specs can specify the routeset that will be used for the example
+ group. This is most useful when testing Rails engines.
+
+Specify engine routes
+
+Given a file named “spec/controllers/widgetscontrollerspec.rb” with:
+require "rails_helper"
+
+# A very simple Rails engine
+module MyEngine
+ class Engine < ::Rails::Engine
+ isolate_namespace MyEngine
+ end
+
+ Engine.routes.draw do
+ resources :widgets, :only => [:show] do
+ get :random, :on => :collection
+ end
+ end
+
+ class WidgetsController < ::ActionController::Base
+ def random
+ @random_widget = Widget.all.shuffle.first
+ redirect_to widget_path(@random_widget)
+ end
+
+ def show
+ @widget = Widget.find(params[:id])
+ render :text => @widget.name
+ end
+ end
+end
+
+RSpec.describe MyEngine::WidgetsController, type: :controller do
+ routes { MyEngine::Engine.routes }
+
+ it "redirects to a random widget" do
+ widget1 = Widget.create!(:name => "Widget 1")
+ widget2 = Widget.create!(:name => "Widget 2")
+
+ get :random
+ expect(response).to be_redirect
+ expect(response).to redirect_to(assigns(:random_widget))
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/controller-specs/index.html b/docs/features/6-0/rspec-rails/controller-specs/index.html
new file mode 100644
index 000000000..59ec23b31
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/controller-specs/index.html
@@ -0,0 +1,90 @@
+
+
+
+
+Controller specs
+
+Controller specs are marked by type: :controller or if you have set
+config.infer_spec_type_from_file_location! by placing them in spec/controllers.
+
+A controller spec is an RSpec wrapper for a Rails functional test
+(ActionController::TestCase::Behavior).
+It allows you to simulate a single http request in each example, and then
+specify expected outcomes such as:
+
+
+- rendered templates
+- redirects
+- instance variables assigned in the controller to be shared with the view
+- cookies sent back with the response
+
+
+To specify outcomes, you can use:
+
+
+- standard rspec matchers (
expect(response.status).to eq(200))
+- standard test/unit assertions (
assert_equal 200, response.status)
+- rails assertions (
assert_response 200)
+rails-specific matchers:
+
+
+expect(response).to render_template(:new) # wraps assert_template
+
+
+redirect_to
+
+expect(response).to redirect_to(location) # wraps assert_redirected_to
+
+
+expect(response).to have_http_status(:created)
+
+
+be_a_new
+
+expect(assigns(:widget)).to be_a_new(Widget)
+
+
+
+Examples
+RSpec.describe TeamsController do
+ describe "GET index" do
+ it "assigns @teams" do
+ team = Team.create
+ get :index
+ expect(assigns(:teams)).to eq([team])
+ end
+
+ it "renders the index template" do
+ get :index
+ expect(response).to render_template("index")
+ end
+ end
+end
+
+Views
+
+
+- by default, views are not rendered. See
+views are stubbed by default and
+render_views for details.
+
+
+Headers
+
+We encourage you to use request specs if you want to set headers in your call. If you still want to use controller specs with custom http headers you can use request.headers:
+require "rails_helper"
+
+RSpec.describe TeamsController, type: :controller do
+ describe "GET index" do
+ it "returns a 200" do
+ request.headers["Authorization"] = "foo"
+ get :show
+ expect(response).to have_http_status(:ok)
+ end
+ end
+end
+
Topics
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/controller-specs/isolation-from-views/index.html b/docs/features/6-0/rspec-rails/controller-specs/isolation-from-views/index.html
new file mode 100644
index 000000000..acc351e1a
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/controller-specs/isolation-from-views/index.html
@@ -0,0 +1,106 @@
+
+
+
+
+Views are stubbed by default
+
+By default, controller specs stub views with a template that renders an empty
+ string instead of the views in the app. This allows you specify which view
+ template an action should try to render regardless of whether the template
+ compiles cleanly.
+
+NOTE: unlike rspec-rails-1.x, the real template must exist.
+
+Expect a template that is rendered by controller action (passes)
+
+Given a file named “spec/controllers/widgetscontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe WidgetsController, type: :controller do
+ describe "index" do
+ it "renders the index template" do
+ get :index
+ expect(response).to render_template("index")
+ expect(response.body).to eq ""
+ end
+ it "renders the widgets/index template" do
+ get :index
+ expect(response).to render_template("widgets/index")
+ expect(response.body).to eq ""
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Expect a template that is not rendered by controller action (fails)
+
+Given a file named “spec/controllers/widgetscontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe WidgetsController, type: :controller do
+ describe "index" do
+ it "renders the 'new' template" do
+ get :index
+ expect(response).to render_template("new")
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the output should contain “1 example, 1 failure”.
+
+Expect empty templates to render when view path is changed at runtime (passes)
+
+Given a file named “spec/controllers/thingscontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ThingsController, type: :controller do
+ describe "custom_action" do
+ it "renders an empty custom_action template" do
+ controller.prepend_view_path 'app/views'
+ controller.append_view_path 'app/views'
+ get :custom_action
+ expect(response).to render_template("custom_action")
+ expect(response.body).to eq ""
+ end
+ end
+end
+
+Given a file named “app/controllers/things_controller.rb” with:
+class ThingsController < ActionController::Base
+ layout false
+ def custom_action
+ end
+end
+
+Given a file named “app/views/things/custom_action.html.erb” with:
+
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Expect a template to render the real template with render_views when view path is changed at runtime
+
+Given a file named “spec/controllers/thingscontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ThingsController, type: :controller do
+ render_views
+
+ it "renders the real custom_action template" do
+ controller.prepend_view_path 'app/views'
+ get :custom_action
+ expect(response).to render_template("custom_action")
+ expect(response.body).to match(/template for a custom action/)
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/controller-specs/render-views/index.html b/docs/features/6-0/rspec-rails/controller-specs/render-views/index.html
new file mode 100644
index 000000000..09a214a54
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/controller-specs/render-views/index.html
@@ -0,0 +1,119 @@
+
+
+
+
+Using render_views
+
+You can tell a controller example group to render views with the
+ render_views declaration in any individual group, or globally.
+
+Use render_views directly in a single group
+
+Given a file named “spec/controllers/widgetscontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe WidgetsController, type: :controller do
+ render_views
+
+ describe "GET index" do
+ it "has a widgets related heading" do
+ get :index
+ expect(response.body).to match /<h1>.*widgets/im
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Use render_views on and off in nested groups
+
+Given a file named “spec/controllers/widgetscontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe WidgetsController, type: :controller do
+ context "with render_views" do
+ render_views
+
+ describe "GET index" do
+ it "renders the actual template" do
+ get :index
+ expect(response.body).to match /<h1>.*widgets/im
+ end
+ end
+
+ context "with render_views(false) nested in a group with render_views" do
+ render_views false
+
+ describe "GET index" do
+ it "renders the RSpec generated template" do
+ get :index
+ expect(response.body).to eq("")
+ end
+ end
+ end
+ end
+
+ context "without render_views" do
+ describe "GET index" do
+ it "renders the RSpec generated template" do
+ get :index
+ expect(response.body).to eq("")
+ end
+ end
+ end
+
+ context "with render_views again" do
+ render_views
+
+ describe "GET index" do
+ it "renders the actual template" do
+ get :index
+ expect(response.body).to match /<h1>.*widgets/im
+ end
+ end
+ end
+end
+
+When I run rspec spec --order default --format documentation
+
+Then the output should contain:
+WidgetsController
+ with render_views
+ GET index
+ renders the actual template
+ with render_views(false) nested in a group with render_views
+ GET index
+ renders the RSpec generated template
+ without render_views
+ GET index
+ renders the RSpec generated template
+ with render_views again
+ GET index
+ renders the actual template
+
+Use render_views globally
+
+Given a file named “spec/support/render_views.rb” with:
+RSpec.configure do |config|
+ config.render_views
+end
+
+And a file named “spec/controllers/widgetscontrollerspec.rb” with:
+require "rails_helper"
+require "support/render_views"
+
+RSpec.describe WidgetsController, type: :controller do
+ describe "GET index" do
+ it "renders the index template" do
+ get :index
+ expect(response.body).to match /<h1>.*widgets/im
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/controller-specs/setting-request-headers/index.html b/docs/features/6-0/rspec-rails/controller-specs/setting-request-headers/index.html
new file mode 100644
index 000000000..833a9b590
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/controller-specs/setting-request-headers/index.html
@@ -0,0 +1,55 @@
+
+
+
+
+Setting request headers
+
+We recommend you to switch to request specs instead of controller specs if you want to set
+ headers in your call. If you still want to set headers in controller specs, you can use
+ request.headers as mentioned below.
+
+Setting a header value in a controller spec
+
+Given a file named “spec/controllers/applicationcontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ApplicationController, type: :controller do
+ controller do
+ def show
+ if request.headers["Authorization"] == "foo"
+ head :ok
+ else
+ head :forbidden
+ end
+ end
+ end
+
+ before do
+ routes.draw { get "show" => "anonymous#show" }
+ end
+
+ context "valid Authorization header" do
+ it "returns a 200" do
+ request.headers["Authorization"] = "foo"
+
+ get :show
+
+ expect(response).to have_http_status(:ok)
+ end
+ end
+
+ context "invalid Authorization header" do
+ it "returns a 403" do
+ request.headers["Authorization"] = "bar"
+
+ get :show
+
+ expect(response).to have_http_status(:forbidden)
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/directory-structure/index.html b/docs/features/6-0/rspec-rails/directory-structure/index.html
new file mode 100644
index 000000000..b9f9edbd0
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/directory-structure/index.html
@@ -0,0 +1,208 @@
+
+
+
+
+The directory structure
+
+Specs are usually placed in a canonical directory structure that describes
+ their purpose:
+
+
+Model specs reside in the spec/models directory
+Controller specs reside in the spec/controllers directory
+Request specs reside in the spec/requests directory. The directory can also be named integration or api.
+Feature specs reside in the spec/features directory
+View specs reside in the spec/views directory
+Helper specs reside in the spec/helpers directory
+Mailer specs reside in the spec/mailers directory
+Routing specs reside in the spec/routing directory
+Job specs reside in the spec/jobs directory
+System specs reside in the spec/system directory
+
+
+Application developers are free to use a different directory structure. In
+ order to include the correct rspec-rails support functions, the specs need
+ to have the appropriate corresponding metadata :type value:
+
+
+- Model specs:
type: :model
+- Controller specs:
type: :controller
+- Request specs:
type: :request
+- Feature specs:
type: :feature
+- View specs:
type: :view
+- Helper specs:
type: :helper
+- Mailer specs:
type: :mailer
+- Routing specs:
type: :routing
+- Job specs:
type: :job
+- System specs:
type: :system
+
+
+For example, say the spec for the ThingsController is located in
+ spec/legacy/things_controller_spec.rb. Simply tag the spec’s
+ RSpec.describe block with the type: :controller metadata:
+ # spec/legacy/things_controller_spec.rb
+ RSpec.describe ThingsController, type: :controller do
+ describe "GET index" do
+ # Examples
+ end
+ end
+
+Note: Standard RSpec specs do not require any additional metadata by
+ default.
+
+Check out the rspec-core documentation on using metadata for more details.
+
+Automatically Adding Metadata
+
+RSpec versions before 3.0.0 automatically added metadata to specs based on
+ their location on the filesystem. This was both confusing to new users and not
+ desirable for some veteran users.
+
+This behaviour must be explicitly enabled:
+ # spec/rails_helper.rb
+ RSpec.configure do |config|
+ config.infer_spec_type_from_file_location!
+ end
+
+Since this assumed behavior is so prevalent in tutorials, the default
+ configuration generated by rails generate rspec:install enables this.
+
+If you follow the above listed canonical directory structure and have
+ configured infer_spec_type_from_file_location!, RSpec will automatically
+ include the correct support functions for each type.
+
+If you want to set metadata for a custom directory that doesn’t follow fit the canonical structure above, you can do the following:
+ # set `:type` for serializers directory
+ RSpec.configure do |config|
+ config.define_derived_metadata(:file_path => Regexp.new('/spec/serializers/')) do |metadata|
+ metadata[:type] = :serializer
+ end
+ end
+
+Tips on Spec Location
+
+It is suggested that the spec/ directory structure generally mirror both
+ app/ and lib/. This makes it easy to locate corresponding code and spec
+ files.
+
+Example:
+ app
+ ├── controllers
+ │ ├── application_controller.rb
+ │ └── books_controller.rb
+ ├── helpers
+ │ ├── application_helper.rb
+ │ └── books_helper.rb
+ ├── models
+ │ ├── author.rb
+ │ └── book.rb
+ └── views
+ ├── books
+ └── layouts
+ lib
+ ├── country_map.rb
+ ├── development_mail_interceptor.rb
+ ├── enviroment_mail_interceptor.rb
+ └── tasks
+ └── irc.rake
+ spec
+ ├── controllers
+ │ └── books_controller_spec.rb
+ ├── country_map_spec.rb
+ ├── features
+ │ └── tracking_book_delivery_spec.rb
+ ├── helpers
+ │ └── books_helper_spec.rb
+ ├── models
+ │ ├── author_spec.rb
+ │ └── book_spec.rb
+ ├── rails_helper.rb
+ ├── requests
+ │ └── books_spec.rb
+ ├── routing
+ │ └── books_routing_spec.rb
+ ├── spec_helper.rb
+ ├── tasks
+ │ └── irc_spec.rb
+ └── views
+ └── books
+
+Standard Rails specs must specify the :type metadata
+
+Given a file named “spec/functional/widgetscontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe WidgetsController, type: :controller do
+ it "responds successfully" do
+ get :index
+ expect(response.status).to eq(200)
+ end
+end
+
+When I run rspec spec
+
+Then the example should pass.
+
+Non-rails related specs do not require :type metadata by default
+
+Given a file named “spec/ledger/entry_spec.rb” with:
+require "spec_helper"
+
+Entry = Struct.new(:description, :us_cents)
+
+RSpec.describe Entry do
+ it "has a description" do
+ is_expected.to respond_to(:description)
+ end
+end
+
+When I run rspec spec
+
+Then the example should pass.
+
+Inferring spec type from the file location adds the appropriate metadata
+
+Given a file named “spec/controllers/widgetscontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.configure do |config|
+ config.infer_spec_type_from_file_location!
+end
+
+RSpec.describe WidgetsController do
+ it "responds successfully" do
+ get :index
+ expect(response.status).to eq(200)
+ end
+end
+
+When I run rspec spec
+
+Then the example should pass.
+
+Specs in canonical directories can override their inferred types
+
+Given a file named “spec/routing/duckduckroutingspec.rb” with:
+require "rails_helper"
+
+Rails.application.routes.draw do
+ get "/example" => redirect("http://example.com")
+end
+
+RSpec.configure do |config|
+ config.infer_spec_type_from_file_location!
+end
+
+# Due to limitations in the Rails routing test framework, routes that
+# perform redirects must actually be tested via request specs
+RSpec.describe "/example", type: :request do
+ it "redirects to example.com" do
+ get "/example"
+ expect(response).to redirect_to("http://example.com")
+ end
+end
+
+When I run rspec spec
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/feature-specs/feature-spec/index.html b/docs/features/6-0/rspec-rails/feature-specs/feature-spec/index.html
new file mode 100644
index 000000000..205445c39
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/feature-specs/feature-spec/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+Feature specs
+
+Feature specs are high-level tests meant to exercise slices of functionality
+ through an application. They should drive the application only via its external
+ interface, usually web pages.
+
+Feature specs are marked by type: :feature or if you have set
+ config.infer_spec_type_from_file_location! by placing them in
+ spec/features.
+
+Feature specs require the Capybara gem, version 2.13.0 or later.
+ Refer to the capybara API documentation for more information on the methods and matchers that can be
+ used in feature specs. Capybara is intended to simulate browser requests with HTTP. It will primarily send HTML content.
+
+The feature and scenario DSL correspond to describe and it, respectively.
+ These methods are simply aliases that allow feature specs to read more as
+ customer and acceptance tests. When capybara is required it sets
+ type: :feature automatically for you.
+
+Specify creating a Widget by driving the application with capybara
+
+Given a file named “spec/features/widgetmanagementspec.rb” with:
+require "rails_helper"
+
+RSpec.feature "Widget management", type: :feature do
+ scenario "User creates a new widget" do
+ visit "/widgets/new"
+
+ click_button "Create Widget"
+
+ expect(page).to have_text("Widget was successfully created.")
+ end
+end
+
+When I run rspec spec/features/widget_management_spec.rb
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/feature-specs/index.html b/docs/features/6-0/rspec-rails/feature-specs/index.html
new file mode 100644
index 000000000..2d3a3dbe3
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/feature-specs/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Feature specs
Topics
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/file-fixture/index.html b/docs/features/6-0/rspec-rails/file-fixture/index.html
new file mode 100644
index 000000000..5cf19d6b3
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/file-fixture/index.html
@@ -0,0 +1,39 @@
+
+
+
+
+Using file_fixture
+
+Rails 5 adds simple access to sample files called file fixtures.
+ File fixtures are normal files stored in spec/fixtures/files by default.
+
+File fixtures are represented as +Pathname+ objects.
+ This makes it easy to extract specific information:
+ file_fixture("example.txt").read # get the file's content
+ file_fixture("example.mp3").size # get the file size
+
+You can customize files location by setting
+ ruby
+ RSpec.configure do |config|
+ config.file_fixture_path = "spec/custom_directory"
+ end
+
+
+Reading file content from fixtures directory
+
+And a file named “spec/fixtures/files/sample.txt” with:
+Hello
+
+And a file named “spec/lib/file_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "file" do
+ it "reads sample file" do
+ expect(file_fixture("sample.txt").read).to eq("Hello")
+ end
+end
+
+When I run rspec spec/lib/file_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/generator-specs/channel-specs/index.html b/docs/features/6-0/rspec-rails/generator-specs/channel-specs/index.html
new file mode 100644
index 000000000..0597179d7
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/generator-specs/channel-specs/index.html
@@ -0,0 +1,35 @@
+
+
+
+
+Channel generator spec
+
+Channel generator
+
+When I run bundle exec rails generate channel group
+
+Then the features should pass
+
+Then the output should contain:
+ invoke rspec
+ create spec/channels/group_channel_spec.rb
+
+Then the output should contain:
+ create app/channels/group_channel.rb
+
+Channel generator with customized default-path
+
+Given a file named “.rspec” with:
+--default-path behaviour
+
+And I run bundle exec rails generate channel group
+
+Then the features should pass
+
+Then the output should contain:
+ invoke rspec
+ create behaviour/channels/group_channel_spec.rb
+
+Then the output should contain:
+ create app/channels/group_channel.rb
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/generator-specs/controller-specs/index.html b/docs/features/6-0/rspec-rails/generator-specs/controller-specs/index.html
new file mode 100644
index 000000000..3b25ba96a
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/generator-specs/controller-specs/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+Controller generator spec
+
+Controller generator
+
+When I run bundle exec rails generate controller posts
+
+Then the features should pass
+
+Then the output should contain:
+ create app/controllers/posts_controller.rb
+ invoke erb
+ create app/views/posts
+ invoke rspec
+ create spec/requests/posts_spec.rb
+ invoke helper
+ create app/helpers/posts_helper.rb
+ invoke rspec
+ create spec/helpers/posts_helper_spec.rb
+
+Controller generator with customized default-path
+
+Given a file named “.rspec” with:
+--default-path behaviour
+
+And I run bundle exec rails generate controller posts
+
+Then the features should pass
+
+Then the output should contain:
+ create app/controllers/posts_controller.rb
+ invoke erb
+ create app/views/posts
+ invoke rspec
+ create behaviour/requests/posts_spec.rb
+ invoke helper
+ create app/helpers/posts_helper.rb
+ invoke rspec
+ create behaviour/helpers/posts_helper_spec.rb
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/generator-specs/feature-specs/index.html b/docs/features/6-0/rspec-rails/generator-specs/feature-specs/index.html
new file mode 100644
index 000000000..c3ee6b06b
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/generator-specs/feature-specs/index.html
@@ -0,0 +1,27 @@
+
+
+
+
+Feature generator spec
+
+Feature generator
+
+When I run bundle exec rails generate rspec:feature posts
+
+Then the features should pass
+
+Then the output should contain:
+ create spec/features/posts_spec.rb
+
+Feature generator with customized default-path
+
+Given a file named “.rspec” with:
+--default-path behaviour
+
+And I run bundle exec rails generate rspec:feature posts
+
+Then the features should pass
+
+Then the output should contain:
+ create behaviour/features/posts_spec.rb
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/generator-specs/generator-specs/index.html b/docs/features/6-0/rspec-rails/generator-specs/generator-specs/index.html
new file mode 100644
index 000000000..7a3d20684
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/generator-specs/generator-specs/index.html
@@ -0,0 +1,39 @@
+
+
+
+
+Generator spec
+
+RSpec spec(s) can be generated when generating application components. For instance, rails generate model will also generate an RSpec spec file for the model but you can also write your own generator. See customizing your workflow
+
+Use custom generator
+
+When I run bundle exec rails generate generator my_generator
+
+Then the features should pass
+
+Then the output should contain:
+ create lib/generators/my_generator
+ create lib/generators/my_generator/my_generator_generator.rb
+ create lib/generators/my_generator/USAGE
+ create lib/generators/my_generator/templates
+ invoke rspec
+ create spec/generator/my_generators_generator_spec.rb
+
+Use custom generator with customized default-path
+
+Given a file named “.rspec” with:
+--default-path behaviour
+
+And I run bundle exec rails generate generator my_generator
+
+Then the features should pass
+
+Then the output should contain:
+ create lib/generators/my_generator
+ create lib/generators/my_generator/my_generator_generator.rb
+ create lib/generators/my_generator/USAGE
+ create lib/generators/my_generator/templates
+ invoke rspec
+ create behaviour/generator/my_generators_generator_spec.rb
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/generator-specs/helper-specs/index.html b/docs/features/6-0/rspec-rails/generator-specs/helper-specs/index.html
new file mode 100644
index 000000000..de18241b9
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/generator-specs/helper-specs/index.html
@@ -0,0 +1,31 @@
+
+
+
+
+Helper generator spec
+
+Helper generator
+
+When I run bundle exec rails generate helper posts
+
+Then the features should pass
+
+Then the output should contain:
+ create app/helpers/posts_helper.rb
+ invoke rspec
+ create spec/helpers/posts_helper_spec.rb
+
+Helper generator with customized default-path
+
+Given a file named “.rspec” with:
+--default-path behaviour
+
+And I run bundle exec rails generate helper posts
+
+Then the features should pass
+
+Then the output should contain:
+ create app/helpers/posts_helper.rb
+ invoke rspec
+ create behaviour/helpers/posts_helper_spec.rb
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/generator-specs/index.html b/docs/features/6-0/rspec-rails/generator-specs/index.html
new file mode 100644
index 000000000..a868424ca
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/generator-specs/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Generator specs
Topics
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/generator-specs/integration-specs/index.html b/docs/features/6-0/rspec-rails/generator-specs/integration-specs/index.html
new file mode 100644
index 000000000..2474227b4
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/generator-specs/integration-specs/index.html
@@ -0,0 +1,27 @@
+
+
+
+
+Integration generator spec
+
+Integration generator
+
+When I run bundle exec rails generate rspec:integration posts
+
+Then the features should pass
+
+Then the output should contain:
+ create spec/requests/posts_spec.rb
+
+Integration generator with customized default-path
+
+Given a file named “.rspec” with:
+--default-path behaviour
+
+And I run bundle exec rails generate rspec:integration posts
+
+Then the features should pass
+
+Then the output should contain:
+ create behaviour/requests/posts_spec.rb
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/generator-specs/job-specs/index.html b/docs/features/6-0/rspec-rails/generator-specs/job-specs/index.html
new file mode 100644
index 000000000..5af684ecb
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/generator-specs/job-specs/index.html
@@ -0,0 +1,31 @@
+
+
+
+
+Job generator spec
+
+Job generator
+
+When I run bundle exec rails generate job user
+
+Then the features should pass
+
+Then the output should contain:
+ invoke rspec
+ create spec/jobs/user_job_spec.rb
+ create app/jobs/user_job.rb
+
+Job generator with customized default-path
+
+Given a file named “.rspec” with:
+--default-path behaviour
+
+And I run bundle exec rails generate job user
+
+Then the features should pass
+
+Then the output should contain:
+ invoke rspec
+ create behaviour/jobs/user_job_spec.rb
+ create app/jobs/user_job.rb
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/generator-specs/mailbox-specs/index.html b/docs/features/6-0/rspec-rails/generator-specs/mailbox-specs/index.html
new file mode 100644
index 000000000..41389df6d
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/generator-specs/mailbox-specs/index.html
@@ -0,0 +1,31 @@
+
+
+
+
+Mailbox generator spec
+
+Mailbox generator
+
+When I run bundle exec rails generate mailbox forwards
+
+Then the features should pass
+
+Then the output should contain:
+ create app/mailboxes/forwards_mailbox.rb
+ invoke rspec
+ create spec/mailboxes/forwards_mailbox_spec.rb
+
+Mailbox generator with customized default-path
+
+Given a file named “.rspec” with:
+--default-path behaviour
+
+And I run bundle exec rails generate mailbox forwards
+
+Then the features should pass
+
+Then the output should contain:
+ create app/mailboxes/forwards_mailbox.rb
+ invoke rspec
+ create behaviour/mailboxes/forwards_mailbox_spec.rb
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/generator-specs/mailer-specs/index.html b/docs/features/6-0/rspec-rails/generator-specs/mailer-specs/index.html
new file mode 100644
index 000000000..75e266540
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/generator-specs/mailer-specs/index.html
@@ -0,0 +1,49 @@
+
+
+
+
+Mailer generator spec
+
+Mailer generator
+
+When I run bundle exec rails generate mailer posts index show
+
+Then the features should pass
+
+Then the output should contain:
+ create app/mailers/posts_mailer.rb
+ invoke erb
+ create app/views/posts_mailer
+ create app/views/posts_mailer/index.text.erb
+ create app/views/posts_mailer/index.html.erb
+ create app/views/posts_mailer/show.text.erb
+ create app/views/posts_mailer/show.html.erb
+ invoke rspec
+ create spec/mailers/posts_spec.rb
+ create spec/fixtures/posts/index
+ create spec/fixtures/posts/show
+ create spec/mailers/previews/posts_preview.rb
+
+Mailer generator with customized default-path
+
+Given a file named “.rspec” with:
+--default-path behaviour
+
+And I run bundle exec rails generate mailer posts index show
+
+Then the features should pass
+
+Then the output should contain:
+ create app/mailers/posts_mailer.rb
+ invoke erb
+ create app/views/posts_mailer
+ create app/views/posts_mailer/index.text.erb
+ create app/views/posts_mailer/index.html.erb
+ create app/views/posts_mailer/show.text.erb
+ create app/views/posts_mailer/show.html.erb
+ invoke rspec
+ create behaviour/mailers/posts_spec.rb
+ create behaviour/fixtures/posts/index
+ create behaviour/fixtures/posts/show
+ create behaviour/mailers/previews/posts_preview.rb
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/generator-specs/request-specs/index.html b/docs/features/6-0/rspec-rails/generator-specs/request-specs/index.html
new file mode 100644
index 000000000..c5c6c1b86
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/generator-specs/request-specs/index.html
@@ -0,0 +1,27 @@
+
+
+
+
+Request generator spec
+
+Request generator
+
+When I run bundle exec rails generate rspec:request posts
+
+Then the features should pass
+
+Then the output should contain:
+ create spec/requests/posts_spec.rb
+
+Request generator with customized default-path
+
+Given a file named “.rspec” with:
+--default-path behaviour
+
+And I run bundle exec rails generate rspec:request posts
+
+Then the features should pass
+
+Then the output should contain:
+ create behaviour/requests/posts_spec.rb
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/generator-specs/system-specs/index.html b/docs/features/6-0/rspec-rails/generator-specs/system-specs/index.html
new file mode 100644
index 000000000..b1b3b2edc
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/generator-specs/system-specs/index.html
@@ -0,0 +1,27 @@
+
+
+
+
+System generator spec
+
+System generator
+
+When I run bundle exec rails generate rspec:system posts
+
+Then the features should pass
+
+Then the output should contain:
+ create spec/system/posts_spec.rb
+
+System generator with customized default-path
+
+Given a file named “.rspec” with:
+--default-path behaviour
+
+And I run bundle exec rails generate rspec:system posts
+
+Then the features should pass
+
+Then the output should contain:
+ create behaviour/system/posts_spec.rb
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/generator-specs/view-specs/index.html b/docs/features/6-0/rspec-rails/generator-specs/view-specs/index.html
new file mode 100644
index 000000000..42071b3ea
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/generator-specs/view-specs/index.html
@@ -0,0 +1,29 @@
+
+
+
+
+View generator spec
+
+View generator
+
+When I run bundle exec rails generate rspec:view posts index
+
+Then the features should pass
+
+Then the output should contain:
+ create spec/views/posts
+ create spec/views/posts/index.html.erb_spec.rb
+
+View generator with customized default-path
+
+Given a file named “.rspec” with:
+--default-path behaviour
+
+And I run bundle exec rails generate rspec:view posts index
+
+Then the features should pass
+
+Then the output should contain:
+ create behaviour/views/posts
+ create behaviour/views/posts/index.html.erb_spec.rb
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/helper-specs/helper-spec/index.html b/docs/features/6-0/rspec-rails/helper-specs/helper-spec/index.html
new file mode 100644
index 000000000..eb874b537
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/helper-specs/helper-spec/index.html
@@ -0,0 +1,126 @@
+
+
+
+
+Helper specs
+
+Helper specs are marked by type: :helper or if you have set
+ config.infer_spec_type_from_file_location! by placing them in spec/helpers.
+
+Helper specs expose a helper object, which includes the helper module being
+ specified, the ApplicationHelper module (if there is one) and all of the
+ helpers built into Rails. It does not include the other helper modules in
+ your app.
+
+To access the helper methods you’re specifying, simply call them directly
+ on the helper object.
+
+NOTE: helper methods defined in controllers are not included.
+
+A helper method that returns a value
+
+Given a file named “spec/helpers/applicationhelperspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ApplicationHelper, type: :helper do
+ describe "#page_title" do
+ it "returns the default title" do
+ expect(helper.page_title).to eq("RSpec is your friend")
+ end
+ end
+end
+
+And a file named “app/helpers/application_helper.rb” with:
+module ApplicationHelper
+ def page_title
+ "RSpec is your friend"
+ end
+end
+
+When I run rspec spec/helpers/application_helper_spec.rb
+
+Then the examples should all pass.
+
+A helper method that accesses an instance variable
+
+Given a file named “spec/helpers/applicationhelperspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ApplicationHelper, type: :helper do
+ describe "#page_title" do
+ it "returns the instance variable" do
+ assign(:title, "My Title")
+ expect(helper.page_title).to eql("My Title")
+ end
+ end
+end
+
+And a file named “app/helpers/application_helper.rb” with:
+module ApplicationHelper
+ def page_title
+ @title || nil
+ end
+end
+
+When I run rspec spec/helpers/application_helper_spec.rb
+
+Then the examples should all pass.
+
+Application helper is included in helper object
+
+Given a file named “spec/helpers/widgetshelperspec.rb” with:
+require "rails_helper"
+
+RSpec.describe WidgetsHelper, type: :helper do
+ describe "#widget_title" do
+ it "includes the app name" do
+ assign(:title, "This Widget")
+ expect(helper.widget_title).to eq("The App: This Widget")
+ end
+ end
+end
+
+And a file named “app/helpers/application_helper.rb” with:
+module ApplicationHelper
+ def app_name
+ "The App"
+ end
+end
+
+And a file named “app/helpers/widgets_helper.rb” with:
+module WidgetsHelper
+ def widget_title
+ "#{app_name}: #{@title}"
+ end
+end
+
+When I run rspec spec/helpers/widgets_helper_spec.rb
+
+Then the examples should all pass.
+
+Url helpers are defined
+
+Given a file named “spec/helpers/widgetshelperspec.rb” with:
+require "rails_helper"
+
+RSpec.describe WidgetsHelper, type: :helper do
+ describe "#link_to_widget" do
+ it "links to a widget using its name" do
+ widget = Widget.create!(:name => "This Widget")
+ expect(helper.link_to_widget(widget)).to include("This Widget")
+ expect(helper.link_to_widget(widget)).to include(widget_path(widget))
+ end
+ end
+end
+
+And a file named “app/helpers/widgets_helper.rb” with:
+module WidgetsHelper
+ def link_to_widget(widget)
+ link_to(widget.name, widget_path(widget))
+ end
+end
+
+When I run rspec spec/helpers/widgets_helper_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/helper-specs/index.html b/docs/features/6-0/rspec-rails/helper-specs/index.html
new file mode 100644
index 000000000..585dae933
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/helper-specs/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Helper specs
Topics
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/index.html b/docs/features/6-0/rspec-rails/index.html
new file mode 100644
index 000000000..3fd7f580d
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/index.html
@@ -0,0 +1,58 @@
+
+
+
+
+RSpec Rails
+
+rspec-rails extends Rails’ built-in testing framework to support rspec
+examples for requests, controllers, models, views, helpers, mailers and
+routing. It is a thin framework around Rails own helpers and you can
+check their documentation for help as well.
+
+Rails
+
+rspec-rails 6 supports Rails 6.1 to 7.0. For earlier versions of Rails, you
+should use rspec-rails-5
+for Rails 5.2 and 6.0, rspec-rails-4
+for Rails 5.x, and rspec-rails 3
+for even older versions.
+
+Install
+gem install rspec-rails
+
+This installs the following gems:
+rspec
+rspec-core
+rspec-expectations
+rspec-mocks
+rspec-rails
+
+Configure
+
+Add rspec-rails to the :test and :development groups in the Gemfile:
+group :test, :development do
+ gem 'rspec-rails', '~> 6.0.0'
+end
+
+It needs to be in the :development group to expose generators and rake tasks
+without having to type RAILS_ENV=test.
+
+Now you can run:
+bundle exec rails generate rspec:install
+
+This adds the spec directory and some skeleton files, including a .rspec
+file.
+
+You can also customize the default spec path with --default-path option:
+bundle exec rails generate rspec:install --default-path behaviour
+
+Issues
+
+The documentation for rspec-rails is a work in progress. We’ll be adding
+Cucumber features over time, and clarifying existing ones. If you have
+specific features you’d like to see added, find the existing documentation
+incomplete or confusing, or, better yet, wish to write a missing Cucumber
+feature yourself, please submit an
+issue or a pull
+request.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/job-specs/index.html b/docs/features/6-0/rspec-rails/job-specs/index.html
new file mode 100644
index 000000000..ab2a70b75
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/job-specs/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Job specs
Topics
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/job-specs/job-spec/index.html b/docs/features/6-0/rspec-rails/job-specs/job-spec/index.html
new file mode 100644
index 000000000..0115cc7d3
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/job-specs/job-spec/index.html
@@ -0,0 +1,165 @@
+
+
+
+
+Job specs
+
+Job specs provide alternative assertions to those available in ActiveJob::TestHelper and help assert behaviour of the jobs themselves and that other entities correctly enqueue them.
+
+Job specs are marked by type: :job or if you have set config.infer_spec_type_from_file_location! by placing them in spec/jobs.
+
+With job specs, you can:
+
+
+- specify the job class which was enqueued
+- specify the arguments passed to the job
+- specify when the job was enqueued until
+- specify the queue which the job was enqueued to
+
+
+Check the documentation on
+ have_been_enqueued,
+ have_enqueued_job,
+ have_been_performed, and
+ have_performed_job
+ for more information.
+
+Background
+
+Given active job is available.
+
+Specify that job was enqueued
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob, type: :job do
+ describe "#perform_later" do
+ it "uploads a backup" do
+ ActiveJob::Base.queue_adapter = :test
+ expect {
+ UploadBackupsJob.perform_later('backup')
+ }.to have_enqueued_job
+ end
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the example should pass.
+
+Specify that job was enqueued for the correct date and time
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob, type: :job do
+ describe "#perform_later" do
+ it "uploads a backup" do
+ ActiveJob::Base.queue_adapter = :test
+ expect {
+ UploadBackupsJob.set(wait_until: Date.tomorrow.noon, queue: "low").perform_later('backup')
+ }.to have_enqueued_job.with('backup').on_queue("low").at(Date.tomorrow.noon)
+ end
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the example should pass.
+
+Specify that job was enqueued with no wait
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob, type: :job do
+ describe "#perform_later" do
+ it "uploads a backup" do
+ ActiveJob::Base.queue_adapter = :test
+ expect {
+ UploadBackupsJob.set(queue: "low").perform_later('backup')
+ }.to have_enqueued_job.with('backup').on_queue("low").at(:no_wait)
+ end
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the example should pass.
+
+Specify that job was enqueued with alias block syntax
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob, type: :job do
+ describe "#perform_later" do
+ it "uploads a backup" do
+ ActiveJob::Base.queue_adapter = :test
+ expect {
+ UploadBackupsJob.perform_later('backup')
+ }.to enqueue_job
+ end
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the example should pass.
+
+Specify that job was enqueued with imperative syntax
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob, type: :job do
+ describe "#perform_later" do
+ it "uploads a backup" do
+ ActiveJob::Base.queue_adapter = :test
+ UploadBackupsJob.perform_later('backup')
+ expect(UploadBackupsJob).to have_been_enqueued
+ end
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the example should pass.
+
+Specify that job was enqueued with imperative syntax and a chained expectation
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob, type: :job do
+ describe "#perform_later" do
+ it "uploads a backup" do
+ ActiveJob::Base.queue_adapter = :test
+ UploadBackupsJob.perform_later('backup')
+ expect(UploadBackupsJob).to have_been_enqueued.exactly(:once)
+ end
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the example should pass.
+
+The test adapter must be set to :test
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob, type: :job do
+ describe "#perform_later" do
+ it "uploads a backup" do
+ ActiveJob::Base.queue_adapter = :development
+ end
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the example should fail.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/mailbox-specs/index.html b/docs/features/6-0/rspec-rails/mailbox-specs/index.html
new file mode 100644
index 000000000..08035e1ca
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/mailbox-specs/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Mailbox specs
Topics
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/mailbox-specs/mailbox-spec/index.html b/docs/features/6-0/rspec-rails/mailbox-specs/mailbox-spec/index.html
new file mode 100644
index 000000000..cb163ce86
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/mailbox-specs/mailbox-spec/index.html
@@ -0,0 +1,89 @@
+
+
+
+
+Action mailbox specs
+
+Mailbox specs provide alternative assertions to those available in ActiveMailbox::TestHelper and help assert behaviour of how the email
+ are routed, delivered, bounced or failed.
+
+Mailbox specs are marked by type: :mailbox or if you have set
+ config.infer_spec_type_from_file_location! by placing them in spec/mailboxes.
+
+With mailbox specs you can:
+ * process(mail_or_attributes) - send mail directly to the mailbox under test for processing.
+ * receive_inbound_email(mail_or_attributes) - matcher for asserting whether incoming email would route to the mailbox under test.
+ * have_been_delivered - matcher for asserting whether an incoming email object was delivered.
+ * have_bounced - matcher for asserting whether an incoming email object has bounced.
+ * have_failed - matcher for asserting whether an incoming email object has failed.
+
+Background
+
+Given action mailbox is available.
+
+Simple testing mail properly routed
+
+Given a file named “app/mailboxes/application_mailbox.rb” with:
+class ApplicationMailbox < ActionMailbox::Base
+ routing (/^replies@/i) => :inbox
+end
+
+And a file named “app/maiboxes/inbox_mailbox.rb” with:
+class InboxMailbox < ApplicationMailbox
+ def process
+ case mail.subject
+ when (/^\[\d*\]/i)
+ # ok
+ when (/^\[\w*\]/i)
+ bounced!
+ else
+ raise "Invalid email subject"
+ end
+ end
+end
+
+And a file named “spec/mailboxes/inboxmailboxspec.rb” with:
+require 'rails_helper'
+
+RSpec.describe InboxMailbox, type: :mailbox do
+ it "route email to properly mailbox" do
+ expect(InboxMailbox)
+ .to receive_inbound_email(to: "replies@example.com")
+ end
+
+ it "marks email as delivered when number tag in subject is valid" do
+ mail = Mail.new(
+ from: "replies@example.com",
+ subject: "[141982763] support ticket"
+ )
+ mail_processed = process(mail)
+
+ expect(mail_processed).to have_been_delivered
+ end
+
+ it "marks email as bounced when number tag in subject is invalid" do
+ mail = Mail.new(
+ from: "replies@example.com",
+ subject: "[111X] support ticket"
+ )
+ mail_processed = process(mail)
+
+ expect(mail_processed).to have_bounced
+ end
+
+ it "marks email as failed when subject is invalid" do
+ mail = Mail.new(
+ from: "replies@example.com",
+ subject: "INVALID"
+ )
+
+ expect {
+ expect(process(mail)).to have_failed
+ }.to raise_error(/Invalid email subject/)
+ end
+end
+
+When I run rspec spec/mailboxes/inbox_mailbox_spec.rb
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/mailer-specs/index.html b/docs/features/6-0/rspec-rails/mailer-specs/index.html
new file mode 100644
index 000000000..7d6f17f95
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/mailer-specs/index.html
@@ -0,0 +1,32 @@
+
+
+
+
+Mailer sepcs
+
+By default Mailer specs reside in the spec/mailers folder. Adding the metadata
+type: :mailer to any context makes its examples be treated as mailer specs.
+
+A mailer spec is a thin wrapper for an ActionMailer::TestCase, and includes all
+of the behavior and assertions that it provides, in addition to RSpec’s own
+behavior and expectations.
+
+Examples
+require "rails_helper"
+
+RSpec.describe Notifications, type: :mailer do
+ describe "notify" do
+ let(:mail) { Notifications.signup }
+
+ it "renders the headers" do
+ expect(mail.subject).to eq("Signup")
+ expect(mail.to).to eq(["to@example.org"])
+ expect(mail.from).to eq(["from@example.com"])
+ end
+
+ it "renders the body" do
+ expect(mail.body.encoded).to match("Hi")
+ end
+ end
+end
+
Topics
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/mailer-specs/mailer-spec/index.html b/docs/features/6-0/rspec-rails/mailer-specs/mailer-spec/index.html
new file mode 100644
index 000000000..64f7058a2
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/mailer-specs/mailer-spec/index.html
@@ -0,0 +1,31 @@
+
+
+
+
+Mailer specs
+
+A simple passing example
+
+Given a file named “spec/mailers/notificationsmailerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe NotificationsMailer, type: :mailer do
+ describe "notify" do
+ let(:mail) { NotificationsMailer.signup }
+
+ it "renders the headers" do
+ expect(mail.subject).to eq("Signup")
+ expect(mail.to).to eq(["to@example.org"])
+ expect(mail.from).to eq(["from@example.com"])
+ end
+
+ it "renders the body" do
+ expect(mail.body.encoded).to match("Hi")
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/mailer-specs/url-helpers/index.html b/docs/features/6-0/rspec-rails/mailer-specs/url-helpers/index.html
new file mode 100644
index 000000000..e3cf9c507
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/mailer-specs/url-helpers/index.html
@@ -0,0 +1,46 @@
+
+
+
+
+URL helpers in mailer examples
+
+Mailer specs are marked by type: :mailer or if you have set
+ config.infer_spec_type_from_file_location! by placing them in spec/mailers.
+
+Using URL helpers with default options
+
+Given a file named “config/initializers/mailer_defaults.rb” with:
+Rails.configuration.action_mailer.default_url_options = { :host => 'example.com' }
+
+And a file named “spec/mailers/notifications_spec.rb” with:
+require 'rails_helper'
+
+RSpec.describe NotificationsMailer, type: :mailer do
+ it 'should have access to URL helpers' do
+ expect { gadgets_url }.not_to raise_error
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Using URL helpers without default options
+
+Given a file named “config/initializers/mailer_defaults.rb” with:
+# no default options
+
+And a file named “spec/mailers/notifications_spec.rb” with:
+require 'rails_helper'
+
+RSpec.describe NotificationsMailer, type: :mailer do
+ it 'should have access to URL helpers' do
+ expect { gadgets_url :host => 'example.com' }.not_to raise_error
+ expect { gadgets_url }.to raise_error
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/matchers/have-been-enqueued-matcher/index.html b/docs/features/6-0/rspec-rails/matchers/have-been-enqueued-matcher/index.html
new file mode 100644
index 000000000..8c35f6688
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/matchers/have-been-enqueued-matcher/index.html
@@ -0,0 +1,99 @@
+
+
+
+
+have_been_enqueued matcher
+
+The have_been_enqueued matcher is used to check if given ActiveJob job was enqueued.
+
+Background
+
+Given active job is available.
+
+Checking job class name
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with enqueued job" do
+ ActiveJob::Base.queue_adapter = :test
+ UploadBackupsJob.perform_later
+ expect(UploadBackupsJob).to have_been_enqueued
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking passed arguments to job
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with enqueued job" do
+ ActiveJob::Base.queue_adapter = :test
+ UploadBackupsJob.perform_later("users-backup.txt", "products-backup.txt")
+ expect(UploadBackupsJob).to(
+ have_been_enqueued.with("users-backup.txt", "products-backup.txt")
+ )
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking job enqueued time
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with enqueued job" do
+ ActiveJob::Base.queue_adapter = :test
+ UploadBackupsJob.set(:wait_until => Date.tomorrow.noon).perform_later
+ expect(UploadBackupsJob).to have_been_enqueued.at(Date.tomorrow.noon)
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking job enqueued with no wait
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with enqueued job" do
+ ActiveJob::Base.queue_adapter = :test
+ UploadBackupsJob.perform_later
+ expect(UploadBackupsJob).to have_been_enqueued.at(:no_wait)
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking job queue name
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with enqueued job" do
+ ActiveJob::Base.queue_adapter = :test
+ UploadBackupsJob.perform_later
+ expect(UploadBackupsJob).to have_been_enqueued.on_queue("default")
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/matchers/have-been-performed-matcher/index.html b/docs/features/6-0/rspec-rails/matchers/have-been-performed-matcher/index.html
new file mode 100644
index 000000000..b0a18033e
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/matchers/have-been-performed-matcher/index.html
@@ -0,0 +1,87 @@
+
+
+
+
+have_been_performed matcher
+
+The have_been_performed matcher is used to check if given ActiveJob job was performed.
+
+Background
+
+Given active job is available.
+
+Checking job class name
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with performed job" do
+ ActiveJob::Base.queue_adapter = :test
+ ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
+ UploadBackupsJob.perform_later
+ expect(UploadBackupsJob).to have_been_performed
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking passed arguments to job
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with performed job" do
+ ActiveJob::Base.queue_adapter = :test
+ ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
+ UploadBackupsJob.perform_later("users-backup.txt", "products-backup.txt")
+ expect(UploadBackupsJob).to(
+ have_been_performed.with("users-backup.txt", "products-backup.txt")
+ )
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking job performed time
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with performed job" do
+ ActiveJob::Base.queue_adapter = :test
+ ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
+ ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = true
+ UploadBackupsJob.set(:wait_until => Date.tomorrow.noon).perform_later
+ expect(UploadBackupsJob).to have_been_performed.at(Date.tomorrow.noon)
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking job queue name
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with performed job" do
+ ActiveJob::Base.queue_adapter = :test
+ ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
+ UploadBackupsJob.perform_later
+ expect(UploadBackupsJob).to have_been_performed.on_queue("default")
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/matchers/have-broadcasted-matcher/index.html b/docs/features/6-0/rspec-rails/matchers/have-broadcasted-matcher/index.html
new file mode 100644
index 000000000..26cf4bb26
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/matchers/have-broadcasted-matcher/index.html
@@ -0,0 +1,162 @@
+
+
+
+
+have_broadcasted_to matcher
+
+The have_broadcasted_to (also aliased as broadcast_to) matcher is used
+ to check if a message has been broadcasted to a given stream.
+
+Background
+
+Given action cable testing is available.
+
+Checking stream name
+
+Given a file named “spec/models/broadcaster_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "broadcasting" do
+ it "matches with stream name" do
+ expect {
+ ActionCable.server.broadcast(
+ "notifications", { text: "Hello!" }
+ )
+ }.to have_broadcasted_to("notifications")
+ end
+end
+
+When I run rspec spec/models/broadcaster_spec.rb
+
+Then the examples should all pass.
+
+Checking passed message to stream
+
+Given a file named “spec/models/broadcaster_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "broadcasting" do
+ it "matches with message" do
+ expect {
+ ActionCable.server.broadcast(
+ "notifications", { text: "Hello!" }
+ )
+ }.to have_broadcasted_to("notifications").with(text: 'Hello!')
+ end
+end
+
+When I run rspec spec/models/broadcaster_spec.rb
+
+Then the examples should all pass.
+
+Checking that message passed to stream matches
+
+Given a file named “spec/models/broadcaster_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "broadcasting" do
+ it "matches with message" do
+ expect {
+ ActionCable.server.broadcast(
+ "notifications", { text: 'Hello!', user_id: 12 }
+ )
+ }.to have_broadcasted_to("notifications").with(a_hash_including(text: 'Hello!'))
+ end
+end
+
+When I run rspec spec/models/broadcaster_spec.rb
+
+Then the examples should all pass.
+
+Checking passed message with block
+
+Given a file named “spec/models/broadcaster_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "broadcasting" do
+ it "matches with message" do
+ expect {
+ ActionCable.server.broadcast(
+ "notifications", { text: 'Hello!', user_id: 12 }
+ )
+ }.to have_broadcasted_to("notifications").with { |data|
+ expect(data['user_id']).to eq 12
+ }
+ end
+end
+
+When I run rspec spec/models/broadcaster_spec.rb
+
+Then the examples should all pass.
+
+Using alias method
+
+Given a file named “spec/models/broadcaster_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "broadcasting" do
+ it "matches with stream name" do
+ expect {
+ ActionCable.server.broadcast(
+ "notifications", { text: 'Hello!' }
+ )
+ }.to broadcast_to("notifications")
+ end
+end
+
+When I run rspec spec/models/broadcaster_spec.rb
+
+Then the examples should all pass.
+
+Checking broadcast to a record
+
+Given a file named “spec/channels/chatchannelspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ChatChannel, type: :channel do
+ it "matches with stream name" do
+ user = User.new(42)
+
+ expect {
+ ChatChannel.broadcast_to(user, text: 'Hi')
+ }.to have_broadcasted_to(user)
+ end
+end
+
+And a file named “app/models/user.rb” with:
+class User < Struct.new(:name)
+ def to_gid_param
+ name
+ end
+end
+
+When I run rspec spec/channels/chat_channel_spec.rb
+
+Then the example should pass.
+
+Checking broadcast to a record in non-channel spec
+
+Given a file named “spec/models/broadcaster_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "broadcasting" do
+ it "matches with stream name" do
+ user = User.new(42)
+
+ expect {
+ ChatChannel.broadcast_to(user, text: 'Hi')
+ }.to broadcast_to(ChatChannel.broadcasting_for(user))
+ end
+end
+
+And a file named “app/models/user.rb” with:
+class User < Struct.new(:name)
+ def to_gid_param
+ name
+ end
+end
+
+When I run rspec spec/models/broadcaster_spec.rb
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/matchers/have-enqueued-job-matcher/index.html b/docs/features/6-0/rspec-rails/matchers/have-enqueued-job-matcher/index.html
new file mode 100644
index 000000000..b07177d02
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/matchers/have-enqueued-job-matcher/index.html
@@ -0,0 +1,141 @@
+
+
+
+
+have_enqueued_job matcher
+
+The have_enqueued_job (also aliased as enqueue_job) matcher is used to check if given ActiveJob job was enqueued.
+
+Background
+
+Given active job is available.
+
+Checking job class name
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with enqueued job" do
+ ActiveJob::Base.queue_adapter = :test
+ expect {
+ UploadBackupsJob.perform_later
+ }.to have_enqueued_job(UploadBackupsJob)
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking passed arguments to job
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with enqueued job" do
+ ActiveJob::Base.queue_adapter = :test
+ expect {
+ UploadBackupsJob.perform_later("users-backup.txt", "products-backup.txt")
+ }.to have_enqueued_job.with("users-backup.txt", "products-backup.txt")
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking passed arguments to job, using a block
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with enqueued job" do
+ ActiveJob::Base.queue_adapter = :test
+ expect {
+ UploadBackupsJob.perform_later('backups.txt', rand(100), 'uninteresting third argument')
+ }.to have_enqueued_job.with { |file_name, seed|
+ expect(file_name).to eq 'backups.txt'
+ expect(seed).to be < 100
+ }
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking job enqueued time
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with enqueued job" do
+ ActiveJob::Base.queue_adapter = :test
+ expect {
+ UploadBackupsJob.set(:wait_until => Date.tomorrow.noon).perform_later
+ }.to have_enqueued_job.at(Date.tomorrow.noon)
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking job enqueued with no wait
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with enqueued job" do
+ ActiveJob::Base.queue_adapter = :test
+ expect {
+ UploadBackupsJob.perform_later
+ }.to have_enqueued_job.at(:no_wait)
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking job queue name
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with enqueued job" do
+ ActiveJob::Base.queue_adapter = :test
+ expect {
+ UploadBackupsJob.perform_later
+ }.to have_enqueued_job.on_queue("default")
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Using alias method
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with enqueued job" do
+ ActiveJob::Base.queue_adapter = :test
+ expect {
+ UploadBackupsJob.perform_later
+ }.to enqueue_job(UploadBackupsJob)
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/matchers/have-enqueued-mail-matcher/index.html b/docs/features/6-0/rspec-rails/matchers/have-enqueued-mail-matcher/index.html
new file mode 100644
index 000000000..75350e1d6
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/matchers/have-enqueued-mail-matcher/index.html
@@ -0,0 +1,136 @@
+
+
+
+
+have_enqueued_mail matcher
+
+The have_enqueued_mail (also aliased as enqueue_mail) matcher is used to check if given mailer was enqueued.
+
+Background
+
+Given active job is available.
+
+Checking mailer class and method name
+
+Given a file named “spec/mailers/usermailerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe NotificationsMailer do
+ it "matches with enqueued mailer" do
+ ActiveJob::Base.queue_adapter = :test
+ expect {
+ NotificationsMailer.signup.deliver_later
+ }.to have_enqueued_mail(NotificationsMailer, :signup)
+ end
+end
+
+When I run rspec spec/mailers/user_mailer_spec.rb
+
+Then the examples should all pass.
+
+Checking mailer enqueued time
+
+Given a file named “spec/mailers/usermailerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe NotificationsMailer do
+ it "matches with enqueued mailer" do
+ ActiveJob::Base.queue_adapter = :test
+ expect {
+ NotificationsMailer.signup.deliver_later(wait_until: Date.tomorrow.noon)
+ }.to have_enqueued_mail.at(Date.tomorrow.noon)
+ end
+end
+
+When I run rspec spec/mailers/user_mailer_spec.rb
+
+Then the examples should all pass.
+
+Checking mailer arguments
+
+Given a file named “app/mailers/my_mailer.rb” with:
+class MyMailer < ApplicationMailer
+
+ def signup(user = nil)
+ @user = user
+
+ mail to: "to@example.org"
+ end
+end
+
+Given a file named “spec/mailers/mymailerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe MyMailer do
+ it "matches with enqueued mailer" do
+ ActiveJob::Base.queue_adapter = :test
+ # Works with plain args
+ expect {
+ MyMailer.signup('user').deliver_later
+ }.to have_enqueued_mail(MyMailer, :signup).with('user')
+ end
+end
+
+When I run rspec spec/mailers/my_mailer_spec.rb
+
+Then the examples should all pass.
+
+Parameterize the mailer
+
+Given a file named “app/mailers/my_mailer.rb” with:
+class MyMailer < ApplicationMailer
+
+ def signup
+ @foo = params[:foo]
+
+ mail to: "to@example.org"
+ end
+end
+
+Given a file named “spec/mailers/mymailerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe MyMailer do
+ it "matches with enqueued mailer" do
+ ActiveJob::Base.queue_adapter = :test
+ # Works with named parameters
+ expect {
+ MyMailer.with(foo: 'bar').signup.deliver_later
+ }.to have_enqueued_mail(MyMailer, :signup).with(a_hash_including(params: {foo: 'bar'}))
+ end
+end
+
+When I run rspec spec/mailers/my_mailer_spec.rb
+
+Then the examples should all pass.
+
+Parameterize and pass an argument to the mailer
+
+Given a file named “app/mailers/my_mailer.rb” with:
+class MyMailer < ApplicationMailer
+
+ def signup(user)
+ @user = user
+ @foo = params[:foo]
+
+ mail to: "to@example.org"
+ end
+end
+
+Given a file named “spec/mailers/mymailerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe MyMailer do
+ it "matches with enqueued mailer" do
+ ActiveJob::Base.queue_adapter = :test
+ # Works also with both, named parameters match first argument
+ expect {
+ MyMailer.with(foo: 'bar').signup('user').deliver_later
+ }.to have_enqueued_mail(MyMailer, :signup).with(params: {foo: 'bar'}, args: ['user'])
+ end
+end
+
+When I run rspec spec/mailers/my_mailer_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/matchers/have-http-status-matcher/index.html b/docs/features/6-0/rspec-rails/matchers/have-http-status-matcher/index.html
new file mode 100644
index 000000000..b28270a28
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/matchers/have-http-status-matcher/index.html
@@ -0,0 +1,163 @@
+
+
+
+
+have_http_status matcher
+
+The have_http_status matcher is used to specify that a response returns a
+ desired status code. It accepts one argument in any of the following formats:
+
+
+- numeric code
+- status name as defined in
Rack::Utils::SYMBOL_TO_STATUS_CODE
+- generic status type (
:success, :missing, :redirect, or :error)
+
+
+The matcher works on any response object. It is available for use in
+ controller specs, request specs, and feature specs.
+
+Checking a numeric status code
+
+Given a file named “spec/controllers/applicationcontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ApplicationController, type: :controller do
+
+ controller do
+ def index
+ render :json => {}, :status => 209
+ end
+ end
+
+ describe "GET #index" do
+ it "returns a 209 custom status code" do
+ get :index
+ expect(response).to have_http_status(209)
+ end
+ end
+
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Checking a symbolic status name
+
+Given a file named “spec/controllers/applicationcontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ApplicationController, type: :controller do
+
+ controller do
+ def index
+ render :json => {}, :status => :see_other
+ end
+ end
+
+ describe "GET #index" do
+ it "returns a :see_other status code" do
+ get :index
+ expect(response).to have_http_status(:see_other)
+ end
+ end
+
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Checking a symbolic generic status type
+
+Given a file named “spec/controllers/applicationcontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ApplicationController, type: :controller do
+
+ controller do
+ def index
+ render :json => {}, :status => :bad_gateway
+ end
+ end
+
+ describe "GET #index" do
+ it "returns a some type of error status code" do
+ get :index
+ expect(response).to have_http_status(:error)
+ end
+ end
+
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
+Using in a controller spec
+
+Given a file named “spec/controllers/gadgets_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe GadgetsController, type: :controller do
+
+ describe "GET #index" do
+ it "returns a 200 OK status" do
+ get :index
+ expect(response).to have_http_status(:ok)
+ end
+ end
+
+end
+
+When I run rspec spec/controllers/gadgets_spec.rb
+
+Then the examples should all pass.
+
+Using in a request spec
+
+Given a file named “spec/requests/gadgets/widgetmanagementspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "Widget management", type: :request do
+
+ it "creates a Widget and redirects to the Widget's page" do
+ get "/widgets/new"
+ expect(response).to have_http_status(:ok)
+
+ post "/widgets", :params => { :widget => {:name => "My Widget"} }
+ expect(response).to have_http_status(302)
+
+ follow_redirect!
+
+ expect(response).to have_http_status(:success)
+ end
+
+end
+
+When I run rspec spec/requests
+
+Then the examples should all pass.
+
+Using in a feature spec
+
+Given a file named “spec/features/widgetmanagementspec.rb” with:
+require "rails_helper"
+
+RSpec.feature "Widget management", type: :feature do
+
+ scenario "User creates a new widget" do
+ visit "/widgets/new"
+ expect(page).to have_http_status(200)
+
+ click_button "Create Widget"
+
+ expect(page).to have_http_status(:success)
+ end
+
+end
+
+When I run rspec spec/features/widget_management_spec.rb
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/matchers/have-performed-job-matcher/index.html b/docs/features/6-0/rspec-rails/matchers/have-performed-job-matcher/index.html
new file mode 100644
index 000000000..dd8dce2a0
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/matchers/have-performed-job-matcher/index.html
@@ -0,0 +1,108 @@
+
+
+
+
+have_performed_job matcher
+
+The have_performed_job (also aliased as perform_job) matcher is used to check if given ActiveJob job was performed.
+
+Background
+
+Given active job is available.
+
+Checking job class name
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with performed job" do
+ ActiveJob::Base.queue_adapter = :test
+ ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
+ expect {
+ UploadBackupsJob.perform_later
+ }.to have_performed_job(UploadBackupsJob)
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking passed arguments to job
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with performed job" do
+ ActiveJob::Base.queue_adapter = :test
+ ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
+ expect {
+ UploadBackupsJob.perform_later("users-backup.txt", "products-backup.txt")
+ }.to have_performed_job.with("users-backup.txt", "products-backup.txt")
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking job performed time
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with performed job" do
+ ActiveJob::Base.queue_adapter = :test
+ ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
+ ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = true
+ expect {
+ UploadBackupsJob.set(:wait_until => Date.tomorrow.noon).perform_later
+ }.to have_performed_job.at(Date.tomorrow.noon)
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Checking job queue name
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with performed job" do
+ ActiveJob::Base.queue_adapter = :test
+ ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
+ expect {
+ UploadBackupsJob.perform_later
+ }.to have_performed_job.on_queue("default")
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
+Using alias method
+
+Given a file named “spec/jobs/uploadbackupsjob_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe UploadBackupsJob do
+ it "matches with performed job" do
+ ActiveJob::Base.queue_adapter = :test
+ ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
+ expect {
+ UploadBackupsJob.perform_later
+ }.to perform_job(UploadBackupsJob)
+ end
+end
+
+When I run rspec spec/jobs/upload_backups_job_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/matchers/have-stream-from-matcher/index.html b/docs/features/6-0/rspec-rails/matchers/have-stream-from-matcher/index.html
new file mode 100644
index 000000000..33d05e914
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/matchers/have-stream-from-matcher/index.html
@@ -0,0 +1,104 @@
+
+
+
+
+have_stream_from matcher
+
+The have_stream_from matcher is used to check if a channel has been subscribed to a given stream specified as a String.
+ If you use stream_for in you channel to subscribe to a model, use have_stream_for matcher instead.
+
+The have_no_streams matcher is used to check if a channel hasn’t been subscribed to any stream.
+
+It is available only in channel specs.
+
+Background
+
+Given action cable testing is available
+
+And a file named “app/channels/chat_channel.rb” with:
+class ChatChannel < ApplicationCable::Channel
+ def subscribed
+ reject unless params[:room_id].present?
+
+ stream_from "chat_#{params[:room_id]}"
+ end
+
+ def leave
+ stop_all_streams
+ end
+end
+
+Subscribing with params and checking streams
+
+Given a file named “spec/channels/chatchannelspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ChatChannel, type: :channel do
+ it "successfully subscribes" do
+ subscribe room_id: 42
+
+ expect(subscription).to be_confirmed
+ expect(subscription).to have_stream_from("chat_42")
+ end
+end
+
+When I run rspec spec/channels/chat_channel_spec.rb
+
+Then the example should pass.
+
+Stopping all streams
+
+Given a file named “spec/channels/chatchannelspec.rb” with:
+require "rails_helper"
+
+RSpec.describe ChatChannel, type: :channel do
+ it "successfully subscribes" do
+ subscribe(room_id: 42)
+
+ expect(subscription).to have_stream_from("chat_42")
+
+ perform :leave
+ expect(subscription).not_to have_streams
+ end
+end
+
+When I run rspec spec/channels/chat_channel_spec.rb
+
+Then the example should pass.
+
+Subscribing and checking streams for models
+
+Given a file named “app/channels/notifications_channel.rb” with:
+class NotificationsChannel < ApplicationCable::Channel
+ def subscribed
+ stream_for current_user
+ end
+end
+
+And a file named “app/channels/application_cable/connection.rb” with:
+class ApplicationCable::Connection < ActionCable::Connection::Base
+ identified_by :current_user
+end
+
+And a file named “app/models/user.rb” with:
+class User < Struct.new(:name)
+ def to_gid_param
+ name
+ end
+end
+
+And a file named “spec/channels/userchannelspec.rb” with:
+require "rails_helper"
+RSpec.describe NotificationsChannel, type: :channel do
+ it "successfully subscribes to user's stream" do
+ stub_connection current_user: User.new(42)
+ subscribe
+ expect(subscription).to be_confirmed
+ expect(subscription).to have_stream_for(User.new(42))
+ end
+end
+
+When I run rspec spec/channels/user_channel_spec.rb
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/matchers/index.html b/docs/features/6-0/rspec-rails/matchers/index.html
new file mode 100644
index 000000000..d3a131ced
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/matchers/index.html
@@ -0,0 +1,22 @@
+
+
+
+
+Matchers
+
+rspec-rails offers a number of custom matchers, most of which are
+rspec-compatible wrappers for Rails’ assertions.
+
+redirects
+# delegates to assert_redirected_to
+expect(response).to redirect_to(path)
+
+templates
+# delegates to assert_template
+expect(response).to render_template(template_name)
+
+assigned objects
+# passes if assigns(:widget) is an instance of Widget
+# and it is not persisted
+expect(assigns(:widget)).to be_a_new(Widget)
+
Topics
- `be_a_new` matcher
- `render_template` matcher
- `redirect_to` matcher
- `have_performed_job` matcher
- `have_been_performed` matcher
- `have_broadcasted_to` matcher
- `have_enqueued_job` matcher
- `have_stream_from` matcher
- `have_enqueued_mail` matcher
- `have_http_status` matcher
- ActiveRecord::Relation match array
- `have_been_enqueued` matcher
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/matchers/new-record-matcher/index.html b/docs/features/6-0/rspec-rails/matchers/new-record-matcher/index.html
new file mode 100644
index 000000000..4b0c15c03
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/matchers/new-record-matcher/index.html
@@ -0,0 +1,47 @@
+
+
+
+
+be_a_new matcher
+
+The be_a_new matcher accepts a class and passes if the subject is an
+ instance of that class that returns false to persisted?
+
+You can also chain with on be_a_new with a hash of attributes to specify
+ the subject has equal attributes.
+
+An example spec with four beanew possibilities
+
+Given a file named “spec/models/widget_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe Widget do
+ context "when initialized" do
+ subject(:widget) { Widget.new }
+
+ it "is a new widget" do
+ expect(widget).to be_a_new(Widget)
+ end
+
+ it "is not a new string" do
+ expect(widget).not_to be_a_new(String)
+ end
+ end
+
+ context "when saved" do
+ subject(:widget) { Widget.create }
+
+ it "is not a new widget" do
+ expect(widget).not_to be_a_new(Widget)
+ end
+
+ it "is not a new string" do
+ expect(widget).not_to be_a_new(String)
+ end
+ end
+end
+
+When I run rspec spec/models/widget_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/matchers/redirect-to-matcher/index.html b/docs/features/6-0/rspec-rails/matchers/redirect-to-matcher/index.html
new file mode 100644
index 000000000..dd73cc11f
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/matchers/redirect-to-matcher/index.html
@@ -0,0 +1,46 @@
+
+
+
+
+redirect_to matcher
+
+The redirect_to matcher is used to specify that a request redirects to a
+ given template or action. It delegates to
+ assert_redirected_to.
+
+It is available in controller specs (spec/controllers) and request
+ specs (spec/requests).
+
+Using redirect_to with four possible options
+
+Given a file named “spec/controllers/widgetscontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe WidgetsController do
+
+ describe "#create" do
+ subject { post :create, :params => { :widget => { :name => "Foo" } } }
+
+ it "redirects to widget_url(@widget)" do
+ expect(subject).to redirect_to(widget_url(assigns(:widget)))
+ end
+
+ it "redirects_to :action => :show" do
+ expect(subject).to redirect_to :action => :show,
+ :id => assigns(:widget).id
+ end
+
+ it "redirects_to(@widget)" do
+ expect(subject).to redirect_to(assigns(:widget))
+ end
+
+ it "redirects_to /widgets/:id" do
+ expect(subject).to redirect_to("/widgets/#{assigns(:widget).id}")
+ end
+ end
+end
+
+When I run rspec spec/controllers/widgets_controller_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/matchers/relation-match-array/index.html b/docs/features/6-0/rspec-rails/matchers/relation-match-array/index.html
new file mode 100644
index 000000000..db15bce3b
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/matchers/relation-match-array/index.html
@@ -0,0 +1,29 @@
+
+
+
+
+ActiveRecord::Relation match array
+
+The match_array matcher can be used with an ActiveRecord::Relation
+ (scope). The assertion will pass if the scope would return all of the
+ elements specified in the array on the right hand side.
+
+An example spec with relation match_array matcher
+
+Given a file named “spec/models/widget_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe Widget do
+ let!(:widgets) { Array.new(3) { Widget.create } }
+
+ subject { Widget.all }
+
+ it "returns all widgets in any order" do
+ expect(subject).to match_array(widgets)
+ end
+end
+
+When I run rspec spec/models/widget_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/matchers/render-template-matcher/index.html b/docs/features/6-0/rspec-rails/matchers/render-template-matcher/index.html
new file mode 100644
index 000000000..17473996d
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/matchers/render-template-matcher/index.html
@@ -0,0 +1,87 @@
+
+
+
+
+render_template matcher
+
+The render_template matcher is used to specify that a request renders a
+ given template or layout. It delegates to
+ assert_template
+
+It is available in controller specs (spec/controllers) and request
+ specs (spec/requests).
+
+NOTE: use redirect_to(:action => 'new') for redirects, not render_template.
+
+Using render_template with three possible options
+
+Given a file named “spec/controllers/gadgets_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe GadgetsController do
+ describe "GET #index" do
+ subject { get :index }
+
+ it "renders the index template" do
+ expect(subject).to render_template(:index)
+ expect(subject).to render_template("index")
+ expect(subject).to render_template("gadgets/index")
+ end
+
+ it "does not render a different template" do
+ expect(subject).to_not render_template("gadgets/show")
+ end
+ end
+end
+
+When I run rspec spec/controllers/gadgets_spec.rb
+
+Then the examples should all pass.
+
+Specify that a request renders a given layout
+
+Given a file named “spec/controllers/gadgets_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe GadgetsController do
+ describe "GET #index" do
+ subject { get :index }
+
+ it "renders the application layout" do
+ expect(subject).to render_template("layouts/application")
+ end
+
+ it "does not render a different layout" do
+ expect(subject).to_not render_template("layouts/admin")
+ end
+ end
+end
+
+When I run rspec spec/controllers/gadgets_spec.rb
+
+Then the examples should all pass.
+
+Using render_template in a view spec
+
+Given a file named “spec/views/gadgets/index.html.erb_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "gadgets/index" do
+ it "renders the index template" do
+ assign(:gadgets, [Gadget.create!])
+ render
+
+ expect(view).to render_template(:index)
+ expect(view).to render_template("index")
+ expect(view).to render_template("gadgets/index")
+ end
+
+ it "does not render a different template" do
+ expect(view).to_not render_template("gadgets/show")
+ end
+end
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/model-specs/index.html b/docs/features/6-0/rspec-rails/model-specs/index.html
new file mode 100644
index 000000000..d64962a24
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/model-specs/index.html
@@ -0,0 +1,27 @@
+
+
+
+
+Model specs
+
+Model specs are marked by type: :model or if you have set
+config.infer_spec_type_from_file_location! by placing them in spec/models.
+
+A model spec is a thin wrapper for an ActiveSupport::TestCase, and includes all
+of the behavior and assertions that it provides, in addition to RSpec’s own
+behavior and expectations.
+
+Examples
+require "rails_helper"
+
+RSpec.describe Post, type: :model do
+ context "with 2 or more comments" do
+ it "orders them in reverse chronologically" do
+ post = Post.create!
+ comment1 = post.comments.create!(:body => "first comment")
+ comment2 = post.comments.create!(:body => "second comment")
+ expect(post.reload.comments).to eq([comment2, comment1])
+ end
+ end
+end
+
Topics
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/model-specs/transactional-examples/index.html b/docs/features/6-0/rspec-rails/model-specs/transactional-examples/index.html
new file mode 100644
index 000000000..52e9d0d57
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/model-specs/transactional-examples/index.html
@@ -0,0 +1,114 @@
+
+
+
+
+Transactional examples
+
+By default rspec executes each individual example in a transaction.
+
+You can also explicitly enable/disable transactions the configuration
+ property ‘usetransactionalexamples’.
+
+Run in transactions (default)
+
+Given a file named “spec/models/widget_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe Widget, type: :model do
+ it "has none to begin with" do
+ expect(Widget.count).to eq 0
+ end
+
+ it "has one after adding one" do
+ Widget.create
+ expect(Widget.count).to eq 1
+ end
+
+ it "has none after one was created in a previous example" do
+ expect(Widget.count).to eq 0
+ end
+end
+
+When I run rspec spec/models/widget_spec.rb
+
+Then the examples should all pass.
+
+Run in transactions (explicit)
+
+Given a file named “spec/models/widget_spec.rb” with:
+require "rails_helper"
+
+RSpec.configure do |c|
+ c.use_transactional_examples = true
+end
+
+RSpec.describe Widget, type: :model do
+ it "has none to begin with" do
+ expect(Widget.count).to eq 0
+ end
+
+ it "has one after adding one" do
+ Widget.create
+ expect(Widget.count).to eq 1
+ end
+
+ it "has none after one was created in a previous example" do
+ expect(Widget.count).to eq 0
+ end
+end
+
+When I run rspec spec/models/widget_spec.rb
+
+Then the examples should all pass.
+
+Disable transactions (explicit)
+
+Given a file named “spec/models/widget_spec.rb” with:
+require "rails_helper"
+
+RSpec.configure do |c|
+ c.use_transactional_examples = false
+ c.order = "defined"
+end
+
+RSpec.describe Widget, type: :model do
+ it "has none to begin with" do
+ expect(Widget.count).to eq 0
+ end
+
+ it "has one after adding one" do
+ Widget.create
+ expect(Widget.count).to eq 1
+ end
+
+ it "has one after one was created in a previous example" do
+ expect(Widget.count).to eq 1
+ end
+
+ after(:all) { Widget.destroy_all }
+end
+
+When I run rspec spec/models/widget_spec.rb
+
+Then the examples should all pass.
+
+Run in transactions with fixture
+
+Given a file named “spec/models/thing_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe Thing, type: :model do
+ fixtures :things
+ it "fixture method defined" do
+ things(:one)
+ end
+end
+
+Given a file named “spec/fixtures/things.yml” with:
+one:
+ name: MyString
+
+When I run rspec spec/models/thing_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/model-specs/verified-doubles/index.html b/docs/features/6-0/rspec-rails/model-specs/verified-doubles/index.html
new file mode 100644
index 000000000..f13807739
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/model-specs/verified-doubles/index.html
@@ -0,0 +1,23 @@
+
+
+
+
+Using verified doubles
+
+By default rspec verified doubles dont support dynamic methods on
+ instance_double. rspec-rails enabled this support for column
+ methods through an extension.
+
+Given a file named “spec/models/widget_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe Widget, type: :model do
+ it "has one after adding one" do
+ instance_double("Widget", :name => "my name")
+ end
+end
+
+When I run rspec spec/models/widget_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/request-specs/index.html b/docs/features/6-0/rspec-rails/request-specs/index.html
new file mode 100644
index 000000000..979e5c5b5
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/request-specs/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+Request specs
Topics
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/request-specs/request-spec/index.html b/docs/features/6-0/rspec-rails/request-specs/request-spec/index.html
new file mode 100644
index 000000000..b1bd6fd5b
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/request-specs/request-spec/index.html
@@ -0,0 +1,167 @@
+
+
+
+
+Request specs
+
+Request specs provide a thin wrapper around Rails’ integration tests, and are
+ designed to drive behavior through the full stack, including routing
+ (provided by Rails) and without stubbing (that’s up to you).
+
+Request specs are marked by type: :request or if you have set
+ config.infer_spec_type_from_file_location! by placing them in spec/requests.
+
+With request specs, you can:
+
+
+- specify a single request
+- specify multiple requests across multiple controllers
+- specify multiple requests across multiple sessions
+
+
+Check the rails documentation on integration tests for more information.
+
+RSpec provides two matchers that delegate to Rails assertions:
+ render_template # delegates to assert_template
+ redirect_to # delegates to assert_redirected_to
+
+Check the Rails docs for details on these methods as well.
+
+Capybara is not supported in
+ request specs. The recommended way to use Capybara is with
+ feature specs.
+
+Specify managing a Widget with Rails integration methods
+
+Given a file named “spec/requests/widgetmanagementspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "Widget management", type: :request do
+
+ it "creates a Widget and redirects to the Widget's page" do
+ get "/widgets/new"
+ expect(response).to render_template(:new)
+
+ post "/widgets", :params => { :widget => {:name => "My Widget"} }
+
+ expect(response).to redirect_to(assigns(:widget))
+ follow_redirect!
+
+ expect(response).to render_template(:show)
+ expect(response.body).to include("Widget was successfully created.")
+ end
+
+ it "does not render a different template" do
+ get "/widgets/new"
+ expect(response).to_not render_template(:show)
+ end
+end
+
+When I run rspec spec/requests/widget_management_spec.rb
+
+Then the example should pass.
+
+Requesting a JSON response
+
+Given a file named “spec/requests/widgetmanagementspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "Widget management", type: :request do
+ it "creates a Widget" do
+ headers = { "ACCEPT" => "application/json" }
+ post "/widgets", :params => { :widget => {:name => "My Widget"} }, :headers => headers
+
+ expect(response.content_type).to eq("application/json; charset=utf-8")
+ expect(response).to have_http_status(:created)
+ end
+end
+
+When I run rspec spec/requests/widget_management_spec.rb
+
+Then the example should pass.
+
+Providing JSON data
+
+Given a file named “spec/requests/widgetmanagementspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "Widget management", type: :request do
+
+ it "creates a Widget and redirects to the Widget's page" do
+ headers = { "CONTENT_TYPE" => "application/json" }
+ post "/widgets", :params => '{ "widget": { "name":"My Widget" } }', :headers => headers
+ expect(response).to redirect_to(assigns(:widget))
+ end
+
+end
+
+When I run rspec spec/requests/widget_management_spec.rb
+
+Then the example should pass.
+
+Using engine route helpers
+
+Given a file named “spec/requests/widgets_spec.rb” with:
+require "rails_helper"
+
+# A very simple Rails engine
+module MyEngine
+ class Engine < ::Rails::Engine
+ isolate_namespace MyEngine
+ end
+
+ class LinksController < ::ActionController::Base
+ def index
+ render plain: 'hit_engine_route'
+ end
+ end
+end
+
+MyEngine::Engine.routes.draw do
+ resources :links, :only => [:index]
+end
+
+Rails.application.routes.draw do
+ mount MyEngine::Engine => "/my_engine"
+end
+
+module MyEngine
+ RSpec.describe "Links", type: :request do
+ include Engine.routes.url_helpers
+
+ it "redirects to a random widget" do
+ get links_url
+ expect(response.body).to eq('hit_engine_route')
+ end
+ end
+end
+
+When I run rspec spec
+
+Then the example should pass.
+
+Testing subdomain constrained requests
+
+Given a file named “spec/requests/widgets_spec.rb” with:
+require "rails_helper"
+
+Rails.application.routes.draw do
+ resources :widgets, constraints: { subdomain: "api" }
+end
+
+RSpec.describe "Widget management", type: :request do
+ before { host! "api.example.com" }
+
+ it "creates a Widget" do
+ headers = { "ACCEPT" => "application/json" }
+ post "/widgets", :params => { :widget => { :name => "My Widget" } }, :headers => headers
+
+ expect(response.content_type).to start_with("application/json")
+ expect(response).to have_http_status(:created)
+ end
+end
+
+When I run rspec spec
+
+Then the example should pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/routing-specs/be-routable-matcher/index.html b/docs/features/6-0/rspec-rails/routing-specs/be-routable-matcher/index.html
new file mode 100644
index 000000000..9e2234cf3
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/routing-specs/be-routable-matcher/index.html
@@ -0,0 +1,85 @@
+
+
+
+
+be_routable matcher
+
+The be_routable matcher is best used with should_not to specify that a
+ given route should not be routable. It is available in routing specs (in
+ spec/routing) and controller specs (in spec/controllers).
+
+Specify routeable route should not be routable (fails)
+
+Given a file named “spec/routing/widgetsroutingspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "routes for Widgets", type: :routing do
+ it "does not route to widgets" do
+ expect(:get => "/widgets").not_to be_routable
+ end
+end
+
+When I run rspec spec/routing/widgets_routing_spec.rb
+
+Then the output should contain “1 example, 1 failure”.
+
+Specify non-routeable route should not be routable (passes)
+
+Given a file named “spec/routing/widgetsroutingspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "routes for Widgets", type: :routing do
+ it "does not route to widgets/foo/bar" do
+ expect(:get => "/widgets/foo/bar").not_to be_routable
+ end
+end
+
+When I run rspec spec/routing/widgets_routing_spec.rb
+
+Then the examples should all pass.
+
+Specify routeable route should be routable (passes)
+
+Given a file named “spec/routing/widgetsroutingspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "routes for Widgets", type: :routing do
+ it "routes to /widgets" do
+ expect(:get => "/widgets").to be_routable
+ end
+end
+
+When I run rspec spec/routing/widgets_routing_spec.rb
+
+Then the examples should all pass.
+
+Specify non-routeable route should be routable (fails)
+
+Given a file named “spec/routing/widgetsroutingspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "routes for Widgets", type: :routing do
+ it "routes to widgets/foo/bar" do
+ expect(:get => "/widgets/foo/bar").to be_routable
+ end
+end
+
+When I run rspec spec/routing/widgets_routing_spec.rb
+
+Then the output should contain “1 example, 1 failure”.
+
+Use be_routable in a controller spec
+
+Given a file named “spec/controllers/widgetscontrollerspec.rb” with:
+require "rails_helper"
+
+RSpec.describe WidgetsController, type: :controller do
+ it "routes to /widgets" do
+ expect(:get => "/widgets").to be_routable
+ end
+end
+
+When I run rspec spec/controllers/widgets_controller_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/routing-specs/engine-routes/index.html b/docs/features/6-0/rspec-rails/routing-specs/engine-routes/index.html
new file mode 100644
index 000000000..0eb91c8f9
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/routing-specs/engine-routes/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+Using engine routes
+
+Routing specs can specify the routeset that will be used for the example
+ group. This is most useful when testing Rails engines.
+
+Specify engine routes
+
+Given a file named “spec/routing/engineroutesspec.rb” with:
+require "rails_helper"
+
+# A very simple Rails engine
+module MyEngine
+ class Engine < ::Rails::Engine
+ isolate_namespace MyEngine
+ end
+
+ Engine.routes.draw do
+ resources :widgets, :only => [:index]
+ end
+
+ class WidgetsController < ::ActionController::Base
+ def index
+ end
+ end
+end
+
+RSpec.describe MyEngine::WidgetsController, type: :routing do
+ routes { MyEngine::Engine.routes }
+
+ it "routes to the list of all widgets" do
+ expect(:get => widgets_path).
+ to route_to(:controller => "my_engine/widgets", :action => "index")
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/routing-specs/index.html b/docs/features/6-0/rspec-rails/routing-specs/index.html
new file mode 100644
index 000000000..6f7f69a82
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/routing-specs/index.html
@@ -0,0 +1,21 @@
+
+
+
+
+Routing specs
+
+Routing specs are marked by type: :routing or if you have set
+config.infer_spec_type_from_file_location! by placing them in spec/routing.
+
+Simple apps with nothing but standard RESTful routes won’t get much value from
+routing specs, but they can provide significant value when used to specify
+customized routes, like vanity links, slugs, etc.
+expect(:get => "/articles/2012/11/when-to-use-routing-specs").to route_to(
+ :controller => "articles",
+ :month => "2012-11",
+ :slug => "when-to-use-routing-specs"
+)
+
+They are also valuable for routes that should not be available:
+expect(:delete => "/accounts/37").not_to be_routable
+
Topics
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/routing-specs/named-routes/index.html b/docs/features/6-0/rspec-rails/routing-specs/named-routes/index.html
new file mode 100644
index 000000000..190da7950
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/routing-specs/named-routes/index.html
@@ -0,0 +1,24 @@
+
+
+
+
+Using named routes
+
+Routing specs have access to named routes.
+
+Access named route
+
+Given a file named “spec/routing/widgetroutesspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "routes to the widgets controller", type: :routing do
+ it "routes a named route" do
+ expect(:get => new_widget_path).
+ to route_to(:controller => "widgets", :action => "new")
+ end
+end
+
+When I run rspec spec
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/routing-specs/route-to-matcher/index.html b/docs/features/6-0/rspec-rails/routing-specs/route-to-matcher/index.html
new file mode 100644
index 000000000..c97d82d43
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/routing-specs/route-to-matcher/index.html
@@ -0,0 +1,94 @@
+
+
+
+
+route_to matcher
+
+The route_to matcher specifies that a request (verb + path) is routable.
+ It is most valuable when specifying routes other than standard RESTful
+ routes.
+ expect(get("/")).to route_to("welcome#index") # new in 2.6.0
+
+ or
+
+ expect(:get => "/").to route_to(:controller => "welcome")
+
+Passing route spec with shortcut syntax
+
+Given a file named “spec/routing/widgetsroutingspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "routes for Widgets", type: :routing do
+ it "routes /widgets to the widgets controller" do
+ expect(get("/widgets")).
+ to route_to("widgets#index")
+ end
+end
+
+When I run rspec spec/routing/widgets_routing_spec.rb
+
+Then the examples should all pass.
+
+Passing route spec with verbose syntax
+
+Given a file named “spec/routing/widgetsroutingspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "routes for Widgets", type: :routing do
+ it "routes /widgets to the widgets controller" do
+ expect(:get => "/widgets").
+ to route_to(:controller => "widgets", :action => "index")
+ end
+end
+
+When I run rspec spec/routing/widgets_routing_spec.rb
+
+Then the examples should all pass.
+
+Route spec for a route that doesn’t exist (fails)
+
+Given a file named “spec/routing/widgetsroutingspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "routes for Widgets", type: :routing do
+ it "routes /widgets/foo to the /foo action" do
+ expect(get("/widgets/foo")).to route_to("widgets#foo")
+ end
+end
+
+When I run rspec spec/routing/widgets_routing_spec.rb
+
+Then the output should contain “1 failure”.
+
+Route spec for a namespaced route with shortcut specifier
+
+Given a file named “spec/routing/adminroutingspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "routes for Widgets", type: :routing do
+ it "routes /admin/accounts to the admin/accounts controller" do
+ expect(get("/admin/accounts")).
+ to route_to("admin/accounts#index")
+ end
+end
+
+When I run rspec spec/routing/admin_routing_spec.rb
+
+Then the examples should all pass.
+
+Route spec for a namespaced route with verbose specifier
+
+Given a file named “spec/routing/adminroutingspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "routes for Widgets", type: :routing do
+ it "routes /admin/accounts to the admin/accounts controller" do
+ expect(get("/admin/accounts")).
+ to route_to(:controller => "admin/accounts", :action => "index")
+ end
+end
+
+When I run rspec spec/routing/admin_routing_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/system-specs/index.html b/docs/features/6-0/rspec-rails/system-specs/index.html
new file mode 100644
index 000000000..eb8f73422
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/system-specs/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+System specs
Topics
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/system-specs/system-specs/index.html b/docs/features/6-0/rspec-rails/system-specs/system-specs/index.html
new file mode 100644
index 000000000..621776fd1
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/system-specs/system-specs/index.html
@@ -0,0 +1,119 @@
+
+
+
+
+System specs
+
+System specs are RSpec’s wrapper around Rails’ own
+ system tests.
+
+
+System tests allow you to test user interactions with your application,
+running tests in either a real or a headless browser. System tests use
+Capybara under the hood.
+
+By default, system tests are run with the Selenium driver, using the
+Chrome browser, and a screen size of 1400x1400. The next section explains
+how to change the default settings.
+
+
+System specs are marked by setting type to :system, e.g. type: :system.
+
+The Capybara gem is automatically required, and Rails includes it in
+ generated application Gemfiles. Configure a webserver (e.g.
+ Capybara.server = :webrick) before attempting to use system specs.
+
+RSpec does not use your ApplicationSystemTestCase helper. Instead it
+ uses the default driven_by(:selenium) from Rails. If you want to override
+ this behaviour you can call driven_by manually in a test.
+
+System specs run in a transaction. So unlike feature specs with
+ javascript, you do not need DatabaseCleaner.
+
+System specs driven by rack_test
+
+Given a file named “spec/system/widgetsystemspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "Widget management", type: :system do
+ before do
+ driven_by(:rack_test)
+ end
+
+ it "enables me to create widgets" do
+ visit "/widgets/new"
+
+ fill_in "Name", :with => "My Widget"
+ click_button "Create Widget"
+
+ expect(page).to have_text("Widget was successfully created.")
+ end
+end
+
+When I run rspec spec/system/widget_system_spec.rb
+
+Then the exit status should be 0
+
+And the output should contain “1 example, 0 failures”.
+
+The ActiveJob queue_adapter can be changed
+
+Given a file named “spec/system/somejobsystem_spec.rb” with:
+require "rails_helper"
+
+class SomeJob < ActiveJob::Base
+ cattr_accessor :job_ran
+
+ def perform
+ @@job_ran = true
+ end
+end
+
+RSpec.describe "spec/system/some_job_system_spec.rb", type: :system do
+ describe "#perform_later" do
+ before do
+ ActiveJob::Base.queue_adapter = :inline
+ end
+
+ it "perform later SomeJob" do
+ expect(ActiveJob::Base.queue_adapter).to be_an_instance_of(ActiveJob::QueueAdapters::InlineAdapter)
+
+ SomeJob.perform_later
+
+ expect(SomeJob.job_ran).to eq(true)
+ end
+ end
+end
+
+When I run rspec spec/system/some_job_system_spec.rb
+
+Then the example should pass.
+
+System specs driven by seleniumchromeheadless
+
+Given a file named “spec/system/widgetsystemspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "Widget management", type: :system do
+ before do
+ driven_by(:selenium_chrome_headless)
+ end
+
+ it "enables me to create widgets" do
+ visit "/widgets/new"
+
+ fill_in "Name", :with => "My Widget"
+ click_button "Create Widget"
+
+ expect(page).to have_text("Widget was successfully created.")
+ end
+end
+
+When I run rspec spec/system/widget_system_spec.rb
+
+Then the output should contain “1 example, 0 failures”
+
+And the output should not contain “starting Puma”
+
+And the exit status should be 0.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/upgrade/index.html b/docs/features/6-0/rspec-rails/upgrade/index.html
new file mode 100644
index 000000000..5c0f528f6
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/upgrade/index.html
@@ -0,0 +1,24 @@
+
+
+
+
+Upgrading from rspec-rails 5.x to version 6
+
+RSpec Rails 6 is a major version under semantic versioning, it also follows our new versioning strategy for RSpec-Rails, which is to keep in step with Rails supported versions. Thus it supports 6.1 and 7.0. There are no changes required to upgrade to RSpec Rails 6 if you are using a supported version of Rails.
+
+If you are using an older version of Rails, you can use 5.x which hard supports 5.2 and 6.x.
+
+Upgrading from rspec-rails 4.x to version 5
+
+RSpec Rails 5 is a major version under semantic versioning, it also follows our new versioning strategy for RSpec-Rails, which is to keep in step with Rails supported versions. Thus it supports 5.2, 6.0 and 6.1. There are no changes required to upgrade to RSpec Rails 5 if you are using a supported version of Rails.
+
+If you are using an older version of Rails, you can use 4.x which hard supports 5.0 and 5.1, and soft supports 4.2 (which is unmaintained).
+
+Upgrading from rspec-rails 3.x to version 4
+
+RSpec Rails 4 is a major version under semantic versioning, it allowed us to change the supported Rails versions to 5 and 6 only. There are no changes required to upgrade to RSpec Rails 4 if you are using Rails 5 or 6.
+
+If you are using Rails 4.2 you can use RSpec Rails 4, but note that support for it is not maintained, we consider this a breaking change hence the version change, and you must be on Ruby 2.2 as a minimum.
+
+If you are upgrading from an earlier version of RSpec Rails, please consult the upgrading 2.x to 3.x guide.
+Topics
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/view-specs/index.html b/docs/features/6-0/rspec-rails/view-specs/index.html
new file mode 100644
index 000000000..2d45e88fe
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/view-specs/index.html
@@ -0,0 +1,5 @@
+
+
+
+
+View specs
Topics
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/view-specs/inferred-controller-path/index.html b/docs/features/6-0/rspec-rails/view-specs/inferred-controller-path/index.html
new file mode 100644
index 000000000..934b51f80
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/view-specs/inferred-controller-path/index.html
@@ -0,0 +1,52 @@
+
+
+
+
+View specs infer controller’s path and action
+
+Infer controller path
+
+Given a file named “spec/views/widgets/new.html.erb_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "widgets/new" do
+ it "infers the controller path" do
+ expect(controller.request.path_parameters[:controller]).to eq("widgets")
+ expect(controller.controller_path).to eq("widgets")
+ end
+end
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
+Infer action
+
+Given a file named “spec/views/widgets/new.html.erb_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "widgets/new" do
+ it "infers the controller action" do
+ expect(controller.request.path_parameters[:action]).to eq("new")
+ end
+end
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
+Do not infer action in a partial
+
+Given a file named “spec/views/widgets/form.html.erbspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "widgets/_form" do
+ it "includes a link to new" do
+ expect(controller.request.path_parameters[:action]).to be_nil
+ end
+end
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/view-specs/stub-template/index.html b/docs/features/6-0/rspec-rails/view-specs/stub-template/index.html
new file mode 100644
index 000000000..b0f7c96bd
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/view-specs/stub-template/index.html
@@ -0,0 +1,55 @@
+
+
+
+
+Using stub_template
+
+In order to isolate view specs from the partials rendered by the primary
+ view, rspec-rails (since 2.2) provides the stub_template method.
+
+Stub a template that does not exist
+
+Given a file named “spec/views/gadgets/list.html.erb_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "gadgets/list" do
+ it "renders the gadget partial for each gadget" do
+ assign(:gadgets, [
+ double(:name => "First"),
+ double(:name => "Second")
+ ])
+ stub_template "gadgets/_gadget.html.erb" => "<%= gadget.name %><br/>"
+ render
+ expect(rendered).to match /First/
+ expect(rendered).to match /Second/
+ end
+end
+
+And a file named “app/views/gadgets/list.html.erb” with:
+<%= render :partial => "gadget", :collection => @gadgets %>
+
+When I run rspec spec/views/gadgets/list.html.erb_spec.rb
+
+Then the examples should all pass.
+
+Stub a template that exists
+
+Given a file named “spec/views/gadgets/edit.html.erb_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "gadgets/edit" do
+ before(:each) do
+ @gadget = assign(:gadget, Gadget.create!)
+ end
+
+ it "renders the form partial" do
+ stub_template "gadgets/_form.html.erb" => "This content"
+ render
+ expect(rendered).to match /This content/
+ end
+end
+
+When I run rspec spec/views/gadgets/edit.html.erb_spec.rb
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/features/6-0/rspec-rails/view-specs/view-spec/index.html b/docs/features/6-0/rspec-rails/view-specs/view-spec/index.html
new file mode 100644
index 000000000..a63a73297
--- /dev/null
+++ b/docs/features/6-0/rspec-rails/view-specs/view-spec/index.html
@@ -0,0 +1,298 @@
+
+
+
+
+View specs
+
+View specs are marked by type: :view
+ or if you have set config.infer_spec_type_from_file_location!
+ by placing them in spec/views.
+
+Use them to test the content of view templates
+ without invoking a specific controller.
+ They generally follow three steps:
+ assign(:widget, Widget.new) # sets @widget = Widget.new in the view template
+
+ render
+
+ expect(rendered).to match(/text/)
+
+
+Use the assign method to set instance variables in the view.
+Use the render method to render the view.
+Set expectations against the resulting rendered template.
+
+
+View specs render the described view file
+
+Given a file named “spec/views/widgets/index.html.erb_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "widgets/index" do
+ it "displays all the widgets" do
+ assign(:widgets, [
+ Widget.create!(:name => "slicer"),
+ Widget.create!(:name => "dicer")
+ ])
+
+ render
+
+ expect(rendered).to match /slicer/
+ expect(rendered).to match /dicer/
+ end
+end
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
+View specs can have before block and nesting
+
+Given a file named “spec/views/widgets/index.html.erb_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "widgets/index" do
+
+ context "with 2 widgets" do
+ before(:each) do
+ assign(:widgets, [
+ Widget.create!(:name => "slicer"),
+ Widget.create!(:name => "dicer")
+ ])
+ end
+
+ it "displays both widgets" do
+ render
+
+ expect(rendered).to match /slicer/
+ expect(rendered).to match /dicer/
+ end
+ end
+end
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
+View specs can explicitly render templates
+
+Given a file named “spec/views/widgets/widget.html.erb_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "rendering the widget template" do
+ it "displays the widget" do
+ assign(:widget, Widget.create!(:name => "slicer"))
+
+ render :template => "widgets/widget"
+
+ expect(rendered).to match /slicer/
+ end
+end
+
+And a file named “app/views/widgets/widget.html.erb” with:
+<h2><%= @widget.name %></h2>
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
+View specs can render templates in layouts
+
+Given a file named “spec/views/widgets/widget.html.erb_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "rendering the widget template" do
+ context "with the inventory layout" do
+ it "displays the widget" do
+ assign(:widget, Widget.create!(:name => "slicer"))
+
+ render :template => "widgets/widget", :layout => "layouts/inventory"
+
+ expect(rendered).to match /slicer/
+ end
+ end
+end
+
+And a file named “app/views/widgets/widget.html.erb” with:
+<h2><%= @widget.name %></h2>
+
+And a file named “app/views/layouts/inventory.html.erb” with:
+<%= yield %>
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
+View specs can have description that includes the format and handler
+
+Given a file named “spec/views/widgets/widget.xml.erb_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "widgets/widget.html.erb" do
+ it "renders the HTML template" do
+ render
+
+ expect(rendered).to match /HTML/
+ end
+end
+
+RSpec.describe "widgets/widget.xml.erb" do
+ it "renders the XML template" do
+ render
+
+ expect(rendered).to match /XML/
+ end
+end
+
+And a file named “app/views/widgets/widget.html.erb” with:
+HTML
+
+And a file named “app/views/widgets/widget.xml.erb” with:
+XML
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
+View specs can render locals in a partial
+
+Given a file named “spec/views/widgets/widget.html.erbspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "rendering locals in a partial" do
+ it "displays the widget" do
+ widget = Widget.create!(:name => "slicer")
+
+ render :partial => "widgets/widget", :locals => {:widget => widget}
+
+ expect(rendered).to match /slicer/
+ end
+end
+
+And a file named “app/views/widgets/_widget.html.erb” with:
+<h3><%= widget.name %></h3>
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
+View specs can render locals in an implicit partial
+
+Given a file named “spec/views/widgets/widget.html.erbspec.rb” with:
+require "rails_helper"
+
+RSpec.describe "rendering locals in a partial" do
+ it "displays the widget" do
+ widget = Widget.create!(:name => "slicer")
+
+ render "widgets/widget", :widget => widget
+
+ expect(rendered).to match /slicer/
+ end
+end
+
+And a file named “app/views/widgets/_widget.html.erb” with:
+<h3><%= widget.name %></h3>
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
+View specs can render text
+
+Given a file named “spec/views/widgets/direct.html.erb_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "rendering text directly" do
+ it "displays the given text" do
+
+ render :plain => "This is directly rendered"
+
+ expect(rendered).to match /directly rendered/
+ end
+end
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
+View specs can stub a helper method
+
+Given a file named “app/helpers/application_helper.rb” with:
+module ApplicationHelper
+ def admin?
+ false
+ end
+end
+
+And a file named “app/views/secrets/index.html.erb” with:
+<%- if admin? %>
+ <h1>Secret admin area</h1>
+<%- end %>
+
+And a file named “spec/views/secrets/index.html.erb_spec.rb” with:
+require 'rails_helper'
+
+RSpec.describe 'secrets/index' do
+ before do
+ allow(view).to receive(:admin?).and_return(true)
+ end
+
+ it 'checks for admin access' do
+ render
+ expect(rendered).to match /Secret admin area/
+ end
+end
+
+When I run rspec spec/views/secrets
+
+Then the examples should all pass.
+
+View specs use symbols for keys in request.path_parameters to match Rails style
+
+Given a file named “spec/views/widgets/index.html.erb_spec.rb” with:
+require "rails_helper"
+
+RSpec.describe "controller.request.path_parameters" do
+ it "matches the Rails environment by using symbols for keys" do
+ [:controller, :action].each { |k| expect(controller.request.path_parameters.keys).to include(k) }
+ end
+end
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
+View spec actions that do not require extra parameters have request.fullpath set
+
+Given a file named “spec/views/widgets/index.html.erb_spec.rb” with:
+ require "rails_helper"
+
+ RSpec.describe "widgets/index" do
+ it "has a request.fullpath that is defined" do
+ expect(controller.request.fullpath).to eq widgets_path
+ end
+ end
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
+View spec actions that require extra parameters have request.fullpath set when the developer supplies them
+
+Given a file named “spec/views/widgets/show.html.erb_spec.rb” with:
+ require "rails_helper"
+
+ RSpec.describe "widgets/show" do
+ it "displays the widget with id: 1" do
+ widget = Widget.create!(:name => "slicer")
+ controller.extra_params = { :id => widget.id }
+
+ expect(controller.request.fullpath).to eq widget_path(widget)
+ end
+ end
+
+When I run rspec spec/views
+
+Then the examples should all pass.
+
\ No newline at end of file
diff --git a/docs/ja/blog/2015/11/rspec-3-4-has-been-released/index.html b/docs/ja/blog/2015/11/rspec-3-4-has-been-released/index.html
index c7a92ebf5..d712a0107 100644
--- a/docs/ja/blog/2015/11/rspec-3-4-has-been-released/index.html
+++ b/docs/ja/blog/2015/11/rspec-3-4-has-been-released/index.html
@@ -13,9 +13,9 @@
このリリースに向けて力になってくれたみなさん、ありがとう!
-主要な変更
+主要な変更
-Core: Bisect アルゴリズムの改善
+Core: Bisect アルゴリズムの改善
RSpec 3.3 では、
実行順序依存の失敗の原因を探す上で、
@@ -41,17 +41,16 @@
Core: Bisect アルゴリズムの改善
こちらの pull request を参照してください。
アルゴリズムの理解に役立つ図も載っています。
-Core: 失敗時の出力の改善
+Core: 失敗時の出力の改善
RSpec は失敗時のわかりやすいログ出力をこれまでずっと重要視してきましたが、
3.4 では様々な方法によってさらに改善されました。
-複数行のコードスニペット
+複数行のコードスニペット
RSpec は、エクスペクテーションが失敗したときにそのコードスニペットを表示します。
RSpec 3.4 以前では、エクスペクテーションが1行に収まっている場合は問題ありませんでしたが、
以下のように複数行で記述した場合、
-
expect {
MyNamespace::MyClass.some_long_method_name(:with, :some, :arguments)
}.to raise_error(/some error snippet/)
@@ -68,7 +67,7 @@ 複数行のコードスニペット
これを実装してくれた Yuji Nakayama、ありがとう!
-coderayがインストール済みの場合、シンタックスハイライトが有効に
+coderayがインストール済みの場合、シンタックスハイライトが有効に
これをさらに一歩進めて、coderay gem がインストールされている場合、
RSpec 3.4 はコードスニペットのシンタックスハイライトを行うようになりました。
@@ -76,7 +75,7 @@
coderayがインストール済みの場合、シ

-失敗元の行の検出の改善
+失敗元の行の検出の改善
RSpec は、例外のスタックトレース中から適切なフレームを調べることで、失敗の元となったコードスニペットを探し出します。
これを行う上で、単純にスタックトレースの一番上のフレームを使うこともできますが、
@@ -96,24 +95,21 @@
失敗元の行の検出の改善
もし該当するフレームが見つからなかった場合は一番最初のスタックフレームにフォールバックします。
もう Unable to find matching line from backtrace が表示されることはありません!
-Expectations: 複合エクスペクテーションの失敗時メッセージの改善
+Expectations: 複合エクスペクテーションの失敗時メッセージの改善
さらに失敗時出力の改善が続きます。
rspec-expectations 3.4 では、複合エクスペクテーション(compound expectations)の失敗メッセージが改善されました。
これまでは複数の失敗メッセージを単純に1行に連結しており、例えば以下のようなエクスペクテーションの場合、
-
expect(lyrics).to start_with("There must be some kind of way out of here")
.and include("No reason to get excited")
このような読みにくいメッセージが出力されてしまっていました。
-
1) All Along the Watchtower has the expected lyrics
Failure/Error: expect(lyrics).to start_with("There must be some kind of way out of here")
expected "I stand up next to a mountain And I chop it down with the edge of my hand" to start with "There must be some kind of way out of here" and expected "I stand up next to a mountain And I chop it down with the edge of my hand" to include "No reason to get excited"
# ./spec/example_spec.rb:20:in `block (2 levels) in <top (required)>'
RSpec 3.4 では、それぞれのメッセージが個別に表示されるようになり、読みやすくなりました。
-
1) All Along the Watchtower has the expected lyrics
Failure/Error:
expect(lyrics).to start_with("There must be some kind of way out of here")
@@ -126,16 +122,14 @@ Expectations: 複合エクスペクテーションの失
expected "I stand up next to a mountain And I chop it down with the edge of my hand" to include "No reason to get excited"
# ./spec/example_spec.rb:20:in `block (2 levels) in <top (required)>'
-Expectations: match マッチャへの with_captures の追加
+Expectations: match マッチャへの with_captures の追加
RSpec 3.4 では、match マッチャに新しい機能が追加され、正規表現のキャプチャを指定することができるようになりました。
新しい with_captures メソッドを使って、このようにインデックスベースのキャプチャを指定することができます。
-
year_regex = /(\d{4})\-(\d{2})\-(\d{2})/
expect(year_regex).to match("2015-12-25").with_captures("2015", "12", "25")
また、名前付きキャプチャを指定することも可能です。
-
year_regex = /(?<year>\d{4})\-(?<month>\d{2})\-(?<day>\d{2})/
expect(year_regex).to match("2015-12-25").with_captures(
year: "2015",
@@ -145,13 +139,12 @@ Expectations: match マ
Sam Phippen と、この実装にあたって協力してくれた Jason Karns、ありがとう。
-Rails: ActiveJob のための新しい have_enqueued_job マッチャ
+Rails: ActiveJob のための新しい have_enqueued_job マッチャ
Rails 4.2 には ActiveJob が組み込まれました。
rspec-rails 3.4 では、任意のコードがジョブをキューに加えることを指定するためのマッチャが追加されました。
このマッチャはメソッドチェーンによるインターフェースを持っており、
rspec-mock を使ったことがあれば見覚えがあるのではないでしょうか。
-
expect {
HeavyLiftingJob.perform_later
}.to have_enqueued_job
@@ -182,134 +175,135 @@ Rails: ActiveJob のための新し
この機能を実装してくれた Wojciech Wnętrzak、ありがとう!
-統計
+統計
-全体:
+全体:
- - 総コミット: 502
- - マージされた pull request: 163
- - 48 コントリビュータ: Aaron Kromer, Alex Dowad, Alex Egan, Alex Pounds, Andrew Horner, Ara Hacopian, Ashley Engelund (aenw / weedySeaDragon), Ben Woosley, Bradley Schaefer, Brian John, Bryce McDonnell, Chris Zetter, Dan Kohn, Dave Marr, Dennis Günnewig, Diego Carrion, Edward Park, Gavin Miller, Jack Scotti, Jam Black, Jamela Black, Jason Karns, Jon Moss, Jon Rowe, Leo Cassarani, Liz Rush, Marek Tuchowski, Max Meyer, Myron Marston, Nikki Murray, Pavel Pravosud, Sam Phippen, Sebastián Tello, Simon Coffey, Tim Mertens, Wojciech Wnętrzak, Xavier Shay, Yuji Nakayama, Zshawn Syed, bennacer860, bootstraponline, draffensperger, georgeu2000, jackscotti, mrageh, rafik, takiy33, unmanbearpig
+- 総コミット: 502
+- マージされた pull request: 163
+- 48 コントリビュータ: Aaron Kromer, Alex Dowad, Alex Egan, Alex Pounds, Andrew Horner, Ara Hacopian, Ashley Engelund (aenw / weedySeaDragon), Ben Woosley, Bradley Schaefer, Brian John, Bryce McDonnell, Chris Zetter, Dan Kohn, Dave Marr, Dennis Günnewig, Diego Carrion, Edward Park, Gavin Miller, Jack Scotti, Jam Black, Jamela Black, Jason Karns, Jon Moss, Jon Rowe, Leo Cassarani, Liz Rush, Marek Tuchowski, Max Meyer, Myron Marston, Nikki Murray, Pavel Pravosud, Sam Phippen, Sebastián Tello, Simon Coffey, Tim Mertens, Wojciech Wnętrzak, Xavier Shay, Yuji Nakayama, Zshawn Syed, bennacer860, bootstraponline, draffensperger, georgeu2000, jackscotti, mrageh, rafik, takiy33, unmanbearpig
-rspec-core:
+rspec-core:
- - 総コミット: 180
- - マージされた pull request: 52
- - 24 コントリビュータ: Aaron Kromer, Alex Pounds, Ashley Engelund (aenw / weedySeaDragon), Ben Woosley, Bradley Schaefer, Brian John, Edward Park, Gavin Miller, Jack Scotti, Jon Moss, Jon Rowe, Leo Cassarani, Marek Tuchowski, Myron Marston, Sebastián Tello, Simon Coffey, Tim Mertens, Yuji Nakayama, bennacer860, bootstraponline, draffensperger, jackscotti, mrageh, takiy33
+- 総コミット: 180
+- マージされた pull request: 52
+- 24 コントリビュータ: Aaron Kromer, Alex Pounds, Ashley Engelund (aenw / weedySeaDragon), Ben Woosley, Bradley Schaefer, Brian John, Edward Park, Gavin Miller, Jack Scotti, Jon Moss, Jon Rowe, Leo Cassarani, Marek Tuchowski, Myron Marston, Sebastián Tello, Simon Coffey, Tim Mertens, Yuji Nakayama, bennacer860, bootstraponline, draffensperger, jackscotti, mrageh, takiy33
-rspec-expectations:
+rspec-expectations:
- - 総コミット: 93
- - マージされた pull request: 34
- - 17 コントリビュータ: Aaron Kromer, Alex Egan, Bradley Schaefer, Brian John, Dennis Günnewig, Jason Karns, Jon Moss, Jon Rowe, Max Meyer, Myron Marston, Nikki Murray, Sam Phippen, Xavier Shay, Yuji Nakayama, Zshawn Syed, mrageh, unmanbearpig
+- 総コミット: 93
+- マージされた pull request: 34
+- 17 コントリビュータ: Aaron Kromer, Alex Egan, Bradley Schaefer, Brian John, Dennis Günnewig, Jason Karns, Jon Moss, Jon Rowe, Max Meyer, Myron Marston, Nikki Murray, Sam Phippen, Xavier Shay, Yuji Nakayama, Zshawn Syed, mrageh, unmanbearpig
-rspec-mocks:
+rspec-mocks:
- - 総コミット: 77
- - マージされた pull request: 26
- - 12 コントリビュータ: Aaron Kromer, Alex Dowad, Alex Egan, Brian John, Bryce McDonnell, Jon Moss, Jon Rowe, Liz Rush, Myron Marston, Pavel Pravosud, Sam Phippen, georgeu2000
+- 総コミット: 77
+- マージされた pull request: 26
+- 12 コントリビュータ: Aaron Kromer, Alex Dowad, Alex Egan, Brian John, Bryce McDonnell, Jon Moss, Jon Rowe, Liz Rush, Myron Marston, Pavel Pravosud, Sam Phippen, georgeu2000
-rspec-rails:
+rspec-rails:
- - 総コミット: 97
- - マージされた pull request: 31
- - 16 コントリビュータ: Aaron Kromer, Alex Egan, Ara Hacopian, Bradley Schaefer, Brian John, Chris Zetter, Dan Kohn, Dave Marr, Diego Carrion, Jam Black, Jamela Black, Jon Moss, Jon Rowe, Myron Marston, Nikki Murray, Wojciech Wnętrzak
+- 総コミット: 97
+- マージされた pull request: 31
+- 16 コントリビュータ: Aaron Kromer, Alex Egan, Ara Hacopian, Bradley Schaefer, Brian John, Chris Zetter, Dan Kohn, Dave Marr, Diego Carrion, Jam Black, Jamela Black, Jon Moss, Jon Rowe, Myron Marston, Nikki Murray, Wojciech Wnętrzak
-rspec-support:
+rspec-support:
- - 総コミット: 55
- - マージされた pull request: 20
- - 10 コントリビュータ: Aaron Kromer, Alex Egan, Andrew Horner, Bradley Schaefer, Brian John, Jon Rowe, Myron Marston, Xavier Shay, Yuji Nakayama, rafik
+- 総コミット: 55
+- マージされた pull request: 20
+- 10 コントリビュータ: Aaron Kromer, Alex Egan, Andrew Horner, Bradley Schaefer, Brian John, Jon Rowe, Myron Marston, Xavier Shay, Yuji Nakayama, rafik
-ドキュメント
+ドキュメント
-API ドキュメント
+API ドキュメント
- - rspec-core
- - rspec-expectations
- - rspec-mocks
- - rspec-rails
+- rspec-core
+- rspec-expectations
+- rspec-mocks
+- rspec-rails
-Cucumber フィーチャ
+Cucumber フィーチャ
- - rspec-core
- - rspec-expectations
- - rspec-mocks
- - rspec-rails
+- rspec-core
+- rspec-expectations
+- rspec-mocks
+- rspec-rails
-リリースノート
+リリースノート
+
+rspec-core 3.4.0
-rspec-core 3.4.0
改善:
- - 複数の
--pattern オプションが指定されたとき、それらを統合して --pattern=1,2,...,n と等価に扱うようにしました。
+ - 複数の
--pattern オプションが指定されたとき、それらを統合して --pattern=1,2,...,n と等価に扱うようにしました。
(Jon Rowe, #2002)
- RSpec::Core::Example オブジェクトの inspect と to_s の出力を、Ruby 標準の冗長過ぎる出力を置き換えることで改善しました。
+RSpec::Core::Example オブジェクトの inspect と to_s の出力を、Ruby 標準の冗長過ぎる出力を置き換えることで改善しました。
(Gavin Miller, #1922)
- silence_filter_announcements 設定オプションを追加しました。
+silence_filter_announcements 設定オプションを追加しました。
(David Raffensperger, #2007)
- Reporter プロトコルに、example の実行結果にかかわらず常に呼び出される example_finished 通知(optional)を追加しました。
+Reporter プロトコルに、example の実行結果にかかわらず常に呼び出される example_finished 通知(optional)を追加しました。
(Jon Rowe, #2013)
- --bisect を並べ替えベースのアルゴリズムから再帰ベースに変更しました。
+--bisect を並べ替えベースのアルゴリズムから再帰ベースに変更しました。
これによって、失敗する example が他の複数の example 群に依存にしているケースによりうまく対応できるようになり、
最小限の組み合わせに到達するまでの実行回数も減りました。
(Simon Coffey, #1997)
- - 単純なフィルタ(
:symbol キーのみ)が、真 (truthy) と評価された場合にも適用されるようになりました。
+ - 単純なフィルタ(
:symbol キーのみ)が、真 (truthy) と評価された場合にも適用されるようになりました。
(Tim Mertens, #2035)
- - Windows で RSpec の
--color オプションを使った場合に表示される、ansicon についての不要な警告を削除しました。
+ - Windows で RSpec の
--color オプションを使った場合に表示される、ansicon についての不要な警告を削除しました。
(Ashley Engelund, #2038)
- - RSpec が警告を表示しようとしたときに例外を発生させるためのオプションを追加しました。
+
- RSpec が警告を表示しようとしたときに例外を発生させるためのオプションを追加しました。
(Jon Rowe, #2052)
- - 失敗やエラーの元となった
cause が存在している場合、それを出力に含めるようにしました。
+ - 失敗やエラーの元となった
cause が存在している場合、それを出力に含めるようにしました。
(Adam Magan)
- NoMemoryError、SignalExcepetion、Interrupt、SystemExit を rescue しないようにしました。
+NoMemoryError、SignalExcepetion、Interrupt、SystemExit を rescue しないようにしました。
これらに干渉するのは危険なためです。
(Myron Marston, #2063)
- - バックトレースがあなたのプロジェクト由来なのか外部ライブラリ由来なのかを RSpec が判断するための
+
- バックトレースがあなたのプロジェクト由来なのか外部ライブラリ由来なのかを RSpec が判断するための
config.project_source_dirs 設定を追加しました。
デフォルトで spec、lib、app が設定されていますが変更可能です。
(Myron Marston, #2088)
- - 失敗元の行の検出を、spec ファイル内だけでなくプロジェクトディレクトリ全体から探すように改善しました。
+
- 失敗元の行の検出を、spec ファイル内だけでなくプロジェクトディレクトリ全体から探すように改善しました。
さらにプロジェクトディレクトリ内で該当の行が見つからなかった場合は、
バックトレースの1番目の行にフォールバックします。
-これによって "Unable to find matching line from backtrace" というメッセージが表示されることは事実上なくなります。
+これによって “Unable to find matching line from backtrace” というメッセージが表示されることは事実上なくなります。
(Myron Marston, #2088)
- - 失敗時の出力に追加して表示される
:extra_failure_lines メタデータを追加しました。
+ - 失敗時の出力に追加して表示される
:extra_failure_lines メタデータを追加しました。
(bootstraponline, #2092)
- - メタデータをコピーしながら新しい example を生成するための
+
- メタデータをコピーしながら新しい example を生成するための
RSpec::Core::Example#duplicate_with を追加しました。
(bootstraponline, #2098)
- - example グループが作成されたときに呼び出されるフックを登録するための
+
- example グループが作成されたときに呼び出されるフックを登録するための
RSpec::Core::Configuration#on_example_group_definition を追加しました。
(bootstraponline, #2094)
- - example グループの example 群を操作するための
add_example と remove_example を
+ - example グループの example 群を操作するための
add_example と remove_example を
RSpec::Core::ExampleGroup に追加しました。
(bootstraponline, #2095)
- - Ripper が利用可能な場合、複数行の失敗したソースを表示できるようにしました(MRI >= 1.9.2 と、JRuby >= 1.7.5 && < 9.0.0.0.rc1)。
+
- Ripper が利用可能な場合、複数行の失敗したソースを表示できるようにしました(MRI >= 1.9.2 と、JRuby >= 1.7.5 && < 9.0.0.0.rc1)。
(Yuji Nakayama, #2083)
- max_displayed_failure_line_count 設定オプション(デフォルト 10)を追加しました。
+max_displayed_failure_line_count 設定オプション(デフォルト 10)を追加しました。
(Yuji Nakayama, #2083)
- fail_fast オプションを拡張し、指定した回数(例: --fail-fast=3)だけ失敗が発生した後に中断することができるようになりました。
+fail_fast オプションを拡張し、指定した回数(例: --fail-fast=3)だけ失敗が発生した後に中断することができるようになりました。
(Jack Scotti, #2065)
- - POSIX システム上で、
color が有効化されていて、coderay gem がインストールされている場合、
+ - POSIX システム上で、
color が有効化されていて、coderay gem がインストールされている場合、
失敗したスニペットがシンタックスハイライトされるようになりました。
(Myron Marston, #2109)
@@ -317,32 +311,33 @@ rspec-core 3.4.0
バグ修正:
- - 複数のプロセスが
example_status_persistence_file が読み書きしようとしたときに競合が発生しないよう、ロックを行うようにしました。
+ - 複数のプロセスが
example_status_persistence_file が読み書きしようとしたときに競合が発生しないよう、ロックを行うようにしました。
(Ben Woosley, #2029)
- - 3.3 において、ファイル名に角括弧が含まれている spec ファイル(例えば
1[]_spec.rb)が読み込まれなくなったバグを修正しました。
+ - 3.3 において、ファイル名に角括弧が含まれている spec ファイル(例えば
1[]_spec.rb)が読み込まれなくなったバグを修正しました。
(Myron Marston, #2041)
- - Ruby 1.9.3 における ASCII リテラル由来の出力エンコーディングの問題を修正しました。
+
- Ruby 1.9.3 における ASCII リテラル由来の出力エンコーディングの問題を修正しました。
(Jon Rowe, #2072)
- - 何人かのユーザに確認された、
rspec/core/rake_task.rb が重複 require を行ってしまう問題を修正しました。
+ - 何人かのユーザに確認された、
rspec/core/rake_task.rb が重複 require を行ってしまう問題を修正しました。
(Myron Marston, #2101)
-rspec-expectations 3.4.0
+rspec-expectations 3.4.0
+
改善:
- - MRI 1.9において、
RSpec::Matchers がサブクラスにすでに include された後にスーパークラスにも include された場合、
+ - MRI 1.9において、
RSpec::Matchers がサブクラスにすでに include された後にスーパークラスにも include された場合、
警告を行うようになりました。その状況で super を使うと無限再帰が発生してしまうためです。
(Myron Marston, #816)
- NoMemoryError、SignalExcepetion、Interrupt、SystemExit を rescue しないようにしました。
+NoMemoryError、SignalExcepetion、Interrupt、SystemExit を rescue しないようにしました。
これらに干渉するのは危険なためです。
(Myron Marston, #845)
- - match マッチャで文字列に対して正規表現をマッチさせるとき、
+
- match マッチャで文字列に対して正規表現をマッチさせるとき、
期待するキャプチャを指定するための
#with_captures を追加しました。
(Sam Phippen, #848)
- - 複合エクスペクテーションの失敗メッセージ群を常に複数行で表示するようにしました。
+
- 複合エクスペクテーションの失敗メッセージ群を常に複数行で表示するようにしました。
それらをすべて1行で表示するのはあまり読みやすくなかったためです。
(Myron Marston, #859)
@@ -350,83 +345,86 @@ rspec-expectations 3.4.0
バグ修正:
- - 動的な predicate マッチャにおいて、オブジェクトがその predicate メソッドに応答しない場合、
+
- 動的な predicate マッチャにおいて、オブジェクトがその predicate メソッドに応答しない場合、
失敗メッセージ出力にそのオブジェクトの
to_s を利用しないように改善しました。
-例えばオブジェクトが nil だった場合、空文字列ではなく "nil" が表示されるようになります。
+例えばオブジェクトが nil だった場合、空文字列ではなく "nil" が表示されるようになります。
(Myron Marston, #841)
- #each がそのオブジェクト自身を含む Enumerable オブジェクトを diff しようとした場合に、
+#each がそのオブジェクト自身を含む Enumerable オブジェクトを diff しようとした場合に、
SystemStackError が発生していた問題を修正しました。
(Yuji Nakayama, #857)
-rspec-mocks 3.4.0
+rspec-mocks 3.4.0
+
改善:
- expect(...).to have_received が rspec-expectations に依存せず利用できるようになりました。
+expect(...).to have_received が rspec-expectations に依存せず利用できるようになりました。
(Myron Marston, #978)
- nil に対してエクスペクテーションを設定した場合にテストを失敗させるオプションを追加しました。
+nil に対してエクスペクテーションを設定した場合にテストを失敗させるオプションを追加しました。
(Liz Rush, #983)
バグ修正:
- - 対象のメソッドに渡されたブロックが
have_received { ... } のブロックに渡されるように修正をしました。
+ - 対象のメソッドに渡されたブロックが
have_received { ... } のブロックに渡されるように修正をしました。
(Myron Marston, #1006)
- respond_to? をスタブしている場合にエラー出力時に無限ループになってしまうのを修正しました。
+respond_to? をスタブしている場合にエラー出力時に無限ループになってしまうのを修正しました。
(Alex Dowad, #1022)
- - Ruby 1.8.7 において、サブクラスのクラスメソッドに対して
receive を使ったときに発生していた問題を修正しました。
+ - Ruby 1.8.7 において、サブクラスのクラスメソッドに対して
receive を使ったときに発生していた問題を修正しました。
(Alex Dowad, #1026)
-rspec-rails 3.4.0
+rspec-rails 3.4.0
+
改善:
- have_rendered マッチャがリダイレクトレスポンスによって失敗したときのメッセージを改善しました。
+have_rendered マッチャがリダイレクトレスポンスによって失敗したときのメッセージを改善しました。
(Alex Egan, #1440)
- - 各種 Rails gem をバックトレースからフィルターするための設定オプションを追加しました。
+
- 各種 Rails gem をバックトレースからフィルターするための設定オプションを追加しました。
(Bradley Schaefer, #1458)
- - 大幅な速度改善のために view spec で resolver cache を有効化しました。
+
- 大幅な速度改善のために view spec で resolver cache を有効化しました。
(Chris Zetter, #1452)
- - ブロックがジョブをキューに追加したかどうかを確認するための
have_enqueued_job マッチャを追加しました。
+ - ブロックがジョブをキューに追加したかどうかを確認するための
have_enqueued_job マッチャを追加しました。
(Wojciech Wnętrzak, #1464)
バグ修正:
- - spec が作成された後で rspec-rails が読み込まれた場合に、
-"undefined method
fixture_path" エラーが発生してしまう、ロード順の問題を修正しました。
+ - spec が作成された後で rspec-rails が読み込まれた場合に、
+“undefined method
fixture_path” エラーが発生してしまう、ロード順の問題を修正しました。
(Nikki Murray, #1430)
- - rspec-rails 自身の
lib コードをバックトレースから除外するためのパターンが、
+ - rspec-rails 自身の
lib コードをバックトレースから除外するためのパターンが、
不適切に空白で囲われてしまっていたのを削除しました。
(Jam Black, #1439)
-rspec-support 3.4.0
+rspec-support 3.4.0
+
改善:
- Delegator ベースのオブジェクト(例: SimpleDelgator)が失敗時メッセージやdiffで表示されたときのフォーマットを改善しました。
+Delegator ベースのオブジェクト(例: SimpleDelgator)が失敗時メッセージやdiffで表示されたときのフォーマットを改善しました。
(Andrew Horner, #215)
- ComparableVersion を追加しました。
+ComparableVersion を追加しました。
(Yuji Nakayama, #245)
- Ripperがサポートされているか検出する機能を追加しました。
+Ripperがサポートされているか検出する機能を追加しました。
(Yuji Nakayama, #245)
バグ修正:
- - JRubyのバグとして、
attr_writer によって生成されたメソッドがパラメータを持たないと報告する問題に対処しました。
+ - JRubyのバグとして、
attr_writer によって生成されたメソッドがパラメータを持たないと報告する問題に対処しました。
RSpec の検証付きダブルで writer メソッドをモックやスタブした時に、間違って失敗してしまっていたためです。
(Myron Marston, #225)
diff --git a/docs/ja/blog/2016/07/rspec-3-5-has-been-released/index.html b/docs/ja/blog/2016/07/rspec-3-5-has-been-released/index.html
index 23b38c5b3..93a32b50c 100644
--- a/docs/ja/blog/2016/07/rspec-3-5-has-been-released/index.html
+++ b/docs/ja/blog/2016/07/rspec-3-5-has-been-released/index.html
@@ -13,9 +13,9 @@
このリリースに向けて力になってくれたみなさん、ありがとう!
-主要な変更
+主要な変更
-Core: config.when_first_matching_example_defined
+Core: config.when_first_matching_example_defined
私たちは基本的に、
一部の spec でしか使わないセットアップロジックは spec_helper.rb には書かないようにすることをおすすめしています。
@@ -23,7 +23,6 @@
Core: config.when_firs
そういったセットアップロジックは spec/support ディレクトリに入れると良いでしょう。
そしてそれを必要とする spec ファイルで、まずサポートファイルを require し、example group にタグをつけることで、
関連付けられたフックやモジュールを include することができます。
-
require 'support/db'
RSpec.describe SomeClassThatUsesTheDB, :db do
@@ -32,7 +31,7 @@ Core: config.when_firs
この方法は上手くいきます。しかし、require と :db タグの両方が必要になるのは最適な方法ではないかもしれません。
その DB を利用するすべての spec において、毎回重複が発生してしまうからです。
-また、もしその DB を使う spec に require 'support/db' を書き忘れてしまった場合、
+また、もしその DB を使う spec に require 'support/db' を書き忘れてしまった場合、
その spec ファイル単体で実行すると失敗するけれども、
すべての spec を実行した場合にはパスする、
というような状況が起こりえます(他の spec ファイルがサポートファイルを読み込むので)。
@@ -40,7 +39,6 @@ Core: config.when_firs
RSpec 3.5 では、こういった状況で上手く使える新しいフックを導入しました。
support/db を必要とするすべての spec ファイルでそれを require する代わりに、
:db タグがついた example が定義されたタイミングでそれを自動的に読み込むように設定できます。
-
RSpec.configure do |config|
config.when_first_matching_example_defined(:db) do
require 'support/db'
@@ -53,11 +51,10 @@ Core: config.when_firs
もちろん、この仕組みは他にもいろいろな使い道があると思いますが、
これが私たちの想定している主なユースケースの一つです。
-Core: config.filter_run_when_matching
+Core: config.filter_run_when_matching
RSpec のメタデータの一般的な使い方の一つとして、focus フィルタがあります。
RSpec 3.5 以前では、このように focus フィルタを設定していたでしょう。
-
RSpec.configure do |config|
config.filter_run :focus
config.run_all_when_everything_filtered = true
@@ -72,7 +69,6 @@ Core: config.filter_run_when_mat
(例えばこの issue)。
この問題に関して、私たちは :focus を 条件付きの フィルタとしてセットアップできれば上手くいくと考え、
RSpec 3.5 では以下のように設定できるようにしました。
-
RSpec.configure do |config|
config.filter_run_when_matching :focus
end
@@ -80,25 +76,23 @@ Core: config.filter_run_when_mat
この設定を使うと、:focus タグのついた example か example group が一つ以上存在する場合にのみ、
:focus フィルタが有効になります。また、以前より短く、シンプルな設定になります!
-Core: コマンドラインで指定された順番で spec ファイルを読み込むように
+Core: コマンドラインで指定された順番で spec ファイルを読み込むように
RSpec 3.5 では、コマンドライン引数で渡された順番で spec ファイルやディレクトリを読み込むようになりました。
これによって、その場で簡単に順序を指定することができるようになります。
例えばその場で一度だけ、高速なユニット spec を、時間のかかる受け入れ spec の前に実行したいという場合、
このように RSpec を実行します。
-
$ rspec spec/unit spec/acceptance --order defined
この --order defined オプションは、
あなたのプロジェクトでデフォルトの実行順序をランダムに設定(推奨)している場合にのみ必要になります。
-Core: Shared example group の include 方式の変更
+Core: Shared example group の include 方式の変更
これまで RSpec は shared context という概念
(任意のコンテキスト用のヘルパーメソッドやフックを共通化するための shared example group)
をサポートしてきました。
Shared context はこんな風に定義します。
-
RSpec.shared_context "DB support" do
let(:db) { MyORM.database }
@@ -118,13 +112,11 @@ Core: Shared example group の incl
end
この shared context を使うには、任意の example group で include_context を使って include します。
-
RSpec.describe MyModel do
include_context "DB support"
end
また、 メタデータによって 暗黙的に shared context を include する方法もあります。
-
RSpec.shared_context "DB support", :db do
# ...
end
@@ -138,22 +130,21 @@ Core: Shared example group の incl
この方法はまあまあ上手くいきます。しかし、いくつかの問題がありました。
- shared_context の第一引数("DB support")は、そのグループが何のためのものかというラベルでしかない(コメントと大差ない)。
- - メタデータが shared example group の場合だけ特別に扱われ、通常の example group のように単純にそのグループに適用されない、
+
shared_context の第一引数("DB support")は、そのグループが何のためのものかというラベルでしかない(コメントと大差ない)。
+- メタデータが shared example group の場合だけ特別に扱われ、通常の example group のように単純にそのグループに適用されない、
という挙動に対して、予想外だという意見がこれまで挙がってきていた。
- - Shared example group を include した側の example group に対して自動的に適用されるようなメタデータを付与することが不可能だった。
+
- Shared example group を include した側の example group に対して自動的に適用されるようなメタデータを付与することが不可能だった。
例えば、一時的に
:skip や :focus メタデータを、include した側の example group に自動的に適用する、ということができない。
- - Shared example group を、すべての example group に自動的に include する明確な方法がなかった
+
- Shared example group を、すべての example group に自動的に include する明確な方法がなかった
(例えば、グローバルな
before フックや let をあらゆる場所で利用可能にするなど)。
- - モジュールの include 方式と一貫性がなかった(例:
config.include DBSupport, :db)。
+- モジュールの include 方式と一貫性がなかった(例:
config.include DBSupport, :db)。
RSpec 3.5 では、いくつかの変更によってこれらの問題に対処しました。
-新しい API: config.include_context
+新しい API: config.include_context
RSpec.configure ブロック内で、shared context の include 定義ができるようになりました。
-
RSpec.configure do |config|
config.include_context "DB support", :db
end
@@ -162,10 +153,9 @@ 新しい API: config.include_context
-新しい設定: config.shared_context_metadata_behavior
+新しい設定: config.shared_context_metadata_behavior
Shared context のメタデータの挙動を変更するための設定も追加されました。
-
RSpec.configure do |config|
config.shared_context_metadata_behavior = :trigger_inclusion
# または
@@ -183,12 +173,11 @@ 新しい設定: config.share
include した側の example group に適用されるようになります。
例えば DB shared context に :focus タグをつけることによって、
それに依存するすべての example group のみを実行することができます。
-
RSpec.shared_context "DB support", :focus do
# ...
end
-Expectations: respond_to マッチャのキーワード引数サポート
+Expectations: respond_to マッチャのキーワード引数サポート
キーワード引数が Ruby の安定した言語機能となってしばらく経ちましたが、
これまで RSpec の多くのマッチャにおいて、キーワード引数に対するエクスペクテーションを設定することができませんでした。
@@ -196,31 +185,28 @@ Expectations: respond_to マッチ
rspec-expectations 3.5 では、
オブジェクトが任意のメソッドに応答するかどうかを、キーワード引数を使って検証できるようになりました。
メソッドが任意のキーワード引数を受け取るかどうかや、通常引数のカウントを検証することができます。
-
expect(my_object).to respond_to(:find).with_keywords(:limit, :offset)
expect(my_object).to respond_to(:find).with(1).argument.and_keywords(:limit, :offset)
さらに、幅のある引数カウントや、無限に引数を受け取れるかどうかも検証できます。
-
expect(my_object).to respond_to(:build).with(2..3).arguments
expect(my_object).to respond_to(:build).with_unlimited_arguments
これを実装してくれた Rob Smith、ありがとう。
-Expectations: Minitest 5.6+ のサポート
+Expectations: Minitest 5.6+ のサポート
rspec-expectations は通常、rspec-core と一緒に使われますが、
他のテストフレームワークで使うことも簡単にできます。
Minitest とのインテグレーションも提供しており、
Minitest 自身を読み込んだ後に rspec-expectations の Minitest サポートを読み込むことで利用できます。
-
require 'rspec/expectations/minitest_integration'
しかし Minitest は、バージョン 5.6 においてそれ自身の expect メソッドを導入したため、
RSpec の expect と衝突し、このインテグレーションが壊れてしまいました。
rspec-expectations 3.5 にはこのための修正が含まれています。
-Mocks: Minitest インテグレーションの追加
+Mocks: Minitest インテグレーションの追加
私たちは以前から rspec-expectations の Minitest インテグレーションを提供していましたが、
rspec-mocks に関しては同レベルの簡単なインテグレーションを提供してきませんでした。
@@ -228,10 +214,9 @@
Mocks: Minitest インテグレーションの追加expect
メソッドが追加され、それによって動作が壊れるまでは問題なく動いていました。
rspec-mock 3.5 では、ファーストクラスの Minitest サポートを提供します。
これを利用するには、ただインテグレーションファイルを require するだけです。
-
require 'rspec/mocks/minitest_integration'
-Rails: Rails 5 のサポート
+Rails: Rails 5 のサポート
今回の重大ニュースは、RSpec 3.5.0 が Rails 5 をサポートしたという点です。
私たちは、Rails 5 のベータや RC がリリースされると共に、並行して RSpec 3.5.0 のベータをリリースしてきました。
@@ -259,7 +244,7 @@
Rails: Rails 5 のサポート
controller spec とは違い、ルーターやミドルウェアスタック、Rack リクエストやレスポンスも関与します。
これによって、より現実に近い環境でテストを実行し、controller spec で発生しがちな多くの問題を避けることができます。
Rails 5 では、request spec が Rails 4までの request spec や controller spec よりもかなり高速になっています。
-これは Rails チームの Eileen Uchitelle1 のおかげです。
+これは Rails チームの Eileen Uchitelle[^foot_1] のおかげです。
他の Rails 5 の重要な機能としては ActionCable があります。
残念ながら、RSpec は今のところ ActionCable をちゃんとテストするための方法を提供できていません。
@@ -271,14 +256,14 @@
Rails: Rails 5 のサポート
また私たちも Rails コアチームに大きく助けられました。
このリリースに向けて力になってくれたみなさんに感謝します。
-Stats
+Stats
-Combined:
+Combined:
- - Total Commits: 625
- - Merged pull requests: 192
- - 62 contributors: Aaron Stone, Ahmed AbouElhamayed, Al Snow, Alex Altair,
+
- Total Commits: 625
+- Merged pull requests: 192
+- 62 contributors: Aaron Stone, Ahmed AbouElhamayed, Al Snow, Alex Altair,
Alexander Skiba, Alireza Bashiri, Andrew Kozin (aka nepalez), Andrew White,
Anton Rieder, Ben Saunders, Benjamin Quorning, Bradley Schaefer, Bruno Bonamin,
DarthSim, David Rodríguez, Diogo Benicá, Eliot Sykes, Fernando Seror, Gautam
@@ -292,44 +277,44 @@
Combined:
Nakayama, Zshawn Syed, chrisarcand, liam-m, mrageh, sleepingkingstudios, yui-knk
-rspec-core:
+rspec-core:
- - Total Commits: 194
- - Merged pull requests: 66
- - 18 contributors: Alexander Skiba, Alireza Bashiri, Benjamin Quorning,
+
- Total Commits: 194
+- Merged pull requests: 66
+- 18 contributors: Alexander Skiba, Alireza Bashiri, Benjamin Quorning,
Bradley Schaefer, Jon Moss, Jon Rowe, Matt Jones, Michele Piccirillo, Myron
Marston, Patrik Wenger, Perry Smith, Sam Phippen, Simon Coffey, Thomas Hart II,
Travis Grathwell, Yuji Nakayama, mrageh, yui-knk
-rspec-expectations:
+rspec-expectations:
- - Total Commits: 83
- - Merged pull requests: 25
- - 14 contributors: Alex Altair, Ben Saunders, Benjamin Quorning, Bradley
+
- Total Commits: 83
+- Merged pull requests: 25
+- 14 contributors: Alex Altair, Ben Saunders, Benjamin Quorning, Bradley
Schaefer, James Coleman, Jon Rowe, Myron Marston, Rob Smith, Sam Phippen,
William Jeffries, Yuji Nakayama, Zshawn Syed, chrisarcand, sleepingkingstudios
-rspec-mocks:
+rspec-mocks:
- - Total Commits: 82
- - Merged pull requests: 28
- - 17 contributors: Andrew Kozin (aka nepalez), Benjamin Quorning, Bradley
+
- Total Commits: 82
+- Merged pull requests: 28
+- 17 contributors: Andrew Kozin (aka nepalez), Benjamin Quorning, Bradley
Schaefer, Bruno Bonamin, David Rodríguez, Isaac Betesh, Joe Rafaniello, Jon
Rowe, Kilian Cirera Sant, Marc Ignacio, Martin Emde, Myron Marston, Patrik
Wenger, Ryan Beckman, Sam Phippen, Tobias Bühlmann, Yuji Nakayama
-rspec-rails:
+rspec-rails:
- - Total Commits: 185
- - Merged pull requests: 47
- - 31 contributors: Ahmed AbouElhamayed, Al Snow, Andrew White, Anton Rieder,
+
- Total Commits: 185
+- Merged pull requests: 47
+- 31 contributors: Ahmed AbouElhamayed, Al Snow, Andrew White, Anton Rieder,
Benjamin Quorning, Bradley Schaefer, DarthSim, David Rodríguez, Diogo Benicá,
Eliot Sykes, Fernando Seror, Gautam Sawhney, John Schroeder, Jon Rowe, Jun
Aruga, Koen Punt, Liss McCabe, Miklos Fazekas, Myron Marston, Peter Swan, Prem
@@ -337,76 +322,78 @@
rspec-rails:
Timo Schilling, Wojciech Wnętrzak, Xavier Shay, Yoshihiro Ashida, Yuji Nakayama
-rspec-support:
+rspec-support:
- - Total Commits: 81
- - Merged pull requests: 26
- - 8 contributors: Aaron Stone, Bradley Schaefer, Jon Rowe, Myron Marston,
+
- Total Commits: 81
+- Merged pull requests: 26
+- 8 contributors: Aaron Stone, Bradley Schaefer, Jon Rowe, Myron Marston,
Sam Phippen, Yuji Nakayama, liam-m, sleepingkingstudios
-Docs
+Docs
-API Docs
+API Docs
- - rspec-core
- - rspec-expectations
- - rspec-mocks
- - rspec-rails
+- rspec-core
+- rspec-expectations
+- rspec-mocks
+- rspec-rails
-Cucumber Features
+Cucumber Features
- - rspec-core
- - rspec-expectations
- - rspec-mocks
- - rspec-rails
+- rspec-core
+- rspec-expectations
+- rspec-mocks
+- rspec-rails
-Release Notes
+Release Notes
+
+RSpec Core (combining all betas of RSpec 3.5.0)
-RSpec Core (combining all betas of RSpec 3.5.0)
+3.5.0 / 2016-07-01
-3.5.0 / 2016-07-01
Enhancements:
- - Include any
SPEC_OPTS in reproduction command printed at the end of
+ - Include any
SPEC_OPTS in reproduction command printed at the end of
a bisect run. (Simon Coffey, #2274)
Bug Fixes:
- - Handle
--bisect in SPEC_OPTS environment variable correctly so as
+ - Handle
--bisect in SPEC_OPTS environment variable correctly so as
to avoid infinite recursion. (Simon Coffey, #2271)
-3.5.0.beta4 / 2016-06-05
+3.5.0.beta4 / 2016-06-05
+
Enhancements:
- - Filter out bundler stackframes from backtraces by default, since
+
- Filter out bundler stackframes from backtraces by default, since
Bundler 1.12 now includes its own frames in stack traces produced
by using
bundle exec. (Myron Marston, #2240)
- - HTML Formatter uses exception presenter to get failure message
+
- HTML Formatter uses exception presenter to get failure message
for consistency with other formatters. (@mrageh, #2222)
- - Load spec files in the order of the directories or files passed
+
- Load spec files in the order of the directories or files passed
at the command line, making it easy to make some specs run before
others in a one-off manner. For example,
rspec spec/unit
spec/acceptance --order defined will run unit specs before acceptance
specs. (Myron Marston, #2253)
- - Add new
config.include_context API for configuring global or
+ - Add new
config.include_context API for configuring global or
filtered inclusion of shared contexts in example groups.
(Myron Marston, #2256)
- - Add new
config.shared_context_metadata_behavior = :apply_to_host_groups
+ - Add new
config.shared_context_metadata_behavior = :apply_to_host_groups
option, which causes shared context metadata to be inherited by the
metadata hash of all host groups and examples instead of configuring
implicit auto-inclusion based on the passed metadata. (Myron Marston, #2256)
@@ -415,21 +402,22 @@ 3.5.0.beta4 / 2016-06-05
Bug Fixes:
- - Fix
--bisect so it works on large spec suites that were previously triggering
-"Argument list too long errors" due to all the spec locations being passed as
+ - Fix
--bisect so it works on large spec suites that were previously triggering
+“Argument list too long errors” due to all the spec locations being passed as
CLI args. (Matt Jones, #2223).
- - Fix deprecated
:example_group-based filtering so that it properly
+ - Fix deprecated
:example_group-based filtering so that it properly
applies to matching example groups. (Myron Marston, #2234)
- - Fix
NoMethodError caused by Java backtraces on JRuby. (Michele Piccirillo, #2244)
+- Fix
NoMethodError caused by Java backtraces on JRuby. (Michele Piccirillo, #2244)
-3.5.0.beta3 / 2016-04-02
+3.5.0.beta3 / 2016-04-02
+
Enhancements:
- - Add new
config.filter_run_when_matching API, intended to replace
+ - Add new
config.filter_run_when_matching API, intended to replace
the combination of config.filter_run and
config.run_all_when_everything_filtered (Myron Marston, #2206)
@@ -437,85 +425,91 @@ 3.5.0.beta3 / 2016-04-02
Bug Fixes:
- - Use the encoded string logic for source extraction. (Jon Rowe, #2183)
- - Fix rounding issue in duration formatting helper. (Fabersky, Jon Rowe, #2208)
- - Fix failure snippet extraction so that
def-end snippets
+ - Use the encoded string logic for source extraction. (Jon Rowe, #2183)
+- Fix rounding issue in duration formatting helper. (Fabersky, Jon Rowe, #2208)
+- Fix failure snippet extraction so that
def-end snippets
ending with end-only line can be extracted properly.
(Yuji Nakayama, #2215)
-3.5.0.beta2 / 2016-03-10
+3.5.0.beta2 / 2016-03-10
+
Enhancements:
- - Remove unneeded
:execution_result example group metadata, saving a
+ - Remove unneeded
:execution_result example group metadata, saving a
bit of memory. (Myron Marston, #2172)
- - Apply hooks registered with
config to previously defined groups.
+ - Apply hooks registered with
config to previously defined groups.
(Myron Marston, #2189)
- RSpec::Core::Configuration#reporter is now public API under SemVer.
+RSpec::Core::Configuration#reporter is now public API under SemVer.
(Jon Rowe, #2193)
- - Add new
config.when_first_matching_example_defined hook. (Myron
+ - Add new
config.when_first_matching_example_defined hook. (Myron
Marston, #2175)
-3.5.0.beta1 / 2016-02-06
+3.5.0.beta1 / 2016-02-06
+
Enhancements:
- - Add
RSpec::Core::ExampleGroup.currently_executing_a_context_hook?,
+ - Add
RSpec::Core::ExampleGroup.currently_executing_a_context_hook?,
primarily for use by rspec-rails. (Sam Phippen, #2131)
Bug Fixes:
- - Ensure
MultipleExceptionError does not contain a recursive reference
+ - Ensure
MultipleExceptionError does not contain a recursive reference
to itself. (Sam Phippen, #2133)
-RSpec Expectations (including all betas of RSpec 3.5.0)
+RSpec Expectations (including all betas of RSpec 3.5.0)
+
+3.5.0 / 2016-07-01
-3.5.0 / 2016-07-01
No user facing changes since beta4
-3.5.0.beta4 / 2016-06-05
+3.5.0.beta4 / 2016-06-05
+
Bug Fixes:
- - Fix
include matcher so that it provides a valid diff for hashes. (Yuji Nakayama, #916)
+- Fix
include matcher so that it provides a valid diff for hashes. (Yuji Nakayama, #916)
-3.5.0.beta3 / 2016-04-02
+3.5.0.beta3 / 2016-04-02
+
Enhancements:
- - Make
rspec/expectations/minitest_integration work on Minitest::Spec
+ - Make
rspec/expectations/minitest_integration work on Minitest::Spec
5.6+. (Myron Marston, #904)
- - Add an alias
having_attributes for have_attributes matcher.
+ - Add an alias
having_attributes for have_attributes matcher.
(Yuji Nakayama, #905)
- - Improve
change matcher error message when block is mis-used.
+ - Improve
change matcher error message when block is mis-used.
(Alex Altair, #908)
-3.5.0.beta2 / 2016-03-10
+3.5.0.beta2 / 2016-03-10
+
Enhancements:
- - Add the ability to raise an error on encountering false positives via
+
- Add the ability to raise an error on encountering false positives via
RSpec::Configuration#on_potential_false_positives = :raise. (Jon Rowe, #900)
- - When using the custom matcher DSL, support new
+
- When using the custom matcher DSL, support new
notify_expectation_failures: true option for the match method to
allow expectation failures to be raised as normal instead of being
converted into a false return value for matches?. (Jon Rowe, #892)
@@ -524,139 +518,144 @@ 3.5.0.beta2 / 2016-03-10
Bug Fixes:
- - Allow
should deprecation check to work on BasicObjects. (James Coleman, #898)
+- Allow
should deprecation check to work on BasicObjects. (James Coleman, #898)
-3.5.0.beta1 / 2016-02-06
+3.5.0.beta1 / 2016-02-06
+
Enhancements:
- - Make
match_when_negated in custom matcher DSL support use of
+ - Make
match_when_negated in custom matcher DSL support use of
expectations within the match logic. (Chris Arcand, #789)
Bug Fixes:
- - Return
true as expected from passing negated expectations
-(such as expect("foo").not_to eq "bar"), so they work
+ - Return
true as expected from passing negated expectations
+(such as expect("foo").not_to eq "bar"), so they work
properly when used within a match or match_when_negated
block. (Chris Arcand, #789)
-RSpec Mocks (including all betas of RSpec 3.5.0)
+RSpec Mocks (including all betas of RSpec 3.5.0)
+
+3.5.0 / 2016-07-01
-3.5.0 / 2016-07-01
Enhancements:
- - Provides a nice string representation of
+
- Provides a nice string representation of
RSpec::Mocks::MessageExpectation (Myron Marston, #1095)
-3.5.0.beta4 / 2016-06-05
+3.5.0.beta4 / 2016-06-05
+
Enhancements:
- - Add
and_throw to any instance handling. (Tobias Bühlmann, #1068)
+- Add
and_throw to any instance handling. (Tobias Bühlmann, #1068)
-3.5.0.beta3 / 2016-04-02
+3.5.0.beta3 / 2016-04-02
+
Enhancements:
- - Issue warning when attempting to use unsupported
+
- Issue warning when attempting to use unsupported
allow(...).to receive(...).ordered. (Jon Rowe, #1000)
- - Add
rspec/mocks/minitest_integration, to properly integrate rspec-mocks
+ - Add
rspec/mocks/minitest_integration, to properly integrate rspec-mocks
with minitest. (Myron Marston, #1065)
-3.5.0.beta2 / 2016-03-10
+3.5.0.beta2 / 2016-03-10
+
Enhancements:
- - Improve error message displayed when using
and_wrap_original on pure test
+ - Improve error message displayed when using
and_wrap_original on pure test
doubles. (betesh, #1063)
Bug Fixes:
- - Fix issue that prevented
receive_message_chain(...).with(...) working
-correctly on "any instance" mocks. (Jon Rowe, #1061)
+- Fix issue that prevented
receive_message_chain(...).with(...) working
+correctly on “any instance” mocks. (Jon Rowe, #1061)
-3.5.0.beta1 / 2016-02-06
+3.5.0.beta1 / 2016-02-06
+
Bug Fixes:
- - Allow
any_instance_of(...).to receive(...) to use and_yield multiple
+ - Allow
any_instance_of(...).to receive(...) to use and_yield multiple
times. (Kilian Cirera Sant, #1054)
- - Allow matchers which inherit from
rspec-mocks matchers to be used for
+ - Allow matchers which inherit from
rspec-mocks matchers to be used for
allow. (Andrew Kozin, #1056)
- - Prevent stubbing
respond_to? on partial doubles from causing infinite
+ - Prevent stubbing
respond_to? on partial doubles from causing infinite
recursion. (Jon Rowe, #1013)
- - Prevent aliased methods from disapearing after being mocked with
+
- Prevent aliased methods from disapearing after being mocked with
any_instance (regression from #1043). (Joe Rafaniello, #1060)
-RSpec Support (including all betas of RSpec 3.5.0)
+RSpec Support (including all betas of RSpec 3.5.0)
+
+3.5.0 / 2016-07-01
-3.5.0 / 2016-07-01
No user facing changes since beat4
-3.5.0.beta4 / 2016-06-05
+3.5.0.beta4 / 2016-06-05
+
Enhancements:
* Improve MethodSignature to better support keyword arguments. (#250, Rob Smith).
-3.5.0.beta3 / 2016-04-02
+3.5.0.beta3 / 2016-04-02
+
Bug Fixes:
- - Fix
EncodedString to properly handle the behavior of String#split
+ - Fix
EncodedString to properly handle the behavior of String#split
on JRuby when the string contains invalid bytes. (Jon Rowe, #268)
- - Fix
ObjectFormatter so that formatting objects that don't respond to
+ - Fix
ObjectFormatter so that formatting objects that don’t respond to
#inspect (such as BasicObject) does not cause NoMethodError.
(Yuji Nakayama, #269)
- - Fix
ObjectFormatter so that formatting recursive array or hash does not
+ - Fix
ObjectFormatter so that formatting recursive array or hash does not
cause SystemStackError. (Yuji Nakayama, #270, #272)
-3.5.0.beta2 / 2016-03-10
+3.5.0.beta2 / 2016-03-10
+
No user-facing changes.
-3.5.0.beta1 / 2016-02-06
+3.5.0.beta1 / 2016-02-06
+
-Footnotes
+Footnotes
-
-
- -
-
See also Eileen's talk about request spec performance ↩
-
-
-
+[^foot_1]: See also Eileen’s talk about request spec performance