Skip to content

Commit

Permalink
feat: add exportAs and alias support
Browse files Browse the repository at this point in the history
also some minor cleanup
  • Loading branch information
ike18t committed Jan 26, 2018
1 parent c0b502d commit 14a1474
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 40 deletions.
21 changes: 12 additions & 9 deletions lib/mock_component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
import { MockComponent } from './mock_component';
import { EmptyComponent } from './test_components/empty_component.component';
import { SimpleComponent } from './test_components/simple_component.component';
import { MockComponent } from './mock_component';

@Component({
selector: 'example-component-container',
template: `
<simple-component [someInput]="\'hi\'" (someOutput1)="someOutputHasEmitted = true"></simple-component>
<simple-component [someInput]="\'hi again\'"></simple-component>
<simple-component [someInput]="\'hi\'"
[someOtherInput]="\'bye\'"
(someOutput1)="someOutputHasEmitted = true">
</simple-component>
<simple-component [someInput]="\'hi again\'" #f='seeimple'></simple-component>
<empty-component></empty-component>
<empty-component id="ng-content-component">doh</empty-component>
<empty-component id="ngmodel-component" [(ngModel)]="someOutputHasEmitted"></empty-component>
Expand Down Expand Up @@ -46,14 +49,13 @@ describe('MockComponent', () => {
FormsModule
]
})
.compileComponents();
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(ExampleComponentContainer);
component = fixture.componentInstance;
});
}));

beforeEach(() => {
fixture = TestBed.createComponent(ExampleComponentContainer);
component = fixture.componentInstance;
});

it('should have use the original component\'s selector', () => {
fixture.detectChanges();
const mockedComponent = fixture.debugElement.query(By.css('simple-component'));
Expand All @@ -66,6 +68,7 @@ describe('MockComponent', () => {
.query(By.directive(mockedSimpleComponent))
.componentInstance as SimpleComponent;
expect(mockedComponent.someInput).toEqual('hi');
expect(mockedComponent.someInput2).toEqual('bye');
});

it('should trigger output bound behavior', () => {
Expand Down
38 changes: 15 additions & 23 deletions lib/mock_component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,30 @@ import { Component, EventEmitter, forwardRef, Type } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

export function MockComponent<TComponent>(component: Type<TComponent>): Type<TComponent> {
const propertyMetadata = getPropertyMetadata(component);

const options = {
inputs: new Array<string>(),
outputs: new Array<string>(),
const annotations = (component as any).__annotations__[0] || {};
const propertyMetadata = (component as any).__prop__metadata__ || {};

const options: Component = {
exportAs: annotations.exportAs,
inputs: Object.keys(propertyMetadata)
.filter((meta) => isInput(propertyMetadata[meta]))
.map((meta) => [meta, propertyMetadata[meta][0].bindingPropertyName || meta].join(':')),
outputs: Object.keys(propertyMetadata)
.filter((meta) => isOutput(propertyMetadata[meta]))
.map((meta) => [meta, propertyMetadata[meta][0].bindingPropertyName || meta].join(':')),
providers: [{
multi: true,
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ComponentMock)
}],
selector: getComponentSelector(component),
selector: annotations.selector,
template: '<ng-content></ng-content>'
};

options.inputs = Object.keys(propertyMetadata).filter((meta) => isInput(propertyMetadata[meta]));
options.outputs = Object.keys(propertyMetadata).filter((meta) => isOutput(propertyMetadata[meta]));

class ComponentMock implements ControlValueAccessor {
constructor() {
options.outputs.forEach((output) => {
(this as any)[output] = new EventEmitter<any>();
(options.outputs || []).forEach((output) => {
(this as any)[output.split(':')[0]] = new EventEmitter<any>();
});
}

Expand All @@ -34,7 +37,7 @@ export function MockComponent<TComponent>(component: Type<TComponent>): Type<TCo
}

/* tslint:disable:no-angle-bracket-type-assertion */
return Component(options as Component)(<any> ComponentMock as Type<TComponent>);
return Component(options)(<any> ComponentMock as Type<TComponent>);
/* tslint:enable:no-angle-bracket-type-assertion */
}

Expand All @@ -45,14 +48,3 @@ function isInput(propertyMetadata: any): boolean {
function isOutput(propertyMetadata: any): boolean {
return propertyMetadata[0].ngMetadataName === 'Output';
}

function getComponentSelector(component: any): string {
if (component.__annotations__) {
return component.__annotations__[0].selector;
}
throw new Error('No annotation or decoration metadata on your component');
}

function getPropertyMetadata(component: any): any {
return component.__prop__metadata__ || {};
}
2 changes: 2 additions & 0 deletions lib/test_components/simple_component.component.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';

@Component({
exportAs: 'seeimple',
selector: 'simple-component',
template: 'some template'
})
export class SimpleComponent {
@Input() someInput: string;
@Input('someOtherInput') someInput2: string;
@Output() someOutput1: EventEmitter<string>;
@Output() someOutput2: EventEmitter<string>;
}
14 changes: 6 additions & 8 deletions tslint.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
{
"extends": "tslint:all",
"rules": {
"comment-format": false,
"interface-name": false,
"completed-docs": false,
"member-access": false,
"newline-before-return": false,
"no-any": false,
"no-implicit-dependencies": false,
"no-import-side-effect": false,
"no-magic-numbers": false,
"no-parameter-properties": false,
"no-implicit-dependencies": [true, "dev"],
"no-floating-promises": false,
"no-submodule-imports": false,
"no-unsafe-any": false,
"no-use-before-declare": false,
"only-arrow-functions": false,
"ordered-imports": false,
"quotemark": [
true,
"single"
],
"strict-boolean-expressions": false,
"trailing-comma": false,
"typedef": false
}
Expand Down

0 comments on commit 14a1474

Please sign in to comment.