Commit 6cb9a84d authored by Paul Slaughter's avatar Paul Slaughter

Merge branch '22457-refactor-web-ide-collapsable-sidebar' into 'master'

Refactor Web IDE collapsible sidebar logic

See merge request gitlab-org/gitlab!22416
parents 0e09920a 8b9fb322
<script> <script>
import Vue from 'vue'; import Vue from 'vue';
import { mapActions, mapState, mapGetters } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import { GlButton, GlLoadingIcon } from '@gitlab/ui'; import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import FindFile from '~/vue_shared/components/file_finder/index.vue'; import FindFile from '~/vue_shared/components/file_finder/index.vue';
......
<script>
import { mapActions, mapState } from 'vuex';
import _ from 'underscore';
import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
import ResizablePanel from '../resizable_panel.vue';
import { GlSkeletonLoading } from '@gitlab/ui';
export default {
name: 'CollapsibleSidebar',
directives: {
tooltip,
},
components: {
Icon,
ResizablePanel,
GlSkeletonLoading,
},
props: {
extensionTabs: {
type: Array,
required: false,
default: () => [],
},
side: {
type: String,
required: true,
},
width: {
type: Number,
required: true,
},
},
computed: {
...mapState(['loading']),
...mapState({
isOpen(state) {
return state[this.namespace].isOpen;
},
currentView(state) {
return state[this.namespace].currentView;
},
isActiveView(state, getters) {
return getters[`${this.namespace}/isActiveView`];
},
isAliveView(_state, getters) {
return getters[`${this.namespace}/isAliveView`];
},
}),
namespace() {
// eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings
return `${this.side}Pane`;
},
tabs() {
return this.extensionTabs.filter(tab => tab.show);
},
tabViews() {
return _.flatten(this.tabs.map(tab => tab.views));
},
aliveTabViews() {
return this.tabViews.filter(view => this.isAliveView(view.name));
},
otherSide() {
return this.side === 'right' ? 'left' : 'right';
},
},
methods: {
...mapActions({
toggleOpen(dispatch) {
return dispatch(`${this.namespace}/toggleOpen`);
},
open(dispatch, view) {
return dispatch(`${this.namespace}/open`, view);
},
}),
clickTab(e, tab) {
e.target.blur();
if (this.isActiveTab(tab)) {
this.toggleOpen();
} else {
this.open(tab.views[0]);
}
},
isActiveTab(tab) {
return tab.views.some(view => this.isActiveView(view.name));
},
buttonClasses(tab) {
return [
this.side === 'right' ? 'is-right' : '',
this.isActiveTab(tab) && this.isOpen ? 'active' : '',
...(tab.buttonClasses || []),
];
},
},
};
</script>
<template>
<div
:class="`ide-${side}-sidebar`"
:data-qa-selector="`ide_${side}_sidebar`"
class="multi-file-commit-panel ide-sidebar"
>
<resizable-panel
v-show="isOpen"
:collapsible="false"
:initial-width="width"
:min-size="width"
:class="`ide-${side}-sidebar-${currentView}`"
:side="side"
class="multi-file-commit-panel-inner"
>
<div class="h-100 d-flex flex-column align-items-stretch">
<slot v-if="isOpen" name="header"></slot>
<div
v-for="tabView in aliveTabViews"
v-show="isActiveView(tabView.name)"
:key="tabView.name"
class="flex-fill js-tab-view"
>
<component :is="tabView.component" />
</div>
<slot name="footer"></slot>
</div>
</resizable-panel>
<nav class="ide-activity-bar">
<ul class="list-unstyled">
<li>
<slot name="header-icon"></slot>
</li>
<li v-for="tab of tabs" :key="tab.title">
<button
v-tooltip
:title="tab.title"
:aria-label="tab.title"
:class="buttonClasses(tab)"
data-container="body"
:data-placement="otherSide"
:data-qa-selector="`${tab.title.toLowerCase()}_tab_button`"
class="ide-sidebar-link"
type="button"
@click="clickTab($event, tab)"
>
<icon :size="16" :name="tab.icon" />
</button>
</li>
</ul>
</nav>
</div>
</template>
<script> <script>
import { mapActions, mapState, mapGetters } from 'vuex'; import { mapGetters, mapState } from 'vuex';
import _ from 'underscore';
import { __ } from '~/locale'; import { __ } from '~/locale';
import tooltip from '../../../vue_shared/directives/tooltip'; import CollapsibleSidebar from './collapsible_sidebar.vue';
import Icon from '../../../vue_shared/components/icon.vue';
import { rightSidebarViews } from '../../constants'; import { rightSidebarViews } from '../../constants';
import MergeRequestInfo from '../merge_requests/info.vue';
import PipelinesList from '../pipelines/list.vue'; import PipelinesList from '../pipelines/list.vue';
import JobsDetail from '../jobs/detail.vue'; import JobsDetail from '../jobs/detail.vue';
import MergeRequestInfo from '../merge_requests/info.vue';
import ResizablePanel from '../resizable_panel.vue';
import Clientside from '../preview/clientside.vue'; import Clientside from '../preview/clientside.vue';
export default { export default {
directives: { name: 'RightPane',
tooltip,
},
components: { components: {
Icon, CollapsibleSidebar,
PipelinesList,
JobsDetail,
ResizablePanel,
MergeRequestInfo,
Clientside,
}, },
props: { props: {
extensionTabs: { extensionTabs: {
...@@ -32,103 +22,40 @@ export default { ...@@ -32,103 +22,40 @@ export default {
}, },
computed: { computed: {
...mapState(['currentMergeRequestId', 'clientsidePreviewEnabled']), ...mapState(['currentMergeRequestId', 'clientsidePreviewEnabled']),
...mapState('rightPane', ['isOpen', 'currentView']),
...mapGetters(['packageJson']), ...mapGetters(['packageJson']),
...mapGetters('rightPane', ['isActiveView', 'isAliveView']),
showLivePreview() { showLivePreview() {
return this.packageJson && this.clientsidePreviewEnabled; return this.packageJson && this.clientsidePreviewEnabled;
}, },
defaultTabs() { rightExtensionTabs() {
return [ return [
{ {
show: this.currentMergeRequestId, show: Boolean(this.currentMergeRequestId),
title: __('Merge Request'), title: __('Merge Request'),
views: [rightSidebarViews.mergeRequestInfo], views: [{ component: MergeRequestInfo, ...rightSidebarViews.mergeRequestInfo }],
icon: 'text-description', icon: 'text-description',
}, },
{ {
show: true, show: true,
title: __('Pipelines'), title: __('Pipelines'),
views: [rightSidebarViews.pipelines, rightSidebarViews.jobsDetail], views: [
{ component: PipelinesList, ...rightSidebarViews.pipelines },
{ component: JobsDetail, ...rightSidebarViews.jobsDetail },
],
icon: 'rocket', icon: 'rocket',
}, },
{ {
show: this.showLivePreview, show: this.showLivePreview,
title: __('Live preview'), title: __('Live preview'),
views: [rightSidebarViews.clientSidePreview], views: [{ component: Clientside, ...rightSidebarViews.clientSidePreview }],
icon: 'live-preview', icon: 'live-preview',
}, },
...this.extensionTabs,
]; ];
}, },
tabs() {
return this.defaultTabs.concat(this.extensionTabs).filter(tab => tab.show);
},
tabViews() {
return _.flatten(this.tabs.map(tab => tab.views));
},
aliveTabViews() {
return this.tabViews.filter(view => this.isAliveView(view.name));
},
},
methods: {
...mapActions('rightPane', ['toggleOpen', 'open']),
clickTab(e, tab) {
e.target.blur();
if (this.isActiveTab(tab)) {
this.toggleOpen();
} else {
this.open(tab.views[0]);
}
},
isActiveTab(tab) {
return tab.views.some(view => this.isActiveView(view.name));
},
}, },
}; };
</script> </script>
<template> <template>
<div class="multi-file-commit-panel ide-right-sidebar" data-qa-selector="ide_right_sidebar"> <collapsible-sidebar :extension-tabs="rightExtensionTabs" side="right" :width="350" />
<resizable-panel
v-show="isOpen"
:collapsible="false"
:initial-width="350"
:min-size="350"
:class="`ide-right-sidebar-${currentView}`"
side="right"
class="multi-file-commit-panel-inner"
>
<div
v-for="tabView in aliveTabViews"
v-show="isActiveView(tabView.name)"
:key="tabView.name"
class="h-100"
>
<component :is="tabView.component || tabView.name" />
</div>
</resizable-panel>
<nav class="ide-activity-bar">
<ul class="list-unstyled">
<li v-for="tab of tabs" :key="tab.title">
<button
v-tooltip
:title="tab.title"
:aria-label="tab.title"
:class="{
active: isActiveTab(tab) && isOpen,
}"
data-container="body"
data-placement="left"
:data-qa-selector="`${tab.title.toLowerCase()}_tab_button`"
class="ide-sidebar-link is-right"
type="button"
@click="clickTab($event, tab)"
>
<icon :size="16" :name="tab.icon" />
</button>
</li>
</ul>
</nav>
</div>
</template> </template>
...@@ -33,19 +33,6 @@ export const setPanelCollapsedStatus = ({ commit }, { side, collapsed }) => { ...@@ -33,19 +33,6 @@ export const setPanelCollapsedStatus = ({ commit }, { side, collapsed }) => {
} }
}; };
export const toggleRightPanelCollapsed = ({ dispatch, state }, e = undefined) => {
if (e) {
$(e.currentTarget)
.tooltip('hide')
.blur();
}
dispatch('setPanelCollapsedStatus', {
side: 'right',
collapsed: !state.rightPanelCollapsed,
});
};
export const setResizingStatus = ({ commit }, resizing) => { export const setResizingStatus = ({ commit }, resizing) => {
commit(types.SET_RESIZING_STATUS, resizing); commit(types.SET_RESIZING_STATUS, resizing);
}; };
......
import * as types from './mutation_types'; import * as types from './mutation_types';
export const toggleOpen = ({ dispatch, state }, view) => { export const toggleOpen = ({ dispatch, state }) => {
if (state.isOpen) { if (state.isOpen) {
dispatch('close'); dispatch('close');
} else { } else {
dispatch('open', view); dispatch('open');
} }
}; };
export const open = ({ commit }, view) => { export const open = ({ state, commit }, view) => {
commit(types.SET_OPEN, true); commit(types.SET_OPEN, true);
if (view) { if (view && view.name !== state.currentView) {
const { name, keepAlive } = view; const { name, keepAlive } = view;
commit(types.SET_CURRENT_VIEW, name); commit(types.SET_CURRENT_VIEW, name);
......
...@@ -11,7 +11,6 @@ export const SET_LINKS = 'SET_LINKS'; ...@@ -11,7 +11,6 @@ export const SET_LINKS = 'SET_LINKS';
// Project Mutation Types // Project Mutation Types
export const SET_PROJECT = 'SET_PROJECT'; export const SET_PROJECT = 'SET_PROJECT';
export const SET_CURRENT_PROJECT = 'SET_CURRENT_PROJECT'; export const SET_CURRENT_PROJECT = 'SET_CURRENT_PROJECT';
export const TOGGLE_PROJECT_OPEN = 'TOGGLE_PROJECT_OPEN';
export const TOGGLE_EMPTY_STATE = 'TOGGLE_EMPTY_STATE'; export const TOGGLE_EMPTY_STATE = 'TOGGLE_EMPTY_STATE';
// Merge Request Mutation Types // Merge Request Mutation Types
......
...@@ -740,6 +740,7 @@ $ide-commit-header-height: 48px; ...@@ -740,6 +740,7 @@ $ide-commit-header-height: 48px;
.ide-sidebar-link { .ide-sidebar-link {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center;
position: relative; position: relative;
height: 60px; height: 60px;
width: 100%; width: 100%;
...@@ -1076,10 +1077,12 @@ $ide-commit-header-height: 48px; ...@@ -1076,10 +1077,12 @@ $ide-commit-header-height: 48px;
} }
} }
.ide-right-sidebar { .ide-sidebar {
width: auto; width: auto;
min-width: 60px; min-width: 60px;
}
.ide-right-sidebar {
.ide-activity-bar { .ide-activity-bar {
border-left: 1px solid $white-dark; border-left: 1px solid $white-dark;
} }
......
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex'; import Vuex from 'vuex';
import EERightPane from 'ee/ide/components/panes/right.vue'; import EERightPane from 'ee/ide/components/panes/right.vue';
import RightPane from '~/ide/components/panes/right.vue'; import RightPane from '~/ide/components/panes/right.vue';
...@@ -29,6 +29,7 @@ describe('IDE EERightPane', () => { ...@@ -29,6 +29,7 @@ describe('IDE EERightPane', () => {
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null;
}); });
it('adds terminal tab', () => { it('adds terminal tab', () => {
......
...@@ -8,8 +8,8 @@ module QA ...@@ -8,8 +8,8 @@ module QA
module WebTerminalPanel module WebTerminalPanel
def self.prepended(page) def self.prepended(page)
page.module_eval do page.module_eval do
view 'app/assets/javascripts/ide/components/panes/right.vue' do view 'app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue' do
element :ide_right_sidebar element :ide_right_sidebar, %q(:data-qa-selector="`ide_${side}_sidebar`") # rubocop:disable QA/ElementWithPattern
element :terminal_tab_button, %q(:data-qa-selector="`${tab.title.toLowerCase()}_tab_button`") # rubocop:disable QA/ElementWithPattern element :terminal_tab_button, %q(:data-qa-selector="`${tab.title.toLowerCase()}_tab_button`") # rubocop:disable QA/ElementWithPattern
end end
......
import { createLocalVue, shallowMount } from '@vue/test-utils';
import { createStore } from '~/ide/stores';
import paneModule from '~/ide/stores/modules/pane';
import CollapsibleSidebar from '~/ide/components/panes/collapsible_sidebar.vue';
import Vuex from 'vuex';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('ide/components/panes/collapsible_sidebar.vue', () => {
let wrapper;
let store;
const width = 350;
const fakeComponentName = 'fake-component';
const createComponent = props => {
wrapper = shallowMount(CollapsibleSidebar, {
localVue,
store,
propsData: {
extensionTabs: [],
side: 'right',
width,
...props,
},
slots: {
'header-icon': '<div class=".header-icon-slot">SLOT ICON</div>',
header: '<div class=".header-slot"/>',
footer: '<div class=".footer-slot"/>',
},
});
};
const findTabButton = () => wrapper.find(`[data-qa-selector="${fakeComponentName}_tab_button"]`);
beforeEach(() => {
store = createStore();
store.registerModule('leftPane', paneModule());
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('with a tab', () => {
let fakeView;
let extensionTabs;
beforeEach(() => {
const FakeComponent = localVue.component(fakeComponentName, {
render: () => {},
});
fakeView = {
name: fakeComponentName,
keepAlive: true,
component: FakeComponent,
};
extensionTabs = [
{
show: true,
title: fakeComponentName,
views: [fakeView],
icon: 'text-description',
buttonClasses: ['button-class-1', 'button-class-2'],
},
];
});
describe.each`
side
${'left'}
${'right'}
`('when side=$side', ({ side }) => {
it('correctly renders side specific attributes', () => {
createComponent({ extensionTabs, side });
const button = findTabButton();
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.classes()).toContain('multi-file-commit-panel');
expect(wrapper.classes()).toContain(`ide-${side}-sidebar`);
expect(wrapper.find('.multi-file-commit-panel-inner')).not.toBe(null);
expect(wrapper.find(`.ide-${side}-sidebar-${fakeComponentName}`)).not.toBe(null);
expect(button.attributes('data-placement')).toEqual(side === 'left' ? 'right' : 'left');
if (side === 'right') {
// this class is only needed on the right side; there is no 'is-left'
expect(button.classes()).toContain('is-right');
} else {
expect(button.classes()).not.toContain('is-right');
}
});
});
});
describe('when default side', () => {
let button;
beforeEach(() => {
createComponent({ extensionTabs });
button = findTabButton();
});
it('correctly renders tab-specific classes', () => {
store.state.rightPane.currentView = fakeComponentName;
return wrapper.vm.$nextTick().then(() => {
expect(button.classes()).toContain('button-class-1');
expect(button.classes()).toContain('button-class-2');
});
});
it('can show an open pane tab with an active view', () => {
store.state.rightPane.isOpen = true;
store.state.rightPane.currentView = fakeComponentName;
return wrapper.vm.$nextTick().then(() => {
expect(button.classes()).toEqual(expect.arrayContaining(['ide-sidebar-link', 'active']));
expect(button.attributes('data-original-title')).toEqual(fakeComponentName);
expect(wrapper.find('.js-tab-view').exists()).toBe(true);
});
});
it('does not show a pane which is not open', () => {
store.state.rightPane.isOpen = false;
store.state.rightPane.currentView = fakeComponentName;
return wrapper.vm.$nextTick().then(() => {
expect(button.classes()).not.toEqual(
expect.arrayContaining(['ide-sidebar-link', 'active']),
);
expect(wrapper.find('.js-tab-view').exists()).toBe(false);
});
});
describe('when button is clicked', () => {
it('opens view', () => {
button.trigger('click');
expect(store.state.rightPane.isOpen).toBeTruthy();
});
it('toggles open view if tab is currently active', () => {
button.trigger('click');
expect(store.state.rightPane.isOpen).toBeTruthy();
button.trigger('click');
expect(store.state.rightPane.isOpen).toBeFalsy();
});
});
it('shows header-icon', () => {
expect(wrapper.find('.header-icon-slot')).not.toBeNull();
});
it('shows header', () => {
expect(wrapper.find('.header-slot')).not.toBeNull();
});
it('shows footer', () => {
expect(wrapper.find('.footer-slot')).not.toBeNull();
});
});
});
});
import Vue from 'vue'; import Vue from 'vue';
import '~/behaviors/markdown/render_gfm'; import Vuex from 'vuex';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import { createStore } from '~/ide/stores'; import { createStore } from '~/ide/stores';
import RightPane from '~/ide/components/panes/right.vue'; import RightPane from '~/ide/components/panes/right.vue';
import CollapsibleSidebar from '~/ide/components/panes/collapsible_sidebar.vue';
import { rightSidebarViews } from '~/ide/constants'; import { rightSidebarViews } from '~/ide/constants';
describe('IDE right pane', () => { const localVue = createLocalVue();
let Component; localVue.use(Vuex);
let vm;
beforeAll(() => { describe('ide/components/panes/right.vue', () => {
Component = Vue.extend(RightPane); let wrapper;
}); let store;
beforeEach(() => { const createComponent = props => {
const store = createStore(); wrapper = shallowMount(RightPane, {
localVue,
store,
propsData: {
...props,
},
});
};
vm = createComponentWithStore(Component, store).$mount(); beforeEach(() => {
store = createStore();
}); });
afterEach(() => { afterEach(() => {
vm.$destroy(); wrapper.destroy();
wrapper = null;
}); });
describe('active', () => { it('allows tabs to be added via extensionTabs prop', () => {
it('renders merge request button as active', done => { createComponent({
vm.$store.state.rightPane.isOpen = true; extensionTabs: [
vm.$store.state.rightPane.currentView = rightSidebarViews.mergeRequestInfo.name; {
vm.$store.state.currentMergeRequestId = '123'; show: true,
vm.$store.state.currentProjectId = 'gitlab-ce'; title: 'FakeTab',
vm.$store.state.currentMergeRequestId = 1;
vm.$store.state.projects['gitlab-ce'] = {
mergeRequests: {
1: {
iid: 1,
title: 'Testing',
title_html: '<span class="title-html">Testing</span>',
description: 'Description',
description_html: '<p class="description-html">Description HTML</p>',
},
}, },
}; ],
vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.ide-sidebar-link.active')).not.toBe(null);
expect(
vm.$el.querySelector('.ide-sidebar-link.active').getAttribute('data-original-title'),
).toBe('Merge Request');
})
.then(done)
.catch(done.fail);
}); });
expect(wrapper.find(CollapsibleSidebar).props('extensionTabs')).toEqual(
expect.arrayContaining([
expect.objectContaining({
show: true,
title: 'FakeTab',
}),
]),
);
}); });
describe('click', () => { describe('pipelines tab', () => {
beforeEach(() => { it('is always shown', () => {
jest.spyOn(vm, 'open').mockReturnValue(); createComponent();
});
it('sets view to merge request', done => { expect(wrapper.find(CollapsibleSidebar).props('extensionTabs')).toEqual(
vm.$store.state.currentMergeRequestId = '123'; expect.arrayContaining([
expect.objectContaining({
show: true,
title: 'Pipelines',
views: expect.arrayContaining([
expect.objectContaining({
name: rightSidebarViews.pipelines.name,
}),
expect.objectContaining({
name: rightSidebarViews.jobsDetail.name,
}),
]),
}),
]),
);
});
});
vm.$nextTick(() => { describe('merge request tab', () => {
vm.$el.querySelector('.ide-sidebar-link').click(); it('is shown if there is a currentMergeRequestId', () => {
store.state.currentMergeRequestId = 1;
expect(vm.open).toHaveBeenCalledWith(rightSidebarViews.mergeRequestInfo); createComponent();
done(); expect(wrapper.find(CollapsibleSidebar).props('extensionTabs')).toEqual(
}); expect.arrayContaining([
expect.objectContaining({
show: true,
title: 'Merge Request',
views: expect.arrayContaining([
expect.objectContaining({
name: rightSidebarViews.mergeRequestInfo.name,
}),
]),
}),
]),
);
}); });
}); });
describe('live preview', () => { describe('clientside live preview tab', () => {
it('renders live preview button', done => { it('is shown if there is a packageJson and clientsidePreviewEnabled', () => {
Vue.set(vm.$store.state.entries, 'package.json', { Vue.set(store.state.entries, 'package.json', {
name: 'package.json', name: 'package.json',
}); });
vm.$store.state.clientsidePreviewEnabled = true; store.state.clientsidePreviewEnabled = true;
vm.$nextTick(() => { createComponent();
expect(vm.$el.querySelector('button[aria-label="Live preview"]')).not.toBeNull();
done(); expect(wrapper.find(CollapsibleSidebar).props('extensionTabs')).toEqual(
}); expect.arrayContaining([
expect.objectContaining({
show: true,
title: 'Live preview',
views: expect.arrayContaining([
expect.objectContaining({
name: rightSidebarViews.clientSidePreview.name,
}),
]),
}),
]),
);
}); });
}); });
}); });
...@@ -8,14 +8,7 @@ describe('IDE pane module actions', () => { ...@@ -8,14 +8,7 @@ describe('IDE pane module actions', () => {
describe('toggleOpen', () => { describe('toggleOpen', () => {
it('dispatches open if closed', done => { it('dispatches open if closed', done => {
testAction( testAction(actions.toggleOpen, TEST_VIEW, { isOpen: false }, [], [{ type: 'open' }], done);
actions.toggleOpen,
TEST_VIEW,
{ isOpen: false },
[],
[{ type: 'open', payload: TEST_VIEW }],
done,
);
}); });
it('dispatches close if opened', done => { it('dispatches close if opened', done => {
...@@ -24,37 +17,48 @@ describe('IDE pane module actions', () => { ...@@ -24,37 +17,48 @@ describe('IDE pane module actions', () => {
}); });
describe('open', () => { describe('open', () => {
it('commits SET_OPEN', done => { describe('with a view specified', () => {
testAction(actions.open, null, {}, [{ type: types.SET_OPEN, payload: true }], [], done); it('commits SET_OPEN and SET_CURRENT_VIEW', done => {
}); testAction(
actions.open,
TEST_VIEW,
{},
[
{ type: types.SET_OPEN, payload: true },
{ type: types.SET_CURRENT_VIEW, payload: TEST_VIEW.name },
],
[],
done,
);
});
it('commits SET_CURRENT_VIEW if view is given', done => { it('commits KEEP_ALIVE_VIEW if keepAlive is true', done => {
testAction( testAction(
actions.open, actions.open,
TEST_VIEW, TEST_VIEW_KEEP_ALIVE,
{}, {},
[ [
{ type: types.SET_OPEN, payload: true }, { type: types.SET_OPEN, payload: true },
{ type: types.SET_CURRENT_VIEW, payload: TEST_VIEW.name }, { type: types.SET_CURRENT_VIEW, payload: TEST_VIEW_KEEP_ALIVE.name },
], { type: types.KEEP_ALIVE_VIEW, payload: TEST_VIEW_KEEP_ALIVE.name },
[], ],
done, [],
); done,
);
});
}); });
it('commits KEEP_ALIVE_VIEW if keepAlive is true', done => { describe('without a view specified', () => {
testAction( it('commits SET_OPEN', done => {
actions.open, testAction(
TEST_VIEW_KEEP_ALIVE, actions.open,
{}, undefined,
[ {},
{ type: types.SET_OPEN, payload: true }, [{ type: types.SET_OPEN, payload: true }],
{ type: types.SET_CURRENT_VIEW, payload: TEST_VIEW_KEEP_ALIVE.name }, [],
{ type: types.KEEP_ALIVE_VIEW, payload: TEST_VIEW_KEEP_ALIVE.name }, done,
], );
[], });
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