Commit 07e89047 authored by Olena Horal-Koretska's avatar Olena Horal-Koretska

Merge branch '323917-remove-roadmap_daterange_filter-ff' into 'master'

Remove `roadmap_daterange_filter` feature flag and related legacy code from Roadmap app

See merge request gitlab-org/gitlab!72419
parents 4f6a4289 605d5dca
<script>
import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
import Cookies from 'js-cookie';
import { GlLoadingIcon } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import { __, s__ } from '~/locale';
import {
EPICS_LIMIT_DISMISSED_COOKIE_NAME,
EPICS_LIMIT_DISMISSED_COOKIE_TIMEOUT,
DATE_RANGES,
} from '../constants';
import { DATE_RANGES } from '../constants';
import EpicsListEmpty from './epics_list_empty.vue';
import RoadmapFilters from './roadmap_filters.vue';
import RoadmapShell from './roadmap_shell.vue';
export default {
i18n: {
warningTitle: s__('GroupRoadmap|Some of your epics might not be visible'),
warningBody: s__(
'GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order.',
),
warningButtonLabel: __('Learn more'),
},
components: {
EpicsListEmpty,
GlAlert,
GlLoadingIcon,
RoadmapFilters,
RoadmapShell,
......@@ -43,11 +29,6 @@ export default {
required: true,
},
},
data() {
return {
isWarningDismissed: Cookies.get(EPICS_LIMIT_DISMISSED_COOKIE_NAME) === 'true',
};
},
computed: {
...mapState([
'currentGroupId',
......@@ -85,12 +66,6 @@ export default {
},
methods: {
...mapActions(['fetchEpics', 'fetchMilestones']),
dismissTooManyEpicsWarning() {
Cookies.set(EPICS_LIMIT_DISMISSED_COOKIE_NAME, 'true', {
expires: EPICS_LIMIT_DISMISSED_COOKIE_TIMEOUT,
});
this.isWarningDismissed = true;
},
},
};
</script>
......@@ -101,16 +76,6 @@ export default {
v-if="showFilteredSearchbar && !epicIid"
:timeframe-range-type="timeframeRangeType"
/>
<gl-alert
v-if="isWarningVisible"
variant="warning"
:title="$options.i18n.warningTitle"
:primary-button-text="$options.i18n.warningButtonLabel"
primary-button-link="https://docs.gitlab.com/ee/user/group/roadmap/"
data-testid="epics_limit_callout"
@dismiss="dismissTooManyEpicsWarning"
>{{ $options.i18n.warningBody }}</gl-alert
>
<div :class="{ 'overflow-reset': epicsFetchResultEmpty }" class="roadmap-container">
<gl-loading-icon v-if="epicsFetchInProgress" class="gl-mt-5" size="md" />
<epics-list-empty
......
......@@ -11,7 +11,6 @@ import { mapState, mapActions } from 'vuex';
import { visitUrl, mergeUrlParams, updateHistory, setUrlParams } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { EPICS_STATES, PRESET_TYPES, DATE_RANGES } from '../constants';
import EpicsFilteredSearchMixin from '../mixins/filtered_search_mixin';
......@@ -56,7 +55,7 @@ export default {
GlDropdownDivider,
FilteredSearchBar,
},
mixins: [EpicsFilteredSearchMixin, glFeatureFlagsMixin()],
mixins: [EpicsFilteredSearchMixin],
props: {
timeframeRangeType: {
type: String,
......@@ -95,10 +94,6 @@ export default {
const months = { text: __('Months'), value: PRESET_TYPES.MONTHS };
const weeks = { text: __('Weeks'), value: PRESET_TYPES.WEEKS };
if (!this.glFeatures.roadmapDaterangeFilter) {
return [quarters, months, weeks];
}
if (this.selectedDaterange === DATE_RANGES.CURRENT_YEAR) {
return [months, weeks];
} else if (this.selectedDaterange === DATE_RANGES.THREE_YEARS) {
......@@ -146,9 +141,7 @@ export default {
handleRoadmapLayoutChange(presetType) {
visitUrl(
mergeUrlParams(
this.glFeatures.roadmapDaterangeFilter
? { timeframe_range_type: this.selectedDaterange, layout: presetType }
: { layout: presetType },
{ timeframe_range_type: this.selectedDaterange, layout: presetType },
window.location.href,
),
);
......@@ -175,7 +168,6 @@ export default {
class="epics-details-filters filtered-search-block gl-display-flex gl-flex-direction-column gl-xl-flex-direction-row gl-pb-3 row-content-block second-block"
>
<gl-dropdown
v-if="glFeatures.roadmapDaterangeFilter"
icon="calendar"
class="gl-mr-0 gl-lg-mr-3 mb-sm-2 roadmap-daterange-dropdown"
toggle-class="gl-rounded-base!"
......
......@@ -41,11 +41,6 @@ export const EPICS_STATES = {
CLOSED: 'closed',
};
export const EXTEND_AS = {
PREPEND: 'prepend',
APPEND: 'append',
};
export const emptyStateDefault = s__(
'GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}.',
);
......@@ -58,18 +53,6 @@ export const emptyStateWithEpicIidFiltered = s__(
'GroupRoadmap|To make your epics appear in the roadmap, add start or due dates to them.',
);
export const PRESET_DEFAULTS = {
QUARTERS: {
TIMEFRAME_LENGTH: 21,
},
MONTHS: {
TIMEFRAME_LENGTH: 8,
},
WEEKS: {
TIMEFRAME_LENGTH: 7,
},
};
export const EPIC_LEVEL_MARGIN = {
1: 'ml-4',
2: 'ml-6',
......@@ -77,8 +60,4 @@ export const EPIC_LEVEL_MARGIN = {
4: 'ml-10',
};
export const EPICS_LIMIT_DISMISSED_COOKIE_NAME = 'epics_limit_warning_dismissed';
export const EPICS_LIMIT_DISMISSED_COOKIE_TIMEOUT = 365;
export const ROADMAP_PAGE_SIZE = 50;
......@@ -11,11 +11,10 @@ import EpicItem from './components/epic_item.vue';
import EpicItemContainer from './components/epic_item_container.vue';
import roadmapApp from './components/roadmap_app.vue';
import { PRESET_TYPES, EPIC_DETAILS_CELL_WIDTH, DATE_RANGES } from './constants';
import { DATE_RANGES } from './constants';
import createStore from './store';
import {
getTimeframeForPreset,
getPresetTypeForTimeframeRangeType,
getTimeframeForRangeType,
} from './utils/roadmap_utils';
......@@ -70,30 +69,16 @@ export default () => {
},
data() {
const { dataset } = this.$options.el;
let timeframe;
let timeframeRangeType;
let presetType;
if (gon.features.roadmapDaterangeFilter) {
timeframeRangeType =
Object.keys(DATE_RANGES).indexOf(dataset.timeframeRangeType) > -1
? dataset.timeframeRangeType
: DATE_RANGES.CURRENT_QUARTER;
presetType = getPresetTypeForTimeframeRangeType(timeframeRangeType, dataset.presetType);
timeframe = getTimeframeForRangeType({
timeframeRangeType,
presetType,
});
} else {
presetType =
Object.keys(PRESET_TYPES).indexOf(dataset.presetType) > -1
? dataset.presetType
: PRESET_TYPES.MONTHS;
timeframe = getTimeframeForPreset(
presetType,
window.innerWidth - el.offsetLeft - EPIC_DETAILS_CELL_WIDTH,
);
}
const timeframeRangeType =
Object.keys(DATE_RANGES).indexOf(dataset.timeframeRangeType) > -1
? dataset.timeframeRangeType
: DATE_RANGES.CURRENT_QUARTER;
const presetType = getPresetTypeForTimeframeRangeType(timeframeRangeType, dataset.presetType);
const timeframe = getTimeframeForRangeType({
timeframeRangeType,
presetType,
});
const rawFilterParams = queryToObject(window.location.search, {
gatherArrays: true,
......
......@@ -19,9 +19,6 @@ export const INIT_EPIC_CHILDREN_FLAGS = 'INIT_EPIC_CHILDREN_FLAGS';
export const EXPAND_EPIC = 'EXPAND_EPIC';
export const COLLAPSE_EPIC = 'COLLAPSE_EPIC';
export const PREPEND_TIMEFRAME = 'PREPEND_TIMEFRAME';
export const APPEND_TIMEFRAME = 'APPEND_TIMEFRAME';
export const SET_MILESTONES = 'SET_MILESTONES';
export const UPDATE_MILESTONE_IDS = 'UPDATE_MILESTONE_IDS';
......
......@@ -85,15 +85,6 @@ export default {
state.childrenFlags[parentItemId].itemExpanded = false;
},
[types.PREPEND_TIMEFRAME](state, extendedTimeframe) {
state.extendedTimeframe = extendedTimeframe;
state.timeframe.unshift(...extendedTimeframe);
},
[types.APPEND_TIMEFRAME](state, extendedTimeframe) {
state.extendedTimeframe = extendedTimeframe;
state.timeframe.push(...extendedTimeframe);
},
[types.SET_MILESTONES](state, milestones) {
state.milestones = milestones;
},
......
......@@ -15,7 +15,6 @@ export default () => ({
currentGroupId: -1,
fullPath: '',
timeframe: [],
extendedTimeframe: [],
presetType: '',
timeframeRangeType: '',
sortedBy: '',
......
import { getTimeframeWindowFrom, newDate, totalDaysInMonth } from '~/lib/utils/datetime_utility';
import {
DAYS_IN_WEEK,
EXTEND_AS,
PRESET_DEFAULTS,
DATE_RANGES,
PRESET_TYPES,
TIMELINE_CELL_MIN_WIDTH,
} from '../constants';
import { DAYS_IN_WEEK, DATE_RANGES, PRESET_TYPES } from '../constants';
const monthsForQuarters = {
1: [0, 1, 2],
......@@ -16,355 +9,6 @@ const monthsForQuarters = {
4: [9, 10, 11],
};
/**
* This method returns array of Objects representing Quarters based on provided initialDate
*
* For eg; If initialDate is 15th Jan 2018
* Then as per Roadmap specs, we need to show
* 2 quarters before current quarters
* current quarter AND
* 4 quarters after current quarter
* thus, total of 7 quarters (21 Months).
*
* So returned array from this method will be;
* [
* {
* quarterSequence: 4,
* year: 2017,
* range: [
* 1 Oct 2017,
* 1 Nov 2017,
* 31 Dec 2017,
* ],
* },
* {
* quarterSequence: 1,
* year: 2018,
* range: [
* 1 Jan 2018,
* 1 Feb 2018,
* 31 Mar 2018,
* ],
* },
* ....
* ....
* ....
* {
* quarterSequence: 1,
* year: 2019,
* range: [
* 1 Jan 2019,
* 1 Feb 2019,
* 31 Mar 2019,
* ],
* },
* ]
*
* @param {Date} initialDate
*/
export const getTimeframeForQuartersView = (initialDate = new Date(), timeframe = []) => {
const startDate = newDate(initialDate);
startDate.setHours(0, 0, 0, 0);
if (!timeframe.length) {
// Get current quarter for current month
const currentQuarter = Math.floor((startDate.getMonth() + 3) / 3);
// Get index of current month in current quarter
// It could be 0, 1, 2 (i.e. first, second or third)
const currentMonthInCurrentQuarter = monthsForQuarters[currentQuarter].indexOf(
startDate.getMonth(),
);
// To move start back to first month of 2 quarters prior by
// adding quarter size (3 + 3) to month order will give us
// exact number of months we need to go back in time
const startMonth = currentMonthInCurrentQuarter + 6;
// Move startDate to first month of previous quarter
startDate.setMonth(startDate.getMonth() - startMonth);
// Get timeframe for the length we determined for this preset
// start from the startDate
timeframe.push(...getTimeframeWindowFrom(startDate, PRESET_DEFAULTS.QUARTERS.TIMEFRAME_LENGTH));
}
const quartersTimeframe = [];
// Iterate over the timeframe and break it down
// in chunks of quarters
for (let i = 0; i < timeframe.length; i += 3) {
const range = timeframe.slice(i, i + 3);
const lastMonthOfQuarter = range[range.length - 1];
const quarterSequence = Math.floor((range[0].getMonth() + 3) / 3);
const year = range[0].getFullYear();
// Ensure that `range` spans across duration of
// entire quarter
lastMonthOfQuarter.setDate(totalDaysInMonth(lastMonthOfQuarter));
quartersTimeframe.push({
quarterSequence,
range,
year,
});
}
return quartersTimeframe;
};
export const extendTimeframeForQuartersView = (initialDate = new Date(), length) => {
const startDate = newDate(initialDate);
startDate.setDate(1);
startDate.setMonth(startDate.getMonth() + (length > 0 ? 1 : -1));
const timeframe = getTimeframeWindowFrom(startDate, length);
return getTimeframeForQuartersView(startDate, length > 0 ? timeframe : timeframe.reverse());
};
/**
* This method returns array of Dates respresenting Months based on provided initialDate
*
* For eg; If initialDate is 15th Jan 2018
* Then as per Roadmap specs, we need to show
* 2 months before current month,
* current month AND
* 5 months after current month
* thus, total of 8 months.
*
* So returned array from this method will be;
* [
* 1 Nov 2017, 1 Dec 2017, 1 Jan 2018, 1 Feb 2018,
* 1 Mar 2018, 1 Apr 2018, 1 May 2018, 30 Jun 2018
* ]
*
* @param {Date} initialDate
*/
export const getTimeframeForMonthsView = (initialDate = new Date()) => {
const startDate = newDate(initialDate);
// Move startDate to a month prior to current month
startDate.setMonth(startDate.getMonth() - 2);
return getTimeframeWindowFrom(startDate, PRESET_DEFAULTS.MONTHS.TIMEFRAME_LENGTH);
};
export const extendTimeframeForMonthsView = (initialDate = new Date(), length) => {
const startDate = newDate(initialDate);
// When length is positive (which means extension is of type APPEND)
// Set initial date as first day of the month.
if (length > 0) {
startDate.setDate(1);
}
const timeframe = getTimeframeWindowFrom(startDate, length - 1).slice(1);
return length > 0 ? timeframe : timeframe.reverse();
};
/**
* This method returns array of Dates respresenting Months based on provided initialDate
*
* For eg; If initialDate is 15th Jan 2018
* Then as per Roadmap specs, we need to show
* 2 weeks before current week,
* current week AND
* 4 weeks after current week
* thus, total of 7 weeks.
* Note that week starts on Sunday
*
* So returned array from this method will be;
* [
* 31 Dec 2017, 7 Jan 2018, 14 Jan 2018, 21 Jan 2018,
* 28 Jan 2018, 4 Mar 2018, 11 Mar 2018
* ]
*
* @param {Date} initialDate
*/
export const getTimeframeForWeeksView = (initialDate = new Date(), length) => {
const timeframe = [];
const startDate = newDate(initialDate);
startDate.setHours(0, 0, 0, 0);
// When length is not provided
// We need to provide standard
// timeframe as per feature specs (see block comment above)
if (!length) {
const dayOfWeek = startDate.getDay();
const daysToFirstDayOfPrevWeek = dayOfWeek + DAYS_IN_WEEK * 2;
// Move startDate to first day (Sunday) of 2 weeks prior
startDate.setDate(startDate.getDate() - daysToFirstDayOfPrevWeek);
}
const rangeLength = length || PRESET_DEFAULTS.WEEKS.TIMEFRAME_LENGTH;
// Iterate for the length of this preset
for (let i = 0; i < rangeLength; i += 1) {
// Push date to timeframe only when day is
// first day (Sunday) of the week
timeframe.push(newDate(startDate));
// Move date next Sunday
startDate.setDate(startDate.getDate() + DAYS_IN_WEEK);
}
return timeframe;
};
export const extendTimeframeForWeeksView = (initialDate = new Date(), length) => {
const startDate = newDate(initialDate);
if (length < 0) {
// When length is negative, we need to go
// back as many weeks in time as value of length
startDate.setDate(startDate.getDate() + length * DAYS_IN_WEEK);
}
return getTimeframeForWeeksView(startDate, Math.abs(length));
};
export const extendTimeframeForPreset = ({
presetType = PRESET_TYPES.MONTHS,
extendAs = EXTEND_AS.PREPEND,
extendByLength = 0,
initialDate,
}) => {
if (presetType === PRESET_TYPES.QUARTERS) {
const length = extendByLength || PRESET_DEFAULTS.QUARTERS.TIMEFRAME_LENGTH;
return extendTimeframeForQuartersView(
initialDate,
extendAs === EXTEND_AS.PREPEND ? -length : length,
);
} else if (presetType === PRESET_TYPES.MONTHS) {
const length = extendByLength || PRESET_DEFAULTS.MONTHS.TIMEFRAME_LENGTH;
return extendTimeframeForMonthsView(
initialDate,
extendAs === EXTEND_AS.PREPEND ? -length : length,
);
}
const length = extendByLength || PRESET_DEFAULTS.WEEKS.TIMEFRAME_LENGTH;
return extendTimeframeForWeeksView(
initialDate,
extendAs === EXTEND_AS.PREPEND ? -length : length,
);
};
export const extendTimeframeForAvailableWidth = ({
timeframe,
timeframeStart,
timeframeEnd,
availableTimeframeWidth,
presetType,
}) => {
let timeframeLength = timeframe.length;
// Estimate how many more timeframe columns are needed
// to fill in extra screen space so that timeline becomes
// horizontally scrollable.
while (availableTimeframeWidth / timeframeLength > TIMELINE_CELL_MIN_WIDTH) {
timeframeLength += 1;
}
// We double the increaseLengthBy to make sure there's enough room
// to perform horizontal scroll without triggering timeframe extension
// on initial page load.
let increaseLengthBy = timeframeLength - timeframe.length;
// Handle a case where window size is leading to
// increaseLength between 1 & 3 which is not big
// enough for extendTimeframeFor*****View methods
if (increaseLengthBy > 0 && increaseLengthBy <= 3) {
increaseLengthBy += 4; // Equalize by adding 2 columns on each end
}
// If there are timeframe items to be added
// to make timeline scrollable, do as follows.
if (increaseLengthBy > 0) {
// Split length in 2 parts and get
// count for both prepend and append.
const prependBy = Math.floor(increaseLengthBy / 2);
const appendBy = Math.ceil(increaseLengthBy / 2);
if (prependBy) {
// Prepend the timeline with
// the count as given by prependBy
timeframe.unshift(
...extendTimeframeForPreset({
extendAs: EXTEND_AS.PREPEND,
initialDate: timeframeStart,
// In case of presetType `quarters`, length would represent
// number of months for total quarters, hence we do `* 3`.
extendByLength: presetType === PRESET_TYPES.QUARTERS ? prependBy * 3 : prependBy,
presetType,
}),
);
}
if (appendBy) {
// Append the timeline with
// the count as given by appendBy
timeframe.push(
...extendTimeframeForPreset({
extendAs: EXTEND_AS.APPEND,
initialDate: timeframeEnd,
// In case of presetType `quarters`, length would represent
// number of months for total quarters, hence we do `* 3`.
//
// For other preset types, we add `2` to appendBy to compensate for
// last item of original timeframe (month or week)
extendByLength: presetType === PRESET_TYPES.QUARTERS ? appendBy * 3 : appendBy + 2,
presetType,
}),
);
}
}
};
export const getTimeframeForPreset = (
presetType = PRESET_TYPES.MONTHS,
availableTimeframeWidth = 0,
) => {
let timeframe;
let timeframeStart;
let timeframeEnd;
// Get timeframe based on presetType and
// extract timeframeStart and timeframeEnd
// date objects
if (presetType === PRESET_TYPES.QUARTERS) {
timeframe = getTimeframeForQuartersView();
[timeframeStart] = timeframe[0].range;
// eslint-disable-next-line prefer-destructuring
timeframeEnd = timeframe[timeframe.length - 1].range[2];
} else if (presetType === PRESET_TYPES.MONTHS) {
timeframe = getTimeframeForMonthsView();
[timeframeStart] = timeframe;
timeframeEnd = timeframe[timeframe.length - 1];
} else {
timeframe = getTimeframeForWeeksView();
timeframeStart = newDate(timeframe[0]);
timeframeEnd = newDate(timeframe[timeframe.length - 1]);
timeframeStart.setDate(timeframeStart.getDate());
timeframeEnd.setDate(timeframeEnd.getDate() + DAYS_IN_WEEK); // Move date ahead by a week
}
// Extend timeframe on initial load to ensure
// timeline is horizontally scrollable in all
// screen sizes.
extendTimeframeForAvailableWidth({
timeframe,
timeframeStart,
timeframeEnd,
availableTimeframeWidth,
presetType,
});
return timeframe;
};
export const getWeeksForDates = (startDate, endDate) => {
const timeframe = [];
const start = newDate(startDate);
......@@ -388,9 +32,10 @@ export const getWeeksForDates = (startDate, endDate) => {
export const getTimeframeForRangeType = ({
timeframeRangeType = DATE_RANGES.CURRENT_QUARTER,
presetType = PRESET_TYPES.WEEKS,
initialDate = new Date(),
}) => {
let timeframe = [];
const startDate = new Date();
const startDate = newDate(initialDate);
startDate.setHours(0, 0, 0, 0);
// We need to prepare timeframe containing all the weeks of
......
......@@ -7,9 +7,6 @@ module Groups
before_action :check_epics_available!
before_action :persist_roadmap_layout, only: [:show]
before_action do
push_frontend_feature_flag(:roadmap_daterange_filter, @group, type: :development, default_enabled: :yaml)
end
feature_category :roadmaps
......
---
name: roadmap_daterange_filter
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55639
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323917
milestone: '14.3'
type: development
group: group::product planning
default_enabled: true
......@@ -29,7 +29,6 @@ RSpec.describe 'group epic roadmap', :js do
before do
stub_licensed_features(epics: true)
stub_feature_flags(unfiltered_epic_aggregates: false)
stub_feature_flags(roadmap_daterange_filter: false)
sign_in(user)
end
......@@ -47,11 +46,47 @@ RSpec.describe 'group epic roadmap', :js do
end
describe 'roadmap page' do
it 'renders roadmap preset buttons correctly' do
page.within('.gl-segmented-control') do
expect(page).to have_css('input[value="QUARTERS"]')
expect(page).to have_css('input[value="MONTHS"]')
expect(page).to have_css('input[value="WEEKS"]')
context 'roadmap daterange filtering' do
def select_date_range(range_type)
page.within('.epics-roadmap-filters') do
page.find('[data-testid="daterange-dropdown"] button.dropdown-toggle').click
click_button(range_type)
end
end
it 'renders daterange filtering dropdown with "This quarter" selected by default no layout presets available', :aggregate_failures do
page.within('.epics-roadmap-filters') do
expect(page).to have_selector('[data-testid="daterange-dropdown"]')
expect(page).not_to have_selector('.gl-segmented-control')
expect(page.find('[data-testid="daterange-dropdown"] button.dropdown-toggle')).to have_content('This quarter')
end
end
it 'selecting "This year" as daterange shows `Months` and `Weeks` layout presets', :aggregate_failures do
select_date_range('This year')
page.within('.epics-roadmap-filters') do
expect(page).to have_selector('.gl-segmented-control')
expect(page).to have_selector('input[value="MONTHS"]')
expect(page).to have_selector('input[value="WEEKS"]')
end
end
it 'selecting "Within 3 years" as daterange shows `Quarters`, `Months` and `Weeks` layout presets', :aggregate_failures do
select_date_range('Within 3 years')
page.within('.epics-roadmap-filters') do
expect(page).to have_selector('.gl-segmented-control')
expect(page).to have_selector('input[value="QUARTERS"]')
expect(page).to have_selector('input[value="MONTHS"]')
expect(page).to have_selector('input[value="WEEKS"]')
end
end
end
it 'renders the epics state dropdown' do
page.within('.content-wrapper .content .epics-filters') do
expect(page).to have_css('.dropdown-epics-state')
end
end
......@@ -192,38 +227,4 @@ RSpec.describe 'group epic roadmap', :js do
end
end
end
context 'when over 1000 epics match roadmap filters' do
before do
create_list(:epic, 2, group: group, start_date: 10.days.ago, end_date: 1.day.ago)
visit group_roadmap_path(group)
execute_script("gon.roadmap_epics_limit = 1;")
end
describe 'roadmap page' do
it 'renders warning callout banner' do
page.within('.content-wrapper .content') do
expect(page).to have_selector('[data-testid="epics_limit_callout"]', count: 1)
expect(find('[data-testid="epics_limit_callout"]')).to have_content 'Some of your epics might not be visible Roadmaps can display up to 1,000 epics. These appear in your selected sort order.'
end
page.within('[data-testid="epics_limit_callout"]') do
expect(find_link('Learn more')[:href]).to eq("https://docs.gitlab.com/ee/user/group/roadmap/")
end
end
it 'is removed after dismissal and even after reload' do
page.within('[data-testid="epics_limit_callout"]') do
find('.gl-dismiss-btn').click
end
expect(page).not_to have_selector('[data-testid="epics_limit_callout"]')
refresh
expect(page).not_to have_selector('[data-testid="epics_limit_callout"]')
end
end
end
end
import { shallowMount } from '@vue/test-utils';
import CurrentDayIndicator from 'ee/roadmap/components/current_day_indicator.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import {
getTimeframeForQuartersView,
getTimeframeForMonthsView,
getTimeframeForWeeksView,
} from 'ee/roadmap/utils/roadmap_utils';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import { mockTimeframeInitialDate } from 'ee_jest/roadmap/mock_data';
const mockTimeframeQuarters = getTimeframeForQuartersView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeWeeks = getTimeframeForWeeksView(mockTimeframeInitialDate);
const mockTimeframeQuarters = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.THREE_YEARS,
presetType: PRESET_TYPES.QUARTERS,
initialDate: mockTimeframeInitialDate,
});
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
const mockTimeframeWeeks = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_QUARTER,
presetType: PRESET_TYPES.WEEKS,
initialDate: mockTimeframeInitialDate,
});
const createComponent = () =>
shallowMount(CurrentDayIndicator, {
......
......@@ -3,9 +3,9 @@ import { mount } from '@vue/test-utils';
import EpicItem from 'ee/roadmap/components/epic_item.vue';
import EpicItemContainer from 'ee/roadmap/components/epic_item_container.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import createStore from 'ee/roadmap/store';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import {
mockTimeframeInitialDate,
......@@ -15,7 +15,11 @@ import {
let store;
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
const createComponent = ({
presetType = PRESET_TYPES.MONTHS,
......
......@@ -6,9 +6,9 @@ import CurrentDayIndicator from 'ee/roadmap/components/current_day_indicator.vue
import EpicItemComponent from 'ee/roadmap/components/epic_item.vue';
import EpicItemContainer from 'ee/roadmap/components/epic_item_container.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import createStore from 'ee/roadmap/store';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import {
mockTimeframeInitialDate,
......@@ -27,7 +27,11 @@ jest.mock('lodash/delay', () =>
let store;
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
const createComponent = ({
presetType = PRESET_TYPES.MONTHS,
......
import { GlPopover, GlProgressBar } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import EpicItemTimeline from 'ee/roadmap/components/epic_item_timeline.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import { mockTimeframeInitialDate, mockFormattedEpic } from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
const createComponent = ({
epic = mockFormattedEpic,
......
import { shallowMount } from '@vue/test-utils';
import EpicsListEmpty from 'ee/roadmap/components/epics_list_empty.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import {
getTimeframeForQuartersView,
getTimeframeForWeeksView,
getTimeframeForMonthsView,
} from 'ee/roadmap/utils/roadmap_utils';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import { mockTimeframeInitialDate, mockSvgPath } from 'ee_jest/roadmap/mock_data';
import { TEST_HOST } from 'helpers/test_constants';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
......@@ -13,9 +9,21 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper';
const TEST_EPICS_PATH = '/epics';
const TEST_NEW_EPIC_PATH = '/epics/new';
const mockTimeframeQuarters = getTimeframeForQuartersView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeWeeks = getTimeframeForWeeksView(mockTimeframeInitialDate);
const mockTimeframeQuarters = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.THREE_YEARS,
presetType: PRESET_TYPES.QUARTERS,
initialDate: mockTimeframeInitialDate,
});
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
const mockTimeframeWeeks = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_QUARTER,
presetType: PRESET_TYPES.WEEKS,
initialDate: mockTimeframeInitialDate,
});
describe('ee/roadmap/components/epics_list_empty.vue', () => {
let wrapper;
......@@ -78,7 +86,7 @@ describe('ee/roadmap/components/epics_list_empty.vue', () => {
});
expect(findSubTitle().text()).toBe(
'To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from Jul 1, 2017 to Mar 31, 2019.',
'To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from Jul 1, 2016 to Jun 30, 2019.',
);
});
......@@ -91,7 +99,7 @@ describe('ee/roadmap/components/epics_list_empty.vue', () => {
});
expect(findSubTitle().text()).toBe(
'To widen your search, change or remove filters; from Jul 1, 2017 to Mar 31, 2019.',
'To widen your search, change or remove filters; from Jul 1, 2016 to Jun 30, 2019.',
);
});
});
......@@ -103,7 +111,7 @@ describe('ee/roadmap/components/epics_list_empty.vue', () => {
});
expect(findSubTitle().text()).toBe(
'To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from Nov 1, 2017 to Jun 30, 2018.',
'To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from Jan 1 to Dec 31, 2018.',
);
});
......@@ -114,7 +122,7 @@ describe('ee/roadmap/components/epics_list_empty.vue', () => {
});
expect(findSubTitle().text()).toBe(
'To widen your search, change or remove filters; from Nov 1, 2017 to Jun 30, 2018.',
'To widen your search, change or remove filters; from Jan 1 to Dec 31, 2018.',
);
});
});
......@@ -135,7 +143,7 @@ describe('ee/roadmap/components/epics_list_empty.vue', () => {
});
expect(findSubTitle().text()).toBe(
'To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from Dec 17, 2017 to Feb 9, 2018.',
'To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from Dec 31, 2017 to Apr 6, 2018.',
);
});
......@@ -148,7 +156,7 @@ describe('ee/roadmap/components/epics_list_empty.vue', () => {
});
expect(findSubTitle().text()).toBe(
'To widen your search, change or remove filters; from Dec 17, 2017 to Feb 15, 2018.',
'To widen your search, change or remove filters; from Dec 31, 2017 to Apr 12, 2018.',
);
});
});
......
......@@ -4,6 +4,7 @@ import { createLocalVue } from '@vue/test-utils';
import EpicItem from 'ee/roadmap/components/epic_item.vue';
import EpicsListSection from 'ee/roadmap/components/epics_list_section.vue';
import {
DATE_RANGES,
PRESET_TYPES,
EPIC_DETAILS_CELL_WIDTH,
TIMELINE_CELL_MIN_WIDTH,
......@@ -11,7 +12,7 @@ import {
import createStore from 'ee/roadmap/store';
import { REQUEST_EPICS_FOR_NEXT_PAGE } from 'ee/roadmap/store/mutation_types';
import { scrollToCurrentDay } from 'ee/roadmap/utils/epic_utils';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import {
mockFormattedChildEpic1,
mockFormattedChildEpic2,
......@@ -30,7 +31,11 @@ jest.mock('ee/roadmap/utils/epic_utils', () => ({
scrollToCurrentDay: jest.fn(),
}));
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
const store = createStore();
store.dispatch('setInitialData', {
currentGroupId: mockGroupId,
......
......@@ -3,18 +3,22 @@ import Vue from 'vue';
import milestoneItemComponent from 'ee/roadmap/components/milestone_item.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import { mockTimeframeInitialDate, mockMilestone2 } from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.THREE_YEARS,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
const createComponent = ({
presetType = PRESET_TYPES.MONTHS,
milestone = mockMilestone2,
timeframe = mockTimeframeMonths,
timeframeItem = mockTimeframeMonths[0],
timeframeItem = mockTimeframeMonths[16], // timeframe item where milestone begins
}) => {
const Component = Vue.extend(milestoneItemComponent);
......
......@@ -2,12 +2,16 @@ import { shallowMount } from '@vue/test-utils';
import MilestoneItem from 'ee/roadmap/components/milestone_item.vue';
import MilestoneTimelineComponent from 'ee/roadmap/components/milestone_timeline.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import { mockTimeframeInitialDate, mockMilestone2, mockGroupId } from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
describe('MilestoneTimelineComponent', () => {
let wrapper;
......
......@@ -3,13 +3,14 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import MilestoneTimeline from 'ee/roadmap/components/milestone_timeline.vue';
import milestonesListSectionComponent from 'ee/roadmap/components/milestones_list_section.vue';
import {
DATE_RANGES,
PRESET_TYPES,
EPIC_DETAILS_CELL_WIDTH,
TIMELINE_CELL_MIN_WIDTH,
} from 'ee/roadmap/constants';
import createStore from 'ee/roadmap/store';
import { scrollToCurrentDay } from 'ee/roadmap/utils/epic_utils';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import {
mockTimeframeInitialDate,
mockGroupId,
......@@ -37,7 +38,11 @@ describe('MilestonesListSectionComponent', () => {
let wrapper;
let store;
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
const findMilestoneCount = () => wrapper.find('[data-testid="count"]');
const findMilestoneCountTooltip = () => getBinding(findMilestoneCount().element, 'gl-tooltip');
const findExpandButtonContainer = () => wrapper.find('[data-testid="expandButton"]');
......
import Vue from 'vue';
import MonthsHeaderItemComponent from 'ee/roadmap/components/preset_months/months_header_item.vue';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from '../../mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
const mockTimeframeIndex = 0;
const createComponent = ({
......@@ -46,7 +51,7 @@ describe('MonthsHeaderItemComponent', () => {
it('returns string containing Year and Month for current timeline header item', () => {
vm = createComponent({});
expect(vm.timelineHeaderLabel).toBe('2017 Nov');
expect(vm.$el.innerText.trim()).toContain('2018 Jan');
});
it('returns string containing only Month for current timeline header item when previous header contained Year', () => {
......@@ -55,7 +60,7 @@ describe('MonthsHeaderItemComponent', () => {
timeframeItem: mockTimeframeMonths[mockTimeframeIndex + 1],
});
expect(vm.timelineHeaderLabel).toBe('Dec');
expect(vm.$el.innerText.trim()).toContain('Feb');
});
});
......@@ -107,7 +112,7 @@ describe('MonthsHeaderItemComponent', () => {
const itemLabelEl = vm.$el.querySelector('.item-label');
expect(itemLabelEl).not.toBeNull();
expect(itemLabelEl.innerText.trim()).toBe('2017 Nov');
expect(itemLabelEl.innerText.trim()).toBe('2018 Jan');
});
});
});
import Vue from 'vue';
import MonthsHeaderSubItemComponent from 'ee/roadmap/components/preset_months/months_header_sub_item.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES, DATE_RANGES } from 'ee/roadmap/constants';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from '../../mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
const createComponent = ({
currentDate = mockTimeframeMonths[0],
......
import Vue from 'vue';
import QuartersHeaderItemComponent from 'ee/roadmap/components/preset_quarters/quarters_header_item.vue';
import { getTimeframeForQuartersView } from 'ee/roadmap/utils/roadmap_utils';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from '../../mock_data';
const mockTimeframeIndex = 0;
const mockTimeframeQuarters = getTimeframeForQuartersView(mockTimeframeInitialDate);
const mockTimeframeQuarters = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.THREE_YEARS,
presetType: PRESET_TYPES.QUARTERS,
initialDate: mockTimeframeInitialDate,
});
const createComponent = ({
timeframeIndex = mockTimeframeIndex,
......@@ -56,7 +61,7 @@ describe('QuartersHeaderItemComponent', () => {
it('returns string containing Year and Quarter for current timeline header item', () => {
vm = createComponent({});
expect(vm.timelineHeaderLabel).toBe('2017 Q3');
expect(vm.$el.innerText.trim()).toContain('2016 Q3');
});
it('returns string containing only Quarter for current timeline header item when previous header contained Year', () => {
......@@ -65,7 +70,7 @@ describe('QuartersHeaderItemComponent', () => {
timeframeItem: mockTimeframeQuarters[mockTimeframeIndex + 2],
});
expect(vm.timelineHeaderLabel).toBe('2018 Q1');
expect(vm.$el.innerText.trim()).toContain('2017 Q1');
});
});
......@@ -118,7 +123,7 @@ describe('QuartersHeaderItemComponent', () => {
const itemLabelEl = vm.$el.querySelector('.item-label');
expect(itemLabelEl).not.toBeNull();
expect(itemLabelEl.innerText.trim()).toBe('2017 Q3');
expect(itemLabelEl.innerText.trim()).toBe('2016 Q3');
});
});
});
import Vue from 'vue';
import QuartersHeaderSubItemComponent from 'ee/roadmap/components/preset_quarters/quarters_header_sub_item.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForQuartersView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES, DATE_RANGES } from 'ee/roadmap/constants';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from '../../mock_data';
const mockTimeframeQuarters = getTimeframeForQuartersView(mockTimeframeInitialDate);
const mockTimeframeQuarters = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.THREE_YEARS,
presetType: PRESET_TYPES.QUARTERS,
initialDate: mockTimeframeInitialDate,
});
const createComponent = ({
currentDate = mockTimeframeQuarters[0].range[1],
......
import Vue from 'vue';
import WeeksHeaderItemComponent from 'ee/roadmap/components/preset_weeks/weeks_header_item.vue';
import { getTimeframeForWeeksView } from 'ee/roadmap/utils/roadmap_utils';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from '../../mock_data';
const mockTimeframeIndex = 0;
const mockTimeframeWeeks = getTimeframeForWeeksView(mockTimeframeInitialDate);
const mockTimeframeWeeks = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_QUARTER,
presetType: PRESET_TYPES.WEEKS,
initialDate: mockTimeframeInitialDate,
});
const createComponent = ({
timeframeIndex = mockTimeframeIndex,
......@@ -42,9 +47,8 @@ describe('WeeksHeaderItemComponent', () => {
describe('computed', () => {
describe('lastDayOfCurrentWeek', () => {
it('returns date object representing last day of the week as set in `timeframeItem`', () => {
expect(vm.lastDayOfCurrentWeek.getDate()).toBe(
mockTimeframeWeeks[mockTimeframeIndex].getDate() + 7,
);
vm = createComponent({});
expect(vm.lastDayOfCurrentWeek.getDate()).toBe(7);
});
});
......@@ -52,7 +56,7 @@ describe('WeeksHeaderItemComponent', () => {
it('returns string containing Year, Month and Date for first timeframe item of the entire timeframe', () => {
vm = createComponent({});
expect(vm.timelineHeaderLabel).toBe('2017 Dec 17');
expect(vm.$el.innerText.trim()).toContain('2017 Dec 31');
});
it('returns string containing Year, Month and Date for timeframe item when it is first week of the year', () => {
......@@ -66,11 +70,11 @@ describe('WeeksHeaderItemComponent', () => {
it('returns string containing only Month and Date timeframe item when it is somewhere in the middle of timeframe', () => {
vm = createComponent({
timeframeIndex: mockTimeframeIndex + 1,
timeframeItem: mockTimeframeWeeks[mockTimeframeIndex + 1],
timeframeIndex: mockTimeframeIndex + 2,
timeframeItem: mockTimeframeWeeks[mockTimeframeIndex + 2],
});
expect(vm.timelineHeaderLabel).toBe('Dec 24');
expect(vm.timelineHeaderLabel).toBe('Jan 14');
});
});
......@@ -116,7 +120,7 @@ describe('WeeksHeaderItemComponent', () => {
const itemLabelEl = vm.$el.querySelector('.item-label');
expect(itemLabelEl).not.toBeNull();
expect(itemLabelEl.innerText.trim()).toBe('2017 Dec 17');
expect(itemLabelEl.innerText.trim()).toBe('2017 Dec 31');
});
});
});
import Vue from 'vue';
import WeeksHeaderSubItemComponent from 'ee/roadmap/components/preset_weeks/weeks_header_sub_item.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForWeeksView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES, DATE_RANGES } from 'ee/roadmap/constants';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from '../../mock_data';
const mockTimeframeWeeks = getTimeframeForWeeksView(mockTimeframeInitialDate);
const mockTimeframeWeeks = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_QUARTER,
presetType: PRESET_TYPES.WEEKS,
initialDate: mockTimeframeInitialDate,
});
const createComponent = ({
currentDate = mockTimeframeWeeks[0],
......
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Cookies from 'js-cookie';
import Vuex from 'vuex';
import EpicsListEmpty from 'ee/roadmap/components/epics_list_empty.vue';
import RoadmapApp from 'ee/roadmap/components/roadmap_app.vue';
import RoadmapFilters from 'ee/roadmap/components/roadmap_filters.vue';
import RoadmapShell from 'ee/roadmap/components/roadmap_shell.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { PRESET_TYPES, DATE_RANGES } from 'ee/roadmap/constants';
import createStore from 'ee/roadmap/store';
import * as types from 'ee/roadmap/store/mutation_types';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import {
basePath,
mockFormattedEpic,
mockFormattedChildEpic2,
mockGroupId,
mockSortedBy,
mockSvgPath,
......@@ -32,7 +30,11 @@ describe('RoadmapApp', () => {
const epics = [mockFormattedEpic];
const hasFiltersApplied = true;
const presetType = PRESET_TYPES.MONTHS;
const timeframe = getTimeframeForMonthsView(mockTimeframeInitialDate);
const timeframe = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
const createComponent = (mountFunction = shallowMount) => {
return mountFunction(RoadmapApp, {
......@@ -151,31 +153,4 @@ describe('RoadmapApp', () => {
});
});
});
describe('roadmap epics limit warning', () => {
beforeEach(() => {
wrapper = createComponent();
store.commit(types.RECEIVE_EPICS_SUCCESS, {
epics: [mockFormattedEpic, mockFormattedChildEpic2],
});
window.gon.roadmap_epics_limit = 1;
});
it('displays warning when epics limit is reached', () => {
expect(wrapper.find(GlAlert).exists()).toBe(true);
expect(wrapper.find(GlAlert).text()).toContain(
'Roadmaps can display up to 1,000 epics. These appear in your selected sort order.',
);
});
it('sets epics_limit_warning_dismissed cookie to true when dismissing alert', () => {
wrapper.find(GlAlert).vm.$emit('dismiss');
expect(Cookies.get('epics_limit_warning_dismissed')).toBe('true');
return wrapper.vm.$nextTick(() => {
expect(wrapper.find(GlAlert).exists()).toBe(false);
});
});
});
});
......@@ -5,7 +5,7 @@ import Vuex from 'vuex';
import RoadmapFilters from 'ee/roadmap/components/roadmap_filters.vue';
import { PRESET_TYPES, EPICS_STATES, DATE_RANGES } from 'ee/roadmap/constants';
import createStore from 'ee/roadmap/store';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import {
mockSortedBy,
mockTimeframeInitialDate,
......@@ -36,10 +36,13 @@ const createComponent = ({
groupFullPath = 'gitlab-org',
listEpicsPath = '/groups/gitlab-org/-/epics',
groupMilestonesPath = '/groups/gitlab-org/-/milestones.json',
timeframe = getTimeframeForMonthsView(mockTimeframeInitialDate),
timeframe = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.THREE_YEARS,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
}),
filterParams = {},
roadmapDaterangeFilter = false,
timeframeRangeType = DATE_RANGES.CURRENT_QUARTER,
timeframeRangeType = DATE_RANGES.THREE_YEARS,
} = {}) => {
const localVue = createLocalVue();
const store = createStore();
......@@ -61,9 +64,6 @@ const createComponent = ({
groupFullPath,
groupMilestonesPath,
listEpicsPath,
glFeatures: {
roadmapDaterangeFilter,
},
},
props: {
timeframeRangeType,
......@@ -130,16 +130,12 @@ describe('RoadmapFilters', () => {
updateHistory({ url: TEST_HOST, title: document.title, replace: true });
});
it('renders roadmap layout switching buttons', () => {
const layoutSwitches = wrapper.find(GlSegmentedControl);
it('switching layout using roadmap layout switching buttons causes page to reload with selected layout', async () => {
wrapper.setData({ selectedDaterange: DATE_RANGES.THREE_YEARS });
expect(layoutSwitches.exists()).toBe(true);
expect(layoutSwitches.props('checked')).toBe(PRESET_TYPES.MONTHS);
expect(layoutSwitches.props('options')).toEqual([quarters, months, weeks]);
});
await wrapper.vm.$nextTick();
it('switching layout using roadmap layout switching buttons causes page to reload with selected layout', () => {
wrapper.find(GlSegmentedControl).vm.$emit('input', PRESET_TYPES.OPENED);
wrapper.findComponent(GlSegmentedControl).vm.$emit('input', PRESET_TYPES.OPENED);
expect(mergeUrlParams).toHaveBeenCalledWith(
expect.objectContaining({ layout: PRESET_TYPES.OPENED }),
......@@ -312,7 +308,7 @@ describe('RoadmapFilters', () => {
});
});
describe('when roadmapDaterangeFilter feature flag is enabled', () => {
describe('daterange filtering', () => {
let wrapperWithDaterangeFilter;
const availableRanges = [
{ text: 'This quarter', value: DATE_RANGES.CURRENT_QUARTER },
......@@ -322,7 +318,6 @@ describe('RoadmapFilters', () => {
beforeEach(async () => {
wrapperWithDaterangeFilter = createComponent({
roadmapDaterangeFilter: true,
timeframeRangeType: DATE_RANGES.CURRENT_QUARTER,
});
......
......@@ -7,10 +7,10 @@ import MonthsHeaderItem from 'ee/roadmap/components/preset_months/months_header_
import MonthsHeaderSubItem from 'ee/roadmap/components/preset_months/months_header_sub_item.vue';
import RoadmapShell from 'ee/roadmap/components/roadmap_shell.vue';
import RoadmapTimelineSection from 'ee/roadmap/components/roadmap_timeline_section.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import eventHub from 'ee/roadmap/event_hub';
import createStore from 'ee/roadmap/store';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import {
mockEpic,
......@@ -19,7 +19,11 @@ import {
mockMilestone,
} from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
describe('RoadmapShell', () => {
const localVue = createLocalVue();
......
import Vue from 'vue';
import roadmapTimelineSectionComponent from 'ee/roadmap/components/roadmap_timeline_section.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import eventHub from 'ee/roadmap/event_hub';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import { mockEpic, mockTimeframeInitialDate } from 'ee_jest/roadmap/mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
const createComponent = ({
presetType = PRESET_TYPES.MONTHS,
......@@ -46,7 +50,7 @@ describe('RoadmapTimelineSectionComponent', () => {
it('returns object containing `width` with value based on epic details cell width, timeline cell width and timeframe length', () => {
expect(vm.sectionContainerStyles).toEqual(
expect.objectContaining({
width: '1760px',
width: '2480px', // We now have fixed columns in timeframe.
}),
);
});
......
import { shallowMount } from '@vue/test-utils';
import EpicItemTimelineComponent from 'ee/roadmap/components/epic_item_timeline.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import { mockTimeframeInitialDate, mockEpic } from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
describe('MonthsPresetMixin', () => {
let wrapper;
......@@ -130,28 +134,24 @@ describe('MonthsPresetMixin', () => {
describe('getTimelineBarWidthForMonths', () => {
it('returns calculated width value based on Epic.startDate and Epic.endDate', () => {
wrapper = createComponent({
timeframeItem: mockTimeframeMonths[1],
timeframeItem: mockTimeframeMonths[0],
epic: {
...mockEpic,
startDate: new Date(2017, 11, 15), // Dec 15, 2017
endDate: new Date(2018, 1, 15), // Feb 15, 2018
startDate: new Date(2018, 0, 1), // Jan 01, 2018
endDate: new Date(2018, 2, 15), // Mar 15, 2018
},
});
/*
The epic timeline bar width calculation:
- The width of the bar should account for 31 - 15 = 16 days from December.
- The width of the bar should fully account for all of January (31 days).
- The width of the bar should account for only 15 days
Dec: 16 days / 31 days * 180px ~= 92.9px
+ Jan: 31 days = 180px
+ Feb: 15 days / 28 days * 180px ~= 96.43px
Jan: 31 days = 180px
+ Feb: 28 days = 180px
+ Mar: (180px / 31 days) * 15 days ~= 87.15px
---------------------------------------------------
Total ~= 369px
Total ~= 447px
*/
const expectedTimelineBarWidth = 369; // in px.
const expectedTimelineBarWidth = 447; // in px.
expect(Math.floor(wrapper.vm.getTimelineBarWidthForMonths())).toBe(
expectedTimelineBarWidth,
);
......
import { shallowMount } from '@vue/test-utils';
import EpicItemTimelineComponent from 'ee/roadmap/components/epic_item_timeline.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForQuartersView } from 'ee/roadmap/utils/roadmap_utils';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import { mockTimeframeInitialDate, mockEpic } from 'ee_jest/roadmap/mock_data';
const mockTimeframeQuarters = getTimeframeForQuartersView(mockTimeframeInitialDate);
const mockTimeframeQuarters = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.THREE_YEARS,
presetType: PRESET_TYPES.QUARTERS,
initialDate: mockTimeframeInitialDate,
});
describe('QuartersPresetMixin', () => {
let wrapper;
......
import { shallowMount } from '@vue/test-utils';
import EpicItemTimelineComponent from 'ee/roadmap/components/epic_item_timeline.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForWeeksView } from 'ee/roadmap/utils/roadmap_utils';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import { mockTimeframeInitialDate, mockEpic } from 'ee_jest/roadmap/mock_data';
const mockTimeframeWeeks = getTimeframeForWeeksView(mockTimeframeInitialDate);
const mockTimeframeWeeks = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_QUARTER,
presetType: PRESET_TYPES.WEEKS,
initialDate: mockTimeframeInitialDate,
});
describe('WeeksPresetMixin', () => {
let wrapper;
......@@ -59,9 +63,9 @@ describe('WeeksPresetMixin', () => {
wrapper = createComponent();
const lastDayOfWeek = wrapper.vm.getLastDayOfWeek(mockTimeframeWeeks[0]);
expect(lastDayOfWeek.getDate()).toBe(23);
expect(lastDayOfWeek.getMonth()).toBe(11);
expect(lastDayOfWeek.getFullYear()).toBe(2017);
expect(lastDayOfWeek.getDate()).toBe(6);
expect(lastDayOfWeek.getMonth()).toBe(0);
expect(lastDayOfWeek.getFullYear()).toBe(2018);
});
});
......@@ -197,7 +201,7 @@ describe('WeeksPresetMixin', () => {
approximately 154px ^
~ approximately 154px
*/
const expectedTimelineBarWidth = 848; // in px;
const expectedTimelineBarWidth = 488; // in px;
expect(Math.floor(wrapper.vm.getTimelineBarWidthForWeeks())).toBe(expectedTimelineBarWidth);
});
......
import { GlFilteredSearchToken } from '@gitlab/ui';
import {
getTimeframeForWeeksView,
getTimeframeForMonthsView,
getTimeframeForQuartersView,
} from 'ee/roadmap/utils/roadmap_utils';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import { dateFromString } from 'helpers/datetime_helpers';
import {
......@@ -137,7 +134,11 @@ export const mockWeekly = {
Oct 18 2020, Oct 25 2020, Nov 1 2020,
Nov 8 2020 ]
*/
timeframe: getTimeframeForWeeksView(OCT_11_2020),
timeframe: getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_QUARTER,
presetType: PRESET_TYPES.WEEKS,
initialDate: OCT_11_2020,
}),
};
const DEC_1_2020 = dateFromString('Dec 1 2020');
......@@ -150,7 +151,11 @@ export const mockMonthly = {
Jan 1 2021, Feb 1 2021, Mar 1 2021,
Apr 1 2021, May 31 2021 ]
*/
timeframe: getTimeframeForMonthsView(DEC_1_2020),
timeframe: getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: DEC_1_2020,
}),
};
const DEC_25_2020 = dateFromString('Dec 25 2020');
......@@ -170,7 +175,11 @@ export const mockQuarterly = {
{ 2021 Q1 }, { 2021 Q2 }, { 2021 Q3 },
{ 2021 Q4 } ]
*/
timeframe: getTimeframeForQuartersView(DEC_25_2020),
timeframe: getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.THREE_YEARS,
presetType: PRESET_TYPES.QUARTERS,
initialDate: DEC_25_2020,
}),
};
export const mockEpic = {
......@@ -269,7 +278,7 @@ export const mockFormattedChildEpic2 = {
export const mockFormattedEpic = {
...mockRawEpic,
startDate: new Date(2017, 10, 1),
startDate: new Date(2018, 0, 1),
originalStartDate: new Date(2017, 5, 26),
endDate: new Date(2018, 2, 10),
originalEndDate: new Date(2018, 2, 10),
......@@ -283,9 +292,9 @@ export const mockFormattedEpic2 = {
...mockRawEpic2,
isChildEpic: false,
newEpic: undefined,
startDateOutOfRange: false,
startDateOutOfRange: true,
endDateOutOfRange: false,
startDate: new Date(2017, 11, 31),
startDate: new Date(2018, 0, 1),
originalStartDate: new Date(2017, 11, 31),
endDate: new Date(2018, 1, 15),
originalEndDate: new Date(2018, 1, 15),
......
import MockAdapter from 'axios-mock-adapter';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { DATE_RANGES, PRESET_TYPES } from 'ee/roadmap/constants';
import groupMilestones from 'ee/roadmap/queries/groupMilestones.query.graphql';
import * as actions from 'ee/roadmap/store/actions';
import * as types from 'ee/roadmap/store/mutation_types';
import defaultState from 'ee/roadmap/store/state';
import * as epicUtils from 'ee/roadmap/utils/epic_utils';
import * as roadmapItemUtils from 'ee/roadmap/utils/roadmap_item_utils';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { getTimeframeForRangeType } from 'ee/roadmap/utils/roadmap_utils';
import testAction from 'helpers/vuex_action_helper';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
......@@ -33,7 +33,11 @@ import {
jest.mock('~/flash');
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
describe('Roadmap Vuex Actions', () => {
const timeframeStartDate = mockTimeframeMonths[0];
......@@ -458,8 +462,8 @@ describe('Roadmap Vuex Actions', () => {
fullPath: 'gitlab-org',
state: mockState.milestonessState,
timeframe: {
start: '2017-11-01',
end: '2018-06-30',
start: '2018-01-01',
end: '2018-12-31',
},
includeDescendants: true,
};
......@@ -551,9 +555,9 @@ describe('Roadmap Vuex Actions', () => {
payload: [
{
...mockFormattedMilestone,
startDateOutOfRange: false,
startDateOutOfRange: true,
endDateOutOfRange: false,
startDate: new Date(2017, 11, 31),
startDate: new Date(2018, 0, 1),
originalStartDate: new Date(2017, 11, 31),
endDate: new Date(2018, 1, 15),
originalEndDate: new Date(2018, 1, 15),
......
......@@ -212,30 +212,6 @@ describe('Roadmap Store Mutations', () => {
});
});
describe('PREPEND_TIMEFRAME', () => {
it('Should set extendedTimeframe to provided extendedTimeframe param and prepend it to timeframe array in state', () => {
state.timeframe.push('foo');
const extendedTimeframe = ['bar'];
mutations[types.PREPEND_TIMEFRAME](state, extendedTimeframe);
expect(state.extendedTimeframe).toBe(extendedTimeframe);
expect(state.timeframe[0]).toBe(extendedTimeframe[0]);
});
});
describe('APPEND_TIMEFRAME', () => {
it('Should set extendedTimeframe to provided extendedTimeframe param and append it to timeframe array in state', () => {
state.timeframe.push('foo');
const extendedTimeframe = ['bar'];
mutations[types.APPEND_TIMEFRAME](state, extendedTimeframe);
expect(state.extendedTimeframe).toBe(extendedTimeframe);
expect(state.timeframe[1]).toBe(extendedTimeframe[0]);
});
});
describe('SET_MILESTONES', () => {
it('Should provided milestones array in state', () => {
const milestones = [{ id: 1 }, { id: 2 }];
......
......@@ -161,11 +161,11 @@ describe('timeframeEndDate', () => {
/*
Note: there are inconsistencies in how timeframes are generated.
A monthly timeframe generated with roadmap_util's getTimeframeForMonthsView function -
A monthly timeframe generated with roadmap_util's getTimeframeForRangeType function -
will always set its last item to the ending date for that month.
E.g., [ Oct 1, Nov 1, Dec 31 ]
The same is true of quarterly timeframes generated with getTimeframeForQuarterlyView
The same is true of quarterly timeframes generated with getTimeframeForRangeType
E.g., [ ..., { range: [ Oct 1, Nov 1, Dec 31 ] }]
In comparison, a weekly timeframe won't have its last item set to the ending date for the week.
......@@ -176,9 +176,9 @@ describe('timeframeEndDate', () => {
*/
it.each`
presetType | endDate | timeframe
${PRESET_TYPES.QUARTERS} | ${dateFromString('Dec 31 2021')} | ${mockQuarterly.timeframe}
${PRESET_TYPES.MONTHS} | ${dateFromString('May 31 2021')} | ${mockMonthly.timeframe}
${PRESET_TYPES.WEEKS} | ${dateFromString('Nov 15 2020')} | ${mockWeekly.timeframe}
${PRESET_TYPES.QUARTERS} | ${dateFromString('May 31 2022')} | ${mockQuarterly.timeframe}
${PRESET_TYPES.MONTHS} | ${dateFromString('Dec 31 2020')} | ${mockMonthly.timeframe}
${PRESET_TYPES.WEEKS} | ${dateFromString('Jan 03 2021')} | ${mockWeekly.timeframe}
`(
`should return ending date for the timeframe range array when preset type is $presetType`,
({ presetType, endDate, timeframe }) => {
......
import { PRESET_TYPES, DATE_RANGES } from 'ee/roadmap/constants';
import {
getTimeframeForQuartersView,
extendTimeframeForQuartersView,
getTimeframeForMonthsView,
extendTimeframeForMonthsView,
getTimeframeForWeeksView,
extendTimeframeForWeeksView,
extendTimeframeForAvailableWidth,
getEpicsTimeframeRange,
getWeeksForDates,
getTimeframeForRangeType,
......@@ -14,299 +7,23 @@ import {
getPresetTypeForTimeframeRangeType,
} from 'ee/roadmap/utils/roadmap_utils';
import {
mockTimeframeInitialDate,
mockTimeframeQuartersPrepend,
mockTimeframeQuartersAppend,
mockTimeframeMonthsPrepend,
mockTimeframeMonthsAppend,
mockTimeframeWeeksPrepend,
mockTimeframeWeeksAppend,
mockUnsortedEpics,
} from '../mock_data';
const mockTimeframeQuarters = getTimeframeForQuartersView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeWeeks = getTimeframeForWeeksView(mockTimeframeInitialDate);
const getDateString = (date) => date.toISOString().split('T')[0];
describe('getTimeframeForQuartersView', () => {
let timeframe;
beforeEach(() => {
timeframe = getTimeframeForQuartersView(new Date(2018, 0, 1));
});
it('returns timeframe with total of 7 quarters', () => {
expect(timeframe).toHaveLength(7);
});
it('each timeframe item has `quarterSequence`, `year` and `range` present', () => {
const timeframeItem = timeframe[0];
expect(timeframeItem.quarterSequence).toEqual(expect.any(Number));
expect(timeframeItem.year).toEqual(expect.any(Number));
expect(Array.isArray(timeframeItem.range)).toBe(true);
});
it('first timeframe item refers to 2 quarters prior to current quarter', () => {
const timeframeItem = timeframe[0];
const expectedQuarter = {
0: { month: 6, date: 1 }, // 1 Jul 2017
1: { month: 7, date: 1 }, // 1 Aug 2017
2: { month: 8, date: 30 }, // 30 Sep 2017
};
expect(timeframeItem.quarterSequence).toEqual(3);
expect(timeframeItem.year).toEqual(2017);
timeframeItem.range.forEach((month, index) => {
expect(month.getFullYear()).toBe(2017);
expect(expectedQuarter[index].month).toBe(month.getMonth());
expect(expectedQuarter[index].date).toBe(month.getDate());
});
});
import { mockTimeframeInitialDate, mockUnsortedEpics } from '../mock_data';
it('last timeframe item refers to 5th quarter from current quarter', () => {
const timeframeItem = timeframe[timeframe.length - 1];
const expectedQuarter = {
0: { month: 0, date: 1 }, // 1 Jan 2019
1: { month: 1, date: 1 }, // 1 Feb 2019
2: { month: 2, date: 31 }, // 31 Mar 2019
};
expect(timeframeItem.quarterSequence).toEqual(1);
expect(timeframeItem.year).toEqual(2019);
timeframeItem.range.forEach((month, index) => {
expect(month.getFullYear()).toBe(2019);
expect(expectedQuarter[index].month).toBe(month.getMonth());
expect(expectedQuarter[index].date).toBe(month.getDate());
});
});
});
describe('extendTimeframeForQuartersView', () => {
it('returns extended timeframe into the past from current timeframe startDate', () => {
const initialDate = mockTimeframeQuarters[0].range[0];
const extendedTimeframe = extendTimeframeForQuartersView(initialDate, -9);
expect(extendedTimeframe).toHaveLength(mockTimeframeQuartersPrepend.length);
extendedTimeframe.forEach((timeframeItem, index) => {
expect(timeframeItem.year).toBe(mockTimeframeQuartersPrepend[index].year);
expect(timeframeItem.quarterSequence).toBe(
mockTimeframeQuartersPrepend[index].quarterSequence,
);
timeframeItem.range.forEach((rangeItem, j) => {
expect(rangeItem.getTime()).toBe(mockTimeframeQuartersPrepend[index].range[j].getTime());
});
});
});
it('returns extended timeframe into the future from current timeframe endDate', () => {
const initialDate = mockTimeframeQuarters[mockTimeframeQuarters.length - 1].range[2];
const extendedTimeframe = extendTimeframeForQuartersView(initialDate, 9);
expect(extendedTimeframe).toHaveLength(mockTimeframeQuartersAppend.length);
extendedTimeframe.forEach((timeframeItem, index) => {
expect(timeframeItem.year).toBe(mockTimeframeQuartersAppend[index].year);
expect(timeframeItem.quarterSequence).toBe(
mockTimeframeQuartersAppend[index].quarterSequence,
);
timeframeItem.range.forEach((rangeItem, j) => {
expect(rangeItem.getTime()).toBe(mockTimeframeQuartersAppend[index].range[j].getTime());
});
});
});
});
describe('getTimeframeForMonthsView', () => {
let timeframe;
beforeEach(() => {
timeframe = getTimeframeForMonthsView(new Date(2018, 0, 1));
});
it('returns timeframe with total of 8 months', () => {
expect(timeframe).toHaveLength(8);
});
it('first timeframe item refers to 2 months prior to current month', () => {
const timeframeItem = timeframe[0];
const expectedMonth = {
year: 2017,
month: 10,
date: 1,
};
expect(timeframeItem.getFullYear()).toBe(expectedMonth.year);
expect(timeframeItem.getMonth()).toBe(expectedMonth.month);
expect(timeframeItem.getDate()).toBe(expectedMonth.date);
});
it('last timeframe item refers to 6th month from current month', () => {
const timeframeItem = timeframe[timeframe.length - 1];
const expectedMonth = {
year: 2018,
month: 5,
date: 30,
};
expect(timeframeItem.getFullYear()).toBe(expectedMonth.year);
expect(timeframeItem.getMonth()).toBe(expectedMonth.month);
expect(timeframeItem.getDate()).toBe(expectedMonth.date);
});
});
describe('extendTimeframeForMonthsView', () => {
it('returns extended timeframe into the past from current timeframe startDate', () => {
const initialDate = mockTimeframeMonths[0];
const extendedTimeframe = extendTimeframeForMonthsView(initialDate, -8);
expect(extendedTimeframe).toHaveLength(mockTimeframeMonthsPrepend.length);
extendedTimeframe.forEach((timeframeItem, index) => {
expect(timeframeItem.getTime()).toBe(mockTimeframeMonthsPrepend[index].getTime());
});
});
it('returns extended timeframe into the future from current timeframe endDate', () => {
const initialDate = mockTimeframeMonths[mockTimeframeMonths.length - 1];
const extendedTimeframe = extendTimeframeForMonthsView(initialDate, 8);
expect(extendedTimeframe).toHaveLength(mockTimeframeMonthsAppend.length);
extendedTimeframe.forEach((timeframeItem, index) => {
expect(timeframeItem.getTime()).toBe(mockTimeframeMonthsAppend[index].getTime());
});
});
});
describe('getTimeframeForWeeksView', () => {
let timeframe;
beforeEach(() => {
timeframe = getTimeframeForWeeksView(mockTimeframeInitialDate);
});
it('returns timeframe with total of 7 weeks', () => {
expect(timeframe).toHaveLength(7);
});
it('first timeframe item refers to 2 weeks prior to current week', () => {
const timeframeItem = timeframe[0];
const expectedMonth = {
year: 2017,
month: 11,
date: 17,
};
expect(timeframeItem.getFullYear()).toBe(expectedMonth.year);
expect(timeframeItem.getMonth()).toBe(expectedMonth.month);
expect(timeframeItem.getDate()).toBe(expectedMonth.date);
});
it('last timeframe item refers to 5th week from current month', () => {
const timeframeItem = timeframe[timeframe.length - 1];
const expectedMonth = {
year: 2018,
month: 0,
date: 28,
};
expect(timeframeItem.getFullYear()).toBe(expectedMonth.year);
expect(timeframeItem.getMonth()).toBe(expectedMonth.month);
expect(timeframeItem.getDate()).toBe(expectedMonth.date);
});
it('returns timeframe starting on a specific date when provided with additional `length` param', () => {
const initialDate = new Date(2018, 0, 7);
timeframe = getTimeframeForWeeksView(initialDate, 5);
const expectedTimeframe = [
initialDate,
new Date(2018, 0, 14),
new Date(2018, 0, 21),
new Date(2018, 0, 28),
new Date(2018, 1, 4),
];
expect(timeframe).toHaveLength(5);
expectedTimeframe.forEach((timeframeItem, index) => {
expect(timeframeItem.getTime()).toBe(expectedTimeframe[index].getTime());
});
});
});
describe('extendTimeframeForWeeksView', () => {
it('returns extended timeframe into the past from current timeframe startDate', () => {
const extendedTimeframe = extendTimeframeForWeeksView(mockTimeframeWeeks[0], -6); // initialDate: 17 Dec 2017
expect(extendedTimeframe).toHaveLength(mockTimeframeWeeksPrepend.length);
extendedTimeframe.forEach((timeframeItem, index) => {
expect(timeframeItem.getTime()).toBe(mockTimeframeWeeksPrepend[index].getTime());
});
});
it('returns extended timeframe into the future from current timeframe endDate', () => {
const extendedTimeframe = extendTimeframeForWeeksView(
mockTimeframeWeeks[mockTimeframeWeeks.length - 1], // initialDate: 28 Jan 2018
6,
);
expect(extendedTimeframe).toHaveLength(mockTimeframeWeeksAppend.length);
extendedTimeframe.forEach((timeframeItem, index) => {
expect(timeframeItem.getTime()).toBe(mockTimeframeWeeksAppend[index].getTime());
});
});
});
describe('extendTimeframeForAvailableWidth', () => {
let timeframe;
let timeframeStart;
let timeframeEnd;
beforeEach(() => {
timeframe = mockTimeframeMonths.slice();
[timeframeStart] = timeframe;
timeframeEnd = timeframe[timeframe.length - 1];
});
it('should not extend `timeframe` when availableTimeframeWidth is small enough to force horizontal scrollbar to show up', () => {
extendTimeframeForAvailableWidth({
availableTimeframeWidth: 100,
presetType: PRESET_TYPES.MONTHS,
timeframe,
timeframeStart,
timeframeEnd,
});
expect(timeframe).toHaveLength(mockTimeframeMonths.length);
});
it('should extend `timeframe` when availableTimeframeWidth is large enough that it can fit more timeframe items to show up horizontal scrollbar', () => {
extendTimeframeForAvailableWidth({
availableTimeframeWidth: 2000,
presetType: PRESET_TYPES.MONTHS,
timeframe,
timeframeStart,
timeframeEnd,
});
expect(timeframe).toHaveLength(12);
expect(timeframe[0].getTime()).toBe(1504224000000); // 1 Sep 2017
expect(timeframe[timeframe.length - 1].getTime()).toBe(1535673600000); // 31 Aug 2018
});
const mockTimeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: mockTimeframeInitialDate,
});
const getDateString = (date) => date.toISOString().split('T')[0];
describe('getWeeksForDates', () => {
it('returns weeks for given dates', () => {
const weeks = getWeeksForDates(mockTimeframeInitialDate, mockTimeframeMonths[4]);
expect(weeks).toHaveLength(9);
expect(weeks).toHaveLength(18);
expect(getDateString(weeks[0])).toBe('2017-12-31');
expect(getDateString(weeks[4])).toBe('2018-01-28');
expect(getDateString(weeks[8])).toBe('2018-02-25');
expect(getDateString(weeks[7])).toBe('2018-02-18');
expect(getDateString(weeks[17])).toBe('2018-04-29');
});
});
......@@ -408,7 +125,11 @@ describe('getTimeframeForRangeType', () => {
describe('getEpicsTimeframeRange', () => {
it('returns object containing startDate and dueDate based on provided timeframe for Quarters', () => {
const timeframeQuarters = getTimeframeForQuartersView(new Date(2018, 0, 1));
const timeframeQuarters = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.THREE_YEARS,
presetType: PRESET_TYPES.QUARTERS,
initialDate: new Date(2018, 0, 1),
});
const range = getEpicsTimeframeRange({
presetType: PRESET_TYPES.QUARTERS,
timeframe: timeframeQuarters,
......@@ -417,15 +138,19 @@ describe('getEpicsTimeframeRange', () => {
expect(range).toEqual(
expect.objectContaining({
timeframe: {
start: '2017-07-01',
end: '2019-03-31',
start: '2016-07-01',
end: '2019-06-30',
},
}),
);
});
it('returns object containing startDate and dueDate based on provided timeframe for Months', () => {
const timeframeMonths = getTimeframeForMonthsView(new Date(2018, 0, 1));
const timeframeMonths = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_YEAR,
presetType: PRESET_TYPES.MONTHS,
initialDate: new Date(2018, 0, 1),
});
const range = getEpicsTimeframeRange({
presetType: PRESET_TYPES.MONTHS,
timeframe: timeframeMonths,
......@@ -434,15 +159,19 @@ describe('getEpicsTimeframeRange', () => {
expect(range).toEqual(
expect.objectContaining({
timeframe: {
start: '2017-11-01',
end: '2018-06-30',
start: '2018-01-01',
end: '2018-12-31',
},
}),
);
});
it('returns object containing startDate and dueDate based on provided timeframe for Weeks', () => {
const timeframeWeeks = getTimeframeForWeeksView(new Date(2018, 0, 1));
const timeframeWeeks = getTimeframeForRangeType({
timeframeRangeType: DATE_RANGES.CURRENT_QUARTER,
presetType: PRESET_TYPES.WEEKS,
initialDate: new Date(2018, 0, 1),
});
const range = getEpicsTimeframeRange({
presetType: PRESET_TYPES.WEEKS,
timeframe: timeframeWeeks,
......@@ -451,8 +180,8 @@ describe('getEpicsTimeframeRange', () => {
expect(range).toEqual(
expect.objectContaining({
timeframe: {
start: '2017-12-17',
end: '2018-02-03',
start: '2017-12-31',
end: '2018-03-31',
},
}),
);
......
......@@ -16215,12 +16215,6 @@ msgstr ""
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr ""
msgid "GroupRoadmap|Roadmaps can display up to 1,000 epics. These appear in your selected sort order."
msgstr ""
msgid "GroupRoadmap|Some of your epics might not be visible"
msgstr ""
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment