Giter VIP home page Giter VIP logo

spreewald's Introduction

Spreewald

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.

Supported versions

Spreewald is currently tested against and Ruby 2.6.6 and 3.0.0 with Rails 7 and Capybara 3.

Installation

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.

Recommended additional setup

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 binary

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.

Waiting for page load

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.

Overriding steps

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.

Recommended Capybara defaults

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

Contributing

Testing

Gemika is used to manage Gemfiles for different ruby versions.

Spreewald has different kind of tests:

  • Unit tests live in spec/
  • Test applications for integration tests with various Capybara versions live in tests/.
  • Tests for the Spreewald binary live in features/

Run all tests for your current ruby version with rake or rake matrix:tests. To bundle use rake matrix:install first.

If you would like to contribute:

  • Fork the repository
  • Push your changes with specs
  • Make sure rake matrix:tests passes
  • Regenerate the "Steps" section of this Readme with rake update_readme, if needed
  • Make a pull request

This README

The "Steps" section is autogenerated by rake update_readme from comments in the step definitions.

Steps

browser_tab_steps.rb

  • 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?

development_steps.rb

  • 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

email_steps.rb

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: [email protected]
      Reply-To: [email protected]
      To: [email protected]
      CC: [email protected]
      BCC: [email protected]
      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:

frame_steps.rb

  • 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.

session_steps.rb

  • 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.

table_steps.rb

  • 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.

time_steps.rb

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
    

web_steps.rb

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 | [email protected]   |
      | 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.

spreewald's People

Contributors

abinoam avatar alexmchale avatar arobecke avatar begerdom avatar bergermx avatar codener avatar dastra-mak avatar denzelem avatar dependabot[bot] avatar dmilisic avatar fleinzi avatar foobear avatar inossidabile avatar johngeorgewright avatar judithroth avatar kraatob avatar kratob avatar makmic avatar manukall avatar minhmakandra avatar nataliezeumann avatar niklas-hasselmeyer avatar niklashae avatar thomase avatar thomast-makandra avatar trianglegrrl avatar triskweline avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spreewald's Issues

Extend paths.rb and selectors.rb

Just like Spreewald holds a set of commonly used Cucumbers steps, let's add commonly used paths and selectors. Add proposals here.

UTF-8 incompatibility

I'm testing with steps in spanish and I get this error:

incompatible encoding regexp match (ASCII-8BIT regexp with UTF-8 string) (Encoding::CompatibilityError)
  /usr/local/rvm/gems/ruby-1.9.3-p194/gems/spreewald-0.1.0/lib/spreewald/table_steps.rb:28:in `gsub'

New `patiently` implementation breaks some steps

I have a scenario that breaks after upgrading spreewald on the following step:

Then the "some select" field should contain "some option"

This happens because the select options are replaced while the step is running. Previously, the patiently in the the ... field should contain ... step saved us, but it does not any more.

What happens is this:

patiently do
  # Capybara.default_wait_time used to be 0, but is now the standard 5 seconds
  field = find_field(label)
  options = field.all('option')
  # options were replaced here
  selected_option = options.detect(&:selected?) # Capybara waits here for 5 seconds and fails with a StaleElementReference
  # patiently has taken up all its time and raises the error
end

Turnip Integration

Hi guys,

Really good work on spreewald, helps a lot on starting with cucumber. Are you looking forward in a integration with turnip? Is it better to add support on spreewald itself or fork on spreewald-turnip ?

Thank you

Encoding error when testing emails with attachments

Since spreewald 1.2.8 (on Rails 4.2 / Ruby 2.1.5), the step "an email should have been sent with" fails with
incompatible character encodings: UTF-8 and ASCII-8BIT (Encoding::CompatibilityError)
The error seems to happen on line 59 of mail_finder.rb:
mail_bodies.join('\n')
If I test an email with a PDF attached, the mail body's encoding is UTF-8, but the PDF's encoding is ASCII-8BIT, so the join throws an error.
Would it make more sense not to test attachments at all? Or let the developer whether to test them?

Add new step "should see a link labeled ..."

Then /^I should( not)? see a link labeled "([^"]*)"$/ do |negate, label|
  expectation = negate ? :should_not : :should
  link = page.first('a', :text => label) || page.first(%(a[title="#{label}"]))
  link.send(expectation, be_present)
end

Add patiently-disabling step

Recently I used this meta step to test things I needed in that very moment, and not after a few seconds. It effectively disables patiently's patience for the given step.

Usage: Append now to any step:

Then I should see "Hallo Welt" now

I think this should be incorporated into Spreewald.

# Disable #patiently (run a step with wait-time 0)
# Then I should see "Hallo Welt" now
When /^(.*) now$/ do |step_text|
  begin
    old_wait_time = Capybara.default_max_wait_time
    Capybara.default_max_wait_time = 0

    step step_text
  ensure
    Capybara.default_max_wait_time = old_wait_time
  end
end

"And I click on" is Broken in 0.7.0

Suppose you have a document like this:

<p>Sign in to your account!</p>
<button>Sign in</button>

You'll get an error like the below when you have a step like "And I click on 'Sign in'":

Ambiguous match, found 2 elements matching xpath "//*[contains(text(), \"Sign in\")]" (Capybara::Ambiguous)
features/sign_up.feature:72:in `And I click on "Sign in"'

