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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

not really clear that inputs can ONLY be assigned using props :/ #567

Open
michahell opened this issue Jun 30, 2022 · 2 comments
Open

not really clear that inputs can ONLY be assigned using props :/ #567

michahell opened this issue Jun 30, 2022 · 2 comments

Comments

@michahell
Copy link

michahell commented Jun 30, 2022

Is this a regression?

No

Description

I tried to use Spectator as a drop-in replacement for a component unit-test and after re-writing the TestBed to Spectators tinier boilerplate 馃帄 I could not get past this error:

TypeError: Cannot read properties of undefined (reading 'id')
	    at templateFn (ng:///CompiledComponent.js:147:54)
	    at executeTemplate (node_modules/@angular/core/fesm2015/core.mjs:9632:9)
	    at refreshView (node_modules/@angular/core/fesm2015/core.mjs:9495:13)
	    at refreshComponent (node_modules/@angular/core/fesm2015/core.mjs:10692:13)
	    at refreshChildComponents (node_modules/@angular/core/fesm2015/core.mjs:9291:9)
	    at refreshView (node_modules/@angular/core/fesm2015/core.mjs:9545:13)
	    at renderComponentOrTemplate (node_modules/@angular/core/fesm2015/core.mjs:9612:9)
	    at tickRootContext (node_modules/@angular/core/fesm2015/core.mjs:10866:9)
	    at detectChangesInRootView (node_modules/@angular/core/fesm2015/core.mjs:10891:5)
	    at RootViewRef.detectChanges (node_modules/@angular/core/fesm2015/core.mjs:21505:9)
	TypeError: Cannot read properties of undefined (reading 'detectChanges')
	    at UserContext.apply (path.component.spec.ts:68:13)
	    at _ZoneDelegate.invoke (node_modules/zone.js/dist/zone.js:409:30)
	    at ProxyZoneSpec.onInvoke (node_modules/zone.js/dist/zone-testing.js:303:43)
	    at _ZoneDelegate.invoke (node_modules/zone.js/dist/zone.js:408:56)
	    at Zone.run (node_modules/zone.js/dist/zone.js:169:47)
	    at runInTestZone (node_modules/zone.js/dist/zone-testing.js:583:38)
	    at UserContext.<anonymous> (node_modules/zone.js/dist/zone-testing.js:598:24)
	    at <Jasmine>

that I got because I kept the original @input assignment, in my beforeEach() after spectator = createComponent():

component.task = { ...testTask };

This does not work, you need to use the props property of createComponent() to assign @inputs.
I think this needs to be clarified better in the docs.
The error given is not descriptive: It emanates from compiled component javascript, and not the spec file, so my immediate reaction was to change the only line of code in the component containing the word id:

this.users$ = this.someService.someMethod(this.task.id) // changed to: this.task.thisIDbroken

to see if this is what was causing the error, but it was not.

Please provide a link to a minimal reproduction of the bug

N/A

Please provide the exception or error you saw

TypeError: Cannot read properties of undefined (reading 'id')
	    at templateFn (ng:///CompiledComponent.js:147:54)
	    at executeTemplate (node_modules/@angular/core/fesm2015/core.mjs:9632:9)
	    at refreshView (node_modules/@angular/core/fesm2015/core.mjs:9495:13)
	    at refreshComponent (node_modules/@angular/core/fesm2015/core.mjs:10692:13)
	    at refreshChildComponents (node_modules/@angular/core/fesm2015/core.mjs:9291:9)
	    at refreshView (node_modules/@angular/core/fesm2015/core.mjs:9545:13)
	    at renderComponentOrTemplate (node_modules/@angular/core/fesm2015/core.mjs:9612:9)
	    at tickRootContext (node_modules/@angular/core/fesm2015/core.mjs:10866:9)
	    at detectChangesInRootView (node_modules/@angular/core/fesm2015/core.mjs:10891:5)
	    at RootViewRef.detectChanges (node_modules/@angular/core/fesm2015/core.mjs:21505:9)
	TypeError: Cannot read properties of undefined (reading 'detectChanges')
	    at UserContext.apply (path.component.spec.ts:68:13)
	    at _ZoneDelegate.invoke (node_modules/zone.js/dist/zone.js:409:30)
	    at ProxyZoneSpec.onInvoke (node_modules/zone.js/dist/zone-testing.js:303:43)
	    at _ZoneDelegate.invoke (node_modules/zone.js/dist/zone.js:408:56)
	    at Zone.run (node_modules/zone.js/dist/zone.js:169:47)
	    at runInTestZone (node_modules/zone.js/dist/zone-testing.js:583:38)
	    at UserContext.<anonymous> (node_modules/zone.js/dist/zone-testing.js:598:24)
	    at <Jasmine>

Please provide the environment you discovered this bug in

Angular / Karma / Jasmine locally

Anything else?

fixed by using props:

props: {
        task: { ...testTask },
      },

Do you want to create a pull request?

Yes

@alixroyere
Copy link

You can also assign an input with spectator.setInput('task', myTask) or spectator.component.task = myTask

Your createComponent function is initializing your component, which seems to call component.task.id, maybe in ngOnInit() (not enough code to guess more)

spectator = createComponent(); 
spectator.setInput('task', myTask);

If you do as above, you're initializing the component, and having the issue because component.task is undefined during this step. The task would be set only after that, once it's too late

An other way is to play with the detectChanges property, but it has other impacts

spectator = createComponent({detectChanges: false}); 
spectator.component.task= myTask;
// Do all kind of initialization
spectator.detectChanges();

So, your issue is specific to your usecase. Using props: { task: myTask } is the best choice here, because you need it on init, but there are other ways to set inputs after the test init

@localpcguy
Copy link

In addition to the above, you can also wrap your component with a HostComponent using the createHostFactory, and pass Input props when the component is instantiated also. This is useful if you need to test more complex Input behavior (although I would default to props or setInput first).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants