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

Bug: Incompatibility of MockComponent with new viewChild signal function #8634

Open
mh-ahs opened this issue Apr 2, 2024 · 20 comments · May be fixed by #8771
Open

Bug: Incompatibility of MockComponent with new viewChild signal function #8634

mh-ahs opened this issue Apr 2, 2024 · 20 comments · May be fixed by #8771
Assignees
Labels
bug Something isn't working

Comments

@mh-ahs
Copy link

mh-ahs commented Apr 2, 2024

Description of the bug

Testing standalone components with nested components that use the new viewChild signal feature is currently not possible if the nested component should be mocked.

I'm not sure if ngMocks can do anything about it or if its an angular-core related problem.

An example of the bug

Link: https://stackblitz.com/edit/github-6eneyd?file=src%2Ftest.spec.ts
I added a "NestedComponent" to the default example and replaced the module-based definitions with a simple standalone definition.

Expected vs actual behavior

Using the Signal implementation leads to
TypeError: Cannot read properties of undefined (reading 'Symbol(SIGNAL)')
Switching the implementation from Signal to Decorator lets test run fine,

@mh-ahs mh-ahs added the bug Something isn't working label Apr 2, 2024
@GipHub123
Copy link

I can confirm this one 👍 Having same problems after the change.

@c-harding
Copy link

Temporary workaround: use MockBuilder#replace

@Component({
  selector: 'app-nested',
  standalone: true,
  template: ``,
})
class NestedComponentStub {
  public readonly anchor = signal(new ElementRef(undefined)).asReadonly();
  public readonly name = input.required<string>();
}

describe('my sandbox', () => {
  beforeEach(() =>
    MockBuilder(TargetComponent).replace(NestedComponent, NestedComponentStub)
  );

@c-harding
Copy link

@satanTime this seems to be a better fix: simply remove the view queries, as they’ll always be null anyway

const generateFinalQueries = (queries: {
[key: string]: Query;
}): [Array<[string, Query & { ngMetadataName?: string }]>, string[]] => {
const final: Array<[string, Query & { ngMetadataName?: string }]> = [];
const scanKeys: string[] = [];
for (const key of Object.keys(queries)) {
const query: Query & { ngMetadataName?: string } = queries[key];
final.push([key, query]);
if (!query.isViewQuery && !isInternalKey(key)) {
scanKeys.push(key);
final.push([`__ngMocksVcr_${key}`, cloneVcrQuery(query)]);
}
}
return [final, scanKeys];
};

  const generateFinalQueries = (queries: { 
    [key: string]: Query; 
  }): [Array<[string, Query & { ngMetadataName?: string }]>, string[]] => { 
    const final: Array<[string, Query & { ngMetadataName?: string }]> = []; 
    const scanKeys: string[] = []; 
   
    for (const key of Object.keys(queries)) { 
      const query: Query & { ngMetadataName?: string } = queries[key]; 
-     final.push([key, query]); 
   
      if (!query.isViewQuery && !isInternalKey(key)) { 
+       final.push([key, query]);
        scanKeys.push(key); 
        final.push([`__ngMocksVcr_${key}`, cloneVcrQuery(query)]); 
      } 
    } 
   
    return [final, scanKeys]; 
  }; 

c-harding added a commit to c-harding/ng-mocks that referenced this issue Apr 16, 2024

Verified

This commit was signed with the committer’s verified signature.
c-harding Charlie Harding
ViewChild will always be null, and so there is no point in mocking it.
viewChild.required throws an error in mocked components without this
change.

Fixes help-me-momGH-8634
@c-harding c-harding linked a pull request Apr 16, 2024 that will close this issue
c-harding added a commit to c-harding/ng-mocks that referenced this issue Apr 16, 2024

Verified

This commit was signed with the committer’s verified signature.
c-harding Charlie Harding
ViewChild will always be null, and so there is no point in mocking it.
viewChild.required throws an error in mocked components without this
change.

Fixes help-me-momGH-8634
@andreandersson
Copy link

This will be fixed by the same fix as #7976, is my guess.

@renanaragao
Copy link

Good evening, any news?

@mishahrokhola
Copy link

Hello, any updates on this issue?

@LukasMachetanz
Copy link

I guess #8895 is a similar problem.

dmitry-stepanenko added a commit to c-harding/ng-mocks that referenced this issue May 28, 2024
dmitry-stepanenko added a commit to c-harding/ng-mocks that referenced this issue May 28, 2024
dmitry-stepanenko added a commit to c-harding/ng-mocks that referenced this issue May 28, 2024
@LukasMachetanz
Copy link

Any news on this issue? This bug really prevents using the new API.

c-harding added a commit to c-harding/ng-mocks that referenced this issue Jun 4, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
@SereetsiKC
Copy link

The fix here is not to mock the component but pass it into your test declarations with you parent component

@satanTime
Copy link
Member

Sorry for the delay. I'll take a look closer next week.

@LukasMachetanz
Copy link

@satanTime, did you already have a chance to look into it?

@pcbowers
Copy link

Another workaround I found until this is fixed:

MockInstance(YourComponent, 'viewChildElement', signal(new ElementRef(document.createElement('div'))));

@LukasMachetanz
Copy link

LukasMachetanz commented Nov 28, 2024

@satanTime, sorry to bother you again, but do you have any updates on this? I guess you have currently limited time to work on a request like this, right? No hard feelings, the effort of this great library is definitely appreciated. :)

@Francesco-Borzi
Copy link

Confirmed. If you try to mock a component that uses a viewChild signal inside, it will give error.

cc @satanTime

@zargham-leanix
Copy link

I can confirm, happening for me as well.

@dankerk
Copy link

dankerk commented Dec 19, 2024

Hey @Francesco-Borzi fancy seeing you here :D

+1 on this issue. Happening on 14.13.1 here.

@Martinspire
Copy link

So @satanTime is this on the list to fix soon as well?

@conner-fallone
Copy link

We are also having this issue.

@DavidACCarvalho
Copy link

I'm having also the same problem

@alixroyere
Copy link

Another workaround I found until this is fixed:

MockInstance(YourComponent, 'viewChildElement', signal(new ElementRef(document.createElement('div'))));

Ok so this workaround works but I had some difficulties to apply it. So here is a more verbose explanation that is working in my case:

describe('my tests', () => {
  // Define a scope to auto-clean mocked instance see https://ng-mocks.sudo.eu/api/MockInstance/#scope
  MockInstance.scope();

  beforeEach(async () => {
       // Put expected TestBed conf WITH the broken MockComponent(MyComponent)
       await TestBed.configureTestingModule [...]
       
       // Override the viewChild element with a viewChild-matching-type mock
       // (can be ElementRef as in the previous answer or Component, etc depending on your code)
       MockInstance(MyComponent, 'myViewChild', signal({} as MyViewChildComponent));
  });

  it('my test', () => {
      // test
  });
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.