Commit 98272880 authored by Paul Slaughter's avatar Paul Slaughter

Merge branch '198729-readd-diff-stats-to-tree-list' into 'master'

Re-add file stats to diff tree list

Closes #198729

See merge request gitlab-org/gitlab!24423
parents 65b8e37b 0def199d
......@@ -4,14 +4,34 @@
* https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23720
*/
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowStats from './file_row_stats.vue';
export default {
name: 'DiffFileRow',
components: {
FileRow,
FileRowStats,
},
props: {
file: {
type: Object,
required: true,
},
hideFileStats: {
type: Boolean,
required: true,
},
},
computed: {
showFileRowStats() {
return !this.hideFileStats && this.file.type === 'blob';
},
},
};
</script>
<template>
<file-row v-bind="$attrs" v-on="$listeners" />
<file-row :file="file" :hide-file-stats="hideFileStats" v-bind="$attrs" v-on="$listeners">
<file-row-stats v-if="showFileRowStats" :file="file" />
</file-row>
</template>
......@@ -5,7 +5,6 @@ import { s__, sprintf } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import FileTree from '~/vue_shared/components/file_tree.vue';
import DiffFileRow from './diff_file_row.vue';
import FileRowStats from './file_row_stats.vue';
export default {
directives: {
......@@ -49,9 +48,6 @@ export default {
return acc;
}, []);
},
fileRowExtraComponent() {
return this.hideFileStats ? null : FileRowStats;
},
},
methods: {
...mapActions('diffs', ['toggleTreeOpen', 'scrollToFile']),
......@@ -98,8 +94,8 @@ export default {
:key="file.key"
:file="file"
:level="0"
:hide-file-stats="hideFileStats"
:hide-extra-on-tree="true"
:extra-component="fileRowExtraComponent"
:show-changed-icon="true"
:file-row-component="$options.DiffFileRow"
@toggleTreeOpen="toggleTreeOpen"
......
......@@ -4,14 +4,35 @@
* https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23720
*/
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowExtra from './file_row_extra.vue';
export default {
name: 'IdeFileRow',
components: {
FileRow,
FileRowExtra,
},
props: {
file: {
type: Object,
required: true,
},
},
data() {
return {
dropdownOpen: false,
};
},
methods: {
toggleDropdown(val) {
this.dropdownOpen = val;
},
},
};
</script>
<template>
<file-row v-bind="$attrs" v-on="$listeners" />
<file-row :file="file" v-bind="$attrs" @mouseleave="toggleDropdown(false)" v-on="$listeners">
<file-row-extra :file="file" :dropdown-open="dropdownOpen" @toggle="toggleDropdown($event)" />
</file-row>
</template>
......@@ -4,7 +4,6 @@ import { GlSkeletonLoading } from '@gitlab/ui';
import FileTree from '~/vue_shared/components/file_tree.vue';
import IdeFileRow from './ide_file_row.vue';
import NavDropdown from './nav_dropdown.vue';
import FileRowExtra from './file_row_extra.vue';
export default {
components: {
......@@ -36,7 +35,6 @@ export default {
methods: {
...mapActions(['updateViewer', 'toggleTreeOpen']),
},
FileRowExtra,
IdeFileRow,
};
</script>
......@@ -60,7 +58,6 @@ export default {
:key="file.key"
:file="file"
:level="0"
:extra-component="$options.FileRowExtra"
:file-row-component="$options.IdeFileRow"
@toggleTreeOpen="toggleTreeOpen"
/>
......
<script>
import Icon from '~/vue_shared/components/icon.vue';
import FileHeader from '~/vue_shared/components/file_row_header.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
......@@ -9,7 +8,6 @@ export default {
components: {
FileHeader,
FileIcon,
Icon,
ChangedFileIcon,
},
props: {
......@@ -21,27 +19,12 @@ export default {
type: Number,
required: true,
},
extraComponent: {
type: Object,
required: false,
default: null,
},
hideExtraOnTree: {
type: Boolean,
required: false,
default: false,
},
showChangedIcon: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
dropdownOpen: false,
};
},
computed: {
isTree() {
return this.file.type === 'tree';
......@@ -120,9 +103,6 @@ export default {
return this.$router.currentRoute.path === `/project${this.file.url}`;
},
toggleDropdown(val) {
this.dropdownOpen = val;
},
},
};
</script>
......@@ -136,7 +116,7 @@ export default {
class="file-row"
role="button"
@click="clickFile"
@mouseleave="toggleDropdown(false)"
@mouseleave="$emit('mouseleave', $event)"
>
<div class="file-row-name-container">
<span ref="textOutput" :style="levelIndentation" class="file-row-name str-truncated">
......@@ -152,13 +132,7 @@ export default {
<changed-file-icon v-else :file="file" :size="16" class="append-right-5" />
{{ file.name }}
</span>
<component
:is="extraComponent"
v-if="extraComponent && !(hideExtraOnTree && file.type === 'tree')"
:file="file"
:dropdown-open="dropdownOpen"
@toggle="toggleDropdown($event)"
/>
<slot></slot>
</div>
</div>
</template>
......
import { shallowMount } from '@vue/test-utils';
import DiffFileRow from '~/diffs/components/diff_file_row.vue';
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowStats from '~/diffs/components/file_row_stats.vue';
describe('Diff File Row component', () => {
let wrapper;
......@@ -16,10 +17,42 @@ describe('Diff File Row component', () => {
});
it('renders file row component', () => {
createComponent({
const sharedProps = {
level: 4,
file: {},
};
const diffFileRowProps = {
hideFileStats: false,
};
createComponent({
...sharedProps,
...diffFileRowProps,
});
expect(wrapper.find(FileRow).props()).toEqual(
expect.objectContaining({
...sharedProps,
}),
);
});
describe('FileRowStats components', () => {
it.each`
type | hideFileStats | value | desc
${'blob'} | ${false} | ${true} | ${'is shown if file type is blob'}
${'tree'} | ${false} | ${false} | ${'is hidden if file is not blob'}
${'blob'} | ${true} | ${false} | ${'is hidden if hideFileStats is true'}
`('$desc', ({ type, value, hideFileStats }) => {
createComponent({
level: 4,
file: {
type,
},
hideFileStats,
});
expect(wrapper.find(FileRowStats).exists()).toEqual(value);
});
expect(wrapper.find(FileRow).exists()).toEqual(true);
});
});
Element.prototype.scrollIntoView = jest.fn();
import './element_scroll_into_view';
import './get_client_rects';
import './inner_text';
import './window_scroll_to';
import { shallowMount } from '@vue/test-utils';
import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
import IdeFileRow from '~/ide/components/ide_file_row.vue';
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowExtra from '~/ide/components/file_row_extra.vue';
import { createStore } from '~/ide/stores';
const localVue = createLocalVue();
localVue.use(Vuex);
const TEST_EXTRA_PROPS = {
testattribute: 'abc',
};
const defaultComponentProps = (type = 'tree') => ({
level: 4,
file: {
type,
name: 'js',
},
});
describe('Ide File Row component', () => {
let wrapper;
const createComponent = (props = {}) => {
wrapper = shallowMount(IdeFileRow, {
propsData: { ...props },
const createComponent = (props = {}, options = {}) => {
wrapper = mount(IdeFileRow, {
propsData: {
...defaultComponentProps(),
...props,
},
store: createStore(),
localVue,
...options,
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
const findFileRowExtra = () => wrapper.find(FileRowExtra);
const findFileRow = () => wrapper.find(FileRow);
const hasDropdownOpen = () => findFileRowExtra().props('dropdownOpen');
it('fileRow component has listeners', () => {
const toggleTreeOpen = jest.fn();
createComponent(
{},
{
listeners: {
toggleTreeOpen,
},
},
);
findFileRow().vm.$emit('toggleTreeOpen');
return wrapper.vm.$nextTick().then(() => {
expect(toggleTreeOpen).toHaveBeenCalled();
});
});
describe('default', () => {
beforeEach(() => {
createComponent(TEST_EXTRA_PROPS);
});
it('renders file row component', () => {
createComponent({
level: 4,
file: {},
const fileRow = findFileRow();
expect(fileRow.props()).toEqual(expect.objectContaining(defaultComponentProps()));
expect(fileRow.attributes()).toEqual(expect.objectContaining(TEST_EXTRA_PROPS));
});
it('renders file row extra', () => {
const extra = findFileRowExtra();
expect(extra.exists()).toBe(true);
expect(extra.props()).toEqual({
file: defaultComponentProps().file,
dropdownOpen: false,
});
});
});
describe('with open dropdown', () => {
beforeEach(() => {
createComponent();
findFileRowExtra().vm.$emit('toggle', true);
return wrapper.vm.$nextTick();
});
it('shows open dropdown', () => {
expect(hasDropdownOpen()).toBe(true);
});
it('hides dropdown when mouseleave', () => {
findFileRow().vm.$emit('mouseleave');
return wrapper.vm.$nextTick().then(() => {
expect(hasDropdownOpen()).toEqual(false);
});
});
it('hides dropdown on toggle', () => {
findFileRowExtra().vm.$emit('toggle', false);
return wrapper.vm.$nextTick().then(() => {
expect(hasDropdownOpen()).toEqual(false);
});
});
expect(wrapper.find(FileRow).exists()).toEqual(true);
});
});
import Vue from 'vue';
import { file } from 'spec/ide/helpers';
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowExtra from '~/ide/components/file_row_extra.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';
describe('File row component', () => {
......@@ -17,9 +16,6 @@ describe('File row component', () => {
vm.$destroy();
});
const findNewDropdown = () => vm.$el.querySelector('.ide-new-btn .dropdown');
const findNewDropdownButton = () => vm.$el.querySelector('.ide-new-btn .dropdown button');
it('renders name', () => {
createComponent({
file: file('t4'),
......@@ -88,59 +84,4 @@ describe('File row component', () => {
expect(vm.$el.classList).toContain('js-file-row-header');
});
describe('new dropdown', () => {
beforeEach(() => {
createComponent({
file: file('t5'),
level: 1,
extraComponent: FileRowExtra,
});
});
it('renders in extra component', () => {
expect(findNewDropdown()).not.toBe(null);
});
it('is hidden at start', () => {
expect(findNewDropdown()).not.toHaveClass('show');
});
it('is opened when button is clicked', done => {
expect(vm.dropdownOpen).toBe(false);
findNewDropdownButton().dispatchEvent(new Event('click'));
vm.$nextTick()
.then(() => {
expect(vm.dropdownOpen).toBe(true);
expect(findNewDropdown()).toHaveClass('show');
})
.then(done)
.catch(done.fail);
});
describe('when opened', () => {
beforeEach(() => {
vm.dropdownOpen = true;
});
it('stays open when button triggers mouseout', () => {
findNewDropdownButton().dispatchEvent(new Event('mouseout'));
expect(vm.dropdownOpen).toBe(true);
});
it('stays open when button triggers mouseleave', () => {
findNewDropdownButton().dispatchEvent(new Event('mouseleave'));
expect(vm.dropdownOpen).toBe(true);
});
it('closes when row triggers mouseleave', () => {
vm.$el.dispatchEvent(new Event('mouseleave'));
expect(vm.dropdownOpen).toBe(false);
});
});
});
});
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