forked from bahmutov/cypress-workshop-basics
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit cf212dd
Showing
196 changed files
with
38,297 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
node_modules/ | ||
*/cypress/videos | ||
*/cypress/screenshots | ||
cypress/videos | ||
cypress/screenshots | ||
cypress/results | ||
mochawesome-report/ | ||
mochawesome.json | ||
cypress/logs | ||
dist | ||
.nyc_output | ||
coverage | ||
npm-debug.log | ||
todomvc-redux/.cache | ||
posted.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
package-lock=true | ||
save-exact=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"trailingComma": "none", | ||
"tabWidth": 2, | ||
"semi": false, | ||
"singleQuote": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
# cypress-workshop-basics | ||
> Basics of end-to-end testing with [Cypress.io](https://www.cypress.io) test runner | ||
## Requirements | ||
|
||
- Any computer: Mac, Windows, Linux | ||
- [Node 12.0.0+ (LTS)](https://nodejs.org/) | ||
- [git](https://git-scm.com) | ||
|
||
In order to get the code and install dependencies | ||
|
||
```bash | ||
git clone [email protected]:bahmutov/cypress-workshop-basics.git | ||
cd cypress-workshop-basics | ||
npm install | ||
``` | ||
|
||
If necessary, install dependencies inside TodoMVC folder | ||
|
||
```bash | ||
cd todomvc | ||
npm install | ||
``` | ||
|
||
### Quick check ✅ | ||
|
||
You can test the installation by starting TodoMVC in the first terminal window | ||
|
||
```shell | ||
npm start | ||
``` | ||
|
||
and you should see in the terminal | ||
|
||
```text | ||
> json-server --static . data.json --middlewares ./node_modules/json-server-reset | ||
\{^_^}/ hi! | ||
Loading data.json | ||
Loading ./node_modules/json-server-reset | ||
Done | ||
Resources | ||
http://localhost:3000/todos | ||
Home | ||
http://localhost:3000 | ||
``` | ||
|
||
From the second terminal window you should be able to open Cypress in the root of the project with | ||
|
||
```bash | ||
$ npm run cy:open | ||
|
||
> [email protected] cy:open /git/cypress-workshop-basics | ||
> cypress open | ||
``` | ||
|
||
### Tip | ||
|
||
You can use the installed [start-server-and-test](https://github.com/bahmutov/start-server-and-test) utility to start the app, open Cypress and then shutdown the app when you exit Cypress. | ||
|
||
```bash | ||
$ npm run dev | ||
``` | ||
|
||
## Application | ||
|
||
[Vue.js](https://vuejs.org/) + [Vuex](https://vuex.vuejs.org/) + REST server application that we are going to test is in the folder `todomvc`. This application and its full testing is described in [this blog post](https://www.cypress.io/blog/2017/11/28/testing-vue-web-application-with-vuex-data-store-and-rest-backend/). The application should run fine without network access. | ||
|
||
## Slides | ||
|
||
## Content | ||
|
||
### Beginner | ||
|
||
| | topic | folder | contents | slides | | ||
| --- | -------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ------ | | ||
| [🔗](#intro) | Introduction, TodoMVC application | [todomvc](todomvc) | [intro.md](slides/intro/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=intro) | ||
| [🔗](#start) | Loading page | [00-start](00-start) | [00-start](slides/00-start/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=00-start) | ||
| [🔗](#basic) | `cypress open` vs `cypress run` | [01-basic](cypress/integration/01-basic) | [01-basic](slides/01-basic/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=01-basic) | ||
| [🔗](#adding-items) | Adding items test, `cypress.json` file | [02-adding-items](cypress/integration/02-adding-items) | [02-adding-items](slides/02-adding-items/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=02-adding-items) | ||
| [🔗](#selector-playground) | Selector Playground | [03-selector-playground](cypress/integration/03-selector-playground) | [03-selector-playground](slides/03-selector-playground/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=03-selector-playground) | ||
| [🔗](#reset-state) | Reset database using `cy.request` | [04-reset-state](cypress/integration/04-reset-state) | [04-reset-state](slides/04-reset-state/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=04-reset-state) | ||
| [🔗](#xhr) | Spy and stub XHR requests, fixtures | [05-xhr](cypress/integration/05-xhr) | [05-xhr](slides/05-xhr/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=05-xhr) | ||
| [🔗](#app-data-store) | Access application code and data | [06-app-data-store](cypress/integration/06-app-data-store) | [06-app-data-store](slides/06-app-data-store/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=06-app-data-store) | ||
|
||
### Intermediate | ||
| | topic | folder | contents | slides | | ||
| --- | -------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ------ | | ||
| [🔗](#ci) | Setting up E2E tests on CI | [07-ci](cypress/integration/07-ci) | [07-ci](slides/07-ci/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=07-ci) | ||
| [🔗](#dashboard) | Setting up Cypress Dashboard | [07-ci](cypress/integration/07-ci) | [08-dashboard](slides/08-dashboard/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=08-dashboard) | ||
| [🔗](#reporters) | Test reporters | - | [09-reporters](slides/09-reporters/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=09-reporters) | ||
| [🔗](#configuration) | Configuration | - | [10-configuration](slides/10-configuration/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=10-configuration) | ||
| [🔗](#retry-ability) | Retry-ability | [11-retry-ability](cypress/integration/11-retry-ability) | [11-retry-ability](slides/11-retry-ability/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=11-retry-ability) | ||
| [🔗](#custom-commands) | Custom commands | [12-custom-commands](cypress/integration/12-custom-commands) | [12-custom-commands](slides/12-custom-commands/PITCHME.md)| [link](https://testing-workshop-cypress.netlify.app?p=12-custom-commands) | ||
|
||
### Advanced | ||
| | topic | folder | contents | slides | | ||
| --- | -------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ------ | | ||
| [🔗](#app-actions) | Page Objects vs App Actions | [13-app-actions](cypress/integration/13-app-actions) | [13-app-actions](slides/13-app-actions/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=13-app-actions) | ||
| [🔗](#fixtures) | Fixtures | [14-fixtures](cypress/integration/14-fixtures) | [14-fixtures](slides/14-fixtures/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=14-fixtures) | ||
| [🔗](#debugging) | Debugging | [02-adding-items/demo.js](cypress/integration/02-adding-items/demo.js) | [15-debugging](slides/15-debugging/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=15-debugging) | ||
| [🔗](#preprocessors) | Preprocessors | [16-preprocessors](cypress/integration/16-preprocessors) | [16-preprocessors](slides/16-preprocessors/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=16-preprocessors) | ||
| [🔗](#component-testing) | Component testing | [17-component-testing](cypress/integration/17-component-testing) | [17-component-testing](slides/17-component-testing/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=17-component-testing) | ||
| [🔗](#backend) | Backend code | [18-backend](cypress/integration/18-backend) | [18-backend](slides/18-backend/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=18-backend) | ||
| [🔗](#code-coverage) | Code coverage | [19-code-coverage](cypress/integration/19-code-coverage) | [19-code-coverage](slides/19-code-coverage/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=19-code-coverage) | ||
| [🔗](#stubbing-methods) | Stubbing methods | [20-stubbing](./cypress/integration/20-stubbing) | [20-stubbing](./slides/20-stubbing/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=20-stubbing) | ||
| | The end | - | [end](slides/end/PITCHME.md) | [link](https://testing-workshop-cypress.netlify.app?p=end) | ||
|
||
## For speakers 🎙 | ||
|
||
[](https://app.netlify.com/sites/testing-workshop-cypress/deploys) | ||
|
||
This workshop can take all day, but you can pick the sections you are interested in teaching at will and customize it into any time duration. Everyone is coding for the most part, except for CI and the Cypress Dashboard sections, where the usage was shown via slides and actual sites. | ||
|
||
During the workshop, keep the `todomvc` app running in one shell, while each section `01-basic`, `02-...`, `03-...` etc. has its own Cypress and specs subfolders `cypress/integration/...`. Usually a spec has several tests with placeholder comments. The workshop attendees are expected to make the tests pass using the knowledge from the slides and hints (and [Cypress documentation](https://docs.cypress.io/)). Note that most folders have a prepared `spec.js` file and an `answer.js` file. The `answer.js` file is ignored by Cypress using a setting in `cypress.json`. | ||
|
||
The only exception is the folder `00-start`. This is a folder for students to see how Cypress scaffolds example specs when you open Cypress for the very first time. In this folder students should execute... | ||
|
||
``` | ||
cd 00-start | ||
npm run cy:open | ||
``` | ||
|
||
...and see the list of created example specs. | ||
|
||
The slides are generated using Reveal.js from Markdown sources in the [slides](slides) folder. You can show the slides locally by running | ||
|
||
```shell | ||
npm run slides:dev | ||
``` | ||
|
||
## Additional information | ||
|
||
- https://www.cypress.io/ | ||
- https://docs.cypress.io/ | ||
- https://glebbahmutov.com/cypress-examples/ | ||
|
||
[renovate-badge]: https://img.shields.io/badge/renovate-app-blue.svg | ||
[renovate-app]: https://renovateapp.com/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"viewportWidth": 600, | ||
"viewportHeight": 800, | ||
"ignoreTestFiles": [ | ||
"**/answer/*", | ||
"*answer.js", | ||
"*.d.ts", | ||
"**/__snapshots__/*", | ||
"**/__image_snapshots__/*", | ||
"**/13-app-actions/todo-page-object.js", | ||
"**/13-app-actions/utils.js", | ||
"**/17-component-testing/filters.js", | ||
"**/17-component-testing/*.jsx" | ||
], | ||
"baseUrl": "http://localhost:3000", | ||
"env": {}, | ||
"$schema": "https://on.cypress.io/cypress.schema.json", | ||
"experimentalStudio": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"name": "Using fixtures to represent data", | ||
"email": "[email protected]", | ||
"body": "Fixtures are a great way to mock data for responses to routes" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
[ | ||
{ | ||
"title": "first item from fixture", | ||
"completed": false, | ||
"id": 1 | ||
}, | ||
{ | ||
"title": "second item from fixture", | ||
"completed": true, | ||
"id": 2 | ||
}, | ||
{ | ||
"title": "third item", | ||
"completed": false, | ||
"id": 3 | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[ | ||
{ | ||
"title": "first item from fixture", | ||
"completed": false, | ||
"id": 1 | ||
}, | ||
{ | ||
"title": "second item from fixture", | ||
"completed": true, | ||
"id": 2 | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/// <reference types="cypress" /> | ||
// @ts-check | ||
it('loads', () => { | ||
cy.visit('localhost:3000') | ||
|
||
// passing assertions | ||
// https://on.cypress.io/get | ||
cy.get('.new-todo').get('footer') | ||
|
||
// https://on.cypress.io/get | ||
// use ("selector", "text") arguments to "cy.contains" | ||
cy.contains('h1', 'todos') | ||
|
||
// or can use regular expression | ||
cy.contains('h1', /^todos$/) | ||
|
||
// also good practice is to use data attributes specifically for testing | ||
// see https://on.cypress.io/best-practices#Selecting-Elements | ||
// which play well with "Selector Playground" tool | ||
cy.contains('[data-cy=app-title]', 'todos') | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/// <reference types="cypress" /> | ||
// @ts-check | ||
it('loads', () => { | ||
// application should be running at port 3000 | ||
cy.visit('localhost:3000') | ||
|
||
// passing assertions | ||
// https://on.cypress.io/get | ||
cy.get('.new-todo').get('footer') | ||
|
||
// this assertion fails on purpose | ||
// can you fix it? | ||
// https://on.cypress.io/get | ||
cy.contains('h1', 'Todos App') | ||
|
||
// can you write "cy.contains" using regular expression? | ||
// cy.contains('h1', /.../) | ||
|
||
// also good practice is to use data attributes specifically for testing | ||
// see https://on.cypress.io/best-practices#Selecting-Elements | ||
// which play well with "Selector Playground" tool | ||
// how would you do select this element? | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/// <reference types="cypress" /> | ||
// IMPORTANT ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ | ||
// remember to manually delete all items before running the test | ||
// IMPORTANT ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ | ||
|
||
beforeEach(() => { | ||
cy.visit('localhost:3000') | ||
}) | ||
|
||
it('loads', () => { | ||
cy.contains('h1', 'todos') | ||
}) | ||
|
||
it('adds two items', () => { | ||
cy.get('.new-todo').type('first item{enter}') | ||
cy.contains('li.todo', 'first item').should('be.visible') | ||
cy.get('.new-todo').type('second item{enter}') | ||
cy.contains('li.todo', 'second item').should('be.visible') | ||
}) | ||
|
||
it('can mark an item as completed', () => { | ||
// adds a few items | ||
addItem('simple') | ||
addItem('hard') | ||
|
||
// marks the first item as completed | ||
cy.contains('li.todo', 'simple').should('exist').find('.toggle').check() | ||
|
||
// confirms the first item has the expected completed class | ||
cy.contains('li.todo', 'simple').should('have.class', 'completed') | ||
// confirms the other items are still incomplete | ||
cy.contains('li.todo', 'hard').should('not.have.class', 'completed') | ||
}) | ||
|
||
it('can delete an item', () => { | ||
// adds a few items | ||
addItem('simple') | ||
addItem('hard') | ||
// deletes the first item | ||
cy.contains('li.todo', 'simple') | ||
.should('exist') | ||
.find('.destroy') | ||
// use force: true because we don't wsnt to hover | ||
.click({ force: true }) | ||
|
||
// confirm the deleted item is gone from the dom | ||
cy.contains('li.todo', 'simple').should('not.exist') | ||
// confirm the other item still exists | ||
cy.contains('li.todo', 'hard').should('exist') | ||
}) | ||
|
||
/** | ||
* Adds a todo item | ||
* @param {string} text | ||
*/ | ||
const addItem = (text) => { | ||
cy.get('.new-todo').type(`${text}{enter}`) | ||
} | ||
|
||
it('can add many items', () => { | ||
// assumes there are no items at the beginning | ||
|
||
const N = 5 | ||
for (let k = 0; k < N; k += 1) { | ||
addItem(`item ${k}`) | ||
} | ||
// check number of items | ||
cy.get('li.todo').should('have.length', 5) | ||
}) | ||
|
||
it('adds item with random text', () => { | ||
const randomLabel = `Item ${Math.random().toString().slice(2, 14)}` | ||
|
||
addItem(randomLabel) | ||
cy.contains('li.todo', randomLabel) | ||
.should('be.visible') | ||
.and('not.have.class', 'completed') | ||
}) | ||
|
||
it('starts with zero items', () => { | ||
cy.get('li.todo').should('have.length', 0) | ||
}) | ||
|
||
it('does not allow adding blank todos', () => { | ||
cy.on('uncaught:exception', (e) => { | ||
// what will happen if this assertion fails? | ||
// will the test fail? | ||
// expect(e.message).to.include('Cannot add a blank todo') | ||
// return false | ||
|
||
// a better shortcut | ||
return !e.message.includes('Cannot add a blank todo') | ||
}) | ||
addItem(' ') | ||
}) | ||
|
||
// what a challenge? | ||
// test more UI at http://todomvc.com/examples/vue/ |
Oops, something went wrong.