Commit d072c18d authored by Phil Hughes's avatar Phil Hughes

Merge branch 'master' into ce-to-ee-2017-12-16

parents 458f54dc 0a395a08
/* eslint-disable comma-dangle, space-before-function-paren, no-new */
/* global MilestoneSelect */
/* global Sidebar */
import Vue from 'vue';
import weight from 'ee/sidebar/components/weight/weight.vue';
import Flash from '../../flash';
import Sidebar from '../../right_sidebar';
import eventHub from '../../sidebar/event_hub';
import assigneeTitle from '../../sidebar/components/assignees/assignee_title';
import assignees from '../../sidebar/components/assignees/assignees';
......
......@@ -25,7 +25,6 @@ class ListIssue {
this.isLoading = {
weight: false,
};
this.isLoading = {};
this.sidebarInfoEndpoint = obj.issue_sidebar_endpoint;
this.toggleSubscriptionEndpoint = obj.toggle_subscription_endpoint;
this.milestone_id = obj.milestone_id;
......
/* global CommentsStore */
/* global notes */
import Vue from 'vue';
import collapseIcon from '../icons/collapse_icon.svg';
import Notes from '../../notes';
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
const DiffNoteAvatars = Vue.extend({
......@@ -129,7 +129,7 @@ const DiffNoteAvatars = Vue.extend({
},
methods: {
clickedAvatar(e) {
notes.onAddDiffNote(e);
Notes.instance.onAddDiffNote(e);
// Toggle the active state of the toggle all button
this.toggleDiscussionsToggleState();
......
......@@ -11,7 +11,7 @@ import NotificationsForm from './notifications_form';
import notificationsDropdown from './notifications_dropdown';
import groupAvatar from './group_avatar';
import GroupLabelSubscription from './group_label_subscription';
/* global LineHighlighter */
import LineHighlighter from './line_highlighter';
import BuildArtifacts from './build_artifacts';
import CILintEditor from './ci_lint_editor';
import groupsSelect from './groups_select';
......@@ -21,7 +21,7 @@ import NamespaceSelect from './namespace_select';
import NewCommitForm from './new_commit_form';
import Project from './project';
import projectAvatar from './project_avatar';
/* global MergeRequest */
import MergeRequest from './merge_request';
import Compare from './compare';
import initCompareAutocomplete from './compare_autocomplete';
/* global PathLocks */
......@@ -30,7 +30,7 @@ import ProjectNew from './project_new';
import projectImport from './project_import';
import Labels from './labels';
import LabelManager from './label_manager';
/* global Sidebar */
import Sidebar from './right_sidebar';
/* global WeightSelect */
/* global AdminEmailSelect */
......
......@@ -3,7 +3,7 @@
/* global WeightSelect */
import LabelsSelect from './labels_select';
import IssuableContext from './issuable_context';
/* global Sidebar */
import Sidebar from './right_sidebar';
import DueDateSelectors from './due_date_select';
......@@ -17,5 +17,5 @@ export default () => {
new WeightSelect();
new IssuableContext(sidebarOptions.currentUser);
new DueDateSelectors();
window.sidebar = new Sidebar();
Sidebar.initialize();
};
/* global Notes */
import Notes from './notes';
export default () => {
const dataEl = document.querySelector('.js-notes-data');
......@@ -10,5 +10,7 @@ export default () => {
autocomplete,
} = JSON.parse(dataEl.innerHTML);
window.notes = new Notes(notesUrl, notesIds, now, diffView, autocomplete);
// Create a singleton so that we don't need to assign
// into the window object, we can just access the current isntance with Notes.instance
Notes.initialize(notesUrl, notesIds, now, diffView, autocomplete);
};
......@@ -175,4 +175,4 @@ LineHighlighter.prototype.__setLocationHash__ = function(value) {
}, document.title, value);
};
window.LineHighlighter = LineHighlighter;
export default LineHighlighter;
......@@ -45,14 +45,10 @@ import './layout_nav';
import LazyLoader from './lazy_loader';
import './line_highlighter';
import initLogoAnimation from './logo';
import './merge_request';
import './merge_request_tabs';
import './milestone_select';
import './notes';
import './preview_markdown';
import './projects_dropdown';
import './render_gfm';
import './right_sidebar';
import initBreadcrumbs from './breadcrumb';
// EE-only scripts
......
......@@ -7,142 +7,138 @@ import MergeRequestTabs from './merge_request_tabs';
import IssuablesHelper from './helpers/issuables_helper';
import { addDelimiter } from './lib/utils/text_utility';
(function() {
this.MergeRequest = (function() {
function MergeRequest(opts) {
// Initialize MergeRequest behavior
//
// Options:
// action - String, current controller action
//
this.opts = opts != null ? opts : {};
this.submitNoteForm = this.submitNoteForm.bind(this);
this.$el = $('.merge-request');
this.$('.show-all-commits').on('click', (function(_this) {
return function() {
return _this.showAllCommits();
};
})(this));
this.initTabs();
this.initMRBtnListeners();
this.initCommitMessageListeners();
this.closeReopenReportToggle = IssuablesHelper.initCloseReopenReport();
if ($("a.btn-close").length) {
this.taskList = new TaskList({
dataType: 'merge_request',
fieldName: 'description',
selector: '.detail-page-description',
onSuccess: (result) => {
document.querySelector('#task_status').innerText = result.task_status;
document.querySelector('#task_status_short').innerText = result.task_status_short;
}
});
}
}
// Local jQuery finder
MergeRequest.prototype.$ = function(selector) {
return this.$el.find(selector);
function MergeRequest(opts) {
// Initialize MergeRequest behavior
//
// Options:
// action - String, current controller action
//
this.opts = opts != null ? opts : {};
this.submitNoteForm = this.submitNoteForm.bind(this);
this.$el = $('.merge-request');
this.$('.show-all-commits').on('click', (function(_this) {
return function() {
return _this.showAllCommits();
};
MergeRequest.prototype.initTabs = function() {
if (window.mrTabs) {
window.mrTabs.unbindEvents();
})(this));
this.initTabs();
this.initMRBtnListeners();
this.initCommitMessageListeners();
this.closeReopenReportToggle = IssuablesHelper.initCloseReopenReport();
if ($("a.btn-close").length) {
this.taskList = new TaskList({
dataType: 'merge_request',
fieldName: 'description',
selector: '.detail-page-description',
onSuccess: (result) => {
document.querySelector('#task_status').innerText = result.task_status;
document.querySelector('#task_status_short').innerText = result.task_status_short;
}
window.mrTabs = new MergeRequestTabs(this.opts);
};
MergeRequest.prototype.showAllCommits = function() {
this.$('.first-commits').remove();
return this.$('.all-commits').removeClass('hide');
};
MergeRequest.prototype.initMRBtnListeners = function() {
var _this;
_this = this;
return $('a.btn-close, a.btn-reopen').on('click', function(e) {
var $this, shouldSubmit;
$this = $(this);
shouldSubmit = $this.hasClass('btn-comment');
if (shouldSubmit && $this.data('submitted')) {
return;
}
if (this.closeReopenReportToggle) this.closeReopenReportToggle.setDisable();
if (shouldSubmit) {
if ($this.hasClass('btn-comment-and-close') || $this.hasClass('btn-comment-and-reopen')) {
e.preventDefault();
e.stopImmediatePropagation();
_this.submitNoteForm($this.closest('form'), $this);
}
}
});
};
MergeRequest.prototype.submitNoteForm = function(form, $button) {
var noteText;
noteText = form.find("textarea.js-note-text").val();
if (noteText.trim().length > 0) {
form.submit();
$button.data('submitted', true);
return $button.trigger('click');
}
};
MergeRequest.prototype.initCommitMessageListeners = function() {
$(document).on('click', 'a.js-with-description-link', function(e) {
var textarea = $('textarea.js-commit-message');
e.preventDefault();
});
}
}
// Local jQuery finder
MergeRequest.prototype.$ = function(selector) {
return this.$el.find(selector);
};
MergeRequest.prototype.initTabs = function() {
if (window.mrTabs) {
window.mrTabs.unbindEvents();
}
window.mrTabs = new MergeRequestTabs(this.opts);
};
MergeRequest.prototype.showAllCommits = function() {
this.$('.first-commits').remove();
return this.$('.all-commits').removeClass('hide');
};
MergeRequest.prototype.initMRBtnListeners = function() {
var _this;
_this = this;
return $('a.btn-close, a.btn-reopen').on('click', function(e) {
var $this, shouldSubmit;
$this = $(this);
shouldSubmit = $this.hasClass('btn-comment');
if (shouldSubmit && $this.data('submitted')) {
return;
}
textarea.val(textarea.data('messageWithDescription'));
$('.js-with-description-hint').hide();
$('.js-without-description-hint').show();
});
if (this.closeReopenReportToggle) this.closeReopenReportToggle.setDisable();
$(document).on('click', 'a.js-without-description-link', function(e) {
var textarea = $('textarea.js-commit-message');
if (shouldSubmit) {
if ($this.hasClass('btn-comment-and-close') || $this.hasClass('btn-comment-and-reopen')) {
e.preventDefault();
e.stopImmediatePropagation();
textarea.val(textarea.data('messageWithoutDescription'));
$('.js-with-description-hint').show();
$('.js-without-description-hint').hide();
});
};
MergeRequest.prototype.updateStatusText = function(classToRemove, classToAdd, newStatusText) {
$('.detail-page-header .status-box')
.removeClass(classToRemove)
.addClass(classToAdd)
.find('span')
.text(newStatusText);
};
MergeRequest.prototype.decreaseCounter = function(by = 1) {
const $el = $('.nav-links .js-merge-counter');
const count = Math.max((parseInt($el.text().replace(/[^\d]/, ''), 10) - by), 0);
$el.text(addDelimiter(count));
};
MergeRequest.prototype.hideCloseButton = function() {
const el = document.querySelector('.merge-request .js-issuable-actions');
const closeDropdownItem = el.querySelector('li.close-item');
if (closeDropdownItem) {
closeDropdownItem.classList.add('hidden');
// Selects the next dropdown item
el.querySelector('li.report-item').click();
} else {
// No dropdown just hide the Close button
el.querySelector('.btn-close').classList.add('hidden');
_this.submitNoteForm($this.closest('form'), $this);
}
// Dropdown for mobile screen
el.querySelector('li.js-close-item').classList.add('hidden');
};
return MergeRequest;
})();
}).call(window);
}
});
};
MergeRequest.prototype.submitNoteForm = function(form, $button) {
var noteText;
noteText = form.find("textarea.js-note-text").val();
if (noteText.trim().length > 0) {
form.submit();
$button.data('submitted', true);
return $button.trigger('click');
}
};
MergeRequest.prototype.initCommitMessageListeners = function() {
$(document).on('click', 'a.js-with-description-link', function(e) {
var textarea = $('textarea.js-commit-message');
e.preventDefault();
textarea.val(textarea.data('messageWithDescription'));
$('.js-with-description-hint').hide();
$('.js-without-description-hint').show();
});
$(document).on('click', 'a.js-without-description-link', function(e) {
var textarea = $('textarea.js-commit-message');
e.preventDefault();
textarea.val(textarea.data('messageWithoutDescription'));
$('.js-with-description-hint').show();
$('.js-without-description-hint').hide();
});
};
MergeRequest.prototype.updateStatusText = function(classToRemove, classToAdd, newStatusText) {
$('.detail-page-header .status-box')
.removeClass(classToRemove)
.addClass(classToAdd)
.find('span')
.text(newStatusText);
};
MergeRequest.prototype.decreaseCounter = function(by = 1) {
const $el = $('.nav-links .js-merge-counter');
const count = Math.max((parseInt($el.text().replace(/[^\d]/, ''), 10) - by), 0);
$el.text(addDelimiter(count));
};
MergeRequest.prototype.hideCloseButton = function() {
const el = document.querySelector('.merge-request .js-issuable-actions');
const closeDropdownItem = el.querySelector('li.close-item');
if (closeDropdownItem) {
closeDropdownItem.classList.add('hidden');
// Selects the next dropdown item
el.querySelector('li.report-item').click();
} else {
// No dropdown just hide the Close button
el.querySelector('.btn-close').classList.add('hidden');
}
// Dropdown for mobile screen
el.querySelector('li.js-close-item').classList.add('hidden');
};
export default MergeRequest;
/* eslint-disable no-new, class-methods-use-this */
/* global notes */
import Cookies from 'js-cookie';
import Flash from './flash';
......@@ -16,6 +15,7 @@ import initDiscussionTab from './image_diff/init_discussion_tab';
import Diff from './diff';
import { localTimeAgo } from './lib/utils/datetime_utility';
import syntaxHighlight from './syntax_highlight';
import Notes from './notes';
/* eslint-disable max-len */
// MergeRequestTabs
......@@ -324,7 +324,7 @@ export default class MergeRequestTabs {
if (anchor && anchor.length > 0) {
const notesContent = anchor.closest('.notes_content');
const lineType = notesContent.hasClass('new') ? 'new' : 'old';
notes.toggleDiffNote({
Notes.instance.toggleDiffNote({
target: anchor,
lineType,
forceShow: true,
......
......@@ -37,6 +37,12 @@ const MAX_VISIBLE_COMMIT_LIST_COUNT = 3;
const REGEX_QUICK_ACTIONS = /^\/\w+.*$/gm;
export default class Notes {
static initialize(notes_url, note_ids, last_fetched_at, view, enableGFM = true) {
if (!this.instance) {
this.instance = new Notes(notes_url, note_ids, last_fetched_at, view, enableGFM);
}
}
constructor(notes_url, note_ids, last_fetched_at, view, enableGFM = true) {
this.updateTargetButtons = this.updateTargetButtons.bind(this);
this.updateComment = this.updateComment.bind(this);
......
<script>
/* global LineHighlighter */
import { mapGetters } from 'vuex';
import LineHighlighter from '../../line_highlighter';
import syntaxHighlight from '../../syntax_highlight';
export default {
......
This diff is collapsed.
/* global Mousetrap */
/* global sidebar */
import _ from 'underscore';
import 'mousetrap';
import Sidebar from './right_sidebar';
import ShortcutsNavigation from './shortcuts_navigation';
import { CopyAsGFM } from './behaviors/copy_as_gfm';
......@@ -69,7 +69,7 @@ export default class ShortcutsIssuable extends ShortcutsNavigation {
}
static openSidebarDropdown(name) {
sidebar.openDropdown(name);
Sidebar.instance.openDropdown(name);
return false;
}
}
......@@ -6,7 +6,7 @@ Vue.use(VueResource);
export default class MRWidgetService {
constructor(endpoints) {
this.mergeResource = Vue.resource(endpoints.mergePath);
this.mergeCheckResource = Vue.resource(endpoints.statusPath);
this.mergeCheckResource = Vue.resource(`${endpoints.statusPath}?serializer=widget`);
this.cancelAutoMergeResource = Vue.resource(endpoints.cancelAutoMergePath);
this.removeWIPResource = Vue.resource(endpoints.removeWIPPath);
this.removeSourceBranchResource = Vue.resource(endpoints.sourceBranchPath);
......
......@@ -133,7 +133,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
.new(project, current_user, wip_event: 'unwip')
.execute(@merge_request)
render json: serializer.represent(@merge_request)
render json: serialize_widget(@merge_request)
end
def commit_change_content
......@@ -149,7 +149,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
.new(@project, current_user)
.cancel(@merge_request)
render json: serializer.represent(@merge_request)
render json: serialize_widget(@merge_request)
end
def merge
......@@ -313,6 +313,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
end
def serialize_widget(merge_request)
serializer.represent(merge_request, serializer: 'widget')
end
def serializer
MergeRequestSerializer.new(current_user: current_user, project: merge_request.project)
end
......
......@@ -32,7 +32,7 @@ module IssuablesHelper
end
end
def serialize_issuable(issuable)
def serialize_issuable(issuable, serializer: nil)
serializer_klass = case issuable
when Issue
IssueSerializer
......@@ -42,7 +42,7 @@ module IssuablesHelper
serializer_klass
.new(current_user: current_user, project: issuable.project)
.represent(issuable)
.represent(issuable, serializer: serializer)
.to_json
end
......
......@@ -3,14 +3,6 @@ class IssuableEntity < Grape::Entity
expose :id
expose :iid
expose :author_id
expose :description
expose :lock_version
expose :milestone_id
expose :title
expose :updated_by_id
expose :created_at
expose :updated_at
expose :milestone, using: API::Entities::Milestone
expose :labels, using: LabelEntity
end
class IssuableSidebarEntity < Grape::Entity
include TimeTrackableEntity
include RequestAwareEntity
prepend ::EE::IssuableSidebarEntity
......@@ -9,9 +10,4 @@ class IssuableSidebarEntity < Grape::Entity
expose :subscribed do |issuable|
issuable.subscribed?(request.current_user, issuable.project)
end
expose :time_estimate
expose :total_time_spent
expose :human_time_estimate
expose :human_total_time_spent
end
......@@ -2,7 +2,15 @@ class IssueEntity < IssuableEntity
include TimeTrackableEntity
expose :state
expose :milestone_id
expose :updated_by_id
expose :created_at
expose :updated_at
expose :deleted_at
expose :milestone, using: API::Entities::Milestone
expose :labels, using: LabelEntity
expose :lock_version
expose :author_id
expose :confidential
expose :discussion_locked
expose :assignees, using: API::Entities::UserBasic
......
class MergeRequestSerializer < BaseSerializer
# This overrided method takes care of which entity should be used
# to serialize the `merge_request` based on `basic` key in `opts` param.
# to serialize the `merge_request` based on `serializer` key in `opts` param.
# Hence, `entity` doesn't need to be declared on the class scope.
def represent(merge_request, opts = {})
entity =
case opts[:serializer]
when 'basic', 'sidebar'
MergeRequestBasicEntity
else
MergeRequestEntity
when 'widget'
MergeRequestWidgetEntity
end
super(merge_request, opts, entity)
......
class MergeRequestEntity < IssuableEntity
include TimeTrackableEntity
prepend ::EE::MergeRequestEntity
class MergeRequestWidgetEntity < IssuableEntity
prepend ::EE::MergeRequestWidgetEntity
expose :state
expose :deleted_at
expose :in_progress_merge_commit_sha
expose :merge_commit_sha
expose :merge_error
......
......@@ -21,7 +21,7 @@
-# haml-lint:disable InlineJavaScript
:javascript
window.gl = window.gl || {};
window.gl.mrWidgetData = #{serialize_issuable(@merge_request)}
window.gl.mrWidgetData = #{serialize_issuable(@merge_request, serializer: 'widget')}
// Append static, server-generated data not included in merge request entity (EE-Only)
// Object.assign would be useful here, but it blows up Phantom.js in tests
......
......@@ -8,16 +8,17 @@
= image_tag 'illustrations/issues.svg'
.col-xs-12
.text-content
- if has_button && current_user
- if current_user
%h4
= _("The Issue Tracker is the place to add things that need to be improved or solved in a project")
%p
= _("Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable.")
.text-center
- if project_select_button
= render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue', type: :issues
- else
= link_to 'New issue', button_path, class: 'btn btn-success', title: 'New issue', id: 'new_issue_link'
- if has_button
.text-center
- if project_select_button
= render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue', type: :issues
- else
= link_to 'New issue', button_path, class: 'btn btn-success', title: 'New issue', id: 'new_issue_link'
- else
%h4.text-center= _("There are no issues to show")
%p
......
---
title: Stop sending milestone and labels data over the wire for MR widget requests
merge_request:
author:
type: performance
......@@ -502,8 +502,8 @@ stages:
unit_test:
stage: test
script:
- composer install
- cp .env.example .env
- composer install
- php artisan key:generate
- php artisan migrate
- vendor/bin/phpunit
......
module EE
module MergeRequestEntity
module MergeRequestWidgetEntity
extend ActiveSupport::Concern
prepended do
......
......@@ -16,18 +16,18 @@ module QA
end
end
module Scenario
module Factory
autoload :License, 'qa/ee/factory/license'
module Geo
autoload :Node, 'qa/ee/scenario/geo/node'
autoload :Node, 'qa/ee/factory/geo/node'
end
end
module Scenario
module Test
autoload :Geo, 'qa/ee/scenario/test/geo'
end
module License
autoload :Add, 'qa/ee/scenario/license/add'
end
end
end
end
module QA
module EE
module Scenario
module Factory
module Geo
class Node < QA::Scenario::Template
class Node < QA::Factory::Base
attr_accessor :address
def perform
def fabricate!
QA::Page::Main::Login.act { sign_in_using_credentials }
QA::Page::Main::Menu.act { go_to_admin_area }
QA::Page::Admin::Menu.act { go_to_geo_nodes }
......
module QA
module EE
module Factory
class License < QA::Factory::Base
def fabricate!(license)
QA::Page::Main::Login.act { sign_in_using_credentials }
QA::Page::Main::Menu.act { go_to_admin_area }
QA::Page::Admin::Menu.act { go_to_license }
EE::Page::Admin::License.act(license) do |key|
add_new_license(key) if no_license?
end
QA::Page::Main::Menu.act { sign_out }
end
end
end
end
end
module QA
module EE
module Scenario
module License
class Add < QA::Scenario::Template
def perform(license)
QA::Page::Main::Login.act { sign_in_using_credentials }
QA::Page::Main::Menu.act { go_to_admin_area }
QA::Page::Admin::Menu.act { go_to_license }
EE::Page::Admin::License.act(license) do |key|
add_new_license(key) if no_license?
end
QA::Page::Main::Menu.act { sign_out }
end
end
end
end
end
end
......@@ -39,32 +39,26 @@ module QA
end
def add_license
# TODO EE license to Runtime.license, gitlab-org/gitlab-qa#86
#
puts 'Adding GitLab EE license ...'
QA::Runtime::Browser.visit(:geo_primary, QA::Page::Main::Login) do
Scenario::License::Add.perform(ENV['EE_LICENSE'])
Factory::License.fabricate!(ENV['EE_LICENSE'])
end
end
def enable_hashed_storage
# TODO, Factory::HashedStorage - gitlab-org/gitlab-qa#86
#
puts 'Enabling hashed repository storage setting ...'
QA::Runtime::Browser.visit(:geo_primary, QA::Page::Main::Login) do
QA::Scenario::Gitlab::Admin::HashedStorage.perform(:enabled)
QA::Factory::Settings::HashedStorage.fabricate!(:enabled)
end
end
def add_secondary_node
# TODO, Factory::Geo::Node - gitlab-org/gitlab-qa#86
#
puts 'Adding new Geo secondary node ...'
QA::Runtime::Browser.visit(:geo_primary, QA::Page::Main::Login) do
Scenario::Geo::Node.perform do |node|
Factory::Geo::Node.fabricate! do |node|
node.address = QA::Runtime::Scenario.geo_secondary_address
end
end
......
......@@ -11,7 +11,7 @@ module QA
return unless ENV['EE_LICENSE']
QA::Runtime::Browser.visit(:gitlab, QA::Page::Main::Login) do
EE::Scenario::License::Add.perform(ENV['EE_LICENSE'])
EE::Factory::License.fabricate!(ENV['EE_LICENSE'])
end
end
end
......
......@@ -4,9 +4,9 @@ module QA
Runtime::Browser.visit(:geo_primary, QA::Page::Main::Login) do
Page::Main::Login.act { sign_in_using_credentials }
Scenario::Gitlab::Project::Create.perform do |scenario|
scenario.name = 'geo-project'
scenario.description = 'Geo test project'
Factory::Resource::Project.fabricate! do |project|
project.name = 'geo-project'
project.description = 'Geo test project'
end
geo_project_name = Page::Project::Show.act { project_name }
......
......@@ -91,11 +91,11 @@ describe Projects::MergeRequestsController do
end
end
context 'without basic serializer param' do
it 'renders the merge request in the json format' do
go(format: :json)
context 'with widget serializer param' do
it 'renders widget MR entity as json' do
go(serializer: 'widget', format: :json)
expect(response).to match_response_schema('entities/merge_request')
expect(response).to match_response_schema('entities/merge_request_widget')
end
end
end
......
......@@ -10,8 +10,7 @@ describe EpicEntity do
subject { described_class.new(resource, request: request).as_json }
it 'has Issuable attributes' do
expect(subject).to include(:id, :iid, :author_id, :description, :lock_version, :milestone_id,
:title, :updated_by_id, :created_at, :updated_at, :milestone, :labels)
expect(subject).to include(:id, :iid, :description, :title)
end
it 'has epic specific attributes' do
......
require 'spec_helper'
describe MergeRequestEntity do
describe MergeRequestWidgetEntity do
let(:user) { create(:user) }
let(:project) { create :project, :repository }
let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
......
This diff is collapsed.
......@@ -15,8 +15,8 @@ feature 'Mini Pipeline Graph', :js do
visit_merge_request
end
def visit_merge_request(format = :html)
visit project_merge_request_path(project, merge_request, format: format)
def visit_merge_request(format: :html, serializer: nil)
visit project_merge_request_path(project, merge_request, format: format, serializer: serializer)
end
it 'should display a mini pipeline graph' do
......@@ -33,12 +33,12 @@ feature 'Mini Pipeline Graph', :js do
end
it 'avoids repeated database queries' do
before = ActiveRecord::QueryRecorder.new { visit_merge_request(:json) }
before = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') }
create(:ci_build, pipeline: pipeline, legacy_artifacts_file: artifacts_file2)
create(:ci_build, pipeline: pipeline, when: 'manual')
after = ActiveRecord::QueryRecorder.new { visit_merge_request(:json) }
after = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') }
expect(before.count).to eq(after.count)
expect(before.cached_count).to eq(after.cached_count)
......
......@@ -81,15 +81,15 @@
"target_branch_tree_path": { "type": "string" },
"source_branch_path": { "type": "string" },
"conflict_resolution_path": { "type": ["string", "null"] },
"cancel_merge_when_pipeline_succeeds_path": { "type": "string" },
"create_issue_to_resolve_discussions_path": { "type": "string" },
"merge_path": { "type": "string" },
"cancel_merge_when_pipeline_succeeds_path": { "type": ["string", "null"] },
"create_issue_to_resolve_discussions_path": { "type": ["string", "null"] },
"merge_path": { "type": ["string", "null"] },
"cherry_pick_in_fork_path": { "type": ["string", "null"] },
"revert_in_fork_path": { "type": ["string", "null"] },
"email_patches_path": { "type": "string" },
"plain_diff_path": { "type": "string" },
"status_path": { "type": "string" },
"new_blob_path": { "type": "string" },
"new_blob_path": { "type": ["string", "null"] },
"merge_check_path": { "type": "string" },
"ci_environments_status_path": { "type": "string" },
"merge_commit_message_with_description": { "type": "string" },
......
/* global Sidebar */
/* eslint-disable no-new */
import _ from 'underscore';
import '~/right_sidebar';
import Sidebar from '~/right_sidebar';
describe('Issuable right sidebar collapsed todo toggle', () => {
const fixtureName = 'issues/open-issue.html.raw';
......
/* eslint-disable space-before-function-paren, no-var, no-param-reassign, quotes, prefer-template, no-else-return, new-cap, dot-notation, no-return-assign, comma-dangle, no-new, one-var, one-var-declaration-per-line, jasmine/no-spec-dupes, no-underscore-dangle, max-len */
/* global LineHighlighter */
import '~/line_highlighter';
import LineHighlighter from '~/line_highlighter';
(function() {
describe('LineHighlighter', function() {
......
/* global Notes */
import 'autosize';
import '~/gl_form';
import '~/lib/utils/text_utility';
import '~/render_gfm';
import '~/render_math';
import '~/notes';
import Notes from '~/notes';
const upArrowKeyCode = 38;
......
/* eslint-disable space-before-function-paren, no-return-assign */
/* global MergeRequest */
import '~/merge_request';
import MergeRequest from '~/merge_request';
import CloseReopenReportToggle from '~/close_reopen_report_toggle';
import IssuablesHelper from '~/helpers/issuables_helper';
......
/* eslint-disable no-var, comma-dangle, object-shorthand */
/* global Notes */
import * as urlUtils from '~/lib/utils/url_utility';
import MergeRequestTabs from '~/merge_request_tabs';
......@@ -7,7 +6,7 @@ import '~/commit/pipelines/pipelines_bundle';
import '~/breakpoints';
import '~/lib/utils/common_utils';
import Diff from '~/diff';
import '~/notes';
import Notes from '~/notes';
import 'vendor/jquery.scrollTo';
(function () {
......@@ -279,8 +278,8 @@ import 'vendor/jquery.scrollTo';
loadFixtures('merge_requests/diff_comment.html.raw');
$('body').attr('data-page', 'projects:merge_requests:show');
window.gl.ImageFile = () => {};
window.notes = new Notes('', []);
spyOn(window.notes, 'toggleDiffNote').and.callThrough();
Notes.initialize('', []);
spyOn(Notes.instance, 'toggleDiffNote').and.callThrough();
});
afterEach(() => {
......@@ -338,7 +337,7 @@ import 'vendor/jquery.scrollTo';
this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
expect(noteId.length).toBeGreaterThan(0);
expect(window.notes.toggleDiffNote).toHaveBeenCalledWith({
expect(Notes.instance.toggleDiffNote).toHaveBeenCalledWith({
target: jasmine.any(Object),
lineType: 'old',
forceShow: true,
......@@ -349,7 +348,7 @@ import 'vendor/jquery.scrollTo';
spyOn(urlUtils, 'getLocationHash').and.returnValue('note_something-that-does-not-exist');
this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
expect(window.notes.toggleDiffNote).not.toHaveBeenCalled();
expect(Notes.instance.toggleDiffNote).not.toHaveBeenCalled();
});
});
......@@ -359,7 +358,7 @@ import 'vendor/jquery.scrollTo';
this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
expect(noteLineNumId.length).toBeGreaterThan(0);
expect(window.notes.toggleDiffNote).not.toHaveBeenCalled();
expect(Notes.instance.toggleDiffNote).not.toHaveBeenCalled();
});
});
});
......@@ -393,7 +392,7 @@ import 'vendor/jquery.scrollTo';
this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
expect(noteId.length).toBeGreaterThan(0);
expect(window.notes.toggleDiffNote).toHaveBeenCalledWith({
expect(Notes.instance.toggleDiffNote).toHaveBeenCalledWith({
target: jasmine.any(Object),
lineType: 'new',
forceShow: true,
......@@ -404,7 +403,7 @@ import 'vendor/jquery.scrollTo';
spyOn(urlUtils, 'getLocationHash').and.returnValue('note_something-that-does-not-exist');
this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
expect(window.notes.toggleDiffNote).not.toHaveBeenCalled();
expect(Notes.instance.toggleDiffNote).not.toHaveBeenCalled();
});
});
......@@ -414,7 +413,7 @@ import 'vendor/jquery.scrollTo';
this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
expect(noteLineNumId.length).toBeGreaterThan(0);
expect(window.notes.toggleDiffNote).not.toHaveBeenCalled();
expect(Notes.instance.toggleDiffNote).not.toHaveBeenCalled();
});
});
});
......
/* eslint-disable space-before-function-paren, no-unused-expressions, no-var, object-shorthand, comma-dangle, max-len */
/* global Notes */
import * as urlUtils from '~/lib/utils/url_utility';
import 'autosize';
import '~/gl_form';
import '~/lib/utils/text_utility';
import '~/render_gfm';
import '~/notes';
import Notes from '~/notes';
(function() {
window.gon || (window.gon = {});
......
/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, new-parens, no-return-assign, new-cap, vars-on-top, max-len */
/* global Sidebar */
import '~/commons/bootstrap';
import '~/right_sidebar';
import Sidebar from '~/right_sidebar';
(function() {
var $aside, $icon, $labelsIcon, $page, $toggle, assertSidebarState;
......
require 'spec_helper'
describe MergeRequestSerializer do
let(:user) { build_stubbed(:user) }
let(:merge_request) { build_stubbed(:merge_request) }
let(:serializer) do
let(:user) { create(:user) }
let(:resource) { create(:merge_request) }
let(:json_entity) do
described_class.new(current_user: user)
.represent(resource, serializer: serializer)
.with_indifferent_access
end
describe '#represent' do
let(:opts) { { serializer: serializer_entity } }
subject { serializer.represent(merge_request, serializer: serializer_entity) }
context 'widget merge request serialization' do
let(:serializer) { 'widget' }
context 'when passing basic serializer param' do
let(:serializer_entity) { 'basic' }
it 'matches issue json schema' do
expect(json_entity).to match_schema('entities/merge_request_widget')
end
end
it 'calls super class #represent with correct params' do
expect_any_instance_of(BaseSerializer).to receive(:represent)
.with(merge_request, opts, MergeRequestBasicEntity)
context 'sidebar merge request serialization' do
let(:serializer) { 'sidebar' }
subject
end
it 'matches basic merge request json schema' do
expect(json_entity).to match_schema('entities/merge_request_basic')
end
end
context 'when serializer param is falsy' do
let(:serializer_entity) { nil }
context 'basic merge request serialization' do
let(:serializer) { 'basic' }
it 'matches basic merge request json schema' do
expect(json_entity).to match_schema('entities/merge_request_basic')
end
end
it 'calls super class #represent with correct params' do
expect_any_instance_of(BaseSerializer).to receive(:represent)
.with(merge_request, opts, MergeRequestEntity)
context 'no serializer' do
let(:serializer) { nil }
subject
end
it 'raises an error' do
expect { json_entity }.to raise_error(NoMethodError)
end
end
end
require 'spec_helper'
describe MergeRequestEntity do
describe MergeRequestWidgetEntity do
let(:project) { create :project, :repository }
let(:resource) { create(:merge_request, source_project: project, target_project: project) }
let(:user) { create(:user) }
......@@ -35,37 +35,6 @@ describe MergeRequestEntity do
end
end
it 'includes issues_links' do
issues_links = subject[:issues_links]
expect(issues_links).to include(:closing, :mentioned_but_not_closing,
:assign_to_closing)
end
it 'has Issuable attributes' do
expect(subject).to include(:id, :iid, :author_id, :description, :lock_version, :milestone_id,
:title, :updated_by_id, :created_at, :updated_at, :milestone, :labels)
end
it 'has time estimation attributes' do
expect(subject).to include(:time_estimate, :total_time_spent, :human_time_estimate, :human_total_time_spent)
end
it 'has important MergeRequest attributes' do
expect(subject).to include(:state, :deleted_at, :diff_head_sha, :merge_commit_message,
:has_conflicts, :has_ci, :merge_path,
:conflict_resolution_path,
:cancel_merge_when_pipeline_succeeds_path,
:create_issue_to_resolve_discussions_path,
:source_branch_path, :target_branch_commits_path,
:target_branch_tree_path, :commits_count, :merge_ongoing,
:ff_only_enabled,
## EE
:can_push_to_source_branch, :approvals_before_merge,
:squash, :rebase_commit_sha, :rebase_in_progress,
:approvals_path)
end
it 'has email_patches_path' do
expect(subject[:email_patches_path])
.to eq("/#{resource.project.full_path}/merge_requests/#{resource.iid}.patch")
......@@ -120,18 +89,6 @@ describe MergeRequestEntity do
end
end
it 'includes merge_event' do
create(:event, :merged, author: user, project: resource.project, target: resource)
expect(subject[:merge_event]).to include(:author, :updated_at)
end
it 'includes closed_event' do
create(:event, :closed, author: user, project: resource.project, target: resource)
expect(subject[:closed_event]).to include(:author, :updated_at)
end
describe 'diverged_commits_count' do
context 'when MR open and its diverging' do
it 'returns diverged commits count' do
......
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