[ADF-3677] Add highlight configuration to SearchQueryBuilder (#4358)

* [ADF-3677] Add highlight configuration to SearchQueryBuilder

* highlight property in search

* Update files.component.ts

* remove comma

* highlight missspell

* fix schhema json highilight

* fix test

* fix lint

* fix lint

* fix lint

* fix search sorting tests

* fix search sorting

* fix lint

* remove useless test

* check for null nodes

* remove duplicated test

* lint

* fix sorting tests

* remove test not search component related
This commit is contained in:
davidcanonieto 2019-03-17 17:23:07 +00:00 committed by Eugenio Romano
parent d6f391c40e
commit 8dc9eba4c7
19 changed files with 401 additions and 444 deletions

View File

@ -249,7 +249,23 @@
} }
} }
} }
] ],
"highlight": {
"prefix": " ",
"postfix": " ",
"mergeContiguous": true,
"fields": [
{
"field": "cm:title"
},
{
"field": "description",
"prefix": "(",
"postfix": ")"
}
]
}
}, },
"pagination": { "pagination": {
"size": 20, "size": 20,

View File

@ -1,10 +1,11 @@
<div class="adf-container"> <div class="adf-container">
<mat-accordion *ngIf="showRecentFiles" class="adf-container-recent"> <mat-accordion *ngIf="showRecentFiles" class="adf-container-recent">
<mat-expansion-panel hideToggle="true"> <mat-expansion-panel hideToggle="true">
<mat-expansion-panel-header > <mat-expansion-panel-header>
<mat-panel-title> <mat-panel-title>
{{ 'DOCUMENT_LIST.RECENT.TITLE' | translate }}<mat-icon>history</mat-icon> {{ 'DOCUMENT_LIST.RECENT.TITLE' | translate }}
<mat-icon>history</mat-icon>
</mat-panel-title> </mat-panel-title>
</mat-expansion-panel-header> </mat-expansion-panel-header>
@ -31,7 +32,8 @@
</adf-sites-dropdown> </adf-sites-dropdown>
</div> </div>
<div id="document-list-container" class="adf-document-list-container" fxLayout="row" fxLayoutAlign="start stretch" fxLayoutGap="16px"> <div id="document-list-container" class="adf-document-list-container" fxLayout="row" fxLayoutAlign="start stretch"
fxLayoutGap="16px">
<adf-upload-drag-area fxFlex="1 1 auto" <adf-upload-drag-area fxFlex="1 1 auto"
[disabled]="disableDragArea" [disabled]="disableDragArea"
[acceptedFilesType]="getFileFiltering()" [acceptedFilesType]="getFileFiltering()"
@ -67,8 +69,12 @@
data-automation-id="document-list-grid-view" data-automation-id="document-list-grid-view"
title="{{ 'DOCUMENT_LIST.TOOLBAR.CARDVIEW' | translate }}" title="{{ 'DOCUMENT_LIST.TOOLBAR.CARDVIEW' | translate }}"
(click)="toggleGalleryView()"> (click)="toggleGalleryView()">
<mat-icon *ngIf="displayMode === 'list'" matTooltip="{{ 'DOCUMENT_LIST.TOOLBAR.CARDVIEW' | translate }}">view_comfy</mat-icon> <mat-icon *ngIf="displayMode === 'list'"
<mat-icon *ngIf="displayMode === 'gallery'" matTooltip="{{ 'DOCUMENT_LIST.TOOLBAR.LISTVIEW' | translate }}">list</mat-icon> matTooltip="{{ 'DOCUMENT_LIST.TOOLBAR.CARDVIEW' | translate }}">view_comfy
</mat-icon>
<mat-icon *ngIf="displayMode === 'gallery'"
matTooltip="{{ 'DOCUMENT_LIST.TOOLBAR.LISTVIEW' | translate }}">list
</mat-icon>
</button> </button>
<button <button
data-automation-id="create-new-folder" data-automation-id="create-new-folder"
@ -136,7 +142,8 @@
</button> </button>
</div> </div>
<button fxFlex="1 0 auto" mat-icon-button [matMenuTriggerFor]="themePicker" matTooltip="{{ 'DOCUMENT_LIST.TOOLBAR.THEME' | translate }}"> <button fxFlex="1 0 auto" mat-icon-button [matMenuTriggerFor]="themePicker"
matTooltip="{{ 'DOCUMENT_LIST.TOOLBAR.THEME' | translate }}">
<mat-icon>format_color_fill</mat-icon> <mat-icon>format_color_fill</mat-icon>
</button> </button>
@ -148,8 +155,12 @@
</mat-menu> </mat-menu>
<button mat-icon-button (click)="showVersions = !showVersions" class="adf-show-versions-button"> <button mat-icon-button (click)="showVersions = !showVersions" class="adf-show-versions-button">
<mat-icon *ngIf="!showVersions" matTooltip="{{ 'DOCUMENT_LIST.TOOLBAR.SHOW_VERSION' | translate }}">chevron_left</mat-icon> <mat-icon *ngIf="!showVersions" matTooltip="{{ 'DOCUMENT_LIST.TOOLBAR.SHOW_VERSION' | translate }}">
<mat-icon *ngIf="showVersions" matTooltip="{{ 'DOCUMENT_LIST.TOOLBAR.HIDE_VERSION' | translate }}">chevron_right</mat-icon> chevron_left
</mat-icon>
<mat-icon *ngIf="showVersions" matTooltip="{{ 'DOCUMENT_LIST.TOOLBAR.HIDE_VERSION' | translate }}">
chevron_right
</mat-icon>
</button> </button>
<adf-toolbar-divider fxFlex="0 0 auto" fxHide fxShow.lt-sm="true"></adf-toolbar-divider> <adf-toolbar-divider fxFlex="0 0 auto" fxHide fxShow.lt-sm="true"></adf-toolbar-divider>
@ -160,7 +171,7 @@
<mat-menu #menu="matMenu"> <mat-menu #menu="matMenu">
<button mat-menu-item <button mat-menu-item
(click)="toggleGalleryView()"> (click)="toggleGalleryView()">
<mat-icon *ngIf="displayMode === 'list'" >view_comfy</mat-icon> <mat-icon *ngIf="displayMode === 'list'">view_comfy</mat-icon>
<mat-icon *ngIf="displayMode === 'gallery'">list</mat-icon> <mat-icon *ngIf="displayMode === 'gallery'">list</mat-icon>
<span>{{ 'DOCUMENT_LIST.TOOLBAR.CARDVIEW' | translate }}</span> <span>{{ 'DOCUMENT_LIST.TOOLBAR.CARDVIEW' | translate }}</span>
</button> </button>
@ -225,12 +236,12 @@
(permissionError)="handlePermissionError($event)" (permissionError)="handlePermissionError($event)"
(name-click)="documentList.onNodeDblClick($event.detail?.node)"> (name-click)="documentList.onNodeDblClick($event.detail?.node)">
<adf-custom-no-permission-template *ngIf="enableCustomPermissionMessage"> <adf-custom-no-permission-template *ngIf="enableCustomPermissionMessage">
<h1>You don't have permissions</h1> <h1>You don't have permissions</h1>
</adf-custom-no-permission-template> </adf-custom-no-permission-template>
<adf-custom-empty-content-template *ngIf="disableDragArea"> <adf-custom-empty-content-template *ngIf="disableDragArea">
<div class="adf-empty_template"> <div class="adf-empty_template">
<div class="adf-no-result-message">{{ 'SEARCH.NO_RESULT' | translate }}</div> <div class="adf-no-result-message">{{ 'SEARCH.NO_RESULT' | translate }}</div>
</div> </div>
</adf-custom-empty-content-template> </adf-custom-empty-content-template>
<data-columns> <data-columns>
<data-column <data-column
@ -271,6 +282,14 @@
title="{{'DOCUMENT_LIST.COLUMNS.SIZE' | translate}}" title="{{'DOCUMENT_LIST.COLUMNS.SIZE' | translate}}"
type="fileSize"> type="fileSize">
</data-column> </data-column>
<data-column
key="search"
title="Search">
<ng-template let-entry="$implicit">
<div *ngIf="searchTerm" [innerHTML]="searchResultsHighlight(entry.row.node.entry.search) | highlight:searchTerm">
</div>
</ng-template>
</data-column>
<!-- Notes: has performance overhead due to multiple files/folders causing separate HTTP calls to get tags --> <!-- Notes: has performance overhead due to multiple files/folders causing separate HTTP calls to get tags -->
<!-- <!--
<data-column <data-column
@ -422,7 +441,7 @@
<adf-info-drawer-layout *ngIf="showVersions" class="adf-manage-versions-sidebar" fxFlex="0 0 auto"> <adf-info-drawer-layout *ngIf="showVersions" class="adf-manage-versions-sidebar" fxFlex="0 0 auto">
<div info-drawer-content> <div info-drawer-content>
<adf-info-drawer [title]="'Details'" *ngIf="documentList.selection[0]" > <adf-info-drawer [title]="'Details'" *ngIf="documentList.selection[0]">
<adf-info-drawer-tab [label]="'Properties'"> <adf-info-drawer-tab [label]="'Properties'">
<adf-content-metadata-card <adf-content-metadata-card
[node]="documentList.selection[0].entry" [node]="documentList.selection[0].entry"
@ -514,7 +533,8 @@
</section> </section>
<section> <section>
<mat-slide-toggle id="adf-extension-filter-upload-switch" [color]="'primary'" [(ngModel)]="acceptedFilesTypeShow"> <mat-slide-toggle id="adf-extension-filter-upload-switch" [color]="'primary'"
[(ngModel)]="acceptedFilesTypeShow">
{{'DOCUMENT_LIST.CUSTOM_FILTER' | translate}} {{'DOCUMENT_LIST.CUSTOM_FILTER' | translate}}
</mat-slide-toggle> </mat-slide-toggle>
</section> </section>
@ -532,13 +552,14 @@
</section> </section>
<section> <section>
<mat-slide-toggle id="adf-document-list-enable-drop-files" [color]="'primary'" [(ngModel)]="allowDropFiles" (click)="toggleAllowDropFiles()" > <mat-slide-toggle id="adf-document-list-enable-drop-files" [color]="'primary'" [(ngModel)]="allowDropFiles"
(click)="toggleAllowDropFiles()">
{{'DOCUMENT_LIST.ALLOW_DROP_FILES' | translate}} {{'DOCUMENT_LIST.ALLOW_DROP_FILES' | translate}}
</mat-slide-toggle> </mat-slide-toggle>
</section> </section>
<section> <section>
<mat-slide-toggle id="adf-version-upload-switch" [color]="'primary'" [(ngModel)]="versioning"> <mat-slide-toggle id="adf-version-upload-switch" [color]="'primary'" [(ngModel)]="versioning">
{{'DOCUMENT_LIST.ENABLE_VERSIONING' | translate}} {{'DOCUMENT_LIST.ENABLE_VERSIONING' | translate}}
</mat-slide-toggle> </mat-slide-toggle>
</section> </section>
@ -656,4 +677,4 @@
</div> </div>
</div> </div>
<adf-file-uploading-dialog #fileDialog (error)="openSnackMessage($event)" ></adf-file-uploading-dialog> <adf-file-uploading-dialog #fileDialog (error)="openSnackMessage($event)"></adf-file-uploading-dialog>

View File

@ -28,7 +28,7 @@ import {
AlfrescoApiService, AuthenticationService, AppConfigService, AppConfigValues, ContentService, TranslationService, AlfrescoApiService, AuthenticationService, AppConfigService, AppConfigValues, ContentService, TranslationService,
FileUploadEvent, FolderCreatedEvent, LogService, NotificationService, FileUploadEvent, FolderCreatedEvent, LogService, NotificationService,
UploadService, DataColumn, DataRow, UserPreferencesService, UploadService, DataColumn, DataRow, UserPreferencesService,
PaginationComponent, FormValues, DisplayMode, InfinitePaginationComponent PaginationComponent, FormValues, DisplayMode, InfinitePaginationComponent, HighlightDirective
} from '@alfresco/adf-core'; } from '@alfresco/adf-core';
import { import {
@ -46,6 +46,7 @@ import { MetadataDialogAdapterComponent } from './metadata-dialog-adapter.compon
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { PreviewService } from '../../services/preview.service'; import { PreviewService } from '../../services/preview.service';
import { debounceTime } from 'rxjs/operators'; import { debounceTime } from 'rxjs/operators';
import { SearchEntry } from '@alfresco/js-api';
const DEFAULT_FOLDER_TO_SHOW = '-my-'; const DEFAULT_FOLDER_TO_SHOW = '-my-';
@ -150,6 +151,9 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
@Input() @Input()
showNameColumn = true; showNameColumn = true;
@Input()
searchTerm = '';
@Output() @Output()
documentListReady: EventEmitter<any> = new EventEmitter(); documentListReady: EventEmitter<any> = new EventEmitter();
@ -180,6 +184,9 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
@ViewChild(InfinitePaginationComponent) @ViewChild(InfinitePaginationComponent)
infinitePaginationComponent: InfinitePaginationComponent; infinitePaginationComponent: InfinitePaginationComponent;
@ViewChild(HighlightDirective)
highlighter: HighlightDirective;
permissionsStyle: PermissionStyleModel[] = []; permissionsStyle: PermissionStyleModel[] = [];
infiniteScrolling: boolean; infiniteScrolling: boolean;
warnOnMultipleUploads = false; warnOnMultipleUploads = false;
@ -581,4 +588,10 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
); );
}); });
} }
searchResultsHighlight(search: SearchEntry): string {
if (search && search.highlight) {
return search.highlight.map((currentHighlight) => currentHighlight.snippets).join(', ');
}
}
} }

