preflight-cypress-plugin
Main features
- Tests adapt to UI changes when selectors are broken.
- Generic tests.
type('{{name.firstName}}'); => should('include.text', 'Good morning, {{name.firstName[1]}}
- Email testing
cy.openEmail('Verify your email');
- PDF testing
cy.openPdf('pdf-test');
- Visual testing
cy.get('#id').visualCheck('[UrlOrPathToYourImage]', 15);
- File upload testing.
- Automatically generates tests with fixed selectors if the test is broken.
Installation
1. Install the module.
npm install -D @preflight-hq/preflight-cypress-plugin
cypress/support/commands.js
.
2. Add the following line to require('@preflight-hq/preflight-cypress-plugin'); // Import Preflight plugin
3. Import plugin
For Cypress 10 and above
Add the following lines to cypress.config.js
.
const { defineConfig } = require('cypress')
const {importPreflightPlugin} = require('@preflight-hq/preflight-cypress-plugin/dist/importPreflightPlugin');
module.exports = defineConfig({
env: {
PREFLIGHT_API_KEY: '[YOUR_API_KEY]'
},
"chromeWebSecurity": false, // Enables PDF testing
e2e: {
setupNodeEvents(on, config) {
importPreflightPlugin(on); // Import Preflight plugin
}
}
})
Preflight.com
Create an account on- The API key will be generated for you automatically after creating account.
- Alternatively you can go to Account Settings / API to generate a new one.
Set API key in your test environment
- You can set key in code like
Cypress.PreflightApiKey = '[YOUR_API_KEY]';
- Or set Cypress env in your
cypress.config.js
file.
env: {
PREFLIGHT_API_KEY: '[YOUR_API_KEY]'
}
Creating test
- Once you have the plugin installed and set up with the API key you can create your first test.
- Download Chrome extension Cypress Recorder from Preflight
- Log in and follow instructions to create your first test.
Example of generated test
describe('test', () => {
it('YourWebApp - POM | Get/POM Autoheal | Email | Variables | checkpoint | Visual check', () => {
let loginYourWebApp = new LoginYourwebappPOM();
cy.viewport(1440, 900);
cy.pf.initAutoheal('SbiHS3EhZ3A8');
cy.visit('https://yourweb.app/#/login');
loginYourWebApp.clickSignup();
cy.pf.get('#pf-lesson-signup-0', {id:3}).type('{{name.firstName}}');
cy.pf.get('#pf-lesson-signup-1', {id:4}).type('{{name.lastName}}');
cy.pf.get('#pf-lesson-signup-2', {id:5}).type('{{generate.email}}');
cy.pf.get('#pf-lesson-signup-3', {id:6}).type('123456');
cy.pf.get('#pf-lesson-signup-4', {id:7}).click();
cy.pf.openEmail('Verify your email');
cy.pf.get('a', {iframe: '.data-box-content>iframe', id:9}).click();
cy.pf.closeEmail()
cy.pf.get('#pf-lesson-login-0', {id:11}).type('{{generate.email}}');
cy.pf.get('#pf-lesson-login-1', {id:12}).type('123456');
loginYourWebApp.clickSignIn(); // broken selector
cy.pf.get('h1', {id:14}).should('include.text', 'Good morning, {{name.firstName[1]}} {{name.lastName[1]}}');
cy.pf.get('.vue-apexcharts', {id: 15}).visualCheck('https://preflightuploadsdev.blob.core.windows.net/uploads/4450434e-e598-49d9-a102-3ec774ac7dec', {id:15});
cy.pf.get('.max-w-xs>svg', {id:16}).click();
cy.pf.get('[role="menu"]>button', {id:17}).click();
cy.pf.get('h2', {id:18}).should('include.text', 'Sign in to your account');
})
});
Example of generated POM.
export default class LoginYourwebappPOM {
visit() {
cy.visit('https://yourweb.app/#/login')
}
/**
"Sign in to your account" Box > "Signup" Button
href: #/signup | tag: a | purpose: navigation | class: font-medium
*/
clickSignup() {
return cy.get('.max-w>a')
.click();
}
/**
"Sign in to your account" Form > "Email address" Input
purpose: email | id: pf-lesson-login-0 | inputType: email | tag: input | class: shadow-sm, appearance-none, block, w-full, border, rounded-md
*/
typeEmailAddress(emailAddress) {
return cy.pf.get('[type="email"]', {id:'pom8YMwIPaIuhk1'})
.clear()
.type(emailAddress);
}
/**
"Sign in to your account" Form > "Password" Input
purpose: password | id: pf-lesson-login-1 | inputType: password | tag: input | class: shadow-sm, appearance-none, block, w-full, border, rounded-md
*/
typePassword(password) {
return cy.pf.get('[type="password"]', {id:'pomz4FaPS7Q7uV9'})
.clear()
.type(password);
}
/**
"Sign in to your account" Form > Checkbox
id: remember_me | tag: input | class: rounded
*/
clickCheckboxOption() {
return cy.pf.get('.rounded', {id:'pomnRn6xwZzGE9K'})
.click();
}
/**
"Sign in to your account" Form > "Forgot your password?" Button
href: #/forgot-password | tag: a | purpose: navigation | class: font-medium
*/
clickForgotYourPassword() {
return cy.pf.get('//*[contains(text(),"Forgot your password?")]', {id:'pomjz4XdywOmNUi'})
.click();
}
/**
"Sign in to your account" Form > "Sign in" Button
purpose: submit | id: pf-lesson-login-2 | tag: button | class: text-white, flex, justify-center, border, border-transparent, rounded-md, shadow-sm, text-sm, font-medium
*/
clickSignIn() {
return cy.pf.get('#pf-lesson-login-2', {id:'pomQB8D1uwQobiH'})
.click();
}
}
Convert code from v1 to v2
To convert your code to the new version you can use this JavaScript function
const convertCodeV1toV2 = (oldCode) => {
let newCode = oldCode;
// Replace "cy.initializeAutoheal" with "cy.pf.initAutoheal"
newCode = newCode.replace(/cy\.initializeAutoheal/g, "cy.pf.initAutoheal");
// Replace "cy.get" with "cy.pf.get" and add options object
newCode = newCode.replace(/cy\.get\((.+?),(\s*)(\d+)\)/g, "cy.pf.get($1, {id:$3})");
// Replace "cy.get" with "cy.pf.get" with iframe
newCode = newCode.replace(/cy\.get\((.+?),(\s*)(\d+),(.+?)\)/g, "cy.pf.get($1, {id:$3, iframe:$4})");
// Replace "cy.openEmail" with "cy.pf.openEmail"
newCode = newCode.replace(/cy\.openEmail/g, "cy.pf.openEmail");
// Replace "cy.closeEmail" with "cy.pf.closeEmail"
newCode = newCode.replace(/cy\.closeEmail/g, "cy.pf.closeEmail");
// Replace "cy.openPdf" with "cy.pf.openPdf"
newCode = newCode.replace(/cy\.openPdf/g, "cy.pf.openPdf");
// Replace "cy.closePdf" with "cy.pf.closePdf"
newCode = newCode.replace(/cy\.closePdf/g, "cy.pf.closePdf");
// Remove "cy.autoheal"
newCode = newCode.replace(/cy\.autoheal\(\);/g, "");
return newCode;
};
And use it like this
let newCode = convertCodeV1toV2(`
describe('test', () => {
it('Dashboard | YourWebApp', () => {
cy.viewport(1440, 900);
cy.initializeAutoheal('16a2d8905e8c');
cy.visit('https://yourweb.app/#/login');
cy.get('.max-w>a', 2).click();
cy.get('#broken', 3).type('{{name.firstName}}');
cy.get('a', 9, '.data-box-content>iframe').click();
cy.openEmail('Verify your email');
cy.closeEmail();
cy.openPdf('pdfName');
cy.closePdf();
cy.autoheal();
})
});`)
console.log(newCode)