Commit e2644335 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 0810b3bf d69809a3
...@@ -79,6 +79,7 @@ const Api = { ...@@ -79,6 +79,7 @@ const Api = {
issuePath: '/api/:version/projects/:id/issues/:issue_iid', issuePath: '/api/:version/projects/:id/issues/:issue_iid',
tagsPath: '/api/:version/projects/:id/repository/tags', tagsPath: '/api/:version/projects/:id/repository/tags',
freezePeriodsPath: '/api/:version/projects/:id/freeze_periods', freezePeriodsPath: '/api/:version/projects/:id/freeze_periods',
freezePeriodPath: '/api/:version/projects/:id/freeze_periods/:freeze_period_id',
usageDataIncrementCounterPath: '/api/:version/usage_data/increment_counter', usageDataIncrementCounterPath: '/api/:version/usage_data/increment_counter',
usageDataIncrementUniqueUsersPath: '/api/:version/usage_data/increment_unique_users', usageDataIncrementUniqueUsersPath: '/api/:version/usage_data/increment_unique_users',
featureFlagUserLists: '/api/:version/projects/:id/feature_flags_user_lists', featureFlagUserLists: '/api/:version/projects/:id/feature_flags_user_lists',
...@@ -832,6 +833,14 @@ const Api = { ...@@ -832,6 +833,14 @@ const Api = {
return axios.post(url, freezePeriod); return axios.post(url, freezePeriod);
}, },
updateFreezePeriod(id, freezePeriod = {}) {
const url = Api.buildUrl(this.freezePeriodPath)
.replace(':id', encodeURIComponent(id))
.replace(':freeze_period_id', encodeURIComponent(freezePeriod.id));
return axios.put(url, freezePeriod);
},
trackRedisCounterEvent(event) { trackRedisCounterEvent(event) {
if (!gon.features?.usageDataApi) { if (!gon.features?.usageDataApi) {
return null; return null;
......
...@@ -3,8 +3,7 @@ import { parseBoolean } from '~/lib/utils/common_utils'; ...@@ -3,8 +3,7 @@ import { parseBoolean } from '~/lib/utils/common_utils';
import CiVariableSettings from './components/ci_variable_settings.vue'; import CiVariableSettings from './components/ci_variable_settings.vue';
import createStore from './store'; import createStore from './store';
export default (containerId = 'js-ci-project-variables') => { const mountCiVariableListApp = (containerEl) => {
const containerEl = document.getElementById(containerId);
const { const {
endpoint, endpoint,
projectId, projectId,
...@@ -43,3 +42,8 @@ export default (containerId = 'js-ci-project-variables') => { ...@@ -43,3 +42,8 @@ export default (containerId = 'js-ci-project-variables') => {
}, },
}); });
}; };
export default () => {
const el = document.querySelector('#js-ci-project-variables');
return !el ? {} : mountCiVariableListApp(el);
};
...@@ -18,7 +18,6 @@ export default { ...@@ -18,7 +18,6 @@ export default {
modalOptions: { modalOptions: {
ref: 'modal', ref: 'modal',
modalId: 'deploy-freeze-modal', modalId: 'deploy-freeze-modal',
title: __('Add deploy freeze'),
actionCancel: { actionCancel: {
text: __('Cancel'), text: __('Cancel'),
}, },
...@@ -30,10 +29,13 @@ export default { ...@@ -30,10 +29,13 @@ export default {
cronSyntaxInstructions: __( cronSyntaxInstructions: __(
'Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}', 'Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}',
), ),
addTitle: __('Add deploy freeze'),
editTitle: __('Edit deploy freeze'),
}, },
computed: { computed: {
...mapState([ ...mapState([
'projectId', 'projectId',
'selectedId',
'selectedTimezone', 'selectedTimezone',
'timezoneData', 'timezoneData',
'freezeStartCron', 'freezeStartCron',
...@@ -45,9 +47,9 @@ export default { ...@@ -45,9 +47,9 @@ export default {
]), ]),
addDeployFreezeButton() { addDeployFreezeButton() {
return { return {
text: __('Add deploy freeze'), text: this.isEditing ? __('Save deploy freeze') : __('Add deploy freeze'),
attributes: [ attributes: [
{ variant: 'success' }, { variant: 'confirm' },
{ {
disabled: disabled:
!isValidCron(this.freezeStartCron) || !isValidCron(this.freezeStartCron) ||
...@@ -77,9 +79,17 @@ export default { ...@@ -77,9 +79,17 @@ export default {
this.setSelectedTimezone(selectedTimezone); this.setSelectedTimezone(selectedTimezone);
}, },
}, },
isEditing() {
return Boolean(this.selectedId);
},
modalTitle() {
return this.isEditing
? this.$options.translations.editTitle
: this.$options.translations.addTitle;
},
}, },
methods: { methods: {
...mapActions(['addFreezePeriod', 'setSelectedTimezone', 'resetModal']), ...mapActions(['addFreezePeriod', 'updateFreezePeriod', 'setSelectedTimezone', 'resetModal']),
resetModalHandler() { resetModalHandler() {
this.resetModal(); this.resetModal();
}, },
...@@ -89,6 +99,13 @@ export default { ...@@ -89,6 +99,13 @@ export default {
} }
return ''; return '';
}, },
submit() {
if (this.isEditing) {
this.updateFreezePeriod();
} else {
this.addFreezePeriod();
}
},
}, },
}; };
</script> </script>
...@@ -96,8 +113,9 @@ export default { ...@@ -96,8 +113,9 @@ export default {
<template> <template>
<gl-modal <gl-modal
v-bind="$options.modalOptions" v-bind="$options.modalOptions"
:title="modalTitle"
:action-primary="addDeployFreezeButton" :action-primary="addDeployFreezeButton"
@primary="addFreezePeriod" @primary="submit"
@canceled="resetModalHandler" @canceled="resetModalHandler"
> >
<p> <p>
......
<script> <script>
import { GlTable, GlButton, GlModalDirective, GlSprintf } from '@gitlab/ui'; import { GlTable, GlButton, GlModalDirective, GlSprintf } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex'; import { mapState, mapActions } from 'vuex';
import { s__, __ } from '~/locale'; import { s__ } from '~/locale';
export default { export default {
fields: [ fields: [
...@@ -17,9 +17,16 @@ export default { ...@@ -17,9 +17,16 @@ export default {
key: 'cronTimezone', key: 'cronTimezone',
label: s__('DeployFreeze|Time zone'), label: s__('DeployFreeze|Time zone'),
}, },
{
key: 'edit',
label: s__('DeployFreeze|Edit'),
},
], ],
translations: { translations: {
addDeployFreeze: __('Add deploy freeze'), addDeployFreeze: s__('DeployFreeze|Add deploy freeze'),
emptyStateText: s__(
'DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}',
),
}, },
components: { components: {
GlTable, GlTable,
...@@ -39,7 +46,7 @@ export default { ...@@ -39,7 +46,7 @@ export default {
this.fetchFreezePeriods(); this.fetchFreezePeriods();
}, },
methods: { methods: {
...mapActions(['fetchFreezePeriods']), ...mapActions(['fetchFreezePeriods', 'setFreezePeriod']),
}, },
}; };
</script> </script>
...@@ -53,15 +60,20 @@ export default { ...@@ -53,15 +60,20 @@ export default {
show-empty show-empty
stacked="lg" stacked="lg"
> >
<template #cell(cronTimezone)="{ item }">
{{ item.cronTimezone.formattedTimezone }}
</template>
<template #cell(edit)="{ item }">
<gl-button
v-gl-modal.deploy-freeze-modal
icon="pencil"
data-testid="edit-deploy-freeze"
@click="setFreezePeriod(item)"
/>
</template>
<template #empty> <template #empty>
<p data-testid="empty-freeze-periods" class="gl-text-center text-plain"> <p data-testid="empty-freeze-periods" class="gl-text-center text-plain">
<gl-sprintf <gl-sprintf :message="$options.translations.emptyStateText">
:message="
s__(
'DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}',
)
"
>
<template #strong="{ content }"> <template #strong="{ content }">
<strong>{{ content }}</strong> <strong>{{ content }}</strong>
</template> </template>
...@@ -73,7 +85,7 @@ export default { ...@@ -73,7 +85,7 @@ export default {
v-gl-modal.deploy-freeze-modal v-gl-modal.deploy-freeze-modal
data-testid="add-deploy-freeze" data-testid="add-deploy-freeze"
category="primary" category="primary"
variant="success" variant="confirm"
> >
{{ $options.translations.addDeployFreeze }} {{ $options.translations.addDeployFreeze }}
</gl-button> </gl-button>
......
...@@ -3,37 +3,53 @@ import { deprecatedCreateFlash as createFlash } from '~/flash'; ...@@ -3,37 +3,53 @@ import { deprecatedCreateFlash as createFlash } from '~/flash';
import { __ } from '~/locale'; import { __ } from '~/locale';
import * as types from './mutation_types'; import * as types from './mutation_types';
export const requestAddFreezePeriod = ({ commit }) => { export const requestFreezePeriod = ({ commit }) => {
commit(types.REQUEST_ADD_FREEZE_PERIOD); commit(types.REQUEST_ADD_FREEZE_PERIOD);
}; };
export const receiveAddFreezePeriodSuccess = ({ commit }) => { export const receiveFreezePeriodSuccess = ({ commit }) => {
commit(types.RECEIVE_ADD_FREEZE_PERIOD_SUCCESS); commit(types.RECEIVE_ADD_FREEZE_PERIOD_SUCCESS);
}; };
export const receiveAddFreezePeriodError = ({ commit }, error) => { export const receiveFreezePeriodError = ({ commit }, error) => {
commit(types.RECEIVE_ADD_FREEZE_PERIOD_ERROR, error); commit(types.RECEIVE_ADD_FREEZE_PERIOD_ERROR, error);
}; };
export const addFreezePeriod = ({ state, dispatch, commit }) => { const receiveFreezePeriod = (store, request) => {
dispatch('requestAddFreezePeriod'); const { dispatch, commit } = store;
dispatch('requestFreezePeriod');
return Api.createFreezePeriod(state.projectId, { request(store)
freeze_start: state.freezeStartCron,
freeze_end: state.freezeEndCron,
cron_timezone: state.selectedTimezoneIdentifier,
})
.then(() => { .then(() => {
dispatch('receiveAddFreezePeriodSuccess'); dispatch('receiveFreezePeriodSuccess');
commit(types.RESET_MODAL); commit(types.RESET_MODAL);
dispatch('fetchFreezePeriods'); dispatch('fetchFreezePeriods');
}) })
.catch((error) => { .catch((error) => {
createFlash(__('Error: Unable to create deploy freeze')); createFlash(__('Error: Unable to create deploy freeze'));
dispatch('receiveAddFreezePeriodError', error); dispatch('receiveFreezePeriodError', error);
}); });
}; };
export const addFreezePeriod = (store) =>
receiveFreezePeriod(store, ({ state }) =>
Api.createFreezePeriod(state.projectId, {
freeze_start: state.freezeStartCron,
freeze_end: state.freezeEndCron,
cron_timezone: state.selectedTimezoneIdentifier,
}),
);
export const updateFreezePeriod = (store) =>
receiveFreezePeriod(store, ({ state }) =>
Api.updateFreezePeriod(state.projectId, {
id: state.selectedId,
freeze_start: state.freezeStartCron,
freeze_end: state.freezeEndCron,
cron_timezone: state.selectedTimezoneIdentifier,
}),
);
export const fetchFreezePeriods = ({ commit, state }) => { export const fetchFreezePeriods = ({ commit, state }) => {
commit(types.REQUEST_FREEZE_PERIODS); commit(types.REQUEST_FREEZE_PERIODS);
...@@ -46,6 +62,13 @@ export const fetchFreezePeriods = ({ commit, state }) => { ...@@ -46,6 +62,13 @@ export const fetchFreezePeriods = ({ commit, state }) => {
}); });
}; };
export const setFreezePeriod = ({ commit }, freezePeriod) => {
commit(types.SET_SELECTED_ID, freezePeriod.id);
commit(types.SET_SELECTED_TIMEZONE, freezePeriod.cronTimezone);
commit(types.SET_FREEZE_START_CRON, freezePeriod.freezeStart);
commit(types.SET_FREEZE_END_CRON, freezePeriod.freezeEnd);
};
export const setSelectedTimezone = ({ commit }, timezone) => { export const setSelectedTimezone = ({ commit }, timezone) => {
commit(types.SET_SELECTED_TIMEZONE, timezone); commit(types.SET_SELECTED_TIMEZONE, timezone);
}; };
......
...@@ -6,6 +6,7 @@ export const RECEIVE_ADD_FREEZE_PERIOD_SUCCESS = 'RECEIVE_ADD_FREEZE_PERIOD_SUCC ...@@ -6,6 +6,7 @@ export const RECEIVE_ADD_FREEZE_PERIOD_SUCCESS = 'RECEIVE_ADD_FREEZE_PERIOD_SUCC
export const RECEIVE_ADD_FREEZE_PERIOD_ERROR = 'RECEIVE_ADD_FREEZE_PERIOD_ERROR'; export const RECEIVE_ADD_FREEZE_PERIOD_ERROR = 'RECEIVE_ADD_FREEZE_PERIOD_ERROR';
export const SET_SELECTED_TIMEZONE = 'SET_SELECTED_TIMEZONE'; export const SET_SELECTED_TIMEZONE = 'SET_SELECTED_TIMEZONE';
export const SET_SELECTED_ID = 'SET_SELECTED_ID';
export const SET_FREEZE_START_CRON = 'SET_FREEZE_START_CRON'; export const SET_FREEZE_START_CRON = 'SET_FREEZE_START_CRON';
export const SET_FREEZE_END_CRON = 'SET_FREEZE_END_CRON'; export const SET_FREEZE_END_CRON = 'SET_FREEZE_END_CRON';
......
...@@ -4,7 +4,11 @@ import * as types from './mutation_types'; ...@@ -4,7 +4,11 @@ import * as types from './mutation_types';
const formatTimezoneName = (freezePeriod, timezoneList) => const formatTimezoneName = (freezePeriod, timezoneList) =>
convertObjectPropsToCamelCase({ convertObjectPropsToCamelCase({
...freezePeriod, ...freezePeriod,
cron_timezone: timezoneList.find((tz) => tz.identifier === freezePeriod.cron_timezone)?.name, cron_timezone: {
formattedTimezone: timezoneList.find((tz) => tz.identifier === freezePeriod.cron_timezone)
?.name,
identifier: freezePeriod.cronTimezone,
},
}); });
export default { export default {
...@@ -45,10 +49,15 @@ export default { ...@@ -45,10 +49,15 @@ export default {
state.freezeEndCron = freezeEndCron; state.freezeEndCron = freezeEndCron;
}, },
[types.SET_SELECTED_ID](state, id) {
state.selectedId = id;
},
[types.RESET_MODAL](state) { [types.RESET_MODAL](state) {
state.freezeStartCron = ''; state.freezeStartCron = '';
state.freezeEndCron = ''; state.freezeEndCron = '';
state.selectedTimezone = ''; state.selectedTimezone = '';
state.selectedTimezoneIdentifier = ''; state.selectedTimezoneIdentifier = '';
state.selectedId = '';
}, },
}; };
...@@ -6,6 +6,7 @@ export default ({ ...@@ -6,6 +6,7 @@ export default ({
selectedTimezoneIdentifier = '', selectedTimezoneIdentifier = '',
freezeStartCron = '', freezeStartCron = '',
freezeEndCron = '', freezeEndCron = '',
selectedId = '',
}) => ({ }) => ({
projectId, projectId,
freezePeriods, freezePeriods,
...@@ -14,4 +15,5 @@ export default ({ ...@@ -14,4 +15,5 @@ export default ({
selectedTimezoneIdentifier, selectedTimezoneIdentifier,
freezeStartCron, freezeStartCron,
freezeEndCron, freezeEndCron,
selectedId,
}); });
...@@ -4,9 +4,7 @@ import initSearchSettings from '~/search_settings'; ...@@ -4,9 +4,7 @@ import initSearchSettings from '~/search_settings';
import selfMonitor from '~/self_monitor'; import selfMonitor from '~/self_monitor';
import initSettingsPanels from '~/settings_panels'; import initSettingsPanels from '~/settings_panels';
if (gon.features?.ciInstanceVariablesUi) { initVariableList('js-instance-variables');
initVariableList('js-instance-variables');
}
selfMonitor(); selfMonitor();
// Initialize expandable settings panels // Initialize expandable settings panels
initSettingsPanels(); initSettingsPanels();
......
...@@ -13,10 +13,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -13,10 +13,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
before_action :disable_query_limiting, only: [:usage_data] before_action :disable_query_limiting, only: [:usage_data]
before_action only: [:ci_cd] do
push_frontend_feature_flag(:ci_instance_variables_ui, default_enabled: true)
end
feature_category :not_owned, [ feature_category :not_owned, [
:general, :reporting, :metrics_and_profiling, :network, :general, :reporting, :metrics_and_profiling, :network,
:preferences, :update, :reset_health_check_token :preferences, :update, :reset_health_check_token
......
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
- page_title _("CI/CD") - page_title _("CI/CD")
- @content_class = "limit-container-width" unless fluid_layout - @content_class = "limit-container-width" unless fluid_layout
- if ::Gitlab::Ci::Features.instance_variables_ui_enabled? %section.settings.no-animate#js-ci-cd-variables{ class: ('expanded' if expanded_by_default?) }
%section.settings.no-animate#js-ci-cd-variables{ class: ('expanded' if expanded_by_default?) }
.settings-header .settings-header
= render 'admin/application_settings/ci/header', expanded: expanded_by_default? = render 'admin/application_settings/ci/header', expanded: expanded_by_default?
.settings-content .settings-content
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
%section.settings.js-service-desk-setting-wrapper.no-animate#js-service-desk{ class: ('expanded' if expanded), data: { qa_selector: 'service_desk_settings_content' } } %section.settings.js-service-desk-setting-wrapper.no-animate#js-service-desk{ class: ('expanded' if expanded), data: { qa_selector: 'service_desk_settings_content' } }
.settings-header .settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Service Desk') %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Service Desk')
%button.btn.gl-button.js-settings-toggle %button.btn.gl-button.btn-default.js-settings-toggle
= expanded ? _('Collapse') : _('Expand') = expanded ? _('Collapse') : _('Expand')
- link_start = "<a href='#{help_page_path('user/project/service_desk')}' target='_blank' rel='noopener noreferrer'>".html_safe - link_start = "<a href='#{help_page_path('user/project/service_desk')}' target='_blank' rel='noopener noreferrer'>".html_safe
%p= _('Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe } %p= _('Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
......
---
title: Add Ability to Edit Freeze Periods
merge_request: 56407
author:
type: added
---
title: Add btn-default class for Service Desk toggle in settings
merge_request: 56195
author: Yogi (@yo)
type: changed
---
title: Enable the instance variables UI
merge_request: 56255
author:
type: other
---
name: ci_instance_variables_ui
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33510
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299879
milestone: '13.1'
type: development
group: group::continuous integration
default_enabled: true
...@@ -217,11 +217,11 @@ To set a deploy freeze window in the UI, complete these steps: ...@@ -217,11 +217,11 @@ To set a deploy freeze window in the UI, complete these steps:
1. Click **Add deploy freeze** to open the deploy freeze modal. 1. Click **Add deploy freeze** to open the deploy freeze modal.
1. Enter the start time, end time, and timezone of the desired deploy freeze period. 1. Enter the start time, end time, and timezone of the desired deploy freeze period.
1. Click **Add deploy freeze** in the modal. 1. Click **Add deploy freeze** in the modal.
1. After the deploy freeze is saved, you can edit it by selecting the edit button (**{pencil}**).
![Deploy freeze modal for setting a deploy freeze period](img/deploy_freeze_v13_2.png) ![Deploy freeze modal for setting a deploy freeze period](img/deploy_freeze_v13_10.png)
WARNING: WARNING:
To edit or delete a deploy freeze, use the [Freeze Periods API](../../../api/freeze_periods.md). To delete a deploy freeze, use the [Freeze Periods API](../../../api/freeze_periods.md).
If a project contains multiple freeze periods, all periods apply. If they overlap, the freeze covers the If a project contains multiple freeze periods, all periods apply. If they overlap, the freeze covers the
complete overlapping period. complete overlapping period.
......
...@@ -24,13 +24,9 @@ RSpec.describe 'GFM autocomplete', :js do ...@@ -24,13 +24,9 @@ RSpec.describe 'GFM autocomplete', :js do
end end
it 'opens quick action autocomplete in the description field' do it 'opens quick action autocomplete in the description field' do
find('#epic-description').native.send_keys('/la') fill_in 'Description', with: '/la'
expect(page).to have_selector('.atwho-container') expect(find_highlighted_autocomplete_item).to have_text('/label')
page.within '.atwho-container #at-view-commands' do
expect(find('li', match: :first)).to have_content('/label')
end
end end
end end
...@@ -42,11 +38,11 @@ RSpec.describe 'GFM autocomplete', :js do ...@@ -42,11 +38,11 @@ RSpec.describe 'GFM autocomplete', :js do
end end
it 'opens quick action autocomplete when updating description' do it 'opens quick action autocomplete when updating description' do
find('.js-issuable-edit').click click_button 'Edit title and description'
find('#issue-description').native.send_keys('/') fill_in 'Description', with: '/'
expect(page).to have_selector('.atwho-container') expect(find_autocomplete_menu).to be_visible
end end
context 'issuables' do context 'issuables' do
...@@ -57,7 +53,7 @@ RSpec.describe 'GFM autocomplete', :js do ...@@ -57,7 +53,7 @@ RSpec.describe 'GFM autocomplete', :js do
issue_1 = create(:issue, project: project) issue_1 = create(:issue, project: project)
issue_2 = create(:issue, project: project) issue_2 = create(:issue, project: project)
type(find('#note-body'), '#') fill_in 'Comment', with: '#'
expect_resources(shown: [issue_1, issue_2]) expect_resources(shown: [issue_1, issue_2])
end end
...@@ -68,7 +64,7 @@ RSpec.describe 'GFM autocomplete', :js do ...@@ -68,7 +64,7 @@ RSpec.describe 'GFM autocomplete', :js do
mr_1 = create(:merge_request, source_project: project) mr_1 = create(:merge_request, source_project: project)
mr_2 = create(:merge_request, source_project: project, source_branch: 'other-branch') mr_2 = create(:merge_request, source_project: project, source_branch: 'other-branch')
type(find('#note-body'), '!') fill_in 'Comment', with: '!'
expect_resources(shown: [mr_1, mr_2]) expect_resources(shown: [mr_1, mr_2])
end end
...@@ -79,10 +75,8 @@ RSpec.describe 'GFM autocomplete', :js do ...@@ -79,10 +75,8 @@ RSpec.describe 'GFM autocomplete', :js do
let!(:epic2) { create(:epic, group: group, title: 'make tea') } let!(:epic2) { create(:epic, group: group, title: 'make tea') }
it 'shows epics' do it 'shows epics' do
note = find('#note-body') fill_in 'Comment', with: '&'
# It should show all the epics on "&".
type(note, '&')
expect_resources(shown: [epic, epic2]) expect_resources(shown: [epic, epic2])
end end
end end
...@@ -93,9 +87,8 @@ RSpec.describe 'GFM autocomplete', :js do ...@@ -93,9 +87,8 @@ RSpec.describe 'GFM autocomplete', :js do
milestone_1 = create(:milestone, title: 'milestone_1', group: group) milestone_1 = create(:milestone, title: 'milestone_1', group: group)
milestone_2 = create(:milestone, title: 'milestone_2', group: group) milestone_2 = create(:milestone, title: 'milestone_2', group: group)
milestone_3 = create(:milestone, title: 'milestone_3', project: project) milestone_3 = create(:milestone, title: 'milestone_3', project: project)
note = find('#note-body')
type(note, '%') fill_in 'Comment', with: '%'
expect_resources(shown: [milestone_1, milestone_2], not_shown: [milestone_3]) expect_resources(shown: [milestone_1, milestone_2], not_shown: [milestone_3])
end end
...@@ -108,36 +101,32 @@ RSpec.describe 'GFM autocomplete', :js do ...@@ -108,36 +101,32 @@ RSpec.describe 'GFM autocomplete', :js do
context 'when no labels are assigned' do context 'when no labels are assigned' do
it 'shows all labels for ~' do it 'shows all labels for ~' do
note = find('#note-body') fill_in 'Comment', with: '~'
type(note, '~')
wait_for_requests wait_for_requests
expect_resources(shown: [backend, bug, feature_proposal]) expect_resources(shown: [backend, bug, feature_proposal])
end end
it 'shows all labels for /label ~' do it 'shows all labels for /label ~' do
note = find('#note-body') fill_in 'Comment', with: '/label ~'
type(note, '/label ~')
wait_for_requests wait_for_requests
expect_resources(shown: [backend, bug, feature_proposal]) expect_resources(shown: [backend, bug, feature_proposal])
end end
it 'shows all labels for /relabel ~' do it 'shows all labels for /relabel ~' do
note = find('#note-body') fill_in 'Comment', with: '/relabel ~'
type(note, '/relabel ~')
wait_for_requests wait_for_requests
expect_resources(shown: [backend, bug, feature_proposal]) expect_resources(shown: [backend, bug, feature_proposal])
end end
it 'shows no labels for /unlabel ~' do it 'shows no labels for /unlabel ~' do
note = find('#note-body') fill_in 'Comment', with: '/unlabel ~'
type(note, '/unlabel ~')
wait_for_requests wait_for_requests
expect_resources(not_shown: [backend, bug, feature_proposal]) expect_resources(not_shown: [backend, bug, feature_proposal])
...@@ -150,36 +139,32 @@ RSpec.describe 'GFM autocomplete', :js do ...@@ -150,36 +139,32 @@ RSpec.describe 'GFM autocomplete', :js do
end end
it 'shows all labels for ~' do it 'shows all labels for ~' do
note = find('#note-body') fill_in 'Comment', with: '~'
type(note, '~')
wait_for_requests wait_for_requests
expect_resources(shown: [backend, bug, feature_proposal]) expect_resources(shown: [backend, bug, feature_proposal])
end end
it 'shows only unset labels for /label ~' do it 'shows only unset labels for /label ~' do
note = find('#note-body') fill_in 'Comment', with: '/label ~'
type(note, '/label ~')
wait_for_requests wait_for_requests
expect_resources(shown: [bug, feature_proposal], not_shown: [backend]) expect_resources(shown: [bug, feature_proposal], not_shown: [backend])
end end
it 'shows all labels for /relabel ~' do it 'shows all labels for /relabel ~' do
note = find('#note-body') fill_in 'Comment', with: '/relabel ~'
type(note, '/relabel ~')
wait_for_requests wait_for_requests
expect_resources(shown: [backend, bug, feature_proposal]) expect_resources(shown: [backend, bug, feature_proposal])
end end
it 'shows only set labels for /unlabel ~' do it 'shows only set labels for /unlabel ~' do
note = find('#note-body') fill_in 'Comment', with: '/unlabel ~'
type(note, '/unlabel ~')
wait_for_requests wait_for_requests
expect_resources(shown: [backend], not_shown: [bug, feature_proposal]) expect_resources(shown: [backend], not_shown: [bug, feature_proposal])
...@@ -192,36 +177,31 @@ RSpec.describe 'GFM autocomplete', :js do ...@@ -192,36 +177,31 @@ RSpec.describe 'GFM autocomplete', :js do
end end
it 'shows all labels for ~' do it 'shows all labels for ~' do
note = find('#note-body') fill_in 'Comment', with: '~'
type(note, '~')
wait_for_requests wait_for_requests
expect_resources(shown: [backend, bug, feature_proposal]) expect_resources(shown: [backend, bug, feature_proposal])
end end
it 'shows no labels for /label ~' do it 'shows no labels for /label ~' do
note = find('#note-body') fill_in 'Comment', with: '/label ~'
type(note, '/label ~')
wait_for_requests wait_for_requests
expect_resources(not_shown: [backend, bug, feature_proposal]) expect_resources(not_shown: [backend, bug, feature_proposal])
end end
it 'shows all labels for /relabel ~' do it 'shows all labels for /relabel ~' do
note = find('#note-body') fill_in 'Comment', with: '/relabel ~'
type(note, '/relabel ~')
wait_for_requests wait_for_requests
expect_resources(shown: [backend, bug, feature_proposal]) expect_resources(shown: [backend, bug, feature_proposal])
end end
it 'shows all labels for /unlabel ~' do it 'shows all labels for /unlabel ~' do
note = find('#note-body') fill_in 'Comment', with: '/unlabel ~'
type(note, '/unlabel ~')
wait_for_requests wait_for_requests
expect_resources(shown: [backend, bug, feature_proposal]) expect_resources(shown: [backend, bug, feature_proposal])
...@@ -232,19 +212,6 @@ RSpec.describe 'GFM autocomplete', :js do ...@@ -232,19 +212,6 @@ RSpec.describe 'GFM autocomplete', :js do
private private
def expect_to_wrap(should_wrap, item, note, value)
expect(item).to have_content(value)
expect(item).not_to have_content("\"#{value}\"")
item.click
if should_wrap
expect(note.value).to include("\"#{value}\"")
else
expect(note.value).not_to include("\"#{value}\"")
end
end
def expect_resources(shown: nil, not_shown: nil) def expect_resources(shown: nil, not_shown: nil)
page.within('.atwho-container') do page.within('.atwho-container') do
if shown if shown
...@@ -259,12 +226,11 @@ RSpec.describe 'GFM autocomplete', :js do ...@@ -259,12 +226,11 @@ RSpec.describe 'GFM autocomplete', :js do
end end
end end
# `note` is a textarea where the given text should be typed. def find_autocomplete_menu
# We don't want to find it each time this function gets called. find('.atwho-view ul', visible: true)
def type(note, text)
page.within('.timeline-content-form') do
note.set('')
note.native.send_keys(text)
end end
def find_highlighted_autocomplete_item
find('.atwho-view li.cur', visible: true)
end end
end end
...@@ -10,10 +10,6 @@ module Gitlab ...@@ -10,10 +10,6 @@ module Gitlab
::Feature.enabled?(:ci_artifacts_exclude, default_enabled: true) ::Feature.enabled?(:ci_artifacts_exclude, default_enabled: true)
end end
def self.instance_variables_ui_enabled?
::Feature.enabled?(:ci_instance_variables_ui, default_enabled: true)
end
def self.pipeline_latest? def self.pipeline_latest?
::Feature.enabled?(:ci_pipeline_latest, default_enabled: true) ::Feature.enabled?(:ci_pipeline_latest, default_enabled: true)
end end
......
...@@ -10245,13 +10245,19 @@ msgstr "" ...@@ -10245,13 +10245,19 @@ msgstr ""
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}" msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
msgstr "" msgstr ""
msgid "DeployFreeze|Add deploy freeze"
msgstr ""
msgid "DeployFreeze|Edit"
msgstr ""
msgid "DeployFreeze|Freeze end" msgid "DeployFreeze|Freeze end"
msgstr "" msgstr ""
msgid "DeployFreeze|Freeze start" msgid "DeployFreeze|Freeze start"
msgstr "" msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}" msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
msgstr "" msgstr ""
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}." msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
...@@ -11191,6 +11197,9 @@ msgstr "" ...@@ -11191,6 +11197,9 @@ msgstr ""
msgid "Edit comment" msgid "Edit comment"
msgstr "" msgstr ""
msgid "Edit deploy freeze"
msgstr ""
msgid "Edit description" msgid "Edit description"
msgstr "" msgstr ""
...@@ -26436,6 +26445,9 @@ msgstr "" ...@@ -26436,6 +26445,9 @@ msgstr ""
msgid "Save comment" msgid "Save comment"
msgstr "" msgstr ""
msgid "Save deploy freeze"
msgstr ""
msgid "Save password" msgid "Save password"
msgstr "" msgstr ""
......
...@@ -1382,6 +1382,38 @@ describe('Api', () => { ...@@ -1382,6 +1382,38 @@ describe('Api', () => {
}); });
}); });
describe('updateFreezePeriod', () => {
const options = {
id: 10,
freeze_start: '* * * * *',
freeze_end: '* * * * *',
cron_timezone: 'America/Juneau',
created_at: '2020-07-11T07:04:50.153Z',
updated_at: '2020-07-11T07:04:50.153Z',
};
const projectId = 8;
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectId}/freeze_periods/${options.id}`;
const expectedResult = {
id: 10,
freeze_start: '* * * * *',
freeze_end: '* * * * *',
cron_timezone: 'America/Juneau',
created_at: '2020-07-11T07:04:50.153Z',
updated_at: '2020-07-11T07:04:50.153Z',
};
describe('when the freeze period is successfully updated', () => {
it('resolves the Promise', () => {
mock.onPut(expectedUrl, options).replyOnce(httpStatus.OK, expectedResult);
return Api.updateFreezePeriod(projectId, options).then(({ data }) => {
expect(data).toStrictEqual(expectedResult);
});
});
});
});
describe('createPipeline', () => { describe('createPipeline', () => {
it('creates new pipeline', () => { it('creates new pipeline', () => {
const redirectUrl = 'ci-project/-/pipelines/95'; const redirectUrl = 'ci-project/-/pipelines/95';
......
import { GlButton, GlModal } from '@gitlab/ui'; import { GlButton, GlModal } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import Api from '~/api';
import DeployFreezeModal from '~/deploy_freeze/components/deploy_freeze_modal.vue'; import DeployFreezeModal from '~/deploy_freeze/components/deploy_freeze_modal.vue';
import createStore from '~/deploy_freeze/store'; import createStore from '~/deploy_freeze/store';
import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue'; import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
import { freezePeriodsFixture, timezoneDataFixture } from '../helpers'; import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
const localVue = createLocalVue(); jest.mock('~/api');
localVue.use(Vuex);
Vue.use(Vuex);
describe('Deploy freeze modal', () => { describe('Deploy freeze modal', () => {
let wrapper; let wrapper;
...@@ -23,18 +26,19 @@ describe('Deploy freeze modal', () => { ...@@ -23,18 +26,19 @@ describe('Deploy freeze modal', () => {
stubs: { stubs: {
GlModal, GlModal,
}, },
localVue,
store, store,
}); });
}); });
const findModal = () => wrapper.find(GlModal); const findModal = () => wrapper.findComponent(GlModal);
const addDeployFreezeButton = () => findModal().findAll(GlButton).at(1); const submitDeployFreezeButton = () => findModal().findAllComponents(GlButton).at(1);
const setInput = (freezeStartCron, freezeEndCron, selectedTimezone) => { const setInput = (freezeStartCron, freezeEndCron, selectedTimezone, id = '') => {
store.state.freezeStartCron = freezeStartCron; store.state.freezeStartCron = freezeStartCron;
store.state.freezeEndCron = freezeEndCron; store.state.freezeEndCron = freezeEndCron;
store.state.selectedTimezone = selectedTimezone; store.state.selectedTimezone = selectedTimezone;
store.state.selectedTimezoneIdentifier = selectedTimezone;
store.state.selectedId = id;
wrapper.find('#deploy-freeze-start').trigger('input'); wrapper.find('#deploy-freeze-start').trigger('input');
wrapper.find('#deploy-freeze-end').trigger('input'); wrapper.find('#deploy-freeze-end').trigger('input');
...@@ -48,18 +52,36 @@ describe('Deploy freeze modal', () => { ...@@ -48,18 +52,36 @@ describe('Deploy freeze modal', () => {
describe('Basic interactions', () => { describe('Basic interactions', () => {
it('button is disabled when freeze period is invalid', () => { it('button is disabled when freeze period is invalid', () => {
expect(addDeployFreezeButton().attributes('disabled')).toBeTruthy(); expect(submitDeployFreezeButton().attributes('disabled')).toBeTruthy();
}); });
}); });
describe('Adding a new deploy freeze', () => { describe('Adding a new deploy freeze', () => {
beforeEach(() => {
const { freeze_start, freeze_end, cron_timezone } = freezePeriodsFixture[0]; const { freeze_start, freeze_end, cron_timezone } = freezePeriodsFixture[0];
beforeEach(() => {
setInput(freeze_start, freeze_end, cron_timezone); setInput(freeze_start, freeze_end, cron_timezone);
}); });
it('button is enabled when valid freeze period settings are present', () => { it('button is enabled when valid freeze period settings are present', () => {
expect(addDeployFreezeButton().attributes('disabled')).toBeUndefined(); expect(submitDeployFreezeButton().attributes('disabled')).toBeUndefined();
});
it('should display Add deploy freeze', () => {
expect(findModal().props('title')).toBe('Add deploy freeze');
expect(submitDeployFreezeButton().text()).toBe('Add deploy freeze');
});
it('should call the add deploy freze API', () => {
Api.createFreezePeriod.mockResolvedValue();
findModal().vm.$emit('primary');
expect(Api.createFreezePeriod).toHaveBeenCalledTimes(1);
expect(Api.createFreezePeriod).toHaveBeenCalledWith(store.state.projectId, {
freeze_start,
freeze_end,
cron_timezone,
});
}); });
}); });
...@@ -70,7 +92,7 @@ describe('Deploy freeze modal', () => { ...@@ -70,7 +92,7 @@ describe('Deploy freeze modal', () => {
}); });
it('disables the add deploy freeze button', () => { it('disables the add deploy freeze button', () => {
expect(addDeployFreezeButton().attributes('disabled')).toBeTruthy(); expect(submitDeployFreezeButton().attributes('disabled')).toBeTruthy();
}); });
}); });
...@@ -81,7 +103,32 @@ describe('Deploy freeze modal', () => { ...@@ -81,7 +103,32 @@ describe('Deploy freeze modal', () => {
}); });
it('does not disable the submit button', () => { it('does not disable the submit button', () => {
expect(addDeployFreezeButton().attributes('disabled')).toBeFalsy(); expect(submitDeployFreezeButton().attributes('disabled')).toBeFalsy();
});
});
});
describe('Editing an existing deploy freeze', () => {
const { freeze_start, freeze_end, cron_timezone, id } = freezePeriodsFixture[0];
beforeEach(() => {
setInput(freeze_start, freeze_end, cron_timezone, id);
});
it('should display Edit deploy freeze', () => {
expect(findModal().props('title')).toBe('Edit deploy freeze');
expect(submitDeployFreezeButton().text()).toBe('Save deploy freeze');
});
it('should call the update deploy freze API', () => {
Api.updateFreezePeriod.mockResolvedValue();
findModal().vm.$emit('primary');
expect(Api.updateFreezePeriod).toHaveBeenCalledTimes(1);
expect(Api.updateFreezePeriod).toHaveBeenCalledWith(store.state.projectId, {
id,
freeze_start,
freeze_end,
cron_timezone,
}); });
}); });
}); });
......
...@@ -2,6 +2,7 @@ import { createLocalVue, mount } from '@vue/test-utils'; ...@@ -2,6 +2,7 @@ import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex'; import Vuex from 'vuex';
import DeployFreezeTable from '~/deploy_freeze/components/deploy_freeze_table.vue'; import DeployFreezeTable from '~/deploy_freeze/components/deploy_freeze_table.vue';
import createStore from '~/deploy_freeze/store'; import createStore from '~/deploy_freeze/store';
import { RECEIVE_FREEZE_PERIODS_SUCCESS } from '~/deploy_freeze/store/mutation_types';
import { freezePeriodsFixture, timezoneDataFixture } from '../helpers'; import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
const localVue = createLocalVue(); const localVue = createLocalVue();
...@@ -26,6 +27,7 @@ describe('Deploy freeze table', () => { ...@@ -26,6 +27,7 @@ describe('Deploy freeze table', () => {
const findEmptyFreezePeriods = () => wrapper.find('[data-testid="empty-freeze-periods"]'); const findEmptyFreezePeriods = () => wrapper.find('[data-testid="empty-freeze-periods"]');
const findAddDeployFreezeButton = () => wrapper.find('[data-testid="add-deploy-freeze"]'); const findAddDeployFreezeButton = () => wrapper.find('[data-testid="add-deploy-freeze"]');
const findEditDeployFreezeButton = () => wrapper.find('[data-testid="edit-deploy-freeze"]');
const findDeployFreezeTable = () => wrapper.find('[data-testid="deploy-freeze-table"]'); const findDeployFreezeTable = () => wrapper.find('[data-testid="deploy-freeze-table"]');
beforeEach(() => { beforeEach(() => {
...@@ -45,17 +47,31 @@ describe('Deploy freeze table', () => { ...@@ -45,17 +47,31 @@ describe('Deploy freeze table', () => {
it('displays empty', () => { it('displays empty', () => {
expect(findEmptyFreezePeriods().exists()).toBe(true); expect(findEmptyFreezePeriods().exists()).toBe(true);
expect(findEmptyFreezePeriods().text()).toBe( expect(findEmptyFreezePeriods().text()).toBe(
'No deploy freezes exist for this project. To add one, click Add deploy freeze', 'No deploy freezes exist for this project. To add one, select Add deploy freeze',
); );
}); });
it('displays data', () => { describe('with data', () => {
store.state.freezePeriods = freezePeriodsFixture; beforeEach(async () => {
store.commit(RECEIVE_FREEZE_PERIODS_SUCCESS, freezePeriodsFixture);
await wrapper.vm.$nextTick();
});
return wrapper.vm.$nextTick(() => { it('displays data', () => {
const tableRows = findDeployFreezeTable().findAll('tbody tr'); const tableRows = findDeployFreezeTable().findAll('tbody tr');
expect(tableRows.length).toBe(freezePeriodsFixture.length); expect(tableRows.length).toBe(freezePeriodsFixture.length);
expect(findEmptyFreezePeriods().exists()).toBe(false); expect(findEmptyFreezePeriods().exists()).toBe(false);
expect(findEditDeployFreezeButton().exists()).toBe(true);
});
it('allows user to edit deploy freeze', async () => {
findEditDeployFreezeButton().trigger('click');
await wrapper.vm.$nextTick();
expect(store.dispatch).toHaveBeenCalledWith(
'setFreezePeriod',
store.state.freezePeriods[0],
);
}); });
}); });
}); });
......
...@@ -23,12 +23,46 @@ describe('deploy freeze store actions', () => { ...@@ -23,12 +23,46 @@ describe('deploy freeze store actions', () => {
}); });
Api.freezePeriods.mockResolvedValue({ data: freezePeriodsFixture }); Api.freezePeriods.mockResolvedValue({ data: freezePeriodsFixture });
Api.createFreezePeriod.mockResolvedValue(); Api.createFreezePeriod.mockResolvedValue();
Api.updateFreezePeriod.mockResolvedValue();
}); });
afterEach(() => { afterEach(() => {
mock.restore(); mock.restore();
}); });
describe('setSelectedFreezePeriod', () => {
it('commits SET_SELECTED_TIMEZONE mutation', () => {
testAction(
actions.setFreezePeriod,
{
id: 3,
cronTimezone: 'UTC',
freezeStart: 'start',
freezeEnd: 'end',
},
{},
[
{
payload: 3,
type: types.SET_SELECTED_ID,
},
{
payload: 'UTC',
type: types.SET_SELECTED_TIMEZONE,
},
{
payload: 'start',
type: types.SET_FREEZE_START_CRON,
},
{
payload: 'end',
type: types.SET_FREEZE_END_CRON,
},
],
);
});
});
describe('setSelectedTimezone', () => { describe('setSelectedTimezone', () => {
it('commits SET_SELECTED_TIMEZONE mutation', () => { it('commits SET_SELECTED_TIMEZONE mutation', () => {
testAction(actions.setSelectedTimezone, {}, {}, [ testAction(actions.setSelectedTimezone, {}, {}, [
...@@ -68,10 +102,16 @@ describe('deploy freeze store actions', () => { ...@@ -68,10 +102,16 @@ describe('deploy freeze store actions', () => {
state, state,
[{ type: 'RESET_MODAL' }], [{ type: 'RESET_MODAL' }],
[ [
{ type: 'requestAddFreezePeriod' }, { type: 'requestFreezePeriod' },
{ type: 'receiveAddFreezePeriodSuccess' }, { type: 'receiveFreezePeriodSuccess' },
{ type: 'fetchFreezePeriods' }, { type: 'fetchFreezePeriods' },
], ],
() =>
expect(Api.createFreezePeriod).toHaveBeenCalledWith(state.projectId, {
freeze_start: state.freezeStartCron,
freeze_end: state.freezeEndCron,
cron_timezone: state.selectedTimezoneIdentifier,
}),
); );
}); });
...@@ -83,7 +123,43 @@ describe('deploy freeze store actions', () => { ...@@ -83,7 +123,43 @@ describe('deploy freeze store actions', () => {
{}, {},
state, state,
[], [],
[{ type: 'requestAddFreezePeriod' }, { type: 'receiveAddFreezePeriodError' }], [{ type: 'requestFreezePeriod' }, { type: 'receiveFreezePeriodError' }],
() => expect(createFlash).toHaveBeenCalled(),
);
});
});
describe('updateFreezePeriod', () => {
it('dispatch correct actions on updating a freeze period', () => {
testAction(
actions.updateFreezePeriod,
{},
state,
[{ type: 'RESET_MODAL' }],
[
{ type: 'requestFreezePeriod' },
{ type: 'receiveFreezePeriodSuccess' },
{ type: 'fetchFreezePeriods' },
],
() =>
expect(Api.updateFreezePeriod).toHaveBeenCalledWith(state.projectId, {
id: state.selectedId,
freeze_start: state.freezeStartCron,
freeze_end: state.freezeEndCron,
cron_timezone: state.selectedTimezoneIdentifier,
}),
);
});
it('should show flash error and set error in state on add failure', () => {
Api.updateFreezePeriod.mockRejectedValue();
testAction(
actions.updateFreezePeriod,
{},
state,
[],
[{ type: 'requestFreezePeriod' }, { type: 'receiveFreezePeriodError' }],
() => expect(createFlash).toHaveBeenCalled(), () => expect(createFlash).toHaveBeenCalled(),
); );
}); });
......
...@@ -33,7 +33,10 @@ describe('Deploy freeze mutations', () => { ...@@ -33,7 +33,10 @@ describe('Deploy freeze mutations', () => {
const expectedFreezePeriods = freezePeriodsFixture.map((freezePeriod, index) => ({ const expectedFreezePeriods = freezePeriodsFixture.map((freezePeriod, index) => ({
...convertObjectPropsToCamelCase(freezePeriod), ...convertObjectPropsToCamelCase(freezePeriod),
cronTimezone: timezoneNames[index], cronTimezone: {
formattedTimezone: timezoneNames[index],
identifier: freezePeriod.cronTimezone,
},
})); }));
expect(stateCopy.freezePeriods).toMatchObject(expectedFreezePeriods); expect(stateCopy.freezePeriods).toMatchObject(expectedFreezePeriods);
...@@ -62,11 +65,19 @@ describe('Deploy freeze mutations', () => { ...@@ -62,11 +65,19 @@ describe('Deploy freeze mutations', () => {
}); });
}); });
describe('SET_FREEZE_ENDT_CRON', () => { describe('SET_FREEZE_END_CRON', () => {
it('should set freezeEndCron', () => { it('should set freezeEndCron', () => {
mutations[types.SET_FREEZE_END_CRON](stateCopy, '5 0 * 8 *'); mutations[types.SET_FREEZE_END_CRON](stateCopy, '5 0 * 8 *');
expect(stateCopy.freezeEndCron).toBe('5 0 * 8 *'); expect(stateCopy.freezeEndCron).toBe('5 0 * 8 *');
}); });
}); });
describe('SET_SELECTED_ID', () => {
it('should set selectedId', () => {
mutations[types.SET_SELECTED_ID](stateCopy, 5);
expect(stateCopy.selectedId).toBe(5);
});
});
}); });
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