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

ngMocks.findInstance returning false instance #298

Closed
parloti opened this issue Feb 12, 2021 · 15 comments · Fixed by #300
Closed

ngMocks.findInstance returning false instance #298

parloti opened this issue Feb 12, 2021 · 15 comments · Fixed by #300
Assignees

Comments

@parloti
Copy link

parloti commented Feb 12, 2021

A situation like this:

<div class="p1"><span myDirective value="d1"></span></div>
<div class="p2"><span myDirective value="d2"></span></div>
<div class="p3"><span myDirective value="d3"></span></div>

const instance1 = ngMocks.findInstance(fixture.debugElement.query(By.css(".p1")), MyDirective);
const instance2 = ngMocks.findInstance(fixture.debugElement.query(By.css(".p2")), MyDirective);
const instance3 = ngMocks.findInstance(fixture.debugElement.query(By.css(".p3")), MyDirective);

Will give:

instance1.value; // "d1";
instance2.value; // "d2";
instance3.value; // "d1"
instance1 === instance3; // true

And with the function ngMocks.findInstances:

const instances1 = ngMocks.findInstances(fixture.debugElement.query(By.css(".p1")), MyDirective);
const instances2 = ngMocks.findInstances(fixture.debugElement.query(By.css(".p2")), MyDirective);
const instances3 = ngMocks.findInstances(fixture.debugElement.query(By.css(".p3")), MyDirective);

Will return:

instances1 // [instance1]
instances2 // [instance2]
instances3 // [instance1, instance2, instance3]

Flow of first instances:

mock-helper.find-instance.ts#L14:: mockHelperFindInstances
mock-helper.find-instances.ts#L25:: nestedCheck
mock-helper.find-instances.ts#L16:: nestedCheck
mock-helper.find-instances.ts#L14:: funcGetFromNode
func.get-from-node.ts#L31:: funcGetFromNodeInjector
func.get-from-node-injector.ts#L11:: result.push

Flow of the last instance:
mock-helper.find-instance.ts#L14:: mockHelperFindInstances
mock-helper.find-instances.ts#L25:: nestedCheck
mock-helper.find-instances.ts#L14:: funcGetFromNode
func.get-from-node.ts#L33:: funcGetFromNodeIvy
func.get-from-node-ivy.ts#L29:: funcGetFromNodeScan
func.get-from-node-scan.ts#L59:: result.push(node)

The problem is apparently happening here (func.get-from-node-scan.ts#L53:: detectGatherFlag), it seems that because for the first divs the others present in the array will change the value of 'gather' to 'false', preventing the instance of the directive from being found with this method.
But for the last div the value of 'gather' will remain 'true' until the first instance of the directive in the component is reached, which will be returned.

I tried to reproduce the problem here (mock-directive), but for some reason at StackBlitz the problem does not occur.

Version:
angular: 11.2.0
ng-mocks: 11.5.0

@satanTime
Copy link
Member

Hi, thank you for the report.

I'll try to investigate the issue.

@satanTime
Copy link
Member

what you describe, it actually the case when there is no .p3 in the template, I think if you change queries to .p4 you should be able to reproduce the issue.

I'll add a fix for it in the next release.

@satanTime
Copy link
Member

satanTime commented Feb 12, 2021

In your case, I would say, check for a typo of English p3 with something similar, for example, Russian р3 (it is not p3).

@parloti
Copy link
Author

parloti commented Feb 13, 2021

what you describe, it actually the case when there is no .p3 in the template, I think if you change queries to .p4 you should be able to reproduce the issue.

If I change to '.p4' I get TypeError: Cannot read property 'debugElement' of null

The flow of the last div on StackBlitz follows the same as locally, up to this point:
func.get-from-node-ivy.ts#L23-L25:: if (!node || node._debugContext) { return;}

Here I have locally:
(node: DebugElement__POST_R3__)._debugContext: undefined
Therefore the condition is false and the function continues.
At StackBlitz I have:
(node: DebugElement__PRE_R3__)._debugContext: DebugContext_
Which is true so the function returns and the flow continues successfully as the others.

In your case, I would say, check for a typo of English p3 with something similar, for example, Russian р3 (it is not p3).

I understand what you mean, the text here on GitHub may have been contaminated by the translator, but I checked and changed my local code and it is without typo.
The template exists and the directive instance too, just not being returned correctly.

See that ...
const p3Instances = ngMocks.findInstances(fixture.debugElement.query(By.css(".p3")), MyDirective);

... will return all three instances of the directive in the component, not just those present in '.p3'

p3Instances[0].value; // "d1"; OK
p3Instances[1].value; // "d2"; OK
p3Instances[2].value; // "d3"; OK

Then the instance of '.p3' exists.

@satanTime
Copy link
Member

Good, thanks for the info. I'm working on fix and will provide a built in a few hours for testing.

@satanTime
Copy link
Member

On StackBlitz - click enable ivy and it fails, checking further.

@satanTime
Copy link
Member

Hi @parloti, good news. Seems like the fix is here.
Could you verify that it works on your project correctly?

ng-mocks.zip

@satanTime
Copy link
Member

ah, false alarm. Fixing the last part with an array of 3.

@satanTime
Copy link
Member

Here we go: ng-mocks.zip

@satanTime satanTime self-assigned this Feb 13, 2021
@parloti
Copy link
Author

parloti commented Feb 13, 2021

Thanks, it's working correctly.

@satanTime
Copy link
Member

Awesome, tomorrow it will be released.

satanTime added a commit that referenced this issue Feb 13, 2021
satanTime added a commit that referenced this issue Feb 13, 2021
fix(#298): better behavior of search functions in normal and ivy mode
@satanTime
Copy link
Member

v11.6.0 has been released and contains a fix for the issue. Feel free to reopen the issue or to submit a new one if you meet any problems.

@satanTime
Copy link
Member

Hi @parloti,

I hope this finds you well and healthy.

Might you do me a favor?
I'm working on new features from #289, and it affects lookup functionality.
Could you check how the new version of ng-mocks works with your app?

Thank you in advance!

ng-mocks.zip

@parloti
Copy link
Author

parloti commented Feb 22, 2021

Hi @satanTime,

I tested this version and it did not visibly affect my tests, they continue to work correctly.

@satanTime
Copy link
Member

Hi @parloti, thanks for the feedback!

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

Successfully merging a pull request may close this issue.

2 participants