fix no result and refactoring tests

This commit is contained in:
Eugenio Romano 2016-09-02 01:00:09 +01:00
parent ef37150902
commit 0c253ffdf0
11 changed files with 376 additions and 351 deletions

View File

@ -32,6 +32,7 @@ export class SearchBarComponent {
fileNodeId: string;
fileShowed: boolean = false;
searchTerm: string = '';
@Output()
expand = new EventEmitter();
@ -50,6 +51,11 @@ export class SearchBarComponent {
}
}
searchTermChange(event) {
console.log('Search term changed', event);
this.searchTerm = event.value;
}
onExpandToggle(event) {
this.expand.emit(event);
}

View File

@ -220,7 +220,7 @@ Also make sure you include these dependencies in your .html page:
```
Example of an component that displays search results, using the Angular2 router to supply a 'q' parameter containing the
search term. If no ruter is present pon the page of if the router does not provide such a parameter then an empty
search term. If no router is present pon the page of if the router does not provide such a parameter then an empty
results page will be shown.
```ts

View File

@ -1,50 +0,0 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AlfrescoSearchService } from '../services/alfresco-search.service';
import { Observable } from 'rxjs/Rx';
export class SearchServiceMock extends AlfrescoSearchService {
getLiveSearchResults(term: string): Observable<any> {
if (term.length > 3) {
return Observable.of({
list: {
entries: [
{
entry: {
id: '123',
name: 'MyDoc',
content: {
mimetype: 'text/plain'
},
createdByUser: {
displayName: 'John Doe'
},
modifiedByUser: {
displayName: 'John Doe'
}
}
}
]
}
});
} else {
return Observable.throw('Fake server error');
}
}
}

View File

@ -1,10 +1,25 @@
<table data-automation-id="autocomplete_results" *ngIf="results && results.length && searchTerm" class="mdl-data-table mdl-js-data-table mdl-shadow--2dp full-width">
<table data-automation-id="autocomplete_results" *ngIf="results && results.length && searchTerm"
class="mdl-data-table mdl-js-data-table mdl-shadow--2dp full-width">
<tbody>
<tr *ngFor="let result of results; let idx = index" (click)="onItemClick(result, $event)"
attr.data-automation-id="autocomplete_result_for_{{result.entry.name}}" >
<td class="img-td"><img src="{{getMimeTypeIcon(result)}}" alt="{{getMimeTypeKey(result)|translate}}" /></td>
<td><div class="truncate" ><b>{{result.entry.name}}</b></div><div class="truncate">{{result.entry.createdByUser.displayName}}</div></td>
<tr id="result_row_{{idx}}" *ngFor="let result of results; let idx = index" (click)="onItemClick(result, $event)"
attr.data-automation-id="autocomplete_result_for_{{result.entry.name}}">
<td class="img-td"><img src="{{getMimeTypeIcon(result)}}" alt="{{getMimeTypeKey(result)|translate}}"/></td>
<td>
<div id="result_name_{{idx}}" class="truncate"><b>{{result.entry.name}}</b></div>
<div id="result_user_{{idx}}" class="truncate">{{result.entry.createdByUser.displayName}}</div>
</td>
</tr>
</tbody>
</table>
<p data-automation-id="autocomplete_error_message" *ngIf="errorMessage">{{ 'SEARCH.RESULTS.ERROR' | translate:{errorMessage: errorMessage} }}</p>
<table id="search_no_result" data-automation-id="search_no_result_found" *ngIf="results && results.length === 0"
class="mdl-data-table mdl-js-data-table mdl-shadow--2dp full-width">
<tbody>
<tr>
<td>
<div class="truncate"><b> {{ 'SEARCH.RESULTS.NONE' | translate:{searchTerm: searchTerm} }}</b></div>
</td>
</tr>
</tbody>
</table>
<p data-automation-id="autocomplete_error_message" *ngIf="errorMessage">{{ 'SEARCH.RESULTS.ERROR' |
translate:{errorMessage: errorMessage} }}</p>

View File

@ -15,34 +15,81 @@
* limitations under the License.
*/
import { provide } from '@angular/core';
import { it, describe, expect, inject, beforeEachProviders } from '@angular/core/testing';
import { it, describe, expect, inject, beforeEachProviders, beforeEach, afterEach } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing';
import { AlfrescoSearchAutocompleteComponent } from './alfresco-search-autocomplete.component';
import { SearchServiceMock } from './../assets/alfresco-search.service.mock';
import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service';
import { TranslationMock } from './../assets/translation.service.mock';
import { AlfrescoSearchService } from '../services/alfresco-search.service';
import {
AlfrescoSettingsService,
AlfrescoAuthenticationService,
AlfrescoContentService,
AlfrescoTranslationService } from 'ng2-alfresco-core';
AlfrescoTranslationService
} from 'ng2-alfresco-core';
declare let jasmine: any;
describe('AlfrescoSearchAutocompleteComponent', () => {
let alfrescoSearchComponentFixture, element, component;
let result = {
list: {
entries: [
{
entry: {
id: '123',
name: 'MyDoc',
isFile : true,
content: {
mimetype: 'text/plain'
},
createdByUser: {
displayName: 'John Doe'
},
modifiedByUser: {
displayName: 'John Doe'
}
}
}
]
}
};
let noResult = {
list: {
entries: []
}
};
beforeEachProviders(() => {
return [
provide(AlfrescoSearchService, {useClass: SearchServiceMock}),
provide(AlfrescoThumbnailService, {}),
provide(AlfrescoTranslationService, {}),
provide(AlfrescoSettingsService, {}),
provide(AlfrescoAuthenticationService, {}),
provide(AlfrescoContentService, {})
{provide: AlfrescoTranslationService, useClass: TranslationMock},
AlfrescoThumbnailService,
AlfrescoSettingsService,
AlfrescoAuthenticationService,
AlfrescoContentService,
AlfrescoSearchService
];
});
it('should setup i18n folder', () => {
beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.createAsync(AlfrescoSearchAutocompleteComponent)
.then(fixture => {
jasmine.Ajax.install();
alfrescoSearchComponentFixture = fixture;
element = alfrescoSearchComponentFixture.nativeElement;
component = alfrescoSearchComponentFixture.componentInstance;
});
}));
afterEach(() => {
jasmine.Ajax.uninstall();
});
it('should setup i18n folder', () => {
let translation = jasmine.createSpyObj('AlfrescoTranslationService', [
'addTranslationFolder'
]);
@ -51,99 +98,87 @@ describe('AlfrescoSearchAutocompleteComponent', () => {
});
it('should display search results when a search term is provided',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.createAsync(AlfrescoSearchAutocompleteComponent)
.then((fixture) => {
let componentInstance = fixture.componentInstance,
searchTerm = 'customSearchTerm';
spyOn(componentInstance, 'displaySearchResults').and.stub();
componentInstance.searchTerm = searchTerm;
componentInstance.ngOnChanges({
searchTerm: searchTerm
});
fixture.detectChanges();
expect(componentInstance.displaySearchResults).toHaveBeenCalledWith(searchTerm);
it('should display search results when a search term is provided', () => {
let searchTerm = 'customSearchTerm';
spyOn(component, 'displaySearchResults').and.stub();
component.searchTerm = searchTerm;
component.ngOnChanges({
searchTerm: searchTerm
});
alfrescoSearchComponentFixture.detectChanges();
expect(component.displaySearchResults).toHaveBeenCalledWith(searchTerm);
});
});
}));
it('should display the returned search results', (done) => {
component.resultsEmitter.subscribe(x => {
alfrescoSearchComponentFixture.detectChanges();
expect( element.querySelector('#result_user_0').innerHTML).toBe('John Doe');
expect( element.querySelector('#result_name_0').innerHTML).toBe('<b _ngcontent-a-1="">MyDoc</b>');
done();
});
it('should display the returned search results',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.createAsync(AlfrescoSearchAutocompleteComponent)
.then((fixture) => {
let componentInstance = fixture.componentInstance;
componentInstance.results = [{
entry: {
id: '123',
name: 'MyDoc',
content: {
mimetype: 'text/plain'
},
createdByUser: {
displayName: 'John Doe'
}
}
}];
componentInstance.searchTerm = '<term>';
fixture.detectChanges();
component.searchTerm = 'searchTerm';
component.ngOnChanges({searchTerm: component.searchTerm});
let element = fixture.nativeElement;
expect(element.querySelectorAll('table tr').length).toBe(1);
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: result
});
});
});
}));
it('should display no result if no result are returned', (done) => {
component.resultsEmitter.subscribe(x => {
alfrescoSearchComponentFixture.detectChanges();
expect( element.querySelector('#search_no_result')).not.toBe(null);
done();
});
it('should emit preview when file item clicked',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.createAsync(AlfrescoSearchAutocompleteComponent)
.then((fixture) => {
let componentInstance = fixture.componentInstance;
componentInstance.results = [{
entry: {
id: '123',
name: 'MyDoc',
content: {
mimetype: 'text/plain'
},
isFile: true
}
}];
fixture.detectChanges(componentInstance.results[0]);
componentInstance.preview.subscribe(e => {
expect(e.value).toBe(componentInstance.results[0]);
});
componentInstance.onItemClick();
component.searchTerm = 'searchTerm';
component.ngOnChanges({searchTerm: component.searchTerm});
});
}));
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: noResult
});
});
it('should not emit preview when non-file item clicked',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.createAsync(AlfrescoSearchAutocompleteComponent)
.then((fixture) => {
let componentInstance = fixture.componentInstance;
componentInstance.results = [{
entry: {
id: '123',
name: 'MyDoc',
content: {
mimetype: 'text/plain'
},
isFile: true
}
}];
fixture.detectChanges(componentInstance.results[0]);
componentInstance.preview.subscribe(e => {
expect(e.value).toBe(componentInstance.results[0]);
});
componentInstance.onItemClick();
it('should emit preview when file item clicked', (done) => {
component.resultsEmitter.subscribe(x => {
alfrescoSearchComponentFixture.detectChanges();
element.querySelector('#result_row_0').click();
});
});
}));
component.searchTerm = 'searchTerm';
component.ngOnChanges({searchTerm: component.searchTerm});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: result
});
component.preview.subscribe(e => {
done();
});
});
it('should not emit preview when non-file item is clicked', () => {
spyOn(component, 'onItemClick').and.stub();
component.ngOnChanges({searchTerm: 'searchTerm'});
component.preview.subscribe(e => {
expect(e.value).toBe(component.results[0]);
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: result
});
expect(component.onItemClick).not.toHaveBeenCalled();
});
});

