diff --git a/libs/ng-mocks/src/lib/common/core.helpers.ts b/libs/ng-mocks/src/lib/common/core.helpers.ts index 158c4c0c00..6a0cdbc353 100644 --- a/libs/ng-mocks/src/lib/common/core.helpers.ts +++ b/libs/ng-mocks/src/lib/common/core.helpers.ts @@ -114,27 +114,31 @@ export const extractDependency = (deps: any[], set?: Set): void => { export const extendClassicClass = (base: AnyType): Type => { let child: any; + const index = ngMocksUniverse.index(); + const glb = funcGetGlobal(); + glb.ngMocksParent = base; // First we try to eval es2015 style and if it fails to use es5 transpilation in the catch block. // The next step is to respect constructor parameters as the parent class via jitReflector. - glb.ngMocksParent = base; // istanbul ignore next try { eval(` var glb = typeof window === 'undefined' ? global : window; - class MockMiddleware extends glb.ngMocksParent {} - glb.ngMocksResult = MockMiddleware + class MockMiddleware${index} extends glb.ngMocksParent {}; + glb.ngMocksResult = MockMiddleware${index}; `); child = glb.ngMocksResult; } catch { class MockMiddleware extends glb.ngMocksParent {} child = MockMiddleware; + } finally { + glb.ngMocksResult = undefined; + glb.ngMocksParent = undefined; } - glb.ngMocksParent = undefined; // A16: adding unique property. - coreDefineProperty(child.prototype, `__ngMocks_index_${ngMocksUniverse.index()}`, undefined, false); + coreDefineProperty(child.prototype, `__ngMocks_index_${index}`, undefined, false); return child; }; diff --git a/tests/issue-5465/test.spec.ts b/tests/issue-5465/test.spec.ts new file mode 100644 index 0000000000..b44fed0820 --- /dev/null +++ b/tests/issue-5465/test.spec.ts @@ -0,0 +1,62 @@ +import { NgForOf } from '@angular/common'; +import { Component, NgModule, VERSION } from '@angular/core'; + +import { MockBuilder, MockRender } from 'ng-mocks'; + +// @see https://github.com/help-me-mom/ng-mocks/issues/5465 +// TypeError: Class constructor CommonModule cannot be invoked without 'new' +describe('issue-5465', () => { + if (Number.parseInt(VERSION.major, 10) < 14) { + it('needs a14', () => { + // pending('Need Angular 14+'); + expect(true).toBeTruthy(); + }); + + return; + } + + @Component({ + selector: 'app-ng-for', + template: ` + {{ letter }} + `, + }) + class AppNgForComponent { + test = ['a', 'b']; + + appNgFor5465() {} + } + + @NgModule({ + imports: [ + NgForOf as never /* TODO: remove after upgrade to a14 */, + ], + declarations: [AppNgForComponent], + exports: [AppNgForComponent], + }) + class AppNgForModule {} + + @Component({ + selector: 'app-root', + template: ` `, + }) + class AppRootComponent { + appRoot5465() {} + } + + @NgModule({ + declarations: [AppRootComponent], + imports: [AppNgForModule], + providers: [], + bootstrap: [AppRootComponent], + }) + class AppModule {} + + beforeEach(() => + MockBuilder([AppRootComponent], [AppModule, NgForOf]), + ); + + it('renders AppRootComponent', () => { + expect(() => MockRender(AppRootComponent)).not.toThrow(); + }); +});