├── README.md
├── cypress.json
├── cypress
├── fixtures
│ └── example.json
├── integration
│ ├── search-tests.js
│ └── visual.js
├── page-objects
│ └── search-page.js
├── plugins
│ └── index.js
├── support
│ ├── commands.js
│ ├── eyes-index.d.ts
│ └── index.js
└── utils
│ └── search-validation-utils.js
└── package.json
/README.md:
--------------------------------------------------------------------------------
1 | # Cypress
2 | Test Automation Using Cypress
3 |
4 | This code base tests https://automationbookstore.dev/
5 |
6 | It demonstrates how to use Cypress for web UI automation, how to implement Page Object Model using Cypress, and also includes examples of visual testing with Applitools
7 |
--------------------------------------------------------------------------------
/cypress.json:
--------------------------------------------------------------------------------
1 | {
2 | "watchForFileChanges": false
3 | }
4 |
--------------------------------------------------------------------------------
/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
--------------------------------------------------------------------------------
/cypress/integration/search-tests.js:
--------------------------------------------------------------------------------
1 | import { SearchPage } from '../page-objects/search-page'
2 | import { ValidationUtils } from '../utils/search-validation-utils'
3 |
4 | describe('Search for books', () => {
5 | const page = new SearchPage()
6 | const validator = new ValidationUtils(page)
7 |
8 | beforeEach( () => {
9 | page.navigate()
10 | })
11 |
12 | it('should return one book with title Agile Testing', () => {
13 | const title = 'Agile Testing'
14 | page.search(title)
15 | validator.validateNumberOfVisibleBooks(1)
16 | validator.validateTitleIsVisible(title)
17 | })
18 |
19 | it('should return multiple books with title Test', () => {
20 | const query = 'Test'
21 | const expectedBooks = [
22 | 'Test Automation in the Real World',
23 | 'Experiences of Test Automation',
24 | 'Agile Testing',
25 | 'How Google Tests Software',
26 | 'Java For Testers']
27 | page.search(query)
28 | validator.validateNumberOfVisibleBooks(expectedBooks.length)
29 | expectedBooks.forEach(b => validator.validateTitleIsVisible(b))
30 | })
31 | })
--------------------------------------------------------------------------------
/cypress/integration/visual.js:
--------------------------------------------------------------------------------
1 | import { SearchPage } from '../page-objects/search-page'
2 | import { ValidationUtils } from '../utils/search-validation-utils'
3 |
4 | describe('Search for books', () => {
5 | const page = new SearchPage()
6 | const validator = new ValidationUtils(page)
7 |
8 | beforeEach( () => {
9 | page.navigate()
10 | cy.eyesOpen({
11 | appName: 'Automation Bookstore',
12 | batchName: 'Search',
13 | browser: [ {name: 'chrome', width: 1024, height: 768} ]
14 | })
15 | })
16 |
17 | afterEach(() => cy.eyesClose())
18 |
19 | it('should return one book with title Agile Testing', () => {
20 | page.search('Agile Testing', true)
21 | cy.eyesCheckWindow()
22 | })
23 |
24 | it('should return multiple books with title Test', () => {
25 | page.search('Test', true)
26 | cy.eyesCheckWindow()
27 | })
28 | })
29 |
--------------------------------------------------------------------------------
/cypress/page-objects/search-page.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | export class SearchPage {
4 |
5 | constructor() {
6 | this.url = 'https://automationbookstore.dev/'
7 | this.searchBar = '#searchBar'
8 | this.visibleBooks = 'li:not(.ui-screen-hidden)'
9 | this.hiddenBooks = 'li.ui-screen-hidden'
10 | }
11 |
12 | navigate() {
13 | cy.visit(this.url)
14 | }
15 |
16 | search(query) {
17 | this.search(false)
18 | }
19 |
20 | search(query, expectBooksToHide){
21 | cy.get(this.searchBar).type(query)
22 | if(expectBooksToHide) {
23 | expect(cy.get(this.hiddenBooks).its('length')).to.not.equal(0)
24 | }
25 | }
26 |
27 | getVisibleBooks() {
28 | return cy.get(this.visibleBooks)
29 | }
30 | }
--------------------------------------------------------------------------------
/cypress/plugins/index.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example plugins/index.js can be used to load plugins
3 | //
4 | // You can change the location of this file or turn off loading
5 | // the plugins file with the 'pluginsFile' configuration option.
6 | //
7 | // You can read more here:
8 | // https://on.cypress.io/plugins-guide
9 | // ***********************************************************
10 |
11 | // This function is called when a project is opened or re-opened (e.g. due to
12 | // the project's config changing)
13 |
14 | module.exports = (on, config) => {
15 | // `on` is used to hook into various events Cypress emits
16 | // `config` is the resolved Cypress config
17 | }
18 |
19 |
20 | require('@applitools/eyes-cypress')(module);
21 |
--------------------------------------------------------------------------------
/cypress/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add("login", (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This is will overwrite an existing command --
25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
26 |
27 | ///
--------------------------------------------------------------------------------
/cypress/support/eyes-index.d.ts:
--------------------------------------------------------------------------------
1 | import "@applitools/eyes-cypress/eyes-index"
--------------------------------------------------------------------------------
/cypress/support/index.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 |
18 | import '@applitools/eyes-cypress/commands'
19 |
20 | import './commands'
21 |
22 | // Alternatively you can use CommonJS syntax:
23 | // require('./commands')
24 |
--------------------------------------------------------------------------------
/cypress/utils/search-validation-utils.js:
--------------------------------------------------------------------------------
1 | export class ValidationUtils {
2 |
3 | constructor(page) {
4 | this.page = page
5 | }
6 |
7 | validateNumberOfVisibleBooks(expectedCount) {
8 | this.page.getVisibleBooks().should('have.length', expectedCount, `There should be exactly ${expectedCount} book(s) visible`)
9 | }
10 |
11 | validateTitleIsVisible(title) {
12 | this.page.getVisibleBooks().within( ()=>{
13 | cy.get('h2').should('contain.text', title, `${title} should be visible`)
14 | })
15 | }
16 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bookstore-tests",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "cypress run"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "@applitools/eyes-cypress": "^3.9.2"
14 | },
15 | "devDependencies": {
16 | "cypress": "3.8.1"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------