Stencil version:
@stencil/[email protected]
I'm submitting a:
[x] bug report
[ ] feature request
[ ] support request => Please do not submit support requests here, use one of these channels: https://stencil-worldwide.herokuapp.com/ or https://forum.ionicframework.com/
Current behavior:
When running unit tests, i sporadically get the following error. It is not bound to a specific test case and occurs with a varying frequency:
TypeError: Cannot read property '$hostElement$' of undefined
at getElement (/Users/guidoknoll/Development/widget/node_modules/@stencil/core/dist/runtime/index.js:2242:88)
at CustomSelect.get el [as el] (/Users/guidoknoll/Development/widget/src/components/filter/custom-select/custom-select/custom-select.tsx:3799:12)
at Timeout.setTimeout (/Users/guidoknoll/Development/widget/src/components/filter/custom-select/custom-select/custom-select.tsx:3070:12)
at listOnTimeout (timers.js:327:15)
at processTimers (timers.js:271:5)
/Users/guidoknoll/Development/widget/node_modules/@stencil/core/dist/runtime/index.js:2242
const getElement = (ref) => buildConditionals.BUILD.lazyLoad ? platform.getHostRef(ref).$hostElement$ : ref;
Expected behavior:
Error is not thrown.
Steps to reproduce:
Can't really tell why the error occurs. If you need some parts of my code i can send it to you but putting it here public is not possible.
Related code:
// insert any relevant code here
Other information:
any update about this? I've the same error
Thank you for opening the issue. To help us debug this further, would you be able to provide a way to replicate this? Thanks
I hope i'll find some time to create a minimal example for reproduction the next days. As far as i can see this error happens in combination with the use of rxjs subjects/observables.
Here is another error log:
TypeError: Cannot read property '$hostElement$' of undefined
at setValue (/Users/guidoknoll/Development/widget/node_modules/@stencil/core/dist/runtime/index.js:1351:60)
at CustomOption.set [as selected] (/Users/guidoknoll/Development/widget/node_modules/@stencil/core/dist/runtime/index.js:1430:25)
at SafeSubscriber._next (/Users/guidoknoll/Development/widget/src/components/filter/custom-select/custom-option/custom-option.tsx:25:20)
at SafeSubscriber.Object.<anonymous>.SafeSubscriber.__tryOrUnsub (/Users/guidoknoll/Development/widget/node_modules/rxjs/src/internal/Subscriber.ts:265:10)
at SafeSubscriber.Object.<anonymous>.SafeSubscriber.next (/Users/guidoknoll/Development/widget/node_modules/rxjs/src/internal/Subscriber.ts:207:14)
at Subscriber.Object.<anonymous>.Subscriber._next (/Users/guidoknoll/Development/widget/node_modules/rxjs/src/internal/Subscriber.ts:139:22)
at Subscriber.Object.<anonymous>.Subscriber.next (/Users/guidoknoll/Development/widget/node_modules/rxjs/src/internal/Subscriber.ts:99:12)
at Subject.Object.<anonymous>.Subject.next (/Users/guidoknoll/Development/widget/node_modules/rxjs/src/internal/Subject.ts:70:17)
at CustomOption.select (/Users/guidoknoll/Development/widget/src/components/filter/custom-select/custom-option/custom-option.tsx:60:33)
at HostElement.onClick (/Users/guidoknoll/Development/widget/src/components/filter/custom-select/custom-option/custom-option.tsx:79:33)
I get the same Error testing a component using popper.js
TypeError: Cannot read property '$hostElement$' of undefined
at setValue (/Code/ui-components/node_modules/@stencil/core/dist/runtime/index.js:1368:60)
at MyPopover.set [as placedAt] (/Code/ui-components/node_modules/@stencil/core/dist/runtime/index.js:1447:25)
at Object.onCreate (/Code/ui-components/src/components/my-popover/my-popover.tsx:835:21)
at Popper.call (/Code/ui-components/node_modules/popper.js/src/methods/update.js:71:18)
at Popper.update$$1 (/Code/ui-components/node_modules/popper.js/src/index.js:94:19)
at Timeout._onTimeout (/Code/ui-components/node_modules/popper.js/dist/umd/popper.js:64:9)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)
As I further inspected this error, it seems like it mostly has to to with rxjs. I often use subjects for managing state across multiple components so i hand over a subject to my stencil web component as a parameter. When i hand over a subject in an unit test spec page and call .next() on it, i get the Cannot read property '$hostElement$' of undefined error.
This is such an unit test for example:
it('should change shown searchterm', async () => {
const subject = new ReplaySubject<string>();
const page = await newSpecPage({
components: [SearchtermInput],
template: () => (
<searchterm-input searchTermChange={subject} />
)
});
await page.waitForChanges();
subject.next('test');
await page.waitForChanges();
expect((page.root.querySelector('.search-input') as HTMLInputElement).value).toBe('test');
});
Error output:
/Users/guidoknoll/Development/widget/node_modules/rxjs/internal/util/hostReportError.js:4
setTimeout(function () { throw err; }, 0);
^
TypeError: Cannot read property '$hostElement$' of undefined
at setValue (/Users/guidoknoll/Development/widget/node_modules/@stencil/core/dist/runtime/index.js:1368:60)
at SearchtermInput.set [as searchTerm] (/Users/guidoknoll/Development/widget/node_modules/@stencil/core/dist/runtime/index.js:1447:25)
at SafeSubscriber._next (/Users/guidoknoll/Development/widget/src/components/searchterm-input/searchterm-input.tsx:23:22)
at SafeSubscriber.Object.<anonymous>.SafeSubscriber.__tryOrUnsub (/Users/guidoknoll/Development/widget/node_modules/rxjs/src/internal/Subscriber.ts:265:10)
at SafeSubscriber.Object.<anonymous>.SafeSubscriber.next (/Users/guidoknoll/Development/widget/node_modules/rxjs/src/internal/Subscriber.ts:207:14)
at Subscriber.Object.<anonymous>.Subscriber._next (/Users/guidoknoll/Development/widget/node_modules/rxjs/src/internal/Subscriber.ts:139:22)
at Subscriber.Object.<anonymous>.Subscriber.next (/Users/guidoknoll/Development/widget/node_modules/rxjs/src/internal/Subscriber.ts:99:12)
at ReplaySubject.Object.<anonymous>.Subject.next (/Users/guidoknoll/Development/widget/node_modules/rxjs/src/internal/Subject.ts:70:17)
at ReplaySubject.Object.<anonymous>.ReplaySubject.nextInfiniteTimeWindow (/Users/guidoknoll/Development/widget/node_modules/rxjs/src/internal/ReplaySubject.ts:46:15)
at Object.<anonymous> (/Users/guidoknoll/Development/widget/src/components/searchterm-input/searchterm-input.spec.tsx:41:13)
Sadly i can't think of a solution for this, can anyone help?
As I see you are calling setTimeout function in your code,
I am assuming, your have called setTimeout function in your next() method,
try with the following changes
it('should change shown searchterm', async () => {
const subject = new ReplaySubject<string>();
const page = await newSpecPage({
components: [SearchtermInput],
template: () => (
<searchterm-input searchTermChange={subject} />
)
});
jest.clearAllTimers();
await page.waitForChanges();
subject.next('test');
jest.advanceTimersByTime(200);
await page.waitForChanges();
expect((page.root.querySelector('.search-input') as HTMLInputElement).value).toBe('test');
});
When writing test cases to cover setTimeout/ setInterval functions, do the below things,
In your test case add jest.clearAllTimers(); before subject.next('test'); and after that add jest.advanceTimersByTime(200);
and at the top of you spec.ts file add below line before describe block
jest.useFakeTimers();
Worked like a charm !!
Thank you @rahul-rautwar, this worked for me too. I figured out that using
testing: {
timers: 'fake'
}
in the stencil.config resolves these errors, too.
Most helpful comment
As I see you are calling setTimeout function in your code,
I am assuming, your have called setTimeout function in your next() method,
try with the following changes
it('should change shown searchterm', async () => { const subject = new ReplaySubject<string>(); const page = await newSpecPage({ components: [SearchtermInput], template: () => ( <searchterm-input searchTermChange={subject} /> ) }); jest.clearAllTimers(); await page.waitForChanges(); subject.next('test'); jest.advanceTimersByTime(200); await page.waitForChanges(); expect((page.root.querySelector('.search-input') as HTMLInputElement).value).toBe('test'); });When writing test cases to cover setTimeout/ setInterval functions, do the below things,
In your test case add
jest.clearAllTimers();beforesubject.next('test');and after that addjest.advanceTimersByTime(200);and at the top of you spec.ts file add below line before describe block
jest.useFakeTimers();