2

I need to use an alias I got after intercepting a cy.wait(@..) in other tests (in different files), but I am not sure how I could do it.

However, seems like it is possible if save the data in plugins/config space and then fetch using cy.task But I am not sure how to do it. Maybe someone could help me?

I am intercepting this request cy.intercept('POST', '**/quotes').as('abccreateQuote')

and as well I am getting the quote Id that comes in the response body.

cy.wait('@createQuote').then(({ response }) => {
        if (response?.statusCode === 201) {
          cy.wrap(response.body.data.id).as('abcQuoteId')
        }  
      })

I need to use this abcQuoteId alias in different tests and located it in different files.

to visit the page cy.visit(`quotes/${abcQuoteId}/show`)

Fah
  • 207
  • 3
  • 16

2 Answers2

1

A task would do it, but less code if you write to a fixture file

cy.wait('@createQuote').then(({ response }) => {
  if (response?.statusCode === 201) {
    cy.writeFile('./cypress/fixtures/abcQuoteId.json', {abcQuoteId: response.body.data.id})
  }  
})

Advantage over task, you can check the fixture file manually in case of typos, should look like this:

{
  "abcQuoteId": 123
}

and use it like this

cy.fixture('abcQuoteId.json')
  .then(fixture => {
    const url = `quotes/${fixture.abcQuoteId}/show`
    console.log(url)                                  // quotes/123/show
    cy.visit(url)
  })
Fody
  • 23,754
  • 3
  • 20
  • 37
  • the files are already created, I need to add data to the file and not create a file. the test will be running a few times and if each time use ```cy. cy.writeFile``` I will have too many files in the end – Fah Sep 27 '22 at 15:33
  • updated your answer so I can select it. I fixed the issue and now it is working ```cy.wait('@createQuote').then(({ response }) => { if (response?.statusCode === 201) { cy.readFile('./cypress/fixtures/abc/abcQuoteId.json').then( (abcQuote) => { abcQuote.abcQuoteId = response.body.data.id cy.writeFile( './cypress/fixtures/abc/abcQuoteId.json', abcQuoteId ) } ) } }) ``` – Fah Sep 27 '22 at 16:23
0

This will allow you to create infinite stores with values that will be available all the time while Cypress is running.

Each Store with it's values is available between all spec files.

Usage:

Saving some value:

// spec.file1.js

cy.wait('@createQuote').then(({ response }) => {
  if (response?.statusCode === 201) {
    cy.task('setItem', {
      storeId: 'Global',
      item: {
        name: 'createQuoteResponse',
        value: response.body.data.id,
      },
    })
  }  
})

Getting the above value inside another spec file:

// spec.file2.js

cy.task('getItem', {
  storeId: 'Global',
  item: {
    name: 'createQuoteResponse',
  },
}).then((item) => {
  console.log(item) // Your response code
})

How to implement?

Edit: Install cypress-store-plugin

npm install @optimumqa/cypress-store

End of Edit

May seem like a lot of code, and it is. But once setup, you won't have to modify or worry about it.

Create a ./cypress/plugins/Store.js file and paste following code:

// `./cypress/plugins/Store.js`

const StoreHelper = require('../support/Store')
const stores = {}

class Store {
  constructor(on, config, pluginConfig) {
    this.CONFIG = {
      ...{
        logging: false,
      },
      ...(pluginConfig || {}),
    }

    this.init(on, config, pluginConfig)
  }
  init(on, config, pluginConfig) {
    on('task', {
      /**
       * @description - Store items to specific store. If store does not exist, it will be created
       *
       * @param {String} data.id - Store id
       * @param {Object} data.item - Object containing item info
       * @param {String} data.item.name - Item name
       * @param {Any} data.item.value - Item value
       *
       * @returns {Store.Item|Null}
       */
      setItem: (data) => {
        let store = stores[data.storeId]
        if (!store) {
          stores[data.storeId] = new StoreHelper()
          store = stores[data.storeId]
        }

        return store.setItem(data.item) || null
      },

      /**
       * @description - Get items from specific store
       *
       * @param {String} data.id - Store id
       * @param {Object} data.item - Object containing item info
       * @param {String} data.item.name - Item name
       *
       * @returns {Store.Item|Null}
       */
      getItem: (data) => {
        const store = stores[data.storeId]
        if (store) {
          return store.getItem(data.item)
        }

        return null
      },
    })
  }
}

module.exports = Store

Then create one more other file ./cypress/support/Store.js and paste following code in it:

// `./cypress/support/Store.js`

class Store {
  constructor() {
    /** @type {object} */
    this.items = {}

    return this
  }

  getItem(data = {}) {
    return this.items[data.name] || null
  }

  setItem(data = {}) {
    this.items[data.name] = new Item(data)

    return this.items[data.name]
  }
}

class Item {
  constructor(data = {}) {
    this.name = data.name || ''
    this.value = data.value || undefined

    return this
  }
}

module.exports = Store

Cypress < v10

Inside your ./cypress/plugins/index.js require the plugin like this:

You need to require the Store file from plugins/.

// `./cypress/plugins/index.js`

module.exports = (on, config) => {
  require('./Store')(on, config)
}

Cypress >= v10

// `./cypress.config.js`

const { defineConfig } = require('cypress')
const Store = require('./cypress/plugins/Store')

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      Store(on, config)    
    },
  },
})

This is by default enabled in the cypress-boilerplate

Darko Riđić
  • 459
  • 3
  • 18