Commit 0d1d35ef authored by Denys Mishunov's avatar Denys Mishunov Committed by Kushal Pandya

Switch viewer switcher to v-model

Since there's just one parameter to keep an eye on in
blob_header_viewer_switcher, instead of relying on an eventHub,
transform it into v-model aware component.
parent c7d27481
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
import ViewerSwitcher from './blob_header_viewer_switcher.vue'; import ViewerSwitcher from './blob_header_viewer_switcher.vue';
import DefaultActions from './blob_header_default_actions.vue'; import DefaultActions from './blob_header_default_actions.vue';
import BlobFilepath from './blob_header_filepath.vue'; import BlobFilepath from './blob_header_filepath.vue';
import eventHub from '../event_hub'; import { SIMPLE_BLOB_VIEWER } from './constants';
import { RICH_BLOB_VIEWER, SIMPLE_BLOB_VIEWER } from './constants';
export default { export default {
components: { components: {
...@@ -26,10 +25,15 @@ export default { ...@@ -26,10 +25,15 @@ export default {
required: false, required: false,
default: false, default: false,
}, },
activeViewerType: {
type: String,
required: false,
default: SIMPLE_BLOB_VIEWER,
},
}, },
data() { data() {
return { return {
activeViewer: this.blob.richViewer ? RICH_BLOB_VIEWER : SIMPLE_BLOB_VIEWER, viewer: this.hideViewerSwitcher ? null : this.activeViewerType,
}; };
}, },
computed: { computed: {
...@@ -40,19 +44,16 @@ export default { ...@@ -40,19 +44,16 @@ export default {
return !this.hideDefaultActions; return !this.hideDefaultActions;
}, },
}, },
created() { watch: {
if (this.showViewerSwitcher) { viewer(newVal, oldVal) {
eventHub.$on('switch-viewer', this.setActiveViewer); if (!this.hideViewerSwitcher && newVal !== oldVal) {
this.$emit('viewer-changed', newVal);
} }
}, },
beforeDestroy() {
if (this.showViewerSwitcher) {
eventHub.$off('switch-viewer', this.setActiveViewer);
}
}, },
methods: { methods: {
setActiveViewer(viewer) { proxyCopyRequest() {
this.activeViewer = viewer; this.$emit('copy');
}, },
}, },
}; };
...@@ -66,11 +67,16 @@ export default { ...@@ -66,11 +67,16 @@ export default {
</blob-filepath> </blob-filepath>
<div class="file-actions d-none d-sm-block"> <div class="file-actions d-none d-sm-block">
<viewer-switcher v-if="showViewerSwitcher" :blob="blob" :active-viewer="activeViewer" /> <viewer-switcher v-if="showViewerSwitcher" v-model="viewer" />
<slot name="actions"></slot> <slot name="actions"></slot>
<default-actions v-if="showDefaultActions" :blob="blob" :active-viewer="activeViewer" /> <default-actions
v-if="showDefaultActions"
:raw-path="blob.rawPath"
:active-viewer="viewer"
@copy="proxyCopyRequest"
/>
</div> </div>
</div> </div>
</template> </template>
...@@ -7,7 +7,6 @@ import { ...@@ -7,7 +7,6 @@ import {
RICH_BLOB_VIEWER, RICH_BLOB_VIEWER,
SIMPLE_BLOB_VIEWER, SIMPLE_BLOB_VIEWER,
} from './constants'; } from './constants';
import eventHub from '../event_hub';
export default { export default {
components: { components: {
...@@ -19,8 +18,8 @@ export default { ...@@ -19,8 +18,8 @@ export default {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
props: { props: {
blob: { rawPath: {
type: Object, type: String,
required: true, required: true,
}, },
activeViewer: { activeViewer: {
...@@ -30,11 +29,8 @@ export default { ...@@ -30,11 +29,8 @@ export default {
}, },
}, },
computed: { computed: {
rawUrl() {
return this.blob.rawPath;
},
downloadUrl() { downloadUrl() {
return `${this.blob.rawPath}?inline=false`; return `${this.rawPath}?inline=false`;
}, },
copyDisabled() { copyDisabled() {
return this.activeViewer === RICH_BLOB_VIEWER; return this.activeViewer === RICH_BLOB_VIEWER;
...@@ -42,7 +38,7 @@ export default { ...@@ -42,7 +38,7 @@ export default {
}, },
methods: { methods: {
requestCopyContents() { requestCopyContents() {
eventHub.$emit('copy'); this.$emit('copy');
}, },
}, },
BTN_COPY_CONTENTS_TITLE, BTN_COPY_CONTENTS_TITLE,
...@@ -65,7 +61,7 @@ export default { ...@@ -65,7 +61,7 @@ export default {
v-gl-tooltip.hover v-gl-tooltip.hover
:aria-label="$options.BTN_RAW_TITLE" :aria-label="$options.BTN_RAW_TITLE"
:title="$options.BTN_RAW_TITLE" :title="$options.BTN_RAW_TITLE"
:href="rawUrl" :href="rawPath"
target="_blank" target="_blank"
> >
<gl-icon name="doc-code" :size="14" /> <gl-icon name="doc-code" :size="14" />
......
...@@ -6,7 +6,6 @@ import { ...@@ -6,7 +6,6 @@ import {
SIMPLE_BLOB_VIEWER, SIMPLE_BLOB_VIEWER,
SIMPLE_BLOB_VIEWER_TITLE, SIMPLE_BLOB_VIEWER_TITLE,
} from './constants'; } from './constants';
import eventHub from '../event_hub';
export default { export default {
components: { components: {
...@@ -18,11 +17,7 @@ export default { ...@@ -18,11 +17,7 @@ export default {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
props: { props: {
blob: { value: {
type: Object,
required: true,
},
activeViewer: {
type: String, type: String,
default: SIMPLE_BLOB_VIEWER, default: SIMPLE_BLOB_VIEWER,
required: false, required: false,
...@@ -30,16 +25,16 @@ export default { ...@@ -30,16 +25,16 @@ export default {
}, },
computed: { computed: {
isSimpleViewer() { isSimpleViewer() {
return this.activeViewer === SIMPLE_BLOB_VIEWER; return this.value === SIMPLE_BLOB_VIEWER;
}, },
isRichViewer() { isRichViewer() {
return this.activeViewer === RICH_BLOB_VIEWER; return this.value === RICH_BLOB_VIEWER;
}, },
}, },
methods: { methods: {
switchToViewer(viewer) { switchToViewer(viewer) {
if (viewer !== this.activeViewer) { if (viewer !== this.value) {
eventHub.$emit('switch-viewer', viewer); this.$emit('input', viewer);
} }
}, },
}, },
......
import Vue from 'vue';
export default new Vue();
...@@ -12,13 +12,12 @@ exports[`Blob Header Default Actions rendering matches the snapshot 1`] = ` ...@@ -12,13 +12,12 @@ exports[`Blob Header Default Actions rendering matches the snapshot 1`] = `
class="file-actions d-none d-sm-block" class="file-actions d-none d-sm-block"
> >
<viewer-switcher-stub <viewer-switcher-stub
activeviewer="rich" value="simple"
blob="[object Object]"
/> />
<default-actions-stub <default-actions-stub
activeviewer="rich" activeviewer="simple"
blob="[object Object]" rawpath="/flightjs/flight/snippets/51/raw"
/> />
</div> </div>
</div> </div>
......
...@@ -8,7 +8,6 @@ import { ...@@ -8,7 +8,6 @@ import {
} from '~/blob/components/constants'; } from '~/blob/components/constants';
import { GlButtonGroup, GlButton } from '@gitlab/ui'; import { GlButtonGroup, GlButton } from '@gitlab/ui';
import { Blob } from './mock_data'; import { Blob } from './mock_data';
import eventHub from '~/blob/event_hub';
describe('Blob Header Default Actions', () => { describe('Blob Header Default Actions', () => {
let wrapper; let wrapper;
...@@ -16,10 +15,10 @@ describe('Blob Header Default Actions', () => { ...@@ -16,10 +15,10 @@ describe('Blob Header Default Actions', () => {
let buttons; let buttons;
const hrefPrefix = 'http://localhost'; const hrefPrefix = 'http://localhost';
function createComponent(blobProps = {}, propsData = {}) { function createComponent(propsData = {}) {
wrapper = mount(BlobHeaderActions, { wrapper = mount(BlobHeaderActions, {
propsData: { propsData: {
blob: Object.assign({}, Blob, blobProps), rawPath: Blob.rawPath,
...propsData, ...propsData,
}, },
}); });
...@@ -60,12 +59,9 @@ describe('Blob Header Default Actions', () => { ...@@ -60,12 +59,9 @@ describe('Blob Header Default Actions', () => {
}); });
it('renders "Copy file contents" button as disables if the viewer is Rich', () => { it('renders "Copy file contents" button as disables if the viewer is Rich', () => {
createComponent( createComponent({
{},
{
activeViewer: RICH_BLOB_VIEWER, activeViewer: RICH_BLOB_VIEWER,
}, });
);
buttons = wrapper.findAll(GlButton); buttons = wrapper.findAll(GlButton);
expect(buttons.at(0).attributes('disabled')).toBeTruthy(); expect(buttons.at(0).attributes('disabled')).toBeTruthy();
...@@ -74,10 +70,10 @@ describe('Blob Header Default Actions', () => { ...@@ -74,10 +70,10 @@ describe('Blob Header Default Actions', () => {
describe('functionally', () => { describe('functionally', () => {
it('emits an event when a Copy Contents button is clicked', () => { it('emits an event when a Copy Contents button is clicked', () => {
jest.spyOn(eventHub, '$emit'); jest.spyOn(wrapper.vm, '$emit');
buttons.at(0).vm.$emit('click'); buttons.at(0).vm.$emit('click');
expect(eventHub.$emit).toHaveBeenCalledWith('copy'); expect(wrapper.vm.$emit).toHaveBeenCalledWith('copy');
}); });
}); });
}); });
...@@ -3,7 +3,6 @@ import BlobHeader from '~/blob/components/blob_header.vue'; ...@@ -3,7 +3,6 @@ import BlobHeader from '~/blob/components/blob_header.vue';
import ViewerSwitcher from '~/blob/components/blob_header_viewer_switcher.vue'; import ViewerSwitcher from '~/blob/components/blob_header_viewer_switcher.vue';
import DefaultActions from '~/blob/components/blob_header_default_actions.vue'; import DefaultActions from '~/blob/components/blob_header_default_actions.vue';
import BlobFilepath from '~/blob/components/blob_header_filepath.vue'; import BlobFilepath from '~/blob/components/blob_header_filepath.vue';
import eventHub from '~/blob/event_hub';
import { Blob } from './mock_data'; import { Blob } from './mock_data';
...@@ -21,10 +20,6 @@ describe('Blob Header Default Actions', () => { ...@@ -21,10 +20,6 @@ describe('Blob Header Default Actions', () => {
}); });
} }
beforeEach(() => {
createComponent();
});
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
}); });
...@@ -96,37 +91,48 @@ describe('Blob Header Default Actions', () => { ...@@ -96,37 +91,48 @@ describe('Blob Header Default Actions', () => {
describe('functionality', () => { describe('functionality', () => {
const newViewer = 'Foo Bar'; const newViewer = 'Foo Bar';
const activeViewerType = 'Alpha Beta';
it('listens to "switch-view" event when viewer switcher is shown and updates activeViewer', () => { const factory = (hideViewerSwitcher = false) => {
expect(wrapper.vm.showViewerSwitcher).toBe(true);
eventHub.$emit('switch-viewer', newViewer);
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.activeViewer).toBe(newViewer);
});
});
it('does not update active viewer if the switcher is not shown', () => {
const activeViewer = 'Alpha Beta';
createComponent( createComponent(
{},
{}, {},
{ {
data() { activeViewerType,
return { hideViewerSwitcher,
activeViewer,
};
},
},
{
hideViewerSwitcher: true,
}, },
); );
};
it('by default sets viewer data based on activeViewerType', () => {
factory();
expect(wrapper.vm.viewer).toBe(activeViewerType);
});
it('sets viewer to null if the viewer switcher should be hidden', () => {
factory(true);
expect(wrapper.vm.viewer).toBe(null);
});
it('watches the changes in viewer data and emits event when the change is registered', () => {
factory();
jest.spyOn(wrapper.vm, '$emit');
wrapper.vm.viewer = newViewer;
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.$emit).toHaveBeenCalledWith('viewer-changed', newViewer);
});
});
it('does not emit event if the switcher is not rendered', () => {
factory(true);
expect(wrapper.vm.showViewerSwitcher).toBe(false); expect(wrapper.vm.showViewerSwitcher).toBe(false);
eventHub.$emit('switch-viewer', newViewer); jest.spyOn(wrapper.vm, '$emit');
wrapper.vm.viewer = newViewer;
return wrapper.vm.$nextTick().then(() => { return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.activeViewer).toBe(activeViewer); expect(wrapper.vm.$emit).not.toHaveBeenCalled();
}); });
}); });
}); });
......
...@@ -7,18 +7,13 @@ import { ...@@ -7,18 +7,13 @@ import {
SIMPLE_BLOB_VIEWER_TITLE, SIMPLE_BLOB_VIEWER_TITLE,
} from '~/blob/components/constants'; } from '~/blob/components/constants';
import { GlButtonGroup, GlButton } from '@gitlab/ui'; import { GlButtonGroup, GlButton } from '@gitlab/ui';
import { Blob } from './mock_data';
import eventHub from '~/blob/event_hub';
describe('Blob Header Viewer Switcher', () => { describe('Blob Header Viewer Switcher', () => {
let wrapper; let wrapper;
function createComponent(blobProps = {}, propsData = {}) { function createComponent(propsData = {}) {
wrapper = mount(BlobHeaderViewerSwitcher, { wrapper = mount(BlobHeaderViewerSwitcher, {
propsData: { propsData,
blob: Object.assign({}, Blob, blobProps),
...propsData,
},
}); });
} }
...@@ -29,7 +24,7 @@ describe('Blob Header Viewer Switcher', () => { ...@@ -29,7 +24,7 @@ describe('Blob Header Viewer Switcher', () => {
describe('intiialization', () => { describe('intiialization', () => {
it('is initialized with simple viewer as active', () => { it('is initialized with simple viewer as active', () => {
createComponent(); createComponent();
expect(wrapper.vm.activeViewer).toBe(SIMPLE_BLOB_VIEWER); expect(wrapper.vm.value).toBe(SIMPLE_BLOB_VIEWER);
}); });
}); });
...@@ -60,42 +55,42 @@ describe('Blob Header Viewer Switcher', () => { ...@@ -60,42 +55,42 @@ describe('Blob Header Viewer Switcher', () => {
let simpleBtn; let simpleBtn;
let richBtn; let richBtn;
function factory(propsOptions = {}) { function factory(propsData = {}) {
createComponent({}, propsOptions); createComponent(propsData);
buttons = wrapper.findAll(GlButton); buttons = wrapper.findAll(GlButton);
simpleBtn = buttons.at(0); simpleBtn = buttons.at(0);
richBtn = buttons.at(1); richBtn = buttons.at(1);
jest.spyOn(eventHub, '$emit'); jest.spyOn(wrapper.vm, '$emit');
} }
it('does not switch the viewer if the selected one is already active', () => { it('does not switch the viewer if the selected one is already active', () => {
factory(); factory();
expect(wrapper.vm.activeViewer).toBe(SIMPLE_BLOB_VIEWER); expect(wrapper.vm.value).toBe(SIMPLE_BLOB_VIEWER);
simpleBtn.vm.$emit('click'); simpleBtn.vm.$emit('click');
expect(wrapper.vm.activeViewer).toBe(SIMPLE_BLOB_VIEWER); expect(wrapper.vm.value).toBe(SIMPLE_BLOB_VIEWER);
expect(eventHub.$emit).not.toHaveBeenCalled(); expect(wrapper.vm.$emit).not.toHaveBeenCalled();
}); });
it('emits an event when a Rich Viewer button is clicked', () => { it('emits an event when a Rich Viewer button is clicked', () => {
factory(); factory();
expect(wrapper.vm.activeViewer).toBe(SIMPLE_BLOB_VIEWER); expect(wrapper.vm.value).toBe(SIMPLE_BLOB_VIEWER);
richBtn.vm.$emit('click'); richBtn.vm.$emit('click');
return wrapper.vm.$nextTick().then(() => { return wrapper.vm.$nextTick().then(() => {
expect(eventHub.$emit).toHaveBeenCalledWith('switch-viewer', RICH_BLOB_VIEWER); expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', RICH_BLOB_VIEWER);
}); });
}); });
it('emits an event when a Simple Viewer button is clicked', () => { it('emits an event when a Simple Viewer button is clicked', () => {
factory({ factory({
activeViewer: RICH_BLOB_VIEWER, value: RICH_BLOB_VIEWER,
}); });
simpleBtn.vm.$emit('click'); simpleBtn.vm.$emit('click');
return wrapper.vm.$nextTick().then(() => { return wrapper.vm.$nextTick().then(() => {
expect(eventHub.$emit).toHaveBeenCalledWith('switch-viewer', SIMPLE_BLOB_VIEWER); expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', SIMPLE_BLOB_VIEWER);
}); });
}); });
}); });
......
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