aboutsummaryrefslogtreecommitdiffstats
path: root/spec/javascript
diff options
context:
space:
mode:
authorLuc Donnet2017-10-16 23:52:06 +0200
committerLuc Donnet2017-10-16 23:52:06 +0200
commitf480ad0739e5c0ec2c0c8bb890344b9c4777ba35 (patch)
treea19bc6b43449b8b978a53c33476fb3eb571d4dda /spec/javascript
parentb611a84ed724036c4929bd4c3eaa7e23ea314f45 (diff)
parent51a1ea5b141032121913f807a162d305828bec54 (diff)
downloadchouette-core-f480ad0739e5c0ec2c0c8bb890344b9c4777ba35.tar.bz2
Merge branch 'master' into staging
Diffstat (limited to 'spec/javascript')
-rw-r--r--spec/javascript/journey_patterns/actions_spec.js154
-rw-r--r--spec/javascript/journey_patterns/reducers/journey_patterns_spec.js125
-rw-r--r--spec/javascript/journey_patterns/reducers/modal_spec.js98
-rw-r--r--spec/javascript/journey_patterns/reducers/pagination_spec.js93
-rw-r--r--spec/javascript/journey_patterns/reducers/status_spec.js51
-rw-r--r--spec/javascript/routes/actions_spec.js101
-rw-r--r--spec/javascript/routes/reducers/stop_points_spec.js486
-rw-r--r--spec/javascript/spec_helper.coffee32
-rw-r--r--spec/javascript/time_table/actions_spec.js237
-rw-r--r--spec/javascript/time_table/reducers/metas_spec.js77
-rw-r--r--spec/javascript/time_table/reducers/modal_spec.js328
-rw-r--r--spec/javascript/time_table/reducers/pagination_spec.js139
-rw-r--r--spec/javascript/time_table/reducers/status_spec.js50
-rw-r--r--spec/javascript/time_table/reducers/timetable_spec.js338
-rw-r--r--spec/javascript/vehicle_journeys/actions_spec.js449
-rw-r--r--spec/javascript/vehicle_journeys/reducers/filters_spec.js165
-rw-r--r--spec/javascript/vehicle_journeys/reducers/modal_spec.js179
-rw-r--r--spec/javascript/vehicle_journeys/reducers/pagination_spec.js123
-rw-r--r--spec/javascript/vehicle_journeys/reducers/status_spec.js45
-rw-r--r--spec/javascript/vehicle_journeys/reducers/vehicle_journeys_spec.js268
20 files changed, 3538 insertions, 0 deletions
diff --git a/spec/javascript/journey_patterns/actions_spec.js b/spec/javascript/journey_patterns/actions_spec.js
new file mode 100644
index 000000000..2542fa2f4
--- /dev/null
+++ b/spec/javascript/journey_patterns/actions_spec.js
@@ -0,0 +1,154 @@
+import actions from '../../../app/javascript/journey_patterns/actions'
+
+const dispatch = function(){}
+const currentPage = 1
+
+describe('when receiveJourneyPatterns is triggered', () => {
+ it('should create an action to pass json to reducer', () => {
+ const json = undefined
+ const expectedAction = {
+ type: 'RECEIVE_JOURNEY_PATTERNS',
+ json
+ }
+ expect(actions.receiveJourneyPatterns()).toEqual(expectedAction)
+ })
+})
+
+describe('when previous navigation button is clicked', () => {
+ it('should create an action to go to previous page', () => {
+ const nextPage = false
+ const pagination = {
+ totalCount: 25,
+ perPage: 12,
+ page:1
+ }
+ const expectedAction = {
+ type: 'GO_TO_PREVIOUS_PAGE',
+ dispatch,
+ pagination,
+ nextPage
+ }
+ expect(actions.goToPreviousPage(dispatch, pagination)).toEqual(expectedAction)
+ })
+})
+describe('when next navigation button is clicked', () => {
+ it('should create an action to go to next page', () => {
+ const nextPage = true
+ const pagination = {
+ totalCount: 25,
+ perPage: 12,
+ page:1
+ }
+ const expectedAction = {
+ type: 'GO_TO_NEXT_PAGE',
+ dispatch,
+ pagination,
+ nextPage
+ }
+ expect(actions.goToNextPage(dispatch, pagination)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on a journey pattern checkbox', () => {
+ it('should create an action to update journey pattern stop points', () => {
+ const event = {
+ currentTarget: {
+ id: '1'
+ }
+ }
+ const index = 1
+ const expectedAction = {
+ type: 'UPDATE_CHECKBOX_VALUE',
+ id: event.currentTarget.id,
+ index,
+ }
+ expect(actions.updateCheckboxValue(event, index)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on next button', () => {
+ it('should create an action to open a confirm modal', () => {
+ const callback = function(){}
+ const expectedAction = {
+ type: 'OPEN_CONFIRM_MODAL',
+ callback
+ }
+ expect(actions.openConfirmModal(callback)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on edit button', () => {
+ it('should create an action to open a edit modal', () => {
+ const index = 1
+ const journeyPattern = {}
+ const expectedAction = {
+ type: 'EDIT_JOURNEYPATTERN_MODAL',
+ index,
+ journeyPattern,
+ }
+ expect(actions.openEditModal(index, journeyPattern)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on add button', () => {
+ it('should create an action to open a create modal', () => {
+ const expectedAction = {
+ type: 'CREATE_JOURNEYPATTERN_MODAL',
+ }
+ expect(actions.openCreateModal()).toEqual(expectedAction)
+ })
+})
+describe('when clicking on close button inside edit or add modal', () => {
+ it('should create an action to close modal', () => {
+ const expectedAction = {
+ type: 'CLOSE_MODAL',
+ }
+ expect(actions.closeModal()).toEqual(expectedAction)
+ })
+})
+describe('when clicking on a journey pattern delete button', () => {
+ it('should create an action to delete journey pattern', () => {
+ const index = 1
+ const expectedAction = {
+ type: 'DELETE_JOURNEYPATTERN',
+ index
+ }
+ expect(actions.deleteJourneyPattern(index)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on validate button inside edit modal', () => {
+ it('should create an action to save journey pattern modifications', () => {
+ const index = 1
+ const data = {}
+ const expectedAction = {
+ type: 'SAVE_MODAL',
+ index,
+ data
+ }
+ expect(actions.saveModal(index, data)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on validate button inside create modal', () => {
+ it('should create an action to create a new journey pattern', () => {
+ const data = {}
+ const expectedAction = {
+ type: 'ADD_JOURNEYPATTERN',
+ data
+ }
+ expect(actions.addJourneyPattern(data)).toEqual(expectedAction)
+ })
+})
+describe('when submitting new journeyPatterns', () => {
+ it('should create an action to update pagination totalCount', () => {
+ const diff = 1
+ const expectedAction = {
+ type: 'UPDATE_TOTAL_COUNT',
+ diff
+ }
+ expect(actions.updateTotalCount(diff)).toEqual(expectedAction)
+ })
+})
+describe('when fetching api', () => {
+ it('should create an action to fetch api', () => {
+ const expectedAction = {
+ type: 'FETCH_API',
+ }
+ expect(actions.fetchingApi()).toEqual(expectedAction)
+ })
+})
diff --git a/spec/javascript/journey_patterns/reducers/journey_patterns_spec.js b/spec/javascript/journey_patterns/reducers/journey_patterns_spec.js
new file mode 100644
index 000000000..24780ab5a
--- /dev/null
+++ b/spec/javascript/journey_patterns/reducers/journey_patterns_spec.js
@@ -0,0 +1,125 @@
+import jpReducer from '../../../../app/javascript/journey_patterns/reducers/journeyPatterns'
+
+let state = []
+let fakeStopPoints = [{
+ area_type : "lda",
+ checked : false,
+ id : 45289,
+ name : "Clichy Levallois",
+ object_id : "FR:92044:LDA:72073:STIF",
+ position : 0,
+},{
+ area_type : "lda",
+ checked : false,
+ id : 40534,
+ name : "Thomas LemaƮtre",
+ object_id : "FR:92050:LDA:70915:STIF",
+ position : 1,
+}]
+let stopPoints = [{
+ area_type : 'zdep',
+ city_name : 'Plaisir',
+ for_alighting : 'normal',
+ for_boarding : 'normal',
+ id : 14892,
+ name : 'test1',
+ object_id : 'test:StopPoint:1',
+ position : 0,
+ zip_code : '78490'
+},{
+ area_type : 'zdep',
+ city_name : 'Plaisir',
+ for_alighting : 'normal',
+ for_boarding : 'normal',
+ id : 14893,
+ name : 'test2',
+ object_id : 'test:StopPoint:2',
+ position : 1,
+ zip_code : '78490'
+}]
+
+describe('journeyPatterns reducer', () => {
+ beforeEach(()=>{
+ state = [
+ {
+ deletable: false,
+ name: 'm1',
+ object_id : 'o1',
+ published_name: 'M1',
+ registration_number: '',
+ stop_points: fakeStopPoints
+ },
+ {
+ deletable: false,
+ name: 'm2',
+ object_id : 'o2',
+ published_name: 'M2',
+ registration_number: '',
+ stop_points: fakeStopPoints
+ }
+ ]
+ })
+
+ it('should return the initial state', () => {
+ expect(
+ jpReducer(undefined, {})
+ ).toEqual([])
+ })
+
+ it('should handle ADD_JOURNEYPATTERN', () => {
+ let fakeData = {
+ name: {value : 'm3'},
+ published_name: {value: 'M3'},
+ registration_number: {value: ''}
+ }
+ let stopPoints = stopPoints
+ expect(
+ jpReducer(state, {
+ type: 'ADD_JOURNEYPATTERN',
+ data: fakeData
+ })
+ ).toEqual([{
+ name : 'm3',
+ published_name: 'M3',
+ registration_number: '',
+ deletable: false,
+ stop_points: stopPoints
+ }, ...state])
+ })
+
+ it('should handle UPDATE_CHECKBOX_VALUE', () => {
+ let newFirstStopPoint = Object.assign({}, fakeStopPoints[0], {checked: !fakeStopPoints[0].checked} )
+ let newStopPoints = [newFirstStopPoint, fakeStopPoints[1]]
+ let newState = Object.assign({}, state[0], {stop_points: newStopPoints})
+ expect(
+ jpReducer(state, {
+ type: 'UPDATE_CHECKBOX_VALUE',
+ id: 45289,
+ index: 0
+ })
+ ).toEqual([newState, state[1]])
+ })
+
+ it('should handle DELETE_JOURNEYPATTERN', () => {
+ expect(
+ jpReducer(state, {
+ type: 'DELETE_JOURNEYPATTERN',
+ index: 1
+ })
+ ).toEqual([state[0], Object.assign({}, state[1], {deletable: true})])
+ })
+ it('should handle SAVE_MODAL', () => {
+ let newState = Object.assign({}, state[0], {name: 'p1', published_name: 'P1', registration_number: 'PP11'})
+ expect(
+ jpReducer(state, {
+ type: 'SAVE_MODAL',
+ data: {
+ name: {value: 'p1'},
+ published_name: {value: 'P1'},
+ registration_number: {value: 'PP11'}
+ },
+ index: 0
+ })
+ ).toEqual([newState, state[1]])
+ })
+})
diff --git a/spec/javascript/journey_patterns/reducers/modal_spec.js b/spec/javascript/journey_patterns/reducers/modal_spec.js
new file mode 100644
index 000000000..4031ea234
--- /dev/null
+++ b/spec/javascript/journey_patterns/reducers/modal_spec.js
@@ -0,0 +1,98 @@
+import modalReducer from '../../../../app/javascript/journey_patterns/reducers/modal'
+
+let state = {}
+
+let fakeJourneyPattern = {
+ name: 'jp_test 1',
+ object_id: 'jp_test:JourneyPattern:1',
+ published_name: 'jp_test publishedname 1',
+ registration_number: 'jp_test registrationnumber 1',
+ stop_points: [],
+ deletable: false
+}
+
+const cb = function(){}
+
+describe('modal reducer', () => {
+ beforeEach(() => {
+ state = {
+ type: '',
+ modalProps: {},
+ confirmModal: {}
+ }
+ })
+
+ it('should return the initial state', () => {
+ expect(
+ modalReducer(undefined, {})
+ ).toEqual({})
+ })
+
+ it('should handle OPEN_CONFIRM_MODAL', () => {
+ let newState = Object.assign({}, state, {
+ type: 'confirm',
+ confirmModal: {
+ callback: cb
+ }
+ })
+ expect(
+ modalReducer(state, {
+ type: 'OPEN_CONFIRM_MODAL',
+ callback: cb
+ })
+ ).toEqual(newState)
+ })
+
+ it('should handle EDIT_JOURNEYPATTERN_MODAL', () => {
+ let newState = Object.assign({}, state, {
+ type: 'edit',
+ modalProps: {
+ index: 0,
+ journeyPattern: fakeJourneyPattern
+ },
+ confirmModal: {}
+ })
+ expect(
+ modalReducer(state, {
+ type: 'EDIT_JOURNEYPATTERN_MODAL',
+ index: 0,
+ journeyPattern : fakeJourneyPattern
+ })
+ ).toEqual(newState)
+ })
+
+ it('should handle CREATE_JOURNEYPATTERN_MODAL', () => {
+ expect(
+ modalReducer(state, {
+ type: 'CREATE_JOURNEYPATTERN_MODAL'
+ })
+ ).toEqual(Object.assign({}, state, { type: 'create' }))
+ })
+
+ it('should handle DELETE_JOURNEYPATTERN', () => {
+ expect(
+ modalReducer(state, {
+ type: 'DELETE_JOURNEYPATTERN',
+ index: 0
+ })
+ ).toEqual(state)
+ })
+
+ it('should handle SAVE_MODAL', () => {
+ expect(
+ modalReducer(state, {
+ type: 'SAVE_MODAL',
+ index: 0,
+ data: {}
+ })
+ ).toEqual(state)
+ })
+
+ it('should handle CLOSE_MODAL', () => {
+ expect(
+ modalReducer(state, {
+ type: 'CLOSE_MODAL'
+ })
+ ).toEqual(state)
+ })
+})
diff --git a/spec/javascript/journey_patterns/reducers/pagination_spec.js b/spec/javascript/journey_patterns/reducers/pagination_spec.js
new file mode 100644
index 000000000..a3cd4bf0a
--- /dev/null
+++ b/spec/javascript/journey_patterns/reducers/pagination_spec.js
@@ -0,0 +1,93 @@
+import reducer from '../../../../app/javascript/journey_patterns/reducers/pagination'
+
+const diff = 1
+let state = {
+ page : 2,
+ totalCount : 50,
+ stateChanged: false,
+ perPage: 20
+}
+let pagination = Object.assign({}, state)
+const dispatch = function(){}
+
+describe('pagination reducer, given parameters allowing page change', () => {
+
+ it('should return the initial state', () => {
+ expect(
+ reducer(undefined, {})
+ ).toEqual({})
+ })
+
+ it('should handle GO_TO_NEXT_PAGE and change state', () => {
+ expect(
+ reducer(state, {
+ type: 'GO_TO_NEXT_PAGE',
+ dispatch,
+ pagination,
+ nextPage : true
+ })
+ ).toEqual(Object.assign({}, state, {page : state.page + 1, stateChanged: false}))
+ })
+
+ it('should return GO_TO_PREVIOUS_PAGE and change state', () => {
+ expect(
+ reducer(state, {
+ type: 'GO_TO_PREVIOUS_PAGE',
+ dispatch,
+ pagination,
+ nextPage : false
+ })
+ ).toEqual(Object.assign({}, state, {page : state.page - 1, stateChanged: false}))
+ })
+})
+
+
+describe('pagination reducer, given parameters not allowing to go to previous page', () => {
+
+ beforeEach(()=>{
+ state.page = 1
+ pagination.page = 1
+ })
+
+ it('should return GO_TO_PREVIOUS_PAGE and not change state', () => {
+ expect(
+ reducer(state, {
+ type: 'GO_TO_PREVIOUS_PAGE',
+ dispatch,
+ pagination,
+ nextPage : false
+ })
+ ).toEqual(state)
+ })
+})
+
+describe('pagination reducer, given parameters not allowing to go to next page', () => {
+
+ beforeEach(()=>{
+ state.page = 3
+ pagination.page = 3
+ })
+
+ it('should return GO_TO_NEXT_PAGE and not change state', () => {
+ expect(
+ reducer(state, {
+ type: 'GO_TO_NEXT_PAGE',
+ dispatch,
+ pagination,
+ nextPage : true
+ })
+ ).toEqual(state)
+ })
+})
+
+describe('pagination reducer, given parameters changing totalCount', () => {
+
+ it('should return UPDATE_TOTAL_COUNT and update totalCount', () => {
+ expect(
+ reducer(state, {
+ type: 'UPDATE_TOTAL_COUNT',
+ diff
+ })
+ ).toEqual(Object.assign({}, state, {totalCount: state.totalCount - diff}))
+ })
+})
diff --git a/spec/javascript/journey_patterns/reducers/status_spec.js b/spec/javascript/journey_patterns/reducers/status_spec.js
new file mode 100644
index 000000000..ab094088a
--- /dev/null
+++ b/spec/javascript/journey_patterns/reducers/status_spec.js
@@ -0,0 +1,51 @@
+import statusReducer from '../../../../app/javascript/journey_patterns/reducers/status'
+
+let state = {}
+
+let pagination = {
+ page : 2,
+ totalCount : 25,
+ stateChanged: false,
+ perPage: 12
+}
+const dispatch = function(){}
+
+describe('status reducer', () => {
+ beforeEach(() => {
+ state = {
+ fetchSuccess: true,
+ isFetching: false
+ }
+ })
+
+ it('should return the initial state', () => {
+ expect(
+ statusReducer(undefined, {})
+ ).toEqual({})
+ })
+
+ it('should handle UNAVAILABLE_SERVER', () => {
+ expect(
+ statusReducer(state, {
+ type: 'UNAVAILABLE_SERVER'
+ })
+ ).toEqual(Object.assign({}, state, {fetchSuccess: false}))
+ })
+
+ it('should handle RECEIVE_JOURNEY_PATTERNS', () => {
+ expect(
+ statusReducer(state, {
+ type: 'RECEIVE_JOURNEY_PATTERNS'
+ })
+ ).toEqual(Object.assign({}, state, {fetchSuccess: true, isFetching: false}))
+ })
+
+ it('should handle FETCH_API', () => {
+ expect(
+ statusReducer(state, {
+ type: 'FETCH_API'
+ })
+ ).toEqual(Object.assign({}, state, {isFetching: true}))
+ })
+
+})
diff --git a/spec/javascript/routes/actions_spec.js b/spec/javascript/routes/actions_spec.js
new file mode 100644
index 000000000..507e1e0ed
--- /dev/null
+++ b/spec/javascript/routes/actions_spec.js
@@ -0,0 +1,101 @@
+import actions from '../../../app/javascript/routes/actions'
+
+describe('actions', () => {
+ it('should create an action to add a stop', () => {
+ const expectedAction = {
+ type: 'ADD_STOP',
+ }
+ expect(actions.addStop()).toEqual(expectedAction)
+ })
+})
+describe('actions', () => {
+ it('should create an action to move up a stop', () => {
+ const index = 1
+ const expectedAction = {
+ type: 'MOVE_STOP_UP',
+ index
+ }
+ expect(actions.moveStopUp(index)).toEqual(expectedAction)
+ })
+})
+describe('actions', () => {
+ it('should create an action to move down a stop', () => {
+ const index = 1
+ const expectedAction = {
+ type: 'MOVE_STOP_DOWN',
+ index
+ }
+ expect(actions.moveStopDown(index)).toEqual(expectedAction)
+ })
+})
+describe('actions', () => {
+ it('should create an action to delete a stop', () => {
+ const index = 1
+ const expectedAction = {
+ type: 'DELETE_STOP',
+ index
+ }
+ expect(actions.deleteStop(index)).toEqual(expectedAction)
+ })
+})
+describe('actions', () => {
+ it('should create an action to update the value of a stop', () => {
+ const text = 'updated text'
+ const index = 1
+ const expectedAction = {
+ type: 'UPDATE_INPUT_VALUE',
+ index,
+ text
+ }
+ expect(actions.updateInputValue(index, text)).toEqual(expectedAction)
+ })
+})
+
+describe('actions', () => {
+ it('should create an action to update the up select of a stop', () => {
+ const event = {
+ currentTarget: {
+ value: 'forbidden',
+ id: 'up'
+ }
+ }
+ const index = 1
+ const expectedAction = {
+ type :'UPDATE_SELECT_VALUE',
+ select_id: 'up',
+ select_value: 'forbidden',
+ index
+ }
+ expect(actions.updateSelectValue(event, index)).toEqual(expectedAction)
+ })
+})
+
+describe('actions', () => {
+ it('should create an action to toggle the map', () => {
+ const index = 1
+ const expectedAction = {
+ type: 'TOGGLE_MAP',
+ index
+ }
+ expect(actions.toggleMap(index)).toEqual(expectedAction)
+ })
+})
+
+describe('actions', () => {
+ it('should create an action to select a marker on the map', () => {
+ const index = 1
+ const data = {
+ geometry: undefined,
+ registration_number: 'rn_test',
+ stoparea_id: 'sid_test',
+ text: 't_test',
+ user_objectid: 'uoid_test'
+ }
+ const expectedAction = {
+ type: 'SELECT_MARKER',
+ index,
+ data
+ }
+ expect(actions.selectMarker(index, data)).toEqual(expectedAction)
+ })
+})
diff --git a/spec/javascript/routes/reducers/stop_points_spec.js b/spec/javascript/routes/reducers/stop_points_spec.js
new file mode 100644
index 000000000..b375cdc2c
--- /dev/null
+++ b/spec/javascript/routes/reducers/stop_points_spec.js
@@ -0,0 +1,486 @@
+import stopPointsReducer from '../../../../app/javascript/routes/reducers/stopPoints'
+
+let state = []
+
+let fakeData = {
+ geometry: undefined,
+ registration_number: 'rn_test',
+ stoparea_id: 'sid_test',
+ text: 't_test',
+ user_objectid: 'uoid_test'
+}
+
+describe('stops reducer', () => {
+ beforeEach(()=>{
+ state = [
+ {
+ text: 'first',
+ index: 0,
+ stoppoint_id: 72,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ },
+ {
+ text: 'second',
+ index: 1,
+ stoppoint_id: 73,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ }
+ ]
+ })
+
+ it('should return the initial state', () => {
+ expect(
+ stopPointsReducer(undefined, {})
+ ).toEqual([])
+ })
+
+ it('should handle ADD_STOP', () => {
+ expect(
+ stopPointsReducer(state, {
+ type: 'ADD_STOP'
+ })
+ ).toEqual(
+ [
+ {
+ text: 'first',
+ index: 0,
+ stoppoint_id: 72,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ },
+ {
+ text: 'second',
+ index: 1,
+ stoppoint_id: 73,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ },
+ {
+ text: '',
+ index: 2,
+ edit: true,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ }
+ ]
+ )
+ })
+
+ it('should handle MOVE_UP_STOP', () => {
+ expect(
+ stopPointsReducer(state, {
+ type: 'MOVE_STOP_UP',
+ index: 1
+ })
+ ).toEqual(
+ [
+ {
+ text: 'second',
+ index: 1,
+ stoppoint_id: 72,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ },
+ {
+ text: 'first',
+ index: 0,
+ stoppoint_id: 73,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ }
+ ]
+ )
+ })
+
+ it('should handle MOVE_DOWN_STOP', () => {
+ expect(
+ stopPointsReducer(state, {
+ type: 'MOVE_STOP_DOWN',
+ index: 0
+ })
+ ).toEqual(
+ [
+ {
+ text: 'second',
+ index: 1,
+ stoppoint_id: 72,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ },
+ {
+ text: 'first',
+ index: 0,
+ stoppoint_id: 73,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ }
+ ]
+ )
+ })
+
+ // it('should handle DELETE_STOP', () => {
+ // expect(
+ // stopPointsReducer(state, {
+ // type: 'DELETE_STOP',
+ // index: 1
+ // })
+ // ).toEqual(
+ // [
+ // {
+ // text: 'first',
+ // index: 0,
+ // stoppoint_id: 72,
+ // edit: false,
+ // for_boarding: 'normal',
+ // for_alighting: 'normal',
+ // olMap: {
+ // isOpened: false,
+ // json: {}
+ // }
+ // }
+ // ]
+ // )
+ // })
+
+ it('should handle UPDATE_INPUT_VALUE', () => {
+ expect(
+ stopPointsReducer(state, {
+ type: 'UPDATE_INPUT_VALUE',
+ index: 0,
+ edit: false,
+ text: {
+ text: "new value",
+ name: 'new',
+ stoparea_id: 1,
+ user_objectid: "1234",
+ longitude: 123,
+ latitude: 123,
+ registration_number: '0',
+ city_name: 'city',
+ area_type: 'area',
+ short_name: 'new',
+ comment: 'newcomment'
+ }
+ })
+ ).toEqual(
+ [
+ {
+ text: 'new value',
+ name: 'new',
+ index: 0,
+ stoppoint_id: 72,
+ edit: false,
+ stoparea_id: 1,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ user_objectid: "1234",
+ longitude: 123,
+ latitude: 123,
+ registration_number: '0',
+ city_name: 'city',
+ area_type: 'area',
+ short_name: 'new',
+ comment: 'newcomment',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ },
+ {
+ text: 'second',
+ index: 1,
+ stoppoint_id: 73,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ }
+ ]
+ )
+ })
+
+ it('should handle UPDATE_SELECT_VALUE', () => {
+ expect(
+ stopPointsReducer(state, {
+ type :'UPDATE_SELECT_VALUE',
+ select_id: 'for_boarding',
+ select_value: 'prohibited',
+ index: 0
+ })
+ ).toEqual(
+ [
+ {
+ text: 'first',
+ index: 0,
+ stoppoint_id: 72,
+ edit: false,
+ for_boarding: 'prohibited',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ },
+ {
+ text: 'second',
+ index: 1,
+ stoppoint_id: 73,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ }
+ ]
+ )
+ })
+
+ it('should handle TOGGLE_MAP', () => {
+ expect(
+ stopPointsReducer(state, {
+ type: 'TOGGLE_MAP',
+ index: 0
+ })
+ ).toEqual(
+ [
+ {
+ text: 'first',
+ index: 0,
+ stoppoint_id: 72,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: true,
+ json: {
+ text: 'first',
+ index: 0,
+ stoppoint_id: 72,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: undefined
+ }
+ }
+ },
+ {
+ text: 'second',
+ index: 1,
+ stoppoint_id: 73,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ }
+ ]
+ )
+ })
+
+ it('should handle TOGGLE_EDIT', () => {
+ expect(
+ stopPointsReducer(state, {
+ type: 'TOGGLE_EDIT',
+ index: 0
+ })
+ ).toEqual(
+ [
+ {
+ text: 'first',
+ index: 0,
+ stoppoint_id: 72,
+ edit: true,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ },
+ {
+ text: 'second',
+ index: 1,
+ stoppoint_id: 73,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ }
+ ]
+ )
+ })
+
+ it('should handle SELECT_MARKER', () => {
+ let openedMapState = [
+ {
+ text: 'first',
+ index: 0,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: true,
+ json: {}
+ }
+ },
+ {
+ text: 'second',
+ index: 1,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ }
+ ]
+ expect(
+ stopPointsReducer(openedMapState, {
+ type: 'SELECT_MARKER',
+ index: 0,
+ data: fakeData
+ })
+ ).toEqual(
+ [
+ {
+ text: 'first',
+ index: 0,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: true,
+ json: fakeData
+ }
+ },
+ {
+ text: 'second',
+ index: 1,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ }
+ ]
+ )
+ })
+
+ it('should handle UNSELECT_MARKER', () => {
+ let openedMapState = [
+ {
+ text: 'first',
+ index: 0,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: true,
+ json: {}
+ }
+ },
+ {
+ text: 'second',
+ index: 1,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ }
+ ]
+
+ expect(
+ stopPointsReducer(openedMapState, {
+ type: 'UNSELECT_MARKER',
+ index: 0
+ })
+ ).toEqual(
+ [
+ {
+ text: 'first',
+ index: 0,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: true,
+ json: {}
+ }
+ },
+ {
+ text: 'second',
+ index: 1,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: {
+ isOpened: false,
+ json: {}
+ }
+ }
+ ]
+ )
+ })
+})
diff --git a/spec/javascript/spec_helper.coffee b/spec/javascript/spec_helper.coffee
new file mode 100644
index 000000000..9ff516885
--- /dev/null
+++ b/spec/javascript/spec_helper.coffee
@@ -0,0 +1,32 @@
+# Teaspoon includes some support files, but you can use anything from your own support path too.
+# require support/jasmine-jquery-1.7.0
+# require support/jasmine-jquery-2.0.0
+# require support/jasmine-jquery-2.1.0
+# require support/sinon
+# require support/your-support-file
+#
+# PhantomJS (Teaspoons default driver) doesn't have support for Function.prototype.bind, which has caused confusion.
+# Use this polyfill to avoid the confusion.
+#= require support/phantomjs-shims
+#
+# You can require your own javascript files here. By default this will include everything in application, however you
+# may get better load performance if you require the specific files that are being used in the spec that tests them.
+#= require application
+#
+# Deferring execution
+# If you're using CommonJS, RequireJS or some other asynchronous library you can defer execution. Call
+# Teaspoon.execute() after everything has been loaded. Simple example of a timeout:
+#
+# Teaspoon.defer = true
+# setTimeout(Teaspoon.execute, 1000)
+#
+# Matching files
+# By default Teaspoon will look for files that match _spec.{js,js.coffee,.coffee}. Add a filename_spec.js file in your
+# spec path and it'll be included in the default suite automatically. If you want to customize suites, check out the
+# configuration in teaspoon_env.rb
+#
+# Manifest
+# If you'd rather require your spec files manually (to control order for instance) you can disable the suite matcher in
+# the configuration and use this file as a manifest.
+#
+# For more information: http://github.com/modeset/teaspoon
diff --git a/spec/javascript/time_table/actions_spec.js b/spec/javascript/time_table/actions_spec.js
new file mode 100644
index 000000000..003b7f6b5
--- /dev/null
+++ b/spec/javascript/time_table/actions_spec.js
@@ -0,0 +1,237 @@
+import actions from '../../../app/javascript/time_tables/actions'
+const dispatch = function(){}
+const dayTypes = [true, true, true, true, true, true, true]
+const day = {
+ date : "2017-05-01",
+ day : "lundi",
+ excluded_date : false,
+ in_periods : true,
+ include_date : false,
+ mday : 1,
+ wday : 1,
+ wnumber : "18"
+}
+describe('actions', () => {
+ it('should create an action to update dayTypes', () => {
+ let obj = {}
+ const expectedAction = {
+ type: 'UPDATE_DAY_TYPES',
+ dayTypes: obj
+ }
+ expect(actions.updateDayTypes(obj)).toEqual(expectedAction)
+ })
+
+ it('should create an action to update comment', () => {
+ const expectedAction = {
+ type: 'UPDATE_COMMENT',
+ comment: 'test'
+ }
+ expect(actions.updateComment('test')).toEqual(expectedAction)
+ })
+
+ it('should create an action to update color', () => {
+ const expectedAction = {
+ type: 'UPDATE_COLOR',
+ color: '#ffffff'
+ }
+ expect(actions.updateColor('#ffffff')).toEqual(expectedAction)
+ })
+
+ it('should create an action to update selected tags', () => {
+ let selectedItem = {
+ id: 1,
+ name: 'test'
+ }
+ const expectedAction = {
+ type: 'UPDATE_SELECT_TAG',
+ selectedItem: selectedItem
+ }
+ expect(actions.select2Tags(selectedItem)).toEqual(expectedAction)
+ })
+
+ it('should create an action to update unselected tags', () => {
+ let selectedItem = {
+ id: 1,
+ name: 'test'
+ }
+ const expectedAction = {
+ type: 'UPDATE_UNSELECT_TAG',
+ selectedItem: selectedItem
+ }
+ expect(actions.unselect2Tags(selectedItem)).toEqual(expectedAction)
+ })
+
+ it('should create an action to go to previous page', () => {
+ let pagination = {
+ currentPage: '2017-01-01',
+ periode_range: [],
+ stateChanged: false
+ }
+ const expectedAction = {
+ type: 'GO_TO_PREVIOUS_PAGE',
+ dispatch,
+ pagination,
+ nextPage: false
+ }
+ expect(actions.goToPreviousPage(dispatch, pagination)).toEqual(expectedAction)
+ })
+
+ it('should create an action to go to next page', () => {
+ let pagination = {
+ currentPage: '2017-01-01',
+ periode_range: [],
+ stateChanged: false
+ }
+ const expectedAction = {
+ type: 'GO_TO_NEXT_PAGE',
+ dispatch,
+ pagination,
+ nextPage: true
+ }
+ expect(actions.goToNextPage(dispatch, pagination)).toEqual(expectedAction)
+ })
+
+ it('should create an action to change page', () => {
+ let page = '2017-05-04'
+ const expectedAction = {
+ type: 'CHANGE_PAGE',
+ dispatch,
+ page: page
+ }
+ expect(actions.changePage(dispatch, page)).toEqual(expectedAction)
+ })
+
+ it('should create an action to delete period', () => {
+ let index = 1
+ const expectedAction = {
+ type: 'DELETE_PERIOD',
+ index,
+ dayTypes
+ }
+ expect(actions.deletePeriod(index, dayTypes)).toEqual(expectedAction)
+ })
+
+ it('should create an action to open add period form', () => {
+ const expectedAction = {
+ type: 'OPEN_ADD_PERIOD_FORM',
+ }
+ expect(actions.openAddPeriodForm()).toEqual(expectedAction)
+ })
+
+ it('should create an action to open edit period form', () => {
+ let period = {
+ id : 1,
+ period_end : "2017-03-05",
+ period_start : "2017-02-23"
+ }
+ let index = 1
+ const expectedAction = {
+ type: 'OPEN_EDIT_PERIOD_FORM',
+ period,
+ index
+ }
+ expect(actions.openEditPeriodForm(period, index)).toEqual(expectedAction)
+ })
+
+ it('should create an action to close period form', () => {
+ const expectedAction = {
+ type: 'CLOSE_PERIOD_FORM',
+ }
+ expect(actions.closePeriodForm()).toEqual(expectedAction)
+ })
+
+ it('should create an action to update period form', () => {
+ let val = "11"
+ let group = "start"
+ let selectType = "day"
+ const expectedAction = {
+ type: 'UPDATE_PERIOD_FORM',
+ val,
+ group,
+ selectType
+ }
+ expect(actions.updatePeriodForm(val, group, selectType)).toEqual(expectedAction)
+ })
+
+ it('should create an action to validate period form', () => {
+ let modalProps = {}
+ let timeTablePeriods = []
+ let metas = {}
+ let timetableInDates = []
+ let error = ''
+ const expectedAction = {
+ type: 'VALIDATE_PERIOD_FORM',
+ modalProps,
+ timeTablePeriods,
+ metas,
+ timetableInDates,
+ error
+ }
+ expect(actions.validatePeriodForm(modalProps, timeTablePeriods, metas, timetableInDates, error)).toEqual(expectedAction)
+ })
+
+ it('should create an action to add an included date', () => {
+ let index = 1
+ let date = actions.formatDate(new Date)
+ const expectedAction = {
+ type: 'ADD_INCLUDED_DATE',
+ index,
+ dayTypes,
+ date
+ }
+ expect(actions.addIncludedDate(index, dayTypes, date)).toEqual(expectedAction)
+ })
+
+ it('should create an action to remove an included dat', () => {
+ let index = 1
+ let date = actions.formatDate(new Date)
+ const expectedAction = {
+ type: 'REMOVE_INCLUDED_DATE',
+ index,
+ dayTypes,
+ date
+ }
+ expect(actions.removeIncludedDate(index, dayTypes, date)).toEqual(expectedAction)
+ })
+
+ it('should create an action to add an excluded date in period', () => {
+ let index = 1
+ let date = actions.formatDate(new Date)
+ const expectedAction = {
+ type: 'ADD_EXCLUDED_DATE',
+ index,
+ dayTypes,
+ date
+ }
+ expect(actions.addExcludedDate(index, dayTypes, date)).toEqual(expectedAction)
+ })
+
+ it('should create an action to remove an excluded date from period', () => {
+ let index = 1
+ let date = actions.formatDate(new Date)
+ const expectedAction = {
+ type: 'REMOVE_EXCLUDED_DATE',
+ index,
+ dayTypes,
+ date
+ }
+ expect(actions.removeExcludedDate(index, dayTypes, date)).toEqual(expectedAction)
+ })
+
+ it('should create an action to open confirm modal', () => {
+ let callback = function(){}
+ const expectedAction = {
+ type: 'OPEN_CONFIRM_MODAL',
+ callback
+ }
+ expect(actions.openConfirmModal(callback)).toEqual(expectedAction)
+ })
+
+ it('should create an action to close modal', () => {
+ const expectedAction = {
+ type: 'CLOSE_MODAL',
+ }
+ expect(actions.closeModal()).toEqual(expectedAction)
+ })
+
+})
diff --git a/spec/javascript/time_table/reducers/metas_spec.js b/spec/javascript/time_table/reducers/metas_spec.js
new file mode 100644
index 000000000..374ad1814
--- /dev/null
+++ b/spec/javascript/time_table/reducers/metas_spec.js
@@ -0,0 +1,77 @@
+import metasReducer from '../../../../app/javascript/time_tables/reducers/metas'
+
+let state = {}
+
+describe('metas reducer', () => {
+ beforeEach(() => {
+ let tag = {
+ id: 0,
+ name: 'test'
+ }
+ state = {
+ comment: 'test',
+ day_types: [true, true, true, true, true, true, true],
+ color: 'blue',
+ initial_tags: [tag],
+ tags: [tag]
+ }
+ })
+
+ it('should return the initial state', () => {
+ expect(
+ metasReducer(undefined, {})
+ ).toEqual({})
+ })
+
+ it('should handle UPDATE_DAY_TYPES', () => {
+ const arr = [false, false, true, true, true, true, true]
+ expect(
+ metasReducer(state, {
+ type: 'UPDATE_DAY_TYPES',
+ dayTypes: arr
+ })
+ ).toEqual(Object.assign({}, state, {day_types: arr, calendar: null}))
+ })
+
+ it('should handle UPDATE_COMMENT', () => {
+ expect(
+ metasReducer(state, {
+ type: 'UPDATE_COMMENT',
+ comment: 'title'
+ })
+ ).toEqual(Object.assign({}, state, {comment: 'title'}))
+ })
+
+ it('should handle UPDATE_COLOR', () => {
+ expect(
+ metasReducer(state, {
+ type: 'UPDATE_COLOR',
+ color: '#ffffff'
+ })
+ ).toEqual(Object.assign({}, state, {color: '#ffffff'}))
+ })
+
+ it('should handle UPDATE_SELECT_TAG', () => {
+ expect(
+ metasReducer(state, {
+ type: 'UPDATE_SELECT_TAG',
+ selectedItem:{
+ id: 1,
+ name: 'great'
+ }
+ })
+ ).toEqual(Object.assign({}, state, {tags: [...state.tags, {id: 1, name:'great'}]}))
+ })
+
+ it('should handle UPDATE_UNSELECT_TAG', () => {
+ expect(
+ metasReducer(state, {
+ type: 'UPDATE_UNSELECT_TAG',
+ selectedItem:{
+ id: 0,
+ name: 'test'
+ }
+ })
+ ).toEqual(Object.assign({}, state, {tags: []}))
+ })
+})
diff --git a/spec/javascript/time_table/reducers/modal_spec.js b/spec/javascript/time_table/reducers/modal_spec.js
new file mode 100644
index 000000000..1794d2acd
--- /dev/null
+++ b/spec/javascript/time_table/reducers/modal_spec.js
@@ -0,0 +1,328 @@
+import modalReducer from '../../../../app/javascript/time_tables/reducers/modal'
+
+let state = {}
+
+describe('modal reducer', () => {
+ beforeEach(() => {
+ state = {
+ confirmModal: {},
+ modalProps: {
+ active: false,
+ begin: {
+ day: '01',
+ month: '01',
+ year: String(new Date().getFullYear())
+ },
+ end: {
+ day: '01',
+ month: '01',
+ year: String(new Date().getFullYear())
+ },
+ index: false,
+ error: ''
+ },
+ type: ""
+ }
+ })
+
+ it('should return the initial state', () => {
+ expect(
+ modalReducer(undefined, {})
+ ).toEqual({})
+ })
+
+ it('should handle OPEN_CONFIRM_MODAL', () => {
+ let callback = function(){}
+ expect(
+ modalReducer(state, {
+ type: 'OPEN_CONFIRM_MODAL',
+ callback
+ })
+ ).toEqual(Object.assign({}, state, {type: "confirm", confirmModal: { callback: callback }}))
+ })
+
+ it('should handle CLOSE_PERIOD_FORM', () => {
+ let newModalProps = Object.assign({}, state.modalProps, {active: false})
+ expect(
+ modalReducer(state, {
+ type: 'CLOSE_PERIOD_FORM'
+ })
+ ).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
+ })
+
+ it('should handle OPEN_EDIT_PERIOD_FORM', () => {
+ let period = {
+ id : 1,
+ period_end : "2017-03-05",
+ period_start : "2017-02-23"
+ }
+ let period_start = period.period_start.split('-')
+ let period_end = period.period_end.split('-')
+
+ let index = 1
+
+ let newModalProps = {
+ active: true,
+ begin: {
+ day: period_start[2],
+ month: period_start[1],
+ year: period_start[0]
+ },
+ end: {
+ day: period_end[2],
+ month: period_end[1],
+ year: period_end[0]
+ },
+ index: index,
+ error: ''
+ }
+ expect(
+ modalReducer(state, {
+ type: 'OPEN_EDIT_PERIOD_FORM',
+ period,
+ index
+ })
+ ).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
+ })
+
+ it('should handle OPEN_ADD_PERIOD_FORM', () => {
+ let emptyDate = {
+ day: '01',
+ month: '01',
+ year: String(new Date().getFullYear())
+ }
+ let newModalProps = Object.assign({}, state.modalProps, {
+ active: true,
+ begin: emptyDate,
+ end: emptyDate,
+ index: false,
+ error: ""
+ })
+
+ expect(
+ modalReducer(state, {
+ type: 'OPEN_ADD_PERIOD_FORM'
+ })
+ ).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
+ })
+
+ it('should handle UPDATE_PERIOD_FORM', () => {
+ let val = "11"
+ let group = "begin"
+ let selectType = "day"
+
+ let newModalProps = {
+ active: false,
+ begin: {
+ day: val,
+ month: '01',
+ year: String(new Date().getFullYear())
+ },
+ end: {
+ day: '01',
+ month: '01',
+ year: String(new Date().getFullYear())
+ },
+ index: false,
+ error: ''
+ }
+
+ expect(
+ modalReducer(state, {
+ type: 'UPDATE_PERIOD_FORM',
+ val,
+ group,
+ selectType
+ })
+ ).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
+ })
+
+ it('should handle VALIDATE_PERIOD_FORM and throw error if period starts after the end', () => {
+ let modProps = {
+ active: false,
+ begin: {
+ day: '13',
+ month: '01',
+ year: String(new Date().getFullYear())
+ },
+ end: {
+ day: '01',
+ month: '01',
+ year: String(new Date().getFullYear())
+ },
+ index: false,
+ error: ''
+ }
+ let newModalProps = {
+ active: true,
+ begin: {
+ day: '01',
+ month: '01',
+ year: String(new Date().getFullYear())
+ },
+ end: {
+ day: '01',
+ month: '01',
+ year: String(new Date().getFullYear())
+ },
+ index: false,
+ error: 'La date de départ doit être antérieure à la date de fin'
+ }
+
+ let ttperiods = []
+ let ttdates = []
+ let metas = []
+
+ expect(
+ modalReducer(state, {
+ type: 'VALIDATE_PERIOD_FORM',
+ modalProps : modProps,
+ timeTablePeriods: ttperiods,
+ metas: metas,
+ timetableInDates: ttdates,
+ error: 'La date de départ doit être antérieure à la date de fin'
+ })
+ ).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
+ })
+
+ it('should handle VALIDATE_PERIOD_FORM and throw error if periods overlap', () => {
+ let state2 = {
+ confirmModal: {},
+ modalProps: {
+ active: false,
+ begin: {
+ day: '03',
+ month: '05',
+ year: '2017'
+ },
+ end: {
+ day: '09',
+ month: '05',
+ year: '2017'
+ },
+ index: false,
+ error: ''
+ },
+ type: ''
+ }
+ let modProps2 = {
+ active: false,
+ begin: {
+ day: '03',
+ month: '05',
+ year: '2017'
+ },
+ end: {
+ day: '09',
+ month: '05',
+ year: '2017'
+ },
+ index: false,
+ error: ''
+ }
+ let ttperiods2 = [
+ {id: 261, period_start: '2017-02-23', period_end: '2017-03-05'},
+ {id: 262, period_start: '2017-03-15', period_end: '2017-03-25'},
+ {id: 264, period_start: '2017-04-24', period_end: '2017-05-04'},
+ {id: 265, period_start: '2017-05-14', period_end: '2017-05-24'}
+ ]
+
+ let ttdates2 = []
+
+ let newModalProps2 = {
+ active: true,
+ begin: {
+ day: '03',
+ month: '05',
+ year: '2017'
+ },
+ end: {
+ day: '09',
+ month: '05',
+ year: '2017'
+ },
+ index: false,
+ error: "Les pƩriodes ne peuvent pas se chevaucher"
+ }
+
+ expect(
+ modalReducer(state2, {
+ type: 'VALIDATE_PERIOD_FORM',
+ modalProps : modProps2,
+ timeTablePeriods: ttperiods2,
+ timetableInDates: ttdates2,
+ error: "Les pƩriodes ne peuvent pas se chevaucher"
+ })
+ ).toEqual(Object.assign({}, state2, {modalProps: newModalProps2}))
+ })
+
+ it('should handle VALIDATE_PERIOD_FORM and throw error if period overlaps date', () => {
+ let state3 = {
+ confirmModal: {},
+ modalProps: {
+ active: false,
+ begin: {
+ day: '01',
+ month: '08',
+ year: '2017'
+ },
+ end: {
+ day: '09',
+ month: '08',
+ year: '2017'
+ },
+ index: false,
+ error: ''
+ },
+ type: ''
+ }
+ let modProps3 = {
+ active: true,
+ begin: {
+ day: '01',
+ month: '08',
+ year: '2017'
+ },
+ end: {
+ day: '09',
+ month: '08',
+ year: '2017'
+ },
+ index: false,
+ error: ''
+ }
+
+ let ttperiods3 = []
+ let ttdates3 = [{date: "2017-08-04", include_date: true}]
+ let metas = {
+ day_types: [true,true,true,true,true,true,true]
+ }
+
+ let newModalProps3 = {
+ active: true,
+ begin: {
+ day: '01',
+ month: '08',
+ year: '2017'
+ },
+ end: {
+ day: '09',
+ month: '08',
+ year: '2017'
+ },
+ index: false,
+ error: "Une pƩriode ne peut chevaucher une date dans un calendrier"
+ }
+
+ expect(
+ modalReducer(state3, {
+ type: 'VALIDATE_PERIOD_FORM',
+ modalProps : modProps3,
+ timeTablePeriods: ttperiods3,
+ timetableInDates: ttdates3,
+ metas: metas,
+ error: "Une pƩriode ne peut chevaucher une date dans un calendrier"
+ })
+ ).toEqual(Object.assign({}, state3, {modalProps: newModalProps3}))
+ })
+})
diff --git a/spec/javascript/time_table/reducers/pagination_spec.js b/spec/javascript/time_table/reducers/pagination_spec.js
new file mode 100644
index 000000000..5aa8d27a2
--- /dev/null
+++ b/spec/javascript/time_table/reducers/pagination_spec.js
@@ -0,0 +1,139 @@
+import paginationReducer from '../../../../app/javascript/time_tables/reducers/pagination'
+
+const dispatch = function(){}
+
+let pagination = {
+ currentPage: "1982-02-15",
+ periode_range: ["1982-02-01", "1982-02-02", "1982-02-03"],
+ stateChanged: false
+}
+
+let state = {}
+
+describe('pagination reducer', () => {
+ beforeEach(() => {
+ state = {
+ currentPage: "",
+ periode_range: [],
+ stateChanged: false
+ }
+ })
+
+ it('should return the initial state', () => {
+ expect(
+ paginationReducer(undefined, {})
+ ).toEqual({})
+ })
+
+ it('should handle RECEIVE_TIME_TABLES', () => {
+ let json = [{
+ current_periode_range: "1982-02-15",
+ periode_range: ["1982-02-01", "1982-02-02", "1982-02-03"]
+ }]
+ expect(
+ paginationReducer(state, {
+ type: 'RECEIVE_TIME_TABLES',
+ json
+ })
+ ).toEqual(Object.assign({}, state, {currentPage: json.current_periode_range, periode_range: json.periode_range}))
+ })
+
+ it('should handle GO_TO_PREVIOUS_PAGE', () => {
+ let nextPage = nextPage ? 1 : -1
+ let newPage = pagination.periode_range[pagination.periode_range.indexOf(pagination.currentPage) + nextPage]
+
+ expect(
+ paginationReducer(state, {
+ type: 'GO_TO_PREVIOUS_PAGE',
+ dispatch,
+ pagination,
+ nextPage: false
+ })
+ ).toEqual(Object.assign({}, state, {currentPage : newPage, stateChanged: false}))
+ })
+ it('should handle GO_TO_NEXT_PAGE', () => {
+ let nextPage = nextPage ? 1 : -1
+ let newPage = pagination.periode_range[pagination.periode_range.indexOf(pagination.currentPage) + nextPage]
+
+ expect(
+ paginationReducer(state, {
+ type: 'GO_TO_NEXT_PAGE',
+ dispatch,
+ pagination,
+ nextPage: false
+ })
+ ).toEqual(Object.assign({}, state, {currentPage : newPage, stateChanged: false}))
+ })
+
+ it('should handle CHANGE_PAGE', () => {
+ let page = "1982-02-15"
+ expect(
+ paginationReducer(state, {
+ type: 'CHANGE_PAGE',
+ dispatch,
+ page
+ })
+ ).toEqual(Object.assign({}, state, {currentPage : page, stateChanged: false}))
+ })
+
+ it('should handle ADD_INCLUDED_DATE', () => {
+ expect(
+ paginationReducer(state, {
+ type: 'ADD_INCLUDED_DATE'
+ })
+ ).toEqual(Object.assign({}, state, {stateChanged: true}))
+ })
+
+ it('should handle REMOVE_INCLUDED_DATE', () => {
+ expect(
+ paginationReducer(state, {
+ type: 'REMOVE_INCLUDED_DATE'
+ })
+ ).toEqual(Object.assign({}, state, {stateChanged: true}))
+ })
+
+ it('should handle ADD_EXCLUDED_DATE', () => {
+ expect(
+ paginationReducer(state, {
+ type: 'ADD_EXCLUDED_DATE'
+ })
+ ).toEqual(Object.assign({}, state, {stateChanged: true}))
+ })
+
+ it('should handle REMOVE_EXCLUDED_DATE', () => {
+ expect(
+ paginationReducer(state, {
+ type: 'REMOVE_EXCLUDED_DATE'
+ })
+ ).toEqual(Object.assign({}, state, {stateChanged: true}))
+ })
+
+ it('should handle DELETE_PERIOD', () => {
+ expect(
+ paginationReducer(state, {
+ type: 'DELETE_PERIOD'
+ })
+ ).toEqual(Object.assign({}, state, {stateChanged: true}))
+ })
+ it('should handle VALIDATE_PERIOD_FORM', () => {
+ expect(
+ paginationReducer(state, {
+ type: 'VALIDATE_PERIOD_FORM'
+ })
+ ).toEqual(Object.assign({}, state, {stateChanged: true}))
+ })
+ it('should handle UPDATE_COMMENT', () => {
+ expect(
+ paginationReducer(state, {
+ type: 'UPDATE_COMMENT'
+ })
+ ).toEqual(Object.assign({}, state, {stateChanged: true}))
+ })
+ it('should handle UPDATE_COLOR', () => {
+ expect(
+ paginationReducer(state, {
+ type: 'UPDATE_COLOR'
+ })
+ ).toEqual(Object.assign({}, state, {stateChanged: true}))
+ })
+})
diff --git a/spec/javascript/time_table/reducers/status_spec.js b/spec/javascript/time_table/reducers/status_spec.js
new file mode 100644
index 000000000..63e4033f9
--- /dev/null
+++ b/spec/javascript/time_table/reducers/status_spec.js
@@ -0,0 +1,50 @@
+import statusReducer from '../../../../app/javascript/time_tables/reducers/status'
+
+let state = {}
+
+describe('status reducer', () => {
+ beforeEach(() => {
+ state = {
+ actionType: "edit",
+ fetchSuccess: true,
+ isFetching: false
+ }
+ })
+
+ it('should return the initial state', () => {
+ expect(
+ statusReducer(undefined, {})
+ ).toEqual({})
+ })
+
+ it('should handle UNAVAILABLE_SERVER', () => {
+ expect(
+ statusReducer(state, {
+ type: 'UNAVAILABLE_SERVER'
+ })
+ ).toEqual(Object.assign({}, state, {fetchSuccess: false}))
+ })
+
+ it('should handle FETCH_API', () => {
+ expect(
+ statusReducer(state, {
+ type: 'FETCH_API'
+ })
+ ).toEqual(Object.assign({}, state, {isFetching: true}))
+ })
+
+ it('should handle RECEIVE_TIME_TABLES', () => {
+ expect(
+ statusReducer(state, {
+ type: 'RECEIVE_TIME_TABLES'
+ })
+ ).toEqual(Object.assign({}, state, {fetchSuccess: true, isFetching: false}))
+ })
+ it('should handle RECEIVE_MONTH', () => {
+ expect(
+ statusReducer(state, {
+ type: 'RECEIVE_MONTH'
+ })
+ ).toEqual(Object.assign({}, state, {fetchSuccess: true, isFetching: false}))
+ })
+})
diff --git a/spec/javascript/time_table/reducers/timetable_spec.js b/spec/javascript/time_table/reducers/timetable_spec.js
new file mode 100644
index 000000000..f0f9eaa8c
--- /dev/null
+++ b/spec/javascript/time_table/reducers/timetable_spec.js
@@ -0,0 +1,338 @@
+require('whatwg-fetch')
+import timetableReducer from '../../../../app/javascript/time_tables/reducers/timetable'
+
+let state = {}
+const dispatch = function(){}
+let arrDayTypes = [true, true, true, true, true, true, true]
+let strDayTypes = 'LuMaMeJeVeSaDi'
+let time_table_periods = [{"id":261,"period_start":"2017-02-23","period_end":"2017-03-05"},{"id":262,"period_start":"2017-03-15","period_end":"2017-03-25"},{"id":263,"period_start":"2017-04-04","period_end":"2017-04-14"},{"id":264,"period_start":"2017-04-24","period_end":"2017-05-04"},{"id":265,"period_start":"2017-05-14","period_end":"2017-05-24"}]
+let time_table_dates = []
+let current_periode_range = "2017-05-01"
+let periode_range = ["2014-05-01","2014-06-01","2014-07-01","2014-08-01","2014-09-01","2014-10-01","2014-11-01","2014-12-01","2015-01-01","2015-02-01","2015-03-01","2015-04-01","2015-05-01","2015-06-01","2015-07-01","2015-08-01","2015-09-01","2015-10-01","2015-11-01","2015-12-01","2016-01-01","2016-02-01","2016-03-01","2016-04-01","2016-05-01","2016-06-01","2016-07-01","2016-08-01","2016-09-01","2016-10-01","2016-11-01","2016-12-01","2017-01-01","2017-02-01","2017-03-01","2017-04-01","2017-05-01","2017-06-01","2017-07-01","2017-08-01","2017-09-01","2017-10-01","2017-11-01","2017-12-01","2018-01-01","2018-02-01","2018-03-01","2018-04-01","2018-05-01","2018-06-01","2018-07-01","2018-08-01","2018-09-01","2018-10-01","2018-11-01","2018-12-01","2019-01-01","2019-02-01","2019-03-01","2019-04-01","2019-05-01","2019-06-01","2019-07-01","2019-08-01","2019-09-01","2019-10-01","2019-11-01","2019-12-01","2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01"]
+let current_month = [{"day":"lundi","date":"2017-05-01","wday":1,"wnumber":"18","mday":1,"include_date":false,"excluded_date":false},{"day":"mardi","date":"2017-05-02","wday":2,"wnumber":"18","mday":2,"include_date":false,"excluded_date":false},{"day":"mercredi","date":"2017-05-03","wday":3,"wnumber":"18","mday":3,"include_date":false,"excluded_date":false},{"day":"jeudi","date":"2017-05-04","wday":4,"wnumber":"18","mday":4,"include_date":false,"excluded_date":false},{"day":"vendredi","date":"2017-05-05","wday":5,"wnumber":"18","mday":5,"include_date":false,"excluded_date":false},{"day":"samedi","date":"2017-05-06","wday":6,"wnumber":"18","mday":6,"include_date":false,"excluded_date":false},{"day":"dimanche","date":"2017-05-07","wday":0,"wnumber":"18","mday":7,"include_date":false,"excluded_date":false},{"day":"lundi","date":"2017-05-08","wday":1,"wnumber":"19","mday":8,"include_date":false,"excluded_date":false},{"day":"mardi","date":"2017-05-09","wday":2,"wnumber":"19","mday":9,"include_date":false,"excluded_date":false},{"day":"mercredi","date":"2017-05-10","wday":3,"wnumber":"19","mday":10,"include_date":false,"excluded_date":false},{"day":"jeudi","date":"2017-05-11","wday":4,"wnumber":"19","mday":11,"include_date":false,"excluded_date":false},{"day":"vendredi","date":"2017-05-12","wday":5,"wnumber":"19","mday":12,"include_date":false,"excluded_date":false},{"day":"samedi","date":"2017-05-13","wday":6,"wnumber":"19","mday":13,"include_date":false,"excluded_date":false},{"day":"dimanche","date":"2017-05-14","wday":0,"wnumber":"19","mday":14,"include_date":false,"excluded_date":false},{"day":"lundi","date":"2017-05-15","wday":1,"wnumber":"20","mday":15,"include_date":false,"excluded_date":false},{"day":"mardi","date":"2017-05-16","wday":2,"wnumber":"20","mday":16,"include_date":false,"excluded_date":false},{"day":"mercredi","date":"2017-05-17","wday":3,"wnumber":"20","mday":17,"include_date":false,"excluded_date":false},{"day":"jeudi","date":"2017-05-18","wday":4,"wnumber":"20","mday":18,"include_date":false,"excluded_date":false},{"day":"vendredi","date":"2017-05-19","wday":5,"wnumber":"20","mday":19,"include_date":false,"excluded_date":false},{"day":"samedi","date":"2017-05-20","wday":6,"wnumber":"20","mday":20,"include_date":false,"excluded_date":false},{"day":"dimanche","date":"2017-05-21","wday":0,"wnumber":"20","mday":21,"include_date":false,"excluded_date":false},{"day":"lundi","date":"2017-05-22","wday":1,"wnumber":"21","mday":22,"include_date":false,"excluded_date":false},{"day":"mardi","date":"2017-05-23","wday":2,"wnumber":"21","mday":23,"include_date":false,"excluded_date":false},{"day":"mercredi","date":"2017-05-24","wday":3,"wnumber":"21","mday":24,"include_date":false,"excluded_date":false},{"day":"jeudi","date":"2017-05-25","wday":4,"wnumber":"21","mday":25,"include_date":false,"excluded_date":false},{"day":"vendredi","date":"2017-05-26","wday":5,"wnumber":"21","mday":26,"include_date":false,"excluded_date":false},{"day":"samedi","date":"2017-05-27","wday":6,"wnumber":"21","mday":27,"include_date":false,"excluded_date":false},{"day":"dimanche","date":"2017-05-28","wday":0,"wnumber":"21","mday":28,"include_date":false,"excluded_date":false},{"day":"lundi","date":"2017-05-29","wday":1,"wnumber":"22","mday":29,"include_date":false,"excluded_date":false},{"day":"mardi","date":"2017-05-30","wday":2,"wnumber":"22","mday":30,"include_date":false,"excluded_date":false},{"day":"mercredi","date":"2017-05-31","wday":3,"wnumber":"22","mday":31,"include_date":false,"excluded_date":false}]
+
+let newCurrentMonth = [{"day":"lundi","date":"2017-05-01","wday":1,"wnumber":"18","mday":1,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"mardi","date":"2017-05-02","wday":2,"wnumber":"18","mday":2,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"mercredi","date":"2017-05-03","wday":3,"wnumber":"18","mday":3,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"jeudi","date":"2017-05-04","wday":4,"wnumber":"18","mday":4,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"vendredi","date":"2017-05-05","wday":5,"wnumber":"18","mday":5,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"samedi","date":"2017-05-06","wday":6,"wnumber":"18","mday":6,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"dimanche","date":"2017-05-07","wday":0,"wnumber":"18","mday":7,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"lundi","date":"2017-05-08","wday":1,"wnumber":"19","mday":8,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"mardi","date":"2017-05-09","wday":2,"wnumber":"19","mday":9,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"mercredi","date":"2017-05-10","wday":3,"wnumber":"19","mday":10,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"jeudi","date":"2017-05-11","wday":4,"wnumber":"19","mday":11,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"vendredi","date":"2017-05-12","wday":5,"wnumber":"19","mday":12,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"samedi","date":"2017-05-13","wday":6,"wnumber":"19","mday":13,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"dimanche","date":"2017-05-14","wday":0,"wnumber":"19","mday":14,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"lundi","date":"2017-05-15","wday":1,"wnumber":"20","mday":15,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"mardi","date":"2017-05-16","wday":2,"wnumber":"20","mday":16,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"mercredi","date":"2017-05-17","wday":3,"wnumber":"20","mday":17,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"jeudi","date":"2017-05-18","wday":4,"wnumber":"20","mday":18,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"vendredi","date":"2017-05-19","wday":5,"wnumber":"20","mday":19,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"samedi","date":"2017-05-20","wday":6,"wnumber":"20","mday":20,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"dimanche","date":"2017-05-21","wday":0,"wnumber":"20","mday":21,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"lundi","date":"2017-05-22","wday":1,"wnumber":"21","mday":22,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"mardi","date":"2017-05-23","wday":2,"wnumber":"21","mday":23,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"mercredi","date":"2017-05-24","wday":3,"wnumber":"21","mday":24,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"jeudi","date":"2017-05-25","wday":4,"wnumber":"21","mday":25,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"vendredi","date":"2017-05-26","wday":5,"wnumber":"21","mday":26,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"samedi","date":"2017-05-27","wday":6,"wnumber":"21","mday":27,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"dimanche","date":"2017-05-28","wday":0,"wnumber":"21","mday":28,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"lundi","date":"2017-05-29","wday":1,"wnumber":"22","mday":29,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"mardi","date":"2017-05-30","wday":2,"wnumber":"22","mday":30,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"mercredi","date":"2017-05-31","wday":3,"wnumber":"22","mday":31,"include_date":false,"excluded_date":false,"in_periods":false}]
+
+let json = {
+ current_month: current_month,
+ current_periode_range: current_periode_range,
+ periode_range: periode_range,
+ time_table_periods: time_table_periods,
+ day_types: strDayTypes,
+ time_table_dates: time_table_dates
+}
+
+
+
+describe('timetable reducer with empty state', () => {
+ beforeEach(() => {
+ state = {
+ current_month: [],
+ current_periode_range: "",
+ periode_range: [],
+ time_table_periods: [],
+ time_table_dates: []
+ }
+ })
+
+ it('should return the initial state', () => {
+ expect(
+ timetableReducer(undefined, {})
+ ).toEqual({})
+ })
+
+ it('should handle RECEIVE_TIME_TABLES', () => {
+ let newState = {
+ current_month: newCurrentMonth,
+ current_periode_range: current_periode_range,
+ periode_range: periode_range,
+ time_table_periods: time_table_periods,
+ time_table_dates: []
+ }
+ expect(
+ timetableReducer(state, {
+ type: 'RECEIVE_TIME_TABLES',
+ json
+ })
+ ).toEqual(newState)
+ })
+})
+
+describe('timetable reducer with filled state', () => {
+ beforeEach(() => {
+ state = {
+ current_month: newCurrentMonth,
+ current_periode_range: current_periode_range,
+ periode_range: periode_range,
+ time_table_periods: time_table_periods,
+ time_table_dates: time_table_dates
+ }
+ })
+
+ it('should handle RECEIVE_MONTH', () => {
+ expect(
+ timetableReducer(state, {
+ type: 'RECEIVE_MONTH',
+ json: {
+ days: current_month,
+ day_types: strDayTypes
+ }
+ })
+ ).toEqual(state)
+ })
+
+
+ it('should handle GO_TO_PREVIOUS_PAGE', () => {
+ let pagination = {
+ periode_range: periode_range,
+ currentPage: current_periode_range
+ }
+ expect(
+ timetableReducer(state, {
+ type: 'GO_TO_PREVIOUS_PAGE',
+ dispatch,
+ pagination,
+ nextPage: false
+ })
+ ).toEqual(Object.assign({}, state, {current_periode_range: '2017-04-01'}))
+ })
+
+ it('should handle GO_TO_NEXT_PAGE', () => {
+ let pagination = {
+ periode_range: periode_range,
+ currentPage: current_periode_range
+ }
+ expect(
+ timetableReducer(state, {
+ type: 'GO_TO_NEXT_PAGE',
+ dispatch,
+ pagination,
+ nextPage: true
+ })
+ ).toEqual(Object.assign({}, state, {current_periode_range: '2017-06-01'}))
+ })
+
+ it('should handle CHANGE_PAGE', () => {
+ const actions = {
+ fetchTimeTables: function(){}
+ }
+ let newPage = '2017-05-01'
+ expect(
+ timetableReducer(state, {
+ type: 'CHANGE_PAGE',
+ dispatch,
+ page: newPage
+ })
+ ).toEqual(Object.assign({}, state, {current_periode_range: newPage}))
+ })
+
+ it('should handle DELETE_PERIOD and remove excluded days that were in period', () => {
+ state.time_table_dates.push({date: "2017-05-01", in_out: false})
+ state.current_month[0].excluded_date = true
+ state.time_table_periods[3].deleted = true
+
+ let begin = new Date(state.time_table_periods[3].period_start)
+ let end = new Date(state.time_table_periods[3].period_end)
+
+ let newState = Object.assign({}, state, {
+ time_table_dates: [],
+ current_month: state.current_month.map((d, i) => {
+ if (new Date(d.date) >= begin && new Date(d.date) <= end) {
+ d.excluded_date = false
+ d.in_periods = false
+ }
+ return d
+ })
+ })
+ expect(
+ timetableReducer(state, {
+ type: 'DELETE_PERIOD',
+ index: 3,
+ dayTypes: arrDayTypes
+ })
+ ).toEqual(newState)
+ })
+
+ it('should handle ADD_INCLUDED_DATE', () => {
+ let newDates = state.time_table_dates.concat({date: "2017-05-05", in_out: true})
+
+ let newCM = newCurrentMonth.map((d,i) => {
+ if (i == 4) d.include_date = true
+ return d
+ })
+
+ let newState = Object.assign({}, state, {time_table_dates: newDates, current_month: newCM})
+
+ expect(
+ timetableReducer(state, {
+ type: 'ADD_INCLUDED_DATE',
+ index: 4,
+ dayTypes: arrDayTypes,
+ date: "2017-05-05"
+ })
+ ).toEqual(newState)
+ })
+
+ it('should handle REMOVE_INCLUDED_DATE', () => {
+ state.current_month[4].include_date = true
+ state.time_table_dates.push({date: "2017-05-05", in_out: true})
+
+ let newCM = newCurrentMonth.map((d,i) => {
+ if (i == 4) d.include_date = false
+ return d
+ })
+
+ let newDates = state.time_table_dates.filter(d => d.date != "2017-05-05" && d.in_out != true )
+ let newState = Object.assign({}, state, {time_table_dates: newDates, current_month: newCM})
+ expect(
+ timetableReducer(state, {
+ type: 'REMOVE_INCLUDED_DATE',
+ index: 4,
+ dayTypes: arrDayTypes,
+ date: "2017-05-05"
+ })
+ ).toEqual(newState)
+ })
+
+ it('should handle ADD_EXCLUDED_DATE', () => {
+ let newDates = state.time_table_dates.concat({date: "2017-05-01", in_out: false})
+
+ let newCM = newCurrentMonth.map((d,i) => {
+ if (i == 0){
+ d.include_date = false
+ d.excluded_date = true
+ }
+ return d
+ })
+
+ let newState = Object.assign({}, state, {time_table_dates: newDates, current_month: newCM})
+
+ expect(
+ timetableReducer(state, {
+ type: 'ADD_EXCLUDED_DATE',
+ index: 0,
+ dayTypes: arrDayTypes,
+ date: "2017-05-01"
+ })
+ ).toEqual(newState)
+ })
+
+ it('should handle REMOVE_EXCLUDED_DATE', () => {
+ state.time_table_dates = [{date: "2017-05-01", in_out: false}]
+ state.current_month[0].excluded_date = false
+ let newState = Object.assign({}, state, {time_table_dates: []})
+ expect(
+ timetableReducer(state, {
+ type: 'REMOVE_EXCLUDED_DATE',
+ index: 0,
+ dayTypes: arrDayTypes,
+ date: "2017-05-01"
+ })
+ ).toEqual(newState)
+ })
+
+ it('should handle UPDATE_DAY_TYPES and remove out_day that are out of day types', () => {
+ state.time_table_dates = [{date: "2017-05-01", in_out: false}]
+ let newArrDayTypes = Array.from(arrDayTypes, (dt, i) => {
+ if (i == 1) dt = false
+ return dt
+ })
+ expect(
+ timetableReducer(state, {
+ type: 'UPDATE_DAY_TYPES',
+ dayTypes: newArrDayTypes
+ }).time_table_dates
+ ).toEqual([])
+ })
+
+ it('should handle UPDATE_DAY_TYPES and remove in_day that are in day types and in period', () => {
+ state.time_table_dates = [{ date: "2017-05-16", in_out: true }]
+ expect(
+ timetableReducer(state, {
+ type: 'UPDATE_DAY_TYPES',
+ dayTypes: arrDayTypes
+ }).time_table_dates
+ ).toEqual([])
+ })
+
+ it('should handle VALIDATE_PERIOD_FORM and add period if modalProps index = false', () => {
+ let newPeriods = state.time_table_periods.concat({"period_start": "2018-05-15", "period_end": "2018-05-24"})
+ let newState = Object.assign({}, state, {time_table_periods: newPeriods, time_table_dates: []})
+ let modalProps = {
+ active: false,
+ begin: {
+ day: '15',
+ month: '05',
+ year: '2018'
+ },
+ end: {
+ day: '24',
+ month: '05',
+ year: '2018'
+ },
+ error: '',
+ index: false
+ }
+ expect(
+ timetableReducer(state, {
+ type: 'VALIDATE_PERIOD_FORM',
+ modalProps: modalProps,
+ timeTablePeriods: state.time_table_periods,
+ metas: {
+ day_types: arrDayTypes
+ },
+ timetableInDates: state.time_table_dates.filter(d => d.in_out == true),
+ error: modalProps.error
+ })
+ ).toEqual(newState)
+ })
+
+ it('should handle VALIDATE_PERIOD_FORM and update period if modalProps index != false', () => {
+
+ let begin = new Date(state.time_table_periods[0].period_start)
+ let end = new Date(state.time_table_periods[0].period_end)
+ let newCM = newCurrentMonth.map((d) => {
+ if (new Date (d.date) >= begin && new Date(d.date) <= end) {
+ d.in_periods = false
+ d.excluded_date = false
+ }
+ return d
+ })
+
+ let newPeriods = state.time_table_periods.map( (p,i) => {
+ if (i == 0) {
+ p.period_start = "2018-05-15"
+ p.period_end = "2018-05-24"
+ }
+ return p
+ })
+ let newState = Object.assign({}, state, {time_table_periods: newPeriods})
+
+ let modalProps = {
+ active: false,
+ begin: {
+ day: '15',
+ month: '05',
+ year: '2018'
+ },
+ end: {
+ day: '24',
+ month: '05',
+ year: '2018'
+ },
+ error: '',
+ index: 0
+ }
+ expect(
+ timetableReducer(state, {
+ type: 'VALIDATE_PERIOD_FORM',
+ modalProps: modalProps,
+ timeTablePeriods: state.time_table_periods,
+ metas: {
+ day_types: arrDayTypes
+ },
+ timetableInDates: state.time_table_dates.filter(d => d.in_out == true)
+ })
+ ).toEqual(newState)
+ })
+})
diff --git a/spec/javascript/vehicle_journeys/actions_spec.js b/spec/javascript/vehicle_journeys/actions_spec.js
new file mode 100644
index 000000000..74765a7ef
--- /dev/null
+++ b/spec/javascript/vehicle_journeys/actions_spec.js
@@ -0,0 +1,449 @@
+import actions from '../../../app/javascript/vehicle_journeys/actions/index'
+
+const dispatch = function(){}
+const currentPage = 1
+
+describe('when cannot fetch api', () => {
+ it('should create an action to toggle error', () => {
+ const expectedAction = {
+ type: 'UNAVAILABLE_SERVER',
+ }
+ expect(actions.unavailableServer()).toEqual(expectedAction)
+ })
+})
+describe('when fetching api', () => {
+ it('should create an action to fetch api', () => {
+ const expectedAction = {
+ type: 'FETCH_API',
+ }
+ expect(actions.fetchingApi()).toEqual(expectedAction)
+ })
+})
+describe('when receiveJourneyPatterns is triggered', () => {
+ it('should create an action to pass json to reducer', () => {
+ const json = undefined
+ const expectedAction = {
+ type: 'RECEIVE_VEHICLE_JOURNEYS',
+ json
+ }
+ expect(actions.receiveVehicleJourneys()).toEqual(expectedAction)
+ })
+})
+describe('when clicking on add button', () => {
+ it('should create an action to open a create modal', () => {
+ const expectedAction = {
+ type: 'CREATE_VEHICLEJOURNEY_MODAL',
+ }
+ expect(actions.openCreateModal()).toEqual(expectedAction)
+ })
+})
+describe('when using select2 to pick a journey pattern', () => {
+ it('should create an action to select a journey pattern inside modal', () => {
+ let selectedJP = {
+ id: 1,
+ object_id: 2,
+ name: 'test',
+ published_name: 'test',
+ stop_area_short_descriptions: ['test']
+ }
+ const expectedAction = {
+ type: 'SELECT_JP_CREATE_MODAL',
+ selectedItem:{
+ id: selectedJP.id,
+ objectid: selectedJP.object_id,
+ name: selectedJP.name,
+ published_name: selectedJP.published_name,
+ stop_areas: selectedJP.stop_area_short_descriptions
+ }
+ }
+ expect(actions.selectJPCreateModal(selectedJP)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on validate button inside create modal', () => {
+ it('should create an action to create a new vehicle journey', () => {
+ const data = {}
+ const selectedJourneyPattern = {}
+ const selectedCompany = {}
+ const stopPointsList = []
+ const expectedAction = {
+ type: 'ADD_VEHICLEJOURNEY',
+ data,
+ selectedJourneyPattern,
+ stopPointsList,
+ selectedCompany
+ }
+ expect(actions.addVehicleJourney(data, selectedJourneyPattern, stopPointsList, selectedCompany)).toEqual(expectedAction)
+ })
+})
+describe('when previous navigation button is clicked', () => {
+ it('should create an action to go to previous page', () => {
+ const nextPage = false
+ const queryString = ''
+ const pagination = {
+ totalCount: 25,
+ perPage: 12,
+ page:1
+ }
+ const expectedAction = {
+ type: 'GO_TO_PREVIOUS_PAGE',
+ dispatch,
+ pagination,
+ nextPage,
+ queryString
+ }
+ expect(actions.goToPreviousPage(dispatch, pagination, queryString)).toEqual(expectedAction)
+ })
+})
+describe('when next navigation button is clicked', () => {
+ it('should create an action to go to next page', () => {
+ const queryString = ''
+ const nextPage = true
+ const pagination = {
+ totalCount: 25,
+ perPage: 12,
+ page:1
+ }
+ const expectedAction = {
+ type: 'GO_TO_NEXT_PAGE',
+ dispatch,
+ pagination,
+ nextPage,
+ queryString
+ }
+ expect(actions.goToNextPage(dispatch, pagination, queryString)).toEqual(expectedAction)
+ })
+})
+describe('when checking a vehicleJourney', () => {
+ it('should create an action to select vj', () => {
+ const index = 1
+ const expectedAction = {
+ type: 'SELECT_VEHICLEJOURNEY',
+ index
+ }
+ expect(actions.selectVehicleJourney(index)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on cancel selection button', () => {
+ it('should create an action to cancel whole selection', () => {
+ const index = 1
+ const expectedAction = {
+ type: 'CANCEL_SELECTION'
+ }
+ expect(actions.cancelSelection()).toEqual(expectedAction)
+ })
+})
+describe('when clicking on delete button', () => {
+ it('should create an action to delete vj', () => {
+ const expectedAction = {
+ type: 'DELETE_VEHICLEJOURNEYS',
+ }
+ expect(actions.deleteVehicleJourneys()).toEqual(expectedAction)
+ })
+})
+describe('when toggling arrivals', () => {
+ it('should create an action to toggleArrivals', () => {
+ const expectedAction = {
+ type: 'TOGGLE_ARRIVALS',
+ }
+ expect(actions.toggleArrivals()).toEqual(expectedAction)
+ })
+})
+describe('when updating vjas time', () => {
+ it('should create an action to update time', () => {
+ const val = 33, subIndex = 0, index = 0, timeUnit = 'minute', isDeparture = true, isArrivalsToggled = true
+ const expectedAction = {
+ type: 'UPDATE_TIME',
+ val,
+ subIndex,
+ index,
+ timeUnit,
+ isDeparture,
+ isArrivalsToggled
+ }
+ expect(actions.updateTime(val, subIndex, index, timeUnit, isDeparture, isArrivalsToggled)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on validate button inside shifting modal', () => {
+ it('should create an action to shift a vehiclejourney schedule', () => {
+ const addtionalTime = 0
+ const expectedAction = {
+ type: 'SHIFT_VEHICLEJOURNEY',
+ addtionalTime
+ }
+ expect(actions.shiftVehicleJourney(addtionalTime)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on validate button inside editing modal', () => {
+ it('should create an action to update a vehiclejourney', () => {
+ const data = {}
+ const selectedCompany = {}
+ const expectedAction = {
+ type: 'EDIT_VEHICLEJOURNEY',
+ data,
+ selectedCompany
+ }
+ expect(actions.editVehicleJourney(data, selectedCompany)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on validate button inside duplicating modal', () => {
+ it('should create an action to duplicate a vehiclejourney schedule', () => {
+ const addtionalTime = 0
+ const departureDelta = 0
+ const duplicateNumber = 1
+ const expectedAction = {
+ type: 'DUPLICATE_VEHICLEJOURNEY',
+ addtionalTime,
+ duplicateNumber,
+ departureDelta
+ }
+ expect(actions.duplicateVehicleJourney(addtionalTime, duplicateNumber, departureDelta)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on edit notes modal', () => {
+ it('should create an action to open footnotes modal', () => {
+ const vehicleJourney = {}
+ const expectedAction = {
+ type: 'EDIT_NOTES_VEHICLEJOURNEY_MODAL',
+ vehicleJourney
+ }
+ expect(actions.openNotesEditModal(vehicleJourney)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on a footnote button inside footnote modal', () => {
+ it('should create an action to toggle this footnote', () => {
+ const footnote = {}, isShown = true
+ const expectedAction = {
+ type: 'TOGGLE_FOOTNOTE_MODAL',
+ footnote,
+ isShown
+ }
+ expect(actions.toggleFootnoteModal(footnote, isShown)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on validate button inside footnote modal', () => {
+ it('should create an action to update vj footnotes', () => {
+ const footnotes = []
+ const expectedAction = {
+ type: 'EDIT_VEHICLEJOURNEY_NOTES',
+ footnotes
+ }
+ expect(actions.editVehicleJourneyNotes(footnotes)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on calendar button in toolbox', () => {
+ it('should create an action to open calendar modal', () => {
+ const vehicleJourneys = []
+ const expectedAction = {
+ type: 'EDIT_CALENDARS_VEHICLEJOURNEY_MODAL',
+ vehicleJourneys
+ }
+ expect(actions.openCalendarsEditModal(vehicleJourneys)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on delete button next to a timetable inside modal', () => {
+ it('should create an action to delete timetable from selected vehicle journeys', () => {
+ const timetable = {}
+ const expectedAction = {
+ type: 'DELETE_CALENDAR_MODAL',
+ timetable
+ }
+ expect(actions.deleteCalendarModal(timetable)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on validate button inside calendars modal', () => {
+ it('should create an action to update vj calendars', () => {
+ const vehicleJourneys = []
+ const timetables = []
+ const expectedAction = {
+ type: 'EDIT_VEHICLEJOURNEYS_TIMETABLES',
+ vehicleJourneys,
+ timetables
+ }
+ expect(actions.editVehicleJourneyTimetables(vehicleJourneys, timetables)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on add button inside calendars modal', () => {
+ it('should create an action to add the selected timetable to preselected vjs', () => {
+ const expectedAction = {
+ type: 'ADD_SELECTED_TIMETABLE',
+ }
+ expect(actions.addSelectedTimetable()).toEqual(expectedAction)
+ })
+})
+describe('when using select2 to pick a timetable', () => {
+ it('should create an action to select a timetable inside modal', () => {
+ let selectedTT = {
+ id: 1,
+ objectid: 2,
+ comment: 'test',
+ }
+ const expectedAction = {
+ type: 'SELECT_TT_CALENDAR_MODAL',
+ selectedItem:{
+ id: selectedTT.id,
+ objectid: selectedTT.objectid,
+ comment: selectedTT.comment,
+ }
+ }
+ expect(actions.selectTTCalendarsModal(selectedTT)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on reset button inside query filters', () => {
+ it('should create an action to reset the query filters', () => {
+ const expectedAction = {
+ type: 'BATCH',
+ payload: [
+ {type: 'RESET_FILTERS'},
+ {type: 'RESET_PAGINATION'},
+ {type: 'QUERY_FILTER_VEHICLEJOURNEYS', dispatch: undefined},
+ ]
+ }
+ expect(actions.resetFilters()).toEqual(expectedAction)
+ })
+})
+describe('when clicking on filter button inside query filters', () => {
+ it('should create an action to filter', () => {
+ const expectedAction = {
+ type: 'BATCH',
+ payload: [
+ {type: 'CREATE_QUERY_STRING'},
+ {type: 'RESET_PAGINATION'},
+ {type: 'QUERY_FILTER_VEHICLEJOURNEYS', dispatch: undefined},
+ ]
+ }
+ expect(actions.filterQuery()).toEqual(expectedAction)
+ })
+})
+describe('when clicking on checkbox to show vj without schedule', () => {
+ it('should create an action to toggle this filter', () => {
+ const expectedAction = {
+ type: 'TOGGLE_WITHOUT_SCHEDULE',
+ }
+ expect(actions.toggleWithoutSchedule()).toEqual(expectedAction)
+ })
+})
+describe('when setting new interval', () => {
+ const val = 1
+ const unit = 'hour'
+ it('should create actions to update intervals in state', () => {
+ let expectedAction = {
+ type: 'UPDATE_START_TIME_FILTER',
+ val,
+ unit
+ }
+ expect(actions.updateStartTimeFilter(val, unit)).toEqual(expectedAction)
+ })
+ it('should create actions to update intervals in state', () => {
+ let expectedAction = {
+ type: 'UPDATE_END_TIME_FILTER',
+ val,
+ unit
+ }
+ expect(actions.updateEndTimeFilter(val, unit)).toEqual(expectedAction)
+ })
+})
+describe('when using select2 to pick a timetable in the filters', () => {
+ it('should create an action to select a timetable as a filter', () => {
+ let selectedTT = {
+ id: 1,
+ objectid: 2,
+ comment: 'test',
+ }
+ const expectedAction = {
+ type: 'SELECT_TT_FILTER',
+ selectedItem:{
+ id: selectedTT.id,
+ objectid: selectedTT.objectid,
+ comment: selectedTT.comment,
+ }
+ }
+ expect(actions.filterSelect2Timetable(selectedTT)).toEqual(expectedAction)
+ })
+})
+describe('when using select2 to pick a journeypattern in the filters', () => {
+ it('should create an action to select a journey pattern as a filter', () => {
+ let selectedJP = {
+ id: 1,
+ object_id: 2,
+ name: 'test',
+ published_name: 'test'
+ }
+ const expectedAction = {
+ type: 'SELECT_JP_FILTER',
+ selectedItem:{
+ id: selectedJP.id,
+ objectid: selectedJP.object_id,
+ name: selectedJP.name,
+ published_name: selectedJP.published_name
+ }
+ }
+ expect(actions.filterSelect2JourneyPattern(selectedJP)).toEqual(expectedAction)
+ })
+})
+describe('when user clicked either on filter or reset button in filters', () => {
+ it('should create an action to reset pagination', () => {
+ const expectedAction = {
+ type: 'RESET_PAGINATION',
+ }
+ expect(actions.resetPagination()).toEqual(expectedAction)
+ })
+})
+describe('when user clicked either on filter or reset button in filters', () => {
+ it('should create an action to create a queryString with params filters', () => {
+ const expectedAction = {
+ type: 'CREATE_QUERY_STRING',
+ }
+ expect(actions.createQueryString()).toEqual(expectedAction)
+ })
+})
+describe('when submitting new vj', () => {
+ it('should create an action to update pagination totalCount', () => {
+ const diff = 1
+ const expectedAction = {
+ type: 'UPDATE_TOTAL_COUNT',
+ diff
+ }
+ expect(actions.updateTotalCount(diff)).toEqual(expectedAction)
+ })
+})
+describe('when receiving vj', () => {
+ it('should create an action to show pagination totalCount', () => {
+ const total = 1
+ const expectedAction = {
+ type: 'RECEIVE_TOTAL_COUNT',
+ total
+ }
+ expect(actions.receiveTotalCount(total)).toEqual(expectedAction)
+ })
+})
+describe('when using select2 to pick a company', () => {
+ it('should create an action to select a company inside modal', () => {
+ let selectedCompany = {
+ id: 1,
+ objectid: 2,
+ name: 'test',
+ }
+ const expectedAction = {
+ type: 'SELECT_CP_EDIT_MODAL',
+ selectedItem:{
+ id: selectedCompany.id,
+ objectid: selectedCompany.objectid,
+ name: selectedCompany.name,
+ }
+ }
+ expect(actions.select2Company(selectedCompany)).toEqual(expectedAction)
+ })
+})
+describe('when using select2 to unselect a company', () => {
+ it('should create an action to unselect a company inside modal', () => {
+ let selectedCompany = {
+ id: 1,
+ objectid: 2,
+ name: 'test',
+ }
+ const expectedAction = {
+ type: 'UNSELECT_CP_EDIT_MODAL'
+ }
+ expect(actions.unselect2Company()).toEqual(expectedAction)
+ })
+})
diff --git a/spec/javascript/vehicle_journeys/reducers/filters_spec.js b/spec/javascript/vehicle_journeys/reducers/filters_spec.js
new file mode 100644
index 000000000..207eaead4
--- /dev/null
+++ b/spec/javascript/vehicle_journeys/reducers/filters_spec.js
@@ -0,0 +1,165 @@
+import statusReducer from '../../../../app/javascript/vehicle_journeys/reducers/filters'
+
+let state = {}
+
+describe('filters reducer', () => {
+ const cleanInterval = {
+ start:{
+ hour: '00',
+ minute: '00'
+ },
+ end:{
+ hour: '23',
+ minute: '59'
+ }
+ }
+ beforeEach(() => {
+ state = {
+ toggleArrivals: false,
+ query: {
+ interval: {
+ start:{
+ hour: '11',
+ minute: '11'
+ },
+ end:{
+ hour: '22',
+ minute: '22'
+ }
+ },
+ journeyPattern: {},
+ vehicleJourney: {},
+ timetable: {},
+ withoutSchedule: true,
+ withoutTimeTable: true
+ },
+ queryString: ''
+ }
+ })
+
+ it('should return the initial state', () => {
+ expect(
+ statusReducer(undefined, {})
+ ).toEqual({})
+ })
+
+ it('should handle TOGGLE_ARRIVALS', () => {
+ expect(
+ statusReducer(state, {
+ type: 'TOGGLE_ARRIVALS'
+ })
+ ).toEqual(Object.assign({}, state, {toggleArrivals: true}))
+ })
+
+ it('should handle RESET_FILTERS', () => {
+ let cleanQuery = JSON.parse(JSON.stringify(state.query))
+ cleanQuery.interval = cleanInterval
+ expect(
+ statusReducer(state, {
+ type: 'RESET_FILTERS'
+ })
+ ).toEqual(Object.assign({}, state, {query: cleanQuery}))
+ })
+
+ it('should handle TOGGLE_WITHOUT_SCHEDULE', () => {
+ let rslt = JSON.parse(JSON.stringify(state.query))
+ rslt.withoutSchedule = false
+ expect(
+ statusReducer(state, {
+ type: 'TOGGLE_WITHOUT_SCHEDULE'
+ })
+ ).toEqual(Object.assign({}, state, {query: rslt}))
+ })
+
+ it('should handle UPDATE_START_TIME_FILTER', () => {
+ let val = 12
+ let unit = 'minute'
+ let rslt = JSON.parse(JSON.stringify(state.query))
+ rslt.interval.start.minute = String(val)
+ expect(
+ statusReducer(state, {
+ type: 'UPDATE_START_TIME_FILTER',
+ val,
+ unit
+ })
+ ).toEqual(Object.assign({}, state, {query: rslt}))
+ })
+
+ it('should handle UPDATE_START_TIME_FILTER and not make any update', () => {
+ let val = 23
+ let unit = 'hour'
+ expect(
+ statusReducer(state, {
+ type: 'UPDATE_START_TIME_FILTER',
+ val,
+ unit
+ })
+ ).toEqual(state)
+ })
+
+ it('should handle UPDATE_END_TIME_FILTER', () => {
+ let val = 12
+ let unit = 'minute'
+ let rslt = JSON.parse(JSON.stringify(state.query))
+ rslt.interval.end.minute = String(val)
+ expect(
+ statusReducer(state, {
+ type: 'UPDATE_END_TIME_FILTER',
+ val,
+ unit
+ })
+ ).toEqual(Object.assign({}, state, {query: rslt}))
+ })
+
+ it('should handle UPDATE_END_TIME_FILTER and not make any update', () => {
+ let val = 1
+ let unit = 'hour'
+ expect(
+ statusReducer(state, {
+ type: 'UPDATE_END_TIME_FILTER',
+ val,
+ unit
+ })
+ ).toEqual(state)
+ })
+
+ it('should handle SELECT_TT_FILTER', () => {
+ let newTimetable = {timetable : {id: 1}}
+ let newQuery = Object.assign({}, state.query, newTimetable)
+ expect(
+ statusReducer(state, {
+ type: 'SELECT_TT_FILTER',
+ selectedItem: {id: 1}
+ })
+ ).toEqual(Object.assign({}, state, {query: newQuery}))
+ })
+
+ it('should handle SELECT_JP_FILTER', () => {
+ let newJourneyPattern = {journeyPattern : {id: 1}}
+ let newQuery = Object.assign({}, state.query, newJourneyPattern)
+ expect(
+ statusReducer(state, {
+ type: 'SELECT_JP_FILTER',
+ selectedItem: {id: 1}
+ })
+ ).toEqual(Object.assign({}, state, {query: newQuery}))
+ })
+
+ it('should handle CREATE_QUERY_STRING', () => {
+ let strResult = [
+ "q%5Bjourney_pattern_id_eq%5D=undefined",
+ "&q%5Bobjectid_cont%5D=undefined",
+ "&q%5Btime_tables_id_eq%5D=undefined",
+ "&q%5Bvehicle_journey_at_stops_departure_time_gteq%5D=11%3A11",
+ "&q%5Bvehicle_journey_at_stops_departure_time_lteq%5D=22%3A22",
+ "&q%5Bvehicle_journey_without_departure_time%5D=true",
+ "&q%5Bvehicle_journey_without_time_table%5D=true"
+ ].join('')
+
+ expect(
+ statusReducer(state, {
+ type: 'CREATE_QUERY_STRING',
+ })
+ ).toEqual(Object.assign({}, state, {queryString: strResult}))
+ })
+})
diff --git a/spec/javascript/vehicle_journeys/reducers/modal_spec.js b/spec/javascript/vehicle_journeys/reducers/modal_spec.js
new file mode 100644
index 000000000..69de9168b
--- /dev/null
+++ b/spec/javascript/vehicle_journeys/reducers/modal_spec.js
@@ -0,0 +1,179 @@
+import modalReducer from '../../../../app/javascript/vehicle_journeys/reducers/modal'
+
+let state = {}
+
+const cb = function(){}
+
+describe('modal reducer', () => {
+ beforeEach(() => {
+ state = {
+ type: '',
+ modalProps: {},
+ confirmModal: {}
+ }
+ })
+
+ it('should return the initial state', () => {
+ expect(
+ modalReducer(undefined, {})
+ ).toEqual({})
+ })
+
+ it('should handle OPEN_CONFIRM_MODAL', () => {
+ let newState = Object.assign({}, state, {
+ type: 'confirm',
+ confirmModal: {
+ callback: cb
+ }
+ })
+ expect(
+ modalReducer(state, {
+ type: 'OPEN_CONFIRM_MODAL',
+ callback: cb
+ })
+ ).toEqual(newState)
+ })
+
+ it('should handle CREATE_VEHICLEJOURNEY_MODAL', () => {
+ expect(
+ modalReducer(state, {
+ type: 'CREATE_VEHICLEJOURNEY_MODAL'
+ })
+ ).toEqual(Object.assign({}, state, { type: 'create' }))
+ })
+
+ it('should handle SELECT_JP_CREATE_MODAL', () => {
+ let newModalProps = {selectedJPModal : {id: 1}}
+ expect(
+ modalReducer(state, {
+ type: 'SELECT_JP_CREATE_MODAL',
+ selectedItem: {id: 1}
+ })
+ ).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
+ })
+
+ it('should handle CLOSE_MODAL', () => {
+ expect(
+ modalReducer(state, {
+ type: 'CLOSE_MODAL'
+ })
+ ).toEqual(state)
+ })
+
+ it('should handle EDIT_NOTES_VEHICLEJOURNEY_MODAL', () => {
+ let vehicleJourney = {}
+ let modalPropsResult = {
+ vehicleJourney: {}
+ }
+ expect(
+ modalReducer(state, {
+ type: 'EDIT_NOTES_VEHICLEJOURNEY_MODAL',
+ vehicleJourney
+ })
+ ).toEqual(Object.assign({}, state, {type: 'notes_edit', modalProps: modalPropsResult}))
+ })
+
+ it('should handle TOGGLE_FOOTNOTE_MODAL', () => {
+ state.modalProps = {vehicleJourney : {footnotes: [{}, {}]}}
+ let footnote = {}
+ let newState = {
+ // for the sake of the test, no need to specify the type
+ type: '',
+ modalProps:{vehicleJourney: {footnotes: [{},{},{}]}},
+ confirmModal: {}
+ }
+ expect(
+ modalReducer(state, {
+ type: 'TOGGLE_FOOTNOTE_MODAL',
+ footnote,
+ isShown: true
+ })
+ ).toEqual(newState)
+ })
+
+ it('should handle EDIT_CALENDARS_VEHICLEJOURNEY_MODAL', () => {
+ let vehicleJourneys = []
+ let modalPropsResult = {
+ vehicleJourneys: [],
+ timetables: []
+ }
+ expect(
+ modalReducer(state, {
+ type: 'EDIT_CALENDARS_VEHICLEJOURNEY_MODAL',
+ vehicleJourneys
+ })
+ ).toEqual(Object.assign({}, state, {type: 'calendars_edit', modalProps: modalPropsResult}))
+ })
+
+ it('should handle SELECT_TT_CALENDAR_MODAL', () => {
+ let newModalProps = {selectedTimetable : {id: 1}}
+ expect(
+ modalReducer(state, {
+ type: 'SELECT_TT_CALENDAR_MODAL',
+ selectedItem: {id: 1}
+ })
+ ).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
+ })
+
+ it('should handle ADD_SELECTED_TIMETABLE', () => {
+ let fakeTimetables = [{'test': 'test'}, {'test 2': 'test 2'}, {'add': 'add'}]
+ let newTimeTables = [{'test': 'test'}, {'test 2': 'test 2'}, {'add': 'add'}]
+ let fakeVehicleJourneys= [{time_tables: fakeTimetables}, {time_tables: newTimeTables}]
+ state.modalProps.vehicleJourneys = fakeVehicleJourneys
+ state.modalProps.timetables = fakeTimetables
+ state.modalProps.selectedTimetable = {'add': 'add'}
+ let newState = {
+ type: '',
+ modalProps:{
+ vehicleJourneys: [{time_tables: newTimeTables},{time_tables: newTimeTables}],
+ timetables: [{'test': 'test'},{'test 2': 'test 2'},{'add': 'add'}],
+ selectedTimetable: {'add': 'add'}
+ },
+ confirmModal: {}
+ }
+ expect(
+ modalReducer(state, {
+ type: 'ADD_SELECTED_TIMETABLE',
+ })
+ ).toEqual(newState)
+ })
+
+ it('should handle DELETE_CALENDAR_MODAL', () => {
+ let deletableTimetable = {'delete': 'delete'}
+ let fakeTimetables = [{'test': 'test'}, {'test 2': 'test 2'}, deletableTimetable]
+ let newTimeTables = [{'test': 'test'}, {'test 2': 'test 2'}]
+ let fakeVehicleJourneys= [{time_tables: fakeTimetables}, {time_tables: fakeTimetables}]
+ state.modalProps = Object.assign({}, state.modalProps,{vehicleJourneys : fakeVehicleJourneys, timetables: fakeTimetables })
+ let newState = {
+ // for the sake of the test, no need to specify the type
+ type: '',
+ modalProps:{vehicleJourneys: [{time_tables: newTimeTables},{time_tables: newTimeTables}], timetables: [{'test': 'test'},{'test 2': 'test 2'}]},
+ confirmModal: {}
+ }
+ expect(
+ modalReducer(state, {
+ type: 'DELETE_CALENDAR_MODAL',
+ timetable: deletableTimetable
+ })
+ ).toEqual(newState)
+ })
+
+ it('should handle SELECT_CP_EDIT_MODAL', () => {
+ let newModalProps = {selectedCompany : {name: 'ALBATRANS'}}
+ expect(
+ modalReducer(state, {
+ type: 'SELECT_CP_EDIT_MODAL',
+ selectedItem: {name: 'ALBATRANS'}
+ })
+ ).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
+ })
+
+ it('should handle UNSELECT_CP_EDIT_MODAL', () => {
+ let newModalProps = {selectedCompany : undefined}
+ expect(
+ modalReducer(state, {
+ type: 'UNSELECT_CP_EDIT_MODAL'
+ })
+ ).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
+ })
+})
diff --git a/spec/javascript/vehicle_journeys/reducers/pagination_spec.js b/spec/javascript/vehicle_journeys/reducers/pagination_spec.js
new file mode 100644
index 000000000..352997c7c
--- /dev/null
+++ b/spec/javascript/vehicle_journeys/reducers/pagination_spec.js
@@ -0,0 +1,123 @@
+import reducer from '../../../../app/javascript/vehicle_journeys/reducers/pagination'
+
+const diff = 1
+let state = {
+ page : 2,
+ totalCount : 25,
+ stateChanged: false,
+ perPage: 12
+}
+let pagination = Object.assign({}, state)
+const dispatch = function(){}
+
+describe('pagination reducer, given parameters allowing page change', () => {
+
+ it('should return the initial state', () => {
+ expect(
+ reducer(undefined, {})
+ ).toEqual({})
+ })
+
+ it('should handle RECEIVE_TOTAL_COUNT', () => {
+ expect(
+ reducer(state, {
+ type: 'RECEIVE_TOTAL_COUNT',
+ total: 1
+ })
+ ).toEqual(Object.assign({}, state, {totalCount: 1}))
+ })
+
+ it('should handle RESET_PAGINATION', () => {
+ expect(
+ reducer(state, {
+ type: 'RESET_PAGINATION',
+ })
+ ).toEqual(Object.assign({}, state, {page: 1}))
+ })
+
+ it('should handle UPDATE_TOTAL_COUNT', () => {
+ expect(
+ reducer(state, {
+ type: 'UPDATE_TOTAL_COUNT',
+ diff: 1
+ })
+ ).toEqual(Object.assign({}, state, {totalCount: 24}))
+ })
+
+ it('should handle GO_TO_NEXT_PAGE and change state', () => {
+ expect(
+ reducer(state, {
+ type: 'GO_TO_NEXT_PAGE',
+ dispatch,
+ pagination,
+ nextPage : true
+ })
+ ).toEqual(Object.assign({}, state, {page : state.page + 1, stateChanged: false}))
+ })
+
+ it('should return GO_TO_PREVIOUS_PAGE and change state', () => {
+ expect(
+ reducer(state, {
+ type: 'GO_TO_PREVIOUS_PAGE',
+ dispatch,
+ pagination,
+ nextPage : false
+ })
+ ).toEqual(Object.assign({}, state, {page : state.page - 1, stateChanged: false}))
+ })
+
+ it('should handle UPDATE_TIME', () => {
+ const val = '33', subIndex = 0, index = 0, timeUnit = 'minute', isDeparture = true, isArrivalsToggled = true
+ expect(
+ reducer(state, {
+ type: 'UPDATE_TIME',
+ val,
+ subIndex,
+ index,
+ timeUnit,
+ isDeparture,
+ isArrivalsToggled
+ })
+ ).toEqual(Object.assign({}, state, {stateChanged: true}))
+ })
+
+})
+
+
+describe('pagination reducer, given parameters not allowing to go to previous page', () => {
+
+ beforeEach(()=>{
+ state.page = 1
+ pagination.page = 1
+ })
+
+ it('should return GO_TO_PREVIOUS_PAGE and not change state', () => {
+ expect(
+ reducer(state, {
+ type: 'GO_TO_PREVIOUS_PAGE',
+ dispatch,
+ pagination,
+ nextPage : false
+ })
+ ).toEqual(state)
+ })
+})
+
+describe('pagination reducer, given parameters not allowing to go to next page', () => {
+
+ beforeEach(()=>{
+ state.page = 3
+ pagination.page = 3
+ })
+
+ it('should return GO_TO_NEXT_PAGE and not change state', () => {
+ expect(
+ reducer(state, {
+ type: 'GO_TO_NEXT_PAGE',
+ dispatch,
+ pagination,
+ nextPage : true
+ })
+ ).toEqual(state)
+ })
+})
diff --git a/spec/javascript/vehicle_journeys/reducers/status_spec.js b/spec/javascript/vehicle_journeys/reducers/status_spec.js
new file mode 100644
index 000000000..8fc0f557e
--- /dev/null
+++ b/spec/javascript/vehicle_journeys/reducers/status_spec.js
@@ -0,0 +1,45 @@
+import statusReducer from '../../../../app/javascript/vehicle_journeys/reducers/status'
+
+let state = {}
+
+const dispatch = function(){}
+
+describe('status reducer', () => {
+ beforeEach(() => {
+ state = {
+ fetchSuccess: true,
+ isFetching: false
+ }
+ })
+
+ it('should return the initial state', () => {
+ expect(
+ statusReducer(undefined, {})
+ ).toEqual({})
+ })
+
+ it('should handle UNAVAILABLE_SERVER', () => {
+ expect(
+ statusReducer(state, {
+ type: 'UNAVAILABLE_SERVER'
+ })
+ ).toEqual(Object.assign({}, state, {fetchSuccess: false}))
+ })
+
+ it('should handle RECEIVE_VEHICLE_JOURNEYS', () => {
+ expect(
+ statusReducer(state, {
+ type: 'RECEIVE_VEHICLE_JOURNEYS'
+ })
+ ).toEqual(Object.assign({}, state, {fetchSuccess: true, isFetching: false}))
+ })
+
+ it('should handle FETCH_API', () => {
+ expect(
+ statusReducer(state, {
+ type: 'FETCH_API'
+ })
+ ).toEqual(Object.assign({}, state, {isFetching: true}))
+ })
+
+})
diff --git a/spec/javascript/vehicle_journeys/reducers/vehicle_journeys_spec.js b/spec/javascript/vehicle_journeys/reducers/vehicle_journeys_spec.js
new file mode 100644
index 000000000..c02ab3398
--- /dev/null
+++ b/spec/javascript/vehicle_journeys/reducers/vehicle_journeys_spec.js
@@ -0,0 +1,268 @@
+import vjReducer from '../../../../app/javascript/vehicle_journeys/reducers/vehicleJourneys'
+
+let state = []
+let stateModal = {
+ type: '',
+ modalProps: {},
+ confirmModal: {}
+}
+let fakeFootnotes = [{
+ id: 1,
+ code: 1,
+ label: "1"
+},{
+ id: 2,
+ code: 2,
+ label: "2"
+}]
+
+let fakeTimeTables = [{
+ published_journey_name: 'test 1',
+ objectid: '1'
+},{
+ published_journey_name: 'test 2',
+ objectid: '2'
+},{
+ published_journey_name: 'test 3',
+ objectid: '3'
+}]
+let fakeVJAS = [{
+ delta : 627,
+ arrival_time : {
+ hour: '11',
+ minute: '55'
+ },
+ departure_time : {
+ hour: '22',
+ minute: '22'
+ },
+ stop_area_object_id : "FR:92024:ZDE:420553:STIF"
+}]
+
+describe('vehicleJourneys reducer', () => {
+ beforeEach(()=>{
+ state = [
+ {
+ journey_pattern_id: 1,
+ published_journey_name: "vj1",
+ objectid: '11',
+ deletable: false,
+ selected: true,
+ footnotes: fakeFootnotes,
+ time_tables: fakeTimeTables,
+ vehicle_journey_at_stops: fakeVJAS
+ },
+ {
+ journey_pattern_id: 2,
+ published_journey_name: "vj2",
+ objectid: '22',
+ selected: false,
+ deletable: false,
+ footnotes: fakeFootnotes,
+ time_tables: fakeTimeTables,
+ vehicle_journey_at_stops: fakeVJAS
+ }
+ ]
+ })
+
+ it('should return the initial state', () => {
+ expect(
+ vjReducer(undefined, {})
+ ).toEqual([])
+ })
+
+
+ it('should handle ADD_VEHICLEJOURNEY', () => {
+ let pristineVjasList = [{
+ delta : 0,
+ arrival_time : {
+ hour: '00',
+ minute: '00'
+ },
+ departure_time : {
+ hour: '00',
+ minute: '00'
+ },
+ stop_point_objectid: 'test',
+ stop_area_cityname: 'city',
+ dummy: true
+ }]
+ let fakeData = {
+ published_journey_name: {value: 'test'},
+ published_journey_identifier: {value : ''}
+ }
+ let fakeSelectedJourneyPattern = {id: "1"}
+ let fakeSelectedCompany = {name: "ALBATRANS"}
+ expect(
+ vjReducer(state, {
+ type: 'ADD_VEHICLEJOURNEY',
+ data: fakeData,
+ selectedJourneyPattern: fakeSelectedJourneyPattern,
+ stopPointsList: [{object_id: 'test', city_name: 'city'}],
+ selectedCompany: fakeSelectedCompany
+ })
+ ).toEqual([{
+ journey_pattern: fakeSelectedJourneyPattern,
+ company: fakeSelectedCompany,
+ published_journey_name: 'test',
+ published_journey_identifier: '',
+ objectid: '',
+ footnotes: [],
+ time_tables: [],
+ vehicle_journey_at_stops: pristineVjasList,
+ selected: false,
+ deletable: false,
+ transport_mode: 'undefined',
+ transport_submode: 'undefined'
+ }, ...state])
+ })
+
+ it('should handle RECEIVE_VEHICLE_JOURNEYS', () => {
+ expect(
+ vjReducer(state, {
+ type: 'RECEIVE_VEHICLE_JOURNEYS',
+ json: state
+ })
+ ).toEqual(state)
+ })
+
+ it('should handle UPDATE_TIME', () => {
+ const val = '33', subIndex = 0, index = 0, timeUnit = 'minute', isDeparture = true, isArrivalsToggled = true
+ let newVJAS = [{
+ delta: 638,
+ arrival_time : {
+ hour: '11',
+ minute: '55'
+ },
+ departure_time : {
+ hour: '22',
+ minute: '33'
+ },
+ stop_area_object_id : "FR:92024:ZDE:420553:STIF"
+ }]
+ let newVJ = Object.assign({}, state[0], {vehicle_journey_at_stops: newVJAS})
+ expect(
+ vjReducer(state, {
+ type: 'UPDATE_TIME',
+ val,
+ subIndex,
+ index,
+ timeUnit,
+ isDeparture,
+ isArrivalsToggled
+ })
+ ).toEqual([newVJ, state[1]])
+ })
+
+ it('should handle SELECT_VEHICLEJOURNEY', () => {
+ const index = 1
+ const newVJ = Object.assign({}, state[1], {selected: true})
+ expect(
+ vjReducer(state, {
+ type: 'SELECT_VEHICLEJOURNEY',
+ index
+ })
+ ).toEqual([state[0], newVJ])
+ })
+
+ it('should handle CANCEL_SELECTION', () => {
+ const index = 1
+ const newVJ = Object.assign({}, state[0], {selected: false})
+ expect(
+ vjReducer(state, {
+ type: 'CANCEL_SELECTION',
+ index
+ })
+ ).toEqual([newVJ, state[1]])
+ })
+
+ it('should handle DELETE_VEHICLEJOURNEYS', () => {
+ const newVJ = Object.assign({}, state[0], {deletable: true, selected: false})
+ expect(
+ vjReducer(state, {
+ type: 'DELETE_VEHICLEJOURNEYS'
+ })
+ ).toEqual([newVJ, state[1]])
+ })
+
+ it('should handle SHIFT_VEHICLEJOURNEY', () => {
+ let newVJAS = [{
+ delta: 627,
+ arrival_time : {
+ hour: '12',
+ minute: '00'
+ },
+ departure_time : {
+ hour: '22',
+ minute: '27'
+ },
+ stop_area_object_id : "FR:92024:ZDE:420553:STIF"
+ }]
+ let addtionalTime = 5
+ let newVJ = Object.assign({}, state[0], {vehicle_journey_at_stops: newVJAS})
+ expect(
+ vjReducer(state, {
+ type: 'SHIFT_VEHICLEJOURNEY',
+ addtionalTime
+ })
+ ).toEqual([newVJ, state[1]])
+ })
+
+ it('should handle DUPLICATE_VEHICLEJOURNEY', () => {
+ let newVJAS = [{
+ delta: 627,
+ arrival_time : {
+ hour: '12',
+ minute: '01'
+ },
+ departure_time : {
+ hour: '22',
+ minute: '28'
+ },
+ stop_area_object_id : "FR:92024:ZDE:420553:STIF"
+ }]
+ let departureDelta = 1
+ let addtionalTime = 5
+ let duplicateNumber = 1
+
+ let newVJ = Object.assign({}, state[0], {vehicle_journey_at_stops: newVJAS, selected: false})
+ newVJ.published_journey_name = state[0].published_journey_name + '-0'
+ delete newVJ['objectid']
+ expect(
+ vjReducer(state, {
+ type: 'DUPLICATE_VEHICLEJOURNEY',
+ addtionalTime,
+ duplicateNumber,
+ departureDelta
+ })
+ ).toEqual([state[0], newVJ, state[1]])
+ })
+
+ it('should handle EDIT_VEHICLEJOURNEY', () => {
+ let fakeData = {
+ published_journey_name: {value : 'test'},
+ published_journey_identifier: {value: 'test'}
+ }
+ let fakeSelectedCompany : {name : 'ALBATRANS'}
+ let newVJ = Object.assign({}, state[0], {company: fakeSelectedCompany, published_journey_name: fakeData.published_journey_name.value, published_journey_identifier: fakeData.published_journey_identifier.value})
+ expect(
+ vjReducer(state, {
+ type: 'EDIT_VEHICLEJOURNEY',
+ data: fakeData
+ })
+ ).toEqual([newVJ, state[1]])
+ })
+
+
+ it('should handle EDIT_VEHICLEJOURNEYS_TIMETABLES', () => {
+ let newState = JSON.parse(JSON.stringify(state))
+ newState[0].time_tables = [fakeTimeTables[0]]
+ expect(
+ vjReducer(state, {
+ type: 'EDIT_VEHICLEJOURNEYS_TIMETABLES',
+ vehicleJourneys: state,
+ timetables: [fakeTimeTables[0]]
+ })
+ ).toEqual(newState)
+ })
+})