Cypress Basic to Advance

1. Create file Platform_Login.cy.js under Cypress\e2e\Platform\Login

describe('My First Test', () => {
    it('Visits Sana framwork', () => {
      cy.visit('https://staging-platform.sana-commerce.com/')      
 
      // that the value has been updated
     cy.get('#Email')
    .type('s.kodagoda@sana-commerce.com')
    .should('have.value', 's.kodagoda@sana-commerce.com')
   cy.get('#Password')
    .type('xxxxxxxxx@123')
    .should('have.value', 'xxxxxxxxx@123')
   
  cy.get('[type=submit]').click()
  cy.title().should('eq','Sana Platform')
   
    })
  })


2. Create Folder Cypress\testbase\testbase.js


class testbase{
 
    Fill(locator, text)
{
        //Get element by by Html element       
        cy.get(locator).type(text)  
    }

    Click(locator)
{
        cy.get(locator).click()
    }
 

}
module.exports = new testbase();

Make it advance with Xpath Addon


class testbase{
 
    Fill(locator, text)
{
        //Get element by by Xpath
        if(locator.includes('//')) {
            cy.xpath(locator).type(text)
        }
        //Get element by by Html element
        else {
            cy.get(locator).type(text)            
        }  
    }

    Click(locator)
{
        cy.get(locator).click()
    }
}
module.exports = new testbase();


Update Login.cy.js

const I = require('../../../testbase/testbase')

describe('Test Login', () => {
  beforeEach(()=>{
    cy.visit('https://staging-platform.sana-commerce.com/')
})


  it('Test Login',()=>{                
      I.Fill('#Email','s.kodagoda@sana-commerce.com')        

  })


  })


Add file cypress/ pageObjects/loginPages.json

{
    "Login": {
      "LoginData": {
        "Email": "#Email",
        "Password": "#Password",
        "CaptureCheckBox": "div.recaptcha-checkbox-border",
        "LoginButton": "button.btn-block"
      }
    }
}

import page objects to the login page 

...
const PlatformLogin = require('../../../pageObjects/loginPages.json')

describe('Test Login', () =>
...

  it('Test Login',()=>{                
      I.Fill(PlatformLogin.Login.LoginData.Email,'s.kodagoda@sana-commerce.com')  
  })
...
 

import test data to login page 

const I = require('../../../testbase/testbase')
const PlatformLogin = require('../../../pageObjects/loginPages.json')
const TestData = require('../../../testdata/platformLoginData.json')

describe('Test Login', () => {
  beforeEach(()=>{
    cy.visit('https://staging-platform.sana-commerce.com/')
})


  it('Test Login',()=>{                
      I.Fill(PlatformLogin.Login.LoginData.Email,TestData.Login.LoginUserData.Email)        

  })

  })


Finaly Add Password and Login button

const I = require('../../../testbase/testbase')
const PlatformLogin = require('../../../pageObjects/loginPages.json')
const TestData = require('../../../testdata/platformLoginData.json')

describe('Test Login', () => {
  beforeEach(()=>{
    cy.visit('https://staging-platform.sana-commerce.com/')
})


  it('Test Login',()=>{                
      I.Fill(PlatformLogin.Login.LoginData.Email,TestData.Login.LoginUserData.Email)        
      I.Fill(PlatformLogin.Login.LoginData.Password,TestData.Login.LoginUserData.Password)
      I.Click(PlatformLogin.Login.LoginData.LoginButton)
  })

  })


Stage 2

How to use Fixtures (Load set of data located in a file)

copy Platform_Login.cy.js to the fixtures folder


Fat arrow function'=>'  with normal function
this keyword not working on Fat arrow function

()=>   ==  function()
(data)) => ==  function(data)


