diff --git a/libs/ng-mocks/src/lib/mock-builder/promise/init-keep-def.ts b/libs/ng-mocks/src/lib/mock-builder/promise/init-keep-def.ts index e002d5f8e7..f12c3c9b8a 100644 --- a/libs/ng-mocks/src/lib/mock-builder/promise/init-keep-def.ts +++ b/libs/ng-mocks/src/lib/mock-builder/promise/init-keep-def.ts @@ -3,7 +3,7 @@ import { funcExtractDeps } from '../../common/func.extract-deps'; import ngMocksUniverse from '../../common/ng-mocks-universe'; export default (keepDef: Set, configDef: Map): Set => { - const mockDef = new Set(); + const dependencies = new Set(); const builtDeclarations = ngMocksUniverse.builtDeclarations; const builtProviders = ngMocksUniverse.builtProviders; const resolutions = ngMocksUniverse.config.get('ngMocksDepsResolution'); @@ -14,9 +14,9 @@ export default (keepDef: Set, configDef: Map): Set => { const config = configDef.get(def); if (config.shallow) { - funcExtractDeps(def, mockDef); + funcExtractDeps(def, dependencies); } } - return mockDef; + return dependencies; }; diff --git a/libs/ng-mocks/src/lib/mock-builder/promise/init-universe.ts b/libs/ng-mocks/src/lib/mock-builder/promise/init-universe.ts index fac2d1a4ce..7fd414db11 100644 --- a/libs/ng-mocks/src/lib/mock-builder/promise/init-universe.ts +++ b/libs/ng-mocks/src/lib/mock-builder/promise/init-universe.ts @@ -28,13 +28,27 @@ export default ({ // flags to understand how to mock nested declarations. ngMocksUniverse.config.set('ngMocksDepsResolution', new Map()); - const standaloneMocks = initKeepDef(keepDef, configDef); - for (const def of mapValues(standaloneMocks)) { - if (configDef.has(def)) { + const dependencies = initKeepDef(keepDef, configDef); + for (const dependency of mapValues(dependencies)) { + // MockBuilder has instruction about the dependency, skipping it. + if (configDef.has(dependency)) { continue; } - mockDef.add(def); - configDef.set(def, { + + // Checking global configuration for the dependency. + const resolution = ngMocksUniverse.getResolution(dependency); + if (resolution === 'replace') { + replaceDef.add(dependency); + defValue.set(dependency, ngMocksUniverse.getBuildDeclaration(dependency)); + } else if (resolution === 'keep') { + keepDef.add(dependency); + } else if (resolution === 'exclude') { + excludeDef.add(dependency); + } else { + mockDef.add(dependency); + } + + configDef.set(dependency, { dependency: true, }); } diff --git a/tests/issue-3161/exclude.spec.ts b/tests/issue-3161/exclude.spec.ts new file mode 100644 index 0000000000..cb01855383 --- /dev/null +++ b/tests/issue-3161/exclude.spec.ts @@ -0,0 +1,61 @@ +import { + Component, + Input, + NgModule, + Pipe, + PipeTransform, + VERSION, +} from '@angular/core'; + +import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; + +@Pipe({ + name: 'translate', +}) +class TranslatePipe implements PipeTransform { + transform(value: string) { + return `${this.constructor.name}:real:${value}`; + } +} + +@NgModule({ + declarations: [TranslatePipe], + exports: [TranslatePipe], +}) +class TranslateModule {} + +ngMocks.globalExclude(TranslateModule); + +@Component( + { + selector: 'standalone', + standalone: true, + template: `{{ name | translate }}`, + imports: [TranslateModule], + } as never /* TODO: remove after upgrade to a14 */, +) +class StandaloneComponent { + @Input() public readonly name: string = ''; +} + +// @see https://github.com/help-me-mom/ng-mocks/issues/3161 +describe('issue-3161:exclude', () => { + if (Number.parseInt(VERSION.major, 10) < 14) { + it('needs a14', () => { + // pending('Need Angular > 5'); + expect(true).toBeTruthy(); + }); + + return; + } + + beforeEach(() => MockBuilder(StandaloneComponent)); + + it('fails because of excluded module', () => { + expect(() => + MockRender(StandaloneComponent, { + name: 'sandbox', + }), + ).toThrowError(/The pipe 'translate' could not be found/); + }); +}); diff --git a/tests/issue-3161/keep.spec.ts b/tests/issue-3161/keep.spec.ts new file mode 100644 index 0000000000..4996119810 --- /dev/null +++ b/tests/issue-3161/keep.spec.ts @@ -0,0 +1,63 @@ +import { + Component, + Input, + NgModule, + Pipe, + PipeTransform, + VERSION, +} from '@angular/core'; + +import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; + +@Pipe({ + name: 'translate', +}) +class TranslatePipe implements PipeTransform { + transform(value: string) { + return `${this.constructor.name}:real:${value}`; + } +} + +@NgModule({ + declarations: [TranslatePipe], + exports: [TranslatePipe], +}) +class TranslateModule {} + +ngMocks.globalKeep(TranslateModule); + +@Component( + { + selector: 'standalone', + standalone: true, + template: `{{ name | translate }}`, + imports: [TranslateModule], + } as never /* TODO: remove after upgrade to a14 */, +) +class StandaloneComponent { + @Input() public readonly name: string = ''; +} + +// @see https://github.com/help-me-mom/ng-mocks/issues/3161 +describe('issue-3161:keep', () => { + if (Number.parseInt(VERSION.major, 10) < 14) { + it('needs a14', () => { + // pending('Need Angular > 5'); + expect(true).toBeTruthy(); + }); + + return; + } + + beforeEach(() => MockBuilder(StandaloneComponent)); + + it('uses the original pipe', () => { + const fixture = MockRender(StandaloneComponent, { + name: 'sandbox', + }); + + expect(ngMocks.formatText(fixture)).toEqual( + 'TranslatePipe:real:sandbox', + ); + }); +}); diff --git a/tests/issue-3161/test.spec.ts b/tests/issue-3161/test.spec.ts new file mode 100644 index 0000000000..c7b5e043a7 --- /dev/null +++ b/tests/issue-3161/test.spec.ts @@ -0,0 +1,78 @@ +import { + Component, + Input, + NgModule, + Pipe, + PipeTransform, + VERSION, +} from '@angular/core'; + +import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; + +@Pipe({ + name: 'translate', +}) +class TranslatePipe implements PipeTransform { + transform(value: string) { + return `${this.constructor.name}:real:${value}`; + } +} + +@NgModule({ + declarations: [TranslatePipe], + exports: [TranslatePipe], +}) +class TranslateModule {} + +@Pipe({ + name: 'translate', +}) +class MockTranslatePipe implements PipeTransform { + transform(value: string) { + return `${this.constructor.name}:mock:${value}`; + } +} + +@NgModule({ + declarations: [MockTranslatePipe], + exports: [MockTranslatePipe], +}) +class MockTranslateModule {} + +ngMocks.globalReplace(TranslateModule, MockTranslateModule); + +@Component( + { + selector: 'standalone', + standalone: true, + template: `{{ name | translate }}`, + imports: [TranslateModule], + } as never /* TODO: remove after upgrade to a14 */, +) +class StandaloneComponent { + @Input() public readonly name: string = ''; +} + +// @see https://github.com/help-me-mom/ng-mocks/issues/3161 +describe('issue-3161', () => { + if (Number.parseInt(VERSION.major, 10) < 14) { + it('needs a14', () => { + // pending('Need Angular > 5'); + expect(true).toBeTruthy(); + }); + + return; + } + + beforeEach(() => MockBuilder(StandaloneComponent)); + + it('uses replaced pipe', () => { + const fixture = MockRender(StandaloneComponent, { + name: 'sandbox', + }); + + expect(ngMocks.formatText(fixture)).toEqual( + 'MockTranslatePipe:mock:sandbox', + ); + }); +});