View File

@ -21,6 +21,7 @@
[nodeResult]="data" [nodeResult]="data"
[disableDragArea]="true" [disableDragArea]="true"
[pagination]="pagination" [pagination]="pagination"
[searchTerm]="searchedWord"
(changedPageSize)="onRefreshPagination($event)" (changedPageSize)="onRefreshPagination($event)"
(changedPageNumber)="onRefreshPagination($event)" (changedPageNumber)="onRefreshPagination($event)"
(turnedNextPage)="onRefreshPagination($event)" (turnedNextPage)="onRefreshPagination($event)"

View File

@ -19,6 +19,7 @@ Represents a main container component for custom search and faceted search setti
- [Categories and widgets](#categories-and-widgets) - [Categories and widgets](#categories-and-widgets)
- [Facet Fields](#facet-fields) - [Facet Fields](#facet-fields)
- [Facet Queries](#facet-queries) - [Facet Queries](#facet-queries)
- [highlight](#highlight)
- [Facet Intervals](#facet-intervals) - [Facet Intervals](#facet-intervals)
- [See also](#see-also) - [See also](#see-also)
@ -420,6 +421,59 @@ Each `intervals` item defined is collected into its collapsible category identif
![Facet Intervals](../../docassets/images/search-facet-intervals.png) ![Facet Intervals](../../docassets/images/search-facet-intervals.png)
### Highlight
You can configure the Highlight using the `search` entry in the `app.config.json` file.
An example query for search highlighting could look like this:
```json
{
"search": {
"highlight": {
"prefix": "¿",
"postfix": "?",
"mergeContiguous": true,
"fields": [
{
"field": "cm:title"
},
{
"field": "description",
"prefix": "(",
"postfix": ")"
}
]
}
}
}
```
The example above changes the highlighting prefix and postfix from the default for all fields to ¿? and just for the "description" field to (). The highlight information will then be added in each node entry response; here is an example partial response:
```json
"entry": {
"createdAt": "2016-10-12T15:24:31.202+0000",
"isFolder": true,
"search": {
"score": 1,
"highlight": [
{
"field": "cm:title",
"snippets": [
"Customized ¿Workflow? Process Definitions"
]
},
{
"field": "description",
"snippets": [
"Customized (Workflow) Process Definitions"
]
}
]
},
```
## See also ## See also
- [Search Query Builder service](../services/search-query-builder.service.md) - [Search Query Builder service](../services/search-query-builder.service.md)

View File

@ -30,8 +30,10 @@ export class NodeActions {
let promises = []; let promises = [];
let nodeList; let nodeList;
for (let i = 0; i < (numberOfElements - 1) ; i++ ) { for (let i = 0; i < (numberOfElements - 1); i++) {
promises.push(alfrescoJsApi.core.nodesApi.getNode(idList[i])); if (idList[i] && idList[i].trim() !== '') {
promises.push(alfrescoJsApi.core.nodesApi.getNode(idList[i]));
}
} }
nodeList = await Promise.all(promises); nodeList = await Promise.all(promises);
return nodeList; return nodeList;

View File

@ -25,6 +25,7 @@ import { DropActions } from '../../actions/drop.actions';
import { by, element, protractor, $$, browser } from 'protractor'; import { by, element, protractor, $$, browser } from 'protractor';
import path = require('path'); import path = require('path');
import { DateUtil } from '../../util/dateUtil';
export class ContentServicesPage { export class ContentServicesPage {
@ -163,10 +164,6 @@ export class ContentServicesPage {
return this; return this;
} }
getElementsDisplayedCreated() {
return this.contentList.dataTablePage().getAllRowsColumnValues('Created');
}
getElementsDisplayedSize() { getElementsDisplayedSize() {
return this.contentList.dataTablePage().getAllRowsColumnValues('Size'); return this.contentList.dataTablePage().getAllRowsColumnValues('Size');
} }
@ -202,31 +199,32 @@ export class ContentServicesPage {
checkElementsSortedAsc(elements) { checkElementsSortedAsc(elements) {
let sorted = true; let sorted = true;
let i = 0; let i = 0;
let compareNumbers = false;
if (elements && elements[0] && typeof elements[0] === 'number') {
compareNumbers = true;
}
while (elements.length > 1 && sorted === true && i < (elements.length - 1)) { while (elements.length > 1 && sorted === true && i < (elements.length - 1)) {
const left = compareNumbers ? elements[i] : JSON.stringify(elements[i]); const left = DateUtil.parse(elements[i], 'DD-MM-YY');
const right = compareNumbers ? elements[i + 1] : JSON.stringify(elements[i + 1]); const right = DateUtil.parse(elements[i + 1], 'DD-MM-YY');
if (left > right) { if (left > right) {
sorted = false; sorted = false;
} }
i++; i++;
} }
return sorted; return sorted;
} }
checkElementsSortedDesc(elements) { checkElementsSortedDesc(elements) {
let sorted = true; let sorted = true;
let i = 0; let i = 0;
while (elements.length > 1 && sorted === true && i < (elements.length - 1)) { while (elements.length > 1 && sorted === true && i < (elements.length - 1)) {
if (elements[i] < elements[i + 1]) { const left = DateUtil.parse(elements[i], 'DD-MM-YY');
const right = DateUtil.parse(elements[i + 1], 'DD-MM-YY');
if (left < right) {
sorted = false; sorted = false;
} }
i++; i++;
} }
return sorted; return sorted;
} }

View File

@ -194,6 +194,10 @@ export class DataTableComponentPage {
return firstNode.getText(); return firstNode.getText();
} }
geCellElementDetail(detail) {
return element.all(by.css(`adf-datatable div[title="${detail}"] span`));
}
sortByColumn(sortOrder, column) { sortByColumn(sortOrder, column) {
let locator = by.css(`div[data-automation-id="auto_id_${column}"]`); let locator = by.css(`div[data-automation-id="auto_id_${column}"]`);
Util.waitUntilElementIsVisible(element(locator)); Util.waitUntilElementIsVisible(element(locator));

View File

@ -18,7 +18,7 @@
import { Util } from '../../util/util'; import { Util } from '../../util/util';
import { DataTableComponentPage } from './dataTableComponentPage'; import { DataTableComponentPage } from './dataTableComponentPage';
import { SearchSortingPickerPage } from './content-services/search/components/search-sortingPicker.page'; import { SearchSortingPickerPage } from './content-services/search/components/search-sortingPicker.page';
import { element, by, protractor } from 'protractor'; import { element, by } from 'protractor';
import { ContentServicesPage } from './contentServicesPage'; import { ContentServicesPage } from './contentServicesPage';
export class SearchResultsPage { export class SearchResultsPage {
@ -95,22 +95,6 @@ export class SearchResultsPage {
return this; return this;
} }
sortAndCheckListIsOrderedByName(sortOrder) {
let deferred = protractor.promise.defer();
this.sortByName(sortOrder);
this.dataTable.waitForTableBody();
if (sortOrder === true) {
this.checkListIsOrderedByNameAsc().then((result) => {
deferred.fulfill(result);
});
} else {
this.checkListIsOrderedByNameDesc().then((result) => {
deferred.fulfill(result);
});
}
return deferred.promise;
}
async checkListIsOrderedByNameAsc() { async checkListIsOrderedByNameAsc() {
let list = await this.contentServices.getElementsDisplayedName(); let list = await this.contentServices.getElementsDisplayedName();
return this.contentServices.checkElementsSortedAsc(list); return this.contentServices.checkElementsSortedAsc(list);
@ -121,60 +105,14 @@ export class SearchResultsPage {
return this.contentServices.checkElementsSortedDesc(list); return this.contentServices.checkElementsSortedDesc(list);
} }
sortAndCheckListIsOrderedByAuthor(alfrescoJsApi, sortOrder) { async checkListIsOrderedByAuthorAsc() {
let deferred = protractor.promise.defer(); let authorList = await this.dataTable.geCellElementDetail('Created by');
this.sortByAuthor(sortOrder); return this.contentServices.checkElementsSortedAsc(authorList);
this.dataTable.waitForTableBody();
if (sortOrder === true) {
this.checkListIsOrderedByAuthorAsc(alfrescoJsApi).then((result) => {
deferred.fulfill(result);
});
} else {
this.checkListIsOrderedByAuthorDesc(alfrescoJsApi).then((result) => {
deferred.fulfill(result);
});
}
return deferred.promise;
} }
async checkListIsOrderedByAuthorAsc(alfrescoJsApi) { async checkListIsOrderedByAuthorDesc() {
let list = await this.contentServices.getElementsDisplayedAuthor(alfrescoJsApi); let authorList = await this.dataTable.geCellElementDetail('Created by');
return this.contentServices.checkElementsSortedAsc(list); return this.contentServices.checkElementsSortedDesc(authorList);
}
async checkListIsOrderedByAuthorDesc(alfrescoJsApi) {
let list = await this.contentServices.getElementsDisplayedAuthor(alfrescoJsApi);
return this.contentServices.checkElementsSortedDesc(list);
}
sortAndCheckListIsOrderedByCreated(sortOrder) {
let deferred = protractor.promise.defer();
this.sortByCreated(sortOrder);
this.dataTable.waitForTableBody();
if (sortOrder === true) {
this.checkListIsOrderedByCreatedAsc().then((result) => {
deferred.fulfill(result);
});
} else {
this.checkListIsOrderedByCreatedDesc().then((result) => {
deferred.fulfill(result);
});
}
return deferred.promise;
}
async checkListIsOrderedByCreatedAsc() {
let stringList = await this.contentServices.getElementsDisplayedCreated();
let list;
await stringList.forEach((stringDate) => {
list.push(new Date(stringDate));
});
return this.contentServices.checkElementsSortedAsc(list);
}
async checkListIsOrderedByCreatedDesc() {
let list = await this.contentServices.getElementsDisplayedCreated();
return this.contentServices.checkElementsSortedDesc(list);
} }
async checkListIsOrderedBySizeAsc() { async checkListIsOrderedBySizeAsc() {

View File

@ -120,7 +120,7 @@ describe('Search Date Range Filter', () => {
.selectTodayDate() .selectTodayDate()
.checkDatePickerIsNotDisplayed(); .checkDatePickerIsNotDisplayed();
dateRangeFilter.getFromDate().then((date) => { dateRangeFilter.getFromDate().then((date) => {
fromDate = DateUtil.formatDate('DD-MM-YY', date); fromDate = DateUtil.formatDate('DD-MM-YY', DateUtil.parse(date, 'DD-MMM-YY'));
}); });
dateRangeFilter.checkApplyButtonIsDisabled(); dateRangeFilter.checkApplyButtonIsDisabled();
@ -129,34 +129,26 @@ describe('Search Date Range Filter', () => {
.selectTodayDate() .selectTodayDate()
.checkDatePickerIsNotDisplayed(); .checkDatePickerIsNotDisplayed();
dateRangeFilter.getToDate().then((date) => { dateRangeFilter.getToDate().then((date) => {
toDate = DateUtil.formatDate('DD-MM-YY', date); toDate = DateUtil.formatDate('DD-MM-YY', DateUtil.parse(date, 'DD-MMM-YY'), 1);
}); });
dateRangeFilter.checkApplyButtonIsEnabled() dateRangeFilter.checkApplyButtonIsEnabled()
.clickApplyButton(); .clickApplyButton();
searchResults.sortByCreated(true); searchResults.sortByCreated(true);
browser.controlFlow().execute(async () => {
let firstResult = await dataTable.getFirstElementDetail('Node id');
await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword);
await this.alfrescoJsApi.core.nodesApi.getNode(firstResult).then(async (node) => {
let nodeCreation = new Date(node.entry.createdAt);
nodeCreation.setHours(0, 0, 0, 0);
await expect(nodeCreation.getTime() >= DateUtil.parse(fromDate).getTime()).toBe(true);
await expect(nodeCreation.getTime() <= DateUtil.parse(toDate).getTime()).toBe(true);
});
});
searchResults.sortByCreated(false);
browser.controlFlow().execute(async () => { browser.controlFlow().execute(async () => {
let firstResult = await dataTable.getFirstElementDetail('Node id'); let results = await dataTable.geCellElementDetail('Created');
await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); for (let currentResult of results) {
await this.alfrescoJsApi.core.nodesApi.getNode(firstResult).then(async (node) => {
let nodeCreation = new Date(node.entry.createdAt); currentResult.getAttribute('title').then(async (currentDate) => {
nodeCreation.setHours(0, 0, 0, 0); let currentDateFormatted = DateUtil.parse(currentDate, 'MMM DD, YYYY, h:mm:ss a');
await expect(nodeCreation.getTime() >= DateUtil.parse(fromDate).getTime()).toBe(true);
await expect(nodeCreation.getTime() <= DateUtil.parse(toDate).getTime()).toBe(true); await expect(currentDateFormatted <= DateUtil.parse(toDate, 'DD-MM-YY')).toBe(true);
}); await expect(currentDateFormatted >= DateUtil.parse(fromDate, 'DD-MM-YY')).toBe(true);
});
}
}); });
}); });

View File

@ -32,6 +32,7 @@ import { FileModel } from '../../models/ACS/fileModel';
import { browser } from 'protractor'; import { browser } from 'protractor';
import resources = require('../../util/resources'); import resources = require('../../util/resources');
import { SearchConfiguration } from '../search.config'; import { SearchConfiguration } from '../search.config';
import { DateUtil } from '../../util/dateUtil';
describe('Search Number Range Filter', () => { describe('Search Number Range Filter', () => {
@ -171,10 +172,16 @@ describe('Search Number Range Filter', () => {
searchResults.sortBySize(false); searchResults.sortBySize(false);
browser.controlFlow().execute(async () => { browser.controlFlow().execute(async () => {
let firstResult = await dataTable.getFirstElementDetail('Node id'); let results = await dataTable.geCellElementDetail('Size');
await this.alfrescoJsApi.core.nodesApi.getNode(firstResult).then(async (node) => { for (let currentResult of results) {
await expect(node.entry.content.sizeInBytes <= toSize).toBe(true); try {
}); let currentSize = await currentResult.getAttribute('title');
if (currentSize && currentSize.trim() !== '') {
await expect(parseInt(currentSize, 10) <= toSize).toBe(true);
}
} catch (e) {
}
}
}); });
}); });
@ -196,10 +203,16 @@ describe('Search Number Range Filter', () => {
searchResults.sortBySize(false); searchResults.sortBySize(false);
browser.controlFlow().execute(async () => { browser.controlFlow().execute(async () => {
let firstResult = await dataTable.getFirstElementDetail('Node id'); let results = await dataTable.geCellElementDetail('Size');
await this.alfrescoJsApi.core.nodesApi.getNode(firstResult).then(async (node) => { for (let currentResult of results) {
await expect(node.entry.content.sizeInBytes <= toSize).toBe(true); try {
}); let currentSize = await currentResult.getAttribute('title');
if (currentSize && currentSize.trim() !== '') {
await expect(parseInt(currentSize, 10) <= toSize).toBe(true);
}
} catch (e) {
}
}
}); });
searchFilters.checkNameFilterIsDisplayed() searchFilters.checkNameFilterIsDisplayed()
@ -208,63 +221,30 @@ describe('Search Number Range Filter', () => {
searchResults.sortBySize(false); searchResults.sortBySize(false);
browser.controlFlow().execute(async () => { browser.controlFlow().execute(async () => {
let firstResult = await dataTable.getFirstElementDetail('Node id'); let results = await dataTable.geCellElementDetail('Size');
await this.alfrescoJsApi.core.nodesApi.getNode(firstResult).then(async (node) => { for (let currentResult of results) {
await expect(node.entry.content.sizeInBytes <= toSize).toBe(true); try {
let name = node.entry.name; let currentSize = await currentResult.getAttribute('title');
await expect(/z*/i.test(name)).toBe(true); if (currentSize && currentSize.trim() !== '') {
}); await expect(parseInt(currentSize, 10) <= toSize).toBe(true);
}
} catch (e) {
}
}
}); });
});
it('[C276950] Should be able to filter by size (slider) when size range filter is applied', () => {
let sizeSliderFilter = searchFilters.sizeSliderFilterPage();
let toSize = 20;
let sliderSize = 18;
searchFilters.checkSizeSliderFilterIsDisplayed()
.clickSizeSliderFilterHeader()
.checkSizeSliderFilterIsExpanded();
sizeSliderFilter.checkSliderIsDisplayed().setValue(sliderSize);
sizeRangeFilter.checkFromFieldIsDisplayed()
.putFromNumber(0)
.putToNumber(toSize);
expect(sizeRangeFilter.checkApplyButtonIsEnabled()).toBe(true);
sizeRangeFilter.clickApplyButton();
searchResults.sortBySize(false);
searchResults.tableIsLoaded();
browser.controlFlow().execute(async () => { browser.controlFlow().execute(async () => {
let firstResult = await dataTable.getFirstElementDetail('Node id'); let results = await dataTable.geCellElementDetail('Display name');
await this.alfrescoJsApi.core.nodesApi.getNode(firstResult).then(async (node) => { for (let currentResult of results) {
await expect(node.entry.content.sizeInBytes <= sliderSize).toBe(true); try {
}); let name = await currentResult.getAttribute('title');
if (name && name.trim() !== '') {
await expect(/z*/i.test(name)).toBe(true);
}
} catch (e) {
}
}
}); });
sizeRangeFilter.checkFromFieldIsDisplayed()
.putFromNumber(1);
expect(sizeRangeFilter.checkApplyButtonIsEnabled()).toBe(true);
sizeRangeFilter.clickApplyButton();
searchResults.sortBySize(true);
searchResults.tableIsLoaded();
browser.controlFlow().execute(async () => {
let firstResult = await dataTable.getFirstElementDetail('Node id');
await this.alfrescoJsApi.core.nodesApi.getNode(firstResult).then(async (node) => {
await expect(node.entry.content.sizeInBytes >= 1).toBe(true);
await expect(node.entry.content.sizeInBytes <= sliderSize).toBe(true);
});
});
sizeRangeFilter.checkFromFieldIsDisplayed()
.putFromNumber(19);
expect(sizeRangeFilter.checkApplyButtonIsEnabled()).toBe(true);
sizeRangeFilter.clickApplyButton();
searchResults.checkNoResultMessageIsDisplayed();
}); });
it('[C276951] Should not display folders when Size range is applied', () => { it('[C276951] Should not display folders when Size range is applied', () => {
@ -297,11 +277,18 @@ describe('Search Number Range Filter', () => {
searchResults.sortBySize(false); searchResults.sortBySize(false);
browser.controlFlow().execute(async () => { browser.controlFlow().execute(async () => {
let firstResult = await dataTable.getFirstElementDetail('Node id'); let results = await dataTable.geCellElementDetail('Size');
await this.alfrescoJsApi.core.nodesApi.getNode(firstResult).then(async (node) => { for (let currentResult of results) {
await expect(node.entry.content.sizeInBytes).toEqual(0); try {
}); let currentSize = await currentResult.getAttribute('title');
if (currentSize && currentSize.trim() !== '') {
await expect(currentSize === '0').toBe(true);
}
} catch (e) {
}
}
}); });
}); });
it('[C277092] Should disable apply button when from field value equal/is bigger than to field value', () => { it('[C277092] Should disable apply button when from field value equal/is bigger than to field value', () => {
@ -328,10 +315,17 @@ describe('Search Number Range Filter', () => {
searchResults.sortBySize(false); searchResults.sortBySize(false);
browser.controlFlow().execute(async () => { browser.controlFlow().execute(async () => {
let firstResult = await dataTable.getFirstElementDetail('Node id'); let results = await dataTable.geCellElementDetail('Size');
await this.alfrescoJsApi.core.nodesApi.getNode(firstResult).then(async (node) => { for (let currentResult of results) {
await expect(node.entry.content.sizeInBytes <= 1).toBe(true); try {
});
let currentSize = await currentResult.getAttribute('title');
if (currentSize && currentSize.trim() !== '') {
await expect(parseInt(currentSize, 10) <= 1000).toBe(true);
}
} catch (e) {
}
}
}); });
sizeRangeFilter.clickClearButton(); sizeRangeFilter.clickClearButton();
@ -340,10 +334,17 @@ describe('Search Number Range Filter', () => {
expect(sizeRangeFilter.getToNumber()).toEqual(''); expect(sizeRangeFilter.getToNumber()).toEqual('');
browser.controlFlow().execute(async () => { browser.controlFlow().execute(async () => {
let firstResult = await dataTable.getFirstElementDetail('Node id'); let results = await dataTable.geCellElementDetail('Size');
await this.alfrescoJsApi.core.nodesApi.getNode(firstResult).then(async (node) => { for (let currentResult of results) {
await expect(node.entry.content.sizeInBytes >= 1).toBe(true); try {
});
let currentSize = await currentResult.getAttribute('title');
if (currentSize && currentSize.trim() !== '') {
await expect(parseInt(currentSize, 10) >= 1000).toBe(true);
}
} catch (e) {
}
}
}); });
}); });
@ -426,20 +427,18 @@ describe('Search Number Range Filter', () => {
searchResults.sortByCreated(false); searchResults.sortByCreated(false);
browser.controlFlow().execute(async () => { browser.controlFlow().execute(async () => {
let firstResult = await dataTable.getFirstElementDetail('Node id'); let results = await dataTable.geCellElementDetail('Created');
await this.alfrescoJsApi.core.nodesApi.getNode(firstResult).then(async (node) => { for (let currentResult of results) {
await expect((node.entry.createdAt.getFullYear()) <= toYear).toBe(true); currentResult.getAttribute('title').then(async (currentDate) => {
}); let currentDateFormatted = DateUtil.parse(currentDate, 'MMM DD, YYYY, h:mm:ss a');
await expect(currentDateFormatted.getFullYear() <= toYear).toBe(true);
await expect(currentDateFormatted.getFullYear() >= fromYear).toBe(true);
});
}
}); });
searchResults.sortByCreated(true);
browser.controlFlow().execute(async () => {
let firstResult = await dataTable.getFirstElementDetail('Node id');
await this.alfrescoJsApi.core.nodesApi.getNode(firstResult).then(async (node) => {
await expect((node.entry.createdAt.getFullYear()) >= fromYear).toBe(true);
});
});
}); });
it('[C277139] Should be able to set To field to be exclusive', () => { it('[C277139] Should be able to set To field to be exclusive', () => {

View File

@ -123,10 +123,16 @@ describe('Search Number Range Filter', () => {
.tableIsLoaded(); .tableIsLoaded();
browser.controlFlow().execute(async () => { browser.controlFlow().execute(async () => {
let firstResult = await dataTable.getFirstElementDetail('Node id'); let results = await dataTable.geCellElementDetail('Size');
await this.alfrescoJsApi.core.nodesApi.getNode(firstResult).then(async (node) => { for (let currentResult of results) {
await expect(node.entry.content.sizeInBytes <= size).toBe(true); try {
}); let currentSize = await currentResult.getAttribute('title');
if (currentSize && currentSize.trim() !== '') {
await expect(parseInt(currentSize, 10) <= 5000).toBe(true);
}
} catch (e) {
}
}
}); });
sizeSliderFilter.checkSliderIsDisplayed() sizeSliderFilter.checkSliderIsDisplayed()
@ -136,10 +142,17 @@ describe('Search Number Range Filter', () => {
.tableIsLoaded(); .tableIsLoaded();
browser.controlFlow().execute(async () => { browser.controlFlow().execute(async () => {
let firstResult = await dataTable.getFirstElementDetail('Node id'); let results = await dataTable.geCellElementDetail('Size');
await this.alfrescoJsApi.core.nodesApi.getNode(firstResult).then(async (node) => { for (let currentResult of results) {
await expect(node.entry.content.sizeInBytes >= size).toBe(true); try {
});
let currentSize = await currentResult.getAttribute('title');
if (currentSize && currentSize.trim() !== '') {
await expect(parseInt(currentSize, 10) >= 5000).toBe(true);
}
} catch (e) {
}
}
}); });
}); });

View File

@ -176,110 +176,40 @@ describe('Search Sorting Picker', () => {
it('[C277280] Should be able to sort the search results by "Name" ASC', () => { it('[C277280] Should be able to sort the search results by "Name" ASC', () => {
searchFilters.checkSearchFiltersIsDisplayed(); searchFilters.checkSearchFiltersIsDisplayed();
searchFilters.creatorCheckListFiltersPage().filterBy(`${acsUser.firstName} ${acsUser.lastName}`); searchFilters.creatorCheckListFiltersPage().filterBy(`${acsUser.firstName} ${acsUser.lastName}`);
expect(searchResults.sortAndCheckListIsOrderedByName(true)).toBe(true); searchResults.sortByName(true);
expect(searchResults.checkListIsOrderedByNameAsc()).toBe(true);
}); });
it('[C277281] Should be able to sort the search results by "Name" DESC', () => { it('[C277281] Should be able to sort the search results by "Name" DESC', () => {
searchFilters.checkSearchFiltersIsDisplayed(); searchFilters.checkSearchFiltersIsDisplayed();
searchFilters.creatorCheckListFiltersPage().filterBy(`${acsUser.firstName} ${acsUser.lastName}`); searchFilters.creatorCheckListFiltersPage().filterBy(`${acsUser.firstName} ${acsUser.lastName}`);
expect(searchResults.sortAndCheckListIsOrderedByName(false)).toBe(true); searchResults.sortByName(false);
expect(searchResults.checkListIsOrderedByNameDesc()).toBe(true);
}); });
it('[C277282] Should be able to sort the search results by "Author" ASC', () => { it('[C277282] Should be able to sort the search results by "Author" ASC', () => {
expect(searchResults.sortAndCheckListIsOrderedByAuthor(this.alfrescoJsApi, true)).toBe(true); searchResults.sortByAuthor(true);
expect(searchResults.checkListIsOrderedByAuthorAsc()).toBe(true);
}); });
it('[C277283] Should be able to sort the search results by "Author" DESC', () => { it('[C277283] Should be able to sort the search results by "Author" DESC', () => {
expect(searchResults.sortAndCheckListIsOrderedByAuthor(this.alfrescoJsApi, false)).toBe(true); searchResults.sortByAuthor(false);
}); expect(searchResults.checkListIsOrderedByAuthorDesc()).toBe(true);
it('[C277284] Should be able to sort the search results by "Modifier" ASC', () => {
let searchConfiguration = new SearchConfiguration();
jsonFile = searchConfiguration.getConfiguration();
navigationBar.clickConfigEditorButton();
configEditor.clickSearchConfiguration();
configEditor.clickClearButton();
jsonFile.sorting.options.push({ 'key': 'Modifier', 'label': 'Modifier', 'type': 'FIELD', 'field': 'cm:modifier', 'ascending': true });
configEditor.enterBigConfigurationText(JSON.stringify(jsonFile));
configEditor.clickSaveButton();
searchDialog.checkSearchIconIsVisible()
.clickOnSearchIcon()
.enterTextAndPressEnter(search);
searchSortingPicker.checkSortingSelectorIsDisplayed()
.sortBy(true, 'Modifier');
browser.controlFlow().execute(async () => {
let idList = await contentServices.getElementsDisplayedId();
let numberOfElements = await contentServices.numberOfResultsDisplayed();
let nodeList = await nodeActions.getNodesDisplayed(this.alfrescoJsApi, idList, numberOfElements);
let modifierList = [];
for (let i = 0; i < nodeList.length; i++) {
modifierList.push(nodeList[i].entry.modifiedByUser.id);
}
expect(contentServices.checkElementsSortedAsc(modifierList)).toBe(true);
});
});
it('[C277285] Should be able to sort the search results by "Modifier" DESC', () => {
let searchConfiguration = new SearchConfiguration();
jsonFile = searchConfiguration.getConfiguration();
navigationBar.clickConfigEditorButton();
configEditor.clickSearchConfiguration();
configEditor.clickClearButton();
jsonFile.sorting.options.push({ 'key': 'Modifier', 'label': 'Modifier', 'type': 'FIELD', 'field': 'cm:modifier', 'ascending': true });
configEditor.enterBigConfigurationText(JSON.stringify(jsonFile));
configEditor.clickSaveButton();
searchDialog.checkSearchIconIsVisible()
.clickOnSearchIcon()
.enterTextAndPressEnter(search);
searchSortingPicker.checkSortingSelectorIsDisplayed()
.sortBy(false, 'Modifier');
browser.controlFlow().execute(async () => {
let idList = await contentServices.getElementsDisplayedId();
let numberOfElements = await contentServices.numberOfResultsDisplayed();
let nodeList = await nodeActions.getNodesDisplayed(this.alfrescoJsApi, idList, numberOfElements);
let modifierList = [];
for (let i = 0; i < nodeList.length; i++) {
modifierList.push(nodeList[i].entry.modifiedByUser.id);
}
expect(contentServices.checkElementsSortedDesc(modifierList)).toBe(true);
});
}); });
it('[C277286] Should be able to sort the search results by "Created Date" ASC', () => { it('[C277286] Should be able to sort the search results by "Created Date" ASC', () => {
searchResults.sortByCreated(true); searchResults.sortByCreated(true);
browser.controlFlow().execute(async () => { browser.controlFlow().execute(async () => {
let idList = await contentServices.getElementsDisplayedId(); let results = await searchResults. dataTable.geCellElementDetail('Created');
let numberOfElements = await contentServices.numberOfResultsDisplayed(); expect(contentServices.checkElementsSortedAsc(results)).toBe(true);
let nodeList = await nodeActions.getNodesDisplayed(this.alfrescoJsApi, idList, numberOfElements);
let dateList = [];
for (let i = 0; i < nodeList.length; i++) {
dateList.push(new Date(nodeList[i].entry.createdAt));
}
expect(contentServices.checkElementsSortedAsc(dateList)).toBe(true);
}); });
}); });
it('[C277287] Should be able to sort the search results by "Created Date" DESC', () => { it('[C277287] Should be able to sort the search results by "Created Date" DESC', () => {
searchResults.sortByCreated(false); searchResults.sortByCreated(false);
browser.controlFlow().execute(async () => { browser.controlFlow().execute(async () => {
let idList = await contentServices.getElementsDisplayedId(); let results = await searchResults. dataTable.geCellElementDetail('Created');
let numberOfElements = await contentServices.numberOfResultsDisplayed(); expect(contentServices.checkElementsSortedDesc(results)).toBe(true);
let nodeList = await nodeActions.getNodesDisplayed(this.alfrescoJsApi, idList, numberOfElements);
let dateList = [];
for (let i = 0; i < nodeList.length; i++) {
dateList.push(new Date(nodeList[i].entry.createdAt));
}
expect(contentServices.checkElementsSortedDesc(dateList)).toBe(true);
}); });
}); });
@ -313,36 +243,6 @@ describe('Search Sorting Picker', () => {
}); });
}); });
it('[C277289] Should be able to sort the search results by "Modified Date" DESC', () => {
let searchConfiguration = new SearchConfiguration();
jsonFile = searchConfiguration.getConfiguration();
navigationBar.clickConfigEditorButton();
configEditor.clickSearchConfiguration();
configEditor.clickClearButton();
jsonFile.sorting.options.push({ 'key': 'Modified Date', 'label': 'Modified Date', 'type': 'FIELD', 'field': 'cm:modified', 'ascending': true });
configEditor.enterBigConfigurationText(JSON.stringify(jsonFile));
configEditor.clickSaveButton();
searchDialog.checkSearchIconIsVisible()
.clickOnSearchIcon()
.enterTextAndPressEnter(search);
searchSortingPicker.checkSortingSelectorIsDisplayed()
.sortBy(false, 'Modified Date');
browser.controlFlow().execute(async () => {
let idList = await contentServices.getElementsDisplayedId();
let numberOfElements = await contentServices.numberOfResultsDisplayed();
let nodeList = await nodeActions.getNodesDisplayed(this.alfrescoJsApi, idList, numberOfElements);
let modifiedDateList = [];
for (let i = 0; i < nodeList.length; i++) {
modifiedDateList.push(new Date(nodeList[i].entry.modifiedAt));
}
expect(contentServices.checkElementsSortedAsc(modifiedDateList)).toBe(false);
});
});
it('[C277290] Should be able to sort the search results by "Size" ASC', () => { it('[C277290] Should be able to sort the search results by "Size" ASC', () => {
searchResults.sortBySize(true); searchResults.sortBySize(true);
expect(searchResults.checkListIsOrderedBySizeAsc()).toBe(true); expect(searchResults.checkListIsOrderedBySizeAsc()).toBe(true);

View File

@ -179,101 +179,6 @@ describe('Search component - Search Page', () => {
searchResultPage.checkNoResultMessageIsDisplayed(); searchResultPage.checkNoResultMessageIsDisplayed();
}); });
describe('Sorting', () => {
beforeEach(() => {
searchDialog
.clickOnSearchIcon()
.enterTextAndPressEnter(search.active.base);
});
afterEach(async (done) => {
await browser.refresh();
done();
});
it('[C272803] Should be able to sort results by name (Ascending)', () => {
searchResultPage.checkContentIsDisplayed(search.active.secondFile);
searchResultPage.sortAndCheckListIsOrderedByName(true).then((result) => {
expect(result).toEqual(true);
});
});
it('[C272804] Should be able to sort results by name (Descending)', () => {
searchResultPage.checkContentIsDisplayed(search.active.secondFile);
searchResultPage.sortAndCheckListIsOrderedByName(false).then((result) => {
expect(result).toEqual(true);
});
});
it('[C272805] Should be able to sort results by author (Ascending)', () => {
searchResultPage.checkContentIsDisplayed(search.active.secondFile);
searchResultPage.sortAndCheckListIsOrderedByAuthor(this.alfrescoJsApi, true).then((result) => {
expect(result).toEqual(true);
});
});
it('[C272806] Should be able to sort results by author (Descending)', () => {
searchResultPage.checkContentIsDisplayed(search.active.secondFile);
searchResultPage.sortAndCheckListIsOrderedByAuthor(this.alfrescoJsApi, false).then((result) => {
expect(result).toEqual(true);
});
});
it('[C272807] Should be able to sort results by date (Ascending)', () => {
searchResultPage.checkContentIsDisplayed(search.active.secondFile);
searchResultPage.sortAndCheckListIsOrderedByCreated(true).then((result) => {
expect(result).toEqual(true);
});
});
it('[C260260] Should be able to sort results by date (Descending)', () => {
searchResultPage.checkContentIsDisplayed(search.active.secondFile);
searchResultPage.sortAndCheckListIsOrderedByCreated(false).then((result) => {
expect(result).toEqual(true);
});
});
});
it('[C260262] Should not be able to delete a file from search results without rights', () => {
searchDialog
.clickOnSearchIcon()
.enterTextAndPressEnter(search.no_permission.noPermFile);
searchResultPage.checkContentIsDisplayed(search.no_permission.noPermFile);
searchResultPage.checkDeleteIsDisabled(search.no_permission.noPermFile);
searchResultPage.checkContentIsDisplayed(search.no_permission.noPermFile);
searchDialog.checkSearchBarIsNotVisible().checkSearchIconIsVisible().clickOnSearchIcon()
.enterTextAndPressEnter(search.no_permission.noPermFile);
searchResultPage.checkNoResultMessageIsNotDisplayed();
searchResultPage.checkContentIsDisplayed(search.no_permission.noPermFile);
});
it('[C272808] Should not be able to delete a folder from search results without rights', () => {
searchDialog
.clickOnSearchIcon()
.enterTextAndPressEnter(search.no_permission.noPermFolder);
searchResultPage.checkContentIsDisplayed(search.no_permission.noPermFolder);
searchResultPage.checkDeleteIsDisabled(search.no_permission.noPermFolder);
searchResultPage.checkContentIsDisplayed(search.no_permission.noPermFolder);
searchDialog
.clickOnSearchIcon()
.enterTextAndPressEnter(search.no_permission.noPermFolder);
searchResultPage.checkNoResultMessageIsNotDisplayed();
searchResultPage.checkContentIsDisplayed(search.no_permission.noPermFolder);
});
it('[C286675] Should display results when searching for all elements', () => { it('[C286675] Should display results when searching for all elements', () => {
searchDialog searchDialog
.clickOnSearchIcon() .clickOnSearchIcon()

View File

@ -20,11 +20,12 @@ import { FacetQuery } from './facet-query.interface';
import { FacetField } from './facet-field.interface'; import { FacetField } from './facet-field.interface';
import { SearchCategory } from './search-category.interface'; import { SearchCategory } from './search-category.interface';
import { SearchSortingDefinition } from './search-sorting-definition.interface'; import { SearchSortingDefinition } from './search-sorting-definition.interface';
import { RequestHighlight } from '@alfresco/js-api';
export interface SearchConfiguration { export interface SearchConfiguration {
include?: string[]; include?: string[];
fields?: string[]; fields?: string[];
categories: SearchCategory[]; categories?: SearchCategory[];
filterQueries?: FilterQuery[]; filterQueries?: FilterQuery[];
filterWithContains?: boolean; filterWithContains?: boolean;
resetButton?: boolean; resetButton?: boolean;
@ -47,4 +48,5 @@ export interface SearchConfiguration {
options: SearchSortingDefinition[]; options: SearchSortingDefinition[];
defaults: SearchSortingDefinition[]; defaults: SearchSortingDefinition[];
}; };
highlight?: RequestHighlight;
} }

View File

@ -190,10 +190,12 @@ describe('SearchQueryBuilder', () => {
it('should fetch facet from the config by label', () => { it('should fetch facet from the config by label', () => {
const config: SearchConfiguration = { const config: SearchConfiguration = {
categories: [], categories: [],
facetFields: { 'fields': [ facetFields: {
{ 'field': 'content.mimetype', 'mincount': 1, 'label': 'Type' }, 'fields': [
{ 'field': 'content.size', 'mincount': 1, 'label': 'Size' } { 'field': 'content.mimetype', 'mincount': 1, 'label': 'Type' },
]} { 'field': 'content.size', 'mincount': 1, 'label': 'Size' }
]
}
}; };
const builder = new SearchQueryBuilderService(buildConfig(config), null); const builder = new SearchQueryBuilderService(buildConfig(config), null);
const field = builder.getFacetField('Size'); const field = builder.getFacetField('Size');
@ -205,10 +207,12 @@ describe('SearchQueryBuilder', () => {
it('should not fetch facet from the config by label', () => { it('should not fetch facet from the config by label', () => {
const config: SearchConfiguration = { const config: SearchConfiguration = {
categories: [], categories: [],
facetFields: { 'fields': [ facetFields: {
{ 'field': 'content.mimetype', 'mincount': 1, 'label': 'Type' }, 'fields': [
{ 'field': 'content.size', 'mincount': 1, 'label': 'Size' } { 'field': 'content.mimetype', 'mincount': 1, 'label': 'Type' },
]} { 'field': 'content.size', 'mincount': 1, 'label': 'Size' }
]
}
}; };
const builder = new SearchQueryBuilderService(buildConfig(config), null); const builder = new SearchQueryBuilderService(buildConfig(config), null);
const field = builder.getFacetField('Missing'); const field = builder.getFacetField('Missing');
@ -373,10 +377,12 @@ describe('SearchQueryBuilder', () => {
categories: [ categories: [
<any> { id: 'cat1', enabled: true } <any> { id: 'cat1', enabled: true }
], ],
facetFields: { fields: [ facetFields: {
{ field: 'field1', label: 'field1', mincount: 1, limit: null, offset: 0, prefix: null }, fields: [
{ field: 'field2', label: 'field2', mincount: 1, limit: null, offset: 0, prefix: null } { field: 'field1', label: 'field1', mincount: 1, limit: null, offset: 0, prefix: null },
]} { field: 'field2', label: 'field2', mincount: 1, limit: null, offset: 0, prefix: null }
]
}
}; };
const builder = new SearchQueryBuilderService(buildConfig(config), null); const builder = new SearchQueryBuilderService(buildConfig(config), null);
builder.queryFragments['cat1'] = 'cm:name:test'; builder.queryFragments['cat1'] = 'cm:name:test';
@ -588,4 +594,23 @@ describe('SearchQueryBuilder', () => {
expect(compiledQuery.query.query).toBe(expectedResult); expect(compiledQuery.query.query).toBe(expectedResult);
}); });
it('should use highlight in the queries', () => {
const config: SearchConfiguration = {
highlight: {
'prefix': 'my-prefix',
'postfix': 'my-postfix',
'mergeContiguous': true
}
};
const builder = new SearchQueryBuilderService(buildConfig(config), null);
builder.userQuery = 'my query';
builder.queryFragments['cat1'] = 'cm:name:test';
const compiled = builder.buildQuery();
expect(compiled.highlight.prefix).toBe('my-prefix');
expect(compiled.highlight.postfix).toBe('my-postfix');
expect(compiled.highlight.mergeContiguous).toBe(true);
});
}); });

View File

@ -23,7 +23,8 @@ import {
RequestFacetFields, RequestFacetFields,
RequestFacetField, RequestFacetField,
RequestSortDefinitionInner, RequestSortDefinitionInner,
ResultSetPaging ResultSetPaging,
RequestHighlight
} from '@alfresco/js-api'; } from '@alfresco/js-api';
import { SearchCategory } from './search-category.interface'; import { SearchCategory } from './search-category.interface';
import { FilterQuery } from './filter-query.interface'; import { FilterQuery } from './filter-query.interface';
@ -227,7 +228,8 @@ export class SearchQueryBuilderService {
facetQueries: this.facetQueries, facetQueries: this.facetQueries,
facetIntervals: this.facetIntervals, facetIntervals: this.facetIntervals,
facetFields: this.facetFields, facetFields: this.facetFields,
sort: this.sort sort: this.sort,
highlight: this.highlight
}; };
result['facetFormat'] = 'V2'; result['facetFormat'] = 'V2';
@ -296,6 +298,10 @@ export class SearchQueryBuilderService {
return false; return false;
} }
get hasFacetHighlight(): boolean {
return this.config && this.config.highlight ? true : false;
}
protected get sort(): RequestSortDefinitionInner[] { protected get sort(): RequestSortDefinitionInner[] {
return this.sorting.map((def) => { return this.sorting.map((def) => {
return new RequestSortDefinitionInner({ return new RequestSortDefinitionInner({
@ -339,6 +345,10 @@ export class SearchQueryBuilderService {
return null; return null;
} }
protected get highlight(): RequestHighlight {
return this.hasFacetHighlight ? this.config.highlight : null;
}
protected getFinalQuery(): string { protected getFinalQuery(): string {
let query = ''; let query = '';

View File

@ -1117,7 +1117,6 @@
], ],
"properties": { "properties": {
"id": { "id": {
"type": "string"
}, },
"name": { "name": {
"type": "string" "type": "string"
@ -1148,6 +1147,68 @@
} }
} }
}, },
"highlight": {
"description": " Request that highlight fragments to be added to result set rows The properties reflect SOLR highlighting parameters.",
"properties": {
"prefix": {
"description": "The string used to mark the start of a highlight in a fragment",
"type": "string"
},
"postfix": {
"description": "The string used to mark the end of a highlight in a fragment",
"type": "string"
},
"snippetCount": {
"description": "The maximum number of distinct highlight snippets to return for each highlight field",
"type": "number"
},
"fragmentSize": {
"description": "The character length of each snippet",
"type": "number"
},
"maxAnalyzedChars": {
"description": "The number of characters to be considered for highlighting. Matches after this count will not be shown",
"type": "number"
},
"mergeContiguous": {
"description": "If fragments over lap they can be merged into one larger fragment",
"type": "boolean"
},
"usePhraseHighlighter": {
"description": "Should phrases be identified",
"type": "boolean"
},
"fields": {
"type": "array",
"minItems": 1,
"items": {
"description": "The fields to highlight and field specific configuration properties for each field",
"type": "object",
"properties": {
"field": {
"description": "The name of the field to highlight",
"type": "string"
},
"snippetCount": {
"type": "number"
},
"fragmentSize": {
"type": "number"
},
"mergeContiguous": {
"type": "boolean"
},
"prefix": {
"type": "string"
},
"postfix": {
"type": "string"
}
}
}
}
}
},
"sorting": { "sorting": {
"description": "Sorting options and defaults", "description": "Sorting options and defaults",
"required": [ "required": [

View File

@ -96,10 +96,13 @@ describe('EditProcessFilterCloudComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
const title = fixture.debugElement.nativeElement.querySelector('#adf-edit-process-filter-title-id'); const title = fixture.debugElement.nativeElement.querySelector('#adf-edit-process-filter-title-id');
const subTitle = fixture.debugElement.nativeElement.querySelector('#adf-edit-process-filter-sub-title-id'); const subTitle = fixture.debugElement.nativeElement.querySelector('#adf-edit-process-filter-sub-title-id');
expect(title).toBeDefined();
expect(subTitle).toBeDefined(); fixture.whenStable().then(() => {
expect(title.innerText).toEqual('FakeRunningProcess'); expect(title).toBeDefined();
expect(subTitle.innerText.trim()).toEqual('ADF_CLOUD_EDIT_PROCESS_FILTER.TITLE'); expect(subTitle).toBeDefined();
expect(title.innerText).toEqual('FakeRunningProcess');
expect(subTitle.innerText.trim()).toEqual('ADF_CLOUD_EDIT_PROCESS_FILTER.TITLE');
});
}); });
describe('EditProcessFilter form', () => { describe('EditProcessFilter form', () => {