Skip to content

Commit

Permalink
fix: flex behavior for a mock pipe
Browse files Browse the repository at this point in the history
  • Loading branch information
satanTime committed Nov 14, 2020
1 parent 939e322 commit 9769061
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 6 deletions.
14 changes: 9 additions & 5 deletions lib/mock-builder/mock-builder-promise.ts
@@ -1,5 +1,6 @@
import { InjectionToken, NgModule, Provider } from '@angular/core';
import { MetadataOverride, TestBed } from '@angular/core/testing';
import { MockService, ngMocks } from 'ng-mocks';

import { extractDependency, flatten, mapEntries, mapValues } from '../common/core.helpers';
import { directiveResolver, jitReflector } from '../common/core.reflect';
Expand Down Expand Up @@ -102,17 +103,22 @@ export class MockBuilderPromise implements PromiseLike<IMockBuilderResult>, IMoc
const instance = this.defValue.get(def);
ngMocksUniverse.builtDeclarations.set(
def,
instance && typeof instance === 'object' && typeof instance.transform === 'function'
typeof instance === 'function'
? MockPipe(def, instance)
: instance && typeof instance === 'object' && typeof instance.transform === 'function'
? MockPipe(def, instance.transform)
: MockPipe(def)
);
}

if (isNgDef(def, 'i') && this.defValue.has(def)) {
const instance = this.defValue.get(def);
const isFunc = isNgDef(def, 'p') && typeof instance === 'function';
ngMocksUniverse.builtProviders.set(
def,
mockServiceHelper.useFactory(def, () => instance)
mockServiceHelper.useFactory(def, () =>
isFunc ? ngMocks.stub(MockService(def), { transform: instance }) : instance
)
);
} else if (isNgDef(def, 'i')) {
ngMocksUniverse.builtProviders.set(def, MockProvider(def));
Expand Down Expand Up @@ -427,9 +433,7 @@ export class MockBuilderPromise implements PromiseLike<IMockBuilderResult>, IMoc
let mock: any = def === a1 ? defaultMock : a1;
let config: any = a2 ? a2 : a1 !== defaultMock ? a1 : undefined;
if (isNgDef(def, 'p') && typeof a1 === 'function') {
mock = {
transform: a1,
};
mock = a1;
config = a2;
} else if (isNgDef(def, 'i') || !isNgDef(def)) {
config = a2;
Expand Down
5 changes: 4 additions & 1 deletion lib/mock-pipe/mock-pipe.ts
Expand Up @@ -62,7 +62,10 @@ export function MockPipe<TPipe extends PipeTransform>(
@Pipe(options)
@MockOf(pipe)
class PipeMock extends Mock implements PipeTransform {
transform = transform;
// tslint:disable-next-line:prefer-function-over-method
public transform(value: any, ...args: any[]): any {
return transform(value, ...args);
}
}

if (ngMocksUniverse.flags.has('cachePipe')) {
Expand Down
6 changes: 6 additions & 0 deletions lib/mock-service/helper.resolve-provider.ts
Expand Up @@ -19,13 +19,19 @@ export default (def: any, resolutions: Map<any, any>, changed?: (flag: boolean)
let mockDef: typeof def;
if (resolutions.has(provider)) {
mockDef = resolutions.get(provider);
const existingMock = ngMocksUniverse.builtProviders.get(provider);
if (existingMock) {
mockDef = existingMock;
}

// A case when a provider is actually a component, directive, pipe.
if (typeof mockDef === 'function') {
mockDef = {
provide: provider,
useClass: mockDef,
};
}

return multi && typeof mockDef === 'object' ? { ...mockDef, multi } : mockDef;
}

Expand Down
176 changes: 176 additions & 0 deletions tests/pipe-as-service/test.spec.ts
@@ -0,0 +1,176 @@
import { Component, Injectable, NgModule, Pipe, PipeTransform } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { MockBuilder, MockInstance, MockRender, MockReset, ngMocks } from 'ng-mocks';

@Pipe({
name: 'target',
})
@Injectable()
class TargetPipe implements PipeTransform {
public readonly name: string = 'target';

public echo(): string {
return this.name;
}

public transform(...args: any[]): string {
return this.name ? JSON.stringify(args) : '';
}
}

@Component({
selector: 'target',
template: `
'pipe:{{ '123' | target }}' 's:transform:{{ service.transform('123') }}' 's:name:{{ service.name }}' 's:echo:{{
service.echo()
}}'
`,
})
class TargetComponent {
public readonly service: TargetPipe;

constructor(service: TargetPipe) {
this.service = service;
}
}

@NgModule({
declarations: [TargetPipe, TargetComponent],
exports: [TargetComponent],
providers: [TargetPipe],
})
class TargetModule {}

describe('pipe-as-service', () => {
describe('default', () => {
beforeEach(() => TestBed.configureTestingModule({ imports: [TargetModule] }).compileComponents());

it('renders correctly', () => {
const fixture = MockRender(TargetComponent);

expect(fixture.nativeElement.innerHTML).toContain(`'pipe:["123"]'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:transform:["123"]'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:name:target'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:echo:target'`);
});
});

describe('guts', () => {
beforeEach(() => TestBed.configureTestingModule(ngMocks.guts(TargetComponent, TargetModule)));

it('renders correctly', () => {
const fixture = MockRender(TargetComponent);

expect(fixture.nativeElement.innerHTML).toContain(`'pipe:'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:transform:'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:name:'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:echo:'`);
});
});

describe('guts:mock-instance', () => {
beforeEach(() => TestBed.configureTestingModule(ngMocks.guts(TargetComponent, TargetModule)));

beforeAll(() =>
MockInstance(TargetPipe, instance =>
ngMocks.stub(instance, {
echo: () => 'echo',
name: 'mock',
transform: () => 'transform',
})
)
);
afterAll(MockReset);

it('renders correctly', () => {
const fixture = MockRender(TargetComponent);

expect(fixture.nativeElement.innerHTML).toContain(`'pipe:transform'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:transform:transform'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:name:mock'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:echo:echo'`);
});
});

describe('mock-builder', () => {
beforeEach(() => MockBuilder(TargetComponent, TargetModule));

it('renders correctly', () => {
const fixture = MockRender(TargetComponent);

expect(fixture.nativeElement.innerHTML).toContain(`'pipe:'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:transform:'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:name:'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:echo:'`);
});
});

describe('mock-builder:mock-instance', () => {
beforeEach(() => MockBuilder(TargetComponent, TargetModule));

beforeAll(() =>
MockInstance(TargetPipe, instance =>
ngMocks.stub(instance, {
echo: () => 'echo',
name: 'mock',
transform: () => 'transform',
})
)
);
afterAll(MockReset);

it('renders correctly', () => {
const fixture = MockRender(TargetComponent);

expect(fixture.nativeElement.innerHTML).toContain(`'pipe:transform'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:transform:transform'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:name:mock'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:echo:echo'`);
});
});

describe('mock-builder:pipe-function', () => {
beforeEach(() => MockBuilder(TargetComponent, TargetModule).mock(TargetPipe, () => 'transform'));

it('renders correctly', () => {
const fixture = MockRender(TargetComponent);

expect(fixture.nativeElement.innerHTML).toContain(`'pipe:transform'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:transform:transform'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:name:'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:echo:'`);
});
});

describe('mock-builder:pipe-mock-cut', () => {
beforeEach(() =>
MockBuilder(TargetComponent, TargetModule).mock(TargetPipe, {
name: 'test',
transform: () => 'transform',
})
);

it('fails because of the missed function', () => {
expect(() => MockRender(TargetComponent)).toThrowError(/.echo is not a function/);
});
});

describe('mock-builder:pipe-mock', () => {
beforeEach(() =>
MockBuilder(TargetComponent, TargetModule).mock(TargetPipe, {
echo: () => 'echo',
name: 'test',
transform: () => 'transform',
})
);

it('renders correctly', () => {
const fixture = MockRender(TargetComponent);

expect(fixture.nativeElement.innerHTML).toContain(`'pipe:transform'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:transform:transform'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:name:test'`);
expect(fixture.nativeElement.innerHTML).toContain(`'s:echo:echo'`);
});
});
});

0 comments on commit 9769061

Please sign in to comment.