View File

@ -15,13 +15,7 @@
* limitations under the License.
*/
import {
Component,
EventEmitter,
Input,
OnChanges,
Output
} from '@angular/core';
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
import { AlfrescoSearchService } from './../services/alfresco-search.service';
import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service';
import { AlfrescoPipeTranslate, AlfrescoTranslationService } from 'ng2-alfresco-core';
@ -53,6 +47,9 @@ export class AlfrescoSearchAutocompleteComponent implements OnChanges {
@Output()
preview: EventEmitter<any> = new EventEmitter();
@Output()
resultsEmitter = new EventEmitter();
constructor(private alfrescoSearchService: AlfrescoSearchService,
private translate: AlfrescoTranslationService,
private alfrescoThumbnailService: AlfrescoThumbnailService) {
@ -62,9 +59,9 @@ export class AlfrescoSearchAutocompleteComponent implements OnChanges {
this.results = null;
}
ngOnChanges(changes): void {
ngOnChanges(changes) {
if (changes.searchTerm) {
this.displaySearchResults(this.searchTerm);
this.displaySearchResults(changes.searchTerm);
}
}
@ -80,6 +77,7 @@ export class AlfrescoSearchAutocompleteComponent implements OnChanges {
results => {
this.results = results.list.entries;
this.errorMessage = null;
this.resultsEmitter.emit(this.results);
},
error => {
this.results = null;

View File

@ -16,133 +16,97 @@
*/
import { provide } from '@angular/core';
import { it, describe, expect, inject, beforeEachProviders } from '@angular/core/testing';
import { it, describe, expect, inject, beforeEachProviders, beforeEach } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing';
import { AlfrescoSearchControlComponent } from './alfresco-search-control.component';
import { SearchServiceMock } from './../assets/alfresco-search.service.mock';
import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service';
import { TranslationMock } from './../assets/translation.service.mock';
import {
AlfrescoSettingsService,
AlfrescoAuthenticationService,
AlfrescoContentService,
AlfrescoTranslationService } from 'ng2-alfresco-core';
import { AlfrescoSettingsService, AlfrescoAuthenticationService, AlfrescoContentService, AlfrescoTranslationService
} from 'ng2-alfresco-core';
import { AlfrescoSearchService } from '../services/alfresco-search.service';
describe('AlfrescoSearchControlComponent', () => {
let alfrescoSearchControlComponentFixture, element, component;
beforeEachProviders(() => {
return [
provide(AlfrescoSearchService, {useClass: SearchServiceMock}),
provide(AlfrescoThumbnailService, {}),
AlfrescoSearchService,
provide(AlfrescoTranslationService, {useClass: TranslationMock}),
provide(AlfrescoSettingsService, {}),
provide(AlfrescoAuthenticationService, {}),
provide(AlfrescoContentService, {})
AlfrescoThumbnailService,
AlfrescoSettingsService,
AlfrescoAuthenticationService,
AlfrescoContentService
];
});
it('should setup i18n folder', () => {
beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.createAsync(AlfrescoSearchControlComponent)
.then(fixture => {
alfrescoSearchControlComponentFixture = fixture;
element = alfrescoSearchControlComponentFixture.nativeElement;
component = alfrescoSearchControlComponentFixture.componentInstance;
});
}));
it('should setup i18n folder', () => {
let translation = jasmine.createSpyObj('AlfrescoTranslationService', [
'addTranslationFolder'
]);
let alfrescoSearchControlComponent = new AlfrescoSearchControlComponent(translation);
expect(alfrescoSearchControlComponent).toBeDefined();
});
it('should emit searchChange when search term changed',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.createAsync(AlfrescoSearchControlComponent)
.then((componentFixture) => {
componentFixture.componentInstance.searchTerm = 'customSearchTerm';
componentFixture.detectChanges();
componentFixture.componentInstance.searchChange.subscribe(e => {
expect(e.value).toBe('customSearchTerm');
});
});
}));
it('should emit searchChange when search term changed', () => {
alfrescoSearchControlComponentFixture.componentInstance.searchTerm = 'customSearchTerm';
alfrescoSearchControlComponentFixture.detectChanges();
alfrescoSearchControlComponentFixture.componentInstance.searchChange.subscribe(e => {
expect(e.value).toBe('customSearchTerm');
});
});
describe('Component rendering', () => {
it('should display a text input field by default',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.createAsync(AlfrescoSearchControlComponent)
.then((componentFixture) => {
const element = componentFixture.nativeElement;
componentFixture.detectChanges();
expect(element.querySelectorAll('input[type="text"]').length).toBe(1);
});
})
);
it('should display a text input field by default', () => {
alfrescoSearchControlComponentFixture.detectChanges();
expect(element.querySelectorAll('input[type="text"]').length).toBe(1);
});
it('should display a search input field when specified',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb.createAsync(AlfrescoSearchControlComponent).then((componentFixture) => {
const element = componentFixture.nativeElement;
componentFixture.componentInstance.inputType = 'search';
componentFixture.detectChanges();
expect(element.querySelectorAll('input[type="search"]').length).toBe(1);
});
}));
it('should display a search input field when specified', () => {
alfrescoSearchControlComponentFixture.componentInstance.inputType = 'search';
alfrescoSearchControlComponentFixture.detectChanges();
expect(element.querySelectorAll('input[type="search"]').length).toBe(1);
});
it('should set browser autocomplete to off by default',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.createAsync(AlfrescoSearchControlComponent)
.then((componentFixture) => {
const element = componentFixture.nativeElement;
componentFixture.detectChanges();
let attr = element.querySelectorAll('input[type="text"]')[0].getAttribute('autocomplete');
expect(attr).toBe('off');
});
})
);
it('should set browser autocomplete to off by default', () => {
alfrescoSearchControlComponentFixture.detectChanges();
let attr = element.querySelectorAll('input[type="text"]')[0].getAttribute('autocomplete');
expect(attr).toBe('off');
});
it('should set browser autocomplete to on when configured',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb.createAsync(AlfrescoSearchControlComponent).then((componentFixture) => {
const element = componentFixture.nativeElement;
componentFixture.componentInstance.autocomplete = true;
componentFixture.detectChanges();
expect(element.querySelectorAll('input[type="text"]')[0].getAttribute('autocomplete'))
.toBe('on');
});
}));
it('should set browser autocomplete to on when configured', () => {
alfrescoSearchControlComponentFixture.componentInstance.autocomplete = true;
alfrescoSearchControlComponentFixture.detectChanges();
expect(element.querySelectorAll('input[type="text"]')[0].getAttribute('autocomplete')).toBe('on');
});
it('should show an expanding control by default',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.createAsync(AlfrescoSearchControlComponent)
.then((componentFixture) => {
const element = componentFixture.nativeElement;
componentFixture.detectChanges();
expect(element.querySelectorAll('div.mdl-textfield--expandable').length).toBe(1);
expect(element.querySelectorAll('div.mdl-textfield__expandable-holder').length).toBe(1);
expect(element.querySelectorAll('label.mdl-button--icon').length).toBe(1);
});
})
);
it('should show an expanding control by default', () => {
alfrescoSearchControlComponentFixture.detectChanges();
expect(element.querySelectorAll('div.mdl-textfield--expandable').length).toBe(1);
expect(element.querySelectorAll('div.mdl-textfield__expandable-holder').length).toBe(1);
expect(element.querySelectorAll('label.mdl-button--icon').length).toBe(1);
});
it('should show a normal non-expanding control when configured',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.createAsync(AlfrescoSearchControlComponent)
.then((componentFixture) => {
const element = componentFixture.nativeElement;
componentFixture.detectChanges();
componentFixture.componentInstance.expandable = false;
componentFixture.detectChanges();
expect(element.querySelectorAll('div.mdl-textfield--expandable').length).toBe(0);
expect(element.querySelectorAll('div.mdl-textfield__expandable-holder').length).toBe(0);
expect(element.querySelectorAll('label.mdl-button--icon').length).toBe(0);
});
})
);
it('should show a normal non-expanding control when configured', () => {
alfrescoSearchControlComponentFixture.detectChanges();
alfrescoSearchControlComponentFixture.componentInstance.expandable = false;
alfrescoSearchControlComponentFixture.detectChanges();
expect(element.querySelectorAll('div.mdl-textfield--expandable').length).toBe(0);
expect(element.querySelectorAll('div.mdl-textfield__expandable-holder').length).toBe(0);
expect(element.querySelectorAll('label.mdl-button--icon').length).toBe(0);
});
});
});

