Skip to content

Commit

Permalink
fix(mock-render): apply overrides to components with no selectors hel…
Browse files Browse the repository at this point in the history
  • Loading branch information
satanTime committed Feb 17, 2022
1 parent ac27ddb commit b032746
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 9 deletions.
5 changes: 4 additions & 1 deletion libs/ng-mocks/src/lib/common/ng-mocks-global-overrides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ const applyOverride = (def: any, override: any) => {

const applyOverrides = (overrides: Map<AnyType<any>, [MetadataOverride<any>, MetadataOverride<any>]>): void => {
for (const [def, [override, original]] of mapEntries(overrides)) {
(TestBed as any).ngMocksOverrides.set(def, original);
(TestBed as any).ngMocksOverrides.set(def, {
...original,
override,
});
applyOverride(def, override);
}
};
Expand Down
30 changes: 22 additions & 8 deletions libs/ng-mocks/src/lib/mock-render/func.reflect-template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,11 @@ import { isNgDef } from '../common/func.is-ng-def';
const registerTemplateMiddleware = (template: AnyType<any>, meta: Directive): void => {
const child = extendClass(template);

let providers = meta.providers || [];
providers = [
...providers,
{
provide: template,
useExisting: child,
},
];
const alias = {
provide: template,
useExisting: child,
};
const providers = [...(meta.providers || []), alias];
meta.providers = providers;

if (isNgDef(template, 'c')) {
Expand All @@ -27,6 +24,23 @@ const registerTemplateMiddleware = (template: AnyType<any>, meta: Directive): vo
TestBed.configureTestingModule({
declarations: [child],
});

// https://github.com/ike18t/ng-mocks/issues/1876
// We need to apply overrides to our cloned declaration.
try {
const ngMocksOverrides: Map<any, any> = (TestBed as any).ngMocksOverrides;
const { override } = ngMocksOverrides.get(template);
const { set } = override;
ngMocksOverrides.set(child, { set: meta });
TestBed.overrideComponent(child, {
set: {
...set,
providers: [...set.providers, alias],
},
});
} catch {
// nothing to do
}
};

export default (template: AnyType<any>): Directive => {
Expand Down
59 changes: 59 additions & 0 deletions tests/issue-1876/test.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import {
Component,
Directive,
Injectable,
Input,
} from '@angular/core';
import { MockBuilder, MockRender, ngMocks } from 'ng-mocks';

@Injectable()
export class HelloService {
public description = 'real service';
}

@Component({
providers: [HelloService],
template: ``,
})
export class HelloComponent {
public serviceDescription = '';

public constructor(private readonly helloService: HelloService) {
this.serviceDescription = this.helloService.description;
}
}

@Directive({
providers: [HelloService],
selector: 'hello',
})
export class HelloDirective {
@Input() public name = '';
public serviceDescription = '';

public constructor(private readonly helloService: HelloService) {
this.serviceDescription = this.helloService.description;
}
}

// Components without selectors should still inherit mocked providers.
// https://github.com/ike18t/ng-mocks/issues/1876
describe('issue-1876', () => {
beforeEach(() =>
MockBuilder([HelloComponent, HelloDirective]).mock(HelloService, {
description: 'fake service',
}),
);

it('uses fake service in components', () => {
MockRender(HelloComponent);
const instance = ngMocks.findInstance(HelloComponent);
expect(instance.serviceDescription).toContain('fake service');
});

it('uses fake service in directives', () => {
MockRender(HelloDirective);
const instance = ngMocks.findInstance(HelloDirective);
expect(instance.serviceDescription).toContain('fake service');
});
});

0 comments on commit b032746

Please sign in to comment.