Merge branch 'multi-file-editor-separate-commits-call' into 'master'
Multi-file editor fetch log data from a different endpoint Closes #38360 See merge request gitlab-org/gitlab-ce!15132
This commit is contained in:
commit
dc1e6b4362
21 changed files with 276 additions and 87 deletions
|
@ -1,11 +1,15 @@
|
|||
<script>
|
||||
import { mapActions, mapGetters } from 'vuex';
|
||||
import timeAgoMixin from '../../vue_shared/mixins/timeago';
|
||||
import skeletonLoadingContainer from '../../vue_shared/components/skeleton_loading_container.vue';
|
||||
|
||||
export default {
|
||||
mixins: [
|
||||
timeAgoMixin,
|
||||
],
|
||||
components: {
|
||||
skeletonLoadingContainer,
|
||||
},
|
||||
props: {
|
||||
file: {
|
||||
type: Object,
|
||||
|
@ -16,6 +20,9 @@
|
|||
...mapGetters([
|
||||
'isCollapsed',
|
||||
]),
|
||||
isSubmodule() {
|
||||
return this.file.type === 'submodule';
|
||||
},
|
||||
fileIcon() {
|
||||
return {
|
||||
'fa-spinner fa-spin': this.file.loading,
|
||||
|
@ -31,6 +38,9 @@
|
|||
shortId() {
|
||||
return this.file.id.substr(0, 8);
|
||||
},
|
||||
submoduleColSpan() {
|
||||
return !this.isCollapsed && this.isSubmodule ? 3 : 1;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
|
@ -44,7 +54,7 @@
|
|||
<tr
|
||||
class="file"
|
||||
@click.prevent="clickedTreeRow(file)">
|
||||
<td>
|
||||
<td :colspan="submoduleColSpan">
|
||||
<i
|
||||
class="fa fa-fw file-icon"
|
||||
:class="fileIcon"
|
||||
|
@ -58,7 +68,7 @@
|
|||
>
|
||||
{{ file.name }}
|
||||
</a>
|
||||
<template v-if="file.type === 'submodule' && file.id">
|
||||
<template v-if="isSubmodule && file.id">
|
||||
@
|
||||
<span class="commit-sha">
|
||||
<a
|
||||
|
@ -71,15 +81,20 @@
|
|||
</template>
|
||||
</td>
|
||||
|
||||
<template v-if="!isCollapsed">
|
||||
<template v-if="!isCollapsed && !isSubmodule">
|
||||
<td class="hidden-sm hidden-xs">
|
||||
<a
|
||||
v-if="file.lastCommit.message"
|
||||
@click.stop
|
||||
:href="file.lastCommit.url"
|
||||
class="commit-message"
|
||||
>
|
||||
{{ file.lastCommit.message }}
|
||||
</a>
|
||||
<skeleton-loading-container
|
||||
v-else
|
||||
:small="true"
|
||||
/>
|
||||
</td>
|
||||
|
||||
<td class="commit-update hidden-xs text-right">
|
||||
|
@ -89,6 +104,11 @@
|
|||
>
|
||||
{{ timeFormated(file.lastCommit.updatedAt) }}
|
||||
</span>
|
||||
<skeleton-loading-container
|
||||
v-else
|
||||
class="animation-container-right"
|
||||
:small="true"
|
||||
/>
|
||||
</td>
|
||||
</template>
|
||||
</tr>
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import skeletonLoadingContainer from '../../vue_shared/components/skeleton_loading_container.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
skeletonLoadingContainer,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'isCollapsed',
|
||||
]),
|
||||
},
|
||||
methods: {
|
||||
lineOfCode(n) {
|
||||
return `skeleton-line-${n}`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -21,36 +20,24 @@
|
|||
aria-label="Loading files"
|
||||
>
|
||||
<td>
|
||||
<div
|
||||
class="animation-container animation-container-small">
|
||||
<div
|
||||
v-for="n in 6"
|
||||
:key="n"
|
||||
:class="lineOfCode(n)">
|
||||
</div>
|
||||
</div>
|
||||
<skeleton-loading-container
|
||||
:small="true"
|
||||
/>
|
||||
</td>
|
||||
<template v-if="!isCollapsed">
|
||||
<td
|
||||
class="hidden-sm hidden-xs">
|
||||
<div class="animation-container">
|
||||
<div
|
||||
v-for="n in 6"
|
||||
:key="n"
|
||||
:class="lineOfCode(n)">
|
||||
</div>
|
||||
</div>
|
||||
<skeleton-loading-container
|
||||
:small="true"
|
||||
/>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="hidden-xs">
|
||||
<div class="animation-container animation-container-small animation-container-right">
|
||||
<div
|
||||
v-for="n in 6"
|
||||
:key="n"
|
||||
:class="lineOfCode(n)">
|
||||
</div>
|
||||
</div>
|
||||
<skeleton-loading-container
|
||||
class="animation-container-right"
|
||||
:small="true"
|
||||
/>
|
||||
</td>
|
||||
</template>
|
||||
</tr>
|
||||
|
|
|
@ -80,7 +80,7 @@ export default {
|
|||
/>
|
||||
<repo-file
|
||||
v-for="(file, index) in treeList"
|
||||
:key="index"
|
||||
:key="file.key"
|
||||
:file="file"
|
||||
/>
|
||||
</tbody>
|
||||
|
|
|
@ -30,4 +30,11 @@ export default {
|
|||
commit(projectId, payload) {
|
||||
return Api.commitMultiple(projectId, payload);
|
||||
},
|
||||
getTreeLastCommit(endpoint) {
|
||||
return Vue.http.get(endpoint, {
|
||||
params: {
|
||||
format: 'json',
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -64,7 +64,7 @@ export const checkCommitStatus = ({ state }) => service.getBranchData(
|
|||
})
|
||||
.catch(() => flash('Error checking branch data. Please try again.'));
|
||||
|
||||
export const commitChanges = ({ commit, state, dispatch }, { payload, newMr }) =>
|
||||
export const commitChanges = ({ commit, state, dispatch, getters }, { payload, newMr }) =>
|
||||
service.commit(state.project.id, payload)
|
||||
.then((data) => {
|
||||
const { branch } = payload;
|
||||
|
@ -73,12 +73,28 @@ export const commitChanges = ({ commit, state, dispatch }, { payload, newMr }) =
|
|||
return;
|
||||
}
|
||||
|
||||
const lastCommit = {
|
||||
commit_path: `${state.project.url}/commit/${data.id}`,
|
||||
commit: {
|
||||
message: data.message,
|
||||
authored_date: data.committed_date,
|
||||
},
|
||||
};
|
||||
|
||||
flash(`Your changes have been committed. Commit ${data.short_id} with ${data.stats.additions} additions, ${data.stats.deletions} deletions.`, 'notice');
|
||||
|
||||
if (newMr) {
|
||||
redirectToUrl(`${state.endpoints.newMergeRequestUrl}${branch}`);
|
||||
} else {
|
||||
commit(types.SET_COMMIT_REF, data.id);
|
||||
|
||||
getters.changedFiles.forEach((entry) => {
|
||||
commit(types.SET_LAST_COMMIT_DATA, {
|
||||
entry,
|
||||
lastCommit,
|
||||
});
|
||||
});
|
||||
|
||||
dispatch('discardAllChanges');
|
||||
dispatch('closeAllFiles');
|
||||
dispatch('toggleEditMode');
|
||||
|
|
|
@ -27,6 +27,8 @@ export const closeFile = ({ commit, state, dispatch }, { file, force = false })
|
|||
} else if (!state.openFiles.length) {
|
||||
pushState(file.parentTreeUrl);
|
||||
}
|
||||
|
||||
dispatch('getLastCommitData');
|
||||
};
|
||||
|
||||
export const setFileActive = ({ commit, state, getters, dispatch }, file) => {
|
||||
|
|
|
@ -7,10 +7,11 @@ import {
|
|||
setPageTitle,
|
||||
findEntry,
|
||||
createTemp,
|
||||
createOrMergeEntry,
|
||||
} from '../utils';
|
||||
|
||||
export const getTreeData = (
|
||||
{ commit, state },
|
||||
{ commit, state, dispatch },
|
||||
{ endpoint = state.endpoints.rootEndpoint, tree = state } = {},
|
||||
) => {
|
||||
commit(types.TOGGLE_LOADING, tree);
|
||||
|
@ -24,14 +25,20 @@ export const getTreeData = (
|
|||
return res.json();
|
||||
})
|
||||
.then((data) => {
|
||||
const prevLastCommitPath = tree.lastCommitPath;
|
||||
if (!state.isInitialRoot) {
|
||||
commit(types.SET_ROOT, data.path === '/');
|
||||
}
|
||||
|
||||
commit(types.SET_DIRECTORY_DATA, { data, tree });
|
||||
dispatch('updateDirectoryData', { data, tree });
|
||||
commit(types.SET_PARENT_TREE_URL, data.parent_tree_url);
|
||||
commit(types.SET_LAST_COMMIT_URL, { tree, url: data.last_commit_path });
|
||||
commit(types.TOGGLE_LOADING, tree);
|
||||
|
||||
if (prevLastCommitPath !== null) {
|
||||
dispatch('getLastCommitData', tree);
|
||||
}
|
||||
|
||||
pushState(endpoint);
|
||||
})
|
||||
.catch(() => {
|
||||
|
@ -48,7 +55,7 @@ export const toggleTreeOpen = ({ commit, dispatch }, { endpoint, tree }) => {
|
|||
pushState(tree.parentTreeUrl);
|
||||
|
||||
commit(types.SET_PREVIOUS_URL, tree.parentTreeUrl);
|
||||
commit(types.SET_DIRECTORY_DATA, { data, tree });
|
||||
dispatch('updateDirectoryData', { data, tree });
|
||||
} else {
|
||||
commit(types.SET_PREVIOUS_URL, endpoint);
|
||||
dispatch('getTreeData', { endpoint, tree });
|
||||
|
@ -108,3 +115,48 @@ export const createTempTree = ({ state, commit, dispatch }, name) => {
|
|||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const getLastCommitData = ({ state, commit, dispatch, getters }, tree = state) => {
|
||||
if (tree.lastCommitPath === null || getters.isCollapsed) return;
|
||||
|
||||
service.getTreeLastCommit(tree.lastCommitPath)
|
||||
.then((res) => {
|
||||
const lastCommitPath = normalizeHeaders(res.headers)['MORE-LOGS-URL'] || null;
|
||||
|
||||
commit(types.SET_LAST_COMMIT_URL, { tree, url: lastCommitPath });
|
||||
|
||||
return res.json();
|
||||
})
|
||||
.then((data) => {
|
||||
data.forEach((lastCommit) => {
|
||||
const entry = findEntry(tree, lastCommit.type, lastCommit.file_name);
|
||||
|
||||
if (entry) {
|
||||
commit(types.SET_LAST_COMMIT_DATA, { entry, lastCommit });
|
||||
}
|
||||
});
|
||||
|
||||
dispatch('getLastCommitData', tree);
|
||||
})
|
||||
.catch(() => flash('Error fetching log data.'));
|
||||
};
|
||||
|
||||
export const updateDirectoryData = ({ commit, state }, { data, tree }) => {
|
||||
const level = tree.level !== undefined ? tree.level + 1 : 0;
|
||||
const parentTreeUrl = data.parent_tree_url ? `${data.parent_tree_url}${data.path}` : state.endpoints.rootUrl;
|
||||
const createEntry = (entry, type) => createOrMergeEntry({
|
||||
tree,
|
||||
entry,
|
||||
level,
|
||||
type,
|
||||
parentTreeUrl,
|
||||
});
|
||||
|
||||
const formattedData = [
|
||||
...data.trees.map(t => createEntry(t, 'tree')),
|
||||
...data.submodules.map(m => createEntry(m, 'submodule')),
|
||||
...data.blobs.map(b => createEntry(b, 'blob')),
|
||||
];
|
||||
|
||||
commit(types.SET_DIRECTORY_DATA, { tree, data: formattedData });
|
||||
};
|
||||
|
|
|
@ -4,11 +4,13 @@ export const SET_COMMIT_REF = 'SET_COMMIT_REF';
|
|||
export const SET_PARENT_TREE_URL = 'SET_PARENT_TREE_URL';
|
||||
export const SET_ROOT = 'SET_ROOT';
|
||||
export const SET_PREVIOUS_URL = 'SET_PREVIOUS_URL';
|
||||
export const SET_LAST_COMMIT_DATA = 'SET_LAST_COMMIT_DATA';
|
||||
|
||||
// Tree mutation types
|
||||
export const SET_DIRECTORY_DATA = 'SET_DIRECTORY_DATA';
|
||||
export const TOGGLE_TREE_OPEN = 'TOGGLE_TREE_OPEN';
|
||||
export const CREATE_TMP_TREE = 'CREATE_TMP_TREE';
|
||||
export const SET_LAST_COMMIT_URL = 'SET_LAST_COMMIT_URL';
|
||||
|
||||
// File mutation types
|
||||
export const SET_FILE_DATA = 'SET_FILE_DATA';
|
||||
|
|
|
@ -48,6 +48,13 @@ export default {
|
|||
previousUrl,
|
||||
});
|
||||
},
|
||||
[types.SET_LAST_COMMIT_DATA](state, { entry, lastCommit }) {
|
||||
Object.assign(entry.lastCommit, {
|
||||
url: lastCommit.commit_path,
|
||||
message: lastCommit.commit.message,
|
||||
updatedAt: lastCommit.commit.authored_date,
|
||||
});
|
||||
},
|
||||
...fileMutations,
|
||||
...treeMutations,
|
||||
...branchMutations,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as types from '../mutation_types';
|
||||
import * as utils from '../utils';
|
||||
|
||||
export default {
|
||||
[types.TOGGLE_TREE_OPEN](state, tree) {
|
||||
|
@ -8,30 +7,8 @@ export default {
|
|||
});
|
||||
},
|
||||
[types.SET_DIRECTORY_DATA](state, { data, tree }) {
|
||||
const level = tree.level !== undefined ? tree.level + 1 : 0;
|
||||
const parentTreeUrl = data.parent_tree_url ? `${data.parent_tree_url}${data.path}` : state.endpoints.rootUrl;
|
||||
|
||||
Object.assign(tree, {
|
||||
tree: [
|
||||
...data.trees.map(t => utils.decorateData({
|
||||
...t,
|
||||
type: 'tree',
|
||||
parentTreeUrl,
|
||||
level,
|
||||
}, state.project.url)),
|
||||
...data.submodules.map(m => utils.decorateData({
|
||||
...m,
|
||||
type: 'submodule',
|
||||
parentTreeUrl,
|
||||
level,
|
||||
}, state.project.url)),
|
||||
...data.blobs.map(b => utils.decorateData({
|
||||
...b,
|
||||
type: 'blob',
|
||||
parentTreeUrl,
|
||||
level,
|
||||
}, state.project.url)),
|
||||
],
|
||||
tree: data,
|
||||
});
|
||||
},
|
||||
[types.SET_PARENT_TREE_URL](state, url) {
|
||||
|
@ -39,6 +16,11 @@ export default {
|
|||
parentTreeUrl: url,
|
||||
});
|
||||
},
|
||||
[types.SET_LAST_COMMIT_URL](state, { tree = state, url }) {
|
||||
Object.assign(tree, {
|
||||
lastCommitPath: url,
|
||||
});
|
||||
},
|
||||
[types.CREATE_TMP_TREE](state, { parent, tmpEntry }) {
|
||||
parent.tree.push(tmpEntry);
|
||||
},
|
||||
|
|
|
@ -8,6 +8,7 @@ export default () => ({
|
|||
endpoints: {},
|
||||
isRoot: false,
|
||||
isInitialRoot: false,
|
||||
lastCommitPath: '',
|
||||
loading: false,
|
||||
onTopOfBranch: false,
|
||||
openFiles: [],
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export const dataStructure = () => ({
|
||||
id: '',
|
||||
key: '',
|
||||
type: '',
|
||||
name: '',
|
||||
url: '',
|
||||
|
@ -12,7 +13,12 @@ export const dataStructure = () => ({
|
|||
opened: false,
|
||||
active: false,
|
||||
changed: false,
|
||||
lastCommit: {},
|
||||
lastCommitPath: '',
|
||||
lastCommit: {
|
||||
url: '',
|
||||
message: '',
|
||||
updatedAt: '',
|
||||
},
|
||||
tree_url: '',
|
||||
blamePath: '',
|
||||
commitsPath: '',
|
||||
|
@ -27,14 +33,13 @@ export const dataStructure = () => ({
|
|||
base64: false,
|
||||
});
|
||||
|
||||
export const decorateData = (entity, projectUrl = '') => {
|
||||
export const decorateData = (entity) => {
|
||||
const {
|
||||
id,
|
||||
type,
|
||||
url,
|
||||
name,
|
||||
icon,
|
||||
last_commit,
|
||||
tree_url,
|
||||
path,
|
||||
renderError,
|
||||
|
@ -51,6 +56,7 @@ export const decorateData = (entity, projectUrl = '') => {
|
|||
return {
|
||||
...dataStructure(),
|
||||
id,
|
||||
key: `${name}-${type}-${id}`,
|
||||
type,
|
||||
name,
|
||||
url,
|
||||
|
@ -66,12 +72,6 @@ export const decorateData = (entity, projectUrl = '') => {
|
|||
renderError,
|
||||
content,
|
||||
base64,
|
||||
// eslint-disable-next-line camelcase
|
||||
lastCommit: last_commit ? {
|
||||
url: `${projectUrl}/commit/${last_commit.id}`,
|
||||
message: last_commit.message,
|
||||
updatedAt: last_commit.committed_date,
|
||||
} : {},
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -106,3 +106,22 @@ export const createTemp = ({ name, path, type, level, changed, content, base64 }
|
|||
renderError: base64,
|
||||
});
|
||||
};
|
||||
|
||||
export const createOrMergeEntry = ({ tree, entry, type, parentTreeUrl, level }) => {
|
||||
const found = findEntry(tree, type, entry.name);
|
||||
|
||||
if (found) {
|
||||
return Object.assign({}, found, {
|
||||
id: entry.id,
|
||||
url: entry.url,
|
||||
tempFile: false,
|
||||
});
|
||||
}
|
||||
|
||||
return decorateData({
|
||||
...entry,
|
||||
type,
|
||||
parentTreeUrl,
|
||||
level,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
small: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
lines: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 6,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
lineClasses() {
|
||||
return new Array(this.lines).fill().map((_, i) => `skeleton-line-${i + 1}`);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="animation-container"
|
||||
:class="{
|
||||
'animation-container-small': small,
|
||||
}"
|
||||
>
|
||||
<div
|
||||
v-for="(css, index) in lineClasses"
|
||||
:key="index"
|
||||
:class="css"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -56,9 +56,12 @@ class Projects::RefsController < Projects::ApplicationController
|
|||
contents[@offset, @limit].to_a.map do |content|
|
||||
file = @path ? File.join(@path, content.name) : content.name
|
||||
last_commit = @repo.last_commit_for_path(@commit.id, file)
|
||||
commit_path = project_commit_path(@project, last_commit) if last_commit
|
||||
{
|
||||
file_name: content.name,
|
||||
commit: last_commit
|
||||
commit: last_commit,
|
||||
type: content.type,
|
||||
commit_path: commit_path
|
||||
}
|
||||
end
|
||||
end
|
||||
|
@ -70,6 +73,11 @@ class Projects::RefsController < Projects::ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html { render_404 }
|
||||
format.json do
|
||||
response.headers["More-Logs-Url"] = @more_log_url
|
||||
|
||||
render json: @logs
|
||||
end
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,10 +3,6 @@ class BlobEntity < Grape::Entity
|
|||
|
||||
expose :id, :path, :name, :mode
|
||||
|
||||
expose :last_commit do |blob|
|
||||
request.project.repository.last_commit_for_path(blob.commit_id, blob.path)
|
||||
end
|
||||
|
||||
expose :icon do |blob|
|
||||
IconsHelper.file_type_icon_class('file', blob.mode, blob.name)
|
||||
end
|
||||
|
|
|
@ -3,10 +3,6 @@ class TreeEntity < Grape::Entity
|
|||
|
||||
expose :id, :path, :name, :mode
|
||||
|
||||
expose :last_commit do |tree|
|
||||
request.project.repository.last_commit_for_path(tree.commit_id, tree.path)
|
||||
end
|
||||
|
||||
expose :icon do |tree|
|
||||
IconsHelper.file_type_icon_class('folder', tree.mode, tree.name)
|
||||
end
|
||||
|
|
|
@ -18,4 +18,8 @@ class TreeRootEntity < Grape::Entity
|
|||
|
||||
project_tree_path(request.project, File.join(request.ref, parent_tree_path))
|
||||
end
|
||||
|
||||
expose :last_commit_path do |tree|
|
||||
logs_file_project_ref_path(request.project, request.ref, tree.path)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,12 +23,15 @@ describe Projects::RefsController do
|
|||
xhr :get,
|
||||
:logs_tree,
|
||||
namespace_id: project.namespace.to_param,
|
||||
project_id: project, id: 'master',
|
||||
path: 'foo/bar/baz.html', format: format
|
||||
project_id: project,
|
||||
id: 'master',
|
||||
path: 'foo/bar/baz.html',
|
||||
format: format
|
||||
end
|
||||
|
||||
it 'never throws MissingTemplate' do
|
||||
expect { default_get }.not_to raise_error
|
||||
expect { xhr_get(:json) }.not_to raise_error
|
||||
expect { xhr_get }.not_to raise_error
|
||||
end
|
||||
|
||||
|
@ -42,5 +45,12 @@ describe Projects::RefsController do
|
|||
xhr_get(:js)
|
||||
expect(response).to be_success
|
||||
end
|
||||
|
||||
it 'renders JSON' do
|
||||
xhr_get(:json)
|
||||
|
||||
expect(response).to be_success
|
||||
expect(json_response).to be_kind_of(Array)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -31,10 +31,5 @@ feature 'Multi-file editor new directory', :js do
|
|||
click_button('Commit 1 file')
|
||||
|
||||
expect(page).to have_selector('td', text: 'commit message')
|
||||
|
||||
click_link('foldername')
|
||||
|
||||
expect(page).to have_selector('td', text: 'commit message', count: 2)
|
||||
expect(page).to have_selector('td', text: '.gitkeep')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,7 +20,7 @@ describe('RepoFile', () => {
|
|||
resetStore(vm.$store);
|
||||
});
|
||||
|
||||
it('renders link, icon, name and last commit details', () => {
|
||||
it('renders link, icon and name', () => {
|
||||
const RepoFile = Vue.extend(repoFile);
|
||||
vm = new RepoFile({
|
||||
store,
|
||||
|
@ -37,10 +37,9 @@ describe('RepoFile', () => {
|
|||
expect(vm.$el.querySelector(`.${vm.file.icon}`).style.marginLeft).toEqual('0px');
|
||||
expect(name.href).toMatch(`/${vm.file.url}`);
|
||||
expect(name.textContent.trim()).toEqual(vm.file.name);
|
||||
expect(vm.$el.querySelector('.commit-message').textContent.trim()).toBe(vm.file.lastCommit.message);
|
||||
expect(vm.$el.querySelector('.commit-update').textContent.trim()).toBe(updated);
|
||||
expect(fileIcon.classList.contains(vm.file.icon)).toBeTruthy();
|
||||
expect(fileIcon.style.marginLeft).toEqual(`${vm.file.level * 10}px`);
|
||||
expect(vm.$el.querySelectorAll('.animation-container').length).toBe(2);
|
||||
});
|
||||
|
||||
it('does render if hasFiles is true and is loading tree', () => {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
import Vue from 'vue';
|
||||
import skeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue';
|
||||
import mountComponent from '../../helpers/vue_mount_component_helper';
|
||||
|
||||
describe('Skeleton loading container', () => {
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
const component = Vue.extend(skeletonLoadingContainer);
|
||||
vm = mountComponent(component);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
it('renders 6 skeleton lines by default', () => {
|
||||
expect(vm.$el.querySelector('.skeleton-line-6')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders in full mode by default', () => {
|
||||
expect(vm.$el.classList.contains('animation-container-small')).toBeFalsy();
|
||||
});
|
||||
|
||||
describe('small', () => {
|
||||
beforeEach((done) => {
|
||||
vm.small = true;
|
||||
|
||||
Vue.nextTick(done);
|
||||
});
|
||||
|
||||
it('renders in small mode', () => {
|
||||
expect(vm.$el.classList.contains('animation-container-small')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('lines', () => {
|
||||
beforeEach((done) => {
|
||||
vm.lines = 5;
|
||||
|
||||
Vue.nextTick(done);
|
||||
});
|
||||
|
||||
it('renders 5 lines', () => {
|
||||
expect(vm.$el.querySelector('.skeleton-line-5')).not.toBeNull();
|
||||
expect(vm.$el.querySelector('.skeleton-line-6')).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue