import 'mocha' ; import { expect } from 'chai' ; import { SelectedScript } from '@/application/Context/State/Selection/SelectedScript' ; import { UserSelection } from '@/application/Context/State/Selection/UserSelection' ; import { CategoryStub } from '@tests/unit/stubs/CategoryStub' ; import { CategoryCollectionStub } from '@tests/unit/stubs/CategoryCollectionStub' ; import { SelectedScriptStub } from '@tests/unit/stubs/SelectedScriptStub' ; import { ScriptStub } from '@tests/unit/stubs/ScriptStub' ; import { UserSelectionTestRunner } from './UserSelectionTestRunner' ; describe ( 'UserSelection' , ( ) => { describe ( 'ctor' , ( ) => { describe ( 'has nothing with no initial selection' , ( ) => { const allScripts = [ new SelectedScriptStub ( 's1' , false ) , ] ; new UserSelectionTestRunner ( ) . withSelectedScripts ( [ ] ) . withCategory ( 1 , allScripts . map ( ( s ) => s . script ) ) . run ( ) . expectFinalScripts ( [ ] ) ; } ) ; describe ( 'has initial selection' , ( ) => { const scripts = [ new SelectedScriptStub ( 's1' , false ) , new SelectedScriptStub ( 's2' , false ) , ] ; new UserSelectionTestRunner ( ) . withSelectedScripts ( scripts ) . withCategory ( 1 , scripts . map ( ( s ) => s . script ) ) . run ( ) . expectFinalScripts ( scripts ) ; } ) ; } ) ; describe ( 'deselectAll' , ( ) => { describe ( 'removes existing items' , ( ) => { const allScripts = [ new SelectedScriptStub ( 's1' , false ) , new SelectedScriptStub ( 's2' , false ) , new SelectedScriptStub ( 's3' , false ) , new SelectedScriptStub ( 's4' , false ) , ] ; const selectedScripts = allScripts . filter ( ( s ) => [ 's1' , 's2' , 's3' ] . includes ( s . id ) ) ; new UserSelectionTestRunner ( ) . withSelectedScripts ( selectedScripts ) . withCategory ( 1 , allScripts . map ( ( s ) => s . script ) ) . run ( ( sut ) => { sut . deselectAll ( ) ; } ) . expectTotalFiredEvents ( 1 ) . expectFinalScripts ( [ ] ) . expectFinalScriptsInEvent ( 0 , [ ] ) ; } ) ; describe ( 'does not notify if nothing is selected' , ( ) => { new UserSelectionTestRunner ( ) . withSelectedScripts ( [ ] ) . run ( ( sut ) => { sut . deselectAll ( ) ; } ) . expectTotalFiredEvents ( 0 ) ; } ) ; } ) ; describe ( 'selectAll' , ( ) => { describe ( 'selects as expected' , ( ) => { const expected = [ new SelectedScriptStub ( 's1' , false ) , new SelectedScriptStub ( 's2' , false ) , ] ; new UserSelectionTestRunner ( ) . withSelectedScripts ( [ ] ) . withCategory ( 1 , expected . map ( ( s ) => s . script ) ) . run ( ( sut ) => { sut . selectAll ( ) ; } ) . expectTotalFiredEvents ( 1 ) . expectFinalScripts ( expected ) . expectFinalScriptsInEvent ( 0 , expected ) ; } ) ; describe ( 'does not notify if nothing new is selected' , ( ) => { const allScripts = [ new ScriptStub ( 's1' ) , new ScriptStub ( 's2' ) ] ; const selectedScripts = allScripts . map ( ( s ) => s . toSelectedScript ( false ) ) ; new UserSelectionTestRunner ( ) . withSelectedScripts ( selectedScripts ) . withCategory ( 0 , allScripts ) . run ( ( sut ) => { sut . selectAll ( ) ; } ) . expectTotalFiredEvents ( 0 ) ; } ) ; } ) ; describe ( 'selectOnly' , ( ) => { describe ( 'selects as expected' , ( ) => { const allScripts = [ new SelectedScriptStub ( 's1' , false ) , new SelectedScriptStub ( 's2' , false ) , new SelectedScriptStub ( 's3' , false ) , new SelectedScriptStub ( 's4' , false ) , ] ; const getScripts = ( ... ids ) => allScripts . filter ( ( s ) => ids . includes ( s . id ) ) ; const testCases = [ { name : 'adds as expected' , preSelected : getScripts ( 's1' ) , toSelect : getScripts ( 's1' , 's2' ) , } , { name : 'removes as expected' , preSelected : getScripts ( 's1' , 's2' , 's3' ) , toSelect : getScripts ( 's1' ) , } , { name : 'adds and removes as expected' , preSelected : getScripts ( 's1' , 's2' , 's3' ) , toSelect : getScripts ( 's2' , 's3' , 's4' ) , } , ] ; for ( const testCase of testCases ) { describe ( testCase . name , ( ) => { new UserSelectionTestRunner ( ) . withSelectedScripts ( testCase . preSelected ) . withCategory ( 1 , testCase . toSelect . map ( ( s ) => s . script ) ) . run ( ( sut ) => { sut . selectOnly ( testCase . toSelect . map ( ( s ) => s . script ) ) ; } ) . expectTotalFiredEvents ( 1 ) . expectFinalScripts ( testCase . toSelect ) . expectFinalScriptsInEvent ( 0 , testCase . toSelect ) ; } ) ; } } ) ; describe ( 'does not notify if selection does not change' , ( ) => { const allScripts = [ new ScriptStub ( 's1' ) , new ScriptStub ( 's2' ) , new ScriptStub ( 's3' ) ] ; const toSelect = [ allScripts [ 0 ] , allScripts [ 1 ] ] ; const preSelected = toSelect . map ( ( s ) => s . toSelectedScript ( false ) ) ; new UserSelectionTestRunner ( ) . withSelectedScripts ( preSelected ) . withCategory ( 0 , allScripts ) . run ( ( sut ) => { sut . selectOnly ( toSelect ) ; } ) . expectTotalFiredEvents ( 0 ) ; } ) ; } ) ; describe ( 'addOrUpdateSelectedScript' , ( ) => { describe ( 'adds when item does not exist' , ( ) => { const scripts = [ new ScriptStub ( 's1' ) , new ScriptStub ( 's2' ) ] ; const expected = [ new SelectedScript ( scripts [ 0 ] , false ) ] ; new UserSelectionTestRunner ( ) . withSelectedScripts ( [ ] ) . withCategory ( 1 , scripts ) . run ( ( sut ) => { sut . addOrUpdateSelectedScript ( scripts [ 0 ] . id , false ) ; } ) . expectTotalFiredEvents ( 1 ) . expectFinalScripts ( expected ) . expectFinalScriptsInEvent ( 0 , expected ) ; } ) ; describe ( 'updates when item exists' , ( ) => { const scripts = [ new ScriptStub ( 's1' ) , new ScriptStub ( 's2' ) ] ; const existing = new SelectedScript ( scripts [ 0 ] , false ) ; const expected = new SelectedScript ( scripts [ 0 ] , true ) ; new UserSelectionTestRunner ( ) . withSelectedScripts ( [ existing ] ) . withCategory ( 1 , scripts ) . run ( ( sut ) => { sut . addOrUpdateSelectedScript ( expected . id , expected . revert ) ; } ) . expectTotalFiredEvents ( 1 ) . expectFinalScripts ( [ expected ] ) . expectFinalScriptsInEvent ( 0 , [ expected ] ) ; } ) ; } ) ; describe ( 'removeAllInCategory' , ( ) => { describe ( 'does nothing when nothing exists' , ( ) => { const categoryId = 99 ; const scripts = [ new ScriptStub ( 's1' ) , new ScriptStub ( 's2' ) ] ; new UserSelectionTestRunner ( ) . withSelectedScripts ( [ ] ) . withCategory ( categoryId , scripts ) . run ( ( sut ) => { sut . removeAllInCategory ( categoryId ) ; } ) . expectTotalFiredEvents ( 0 ) . expectFinalScripts ( [ ] ) ; } ) ; describe ( 'removes all when all exists' , ( ) => { const categoryId = 34 ; const scripts = [ new SelectedScriptStub ( 's1' ) , new SelectedScriptStub ( 's2' ) ] ; new UserSelectionTestRunner ( ) . withSelectedScripts ( scripts ) . withCategory ( categoryId , scripts . map ( ( s ) => s . script ) ) . run ( ( sut ) => { sut . removeAllInCategory ( categoryId ) ; } ) . expectTotalFiredEvents ( 1 ) . expectFinalScripts ( [ ] ) ; } ) ; describe ( 'removes existing when some exists' , ( ) => { const categoryId = 55 ; const existing = [ new ScriptStub ( 's1' ) , new ScriptStub ( 's2' ) ] ; const notExisting = [ new ScriptStub ( 's3' ) , new ScriptStub ( 's4' ) ] ; new UserSelectionTestRunner ( ) . withSelectedScripts ( existing . map ( ( script ) => new SelectedScript ( script , false ) ) ) . withCategory ( categoryId , [ ... existing , ... notExisting ] ) . run ( ( sut ) => { sut . removeAllInCategory ( categoryId ) ; } ) . expectTotalFiredEvents ( 1 ) . expectFinalScripts ( [ ] ) ; } ) ; } ) ; describe ( 'addOrUpdateAllInCategory' , ( ) => { describe ( 'when all already exists' , ( ) => { describe ( 'does nothing if nothing is changed' , ( ) => { const categoryId = 55 ; const existingScripts = [ new SelectedScriptStub ( 's1' , false ) , new SelectedScriptStub ( 's2' , false ) , ] ; new UserSelectionTestRunner ( ) . withSelectedScripts ( existingScripts ) . withCategory ( categoryId , existingScripts . map ( ( s ) => s . script ) ) . run ( ( sut ) => { sut . addOrUpdateAllInCategory ( categoryId ) ; } ) . expectTotalFiredEvents ( 0 ) . expectFinalScripts ( existingScripts ) ; } ) ; describe ( 'changes revert status of all' , ( ) => { const newStatus = false ; const scripts = [ new SelectedScriptStub ( 'e1' , ! newStatus ) , new SelectedScriptStub ( 'e2' , ! newStatus ) , new SelectedScriptStub ( 'e3' , newStatus ) , ] ; const expectedScripts = scripts . map ( ( s ) => new SelectedScript ( s . script , newStatus ) ) ; const categoryId = 31 ; new UserSelectionTestRunner ( ) . withSelectedScripts ( scripts ) . withCategory ( categoryId , scripts . map ( ( s ) => s . script ) ) . run ( ( sut ) => { sut . addOrUpdateAllInCategory ( categoryId , newStatus ) ; } ) . expectTotalFiredEvents ( 1 ) . expectFinalScripts ( expectedScripts ) . expectFinalScriptsInEvent ( 0 , expectedScripts ) ; } ) ; } ) ; describe ( 'when nothing exists; adds all with given revert status' , ( ) => { const revertStatuses = [ true , false ] ; for ( const revertStatus of revertStatuses ) { describe ( `when revert status is ${ revertStatus }` , ( ) => { const categoryId = 1 ; const scripts = [ new SelectedScriptStub ( 's1' , ! revertStatus ) , new SelectedScriptStub ( 's2' , ! revertStatus ) , ] ; const expected = scripts . map ( ( s ) => new SelectedScript ( s . script , revertStatus ) ) ; new UserSelectionTestRunner ( ) . withSelectedScripts ( [ ] ) . withCategory ( categoryId , scripts . map ( ( s ) => s . script ) ) . run ( ( sut ) => { sut . addOrUpdateAllInCategory ( categoryId , revertStatus ) ; } ) . expectTotalFiredEvents ( 1 ) . expectFinalScripts ( expected ) . expectFinalScriptsInEvent ( 0 , expected ) ; } ) ; } } ) ; describe ( 'when some exists; changes revert status of all' , ( ) => { const newStatus = true ; const existing = [ new SelectedScriptStub ( 'e1' , true ) , new SelectedScriptStub ( 'e2' , false ) , ] ; const notExisting = [ new SelectedScriptStub ( 'n3' , true ) , new SelectedScriptStub ( 'n4' , false ) , ] ; const allScripts = [ ... existing , ... notExisting ] ; const expectedScripts = allScripts . map ( ( s ) => new SelectedScript ( s . script , newStatus ) ) ; const categoryId = 77 ; new UserSelectionTestRunner ( ) . withSelectedScripts ( existing ) . withCategory ( categoryId , allScripts . map ( ( s ) => s . script ) ) . run ( ( sut ) => { sut . addOrUpdateAllInCategory ( categoryId , newStatus ) ; } ) . expectTotalFiredEvents ( 1 ) . expectFinalScripts ( expectedScripts ) . expectFinalScriptsInEvent ( 0 , expectedScripts ) ; } ) ; } ) ; describe ( 'isSelected' , ( ) => { it ( 'returns false when not selected' , ( ) => { const selectedScript = new ScriptStub ( 'selected' ) ; const notSelectedScript = new ScriptStub ( 'not selected' ) ; const collection = new CategoryCollectionStub ( ) . withAction ( new CategoryStub ( 1 ) . withScripts ( selectedScript , notSelectedScript ) ) ; const sut = new UserSelection ( collection , [ new SelectedScript ( selectedScript , false ) ] ) ; const actual = sut . isSelected ( notSelectedScript . id ) ; expect ( actual ) . to . equal ( false ) ; } ) ; it ( 'returns true when selected' , ( ) => { const selectedScript = new ScriptStub ( 'selected' ) ; const notSelectedScript = new ScriptStub ( 'not selected' ) ; const collection = new CategoryCollectionStub ( ) . withAction ( new CategoryStub ( 1 ) . withScripts ( selectedScript , notSelectedScript ) ) ; const sut = new UserSelection ( collection , [ new SelectedScript ( selectedScript , false ) ] ) ; const actual = sut . isSelected ( selectedScript . id ) ; expect ( actual ) . to . equal ( true ) ; } ) ; } ) ; describe ( 'category state' , ( ) => { describe ( 'when no scripts are selected' , ( ) => { const category = new CategoryStub ( 1 ) . withScriptIds ( 'non-selected-script-1' , 'non-selected-script-2' ) ; const collection = new CategoryCollectionStub ( ) . withAction ( category ) ; const sut = new UserSelection ( collection , [ ] ) ; it ( 'areAllSelected returns false' , ( ) => { const actual = sut . areAllSelected ( category ) ; expect ( actual ) . to . equal ( false ) ; } ) ; it ( 'isAnySelected returns false' , ( ) => { const actual = sut . isAnySelected ( category ) ; expect ( actual ) . to . equal ( false ) ; } ) ; } ) ; describe ( 'when no subscript exists in selected scripts' , ( ) => { const category = new CategoryStub ( 1 ) . withScriptIds ( 'non-selected-script-1' , 'non-selected-script-2' ) ; const selectedScript = new ScriptStub ( 'selected' ) ; const collection = new CategoryCollectionStub ( ) . withAction ( category ) . withAction ( new CategoryStub ( 22 ) . withScript ( selectedScript ) ) ; const sut = new UserSelection ( collection , [ new SelectedScript ( selectedScript , false ) ] ) ; it ( 'areAllSelected returns false' , ( ) => { const actual = sut . areAllSelected ( category ) ; expect ( actual ) . to . equal ( false ) ; } ) ; it ( 'isAnySelected returns false' , ( ) => { const actual = sut . isAnySelected ( category ) ; expect ( actual ) . to . equal ( false ) ; } ) ; } ) ; describe ( 'when one of the scripts are selected' , ( ) => { const selectedScript = new ScriptStub ( 'selected' ) ; const category = new CategoryStub ( 1 ) . withScriptIds ( 'non-selected-script-1' , 'non-selected-script-2' ) . withCategory ( new CategoryStub ( 12 ) . withScript ( selectedScript ) ) ; const collection = new CategoryCollectionStub ( ) . withAction ( category ) ; const sut = new UserSelection ( collection , [ new SelectedScript ( selectedScript , false ) ] ) ; it ( 'areAllSelected returns false' , ( ) => { const actual = sut . areAllSelected ( category ) ; expect ( actual ) . to . equal ( false ) ; } ) ; it ( 'isAnySelected returns true' , ( ) => { const actual = sut . isAnySelected ( category ) ; expect ( actual ) . to . equal ( true ) ; } ) ; } ) ; describe ( 'when all scripts are selected' , ( ) => { const firstSelectedScript = new ScriptStub ( 'selected1' ) ; const secondSelectedScript = new ScriptStub ( 'selected2' ) ; const category = new CategoryStub ( 1 ) . withScript ( firstSelectedScript ) . withCategory ( new CategoryStub ( 12 ) . withScript ( secondSelectedScript ) ) ; const collection = new CategoryCollectionStub ( ) . withAction ( category ) ; const selectedScripts = [ firstSelectedScript , secondSelectedScript ] . map ( ( s ) => new SelectedScript ( s , false ) ) ; const sut = new UserSelection ( collection , selectedScripts ) ; it ( 'areAllSelected returns true' , ( ) => { const actual = sut . areAllSelected ( category ) ; expect ( actual ) . to . equal ( true ) ; } ) ; it ( 'isAnySelected returns true' , ( ) => { const actual = sut . isAnySelected ( category ) ; expect ( actual ) . to . equal ( true ) ; } ) ; } ) ; } ) ; } ) ;