From 637f52b388278b29f2148a4011824b55fd4dbe3d Mon Sep 17 00:00:00 2001
From: Saninn Salas Diaz <5490201+distante@users.noreply.github.com>
Date: Sat, 18 Apr 2026 11:54:56 +0200
Subject: [PATCH 1/2] fix: filter ion-page-hidden elements before asserting
hydration in JQuery/Chainable branches
In the JQuery and Chainable branches, the hydration assertion ran on the full
element set before hidden-page elements were filtered out. If all elements were
on hidden pages and lacked the .hydrated class, Cypress's .not() command would
retry until timeout rather than returning an empty set.
The fix uses jQuery's native .not() synchronously inside a .then() callback to
filter hidden elements first, then skips the hydration assertion when the
filtered set is empty.
---
.../e2e/get-from-supported-selector.spec.ts | 44 +++++++++++++++++++
src/helpers/get-from-supported-selector.ts | 27 +++++++-----
2 files changed, 60 insertions(+), 11 deletions(-)
diff --git a/cypress/e2e/get-from-supported-selector.spec.ts b/cypress/e2e/get-from-supported-selector.spec.ts
index a3cb02b..9587b93 100644
--- a/cypress/e2e/get-from-supported-selector.spec.ts
+++ b/cypress/e2e/get-from-supported-selector.spec.ts
@@ -96,6 +96,50 @@ describe('Get From Supported Selector', () => {
});
});
+ describe('filters hidden-page elements BEFORE asserting hydration', () => {
+ beforeEach(() => {
+ cy.document().then((doc) => {
+ doc.body.insertAdjacentHTML(
+ 'beforeend',
+ `
+ `,
+ );
+ });
+ });
+
+ it('Chainable - does not fail when a hidden element lacks .hydrated', () => {
+ getFromSupportedSelector(cy.get('.testing-order-bug'))
+ .should('have.length', 1)
+ .should('have.text', 'Visible Hydrated');
+ });
+
+ it('JQuery - does not fail when a hidden element lacks .hydrated', () => {
+ cy.get('.testing-order-bug').then(($els) => {
+ getFromSupportedSelector($els)
+ .should('have.length', 1)
+ .should('have.text', 'Visible Hydrated');
+ });
+ });
+
+ it('Chainable - returns empty set without timing out when all matches are hidden', () => {
+ getFromSupportedSelector(
+ cy.get('.testing-order-bug').filter(':not(.hydrated)'),
+ ).should('have.length', 0);
+ });
+
+ it('JQuery - returns empty set without timing out when all matches are hidden', () => {
+ cy.get('.testing-order-bug')
+ .filter(':not(.hydrated)')
+ .then(($els) => {
+ getFromSupportedSelector($els).should('have.length', 0);
+ });
+ });
+ });
+
describe('waiting for components hydration', () => {
it('css selector', () => {
getFromSupportedSelector('.ion-range-to-test-hydration')
diff --git a/src/helpers/get-from-supported-selector.ts b/src/helpers/get-from-supported-selector.ts
index a31a648..2551a2e 100644
--- a/src/helpers/get-from-supported-selector.ts
+++ b/src/helpers/get-from-supported-selector.ts
@@ -10,19 +10,10 @@ export function getFromSupportedSelector(
}
if (isJQuery(selector)) {
- return filterOutHiddenPage(
- cy
- .wrap(selector)
- .should('have.class', 'hydrated') as CypressIonicReturn,
- );
+ return filterThenAssertHydrated(cy.wrap(selector) as CypressIonicReturn);
}
- return filterOutHiddenPage(
- (selector as unknown as CypressIonicReturn).should(
- 'have.class',
- 'hydrated',
- ),
- );
+ return filterThenAssertHydrated(selector as unknown as CypressIonicReturn);
}
function filterOutHiddenPage(
@@ -33,6 +24,20 @@ function filterOutHiddenPage(
) as unknown as CypressIonicReturn;
}
+function filterThenAssertHydrated(
+ subject: CypressIonicReturn,
+): CypressIonicReturn {
+ return subject.then((elements) => {
+ const $visible = elements.not(
+ '.ion-page-hidden, .ion-page-hidden *',
+ ) as unknown as JQuery;
+ if ($visible.length === 0) {
+ return cy.wrap($visible);
+ }
+ return cy.wrap($visible).should('have.class', 'hydrated');
+ }) as unknown as CypressIonicReturn;
+}
+
function isJQuery(
selector: SupportedSelectors,
): selector is JQuery {
From 9cbf2a7d65260f256fae4f4c3932c59df92343a3 Mon Sep 17 00:00:00 2001
From: Saninn Salas Diaz <5490201+distante@users.noreply.github.com>
Date: Sat, 18 Apr 2026 12:12:58 +0200
Subject: [PATCH 2/2] fix: filter hidden ion-page elements before hydration
assertion
Route the string-selector path through the same filter-then-assert flow as Chainable/JQuery inputs,
so hidden page matches are removed before checking hydrated class.
Prevents timeout retries when all matches are inside ion-page-hidden and never hydrated,
returning an empty set instead.
Add a Cypress regression test for the css-selector hidden-only non-hydrated scenario.
---
cypress/e2e/get-from-supported-selector.spec.ts | 16 ++++++++++++++++
src/helpers/get-from-supported-selector.ts | 17 +++++------------
2 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/cypress/e2e/get-from-supported-selector.spec.ts b/cypress/e2e/get-from-supported-selector.spec.ts
index 9587b93..f94521f 100644
--- a/cypress/e2e/get-from-supported-selector.spec.ts
+++ b/cypress/e2e/get-from-supported-selector.spec.ts
@@ -138,6 +138,22 @@ describe('Get From Supported Selector', () => {
getFromSupportedSelector($els).should('have.length', 0);
});
});
+
+ it('css selector - returns empty set without timing out when all matches are hidden and not hydrated', () => {
+ cy.document().then((doc) => {
+ doc.body.insertAdjacentHTML(
+ 'beforeend',
+ ``,
+ );
+ });
+
+ getFromSupportedSelector('.testing-order-hidden-only').should(
+ 'have.length',
+ 0,
+ );
+ });
});
describe('waiting for components hydration', () => {
diff --git a/src/helpers/get-from-supported-selector.ts b/src/helpers/get-from-supported-selector.ts
index 2551a2e..0429ead 100644
--- a/src/helpers/get-from-supported-selector.ts
+++ b/src/helpers/get-from-supported-selector.ts
@@ -1,4 +1,7 @@
import { CypressIonicReturn, SupportedSelectors } from '../interfaces';
+
+const HIDDEN_PAGE_SELECTOR = '.ion-page-hidden, .ion-page-hidden *';
+
/**
* @internal
*/
@@ -6,7 +9,7 @@ export function getFromSupportedSelector(
selector: SupportedSelectors,
): CypressIonicReturn {
if (typeof selector === 'string') {
- return filterOutHiddenPage(cy.get(`${selector}.hydrated`));
+ return filterThenAssertHydrated(cy.get(selector));
}
if (isJQuery(selector)) {
@@ -16,21 +19,11 @@ export function getFromSupportedSelector(
return filterThenAssertHydrated(selector as unknown as CypressIonicReturn);
}
-function filterOutHiddenPage(
- subject: CypressIonicReturn,
-): CypressIonicReturn {
- return subject.not(
- '.ion-page-hidden, .ion-page-hidden *',
- ) as unknown as CypressIonicReturn;
-}
-
function filterThenAssertHydrated(
subject: CypressIonicReturn,
): CypressIonicReturn {
return subject.then((elements) => {
- const $visible = elements.not(
- '.ion-page-hidden, .ion-page-hidden *',
- ) as unknown as JQuery;
+ const $visible = elements.not(HIDDEN_PAGE_SELECTOR) as unknown as JQuery;
if ($visible.length === 0) {
return cy.wrap($visible);
}