Cucumber with Brine
Written By: @tolicodes at @hoverinc
Time travel
Debug in Chrome DevTools
Live reload
Auto wait/sleep
Class-A stubbing
Recording test runs
Stable, complete and built from scratch
Scenario: I should be able to search for a doc
# An AJAX Search Happens Here
When I type "recommended" into the "Search Input" in the "Header"
Then I should see "Recommended Cypress Setup" in the "Search Result" in the "Header"
# A redirect happens here
When I click the "Search Result" in the "Header" containing "Recommended Cypress Setup"
Then I should be redirected to "Recommended Cypress Setup"
// That's all you need to do to stub an endpoint!
cy.route('GET', '/users/*', {
id: 1,
name: 'toli'
});
// or put it in a file
cy.route('GET', '/users/*', 'users.json');
One Framework to Rule Them All
Stubbing - Assertions - Screenshot Diff - Recording -
Reporting - Test Runner - Browser Control
Write tests in plain English
Regular expression turns it into code
Scenario: I should be able to login
When I open the "Login Page"
And I type "toli@tolicodes.com" into the "Email Field"
And I type "ilovepickles" into the "Password Field"
And I click "Submit"
Then I should see the "Login Successful" modal
As a developer, product manager, or QA engineer,
I should be able to read and write feature tests without
programming knowledge
When I open "Some Page"
When I click "Some Element" inside "Some Container"
When I type "some text" into "Some Field"
When I scroll to the bottom of the page
When I drag "Some Element" above "Some Other Element"
When I take a snapshot named "Cheese"
Then I should be redirected to "the Home Page"
Then I should see 2 "Elements" containing "hello!"
Then I should see an "Element" in the "Container"
Then I should see a "red" background on the "Button"
Then I should see a "blue" border on the "Button"
95% of tests I write use the same patterns
Why write custom regular expressions every time?
No Javascript
Centralizing selectors
Selectors for styled components
Flexible grammar
Fixture & stubbing management
Enumerating elements
Sharing state
{
"Account Container": {
"default": ".AccountSelection"
"Title": ".Title"
"Message": ".Message"
"Accounts Select": ".AccountsSelect",
"Next Button": "input:contains('Next')"
},
"Account Confirmation Modal": {
"default": ".AccountConfirmationModal"
}
}
Scenario: I select an account from the account modal
When I select "PICKLE FARM" from the
"Account Select" in the "Account Modal"
And I click the "Next Button" in
the "Account Modal"
Then I should see an
"Account Confirmation Modal"
Just write it in English!
{
"Account Container": {
"default": ".AccountSelection"
"Title": ".Title"
"Message": ".Message"
"Accounts Select": ".AccountsSelect",
"Next Button": "input:contains('Next')"
},
"Account Confirmation Modal": {
"default": ".AccountConfirmationModal"
}
}
The first key concept of PickleJS is keeping all your selectors and page URLs in one place and only refer to them by human-readable names
{
"Home": "/",
"Users": "/users",
"Sign Up": "/sign-up",
"Messages": "/messages",
"External Link": "http://extenal.link"
}
{
"Account Selection Container": {
"default": ".AccountSelection"
"Title": ".Title"
"Message": ".Message"
"Accounts Select": ".AccountsSelect",
"Next Button": "input:contains('Next')"
}
}
Some things sound awkward with a rigid structure
When I click the "Button"
When I click on the "Submit"
When I click "Submit"
When I click a "Button"
When I click on "Click Me"
When I click on the "Button" in the "Footer"
containing "Submit"
When I click the "Button" inside the "Modal"
When I click into the "Modal"
When I click inside of the "Modal"
... and much much more
Built for front-end integration testing (no API)
Everything is stubbed by default
(returns empty object with 200 Response)
router({
'/users': '/users/getUsers',
'GET /users/*': '/users/getUser',
'PUT /users/*': '/users/putUsers',
'POST /users/*': '/users/postUsers'
});
// Returns a success response with optional json
apiSuccess('/someUrl', 'GET', { hi: 'there' });
// Returns a 404 (default for GET)
apiNotFound('/someUrl');
When I click the "seventh Button" in the "Modal"
And I click the "last Button" in the "Modal"
And I type "hello" in the "ten-thousandth Input"
Then I should see "hello" in the "ten-thousandth Output"
Uses the wordsToNumbers library to easily refer to ordinal elements
When('I login', () => {
const username = 'toli';
setState('username', username);
cy.get('.loginInput').type(username);
});
Then('The username should match in the header', () => {
cy.get('.header .username').should('contain', STATE['username']);
});
Easily share state in between Scenarios and Steps across files when using Cucumber/Pickle. WIP.
This website is the example application. Everything is tested using Cypress & Pickle
You can view the source for the website in the
Pickle JS Repo under /website
All the Cypress tests under website/cypress
Text
Start Simple
The Kitchen Sink
Save developer time - PMs write tests
Automatical documentation of features in English
Real TDD/BDD - PMs write all test cases first
Step 1: Product Manager defines Scenarios for a Feature in Pickle format
Step 2: Developer copies Scenarios to Integration tests in Pickle
Step 3: Developer develops the feature and all the scenarios in Storybook
Step 4: Developer writes unit tests in Jest
Step 5: Developer integrates the feature into the app
Step 6: PR must be approved by 2 team members and Integration/Unit tests must pass
Step 7: QA writes their own set of End to End Tests
Step 8: Deploy
The base framework that makes this possible
My employer who sponsored Pickle's development
The cucumber interpreter for Cypress