Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Spreewald is a collection of useful steps for cucumber. Feel free to fork.
You can find a list of all contained steps at the end of this README.
Spreewald is currently tested against and Ruby 2.6.6 and 3.0.0 with Rails 7 and Capybara 3.
Add this line to your application's Gemfile:
gem 'spreewald'
And then execute:
$ bundle install
Require all Spreewald steps by putting
require 'spreewald/all_steps'
into either your support/env.rb
or step_definitions/spreewald_steps.rb
.
Steps are grouped into a number of categories. If you only want to use a subset
of Spreewald's steps, instead of require 'spreewald/all_steps'
, you can pick
and choose single categories by requiring single files like this:
require 'spreewald/email_steps'
require 'spreewald/web_steps'
After that you are good to go and use the steps described below.
We recommend using a features/support/paths.rb
file in your project to define mappings between verbal phrases and your project's routes. You can then use these phrases in steps like Then I should be on ...
or When I go to ...
.
You can find an example in this repository. Please note that you may have to adapt it depending on the namespaces and other setup of your application's routes.
Similarly, you may define a features/support/selectors.rb
file in your project to define mappings of verbal phrases to CSS selectors. You can also find an example for that in this repository. These mappings can be used with steps like Then I should( not)? see (an|the) element for ...
or When I click on the element for ...
.
We also suggest to look at our recommended Capybara defaults as they impact the behavior of many Spreewald steps.
Spreewald comes with a binary that prints a list of all Cucumber steps from Spreewald and your project. It will filter the list by any string you pass it. Example usage (e.g. on a linux shell in the root folder of the project which uses Spreewald):
spreewald # lists all steps
spreewald mail # lists all steps that contain "mail"
The binary also prints paths and selectors; run spreewald --help
to learn more.
Spreewald's web steps are all aware that you might run them with a Selenium/Capybara webdriver, and wait for the browser to finish loading the page, if necessary.
This is done by rerunning any assertions until they succeed or a timeout is reached.
We consider a couple of potential exceptions as "retriable", including
Capybara::ElementNotFound, (R)Spec::Expectations::ExpectationNotMetError, Capybara::Poltergeist::ClickFailed
You can add your own error class with
ToleranceForSeleniumSyncIssues::RETRY_ERRORS << 'MyCustomError'
You can achieve this in your own steps by wrapping them inside a patiently do
block, like
Then /^I should see "([^\"]*)" in the HTML$/ do |text|
patiently do
page.body.should include(text)
end
end
More info here.
Thanks to cucumber_priority you can override any step definition from Spreewald with your own pattern. Cucumber will not raise Cucumber::Ambiguous
if your custom steps collide with a Spreewald step.
If you are upgrading from Capybara 2 to Capybara 3, you might see failing tests with Spreewald steps like I should see
. This is caused by a breaking change in Capybara's Finders that accept a :text
option. To activate Capybara 2 behavior globally in your project, enable this flag:
Capybara.default_normalize_ws = true
This will affect all Spreewald steps that are using Capybara's :text
option.
Furthermore, we recommend setting Capybara's matching strategy to :prefer_exact
. This will positively affect Spreewald steps as it prevents the Capybara::Ambiguous
error in the edge case when two fields are matching the given name, but one of the matches includes the name only as a substring.
Capybara.match = :prefer_exact
If you want Spreewald to match fields, links and buttons against the aria-label
attribute, enable the following global configuration in Capybara 2.8+:
Capybara.enable_aria_label = true
Gemika is used to manage Gemfiles for different ruby versions.
Spreewald has different kind of tests:
spec/
tests/
.features/
Run all tests for your current ruby version with rake
or rake matrix:tests
. To bundle use rake matrix:install
first.
rake matrix:tests
passesrake update_readme
, if neededThe "Steps" section is autogenerated by rake update_readme
from comments in
the step definitions.
When I open ... in a new browser tab
Opens the page in a new browser tab and switches to it.
When I close the browser tab
Closes the current browser tab and switches back to the first tab.
When I switch to the new(ly opened)? browser tab
Waits for the new browser tab to appear, then switches to it.
When I switch( back)? to the previous browser tab
Changes the browser context to the second-last browser tab.
When I may open a new browser tab
Required for the check whether a new browser tab was opened or not.
Then I should( not)? have opened a new browser tab
Example (positive expectation):
When I may open a new browser tab
And I click on "Open link in new browser tab"
Then I should have opened a new browser tab
Example (negative expectation):
When I may open a new browser tab
And I click on "Open link in current browser tab"
Then I should not have opened a new browser tab
Then there should be (\d+) browser tabs?
Then there should be at least (\d+) browser tabs?
Then it should work...?
Marks scenario as pending, optionally explained with a reason.
Then console
Pauses test execution and opens an IRB shell with current context. Does not halt the application- under-test.
AfterStep @slow-motion
Waits 2 seconds after each step
AfterStep @single-step
Waits for a keypress after each step
When specifying the to
, cc
, bcc
, from
or reply_to
targets within email steps, you can either specify email addresses or any arbitrary identifier. When an identifier (other than an email address) is given, Spreewald can try to use this information to determine the associated user and gather its email address automatically over the application's User
model. For this, you may set Spreewald::MailFinder.user_identity
to an attribute name and Spreewald will call User.find_by_<user_identity>(identifier)
and then use the email
of the found user.
For example, if you set reply_to
to the name John Doe
within a scenario step and specify Spreewald::MailFinder.user_identity = 'name'
, Spreewald will call User.find_by_name('John Doe')
, find the according user with this name and expect its email address as reply_to
.
When I clear my e?mails
Then (an?|no)( HTML| plain-text|) e?mail should have been sent with:
Example:
Then an email should have been sent with:
"""
From: max.mustermann@example.com
Reply-To: mmuster@gmail.com
To: john.doe@example.com
CC: jane.doe@example.com
BCC: johnny.doe@example.com
Subject: The subject may contain "quotes"
Attachments: image.jpg, attachment.pdf
This is the message body. You can use * as a wildcard to omit the rest
of a line *
Or you can omit multiple lines if the asterisk is the only
character in a single line, like this:
*
"""
You may skip lines in the header. Please note: In older versions of Spreewald, unmentioned body lines were skipped. Now you have to use the asterisk explicitly to omit lines in the body.
When I follow the (first|second|third)? link in the e?mail
Please note that this step will only follow HTTP and HTTPS links. Other links (such as mailto: or ftp:// links) are ignored.
Then no e?mail should have been sent
Then I should see "..." in the( HTML| plain-text|) e?mail
Checks that the last sent email includes some text
Then show me the e?mail( header)?s
Print all sent emails to STDOUT (optionally only the headers).
Then show me the e?mail( header)?s with:
Print a subset of all sent emails to STDOUT
This uses the same syntax as Then an email should have been sent with:
When ... inside the ... iframe
You can append inside the [name or number] iframe
to any other step.
Then the step will operate inside the given iframe.
Examples:
Then I should see "Kiwi" inside the 1st iframe
Then I should see "Cherry" inside the fruits iframe
When I press "Save" inside the 2nd iframe
When I switch to the ... iframe
This step will switch to the iframe identified by its name or number. All further steps will operate inside the iframe. To switch to operating on the main page again, use the step "I switch back to the whole page". Examples:
When I switch to the 1st iframe
When I switch to the fruits iframe
Please note: This step is only available for Capybara >= 3.
When I switch back to the whole page
This step can be used to switch back to the whole page if you switched
to operating inside an iframe before (step I switch to the ... iframe
).
Please note: This step is only available for Capybara >= 3.
When ... in the browser session "..."
You can append in the browser session "name"
to any other step to execute
the step in a different browser session.
You may need to update other steps to allow multiple sessions (e.g. your authentication steps have to support multiple logged in users). More details here.
Then I should( not)? see a table with (exactly )?the following rows( in any order)?:?
Check the content of tables in your HTML.
See this article for details.
Steps to travel through time
This uses Timecop or Active Support 4.1+ to stub Time.now / Time.current. The user is responsible for including one of the two gems.
Please note that the two approaches branch. While ActiveSupport will freeze the time, Timecop will keep it running.
When the (date|time) is "?(\d{4}-\d{2}-\d{2}( \d{1,2}:\d{2})?)"?
Example:
Given the date is 2012-02-10
Given the time is 2012-02-10 13:40
When the time is "?(\d{1,2}:\d{2})"?
Example:
Given the time is 13:40
When it is (\d+|an?|some|a few) (seconds?|minutes?|hours?|days?|weeks?|months?|years?) (later|earlier)
Example:
When it is 10 minutes later
When it is a few hours earlier
Most of cucumber-rails' original web steps plus a few of our own.
Note that cucumber-rails deprecated all its steps quite a while ago with the following deprecation notice. Decide for yourself whether you want to use them:
This file was generated by Cucumber-Rails and is only here to get you a head start These step definitions are thin wrappers around the Capybara/Webrat API that lets you visit pages, interact with widgets and make assertions about page content.
If you use these step definitions as basis for your features you will quickly end up with features that are:
- Hard to maintain
- Verbose to read
A much better approach is to write your own higher level step definitions, following the advice in the following blog posts:
When ... within ...
You can append within [selector]
to any other web step, even multiple times.
Be aware that within will only look at the first element that matches.
If this is a problem for you following links, you might want to have a look
at the 'When I follow "..." inside any "..."'-step.
Example:
Then I should see "some text" within ".page_body"
Given I am on ...
When I go to ...
Then I should be on ...
When I press "..."
When I follow "..."
When I fill in "..." (with|for) "..."
Fill in text field
When I fill in "..." (with|for):
Fill in text field with multi-line block You can use a doc string to supply multi-line text
Example:
When I fill in "some field" with:
"""
Apple
Banana
Pear
"""
When I fill in "..." (with|for) '...'
Fill in text field
When I select "..." from "..."
Select from select box
When I check "..."
Check a checkbox
When I uncheck "..."
Uncheck a checkbox
When I choose "..."
Select a radio button
When I attach the file "..." to "..."
Attach a file to a file upload form field
Then I should( not)? see "..."
Checks that some text appears on the page
Note that this does not detect if the text might be hidden via CSS
Then I should( not)? see /.../
Checks that a regexp appears on the page
Note that this does not detect if the text might be hidden via CSS
Then I should( not)? see a field "..."
Checks for the existance of an input field (given its id or label)
Then I should( not)? see the (number|amount) ([-\d,.]+)( ...)?
Use this step to test for a number or money amount instead of a simple Then I should see
Checks for an unexpected minus sign, correct decimal places etc.
See here for details
Then I should( not)? see '...'
Like Then I should see
, but with single instead of double quotes. In case
the expected string contains quotes as well.
Then I should( not)? see "..." in the HTML
Check that the raw HTML contains a string
Then I should see an error
Checks that status code is 400..599
Then I should( not)? see (an|the) element "..."
Check that an element with the given selector is present on the page.
Example:
Then I should see an element ".panel"
Then I should see the element ".panel"
Then I should not see an element ".sidebar"
Then I should not see the element ".sidebar"
Then I should( not)? see (an|the) element for ...
Check that an element with the given selector alias is present on the page.
Example:
Then I should see an element for the panel
Then I should see the element for the panel
Then I should not see an element for the sidebar
Then I should not see the element for the sidebar
Then I should see in this order:?
Checks that these strings are rendered in the given order in a single line or in multiple lines
Example:
Then I should see in this order:
| Alpha Group |
| Augsburg |
| Berlin |
| Beta Group |
Then I should( not)? see a link labeled "..."
Checks that the page contains a link with a given text or title attribute.
Then the "..." field should( not)? contain "..."
Checks that an input field contains some value (allowing * as wildcard character)
Then the "..." field should( not)? contain:
Checks that a multiline textarea contains some value (allowing * as wildcard character)
Then I should see a form with the following values:
Checks that a list of label/value pairs are visible as control inputs.
Example:
Then I should see a form with the following values:
| E-mail | foo@bar.com |
| Role | Administrator |
Then the "..." field should have the error "..."
Checks that an input field was wrapped with a validation error. This is done by checking for different error HTML structures that display errors.
Spreewald first checks for custom error wrappers (if specified), then Boostrap 3 error wrappers (.form-group.has-error
), then Bootstrap 4/5 error wrappers (:invalid
or is-invalid
) and lastly, Rails error wrappers (field_with_errors
). You are able to specify a custom error wrapper by setting Spreewald.field_error_class = 'my-custom-error-class'
which is then used to look for the error class on the current or any ancestor div
.
The same principle applies for matching the error message. First, it will look for the message text (starting from the input element) with a custom XPath (if specified), then one targeting a sibling element with a help-block
class for Bootstrap 3 and then one targeting a sibling element with an invalid-feedback
class for Bootstrap 4/5. Rails errors are checked specifically over the field title as this one contains the error message. You may specify the custom XPath by setting (e.g.) Spreewald.error_message_xpath_selector = 'parent::*/child::*[@class="my-error-message"]'
.
Then the "..." field should( not)? have an error
Then the "..." checkbox should( not)? be checked?
Then the radio button "..." should( not)? be (checked|selected)
Then I should have the following query string:
Example:
I should have the following query string:
| locale | de |
| currency_code | EUR |
Succeeds when the URL contains the given locale
and currency_code
params
Then show me the page
Open the current Capybara page using the launchy
or capybara_screenshot
gem
Then I should get a response with content-type "..."
Checks Content-Type
HTTP header
Then I should get a download with filename "..."
Checks Content-Disposition
HTTP header
Attention: Doesn't work with Selenium, see https://github.com/jnicklas/capybara#gotchas
Then "..." should( not)? be selected for "..."
Checks that a certain option is selected for a text field
Then nothing should be selected for "..."
Then "..." should( not)? be an option for "..."
Checks for the presence of an option in a select
Then the window should be titled "..."
When I reload the page
Then (the tag )?"..." should be visible
Checks that an element is actually present and visible, also considering styles.
Within a selenium test, the browser is asked whether the element is really visible
In a non-selenium test, we only check for .hidden
, .invisible
or style: display:none
More details here
Then (the tag )?"..." should be hidden
Checks that an element is actually present and hidden, also considering styles.
Within a selenium test, the browser is asked whether the element is really hidden.
In a non-selenium test, we only check for .hidden
, .invisible
or style: display:none
When I click on "..."
Click on some text that might not be a link.
Example:
When I click on "Collapse"
When I click on the element "..."
Click on an element with the given selector.
Example:
When I click on the element ".sidebar"
When I click on the element for ...
Click on the element with the given selector alias.
Example:
When I click on the element for the sidebar
Then "..." should link to "..."
Use this step to check external links.
Example:
Then "Sponsor" should link to "http://makandra.com/"
Don't forget the trailing slash. Otherwise you'll get the error expected: /http://makandra.com(?[^/]*)?$/ got: "http://makandra.com/" (using =~)
When I follow "..." inside any "..."
Click a link within an element matching the given selector. Will try to be clever and disregard elements that don't contain a matching link.
Example:
When I follow "Read more" inside any ".text_snippet"
Then I should( not)? see "..." inside any "..."
When I fill in "..." with "..." inside any "..."
When I confirm the browser dialog
When I cancel the browser dialog
When I enter "..." into the browser dialog
Then the "..." (field|button|checkbox|radio button) should( not)? be disabled
Tests that an input, button, checkbox or radio button with the given label is disabled.
Then the "..." field should( not)? be visible
Tests that a field with the given label is visible.
When I perform basic authentication as ".../..." and go to ...
Performs HTTP basic authentication with the given credentials and visits the given path.
More details here.
When I go back
Goes to the previously viewed page.
Then the "..." select should( not)? be sorted
Tests whether a select field is sorted. Uses Array#natural_sort, if defined; Array#sort else.
FAQs
Unknown package
We found that spreewald demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.