describe('Test Login', () => {
...
//Not working
     cy.fixture('PlatformLogins').then((data) => {
         this.data = data;         
         cy.log('e-mail: ',this.data.Email)
               
      })


PlatformLogins.json
  {
    "Name":"should login to Home page",
    "Email":"s.kodagoda@sana-commerce.com",
    "Password":"1smStandard@123",
    "Expected":"Invalid login attempt"    
  }
   

it('Test Fixture,Get All Platform Emails.', function() {
   
      cy.fixture('PlatformLogins').then(function(TestDataList) {
        this.TestDataList = TestDataList;

        cy.log('e-mail: ',this.TestDataList.Email)         
    })     
  })

add another 'it'

  it('Test Fixture,Login Platform Emails.', function() {
   
    cy.fixture('PlatformLogins').then(function(TestDataList) {
      this.TestDataList = TestDataList;

      cy.log('e-mail: ',this.TestDataList.Email)
   
     I.Fill(PlatformLogin.Login.LoginData.Email,this.TestDataList.Email)        
     I.Fill(PlatformLogin.Login.LoginData.Password,this.TestDataList.Password)
     I.Click(PlatformLogin.Login.LoginData.LoginButton)          
  })


Test with Multiple data

update PlatformLogins.json

[
    {
    "Name":"should login to Home page",
    "Email":"apitestuser@sana-commerce.com",
    "Password":"xxxxxxxxxxxxxxxxxxxxxx",
    "Expected":"Invalid login attempt"
    },
    {
        "Name":"should display incorrect user name message",
        "Email":"xxx@sana-commerce.com",
        "Password":"xxx@123",
        "Expected":"Invalid login attempt"
    },
    {
        "Name":"should display incorrect password message",
        "Email":"xxx@sana-commerce.com",
        "Password":"xxx@123",
        "Expected":"Invalid login attempt"
    }
]

add foreach to a basic method

it('Test Fixture,Get All Platform Emails.', function() {
   
      cy.fixture('PlatformLogins').then(function(TestDataList) {
        this.TestDataList = TestDataList;

        this.TestDataList.forEach(testLogin => {
           cy.log('e-mail: ',testLogin.Email)
         })
        //cy.log('e-mail: ',this.TestDataList.Email)              
    })      
  })

add foreach to a Login

 it('Test Fixture,Login Platform Emails.', function() {
   
    cy.fixture('PlatformLogins').then(function(TestDataList) {
      this.TestDataList = TestDataList;

      this.TestDataList.forEach(testLogin => {                
        I.Fill(PlatformLogin.Login.LoginData.Email,testLogin.Email)        
        I.Fill(PlatformLogin.Login.LoginData.Password,testLogin.Password)
        I.Click(PlatformLogin.Login.LoginData.LoginButton)
      })        
    })    
  })


create a folder fixture/testData and copy  PlatformLogins.json



get file 

const TestDataList = require('../../../fixtures/testData/PlatformLogins.json')

  // ~ ForEach Example ~

  TestDataList.forEach(testLogin =>{

    it(testLogin.Name,() =>{
      I.Fill(PlatformLogin.Login.LoginData.Email,testLogin.Email)        
      I.Fill(PlatformLogin.Login.LoginData.Password,testLogin.Password)
      I.Click(PlatformLogin.Login.LoginData.LoginButton)
               

      if(testLogin.Name=="should login to Home page")
      {
         
      }
      else{
        I.SeeText(PlatformLogin.Login.LoginData.ErrorMessage,testLogin.Expected)    
        //cy.get(PlatformLogin.Login.LoginData.ErrorMessage).should('have.text',testLogin.Expected)
      }

    })
  })


Cypress Hooks 

Create file e2e/hooks.cy.js

/*
Order

1. before --> Execute once, as soon as the first Test Script is executed
2 beforeEach > Executed Before Each TS is executed
3. testExecution
4. afterEach >  Executed After Each TS is executed
5. after > Execute once, as soon as the Last Test Script is executed
*/

describe('',function(){

    before(function(){
        cy.log('Before')
    })
    beforeEach(function(){
        cy.log('Before each')
    })


    it('TC #1',function(){
        console.log('TC #1')
    })
    it('TC #2',function(){
        console.log('TC #2')
    })
    it('TC #3',function(){
        console.log('TC #3')
    })
    it('TC #4',function(){
        console.log('TC #4')
    })

   
    afterEach(function(){
        cy.log('After each')
    })

    after(function(){
        cy.log('After')
    })
})


Commands 

video 12 (https://www.youtube.com/watch?v=66bEpdatEYQ&list=PLYDwWPRvXB8-8LG2hZv25HO6C3w_vezZb&index=12&ab_channel=JoanMedia)


support/commands.js

Cypress.Commands.add('typeLogin',(username,password)=>{
    cy.get('#Email').type(username)
    cy.get('#Password').type(password)
})


const PlatformLogin = require('../pageObjects/loginPages.json')

Cypress.Commands.add('typeLogin',(username,password)=>{
    cy.get(PlatformLogin.Login.LoginData.Email).type(username)
    cy.get(PlatformLogin.Login.LoginData.Password).type(password)
})


create file 

e2e/Commands/commadsTest.cy.js

typeLogin can call anywhere  ,support/e2e.js  jas already import 

//This is e2e.js
//Import commands.js using ES2015 syntax:
import './commands'


describe('Command example',function(){
    beforeEach(function(){
        cy.visit('https://staging-platform.sana-commerce.com/')      

       cy.typeLogin('s.kodagoda@sana-commerce.com','abc')

    })

    it('Visits Sana framwork', () => {      
      cy.log('test comands')  
cy.url().should('include', 'Home')   
      })
})


Add logout 

command.js

Cypress.Commands.add('logout',()=>{    
    cy.get('.image > .img-circle').click()
    cy.get("#logoutForm > a").click()
})

commandTest.cy.js

it('Test Login', () => {      
      cy.log('test comands')  
cy.url().should('include', 'Home')    
      })

      afterEach(function(){ <--------
        cy.logout()
      })


Move Logout details to pageobject

cypress/pageObject/homePages.json

{
    "Home": {
      "HeaderPanel": {
        "PlatformLogo": ".logo",
        "ProfileImage" : ".image > .img-circle",
        "ButonLogout" : "#logoutForm > a"
      }
    },
    "LeftPanelMenu": {
       "UserAccounts" : "//p[contains(text(),'User accounts')]",
       "ManageRolesMenuItem" : "//p[contains(text(),'Manage roles')]"
   
    }
}


update loginHelper

export function I_Login(){
  ...
}

export function I_Logout(){
    I.Click(PlaformHome.Home.HeaderPanel.ProfileImage)
    I.Click(PlaformHome.Home.HeaderPanel.ButonLogout)  
}


How Login/Logout use in Sana platform Code.

use separate Hepler class cypress/helpers/loginHelper.js

const I = require('../testbase/testbase')
const PlatformTestData = require('../fixtures/platformLoginData.json')
const PlaformLogin = require('../pageObjects/loginPages.json')

export function I_Login(){
    I.Fill(PlaformLogin.Login.LoginData.Email,PlatformTestData.Login.LoginUserData.Email)
    I.Fill(PlaformLogin.Login.LoginData.Password,PlatformTestData.Login.LoginUserData.Password)
    I.Click(PlaformLogin.Login.LoginData.LoginButton)
}


create file e2e/Platfrom/Home/PlatformHome.cy.js

import { I_Login } from "../../../helpers/loginHelper";

describe('Home page Testing', () => {
    it('get url from config file', () => {     
      cy.visit('https://staging-platform.sana-commerce.com/')          
 
      I_Login()
   
    })
  })


How to add site URL on config file 

update cypress.config.js 

Old versions have cypress.json but with new version its use on cypress.config.js 

...
  e2e: {
    setupNodeEvents(on, config) {
      // implement node event listeners here
    },
    baseUrl: 'https://staging-platform.sana-commerce.com/'
  },
});

PlatformHome.cy.js

import { I_Login } from "../../../helpers/loginHelper";

describe('Home page Testing', () => {
    it('get url from config file', () => {
      cy.visit(Cypress.config().baseUrl)
     
      I_Login()   
    })
  })


Move Visit method to testbase.js 

    SeeText(locator, expectedText)
    {  ... }

    Open(url="")
    {
        cy.visit(url);
    }


PlatformHome.cy.js

import { I_Login } from "../../../helpers/loginHelper";
const I = require('../../../testbase/testbase')

describe('Home page Testing', () => {
    it('get url from config file', () => {

      I.Open(Cypress.config().baseUrl)
      I_Login()   
    })
  })


If only import a function inside a file separately.

import { I_Login } from "../../../helpers/loginHelper";

if want to access all methods/functions

const LoginHelper = require('../../../helpers/loginHelper')


PlatformHome.cy.js

const LoginHelper = require('../../../helpers/loginHelper')
const I = require('../../../testbase/testbase')

describe('Home page Testing', () => {
    it('get url from config file', () => {
 
      I.Open(Cypress.config().baseUrl)
      LoginHelper.I_Login()      
      LoginHelper.I_Logout()   
    })
  })


add before each and after each.

const LoginHelper = require('../../../helpers/loginHelper')
const I = require('../../../testbase/testbase')

describe('Home page Testing', () => {
    beforeEach(function(){
        I.Open(Cypress.config().baseUrl)
        LoginHelper.I_Login()
    })

    it('get url from config file', () => {
     
      cy.log('test comands')
cy.url().should('include', 'Home')
   
    })

    afterEach(function(){
        LoginHelper.I_Logout()
      })

  })

Log and URL assertion move to testbase.js

Open(url="")
    {
       ...
    }
    Log(text){
        cy.log(text)
    }
    UrlInclude(pageName){
        cy.url().should('include', pageName)
    }
SeeInTitle(pageTitle)
    {
        cy.title().should('contain', pageTitle);
    }

PlatformHome.cy.js

describe('Home page Testing', () => {
    beforeEach(function(){
      ..
    })

    it('get url from config file', () => {     
      I.Log('test comands')
      I.UrlInclude('Home'
I.SeeInTitle('Sana Platform'
    })
...  
  })


Login with Session

need to add following to cypress.config.js

experimentalSessionAndOrigin : true


const { defineConfig } = require("cypress");

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      // implement node event listeners here
    },
    baseUrl: 'https://staging-platform.sana-commerce.com/',
    experimentalSessionAndOrigin : true  
  },
});


following example can pass session name as single string  or multiple strings.

describe('Login test with session', () => {
   
    beforeEach(()=>{
       
        cy.session('user',()=>{ //<-------- single string
            LoginHelper.I_Login()
           })
    })


multiple strings.

cy.session(['user','password',.....],()=>{


update login helper

export function I_Login(){
   
    I.Open(Cypress.config().baseUrl) <--------
    I.Fill(PlaformLogin.Login.LoginData.Email,PlatformTestData.Login.LoginUserData.Email)
    I.Fill(PlaformLogin.Login.LoginData.Password,PlatformTestData.Login.LoginUserData.Password)
    I.Click(PlaformLogin.Login.LoginData.LoginButton)
}

export function I_LoginWithSession(){
    cy.session('user',()=>{        
        I.Open('/')
        I.Fill(PlatformLogin.Login.LoginData.Email,PlatformTestData.Login.LoginUserData.Email)
        I.Fill(PlatformLogin.Login.LoginData.Password,PlatformTestData.Login.LoginUserData.Password)
        I.Click(PlatformLogin.Login.LoginData.LoginButton)
    })
}


When use commands.js 

const PlatformLogin = require('../pageObjects/loginPages.json')
const PlatformTestData = require('../fixtures/platformLoginData.json')
const I = require('../testbase/testbase')

...

Cypress.Commands.add('LoginWithSession',()=>{
    cy.session('user',()=>{              
        I.Open('/')
        I.Fill(PlatformLogin.Login.LoginData.Email,PlatformTestData.Login.LoginUserData.Email)
        I.Fill(PlatformLogin.Login.LoginData.Password,PlatformTestData.Login.LoginUserData.Password)
        I.Click(PlatformLogin.Login.LoginData.LoginButton)
    })

})


before and after use session Time reduce


always need to call the base URL 

it('Validate main 4 items',()=>{
      I.Open('/') <---------------
           
      cy.get('.container-fluid .row').find('.col-lg-3').should('have.length', 4)


    })

use unique id for session 

Install uuid

npm install uuid

command.js

import { v4 as uuidv4 } from 'uuid';
const userUuid = "user_"+uuidv4(); //<-----

Cypress.Commands.add('LoginWithSession',()=>{
   
    cy.session(userUuid,()=>{ //<-----
    //cy.session('user',()=>{    
        //cy.log("uuid :"+userUuid)
        I.Open('/')
        I.Fill(PlatformLogin.Login.LoginData.Email,PlatformTestData.Login.LoginUserData.Email)
        I.Fill(PlatformLogin.Login.LoginData.Password,PlatformTestData.Login.LoginUserData.Password)
        I.Click(PlatformLogin.Login.LoginData.LoginButton)
    })

})


Update homePages.json 

"Home": {
...
"DashBoardCards":[
        {  
          "Name":"ActiveTrial",    
          "Button":":nth-child(1) > .small-box > .small-box-footer",
          "RedirectUrl":"Webstore/AllWebstores?category=Active%20Trials",
          "DetailPageRedioButton":"#activeTrialsCheckBox"
        },
        {
          "Name":"InProduction",  
          "Button":":nth-child(2) > .small-box > .small-box-footer",
          "RedirectUrl":"Webstore/AllWebstores?category=In%20Production",
          "DetailPageRedioButton":"#inProductionCheckBox"
        },      
        {
          "Name":"ExpiredTrials",  
          "Button":":nth-child(3) > .small-box > .small-box-footer",
          "RedirectUrl":"Webstore/AllWebstores?category=Expired%20Trials",
          "DetailPageRedioButton":"#extendTrialsCheckBox"
        },    
        {
          "Name":"ExpiredTrials",  
          "Button":":nth-child(4) > .small-box > .small-box-footer",
          "RedirectUrl":"#",
          "DetailPageRedioButton":"#archivedCheckBox"
        }
      ]


PlatformHome.cy.js

 ...

it('Redirect to Active trails',()=>{
      I.Open('/')
      I.Click(HomePage.DashBoard.DashBoardCards.ActiveTrial.Name)      
      I.UrlInclude(HomePage.DashBoard.DashBoardCards.ActiveTrial.RedirectUrl)
      //I.Wait(1000)      
      cy.get(HomePage.DashBoard.DashBoardCards.ActiveTrial.DetailPageRedioButton).should('be.checked').and('have.value', 'Active Trials')
     
    }) 

    it('Redirect to In production',()=>{
      I.Open('/')
      I.Click(HomePage.DashBoard.DashBoardCards.InProduction.Name)      
      I.UrlInclude(HomePage.DashBoard.DashBoardCards.InProduction.RedirectUrl)
      cy.get('#inProductionCheckBox').should('be.checked').and('have.value', 'In Production')
     
    })
...


To reduce code, we can write above as following

PlatformHome.cy.js


//use for each
    const dashBoardCards = HomePage.DashBoardCards;
   
    dashBoardCards.forEach(dashBoardCard =>{
      it("Testing Dash board card: " + dashBoardCard.Name,() =>{
       
         I.Open('/')
         I.Click(dashBoardCard.Button)      
         I.UrlInclude(dashBoardCard.RedirectUrl)
         I.Wait(1000)      
          cy.get(dashBoardCard.DetailPageRedioButton)
          .should('be.checked')
          .and('have.value', dashBoardCard.RedioButtonValue)        
      })
    })


Home Header buttons 

homePage.json

"Home": {
      ...
        "TopMenu":[{
          "Name":"Manage",
          "Button":".main-header > .navbar-nav > :nth-child(1) > .nav-link",
          "RedirectUrl":"/Webstore/AllWebstores"
         
        },
        {
          "Name":"New",          
          "Button":".navbar-nav > :nth-child(2) > .nav-link",
          "RedirectUrl":"/Webstore/Install"          
        },
        {
          "Name":"Create",
          "Button":".navbar-nav > :nth-child(3) > .nav-link",
          "RedirectUrl":"/User/CreateUser"          
        },
        {
          "Name":"Help",
          "Button":".navbar-nav > :nth-child(4) > .nav-link",
          "RedirectUrl":"/help"          
        }
      ]
      }
    },


How to write one by one 

//Home Header buttons : Manage
    it('Redirect to Expired Trials',()=>{
      I.Open('/')
       //const ss = HomePage.Home.HeaderPanel.TopMenu;

      I.Click(HomePage.Home.HeaderPanel.TopMenu[0].Button)        
      I.UrlInclude(HomePage.Home.HeaderPanel.TopMenu[0].RedirectUrl)
      cy.get(HomePage.Home.HeaderPanel.TopMenu[0].DetailPageRedioButton).should('be.checked')
      .and('have.value', 'All')
    })  


Home page Left Panel menu Testing 

NewInstallation.json

 },
    "LeftPanelMenu": {
       "MenuButton":"cy.get('.main-nav-wrapper > .navbar-nav > .nav-item > .nav-link')",
       "LeftPanelMenuItems":[
        {
          "Name":"Installations",
          "Button":".active",
          "MenuItems" :[{
            "Name":"New installation",
            "Button":".menu-open > .nav > :nth-child(1) > .nav-link",
            "RedirectUrl":"/Webstore/Install"          
          },
          {
            "Name":"All installations",
            "Button":".menu-open > .nav > :nth-child(2) > .nav-link",
            "RedirectUrl":"/Webstore/AllWebstores"
          }
        ]
         
        },
        {
          "Name":"Approvals",
          "Button":"#approvalMenu > [href='#']",
          "MenuItems" :[{
            "Name":"New installation",
            "Button":"#approvalMenu > .nav > :nth-child(1) > .nav-link",
            "RedirectUrl":"/Approval/WebstoreInstallationRequests"          
            }
          ]          
        }
       ]        
    },


Platform.cy.js

 // Left Panel Menu --------------------------------------------------

    const leftPanelMenuItems = HomePage.LeftPanelMenu.LeftPanelMenuItems;
    leftPanelMenuItems.forEach(leftPanelMenuItem =>{
     
      const subMenuItems = leftPanelMenuItem.MenuItems;
      subMenuItems.forEach(subMenuItem =>{

        it("Left Panel: " + leftPanelMenuItem.Name+" : " + subMenuItem.Name,() =>{
       
          I.Open('/')
          I.Click(leftPanelMenuItem.Button)    
          I.Click(subMenuItem.Button)      
          I.UrlInclude(subMenuItem.RedirectUrl)          
        })
      })



Add Snippet for VS Code

Ctrl +shift +p

type "snippet" 

select javascript it will open javascript .js file 

"Console log":{
        "prefix":"cl",
        "body":"console.log($1);",
        "description": "Console Log"
    }

When yo type cl it will create the code for you

 console.log();

https://snippet-generator.app/


    },
    "IT": {
        "prefix": "it",
        "body": [
          "it(${1:functionName},()=>{",
          "})"
        ],
        "description": "IT"
      }

after use

     it(functionName,()=>{
     })


cypress screenshort.

it(userData.Title,() =>{
    I.Fill(PlatformLogin.Login.LoginData.Email,userData.Email)        
    I.Fill(PlatformLogin.Login.LoginData.Password,userData.Password
   
cy.screenshot(); //<----

  })

it will create a new folder.



How  to retry 

...
    baseUrl: 'https://staging-platform.sana-commerce.com/',
    experimentalSessionAndOrigin : true  ,
    retries:2 // 1 + 2 extra times
  },
});


Configure Dashboard 

Cypress.config.js

login and add project id 

module.exports = defineConfig({
....
    retries:3,
    projectId: "w81smh"
  },
});


cypress dashboard

https://www.youtube.com/watch?v=ydTviHjpxh0&ab_channel=JoanMedia




past on :cypress.config.js

  e2e: {
    .....
    retries:3,
    projectId: "w81smh" // <-------
  },


npx cypress run --record --key da6d9485-4c46-49f9-b5e3-c4a9926889ef


Note: To locate the project-id and record-key of your Cypress project, navigate to Project > Project Settings in the Cypress dashboard. You can find the project-id and record-key under the General and



cypress-axe

https://www.npmjs.com/package/cypress-axe


npm install --save-dev cypress-axe

package.json  record adds automatically.

 "cypress-axe": "^1.0.0",

add e2e.js

import 'cypress-axe'

accessbility.cy.js


describe('Testing', () => {    
     
    it("How to test accesbility",()=>{
        cy.visit("https://staging-platform.sana-commerce.com/")
        cy.injectAxe() // staart the injector / scan the site
        cy.checkA11y()

    })

 })


improve 

https://www.youtube.com/watch?v=TaBhwaOy1XI&ab_channel=Sparkbox



Add Emoji 

click extension > type emoji

install 




File >Preferance > Settings 

User Tab> Extention > :emojisense > Edit in Settings .json


paset the flowing test inside emojisense.languages

"javascript.validate.enable": false, "abap": true, "bat": true, "bibtex": true, "clojure": true, "coffeescript": true, "c": true, "cpp": true, "csharp": true, "css": true, "diff": true, "dockerfile": true, "fsharp": true, "git-commit": true, "git-rebase": true, "go": true, "groovy": true, "handlebars": true, "html": true, "ini": true, "java": true, "javascript": true, "javascriptreact": true, "json": true, "jsonc": true, "latex": true, "less": true, "lua": true, "makefile": true, "markdown": true, "objective-c": true, "objective-cpp": true, "perl6": true, "php": true, "powershell": true, "jade": true, "python": true, "r": true, "razor": true, "ruby": true, "rust": true, "scss": true, "sass": true, "shaderlab": true, "shellscript": true, "sql": true, "swift": true, "typescript": true, "typescriptreact": true, "tex": true, "vb": true, "xml": true, "xsl": true, "yaml": true }

full doc looks like as following 

{
    "diffEditor.codeLens": true,
    "javascript.referencesCodeLens.enabled": true,
    "javascript.referencesCodeLens.showOnAllFunctions": true,
    "typescript.implementationsCodeLens.enabled": true,
    "typescript.referencesCodeLens.enabled": true,
    "typescript.referencesCodeLens.showOnAllFunctions": true,
   
    "emojisense.languages": {

        "markdown": true,
        "plaintext": {
            "markupCompletionsEnabled": true,
            "emojiDecoratorsEnabled": true
        },
        "scminput": true,
        "git-commit": true,

        "javascript.validate.enable": false,
        "abap": true,
        "bat": true,
        "bibtex": true,
        "clojure": true,
        "coffeescript": true,
        "c": true,
        "cpp": true,
        "csharp": true,
        "css": true,
        "diff": true,
        "dockerfile": true,
        "fsharp": true,
        "git-commit": true,
        "git-rebase": true,
        "go": true,
        "groovy": true,
        "handlebars": true,
        "html": true,
        "ini": true,
        "java": true,
        "javascript": true,
        "javascriptreact": true,
        "json": true,
        "jsonc": true,
        "latex": true,
        "less": true,
        "lua": true,
        "makefile": true,
        "markdown": true,
        "objective-c": true,
        "objective-cpp": true,
        "perl6": true,
        "php": true,
        "powershell": true,
        "jade": true,
        "python": true,
        "r": true,
        "razor": true,
        "ruby": true,
        "rust": true,
        "scss": true,
        "sass": true,
        "shaderlab": true,
        "shellscript": true,
        "sql": true,
        "swift": true,
        "typescript": true,
        "typescriptreact": true,
        "tex": true,
        "vb": true,
        "xml": true,
        "xsl": true,
        "yaml": true        
    }
}


Then Type -- > :Circle 

/*
  //checkPageA11y
  //https://www.youtube.com/watch?v=TaBhwaOy1XI&ab_channel=Sparkbox
  Cypress.Commands.add('checkPageA11y', (path) => {
     
      cy.visit(path)
      cy.injectAxe() // staart the injector / scan the site
      cy.checkA11y(null,null,callback)
    })
   

function callback(violations){

    violations.forEach(violation =>{
        const nodes = Cypress.$(violation.nodes.map(node=> node.target).join(','))

        Cypress.log({
            name:`${severityIndicators[violation.impact]} A11y`,
            consoleProps:()=> violation,
            $el:nodes,
            message:`[${violation.help}](${violation.helpUrl})`
        })

        violation.nodes.forEach(({target}) => {
            Cypress.log({
                name: '🔧',
                consoleProps:() => violation,
                $el: Cypress.$(target.join(',')),
                message:target
            })
        })


    })
}
const severityIndicators={
    minor: 'Minor ⚪',
    moderate: 'Moderate 🟡',
    serious: 'Serious 🟠',
    critical: 'Critical 🔴'
   
}

*/


accesbilityhelper.js

  //checkPageA11y
  //https://www.youtube.com/watch?v=TaBhwaOy1XI&ab_channel=Sparkbox

const severityIndicators={
    minor: 'Minor ⚪',
    moderate: 'Moderate 🟡',
    serious: 'Serious 🟠',
    critical: 'Critical 🔴'
}

function callback(violations){

    violations.forEach(violation =>{
        const nodes = Cypress.$(violation.nodes.map(node=> node.target).join(','))

        Cypress.log({
            name:`${severityIndicators[violation.impact]} A11y`,
            consoleProps:()=> violation,
            $el:nodes,
            message:`[${violation.help}](${violation.helpUrl})`
        })

        violation.nodes.forEach(({target}) => {
            Cypress.log({
                name: '🔧',
                consoleProps:() => violation,
                $el: Cypress.$(target.join(',')),
                message:target
            })
        })


    })
}

export function I_CheckPageAccesbility_A11y(path){
     
    cy.visit(path)
    cy.injectAxe() // start the injector / scan the site
    cy.checkA11y(null,null,callback)
}


Type script 

install 

npm install --save-dev typescript


it will add record in package.json 

"devDependencies": {
    "cypress": "^10.3.0",
    "cypress-axe": "^1.0.0",
    "cypress-xpath": "^2.0.0",
    "typescript": "^4.8.4" <------------------------
  },

Configure tsconfig.json

We recommend creating a tsconfig.json inside your cypress folder with the following configuration:

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["es5", "dom"],
    "types": ["cypress", "node"]
  },
  "include": ["**/*.ts"]
}