View File

@ -0,0 +1,16 @@
:host .mdl-data-table caption {
margin: 0 0 16px 0;
text-align: left;
}
:host .mdl-data-table td {
max-width: 0;
white-space: nowrap;
}
:host .mdl-data-table td.col-mimetype-icon {
width: 24px;
}
:host .col-display-name {
min-width: 250px;
overflow: hidden;
text-overflow: ellipsis;
}

View File

@ -1,4 +1,3 @@
<p data-automation-id="search_no_result_found" *ngIf="results&& results.length == 0">{{ 'SEARCH.RESULTS.NONE' | translate:{searchTerm: searchTerm} }}</p>
<table data-automation-id="search_result_table" *ngIf="results && results.length && searchTerm" class="mdl-data-table mdl-js-data-table mdl-shadow--2dp full-width">
<caption data-automation-id="search_result_found">{{ 'SEARCH.RESULTS.SUMMARY' | translate:{numResults: results.length, searchTerm: searchTerm} }}</caption>
<thead>
@ -17,16 +16,25 @@
</thead>
<tbody>
<tr *ngFor="let result of results; let idx = index" (click)="onItemClick(result, $event)">
<tr id="result_row_{{idx}}" *ngFor="let result of results; let idx = index" (click)="onItemClick(result, $event)">
<td class="col-mimetype-icon"><img src="{{getMimeTypeIcon(result)}}" alt="{{getMimeTypeKey(result)|translate}}" /></td>
<td class="mdl-data-table__cell--non-numeric col-display-name"
<td id="result_name_{{idx}}" class="mdl-data-table__cell--non-numeric col-display-name"
attr.data-automation-id=file_{{result.entry.name}} >{{result.entry.name}}</td>
<td class="mdl-data-table__cell--non-numeric col-modified-by"
attr.data-automation-id=file_{{result.entry.name}}_{{result.entry.modifiedByUser.displayName}}>
{{result.entry.modifiedByUser.displayName}}</td>
<td id="result_user_{{idx}}" class="mdl-data-table__cell--non-numeric col-modified-by"
attr.data-automation-id=file_{{result.entry.name}}_{{result.entry.modifiedByUser.displayName}}>{{result.entry.modifiedByUser.displayName}}</td>
<td class="col-modified-at">{{result.entry.modifiedAt | date}}</td>
</tr>
</tbody>
</table>
<table id="search_no_result" data-automation-id="search_no_result_found" *ngIf="results && results.length === 0"
class="mdl-data-table mdl-js-data-table mdl-shadow--2dp full-width">
<tbody>
<tr>
<td>
<div class="truncate"><b> {{ 'SEARCH.RESULTS.NONE' | translate:{searchTerm: searchTerm} }}</b></div>
</td>
</tr>
</tbody>
</table>
<p data-automation-id="search_error_message" *ngIf="errorMessage">{{ 'SEARCH.RESULTS.ERROR' | translate:{errorMessage: errorMessage} }}</p>

View File

@ -15,11 +15,10 @@
* limitations under the License.
*/
import { it, describe, expect, inject, beforeEachProviders } from '@angular/core/testing';
import { it, describe, expect, inject, beforeEachProviders, beforeEach } from '@angular/core/testing';
import { TestComponentBuilder } from '@angular/compiler/testing';
import { RouteParams } from '@angular/router-deprecated';
import { AlfrescoSearchComponent } from './alfresco-search.component';
import { SearchServiceMock } from './../assets/alfresco-search.service.mock';
import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service';
import { TranslationMock } from './../assets/translation.service.mock';
import { AlfrescoSearchService } from '../services/alfresco-search.service';
@ -27,22 +26,70 @@ import {
AlfrescoSettingsService,
AlfrescoAuthenticationService,
AlfrescoContentService,
AlfrescoTranslationService } from 'ng2-alfresco-core';
AlfrescoTranslationService
} from 'ng2-alfresco-core';
declare let jasmine: any;
describe('AlfrescoSearchComponent', () => {
beforeEachProviders(() => {
let alfrescoSearchComponentFixture, element, component;
let result = {
list: {
entries: [
{
entry: {
id: '123',
name: 'MyDoc',
isFile : true,
content: {
mimetype: 'text/plain'
},
createdByUser: {
displayName: 'John Doe'
},
modifiedByUser: {
displayName: 'John Doe'
}
}
}
]
}
};
let noResult = {
list: {
entries: []
}
};
beforeEachProviders(() => {
return [
{ provide: AlfrescoSearchService, useClass: SearchServiceMock },
{ provide: AlfrescoThumbnailService },
{ provide: AlfrescoTranslationService, useClass: TranslationMock },
{ provide: AlfrescoSettingsService },
{ provide: AlfrescoAuthenticationService },
{ provide: AlfrescoContentService }
AlfrescoSearchService,
{provide: AlfrescoTranslationService, useClass: TranslationMock},
AlfrescoThumbnailService,
AlfrescoSettingsService,
AlfrescoAuthenticationService,
AlfrescoContentService
];
});
beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.createAsync(AlfrescoSearchComponent)
.then(fixture => {
jasmine.Ajax.install();
alfrescoSearchComponentFixture = fixture;
element = alfrescoSearchComponentFixture.nativeElement;
component = alfrescoSearchComponentFixture.componentInstance;
});
}));
afterEach(() => {
jasmine.Ajax.uninstall();
});
it('should not have a search term by default', () => {
let search = new AlfrescoSearchComponent(null, null, null, null);
expect(search).toBeDefined();
@ -50,7 +97,7 @@ describe('AlfrescoSearchComponent', () => {
});
it('should take the provided search term from query param provided via RouteParams', () => {
let search = new AlfrescoSearchComponent(null, null, null, new RouteParams({ q: 'exampleTerm692' }));
let search = new AlfrescoSearchComponent(null, null, null, new RouteParams({q: 'exampleTerm692'}));
expect(search.searchTerm).toBe('exampleTerm692');
});
@ -72,72 +119,69 @@ describe('AlfrescoSearchComponent', () => {
describe('Rendering search results', () => {
it('should display search results when a search term is provided',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.createAsync(AlfrescoSearchComponent)
.then((fixture) => {
let componentInstance = fixture.componentInstance,
searchTerm = 'customSearchTerm';
spyOn(componentInstance, 'displaySearchResults').and.stub();
componentInstance.searchTerm = searchTerm;
componentInstance.ngOnChanges();
fixture.detectChanges();
expect(componentInstance.displaySearchResults).toHaveBeenCalledWith(searchTerm);
it('should display search results when a search term is provided', (done) => {
});
}));
component.searchTerm = 'searchTerm';
component.ngOnChanges({searchTerm: component.searchTerm});
it('should display the returned search results',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.overrideProviders(AlfrescoSearchComponent, [
{ provide: AlfrescoSearchService, useClass: SearchServiceMock }
])
.createAsync(AlfrescoSearchComponent)
.then((fixture) => {
let componentInstance = fixture.componentInstance;
componentInstance.searchTerm = '<term>';
componentInstance.ngOnChanges();
fixture.detectChanges();
component.resultsEmitter.subscribe(x => {
alfrescoSearchComponentFixture.detectChanges();
expect( element.querySelector('#result_user_0').innerHTML).toBe('John Doe');
expect( element.querySelector('#result_name_0').innerHTML).toBe('MyDoc');
done();
});
let element = fixture.nativeElement;
expect(element.querySelectorAll('table tbody tr').length).toBe(1);
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: result
});
});
});
}));
it('should display no result if no result are returned', (done) => {
component.resultsEmitter.subscribe(x => {
alfrescoSearchComponentFixture.detectChanges();
expect( element.querySelector('#search_no_result')).not.toBe(null);
done();
});
component.searchTerm = 'searchTerm';
component.ngOnChanges({searchTerm: component.searchTerm});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'json',
responseText: noResult
});
});
});
describe('search result actions', () => {
it('should emit preview when file item clicked',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.overrideProviders(AlfrescoSearchComponent, [
{ provide: AlfrescoSearchService, useClass: SearchServiceMock }
])
.createAsync(AlfrescoSearchComponent)
.then((fixture) => {
let componentInstance = fixture.componentInstance;
componentInstance.results = [{
entry: {
id: '123',
name: 'MyDoc',
content: {
mimetype: 'text/plain'
},
isFile: true
}
}];
fixture.detectChanges(componentInstance.results[0]);
componentInstance.preview.subscribe(e => {
expect(e.value).toBe(componentInstance.results[0]);
});
componentInstance.onItemClick();
it('should emit preview when file item clicked', () => {
component.results = [{
entry: {
id: '123',
name: 'MyDoc',
content: {
mimetype: 'text/plain'
},
isFile: true
}
}];
});
}));
alfrescoSearchComponentFixture.detectChanges(component.results[0]);
component.preview.subscribe(e => {
expect(e.value).toBe(component.results[0]);
});
jasmine.Ajax.requests.mostRecent().respondWith({
status: 200,
contentType: 'text/plain',
responseText: '<div></div>'
});
});
});
});

