import { TestBed , ComponentFixture } from '@angular/core/testing' ; import { RouterTestingModule } from '@angular/router/testing' ; import { HttpClientTestingModule } from '@angular/common/http/testing' ; import { FormsModule } from '@angular/forms' ; import { DomSanitizer } from '@angular/platform-browser' ; import { DragDropModule } from '@angular/cdk/drag-drop' ; import { ColumnDisplayComponent } from 'src/app/board/column/column.component' ; import { TaskDisplayComponent } from 'src/app/board/task/task.component' ; import { AuthService , StringsService , ModalService , NotificationsService } from 'src/app/shared/services' ; import { BoardService } from 'src/app/board/board.service' ; import { SharedModule } from 'src/app/shared/shared.module' ; import { User } from 'src/app/shared/models' ; describe ( 'ColumnDisplay' , ( ) => { let component ; let fixture ; const mockTask = { id : 1 , title : 'test' , description : '' , color : '#ffffe0' , due : Date . now , points : 3 , position : 1 , column_id : 1 , ownComment : [ { id : 1 , text : '' , user_id : 1 , task_id : 1 , timestamp : Date . now ( ) } ] , ownAttachment : [ { id : 1 , filename : 'file.png' , diskfilename : 'asdfasdfasdf' } ] , sharedUser : [ ] , sharedCategory : [ ] } ; beforeEach ( ( ) => { TestBed . configureTestingModule ( { imports : [ HttpClientTestingModule , FormsModule , RouterTestingModule , SharedModule , DragDropModule , ] , declarations : [ ColumnDisplayComponent , TaskDisplayComponent , ] , providers : [ AuthService , NotificationsService , ModalService , StringsService , BoardService , { provide : DomSanitizer , useValue : { sanitize : ( _ , val ) => val , bypassSecurityTrustResourceUrl : ( val ) => val , bypassSecurityTrustHtml : ( val ) => val , } , } , ] } ) . compileComponents ( ) ; } ) ; beforeEach ( ( ) => { fixture = TestBed . createComponent ( ColumnDisplayComponent ) ; component = fixture . componentInstance ; fixture . detectChanges ( ) ; } ) ; it ( 'can be constructed' , ( ) => { expect ( component ) . toBeTruthy ( ) ; } ) ; it ( 'implements OnInit' , ( ) => { component . userOptions = { multiple_tasks_per_row : true } as any ; component . columnData = { id : 1 , task_limit : 3 , tasks : [ ] } as any ; component . activeUser = { collapsed : [ 1 ] } as any ; component . ngOnInit ( ) ; expect ( component . templateElement . classList . contains ( 'collapsed' ) ) . toEqual ( true ) ; } ) ; it ( 'gets a username' , ( ) => { component . activeBoard = < any > { users : [ < any > { id : 1 , username : 'hi' } ] } ; const username = component . userName ( 1 ) ; expect ( username ) . toEqual ( 'hi' ) ; component . strings = { none : '' } as any ; const noUser = component . userName ( 3 ) ; expect ( noUser ) . toEqual ( '' ) ; } ) ; it ( 'sorts tasks' , ( ) => { component . columnData = { tasks : [ { position : 2 , due_date : '1/1/2018' , points : 1 } , { position : 1 , due_date : '1/1/2019' , points : 3 } ] } as any ; component . sortOption = 'pos' ; component . sortTasks ( ) ; expect ( component . columnData . tasks [ 0 ] . position ) . toEqual ( 1 ) ; component . sortOption = 'due' ; component . sortTasks ( ) ; expect ( component . columnData . tasks [ 0 ] . due_date ) . toEqual ( '1/1/2018' ) ; component . sortOption = 'pnt' ; component . sortTasks ( ) ; expect ( component . columnData . tasks [ 0 ] . points ) . toEqual ( 3 ) ; } ) ; it ( 'sorts comments' , ( ) => { ( component . viewModalProps . comments as any [ ] ) = [ { timestamp : 123 } , { timestamp : 12 } ] ; component . sortComments ( ) ; expect ( component . viewModalProps . comments [ 0 ] . timestamp ) . toEqual ( 12 ) ; component . commentOrder = 'newest' ; component . sortComments ( ) ; expect ( component . viewModalProps . comments [ 0 ] . timestamp ) . toEqual ( 123 ) ; } ) ; it ( 'calls a service to toggle collapsed state' , ( ) => { ( component . boardService . toggleCollapsed as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { data : [ { } , [ 1 ] ] } as any ) } ; } ; component . activeUser = { id : 1 , collapsed : [ ] } as any ; component . columnData = { id : 1 } as any ; component . toggleCollapsed ( ) ; expect ( component . templateElement . classList . contains ( 'collapsed' ) ) . toEqual ( true ) ; expect ( component . activeUser . collapsed [ 0 ] ) . toEqual ( 1 ) ; } ) ; it ( 'toggles task collapsing' , ( ) => { component . collapseTasks = false ; component . toggleTaskCollapse ( ) ; expect ( component . collapseTasks ) . toEqual ( true ) ; } ) ; it ( 'updates task color by category' , ( ) => { const mock = [ { default_task_color : 'red' } as any ] ; component . updateTaskColorByCategory ( mock ) ; expect ( component . modalProps . categories ) . toEqual ( mock ) ; expect ( component . modalProps . color ) . toEqual ( 'red' ) ; } ) ; it ( 'calls a service to add a task' , ( ) => { component . columnData = { id : 1 } as any ; component . addTask ( ) ; expect ( component . saving ) . toEqual ( false ) ; ( component . boardService . addTask as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'error' , alerts : [ { } ] } as any ) } ; } ; component . modalProps = { title : 'Testing' } as any ; component . addTask ( ) ; expect ( component . saving ) . toEqual ( false ) ; ( component . boardService . addTask as any ) = ( ) => { return { subscribe : ( _ , err ) => { err ( 'Err' ) ; } } ; } ; component . addTask ( ) ; ( component . boardService . addTask as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'success' , alerts : [ ] , data : [ { } , { } , [ { ownColumn : [ { } ] } ] ] } as any ) } ; } ; component . addTask ( ) ; expect ( component . saving ) . toEqual ( false ) ; } ) ; it ( 'handles drop events' , ( ) => { const prev = { data : { } , id : 'col1' } ; const evt = { currentIndex : 0 , previousContainer : prev , container : prev } ; component . activeBoard = { columns : [ { id : 1 , tasks : [ { id : 1 } , { id : 2 } ] } , { id : 3 } ] } as any ; component . moveItemInArray = ( ) => true ; component . transferArrayItem = ( ) => true ; component . drop ( evt as any ) ; expect ( component . activeBoard . columns [ 0 ] . tasks [ 0 ] . position ) . toEqual ( 1 ) ; evt . previousContainer = { data : { } , id : 'col1' } ; component . drop ( evt as any ) ; expect ( component . activeBoard . columns [ 0 ] . tasks [ 0 ] . position ) . toEqual ( 1 ) ; } ) ; it ( 'calls a service to update a task' , ( ) => { component . updateTask ( ) ; expect ( component . saving ) . toEqual ( false ) ; ( component . boardService . updateTask as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'error' , alerts : [ { } ] } as any ) } ; } ; component . modalProps = { title : 'Testing' } as any ; component . updateTask ( ) ; expect ( component . saving ) . toEqual ( false ) ; ( component . boardService . updateTask as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'success' , alerts : [ ] , data : [ { } , { } , [ { ownColumn : [ { } ] } ] ] } as any ) } ; } ; component . updateTask ( ) ; expect ( component . saving ) . toEqual ( false ) ; } ) ; it ( 'calls a service to remove a task' , ( ) => { let called = false ; component . taskToRemove = 1 ; ( component . boardService . removeTask as any ) = ( ) => { return { subscribe : ( fn ) => { called = true ; fn ( { status : 'error' , alerts : [ { } ] } as any ) ; } } ; } ; component . removeTask ( ) ; expect ( called ) . toEqual ( true ) ; ( component . boardService . removeTask as any ) = ( ) => { return { subscribe : ( fn ) => { called = true ; fn ( { status : 'success' , alerts : [ { } ] , data : [ { } , [ { } ] ] } as any ) ; } } ; } ; component . removeTask ( ) ; expect ( called ) . toEqual ( true ) ; } ) ; it ( 'handles file input changes' , ( ) => { const file = { test : true } ; component . fileChange ( file as any ) ; expect ( component . fileUpload ) . toEqual ( file ) ; } ) ; it ( 'calls a service to add a file' , ( ) => { let called = false ; component . notes . noteAdded . subscribe ( ( ) => { called = true ; } ) ; component . addFile ( ) ; expect ( called ) . toEqual ( true ) ; component . fileUpload = { name : 'test.png' , type : 'image/png' , } ; component . activeUser = { id : 1 } as any ; component . viewModalProps = { id : 1 , attachments : [ ] } as any ; ( component . boardService . addAttachment as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'error' } as any ) } ; } ; component . addFile ( ) ; expect ( component . fileUploading ) . toEqual ( false ) ; ( component . boardService . addAttachment as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'success' , data : [ { } , { id : 3 , diskfilename : 'asdfghjkl' } ] , alerts : [ { } ] } ) } ; } ; ( component . boardService . uploadAttachment as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'success' , alerts : [ { } ] } ) } ; } ; component . addFile ( ) ; expect ( component . fileUploading ) . toEqual ( false ) ; } ) ; it ( 'opens a file viewer in a new window' , ( ) => { spyOn ( window , 'open' ) ; component . viewFile ( 'asdf' ) ; expect ( window . open ) . toHaveBeenCalledWith ( './files/asdf' , 'tb-file-view' ) ; } ) ; it ( 'provides a way to get a the URL for a file' , ( ) => { const url = component . getUrl ( 'asdf' ) . toString ( ) ; expect ( url ) . toEqual ( './api/uploads/asdf' ) ; } ) ; it ( 'calls a service to remove a file' , ( ) => { ( component . boardService . removeAttachment as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'error' , alerts : [ ] } ) } ; } ; component . activeUser = { id : 1 , security_level : 3 } as any ; component . attachmentToRemove = { id : 0 } as any ; component . removeAttachment ( ) ; ( component . boardService . removeAttachment as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'success' , alerts : [ { } ] , } ) } ; } ; component . viewModalProps . attachments = [ { id : 0 } as any ] ; component . removeAttachment ( ) ; expect ( component . viewModalProps . attachments . length ) . toEqual ( 0 ) ; } ) ; it ( 'calls a service to add a comment' , ( ) => { component . viewModalProps . id = 0 ; component . addComment ( ) ; component . activeUser = new User ( ) ; component . viewModalProps . id = 1 ; component . newComment = 'Testing.' ; component . addComment ( ) ; expect ( component . newComment ) . toEqual ( '' ) ; ( component . boardService . addComment as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'error' , alerts : [ ] } as any ) } ; } ; component . newComment = 'Testing.' ; component . addComment ( ) ; expect ( component . newComment ) . toEqual ( '' ) ; ( component . boardService . addComment as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'success' , data : [ { } , [ mockTask , { id : 2 } ] ] , alerts : [ { } ] } as any ) } ; } ; component . activeBoard = { columns : [ { id : 1 , tasks : [ { id : 1 } , { id : 2 } ] } , { id : 3 } ] } as any ; component . addComment ( ) ; expect ( component . viewModalProps . id ) . toEqual ( 1 ) ; } ) ; it ( 'loads a comment into the editor' , ( ) => { component . beginEditComment ( { id : 1 , text : 'Testing' } as any ) ; expect ( component . commentEdit . text ) . toEqual ( 'Testing' ) ; } ) ; it ( 'calls a service to edit a comment' , ( ) => { component . activeUser = { id : 1 } as any ; component . commentEdit = { is_edited : false , user_id : 0 } as any ; ( component . boardService . updateComment as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'error' , alerts : [ { } ] } as any ) } ; } ; component . editComment ( ) ; expect ( component . commentEdit . is_edited ) . toEqual ( true ) ; component . activeBoard = { columns : [ { id : 1 , tasks : [ { id : 1 } , { id : 2 } ] } , { id : 2 } ] } as any ; ( component . boardService . updateComment as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'success' , alerts : [ { } ] , data : [ { } , [ mockTask ] ] } as any ) } ; } ; component . editComment ( ) ; expect ( component . viewModalProps . id ) . toEqual ( 1 ) ; } ) ; it ( 'calls a service to remove a comment' , ( ) => { component . viewModalProps = { comments : [ { id : 1 } ] } as any ; component . commentToRemove = { id : 1 } as any ; component . activeUser = { id : 1 , security_level : 2 } as any ; component . activeBoard = { columns : [ { id : 1 , tasks : [ { id : 1 , text : 'test' } , { id : 2 } ] } , { id : 2 } ] } as any ; ( component . boardService . removeComment as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { alerts : [ { } ] , data : [ { } , [ mockTask ] ] } as any ) } ; } ; component . removeComment ( ) ; expect ( ( component . activeBoard . columns [ 0 ] . tasks [ 0 ] as any ) . text ) . toEqual ( 'test' ) ; } ) ; it ( 'has a function to check user comment admin' , ( ) => { component . activeUser = { id : 2 , isAnyAdmin : ( ) => false } as any ; expect ( component . canAdminComment ( { user_id : 1 } as any ) ) . toEqual ( false ) ; component . activeUser . id = 1 ; expect ( component . canAdminComment ( { user_id : 1 } as any ) ) . toEqual ( true ) ; } ) ; it ( 'has a function to show the editor for column task limit' , ( ) => { component . columnData = { task_limit : 3 } as any ; component . beginLimitEdit ( ) ; expect ( component . taskLimit ) . toEqual ( 3 ) ; expect ( component . showLimitEditor ) . toEqual ( true ) ; } ) ; it ( 'has a function to cancel editing for column task limit' , ( ) => { component . cancelLimitChanges ( ) ; expect ( component . showLimitEditor ) . toEqual ( false ) ; } ) ; it ( 'calls a service to save column task limit changes' , ( ) => { component . columnData = { task_limit : 3 } as any ; component . taskLimit = 2 ; ( component . boardService . updateColumn as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'error' , alerts : [ { } ] } as any ) } ; } ; component . saveLimitChanges ( ) ; expect ( component . columnData . task_limit ) . toEqual ( 3 ) ; ( component . boardService . updateColumn as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { status : 'success' , alerts : [ ] , data : [ { } , [ { id : 1 , name : 'test' , position : 1 , board_id : 1 , task_limit : 2 , ownTask : [ ] } ] ] } as any ) } ; } ; component . saveLimitChanges ( ) ; expect ( component . columnData . task_limit ) . toEqual ( 2 ) ; expect ( component . showLimitEditor ) . toEqual ( false ) ; } ) ; it ( 'has a function to determine text color by bg color' , ( ) => { let color = component . getTextColor ( '#ffffff' ) ; expect ( color ) . toEqual ( '#333333' ) ; color = component . getTextColor ( '#000000' ) ; expect ( color ) . toEqual ( '#efefef' ) ; } ) ; it ( 'can add a task with only a title' , ( ) => { let called = false ; component . quickAdd = { title : 'test' } as any ; component . columnData = { id : 1 } as any ; component . addTask = ( ) => { called = true ; } ; component . quickAddClicked ( { preventEnter : ( ) => { } } ) ; expect ( called ) . toEqual ( true ) ; } ) ; it ( 'opens a modal to add a task' , ( ) => { component . quickAdd = { title : '' } as any ; component . columnData = { id : 1 } as any ; component . quickAddClicked ( { stopPropagation : ( ) => { } } ) ; expect ( component . modalProps . column_id ) . toEqual ( 1 ) ; } ) ; it ( 'checks a due date against the current date' , ( ) => { component . checkDueDate ( ) ; component . viewModalProps = { due_date : 'asdf' } as any ; component . checkDueDate ( ) ; const today = new Date ( ) ; const yesterday = new Date ( today . getFullYear ( ) , today . getMonth ( ) , today . getDay ( ) - 2 ) ; component . viewModalProps = { due_date : today } as any ; component . checkDueDate ( ) ; expect ( component . isNearlyDue ) . toEqual ( true ) ; component . viewModalProps = { due_date : yesterday } as any ; component . checkDueDate ( ) ; expect ( component . isOverdue ) . toEqual ( true ) ; } ) ; it ( 'provides a function to remove a task' , ( ) => { const remove = component . getRemoveTaskFunction ( 3 ) ; expect ( remove ) . toEqual ( jasmine . any ( Function ) ) ; component . columnData = { id : 1 } as any ; remove ( ) ; expect ( component . taskToRemove ) . toEqual ( 3 ) ; } ) ; it ( 'provides a function to show a modal' , ( ) => { const show = component . getShowModalFunction ( 3 ) ; expect ( show ) . toEqual ( jasmine . any ( Function ) ) ; component . columnData = { id : 1 , tasks : [ { id : 3 , title : 'test' , description : '' , color : '#ffffe0' , points : 1 , position : 1 , column_id : 1 , comments : [ ] , attachments : [ ] , assignees : [ { } ] , categories : [ { } ] } ] } as any ; component . activeBoard = { users : [ { } ] , categories : [ { } ] } as any ; show ( ) ; expect ( component . modalProps . column_id ) . toEqual ( 1 ) ; } ) ; it ( 'provides a function to show a view modal' , ( ) => { const view = component . getShowViewModalFunction ( 3 ) ; expect ( view ) . toEqual ( jasmine . any ( Function ) ) ; component . activeUser = { id : 1 , security_level : 1 } as any ; component . activeBoard = { issue_trackers : [ ] } as any ; component . showActivity = true ; component . columnData = { id : 1 , tasks : [ { id : 3 , title : 'test' , description : '' , color : '#ffffe0' , points : 1 , position : 1 , column_id : 1 , comments : [ { text : '' } as any ] , attachments : [ ] , assignees : [ { } ] , categories : [ { } ] } ] } as any ; ( component . boardService . getTaskActivity as any ) = ( ) => { return { subscribe : ( fn ) => fn ( { data : [ { } , [ { text : '' , timestamp : '' } ] ] } as any ) } ; } ; view ( ) ; expect ( component . viewModalProps . column_id ) . toEqual ( 1 ) ; } ) ; it ( 'gets a username by user id' , ( ) => { component . activeBoard = { users : [ { id : 1 , username : 'test' } as any ] } as any ; const uname = component . getUserName ( 1 ) ; expect ( uname ) . toEqual ( 'test' ) ; } ) ; it ( 'can call board update with an emitter' , ( ) => { let called = false ; component . onUpdateBoards . subscribe ( ( ) => { called = true ; } ) ; component . callBoardUpdate ( ) ; expect ( called ) . toEqual ( true ) ; } ) ; } ) ;