admin管理员组

文章数量:1384366

I am currently working with Cypress and have created a function that randomly clicks an element from a list. I am trying to also get the text from that same function for future assertions. The problem is I am unable to return the text properly. The code I currently have is:

    export function selectRandomFromList(listLocator, elementLocator) {
    cy.get(listLocator).within(() => {
       let numberOfElements = Cypress.$(listLocator + ' ' + elementLocator).length
       let selected = Cypress._.random(0, numberOfElements - 1)
        cy.get(elementLocator).eq(selected).then(($text) => {
                const text = $text.text()
                return text
        }).click()
    })
  }

I was hoping that I could then in my test run this function, do the click and then store the returned text in a variable for future checking. What am I doing wrong? Also tried some other stuff with promises and such, when the code was saying I am trying to mix sync and async..

Forgot to add. This is in the support file and I want to use the text variable in the test file. Something like this:

var text = function.selectRandomFromList('[class*=***]', 'li ul li button')

After which I should have the text of the clicked button in text.

I am currently working with Cypress and have created a function that randomly clicks an element from a list. I am trying to also get the text from that same function for future assertions. The problem is I am unable to return the text properly. The code I currently have is:

    export function selectRandomFromList(listLocator, elementLocator) {
    cy.get(listLocator).within(() => {
       let numberOfElements = Cypress.$(listLocator + ' ' + elementLocator).length
       let selected = Cypress._.random(0, numberOfElements - 1)
        cy.get(elementLocator).eq(selected).then(($text) => {
                const text = $text.text()
                return text
        }).click()
    })
  }

I was hoping that I could then in my test run this function, do the click and then store the returned text in a variable for future checking. What am I doing wrong? Also tried some other stuff with promises and such, when the code was saying I am trying to mix sync and async..

Forgot to add. This is in the support file and I want to use the text variable in the test file. Something like this:

var text = function.selectRandomFromList('[class*=***]', 'li ul li button')

After which I should have the text of the clicked button in text.

Share Improve this question edited Apr 15, 2020 at 6:19 andrei1015 asked Apr 14, 2020 at 8:18 andrei1015andrei1015 631 gold badge2 silver badges11 bronze badges 1
  • 1 You shouldn't return values from Cypress mands, instead try to assign the value to an alias and retrieve it later. – user12697177 Commented Apr 15, 2020 at 7:07
Add a ment  | 

1 Answer 1

Reset to default 5

Cypress mands work the same way as Promises. You need to return a Promise when inside a then() callback. See doc here.

You may use cy.wrap($text).invoke('text') inside your then() callback instead of returning a string. But then, your click() would not work because your then() would yield a text value that cannot be clicked.

I suggest not using the within() and working directly with the elements. You'll end up with the same result, but with less plexity. I use the within() mand when I need to perform several actions on several elements within a div container for example.

You can perform what you need with default mands instead of a function:

let mixLocator = listLocator + ' ' + elementLocator;
cy.get(mixLocator).its('length').then(elementCount => {
    let selected = Cypress._.random(elementCount - 1); // lower = 0 is default
    cy.get(mixLocator).eq(selected).click().invoke('text').as('selectedText'); // saving the text as an alias to be used later
});

Here, the invoke('text') should still work even if it is after the click(), but it is impossible to do the opposite invoke('text').click() because the invoke('text') mand yields a string. If it doesn't, call it once to get the text and again to click it:

cy.get(mixLocator).eq(selected).invoke('text').as('selectedText');
cy.get(mixLocator).eq(selected).click();

or:

cy.get(mixLocator).eq(selected).then(selectedElement => {
    cy.wrap(selectedElement).invoke('text').as('selectedText');
    cy.wrap(selectedElement).click();
});

You may then use your saved alias later:

cy.get('@selectedText').then(selectedText => {
    // use selectedText here
});

I often prefer to chose random elements in our tests to have a better coverage. I came up with a custom mands:

mands.js

Cypress.Commands.add('any', { prevSubject: 'element' }, (subject, size = 1) => {
  cy.wrap(subject).then(elementList => {
    elementList = (elementList.jquery) ? elementList.get() : elementList;
    elementList = Cypress._.sampleSize(elementList, size);
    elementList = (elementList.length > 1) ? elementList : elementList[0];
    cy.wrap(elementList);
  });
});

I use it like this:

cy.get(elementLocator).any().click();

or

cy.get(elementLocator).any(5).each(randomElement => {
    cy.wrap(randomElement).click();
});

本文标签: javascriptCypressio function to click random element AND get its textStack Overflow