Commit 0219bbdd authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'psi-cadence-edit' into 'master'

Add cadence edit page

See merge request gitlab-org/gitlab!62587
parents 8ae2080e d02d5775
...@@ -9,8 +9,11 @@ import { ...@@ -9,8 +9,11 @@ import {
GlFormInput, GlFormInput,
GlFormSelect, GlFormSelect,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { s__, __ } from '~/locale'; import { s__, __ } from '~/locale';
import createCadence from '../queries/create_cadence.mutation.graphql'; import createCadence from '../queries/cadence_create.mutation.graphql';
import updateCadence from '../queries/cadence_update.mutation.graphql';
import readCadence from '../queries/iteration_cadence.query.graphql';
const i18n = Object.freeze({ const i18n = Object.freeze({
title: { title: {
...@@ -36,16 +39,22 @@ const i18n = Object.freeze({ ...@@ -36,16 +39,22 @@ const i18n = Object.freeze({
description: s__('Iterations|Number of future iterations you would like to have scheduled'), description: s__('Iterations|Number of future iterations you would like to have scheduled'),
placeholder: s__('Iterations|Select number'), placeholder: s__('Iterations|Select number'),
}, },
pageTitle: s__('Iterations|New iteration cadence'), edit: {
create: s__('Iterations|Create cadence'), title: s__('Iterations|Edit iteration cadence'),
save: s__('Iterations|Save cadence'),
},
new: {
title: s__('Iterations|New iteration cadence'),
save: s__('Iterations|Create cadence'),
},
cancel: __('Cancel'), cancel: __('Cancel'),
requiredField: __('This field is required.'), requiredField: __('This field is required.'),
}); });
export default { export default {
availableDurations: [{ value: null, text: i18n.duration.placeholder }, 1, 2, 3, 4, 5, 6], availableDurations: [{ value: 0, text: i18n.duration.placeholder }, 1, 2, 3, 4, 5, 6],
availableFutureIterations: [ availableFutureIterations: [
{ value: null, text: i18n.futureIterations.placeholder }, { value: 0, text: i18n.futureIterations.placeholder },
2, 2,
4, 4,
6, 6,
...@@ -67,15 +76,19 @@ export default { ...@@ -67,15 +76,19 @@ export default {
inject: ['groupPath', 'cadencesListPath'], inject: ['groupPath', 'cadencesListPath'],
data() { data() {
return { return {
cadences: [], group: {
loading: false,
iterationCadences: {
nodes: [],
},
},
loading: false, loading: false,
errorMessage: '', errorMessage: '',
title: '', title: '',
automatic: true, automatic: true,
startDate: null, startDate: null,
durationInWeeks: null, durationInWeeks: 0,
rollOverIssues: false, iterationsInAdvance: 0,
iterationsInAdvance: null,
validationState: { validationState: {
title: null, title: null,
startDate: null, startDate: null,
...@@ -86,27 +99,80 @@ export default { ...@@ -86,27 +99,80 @@ export default {
}; };
}, },
computed: { computed: {
loadingCadence() {
return this.$apollo.queries.group.loading;
},
cadenceId() {
return this.$router.currentRoute.params.cadenceId;
},
isEdit() {
return Boolean(this.cadenceId);
},
page() {
return this.isEdit ? 'edit' : 'new';
},
mutation() {
return this.isEdit ? updateCadence : createCadence;
},
valid() { valid() {
return !Object.values(this.validationState).includes(false); return !Object.values(this.validationState).includes(false);
}, },
variables() { variables() {
const id = this.isEdit
? convertToGraphQLId('Iterations::Cadence', this.cadenceId)
: undefined;
const groupPath = this.isEdit ? undefined : this.groupPath;
const vars = { const vars = {
input: { input: {
groupPath: this.groupPath, groupPath,
id,
title: this.title, title: this.title,
automatic: this.automatic, automatic: this.automatic,
startDate: this.startDate, startDate: this.startDate,
durationInWeeks: this.durationInWeeks, durationInWeeks: this.durationInWeeks,
active: true, active: true,
iterationsInAdvance: this.iterationsInAdvance,
}, },
}; };
if (this.automatic) {
vars.input = { return vars;
...vars.input, },
iterationsInAdvance: this.iterationsInAdvance, },
apollo: {
group: {
skip() {
return !this.isEdit;
},
query: readCadence,
variables() {
return {
fullPath: this.groupPath,
id: this.cadenceId,
}; };
},
result({ data: { group, errors } }) {
if (errors?.length) {
[this.errorMessage] = errors;
return;
} }
return vars;
const cadence = group?.iterationCadences?.nodes?.[0];
if (!cadence) {
this.errorMessage = s__("Iterations|Couldn't find iteration cadence");
return;
}
this.title = cadence.title;
this.automatic = cadence.automatic;
this.startDate = cadence.startDate;
this.durationInWeeks = cadence.durationInWeeks;
this.iterationsInAdvance = cadence.iterationsInAdvance;
},
error(error) {
this.errorMessage = error;
},
}, },
}, },
methods: { methods: {
...@@ -131,6 +197,12 @@ export default { ...@@ -131,6 +197,12 @@ export default {
this.validationState.durationInWeeks = null; this.validationState.durationInWeeks = null;
this.validationState.iterationsInAdvance = null; this.validationState.iterationsInAdvance = null;
}, },
updateAutomatic(value) {
this.clearValidation();
if (!value) {
this.iterationsInAdvance = 0;
}
},
save() { save() {
this.validateAllFields(); this.validateAllFields();
...@@ -147,18 +219,18 @@ export default { ...@@ -147,18 +219,18 @@ export default {
createCadence() { createCadence() {
return this.$apollo return this.$apollo
.mutate({ .mutate({
mutation: createCadence, mutation: this.mutation,
variables: this.variables, variables: this.variables,
}) })
.then(({ data, errors: topLevelErrors = [] }) => { .then(({ data, errors: topLevelErrors = [] } = {}) => {
if (topLevelErrors.length > 0) { if (topLevelErrors.length > 0) {
this.errorMessage = topLevelErrors[0].message; this.errorMessage = topLevelErrors[0].message;
return; return;
} }
const { errors } = data.iterationCadenceCreate; const { errors } = data?.result || {};
if (errors.length > 0) { if (errors?.length > 0) {
[this.errorMessage] = errors; [this.errorMessage] = errors;
return; return;
} }
...@@ -181,7 +253,7 @@ export default { ...@@ -181,7 +253,7 @@ export default {
<article> <article>
<div class="gl-display-flex"> <div class="gl-display-flex">
<h3 ref="pageTitle" class="page-title"> <h3 ref="pageTitle" class="page-title">
{{ i18n.pageTitle }} {{ i18n[page].title }}
</h3> </h3>
</div> </div>
<gl-form> <gl-form>
...@@ -205,6 +277,7 @@ export default { ...@@ -205,6 +277,7 @@ export default {
:placeholder="i18n.title.placeholder" :placeholder="i18n.title.placeholder"
size="xl" size="xl"
:state="validationState.title" :state="validationState.title"
:disabled="loadingCadence"
@blur="validate('title')" @blur="validate('title')"
/> />
</gl-form-group> </gl-form-group>
...@@ -218,7 +291,8 @@ export default { ...@@ -218,7 +291,8 @@ export default {
<gl-form-checkbox <gl-form-checkbox
id="cadence-automated-scheduling" id="cadence-automated-scheduling"
v-model="automatic" v-model="automatic"
@change="clearValidation" :disabled="loadingCadence"
@change="updateAutomatic"
> >
<span class="gl-font-weight-bold">{{ i18n.automatedScheduling.label }}</span> <span class="gl-font-weight-bold">{{ i18n.automatedScheduling.label }}</span>
</gl-form-checkbox> </gl-form-checkbox>
...@@ -243,6 +317,7 @@ export default { ...@@ -243,6 +317,7 @@ export default {
inputmode="none" inputmode="none"
required required
:state="validationState.startDate" :state="validationState.startDate"
:disabled="loadingCadence"
data-qa-selector="cadence_start_date" data-qa-selector="cadence_start_date"
@blur="validate('startDate')" @blur="validate('startDate')"
/> />
...@@ -265,6 +340,7 @@ export default { ...@@ -265,6 +340,7 @@ export default {
class="gl-form-input-md" class="gl-form-input-md"
required required
data-qa-selector="iteration_cadence_name_field" data-qa-selector="iteration_cadence_name_field"
:disabled="loadingCadence"
@change="validate('durationInWeeks')" @change="validate('durationInWeeks')"
/> />
</gl-form-group> </gl-form-group>
...@@ -282,7 +358,7 @@ export default { ...@@ -282,7 +358,7 @@ export default {
<gl-form-select <gl-form-select
id="cadence-schedule-future-iterations" id="cadence-schedule-future-iterations"
v-model.number="iterationsInAdvance" v-model.number="iterationsInAdvance"
:disabled="!automatic" :disabled="!automatic || loadingCadence"
:options="$options.availableFutureIterations" :options="$options.availableFutureIterations"
:required="automatic" :required="automatic"
class="gl-form-input-md" class="gl-form-input-md"
...@@ -299,7 +375,7 @@ export default { ...@@ -299,7 +375,7 @@ export default {
data-qa-selector="save_cadence_button" data-qa-selector="save_cadence_button"
@click="save" @click="save"
> >
{{ i18n.create }} {{ i18n[page].save }}
</gl-button> </gl-button>
<gl-button class="ml-auto" data-testid="cancel-create-cadence" @click="cancel"> <gl-button class="ml-auto" data-testid="cancel-create-cadence" @click="cancel">
{{ i18n.cancel }} {{ i18n.cancel }}
......
...@@ -3,6 +3,8 @@ import { ...@@ -3,6 +3,8 @@ import {
GlAlert, GlAlert,
GlButton, GlButton,
GlCollapse, GlCollapse,
GlDropdown,
GlDropdownItem,
GlIcon, GlIcon,
GlInfiniteScroll, GlInfiniteScroll,
GlSkeletonLoader, GlSkeletonLoader,
...@@ -24,6 +26,8 @@ export default { ...@@ -24,6 +26,8 @@ export default {
GlAlert, GlAlert,
GlButton, GlButton,
GlCollapse, GlCollapse,
GlDropdown,
GlDropdownItem,
GlIcon, GlIcon,
GlInfiniteScroll, GlInfiniteScroll,
GlSkeletonLoader, GlSkeletonLoader,
...@@ -42,7 +46,7 @@ export default { ...@@ -42,7 +46,7 @@ export default {
}, },
}, },
}, },
inject: ['groupPath'], inject: ['groupPath', 'canEditCadence'],
props: { props: {
title: { title: {
type: String, type: String,
...@@ -159,7 +163,7 @@ export default { ...@@ -159,7 +163,7 @@ export default {
<div class="gl-display-flex gl-align-items-center"> <div class="gl-display-flex gl-align-items-center">
<gl-button <gl-button
variant="link" variant="link"
class="gl-font-weight-bold gl-text-body! gl-py-5! gl-px-3! gl-mr-auto" class="gl-font-weight-bold gl-text-body! gl-py-5! gl-px-3! gl-mr-auto gl-min-w-0"
:aria-expanded="expanded" :aria-expanded="expanded"
@click="expanded = !expanded" @click="expanded = !expanded"
> >
...@@ -171,10 +175,23 @@ export default { ...@@ -171,10 +175,23 @@ export default {
{{ title }} {{ title }}
</gl-button> </gl-button>
<span v-if="durationInWeeks" class="gl-mr-5"> <span v-if="durationInWeeks" class="gl-mr-5 gl-display-none gl-sm-display-inline-block">
<gl-icon name="clock" class="gl-mr-3" /> <gl-icon name="clock" class="gl-mr-3" />
{{ n__('Every week', 'Every %d weeks', durationInWeeks) }}</span {{ n__('Every week', 'Every %d weeks', durationInWeeks) }}</span
> >
<gl-dropdown
v-if="canEditCadence"
icon="ellipsis_v"
category="tertiary"
right
lazy
text-sr-only
no-caret
>
<gl-dropdown-item :to="editCadence">
{{ s__('Iterations|Edit cadence') }}
</gl-dropdown-item>
</gl-dropdown>
</div> </div>
<gl-alert v-if="error" variant="danger" :dismissible="true" @dismiss="error = ''"> <gl-alert v-if="error" variant="danger" :dismissible="true" @dismiss="error = ''">
......
...@@ -32,12 +32,14 @@ export default { ...@@ -32,12 +32,14 @@ export default {
data() { data() {
return { return {
group: { group: {
iterationCadences: [], iterationCadences: {
nodes: [],
pageInfo: { pageInfo: {
hasNextPage: true, hasNextPage: true,
hasPreviousPage: false, hasPreviousPage: false,
}, },
}, },
},
pagination: {}, pagination: {},
tabIndex: 0, tabIndex: 0,
error: '', error: '',
...@@ -104,11 +106,13 @@ export default { ...@@ -104,11 +106,13 @@ export default {
<template #title> <template #title>
{{ tab }} {{ tab }}
</template> </template>
<gl-loading-icon v-if="loading" class="gl-my-5" size="lg" />
<gl-alert v-else-if="error" variant="danger" @dismiss="error = ''"> <gl-alert v-if="error" variant="danger" @dismiss="error = ''">
{{ error }} {{ error }}
</gl-alert> </gl-alert>
<gl-loading-icon v-if="loading" class="gl-my-5" size="lg" />
<template v-else> <template v-else>
<ul v-if="cadences.length" class="content-list"> <ul v-if="cadences.length" class="content-list">
<iteration-cadence-list-item <iteration-cadence-list-item
......
...@@ -114,6 +114,7 @@ export function initCadenceApp() { ...@@ -114,6 +114,7 @@ export function initCadenceApp() {
router, router,
apolloProvider, apolloProvider,
provide: { provide: {
fullPath: groupPath,
groupPath, groupPath,
cadencesListPath, cadencesListPath,
canCreateCadence: parseBoolean(canCreateCadence), canCreateCadence: parseBoolean(canCreateCadence),
......
#import "./iteration_cadence.fragment.graphql"
mutation createIterationCadence($input: IterationCadenceCreateInput!) { mutation createIterationCadence($input: IterationCadenceCreateInput!) {
iterationCadenceCreate(input: $input) { result: iterationCadenceCreate(input: $input) {
iterationCadence { iterationCadence {
id ...IterationCadence
title
} }
errors errors
} }
......
#import "./iteration_cadence.fragment.graphql"
mutation updateIterationCadence($input: IterationCadenceUpdateInput!) {
result: iterationCadenceUpdate(input: $input) {
iterationCadence {
...IterationCadence
}
errors
}
}
fragment IterationCadence on IterationCadence {
id
title
automatic
startDate
durationInWeeks
iterationsInAdvance
}
#import "./iteration_cadence.fragment.graphql"
# todo: should this use IterationsCadenceID! ?
query IterationCadences($fullPath: ID!, $id: ID!) {
group(fullPath: $fullPath) {
iterationCadences(id: $id) {
nodes {
...IterationCadence
}
}
}
}
...@@ -12,6 +12,11 @@ const routes = [ ...@@ -12,6 +12,11 @@ const routes = [
path: '/new', path: '/new',
component: IterationCadenceForm, component: IterationCadenceForm,
}, },
{
name: 'edit',
path: '/:cadenceId/edit',
component: IterationCadenceForm,
},
{ {
name: 'index', name: 'index',
path: '/', path: '/',
......
import { GlFormCheckbox, GlFormGroup } from '@gitlab/ui'; import { GlAlert, GlFormCheckbox, GlFormGroup } from '@gitlab/ui';
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import Vue from 'vue'; import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import IterationCadenceForm from 'ee/iterations/components/iteration_cadence_form.vue'; import IterationCadenceForm from 'ee/iterations/components/iteration_cadence_form.vue';
import createCadence from 'ee/iterations/queries/create_cadence.mutation.graphql'; import createCadence from 'ee/iterations/queries/cadence_create.mutation.graphql';
import readCadence from 'ee/iterations/queries/iteration_cadence.query.graphql';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import { TEST_HOST } from 'helpers/test_constants'; import { TEST_HOST } from 'helpers/test_constants';
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
...@@ -11,6 +13,9 @@ import waitForPromises from 'helpers/wait_for_promises'; ...@@ -11,6 +13,9 @@ import waitForPromises from 'helpers/wait_for_promises';
const push = jest.fn(); const push = jest.fn();
const $router = { const $router = {
currentRoute: {
params: {},
},
push, push,
}; };
...@@ -25,24 +30,34 @@ describe('Iteration cadence form', () => { ...@@ -25,24 +30,34 @@ describe('Iteration cadence form', () => {
const groupPath = 'gitlab-org'; const groupPath = 'gitlab-org';
const id = 72; const id = 72;
const iterationCadence = { const iterationCadence = {
id: `gid://gitlab/Iteration/${id}`, id: `gid://gitlab/Iterations::Cadence/${id}`,
title: 'An iteration', title: 'An iteration',
description: 'The words', automatic: true,
startDate: '2020-06-28', startDate: '2020-06-28',
dueDate: '2020-07-05', durationInWeeks: '3',
iterationsInAdvance: '2',
}; };
const createMutationSuccess = { const createMutationSuccess = {
data: { iterationCadenceCreate: { iterationCadence, errors: [] } }, data: { result: { iterationCadence, errors: [] } },
}; };
const createMutationFailure = { const createMutationFailure = {
data: { data: {
iterationCadenceCreate: { iterationCadence, errors: ['alas, your data is unchanged'] }, result: { iterationCadence, errors: ['alas, your data is unchanged'] },
},
};
const getCadenceSuccess = {
data: {
group: {
iterationCadences: {
nodes: [iterationCadence],
},
},
}, },
}; };
function createComponent({ resolverMock } = {}) { function createComponent({ query = createCadence, resolverMock } = {}) {
const apolloProvider = createMockApolloProvider([[createCadence, resolverMock]]); const apolloProvider = createMockApolloProvider([[query, resolverMock]]);
wrapper = extendedWrapper( wrapper = extendedWrapper(
mount(IterationCadenceForm, { mount(IterationCadenceForm, {
apolloProvider, apolloProvider,
...@@ -67,11 +82,30 @@ describe('Iteration cadence form', () => { ...@@ -67,11 +82,30 @@ describe('Iteration cadence form', () => {
const findDurationGroup = () => wrapper.findAllComponents(GlFormGroup).at(3); const findDurationGroup = () => wrapper.findAllComponents(GlFormGroup).at(3);
const findFutureIterationsGroup = () => wrapper.findAllComponents(GlFormGroup).at(4); const findFutureIterationsGroup = () => wrapper.findAllComponents(GlFormGroup).at(4);
const findError = () => wrapper.findComponent(GlAlert);
const findTitle = () => wrapper.find('#cadence-title'); const findTitle = () => wrapper.find('#cadence-title');
const findStartDate = () => wrapper.find('#cadence-start-date'); const findStartDate = () => wrapper.find('#cadence-start-date');
const findFutureIterations = () => wrapper.find('#cadence-schedule-future-iterations'); const findFutureIterations = () => wrapper.find('#cadence-schedule-future-iterations');
const findDuration = () => wrapper.find('#cadence-duration'); const findDuration = () => wrapper.find('#cadence-duration');
const setTitle = (value) => findTitle().vm.$emit('input', value);
const setStartDate = (value) => findStartDate().vm.$emit('input', value);
const setFutureIterations = (value) => findFutureIterations().vm.$emit('input', value);
const setDuration = (value) => findDuration().vm.$emit('input', value);
const setAutomaticValue = (value) => {
const checkbox = findAutomatedSchedulingGroup().find(GlFormCheckbox).vm;
checkbox.$emit('input', value);
checkbox.$emit('change', value);
};
const findAllFields = () => [
findTitle(),
findStartDate(),
findFutureIterations(),
findDuration(),
];
const findSaveButton = () => wrapper.findByTestId('save-cadence'); const findSaveButton = () => wrapper.findByTestId('save-cadence');
const findCancelButton = () => wrapper.findByTestId('cancel-create-cadence'); const findCancelButton = () => wrapper.findByTestId('cancel-create-cadence');
const clickSave = () => findSaveButton().vm.$emit('click'); const clickSave = () => findSaveButton().vm.$emit('click');
...@@ -92,19 +126,20 @@ describe('Iteration cadence form', () => { ...@@ -92,19 +126,20 @@ describe('Iteration cadence form', () => {
}); });
describe('save', () => { describe('save', () => {
it('triggers mutation with form data', () => {
const title = 'Iteration 5'; const title = 'Iteration 5';
const startDate = '2020-05-05'; const startDate = '2020-05-05';
const durationInWeeks = 2; const durationInWeeks = 2;
const iterationsInAdvance = 6; const iterationsInAdvance = 6;
findTitle().vm.$emit('input', title); it('triggers mutation with form data', () => {
findStartDate().vm.$emit('input', startDate); setTitle(title);
findDuration().vm.$emit('input', durationInWeeks); setStartDate(startDate);
findFutureIterations().vm.$emit('input', iterationsInAdvance); setDuration(durationInWeeks);
setFutureIterations(iterationsInAdvance);
clickSave(); clickSave();
expect(findError().exists()).toBe(false);
expect(resolverMock).toHaveBeenCalledWith({ expect(resolverMock).toHaveBeenCalledWith({
input: { input: {
groupPath, groupPath,
...@@ -119,15 +154,10 @@ describe('Iteration cadence form', () => { ...@@ -119,15 +154,10 @@ describe('Iteration cadence form', () => {
}); });
it('redirects to Iteration page on success', async () => { it('redirects to Iteration page on success', async () => {
const title = 'Iteration 5'; setTitle(title);
const startDate = '2020-05-05'; setStartDate(startDate);
const durationInWeeks = 2; setDuration(durationInWeeks);
const iterationsInAdvance = 6; setFutureIterations(iterationsInAdvance);
findTitle().vm.$emit('input', title);
findStartDate().vm.$emit('input', startDate);
findDuration().vm.$emit('input', durationInWeeks);
findFutureIterations().vm.$emit('input', iterationsInAdvance);
clickSave(); clickSave();
...@@ -159,22 +189,28 @@ describe('Iteration cadence form', () => { ...@@ -159,22 +189,28 @@ describe('Iteration cadence form', () => {
}); });
describe('automated scheduling disabled', () => { describe('automated scheduling disabled', () => {
beforeEach(() => { it('disables future iterations', async () => {
findAutomatedSchedulingGroup().find(GlFormCheckbox).vm.$emit('input', false); setAutomaticValue(false);
});
await nextTick();
it('disables future iterations', () => {
expect(findFutureIterations().attributes('disabled')).toBe('disabled'); expect(findFutureIterations().attributes('disabled')).toBe('disabled');
}); });
it('does not require future iterations ', () => { it('sets future iterations to 0', async () => {
const title = 'Iteration 5'; const title = 'Iteration 5';
const startDate = '2020-05-05'; const startDate = '2020-05-05';
const durationInWeeks = 2; const durationInWeeks = 2;
findTitle().vm.$emit('input', title); setFutureIterations(10);
findStartDate().vm.$emit('input', startDate);
findDuration().vm.$emit('input', durationInWeeks); setAutomaticValue(false);
await nextTick();
setTitle(title);
setStartDate(startDate);
setDuration(durationInWeeks);
clickSave(); clickSave();
...@@ -185,10 +221,58 @@ describe('Iteration cadence form', () => { ...@@ -185,10 +221,58 @@ describe('Iteration cadence form', () => {
automatic: false, automatic: false,
startDate, startDate,
durationInWeeks, durationInWeeks,
iterationsInAdvance: 0,
active: true, active: true,
}, },
}); });
}); });
}); });
}); });
describe('Edit cadence', () => {
const query = readCadence;
const resolverMock = jest.fn().mockResolvedValue(getCadenceSuccess);
beforeEach(() => {
$router.currentRoute.params.cadenceId = id;
});
afterEach(() => {
delete $router.currentRoute.params.cadenceId;
});
it('shows correct title and button text', () => {
createComponent({ query, resolverMock });
expect(wrapper.text()).toContain(wrapper.vm.i18n.edit.title);
expect(wrapper.text()).toContain(wrapper.vm.i18n.edit.save);
});
it('disables fields while loading', async () => {
createComponent({ query, resolverMock });
findAllFields().forEach(({ element }) => {
expect(element).toBeDisabled();
});
await waitForPromises();
findAllFields().forEach(({ element }) => {
expect(element).not.toBeDisabled();
});
});
it('fills fields with existing cadence info after loading', async () => {
createComponent({ query, resolverMock });
await waitForPromises();
await nextTick();
expect(findTitle().element.value).toBe(iterationCadence.title);
expect(findStartDate().element.value).toBe(iterationCadence.startDate);
expect(findFutureIterations().element.value).toBe(iterationCadence.iterationsInAdvance);
expect(findDuration().element.value).toBe(iterationCadence.durationInWeeks);
});
});
}); });
import { GlInfiniteScroll, GlSkeletonLoader } from '@gitlab/ui'; import { GlDropdown, GlInfiniteScroll, GlSkeletonLoader } from '@gitlab/ui';
import { createLocalVue, RouterLinkStub } from '@vue/test-utils'; import { createLocalVue, RouterLinkStub } from '@vue/test-utils';
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
...@@ -82,6 +82,7 @@ describe('Iteration cadence list item', () => { ...@@ -82,6 +82,7 @@ describe('Iteration cadence list item', () => {
function createComponent({ function createComponent({
props = {}, props = {},
canCreateCadence, canCreateCadence,
canEditCadence,
resolverMock = jest.fn().mockResolvedValue(querySuccessResponse), resolverMock = jest.fn().mockResolvedValue(querySuccessResponse),
} = {}) { } = {}) {
apolloProvider = createMockApolloProvider([[iterationsInCadenceQuery, resolverMock]]); apolloProvider = createMockApolloProvider([[iterationsInCadenceQuery, resolverMock]]);
...@@ -98,6 +99,7 @@ describe('Iteration cadence list item', () => { ...@@ -98,6 +99,7 @@ describe('Iteration cadence list item', () => {
provide: { provide: {
groupPath, groupPath,
canCreateCadence, canCreateCadence,
canEditCadence,
}, },
propsData: { propsData: {
title: cadence.title, title: cadence.title,
...@@ -185,4 +187,16 @@ describe('Iteration cadence list item', () => { ...@@ -185,4 +187,16 @@ describe('Iteration cadence list item', () => {
}), }),
); );
}); });
it('hides dropdown when canEditCadence is false', async () => {
await createComponent({ canEditCadence: false });
expect(wrapper.find(GlDropdown).exists()).toBe(false);
});
it('shows dropdown when canEditCadence is true', async () => {
await createComponent({ canEditCadence: true });
expect(wrapper.find(GlDropdown).exists()).toBe(true);
});
}); });
...@@ -82,6 +82,7 @@ describe('Iteration cadences list', () => { ...@@ -82,6 +82,7 @@ describe('Iteration cadences list', () => {
function createComponent({ function createComponent({
canCreateCadence, canCreateCadence,
canEditCadence,
resolverMock = jest.fn().mockResolvedValue(querySuccessResponse), resolverMock = jest.fn().mockResolvedValue(querySuccessResponse),
} = {}) { } = {}) {
apolloProvider = createMockApolloProvider([[cadencesListQuery, resolverMock]]); apolloProvider = createMockApolloProvider([[cadencesListQuery, resolverMock]]);
...@@ -96,6 +97,7 @@ describe('Iteration cadences list', () => { ...@@ -96,6 +97,7 @@ describe('Iteration cadences list', () => {
groupPath, groupPath,
cadencesListPath, cadencesListPath,
canCreateCadence, canCreateCadence,
canEditCadence,
}, },
}); });
......
...@@ -18556,12 +18556,21 @@ msgstr "" ...@@ -18556,12 +18556,21 @@ msgstr ""
msgid "Iterations|Cadence name" msgid "Iterations|Cadence name"
msgstr "" msgstr ""
msgid "Iterations|Couldn't find iteration cadence"
msgstr ""
msgid "Iterations|Create cadence" msgid "Iterations|Create cadence"
msgstr "" msgstr ""
msgid "Iterations|Duration" msgid "Iterations|Duration"
msgstr "" msgstr ""
msgid "Iterations|Edit cadence"
msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
msgid "Iterations|Error loading iteration cadences." msgid "Iterations|Error loading iteration cadences."
msgstr "" msgstr ""
...@@ -18583,6 +18592,9 @@ msgstr "" ...@@ -18583,6 +18592,9 @@ msgstr ""
msgid "Iterations|Number of future iterations you would like to have scheduled" msgid "Iterations|Number of future iterations you would like to have scheduled"
msgstr "" msgstr ""
msgid "Iterations|Save cadence"
msgstr ""
msgid "Iterations|Select duration" msgid "Iterations|Select duration"
msgstr "" 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