diff options
author | Paul Gascou-Vaillancourt <paul.gascvail@gmail.com> | 2019-08-29 13:52:25 -0400 |
---|---|---|
committer | Paul Gascou-Vaillancourt <paul.gascvail@gmail.com> | 2019-09-04 12:17:56 -0400 |
commit | 929eb0568874cfe224ec59dbc4dda939f050dff4 (patch) | |
tree | af794d1db9962b3d9abf935edc8b2fb775976815 | |
parent | ea4e9ada64091e186969d9656c74c7923652fcad (diff) | |
download | gitlab-ce-929eb0568874cfe224ec59dbc4dda939f050dff4.tar.gz |
Backport "Add toggle to hide dismissed vulnerabilities"9102-hide-dismissed-vulnerabilities-in-the-group-security-dashboard-backport
Backport of https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/15333
-rw-r--r-- | app/assets/javascripts/vue_shared/components/gl_toggle_vuex.vue | 49 | ||||
-rw-r--r-- | spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js | 115 |
2 files changed, 164 insertions, 0 deletions
diff --git a/app/assets/javascripts/vue_shared/components/gl_toggle_vuex.vue b/app/assets/javascripts/vue_shared/components/gl_toggle_vuex.vue new file mode 100644 index 00000000000..b649dac029a --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/gl_toggle_vuex.vue @@ -0,0 +1,49 @@ +<script> +import { GlToggle } from '@gitlab/ui'; +import { capitalizeFirstCharacter } from '~/lib/utils/text_utility'; + +export default { + name: 'GlToggleVuex', + components: { + GlToggle, + }, + props: { + stateProperty: { + type: String, + required: true, + }, + storeModule: { + type: String, + required: false, + default: null, + }, + setAction: { + type: String, + required: false, + default() { + return `set${capitalizeFirstCharacter(this.stateProperty)}`; + }, + }, + }, + computed: { + value: { + get() { + const { state } = this.$store; + const { stateProperty, storeModule } = this; + return storeModule ? state[storeModule][stateProperty] : state[stateProperty]; + }, + set(value) { + const { stateProperty, storeModule, setAction } = this; + const action = storeModule ? `${storeModule}/${setAction}` : setAction; + this.$store.dispatch(action, { key: stateProperty, value }); + }, + }, + }, +}; +</script> + +<template> + <gl-toggle v-model="value"> + <slot v-bind="{ value }"></slot> + </gl-toggle> +</template> diff --git a/spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js b/spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js new file mode 100644 index 00000000000..f076c45e56c --- /dev/null +++ b/spec/frontend/vue_shared/components/gl_toggle_vuex_spec.js @@ -0,0 +1,115 @@ +import Vuex from 'vuex'; +import GlToggleVuex from '~/vue_shared/components/gl_toggle_vuex.vue'; +import { GlToggle } from '@gitlab/ui'; +import { mount, createLocalVue } from '@vue/test-utils'; + +const localVue = createLocalVue(); +localVue.use(Vuex); + +describe('GlToggleVuex component', () => { + let wrapper; + let store; + + const findButton = () => wrapper.find('button'); + + const createWrapper = (props = {}) => { + wrapper = mount(GlToggleVuex, { + localVue, + store, + propsData: { + stateProperty: 'toggleState', + ...props, + }, + sync: false, + }); + }; + + beforeEach(() => { + store = new Vuex.Store({ + state: { + toggleState: false, + }, + actions: { + setToggleState: ({ commit }, { key, value }) => commit('setToggleState', { key, value }), + }, + mutations: { + setToggleState: (state, { key, value }) => { + state[key] = value; + }, + }, + }); + createWrapper(); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('renders gl-toggle', () => { + expect(wrapper.find(GlToggle).exists()).toBe(true); + }); + + it('properly computes default value for setAction', () => { + expect(wrapper.props('setAction')).toBe('setToggleState'); + }); + + describe('without a store module', () => { + it('calls action with new value when value changes', () => { + jest.spyOn(store, 'dispatch'); + + findButton().trigger('click'); + expect(store.dispatch).toHaveBeenCalledWith('setToggleState', { + key: 'toggleState', + value: true, + }); + }); + + it('updates store property when value changes', () => { + findButton().trigger('click'); + expect(store.state.toggleState).toBe(true); + }); + }); + + describe('with a store module', () => { + beforeEach(() => { + store = new Vuex.Store({ + modules: { + someModule: { + namespaced: true, + state: { + toggleState: false, + }, + actions: { + setToggleState: ({ commit }, { key, value }) => + commit('setToggleState', { key, value }), + }, + mutations: { + setToggleState: (state, { key, value }) => { + state[key] = value; + }, + }, + }, + }, + }); + + createWrapper({ + storeModule: 'someModule', + }); + }); + + it('calls action with new value when value changes', () => { + jest.spyOn(store, 'dispatch'); + + findButton().trigger('click'); + expect(store.dispatch).toHaveBeenCalledWith('someModule/setToggleState', { + key: 'toggleState', + value: true, + }); + }); + + it('updates store property when value changes', () => { + findButton().trigger('click'); + expect(store.state.someModule.toggleState).toBe(true); + }); + }); +}); |