Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(testing): prevent find from throwing error when query has no match #5641

Merged
merged 3 commits into from
Apr 9, 2024
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
5 changes: 5 additions & 0 deletions src/testing/puppeteer/puppeteer-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,11 @@ export async function find(page: pd.E2EPageInternal, rootHandle: puppeteer.Eleme

if (typeof selector === 'string' && selector.includes('>>>')) {
const handle = await page.$(selector);

if (!handle) {
return null;
}

const elm = new E2EElement(page, handle);
await elm.e2eSync();
return elm;
Expand Down
26 changes: 26 additions & 0 deletions test/end-to-end/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export namespace Components {
}
interface ElementCmp {
}
interface EmptyCmp {
}
interface EmptyCmpShadow {
}
interface EnvData {
}
interface EventCmp {
Expand Down Expand Up @@ -187,6 +191,18 @@ declare global {
prototype: HTMLElementCmpElement;
new (): HTMLElementCmpElement;
};
interface HTMLEmptyCmpElement extends Components.EmptyCmp, HTMLStencilElement {
}
var HTMLEmptyCmpElement: {
prototype: HTMLEmptyCmpElement;
new (): HTMLEmptyCmpElement;
};
interface HTMLEmptyCmpShadowElement extends Components.EmptyCmpShadow, HTMLStencilElement {
}
var HTMLEmptyCmpShadowElement: {
prototype: HTMLEmptyCmpShadowElement;
new (): HTMLEmptyCmpShadowElement;
};
interface HTMLEnvDataElement extends Components.EnvData, HTMLStencilElement {
}
var HTMLEnvDataElement: {
Expand Down Expand Up @@ -284,6 +300,8 @@ declare global {
"dom-interaction": HTMLDomInteractionElement;
"dom-visible": HTMLDomVisibleElement;
"element-cmp": HTMLElementCmpElement;
"empty-cmp": HTMLEmptyCmpElement;
"empty-cmp-shadow": HTMLEmptyCmpShadowElement;
"env-data": HTMLEnvDataElement;
"event-cmp": HTMLEventCmpElement;
"import-assets": HTMLImportAssetsElement;
Expand Down Expand Up @@ -328,6 +346,10 @@ declare namespace LocalJSX {
}
interface ElementCmp {
}
interface EmptyCmp {
}
interface EmptyCmpShadow {
}
interface EnvData {
}
interface EventCmp {
Expand Down Expand Up @@ -376,6 +398,8 @@ declare namespace LocalJSX {
"dom-interaction": DomInteraction;
"dom-visible": DomVisible;
"element-cmp": ElementCmp;
"empty-cmp": EmptyCmp;
"empty-cmp-shadow": EmptyCmpShadow;
"env-data": EnvData;
"event-cmp": EventCmp;
"import-assets": ImportAssets;
Expand Down Expand Up @@ -408,6 +432,8 @@ declare module "@stencil/core" {
"dom-interaction": LocalJSX.DomInteraction & JSXBase.HTMLAttributes<HTMLDomInteractionElement>;
"dom-visible": LocalJSX.DomVisible & JSXBase.HTMLAttributes<HTMLDomVisibleElement>;
"element-cmp": LocalJSX.ElementCmp & JSXBase.HTMLAttributes<HTMLElementCmpElement>;
"empty-cmp": LocalJSX.EmptyCmp & JSXBase.HTMLAttributes<HTMLEmptyCmpElement>;
"empty-cmp-shadow": LocalJSX.EmptyCmpShadow & JSXBase.HTMLAttributes<HTMLEmptyCmpShadowElement>;
"env-data": LocalJSX.EnvData & JSXBase.HTMLAttributes<HTMLEnvDataElement>;
"event-cmp": LocalJSX.EventCmp & JSXBase.HTMLAttributes<HTMLEventCmpElement>;
"import-assets": LocalJSX.ImportAssets & JSXBase.HTMLAttributes<HTMLImportAssetsElement>;
Expand Down
11 changes: 11 additions & 0 deletions test/end-to-end/src/non-existent-element/empty-cmp-shadow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Component, h, Host } from '@stencil/core';

@Component({
tag: 'empty-cmp-shadow',
shadow: true,
})
export class EmptyComponentShadow {
render() {
return <Host>I have no children!</Host>;
}
}
12 changes: 12 additions & 0 deletions test/end-to-end/src/non-existent-element/empty-cmp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Component, h, Host } from '@stencil/core';

@Component({
tag: 'empty-cmp',
shadow: false,
scoped: false,
})
export class EmptyComponent {
render() {
return <Host>I have no children!</Host>;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add a similar component (and matching suite of tests) where it doesn't use shadow? I don't think it matters if it's totally non-encapsulated or used scoped - I just want to make sure that in the case there's not an actual shadow root, we handle that case as well.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { newE2EPage } from '@stencil/core/testing';

describe('Querying non-existent element(s)', () => {
describe('Shadow DOM', () => {
it('returns `null` if the element does not exist', async () => {
// create a new puppeteer page
const page = await newE2EPage({
html: `
<empty-cmp-shadow></empty-cmp-shadow>
`,
});

const elm = await page.find('empty-cmp-shadow >>> .non-existent');
expect(elm).toBeNull();
});

it('returns an empty array if no elements match the selector', async () => {
// create a new puppeteer page
const page = await newE2EPage({
html: `
<empty-cmp-shadow></empty-cmp-shadow>
`,
});

const elm = await page.findAll('empty-cmp-shadow >>> .non-existent');
expect(elm).toEqual([]);
});
});

describe('Light DOM', () => {
it('returns `null` if the element does not exist', async () => {
// create a new puppeteer page
const page = await newE2EPage({
html: `
<empty-cmp></empty-cmp>
`,
});

const elm = await page.find('empty-cmp >>> .non-existent');
expect(elm).toBeNull();
});

it('returns an empty array if no elements match the selector', async () => {
// create a new puppeteer page
const page = await newE2EPage({
html: `
<empty-cmp></empty-cmp>
`,
});

const elm = await page.findAll('empty-cmp >>> .non-existent');
expect(elm).toEqual([]);
});
});
});
10 changes: 10 additions & 0 deletions test/end-to-end/src/non-existent-element/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# empty-cmp



<!-- Auto Generated Below -->


----------------------------------------------

*Built with [StencilJS](https://stenciljs.com/)*