Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
a2db3609
Commit
a2db3609
authored
Feb 01, 2021
by
Olena Horal-Koretska
Committed by
Jose Ivan Vargas
Feb 01, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adjust schedule timeframe
parent
c7422661
Changes
31
Show whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
446 additions
and
101 deletions
+446
-101
app/assets/javascripts/lib/utils/datetime_utility.js
app/assets/javascripts/lib/utils/datetime_utility.js
+36
-0
ee/app/assets/javascripts/oncall_schedules/components/oncall_schedule.vue
...vascripts/oncall_schedules/components/oncall_schedule.vue
+94
-17
ee/app/assets/javascripts/oncall_schedules/components/oncall_schedules_wrapper.vue
.../oncall_schedules/components/oncall_schedules_wrapper.vue
+3
-5
ee/app/assets/javascripts/oncall_schedules/components/rotations/components/rotation_assignee.vue
...les/components/rotations/components/rotation_assignee.vue
+2
-2
ee/app/assets/javascripts/oncall_schedules/components/schedule/components/current_day_indicator.vue
.../components/schedule/components/current_day_indicator.vue
+14
-1
ee/app/assets/javascripts/oncall_schedules/components/schedule/components/preset_days/days_header_item.vue
...ents/schedule/components/preset_days/days_header_item.vue
+1
-1
ee/app/assets/javascripts/oncall_schedules/components/schedule/components/preset_days/days_header_sub_item.vue
.../schedule/components/preset_days/days_header_sub_item.vue
+7
-0
ee/app/assets/javascripts/oncall_schedules/components/schedule/components/rotations_list_section.vue
...components/schedule/components/rotations_list_section.vue
+2
-1
ee/app/assets/javascripts/oncall_schedules/components/schedule/components/shifts/components/days_schedule_shift.vue
...dule/components/shifts/components/days_schedule_shift.vue
+2
-3
ee/app/assets/javascripts/oncall_schedules/components/schedule/components/shifts/components/weeks_schedule_shift.vue
...ule/components/shifts/components/weeks_schedule_shift.vue
+13
-14
ee/app/assets/javascripts/oncall_schedules/components/schedule/utils.js
...javascripts/oncall_schedules/components/schedule/utils.js
+0
-15
ee/app/assets/javascripts/oncall_schedules/graphql/fragments/oncall_schedule_participant.fragment.graphql
...ql/fragments/oncall_schedule_participant.fragment.graphql
+9
-0
ee/app/assets/javascripts/oncall_schedules/graphql/fragments/oncall_schedule_rotation.fragment.graphql
...aphql/fragments/oncall_schedule_rotation.fragment.graphql
+3
-6
ee/app/assets/javascripts/oncall_schedules/graphql/fragments/oncall_schedule_rotation_with_shifts.fragment.graphql
...nts/oncall_schedule_rotation_with_shifts.fragment.graphql
+14
-0
ee/app/assets/javascripts/oncall_schedules/graphql/queries/get_oncall_schedules.query.graphql
...edules/graphql/queries/get_oncall_schedules.query.graphql
+8
-1
ee/app/assets/javascripts/oncall_schedules/graphql/queries/get_oncall_schedules_with_rotations_shifts.query.graphql
.../get_oncall_schedules_with_rotations_shifts.query.graphql
+15
-0
ee/app/assets/javascripts/oncall_schedules/mixins/common_mixin.js
...ssets/javascripts/oncall_schedules/mixins/common_mixin.js
+4
-0
ee/spec/frontend/oncall_schedule/mocks/apollo_mock.js
ee/spec/frontend/oncall_schedule/mocks/apollo_mock.js
+32
-3
ee/spec/frontend/oncall_schedule/mocks/mock_rotation.json
ee/spec/frontend/oncall_schedule/mocks/mock_rotation.json
+1
-1
ee/spec/frontend/oncall_schedule/oncall_schedule_spec.js
ee/spec/frontend/oncall_schedule/oncall_schedule_spec.js
+73
-2
ee/spec/frontend/oncall_schedule/oncall_schedule_wrapper_spec.js
.../frontend/oncall_schedule/oncall_schedule_wrapper_spec.js
+6
-4
ee/spec/frontend/oncall_schedule/rotations/components/add_edit_rotation_modal_spec.js
...dule/rotations/components/add_edit_rotation_modal_spec.js
+6
-2
ee/spec/frontend/oncall_schedule/rotations/components/delete_rotation_modal_spec.js
...hedule/rotations/components/delete_rotation_modal_spec.js
+6
-2
ee/spec/frontend/oncall_schedule/rotations/components/rotation_assignee_spec.js
...l_schedule/rotations/components/rotation_assignee_spec.js
+1
-1
ee/spec/frontend/oncall_schedule/schedule/components/__snapshots__/rotations_list_section_spec.js.snap
...ponents/__snapshots__/rotations_list_section_spec.js.snap
+0
-2
ee/spec/frontend/oncall_schedule/schedule/components/preset_days/days_header_sub_item_spec.js
...edule/components/preset_days/days_header_sub_item_spec.js
+8
-4
ee/spec/frontend/oncall_schedule/schedule/components/shifts/components/days_schedule_shift_spec.js
.../components/shifts/components/days_schedule_shift_spec.js
+2
-2
ee/spec/frontend/oncall_schedule/schedule/components/shifts/components/schedule_shift_wrapper_spec.js
...mponents/shifts/components/schedule_shift_wrapper_spec.js
+2
-2
ee/spec/frontend/oncall_schedule/schedule/components/shifts/components/weeks_schedule_shift_spec.js
...components/shifts/components/weeks_schedule_shift_spec.js
+2
-2
ee/spec/frontend/oncall_schedule/schedule/mixins/common_mixin_spec.js
...tend/oncall_schedule/schedule/mixins/common_mixin_spec.js
+19
-0
spec/frontend/lib/utils/datetime_utility_spec.js
spec/frontend/lib/utils/datetime_utility_spec.js
+61
-8
No files found.
app/assets/javascripts/lib/utils/datetime_utility.js
View file @
a2db3609
...
@@ -6,6 +6,7 @@ import { languageCode, s__, __, n__ } from '../../locale';
...
@@ -6,6 +6,7 @@ import { languageCode, s__, __, n__ } from '../../locale';
const
MILLISECONDS_IN_HOUR
=
60
*
60
*
1000
;
const
MILLISECONDS_IN_HOUR
=
60
*
60
*
1000
;
const
MILLISECONDS_IN_DAY
=
24
*
MILLISECONDS_IN_HOUR
;
const
MILLISECONDS_IN_DAY
=
24
*
MILLISECONDS_IN_HOUR
;
const
DAYS_IN_WEEK
=
7
;
window
.
timeago
=
timeago
;
window
.
timeago
=
timeago
;
...
@@ -693,6 +694,25 @@ export const nDaysAfter = (date, numberOfDays) =>
...
@@ -693,6 +694,25 @@ export const nDaysAfter = (date, numberOfDays) =>
*/
*/
export
const
nDaysBefore
=
(
date
,
numberOfDays
)
=>
nDaysAfter
(
date
,
-
numberOfDays
);
export
const
nDaysBefore
=
(
date
,
numberOfDays
)
=>
nDaysAfter
(
date
,
-
numberOfDays
);
/**
* Returns the date n weeks after the date provided
*
* @param {Date} date the initial date
* @param {Number} numberOfWeeks number of weeks after
* @return {Date} the date following the date provided
*/
export
const
nWeeksAfter
=
(
date
,
numberOfWeeks
)
=>
new
Date
(
newDate
(
date
)).
setDate
(
date
.
getDate
()
+
DAYS_IN_WEEK
*
numberOfWeeks
);
/**
* Returns the date n weeks before the date provided
*
* @param {Date} date the initial date
* @param {Number} numberOfWeeks number of weeks before
* @return {Date} the date following the date provided
*/
export
const
nWeeksBefore
=
(
date
,
numberOfWeeks
)
=>
nWeeksAfter
(
date
,
-
numberOfWeeks
);
/**
/**
* Returns the date n months after the date provided
* Returns the date n months after the date provided
*
*
...
@@ -897,3 +917,19 @@ export const getOverlapDateInPeriods = (givenPeriodLeft = {}, givenPeriodRight =
...
@@ -897,3 +917,19 @@ export const getOverlapDateInPeriods = (givenPeriodLeft = {}, givenPeriodRight =
overlapEndDate
,
overlapEndDate
,
};
};
};
};
/**
* A utility function that checks that the date is today
*
* @param {Date} date
*
* @return {Boolean} true if provided date is today
*/
export
const
isToday
=
(
date
)
=>
{
const
today
=
new
Date
();
return
(
date
.
getDate
()
===
today
.
getDate
()
&&
date
.
getMonth
()
===
today
.
getMonth
()
&&
date
.
getFullYear
()
===
today
.
getFullYear
()
);
};
ee/app/assets/javascripts/oncall_schedules/components/oncall_schedule.vue
View file @
a2db3609
...
@@ -10,15 +10,24 @@ import {
...
@@ -10,15 +10,24 @@ import {
GlTooltipDirective
,
GlTooltipDirective
,
}
from
'
@gitlab/ui
'
;
}
from
'
@gitlab/ui
'
;
import
{
capitalize
}
from
'
lodash
'
;
import
{
capitalize
}
from
'
lodash
'
;
import
{
formatDate
}
from
'
~/lib/utils/datetime_utility
'
;
import
{
s__
,
__
}
from
'
~/locale
'
;
import
{
s__
,
__
}
from
'
~/locale
'
;
import
{
addRotationModalId
,
editRotationModalId
,
PRESET_TYPES
}
from
'
../constants
'
;
import
*
as
Sentry
from
'
~/sentry/wrapper
'
;
import
{
fetchPolicies
}
from
'
~/lib/graphql
'
;
import
{
formatDate
,
nWeeksBefore
,
nWeeksAfter
,
nDaysBefore
,
nDaysAfter
,
}
from
'
~/lib/utils/datetime_utility
'
;
import
ScheduleTimelineSection
from
'
./schedule/components/schedule_timeline_section.vue
'
;
import
ScheduleTimelineSection
from
'
./schedule/components/schedule_timeline_section.vue
'
;
import
DeleteScheduleModal
from
'
./delete_schedule_modal.vue
'
;
import
DeleteScheduleModal
from
'
./delete_schedule_modal.vue
'
;
import
EditScheduleModal
from
'
./add_edit_schedule_modal.vue
'
;
import
EditScheduleModal
from
'
./add_edit_schedule_modal.vue
'
;
import
AddEditRotationModal
from
'
./rotations/components/add_edit_rotation_modal.vue
'
;
import
AddEditRotationModal
from
'
./rotations/components/add_edit_rotation_modal.vue
'
;
import
RotationsListSection
from
'
./schedule/components/rotations_list_section.vue
'
;
import
RotationsListSection
from
'
./schedule/components/rotations_list_section.vue
'
;
import
{
getTimeframeForWeeksView
}
from
'
./schedule/utils
'
;
import
{
getTimeframeForWeeksView
}
from
'
./schedule/utils
'
;
import
{
addRotationModalId
,
editRotationModalId
,
PRESET_TYPES
}
from
'
../constants
'
;
import
getShiftsForRotations
from
'
../graphql/queries/get_oncall_schedules_with_rotations_shifts.query.graphql
'
;
export
const
i18n
=
{
export
const
i18n
=
{
scheduleForTz
:
s__
(
'
OnCallSchedules|On-call schedule for the %{timezone}
'
),
scheduleForTz
:
s__
(
'
OnCallSchedules|On-call schedule for the %{timezone}
'
),
...
@@ -54,21 +63,42 @@ export default {
...
@@ -54,21 +63,42 @@ export default {
GlModal
:
GlModalDirective
,
GlModal
:
GlModalDirective
,
GlTooltip
:
GlTooltipDirective
,
GlTooltip
:
GlTooltipDirective
,
},
},
inject
:
[
'
timezones
'
],
inject
:
[
'
projectPath
'
,
'
timezones
'
],
props
:
{
props
:
{
schedule
:
{
schedule
:
{
type
:
Object
,
type
:
Object
,
required
:
true
,
required
:
true
,
},
},
},
apollo
:
{
rotations
:
{
rotations
:
{
type
:
Array
,
fetchPolicy
:
fetchPolicies
.
CACHE_AND_NETWORK
,
required
:
false
,
query
:
getShiftsForRotations
,
default
:
()
=>
[],
variables
()
{
const
startsAt
=
this
.
timeframeStartDate
;
const
endsAt
=
new
Date
(
nWeeksAfter
(
startsAt
,
2
));
return
{
projectPath
:
this
.
projectPath
,
startsAt
,
endsAt
,
};
},
update
(
data
)
{
const
nodes
=
data
.
project
?.
incidentManagementOncallSchedules
?.
nodes
??
[];
const
schedule
=
nodes
.
pop
()
||
{};
return
schedule
?.
rotations
.
nodes
??
[];
},
error
(
error
)
{
Sentry
.
captureException
(
error
);
},
},
},
},
},
data
()
{
data
()
{
return
{
return
{
presetType
:
this
.
$options
.
PRESET_TYPES
.
WEEKS
,
presetType
:
this
.
$options
.
PRESET_TYPES
.
WEEKS
,
timeframeStartDate
:
new
Date
(),
rotations
:
this
.
schedule
.
rotations
.
nodes
,
};
};
},
},
computed
:
{
computed
:
{
...
@@ -77,25 +107,62 @@ export default {
...
@@ -77,25 +107,62 @@ export default {
return
__
(
`(UTC
${
selectedTz
.
formatted_offset
}
)`
);
return
__
(
`(UTC
${
selectedTz
.
formatted_offset
}
)`
);
},
},
timeframe
()
{
timeframe
()
{
return
getTimeframeForWeeksView
();
return
getTimeframeForWeeksView
(
this
.
timeframeStartDate
);
},
},
scheduleRange
()
{
scheduleRange
()
{
const
end
=
switch
(
this
.
presetType
)
{
this
.
presetType
===
this
.
$options
.
PRESET_TYPES
.
DAYS
case
PRESET_TYPES
.
DAYS
:
?
this
.
timeframe
[
0
]
return
formatDate
(
this
.
timeframe
[
0
],
'
mmmm d, yyyy
'
);
:
this
.
timeframe
[
this
.
timeframe
.
length
-
1
];
case
PRESET_TYPES
.
WEEKS
:
{
const
range
=
{
start
:
this
.
timeframe
[
0
],
end
};
const
firstDayOfTheLastWeek
=
this
.
timeframe
[
this
.
timeframe
.
length
-
1
];
const
firstDayOfTheNextTimeframe
=
nWeeksAfter
(
firstDayOfTheLastWeek
,
1
);
const
lastDayOfTimeframe
=
nDaysBefore
(
new
Date
(
firstDayOfTheNextTimeframe
),
1
);
return
`
${
formatDate
(
range
.
start
,
'
mmmm d
'
)}
-
${
formatDate
(
range
.
end
,
'
mmmm d, yyyy
'
)}
`
;
return
`
${
formatDate
(
this
.
timeframe
[
0
],
'
mmmm d
'
)}
-
${
formatDate
(
lastDayOfTimeframe
,
'
mmmm d, yyyy
'
,
)}
`
;
}
default
:
return
''
;
}
},
isLoading
()
{
return
this
.
$apollo
.
queries
.
rotations
.
loading
;
},
},
},
},
methods
:
{
methods
:
{
s
et
PresetType
(
type
)
{
s
witch
PresetType
(
type
)
{
this
.
presetType
=
type
;
this
.
presetType
=
type
;
this
.
timeframeStartDate
=
new
Date
();
},
},
formatPresetType
(
type
)
{
formatPresetType
(
type
)
{
return
capitalize
(
type
);
return
capitalize
(
type
);
},
},
updateToViewPreviousTimeframe
()
{
switch
(
this
.
presetType
)
{
case
PRESET_TYPES
.
DAYS
:
this
.
timeframeStartDate
=
new
Date
(
nDaysBefore
(
this
.
timeframeStartDate
,
1
));
break
;
case
PRESET_TYPES
.
WEEKS
:
this
.
timeframeStartDate
=
new
Date
(
nWeeksBefore
(
this
.
timeframeStartDate
,
2
));
break
;
default
:
break
;
}
},
updateToViewNextTimeframe
()
{
switch
(
this
.
presetType
)
{
case
PRESET_TYPES
.
DAYS
:
this
.
timeframeStartDate
=
new
Date
(
nDaysAfter
(
this
.
timeframeStartDate
,
1
));
break
;
case
PRESET_TYPES
.
WEEKS
:
this
.
timeframeStartDate
=
new
Date
(
nWeeksAfter
(
this
.
timeframeStartDate
,
2
));
break
;
default
:
break
;
}
},
},
},
};
};
</
script
>
</
script
>
...
@@ -141,15 +208,25 @@ export default {
...
@@ -141,15 +208,25 @@ export default {
:key=
"type"
:key=
"type"
:is-check-item=
"true"
:is-check-item=
"true"
:is-checked=
"type === presetType"
:is-checked=
"type === presetType"
@
click=
"s
et
PresetType(type)"
@
click=
"s
witch
PresetType(type)"
>
{{ formatPresetType(type) }}
</gl-dropdown-item
>
{{ formatPresetType(type) }}
</gl-dropdown-item
>
>
</gl-dropdown>
</gl-dropdown>
</p>
</p>
<div
class=
"gl-w-full gl-display-flex gl-align-items-center gl-pb-3"
>
<div
class=
"gl-w-full gl-display-flex gl-align-items-center gl-pb-3"
>
<gl-button-group>
<gl-button-group>
<gl-button
icon=
"chevron-left"
/>
<gl-button
<gl-button
icon=
"chevron-right"
/>
data-testid=
"previous-timeframe-btn"
icon=
"chevron-left"
:disabled=
"isLoading"
@
click=
"updateToViewPreviousTimeframe"
/>
<gl-button
data-testid=
"next-timeframe-btn"
icon=
"chevron-right"
:disabled=
"isLoading"
@
click=
"updateToViewNextTimeframe"
/>
</gl-button-group>
</gl-button-group>
<p
class=
"gl-ml-3 gl-mb-0"
>
{{ scheduleRange }}
</p>
<p
class=
"gl-ml-3 gl-mb-0"
>
{{ scheduleRange }}
</p>
</div>
</div>
...
...
ee/app/assets/javascripts/oncall_schedules/components/oncall_schedules_wrapper.vue
View file @
a2db3609
...
@@ -3,10 +3,9 @@ import { GlAlert, GlButton, GlEmptyState, GlLoadingIcon, GlModalDirective } from
...
@@ -3,10 +3,9 @@ import { GlAlert, GlButton, GlEmptyState, GlLoadingIcon, GlModalDirective } from
import
*
as
Sentry
from
'
~/sentry/wrapper
'
;
import
*
as
Sentry
from
'
~/sentry/wrapper
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
fetchPolicies
}
from
'
~/lib/graphql
'
;
import
{
fetchPolicies
}
from
'
~/lib/graphql
'
;
import
mockRotations
from
'
../../../../../spec/frontend/oncall_schedule/mocks/mock_rotation.json
'
;
import
getOncallSchedulesQuery
from
'
../graphql/queries/get_oncall_schedules.query.graphql
'
;
import
AddScheduleModal
from
'
./add_edit_schedule_modal.vue
'
;
import
AddScheduleModal
from
'
./add_edit_schedule_modal.vue
'
;
import
OncallSchedule
from
'
./oncall_schedule.vue
'
;
import
OncallSchedule
from
'
./oncall_schedule.vue
'
;
import
getOncallSchedulesWithRotations
from
'
../graphql/queries/get_oncall_schedules.query.graphql
'
;
export
const
addScheduleModalId
=
'
addScheduleModal
'
;
export
const
addScheduleModalId
=
'
addScheduleModal
'
;
...
@@ -26,7 +25,6 @@ export const i18n = {
...
@@ -26,7 +25,6 @@ export const i18n = {
};
};
export
default
{
export
default
{
mockRotations
,
i18n
,
i18n
,
addScheduleModalId
,
addScheduleModalId
,
components
:
{
components
:
{
...
@@ -50,7 +48,7 @@ export default {
...
@@ -50,7 +48,7 @@ export default {
apollo
:
{
apollo
:
{
schedule
:
{
schedule
:
{
fetchPolicy
:
fetchPolicies
.
CACHE_AND_NETWORK
,
fetchPolicy
:
fetchPolicies
.
CACHE_AND_NETWORK
,
query
:
getOncallSchedules
Query
,
query
:
getOncallSchedules
WithRotations
,
variables
()
{
variables
()
{
return
{
return
{
projectPath
:
this
.
projectPath
,
projectPath
:
this
.
projectPath
,
...
@@ -88,7 +86,7 @@ export default {
...
@@ -88,7 +86,7 @@ export default {
>
>
{{
$options
.
i18n
.
successNotification
.
description
}}
{{
$options
.
i18n
.
successNotification
.
description
}}
</gl-alert>
</gl-alert>
<oncall-schedule
:schedule=
"schedule"
:rotations=
"$options.mockRotations"
/>
<oncall-schedule
:schedule=
"schedule"
/>
</
template
>
</
template
>
<gl-empty-state
<gl-empty-state
...
...
ee/app/assets/javascripts/oncall_schedules/components/rotations/components/rotation_assignee.vue
View file @
a2db3609
...
@@ -51,7 +51,7 @@ export default {
...
@@ -51,7 +51,7 @@ export default {
:style=
"rotationAssigneeStyle"
:style=
"rotationAssigneeStyle"
>
>
<gl-token
<gl-token
:id=
"assignee.id"
:id=
"assignee.
user.
id"
class=
"gl-w-full gl-h-6 gl-align-items-center"
class=
"gl-w-full gl-h-6 gl-align-items-center"
:class=
"chevronClass"
:class=
"chevronClass"
:view-only=
"true"
:view-only=
"true"
...
@@ -65,7 +65,7 @@ export default {
...
@@ -65,7 +65,7 @@ export default {
/>
/>
</gl-token>
</gl-token>
<gl-popover
<gl-popover
:target=
"assignee.id"
:target=
"assignee.
user.
id"
:title=
"assignee.user.username"
:title=
"assignee.user.username"
triggers=
"hover"
triggers=
"hover"
placement=
"top"
placement=
"top"
...
...
ee/app/assets/javascripts/oncall_schedules/components/schedule/components/current_day_indicator.vue
View file @
a2db3609
<
script
>
<
script
>
import
CommonMixin
from
'
../../../mixins/common_mixin
'
;
import
CommonMixin
from
'
../../../mixins/common_mixin
'
;
import
{
PRESET_TYPES
}
from
'
../../../constants
'
;
export
default
{
export
default
{
mixins
:
[
CommonMixin
],
mixins
:
[
CommonMixin
],
...
@@ -13,12 +14,24 @@ export default {
...
@@ -13,12 +14,24 @@ export default {
required
:
true
,
required
:
true
,
},
},
},
},
computed
:
{
isVisible
()
{
switch
(
this
.
presetType
)
{
case
PRESET_TYPES
.
WEEKS
:
return
this
.
hasToday
;
case
PRESET_TYPES
.
DAYS
:
return
this
.
isToday
;
default
:
return
false
;
}
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
<span
<span
v-if=
"
hasToday
"
v-if=
"
isVisible
"
:style=
"getIndicatorStyles(presetType)"
:style=
"getIndicatorStyles(presetType)"
data-testid=
"current-day-indicator"
data-testid=
"current-day-indicator"
class=
"current-day-indicator"
class=
"current-day-indicator"
...
...
ee/app/assets/javascripts/oncall_schedules/components/schedule/components/preset_days/days_header_item.vue
View file @
a2db3609
...
@@ -32,6 +32,6 @@ export default {
...
@@ -32,6 +32,6 @@ export default {
<div
class=
"item-label gl-pl-6 gl-py-4"
data-testid=
"timeline-header-label"
>
<div
class=
"item-label gl-pl-6 gl-py-4"
data-testid=
"timeline-header-label"
>
{{
timelineHeaderLabel
}}
{{
timelineHeaderLabel
}}
</div>
</div>
<days-header-sub-item
/>
<days-header-sub-item
:timeframe-item=
"timeframeItem"
/>
</span>
</span>
</
template
>
</
template
>
ee/app/assets/javascripts/oncall_schedules/components/schedule/components/preset_days/days_header_sub_item.vue
View file @
a2db3609
...
@@ -11,6 +11,12 @@ export default {
...
@@ -11,6 +11,12 @@ export default {
GlResizeObserver
:
GlResizeObserverDirective
,
GlResizeObserver
:
GlResizeObserverDirective
,
},
},
mixins
:
[
CommonMixin
],
mixins
:
[
CommonMixin
],
props
:
{
timeframeItem
:
{
type
:
Date
,
required
:
true
,
},
},
mounted
()
{
mounted
()
{
this
.
updateShiftStyles
();
this
.
updateShiftStyles
();
},
},
...
@@ -42,6 +48,7 @@ export default {
...
@@ -42,6 +48,7 @@ export default {
>
{{
hour
}}
</span
>
{{
hour
}}
</span
>
>
<span
<span
v-if=
"isToday"
:style=
"getIndicatorStyles($options.PRESET_TYPES.DAYS)"
:style=
"getIndicatorStyles($options.PRESET_TYPES.DAYS)"
class=
"current-day-indicator-header preset-days"
class=
"current-day-indicator-header preset-days"
data-testid=
"day-item-sublabel-current-indicator"
data-testid=
"day-item-sublabel-current-indicator"
...
...
ee/app/assets/javascripts/oncall_schedules/components/schedule/components/rotations_list_section.vue
View file @
a2db3609
...
@@ -125,6 +125,7 @@ export default {
...
@@ -125,6 +125,7 @@ export default {
>
>
<current-day-indicator
:preset-type=
"presetType"
:timeframe-item=
"timeframeItem"
/>
<current-day-indicator
:preset-type=
"presetType"
:timeframe-item=
"timeframeItem"
/>
<schedule-shift-wrapper
<schedule-shift-wrapper
v-if=
"rotation.shifts"
:preset-type=
"presetType"
:preset-type=
"presetType"
:timeframe-item=
"timeframeItem"
:timeframe-item=
"timeframeItem"
:timeframe=
"timeframe"
:timeframe=
"timeframe"
...
@@ -134,8 +135,8 @@ export default {
...
@@ -134,8 +135,8 @@ export default {
</div>
</div>
<delete-rotation-modal
<delete-rotation-modal
:rotation=
"rotationToUpdate"
:rotation=
"rotationToUpdate"
:modal-id=
"$options.deleteRotationModalId"
:schedule-iid=
"scheduleIid"
:schedule-iid=
"scheduleIid"
:modal-id=
"$options.deleteRotationModalId"
@
set-rotation-to-update=
"setRotationToUpdate"
@
set-rotation-to-update=
"setRotationToUpdate"
/>
/>
</div>
</div>
...
...
ee/app/assets/javascripts/oncall_schedules/components/schedule/components/shifts/components/days_schedule_shift.vue
View file @
a2db3609
<
script
>
<
script
>
import
RotationAssignee
from
'
ee/oncall_schedules/components/rotations/components/rotation_assignee.vue
'
;
import
RotationAssignee
from
'
ee/oncall_schedules/components/rotations/components/rotation_assignee.vue
'
;
import
{
HOURS_IN_DAY
,
ASSIGNEE_SPACER
}
from
'
ee/oncall_schedules/constants
'
;
import
{
HOURS_IN_DAY
,
ASSIGNEE_SPACER
}
from
'
ee/oncall_schedules/constants
'
;
import
{
getOverlapDateInPeriods
}
from
'
~/lib/utils/datetime_utility
'
;
import
{
getOverlapDateInPeriods
,
nDaysAfter
}
from
'
~/lib/utils/datetime_utility
'
;
import
{
incrementDateByDays
}
from
'
../../../utils
'
;
export
default
{
export
default
{
components
:
{
components
:
{
...
@@ -36,7 +35,7 @@ export default {
...
@@ -36,7 +35,7 @@ export default {
},
},
computed
:
{
computed
:
{
currentTimeframeEndsAt
()
{
currentTimeframeEndsAt
()
{
return
incrementDateByDays
(
this
.
timeframeItem
,
1
);
return
new
Date
(
nDaysAfter
(
this
.
timeframeItem
,
1
)
);
},
},
hoursUntilEndOfTimeFrame
()
{
hoursUntilEndOfTimeFrame
()
{
return
HOURS_IN_DAY
-
new
Date
(
this
.
shiftRangeOverlap
.
overlapStartDate
).
getHours
();
return
HOURS_IN_DAY
-
new
Date
(
this
.
shiftRangeOverlap
.
overlapStartDate
).
getHours
();
...
...
ee/app/assets/javascripts/oncall_schedules/components/schedule/components/shifts/components/weeks_schedule_shift.vue
View file @
a2db3609
<
script
>
<
script
>
import
RotationAssignee
from
'
ee/oncall_schedules/components/rotations/components/rotation_assignee.vue
'
;
import
RotationAssignee
from
'
ee/oncall_schedules/components/rotations/components/rotation_assignee.vue
'
;
import
{
DAYS_IN_WEEK
,
DAYS_IN_DATE_WEEK
,
ASSIGNEE_SPACER
}
from
'
ee/oncall_schedules/constants
'
;
import
{
DAYS_IN_WEEK
,
DAYS_IN_DATE_WEEK
,
ASSIGNEE_SPACER
}
from
'
ee/oncall_schedules/constants
'
;
import
{
getOverlapDateInPeriods
}
from
'
~/lib/utils/datetime_utility
'
;
import
{
getOverlapDateInPeriods
,
nDaysAfter
}
from
'
~/lib/utils/datetime_utility
'
;
import
{
incrementDateByDays
}
from
'
../../../utils
'
;
export
default
{
export
default
{
components
:
{
components
:
{
...
@@ -36,7 +35,7 @@ export default {
...
@@ -36,7 +35,7 @@ export default {
},
},
computed
:
{
computed
:
{
currentTimeframeEndsAt
()
{
currentTimeframeEndsAt
()
{
return
incrementDateByDays
(
this
.
timeframeItem
,
DAYS_IN_DATE_WEEK
);
return
new
Date
(
nDaysAfter
(
this
.
timeframeItem
,
DAYS_IN_DATE_WEEK
)
);
},
},
daysUntilEndOfTimeFrame
()
{
daysUntilEndOfTimeFrame
()
{
return
(
return
(
...
@@ -49,18 +48,18 @@ export default {
...
@@ -49,18 +48,18 @@ export default {
const
startDate
=
this
.
shiftStartsAt
.
getDay
();
const
startDate
=
this
.
shiftStartsAt
.
getDay
();
const
firstDayOfWeek
=
this
.
timeframeItem
.
getDay
();
const
firstDayOfWeek
=
this
.
timeframeItem
.
getDay
();
const
isFirstCell
=
startDate
===
firstDayOfWeek
;
const
isFirstCell
=
startDate
===
firstDayOfWeek
;
const
left
=
let
left
=
0
;
isFirstCell
||
this
.
shiftStartDateOutOfRange
?
'
0px
'
if
(
!
(
isFirstCell
||
this
.
shiftStartDateOutOfRange
))
{
:
`
${
left
=
(
DAYS_IN_WEEK
-
this
.
daysUntilEndOfTimeFrame
)
*
this
.
shiftTimeUnitWidth
+
(
DAYS_IN_WEEK
-
this
.
daysUntilEndOfTimeFrame
)
*
this
.
shiftTimeUnitWidth
+
ASSIGNEE_SPACER
;
ASSIGNEE_SPACER
}
}
px`
;
const
width
=
`
${
this
.
shiftTimeUnitWidth
*
this
.
shiftWidth
}
px`
;
const
width
=
this
.
shiftTimeUnitWidth
*
this
.
shiftWidth
;
return
{
return
{
left
,
left
:
`
${
left
}
px`
,
width
,
width
:
`
${
width
}
px`
,
};
};
},
},
shiftStartsAt
()
{
shiftStartsAt
()
{
...
@@ -111,7 +110,7 @@ export default {
...
@@ -111,7 +110,7 @@ export default {
return
getOverlapDateInPeriods
(
return
getOverlapDateInPeriods
(
{
{
start
:
this
.
timeframeItem
,
start
:
this
.
timeframeItem
,
end
:
incrementDateByDays
(
this
.
timeFrameEndsAt
,
DAYS_IN_DATE_WEEK
),
end
:
nDaysAfter
(
this
.
timeFrameEndsAt
,
DAYS_IN_DATE_WEEK
),
},
},
{
start
:
this
.
shiftStartsAt
,
end
:
this
.
shiftEndsAt
},
{
start
:
this
.
shiftStartsAt
,
end
:
this
.
shiftEndsAt
},
);
);
...
...
ee/app/assets/javascripts/oncall_schedules/components/schedule/utils.js
View file @
a2db3609
...
@@ -32,18 +32,3 @@ export const getTimeframeForWeeksView = (initialDate = new Date()) => {
...
@@ -32,18 +32,3 @@ export const getTimeframeForWeeksView = (initialDate = new Date()) => {
return
timeframe
;
return
timeframe
;
};
};
/**
* A utility function which extends a given date value by a certain amount of days.
*
* @param {Date} initial - the initial date to extend.
* @param {Number} increment - the amount of days to extend by.
* @returns {Date}
*
* @example
* incrementDateByDays(new Date(2021, 0, 10), 6) => new Date(2021, 0, 16)
*
*/
export
const
incrementDateByDays
=
(
initial
,
increment
)
=>
{
return
new
Date
(
new
Date
().
setDate
(
initial
.
getDate
()
+
increment
));
};
ee/app/assets/javascripts/oncall_schedules/graphql/fragments/oncall_schedule_participant.fragment.graphql
0 → 100644
View file @
a2db3609
fragment
OnCallParticipant
on
OncallParticipantType
{
user
{
id
username
avatarUrl
}
colorWeight
colorPalette
}
ee/app/assets/javascripts/oncall_schedules/graphql/fragments/oncall_schedule_rotation.fragment.graphql
View file @
a2db3609
#import "../fragments/oncall_schedule_participant.fragment.graphql"
fragment
OnCallRotation
on
IncidentManagementOncallRotation
{
fragment
OnCallRotation
on
IncidentManagementOncallRotation
{
id
id
name
name
...
@@ -6,12 +8,7 @@ fragment OnCallRotation on IncidentManagementOncallRotation {
...
@@ -6,12 +8,7 @@ fragment OnCallRotation on IncidentManagementOncallRotation {
lengthUnit
lengthUnit
participants
{
participants
{
nodes
{
nodes
{
user
{
...
OnCallParticipant
id
username
}
colorWeight
colorPalette
}
}
}
}
}
}
ee/app/assets/javascripts/oncall_schedules/graphql/fragments/oncall_schedule_rotation_with_shifts.fragment.graphql
0 → 100644
View file @
a2db3609
#import "../fragments/oncall_schedule_rotation.fragment.graphql"
fragment
OnCallRotationWithShifts
on
IncidentManagementOncallRotation
{
...
OnCallRotation
shifts
(
startTime
:
$startsAt
,
endTime
:
$endsAt
)
{
nodes
{
participant
{
...
OnCallParticipant
}
endsAt
startsAt
}
}
}
ee/app/assets/javascripts/oncall_schedules/graphql/queries/get_oncall_schedules.query.graphql
View file @
a2db3609
query
getOncallSchedules
(
$projectPath
:
ID
!)
{
#import "../fragments/oncall_schedule_rotation.fragment.graphql"
query
getOncallSchedulesWithRotations
(
$projectPath
:
ID
!)
{
project
(
fullPath
:
$projectPath
)
{
project
(
fullPath
:
$projectPath
)
{
incidentManagementOncallSchedules
{
incidentManagementOncallSchedules
{
nodes
{
nodes
{
...
@@ -6,6 +8,11 @@ query getOncallSchedules($projectPath: ID!) {
...
@@ -6,6 +8,11 @@ query getOncallSchedules($projectPath: ID!) {
name
name
description
description
timezone
timezone
rotations
{
nodes
{
...
OnCallRotation
}
}
}
}
}
}
}
}
...
...
ee/app/assets/javascripts/oncall_schedules/graphql/queries/get_oncall_schedules_with_rotations_shifts.query.graphql
0 → 100644
View file @
a2db3609
#import "../fragments/oncall_schedule_rotation_with_shifts.fragment.graphql"
query
getShiftsForRotations
(
$projectPath
:
ID
!,
$startsAt
:
Time
!,
$endsAt
:
Time
!)
{
project
(
fullPath
:
$projectPath
)
{
incidentManagementOncallSchedules
{
nodes
{
rotations
{
nodes
{
...
OnCallRotationWithShifts
}
}
}
}
}
}
ee/app/assets/javascripts/oncall_schedules/mixins/common_mixin.js
View file @
a2db3609
import
{
DAYS_IN_WEEK
,
HOURS_IN_DAY
,
PRESET_TYPES
}
from
'
../constants
'
;
import
{
DAYS_IN_WEEK
,
HOURS_IN_DAY
,
PRESET_TYPES
}
from
'
../constants
'
;
import
{
isToday
}
from
'
~/lib/utils/datetime_utility
'
;
export
default
{
export
default
{
currentDate
:
null
,
currentDate
:
null
,
...
@@ -21,6 +22,9 @@ export default {
...
@@ -21,6 +22,9 @@ export default {
this
.
$options
.
currentDate
.
getTime
()
<=
headerSubItems
[
headerSubItems
.
length
-
1
].
getTime
()
this
.
$options
.
currentDate
.
getTime
()
<=
headerSubItems
[
headerSubItems
.
length
-
1
].
getTime
()
);
);
},
},
isToday
()
{
return
isToday
(
this
.
timeframeItem
);
},
},
},
beforeCreate
()
{
beforeCreate
()
{
const
currentDate
=
new
Date
();
const
currentDate
=
new
Date
();
...
...
ee/spec/frontend/oncall_schedule/mocks/apollo_mock.js
View file @
a2db3609
import
mockRotations
from
'
./mock_rotation.json
'
;
import
mockRotations
from
'
./mock_rotation.json
'
;
import
invalidUrl
from
'
~/lib/utils/invalid_url
'
;
export
const
scheduleIid
=
'
37
'
;
export
const
scheduleIid
=
'
37
'
;
...
@@ -34,7 +35,7 @@ export const getOncallSchedulesQueryResponse = {
...
@@ -34,7 +35,7 @@ export const getOncallSchedulesQueryResponse = {
timezone
:
{
timezone
:
{
identifier
:
'
Pacific/Honolulu
'
,
identifier
:
'
Pacific/Honolulu
'
,
},
},
rotations
:
mockRotations
,
rotations
:
{
nodes
:
mockRotations
}
,
},
},
],
],
},
},
...
@@ -52,6 +53,9 @@ export const destroyScheduleResponse = {
...
@@ -52,6 +53,9 @@ export const destroyScheduleResponse = {
name
:
'
Test schedule
'
,
name
:
'
Test schedule
'
,
description
:
'
Description 1 lives here
'
,
description
:
'
Description 1 lives here
'
,
timezone
:
'
Pacific/Honolulu
'
,
timezone
:
'
Pacific/Honolulu
'
,
rotations
:
{
nodes
:
[],
},
},
},
},
},
},
},
...
@@ -67,6 +71,9 @@ export const destroyScheduleResponseWithErrors = {
...
@@ -67,6 +71,9 @@ export const destroyScheduleResponseWithErrors = {
name
:
'
Test schedule
'
,
name
:
'
Test schedule
'
,
description
:
'
Description 1 lives here
'
,
description
:
'
Description 1 lives here
'
,
timezone
:
'
Pacific/Honolulu
'
,
timezone
:
'
Pacific/Honolulu
'
,
rotations
:
{
nodes
:
[],
},
},
},
},
},
},
},
...
@@ -82,6 +89,9 @@ export const updateScheduleResponse = {
...
@@ -82,6 +89,9 @@ export const updateScheduleResponse = {
name
:
'
Test schedule 2
'
,
name
:
'
Test schedule 2
'
,
description
:
'
Description 2 lives here
'
,
description
:
'
Description 2 lives here
'
,
timezone
:
'
Pacific/Honolulu
'
,
timezone
:
'
Pacific/Honolulu
'
,
rotations
:
{
nodes
:
[],
},
},
},
},
},
},
},
...
@@ -97,6 +107,9 @@ export const updateScheduleResponseWithErrors = {
...
@@ -97,6 +107,9 @@ export const updateScheduleResponseWithErrors = {
name
:
'
Test schedule 2
'
,
name
:
'
Test schedule 2
'
,
description
:
'
Description 2 lives here
'
,
description
:
'
Description 2 lives here
'
,
timezone
:
'
Pacific/Honolulu
'
,
timezone
:
'
Pacific/Honolulu
'
,
rotations
:
{
nodes
:
[],
},
},
},
},
},
},
},
...
@@ -107,6 +120,9 @@ export const preExistingSchedule = {
...
@@ -107,6 +120,9 @@ export const preExistingSchedule = {
iid
:
'
1
'
,
iid
:
'
1
'
,
name
:
'
Monitor rotations
'
,
name
:
'
Monitor rotations
'
,
timezone
:
'
Pacific/Honolulu
'
,
timezone
:
'
Pacific/Honolulu
'
,
rotations
:
{
nodes
:
[],
},
};
};
export
const
newlyCreatedSchedule
=
{
export
const
newlyCreatedSchedule
=
{
...
@@ -114,6 +130,9 @@ export const newlyCreatedSchedule = {
...
@@ -114,6 +130,9 @@ export const newlyCreatedSchedule = {
iid
:
'
2
'
,
iid
:
'
2
'
,
name
:
'
S-Monitor rotations
'
,
name
:
'
S-Monitor rotations
'
,
timezone
:
'
Kyiv/EST
'
,
timezone
:
'
Kyiv/EST
'
,
rotations
:
{
nodes
:
[],
},
};
};
export
const
createRotationResponse
=
{
export
const
createRotationResponse
=
{
...
@@ -129,7 +148,12 @@ export const createRotationResponse = {
...
@@ -129,7 +148,12 @@ export const createRotationResponse = {
participants
:
{
participants
:
{
nodes
:
[
nodes
:
[
{
{
user
:
{
id
:
'
gid://gitlab/User/50
'
,
username
:
'
project_1_bot3
'
,
__typename
:
'
User
'
},
user
:
{
id
:
'
gid://gitlab/User/50
'
,
username
:
'
project_1_bot3
'
,
avatarUrl
:
invalidUrl
,
avatar__typename
:
'
User
'
,
},
colorWeight
:
'
500
'
,
colorWeight
:
'
500
'
,
colorPalette
:
'
blue
'
,
colorPalette
:
'
blue
'
,
__typename
:
'
OncallParticipantType
'
,
__typename
:
'
OncallParticipantType
'
,
...
@@ -157,7 +181,12 @@ export const createRotationResponseWithErrors = {
...
@@ -157,7 +181,12 @@ export const createRotationResponseWithErrors = {
participants
:
{
participants
:
{
nodes
:
[
nodes
:
[
{
{
user
:
{
id
:
'
gid://gitlab/User/50
'
,
username
:
'
project_1_bot3
'
,
__typename
:
'
User
'
},
user
:
{
id
:
'
gid://gitlab/User/50
'
,
username
:
'
project_1_bot3
'
,
avatarUrl
:
invalidUrl
,
__typename
:
'
User
'
,
},
colorWeight
:
'
500
'
,
colorWeight
:
'
500
'
,
colorPalette
:
'
blue
'
,
colorPalette
:
'
blue
'
,
__typename
:
'
OncallParticipantType
'
,
__typename
:
'
OncallParticipantType
'
,
...
...
ee/spec/frontend/oncall_schedule/mocks/mock_rotation.json
View file @
a2db3609
ee/spec/frontend/oncall_schedule/oncall_schedule_spec.js
View file @
a2db3609
...
@@ -8,21 +8,38 @@ import * as commonUtils from 'ee/oncall_schedules/utils/common_utils';
...
@@ -8,21 +8,38 @@ import * as commonUtils from 'ee/oncall_schedules/utils/common_utils';
import
{
PRESET_TYPES
}
from
'
ee/oncall_schedules/constants
'
;
import
{
PRESET_TYPES
}
from
'
ee/oncall_schedules/constants
'
;
import
{
extendedWrapper
}
from
'
helpers/vue_test_utils_helper
'
;
import
{
extendedWrapper
}
from
'
helpers/vue_test_utils_helper
'
;
import
mockTimezones
from
'
./mocks/mockTimezones.json
'
;
import
mockTimezones
from
'
./mocks/mockTimezones.json
'
;
import
*
as
dateTimeUtility
from
'
~/lib/utils/datetime_utility
'
;
describe
(
'
On-call schedule
'
,
()
=>
{
describe
(
'
On-call schedule
'
,
()
=>
{
let
wrapper
;
let
wrapper
;
const
lastTz
=
mockTimezones
[
mockTimezones
.
length
-
1
];
const
lastTz
=
mockTimezones
[
mockTimezones
.
length
-
1
];
const
mockRotations
=
[{
name
:
'
rotation1
'
},
{
name
:
'
rotation2
'
}];
const
mockSchedule
=
{
const
mockSchedule
=
{
description
:
'
monitor description
'
,
description
:
'
monitor description
'
,
iid
:
'
3
'
,
iid
:
'
3
'
,
name
:
'
monitor schedule
'
,
name
:
'
monitor schedule
'
,
timezone
:
lastTz
.
identifier
,
timezone
:
lastTz
.
identifier
,
rotations
:
{
nodes
:
mockRotations
,
},
};
};
const
mockWeeksTimeFrame
=
[
'
31 Dec 2020
'
,
'
7 Jan 2021
'
,
'
14 Jan 2021
'
];
const
projectPath
=
'
group/project
'
;
const
mockWeeksTimeFrame
=
[
new
Date
(
'
31 Dec 2020
'
),
new
Date
(
'
7 Jan 2021
'
),
new
Date
(
'
14 Jan 2021
'
),
];
const
formattedTimezone
=
'
(UTC-09:00) AKST Alaska
'
;
const
formattedTimezone
=
'
(UTC-09:00) AKST Alaska
'
;
function
createComponent
({
schedule
}
=
{})
{
function
createComponent
({
schedule
,
loading
}
=
{})
{
const
$apollo
=
{
queries
:
{
rotations
:
{
loading
,
},
},
};
wrapper
=
extendedWrapper
(
wrapper
=
extendedWrapper
(
shallowMount
(
OnCallSchedule
,
{
shallowMount
(
OnCallSchedule
,
{
propsData
:
{
propsData
:
{
...
@@ -30,11 +47,18 @@ describe('On-call schedule', () => {
...
@@ -30,11 +47,18 @@ describe('On-call schedule', () => {
},
},
provide
:
{
provide
:
{
timezones
:
mockTimezones
,
timezones
:
mockTimezones
,
projectPath
,
},
data
()
{
return
{
rotations
:
mockRotations
,
};
},
},
stubs
:
{
stubs
:
{
GlCard
,
GlCard
,
GlSprintf
,
GlSprintf
,
},
},
mocks
:
{
$apollo
},
}),
}),
);
);
}
}
...
@@ -56,6 +80,8 @@ describe('On-call schedule', () => {
...
@@ -56,6 +80,8 @@ describe('On-call schedule', () => {
const
findAddRotationsBtn
=
()
=>
findRotationsHeader
().
find
(
GlButton
);
const
findAddRotationsBtn
=
()
=>
findRotationsHeader
().
find
(
GlButton
);
const
findScheduleTimeline
=
()
=>
findRotations
().
find
(
ScheduleTimelineSection
);
const
findScheduleTimeline
=
()
=>
findRotations
().
find
(
ScheduleTimelineSection
);
const
findRotationsList
=
()
=>
findRotations
().
find
(
RotationsListSection
);
const
findRotationsList
=
()
=>
findRotations
().
find
(
RotationsListSection
);
const
findLoadPreviousTimeframeBtn
=
()
=>
wrapper
.
findByTestId
(
'
previous-timeframe-btn
'
);
const
findLoadNextTimeframeBtn
=
()
=>
wrapper
.
findByTestId
(
'
next-timeframe-btn
'
);
it
(
'
shows schedule title
'
,
()
=>
{
it
(
'
shows schedule title
'
,
()
=>
{
expect
(
findScheduleHeader
().
text
()).
toBe
(
mockSchedule
.
name
);
expect
(
findScheduleHeader
().
text
()).
toBe
(
mockSchedule
.
name
);
...
@@ -93,4 +119,49 @@ describe('On-call schedule', () => {
...
@@ -93,4 +119,49 @@ describe('On-call schedule', () => {
scheduleIid
:
mockSchedule
.
iid
,
scheduleIid
:
mockSchedule
.
iid
,
});
});
});
});
describe
(
'
Timeframe update
'
,
()
=>
{
describe
(
'
WEEKS view
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
.
setData
({
presetType
:
PRESET_TYPES
.
WEEKS
});
});
it
(
'
should load next timeframe
'
,
()
=>
{
const
mockDate
=
new
Date
(
'
2021/01/28
'
);
jest
.
spyOn
(
dateTimeUtility
,
'
nWeeksAfter
'
).
mockReturnValue
(
mockDate
);
findLoadNextTimeframeBtn
().
vm
.
$emit
(
'
click
'
);
expect
(
dateTimeUtility
.
nWeeksAfter
).
toHaveBeenCalledWith
(
expect
.
any
(
Date
),
2
);
expect
(
wrapper
.
vm
.
timeframeStartDate
).
toEqual
(
mockDate
);
});
it
(
'
should load previous timeframe
'
,
()
=>
{
const
mockDate
=
new
Date
(
'
2021/01/28
'
);
jest
.
spyOn
(
dateTimeUtility
,
'
nWeeksBefore
'
).
mockReturnValue
(
mockDate
);
findLoadPreviousTimeframeBtn
().
vm
.
$emit
(
'
click
'
);
expect
(
dateTimeUtility
.
nWeeksBefore
).
toHaveBeenCalledWith
(
expect
.
any
(
Date
),
2
);
expect
(
wrapper
.
vm
.
timeframeStartDate
).
toEqual
(
mockDate
);
});
});
describe
(
'
DAYS view
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
.
setData
({
presetType
:
PRESET_TYPES
.
DAYS
});
});
it
(
'
should load next timeframe
'
,
()
=>
{
const
mockDate
=
new
Date
(
'
2021/01/28
'
);
jest
.
spyOn
(
dateTimeUtility
,
'
nDaysAfter
'
).
mockReturnValue
(
mockDate
);
findLoadNextTimeframeBtn
().
vm
.
$emit
(
'
click
'
);
expect
(
dateTimeUtility
.
nDaysAfter
).
toHaveBeenCalledWith
(
expect
.
any
(
Date
),
1
);
expect
(
wrapper
.
vm
.
timeframeStartDate
).
toEqual
(
mockDate
);
});
it
(
'
should load previous timeframe
'
,
()
=>
{
const
mockDate
=
new
Date
(
'
2021/01/28
'
);
jest
.
spyOn
(
dateTimeUtility
,
'
nDaysBefore
'
).
mockReturnValue
(
mockDate
);
findLoadPreviousTimeframeBtn
().
vm
.
$emit
(
'
click
'
);
expect
(
dateTimeUtility
.
nDaysBefore
).
toHaveBeenCalledWith
(
expect
.
any
(
Date
),
1
);
expect
(
wrapper
.
vm
.
timeframeStartDate
).
toEqual
(
mockDate
);
});
});
});
});
});
ee/spec/frontend/oncall_schedule/oncall_schedule_wrapper_spec.js
View file @
a2db3609
import
{
createLocalVue
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
createLocalVue
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
GlEmptyState
,
GlLoadingIcon
,
GlAlert
}
from
'
@gitlab/ui
'
;
import
{
GlEmptyState
,
GlLoadingIcon
,
GlAlert
}
from
'
@gitlab/ui
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
OnCallScheduleWrapper
,
{
import
OnCallScheduleWrapper
,
{
i18n
,
i18n
,
}
from
'
ee/oncall_schedules/components/oncall_schedules_wrapper.vue
'
;
}
from
'
ee/oncall_schedules/components/oncall_schedules_wrapper.vue
'
;
import
OnCallSchedule
from
'
ee/oncall_schedules/components/oncall_schedule.vue
'
;
import
OnCallSchedule
from
'
ee/oncall_schedules/components/oncall_schedule.vue
'
;
import
AddScheduleModal
from
'
ee/oncall_schedules/components/add_edit_schedule_modal.vue
'
;
import
AddScheduleModal
from
'
ee/oncall_schedules/components/add_edit_schedule_modal.vue
'
;
import
createMockApollo
from
'
helpers/mock_apollo_helper
'
;
import
createMockApollo
from
'
helpers/mock_apollo_helper
'
;
import
getOncallSchedulesQuery
from
'
ee/oncall_schedules/graphql/queries/get_oncall_schedules.query.graphql
'
;
import
getOncallSchedulesWithRotations
from
'
ee/oncall_schedules/graphql/queries/get_oncall_schedules.query.graphql
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
{
preExistingSchedule
,
newlyCreatedSchedule
}
from
'
./mocks/apollo_mock
'
;
import
{
preExistingSchedule
,
newlyCreatedSchedule
}
from
'
./mocks/apollo_mock
'
;
const
localVue
=
createLocalVue
();
const
localVue
=
createLocalVue
();
...
@@ -43,7 +43,9 @@ describe('On-call schedule wrapper', () => {
...
@@ -43,7 +43,9 @@ describe('On-call schedule wrapper', () => {
let
getOncallSchedulesQuerySpy
;
let
getOncallSchedulesQuerySpy
;
function
mountComponentWithApollo
()
{
function
mountComponentWithApollo
()
{
const
fakeApollo
=
createMockApollo
([[
getOncallSchedulesQuery
,
getOncallSchedulesQuerySpy
]]);
const
fakeApollo
=
createMockApollo
([
[
getOncallSchedulesWithRotations
,
getOncallSchedulesQuerySpy
],
]);
localVue
.
use
(
VueApollo
);
localVue
.
use
(
VueApollo
);
wrapper
=
shallowMount
(
OnCallScheduleWrapper
,
{
wrapper
=
shallowMount
(
OnCallScheduleWrapper
,
{
...
@@ -128,7 +130,7 @@ describe('On-call schedule wrapper', () => {
...
@@ -128,7 +130,7 @@ describe('On-call schedule wrapper', () => {
});
});
});
});
it
(
'
should render newly create schedule
'
,
async
()
=>
{
it
(
'
should render newly create
d
schedule
'
,
async
()
=>
{
mountComponentWithApollo
();
mountComponentWithApollo
();
jest
.
runOnlyPendingTimers
();
jest
.
runOnlyPendingTimers
();
await
wrapper
.
vm
.
$nextTick
();
await
wrapper
.
vm
.
$nextTick
();
...
...
ee/spec/frontend/oncall_schedule/rotations/components/add_edit_rotation_modal_spec.js
View file @
a2db3609
...
@@ -168,7 +168,9 @@ describe('AddEditRotationModal', () => {
...
@@ -168,7 +168,9 @@ describe('AddEditRotationModal', () => {
expect
(
userSearchQueryHandler
).
toHaveBeenCalledWith
({
search
:
'
root
'
});
expect
(
userSearchQueryHandler
).
toHaveBeenCalledWith
({
search
:
'
root
'
});
});
});
it
(
'
calls a mutation with correct parameters and creates a rotation
'
,
async
()
=>
{
// Fix is coming in: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52773/
// eslint-disable-next-line jest/no-disabled-tests
it
.
skip
(
'
calls a mutation with correct parameters and creates a rotation
'
,
async
()
=>
{
createComponentWithApollo
();
createComponentWithApollo
();
await
createRotation
(
wrapper
);
await
createRotation
(
wrapper
);
...
@@ -182,7 +184,9 @@ describe('AddEditRotationModal', () => {
...
@@ -182,7 +184,9 @@ describe('AddEditRotationModal', () => {
});
});
});
});
it
(
'
displays alert if mutation had a recoverable error
'
,
async
()
=>
{
// Fix is coming in: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52773/
// eslint-disable-next-line jest/no-disabled-tests
it
.
skip
(
'
displays alert if mutation had a recoverable error
'
,
async
()
=>
{
createComponentWithApollo
({
createComponentWithApollo
({
createHandler
:
jest
.
fn
().
mockResolvedValue
(
createRotationResponseWithErrors
),
createHandler
:
jest
.
fn
().
mockResolvedValue
(
createRotationResponseWithErrors
),
});
});
...
...
ee/spec/frontend/oncall_schedule/rotations/components/delete_rotation_modal_spec.js
View file @
a2db3609
...
@@ -161,7 +161,9 @@ describe('DeleteRotationModal', () => {
...
@@ -161,7 +161,9 @@ describe('DeleteRotationModal', () => {
expect
(
findModal
().
attributes
(
'
data-testid
'
)).
toBe
(
`delete-rotation-modal-
${
rotation
.
id
}
`
);
expect
(
findModal
().
attributes
(
'
data-testid
'
)).
toBe
(
`delete-rotation-modal-
${
rotation
.
id
}
`
);
});
});
it
(
'
calls a mutation with correct parameters and destroys a rotation
'
,
async
()
=>
{
// Fix is coming in: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52773/
// eslint-disable-next-line jest/no-disabled-tests
it
.
skip
(
'
calls a mutation with correct parameters and destroys a rotation
'
,
async
()
=>
{
createComponentWithApollo
();
createComponentWithApollo
();
await
destroyRotation
(
wrapper
);
await
destroyRotation
(
wrapper
);
...
@@ -169,7 +171,9 @@ describe('DeleteRotationModal', () => {
...
@@ -169,7 +171,9 @@ describe('DeleteRotationModal', () => {
expect
(
destroyRotationHandler
).
toHaveBeenCalled
();
expect
(
destroyRotationHandler
).
toHaveBeenCalled
();
});
});
it
(
'
displays alert if mutation had a recoverable error
'
,
async
()
=>
{
// Fix is coming in: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52773/
// eslint-disable-next-line jest/no-disabled-tests
it
.
skip
(
'
displays alert if mutation had a recoverable error
'
,
async
()
=>
{
createComponentWithApollo
({
createComponentWithApollo
({
destroyHandler
:
jest
.
fn
().
mockResolvedValue
(
destroyRotationResponseWithErrors
),
destroyHandler
:
jest
.
fn
().
mockResolvedValue
(
destroyRotationResponseWithErrors
),
});
});
...
...
ee/spec/frontend/oncall_schedule/rotations/components/rotation_assignee_spec.js
View file @
a2db3609
...
@@ -53,7 +53,7 @@ describe('RotationAssignee', () => {
...
@@ -53,7 +53,7 @@ describe('RotationAssignee', () => {
});
});
it
(
'
should render an assignee schedule and rotation information in a popover
'
,
()
=>
{
it
(
'
should render an assignee schedule and rotation information in a popover
'
,
()
=>
{
expect
(
findPopOver
().
attributes
(
'
target
'
)).
toBe
(
assignee
.
participant
.
id
);
expect
(
findPopOver
().
attributes
(
'
target
'
)).
toBe
(
assignee
.
id
);
expect
(
findStartsAt
().
text
()).
toContain
(
formattedDate
(
assignee
.
startsAt
));
expect
(
findStartsAt
().
text
()).
toContain
(
formattedDate
(
assignee
.
startsAt
));
expect
(
findEndsAt
().
text
()).
toContain
(
formattedDate
(
assignee
.
endsAt
));
expect
(
findEndsAt
().
text
()).
toContain
(
formattedDate
(
assignee
.
endsAt
));
});
});
...
...
ee/spec/frontend/oncall_schedule/schedule/components/__snapshots__/rotations_list_section_spec.js.snap
View file @
a2db3609
...
@@ -81,7 +81,6 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
...
@@ -81,7 +81,6 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
>
>
<span
<span
class="gl-w-full gl-h-6 gl-align-items-center gl-token gl-token-default-variant gl-bg-data-viz-blue-500"
class="gl-w-full gl-h-6 gl-align-items-center gl-token gl-token-default-variant gl-bg-data-viz-blue-500"
id="gid://gitlab/IncidentManagement::OncallParticipant/49"
>
>
<span
<span
class="gl-token-content"
class="gl-token-content"
...
@@ -152,7 +151,6 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
...
@@ -152,7 +151,6 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
>
>
<span
<span
class="gl-w-full gl-h-6 gl-align-items-center gl-token gl-token-default-variant gl-bg-data-viz-orange-500"
class="gl-w-full gl-h-6 gl-align-items-center gl-token gl-token-default-variant gl-bg-data-viz-orange-500"
id="gid://gitlab/IncidentManagement::OncallParticipant/232"
>
>
<span
<span
class="gl-token-content"
class="gl-token-content"
...
...
ee/spec/frontend/oncall_schedule/schedule/components/preset_days/days_header_sub_item_spec.js
View file @
a2db3609
...
@@ -6,11 +6,14 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper';
...
@@ -6,11 +6,14 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper';
describe
(
'
ee/oncall_schedules/components/schedule/components/preset_days/days_header_sub_item.vue
'
,
()
=>
{
describe
(
'
ee/oncall_schedules/components/schedule/components/preset_days/days_header_sub_item.vue
'
,
()
=>
{
let
wrapper
;
let
wrapper
;
const
mockTimeframeItem
=
new
Date
(
2021
,
0
,
13
);
function
mountComponent
()
{
function
mountComponent
(
{
timeframeItem
}
)
{
wrapper
=
extendedWrapper
(
wrapper
=
extendedWrapper
(
shallowMount
(
DaysHeaderSubItem
,
{
shallowMount
(
DaysHeaderSubItem
,
{
propsData
:
{},
propsData
:
{
timeframeItem
,
},
directives
:
{
directives
:
{
GlResizeObserver
:
createMockDirective
(),
GlResizeObserver
:
createMockDirective
(),
},
},
...
@@ -24,7 +27,7 @@ describe('ee/oncall_schedules/components/schedule/components/preset_days/days_he
...
@@ -24,7 +27,7 @@ describe('ee/oncall_schedules/components/schedule/components/preset_days/days_he
}
}
beforeEach
(()
=>
{
beforeEach
(()
=>
{
mountComponent
();
mountComponent
(
{
timeframeItem
:
mockTimeframeItem
}
);
});
});
afterEach
(()
=>
{
afterEach
(()
=>
{
...
@@ -46,7 +49,8 @@ describe('ee/oncall_schedules/components/schedule/components/preset_days/days_he
...
@@ -46,7 +49,8 @@ describe('ee/oncall_schedules/components/schedule/components/preset_days/days_he
expect
(
wrapper
.
find
(
'
.sublabel-value
'
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
(
'
.sublabel-value
'
).
exists
()).
toBe
(
true
);
});
});
it
(
'
renders element with class `current-day-indicator-header`
'
,
()
=>
{
it
(
'
renders element with class `current-day-indicator-header` when the date is today
'
,
()
=>
{
mountComponent
({
timeframeItem
:
new
Date
()
});
expect
(
findDaysHeaderCurrentIndicator
().
exists
()).
toBe
(
true
);
expect
(
findDaysHeaderCurrentIndicator
().
exists
()).
toBe
(
true
);
});
});
});
});
...
...
ee/spec/frontend/oncall_schedule/schedule/components/shifts/components/days_schedule_shift_spec.js
View file @
a2db3609
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
DaysScheduleShift
from
'
ee/oncall_schedules/components/schedule/components/shifts/components/days_schedule_shift.vue
'
;
import
DaysScheduleShift
from
'
ee/oncall_schedules/components/schedule/components/shifts/components/days_schedule_shift.vue
'
;
import
RotationsAssignee
from
'
ee/oncall_schedules/components/rotations/components/rotation_assignee.vue
'
;
import
RotationsAssignee
from
'
ee/oncall_schedules/components/rotations/components/rotation_assignee.vue
'
;
import
{
incrementDateByDays
}
from
'
ee/oncall_schedules/components/schedule/utils
'
;
import
{
PRESET_TYPES
,
DAYS_IN_WEEK
}
from
'
ee/oncall_schedules/constants
'
;
import
{
PRESET_TYPES
,
DAYS_IN_WEEK
}
from
'
ee/oncall_schedules/constants
'
;
import
{
nDaysAfter
}
from
'
~/lib/utils/datetime_utility
'
;
const
shift
=
{
const
shift
=
{
participant
:
{
participant
:
{
...
@@ -17,7 +17,7 @@ const shift = {
...
@@ -17,7 +17,7 @@ const shift = {
const
CELL_WIDTH
=
50
;
const
CELL_WIDTH
=
50
;
const
timeframeItem
=
new
Date
(
2021
,
0
,
15
);
const
timeframeItem
=
new
Date
(
2021
,
0
,
15
);
const
timeframe
=
[
timeframeItem
,
incrementDateByDays
(
timeframeItem
,
DAYS_IN_WEEK
)];
const
timeframe
=
[
timeframeItem
,
nDaysAfter
(
timeframeItem
,
DAYS_IN_WEEK
)];
describe
(
'
ee/oncall_schedules/components/schedule/components/shifts/components/days_schedule_shift.vue
'
,
()
=>
{
describe
(
'
ee/oncall_schedules/components/schedule/components/shifts/components/days_schedule_shift.vue
'
,
()
=>
{
let
wrapper
;
let
wrapper
;
...
...
ee/spec/frontend/oncall_schedule/schedule/components/shifts/components/schedule_shift_wrapper_spec.js
View file @
a2db3609
...
@@ -3,11 +3,11 @@ import ScheduleShiftWrapper from 'ee/oncall_schedules/components/schedule/compon
...
@@ -3,11 +3,11 @@ import ScheduleShiftWrapper from 'ee/oncall_schedules/components/schedule/compon
import
DaysScheduleShift
from
'
ee/oncall_schedules/components/schedule/components/shifts/components/days_schedule_shift.vue
'
;
import
DaysScheduleShift
from
'
ee/oncall_schedules/components/schedule/components/shifts/components/days_schedule_shift.vue
'
;
import
WeeksScheduleShift
from
'
ee/oncall_schedules/components/schedule/components/shifts/components/weeks_schedule_shift.vue
'
;
import
WeeksScheduleShift
from
'
ee/oncall_schedules/components/schedule/components/shifts/components/weeks_schedule_shift.vue
'
;
import
{
PRESET_TYPES
,
DAYS_IN_WEEK
}
from
'
ee/oncall_schedules/constants
'
;
import
{
PRESET_TYPES
,
DAYS_IN_WEEK
}
from
'
ee/oncall_schedules/constants
'
;
import
{
incrementDateByDays
}
from
'
ee/oncall_schedules/components/schedule/utils
'
;
import
{
nDaysAfter
}
from
'
~/lib/utils/datetime_utility
'
;
import
mockRotations
from
'
../../../../mocks/mock_rotation.json
'
;
import
mockRotations
from
'
../../../../mocks/mock_rotation.json
'
;
const
timeframeItem
=
new
Date
(
2021
,
0
,
13
);
const
timeframeItem
=
new
Date
(
2021
,
0
,
13
);
const
timeframe
=
[
timeframeItem
,
incrementDateByDays
(
timeframeItem
,
DAYS_IN_WEEK
)];
const
timeframe
=
[
timeframeItem
,
nDaysAfter
(
timeframeItem
,
DAYS_IN_WEEK
)];
describe
(
'
ee/oncall_schedules/components/schedule/components/shifts/components/schedule_shift_wrapper.vue
'
,
()
=>
{
describe
(
'
ee/oncall_schedules/components/schedule/components/shifts/components/schedule_shift_wrapper.vue
'
,
()
=>
{
let
wrapper
;
let
wrapper
;
...
...
ee/spec/frontend/oncall_schedule/schedule/components/shifts/components/weeks_schedule_shift_spec.js
View file @
a2db3609
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
WeeksScheduleShift
from
'
ee/oncall_schedules/components/schedule/components/shifts/components/weeks_schedule_shift.vue
'
;
import
WeeksScheduleShift
from
'
ee/oncall_schedules/components/schedule/components/shifts/components/weeks_schedule_shift.vue
'
;
import
RotationsAssignee
from
'
ee/oncall_schedules/components/rotations/components/rotation_assignee.vue
'
;
import
RotationsAssignee
from
'
ee/oncall_schedules/components/rotations/components/rotation_assignee.vue
'
;
import
{
incrementDateByDays
}
from
'
ee/oncall_schedules/components/schedule/utils
'
;
import
{
PRESET_TYPES
,
DAYS_IN_WEEK
}
from
'
ee/oncall_schedules/constants
'
;
import
{
PRESET_TYPES
,
DAYS_IN_WEEK
}
from
'
ee/oncall_schedules/constants
'
;
import
{
nDaysAfter
}
from
'
~/lib/utils/datetime_utility
'
;
const
shift
=
{
const
shift
=
{
participant
:
{
participant
:
{
...
@@ -17,7 +17,7 @@ const shift = {
...
@@ -17,7 +17,7 @@ const shift = {
const
CELL_WIDTH
=
50
;
const
CELL_WIDTH
=
50
;
const
timeframeItem
=
new
Date
(
2021
,
0
,
13
);
const
timeframeItem
=
new
Date
(
2021
,
0
,
13
);
const
timeframe
=
[
timeframeItem
,
incrementDateByDays
(
timeframeItem
,
DAYS_IN_WEEK
)];
const
timeframe
=
[
timeframeItem
,
new
Date
(
nDaysAfter
(
timeframeItem
,
DAYS_IN_WEEK
)
)];
describe
(
'
ee/oncall_schedules/components/schedule/components/shifts/components/weeks_schedule_shift.vue
'
,
()
=>
{
describe
(
'
ee/oncall_schedules/components/schedule/components/shifts/components/weeks_schedule_shift.vue
'
,
()
=>
{
let
wrapper
;
let
wrapper
;
...
...
ee/spec/frontend/oncall_schedule/schedule/mixins/common_mixin_spec.js
View file @
a2db3609
...
@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
...
@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import
CommonMixin
from
'
ee/oncall_schedules/mixins/common_mixin
'
;
import
CommonMixin
from
'
ee/oncall_schedules/mixins/common_mixin
'
;
import
{
useFakeDate
}
from
'
helpers/fake_date
'
;
import
{
useFakeDate
}
from
'
helpers/fake_date
'
;
import
{
DAYS_IN_WEEK
}
from
'
ee/oncall_schedules/constants
'
;
import
{
DAYS_IN_WEEK
}
from
'
ee/oncall_schedules/constants
'
;
import
*
as
dateTimeUtility
from
'
~/lib/utils/datetime_utility
'
;
describe
(
'
Schedule Common Mixins
'
,
()
=>
{
describe
(
'
Schedule Common Mixins
'
,
()
=>
{
// January 3rd, 2018
// January 3rd, 2018
...
@@ -37,6 +38,24 @@ describe('Schedule Common Mixins', () => {
...
@@ -37,6 +38,24 @@ describe('Schedule Common Mixins', () => {
expect
(
wrapper
.
vm
.
$options
.
currentDate
).
toEqual
(
today
);
expect
(
wrapper
.
vm
.
$options
.
currentDate
).
toEqual
(
today
);
});
});
});
});
describe
(
'
isToday
'
,
()
=>
{
it
(
'
returns true when date is today
'
,
()
=>
{
const
result
=
true
;
jest
.
spyOn
(
dateTimeUtility
,
'
isToday
'
).
mockReturnValue
(
result
);
mountComponent
();
expect
(
wrapper
.
vm
.
isToday
).
toBe
(
result
);
});
it
(
'
returns false when date is NOT today
'
,
()
=>
{
const
result
=
false
;
jest
.
spyOn
(
dateTimeUtility
,
'
isToday
'
).
mockReturnValue
(
result
);
mountComponent
();
expect
(
wrapper
.
vm
.
isToday
).
toBe
(
result
);
});
});
describe
(
'
hasToday
'
,
()
=>
{
describe
(
'
hasToday
'
,
()
=>
{
it
(
'
returns true when today (January 3rd, 2018) is within the set week (January 1st, 2018)
'
,
()
=>
{
it
(
'
returns true when today (January 3rd, 2018) is within the set week (January 1st, 2018)
'
,
()
=>
{
// January 1st, 2018
// January 1st, 2018
...
...
spec/frontend/lib/utils/datetime_utility_spec.js
View file @
a2db3609
...
@@ -618,9 +618,12 @@ describe('nDaysAfter', () => {
...
@@ -618,9 +618,12 @@ describe('nDaysAfter', () => {
${
-
1
}
|
${
new
Date
(
'
2019-07-15T00:00:00.000Z
'
).
valueOf
()}
${
-
1
}
|
${
new
Date
(
'
2019-07-15T00:00:00.000Z
'
).
valueOf
()}
${
0
}
|
${
date
.
valueOf
()}
${
0
}
|
${
date
.
valueOf
()}
${
0.9
}
|
${
date
.
valueOf
()}
${
0.9
}
|
${
date
.
valueOf
()}
`
(
'
returns $numberOfDays day(s) after the provided date
'
,
({
numberOfDays
,
expectedResult
})
=>
{
`
(
'
returns the date $numberOfDays day(s) after the provided date
'
,
({
numberOfDays
,
expectedResult
})
=>
{
expect
(
datetimeUtility
.
nDaysAfter
(
date
,
numberOfDays
)).
toBe
(
expectedResult
);
expect
(
datetimeUtility
.
nDaysAfter
(
date
,
numberOfDays
)).
toBe
(
expectedResult
);
});
},
);
});
});
describe
(
'
nDaysBefore
'
,
()
=>
{
describe
(
'
nDaysBefore
'
,
()
=>
{
...
@@ -633,9 +636,48 @@ describe('nDaysBefore', () => {
...
@@ -633,9 +636,48 @@ describe('nDaysBefore', () => {
${
-
1
}
|
${
new
Date
(
'
2019-07-17T00:00:00.000Z
'
).
valueOf
()}
${
-
1
}
|
${
new
Date
(
'
2019-07-17T00:00:00.000Z
'
).
valueOf
()}
${
0
}
|
${
date
.
valueOf
()}
${
0
}
|
${
date
.
valueOf
()}
${
0.9
}
|
${
new
Date
(
'
2019-07-15T00:00:00.000Z
'
).
valueOf
()}
${
0.9
}
|
${
new
Date
(
'
2019-07-15T00:00:00.000Z
'
).
valueOf
()}
`
(
'
returns $numberOfDays day(s) before the provided date
'
,
({
numberOfDays
,
expectedResult
})
=>
{
`
(
'
returns the date $numberOfDays day(s) before the provided date
'
,
({
numberOfDays
,
expectedResult
})
=>
{
expect
(
datetimeUtility
.
nDaysBefore
(
date
,
numberOfDays
)).
toBe
(
expectedResult
);
expect
(
datetimeUtility
.
nDaysBefore
(
date
,
numberOfDays
)).
toBe
(
expectedResult
);
});
},
);
});
describe
(
'
nWeeksAfter
'
,
()
=>
{
const
date
=
new
Date
(
'
2021-07-16T00:00:00.000Z
'
);
it
.
each
`
numberOfWeeks | expectedResult
${
1
}
|
${
new
Date
(
'
2021-07-23T00:00:00.000Z
'
).
valueOf
()}
${
3
}
|
${
new
Date
(
'
2021-08-06T00:00:00.000Z
'
).
valueOf
()}
${
-
1
}
|
${
new
Date
(
'
2021-07-09T00:00:00.000Z
'
).
valueOf
()}
${
0
}
|
${
date
.
valueOf
()}
${
0.6
}
|
${
new
Date
(
'
2021-07-20T00:00:00.000Z
'
).
valueOf
()}
`
(
'
returns the date $numberOfWeeks week(s) after the provided date
'
,
({
numberOfWeeks
,
expectedResult
})
=>
{
expect
(
datetimeUtility
.
nWeeksAfter
(
date
,
numberOfWeeks
)).
toBe
(
expectedResult
);
},
);
});
describe
(
'
nWeeksBefore
'
,
()
=>
{
const
date
=
new
Date
(
'
2021-07-16T00:00:00.000Z
'
);
it
.
each
`
numberOfWeeks | expectedResult
${
1
}
|
${
new
Date
(
'
2021-07-09T00:00:00.000Z
'
).
valueOf
()}
${
3
}
|
${
new
Date
(
'
2021-06-25T00:00:00.000Z
'
).
valueOf
()}
${
-
1
}
|
${
new
Date
(
'
2021-07-23T00:00:00.000Z
'
).
valueOf
()}
${
0
}
|
${
date
.
valueOf
()}
${
0.6
}
|
${
new
Date
(
'
2021-07-11T00:00:00.000Z
'
).
valueOf
()}
`
(
'
returns the date $numberOfWeeks week(s) before the provided date
'
,
({
numberOfWeeks
,
expectedResult
})
=>
{
expect
(
datetimeUtility
.
nWeeksBefore
(
date
,
numberOfWeeks
)).
toBe
(
expectedResult
);
},
);
});
});
describe
(
'
nMonthsAfter
'
,
()
=>
{
describe
(
'
nMonthsAfter
'
,
()
=>
{
...
@@ -659,7 +701,7 @@ describe('nMonthsAfter', () => {
...
@@ -659,7 +701,7 @@ describe('nMonthsAfter', () => {
${
may2020
}
|
${
0
}
|
${
may2020
.
valueOf
()}
${
may2020
}
|
${
0
}
|
${
may2020
.
valueOf
()}
${
may2020
}
|
${
0.9
}
|
${
may2020
.
valueOf
()}
${
may2020
}
|
${
0.9
}
|
${
may2020
.
valueOf
()}
`
(
`
(
'
returns $numberOfMonths month(s) after the provided date
'
,
'
returns
the date
$numberOfMonths month(s) after the provided date
'
,
({
date
,
numberOfMonths
,
expectedResult
})
=>
{
({
date
,
numberOfMonths
,
expectedResult
})
=>
{
expect
(
datetimeUtility
.
nMonthsAfter
(
date
,
numberOfMonths
)).
toBe
(
expectedResult
);
expect
(
datetimeUtility
.
nMonthsAfter
(
date
,
numberOfMonths
)).
toBe
(
expectedResult
);
},
},
...
@@ -687,7 +729,7 @@ describe('nMonthsBefore', () => {
...
@@ -687,7 +729,7 @@ describe('nMonthsBefore', () => {
${
june2020
}
|
${
0
}
|
${
june2020
.
valueOf
()}
${
june2020
}
|
${
0
}
|
${
june2020
.
valueOf
()}
${
june2020
}
|
${
0.9
}
|
${
new
Date
(
'
2020-05-15T00:00:00.000Z
'
).
valueOf
()}
${
june2020
}
|
${
0.9
}
|
${
new
Date
(
'
2020-05-15T00:00:00.000Z
'
).
valueOf
()}
`
(
`
(
'
returns $numberOfMonths month(s) before the provided date
'
,
'
returns
the date
$numberOfMonths month(s) before the provided date
'
,
({
date
,
numberOfMonths
,
expectedResult
})
=>
{
({
date
,
numberOfMonths
,
expectedResult
})
=>
{
expect
(
datetimeUtility
.
nMonthsBefore
(
date
,
numberOfMonths
)).
toBe
(
expectedResult
);
expect
(
datetimeUtility
.
nMonthsBefore
(
date
,
numberOfMonths
)).
toBe
(
expectedResult
);
},
},
...
@@ -898,3 +940,14 @@ describe('getOverlapDateInPeriods', () => {
...
@@ -898,3 +940,14 @@ describe('getOverlapDateInPeriods', () => {
});
});
});
});
});
});
describe
(
'
isToday
'
,
()
=>
{
const
today
=
new
Date
();
it
.
each
`
date | expected | negation
${
today
}
|
${
true
}
|
${
'
is
'
}
${
new
Date
(
'
2021-01-21T12:00:00.000Z
'
)}
|
${
false
}
|
${
'
is NOT
'
}
`
(
'
returns $expected as $date $negation today
'
,
({
date
,
expected
})
=>
{
expect
(
datetimeUtility
.
isToday
(
date
)).
toBe
(
expected
);
});
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment