From 147af98bda478d7782390fb7e4600e5d62e55e0b Mon Sep 17 00:00:00 2001 From: Will Abson Date: Fri, 23 Sep 2016 18:07:40 +0100 Subject: [PATCH 01/16] Restore navigation to search page in demo-shell - Remove deprecated router component - searchChanges and new searchSubmit component outputs work as you would expect - Update tests Refs #737 --- .../search/search-bar.component.html | 2 +- .../components/search/search-bar.component.ts | 18 ++++++++-- .../alfresco-search-control.component.spec.ts | 34 +++++++++++++++++++ .../alfresco-search-control.component.ts | 12 ++++--- .../alfresco-search.component.spec.ts | 19 +++++++---- .../components/alfresco-search.component.ts | 24 +++++++------ 6 files changed, 85 insertions(+), 24 deletions(-) diff --git a/demo-shell-ng2/app/components/search/search-bar.component.html b/demo-shell-ng2/app/components/search/search-bar.component.html index 4d89fd0d8b..52d8ee7a52 100644 --- a/demo-shell-ng2/app/components/search/search-bar.component.html +++ b/demo-shell-ng2/app/components/search/search-bar.component.html @@ -1,5 +1,5 @@ + (searchSubmit)="onSearchSubmit($event);" (searchChange)="onSearchTermChange($event);" (expand)="onExpandToggle($event);" (preview)="onFileClicked($event)"> { expect(element.querySelectorAll('label.mdl-button--icon').length).toBe(0); }); }); + + describe('search submit', () => { + + it('should fire a search when a term has been entered', () => { + spyOn(component.searchSubmit, 'emit'); + alfrescoSearchControlComponentFixture.detectChanges(); + let formEl = element.querySelector('form'); + component.searchTerm = 'searchTerm1'; + component.searchControl.updateValue('searchTerm1'); + alfrescoSearchControlComponentFixture.detectChanges(); + formEl.dispatchEvent(new Event('submit')); + + alfrescoSearchControlComponentFixture.detectChanges(); + + expect(component.searchSubmit.emit).toHaveBeenCalledWith({ + 'value': 'searchTerm1' + }); + }); + + it('should not fire a search when no term has been entered', () => { + spyOn(component.searchSubmit, 'emit'); + alfrescoSearchControlComponentFixture.detectChanges(); + let inputEl = element.querySelector('input[type="text"]'); + let formEl = element.querySelector('form'); + inputEl.value = ''; + formEl.dispatchEvent(new Event('submit')); + + alfrescoSearchControlComponentFixture.detectChanges(); + + expect(component.searchSubmit.emit).not.toHaveBeenCalled(); + }); + + }); + }); */ diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts index 09eee56960..1432361a88 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts @@ -45,6 +45,9 @@ export class AlfrescoSearchControlComponent { @Output() searchChange = new EventEmitter(); + @Output() + searchSubmit = new EventEmitter(); + @Output() preview = new EventEmitter(); @@ -74,6 +77,10 @@ export class AlfrescoSearchControlComponent { (value: string) => { this.autocompleteSearchTerm = value; this.searchValid = this.searchControl.valid; + this.searchChange.emit({ + value: value, + valid: this.searchValid + }); } ); @@ -98,11 +105,8 @@ export class AlfrescoSearchControlComponent { * @param event Submit event that was fired */ onSearch(event): void { - if (event) { - event.preventDefault(); - } if (this.searchControl.valid) { - this.searchChange.emit({ + this.searchSubmit.emit({ value: this.searchTerm }); this.searchInput.nativeElement.blur(); diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts index 7136ea6306..b1c8e34a6a 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts @@ -15,11 +15,11 @@ * limitations under the License. */ -/* -import { PLATFORM_PIPES } from '@angular/core'; +import { PLATFORM_PIPES, ReflectiveInjector } from '@angular/core'; import { it, describe, expect, inject, beforeEachProviders, beforeEach } from '@angular/core/testing'; import { TestComponentBuilder } from '@angular/compiler/testing'; -import { RouteParams } from '@angular/router-deprecated'; +import { ActivatedRoute } from '@angular/router'; +import { Observable } from 'rxjs/Rx'; import { AlfrescoSearchComponent } from './alfresco-search.component'; import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service'; import { TranslationMock } from './../assets/translation.service.mock'; @@ -103,12 +103,20 @@ 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 injector = ReflectiveInjector.resolveAndCreate([ + { provide: ActivatedRoute, useValue: { params: Observable.from([{ q: 'exampleTerm692' }]) } } + ]); + let search = new AlfrescoSearchComponent(null, null, null, injector.get(ActivatedRoute)); + search.ngOnInit(); expect(search.searchTerm).toBe('exampleTerm692'); }); it('should have a null search term if no query param provided via RouteParams', () => { - let search = new AlfrescoSearchComponent(null, null, null, new RouteParams({})); + let injector = ReflectiveInjector.resolveAndCreate([ + { provide: ActivatedRoute, useValue: { params: Observable.from([{}]) } } + ]); + let search = new AlfrescoSearchComponent(null, null, null, injector.get(ActivatedRoute)); + search.ngOnInit(); expect(search.searchTerm).toBeNull(); }); @@ -191,4 +199,3 @@ describe('AlfrescoSearchComponent', () => { }); }); -*/ diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts index 1c06325fa9..6930c03851 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Component, EventEmitter, Input, Output, OnChanges, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { Component, EventEmitter, Input, Output, Optional, OnChanges, SimpleChanges, OnInit } from '@angular/core'; +import { ActivatedRoute, Params } from '@angular/router'; import { AlfrescoSearchService } from './../services/alfresco-search.service'; import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service'; import { AlfrescoTranslationService } from 'ng2-alfresco-core'; @@ -46,12 +46,12 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit { errorMessage; - route: any[] = []; + queryParamName = 'q'; constructor(private alfrescoSearchService: AlfrescoSearchService, private translate: AlfrescoTranslationService, private _alfrescoThumbnailService: AlfrescoThumbnailService, - private activatedRoute: ActivatedRoute) { + @Optional() private route: ActivatedRoute) { if (translate !== null) { translate.addTranslationFolder('node_modules/ng2-alfresco-search/dist/src'); @@ -61,15 +61,19 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit { } ngOnInit(): void { - this.activatedRoute.params.subscribe(params => { - this.searchTerm = params['q']; + if (this.route) { + this.route.params.forEach((params: Params) => { + this.searchTerm = params.hasOwnProperty(this.queryParamName) ? params[this.queryParamName] : null; + this.displaySearchResults(this.searchTerm); + }); + } else { this.displaySearchResults(this.searchTerm); - }); + } } - ngOnChanges(changes): void { - if (changes.searchTerm) { - this.displaySearchResults(changes.searchTerm.currentValue); + ngOnChanges(changes: SimpleChanges): void { + if (changes['searchTerm']) { + this.displaySearchResults(changes['searchTerm'].currentValue); } } From 2e58481f1556702215fd999adecd228b93f1026a Mon Sep 17 00:00:00 2001 From: Will Abson Date: Fri, 23 Sep 2016 18:19:34 +0100 Subject: [PATCH 02/16] Add additional tests for search control component Refs #737 --- .../alfresco-search-control.component.spec.ts | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts index 32d420b882..258e7e4202 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts @@ -152,5 +152,51 @@ describe('AlfrescoSearchControlComponent', () => { }); + describe('component focus', () => { + + it('should fire an event when the search box receives focus', () => { + spyOn(component.expand, 'emit'); + let inputEl = element.querySelector('input'); + inputEl.dispatchEvent(new Event('focus')); + expect(component.expand.emit).toHaveBeenCalledWith({ + expanded: true + }); + }); + + it('should fire an event when the search box loses focus', () => { + spyOn(component.expand, 'emit'); + let inputEl = element.querySelector('input'); + inputEl.dispatchEvent(new Event('blur')); + expect(component.expand.emit).toHaveBeenCalledWith({ + expanded: false + }); + }); + + it('should NOT fire an event when the search box receives/loses focus but the component is not expandable', + () => { + spyOn(component.expand, 'emit'); + component.expandable = false; + let inputEl = element.querySelector('input'); + inputEl.dispatchEvent(new Event('focus')); + inputEl.dispatchEvent(new Event('blur')); + expect(component.expand.emit).not.toHaveBeenCalled(); + }); + + }); + + describe('file preview', () => { + + it('should emit a preview event when onFileClicked is called', () => { + spyOn(component.preview, 'emit'); + component.onFileClicked({ + value: 'node12345' + }); + expect(component.preview.emit).toHaveBeenCalledWith({ + 'value': 'node12345' + }); + }); + + }); + }); */ From 124da1ff0bbae02d58a7124771af6682b1b2ac5b Mon Sep 17 00:00:00 2001 From: Will Abson Date: Fri, 23 Sep 2016 18:21:03 +0100 Subject: [PATCH 03/16] Add missing tests for search autocomplete component Refs #737, #363 --- ...esco-search-autocomplete.component.spec.ts | 102 +++++++++++++++--- .../alfresco-search-autocomplete.component.ts | 4 + 2 files changed, 94 insertions(+), 12 deletions(-) diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts index 7e0b47e6b6..a2eee1014e 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts @@ -47,7 +47,7 @@ describe('AlfrescoSearchAutocompleteComponent', () => { name: 'MyDoc', isFile : true, content: { - mimetype: 'text/plain' + mimeType: 'text/plain' }, createdByUser: { displayName: 'John Doe' @@ -61,12 +61,43 @@ describe('AlfrescoSearchAutocompleteComponent', () => { } }; + let folderResult = { + list: { + entries: [ + { + entry: { + id: '123', + name: 'MyFolder', + isFile : false, + isFolder : true, + createdByUser: { + displayName: 'John Doe' + }, + modifiedByUser: { + displayName: 'John Doe' + } + } + } + ] + } + }; + let noResult = { list: { entries: [] } }; + let errorJson = { + error: { + errorKey: 'Search failed', + statusCode: 400, + briefSummary: '08220082 search failed', + stackTrace: 'For security reasons the stack trace is no longer displayed, but the property is kept for previous versions.', + descriptionURL: 'https://api-explorer.alfresco.com' + } + }; + beforeEachProviders(() => { return [ { provide: PLATFORM_PIPES, useValue: AlfrescoPipeTranslate, multi: true }, @@ -133,10 +164,35 @@ describe('AlfrescoSearchAutocompleteComponent', () => { }); }); + it('should display the correct thumbnail for result items', (done) => { + + component.baseComponentPath = 'http://localhost'; + spyOn(component.alfrescoThumbnailService, 'getMimeTypeIcon').and.returnValue('fake-type-icon.svg'); + spyOn(component.alfrescoThumbnailService, 'getMimeTypeKey').and.returnValue('FAKE_TYPE'); + + component.resultsEmitter.subscribe(() => { + alfrescoSearchComponentFixture.detectChanges(); + let imgEl = element.querySelector('#result_row_0 img'); + expect(imgEl).not.toBeNull(); + expect(imgEl.src).toBe('http://localhost/img/fake-type-icon.svg'); + expect(imgEl.alt).toBe('SEARCH.ICONS.FAKE_TYPE'); + done(); + }); + + component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; + component.ngOnChanges({searchTerm: component.searchTerm }); + + 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); + expect(element.querySelector('#search_no_result')).not.toBeNull(); done(); }); @@ -150,6 +206,27 @@ describe('AlfrescoSearchAutocompleteComponent', () => { }); }); + it('should display an error if an error is encountered running the search', (done) => { + component.errorEmitter.subscribe(() => { + alfrescoSearchComponentFixture.detectChanges(); + let resultsEl = element.querySelector('[data-automation-id="autocomplete_results"]'); + let errorEl = element.querySelector('[data-automation-id="autocomplete_error_message"]'); + expect(resultsEl).toBeNull(); + expect(errorEl).not.toBeNull(); + expect(errorEl.innerText).toBe('SEARCH.RESULTS.ERROR'); + done(); + }); + + component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; + component.ngOnChanges({searchTerm: component.searchTerm}); + + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 500, + contentType: 'json', + responseText: errorJson + }); + }); + it('should emit preview when file item clicked', (done) => { component.resultsEmitter.subscribe(x => { alfrescoSearchComponentFixture.detectChanges(); @@ -170,22 +247,23 @@ describe('AlfrescoSearchAutocompleteComponent', () => { }); }); - it('should not emit preview when non-file item is clicked', () => { - spyOn(component, 'onItemClick').and.stub(); - - component.ngOnChanges({searchTerm: { currentValue: 'searchTerm', previousValue: ''} }); - - component.preview.subscribe(e => { - expect(e.value).toBe(component.results[0]); + it('should not emit preview if a non-file item is clicked', (done) => { + spyOn(component.preview, 'emit'); + component.resultsEmitter.subscribe(x => { + alfrescoSearchComponentFixture.detectChanges(); + element.querySelector('#result_row_0').click(); + expect(component.preview.emit).not.toHaveBeenCalled(); + done(); }); + component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; + component.ngOnChanges({searchTerm: component.searchTerm}); + jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, contentType: 'json', - responseText: result + responseText: folderResult }); - - expect(component.onItemClick).not.toHaveBeenCalled(); }); }); diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts index 65e552d651..6d43ed470f 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts @@ -48,6 +48,9 @@ export class AlfrescoSearchAutocompleteComponent implements OnChanges { @Output() resultsEmitter = new EventEmitter(); + @Output() + errorEmitter = new EventEmitter(); + constructor(private alfrescoSearchService: AlfrescoSearchService, private translate: AlfrescoTranslationService, private alfrescoThumbnailService: AlfrescoThumbnailService) { @@ -80,6 +83,7 @@ export class AlfrescoSearchAutocompleteComponent implements OnChanges { error => { this.results = null; this.errorMessage = error; + this.errorEmitter.emit(error); } ); } From f0fa43e2ee4e657f4e0b7d80baf322c088f49706 Mon Sep 17 00:00:00 2001 From: Will Abson Date: Fri, 23 Sep 2016 18:23:25 +0100 Subject: [PATCH 04/16] More tests for search (results) component Refs #737, #363 --- .../alfresco-search.component.spec.ts | 106 ++++++++++++++---- .../components/alfresco-search.component.ts | 4 + 2 files changed, 90 insertions(+), 20 deletions(-) diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts index b1c8e34a6a..01190c0528 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts @@ -48,7 +48,7 @@ describe('AlfrescoSearchComponent', () => { name: 'MyDoc', isFile: true, content: { - mimetype: 'text/plain' + mimeType: 'text/plain' }, createdByUser: { displayName: 'John Doe' @@ -62,12 +62,43 @@ describe('AlfrescoSearchComponent', () => { } }; + let folderResult = { + list: { + entries: [ + { + entry: { + id: '123', + name: 'MyFolder', + isFile : false, + isFolder : true, + createdByUser: { + displayName: 'John Doe' + }, + modifiedByUser: { + displayName: 'John Doe' + } + } + } + ] + } + }; + let noResult = { list: { entries: [] } }; + let errorJson = { + error: { + errorKey: 'Search failed', + statusCode: 400, + briefSummary: '08220082 search failed', + stackTrace: 'For security reasons the stack trace is no longer displayed, but the property is kept for previous versions.', + descriptionURL: 'https://api-explorer.alfresco.com' + } + }; + beforeEachProviders(() => { return [ { provide: PLATFORM_PIPES, useValue: AlfrescoPipeTranslate, multi: true }, @@ -152,11 +183,10 @@ describe('AlfrescoSearchComponent', () => { }); }); - 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); + expect(element.querySelector('#search_no_result')).not.toBeNull(); done(); }); @@ -169,31 +199,67 @@ describe('AlfrescoSearchComponent', () => { responseText: noResult }); }); + + it('should display an error if an error is encountered running the search', (done) => { + component.errorEmitter.subscribe(() => { + alfrescoSearchComponentFixture.detectChanges(); + let resultsEl = element.querySelector('[data-automation-id="search_result_table"]'); + let errorEl = element.querySelector('[data-automation-id="search_error_message"]'); + expect(resultsEl).toBeNull(); + expect(errorEl).not.toBeNull(); + expect(errorEl.innerText).toBe('SEARCH.RESULTS.ERROR'); + done(); + }); + + component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; + component.ngOnChanges({searchTerm: component.searchTerm}); + + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 500, + contentType: 'json', + responseText: errorJson + }); + }); }); describe('search result actions', () => { - 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]); + it('should emit preview when file item clicked', (done) => { + component.resultsEmitter.subscribe(() => { + alfrescoSearchComponentFixture.detectChanges(); + element.querySelector('#result_row_0').click(); }); + component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; + component.ngOnChanges({searchTerm: component.searchTerm}); + jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, - contentType: 'text/plain', - responseText: '
' + contentType: 'json', + responseText: result + }); + + component.preview.subscribe(e => { + done(); + }); + }); + + it('should not emit preview when non-file item is clicked', (done) => { + spyOn(component.preview, 'emit'); + component.resultsEmitter.subscribe(x => { + alfrescoSearchComponentFixture.detectChanges(); + element.querySelector('#result_row_0').click(); + expect(component.preview.emit).not.toHaveBeenCalled(); + done(); + }); + + component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; + component.ngOnChanges({searchTerm: component.searchTerm}); + + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + contentType: 'json', + responseText: folderResult }); }); }); diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts index 6930c03851..399fdb4ae2 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts @@ -42,6 +42,9 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit { @Output() resultsEmitter = new EventEmitter(); + @Output() + errorEmitter = new EventEmitter(); + results: any; errorMessage; @@ -119,6 +122,7 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit { error => { this.results = null; this.errorMessage = error; + this.errorEmitter.emit(error); } ); } From dc4a9722d2ea017ef01c69d6ccadecc8a68c745f Mon Sep 17 00:00:00 2001 From: Will Abson Date: Fri, 23 Sep 2016 18:35:41 +0100 Subject: [PATCH 05/16] Update README with new output names and fix typos Refs #737, 363 --- ng2-components/ng2-alfresco-search/README.md | 23 ++++++++++---------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/ng2-components/ng2-alfresco-search/README.md b/ng2-components/ng2-alfresco-search/README.md index e1e6479985..9bcff08f8e 100644 --- a/ng2-components/ng2-alfresco-search/README.md +++ b/ng2-components/ng2-alfresco-search/README.md @@ -91,7 +91,8 @@ Also make sure you include these dependencies in your .html page: ```html + (searchChange)="onSearchChange($event);" + (searchSubmit)="onSearchSubmit($event);"> ``` @@ -116,7 +117,7 @@ import { @Component({ selector: 'alfresco-search-demo', template: ` - +
Authentication failed to ip {{ host }} @@ -141,11 +142,15 @@ class SearchDemo implements OnInit { translation.addTranslationFolder(); } - searchTermChange(event) { + onSearchChange(event) { console.log('Search term changed', event); this.searchTerm = event.value; } + onSearchSubmit(event) { + console.log('Search submitted', event); + } + ngOnInit() { this.login(); } @@ -165,7 +170,8 @@ bootstrap(SearchDemo, [ ``` #### Events -**searchChange**: Emitted when the search term is changed and the form submitted, provided that the term is at least three characters in length
+**searchChange**: Emitted when the search term is changed. The search term is provided in the 'value' property of the returned object. If the term is at less than three characters in length then the term is truncated to an empty string.
+**searchSubmit**: Emitted when the search form is submitted. The search term is provided in the 'value' property of the returned object.
#### Options @@ -220,7 +226,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 router 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 on the page of if the router does not provide such a parameter then an empty results page will be shown. ```ts @@ -242,7 +248,7 @@ import { @Component({ selector: 'alfresco-search-demo', template: ` - +
Authentication failed to ip {{ host }}
@@ -266,11 +272,6 @@ class SearchDemo implements OnInit { translation.addTranslationFolder(); } - searchTermChange(event) { - console.log('Search term changed', event); - this.searchTerm = event.value; - } - ngOnInit() { this.login(); } From f412871b25938904f1c26640673e0695b4ead25e Mon Sep 17 00:00:00 2001 From: Will Abson Date: Fri, 23 Sep 2016 18:36:39 +0100 Subject: [PATCH 06/16] Add missing tests for search thumbnail service Refs #737, 363 --- .../alfresco-thumbnail.service.spec.ts | 22 +++++++++++++++++-- .../services/alfresco-thumbnail.service.ts | 2 +- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/ng2-components/ng2-alfresco-search/src/services/alfresco-thumbnail.service.spec.ts b/ng2-components/ng2-alfresco-search/src/services/alfresco-thumbnail.service.spec.ts index 2ae14327d0..14441ca6c3 100644 --- a/ng2-components/ng2-alfresco-search/src/services/alfresco-thumbnail.service.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/services/alfresco-thumbnail.service.spec.ts @@ -15,16 +15,29 @@ * limitations under the License. */ +import { describe, beforeEach, beforeEachProviders, inject } from '@angular/core/testing'; import { AlfrescoThumbnailService } from './alfresco-thumbnail.service'; +import { AlfrescoApiService, AlfrescoAuthenticationService, AlfrescoContentService, AlfrescoSettingsService } from 'ng2-alfresco-core'; describe('AlfrescoThumbnailService', () => { let service: AlfrescoThumbnailService; - beforeEach(() => { - service = new AlfrescoThumbnailService(null); + + beforeEachProviders(() => { + return [ + AlfrescoApiService, + AlfrescoAuthenticationService, + AlfrescoContentService, + AlfrescoSettingsService, + AlfrescoThumbnailService + ]; }); + beforeEach(inject([AlfrescoThumbnailService], (thumbnailService: AlfrescoThumbnailService) => { + service = thumbnailService; + })); + it('should return the correct icon for a plain text file', () => { expect(service.getMimeTypeIcon('text/plain')).toBe('ft_ic_document.svg'); }); @@ -41,4 +54,9 @@ describe('AlfrescoThumbnailService', () => { expect(service.getMimeTypeIcon('x-unknown/yyy')).toBe('ft_ic_miscellaneous.svg'); }); + it('should return the thumbnail URL for a content item', () => { + spyOn(service.contentService, 'getDocumentThumbnailUrl').and.returnValue('/fake-thumbnail.png'); + expect(service.getDocumentThumbnailUrl({})).toBe('/fake-thumbnail.png'); + }); + }); diff --git a/ng2-components/ng2-alfresco-search/src/services/alfresco-thumbnail.service.ts b/ng2-components/ng2-alfresco-search/src/services/alfresco-thumbnail.service.ts index 593f2c8921..6cec75e9e4 100644 --- a/ng2-components/ng2-alfresco-search/src/services/alfresco-thumbnail.service.ts +++ b/ng2-components/ng2-alfresco-search/src/services/alfresco-thumbnail.service.ts @@ -50,7 +50,7 @@ export class AlfrescoThumbnailService { 'application/vnd.apple.numbers': 'ft_ic_spreadsheet' }; - constructor(private contentService: AlfrescoContentService) { + constructor(public contentService: AlfrescoContentService) { } /** From 969d961e23d7387bcd42172341ebb86864df2e92 Mon Sep 17 00:00:00 2001 From: Will Abson Date: Fri, 23 Sep 2016 18:37:26 +0100 Subject: [PATCH 07/16] Fix width and simplify markup in 'no results found' message Refs #737 --- .../src/components/alfresco-search.component.css | 1 - .../src/components/alfresco-search.component.html | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.css b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.css index eb625a5c99..5f087e32c3 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.css +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.css @@ -3,7 +3,6 @@ text-align: left; } :host .mdl-data-table td { - max-width: 0; white-space: nowrap; } :host .mdl-data-table td.col-mimetype-icon { diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.html b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.html index 2c9fcc4a50..224ab2ec98 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.html +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.html @@ -31,9 +31,7 @@ class="mdl-data-table mdl-js-data-table mdl-shadow--2dp full-width"> - -
{{ 'SEARCH.RESULTS.NONE' | translate:{searchTerm: searchTerm} }}
- + {{ 'SEARCH.RESULTS.NONE' | translate:{searchTerm: searchTerm} }} From 8df2b08b31637b1ef4db25cf1c0193a3e9f6600b Mon Sep 17 00:00:00 2001 From: Will Abson Date: Thu, 29 Sep 2016 17:08:13 +0100 Subject: [PATCH 08/16] Fix up search component and search thumbnail service tests Refs #737 --- .../alfresco-search.component.spec.ts | 173 +++++++++--------- .../components/alfresco-search.component.ts | 5 +- .../alfresco-thumbnail.service.spec.ts | 16 +- 3 files changed, 99 insertions(+), 95 deletions(-) diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts index 01190c0528..f3b1b11e8f 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts @@ -15,9 +15,8 @@ * limitations under the License. */ -import { PLATFORM_PIPES, ReflectiveInjector } from '@angular/core'; -import { it, describe, expect, inject, beforeEachProviders, beforeEach } from '@angular/core/testing'; -import { TestComponentBuilder } from '@angular/compiler/testing'; +import { ReflectiveInjector, SimpleChange } from '@angular/core'; +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs/Rx'; import { AlfrescoSearchComponent } from './alfresco-search.component'; @@ -30,14 +29,13 @@ import { AlfrescoAuthenticationService, AlfrescoContentService, AlfrescoTranslationService, - AlfrescoPipeTranslate + CoreModule } from 'ng2-alfresco-core'; -declare let jasmine: any; - describe('AlfrescoSearchComponent', () => { - let alfrescoSearchComponentFixture, element, component; + let alfrescoSearchComponentFixture: ComponentFixture, element: HTMLElement; + let component: AlfrescoSearchComponent; let result = { list: { @@ -99,34 +97,28 @@ describe('AlfrescoSearchComponent', () => { } }; - beforeEachProviders(() => { - return [ - { provide: PLATFORM_PIPES, useValue: AlfrescoPipeTranslate, multi: true }, - AlfrescoSearchService, - {provide: AlfrescoTranslationService, useClass: TranslationMock}, - AlfrescoThumbnailService, - AlfrescoSettingsService, - AlfrescoApiService, - AlfrescoAuthenticationService, - AlfrescoContentService - ]; - }); - - beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { - return tcb - .createAsync(AlfrescoSearchComponent) - .then(fixture => { - jasmine.Ajax.install(); - alfrescoSearchComponentFixture = fixture; - element = alfrescoSearchComponentFixture.nativeElement; - component = alfrescoSearchComponentFixture.componentInstance; - }); + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + CoreModule + ], + declarations: [ AlfrescoSearchComponent ], // declare the test component + providers: [ + AlfrescoSearchService, + {provide: AlfrescoTranslationService, useClass: TranslationMock}, + AlfrescoThumbnailService, + AlfrescoSettingsService, + AlfrescoApiService, + AlfrescoAuthenticationService, + AlfrescoContentService + ] + }).compileComponents().then(() => { + alfrescoSearchComponentFixture = TestBed.createComponent(AlfrescoSearchComponent); + component = alfrescoSearchComponentFixture.componentInstance; + element = alfrescoSearchComponentFixture.nativeElement; + }); })); - afterEach(() => { - jasmine.Ajax.uninstall(); - }); - it('should not have a search term by default', () => { let search = new AlfrescoSearchComponent(null, null, null, null); expect(search).toBeDefined(); @@ -144,100 +136,114 @@ describe('AlfrescoSearchComponent', () => { it('should have a null search term if no query param provided via RouteParams', () => { let injector = ReflectiveInjector.resolveAndCreate([ + AlfrescoSearchService, + AlfrescoAuthenticationService, + AlfrescoSettingsService, + AlfrescoApiService, { provide: ActivatedRoute, useValue: { params: Observable.from([{}]) } } ]); - let search = new AlfrescoSearchComponent(null, null, null, injector.get(ActivatedRoute)); + let search = new AlfrescoSearchComponent(injector.get(AlfrescoSearchService), null, null, injector.get(ActivatedRoute)); search.ngOnInit(); expect(search.searchTerm).toBeNull(); }); - it('should setup i18n folder', () => { - - let translation = jasmine.createSpyObj('AlfrescoTranslationService', [ - 'addTranslationFolder' - ]); - - let search = new AlfrescoSearchComponent(null, translation, null, null); - expect(search).toBeDefined(); - expect(translation.addTranslationFolder).toHaveBeenCalledWith('node_modules/ng2-alfresco-search/dist/src'); - }); + // it('should setup i18n folder', () => { + // let translationService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoTranslationService); + // spyOn(translationService, 'addTranslationFolder'); + // expect(translationService.addTranslationFolder).toHaveBeenCalledWith('node_modules/ng2-alfresco-search/dist/src'); + // }); describe('Rendering search results', () => { it('should display search results when a search term is provided', (done) => { - component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; - component.ngOnChanges({searchTerm: component.searchTerm}); + let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + spyOn(searchService, 'getSearchNodesPromise') + .and.returnValue(Promise.resolve(result)); component.resultsEmitter.subscribe(x => { alfrescoSearchComponentFixture.detectChanges(); + expect(searchService.getSearchNodesPromise).toHaveBeenCalled(); + expect(element.querySelector('#result_user_0')).not.toBeNull(); expect(element.querySelector('#result_user_0').innerHTML).toBe('John Doe'); expect(element.querySelector('#result_name_0').innerHTML).toBe('MyDoc'); done(); }); - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200, - contentType: 'json', - responseText: result - }); + component.searchTerm = 'searchTerm'; + component.ngOnInit(); }); it('should display no result if no result are returned', (done) => { + + let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + spyOn(searchService, 'getSearchNodesPromise') + .and.returnValue(Promise.resolve(noResult)); + component.resultsEmitter.subscribe(x => { alfrescoSearchComponentFixture.detectChanges(); expect(element.querySelector('#search_no_result')).not.toBeNull(); done(); }); - component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; - component.ngOnChanges({searchTerm: component.searchTerm}); - - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200, - contentType: 'json', - responseText: noResult - }); + component.searchTerm = 'searchTerm'; + component.ngOnInit(); }); it('should display an error if an error is encountered running the search', (done) => { + + let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + spyOn(searchService, 'getSearchNodesPromise') + .and.returnValue(Promise.reject(errorJson)); + component.errorEmitter.subscribe(() => { alfrescoSearchComponentFixture.detectChanges(); let resultsEl = element.querySelector('[data-automation-id="search_result_table"]'); let errorEl = element.querySelector('[data-automation-id="search_error_message"]'); expect(resultsEl).toBeNull(); expect(errorEl).not.toBeNull(); - expect(errorEl.innerText).toBe('SEARCH.RESULTS.ERROR'); + expect((errorEl).innerText).toBe('SEARCH.RESULTS.ERROR'); done(); }); - component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; - component.ngOnChanges({searchTerm: component.searchTerm}); + component.searchTerm = 'searchTerm'; + component.ngOnInit(); + }); - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 500, - contentType: 'json', - responseText: errorJson + it('should update search results when the search term input is changed', (done) => { + + let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + spyOn(searchService, 'getSearchNodesPromise') + .and.returnValue(Promise.resolve(result)); + + component.resultsEmitter.subscribe(x => { + alfrescoSearchComponentFixture.detectChanges(); + expect(searchService.getSearchNodesPromise).toHaveBeenCalledWith('searchTerm2'); + expect(element.querySelector('#result_user_0')).not.toBeNull(); + expect(element.querySelector('#result_user_0').innerHTML).toBe('John Doe'); + expect(element.querySelector('#result_name_0').innerHTML).toBe('MyDoc'); + done(); }); + + component.ngOnChanges({searchTerm: new SimpleChange('', 'searchTerm2')}); }); }); describe('search result actions', () => { it('should emit preview when file item clicked', (done) => { + + let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + spyOn(searchService, 'getSearchNodesPromise') + .and.returnValue(Promise.resolve(result)); + component.resultsEmitter.subscribe(() => { alfrescoSearchComponentFixture.detectChanges(); - element.querySelector('#result_row_0').click(); + ( element.querySelector('#result_row_0')).click(); }); - component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; - component.ngOnChanges({searchTerm: component.searchTerm}); - - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200, - contentType: 'json', - responseText: result - }); + component.searchTerm = 'searchTerm'; + component.ngOnInit(); component.preview.subscribe(e => { done(); @@ -245,22 +251,21 @@ describe('AlfrescoSearchComponent', () => { }); it('should not emit preview when non-file item is clicked', (done) => { + + let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + spyOn(searchService, 'getSearchNodesPromise') + .and.returnValue(Promise.resolve(folderResult)); + spyOn(component.preview, 'emit'); component.resultsEmitter.subscribe(x => { alfrescoSearchComponentFixture.detectChanges(); - element.querySelector('#result_row_0').click(); + ( element.querySelector('#result_row_0')).click(); expect(component.preview.emit).not.toHaveBeenCalled(); done(); }); - component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; - component.ngOnChanges({searchTerm: component.searchTerm}); - - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200, - contentType: 'json', - responseText: folderResult - }); + component.searchTerm = 'searchTerm'; + component.ngOnInit(); }); }); diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts index 399fdb4ae2..3633941136 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts @@ -76,7 +76,8 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit { ngOnChanges(changes: SimpleChanges): void { if (changes['searchTerm']) { - this.displaySearchResults(changes['searchTerm'].currentValue); + this.searchTerm = changes['searchTerm'].currentValue; + this.displaySearchResults(this.searchTerm); } } @@ -110,7 +111,7 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit { * @param searchTerm Search query entered by user */ public displaySearchResults(searchTerm): void { - if (searchTerm !== null) { + if (searchTerm !== null && this.alfrescoSearchService !== null) { this.alfrescoSearchService .getLiveSearchResults(searchTerm) .subscribe( diff --git a/ng2-components/ng2-alfresco-search/src/services/alfresco-thumbnail.service.spec.ts b/ng2-components/ng2-alfresco-search/src/services/alfresco-thumbnail.service.spec.ts index 14441ca6c3..459a26c3c7 100644 --- a/ng2-components/ng2-alfresco-search/src/services/alfresco-thumbnail.service.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/services/alfresco-thumbnail.service.spec.ts @@ -15,28 +15,26 @@ * limitations under the License. */ -import { describe, beforeEach, beforeEachProviders, inject } from '@angular/core/testing'; +import { ReflectiveInjector } from '@angular/core'; import { AlfrescoThumbnailService } from './alfresco-thumbnail.service'; import { AlfrescoApiService, AlfrescoAuthenticationService, AlfrescoContentService, AlfrescoSettingsService } from 'ng2-alfresco-core'; describe('AlfrescoThumbnailService', () => { + let injector: ReflectiveInjector; let service: AlfrescoThumbnailService; - - beforeEachProviders(() => { - return [ + beforeEach(() => { + injector = ReflectiveInjector.resolveAndCreate([ AlfrescoApiService, AlfrescoAuthenticationService, AlfrescoContentService, AlfrescoSettingsService, AlfrescoThumbnailService - ]; - }); + ]); - beforeEach(inject([AlfrescoThumbnailService], (thumbnailService: AlfrescoThumbnailService) => { - service = thumbnailService; - })); + service = injector.get(AlfrescoThumbnailService); + }); it('should return the correct icon for a plain text file', () => { expect(service.getMimeTypeIcon('text/plain')).toBe('ft_ic_document.svg'); From 420b11449ca1fab8c9a1160f7c2170ed66cff5d0 Mon Sep 17 00:00:00 2001 From: Will Abson Date: Thu, 29 Sep 2016 17:12:35 +0100 Subject: [PATCH 09/16] Fix up Karma warnings --- ng2-components/ng2-alfresco-search/karma.conf.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/ng2-components/ng2-alfresco-search/karma.conf.js b/ng2-components/ng2-alfresco-search/karma.conf.js index 2aa3ff5612..7d786304a2 100644 --- a/ng2-components/ng2-alfresco-search/karma.conf.js +++ b/ng2-components/ng2-alfresco-search/karma.conf.js @@ -34,7 +34,6 @@ module.exports = function (config) { 'node_modules/alfresco-js-api/dist/alfresco-js-api.js', {pattern: 'node_modules/ng2-translate/**/*.js', included: false, watched: false}, - {pattern: 'node_modules/ng2-translate/**/*.js.map', included: false, watched: false}, 'karma-test-shim.js', @@ -44,18 +43,8 @@ module.exports = function (config) { {pattern: 'dist/**/*.css', included: true, served: true, watched: true}, // ng2-components - { pattern: 'node_modules/ng2-activiti-form/dist/**/*.js', included: false, served: true, watched: false }, - { pattern: 'node_modules/ng2-activiti-processlist/dist/**/*.js', included: false, served: true, watched: false }, - { pattern: 'node_modules/ng2-activiti-tasklist/dist/**/*.js', included: false, served: true, watched: false }, { pattern: 'node_modules/ng2-alfresco-core/dist/**/*.js', included: false, served: true, watched: false }, - { pattern: 'node_modules/ng2-alfresco-datatable/dist/**/*.js', included: false, served: true, watched: false }, - { pattern: 'node_modules/ng2-alfresco-documentlist/dist/**/*.js', included: false, served: true, watched: false }, - { pattern: 'node_modules/ng2-alfresco-login/dist/**/*.js', included: false, served: true, watched: false }, { pattern: 'node_modules/ng2-alfresco-search/dist/**/*.js', included: false, served: true, watched: false }, - { pattern: 'node_modules/ng2-alfresco-tag/dist/**/*.js', included: false, served: true, watched: false }, - { pattern: 'node_modules/ng2-alfresco-upload/dist/**/*.js', included: false, served: true, watched: false }, - { pattern: 'node_modules/ng2-alfresco-viewer/dist/**/*.js', included: false, served: true, watched: false }, - { pattern: 'node_modules/ng2-alfresco-webscript/dist/**/*.js', included: false, served: true, watched: false }, // paths to support debugging with source maps in dev tools {pattern: 'src/**/*.ts', included: false, watched: false}, From 28783322fdf4b4c857eb4273e01b6b0de65c7683 Mon Sep 17 00:00:00 2001 From: Will Abson Date: Mon, 3 Oct 2016 12:51:51 +0100 Subject: [PATCH 10/16] Re-add search control tests working for final NG 2.0.0 Refs #737 --- ng2-components/ng2-alfresco-search/index.ts | 1 + ...esco-search-autocomplete.component.spec.ts | 180 ++++++++---------- .../alfresco-search-autocomplete.component.ts | 4 +- .../alfresco-search-control.component.spec.ts | 100 +++++----- .../alfresco-search-control.component.ts | 33 ++-- 5 files changed, 163 insertions(+), 155 deletions(-) diff --git a/ng2-components/ng2-alfresco-search/index.ts b/ng2-components/ng2-alfresco-search/index.ts index c3d7b740af..2953569171 100644 --- a/ng2-components/ng2-alfresco-search/index.ts +++ b/ng2-components/ng2-alfresco-search/index.ts @@ -29,6 +29,7 @@ export * from './src/services/alfresco-search.service'; export * from './src/services/alfresco-thumbnail.service'; export * from './src/components/alfresco-search.component'; export * from './src/components/alfresco-search-control.component'; +export * from './src/components/alfresco-search-autocomplete.component'; export const ALFRESCO_SEARCH_DIRECTIVES: [any] = [ AlfrescoSearchComponent, diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts index a2eee1014e..6b9340f131 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts @@ -15,10 +15,7 @@ * limitations under the License. */ -/* -import { it, describe, expect, inject, beforeEachProviders, beforeEach, afterEach } from '@angular/core/testing'; -import { PLATFORM_PIPES } from '@angular/core'; -import { TestComponentBuilder } from '@angular/compiler/testing'; +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; import { AlfrescoSearchAutocompleteComponent } from './alfresco-search-autocomplete.component'; import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service'; import { TranslationMock } from './../assets/translation.service.mock'; @@ -29,14 +26,13 @@ import { AlfrescoAuthenticationService, AlfrescoContentService, AlfrescoTranslationService, - AlfrescoPipeTranslate + CoreModule } from 'ng2-alfresco-core'; -declare let jasmine: any; - describe('AlfrescoSearchAutocompleteComponent', () => { - let alfrescoSearchComponentFixture, element, component; + let alfrescoSearchComponentFixture: ComponentFixture, element: HTMLElement; + let component: AlfrescoSearchAutocompleteComponent; let result = { list: { @@ -98,47 +94,41 @@ describe('AlfrescoSearchAutocompleteComponent', () => { } }; - beforeEachProviders(() => { - return [ - { provide: PLATFORM_PIPES, useValue: AlfrescoPipeTranslate, multi: true }, - {provide: AlfrescoTranslationService, useClass: TranslationMock}, - AlfrescoThumbnailService, - AlfrescoSettingsService, - AlfrescoApiService, - AlfrescoAuthenticationService, - AlfrescoContentService, - AlfrescoSearchService - ]; - }); - - beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { - return tcb - .createAsync(AlfrescoSearchAutocompleteComponent) - .then(fixture => { - jasmine.Ajax.install(); - alfrescoSearchComponentFixture = fixture; - element = alfrescoSearchComponentFixture.nativeElement; - component = alfrescoSearchComponentFixture.componentInstance; - }); + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + CoreModule + ], + declarations: [ AlfrescoSearchAutocompleteComponent ], // declare the test component + providers: [ + {provide: AlfrescoTranslationService, useClass: TranslationMock}, + AlfrescoThumbnailService, + AlfrescoSettingsService, + AlfrescoApiService, + AlfrescoAuthenticationService, + AlfrescoContentService, + AlfrescoSearchService + ] + }).compileComponents().then(() => { + alfrescoSearchComponentFixture = TestBed.createComponent(AlfrescoSearchAutocompleteComponent); + component = alfrescoSearchComponentFixture.componentInstance; + element = alfrescoSearchComponentFixture.nativeElement; + }); })); - afterEach(() => { - jasmine.Ajax.uninstall(); - }); - - it('should setup i18n folder', () => { - let translation = jasmine.createSpyObj('AlfrescoTranslationService', [ - 'addTranslationFolder' - ]); - let search = new AlfrescoSearchAutocompleteComponent(null, translation, null); - expect(search).toBeDefined(); - - }); + // it('should setup i18n folder', () => { + // let translation = jasmine.createSpyObj('AlfrescoTranslationService', [ + // 'addTranslationFolder' + // ]); + // let search = new AlfrescoSearchAutocompleteComponent(null, translation, null); + // expect(search).toBeDefined(); + // + // }); it('should display search results when a search term is provided', () => { let searchTerm = { currentValue: 'customSearchTerm', previousValue: ''}; spyOn(component, 'displaySearchResults').and.stub(); - component.searchTerm = searchTerm; + component.searchTerm = 'searchTerm'; component.ngOnChanges({ searchTerm: searchTerm }); @@ -147,6 +137,11 @@ describe('AlfrescoSearchAutocompleteComponent', () => { }); it('should display the returned search results', (done) => { + + let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + spyOn(searchService, 'getSearchNodesPromise') + .and.returnValue(Promise.resolve(result)); + component.resultsEmitter.subscribe(x => { alfrescoSearchComponentFixture.detectChanges(); expect( element.querySelector('#result_user_0').innerHTML).toBe('John Doe'); @@ -154,93 +149,84 @@ describe('AlfrescoSearchAutocompleteComponent', () => { done(); }); - component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; - component.ngOnChanges({searchTerm: component.searchTerm }); - - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200, - contentType: 'json', - responseText: result - }); + component.searchTerm = 'searchTerm'; + component.ngOnChanges({searchTerm: { currentValue: 'searchTerm', previousValue: ''} }); }); it('should display the correct thumbnail for result items', (done) => { + let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + spyOn(searchService, 'getSearchNodesPromise') + .and.returnValue(Promise.resolve(result)); + component.baseComponentPath = 'http://localhost'; - spyOn(component.alfrescoThumbnailService, 'getMimeTypeIcon').and.returnValue('fake-type-icon.svg'); - spyOn(component.alfrescoThumbnailService, 'getMimeTypeKey').and.returnValue('FAKE_TYPE'); + + let thumbnailService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoThumbnailService); + spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue('fake-type-icon.svg'); + spyOn(thumbnailService, 'getMimeTypeKey').and.returnValue('FAKE_TYPE'); component.resultsEmitter.subscribe(() => { alfrescoSearchComponentFixture.detectChanges(); - let imgEl = element.querySelector('#result_row_0 img'); + let imgEl = element.querySelector('#result_row_0 img'); expect(imgEl).not.toBeNull(); expect(imgEl.src).toBe('http://localhost/img/fake-type-icon.svg'); expect(imgEl.alt).toBe('SEARCH.ICONS.FAKE_TYPE'); done(); }); - component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; - component.ngOnChanges({searchTerm: component.searchTerm }); - - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200, - contentType: 'json', - responseText: result - }); + component.searchTerm = 'searchTerm'; + component.ngOnChanges({searchTerm: { currentValue: 'searchTerm', previousValue: ''} }); }); it('should display no result if no result are returned', (done) => { + + let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + spyOn(searchService, 'getSearchNodesPromise') + .and.returnValue(Promise.resolve(noResult)); + component.resultsEmitter.subscribe(x => { alfrescoSearchComponentFixture.detectChanges(); expect(element.querySelector('#search_no_result')).not.toBeNull(); done(); }); - component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; - component.ngOnChanges({searchTerm: component.searchTerm}); - - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200, - contentType: 'json', - responseText: noResult - }); + component.searchTerm = 'searchTerm'; + component.ngOnChanges({searchTerm: { currentValue: 'searchTerm', previousValue: ''}}); }); it('should display an error if an error is encountered running the search', (done) => { + + let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + spyOn(searchService, 'getSearchNodesPromise') + .and.returnValue(Promise.reject(errorJson)); + component.errorEmitter.subscribe(() => { alfrescoSearchComponentFixture.detectChanges(); let resultsEl = element.querySelector('[data-automation-id="autocomplete_results"]'); - let errorEl = element.querySelector('[data-automation-id="autocomplete_error_message"]'); + let errorEl = element.querySelector('[data-automation-id="autocomplete_error_message"]'); expect(resultsEl).toBeNull(); expect(errorEl).not.toBeNull(); expect(errorEl.innerText).toBe('SEARCH.RESULTS.ERROR'); done(); }); - component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; - component.ngOnChanges({searchTerm: component.searchTerm}); - - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 500, - contentType: 'json', - responseText: errorJson - }); + component.searchTerm = 'searchTerm'; + component.ngOnChanges({searchTerm: { currentValue: 'searchTerm', previousValue: ''}}); }); it('should emit preview when file item clicked', (done) => { + + let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + spyOn(searchService, 'getSearchNodesPromise') + .and.returnValue(Promise.resolve(result)); + component.resultsEmitter.subscribe(x => { alfrescoSearchComponentFixture.detectChanges(); - element.querySelector('#result_row_0').click(); + ( element.querySelector('#result_row_0')).click(); }); - component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; - component.ngOnChanges({searchTerm: component.searchTerm}); - - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200, - contentType: 'json', - responseText: result - }); + component.searchTerm = 'searchTerm'; + component.ngOnChanges({searchTerm: { currentValue: 'searchTerm', previousValue: ''}}); component.preview.subscribe(e => { done(); @@ -248,23 +234,21 @@ describe('AlfrescoSearchAutocompleteComponent', () => { }); it('should not emit preview if a non-file item is clicked', (done) => { + + let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + spyOn(searchService, 'getSearchNodesPromise') + .and.returnValue(Promise.resolve(folderResult)); + spyOn(component.preview, 'emit'); component.resultsEmitter.subscribe(x => { alfrescoSearchComponentFixture.detectChanges(); - element.querySelector('#result_row_0').click(); + ( element.querySelector('#result_row_0')).click(); expect(component.preview.emit).not.toHaveBeenCalled(); done(); }); - component.searchTerm = { currentValue: 'searchTerm', previousValue: ''}; - component.ngOnChanges({searchTerm: component.searchTerm}); - - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200, - contentType: 'json', - responseText: folderResult - }); + component.searchTerm = 'searchTerm'; + component.ngOnChanges({searchTerm: { currentValue: 'searchTerm', previousValue: ''}}); }); }); -*/ diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts index 6d43ed470f..f4e7f75274 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts @@ -73,8 +73,8 @@ export class AlfrescoSearchAutocompleteComponent implements OnChanges { public displaySearchResults(searchTerm) { if (searchTerm !== null && searchTerm !== '') { this.alfrescoSearchService - .getLiveSearchResults(searchTerm) - .subscribe( + .getSearchNodesPromise(searchTerm) + .then( results => { this.results = results.list.entries; this.errorMessage = null; diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts index 258e7e4202..c8c6bd9d1f 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts @@ -15,11 +15,10 @@ * limitations under the License. */ -/* -import { provide, PLATFORM_PIPES } from '@angular/core'; -import { it, describe, expect, inject, beforeEachProviders, beforeEach } from '@angular/core/testing'; -import { TestComponentBuilder } from '@angular/compiler/testing'; +import { SimpleChange } from '@angular/core'; +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; import { AlfrescoSearchControlComponent } from './alfresco-search-control.component'; +import { AlfrescoSearchAutocompleteComponent } from './alfresco-search-autocomplete.component'; import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service'; import { TranslationMock } from './../assets/translation.service.mock'; import { @@ -28,53 +27,67 @@ import { AlfrescoAuthenticationService, AlfrescoContentService, AlfrescoTranslationService, - AlfrescoPipeTranslate + CoreModule } from 'ng2-alfresco-core'; import { AlfrescoSearchService } from '../services/alfresco-search.service'; describe('AlfrescoSearchControlComponent', () => { - let alfrescoSearchControlComponentFixture, element, component; + let alfrescoSearchControlComponentFixture: ComponentFixture; + let component: AlfrescoSearchControlComponent, element: HTMLElement; - beforeEachProviders(() => { - return [ - { provide: PLATFORM_PIPES, useValue: AlfrescoPipeTranslate, multi: true }, - AlfrescoSearchService, - provide(AlfrescoTranslationService, {useClass: TranslationMock}), - AlfrescoThumbnailService, - AlfrescoSettingsService, - AlfrescoApiService, - AlfrescoAuthenticationService, - AlfrescoContentService - ]; - }); - - beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { - return tcb - .createAsync(AlfrescoSearchControlComponent) - .then(fixture => { - alfrescoSearchControlComponentFixture = fixture; - element = alfrescoSearchControlComponentFixture.nativeElement; - component = alfrescoSearchControlComponentFixture.componentInstance; - }); + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + CoreModule + ], + declarations: [ + AlfrescoSearchControlComponent, + AlfrescoSearchAutocompleteComponent + ], + providers: [ + {provide: AlfrescoTranslationService, useClass: TranslationMock}, + AlfrescoThumbnailService, + AlfrescoSettingsService, + AlfrescoApiService, + AlfrescoAuthenticationService, + AlfrescoContentService, + AlfrescoSearchService + ] + }).compileComponents().then(() => { + alfrescoSearchControlComponentFixture = TestBed.createComponent(AlfrescoSearchControlComponent); + component = alfrescoSearchControlComponentFixture.componentInstance; + element = alfrescoSearchControlComponentFixture.nativeElement; + }); })); it('should setup i18n folder', () => { - let translation = jasmine.createSpyObj('AlfrescoTranslationService', [ - 'addTranslationFolder' - ]); - - let alfrescoSearchControlComponent = new AlfrescoSearchControlComponent(translation); - expect(alfrescoSearchControlComponent).toBeDefined(); + let translationService = alfrescoSearchControlComponentFixture.debugElement.injector.get(AlfrescoTranslationService); + spyOn(translationService, 'addTranslationFolder'); + alfrescoSearchControlComponentFixture.detectChanges(); + expect(translationService.addTranslationFolder) + .toHaveBeenCalledWith('node_modules/ng2-alfresco-search/dist/src'); }); - it('should emit searchChange when search term changed', () => { - alfrescoSearchControlComponentFixture.componentInstance.searchTerm = 'customSearchTerm'; - alfrescoSearchControlComponentFixture.detectChanges(); + it('should emit searchChange when search term input changed', (done) => { alfrescoSearchControlComponentFixture.componentInstance.searchChange.subscribe(e => { expect(e.value).toBe('customSearchTerm'); + done(); }); + alfrescoSearchControlComponentFixture.detectChanges(); + alfrescoSearchControlComponentFixture.componentInstance.searchTerm = 'customSearchTerm'; + alfrescoSearchControlComponentFixture.componentInstance + .ngOnChanges({'searchTerm': new SimpleChange('', 'customSearchTerm')}); + }); + + it('should emit searchChange when search term changed by user', (done) => { + alfrescoSearchControlComponentFixture.componentInstance.searchChange.subscribe(e => { + expect(e.value).toBe('customSearchTerm211'); + done(); + }); + alfrescoSearchControlComponentFixture.detectChanges(); + component.searchControl.setValue('customSearchTerm211', true); }); describe('Component rendering', () => { @@ -124,9 +137,9 @@ describe('AlfrescoSearchControlComponent', () => { it('should fire a search when a term has been entered', () => { spyOn(component.searchSubmit, 'emit'); alfrescoSearchControlComponentFixture.detectChanges(); - let formEl = element.querySelector('form'); + let formEl: HTMLElement = element.querySelector('form'); component.searchTerm = 'searchTerm1'; - component.searchControl.updateValue('searchTerm1'); + component.searchControl.setValue('searchTerm1', true); alfrescoSearchControlComponentFixture.detectChanges(); formEl.dispatchEvent(new Event('submit')); @@ -140,8 +153,8 @@ describe('AlfrescoSearchControlComponent', () => { it('should not fire a search when no term has been entered', () => { spyOn(component.searchSubmit, 'emit'); alfrescoSearchControlComponentFixture.detectChanges(); - let inputEl = element.querySelector('input[type="text"]'); - let formEl = element.querySelector('form'); + let inputEl: HTMLInputElement = element.querySelector('input[type="text"]'); + let formEl: HTMLElement = element.querySelector('form'); inputEl.value = ''; formEl.dispatchEvent(new Event('submit')); @@ -156,7 +169,7 @@ describe('AlfrescoSearchControlComponent', () => { it('should fire an event when the search box receives focus', () => { spyOn(component.expand, 'emit'); - let inputEl = element.querySelector('input'); + let inputEl: HTMLElement = element.querySelector('input'); inputEl.dispatchEvent(new Event('focus')); expect(component.expand.emit).toHaveBeenCalledWith({ expanded: true @@ -165,7 +178,7 @@ describe('AlfrescoSearchControlComponent', () => { it('should fire an event when the search box loses focus', () => { spyOn(component.expand, 'emit'); - let inputEl = element.querySelector('input'); + let inputEl: HTMLElement = element.querySelector('input'); inputEl.dispatchEvent(new Event('blur')); expect(component.expand.emit).toHaveBeenCalledWith({ expanded: false @@ -176,7 +189,7 @@ describe('AlfrescoSearchControlComponent', () => { () => { spyOn(component.expand, 'emit'); component.expandable = false; - let inputEl = element.querySelector('input'); + let inputEl: HTMLElement = element.querySelector('input'); inputEl.dispatchEvent(new Event('focus')); inputEl.dispatchEvent(new Event('blur')); expect(component.expand.emit).not.toHaveBeenCalled(); @@ -199,4 +212,3 @@ describe('AlfrescoSearchControlComponent', () => { }); }); -*/ diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts index 1432361a88..2737c2162a 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts @@ -16,7 +16,7 @@ */ import { FormControl, Validators } from '@angular/forms'; -import { Component, Input, Output, ElementRef, EventEmitter, ViewChild } from '@angular/core'; +import { Component, Input, Output, OnInit, OnChanges, SimpleChanges, ElementRef, EventEmitter, ViewChild } from '@angular/core'; import { AlfrescoTranslationService } from 'ng2-alfresco-core'; import { SearchTermValidator } from './../forms/search-term-validator'; @@ -28,7 +28,7 @@ declare let __moduleName: string; templateUrl: './alfresco-search-control.component.html', styleUrls: ['./alfresco-search-control.component.css'] }) -export class AlfrescoSearchControlComponent { +export class AlfrescoSearchControlComponent implements OnInit, OnChanges { @Input() searchTerm = ''; @@ -71,20 +71,31 @@ export class AlfrescoSearchControlComponent { this.searchTerm, Validators.compose([Validators.required, SearchTermValidator.minAlphanumericChars(3)]) ); + } + ngOnInit(): void { this.searchControl.valueChanges.map(value => this.searchControl.valid ? value : '') - .debounceTime(400).distinctUntilChanged().subscribe( - (value: string) => { - this.autocompleteSearchTerm = value; - this.searchValid = this.searchControl.valid; - this.searchChange.emit({ - value: value, - valid: this.searchValid - }); + .debounceTime(400).distinctUntilChanged().subscribe((value: string) => { + this.onSearchTermChange(value); } ); - translate.addTranslationFolder('node_modules/ng2-alfresco-search/dist/src'); + this.translate.addTranslationFolder('node_modules/ng2-alfresco-search/dist/src'); + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes.hasOwnProperty('searchTerm')) { + this.searchControl.setValue(changes['searchTerm'].currentValue, true); + } + } + + private onSearchTermChange(value: string): void { + this.autocompleteSearchTerm = value; + this.searchValid = this.searchControl.valid; + this.searchChange.emit({ + value: value, + valid: this.searchValid + }); } getTextFieldClassName(): string { From 8f823cf0e2799f7e2482c0bde19f34b3c10d6362 Mon Sep 17 00:00:00 2001 From: Will Abson Date: Tue, 4 Oct 2016 15:26:47 +0100 Subject: [PATCH 11/16] Update search control component and tests ng2-forms 2.0.0 Refs #737 --- ng2-components/ng2-alfresco-search/index.ts | 5 ++++- .../alfresco-search-control.component.html | 5 ++--- .../alfresco-search-control.component.spec.ts | 7 +++---- .../alfresco-search-control.component.ts | 18 +++++++----------- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/ng2-components/ng2-alfresco-search/index.ts b/ng2-components/ng2-alfresco-search/index.ts index 2953569171..c2ce45856f 100644 --- a/ng2-components/ng2-alfresco-search/index.ts +++ b/ng2-components/ng2-alfresco-search/index.ts @@ -16,6 +16,7 @@ */ import { NgModule, ModuleWithProviders } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { CoreModule } from 'ng2-alfresco-core'; import { AlfrescoSearchService } from './src/services/alfresco-search.service'; @@ -44,7 +45,9 @@ export const ALFRESCO_SEARCH_PROVIDERS: [any] = [ @NgModule({ imports: [ - CoreModule + CoreModule, + FormsModule, + ReactiveFormsModule ], declarations: [ ...ALFRESCO_SEARCH_DIRECTIVES diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.html b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.html index c38ca8884a..faedc3235a 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.html +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.html @@ -1,4 +1,4 @@ -
+
- diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts index ba97dd2c8e..703c811f2b 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts @@ -131,6 +131,80 @@ describe('AlfrescoSearchControlComponent', () => { }); }); + describe('Find as you type', () => { + + let inputEl: HTMLInputElement; + + beforeEach(() => { + inputEl = element.querySelector('input'); + }); + + it('should display a find-as-you-type control by default', () => { + alfrescoSearchControlComponentFixture.detectChanges(); + let autocomplete: Element = element.querySelector('alfresco-search-autocomplete'); + expect(autocomplete).not.toBeNull(); + }); + + it('should make find-as-you-type control hidden initially', () => { + alfrescoSearchControlComponentFixture.detectChanges(); + let autocomplete: Element = element.querySelector('alfresco-search-autocomplete'); + expect(autocomplete.classList.contains('active')).toBe(false); + }); + + it('should make find-as-you-type control visible when search box has focus', () => { + alfrescoSearchControlComponentFixture.detectChanges(); + inputEl.dispatchEvent(new Event('focus')); + alfrescoSearchControlComponentFixture.detectChanges(); + let autocomplete: Element = element.querySelector('alfresco-search-autocomplete'); + expect(autocomplete.classList.contains('active')).toBe(true); + }); + + it('should hide find-as-you-type results when the search box loses focus', (done) => { + alfrescoSearchControlComponentFixture.detectChanges(); + inputEl.dispatchEvent(new Event('focus')); + inputEl.dispatchEvent(new Event('blur')); + window.setTimeout(() => { + alfrescoSearchControlComponentFixture.detectChanges(); + let autocomplete: Element = element.querySelector('alfresco-search-autocomplete'); + expect(autocomplete.classList.contains('active')).toBe(false); + done(); + }, 250); + }); + + it('should hide find-as-you-type results when escape key pressed', () => { + alfrescoSearchControlComponentFixture.detectChanges(); + inputEl.dispatchEvent(new Event('focus')); + inputEl.dispatchEvent(new KeyboardEvent('keyup', { + key: 'Escape' + })); + alfrescoSearchControlComponentFixture.detectChanges(); + let autocomplete: Element = element.querySelector('alfresco-search-autocomplete'); + expect(autocomplete.classList.contains('active')).toBe(false); + }); + + it('should make find-as-you-type control visible again when down arrow is pressed', () => { + alfrescoSearchControlComponentFixture.detectChanges(); + inputEl.dispatchEvent(new Event('focus')); + inputEl.dispatchEvent(new KeyboardEvent('keyup', { + key: 'Escape' + })); + inputEl.dispatchEvent(new KeyboardEvent('keyup', { + key: 'ArrowDown' + })); + alfrescoSearchControlComponentFixture.detectChanges(); + let autocomplete: Element = element.querySelector('alfresco-search-autocomplete'); + expect(autocomplete.classList.contains('active')).toBe(true); + }); + + it('should NOT display a find-as-you-type control when configured not to', () => { + alfrescoSearchControlComponentFixture.componentInstance.autocompleteEnabled = false; + alfrescoSearchControlComponentFixture.detectChanges(); + let autocomplete: Element = element.querySelector('alfresco-search-autocomplete'); + expect(autocomplete).toBeNull(); + }); + + }); + describe('search submit', () => { it('should fire a search when a term has been entered', () => { diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts index 5435cd67d0..b572b7f444 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts @@ -58,6 +58,9 @@ export class AlfrescoSearchControlComponent implements OnInit { @ViewChild('searchInput', {}) searchInput: ElementRef; + @Input() + autocompleteEnabled = true; + @Input() autocompleteSearchTerm = ''; @@ -146,4 +149,12 @@ export class AlfrescoSearchControlComponent implements OnInit { } } + onEscape(): void { + this.searchActive = false; + } + + onArrowDown(): void { + this.searchActive = true; + } + } From 4beda8e55e5a67f5a1fcb7f8484d676538c103b9 Mon Sep 17 00:00:00 2001 From: Will Abson Date: Tue, 4 Oct 2016 16:17:53 +0100 Subject: [PATCH 14/16] Clear autocomplete results/errors between searches Refs #737 --- ...esco-search-autocomplete.component.spec.ts | 39 +++++++++++++++++++ .../alfresco-search-autocomplete.component.ts | 2 + 2 files changed, 41 insertions(+) diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts index 5af3258689..98049462e6 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts @@ -136,6 +136,25 @@ describe('AlfrescoSearchAutocompleteComponent', () => { expect(component.displaySearchResults).toHaveBeenCalledWith(searchTerm.currentValue); }); + it('should clear results straight away when a new search term is entered', (done) => { + + let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + spyOn(searchService, 'getSearchNodesPromise') + .and.returnValue(Promise.resolve(result)); + + component.resultsEmitter.subscribe(x => { + alfrescoSearchComponentFixture.detectChanges(); + component.searchTerm = 'searchTerm2'; + component.ngOnChanges({searchTerm: { currentValue: 'searchTerm2', previousValue: 'searchTerm'} }); + alfrescoSearchComponentFixture.detectChanges(); + expect(element.querySelectorAll('table[data-automation-id="autocomplete_results"] tbody tr').length).toBe(0); + done(); + }); + + component.searchTerm = 'searchTerm'; + component.ngOnChanges({searchTerm: { currentValue: 'searchTerm', previousValue: ''} }); + }); + it('should display the returned search results', (done) => { let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); @@ -214,6 +233,26 @@ describe('AlfrescoSearchAutocompleteComponent', () => { component.ngOnChanges({searchTerm: { currentValue: 'searchTerm', previousValue: ''}}); }); + it('should clear errors straight away when a new search is performed', (done) => { + + let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + spyOn(searchService, 'getSearchNodesPromise') + .and.returnValue(Promise.reject(errorJson)); + + component.errorEmitter.subscribe(() => { + alfrescoSearchComponentFixture.detectChanges(); + component.searchTerm = 'searchTerm2'; + component.ngOnChanges({searchTerm: { currentValue: 'searchTerm2', previousValue: 'searchTerm'} }); + alfrescoSearchComponentFixture.detectChanges(); + let errorEl = element.querySelector('[data-automation-id="autocomplete_error_message"]'); + expect(errorEl).toBeNull(); + done(); + }); + + component.searchTerm = 'searchTerm'; + component.ngOnChanges({searchTerm: { currentValue: 'searchTerm', previousValue: ''}}); + }); + it('should emit preview when file item clicked', (done) => { let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts index f4e7f75274..38d87946e5 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts @@ -62,6 +62,8 @@ export class AlfrescoSearchAutocompleteComponent implements OnChanges { ngOnChanges(changes) { if (changes.searchTerm) { + this.results = null; + this.errorMessage = null; this.displaySearchResults(changes.searchTerm.currentValue); } } From dda838be5e259f4e6697cd15b17c2d7796fb0929 Mon Sep 17 00:00:00 2001 From: Will Abson Date: Wed, 5 Oct 2016 09:58:13 +0100 Subject: [PATCH 15/16] Re-enable translation service tests Refs #737 --- .../alfresco-search-autocomplete.component.spec.ts | 14 ++++++-------- .../alfresco-search-autocomplete.component.ts | 14 ++++++++------ .../components/alfresco-search.component.spec.ts | 11 ++++++----- .../src/components/alfresco-search.component.ts | 11 ++++------- 4 files changed, 24 insertions(+), 26 deletions(-) diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts index 98049462e6..f8e55488e5 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts @@ -116,14 +116,12 @@ describe('AlfrescoSearchAutocompleteComponent', () => { }); })); - // it('should setup i18n folder', () => { - // let translation = jasmine.createSpyObj('AlfrescoTranslationService', [ - // 'addTranslationFolder' - // ]); - // let search = new AlfrescoSearchAutocompleteComponent(null, translation, null); - // expect(search).toBeDefined(); - // - // }); + it('should setup i18n folder', () => { + let translationService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoTranslationService); + spyOn(translationService, 'addTranslationFolder'); + alfrescoSearchComponentFixture.detectChanges(); + expect(translationService.addTranslationFolder).toHaveBeenCalledWith('node_modules/ng2-alfresco-search/dist/src'); + }); it('should display search results when a search term is provided', () => { let searchTerm = { currentValue: 'customSearchTerm', previousValue: ''}; diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts index 38d87946e5..69e0859c16 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, OnChanges, Output } from '@angular/core'; import { AlfrescoSearchService } from './../services/alfresco-search.service'; import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service'; import { AlfrescoTranslationService } from 'ng2-alfresco-core'; @@ -28,14 +28,14 @@ declare let __moduleName: string; templateUrl: './alfresco-search-autocomplete.component.html', styleUrls: ['./alfresco-search-autocomplete.component.css'] }) -export class AlfrescoSearchAutocompleteComponent implements OnChanges { +export class AlfrescoSearchAutocompleteComponent implements OnInit, OnChanges { baseComponentPath = __moduleName.replace('/components/alfresco-search-autocomplete.component.js', ''); @Input() searchTerm: string = ''; - results: any; + results: any = null; errorMessage; @@ -54,10 +54,12 @@ export class AlfrescoSearchAutocompleteComponent implements OnChanges { constructor(private alfrescoSearchService: AlfrescoSearchService, private translate: AlfrescoTranslationService, private alfrescoThumbnailService: AlfrescoThumbnailService) { - if (translate) { - translate.addTranslationFolder('node_modules/ng2-alfresco-search/dist/src'); + } + + ngOnInit(): void { + if (this.translate) { + this.translate.addTranslationFolder('node_modules/ng2-alfresco-search/dist/src'); } - this.results = null; } ngOnChanges(changes) { diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts index f3b1b11e8f..ec6cd7d195 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts @@ -147,11 +147,12 @@ describe('AlfrescoSearchComponent', () => { expect(search.searchTerm).toBeNull(); }); - // it('should setup i18n folder', () => { - // let translationService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoTranslationService); - // spyOn(translationService, 'addTranslationFolder'); - // expect(translationService.addTranslationFolder).toHaveBeenCalledWith('node_modules/ng2-alfresco-search/dist/src'); - // }); + it('should setup i18n folder', () => { + let translationService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoTranslationService); + spyOn(translationService, 'addTranslationFolder'); + alfrescoSearchComponentFixture.detectChanges(); + expect(translationService.addTranslationFolder).toHaveBeenCalledWith('node_modules/ng2-alfresco-search/dist/src'); + }); describe('Rendering search results', () => { diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts index 3633941136..b1aab94761 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts @@ -45,7 +45,7 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit { @Output() errorEmitter = new EventEmitter(); - results: any; + results: any = null; errorMessage; @@ -55,15 +55,12 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit { private translate: AlfrescoTranslationService, private _alfrescoThumbnailService: AlfrescoThumbnailService, @Optional() private route: ActivatedRoute) { - - if (translate !== null) { - translate.addTranslationFolder('node_modules/ng2-alfresco-search/dist/src'); - } - - this.results = null; } ngOnInit(): void { + if (this.translate !== null) { + this.translate.addTranslationFolder('node_modules/ng2-alfresco-search/dist/src'); + } if (this.route) { this.route.params.forEach((params: Params) => { this.searchTerm = params.hasOwnProperty(this.queryParamName) ? params[this.queryParamName] : null; From b200eab4665460e27955d7b8d8646c9870a704ec Mon Sep 17 00:00:00 2001 From: Will Abson Date: Wed, 5 Oct 2016 10:18:01 +0100 Subject: [PATCH 16/16] Rename fixture variable to clean up test code Refs #737 --- ...esco-search-autocomplete.component.spec.ts | 52 ++++++------ .../alfresco-search-control.component.spec.ts | 80 +++++++++---------- .../alfresco-search.component.spec.ts | 36 ++++----- 3 files changed, 84 insertions(+), 84 deletions(-) diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts index f8e55488e5..7694f261e1 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts @@ -31,7 +31,7 @@ import { describe('AlfrescoSearchAutocompleteComponent', () => { - let alfrescoSearchComponentFixture: ComponentFixture, element: HTMLElement; + let fixture: ComponentFixture, element: HTMLElement; let component: AlfrescoSearchAutocompleteComponent; let result = { @@ -110,16 +110,16 @@ describe('AlfrescoSearchAutocompleteComponent', () => { AlfrescoSearchService ] }).compileComponents().then(() => { - alfrescoSearchComponentFixture = TestBed.createComponent(AlfrescoSearchAutocompleteComponent); - component = alfrescoSearchComponentFixture.componentInstance; - element = alfrescoSearchComponentFixture.nativeElement; + fixture = TestBed.createComponent(AlfrescoSearchAutocompleteComponent); + component = fixture.componentInstance; + element = fixture.nativeElement; }); })); it('should setup i18n folder', () => { - let translationService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoTranslationService); + let translationService = fixture.debugElement.injector.get(AlfrescoTranslationService); spyOn(translationService, 'addTranslationFolder'); - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); expect(translationService.addTranslationFolder).toHaveBeenCalledWith('node_modules/ng2-alfresco-search/dist/src'); }); @@ -130,21 +130,21 @@ describe('AlfrescoSearchAutocompleteComponent', () => { component.ngOnChanges({ searchTerm: searchTerm }); - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); expect(component.displaySearchResults).toHaveBeenCalledWith(searchTerm.currentValue); }); it('should clear results straight away when a new search term is entered', (done) => { - let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + let searchService = fixture.debugElement.injector.get(AlfrescoSearchService); spyOn(searchService, 'getSearchNodesPromise') .and.returnValue(Promise.resolve(result)); component.resultsEmitter.subscribe(x => { - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); component.searchTerm = 'searchTerm2'; component.ngOnChanges({searchTerm: { currentValue: 'searchTerm2', previousValue: 'searchTerm'} }); - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); expect(element.querySelectorAll('table[data-automation-id="autocomplete_results"] tbody tr').length).toBe(0); done(); }); @@ -155,12 +155,12 @@ describe('AlfrescoSearchAutocompleteComponent', () => { it('should display the returned search results', (done) => { - let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + let searchService = fixture.debugElement.injector.get(AlfrescoSearchService); spyOn(searchService, 'getSearchNodesPromise') .and.returnValue(Promise.resolve(result)); component.resultsEmitter.subscribe(x => { - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); expect( element.querySelector('#result_user_0').innerHTML).toBe('John Doe'); expect( element.querySelector('#result_name_0').innerHTML).toBe('MyDoc'); done(); @@ -172,18 +172,18 @@ describe('AlfrescoSearchAutocompleteComponent', () => { it('should display the correct thumbnail for result items', (done) => { - let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + let searchService = fixture.debugElement.injector.get(AlfrescoSearchService); spyOn(searchService, 'getSearchNodesPromise') .and.returnValue(Promise.resolve(result)); component.baseComponentPath = 'http://localhost'; - let thumbnailService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoThumbnailService); + let thumbnailService = fixture.debugElement.injector.get(AlfrescoThumbnailService); spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue('fake-type-icon.svg'); spyOn(thumbnailService, 'getMimeTypeKey').and.returnValue('FAKE_TYPE'); component.resultsEmitter.subscribe(() => { - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); let imgEl = element.querySelector('#result_row_0 img'); expect(imgEl).not.toBeNull(); expect(imgEl.src).toBe('http://localhost/img/fake-type-icon.svg'); @@ -197,12 +197,12 @@ describe('AlfrescoSearchAutocompleteComponent', () => { it('should display no result if no result are returned', (done) => { - let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + let searchService = fixture.debugElement.injector.get(AlfrescoSearchService); spyOn(searchService, 'getSearchNodesPromise') .and.returnValue(Promise.resolve(noResult)); component.resultsEmitter.subscribe(x => { - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); expect(element.querySelector('#search_no_result')).not.toBeNull(); done(); }); @@ -213,12 +213,12 @@ describe('AlfrescoSearchAutocompleteComponent', () => { it('should display an error if an error is encountered running the search', (done) => { - let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + let searchService = fixture.debugElement.injector.get(AlfrescoSearchService); spyOn(searchService, 'getSearchNodesPromise') .and.returnValue(Promise.reject(errorJson)); component.errorEmitter.subscribe(() => { - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); let resultsEl = element.querySelector('[data-automation-id="autocomplete_results"]'); let errorEl = element.querySelector('[data-automation-id="autocomplete_error_message"]'); expect(resultsEl).toBeNull(); @@ -233,15 +233,15 @@ describe('AlfrescoSearchAutocompleteComponent', () => { it('should clear errors straight away when a new search is performed', (done) => { - let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + let searchService = fixture.debugElement.injector.get(AlfrescoSearchService); spyOn(searchService, 'getSearchNodesPromise') .and.returnValue(Promise.reject(errorJson)); component.errorEmitter.subscribe(() => { - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); component.searchTerm = 'searchTerm2'; component.ngOnChanges({searchTerm: { currentValue: 'searchTerm2', previousValue: 'searchTerm'} }); - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); let errorEl = element.querySelector('[data-automation-id="autocomplete_error_message"]'); expect(errorEl).toBeNull(); done(); @@ -253,12 +253,12 @@ describe('AlfrescoSearchAutocompleteComponent', () => { it('should emit preview when file item clicked', (done) => { - let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + let searchService = fixture.debugElement.injector.get(AlfrescoSearchService); spyOn(searchService, 'getSearchNodesPromise') .and.returnValue(Promise.resolve(result)); component.resultsEmitter.subscribe(x => { - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); ( element.querySelector('#result_row_0')).click(); }); @@ -272,13 +272,13 @@ describe('AlfrescoSearchAutocompleteComponent', () => { it('should not emit preview if a non-file item is clicked', (done) => { - let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + let searchService = fixture.debugElement.injector.get(AlfrescoSearchService); spyOn(searchService, 'getSearchNodesPromise') .and.returnValue(Promise.resolve(folderResult)); spyOn(component.preview, 'emit'); component.resultsEmitter.subscribe(x => { - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); ( element.querySelector('#result_row_0')).click(); expect(component.preview.emit).not.toHaveBeenCalled(); done(); diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts index 703c811f2b..f1836f456a 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.spec.ts @@ -33,7 +33,7 @@ import { AlfrescoSearchService } from '../services/alfresco-search.service'; describe('AlfrescoSearchControlComponent', () => { - let alfrescoSearchControlComponentFixture: ComponentFixture; + let fixture: ComponentFixture; let component: AlfrescoSearchControlComponent, element: HTMLElement; beforeEach(async(() => { @@ -55,76 +55,76 @@ describe('AlfrescoSearchControlComponent', () => { AlfrescoSearchService ] }).compileComponents().then(() => { - alfrescoSearchControlComponentFixture = TestBed.createComponent(AlfrescoSearchControlComponent); - component = alfrescoSearchControlComponentFixture.componentInstance; - element = alfrescoSearchControlComponentFixture.nativeElement; + fixture = TestBed.createComponent(AlfrescoSearchControlComponent); + component = fixture.componentInstance; + element = fixture.nativeElement; }); })); it('should setup i18n folder', () => { - let translationService = alfrescoSearchControlComponentFixture.debugElement.injector.get(AlfrescoTranslationService); + let translationService = fixture.debugElement.injector.get(AlfrescoTranslationService); spyOn(translationService, 'addTranslationFolder'); - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); expect(translationService.addTranslationFolder) .toHaveBeenCalledWith('node_modules/ng2-alfresco-search/dist/src'); }); it('should emit searchChange when search term input changed', (done) => { - alfrescoSearchControlComponentFixture.componentInstance.searchChange.subscribe(e => { + fixture.componentInstance.searchChange.subscribe(e => { expect(e.value).toBe('customSearchTerm'); done(); }); - alfrescoSearchControlComponentFixture.detectChanges(); - alfrescoSearchControlComponentFixture.componentInstance.searchTerm = 'customSearchTerm'; - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); + fixture.componentInstance.searchTerm = 'customSearchTerm'; + fixture.detectChanges(); }); it('should emit searchChange when search term changed by user', (done) => { - alfrescoSearchControlComponentFixture.detectChanges(); - alfrescoSearchControlComponentFixture.componentInstance.searchChange.subscribe(e => { + fixture.detectChanges(); + fixture.componentInstance.searchChange.subscribe(e => { expect(e.value).toBe('customSearchTerm211'); done(); }); component.searchControl.setValue('customSearchTerm211', true); - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); }); describe('Component rendering', () => { it('should display a text input field by default', () => { - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); expect(element.querySelectorAll('input[type="text"]').length).toBe(1); }); it('should display a search input field when specified', () => { - alfrescoSearchControlComponentFixture.componentInstance.inputType = 'search'; - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.componentInstance.inputType = 'search'; + fixture.detectChanges(); expect(element.querySelectorAll('input[type="search"]').length).toBe(1); }); it('should set browser autocomplete to off by default', () => { - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); let attr = element.querySelectorAll('input[type="text"]')[0].getAttribute('autocomplete'); expect(attr).toBe('off'); }); it('should set browser autocomplete to on when configured', () => { - alfrescoSearchControlComponentFixture.componentInstance.autocomplete = true; - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.componentInstance.autocomplete = true; + fixture.detectChanges(); expect(element.querySelectorAll('input[type="text"]')[0].getAttribute('autocomplete')).toBe('on'); }); it('should show an expanding control by default', () => { - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.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', () => { - alfrescoSearchControlComponentFixture.detectChanges(); - alfrescoSearchControlComponentFixture.componentInstance.expandable = false; - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); + fixture.componentInstance.expandable = false; + fixture.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); @@ -140,31 +140,31 @@ describe('AlfrescoSearchControlComponent', () => { }); it('should display a find-as-you-type control by default', () => { - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); let autocomplete: Element = element.querySelector('alfresco-search-autocomplete'); expect(autocomplete).not.toBeNull(); }); it('should make find-as-you-type control hidden initially', () => { - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); let autocomplete: Element = element.querySelector('alfresco-search-autocomplete'); expect(autocomplete.classList.contains('active')).toBe(false); }); it('should make find-as-you-type control visible when search box has focus', () => { - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); inputEl.dispatchEvent(new Event('focus')); - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); let autocomplete: Element = element.querySelector('alfresco-search-autocomplete'); expect(autocomplete.classList.contains('active')).toBe(true); }); it('should hide find-as-you-type results when the search box loses focus', (done) => { - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); inputEl.dispatchEvent(new Event('focus')); inputEl.dispatchEvent(new Event('blur')); window.setTimeout(() => { - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); let autocomplete: Element = element.querySelector('alfresco-search-autocomplete'); expect(autocomplete.classList.contains('active')).toBe(false); done(); @@ -172,18 +172,18 @@ describe('AlfrescoSearchControlComponent', () => { }); it('should hide find-as-you-type results when escape key pressed', () => { - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); inputEl.dispatchEvent(new Event('focus')); inputEl.dispatchEvent(new KeyboardEvent('keyup', { key: 'Escape' })); - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); let autocomplete: Element = element.querySelector('alfresco-search-autocomplete'); expect(autocomplete.classList.contains('active')).toBe(false); }); it('should make find-as-you-type control visible again when down arrow is pressed', () => { - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); inputEl.dispatchEvent(new Event('focus')); inputEl.dispatchEvent(new KeyboardEvent('keyup', { key: 'Escape' @@ -191,14 +191,14 @@ describe('AlfrescoSearchControlComponent', () => { inputEl.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowDown' })); - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); let autocomplete: Element = element.querySelector('alfresco-search-autocomplete'); expect(autocomplete.classList.contains('active')).toBe(true); }); it('should NOT display a find-as-you-type control when configured not to', () => { - alfrescoSearchControlComponentFixture.componentInstance.autocompleteEnabled = false; - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.componentInstance.autocompleteEnabled = false; + fixture.detectChanges(); let autocomplete: Element = element.querySelector('alfresco-search-autocomplete'); expect(autocomplete).toBeNull(); }); @@ -209,14 +209,14 @@ describe('AlfrescoSearchControlComponent', () => { it('should fire a search when a term has been entered', () => { spyOn(component.searchSubmit, 'emit'); - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); let formEl: HTMLElement = element.querySelector('form'); component.searchTerm = 'searchTerm1'; component.searchControl.setValue('searchTerm1', true); - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); formEl.dispatchEvent(new Event('submit')); - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); expect(component.searchSubmit.emit).toHaveBeenCalledWith({ 'value': 'searchTerm1' @@ -225,13 +225,13 @@ describe('AlfrescoSearchControlComponent', () => { it('should not fire a search when no term has been entered', () => { spyOn(component.searchSubmit, 'emit'); - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); let inputEl: HTMLInputElement = element.querySelector('input[type="text"]'); let formEl: HTMLElement = element.querySelector('form'); inputEl.value = ''; formEl.dispatchEvent(new Event('submit')); - alfrescoSearchControlComponentFixture.detectChanges(); + fixture.detectChanges(); expect(component.searchSubmit.emit).not.toHaveBeenCalled(); }); diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts index ec6cd7d195..b4278936c4 100644 --- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts +++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts @@ -34,7 +34,7 @@ import { describe('AlfrescoSearchComponent', () => { - let alfrescoSearchComponentFixture: ComponentFixture, element: HTMLElement; + let fixture: ComponentFixture, element: HTMLElement; let component: AlfrescoSearchComponent; let result = { @@ -113,9 +113,9 @@ describe('AlfrescoSearchComponent', () => { AlfrescoContentService ] }).compileComponents().then(() => { - alfrescoSearchComponentFixture = TestBed.createComponent(AlfrescoSearchComponent); - component = alfrescoSearchComponentFixture.componentInstance; - element = alfrescoSearchComponentFixture.nativeElement; + fixture = TestBed.createComponent(AlfrescoSearchComponent); + component = fixture.componentInstance; + element = fixture.nativeElement; }); })); @@ -148,9 +148,9 @@ describe('AlfrescoSearchComponent', () => { }); it('should setup i18n folder', () => { - let translationService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoTranslationService); + let translationService = fixture.debugElement.injector.get(AlfrescoTranslationService); spyOn(translationService, 'addTranslationFolder'); - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); expect(translationService.addTranslationFolder).toHaveBeenCalledWith('node_modules/ng2-alfresco-search/dist/src'); }); @@ -158,12 +158,12 @@ describe('AlfrescoSearchComponent', () => { it('should display search results when a search term is provided', (done) => { - let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + let searchService = fixture.debugElement.injector.get(AlfrescoSearchService); spyOn(searchService, 'getSearchNodesPromise') .and.returnValue(Promise.resolve(result)); component.resultsEmitter.subscribe(x => { - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); expect(searchService.getSearchNodesPromise).toHaveBeenCalled(); expect(element.querySelector('#result_user_0')).not.toBeNull(); expect(element.querySelector('#result_user_0').innerHTML).toBe('John Doe'); @@ -177,12 +177,12 @@ describe('AlfrescoSearchComponent', () => { it('should display no result if no result are returned', (done) => { - let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + let searchService = fixture.debugElement.injector.get(AlfrescoSearchService); spyOn(searchService, 'getSearchNodesPromise') .and.returnValue(Promise.resolve(noResult)); component.resultsEmitter.subscribe(x => { - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); expect(element.querySelector('#search_no_result')).not.toBeNull(); done(); }); @@ -193,12 +193,12 @@ describe('AlfrescoSearchComponent', () => { it('should display an error if an error is encountered running the search', (done) => { - let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + let searchService = fixture.debugElement.injector.get(AlfrescoSearchService); spyOn(searchService, 'getSearchNodesPromise') .and.returnValue(Promise.reject(errorJson)); component.errorEmitter.subscribe(() => { - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); let resultsEl = element.querySelector('[data-automation-id="search_result_table"]'); let errorEl = element.querySelector('[data-automation-id="search_error_message"]'); expect(resultsEl).toBeNull(); @@ -213,12 +213,12 @@ describe('AlfrescoSearchComponent', () => { it('should update search results when the search term input is changed', (done) => { - let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + let searchService = fixture.debugElement.injector.get(AlfrescoSearchService); spyOn(searchService, 'getSearchNodesPromise') .and.returnValue(Promise.resolve(result)); component.resultsEmitter.subscribe(x => { - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); expect(searchService.getSearchNodesPromise).toHaveBeenCalledWith('searchTerm2'); expect(element.querySelector('#result_user_0')).not.toBeNull(); expect(element.querySelector('#result_user_0').innerHTML).toBe('John Doe'); @@ -234,12 +234,12 @@ describe('AlfrescoSearchComponent', () => { it('should emit preview when file item clicked', (done) => { - let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + let searchService = fixture.debugElement.injector.get(AlfrescoSearchService); spyOn(searchService, 'getSearchNodesPromise') .and.returnValue(Promise.resolve(result)); component.resultsEmitter.subscribe(() => { - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); ( element.querySelector('#result_row_0')).click(); }); @@ -253,13 +253,13 @@ describe('AlfrescoSearchComponent', () => { it('should not emit preview when non-file item is clicked', (done) => { - let searchService = alfrescoSearchComponentFixture.debugElement.injector.get(AlfrescoSearchService); + let searchService = fixture.debugElement.injector.get(AlfrescoSearchService); spyOn(searchService, 'getSearchNodesPromise') .and.returnValue(Promise.resolve(folderResult)); spyOn(component.preview, 'emit'); component.resultsEmitter.subscribe(x => { - alfrescoSearchComponentFixture.detectChanges(); + fixture.detectChanges(); ( element.querySelector('#result_row_0')).click(); expect(component.preview.emit).not.toHaveBeenCalled(); done();