Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ it('can be changed by set value', () => {
## Development

Each exported function is directly tested on Cypress.
Call `npm run develop` to start a simple server and open cypress.
Call `npm run start` to start a simple server and open cypress.
You can see the served host on `http://localhost:3999` with:

- [html/index.html](/html/index.html) is the file with the supported components.
Expand Down
1 change: 1 addition & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { defineConfig } from 'cypress';
export default defineConfig({
includeShadowDom: true,
projectId: '1tfaog',
allowCypressEnv: false,
e2e: {
// We've imported your old cypress plugins here.
// You may want to clean this up later by importing these.
Expand Down
74 changes: 67 additions & 7 deletions cypress/e2e/get-from-supported-selector.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,99 @@ describe('Get From Supported Selector', () => {
it('css selector', () => {
getFromSupportedSelector('.testing-class').should(
'have.text',
'Label With Class'
'Label With Class',
);
});

it('Chainable Object from class', () => {
getFromSupportedSelector(cy.get('.testing-class')).should(
'have.text',
'Label With Class'
'Label With Class',
);
});

it('Chainable Object from test-id', () => {
getFromSupportedSelector(cy.findByTestId('testing-test-id')).should(
'have.text',
'Label With Test Id'
'Label With Test Id',
);
});

it('JQuery Object', () => {
cy.get('.testing-class').then(($jQueryObject) => {
getFromSupportedSelector($jQueryObject).should(
'have.text',
'Label With Class'
'Label With Class',
);
});
});

describe('returns only visible element when selector matches both hidden and visible pages', () => {
beforeEach(() => {
cy.document().then((doc) => {
doc.body.insertAdjacentHTML(
'beforeend',
`
<div class="ion-page ion-page-hidden">
<ion-label class="testing-class-conflict">Hidden Label</ion-label>
</div>
<div class="ion-page">
<ion-label class="testing-class-conflict">Visible Label</ion-label>
</div>
`,
);
});
});

it('css selector', () => {
getFromSupportedSelector('.testing-class-conflict')
.should('have.length', 1)
.should('have.text', 'Visible Label');
});

it('Chainable Object', () => {
getFromSupportedSelector(cy.get('.testing-class-conflict'))
.should('have.length', 1)
.should('have.text', 'Visible Label');
});

it('JQuery Object', () => {
cy.get('.testing-class-conflict').then(($jQueryObject) => {
getFromSupportedSelector($jQueryObject)
.should('have.length', 1)
.should('have.text', 'Visible Label');
});
});
});

describe('ignores elements inside ion-page-hidden', () => {
it('css selector', () => {
getFromSupportedSelector('.testing-class-hidden').should(
'have.length',
0,
);
});

it('Chainable Object', () => {
getFromSupportedSelector(cy.get('.testing-class-hidden')).should(
'have.length',
0,
);
});

it('JQuery Object', () => {
cy.get('.testing-class-hidden').then(($jQueryObject) => {
getFromSupportedSelector($jQueryObject).should('have.length', 0);
});
});
});

Comment thread
distante marked this conversation as resolved.
describe('waiting for components hydration', () => {
it('css selector', () => {
getFromSupportedSelector<IonRange>('.ion-range-to-test-hydration')
.then(($ionRange) => {
return $ionRange[0].shadowRoot?.querySelector(
'.range-knob-handle-a, .range-knob-handle.range-knob-a'
'.range-knob-handle-a, .range-knob-handle.range-knob-a',
);
})
.should('exist');
Expand All @@ -51,7 +111,7 @@ describe('Get From Supported Selector', () => {
getFromSupportedSelector<IonRange>(cy.get('.ion-range-to-test-hydration'))
.then(($ionRange) => {
return $ionRange[0].shadowRoot?.querySelector(
'.range-knob-handle-a, .range-knob-handle.range-knob-a'
'.range-knob-handle-a, .range-knob-handle.range-knob-a',
);
})
.should('exist');
Expand All @@ -63,7 +123,7 @@ describe('Get From Supported Selector', () => {
getFromSupportedSelector($jQueryObject)
.then(($ionRange) => {
return $ionRange[0].shadowRoot?.querySelector(
'.range-knob-handle-a, .range-knob-handle.range-knob-a'
'.range-knob-handle-a, .range-knob-handle.range-knob-a',
);
})
.should('exist');
Expand Down
9 changes: 8 additions & 1 deletion html/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
Expand All @@ -22,6 +22,13 @@
<body>
<main>
<h2>Get from supported selectors</h2>
<div class="ion-page-hidden">
<ion-item>
<ion-label class="testing-class-hidden"
>Label Inside Hidden Page</ion-label
>
</ion-item>
</div>
<ion-item class="for-get-from-supported-selector">
<ion-label data-testId="testing-test-id">Label With Test Id</ion-label>
<ion-label class="testing-class">Label With Class</ion-label>
Expand Down
30 changes: 15 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
"scripts": {
"prepare": "husky && ts-patch install -s",
"serve": "tsx ./scripts/serve.mjs",
"develop": "start-server-and-test serve http://localhost:3999 test-open",
"start": "start-server-and-test serve http://localhost:3999 test-open",
"test-open": "cypress open",
"test": "cypress run",
"test-ci": "cypress run --config video=false",
"full-test": "start-server-and-test serve http://localhost:3999 test-ci",
"ci": "tsx --experimental-json-modules ./scripts/test.mjs",
"build": "tsc --project tsconfig.json",
"make-docs": "typedoc",
"make-docs": "typedoc --cname cypress-ionic.saninnsalas.com",
"tsc:check": "tsc --noEmit",
"prettier:check": "prettier --config ./.prettierrc ./src --check",
"release": "release-it --verbose",
Expand Down Expand Up @@ -87,7 +87,7 @@
"release-it": {
"hooks": {
"before:init": "npm run build && npm run ci",
"after:bump": "npx typedoc && git add ./docs && git commit -m 'docs: pre-release docs'",
"after:bump": "npm run make-docs && git add ./docs && git commit -m 'docs: pre-release docs'",
"after:release": "echo Successfully released ${name} v${version} to https://${repo.host}/${repo.repository}/releases/tag/v${version}"
},
"git": {
Expand Down
25 changes: 19 additions & 6 deletions src/helpers/get-from-supported-selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,33 @@ export function getFromSupportedSelector<T extends Element>(
selector: SupportedSelectors<T>,
): CypressIonicReturn<T> {
if (typeof selector === 'string') {
return cy.get<T>(`${selector}.hydrated`);
return filterOutHiddenPage(cy.get<T>(`${selector}.hydrated`));
Comment thread
distante marked this conversation as resolved.
}

if (isJQuery<T>(selector)) {
// selector.attr('cypress-ionic-test-id', )
return cy.wrap(selector).should('have.class', 'hydrated');
return filterOutHiddenPage(
cy
.wrap(selector)
.should('have.class', 'hydrated') as CypressIonicReturn<T>,
);
}

return (selector as unknown as CypressIonicReturn<T>).should(
'have.class',
'hydrated',
return filterOutHiddenPage(
(selector as unknown as CypressIonicReturn<T>).should(
'have.class',
'hydrated',
),
Comment on lines 12 to +24
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Chainable/JQuery branches, the .should('have.class', 'hydrated') assertion runs before filtering out .ion-page-hidden matches. This means hidden-page elements can still cause the command to fail (e.g., if a hidden match is not hydrated yet), even though the intent is to ignore them. Consider filtering out hidden-page elements first, and then only asserting hydration on the remaining elements (and skipping the hydration assertion when the filtered set is empty so callers can assert have.length, 0).

Copilot uses AI. Check for mistakes.
);
}

function filterOutHiddenPage<T extends Element>(
subject: CypressIonicReturn<T>,
): CypressIonicReturn<T> {
return subject.not(
'.ion-page-hidden, .ion-page-hidden *',
) as unknown as CypressIonicReturn<T>;
}

function isJQuery<T extends Element>(
selector: SupportedSelectors<T>,
): selector is JQuery<T> {
Expand Down
Loading