diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/tests/unit/LivedataDropdownMenu.spec.js b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/tests/unit/LivedataDropdownMenu.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..05389df0aa947d0067f88e15a1e4d2c2687d460a --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/tests/unit/LivedataDropdownMenu.spec.js @@ -0,0 +1,106 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ + +import {mount} from "@vue/test-utils"; +import LivedataDropdownMenu from "../../LivedataDropdownMenu"; + +/** + * Vue component initializer for `LivedataDropdownMenu` components. Calls `mount()` with preconfigured values. + * + * @returns a map containing a wrapper for `LivedataDropdownMenu` components and a mock of logic.changeLayout + */ +function initWrapper() { + global.XWiki = { + contextPath: '' + } + + const changeLayout = jest.fn(); + const wrapper = mount(LivedataDropdownMenu, { + provide: { + logic: { + currentLayoutId: 'cards', + data: { + meta: { + layouts: [{id: 'table'}, {id: 'cards'}] + } + }, + changeLayout: changeLayout + }, + }, + mocks: { + $t: (key) => key + } + }); + return {wrapper, changeLayout}; +} + +// Since the <li> elements does not have distinguishing attributes, we look for the layout items by looking at the +// elements located after the second separator (class dropdown-header). +function findSecondDropdownHeaderIndex(lis) { + var dropdownHeadersCptr = 0; + var liIdx = 0; + for (; liIdx < lis.length; liIdx++) { + const li = lis.at(liIdx); + if (li.classes().includes('dropdown-header')) { + dropdownHeadersCptr++; + } + if (dropdownHeadersCptr >= 2) { + break; + } + } + return liIdx; +} + +describe('LivedataDropdownMenu.vue', () => { + it('Current layout is greyed out', () => { + const {wrapper} = initWrapper(); + const lis = wrapper.findAll('li'); + const dropDownHeaderIndex = findSecondDropdownHeaderIndex(lis); + + const tableLayout = lis.at(dropDownHeaderIndex + 1); + const cardsLayout = lis.at(dropDownHeaderIndex + 2); + + expect(tableLayout.classes()).not.toContain('disabled'); + expect(cardsLayout.classes()).toContain('disabled'); + }) + + it('Clicking on an enabled layout changes the layout', () => { + const {wrapper, changeLayout} = initWrapper(); + const lis = wrapper.findAll('li'); + const dropDownHeaderIndex = findSecondDropdownHeaderIndex(lis); + const tableLayout = lis.at(dropDownHeaderIndex + 1); + + tableLayout.find('a').trigger('click'); + + expect(changeLayout.mock.calls.length).toBe(1); + expect(changeLayout.mock.calls[0][0]).toBe('table'); + }) + + it('Clicking on a disabled layout does nothing', () => { + const {wrapper, changeLayout} = initWrapper(); + const lis = wrapper.findAll('li'); + const dropDownHeaderIndex = findSecondDropdownHeaderIndex(lis); + const cardsLayout = lis.at(dropDownHeaderIndex + 2); + + cardsLayout.find('a').trigger('click'); + + expect(changeLayout.mock.calls.length).toBe(0); + }) +}) diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/LivedataDropdownMenu.vue b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/LivedataDropdownMenu.vue index 4577e0e5f948dbb117b954e5a7b006f3cbfde9a7..1fa53d375553d756dd374aa97255a36162b61d03 100644 --- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/LivedataDropdownMenu.vue +++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/LivedataDropdownMenu.vue @@ -69,10 +69,10 @@ v-for="layout in data.meta.layouts" :key="layout.id" :class="{ - 'disabled': logic.currentLayoutId === layout.id, + 'disabled': isCurrentLayout(layout.id), }" > - <a href="#" @click.prevent="logic.changeLayout(layout.id)"> + <a href="#" @click.prevent="changeLayout(layout.id)"> <XWikiIcon :icon-descriptor="layout.icon"></XWikiIcon> {{ layout.name }} </a> @@ -127,6 +127,17 @@ export default { data () { return this.logic.data; }, }, + methods: { + isCurrentLayout(layoutId) { + return this.logic.currentLayoutId === layoutId + }, + changeLayout(layoutId) { + if (!this.isCurrentLayout(layoutId)) { + this.logic.changeLayout(layoutId) + } + } + } + }; </script>