View File

@ -26,24 +26,7 @@ declare let __moduleName: string;
@Component({
moduleId: __moduleName,
selector: 'alfresco-search',
styles: [`
:host .mdl-data-table caption {
margin: 0 0 16px 0;
text-align: left;
}
:host .mdl-data-table td {
max-width: 0;
white-space: nowrap;
}
:host .mdl-data-table td.col-mimetype-icon {
width: 24px;
}
:host .col-display-name {
min-width: 250px;
overflow: hidden;
text-overflow: ellipsis;
}
`],
styleUrls: ['./alfresco-search.component.css'],
templateUrl: './alfresco-search.component.html',
providers: [AlfrescoSearchService],
pipes: [AlfrescoPipeTranslate]
@ -58,6 +41,9 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit {
@Output()
preview: EventEmitter<any> = new EventEmitter();
@Output()
resultsEmitter = new EventEmitter();
results: any;
errorMessage;
@ -84,7 +70,9 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit {
}
ngOnChanges(changes): void {
this.displaySearchResults(this.searchTerm);
if (changes.searchTerm) {
this.displaySearchResults(changes.searchTerm);
}
}
/**
@ -123,6 +111,7 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit {
.subscribe(
results => {
this.results = results.list.entries;
this.resultsEmitter.emit(this.results);
this.errorMessage = null;
},
error => {