Invoke 

can use the Jquery function inside cypress

cy.get('#IPAddresses').invoke('attr', 'placeholder').should('contain', 'The partne..')


cypress file upload

npm install --save-dev cypress-file-upload


find 

      // cy.get(".card-columns").find('.card').each(($card) => {
        cy.get(overviewPage.Overview.CardsPath).each(($card) => {            
            count += 1
        }).then(() =>{
            expect(count, 'count').to.equal(8)
            cy.get(overviewPage.Overview.CardsPath).its('length').should('eq', count)
        })



testautomationu.applitools.com



from: https://testautomationu.applitools.com/cypress-tutorial/chapter3.html

Whether Cypress will watch and restart tests on test file changes.

watchForFileChanges:false //it will control restart tests on test file changes.


Delay an element 

?delay-new-todo=5000'

cy.get('.new-todo',{timeout:6000})

it("functionName",()=>{
    cy.visit('http://todomvc-app-for-testing.surge.sh/?delay-new-todo=5000')
   
    cy.get('.new-todo',{timeout:6000}).type("Clean room{enter}")
})


How to get the length of the collection and return 

it.only("Multiple assertions",()=>{
     
        cy.get("table[id='partnerGrid'] thead > tr >th")
         .then(item =>{
               
            const listingCount = item.length
            //const listingCount = Cypress.$(item).length;
            cy.log("List count "+listingCount)             
           
         })              
       
     })

