I recently encountered a frustrating issue while trying to write Cypress tests for promotions in SAP Hybris. The problem involved searching for a specific promotion version, but my test kept clicking the wrong version. For example, I needed to select promotion version 2, but my Cypress script was incorrectly matching promotions that contained the similar input.
The Initial Problem
The structure of the promotions page listed multiple versions of the same promotion in rows, like:
10 ZYN Cans multi-buy + 10 ZYN Cans multi-buy [UK_ZYN_MULTI_BUY_20/INACTIVE/v0]
10 ZYN Cans multi-buy + 10 ZYN Cans multi-buy [UK_ZYN_MULTI_BUY_20/INACTIVE/v1]
10 ZYN Cans multi-buy + 10 ZYN Cans multi-buy [UK_ZYN_MULTI_BUY_20/INACTIVE/v2]
I needed to select version “v2” exactly. However, my initial code was not specific enough, and I sometimes clicked on “v1” or “v0.” Here’s a simplified version of my original code:
cy.get(selector).within(() => {
cy.get('.yw-listview-cell-label.z-label')
.filter((_, el) => el.innerText.trim() === promotionVersion)
.click({ force: true });
});
The issue was that this code didn’t differentiate between “v0,” “v1,” and “v2” because the filter()
method wasn’t isolated to match just the exact version number.
What I Tried
I initially thought the issue might be that my code matched text loosely, so I tried using a stricter filter that should have picked only the exact “v2” promotion. However, I quickly ran into a CypressError: cy.within() can only be called on a single element. Your subject contained 3 elements.
This error occurred because multiple elements were returned, and .within()
could only handle one element at a time. I needed to narrow down the results to a single element before calling .within()
. I tried adding more filters, but nothing seemed to work as expected.
The Final Solution
After some trial and error, I came up with a solution that worked perfectly. I restructured the code to ensure that it first finds the correct promotion (based on promotion code, name, and environment) and then checks for the correct version.
Here’s the code that solved the problem:
// Loop through pages to find the promotion
function checkPage() {
cy.get('body').then($body => {
// Define a more precise selector for the rows containing promotion details
cy.get('tr.yw-coll-browser-hyperlink').each(($row) => {
// Ensure that the row contains all necessary values except for the version first
if (
$row.find('.yw-listview-cell-label.z-label:contains("' + promotionCode + '")').length > 0 &&
$row.find('.yw-listview-cell-label.z-label:contains("' + promotionName + '")').length > 0 &&
$row.find('.yw-listview-cell-label.z-label:contains("' + websiteEnv + '")').length > 0) {
// Check for the correct version specifically, using each() instead of filter()
cy.wrap($row).within(() => {
cy.get('.yw-listview-cell-label.z-label').each(($el) => {
const versionText = $el.text().trim();
const className = $el.attr('class'); // Get the class name of the element
// Ensure the class and the version both match exactly
if (className.includes('z-label') && versionText === promotionVersion) {
cy.wrap($el).click({ force: true }); // Click only if it matches the correct version
}
});
});
}
});
// Handle pagination if necessary
cy.get('button.z-paging-button.z-paging-next[title="Next Page"]').eq(2).then($button => {
if ($button.is(':visible') && !$button.attr('disabled')) {
cy.wrap($button).click({ force: true }).wait(5000);
checkPage(); // Recursively check the next page
} else {
cy.log('Promotion not found or next page button is not clickable');
}
});
});
}
checkPage();
Breaking Down the Solution
- Looping Through Rows: I used
.each()
to iterate through the rows that contain promotion details. For each row, I checked if the promotion code, name, and environment matched the one I was looking for. - Exact Match on Version: Once I found the correct row, I used
.within()
to limit the scope to that specific row. Inside this row, I used.each()
again to check all the labels for the correct version.The key line here is the condition that checks both the class name and the text:javascriptCopy codeif (className.includes('z-label') && versionText === promotionVersion)
This ensures that only the label with the exact version number (e.g., “v2”) is clicked. - Pagination Handling: If the promotion wasn’t found on the current page, I handled pagination by clicking the “Next Page” button and recursively calling
checkPage()
until I either found the promotion or ran out of pages.
Why This Worked
The solution worked because it broke down the problem into smaller, manageable steps. First, I identified the row containing the right promotion, ignoring the version. Then, I zeroed in on the exact version number by iterating through the labels inside the row. By using both .each()
and .within()
, I made sure Cypress was looking at the right element at the right time.
This solution not only fixed the issue but also made my test script more robust, ensuring that it will handle multiple versions of the same promotion without errors.