Skip to content

Commit

Permalink
feat(spectator): additional query capabilities (#143)
Browse files Browse the repository at this point in the history
Closes #142.
  • Loading branch information
dirkluijk authored Aug 6, 2019
1 parent d0078dc commit 1dccdb2
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 66 deletions.
31 changes: 10 additions & 21 deletions projects/spectator/src/lib/host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
import { DebugElement, Type } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
import { By } from '@angular/platform-browser';

import { _getChild, _getChildren, _setInput, Spectator } from './internals';
import * as customMatchers from './matchers';
import { By } from '@angular/platform-browser';
import { DOMSelector } from './dom-selectors';
import { HostComponent, initialModule, SpectatorOptions } from './config';
import { Token } from './token';
import { isType } from './is-type';
Expand All @@ -39,29 +40,17 @@ export class SpectatorWithHost<C, H = HostComponent> extends Spectator<C> {
this.hostFixture.detectChanges();
}

/**
*
* @param directiveOrSelector
* @param options
* @returns
*/
queryHost<T extends Element>(directiveOrSelector: string): T;
queryHost<T>(directiveOrSelector: Type<T>): T;
queryHost<T>(directiveOrSelector: Type<any>, options: { read: Token<T> }): T;
queryHost<T>(directiveOrSelector: Type<T> | string, options: { read } = { read: undefined }): T {
queryHost<T extends Element>(selector: string | DOMSelector): T;
queryHost<T>(directive: Type<T>): T;
queryHost<T>(directiveOrSelector: Type<any> | string, options: { read: Token<T> }): T;
queryHost<T>(directiveOrSelector: Type<T> | DOMSelector | string, options: { read } = { read: undefined }): T {
return _getChild<T>(this.hostDebugElement)(directiveOrSelector, options);
}

/**
*
* @param directiveOrSelector
* @param options
* @returns
*/
queryHostAll<T extends Element>(directiveOrSelector: string): T[];
queryHostAll<T>(directiveOrSelector: Type<T>): T[];
queryHostAll<T>(directiveOrSelector: Type<any>, options: { read: Token<T> }): T[];
queryHostAll<T>(directiveOrSelector: Type<T> | string, options: { read } = { read: undefined }): T[] {
queryHostAll<T extends Element>(selector: string | DOMSelector): T[];
queryHostAll<T>(directive: Type<T>): T[];
queryHostAll<T>(directiveOrSelector: Type<any> | string, options: { read: Token<T> }): T[];
queryHostAll<T>(directiveOrSelector: Type<T> | DOMSelector | string, options: { read } = { read: undefined }): T[] {
return _getChildren<T>(this.hostDebugElement)(directiveOrSelector, options);
}

Expand Down
65 changes: 20 additions & 45 deletions projects/spectator/src/lib/internals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,9 @@ export class Spectator<C> {
}
}

/**
*
* @param directiveOrSelector
* @param options
* @returns
*/
query<R extends Element>(directiveOrSelector: string | DOMSelector): R;
query<R>(directiveOrSelector: Type<R>): R;
query<R>(directiveOrSelector: Type<any>, options: { read: Token<R> }): R;
query<R extends Element>(selector: string | DOMSelector): R;
query<R>(directive: Type<R>): R;
query<R>(directiveOrSelector: Type<any> | string, options: { read: Token<R> }): R;
query<R>(directiveOrSelector: Type<any> | DOMSelector | string, options: { read: Token<R> } = { read: undefined }): R {
try {
return _getChild<R>(this.debugElement)(directiveOrSelector, options);
Expand All @@ -84,28 +78,19 @@ export class Spectator<C> {
}
}

/**
*
* @param directiveOrSelector
* @param options
* @returns
*/
queryAll<R extends Element[]>(directiveOrSelector: string | DOMSelector): R;
queryAll<R>(directiveOrSelector: Type<R>): R[];
queryAll<R>(directiveOrSelector: Type<any>, options: { read: Token<R> }): R[];
queryAll<R extends Element[]>(selector: string | DOMSelector): R;
queryAll<R>(directive: Type<R>): R[];
queryAll<R>(directiveOrSelector: Type<any> | string, options: { read: Token<R> }): R[];
queryAll<R>(directiveOrSelector: Type<any> | DOMSelector | string, options: { read: Token<R> } = { read: undefined }): R[] {
return _getChildren<R>(this.debugElement)(directiveOrSelector, options);
}

/**
* Helper for getting the last value
* @param directiveOrSelector
* @param options
* @returns
*/
queryLast<R extends Element>(directiveOrSelector: string | DOMSelector): R;
queryLast<R>(directiveOrSelector: Type<R>): R;
queryLast<R>(directiveOrSelector: Type<any>, options: { read: Token<R> }): R;
queryLast<R extends Element>(selector: string | DOMSelector): R;
queryLast<R>(directive: Type<R>): R;
queryLast<R>(directiveOrSelector: Type<any> | string, options: { read: Token<R> }): R;
queryLast<R>(directiveOrSelector: Type<R> | DOMSelector | string, options: { read: Token<R> } = { read: undefined }): R {
const result = _getChildren<R>(this.debugElement)(directiveOrSelector, options);
if (result && result.length) {
Expand Down Expand Up @@ -305,26 +290,13 @@ export class Spectator<C> {
*/
export function _getChild<R>(debugElementRoot: DebugElement) {
return function(directiveOrSelector: Type<R> | DOMSelector | string, options: { read } = { read: undefined }): R {
let debugElement: DebugElement;
const [child] = _getChildren<R>(debugElementRoot)(directiveOrSelector, options);

if (typeof directiveOrSelector === 'string') {
debugElement = debugElementRoot.query(By.css(directiveOrSelector));
return debugElement && debugElement.nativeElement;
} else if (directiveOrSelector instanceof DOMSelector) {
return directiveOrSelector.execute(debugElementRoot.nativeElement)[0] as any;
} else {
debugElement = debugElementRoot.query(By.directive(directiveOrSelector));
}

if (!debugElement) {
if (!child) {
throw new SpectatorDebugElementNotFoundError(`Cannot find a debug element for ${directiveOrSelector}`);
}

if (options.read) {
return debugElement.injector.get(options.read);
}

return debugElement.componentInstance;
return child;
};
}

Expand All @@ -336,13 +308,14 @@ export function _getChild<R>(debugElementRoot: DebugElement) {
*/
export function _getChildren<R>(debugElementRoot: DebugElement) {
return function(directiveOrSelector: Type<R> | DOMSelector | string, options: { read } = { read: undefined }): R[] {
if (directiveOrSelector instanceof DOMSelector) {
return directiveOrSelector.execute(debugElementRoot.nativeElement) as any[];
}

let debugElement: DebugElement[];

if (typeof directiveOrSelector === 'string') {
debugElement = debugElementRoot.queryAll(By.css(directiveOrSelector));
return debugElement && debugElement.map(debug => debug.nativeElement);
} else if (directiveOrSelector instanceof DOMSelector) {
return directiveOrSelector.execute(debugElementRoot.nativeElement) as any[];
} else {
debugElement = debugElementRoot.queryAll(By.directive(directiveOrSelector));
}
Expand All @@ -353,9 +326,11 @@ export function _getChildren<R>(debugElementRoot: DebugElement) {

if (options.read) {
return debugElement.map(debug => debug.injector.get(options.read));
} else if (typeof directiveOrSelector === 'string') {
return debugElement.map(debug => debug.nativeElement);
} else {
return debugElement.map(debug => debug.componentInstance);
}

return debugElement.map(debug => debug.componentInstance);
};
}

Expand Down
7 changes: 7 additions & 0 deletions src/app/view-children/view-children.component.jest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ describe('ViewChildrenComponent', () => {
expect(serviceFromChild.length).toBe(4);
expect(components.length).toBe(4);
expect(divs.length).toBe(2);

expect(spectator.queryAll(ChildComponent, { read: ChildServiceService })).toEqual(serviceFromChild);
expect(spectator.queryAll('app-child', { read: ChildServiceService })).toEqual(serviceFromChild);
});
});

Expand All @@ -60,5 +63,9 @@ describe('ContentChild', () => {

const contentChilds = host.queryAll(ChildComponent);
expect(contentChilds.length).toBe(6);

const lastContentChild = host.queryLast(ChildComponent);

expect(host.query('app-child:last-child', { read: ChildComponent })).toBe(lastContentChild);
});
});
7 changes: 7 additions & 0 deletions src/app/view-children/view-children.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ describe('ViewChildrenComponent', () => {
expect(serviceFromChild.length).toBe(4);
expect(components.length).toBe(4);
expect(divs.length).toBe(2);

expect(spectator.queryAll(ChildComponent, { read: ChildServiceService })).toEqual(serviceFromChild);
expect(spectator.queryAll('app-child', { read: ChildServiceService })).toEqual(serviceFromChild);
});
});

Expand All @@ -60,5 +63,9 @@ describe('ContentChild', () => {

const contentChilds = host.queryAll(ChildComponent);
expect(contentChilds.length).toBe(6);

const lastContentChild = host.queryLast(ChildComponent);

expect(host.query('app-child:last-child', { read: ChildComponent })).toBe(lastContentChild);
});
});

0 comments on commit 1dccdb2

Please sign in to comment.