diff --git a/src/app/models/voting-event-step.ts b/src/app/models/voting-event-step.ts index 4dbf51f..dd82a41 100644 --- a/src/app/models/voting-event-step.ts +++ b/src/app/models/voting-event-step.ts @@ -6,5 +6,8 @@ export interface VotingEventStep { name: string; description?: string; identification: { name: IdentificationTypeNames; roles?: string[] }; - action: { name: ActionNames; parameters?: { commentOnVoteBlocked?: boolean; techSelectLogic?: TechSelectLogic } }; + action: { + name: ActionNames; + parameters?: { commentOnVoteBlocked?: boolean; techSelectLogic?: TechSelectLogic; displayVotesAndCommentNumbers?: boolean }; + }; } diff --git a/src/app/modules/conversation/select-tech-for-conversation/select-tech-for-conversation.component.spec.ts b/src/app/modules/conversation/select-tech-for-conversation/select-tech-for-conversation.component.spec.ts index a26939f..97c6670 100644 --- a/src/app/modules/conversation/select-tech-for-conversation/select-tech-for-conversation.component.spec.ts +++ b/src/app/modules/conversation/select-tech-for-conversation/select-tech-for-conversation.component.spec.ts @@ -13,7 +13,14 @@ class MockVoteService { constructor() { this.credentials = { voterId: null, - votingEvent: { technologies: [], name: null, status: 'closed', _id: null, creationTS: null } + votingEvent: { + technologies: [], + name: null, + status: 'closed', + _id: null, + creationTS: null, + flow: { steps: [{ name: 'the flow', identification: { name: 'nickname' }, action: { name: 'vote' } }] } + } }; } } diff --git a/src/app/modules/technology-list/technology-list/technology-list.component.html b/src/app/modules/technology-list/technology-list/technology-list.component.html index aa70649..566bdbc 100644 --- a/src/app/modules/technology-list/technology-list/technology-list.component.html +++ b/src/app/modules/technology-list/technology-list/technology-list.component.html @@ -37,7 +37,11 @@ - {{truncatedName(technology.name)}} + how_to_vote + + {{truncatedName(technology.name)}} + + comment diff --git a/src/app/modules/technology-list/technology-list/technology-list.component.spec.ts b/src/app/modules/technology-list/technology-list/technology-list.component.spec.ts index 49c8cba..2a6f25e 100644 --- a/src/app/modules/technology-list/technology-list/technology-list.component.spec.ts +++ b/src/app/modules/technology-list/technology-list/technology-list.component.spec.ts @@ -53,9 +53,19 @@ const TEST_TECHNOLOGIES = [ ]; class MockBackEndService { getVotingEvent() { - const votingEvent = { technologies: TEST_TECHNOLOGIES, name: null, status: 'closed', _id: null, creationTS: null }; + const votingEvent = { + technologies: TEST_TECHNOLOGIES, + name: null, + status: 'closed', + _id: null, + creationTS: null, + flow: { steps: [{ name: 'the flow', identification: { name: 'nickname' }, action: { name: 'vote' } }] } + }; return of(votingEvent).pipe(observeOn(asyncScheduler)); } + getVotingEventWithNumberOfCommentsAndVotes() { + return of(null); + } } class MockVoteService { credentials; @@ -71,7 +81,15 @@ class MockAppSessionService { private selectedVotingEvent: VotingEvent; constructor() { - this.selectedVotingEvent = { _id: '123', name: 'an event', status: 'open', creationTS: 'abc' }; + this.selectedVotingEvent = { + _id: '123', + name: 'an event', + status: 'open', + creationTS: 'abc', + flow: { + steps: [{ name: 'step 1', identification: { name: 'nickname' }, action: { name: 'vote' } }] + } + }; } getSelectedVotingEvent() { @@ -216,3 +234,96 @@ describe('add a new technology', () => { }); }); }); + +describe('The voting event flow is in a step where it requires to read number of votes and comments for each tech', () => { + const numberOfVotes = 1; + const numberOfComments = 2; + const TEST_TECHNOLOGIES_WITH_NUMBER_OF_VOTES_AND_COMMENTS: Technology[] = [ + { + id: '0001', + name: 'Babel', + quadrant: 'Tools', + isnew: true, + description: 'Description of Babel', + numberOfVotes, + numberOfComments + } + ]; + + let component: TechnologyListComponent; + let fixture: ComponentFixture; + + class MockBackEndServiceForNumberOfVotesAndComments { + getVotingEvent() { + return of(null).pipe(observeOn(asyncScheduler)); + } + getVotingEventWithNumberOfCommentsAndVotes() { + const votingEvent = { + technologies: TEST_TECHNOLOGIES_WITH_NUMBER_OF_VOTES_AND_COMMENTS, + name: null, + status: 'closed', + _id: null, + creationTS: null, + flow: { steps: [{ name: 'the flow', identification: { name: 'nickname' }, action: { name: 'vote' } }] } + }; + return of(votingEvent).pipe(observeOn(asyncScheduler)); + } + } + class MockAppSessionServiceForVotingEventInStep2 { + private selectedVotingEvent: VotingEvent; + + constructor() { + this.selectedVotingEvent = { + _id: '123', + name: 'an event', + status: 'open', + creationTS: 'abc', + round: 2, + flow: { + steps: [ + { name: 'step 1', identification: { name: 'nickname' }, action: { name: 'vote' } }, + { + name: 'step 2', + identification: { name: 'nickname' }, + action: { name: 'conversation', parameters: { displayVotesAndCommentNumbers: true } } + } + ] + } + }; + } + + getSelectedVotingEvent() { + return this.selectedVotingEvent; + } + } + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [TechnologyListComponent], + imports: [BrowserAnimationsModule, HttpClientTestingModule, RouterTestingModule, AppMaterialModule], + providers: [ + { provide: BackendService, useClass: MockBackEndServiceForNumberOfVotesAndComments }, + { provide: VoteService, useClass: MockVoteService }, + { provide: AppSessionService, useClass: MockAppSessionServiceForVotingEventInStep2 }, + TechnologyListService + ] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TechnologyListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('2.1 if the flow step requires to read technologies with number of votes and comments it calls the right API', () => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + if (component.technologiesToShow.length !== TEST_TECHNOLOGIES_WITH_NUMBER_OF_VOTES_AND_COMMENTS.length) { + throw new Error('technologiesToShow are not as expected'); + } + expect(component.technologiesToShow.length === TEST_TECHNOLOGIES_WITH_NUMBER_OF_VOTES_AND_COMMENTS.length).toBeTruthy(); + expect(component.technologiesToShow[0].numberOfComments).toBe(numberOfComments); + expect(component.technologiesToShow[0].numberOfVotes).toBe(numberOfVotes); + }); + }); +}); diff --git a/src/app/modules/technology-list/technology-list/technology-list.component.ts b/src/app/modules/technology-list/technology-list/technology-list.component.ts index a55af4d..4c80d59 100644 --- a/src/app/modules/technology-list/technology-list/technology-list.component.ts +++ b/src/app/modules/technology-list/technology-list/technology-list.component.ts @@ -13,7 +13,7 @@ import * as _ from 'lodash'; import { TwRings } from 'src/app/models/ring'; import { logError } from 'src/app/utils/utils'; import { AppSessionService } from 'src/app/app-session.service'; -import { getActionName } from 'src/app/utils/voting-event-flow.util'; +import { getActionName, getAction } from 'src/app/utils/voting-event-flow.util'; import { TechnologyListService } from '../services/technology-list.service'; @Component({ @@ -113,7 +113,13 @@ export class TechnologyListComponent implements OnInit, AfterViewInit, OnDestroy getTechnologies() { // @todo remove "|| this.voteService.credentials.votingEvent" once the enableVotingEventFlow toggle is removed const votingEvent = this.appSession.getSelectedVotingEvent() || this.voteService.credentials.votingEvent; - return this.backEnd.getVotingEvent(votingEvent._id).pipe( + + const actionParams = getAction(votingEvent).parameters; + const getVotingEventObs = + actionParams && actionParams.displayVotesAndCommentNumbers + ? this.backEnd.getVotingEventWithNumberOfCommentsAndVotes(votingEvent._id) + : this.backEnd.getVotingEvent(votingEvent._id); + return getVotingEventObs.pipe( map((event) => { const technologies = event.technologies; return _.sortBy(technologies, function(item: Technology) { diff --git a/src/app/modules/vote/vote/vote.component.spec.ts b/src/app/modules/vote/vote/vote.component.spec.ts index a27097a..abe7c72 100644 --- a/src/app/modules/vote/vote/vote.component.spec.ts +++ b/src/app/modules/vote/vote/vote.component.spec.ts @@ -13,7 +13,6 @@ import { BackendService } from '../../../services/backend.service'; import { TwRings } from 'src/app/models/ring'; import { AppSessionService } from 'src/app/app-session.service'; import { VotingEvent } from 'src/app/models/voting-event'; -import { TechnologyListService } from '../../technology-list/services/technology-list.service'; import { TechnologyListModule } from '../../technology-list/technology-list.module'; const TEST_TECHNOLOGIES = [ @@ -73,7 +72,13 @@ class MockAppSessionService { private selectedVotingEvent: VotingEvent; constructor() { - this.selectedVotingEvent = { _id: '123', name: 'an event', status: 'open', creationTS: 'abc' }; + this.selectedVotingEvent = { + _id: '123', + name: 'an event', + status: 'open', + creationTS: 'abc', + flow: { steps: [{ name: 'the flow', identification: { name: 'nickname' }, action: { name: 'vote' } }] } + }; } getSelectedVotingEvent() { diff --git a/src/app/services/backend.service.spec.ts b/src/app/services/backend.service.spec.ts index f1c15ec..651e9a2 100644 --- a/src/app/services/backend.service.spec.ts +++ b/src/app/services/backend.service.spec.ts @@ -630,6 +630,16 @@ describe('BackendService', () => { expect(votesWithComments.length).toBe(2); expect(votesWithComments.filter((v) => v.comment.text === commentOnVote1).length).toBe(1); expect(votesWithComments.filter((v) => v.comment.text === commentOnVote2).length).toBe(1); + }), + concatMap(() => service.getVotingEventWithNumberOfCommentsAndVotes(votingEvent._id)), + tap((vEvent: VotingEvent) => { + const techs = vEvent.technologies; + const t1 = techs.find((t) => t.name === tech1.name); + const t2 = techs.find((t) => t.name === tech2.name); + expect(t1.numberOfVotes).toBe(2); + expect(t1.numberOfComments).toBe(0); + expect(t2.numberOfVotes).toBe(2); + expect(t2.numberOfComments).toBe(2); }) ) .subscribe({ diff --git a/src/app/services/backend.service.ts b/src/app/services/backend.service.ts index 192b958..82146fe 100644 --- a/src/app/services/backend.service.ts +++ b/src/app/services/backend.service.ts @@ -255,6 +255,17 @@ export class BackendService { ); } + getVotingEventWithNumberOfCommentsAndVotes(eventId: string): Observable { + const payload = this.buildPostPayloadForService(ServiceNames.getVotingEventWithNumberOfCommentsAndVotes); + payload['_id'] = eventId; + return this.http.post(this.url, payload).pipe( + map((resp: any) => { + return this.handleReponseDefault(resp); + }), + catchError(this.handleError) + ); + } + createVotingEvent(name: string, flow?: VotingEventFlow) { const payload = this.buildPostPayloadForService(ServiceNames.createVotingEvent); payload['name'] = name; diff --git a/src/app/services/service-names.ts b/src/app/services/service-names.ts index 90fe331..9c3037c 100644 --- a/src/app/services/service-names.ts +++ b/src/app/services/service-names.ts @@ -11,6 +11,7 @@ export enum ServiceNames { getVotesWithCommentsForTechAndEvent, addReplyToVoteComment, getVotingEvents, + getVotingEventWithNumberOfCommentsAndVotes, getVotingEvent, createVotingEvent, openVotingEvent,