Skip to content

Instantly share code, notes, and snippets.

@DominikStyp
Last active March 25, 2022 13:22
Show Gist options
  • Save DominikStyp/a6e2f2641c856ac183506cc98228e4ad to your computer and use it in GitHub Desktop.
Save DominikStyp/a6e2f2641c856ac183506cc98228e4ad to your computer and use it in GitHub Desktop.
Cypress: example tests
# Dependency directories
node_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
/cypress/videos/
/cypress/screenshots/
{
"baseUrl": "http://some.site.localhost:3000",
"chromeWebSecurity": false,
"video": false,
"env": {
"backendBaseUrl": "http://api.some.site",
"adminUser": {
"email":"admin@example.com",
"password": "admin123"
}
}
}
export class MailDevHelper {
private static maildevUrl = 'http://localhost:1080/';
static clickActivationLinkFromLastEmail(anchorSelector: string, anchorText: string): Cypress.Chainable {
/**
* Flow:
* 1) run http://localhost:1080/ (maildev) in the current window
* 2) click the first email
* 3) get activation link from email: anchor.attr('href')
* 4) go to the activation link
*/
return cy.window().then((win) => {
win.location.href = this.maildevUrl;
cy.get('.email-list .email-item').eq(0).click();
cy.wait(1000);
return this.getIframeBody()
.find(anchorSelector)
.contains(anchorText)
.eq(0)
.then((anchor) => {
win.location.href = anchor.attr('href');
});
});
}
private static getIframeDocument(): Cypress.Chainable {
return cy.get('iframe.panel-html').its('0.contentDocument').should('exist');
}
private static getIframeBody(): Cypress.Chainable {
return this.getIframeDocument().its('body').should('not.be.undefined').then(cy.wrap);
}
}
{
"private": true,
"devDependencies": {
"@types/faker": "^5.5.9",
"cypress": "^9.0.0",
"faker": "^5.5.3",
"typescript": "^4.5.2"
}
}
it('Re-seed Laravel database', () => {
// Warmging: make sure -T option is checked because it disables pseudo-tty allocation
// https://stackoverflow.com/questions/43099116/error-the-input-device-is-not-a-tty
cy.exec("cd ../../backend/.docker && docker-compose exec -T api bash -c 'php artisan migrate:fresh --seed'", {
failOnNonZeroExit: false,
timeout: 60 * 1000,
}).then((result) => {
cy.log(result.stdout);
cy.log(result.stderr);
expect(result.stdout).to.contain('Migration table created successfully.');
});
});
// contains all test suites
import { Search } from '../support/Actions/Search';
describe('E2E tests', () => {
it('Search: price range', () => {
Search.priceRange();
});
});
export class Search {
static priceRange() {
// visit search page
cy.visit('/searchPage');
cy.get('.filter-box').then((el) => {
// intercept the AJAX request to the backend API and set 'search' .as('someAlias')
// you can use regular expressions here too, and glob pattern matching
// also you can define which method do you expect: PUT, PATCH, POST, DELETE, GET
cy.intercept(`${Cypress.env('backendBaseUrl')}/api/v1/search?price[]=,10000*`).as('search');
// test click checkbox "Price up to 10k"
cy.wrap(el)
.find('.title')
.contains('Price')
.next('.content')
.find('.filter-checkboxes .element')
.eq(0)
.contains('Price up to 10k')
.find('.form-check-input')
.click();
// click search button
cy.get('.search-button').click();
// wait for the 'search' endpoint to end (which was aliased as 'search' above)
// and checks if the status of the response is 200
cy.wait('@search').its('response.statusCode').should('eq', 200);
// check if current location contains "filterPrice=%2C1000"
cy.location('search').should('match', /filterPrice=%2C10000/);
// use chai assertions
cy.get('input[name="address"]').should('have.value', '2436 Rayburn House Office Building');
// use invoke to run methods from jQuery element like 'val' and chain more actions after that
cy.get('input[name="address"]').invoke('val', '').type('2436 Rayburn House Office Building');
// select all Card_price elements, iterate over them and check if innerHTML matches regular expression
cy.get('[class^="Card_price"]').each((el) => {
cy.wrap(el).contains(/\$\d,\d+/);
});
// select <select> tag and check option
cy.get('.acre-bootstrap-table tr:first-child form select', { timeout: 10000 }).each((select) => {
const val = select.val();
const optName = select.find(`option[value="${val}"]`).text();
cy.log(`Current listing option: ${optName}`);
const newVal = val === 1 ? 2 : 1;
const newOpt = select.find(`option[value="${newVal}"]`).text();
// change selected option to 2 if it's 1, and to 1 if it's 2
cy.wrap(select).select(newOpt);
});
});
}
}
{
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom"],
"types": ["cypress", "faker"]
},
"include": [
"**/*.ts"
]
}
@DominikStyp
Copy link
Author

Examples for:

  • visiting page
  • wait for endpoints
  • iterate over HTML elements that are JQuery elements

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment