Commit a404a66b authored by Jiaan Louw's avatar Jiaan Louw Committed by Mike Greiling

Refactor and apply suggestions to WeightSelect

Refactor WeightSelect component

Remove value prop as it is not required since
the weight is set by the board property.

Migrate board/weight_select_spec to jest

Migrate from karma to jest spec and update
specs for new component.

Prettify weight select files

This applies prettier to the WeightSelect
component and its spec file.

Remove nextTick from WeightSelect

Update WeightSelect component and spec

Reference weight select container by ref instead
of classname.

Update weight select component spec

Add test for canEdit property.

Update weight select components and sepcs

Remove ref used to test div click.

Prettify weight select spec

Remove jquery weight_select component

Remove the old and unused weight_select component
and its reference.

Update weight select specs

Fixes the rspec weight board specs
Improves the jest spec with each.it block

Add changelog entry for component refactor

Remove unused data prop from WeightSelect

Prettify weight_select spec

Apply suggestions to WeightSelect

Changes apply to both the component and spec files

Undo changes made to the old weight_select files

This touches the changes to issues/form.js and the
old jqiery weight_select component.
parent bd392b93
<script>
/* eslint-disable vue/require-default-prop */
/* eslint-disable @gitlab/vue-i18n/no-bare-strings */
import WeightSelect from 'ee/weight_select';
import { GlLoadingIcon } from '@gitlab/ui';
import { GlButton, GlDropdown, GlDropdownItem } from '@gitlab/ui';
const ANY_WEIGHT = 'Any Weight';
const NO_WEIGHT = 'No Weight';
export default {
components: {
GlLoadingIcon,
GlButton,
GlDropdown,
GlDropdownItem,
},
props: {
board: {
type: Object,
required: true,
},
value: {
type: [Number, String],
required: false,
},
canEdit: {
type: Boolean,
required: false,
......@@ -33,7 +27,7 @@ export default {
},
data() {
return {
fieldName: 'weight',
dropdownHidden: true,
};
},
computed: {
......@@ -44,21 +38,20 @@ export default {
return 'bold';
},
valueText() {
if (this.value > 0) return this.value;
if (this.value === 0) return NO_WEIGHT;
const { weight } = this.board;
if (weight > 0) return weight.toString();
if (weight === 0 || weight === NO_WEIGHT) return NO_WEIGHT;
return ANY_WEIGHT;
},
},
mounted() {
this.weightDropdown = new WeightSelect(this.$refs.dropdownButton, {
handleClick: this.selectWeight,
selected: this.value,
fieldName: this.fieldName,
});
},
methods: {
selectWeight(weight) {
showDropdown() {
this.dropdownHidden = false;
this.$refs.dropdown.$children[0].show();
},
selectWeight({ target: { value: weight } }) {
this.board.weight = this.weightInt(weight);
this.dropdownHidden = true;
},
weightInt(weight) {
if (weight > 0) {
......@@ -76,38 +69,26 @@ export default {
<template>
<div class="block weight">
<div class="title append-bottom-10">
Weight
<button v-if="canEdit" type="button" class="edit-link btn btn-blank float-right">
{{ __('Weight') }}
<gl-button v-if="canEdit" variant="blank" class="float-right" @click="showDropdown">
{{ __('Edit') }}
</button>
</gl-button>
</div>
<div :class="valueClass" class="value">{{ valueText }}</div>
<div class="selectbox" style="display: none;">
<input :name="fieldName" type="hidden" />
<div class="dropdown">
<button
ref="dropdownButton"
class="dropdown-menu-toggle js-weight-select wide"
type="button"
data-default-label="Weight"
data-toggle="dropdown"
>
<span class="dropdown-toggle-text is-default">{{ __('Weight') }}</span>
<i aria-hidden="true" data-hidden="true" class="fa fa-chevron-down"> </i>
</button>
<div class="dropdown-menu dropdown-select dropdown-menu-selectable dropdown-menu-weight">
<div class="dropdown-content ">
<ul>
<li v-for="weight in weights" :key="weight">
<a :class="{ 'is-active': weight == valueText }" :data-id="weight" href="#">
{{ weight }}
</a>
</li>
</ul>
</div>
<div class="dropdown-loading"><gl-loading-icon /></div>
</div>
<div :class="valueClass" :hidden="!dropdownHidden" class="value">{{ valueText }}</div>
<gl-dropdown
ref="dropdown"
:hidden="dropdownHidden"
:text="valueText"
class="w-100"
menu-class="w-100"
toggle-class="d-flex justify-content-between"
>
<div ref="weight-select" @click="selectWeight">
<gl-dropdown-item v-for="weight in weights" :key="weight" :value="weight">
{{ weight }}
</gl-dropdown-item>
</div>
</div>
</gl-dropdown>
</div>
</template>
---
title: Refactor WeightSelect to use gitlab-ui dropdown
merge_request: 20770
author:
type: change
......@@ -508,6 +508,8 @@ describe 'Scoped issue boards', :js do
if value.is_a?(Array)
value.each { |value| click_link value }
elsif filter == 'weight'
click_button value
else
click_link value
end
......@@ -536,7 +538,7 @@ describe 'Scoped issue boards', :js do
page.within(".#{filter}") do
click_button 'Edit'
click_link value
filter == 'weight' ? click_button(value) : click_link(value)
end
click_on_board_modal
......
import { mount } from '@vue/test-utils';
import WeightSelect from 'ee/boards/components/weight_select.vue';
import { GlButton, GlDropdown } from '@gitlab/ui';
describe('WeightSelect', () => {
let wrapper;
const editButton = () => wrapper.find(GlButton);
const valueContainer = () => wrapper.find('.value');
const weightDropdown = () => wrapper.find(GlDropdown);
const weightSelect = () => wrapper.find({ ref: 'weight-select' });
const defaultProps = {
weights: ['Any Weight', 'No Weight', 1, 2, 3],
board: {
weight: null,
},
canEdit: true,
};
const createComponent = (props = {}) => {
wrapper = mount(WeightSelect, {
propsData: {
...defaultProps,
...props,
},
});
};
afterEach(() => {
wrapper.destroy();
});
describe('when no weight has been selected', () => {
beforeEach(() => {
createComponent();
});
it('displays "Any Weight"', () => {
expect(valueContainer().text()).toEqual('Any Weight');
});
it('hides the weight dropdown', () => {
expect(weightDropdown().isVisible()).toBeFalsy();
});
});
describe('when the weight cannot be edited', () => {
beforeEach(() => {
createComponent({ canEdit: false });
});
it('does not render the edit button', () => {
expect(editButton().exists()).toBeFalsy();
});
});
describe('when the weight can be edited', () => {
beforeEach(() => {
createComponent();
});
it('shows the edit button', () => {
expect(editButton().isVisible()).toBeTruthy();
});
describe('and the edit button is clicked', () => {
beforeEach(() => {
editButton().trigger('click');
});
describe('and no weight has been selected yet', () => {
it('hides the value text', () => {
expect(valueContainer().isVisible()).toBeFalsy();
});
it('shows the weight dropdown', () => {
expect(weightDropdown().isVisible()).toBeTruthy();
});
});
describe('and a weight has been selected', () => {
beforeEach(() => {
weightSelect().trigger('click');
});
it('shows the value text', () => {
expect(valueContainer().isVisible()).toBeTruthy();
});
it('hides the weight dropdown', () => {
expect(weightDropdown().isVisible()).toBeFalsy();
});
});
});
});
describe('when a new weight value is selected', () => {
it.each`
weight | text
${'Any Weight'} | ${'Any Weight'}
${'No Weight'} | ${'No Weight'}
${0} | ${'No Weight'}
${-1} | ${'Any Weight'}
${1} | ${'1'}
`('$weight displays as "$text"', ({ weight, text }) => {
createComponent({ board: { weight } });
expect(valueContainer().text()).toEqual(text);
});
});
});
import Vue from 'vue';
import WeightSelect from 'ee/boards/components/weight_select.vue';
import IssuableContext from '~/issuable_context';
let vm;
let board;
const weights = ['Any Weight', 'No Weight', 1, 2, 3];
function getSelectedText() {
return vm.$el.querySelector('.value').innerText.trim();
}
function activeDropdownItem() {
return vm.$el.querySelector('.is-active').innerText.trim();
}
describe('WeightSelect', () => {
beforeEach(done => {
setFixtures('<div class="test-container"></div>');
board = {
weight: 0,
labels: [],
};
// eslint-disable-next-line no-new
new IssuableContext();
const Component = Vue.extend(WeightSelect);
vm = new Component({
propsData: {
board,
canEdit: true,
weights,
},
}).$mount('.test-container');
Vue.nextTick(done);
});
describe('selected value', () => {
it('defaults to Any Weight', () => {
expect(getSelectedText()).toBe('Any Weight');
});
it('displays Any Weight for value -1', done => {
vm.value = -1;
Vue.nextTick(() => {
expect(getSelectedText()).toEqual('Any Weight');
done();
});
});
it('displays No Weight', done => {
vm.value = 0;
Vue.nextTick(() => {
expect(getSelectedText()).toEqual('No Weight');
done();
});
});
it('weight 1', done => {
vm.value = 1;
Vue.nextTick(() => {
expect(getSelectedText()).toEqual('1');
done();
});
});
});
describe('active item in dropdown', () => {
it('defaults to Any Weight', done => {
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
expect(activeDropdownItem()).toEqual('Any Weight');
done();
});
});
it('shows No Weight', done => {
vm.value = 0;
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
expect(activeDropdownItem()).toEqual('No Weight');
done();
});
});
it('shows correct weight', done => {
vm.value = 1;
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
expect(activeDropdownItem()).toEqual('1');
done();
});
});
});
describe('changing weight', () => {
it('sets value', done => {
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
vm.$el.querySelectorAll('li a')[3].click();
});
setTimeout(() => {
expect(activeDropdownItem()).toEqual('2');
expect(board.weight).toEqual('2');
done();
});
});
it('sets Any Weight', done => {
vm.value = 2;
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
vm.$el.querySelectorAll('li a')[0].click();
});
setTimeout(() => {
expect(activeDropdownItem()).toEqual('Any Weight');
expect(board.weight).toEqual(-1);
done();
});
});
it('sets No Weight', done => {
vm.value = 2;
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
vm.$el.querySelectorAll('li a')[1].click();
});
setTimeout(() => {
expect(activeDropdownItem()).toEqual('No Weight');
expect(board.weight).toEqual(0);
done();
});
});
});
});
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