11import { CUSTOM_ELEMENTS_SCHEMA , SimpleChange } from '@angular/core' ;
2- import { ComponentFixture , TestBed } from '@angular/core/testing' ;
2+ import {
3+ ComponentFixture ,
4+ discardPeriodicTasks ,
5+ fakeAsync ,
6+ flush ,
7+ TestBed ,
8+ tick ,
9+ } from '@angular/core/testing' ;
310import { By } from '@angular/platform-browser' ;
411import { TranslateModule } from '@ngx-translate/core' ;
512import { BehaviorSubject , Subject } from 'rxjs' ;
@@ -25,6 +32,7 @@ describe('MessageInputComponent', () => {
2532 let querySendButton : ( ) => HTMLButtonElement | null ;
2633 let queryattachmentUploadButton : ( ) => HTMLElement | null ;
2734 let queryFileInput : ( ) => HTMLInputElement | null ;
35+ let queryCooldownTimer : ( ) => HTMLElement | null ;
2836 let mockActiveChannel$ : BehaviorSubject < Channel > ;
2937 let mockActiveParentMessageId$ : BehaviorSubject < string | undefined > ;
3038 let sendMessageSpy : jasmine . Spy ;
@@ -45,6 +53,9 @@ describe('MessageInputComponent', () => {
4553 let selectMessageToQuoteSpy : jasmine . Spy ;
4654 let typingStartedSpy : jasmine . Spy ;
4755 let typingStoppedSpy : jasmine . Spy ;
56+ let latestMessageDateByUserByChannels$ : BehaviorSubject < {
57+ [ key : string ] : Date ;
58+ } > ;
4859
4960 beforeEach ( ( ) => {
5061 appSettings$ = new Subject < AppSettings > ( ) ;
@@ -70,6 +81,7 @@ describe('MessageInputComponent', () => {
7081 mockMessageToQuote$ = new BehaviorSubject < undefined | StreamMessage > (
7182 undefined
7283 ) ;
84+ latestMessageDateByUserByChannels$ = new BehaviorSubject ( { } ) ;
7385 selectMessageToQuoteSpy = jasmine . createSpy ( ) ;
7486 TestBed . overrideComponent ( MessageInputComponent , {
7587 set : {
@@ -107,6 +119,7 @@ describe('MessageInputComponent', () => {
107119 selectMessageToQuote : selectMessageToQuoteSpy ,
108120 typingStarted : typingStartedSpy ,
109121 typingStopped : typingStoppedSpy ,
122+ latestMessageDateByUserByChannels$,
110123 } ,
111124 } ,
112125 {
@@ -130,6 +143,8 @@ describe('MessageInputComponent', () => {
130143 nativeElement . querySelector ( '[data-testid="file-upload-button"]' ) ;
131144 queryFileInput = ( ) =>
132145 nativeElement . querySelector ( '[data-testid="file-input"]' ) ;
146+ queryCooldownTimer = ( ) =>
147+ nativeElement . querySelector ( '[data-testid="cooldown-timer"]' ) ;
133148 } ) ;
134149
135150 it ( 'should display textarea' , ( ) => {
@@ -803,4 +818,127 @@ describe('MessageInputComponent', () => {
803818
804819 expect ( typingStartedSpy ) . toHaveBeenCalledWith ( 'parentMessage' ) ;
805820 } ) ;
821+
822+ it ( `shouldn't activate cooldown for users without 'slow-mode' restriction` , ( ) => {
823+ const channel = generateMockChannels ( 1 ) [ 0 ] ;
824+ channel . data ! . own_capabilities = [ ] ;
825+ channel . data ! . cooldown = 3 ;
826+ mockActiveChannel$ . next ( channel ) ;
827+ latestMessageDateByUserByChannels$ . next ( {
828+ [ channel . cid ] : new Date ( ) ,
829+ } ) ;
830+
831+ expect ( component . isCooldownInProgress ) . toBeFalse ( ) ;
832+ } ) ;
833+
834+ it ( 'should activate cooldown timer' , fakeAsync ( ( ) => {
835+ const channel = generateMockChannels ( 1 ) [ 0 ] ;
836+ channel . data ! . own_capabilities = [ 'slow-mode' ] ;
837+ channel . data ! . cooldown = 30 ;
838+ mockActiveChannel$ . next ( channel ) ;
839+ latestMessageDateByUserByChannels$ . next ( {
840+ [ channel . cid ] : new Date ( ) ,
841+ } ) ;
842+ const spy = jasmine . createSpy ( ) ;
843+ component . cooldown$ ?. subscribe ( spy ) ;
844+ tick ( 1 ) ;
845+
846+ expect ( spy ) . toHaveBeenCalledWith ( 30 ) ;
847+
848+ tick ( 1000 ) ;
849+
850+ expect ( spy ) . toHaveBeenCalledWith ( 29 ) ;
851+
852+ tick ( 1000 ) ;
853+
854+ expect ( spy ) . toHaveBeenCalledWith ( 28 ) ;
855+
856+ spy . calls . reset ( ) ;
857+ tick ( 28000 ) ;
858+
859+ expect ( spy ) . toHaveBeenCalledWith ( 0 ) ;
860+
861+ discardPeriodicTasks ( ) ;
862+ } ) ) ;
863+
864+ it ( 'should disable text input during cooldown period' , fakeAsync ( ( ) => {
865+ const channel = generateMockChannels ( 1 ) [ 0 ] ;
866+ channel . data ! . own_capabilities = [ 'slow-mode' , 'send-message' ] ;
867+ channel . data ! . cooldown = 30 ;
868+ mockActiveChannel$ . next ( channel ) ;
869+ latestMessageDateByUserByChannels$ . next ( {
870+ [ channel . cid ] : new Date ( ) ,
871+ } ) ;
872+ fixture . detectChanges ( ) ;
873+
874+ const textarea = nativeElement . querySelector (
875+ '[data-testid="disabled-textarea"]'
876+ ) as HTMLTextAreaElement ;
877+
878+ expect ( textarea ?. disabled ) . toBeTrue ( ) ;
879+ expect ( textarea ?. value ) . toContain ( 'streamChat.Slow Mode ON' ) ;
880+
881+ discardPeriodicTasks ( ) ;
882+ } ) ) ;
883+
884+ it ( 'should not display emoji picker and file upload button during cooldown period' , fakeAsync ( ( ) => {
885+ const channel = generateMockChannels ( 1 ) [ 0 ] ;
886+ channel . data ! . own_capabilities = [ 'slow-mode' , 'send-message' ] ;
887+ channel . data ! . cooldown = 30 ;
888+ mockActiveChannel$ . next ( channel ) ;
889+ latestMessageDateByUserByChannels$ . next ( {
890+ [ channel . cid ] : new Date ( ) ,
891+ } ) ;
892+ tick ( 1 ) ;
893+ fixture . detectChanges ( ) ;
894+
895+ expect ( queryattachmentUploadButton ( ) ) . toBeNull ( ) ;
896+ expect (
897+ nativeElement . querySelector ( '[data-testid="emoji-picker"]' )
898+ ) . toBeNull ( ) ;
899+
900+ flush ( ) ;
901+ discardPeriodicTasks ( ) ;
902+ } ) ) ;
903+
904+ it ( 'should display cooldown timer' , fakeAsync ( ( ) => {
905+ const channel = generateMockChannels ( 1 ) [ 0 ] ;
906+ channel . data ! . own_capabilities = [ 'slow-mode' , 'send-message' ] ;
907+ channel . data ! . cooldown = 30 ;
908+ mockActiveChannel$ . next ( channel ) ;
909+ latestMessageDateByUserByChannels$ . next ( {
910+ [ channel . cid ] : new Date ( ) ,
911+ } ) ;
912+ fixture . detectChanges ( ) ;
913+ tick ( 1 ) ;
914+ fixture . detectChanges ( ) ;
915+
916+ expect ( queryCooldownTimer ( ) ) . not . toBeNull ( ) ;
917+ expect ( queryCooldownTimer ( ) ?. innerHTML ) . toContain ( 30 ) ;
918+
919+ discardPeriodicTasks ( ) ;
920+ } ) ) ;
921+
922+ it ( 'should discard cooldown timer after channel is chnaged' , ( ) => {
923+ component . isCooldownInProgress = true ;
924+ const channel = generateMockChannels ( 1 ) [ 0 ] ;
925+ channel . data ! . own_capabilities = [ 'slow-mode' , 'send-message' ] ;
926+ channel . data ! . cooldown = 30 ;
927+ channel . cid = 'newchannel' ;
928+ mockActiveChannel$ . next ( channel ) ;
929+
930+ expect ( component . isCooldownInProgress ) . toBeFalse ( ) ;
931+ } ) ;
932+
933+ it ( `shouldn't start a cooldown if message was sent in another channel` , ( ) => {
934+ const channel = generateMockChannels ( 1 ) [ 0 ] ;
935+ channel . data ! . own_capabilities = [ 'slow-mode' , 'send-message' ] ;
936+ channel . data ! . cooldown = 30 ;
937+ mockActiveChannel$ . next ( channel ) ;
938+ latestMessageDateByUserByChannels$ . next ( {
939+ [ channel . cid + 'not' ] : new Date ( ) ,
940+ } ) ;
941+
942+ expect ( component . isCooldownInProgress ) . toBeFalse ( ) ;
943+ } ) ;
806944} ) ;
0 commit comments