mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-4552][ADF-4482] Social component refactoring, add ability to unRate, added e2e automation (#4749)
* [ADF-4552] Rating component refactoring, add ability to unRate * [ADF-4552] RTL support added * [ADF-4552] Improve behaviour and styling structure in RTL languages * [ADF-4552] Improve behaviour and styling structure in RTL languages * [ADF-4552] Added refresh rating when the node Id input changes * [ADF-4552][ADF-4482] Refactor social component, add ability to unrate, add e2e automation * [ADF-4552][ADF-4482] Added unsibscribe from Observables, added css variables, removed unused class id's * [ADF-4552][ADF-4482] Improve structure and behaviour of e2e automation tests * [ADF-4552][ADF-4482] Improve structure and behaviour of e2e automation tests * [ADF-4552][ADF-4482] fix expected single space * [ADF-4552][ADF-4482] fix lint check failure * Fix circular dependency error
This commit is contained in:
committed by
Eugenio Romano
parent
b19646d201
commit
3d67d9dc75
@@ -7,10 +7,18 @@ Last reviewed: 2019-01-14
|
||||
|
||||
# [Rating component](../../../lib/content-services/social/rating.component.ts "Defined in rating.component.ts")
|
||||
|
||||
Allows a user to add ratings to an item.
|
||||
Allows a user to add and remove rating to an item.
|
||||
It displays the average rating and the number of ratings. If the user has not rated the item the average rating stars color is grey.
|
||||
|
||||

|
||||
|
||||
If the user has rated the item the average rating stars color is yellow.
|
||||
|
||||

|
||||
|
||||
In order to remove the rating the user should click on the same star that he rated.
|
||||
If the average is decimal number it will be rounded.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```html
|
||||
@@ -31,7 +39,7 @@ Allows a user to add ratings to an item.
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| changeVote | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<Object>` | Emitted when the "vote" gets changed. |
|
||||
| changeVote | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<Object>` | Average rating is emitted when the "vote" gets changed. |
|
||||
|
||||
## See also
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 9.9 KiB |
BIN
docs/docassets/images/social3.png
Normal file
BIN
docs/docassets/images/social3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.3 KiB |
209
e2e/content-services/social/social.component.e2e.ts
Normal file
209
e2e/content-services/social/social.component.e2e.ts
Normal file
@@ -0,0 +1,209 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { LoginPage, LikePage, RatePage } from '@alfresco/adf-testing';
|
||||
import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api';
|
||||
import { AcsUserModel } from '../../models/ACS/acsUserModel';
|
||||
import { FileModel } from '../../models/ACS/fileModel';
|
||||
import resources = require('../../util/resources');
|
||||
import { UploadActions } from '../../actions/ACS/upload.actions';
|
||||
import { NavigationBarPage } from '../../pages/adf/navigationBarPage';
|
||||
import { SocialPage } from '../../pages/adf/demo-shell/socialPage';
|
||||
import { browser } from 'protractor';
|
||||
|
||||
describe('Social component', () => {
|
||||
|
||||
const loginPage = new LoginPage();
|
||||
const likePage = new LikePage();
|
||||
const ratePage = new RatePage();
|
||||
const socialPage = new SocialPage();
|
||||
const navigationBarPage = new NavigationBarPage();
|
||||
const componentOwner = new AcsUserModel();
|
||||
const componentVisitor = new AcsUserModel();
|
||||
const secondComponentVisitor = new AcsUserModel();
|
||||
const uploadActions = new UploadActions();
|
||||
|
||||
const blueLikeColor = ('rgba(33, 150, 243, 1)');
|
||||
const greyLikeColor = ('rgba(128, 128, 128, 1)');
|
||||
const yellowRatedStarColor = ('rgba(255, 233, 68, 1)');
|
||||
const averageStarColor = ('rgba(128, 128, 128, 1)');
|
||||
|
||||
let emptyFile;
|
||||
|
||||
const emptyFileModel = new FileModel({
|
||||
'name': resources.Files.ADF_DOCUMENTS.TXT_0B.file_name,
|
||||
'location': resources.Files.ADF_DOCUMENTS.TXT_0B.file_location
|
||||
});
|
||||
|
||||
beforeAll(async (done) => {
|
||||
this.alfrescoJsApi = new AlfrescoApi({
|
||||
provider: 'ECM',
|
||||
hostEcm: browser.params.testConfig.adf.url
|
||||
});
|
||||
|
||||
await this.alfrescoJsApi.login(browser.params.testConfig.adf.adminEmail, browser.params.testConfig.adf.adminPassword);
|
||||
|
||||
await this.alfrescoJsApi.core.peopleApi.addPerson(componentOwner);
|
||||
|
||||
await this.alfrescoJsApi.core.peopleApi.addPerson(componentVisitor);
|
||||
|
||||
await this.alfrescoJsApi.core.peopleApi.addPerson(secondComponentVisitor);
|
||||
|
||||
await this.alfrescoJsApi.login(componentOwner.id, componentOwner.password);
|
||||
|
||||
emptyFile = await uploadActions.uploadFile(this.alfrescoJsApi, emptyFileModel.location, emptyFileModel.name, '-my-');
|
||||
|
||||
await this.alfrescoJsApi.core.nodesApi.updateNode(emptyFile.entry.id,
|
||||
|
||||
{
|
||||
permissions: {
|
||||
locallySet: [{
|
||||
authorityId: componentVisitor.getId(),
|
||||
name: 'Consumer',
|
||||
accessStatus: 'ALLOWED'
|
||||
}, {
|
||||
authorityId: secondComponentVisitor.getId(),
|
||||
name: 'Consumer',
|
||||
accessStatus: 'ALLOWED'
|
||||
}]
|
||||
}
|
||||
});
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
afterAll(async (done) => {
|
||||
await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, emptyFile.entry.id);
|
||||
done();
|
||||
});
|
||||
|
||||
describe('User interaction on their own components', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await loginPage.loginToContentServicesUsingUserModel(componentOwner);
|
||||
await navigationBarPage.clickSocialButton();
|
||||
});
|
||||
|
||||
it('[C203006] Should be able to like and unlike their components but not rate them,', () => {
|
||||
socialPage.writeCustomNodeId(emptyFile.entry.id);
|
||||
expect(socialPage.getNodeIdFieldValue()).toEqual(emptyFile.entry.id);
|
||||
likePage.clickLike();
|
||||
expect(likePage.getLikeCounter()).toBe('1');
|
||||
likePage.removeHoverFromLikeButton();
|
||||
expect(likePage.getLikedIconColor()).toBe(blueLikeColor);
|
||||
ratePage.rateComponent(4);
|
||||
expect(ratePage.getRatingCounter()).toBe('0');
|
||||
expect(ratePage.isNotStarRated(4));
|
||||
expect(ratePage.getUnratedStarColor(4)).toBe(averageStarColor);
|
||||
likePage.clickUnlike();
|
||||
expect(likePage.getLikeCounter()).toBe('0');
|
||||
likePage.removeHoverFromLikeButton();
|
||||
expect(likePage.getUnLikedIconColor()).toBe(greyLikeColor);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('User interaction on components that belong to other users', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await loginPage.loginToContentServicesUsingUserModel(componentVisitor);
|
||||
await navigationBarPage.clickSocialButton();
|
||||
});
|
||||
|
||||
it('[C260324] Should be able to like and unlike a component', () => {
|
||||
socialPage.writeCustomNodeId(emptyFile.entry.id);
|
||||
expect(socialPage.getNodeIdFieldValue()).toEqual(emptyFile.entry.id);
|
||||
expect(likePage.getLikeCounter()).toEqual('0');
|
||||
expect(likePage.getUnLikedIconColor()).toBe(greyLikeColor);
|
||||
likePage.clickLike();
|
||||
expect(likePage.getLikeCounter()).toBe('1');
|
||||
likePage.removeHoverFromLikeButton();
|
||||
expect(likePage.getLikedIconColor()).toBe(blueLikeColor);
|
||||
likePage.clickUnlike();
|
||||
expect(likePage.getLikeCounter()).toBe('0');
|
||||
likePage.removeHoverFromLikeButton();
|
||||
expect(likePage.getUnLikedIconColor()).toBe(greyLikeColor);
|
||||
});
|
||||
|
||||
it('[C310198] Should be able to rate and unRate a component', () => {
|
||||
socialPage.writeCustomNodeId(emptyFile.entry.id);
|
||||
expect(socialPage.getNodeIdFieldValue()).toEqual(emptyFile.entry.id);
|
||||
expect(ratePage.getRatingCounter()).toBe('0');
|
||||
ratePage.rateComponent(4);
|
||||
expect(ratePage.getRatingCounter()).toBe('1');
|
||||
expect(ratePage.isStarRated(4));
|
||||
expect(ratePage.getRatedStarColor(4)).toBe(yellowRatedStarColor);
|
||||
ratePage.removeRating(4);
|
||||
expect(ratePage.getRatingCounter()).toBe('0');
|
||||
expect(ratePage.isNotStarRated(4));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Multiple Users interaction', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await loginPage.loginToContentServicesUsingUserModel(componentVisitor);
|
||||
await navigationBarPage.clickSocialButton();
|
||||
});
|
||||
|
||||
it('[C310197] Should be able to like, unLike, display total likes', async () => {
|
||||
socialPage.writeCustomNodeId(emptyFile.entry.id);
|
||||
expect(socialPage.getNodeIdFieldValue()).toEqual(emptyFile.entry.id);
|
||||
expect(likePage.getUnLikedIconColor()).toBe(greyLikeColor);
|
||||
likePage.clickLike();
|
||||
expect(likePage.getLikeCounter()).toBe('1');
|
||||
likePage.removeHoverFromLikeButton();
|
||||
expect(likePage.getLikedIconColor()).toBe(blueLikeColor);
|
||||
|
||||
await loginPage.loginToContentServicesUsingUserModel(secondComponentVisitor);
|
||||
navigationBarPage.clickSocialButton();
|
||||
socialPage.writeCustomNodeId(emptyFile.entry.id);
|
||||
expect(likePage.getUnLikedIconColor()).toBe(greyLikeColor);
|
||||
likePage.clickLike();
|
||||
expect(likePage.getLikeCounter()).toEqual('2');
|
||||
likePage.removeHoverFromLikeButton();
|
||||
expect(likePage.getLikedIconColor()).toBe(blueLikeColor);
|
||||
likePage.clickUnlike();
|
||||
expect(likePage.getLikeCounter()).toEqual('1');
|
||||
likePage.removeHoverFromLikeButton();
|
||||
expect(likePage.getUnLikedIconColor()).toBe(greyLikeColor);
|
||||
});
|
||||
|
||||
it('[C260327] Should be able to rate, unRate, display total ratings, display average rating', async () => {
|
||||
socialPage.writeCustomNodeId(emptyFile.entry.id);
|
||||
expect(socialPage.getNodeIdFieldValue()).toEqual(emptyFile.entry.id);
|
||||
ratePage.rateComponent(4);
|
||||
expect(ratePage.getRatingCounter()).toEqual('1');
|
||||
expect(ratePage.isStarRated(4));
|
||||
expect(ratePage.getRatedStarColor(4)).toBe(yellowRatedStarColor);
|
||||
|
||||
await loginPage.loginToContentServicesUsingUserModel(secondComponentVisitor);
|
||||
navigationBarPage.clickSocialButton();
|
||||
socialPage.writeCustomNodeId(emptyFile.entry.id);
|
||||
expect(socialPage.getNodeIdFieldValue()).toEqual(emptyFile.entry.id);
|
||||
expect(ratePage.getRatingCounter()).toEqual('1');
|
||||
expect(ratePage.getAverageStarColor(4)).toBe(averageStarColor);
|
||||
ratePage.rateComponent(0);
|
||||
expect(ratePage.getRatingCounter()).toEqual('2');
|
||||
expect(ratePage.isStarRated(2));
|
||||
ratePage.removeRating(0);
|
||||
expect(ratePage.getRatingCounter()).toEqual('1');
|
||||
expect(ratePage.getAverageStarColor(4)).toBe(averageStarColor);
|
||||
});
|
||||
});
|
||||
});
|
34
e2e/pages/adf/demo-shell/socialPage.ts
Normal file
34
e2e/pages/adf/demo-shell/socialPage.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { by, element } from 'protractor';
|
||||
import { BrowserActions, BrowserVisibility } from '@alfresco/adf-testing';
|
||||
|
||||
export class SocialPage {
|
||||
|
||||
nodeIdField = element(by.css(`input[id="nodeId"]`));
|
||||
|
||||
getNodeIdFieldValue() {
|
||||
BrowserVisibility.waitUntilElementIsVisible(this.nodeIdField);
|
||||
return this.nodeIdField.getAttribute('value');
|
||||
}
|
||||
|
||||
writeCustomNodeId(nodeId: string) {
|
||||
return BrowserActions.clearSendKeys(this.nodeIdField, nodeId);
|
||||
}
|
||||
|
||||
}
|
@@ -47,6 +47,10 @@ export class NavigationBarPage {
|
||||
BrowserActions.clickExecuteScript(`.adf-sidenav-link[data-automation-id="${title}"]`);
|
||||
}
|
||||
|
||||
async clickSocialButton() {
|
||||
this.clickMenuButton('Social');
|
||||
}
|
||||
|
||||
async clickTagButton() {
|
||||
this.clickMenuButton('Tag');
|
||||
}
|
||||
|
@@ -5,7 +5,9 @@
|
||||
<mat-icon>thumb_up</mat-icon>
|
||||
</span>
|
||||
</div>
|
||||
<div class="adf-like-counter-container">
|
||||
<div id="adf-like-counter" class="adf-like-counter">{{likesCounter}}</div>
|
||||
<div class="adf-left" *ngIf="likesCounter<=1">Like</div>
|
||||
<div class="adf-left" *ngIf="likesCounter>1">Likes</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,42 +1,41 @@
|
||||
@mixin selected {
|
||||
color: #2196f3;
|
||||
}
|
||||
|
||||
@mixin unselected {
|
||||
color: #808080;
|
||||
}
|
||||
|
||||
.adf-like-container {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
margin-top: 13px;
|
||||
|
||||
.adf-like {
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
margin: 5px 0 5px 5px;
|
||||
.adf-like-counter-container {
|
||||
display: inherit;
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
.adf-left {
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
.adf-like-select {
|
||||
cursor: pointer;
|
||||
color: #2196f3;
|
||||
@include selected;
|
||||
&:hover {
|
||||
@include unselected;
|
||||
}
|
||||
|
||||
.adf-like-select:hover {
|
||||
cursor: pointer;
|
||||
color: #808080;
|
||||
}
|
||||
|
||||
.adf-like-grey {
|
||||
cursor: pointer;
|
||||
color: #808080;
|
||||
@include unselected;
|
||||
&:hover {
|
||||
@include selected;
|
||||
}
|
||||
|
||||
.adf-like-grey:hover {
|
||||
cursor: pointer;
|
||||
color: #2196f3;
|
||||
}
|
||||
|
||||
.adf-like-counter {
|
||||
float: left;
|
||||
padding: 13px 0 0;
|
||||
}
|
||||
|
||||
.adf-left {
|
||||
float: left;
|
||||
padding: 13px 0 0 4px;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,12 +1,18 @@
|
||||
<mat-list id="adf-rating-container" class="adf-rating-container">
|
||||
<mat-list-item class="adf-rating-star" *ngFor="let currentRate of stars; let idx = index">
|
||||
<mat-list-item class="adf-rating-star" *ngFor="let currentRate of stars; let idx = index;">
|
||||
<span id="adf-rate-{{idx}}">
|
||||
<mat-icon id="adf-grey-star-{{idx}}" *ngIf="currentRate.fill" class="adf-colored-star"
|
||||
<mat-icon id="adf-colored-star-{{idx}}" *ngIf="currentRate.fill" class="adf-colored-star"
|
||||
[ngClass]="{'adf-average-star': !ratingValue}"
|
||||
(click)="updateVote(idx + 1)">star_rate
|
||||
</mat-icon>
|
||||
<mat-icon id="adf-colored-star-{{idx}}" *ngIf="!currentRate.fill" class="adf-grey-star"
|
||||
<mat-icon id="adf-grey-star-{{idx}}" *ngIf="!currentRate.fill" class="adf-grey-star"
|
||||
(click)="updateVote(idx + 1)">star_border
|
||||
</mat-icon>
|
||||
</span>
|
||||
</mat-list-item>
|
||||
<div class="adf-rating-counter-container">
|
||||
<div id="adf-rating-counter" class="adf-rating-counter">{{ratingsCounter}}</div>
|
||||
<div class="adf-rating-left" *ngIf="ratingsCounter<=1">Rating</div>
|
||||
<div class="adf-rating-left" *ngIf="ratingsCounter>1">Ratings</div>
|
||||
</div>
|
||||
</mat-list>
|
||||
|
@@ -1,35 +1,54 @@
|
||||
$adf-rated-star-color: #ffe944;
|
||||
$adf-average-star-color: #808080;
|
||||
|
||||
.adf-rating-container {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
|
||||
.adf-rating-counter-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
.adf-rating-left {
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
.adf-rating-star {
|
||||
float: left;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
transition: all 0.3s;
|
||||
padding: 1px;
|
||||
cursor: pointer;
|
||||
width: 25px !important;
|
||||
width: 25px;
|
||||
|
||||
.mat-list-item-content {
|
||||
padding: 0 2px !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: rotate(13deg) scale(1.2);
|
||||
}
|
||||
}
|
||||
|
||||
.adf-colored-star {
|
||||
color: #ffe944;
|
||||
color: $adf-rated-star-color;
|
||||
}
|
||||
|
||||
.adf-grey-star {
|
||||
color: #808080;
|
||||
.adf-grey-star, .adf-average-star {
|
||||
color: $adf-average-star-color !important;
|
||||
}
|
||||
|
||||
.adf-stars-container {
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
[dir='rtl'] .adf-rating-container {
|
||||
|
||||
.adf-rating-star {
|
||||
transform: rotate(145deg);
|
||||
}
|
||||
|
||||
.adf-rating-star:hover {
|
||||
transform: rotate(13deg) scale(1.2);
|
||||
transform: rotate(158deg) scale(1.2);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -61,28 +61,26 @@ describe('Rating component', () => {
|
||||
}
|
||||
}));
|
||||
|
||||
component.ngOnChanges();
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
component.ngOnChanges().subscribe(() => {
|
||||
expect(element.querySelector('#adf-rating-container')).not.toBe(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should the star rating filled with the right grey/colored star', (done) => {
|
||||
spyOn(service, 'getRating').and.returnValue(of({
|
||||
entry: {
|
||||
id: 'fiveStar',
|
||||
aggregate: {
|
||||
numberOfRatings: 4,
|
||||
average: 3
|
||||
}
|
||||
'entry': {
|
||||
myRating: 3,
|
||||
'ratedAt': '2017-04-06T14:34:28.061+0000',
|
||||
'id': 'fiveStar',
|
||||
'aggregate': {'numberOfRatings': 1, 'average': 3.0}
|
||||
}
|
||||
}));
|
||||
|
||||
fixture.detectChanges();
|
||||
component.ngOnChanges();
|
||||
|
||||
component.ngOnChanges().subscribe(() => {
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(element.querySelectorAll('.adf-colored-star').length).toBe(3);
|
||||
@@ -91,7 +89,7 @@ describe('Rating component', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should click on a star change your vote', (done) => {
|
||||
it('should click on a star to change your vote', (done) => {
|
||||
spyOn(service, 'getRating').and.returnValue(of({
|
||||
'entry': {
|
||||
myRating: 1,
|
||||
@@ -101,7 +99,7 @@ describe('Rating component', () => {
|
||||
}
|
||||
}));
|
||||
|
||||
spyOn(service, 'postRating').and.returnValue(of({
|
||||
const rateSpy = spyOn(service, 'postRating').and.returnValue(of({
|
||||
'entry': {
|
||||
'myRating': 3,
|
||||
'ratedAt': '2017-04-06T14:36:40.731+0000',
|
||||
@@ -110,26 +108,40 @@ describe('Rating component', () => {
|
||||
}
|
||||
}));
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
component.ngOnChanges().subscribe(() => {
|
||||
component.ngOnChanges();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(element.querySelectorAll('.adf-colored-star').length).toBe(1);
|
||||
|
||||
component.changeVote.subscribe(() => {
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(rateSpy).toHaveBeenCalled();
|
||||
expect(element.querySelectorAll('.adf-colored-star').length).toBe(3);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
const starThree: any = element.querySelector('#adf-colored-star-3');
|
||||
const starThree: any = element.querySelector('#adf-grey-star-2');
|
||||
starThree.click();
|
||||
});
|
||||
|
||||
});
|
||||
it('should click on the rated star to remove your vote', () => {
|
||||
spyOn(service, 'getRating').and.returnValue(of({
|
||||
'entry': {
|
||||
myRating: 3,
|
||||
'ratedAt': '2017-04-06T14:34:28.061+0000',
|
||||
'id': 'fiveStar',
|
||||
'aggregate': {'numberOfRatings': 1, 'average': 3.0}
|
||||
}
|
||||
}));
|
||||
|
||||
const deleteSpy = spyOn(service, 'deleteRating');
|
||||
|
||||
component.ngOnChanges();
|
||||
fixture.detectChanges();
|
||||
const starThree: any = element.querySelector('#adf-colored-star-2');
|
||||
starThree.click();
|
||||
expect(element.querySelectorAll('.adf-colored-star').length).toBe(3);
|
||||
expect(deleteSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@@ -18,6 +18,8 @@
|
||||
import { Component, EventEmitter, Input, OnChanges, Output, ViewEncapsulation } from '@angular/core';
|
||||
import { RatingService } from './services/rating.service';
|
||||
import { RatingEntry } from '@alfresco/js-api';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-rating',
|
||||
@@ -33,56 +35,87 @@ export class RatingComponent implements OnChanges {
|
||||
|
||||
average: number = 0;
|
||||
|
||||
ratingsCounter = 0;
|
||||
|
||||
ratingType: string = 'fiveStar';
|
||||
|
||||
ratingValue: number;
|
||||
|
||||
/** Emitted when the "vote" gets changed. */
|
||||
@Output()
|
||||
changeVote = new EventEmitter();
|
||||
|
||||
stars: Array<any> = [];
|
||||
|
||||
onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private ratingService: RatingService) {
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
const ratingObserver = this.ratingService.getRating(this.nodeId, this.ratingType);
|
||||
|
||||
ratingObserver.subscribe(
|
||||
this.ratingService.getRating(this.nodeId, this.ratingType)
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(
|
||||
(ratingEntry: RatingEntry) => {
|
||||
if (ratingEntry.entry.aggregate) {
|
||||
this.average = ratingEntry.entry.aggregate.average;
|
||||
this.calculateStars();
|
||||
}
|
||||
this.refreshRating(ratingEntry);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return ratingObserver;
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
calculateStars() {
|
||||
this.stars = [];
|
||||
const roundedAverage = Math.round(this.average);
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
if (i < this.average) {
|
||||
if (i < roundedAverage) {
|
||||
this.stars.push({fill: true});
|
||||
} else {
|
||||
this.stars.push({fill: false});
|
||||
}
|
||||
}
|
||||
|
||||
this.changeVote.emit(this.average);
|
||||
}
|
||||
|
||||
updateVote(vote: number) {
|
||||
this.ratingService.postRating(this.nodeId, this.ratingType, vote).subscribe(
|
||||
if (this.ratingValue === vote) {
|
||||
this.unRateItem();
|
||||
} else {
|
||||
this.rateItem(vote);
|
||||
}
|
||||
}
|
||||
|
||||
rateItem(vote: number) {
|
||||
this.ratingService.postRating(this.nodeId, this.ratingType, vote)
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(
|
||||
(ratingEntry: RatingEntry) => {
|
||||
if (ratingEntry.entry.aggregate) {
|
||||
if (this.average !== ratingEntry.entry.aggregate.average) {
|
||||
this.average = ratingEntry.entry.aggregate.average;
|
||||
this.calculateStars();
|
||||
}
|
||||
}
|
||||
this.refreshRating(ratingEntry);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
unRateItem() {
|
||||
this.ratingService.deleteRating(this.nodeId, this.ratingType).subscribe(
|
||||
() => {
|
||||
this.ratingService.getRating(this.nodeId, this.ratingType)
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(
|
||||
(ratingEntry: RatingEntry) => {
|
||||
this.refreshRating(ratingEntry);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
refreshRating(ratingEntry: RatingEntry) {
|
||||
this.ratingValue = Number.parseFloat(ratingEntry.entry.myRating);
|
||||
this.average = ratingEntry.entry.aggregate.average;
|
||||
this.ratingsCounter = ratingEntry.entry.aggregate.numberOfRatings;
|
||||
this.calculateStars();
|
||||
this.changeVote.emit(this.average);
|
||||
}
|
||||
}
|
||||
|
50
lib/testing/src/lib/content-services/pages/like.page.ts
Normal file
50
lib/testing/src/lib/content-services/pages/like.page.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { browser, by, element } from 'protractor';
|
||||
import { BrowserActions } from '../../core/utils/browser-actions';
|
||||
|
||||
export class LikePage {
|
||||
|
||||
likeCounter = element(by.css(`div[id="adf-like-counter"]`));
|
||||
likeButton = element(by.css(`span[class="adf-like-grey"]`));
|
||||
unlikeButton = element(by.css(`span[class="adf-like-select"]`));
|
||||
|
||||
getLikeCounter() {
|
||||
return BrowserActions.getText(this.likeCounter);
|
||||
}
|
||||
|
||||
clickLike() {
|
||||
return BrowserActions.click(this.likeButton);
|
||||
}
|
||||
|
||||
clickUnlike() {
|
||||
return BrowserActions.click(this.unlikeButton);
|
||||
}
|
||||
|
||||
removeHoverFromLikeButton() {
|
||||
browser.actions().mouseMove({x: 200, y: 200}).click().perform();
|
||||
}
|
||||
|
||||
getLikedIconColor() {
|
||||
return BrowserActions.getColor(this.unlikeButton);
|
||||
}
|
||||
|
||||
getUnLikedIconColor() {
|
||||
return BrowserActions.getColor(this.likeButton);
|
||||
}
|
||||
}
|
@@ -15,4 +15,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './like.page';
|
||||
export * from './rate.page';
|
||||
export * from './document-list.page';
|
||||
|
64
lib/testing/src/lib/content-services/pages/rate.page.ts
Normal file
64
lib/testing/src/lib/content-services/pages/rate.page.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { by, element } from 'protractor';
|
||||
import { BrowserVisibility } from '../../core/utils/browser-visibility';
|
||||
import { BrowserActions } from '../../core/utils/browser-actions';
|
||||
|
||||
export class RatePage {
|
||||
|
||||
rateComponent(rateValue: number) {
|
||||
const unratedStar = element(by.css(`span[id="adf-rate-${rateValue}"]`));
|
||||
return BrowserActions.click(unratedStar);
|
||||
}
|
||||
|
||||
removeRating(rateValue: number) {
|
||||
const ratedStar = element(by.css(`mat-icon[id="adf-colored-star-${rateValue}"]`));
|
||||
return BrowserActions.click(ratedStar);
|
||||
}
|
||||
|
||||
getRatingCounter() {
|
||||
const ratingsCounter = element(by.css(`div[id="adf-rating-counter"]`));
|
||||
return BrowserActions.getText(ratingsCounter);
|
||||
}
|
||||
|
||||
isStarRated(rateValue: number) {
|
||||
const ratedStar = element(by.css(`mat-icon[id="adf-colored-star-${rateValue}"]`));
|
||||
return BrowserVisibility.waitUntilElementIsVisible(ratedStar);
|
||||
}
|
||||
|
||||
isNotStarRated(rateValue: number) {
|
||||
const unratedStar = element(by.css(`mat-icon[id="adf-grey-star-${rateValue}"]`));
|
||||
return BrowserVisibility.waitUntilElementIsVisible(unratedStar);
|
||||
}
|
||||
|
||||
getRatedStarColor(rateValue: number) {
|
||||
const ratedStar = element(by.css(`mat-icon[id="adf-colored-star-${rateValue}"]`));
|
||||
return BrowserActions.getColor(ratedStar);
|
||||
}
|
||||
|
||||
getUnratedStarColor(rateValue: number) {
|
||||
const unratedStar = element(by.css(`mat-icon[id="adf-grey-star-${rateValue}"]`));
|
||||
return BrowserActions.getColor(unratedStar);
|
||||
}
|
||||
|
||||
getAverageStarColor(rateValue: number) {
|
||||
const coloredStar = element(by.css(`mat-icon[id="adf-colored-star-${rateValue}"]`));
|
||||
return BrowserActions.getColor(coloredStar);
|
||||
}
|
||||
|
||||
}
|
@@ -40,6 +40,11 @@ export class BrowserActions {
|
||||
return elementFinder.getText();
|
||||
}
|
||||
|
||||
static async getColor(elementFinder: ElementFinder) {
|
||||
BrowserVisibility.waitUntilElementIsVisible(elementFinder);
|
||||
return elementFinder.getWebElement().getCssValue('color');
|
||||
}
|
||||
|
||||
static async clearSendKeys(elementFinder: ElementFinder, text: string) {
|
||||
BrowserVisibility.waitUntilElementIsVisible(elementFinder);
|
||||
elementFinder.click();
|
||||
|
@@ -235,7 +235,7 @@
|
||||
"typings": "./index.d.ts",
|
||||
"lint-staged": {
|
||||
"linters": {
|
||||
"**/demo-shell/**/*.ts": "npm run lint-lib -- --fix",
|
||||
"**/demo-shell/src/**/*.ts": "npm run lint-lib -- --fix",
|
||||
"**/lib/**/*.ts": "npm run lint-lib -- --fix",
|
||||
"**/e2e/**/*.ts": "npm run lint-e2e -- --fix",
|
||||
"*.scss": "npm run stylelint -- --fix"
|
||||
|
Reference in New Issue
Block a user