summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2018-05-04 15:25:52 +0000
committerFilipa Lacerda <filipa@gitlab.com>2018-05-04 15:25:52 +0000
commit5c25ea48c8e01b14c8c09b063c6dc1014e095bd2 (patch)
tree9c22064915d04db3b43fe86bac78d205d26de0d4
parent9f2f8679bec1e2d4161c429c2e6db80a20e376c9 (diff)
parent8a21c31b8b2baf19b1433ab5175fbc8bd66d07c6 (diff)
downloadgitlab-ce-5c25ea48c8e01b14c8c09b063c6dc1014e095bd2.tar.gz
Merge branch 'ide-sidebar-commit-box' into '44846-improve-web-ide-left-panel-and-modes'
Updated commit section in IDE sidebar See merge request gitlab-org/gitlab-ce!18616
-rw-r--r--app/assets/javascripts/ide/components/activity_bar.vue4
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/actions.vue16
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/form.vue171
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list.vue17
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue30
-rw-r--r--app/assets/javascripts/ide/components/ide_side_bar.vue23
-rw-r--r--app/assets/javascripts/ide/components/ide_tree.vue14
-rw-r--r--app/assets/javascripts/ide/components/repo_commit_section.vue84
-rw-r--r--app/assets/javascripts/ide/components/repo_tab.vue3
-rw-r--r--app/assets/javascripts/ide/constants.js4
-rw-r--r--app/assets/javascripts/ide/stores/actions/file.js8
-rw-r--r--app/assets/javascripts/ide/stores/getters.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/actions.js39
-rw-r--r--app/assets/javascripts/ide/stores/mutations/file.js49
-rw-r--r--app/assets/stylesheets/pages/repo.scss106
-rw-r--r--spec/features/projects/tree/create_directory_spec.rb3
-rw-r--r--spec/features/projects/tree/create_file_spec.rb3
-rw-r--r--spec/javascripts/ide/components/commit_sidebar/form_spec.js146
-rw-r--r--spec/javascripts/ide/components/commit_sidebar/list_spec.js12
-rw-r--r--spec/javascripts/ide/components/repo_commit_section_spec.js100
-rw-r--r--spec/javascripts/ide/stores/actions/file_spec.js14
-rw-r--r--spec/javascripts/ide/stores/modules/commit/actions_spec.js30
-rw-r--r--spec/javascripts/ide/stores/mutations/file_spec.js36
23 files changed, 618 insertions, 300 deletions
diff --git a/app/assets/javascripts/ide/components/activity_bar.vue b/app/assets/javascripts/ide/components/activity_bar.vue
index e27404a08d3..edea6a9b894 100644
--- a/app/assets/javascripts/ide/components/activity_bar.vue
+++ b/app/assets/javascripts/ide/components/activity_bar.vue
@@ -8,7 +8,7 @@ export default {
Icon,
},
computed: {
- ...mapGetters(['currentProject']),
+ ...mapGetters(['currentProject', 'hasChanges']),
...mapState(['currentActivityView']),
goBackUrl() {
return document.referrer || this.currentProject.web_url;
@@ -65,7 +65,7 @@ export default {
/>
</button>
</li>
- <li>
+ <li v-show="hasChanges">
<button
type="button"
class="ide-sidebar-link js-ide-commit-mode"
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
index 45321df191c..6a5790c9dff 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
@@ -1,5 +1,5 @@
<script>
-import { mapState } from 'vuex';
+import { mapActions, mapState } from 'vuex';
import { sprintf, __ } from '~/locale';
import * as consts from '../../stores/modules/commit/constants';
import RadioGroup from './radio_group.vue';
@@ -9,7 +9,7 @@ export default {
RadioGroup,
},
computed: {
- ...mapState(['currentBranchId']),
+ ...mapState(['currentBranchId', 'changedFiles', 'stagedFiles']),
commitToCurrentBranchText() {
return sprintf(
__('Commit to %{branchName} branch'),
@@ -17,6 +17,17 @@ export default {
false,
);
},
+ disableMergeRequestRadio() {
+ return this.changedFiles.length > 0 && this.stagedFiles.length > 0;
+ },
+ },
+ mounted() {
+ if (this.disableMergeRequestRadio) {
+ this.updateCommitAction(consts.COMMIT_TO_CURRENT_BRANCH);
+ }
+ },
+ methods: {
+ ...mapActions('commit', ['updateCommitAction']),
},
commitToCurrentBranch: consts.COMMIT_TO_CURRENT_BRANCH,
commitToNewBranch: consts.COMMIT_TO_NEW_BRANCH,
@@ -44,6 +55,7 @@ export default {
:value="$options.commitToNewBranchMR"
:label="__('Create a new branch and merge request')"
:show-input="true"
+ :disabled="disableMergeRequestRadio"
/>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/form.vue b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
new file mode 100644
index 00000000000..4a645c827ad
--- /dev/null
+++ b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
@@ -0,0 +1,171 @@
+<script>
+import { mapState, mapActions, mapGetters } from 'vuex';
+import { sprintf, __ } from '~/locale';
+import LoadingButton from '~/vue_shared/components/loading_button.vue';
+import CommitMessageField from './message_field.vue';
+import Actions from './actions.vue';
+import SuccessMessage from './success_message.vue';
+import { activityBarViews, MAX_WINDOW_HEIGHT_COMPACT, COMMIT_ITEM_PADDING } from '../../constants';
+
+export default {
+ components: {
+ Actions,
+ LoadingButton,
+ CommitMessageField,
+ SuccessMessage,
+ },
+ data() {
+ return {
+ isCompact: true,
+ componentHeight: null,
+ };
+ },
+ computed: {
+ ...mapState(['changedFiles', 'stagedFiles', 'currentActivityView', 'lastCommitMsg']),
+ ...mapState('commit', ['commitMessage', 'submitCommitLoading']),
+ ...mapGetters(['hasChanges']),
+ ...mapGetters('commit', ['commitButtonDisabled', 'discardDraftButtonDisabled']),
+ overviewText() {
+ return sprintf(
+ __(
+ '<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes',
+ ),
+ {
+ stagedFilesLength: this.stagedFiles.length,
+ changedFilesLength: this.changedFiles.length,
+ },
+ );
+ },
+ },
+ watch: {
+ currentActivityView() {
+ if (this.lastCommitMsg) {
+ this.isCompact = false;
+ } else {
+ this.isCompact = !(
+ this.currentActivityView === activityBarViews.commit &&
+ window.innerHeight >= MAX_WINDOW_HEIGHT_COMPACT
+ );
+ }
+ },
+ lastCommitMsg() {
+ this.isCompact =
+ this.currentActivityView !== activityBarViews.commit && this.lastCommitMsg === '';
+ },
+ },
+ methods: {
+ ...mapActions(['updateActivityBarView']),
+ ...mapActions('commit', ['updateCommitMessage', 'discardDraft', 'commitChanges']),
+ toggleIsSmall() {
+ this.updateActivityBarView(activityBarViews.commit)
+ .then(() => {
+ this.isCompact = !this.isCompact;
+ })
+ .catch(e => {
+ throw e;
+ });
+ },
+ beforeEnterTransition() {
+ const elHeight = this.isCompact
+ ? this.$refs.formEl && this.$refs.formEl.offsetHeight
+ : this.$refs.compactEl && this.$refs.compactEl.offsetHeight;
+
+ this.componentHeight = elHeight + COMMIT_ITEM_PADDING;
+ },
+ enterTransition() {
+ this.$nextTick(() => {
+ const elHeight = this.isCompact
+ ? this.$refs.compactEl && this.$refs.compactEl.offsetHeight
+ : this.$refs.formEl && this.$refs.formEl.offsetHeight;
+
+ this.componentHeight = elHeight + COMMIT_ITEM_PADDING;
+ });
+ },
+ afterEndTransition() {
+ this.componentHeight = null;
+ },
+ },
+ activityBarViews,
+};
+</script>
+
+<template>
+ <div
+ class="multi-file-commit-form"
+ :class="{
+ 'is-compact': isCompact,
+ 'is-full': !isCompact
+ }"
+ :style="{
+ height: componentHeight ? `${componentHeight}px` : null,
+ }"
+ >
+ <transition
+ name="commit-form-slide-up"
+ @before-enter="beforeEnterTransition"
+ @enter="enterTransition"
+ @after-enter="afterEndTransition"
+ >
+ <div
+ v-if="isCompact"
+ class="commit-form-compact"
+ ref="compactEl"
+ >
+ <button
+ type="button"
+ :disabled="!hasChanges"
+ class="btn btn-primary btn-sm btn-block"
+ @click="toggleIsSmall"
+ >
+ {{ __('Commit') }}
+ </button>
+ <p
+ class="text-center"
+ v-html="overviewText"
+ ></p>
+ </div>
+ <form
+ v-if="!isCompact"
+ class="form-horizontal"
+ @submit.prevent.stop="commitChanges"
+ ref="formEl"
+ >
+ <transition name="fade">
+ <success-message
+ v-show="lastCommitMsg"
+ />
+ </transition>
+ <commit-message-field
+ :text="commitMessage"
+ @input="updateCommitMessage"
+ />
+ <div class="clearfix prepend-top-15">
+ <actions />
+ <loading-button
+ :loading="submitCommitLoading"
+ :disabled="commitButtonDisabled"
+ container-class="btn btn-success btn-sm pull-left"
+ :label="__('Commit')"
+ @click="commitChanges"
+ />
+ <button
+ v-if="!discardDraftButtonDisabled"
+ type="button"
+ class="btn btn-default btn-sm pull-right"
+ @click="discardDraft"
+ >
+ {{ __('Discard draft') }}
+ </button>
+ <button
+ v-else
+ type="button"
+ class="btn btn-default btn-sm pull-right"
+ @click="toggleIsSmall"
+ >
+ {{ __('Collapse') }}
+ </button>
+ </div>
+ </form>
+ </transition>
+ </div>
+</template>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list.vue b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
index e0de30d935b..f6625fda596 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
@@ -44,6 +44,11 @@ export default {
default: false,
},
},
+ data() {
+ return {
+ showActionButton: false,
+ };
+ },
computed: {
titleText() {
return sprintf(__('%{title} changes'), {
@@ -56,6 +61,9 @@ export default {
actionBtnClicked() {
this[this.action]();
},
+ setShowActionButton(show) {
+ this.showActionButton = show;
+ },
},
};
</script>
@@ -76,7 +84,16 @@ export default {
:size="18"
/>
{{ titleText }}
+ <span
+ v-show="!showActionButton"
+ @mouseenter="setShowActionButton(true)"
+ class="ide-commit-file-count"
+ >
+ {{ fileList.length }}
+ </span>
<button
+ v-show="showActionButton"
+ @mouseleave="setShowActionButton(false)"
type="button"
class="btn btn-blank btn-link ide-staged-action-btn"
@click="actionBtnClicked"
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
index b660a2961cb..00f2312ae51 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
@@ -1,5 +1,6 @@
<script>
import { mapActions, mapState, mapGetters } from 'vuex';
+import { __ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
@@ -26,10 +27,20 @@ export default {
required: false,
default: false,
},
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
...mapState('commit', ['commitAction']),
...mapGetters('commit', ['newBranchName']),
+ tooltipTitle() {
+ return this.disabled
+ ? __('This option is disabled while you still have unstaged changes')
+ : '';
+ },
},
methods: {
...mapActions('commit', ['updateCommitAction', 'updateBranchName']),
@@ -39,19 +50,28 @@ export default {
<template>
<fieldset>
- <label>
+ <label
+ v-tooltip
+ :title="tooltipTitle"
+ :class="{
+ 'is-disabled': disabled
+ }"
+ >
<input
type="radio"
name="commit-action"
:value="value"
@change="updateCommitAction($event.target.value)"
- :checked="checked"
- v-once
+ :checked="commitAction === value"
+ :disabled="disabled"
/>
<span class="prepend-left-10">
- <template v-if="label">
+ <span
+ v-if="label"
+ class="ide-radio-label"
+ >
{{ label }}
- </template>
+ </span>
<slot v-else></slot>
</span>
</label>
diff --git a/app/assets/javascripts/ide/components/ide_side_bar.vue b/app/assets/javascripts/ide/components/ide_side_bar.vue
index 2872d4e8687..3f980203911 100644
--- a/app/assets/javascripts/ide/components/ide_side_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_side_bar.vue
@@ -10,7 +10,10 @@ import IdeTree from './ide_tree.vue';
import ResizablePanel from './resizable_panel.vue';
import ActivityBar from './activity_bar.vue';
import CommitSection from './repo_commit_section.vue';
+import CommitForm from './commit_sidebar/form.vue';
import IdeReview from './ide_review.vue';
+import SuccessMessage from './commit_sidebar/success_message.vue';
+import { activityBarViews } from '../constants';
export default {
directives: {
@@ -26,7 +29,9 @@ export default {
Identicon,
CommitSection,
IdeTree,
+ CommitForm,
IdeReview,
+ SuccessMessage,
},
data() {
return {
@@ -34,8 +39,21 @@ export default {
};
},
computed: {
- ...mapState(['loading', 'currentBranchId', 'currentActivityView']),
- ...mapGetters(['currentProject']),
+ ...mapState([
+ 'loading',
+ 'currentBranchId',
+ 'currentActivityView',
+ 'changedFiles',
+ 'stagedFiles',
+ 'lastCommitMsg',
+ ]),
+ ...mapGetters(['currentProject', 'someUncommitedChanges']),
+ showSuccessMessage() {
+ return (
+ this.currentActivityView === activityBarViews.edit &&
+ (this.lastCommitMsg && !this.someUncommitedChanges)
+ );
+ },
branchTooltipTitle() {
return this.showTooltip ? this.currentBranchId : undefined;
},
@@ -115,6 +133,7 @@ export default {
:is="currentActivityView"
/>
</div>
+ <commit-form />
</template>
</div>
</resizable-panel>
diff --git a/app/assets/javascripts/ide/components/ide_tree.vue b/app/assets/javascripts/ide/components/ide_tree.vue
index 569d55d28ac..8fc4ebe6ca6 100644
--- a/app/assets/javascripts/ide/components/ide_tree.vue
+++ b/app/assets/javascripts/ide/components/ide_tree.vue
@@ -1,5 +1,5 @@
<script>
-import { mapState, mapGetters } from 'vuex';
+import { mapState, mapGetters, mapActions } from 'vuex';
import NewDropdown from './new_dropdown/index.vue';
import IdeTreeList from './ide_tree_list.vue';
@@ -10,7 +10,17 @@ export default {
},
computed: {
...mapState(['currentBranchId']),
- ...mapGetters(['currentProject']),
+ ...mapGetters(['currentProject', 'currentTree', 'activeFile']),
+ },
+ mounted() {
+ if (this.activeFile && this.activeFile.pending) {
+ this.$router.push(`/project${this.activeFile.url}`, () => {
+ this.updateViewer('editor');
+ });
+ }
+ },
+ methods: {
+ ...mapActions(['updateViewer']),
},
};
</script>
diff --git a/app/assets/javascripts/ide/components/repo_commit_section.vue b/app/assets/javascripts/ide/components/repo_commit_section.vue
index 4c0dab70ab0..c5092d8e04d 100644
--- a/app/assets/javascripts/ide/components/repo_commit_section.vue
+++ b/app/assets/javascripts/ide/components/repo_commit_section.vue
@@ -3,13 +3,10 @@ import { mapState, mapActions, mapGetters } from 'vuex';
import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
-import LoadingButton from '~/vue_shared/components/loading_button.vue';
import CommitFilesList from './commit_sidebar/list.vue';
import EmptyState from './commit_sidebar/empty_state.vue';
-import CommitMessageField from './commit_sidebar/message_field.vue';
-import SuccessMessage from './commit_sidebar/success_message.vue';
import * as consts from '../stores/modules/commit/constants';
-import Actions from './commit_sidebar/actions.vue';
+import { activityBarViews } from '../constants';
export default {
components: {
@@ -17,21 +14,11 @@ export default {
Icon,
CommitFilesList,
EmptyState,
- SuccessMessage,
- Actions,
- LoadingButton,
- CommitMessageField,
},
directives: {
tooltip,
},
computed: {
- showStageUnstageArea() {
- return !!(this.someUncommitedChanges || this.lastCommitMsg || !this.unusedSeal);
- },
- someUncommitedChanges() {
- return !!(this.changedFiles.length || this.stagedFiles.length);
- },
...mapState([
'changedFiles',
'stagedFiles',
@@ -40,15 +27,37 @@ export default {
'unusedSeal',
]),
...mapState('commit', ['commitMessage', 'submitCommitLoading']),
+ ...mapGetters(['lastOpenedFile', 'hasChanges', 'someUncommitedChanges']),
...mapGetters('commit', ['commitButtonDisabled', 'discardDraftButtonDisabled']),
+ showStageUnstageArea() {
+ return !!(this.someUncommitedChanges || this.lastCommitMsg || !this.unusedSeal);
+ },
+ },
+ watch: {
+ hasChanges() {
+ if (!this.hasChanges) {
+ this.updateActivityBarView(activityBarViews.edit);
+ }
+ },
+ },
+ mounted() {
+ if (this.lastOpenedFile) {
+ this.openPendingTab({
+ file: this.lastOpenedFile,
+ })
+ .then(changeViewer => {
+ if (changeViewer) {
+ this.updateViewer('diff');
+ }
+ })
+ .catch(e => {
+ throw e;
+ });
+ }
},
methods: {
- ...mapActions('commit', [
- 'updateCommitMessage',
- 'discardDraft',
- 'commitChanges',
- 'updateCommitAction',
- ]),
+ ...mapActions(['openPendingTab', 'updateViewer', 'updateActivityBarView']),
+ ...mapActions('commit', ['commitChanges', 'updateCommitAction']),
forceCreateNewBranch() {
return this.updateCommitAction(consts.COMMIT_TO_NEW_BRANCH).then(() => this.commitChanges());
},
@@ -76,6 +85,7 @@ export default {
v-if="showStageUnstageArea"
>
<commit-files-list
+ class="is-first"
icon-name="unstaged"
:title="__('Unstaged')"
:file-list="changedFiles"
@@ -96,39 +106,5 @@ export default {
<empty-state
v-if="unusedSeal"
/>
- <div
- class="multi-file-commit-panel-bottom"
- >
- <form
- class="form-horizontal multi-file-commit-form"
- @submit.prevent.stop="commitChanges"
- >
- <success-message
- v-if="lastCommitMsg && !someUncommitedChanges"
- />
- <commit-message-field
- :text="commitMessage"
- @input="updateCommitMessage"
- />
- <div class="clearfix prepend-top-15">
- <actions />
- <loading-button
- :loading="submitCommitLoading"
- :disabled="commitButtonDisabled"
- container-class="btn btn-success btn-sm pull-left"
- :label="__('Commit')"
- @click="commitChanges"
- />
- <button
- v-if="!discardDraftButtonDisabled"
- type="button"
- class="btn btn-default btn-sm pull-right"
- @click="discardDraft"
- >
- {{ __('Discard draft') }}
- </button>
- </div>
- </form>
- </div>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/repo_tab.vue b/app/assets/javascripts/ide/components/repo_tab.vue
index b3221deada0..fb26b973236 100644
--- a/app/assets/javascripts/ide/components/repo_tab.vue
+++ b/app/assets/javascripts/ide/components/repo_tab.vue
@@ -32,6 +32,8 @@ export default {
return `Close ${this.tab.name}`;
},
showChangedIcon() {
+ if (this.tab.pending) return true;
+
return this.fileHasChanged ? !this.tabMouseOver : false;
},
fileHasChanged() {
@@ -91,6 +93,7 @@ export default {
class="multi-file-tab-close"
@click.stop.prevent="closeFile(tab)"
:aria-label="closeLabel"
+ :disabled="tab.pending"
>
<icon
v-if="!showChangedIcon"
diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js
index 86c5f0c4421..48d4cc43198 100644
--- a/app/assets/javascripts/ide/constants.js
+++ b/app/assets/javascripts/ide/constants.js
@@ -3,6 +3,10 @@ export const MAX_FILE_FINDER_RESULTS = 40;
export const FILE_FINDER_ROW_HEIGHT = 55;
export const FILE_FINDER_EMPTY_ROW_HEIGHT = 33;
+export const MAX_WINDOW_HEIGHT_COMPACT = 750;
+
+export const COMMIT_ITEM_PADDING = 32;
+
// Commit message textarea
export const MAX_TITLE_LENGTH = 50;
export const MAX_BODY_LENGTH = 72;
diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js
index 8076de1b7e3..fc163cd021a 100644
--- a/app/assets/javascripts/ide/stores/actions/file.js
+++ b/app/assets/javascripts/ide/stores/actions/file.js
@@ -195,13 +195,7 @@ export const unstageChange = ({ commit }, path) => {
};
export const openPendingTab = ({ commit, getters, dispatch, state }, { file, keyPrefix }) => {
- if (
- getters.activeFile &&
- getters.activeFile.path === file.path &&
- state.viewer === viewerTypes.diff
- ) {
- return false;
- }
+ state.openFiles.forEach(f => eventHub.$emit(`editor.update.model.dispose.${f.key}`));
commit(types.ADD_PENDING_TAB, { file, keyPrefix });
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
index e1ee8047e13..75286ed0cd2 100644
--- a/app/assets/javascripts/ide/stores/getters.js
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -56,10 +56,16 @@ export const allBlobs = state =>
export const getChangedFile = state => path => state.changedFiles.find(f => f.path === path);
export const getStagedFile = state => path => state.stagedFiles.find(f => f.path === path);
+export const lastOpenedFile = state =>
+ [...state.changedFiles, ...state.stagedFiles].sort((a, b) => b.lastOpenedAt - a.lastOpenedAt)[0];
+
export const isEditModeActive = state => state.currentActivityView === activityBarViews.edit;
export const isCommitModeActive = state => state.currentActivityView === activityBarViews.commit;
export const isReviewModeActive = state => state.currentActivityView === activityBarViews.review;
+export const someUncommitedChanges = state =>
+ !!(state.changedFiles.length || state.stagedFiles.length);
+
export const getChangesInFolder = state => path => {
const changedFilesCount = state.changedFiles.filter(f => filePathMatches(f, path)).length;
const stagedFilesCount = state.stagedFiles.filter(
diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js
index 4fbc97d053e..ab00d12089d 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js
@@ -8,6 +8,7 @@ import router from '../../../ide_router';
import service from '../../../services';
import * as types from './mutation_types';
import * as consts from './constants';
+import { activityBarViews } from '../../../constants';
import eventHub from '../../../eventhub';
export const updateCommitMessage = ({ commit }, message) => {
@@ -75,7 +76,7 @@ export const checkCommitStatus = ({ rootState }) =>
export const updateFilesAfterCommit = (
{ commit, dispatch, state, rootState, rootGetters },
- { data, branch },
+ { data },
) => {
const selectedProject = rootState.projects[rootState.currentProjectId];
const lastCommit = {
@@ -126,15 +127,9 @@ export const updateFilesAfterCommit = (
changed: !!changedFile,
});
});
-
- if (state.commitAction === consts.COMMIT_TO_NEW_BRANCH && rootGetters.activeFile) {
- router.push(
- `/project/${rootState.currentProjectId}/blob/${branch}/${rootGetters.activeFile.path}`,
- );
- }
};
-export const commitChanges = ({ commit, state, getters, dispatch, rootState }) => {
+export const commitChanges = ({ commit, state, getters, dispatch, rootState, rootGetters }) => {
const newBranch = state.commitAction !== consts.COMMIT_TO_CURRENT_BRANCH;
const payload = createCommitPayload(getters.branchName, newBranch, state, rootState);
const getCommitStatus = newBranch ? Promise.resolve(false) : dispatch('checkCommitStatus');
@@ -187,6 +182,34 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState }) =
commit(rootTypes.SET_LAST_COMMIT_MSG, '', { root: true });
}, 5000);
})
+ .then(() => {
+ if (rootGetters.lastOpenedFile) {
+ dispatch(
+ 'openPendingTab',
+ {
+ file: rootGetters.lastOpenedFile,
+ },
+ { root: true },
+ )
+ .then(changeViewer => {
+ if (changeViewer) {
+ dispatch('updateViewer', 'diff', { root: true });
+ }
+ })
+ .catch(e => {
+ throw e;
+ });
+ } else {
+ dispatch('updateActivityBarView', activityBarViews.edit, { root: true });
+ dispatch('updateViewer', 'editor', { root: true });
+
+ router.push(
+ `/project/${rootState.currentProjectId}/blob/${getters.branchName}/${
+ rootGetters.activeFile.path
+ }`,
+ );
+ }
+ })
.then(() => dispatch('updateCommitAction', consts.COMMIT_TO_CURRENT_BRANCH));
})
.catch(err => {
diff --git a/app/assets/javascripts/ide/stores/mutations/file.js b/app/assets/javascripts/ide/stores/mutations/file.js
index 7f670eb744c..13f123b6630 100644
--- a/app/assets/javascripts/ide/stores/mutations/file.js
+++ b/app/assets/javascripts/ide/stores/mutations/file.js
@@ -1,3 +1,4 @@
+/* eslint-disable no-param-reassign */
import * as types from '../mutation_types';
export default {
@@ -169,36 +170,24 @@ export default {
});
},
[types.ADD_PENDING_TAB](state, { file, keyPrefix = 'pending' }) {
- const key = `${keyPrefix}-${file.key}`;
- const pendingTab = state.openFiles.find(f => f.key === key && f.pending);
- let openFiles = state.openFiles.map(f => Object.assign(f, { active: false, opened: false }));
-
- if (!pendingTab) {
- const openFile = openFiles.find(f => f.path === file.path);
-
- openFiles = openFiles.concat(openFile ? null : file).reduce((acc, f) => {
- if (!f) return acc;
-
- if (f.path === file.path) {
- return acc.concat({
- ...f,
- content: file.content,
- active: true,
- pending: true,
- opened: true,
- key,
- });
- }
-
- return acc.concat(f);
- }, []);
- } else {
- openFiles = state.openFiles.map(f =>
- Object.assign(f, { active: f.key === key, opened: f.key === key }),
- );
- }
-
- Object.assign(state, { openFiles });
+ state.entries[file.path].opened = false;
+ state.entries[file.path].active = false;
+ state.entries[file.path].lastOpenedAt = new Date().getTime();
+ state.openFiles.forEach(f =>
+ Object.assign(f, {
+ opened: false,
+ active: false,
+ }),
+ );
+ state.openFiles = [
+ {
+ ...file,
+ key: `${keyPrefix}-${file.key}`,
+ pending: true,
+ opened: true,
+ active: true,
+ },
+ ];
},
[types.REMOVE_PENDING_TAB](state, file) {
Object.assign(state, {
diff --git a/app/assets/stylesheets/pages/repo.scss b/app/assets/stylesheets/pages/repo.scss
index d3330cda8c6..c03446d1e40 100644
--- a/app/assets/stylesheets/pages/repo.scss
+++ b/app/assets/stylesheets/pages/repo.scss
@@ -192,11 +192,11 @@
right: 3px;
}
- &:hover {
+ &:not([disabled]):hover {
background-color: $theme-gray-200;
}
- &:focus {
+ &:not([disabled]):focus {
background-color: $blue-500;
color: $white-light;
outline: 0;
@@ -443,6 +443,7 @@
}
.multi-file-commit-panel-inner {
+ position: relative;
display: flex;
flex-direction: column;
height: 100%;
@@ -484,14 +485,13 @@
align-items: center;
margin-bottom: 0;
border-bottom: 1px solid $white-dark;
- padding: $gl-btn-padding 0;
- min-height: 56px;
+ padding: $gl-btn-padding $gl-padding;
}
.multi-file-commit-panel-header-title {
display: flex;
flex: 1;
- padding-left: $grid-size;
+ align-items: center;
svg {
margin-right: $gl-btn-padding;
@@ -507,7 +507,7 @@
.multi-file-commit-list {
flex: 1;
overflow: auto;
- padding: $gl-padding 0;
+ padding: $gl-padding;
min-height: 60px;
}
@@ -602,30 +602,24 @@
}
.multi-file-commit-form {
+ position: relative;
padding: $gl-padding;
+ background-color: $white-light;
border-top: 1px solid $white-dark;
+ border-left: 1px solid $white-dark;
+ transition: all 0.3s ease;
.btn {
font-size: $gl-font-size;
}
+
+ .multi-file-commit-panel-success-message {
+ top: 0;
+ }
}
.multi-file-commit-panel-bottom {
position: relative;
-
- .multi-file-commit-panel-success-message {
- position: absolute;
- top: 1px;
- left: 3px;
- bottom: 0;
- right: 0;
- z-index: 10;
- background: $gray-light;
- overflow: auto;
- display: flex;
- flex-direction: column;
- justify-content: center;
- }
}
.dirty-diff {
@@ -779,17 +773,36 @@
flex-direction: column;
width: 100%;
min-height: 140px;
- padding: 0 16px;
+
+ &.is-first {
+ border-bottom: 1px solid $white-dark;
+ }
}
.ide-staged-action-btn {
margin-left: auto;
- color: $gl-link-color;
+ line-height: 22px;
+}
+
+.ide-commit-file-count {
+ min-width: 22px;
+ margin-left: auto;
+ background-color: $gray-light;
+ border-radius: $border-radius-default;
+ border: 1px solid $white-dark;
+ line-height: 20px;
+ text-align: center;
}
.ide-commit-radios {
label {
font-weight: normal;
+
+ &.is-disabled {
+ .ide-radio-label {
+ text-decoration: line-through;
+ }
+ }
}
.help-block {
@@ -853,6 +866,7 @@
.ide-activity-bar {
position: relative;
flex: 0 0 60px;
+ z-index: 1;
}
.ide-file-finder-overlay {
@@ -969,6 +983,40 @@
}
}
+.commit-form-compact {
+ .btn {
+ margin-bottom: 8px;
+ }
+
+ p {
+ margin-bottom: 0;
+ }
+}
+
+.commit-form-slide-up-enter-active,
+.commit-form-slide-up-leave-active {
+ position: absolute;
+ top: 16px;
+ left: 16px;
+ right: 16px;
+ transition: all 0.3s ease;
+}
+
+.is-full .commit-form-slide-up-enter,
+.is-compact .commit-form-slide-up-leave-to {
+ transform: translateY(100%);
+}
+
+.is-full .commit-form-slide-up-enter-to,
+.is-compact .commit-form-slide-up-leave {
+ transform: translateY(0);
+}
+
+.commit-form-slide-up-enter,
+.commit-form-slide-up-leave-to {
+ opacity: 0;
+}
+
.ide-review-header {
flex-direction: column;
align-items: flex-start;
@@ -996,6 +1044,20 @@
line-height: 34px;
}
+.multi-file-commit-panel-success-message {
+ position: absolute;
+ top: 61px;
+ left: 1px;
+ bottom: 0;
+ right: 0;
+ z-index: 10;
+ background: $white-light;
+ overflow: auto;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
+
.ide-review-button-holder {
display: flex;
width: 100%;
diff --git a/spec/features/projects/tree/create_directory_spec.rb b/spec/features/projects/tree/create_directory_spec.rb
index 43581c5cdca..3017048e506 100644
--- a/spec/features/projects/tree/create_directory_spec.rb
+++ b/spec/features/projects/tree/create_directory_spec.rb
@@ -46,7 +46,8 @@ feature 'Multi-file editor new directory', :js do
find('.js-ide-commit-mode').click
- click_button 'Stage all'
+ find('.multi-file-commit-list-item').hover
+ first('.multi-file-discard-btn .btn').click
fill_in('commit-message', with: 'commit message ide')
diff --git a/spec/features/projects/tree/create_file_spec.rb b/spec/features/projects/tree/create_file_spec.rb
index 3d938df2ca5..56471c8e7aa 100644
--- a/spec/features/projects/tree/create_file_spec.rb
+++ b/spec/features/projects/tree/create_file_spec.rb
@@ -36,7 +36,8 @@ feature 'Multi-file editor new file', :js do
find('.js-ide-commit-mode').click
- click_button 'Stage all'
+ find('.multi-file-commit-list-item').hover
+ first('.multi-file-discard-btn .btn').click
fill_in('commit-message', with: 'commit message ide')
diff --git a/spec/javascripts/ide/components/commit_sidebar/form_spec.js b/spec/javascripts/ide/components/commit_sidebar/form_spec.js
new file mode 100644
index 00000000000..ce7c134bc97
--- /dev/null
+++ b/spec/javascripts/ide/components/commit_sidebar/form_spec.js
@@ -0,0 +1,146 @@
+import Vue from 'vue';
+import store from '~/ide/stores';
+import CommitForm from '~/ide/components/commit_sidebar/form.vue';
+import { activityBarViews } from '~/ide/constants';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
+import { resetStore } from '../../helpers';
+
+describe('IDE commit form', () => {
+ const Component = Vue.extend(CommitForm);
+ let vm;
+
+ beforeEach(() => {
+ spyOnProperty(window, 'innerHeight').and.returnValue(800);
+
+ store.state.changedFiles.push('test');
+
+ vm = createComponentWithStore(Component, store).$mount();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+
+ resetStore(vm.$store);
+ });
+
+ it('enables button when has changes', () => {
+ expect(vm.$el.querySelector('[disabled]')).toBe(null);
+ });
+
+ describe('compact', () => {
+ it('renders commit button in compact mode', () => {
+ expect(vm.$el.querySelector('.btn-primary')).not.toBeNull();
+ expect(vm.$el.querySelector('.btn-primary').textContent).toContain('Commit');
+ });
+
+ it('does not render form', () => {
+ expect(vm.$el.querySelector('form')).toBeNull();
+ });
+
+ it('renders overview text', done => {
+ vm.$store.state.stagedFiles.push('test');
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('p').textContent).toContain('1 unstaged and 1 staged changes');
+ done();
+ });
+ });
+
+ it('shows form when clicking commit button', done => {
+ vm.$el.querySelector('.btn-primary').click();
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('form')).not.toBeNull();
+
+ done();
+ });
+ });
+
+ it('toggles activity bar vie when clicking commit button', done => {
+ vm.$el.querySelector('.btn-primary').click();
+
+ vm.$nextTick(() => {
+ expect(store.state.currentActivityView).toBe(activityBarViews.commit);
+
+ done();
+ });
+ });
+ });
+
+ describe('full', () => {
+ beforeEach(done => {
+ vm.isCompact = false;
+
+ vm.$nextTick(done);
+ });
+
+ it('updates commitMessage in store on input', done => {
+ const textarea = vm.$el.querySelector('textarea');
+
+ textarea.value = 'testing commit message';
+
+ textarea.dispatchEvent(new Event('input'));
+
+ getSetTimeoutPromise()
+ .then(() => {
+ expect(vm.$store.state.commit.commitMessage).toBe('testing commit message');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('updating currentActivityView not to commit view sets compact mode', done => {
+ store.state.currentActivityView = 'a';
+
+ vm.$nextTick(() => {
+ expect(vm.isCompact).toBe(true);
+
+ done();
+ });
+ });
+
+ describe('discard draft button', () => {
+ it('hidden when commitMessage is empty', () => {
+ expect(vm.$el.querySelector('.btn-default').textContent).toContain('Collapse');
+ });
+
+ it('resets commitMessage when clicking discard button', done => {
+ vm.$store.state.commit.commitMessage = 'testing commit message';
+
+ getSetTimeoutPromise()
+ .then(() => {
+ vm.$el.querySelector('.btn-default').click();
+ })
+ .then(Vue.nextTick)
+ .then(() => {
+ expect(vm.$store.state.commit.commitMessage).not.toBe('testing commit message');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('when submitting', () => {
+ beforeEach(() => {
+ spyOn(vm, 'commitChanges');
+ vm.$store.state.stagedFiles.push('test');
+ });
+
+ it('calls commitChanges', done => {
+ vm.$store.state.commit.commitMessage = 'testing commit message';
+
+ getSetTimeoutPromise()
+ .then(() => {
+ vm.$el.querySelector('.btn-success').click();
+ })
+ .then(Vue.nextTick)
+ .then(() => {
+ expect(vm.commitChanges).toHaveBeenCalled();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/ide/components/commit_sidebar/list_spec.js b/spec/javascripts/ide/components/commit_sidebar/list_spec.js
index 412c272c8cc..54625ef90f8 100644
--- a/spec/javascripts/ide/components/commit_sidebar/list_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/list_spec.js
@@ -49,16 +49,4 @@ describe('Multi-file editor commit sidebar list', () => {
expect(vm.$el.textContent).toContain('No changes');
});
});
-
- describe('action button', () => {
- beforeEach(() => {
- spyOn(vm, 'stageAllChanges');
- });
-
- it('calls store action when clicked', () => {
- vm.$el.querySelector('.ide-staged-action-btn').click();
-
- expect(vm.stageAllChanges).toHaveBeenCalled();
- });
- });
});
diff --git a/spec/javascripts/ide/components/repo_commit_section_spec.js b/spec/javascripts/ide/components/repo_commit_section_spec.js
index c2b2761cf61..5e3e00a180b 100644
--- a/spec/javascripts/ide/components/repo_commit_section_spec.js
+++ b/spec/javascripts/ide/components/repo_commit_section_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import store from '~/ide/stores';
import service from '~/ide/services';
+import router from '~/ide/ide_router';
import repoCommitSection from '~/ide/components/repo_commit_section.vue';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
-import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
import { file, resetStore } from '../helpers';
describe('RepoCommitSection', () => {
@@ -60,6 +60,8 @@ describe('RepoCommitSection', () => {
}
beforeEach(done => {
+ spyOn(router, 'push');
+
vm = createComponent();
spyOn(service, 'getTreeData').and.returnValue(
@@ -105,30 +107,28 @@ describe('RepoCommitSection', () => {
it('renders a commit section', () => {
const changedFileElements = [...vm.$el.querySelectorAll('.multi-file-commit-list li')];
- const submitCommit = vm.$el.querySelector('form .btn');
const allFiles = vm.$store.state.changedFiles.concat(vm.$store.state.stagedFiles);
- expect(vm.$el.querySelector('.multi-file-commit-form')).not.toBeNull();
expect(changedFileElements.length).toEqual(4);
changedFileElements.forEach((changedFile, i) => {
expect(changedFile.textContent.trim()).toContain(allFiles[i].path);
});
-
- expect(submitCommit.disabled).toBeTruthy();
- expect(submitCommit.querySelector('.fa-spinner.fa-spin')).toBeNull();
});
it('adds changed files into staged files', done => {
- vm.$el.querySelector('.ide-staged-action-btn').click();
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.ide-commit-list-container').textContent).toContain(
- 'No changes',
- );
-
- done();
- });
+ vm.$el.querySelector('.multi-file-discard-btn .btn').click();
+ vm
+ .$nextTick()
+ .then(() => vm.$el.querySelector('.multi-file-discard-btn .btn').click())
+ .then(vm.$nextTick)
+ .then(() => {
+ expect(vm.$el.querySelector('.ide-commit-list-container').textContent).toContain(
+ 'No changes',
+ );
+ })
+ .then(done)
+ .catch(done.fail);
});
it('stages a single file', done => {
@@ -156,18 +156,6 @@ describe('RepoCommitSection', () => {
});
});
- it('removes all staged files', done => {
- vm.$el.querySelectorAll('.ide-staged-action-btn')[1].click();
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelectorAll('.ide-commit-list-container')[1].textContent).toContain(
- 'No changes',
- );
-
- done();
- });
- });
-
it('unstages a single file', done => {
vm.$el
.querySelectorAll('.multi-file-discard-btn')[2]
@@ -183,60 +171,10 @@ describe('RepoCommitSection', () => {
});
});
- it('updates commitMessage in store on input', done => {
- const textarea = vm.$el.querySelector('textarea');
-
- textarea.value = 'testing commit message';
-
- textarea.dispatchEvent(new Event('input'));
-
- getSetTimeoutPromise()
- .then(() => {
- expect(vm.$store.state.commit.commitMessage).toBe('testing commit message');
- })
- .then(done)
- .catch(done.fail);
- });
-
- describe('discard draft button', () => {
- it('hidden when commitMessage is empty', () => {
- expect(vm.$el.querySelector('.multi-file-commit-form .btn-default')).toBeNull();
- });
-
- it('resets commitMessage when clicking discard button', done => {
- vm.$store.state.commit.commitMessage = 'testing commit message';
-
- getSetTimeoutPromise()
- .then(() => {
- vm.$el.querySelector('.multi-file-commit-form .btn-default').click();
- })
- .then(Vue.nextTick)
- .then(() => {
- expect(vm.$store.state.commit.commitMessage).not.toBe('testing commit message');
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('when submitting', () => {
- beforeEach(() => {
- spyOn(vm, 'commitChanges');
- });
-
- it('calls commitChanges', done => {
- vm.$store.state.commit.commitMessage = 'testing commit message';
-
- getSetTimeoutPromise()
- .then(() => {
- vm.$el.querySelector('.multi-file-commit-form .btn-success').click();
- })
- .then(Vue.nextTick)
- .then(() => {
- expect(vm.commitChanges).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
+ describe('mounted', () => {
+ it('opens last opened file', () => {
+ expect(store.state.openFiles.length).toBe(1);
+ expect(store.state.openFiles[0].pending).toBe(true);
});
});
});
diff --git a/spec/javascripts/ide/stores/actions/file_spec.js b/spec/javascripts/ide/stores/actions/file_spec.js
index 3ee11bd2f03..3de48cd0d2d 100644
--- a/spec/javascripts/ide/stores/actions/file_spec.js
+++ b/spec/javascripts/ide/stores/actions/file_spec.js
@@ -589,20 +589,6 @@ describe('IDE store file actions', () => {
.then(done)
.catch(done.fail);
});
-
- it('returns false when passed in file is active & viewer is diff', done => {
- f.active = true;
- store.state.openFiles.push(f);
- store.state.viewer = 'diff';
-
- store
- .dispatch('openPendingTab', { file: f, keyPrefix: 'pending' })
- .then(added => {
- expect(added).toBe(false);
- })
- .then(done)
- .catch(done.fail);
- });
});
describe('removePendingTab', () => {
diff --git a/spec/javascripts/ide/stores/modules/commit/actions_spec.js b/spec/javascripts/ide/stores/modules/commit/actions_spec.js
index b2b4b85ca42..a2869ff378b 100644
--- a/spec/javascripts/ide/stores/modules/commit/actions_spec.js
+++ b/spec/javascripts/ide/stores/modules/commit/actions_spec.js
@@ -289,21 +289,6 @@ describe('IDE commit module actions', () => {
.then(done)
.catch(done.fail);
});
-
- it('pushes route to new branch if commitAction is new branch', done => {
- store.state.commit.commitAction = consts.COMMIT_TO_NEW_BRANCH;
-
- store
- .dispatch('commit/updateFilesAfterCommit', {
- data,
- branch,
- })
- .then(() => {
- expect(router.push).toHaveBeenCalledWith(`/project/abcproject/blob/master/${f.path}`);
- })
- .then(done)
- .catch(done.fail);
- });
});
describe('commitChanges', () => {
@@ -391,21 +376,6 @@ describe('IDE commit module actions', () => {
.catch(done.fail);
});
- it('pushes router to new route', done => {
- store
- .dispatch('commit/commitChanges')
- .then(() => {
- expect(router.push).toHaveBeenCalledWith(
- `/project/${store.state.currentProjectId}/blob/${
- store.getters['commit/newBranchName']
- }/changed`,
- );
-
- done();
- })
- .catch(done.fail);
- });
-
it('sets last Commit Msg', done => {
store
.dispatch('commit/commitChanges')
diff --git a/spec/javascripts/ide/stores/mutations/file_spec.js b/spec/javascripts/ide/stores/mutations/file_spec.js
index 6fba934810d..e83961fcedc 100644
--- a/spec/javascripts/ide/stores/mutations/file_spec.js
+++ b/spec/javascripts/ide/stores/mutations/file_spec.js
@@ -267,41 +267,23 @@ describe('IDE store file mutations', () => {
it('adds file into openFiles as pending', () => {
mutations.ADD_PENDING_TAB(localState, { file: localFile });
- expect(localState.openFiles.length).toBe(2);
- expect(localState.openFiles[1].pending).toBe(true);
- expect(localState.openFiles[1].key).toBe(`pending-${localFile.key}`);
- });
-
- it('updates open file to pending', () => {
- mutations.ADD_PENDING_TAB(localState, { file: localState.openFiles[0] });
-
expect(localState.openFiles.length).toBe(1);
+ expect(localState.openFiles[0].pending).toBe(true);
+ expect(localState.openFiles[0].key).toBe(`pending-${localFile.key}`);
});
- it('updates pending open file to active', () => {
- localState.openFiles.push({
- ...localFile,
- pending: true,
- });
+ it('only allows 1 open pending file', () => {
+ const newFile = file('test');
+ localState.entries[newFile.path] = newFile;
mutations.ADD_PENDING_TAB(localState, { file: localFile });
- expect(localState.openFiles[1].pending).toBe(true);
- expect(localState.openFiles[1].active).toBe(true);
- });
-
- it('sets all openFiles to not active', () => {
- mutations.ADD_PENDING_TAB(localState, { file: localFile });
+ expect(localState.openFiles.length).toBe(1);
- expect(localState.openFiles.length).toBe(2);
+ mutations.ADD_PENDING_TAB(localState, { file: file('test') });
- localState.openFiles.forEach(f => {
- if (f.pending) {
- expect(f.active).toBe(true);
- } else {
- expect(f.active).toBe(false);
- }
- });
+ expect(localState.openFiles.length).toBe(1);
+ expect(localState.openFiles[0].name).toBe('test');
});
});