Merge branch 'master' into ph-multi-file-editor-new-file-folder-dropdown
This commit is contained in:
commit
c147bccc45
17 changed files with 520 additions and 12 deletions
|
@ -1280,10 +1280,12 @@ export default class Notes {
|
||||||
* Get data from Form attributes to use for saving/submitting comment.
|
* Get data from Form attributes to use for saving/submitting comment.
|
||||||
*/
|
*/
|
||||||
getFormData($form) {
|
getFormData($form) {
|
||||||
|
const content = $form.find('.js-note-text').val();
|
||||||
return {
|
return {
|
||||||
formData: $form.serialize(),
|
formData: $form.serialize(),
|
||||||
formContent: _.escape($form.find('.js-note-text').val()),
|
formContent: _.escape(content),
|
||||||
formAction: $form.attr('action'),
|
formAction: $form.attr('action'),
|
||||||
|
formContentOriginal: content,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1415,7 +1417,7 @@ export default class Notes {
|
||||||
const isMainForm = $form.hasClass('js-main-target-form');
|
const isMainForm = $form.hasClass('js-main-target-form');
|
||||||
const isDiscussionForm = $form.hasClass('js-discussion-note-form');
|
const isDiscussionForm = $form.hasClass('js-discussion-note-form');
|
||||||
const isDiscussionResolve = $submitBtn.hasClass('js-comment-resolve-button');
|
const isDiscussionResolve = $submitBtn.hasClass('js-comment-resolve-button');
|
||||||
const { formData, formContent, formAction } = this.getFormData($form);
|
const { formData, formContent, formAction, formContentOriginal } = this.getFormData($form);
|
||||||
let noteUniqueId;
|
let noteUniqueId;
|
||||||
let systemNoteUniqueId;
|
let systemNoteUniqueId;
|
||||||
let hasQuickActions = false;
|
let hasQuickActions = false;
|
||||||
|
@ -1574,7 +1576,7 @@ export default class Notes {
|
||||||
$form = $notesContainer.parent().find('form');
|
$form = $notesContainer.parent().find('form');
|
||||||
}
|
}
|
||||||
|
|
||||||
$form.find('.js-note-text').val(formContent);
|
$form.find('.js-note-text').val(formContentOriginal);
|
||||||
this.reenableTargetFormSubmitButton(e);
|
this.reenableTargetFormSubmitButton(e);
|
||||||
this.addNoteError($form);
|
this.addNoteError($form);
|
||||||
});
|
});
|
||||||
|
|
115
app/assets/javascripts/repo/components/new_branch_form.vue
Normal file
115
app/assets/javascripts/repo/components/new_branch_form.vue
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
<script>
|
||||||
|
import flash, { hideFlash } from '../../flash';
|
||||||
|
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
|
||||||
|
import eventHub from '../event_hub';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
loadingIcon,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
currentBranch: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
branchName: '',
|
||||||
|
loading: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
btnDisabled() {
|
||||||
|
return this.loading || this.branchName === '';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleDropdown() {
|
||||||
|
this.$dropdown.dropdown('toggle');
|
||||||
|
},
|
||||||
|
submitNewBranch() {
|
||||||
|
// need to query as the element is appended outside of Vue
|
||||||
|
const flashEl = this.$refs.flashContainer.querySelector('.flash-alert');
|
||||||
|
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
|
if (flashEl) {
|
||||||
|
hideFlash(flashEl, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
eventHub.$emit('createNewBranch', this.branchName);
|
||||||
|
},
|
||||||
|
showErrorMessage(message) {
|
||||||
|
this.loading = false;
|
||||||
|
flash(message, 'alert', this.$el);
|
||||||
|
},
|
||||||
|
createdNewBranch(newBranchName) {
|
||||||
|
this.loading = false;
|
||||||
|
this.branchName = '';
|
||||||
|
|
||||||
|
if (this.dropdownText) {
|
||||||
|
this.dropdownText.textContent = newBranchName;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// Dropdown is outside of Vue instance & is controlled by Bootstrap
|
||||||
|
this.$dropdown = $('.git-revision-dropdown');
|
||||||
|
|
||||||
|
// text element is outside Vue app
|
||||||
|
this.dropdownText = document.querySelector('.project-refs-form .dropdown-toggle-text');
|
||||||
|
|
||||||
|
eventHub.$on('createNewBranchSuccess', this.createdNewBranch);
|
||||||
|
eventHub.$on('createNewBranchError', this.showErrorMessage);
|
||||||
|
eventHub.$on('toggleNewBranchDropdown', this.toggleDropdown);
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
eventHub.$off('createNewBranchSuccess', this.createdNewBranch);
|
||||||
|
eventHub.$off('toggleNewBranchDropdown', this.toggleDropdown);
|
||||||
|
eventHub.$off('createNewBranchError', this.showErrorMessage);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="flash-container"
|
||||||
|
ref="flashContainer"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
Create from:
|
||||||
|
<code>{{ currentBranch }}</code>
|
||||||
|
</p>
|
||||||
|
<input
|
||||||
|
class="form-control js-new-branch-name"
|
||||||
|
type="text"
|
||||||
|
placeholder="Name new branch"
|
||||||
|
v-model="branchName"
|
||||||
|
@keyup.enter.stop.prevent="submitNewBranch"
|
||||||
|
/>
|
||||||
|
<div class="prepend-top-default clearfix">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-primary pull-left"
|
||||||
|
:disabled="btnDisabled"
|
||||||
|
@click.stop.prevent="submitNewBranch"
|
||||||
|
>
|
||||||
|
<loading-icon
|
||||||
|
v-if="loading"
|
||||||
|
:inline="true"
|
||||||
|
/>
|
||||||
|
<span>Create</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-default pull-right"
|
||||||
|
@click.stop.prevent="toggleDropdown"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -8,7 +8,9 @@ import RepoMixin from '../mixins/repo_mixin';
|
||||||
import PopupDialog from '../../vue_shared/components/popup_dialog.vue';
|
import PopupDialog from '../../vue_shared/components/popup_dialog.vue';
|
||||||
import Store from '../stores/repo_store';
|
import Store from '../stores/repo_store';
|
||||||
import Helper from '../helpers/repo_helper';
|
import Helper from '../helpers/repo_helper';
|
||||||
|
import Service from '../services/repo_service';
|
||||||
import MonacoLoaderHelper from '../helpers/monaco_loader_helper';
|
import MonacoLoaderHelper from '../helpers/monaco_loader_helper';
|
||||||
|
import eventHub from '../event_hub';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
|
@ -24,12 +26,19 @@ export default {
|
||||||
PopupDialog,
|
PopupDialog,
|
||||||
RepoPreview,
|
RepoPreview,
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
eventHub.$on('createNewBranch', this.createNewBranch);
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
Helper.getContent().catch(Helper.loadingError);
|
Helper.getContent().catch(Helper.loadingError);
|
||||||
},
|
},
|
||||||
|
destroyed() {
|
||||||
|
eventHub.$off('createNewBranch', this.createNewBranch);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getCurrentLocation() {
|
||||||
|
return location.href;
|
||||||
|
},
|
||||||
toggleDialogOpen(toggle) {
|
toggleDialogOpen(toggle) {
|
||||||
this.dialog.open = toggle;
|
this.dialog.open = toggle;
|
||||||
},
|
},
|
||||||
|
@ -42,8 +51,25 @@ export default {
|
||||||
Helper.removeAllTmpFiles('openedFiles');
|
Helper.removeAllTmpFiles('openedFiles');
|
||||||
Helper.removeAllTmpFiles('files');
|
Helper.removeAllTmpFiles('files');
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleBlobView: Store.toggleBlobView,
|
toggleBlobView: Store.toggleBlobView,
|
||||||
|
createNewBranch(branch) {
|
||||||
|
Service.createBranch({
|
||||||
|
branch,
|
||||||
|
ref: Store.currentBranch,
|
||||||
|
}).then((res) => {
|
||||||
|
const newBranchName = res.data.name;
|
||||||
|
const newUrl = this.getCurrentLocation().replace(Store.currentBranch, newBranchName);
|
||||||
|
|
||||||
|
Store.currentBranch = newBranchName;
|
||||||
|
|
||||||
|
history.pushState({ key: Helper.key }, '', newUrl);
|
||||||
|
|
||||||
|
eventHub.$emit('createNewBranchSuccess', newBranchName);
|
||||||
|
eventHub.$emit('toggleNewBranchDropdown');
|
||||||
|
}).catch((err) => {
|
||||||
|
eventHub.$emit('createNewBranchError', err.response.data.message);
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -5,6 +5,7 @@ import Service from './services/repo_service';
|
||||||
import Store from './stores/repo_store';
|
import Store from './stores/repo_store';
|
||||||
import Repo from './components/repo.vue';
|
import Repo from './components/repo.vue';
|
||||||
import RepoEditButton from './components/repo_edit_button.vue';
|
import RepoEditButton from './components/repo_edit_button.vue';
|
||||||
|
import newBranchForm from './components/new_branch_form.vue';
|
||||||
import newDropdown from './components/new_dropdown/index.vue';
|
import newDropdown from './components/new_dropdown/index.vue';
|
||||||
import Translate from '../vue_shared/translate';
|
import Translate from '../vue_shared/translate';
|
||||||
|
|
||||||
|
@ -76,6 +77,26 @@ function initNewDropdown(el) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initNewBranchForm() {
|
||||||
|
const el = document.querySelector('.js-new-branch-dropdown');
|
||||||
|
|
||||||
|
if (!el) return null;
|
||||||
|
|
||||||
|
return new Vue({
|
||||||
|
el,
|
||||||
|
components: {
|
||||||
|
newBranchForm,
|
||||||
|
},
|
||||||
|
render(createElement) {
|
||||||
|
return createElement('new-branch-form', {
|
||||||
|
props: {
|
||||||
|
currentBranch: Store.currentBranch,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function initRepoBundle() {
|
function initRepoBundle() {
|
||||||
const repo = document.getElementById('repo');
|
const repo = document.getElementById('repo');
|
||||||
const editButton = document.querySelector('.editable-mode');
|
const editButton = document.querySelector('.editable-mode');
|
||||||
|
@ -88,6 +109,7 @@ function initRepoBundle() {
|
||||||
|
|
||||||
initRepo(repo);
|
initRepo(repo);
|
||||||
initRepoEditButton(editButton);
|
initRepoEditButton(editButton);
|
||||||
|
initNewBranchForm();
|
||||||
initNewDropdown(newDropdownHolder);
|
initNewDropdown(newDropdownHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import csrf from '../../lib/utils/csrf';
|
||||||
import Store from '../stores/repo_store';
|
import Store from '../stores/repo_store';
|
||||||
import Api from '../../api';
|
import Api from '../../api';
|
||||||
import Helper from '../helpers/repo_helper';
|
import Helper from '../helpers/repo_helper';
|
||||||
|
|
||||||
|
axios.defaults.headers.common[csrf.headerKey] = csrf.token;
|
||||||
|
|
||||||
const RepoService = {
|
const RepoService = {
|
||||||
url: '',
|
url: '',
|
||||||
options: {
|
options: {
|
||||||
|
@ -10,6 +13,7 @@ const RepoService = {
|
||||||
format: 'json',
|
format: 'json',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
createBranchPath: '/api/:version/projects/:id/repository/branches',
|
||||||
richExtensionRegExp: /md/,
|
richExtensionRegExp: /md/,
|
||||||
|
|
||||||
getRaw(file) {
|
getRaw(file) {
|
||||||
|
@ -79,6 +83,12 @@ const RepoService = {
|
||||||
.then(this.commitFlash);
|
.then(this.commitFlash);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
createBranch(payload) {
|
||||||
|
const url = Api.buildUrl(this.createBranchPath)
|
||||||
|
.replace(':id', Store.projectId);
|
||||||
|
return axios.post(url, payload);
|
||||||
|
},
|
||||||
|
|
||||||
commitFlash(data) {
|
commitFlash(data) {
|
||||||
if (data.short_id && data.stats) {
|
if (data.short_id && data.stats) {
|
||||||
window.Flash(`Your changes have been committed. Commit ${data.short_id} with ${data.stats.additions} additions, ${data.stats.deletions} deletions.`, 'notice');
|
window.Flash(`Your changes have been committed. Commit ${data.short_id} with ${data.stats.additions} additions, ${data.stats.deletions} deletions.`, 'notice');
|
||||||
|
|
|
@ -13,6 +13,7 @@ const RepoStore = {
|
||||||
projectId: '',
|
projectId: '',
|
||||||
projectName: '',
|
projectName: '',
|
||||||
projectUrl: '',
|
projectUrl: '',
|
||||||
|
branchUrl: '',
|
||||||
blobRaw: '',
|
blobRaw: '',
|
||||||
currentBlobView: 'repo-preview',
|
currentBlobView: 'repo-preview',
|
||||||
openedFiles: [],
|
openedFiles: [],
|
||||||
|
|
7
app/views/peek/views/_gitaly.html.haml
Normal file
7
app/views/peek/views/_gitaly.html.haml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
- local_assigns.fetch(:view)
|
||||||
|
|
||||||
|
%strong
|
||||||
|
%span{ data: { defer_to: "#{view.defer_key}-duration" } } ...
|
||||||
|
\/
|
||||||
|
%span{ data: { defer_to: "#{view.defer_key}-calls" } } ...
|
||||||
|
Gitaly
|
|
@ -1,6 +1,6 @@
|
||||||
.tree-ref-container
|
.tree-ref-container
|
||||||
.tree-ref-holder
|
.tree-ref-holder
|
||||||
= render 'shared/ref_switcher', destination: 'tree', path: @path
|
= render 'shared/ref_switcher', destination: 'tree', path: @path, show_create: true
|
||||||
|
|
||||||
- if show_new_repo?
|
- if show_new_repo?
|
||||||
.js-new-dropdown
|
.js-new-dropdown
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
- show_new_branch_form = show_new_repo? && show_create && can?(current_user, :push_code, @project)
|
||||||
- dropdown_toggle_text = @ref || @project.default_branch
|
- dropdown_toggle_text = @ref || @project.default_branch
|
||||||
= form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do
|
= form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do
|
||||||
= hidden_field_tag :destination, destination
|
= hidden_field_tag :destination, destination
|
||||||
|
@ -7,8 +8,20 @@
|
||||||
= hidden_field_tag key, value, id: nil
|
= hidden_field_tag key, value, id: nil
|
||||||
.dropdown
|
.dropdown
|
||||||
= dropdown_toggle dropdown_toggle_text, { toggle: "dropdown", selected: dropdown_toggle_text, ref: @ref, refs_url: refs_project_path(@project), field_name: 'ref', submit_form_on_click: true, visit: true }, { toggle_class: "js-project-refs-dropdown" }
|
= dropdown_toggle dropdown_toggle_text, { toggle: "dropdown", selected: dropdown_toggle_text, ref: @ref, refs_url: refs_project_path(@project), field_name: 'ref', submit_form_on_click: true, visit: true }, { toggle_class: "js-project-refs-dropdown" }
|
||||||
.dropdown-menu.dropdown-menu-selectable.git-revision-dropdown{ class: ("dropdown-menu-align-right" if local_assigns[:align_right]) }
|
.dropdown-menu.dropdown-menu-selectable.git-revision-dropdown.dropdown-menu-paging{ class: ("dropdown-menu-align-right" if local_assigns[:align_right]) }
|
||||||
= dropdown_title _("Switch branch/tag")
|
.dropdown-page-one
|
||||||
= dropdown_filter _("Search branches and tags")
|
= dropdown_title _("Switch branch/tag")
|
||||||
= dropdown_content
|
= dropdown_filter _("Search branches and tags")
|
||||||
= dropdown_loading
|
= dropdown_content
|
||||||
|
= dropdown_loading
|
||||||
|
- if show_new_branch_form
|
||||||
|
= dropdown_footer do
|
||||||
|
%ul.dropdown-footer-list
|
||||||
|
%li
|
||||||
|
%a.dropdown-toggle-page{ href: "#" }
|
||||||
|
Create new branch
|
||||||
|
- if show_new_branch_form
|
||||||
|
.dropdown-page-two
|
||||||
|
= dropdown_title("Create new branch", options: { back: true })
|
||||||
|
= dropdown_content do
|
||||||
|
.js-new-branch-dropdown
|
||||||
|
|
5
changelogs/unreleased/zj-peek-gitaly.yml
Normal file
5
changelogs/unreleased/zj-peek-gitaly.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Add Gitaly metrics to the performance bar
|
||||||
|
merge_request:
|
||||||
|
author:
|
||||||
|
type: other
|
|
@ -16,6 +16,7 @@ Peek.into Peek::Views::Redis
|
||||||
Peek.into Peek::Views::Sidekiq
|
Peek.into Peek::Views::Sidekiq
|
||||||
Peek.into Peek::Views::Rblineprof
|
Peek.into Peek::Views::Rblineprof
|
||||||
Peek.into Peek::Views::GC
|
Peek.into Peek::Views::GC
|
||||||
|
Peek.into Peek::Views::Gitaly
|
||||||
|
|
||||||
# rubocop:disable Style/ClassAndModuleCamelCase
|
# rubocop:disable Style/ClassAndModuleCamelCase
|
||||||
class PEEK_DB_CLIENT
|
class PEEK_DB_CLIENT
|
||||||
|
|
|
@ -33,6 +33,12 @@ module Gitlab
|
||||||
MUTEX = Mutex.new
|
MUTEX = Mutex.new
|
||||||
private_constant :MUTEX
|
private_constant :MUTEX
|
||||||
|
|
||||||
|
class << self
|
||||||
|
attr_accessor :query_time
|
||||||
|
end
|
||||||
|
|
||||||
|
self.query_time = 0
|
||||||
|
|
||||||
def self.stub(name, storage)
|
def self.stub(name, storage)
|
||||||
MUTEX.synchronize do
|
MUTEX.synchronize do
|
||||||
@stubs ||= {}
|
@stubs ||= {}
|
||||||
|
@ -83,11 +89,14 @@ module Gitlab
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
def self.call(storage, service, rpc, request)
|
def self.call(storage, service, rpc, request)
|
||||||
|
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
||||||
enforce_gitaly_request_limits(:call)
|
enforce_gitaly_request_limits(:call)
|
||||||
|
|
||||||
kwargs = request_kwargs(storage)
|
kwargs = request_kwargs(storage)
|
||||||
kwargs = yield(kwargs) if block_given?
|
kwargs = yield(kwargs) if block_given?
|
||||||
stub(service, storage).__send__(rpc, request, kwargs) # rubocop:disable GitlabSecurity/PublicSend
|
stub(service, storage).__send__(rpc, request, kwargs) # rubocop:disable GitlabSecurity/PublicSend
|
||||||
|
ensure
|
||||||
|
self.query_time += Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.request_kwargs(storage)
|
def self.request_kwargs(storage)
|
||||||
|
|
34
lib/peek/views/gitaly.rb
Normal file
34
lib/peek/views/gitaly.rb
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
module Peek
|
||||||
|
module Views
|
||||||
|
class Gitaly < View
|
||||||
|
def duration
|
||||||
|
::Gitlab::GitalyClient.query_time
|
||||||
|
end
|
||||||
|
|
||||||
|
def calls
|
||||||
|
::Gitlab::GitalyClient.get_request_count
|
||||||
|
end
|
||||||
|
|
||||||
|
def results
|
||||||
|
{ duration: formatted_duration, calls: calls }
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def formatted_duration
|
||||||
|
ms = duration * 1000
|
||||||
|
if ms >= 1000
|
||||||
|
"%.2fms" % ms
|
||||||
|
else
|
||||||
|
"%.0fms" % ms
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup_subscribers
|
||||||
|
subscribe 'start_processing.action_controller' do
|
||||||
|
::Gitlab::GitalyClient.query_time = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -6,6 +6,7 @@ feature 'Ref switcher', :js do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
project.team << [user, :master]
|
project.team << [user, :master]
|
||||||
|
page.driver.set_cookie('new_repo', 'true')
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
visit project_tree_path(project, 'master')
|
visit project_tree_path(project, 'master')
|
||||||
end
|
end
|
||||||
|
@ -40,4 +41,38 @@ feature 'Ref switcher', :js do
|
||||||
|
|
||||||
expect(page).to have_title "'test'"
|
expect(page).to have_title "'test'"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "create branch" do
|
||||||
|
let(:input) { find('.js-new-branch-name') }
|
||||||
|
|
||||||
|
before do
|
||||||
|
click_button 'master'
|
||||||
|
wait_for_requests
|
||||||
|
|
||||||
|
page.within '.project-refs-form' do
|
||||||
|
find(".dropdown-footer-list a").click
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "shows error message for the invalid branch name" do
|
||||||
|
input.set 'foo bar'
|
||||||
|
click_button('Create')
|
||||||
|
wait_for_requests
|
||||||
|
expect(page).to have_content 'Branch name is invalid'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should create new branch properly" do
|
||||||
|
input.set 'new-branch-name'
|
||||||
|
click_button('Create')
|
||||||
|
wait_for_requests
|
||||||
|
expect(find('.js-project-refs-dropdown')).to have_content 'new-branch-name'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should create new branch by Enter key" do
|
||||||
|
input.set 'new-branch-name-2'
|
||||||
|
input.native.send_keys :enter
|
||||||
|
wait_for_requests
|
||||||
|
expect(find('.js-project-refs-dropdown')).to have_content 'new-branch-name-2'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -103,6 +103,16 @@ import '~/notes';
|
||||||
$('.js-comment-button').click();
|
$('.js-comment-button').click();
|
||||||
expect(this.autoSizeSpy).toHaveBeenTriggered();
|
expect(this.autoSizeSpy).toHaveBeenTriggered();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not place escaped text in the comment box in case of error', function() {
|
||||||
|
const deferred = $.Deferred();
|
||||||
|
spyOn($, 'ajax').and.returnValue(deferred.promise());
|
||||||
|
$(textarea).text('A comment with `markup`.');
|
||||||
|
|
||||||
|
deferred.reject();
|
||||||
|
$('.js-comment-button').click();
|
||||||
|
expect($(textarea).val()).toEqual('A comment with `markup`.');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('updateNote', () => {
|
describe('updateNote', () => {
|
||||||
|
|
122
spec/javascripts/repo/components/new_branch_form_spec.js
Normal file
122
spec/javascripts/repo/components/new_branch_form_spec.js
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
import Vue from 'vue';
|
||||||
|
import newBranchForm from '~/repo/components/new_branch_form.vue';
|
||||||
|
import eventHub from '~/repo/event_hub';
|
||||||
|
import RepoStore from '~/repo/stores/repo_store';
|
||||||
|
import createComponent from '../../helpers/vue_mount_component_helper';
|
||||||
|
|
||||||
|
describe('Multi-file editor new branch form', () => {
|
||||||
|
let vm;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const Component = Vue.extend(newBranchForm);
|
||||||
|
|
||||||
|
RepoStore.currentBranch = 'master';
|
||||||
|
|
||||||
|
vm = createComponent(Component, {
|
||||||
|
currentBranch: RepoStore.currentBranch,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vm.$destroy();
|
||||||
|
|
||||||
|
RepoStore.currentBranch = '';
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('template', () => {
|
||||||
|
it('renders submit as disabled', () => {
|
||||||
|
expect(vm.$el.querySelector('.btn').getAttribute('disabled')).toBe('disabled');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('enables the submit button when branch is not empty', (done) => {
|
||||||
|
vm.branchName = 'testing';
|
||||||
|
|
||||||
|
Vue.nextTick(() => {
|
||||||
|
expect(vm.$el.querySelector('.btn').getAttribute('disabled')).toBeNull();
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays current branch creating from', (done) => {
|
||||||
|
Vue.nextTick(() => {
|
||||||
|
expect(vm.$el.querySelector('p').textContent.replace(/\s+/g, ' ').trim()).toBe('Create from: master');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('submitNewBranch', () => {
|
||||||
|
it('sets to loading', () => {
|
||||||
|
vm.submitNewBranch();
|
||||||
|
|
||||||
|
expect(vm.loading).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hides current flash element', (done) => {
|
||||||
|
vm.$refs.flashContainer.innerHTML = '<div class="flash-alert"></div>';
|
||||||
|
|
||||||
|
vm.submitNewBranch();
|
||||||
|
|
||||||
|
Vue.nextTick(() => {
|
||||||
|
expect(vm.$el.querySelector('.flash-alert')).toBeNull();
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('emits an event with branchName', () => {
|
||||||
|
spyOn(eventHub, '$emit');
|
||||||
|
|
||||||
|
vm.branchName = 'testing';
|
||||||
|
|
||||||
|
vm.submitNewBranch();
|
||||||
|
|
||||||
|
expect(eventHub.$emit).toHaveBeenCalledWith('createNewBranch', 'testing');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('showErrorMessage', () => {
|
||||||
|
it('sets loading to false', () => {
|
||||||
|
vm.loading = true;
|
||||||
|
|
||||||
|
vm.showErrorMessage();
|
||||||
|
|
||||||
|
expect(vm.loading).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates flash element', () => {
|
||||||
|
vm.showErrorMessage('error message');
|
||||||
|
|
||||||
|
expect(vm.$el.querySelector('.flash-alert')).not.toBeNull();
|
||||||
|
expect(vm.$el.querySelector('.flash-alert').textContent.trim()).toBe('error message');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('createdNewBranch', () => {
|
||||||
|
it('set loading to false', () => {
|
||||||
|
vm.loading = true;
|
||||||
|
|
||||||
|
vm.createdNewBranch();
|
||||||
|
|
||||||
|
expect(vm.loading).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('resets branch name', () => {
|
||||||
|
vm.branchName = 'testing';
|
||||||
|
|
||||||
|
vm.createdNewBranch();
|
||||||
|
|
||||||
|
expect(vm.branchName).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets the dropdown toggle text', () => {
|
||||||
|
vm.dropdownText = document.createElement('span');
|
||||||
|
|
||||||
|
vm.createdNewBranch('branch name');
|
||||||
|
|
||||||
|
expect(vm.dropdownText.textContent).toBe('branch name');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
96
spec/javascripts/repo/components/repo_spec.js
Normal file
96
spec/javascripts/repo/components/repo_spec.js
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
import Vue from 'vue';
|
||||||
|
import repo from '~/repo/components/repo.vue';
|
||||||
|
import RepoStore from '~/repo/stores/repo_store';
|
||||||
|
import Service from '~/repo/services/repo_service';
|
||||||
|
import eventHub from '~/repo/event_hub';
|
||||||
|
import createComponent from '../../helpers/vue_mount_component_helper';
|
||||||
|
|
||||||
|
describe('repo component', () => {
|
||||||
|
let vm;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const Component = Vue.extend(repo);
|
||||||
|
|
||||||
|
RepoStore.currentBranch = 'master';
|
||||||
|
|
||||||
|
vm = createComponent(Component);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vm.$destroy();
|
||||||
|
|
||||||
|
RepoStore.currentBranch = '';
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('createNewBranch', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn(history, 'pushState');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn(Service, 'createBranch').and.returnValue(Promise.resolve({
|
||||||
|
data: {
|
||||||
|
name: 'test',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls createBranch with branchName', () => {
|
||||||
|
eventHub.$emit('createNewBranch', 'test');
|
||||||
|
|
||||||
|
expect(Service.createBranch).toHaveBeenCalledWith({
|
||||||
|
branch: 'test',
|
||||||
|
ref: RepoStore.currentBranch,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('pushes new history state', (done) => {
|
||||||
|
RepoStore.currentBranch = 'master';
|
||||||
|
|
||||||
|
spyOn(vm, 'getCurrentLocation').and.returnValue('http://test.com/master');
|
||||||
|
|
||||||
|
eventHub.$emit('createNewBranch', 'test');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(history.pushState).toHaveBeenCalledWith(jasmine.anything(), '', 'http://test.com/test');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates stores currentBranch', (done) => {
|
||||||
|
eventHub.$emit('createNewBranch', 'test');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(RepoStore.currentBranch).toBe('test');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('failure', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn(Service, 'createBranch').and.returnValue(Promise.reject({
|
||||||
|
response: {
|
||||||
|
data: {
|
||||||
|
message: 'test',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('emits createNewBranchError event', (done) => {
|
||||||
|
spyOn(eventHub, '$emit').and.callThrough();
|
||||||
|
|
||||||
|
eventHub.$emit('createNewBranch', 'test');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(eventHub.$emit).toHaveBeenCalledWith('createNewBranchError', 'test');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue