Kayote
Kayote

Reputation: 15647

Cypress Testing - expect text to be one of

I want to test against the values of an array of elements & the text content of each element should be one of 'a' or 'b'.

it("should display for adventure & cabin charter when both are the only ones selected", () => {
    cy.get("button.expCategoryBtn")
      .contains("a")
      .click();
    cy.get("button.expCategoryBtn")
      .contains("b")
      .click();
    // the following line doesnt work
    cy.get("div.tag").each(x => {
    // the problem line:
    // I want to get the text value of each el & expect
    // it to be one of a or b
      expect(cy.wrap(x).invoke("text")).to.be.oneOf([
        "a",
        "b"
      ]);
    });
  });

EDIT: I did it like this:

  it("should display for adventure & cabin charter when both are the only ones selected", () => {
    cy.get("button.expCategoryBtn")
      .contains("Adventure")
      .click();
    cy.get("button.expCategoryBtn")
      .contains("Cabin Charter")
      .click();
    cy.get("div.tag")
      .invoke("text")
      .should("include", "adventure")
      .should("include", "cabin_charter")
      .should("not.include", "science_and_nature");
  });

However, I am not happy with this and would still like some feedback on whats the correct way of testing when we wnat to assert one of multiple values. Thank you.

Upvotes: 4

Views: 17495

Answers (3)

Pasha Shtefanesku
Pasha Shtefanesku

Reputation: 31

To check text value being one of many, you can use expect, as was suggested by Zach, but you can do it without redundant nesting simply using should :

cy.get('div.tag')
  .invoke('text')
  .should('be.oneOf', ['adventure', 'cabin_charter']);

Additionally, instead of

cy.get('button.expCategoryBtn')
  .contains('Adventure')

you can omit the get part and just write:

cy.contains('button.expCategoryBtn', 'Adventure')

And the last one, to make it "prettier" instead of multiple should you can spice it up with and (it does exactly the same).

So, to sum up

it("should display for adventure & cabin charter when both are the only ones selected", () => {
  cy.contains('button.expCategoryBtn', 'Adventure')
    .click();
  cy.contains('button.expCategoryBtn', 'Cabin Charter')
    .click();
  cy.get('div.tag')
    .invoke('text')
    .should('be.oneOf', ['adventure', 'cabin_charter'])
    .and('not.include', 'science_and_nature');
});

p.s. I recommend checking cypress documentation to everyone who wants to start learning it, or is familiar but still has questions. It is quite comprehensible, useful and clear.

Upvotes: -1

hc_dev
hc_dev

Reputation: 9418

So the BDD specification would read like:

When user clicks both buttons A and B
Then both tags A and B are displayed

Multiple verification

We can use this multiple in Cypress by defining our set of buttons or tags using an array. This array can then be used to test repetitive similar interactions in sequence.

For simplicity I have duplicated the interaction lines with increasing index.

it("should display for adventure & cabin charter when both are the only ones selected", () => {
    const buttonText = ["Adventure", "Cabin Charter"];
    const tagText = ["adventure","cabin_charter"];

    // WHEN both buttons clicked
    cy.contains("button.expCategoryBtn", buttonText[0]).click();
    cy.contains("button.expCategoryBtn", buttonText[1]).click();

    // THEN both tags should be displayed
    cy.get("div.tag").should('have.length', 2)  // only 2 tags displayed
    cy.get("div.tag").eq(0).hould('have.text', tagText[0])
    cy.get("div.tag").eq(1).hould('have.text', tagText[1])
});

Note the emphasis on order using indexed arrays. This allows you to test and add for multiple buttons and tags.

Since we use an array we can also wrap the click-display verification inside a for-loop as sequence.

Sidenote: Click multiple

See also the explanation of click option { multiple: true } in RunEBook's article:Click a DOM element:

By default, Cypress will error if you're trying to click multiple elements. By passing { multiple: true } Cypress will iteratively apply the click to each element and will also log to the Command Log multiple times.

Upvotes: 0

Zach Bloomquist
Zach Bloomquist

Reputation: 5889

It kinda sounds like you're trying to do conditional testing, which is not a best practice.

Regardless, you can do this like so:

    cy.get("div.tag").each(x => {
      expect(x.text()).to.be.oneOf([
        "a",
        "b"
      ]);
    });

Upvotes: 10

Related Questions