simple way 

 cy.get("#partnerGrid>thead>tr>th").should('have.length','4')


How to throw an error 

 throw new Error("sdsdsd")


Expect text 

expect(item[1]).to.contain.text('Sana ERP partner')


https://testautomationu.applitools.com/advanced-cypress-tutorial/chapter4.html

When the element is hidden 

 cy.get("location").invoke('show')
        .click()

        // add css class
 cy.get("location")
        .invoke('addClass','NewClassName')
       
        //hover change event trigger
 cy.get("location")
        .trigger('mouseover')


environment variables 

export function FillGenerateName(locator,name){
    const randomName = Name_Alpha_Numeric()
    name = name+randomName
    cy.get(locator).type(name)
   
    // Create Environment variables
    Cypress.env('GenerateWebStoreName', name)  //<-------------
    return name;
}


  let webStoreName = Cypress.env('GenerateWebStoreName')


Get name from and assign to the variable 

 cy.get(allWebStoresTable.LatestWebStoreNamePath)
         .then(item =>{
                 webStoreName = item.text()
                 I.Log("Site Name inside: "+ webStoreName)


covert API response to json

convert json to string
const webstores =JSON.stringify(res.body)
cy.log(webstores)


Cypress Auto-completion use following

/// <reference types="cypress"/>


---------------------------------------------------------------------------

Install Cypress Grep for tagging

npm install -g cypress-grep

 npm i -D @cypress/grep --force 





it will auto-update package,json and package-lock.json



update e2e.ts 

// Import commands.js using ES2015 syntax:
import './commands'
import './commands/commands'
import 'cypress-axe'
import 'cypress-file-upload'

// Alternatively you can use CommonJS syntax:
// require('./commands')
require('cypress-xpath');

 const registerCypressGrep = require('@cypress/grep')
 registerCypressGrep()

// if you want to use the "import" keyword
// note: `./index.d.ts` currently extends the global Cypress types and
// does not define `registerCypressGrep` so the import path is directly
// pointed to the `support.js` file
import registerCypressGrep from '@cypress/grep/src/support'
registerCypressGrep()


add command so no need to call all the cy.ts pages 




describe('🥇 Field Verification',{tags:'@smoke'}, () => {

npx cypress run --env grepTags=@smoke


npx cypress run --headed --env grepTags=@smoke --record --key 56dcf788-902a-42f3-ba5f-93b05694a61d

How to run Head mode 

 npx cypress run --headed


Add reporting to Cypress 

install  cypress-mochawesome-reporter

follow this : https://www.npmjs.com/package/cypress-mochawesome-reporter

1 install cypress-mochawesome-reporter

npm i --save-dev cypress-mochawesome-reporter 

--force 

use following to ignore warnings 
npm i --save-dev cypress-mochawesome-reporter --force

it will update package.json 

 "cypress-mochawesome-reporter": "^3.5.0", <--------------------


Change cypress reporter & setup hooks

const { defineConfig } = require('cypress');

module.exports = defineConfig({
  reporter: 'cypress-mochawesome-reporter',
  e2e: {
    setupNodeEvents(on, config) {
      require('cypress-mochawesome-reporter/plugin')(on); 
    },
  },
});
Add to cypress/support/e2e.js
import 'cypress-mochawesome-reporter/register';

it will create a folder as 
~\cypress\reports\html



-----------------------------------------------------------------------------------------------------------
Change base URL on comandline 

package.json

"scripts": {
    ...
   
"cypress:open4": "cypress open --config baseUrl=http://www.google.com/",  
    
   
  },

execute as follows,
npm run cypress:open4






Visual testing 

https://applitools.com/
https://applitools.com/tutorials/quickstart/web/cypress#applitools-eyes-cypress-sdl

to install 

npm install @applitools/eyes-cypress

and 
npx eyes-setup

it will add new dependency to 'package.json'





Cypress Chrome recorder

https://www.youtube.com/watch?v=-RJuZrq-wOk&t=194s&ab_channel=Cypress.io

1. install the chrome browser extension.
2. record the process and save 
3. When saving as JSON  you need to convert JSON to a cypress file 
    to do that we are required to install following 

npm install --location=global  @cypress/chrome-recorder

(disable the Global protector)

4. after installation, convert the file. 
create output folder path (cypress/tests/ui )

npx @cypress/chrome-recorder D:/Recordingcy.json -o=cypress/tests/ui


or use Export via extension  > cypress Test


 

Cypress Cross-origin testing



install "@cypress/webpack-preprocessor"

cypress.config.ts  set following 
chromeWebSecurity:false
experimentalOriginDependencies :true,


To prevent button click exceptions use 


Cypress.on('uncaught:exception', (err, runnable) => {
    // returning false here prevents Cypress from failing the test
    return false
  })





Cypress API plugging

https://www.youtube.com/watch?v=kENXELkT4O4&ab_channel=LambdaTest



npm install --save-dev @bahmutov/cy-api
command.ts
import '@bahmutov/cy-api'

update tsconfig.json

"types": ["cypress", "node","cypress-xpath","cypress-axe","@bahmutov/cy-api"],

output



Cy spok

npm i -D cy-spok
its uses to make expected body  items value generic 


chai-json-schema


npm install chai-json-schema

e2e.ts

chai.use(require('chai-json-schema'));



Json Not working with typescript 

to fix add folowing to tsconfig file 


{
  "compilerOptions": {
   ...
    "resolveJsonModule": true, <-------------------
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true, // use json import
  },
 
}



cypress API New with new update

https://www.npmjs.com/package/cypress-plugin-api


npm i cypress-plugin-api
it will add new dependent 

"dependencies": {
    "chai-json-schema": "^1.5.1",
    "cypress-plugin-api": "^2.11.0" <--------------------------------
  }