How to redirect to edit page

I apply this step ( Then /^(?:|I )should be on (.+)$/ do |page_name| ) for index page then it works.
But it does not work for edit page. How can I resolve this issue?
Thank in advanced.

"I should see /REGEX/" should allow escaped slashes

Hi there!

Currently, the RegEx for spreewald's I should see /REGEX/ step does not allow escaped slashes - which prevents me from matching a full URL.

Issue description

  • The matching pattern is /^(?:|I )should see \/([^\/]*)\/$/
  • The RegEx I want to use with this step Is similar to /http:\/\/example\.com/
  • I would expect this pattern not to be excluded from the step definition.

I guess the matching pattern has to include some kind of lookahead operator for \/ instead of only unescaped slashes `/.

Thank you!

Running steps when debugging

Hello,
I am trying to do the following

  • Then debugger

and then run a step like

  • step "my step name"

Unfortunately it does not work.
This would help me trying out the steps without restarting the cuke each time.
Is it even possible?

Thank you

Using the "And debugger" step twice in a Cucumber scenario prints a wall of warnings

The second (or any further) invocation of the debugger step print these warnings:

/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: already initialized constant IRB::UnrecognizedSwitch
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: previous definition of UnrecognizedSwitch was here
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: already initialized constant IRB::NotImplementedError
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: previous definition of NotImplementedError was here
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: already initialized constant IRB::CantReturnToNormalMode
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: previous definition of CantReturnToNormalMode was here
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: already initialized constant IRB::IllegalParameter
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: previous definition of IllegalParameter was here
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: already initialized constant IRB::IrbAlreadyDead
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: previous definition of IrbAlreadyDead was here
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: already initialized constant IRB::IrbSwitchedToCurrentThread
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: previous definition of IrbSwitchedToCurrentThread was here
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: already initialized constant IRB::NoSuchJob
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: previous definition of NoSuchJob was here
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: already initialized constant IRB::CantShiftToMultiIrbMode
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: previous definition of CantShiftToMultiIrbMode was here
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: already initialized constant IRB::CantChangeBinding
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: previous definition of CantChangeBinding was here
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: already initialized constant IRB::UndefinedPromptMode
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: previous definition of UndefinedPromptMode was here
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: already initialized constant IRB::IllegalRCGenerator
/home/me/.rbenv/versions/2.2.3/lib/ruby/2.2.0/e2mmap.rb:133: warning: previous definition of IllegalRCGenerator was here
>> (debugger prompt)

I assume this is caused by how IRB is required/initialized inside the step.

Expected behavior

No wall of warnings.

Missing rspec dependency

Although Spreewald requires rspec, it doesn't state so in its gemspec.
It should also require "rspec" when its being loaded.

This is usually not an issue because something, somewhere has already loaded RSpec before Spreewald, but I tripped over it tonight.

"Then show me the page" should support capybara-screenshot

As mentioned in #50, Then show me the page depends on a method defined by the launchy gem.

We do not want to add launchy as a dependency, but use it, if available. In addition, we use capybara-screenshot in recent projects and want the step to support its screenshot_and_save_page, too.

I recommend we make show me the page detect if either is available and use its way to create a snapshot, or fail with a helpful error message if neither is available.

Method documentation / Readme should be updated accordingly.

Deprecation warning when used with ActiveSupport 5+

Every time my Bundler requires spreewald gem I see these 2 warning messages

DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from require at /Users/username/.gem/ruby/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:86)
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from require at /Users/username/.gem/ruby/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:86)

Happens on:
require 'cucumber_priority/ambiguous_error_ext'
require 'cucumber_priority/rb_step_definition_ext'

Ambiguous step definitions

The "within" step collides with the "checkbox should be checked" step.

Error message:

Ambiguous match of "the "Project A" checkbox within '.projects' should be checked":

spreewald-1.1.1/lib/spreewald/web_steps.rb:40:in `/^(.*) within (.*[^:])$/'
spreewald-1.1.1/lib/spreewald/web_steps.rb:267:in `/^the "([^"]*)" checkbox(?: within (.*))? should be checked$/'

Suggested solutions:

  • a) remove "within" support from the checkbox step, as the within steps takes care of this
  • b) for better wording, find a way to turn of the within step for the checkbox step

New step for visible button

check if page has a button ...

Then /^(?:|I )should see a "([^"]*)" button$/ do |text|
  if page.respond_to? :should
    page.should have_button(text)
  else
    assert page.has_button?(text)
  end
end

Make "an email should have been sent with:" step more flexible

Today the mentioned step bit me when I had too much white space:

Then an email should have been sent with:
  """
  From: < 2+ spaces here > [email protected]
  """

The step should be flexible enough to strip any white space around email addresses and/or the subject.


Also, it would be nice to have better output if the specified email could not be found. Current output is expected nil.present? to return true, got false. Improved output:

Could not find email with:
<multiline string>

Found emails:
<list of emails like "show me the emails" prints them>

Incompatibility with RSpec 3.0

The meaning of #be_true and #be_false has changed in RSpec 3.0, as explained in this Stackoverflow answer.

For compatibility with all RSpec versions, these method calls should be replaced with == true and == false. Currently this only needs to be done in lib/spreewald_support/web_steps_helpers.rb:79:81.

deprecation warning when using talbe steps

I have a few deprecation warnings when using the table steps helper:

DEPRECATION: `failure_message_for_should` is deprecated. Use `failure_message` instead. Called from /Users/bodo/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/spreewald-1.2.6/lib/spreewald/table_steps.rb:76:in `block in <module:TableStepsHelper>'.
DEPRECATION: `failure_message_for_should_not` is deprecated. Use `failure_message_when_negated` instead. Called from /Users/bodo/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/spreewald-1.2.6/lib/spreewald/table_steps.rb:86:in `block in <module:TableStepsHelper>'.
DEPRECATION: Using `should` from rspec-expectations' old `:should` syntax without explicitly enabling the syntax is deprecated. Use the new `:expect` syntax or explicitly enable `:should` with `config.expect_with(:rspec) { |c| c.syntax = :should }` instead. Called from /Users/bodo/.rbenv/versions/2.2.1/lib/ruby/gems/2.2.0/gems/spreewald-1.2.6/lib/spreewald/table_steps.rb:122:in `block (2 levels) in <top (required)>'.

