Commit 3aaa0b21 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch '213059-explicit-prop-listener' into 'master'

Set props and listener in snippet_blob_edit.vue explicitely

Closes #213059

See merge request gitlab-org/gitlab!28719
parents 869c6b43 3e32fcab
...@@ -5,7 +5,8 @@ export default { ...@@ -5,7 +5,8 @@ export default {
props: { props: {
value: { value: {
type: String, type: String,
required: true, required: false,
default: '',
}, },
fileName: { fileName: {
type: String, type: String,
...@@ -15,7 +16,6 @@ export default { ...@@ -15,7 +16,6 @@ export default {
}, },
data() { data() {
return { return {
content: this.value,
editor: null, editor: null,
}; };
}, },
...@@ -28,14 +28,12 @@ export default { ...@@ -28,14 +28,12 @@ export default {
this.editor = initEditorLite({ this.editor = initEditorLite({
el: this.$refs.editor, el: this.$refs.editor,
blobPath: this.fileName, blobPath: this.fileName,
blobContent: this.content, blobContent: this.value,
}); });
}, },
methods: { methods: {
triggerFileChange() { triggerFileChange() {
const val = this.editor.getValue(); this.$emit('input', this.editor.getValue());
this.content = val;
this.$emit('input', val);
}, },
}, },
}; };
...@@ -43,7 +41,7 @@ export default { ...@@ -43,7 +41,7 @@ export default {
<template> <template>
<div class="file-content code"> <div class="file-content code">
<pre id="editor" ref="editor" data-editor-loading @focusout="triggerFileChange">{{ <pre id="editor" ref="editor" data-editor-loading @focusout="triggerFileChange">{{
content value
}}</pre> }}</pre>
</div> </div>
</template> </template>
<script> <script>
import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue'; import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue';
import BlobContentEdit from '~/blob/components/blob_edit_content.vue'; import BlobContentEdit from '~/blob/components/blob_edit_content.vue';
import { GlLoadingIcon } from '@gitlab/ui';
export default { export default {
components: { components: {
BlobHeaderEdit, BlobHeaderEdit,
BlobContentEdit, BlobContentEdit,
GlLoadingIcon,
}, },
inheritAttrs: false, inheritAttrs: false,
props: { props: {
value: {
type: String,
required: false,
default: '',
},
fileName: { fileName: {
type: String, type: String,
required: false, required: false,
default: '', default: '',
}, },
}, isLoading: {
methods: { type: Boolean,
emitFileNameChange(newFileName) { required: false,
this.$emit('name-change', newFileName); default: true,
}, },
}, },
}; };
...@@ -26,8 +33,19 @@ export default { ...@@ -26,8 +33,19 @@ export default {
<div class="form-group file-editor"> <div class="form-group file-editor">
<label>{{ s__('Snippets|File') }}</label> <label>{{ s__('Snippets|File') }}</label>
<div class="file-holder snippet"> <div class="file-holder snippet">
<blob-header-edit :value="fileName" @input="emitFileNameChange" /> <blob-header-edit :value="fileName" @input="$emit('name-change', $event)" />
<blob-content-edit v-bind="$attrs" :file-name="fileName" v-on="$listeners" /> <gl-loading-icon
v-if="isLoading"
:label="__('Loading snippet')"
:size="2"
class="loading-animation prepend-top-20 append-bottom-20"
/>
<blob-content-edit
v-else
:value="value"
:file-name="fileName"
@input="$emit('input', $event)"
/>
</div> </div>
</div> </div>
</template> </template>
...@@ -12,11 +12,12 @@ describe('Blob Header Editing', () => { ...@@ -12,11 +12,12 @@ describe('Blob Header Editing', () => {
const value = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; const value = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
const fileName = 'lorem.txt'; const fileName = 'lorem.txt';
function createComponent() { function createComponent(props = {}) {
wrapper = shallowMount(BlobEditContent, { wrapper = shallowMount(BlobEditContent, {
propsData: { propsData: {
value, value,
fileName, fileName,
...props,
}, },
}); });
} }
...@@ -40,6 +41,14 @@ describe('Blob Header Editing', () => { ...@@ -40,6 +41,14 @@ describe('Blob Header Editing', () => {
}); });
describe('functionality', () => { describe('functionality', () => {
it('does not fail without content', () => {
const spy = jest.spyOn(global.console, 'error');
createComponent({ value: undefined });
expect(spy).not.toHaveBeenCalled();
expect(wrapper.contains('#editor')).toBe(true);
});
it('initialises Editor Lite', () => { it('initialises Editor Lite', () => {
const el = wrapper.find({ ref: 'editor' }).element; const el = wrapper.find({ ref: 'editor' }).element;
expect(initEditorLite).toHaveBeenCalledWith({ expect(initEditorLite).toHaveBeenCalledWith({
......
import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue'; import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue';
import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue'; import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue';
import BlobContentEdit from '~/blob/components/blob_edit_content.vue'; import BlobContentEdit from '~/blob/components/blob_edit_content.vue';
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue'; import { nextTick } from 'vue';
...@@ -13,11 +14,13 @@ describe('Snippet Blob Edit component', () => { ...@@ -13,11 +14,13 @@ describe('Snippet Blob Edit component', () => {
const findHeader = () => wrapper.find(BlobHeaderEdit); const findHeader = () => wrapper.find(BlobHeaderEdit);
const findContent = () => wrapper.find(BlobContentEdit); const findContent = () => wrapper.find(BlobContentEdit);
function createComponent() { function createComponent(props = {}) {
wrapper = shallowMount(SnippetBlobEdit, { wrapper = shallowMount(SnippetBlobEdit, {
propsData: { propsData: {
value, value,
fileName, fileName,
isLoading: false,
...props,
}, },
}); });
} }
...@@ -39,9 +42,23 @@ describe('Snippet Blob Edit component', () => { ...@@ -39,9 +42,23 @@ describe('Snippet Blob Edit component', () => {
expect(findHeader().exists()).toBe(true); expect(findHeader().exists()).toBe(true);
expect(findContent().exists()).toBe(true); expect(findContent().exists()).toBe(true);
}); });
it('renders loader if isLoading equals true', () => {
createComponent({ isLoading: true });
expect(wrapper.contains(GlLoadingIcon)).toBe(true);
expect(findContent().exists()).toBe(false);
});
}); });
describe('functionality', () => { describe('functionality', () => {
it('does not fail without content', () => {
const spy = jest.spyOn(global.console, 'error');
createComponent({ value: undefined });
expect(spy).not.toHaveBeenCalled();
expect(findContent().exists()).toBe(true);
});
it('emits "name-change" event when the file name gets changed', () => { it('emits "name-change" event when the file name gets changed', () => {
expect(wrapper.emitted('name-change')).toBeUndefined(); expect(wrapper.emitted('name-change')).toBeUndefined();
const newFilename = 'foo.bar'; const newFilename = 'foo.bar';
...@@ -51,5 +68,15 @@ describe('Snippet Blob Edit component', () => { ...@@ -51,5 +68,15 @@ describe('Snippet Blob Edit component', () => {
expect(wrapper.emitted('name-change')[0]).toEqual([newFilename]); expect(wrapper.emitted('name-change')[0]).toEqual([newFilename]);
}); });
}); });
it('emits "input" event when the file content gets changed', () => {
expect(wrapper.emitted('input')).toBeUndefined();
const newValue = 'foo.bar';
findContent().vm.$emit('input', newValue);
return nextTick().then(() => {
expect(wrapper.emitted('input')[0]).toEqual([newValue]);
});
});
}); });
}); });
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