diff --git a/docs/content-services/components/rating.component.md b/docs/content-services/components/rating.component.md index c5ef2d72922..c235888442b 100644 --- a/docs/content-services/components/rating.component.md +++ b/docs/content-services/components/rating.component.md @@ -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. + +![Rating component screenshot](../../docassets/images/social3.png) + +If the user has rated the item the average rating stars color is yellow. ![Rating component screenshot](../../docassets/images/social2.png) +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)`` | Emitted when the "vote" gets changed. | +| changeVote | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`` | Average rating is emitted when the "vote" gets changed. | ## See also diff --git a/docs/docassets/images/social2.png b/docs/docassets/images/social2.png index 3094771d9fd..027afef2168 100644 Binary files a/docs/docassets/images/social2.png and b/docs/docassets/images/social2.png differ diff --git a/docs/docassets/images/social3.png b/docs/docassets/images/social3.png new file mode 100644 index 00000000000..257b8ca6b8c Binary files /dev/null and b/docs/docassets/images/social3.png differ diff --git a/e2e/content-services/social/social.component.e2e.ts b/e2e/content-services/social/social.component.e2e.ts new file mode 100644 index 00000000000..17124f938d8 --- /dev/null +++ b/e2e/content-services/social/social.component.e2e.ts @@ -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); + }); + }); +}); diff --git a/e2e/pages/adf/demo-shell/socialPage.ts b/e2e/pages/adf/demo-shell/socialPage.ts new file mode 100644 index 00000000000..3c2f2b4625b --- /dev/null +++ b/e2e/pages/adf/demo-shell/socialPage.ts @@ -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); + } + +} diff --git a/e2e/pages/adf/navigationBarPage.ts b/e2e/pages/adf/navigationBarPage.ts index 1168181673d..c6450de7765 100644 --- a/e2e/pages/adf/navigationBarPage.ts +++ b/e2e/pages/adf/navigationBarPage.ts @@ -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'); } diff --git a/lib/content-services/social/like.component.html b/lib/content-services/social/like.component.html index 08f5be9b0d2..cb24d58119c 100644 --- a/lib/content-services/social/like.component.html +++ b/lib/content-services/social/like.component.html @@ -5,7 +5,9 @@ thumb_up -
{{likesCounter}}
-
Like
-
Likes
+
+
{{likesCounter}}
+
Like
+
Likes
+
diff --git a/lib/content-services/social/like.component.scss b/lib/content-services/social/like.component.scss index e737d524124..a808c2ee65e 100644 --- a/lib/content-services/social/like.component.scss +++ b/lib/content-services/social/like.component.scss @@ -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-like-select { - cursor: pointer; - color: #2196f3; + .adf-left { + padding: 0 6px; } - .adf-like-select:hover { + .adf-like-select { cursor: pointer; - color: #808080; + @include selected; + &:hover { + @include unselected; + } } .adf-like-grey { cursor: pointer; - color: #808080; - } - - .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; + @include unselected; + &:hover { + @include selected; + } } } diff --git a/lib/content-services/social/rating.component.html b/lib/content-services/social/rating.component.html index 90885a5a1e4..a847f9b035d 100644 --- a/lib/content-services/social/rating.component.html +++ b/lib/content-services/social/rating.component.html @@ -1,12 +1,18 @@ - + - star_rate + star_rate - star_border + star_border +
+
{{ratingsCounter}}
+
Rating
+
Ratings
+
diff --git a/lib/content-services/social/rating.component.scss b/lib/content-services/social/rating.component.scss index 633a230dd06..4269e6f7c09 100644 --- a/lib/content-services/social/rating.component.scss +++ b/lib/content-services/social/rating.component.scss @@ -1,35 +1,54 @@ +$adf-rated-star-color: #ffe944; +$adf-average-star-color: #808080; + .adf-rating-container { - overflow: hidden; - width: 100%; + 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); } - } diff --git a/lib/content-services/social/rating.component.spec.ts b/lib/content-services/social/rating.component.spec.ts index c1103194050..eddc56364f5 100644 --- a/lib/content-services/social/rating.component.spec.ts +++ b/lib/content-services/social/rating.component.spec.ts @@ -61,75 +61,87 @@ describe('Rating component', () => { } })); - 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 - } - } - })); + component.ngOnChanges(); fixture.detectChanges(); - component.ngOnChanges().subscribe(() => { - fixture.detectChanges(); - - expect(element.querySelectorAll('.adf-colored-star').length).toBe(3); - expect(element.querySelectorAll('.adf-grey-star').length).toBe(2); - done(); - }); + expect(element.querySelector('#adf-rating-container')).not.toBe(null); + done(); }); - it('should click on a star change your vote', (done) => { + it('should the star rating filled with the right grey/colored star', (done) => { spyOn(service, 'getRating').and.returnValue(of({ 'entry': { - myRating: 1, + myRating: 3, 'ratedAt': '2017-04-06T14:34:28.061+0000', 'id': 'fiveStar', - 'aggregate': { 'numberOfRatings': 1, 'average': 1.0 } + 'aggregate': {'numberOfRatings': 1, 'average': 3.0} } })); - spyOn(service, 'postRating').and.returnValue(of({ - 'entry': { - 'myRating': 3, - 'ratedAt': '2017-04-06T14:36:40.731+0000', - 'id': 'fiveStar', - 'aggregate': { 'numberOfRatings': 1, 'average': 3.0 } - } - })); + component.ngOnChanges(); fixture.detectChanges(); - component.ngOnChanges().subscribe(() => { - fixture.detectChanges(); + expect(element.querySelectorAll('.adf-colored-star').length).toBe(3); + expect(element.querySelectorAll('.adf-grey-star').length).toBe(2); + done(); + }); + }); - expect(element.querySelectorAll('.adf-colored-star').length).toBe(1); + it('should click on a star to change your vote', (done) => { + spyOn(service, 'getRating').and.returnValue(of({ + 'entry': { + myRating: 1, + 'ratedAt': '2017-04-06T14:34:28.061+0000', + 'id': 'fiveStar', + 'aggregate': {'numberOfRatings': 1, 'average': 1.0} + } + })); + + const rateSpy = spyOn(service, 'postRating').and.returnValue(of({ + 'entry': { + 'myRating': 3, + 'ratedAt': '2017-04-06T14:36:40.731+0000', + 'id': 'fiveStar', + 'aggregate': {'numberOfRatings': 1, 'average': 3.0} + } + })); + + component.ngOnChanges(); + fixture.detectChanges(); - component.changeVote.subscribe(() => { - fixture.detectChanges(); + expect(element.querySelectorAll('.adf-colored-star').length).toBe(1); - expect(element.querySelectorAll('.adf-colored-star').length).toBe(3); + component.changeVote.subscribe(() => { + fixture.detectChanges(); + expect(rateSpy).toHaveBeenCalled(); + expect(element.querySelectorAll('.adf-colored-star').length).toBe(3); + + done(); + }); - done(); - }); + const starThree: any = element.querySelector('#adf-grey-star-2'); + starThree.click(); + }); - const starThree: any = element.querySelector('#adf-colored-star-3'); - 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(); }); }); diff --git a/lib/content-services/social/rating.component.ts b/lib/content-services/social/rating.component.ts index 32e2614668d..0edaf73b944 100644 --- a/lib/content-services/social/rating.component.ts +++ b/lib/content-services/social/rating.component.ts @@ -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 = []; + onDestroy$ = new Subject(); + 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) { - this.stars.push({ fill: true }); + if (i < roundedAverage) { + this.stars.push({fill: true}); } else { - this.stars.push({ fill: false }); + 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); + } } diff --git a/lib/testing/src/lib/content-services/pages/like.page.ts b/lib/testing/src/lib/content-services/pages/like.page.ts new file mode 100644 index 00000000000..e7ee6ce005a --- /dev/null +++ b/lib/testing/src/lib/content-services/pages/like.page.ts @@ -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); + } +} diff --git a/lib/testing/src/lib/content-services/pages/public-api.ts b/lib/testing/src/lib/content-services/pages/public-api.ts index a499c820642..b1a2c48f3fa 100644 --- a/lib/testing/src/lib/content-services/pages/public-api.ts +++ b/lib/testing/src/lib/content-services/pages/public-api.ts @@ -15,4 +15,6 @@ * limitations under the License. */ +export * from './like.page'; +export * from './rate.page'; export * from './document-list.page'; diff --git a/lib/testing/src/lib/content-services/pages/rate.page.ts b/lib/testing/src/lib/content-services/pages/rate.page.ts new file mode 100644 index 00000000000..e9267a39822 --- /dev/null +++ b/lib/testing/src/lib/content-services/pages/rate.page.ts @@ -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); + } + +} diff --git a/lib/testing/src/lib/core/utils/browser-actions.ts b/lib/testing/src/lib/core/utils/browser-actions.ts index 4f31b4177de..9372253218a 100644 --- a/lib/testing/src/lib/core/utils/browser-actions.ts +++ b/lib/testing/src/lib/core/utils/browser-actions.ts @@ -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(); diff --git a/package.json b/package.json index 7bc3e7b9337..a93943a20c1 100644 --- a/package.json +++ b/package.json @@ -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"