spreewald independet from testframework (use with minitest)

I use cucumber w capybara and minitest (rails default). The original web_steps.rb supported both rspec and minites like this ...

Then /^(?:|I )should see "([^"]*)"$/ do |text|
  if page.respond_to? :should
    page.should have_content(text)
  else
    assert page.has_content?(text)
  end
end

it would be nice if spreewald would support more than just rspec - related to #50.

Then I should see in this order within ".something":

The following step will fail:

Then I should see in this order within ".something":
  | One   |
  | Two   |
  | Three |

... with ...

Unable to find css "body" (Capybara::ElementNotFound)
.../spreewald/lib/spreewald/web_steps.rb:579:in `block (2 levels) in <top (required)>'
.../spreewald/lib/spreewald_support/tolerance_for_selenium_sync_issues.rb:23:in `call'
.../spreewald/lib/spreewald_support/tolerance_for_selenium_sync_issues.rb:23:in `patiently'
.../spreewald/lib/spreewald/web_steps.rb:578:in `/^I should see in this order:?$/'
.../spreewald/lib/spreewald_support/step_fallback.rb:6:in `step'
.../spreewald/lib/spreewald/web_steps.rb:44:in `block (2 levels) in <top (required)>'
.../spreewald/lib/spreewald_support/path_selector_fallbacks.rb:34:in `block in with_scope'
.../spreewald/lib/spreewald_support/path_selector_fallbacks.rb:34:in `with_scope'
.../spreewald/lib/spreewald/web_steps.rb:44:in `/^(.*) within (.*[^:]):$/'
...

I'm assuming the within statement is changing the DOM context and body is no longer accessible?

New step for inspecting PDF attachments

These steps allows for inspection of PDF documents attached to sent emails.

# For email attachments
When /^I inspect the attached PDF$/ do
  expect( ActionMailer::Base.deliveries ).to_not be_empty

  # @mail can be set by one of the other email steps
  @mail ||= ActionMailer::Base.deliveries.last
  attachment = @mail.attachments.first{ |a| a.mime_type == 'application/pdf' }
  expect( attachment ).to be_present, 'Could not find an attached PDF'

  pdf = StringIO.new(attachment.decoded)
  reader = PDF::Reader.new(pdf)

  @pdf = reader.pages.collect(&:text).join("\n")
end

Then /^I should( not)? see "(.+?)" in the PDF$/ do |negate, text|
  to = negate ? :to_not : :to
  expect( @pdf ).send to, include(text)
end

Note that this requires the pdf-reader gem in the :test group of your Gemfile.

new step for right click

something like ...

When /^(?:|I )right click on "([^\"]+)"$/ do |text|
  begin
    # Capybara throws an exception if the element is not found
    element = page.find(:xpath, ".//*[contains(text(), \"#{text}\")]")
  rescue Capybara::ElementNotFound
    # if we could not find the element by text, try by selector
    element = page.find(*selector_for(text)) 
  end   

  element.right_click 
end

False Positives on tables on steps to match table rows

For a step like this, if any of the inner rows are not a match, the test still passes when it should not. If the first or last rows do not match, the test will fail as it should

Then I should see a table with exactly the following rows:
    | Filename 1 | document |
    | Filename 2 | certificate |
    | Filename One | compliance document |
    | Cco document | document |
    | Cco with expiration | certificate |
    | Cco without expiration | compliance document |

Not able to install Spreewald

When I'm running gem install spreewald I got an error:
installing into parent path /Users/idikhtiar/.rubies/ruby-2.3.1/lib/ruby/gems/2.3.0/gems/shared/app of /Users/idikhtiar/.rubies/ruby-2.3.1/lib/ruby/gems/2.3.0/gems/spreewald-1.5.3 is not allowed

My work-around was:

  1. running gem update --system
  2. gem install spreewald
  3. deleting spreewald folder from gems folder
  4. gem install spreewald

Could reproduce this on another machine with the same issue. Not pushing this code to Staging tests because it will fail on Jenkins. Any idea if it's possible to fix?

Within can not be used inside an argument for other steps due to ambiguous match

Then I should see "You will receive an email within the next few minutes. It contains instructions for changing your password."
Ambiguous match of "I should see "You will receive an email within the next few minutes. It contains instructions for changing your password."":

spreewald-1.2.6/lib/spreewald/web_steps.rb:41:in `/^(.*) within (.*[^:])$/'
spreewald-1.2.6/lib/spreewald/web_steps.rb:155:in `/^(?:|I )should see "([^"]*)"$/'

Revert delegation of debugger step to console step

I've noticed that I used quite often the step Then debugger to have a debugger in context of the cucumber world.

E.g. When I want to test why a radio button is not checked with the step

And I choose "Ordered" within the order

then the original debugger step would be useful to paste into the console

with_scope('the order') { step('I choose "Ordered"') }

while watching the browser in VNC for changes.

The removal was introduced in aa7ae11.

@codener Can we keep both debugger and console within spreewald?

False positive when middle row removed from expected table

The following step passes as expected.

Then I should see a table with exactly the following rows:
  | Row 1 text |
  | Row 2 text |
  | Row 3 text |

However, if a row from the middle is removed, the step still passes. Expecting it to fail.

Then I should see a table with exactly the following rows:
  | Row 1 text |
  | Row 3 text |

The "I should see /REGEXP/" step cannot be composed with the `within` step.

The current definition of the mentioned step looks like this:

Then /^(?:|I )should see \/([^\/]*)\/$/ do |regexp|
  regexp = Regexp.new(regexp)
  patiently do
    expect(page).to have_xpath('//*', :text => regexp)
  end

Since the //* XPATH selector selects all elements in the document, the context given by the within step is lost.

Following the XPATH 3.1 Standard, I think this can be very easily corrected replacing //* with .//*:

An except of the Standard:

chapter//para selects the para element descendants of the chapter element children of the context node

//para selects all the para descendants of the root document node and thus selects all para elements in the same document as the context node

//list/member selects all the member elements in the same document as the context node that have a list parent

.//para selects the para element descendants of the context node

Step "the ... checkbox should (not) be checked" doesn't seem to work with current Selenium versions

The step Then the "Nutzungsbedingungen" checkbox should not be checked passes with Rack::Test, but fails when used with Selenium:

Unable to find field "Nutzungsbedingungen" (Capybara::ElementNotFound)

Capybara is not able to find a checkbox field using #find_field when running with Selenium. However, the #has_checked_field? family of methods seems to work.

There should be a @javascript test similar to

Scenario: /^the "([^"]*)" checkbox should( not)? be checked$/
.

New step for validating definition lists

<dl>
  <dt>Some term</dt>
  <dd>Some defintion</dd>
<dl>
Then(/^I should see the term "(.*?)" with the description "(.*?)"$/) do |term, description|
  patiently do
    term_regex = /\A#{Regexp.escape(term)}\z/
    description_regex = /\A#{Regexp.escape(description)}\z/
    page.find('dt', text: term_regex).find('+dd', text: description_regex)
  end
end

License missing from gemspec

RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.

via e.g.

spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']

Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can image, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.

There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!

Appendix:

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies

p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post aobut this project for more information.

Spreewald should never check the current driver name, but its class

In multiple places in web_steps.rb, spreewald distinguishes Capybara drivers by their name. However, since the driver name is variable (i.e. it is chosen by project developers), this is a weak means for differentiation.

Spreewald should check the driver's class instead, e.g. check if it is Capybara::Selenium::Driver or the like.

"element for" step conflicts with "within" step

After upgrading from 1.12.2 to 1.12.5 (probably because of the changes for #80), the following step no longer works for me:

Then I should see the element for the message indicator within the sidebar

This is because "element for" uses selector_for, if defined. My selector_for uses a regular expression that eventually captures the remainder of the string, so "within ..." will actually never work for me.

We can not fix this in the regexp as it can not know when to stop. The "element for" step should happen only after the generic "within" scoping.

Email steps do not support CRLF in plain text mails

mikel/mail#1168
mikel/mail@d17be66

The mail gem switched from \n to \r\n line breaks (LF to CRLF) in plain text mails (2.7.1). This affects at least the step Then an email should have been sent with: .... You will see a error message like expected nil.present? to return true, got false (RSpec::Expectations::ExpectationNotMetError), as the body does not match anymore.

Internally this part https://github.com/makandra/spreewald/blob/878862fb6b6d0a36cf2f064c395b06926ca32eea/lib/spreewald_support/mail_finder.rb#L46 needs to have a proper support for \n and \r\n.

"test\r\ntest".include?("test\ntest") => false

`I fill in` does not support multi-line arguments

I had to write my own version of I fill in "Field" with "Value" because I expected this to work, but it does not:

    And I fill in "Options" with
      """
      Sage
      Yellow
      Fuchsia
      """

You can implement step definitions for undefined steps with these snippets:

When(/^I fill in "(.*?)" with$/) do |arg1, string|
  pending # express the regexp above with the code you wish you had
end

To make this work in my tests, I defined a custom step for textareas like so; it's really just based off of the step in web_steps.rb:

When(/^I fill in textarea "(.*?)" with$/) do |field, string|
  patiently do
    fill_in(field, :with => string)
  end
end

I'm happy to write a step for this and create a pull request, but before I do I'd like to get a vote: what would the most Spreewaldy syntax be for the step matching?

@javascript steps are not tested

Currently, we cannot test steps that are designed for @javascript scenarios. Creating a consistent environment for making them pass is far too expensive.

One day we might try using phantomJS or RSpec.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.