Is there any way to test every possible combination of a sentence with cypress?

Viewed 62

Let say there are three array.

const initialArray = ['He', 'She', 'It']

const middleArray = ['is', 'was', 'were']

const lastArray = ['a dog', 'a cat', 'a wizard']

What I mean is if any of these 3 combinations comes the sentence is valid but the sentence need to be

'initialArray middleArray lastArray' only this sequence combination is correct others are false

I am trying to write something like this which is hardcoded but it won't work when the number of variables increase.

cy.get(`.${className} .legend_title`).should((key) => {
            let mytext = key.text();
            expect(mytext.trim()).to.be.oneOf([
              'He is a dog',
              "He is a cat",
              'He is a wizard',
              'She is a dog', .......
            ]);
          });
4 Answers

An easier way is to use regex to match against the sentence. You can programmatically create the matcher if you choose.

Here is a working example.

// regex for simpilicity
const matcher = /(He|She|It)\s(is|was|were)\s(a)\s(dog|cat|wizard)/i;
cy.get("#sentence").invoke("text").should("match", matcher);

So if you do a nested forEach Loop for all three arrays, you can check all the combinations like this:

initialArray.forEach((init) => {
  middleArray.forEach((mid) => {
    lastArray.forEach((last) => {
      console.log(init + ' ' + mid + ' ' + last)
    })
  })
})

Combinations:

Combinations

Adding all this, your code should look like this:

let sentenceArray = [] //initialize an empty array

initialArray.forEach((init) => {
  middleArray.forEach((mid) => {
    lastArray.forEach((last) => {
      sentenceArray.push(init + ' ' + mid + ' ' + last) //populate array with all combinations
    })
  })
})

cy.get(`.${className} .legend_title`)
  .invoke('text')
  .then((myText) => {
    expect(mytext.trim()).to.be.oneOf(sentenceArray)
  })

I like @jjhelguero answer but here's another way using .flatMap() to create the permutations.

const initialArray = ['He', 'She', 'It']
const middleArray = ['is', 'was', 'were']
const lastArray = ['a dog', 'a cat', 'a wizard']

const permutations = initialArray.flatMap(i => 
  middleArray.flatMap(m => 
    lastArray.flatMap(l => `${i} ${m} ${l}`)
  )
)
console.log(permutations)
console.assert(permutations.includes('She was a cat'))

expect(mytext.trim()).to.be.oneOf(permutations);

To build a regex from the array of values, use the RegExp constructor

const initialArray = ['He', 'She', 'It']
const middleArray = ['is', 'was', 'were']
const lastArray = ['a dog', 'a cat', 'a wizard']

const initialChoices = initialArray.join('|')
const middleChoices = middleArray.join('|')
const lastChoices = lastArray.join('|')

let re = new RegExp(`(${initialChoices})\s(${middleChoices})\s(${lastChoices})`, 'i')
 
cy.get("#sentence").invoke("text").should("match", re);

Note with regex you get more flexibility for handling edge cases, for example this can't be handled by .trim()

"She          was     a cat"

In the regex change \s (one space) to [\s]+ (one or more spaces).

Related