Commit bce9f31c authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch 'master' into 27932-merge-request-pipelines-displays-json

* master: (32 commits)
  Fix contribution activity alignment
  Adds a null check to build notifications
  Add a spec for our custom GemFetcher cop
  add CHANGELOG.md entry for !9078
  approve new dependencies
  update karma deps to work with webpack 2
  upgrade to webpack 2.2.x
  add CHANGELOG.md entry for !9072
  approve MIT license for wordwrap submodule
  fix failing karma test
  upgrade babel to v6
  exclude node_modules from imports-loader wrapper
  Allow copying a created branch name to the clipboard.
  Uses shared vue resource interceptor
  Refactored diff notes Vue app
  Fix expand_collapse_diffs specs
  Update the rspec_profiling gem to 0.0.5
  Fix menu link in CONTRIBUTING
  adds max-width only for new filter dropdown
  adds changelog
  ...
parents 5d0c5663 57d5a549
......@@ -163,64 +163,7 @@ spinach 7 10: *spinach-knapsack
spinach 8 10: *spinach-knapsack
spinach 9 10: *spinach-knapsack
# Execute all testing suites against Ruby 2.1
.ruby-21: &ruby-21
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.1-git-2.7-phantomjs-2.1"
<<: *use-db
only:
- master@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee
- master@gitlab/gitlabhq
- master@gitlab/gitlab-ee
cache:
key: "ruby21"
paths:
- vendor/ruby
.rspec-knapsack-ruby21: &rspec-knapsack-ruby21
<<: *rspec-knapsack
<<: *dedicated-runner
<<: *ruby-21
.spinach-knapsack-ruby21: &spinach-knapsack-ruby21
<<: *spinach-knapsack
<<: *dedicated-runner
<<: *ruby-21
rspec 0 20 ruby21: *rspec-knapsack-ruby21
rspec 1 20 ruby21: *rspec-knapsack-ruby21
rspec 2 20 ruby21: *rspec-knapsack-ruby21
rspec 3 20 ruby21: *rspec-knapsack-ruby21
rspec 4 20 ruby21: *rspec-knapsack-ruby21
rspec 5 20 ruby21: *rspec-knapsack-ruby21
rspec 6 20 ruby21: *rspec-knapsack-ruby21
rspec 7 20 ruby21: *rspec-knapsack-ruby21
rspec 8 20 ruby21: *rspec-knapsack-ruby21
rspec 9 20 ruby21: *rspec-knapsack-ruby21
rspec 10 20 ruby21: *rspec-knapsack-ruby21
rspec 11 20 ruby21: *rspec-knapsack-ruby21
rspec 12 20 ruby21: *rspec-knapsack-ruby21
rspec 13 20 ruby21: *rspec-knapsack-ruby21
rspec 14 20 ruby21: *rspec-knapsack-ruby21
rspec 15 20 ruby21: *rspec-knapsack-ruby21
rspec 16 20 ruby21: *rspec-knapsack-ruby21
rspec 17 20 ruby21: *rspec-knapsack-ruby21
rspec 18 20 ruby21: *rspec-knapsack-ruby21
rspec 19 20 ruby21: *rspec-knapsack-ruby21
spinach 0 10 ruby21: *spinach-knapsack-ruby21
spinach 1 10 ruby21: *spinach-knapsack-ruby21
spinach 2 10 ruby21: *spinach-knapsack-ruby21
spinach 3 10 ruby21: *spinach-knapsack-ruby21
spinach 4 10 ruby21: *spinach-knapsack-ruby21
spinach 5 10 ruby21: *spinach-knapsack-ruby21
spinach 6 10 ruby21: *spinach-knapsack-ruby21
spinach 7 10 ruby21: *spinach-knapsack-ruby21
spinach 8 10 ruby21: *spinach-knapsack-ruby21
spinach 9 10 ruby21: *spinach-knapsack-ruby21
# Other generic tests
.ruby-static-analysis: &ruby-static-analysis
variables:
SIMPLECOV: "false"
......
......@@ -6,13 +6,13 @@
(How one can reproduce the issue - this is very important)
### Expected behavior
### What is the current *bug* behavior?
(What you should see instead)
(What actually happens)
### Actual behavior
### What is the expected *correct* behavior?
(What actually happens)
(What you should see instead)
### Relevant logs and/or screenshots
......@@ -23,23 +23,23 @@ logs, and code as it's very hard to read otherwise.)
(If you are reporting a bug on GitLab.com, write: This bug happens on GitLab.com)
#### Results of GitLab application Check
#### Results of GitLab environment info
(For installations with omnibus-gitlab package run and paste the output of:
`sudo gitlab-rake gitlab:check SANITIZE=true`)
`sudo gitlab-rake gitlab:env:info`)
(For installations from source run and paste the output of:
`sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true`)
(we will only investigate if the tests are passing)
`sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`)
#### Results of GitLab environment info
#### Results of GitLab application Check
(For installations with omnibus-gitlab package run and paste the output of:
`sudo gitlab-rake gitlab:env:info`)
`sudo gitlab-rake gitlab:check SANITIZE=true`)
(For installations from source run and paste the output of:
`sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`)
`sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true`)
(we will only investigate if the tests are passing)
### Possible fixes
......
......@@ -31,8 +31,7 @@ AllCops:
- 'lib/gitlab/seeder.rb'
- 'generator_templates/**/*'
##################### Style ##################################
# Style #######################################################################
# Check indentation of private/protected visibility modifiers.
Style/AccessModifierIndentation:
......@@ -471,7 +470,7 @@ Style/WhileUntilModifier:
Style/WordArray:
Enabled: false
#################### Metrics ################################
# Metrics #####################################################################
# A calculated magnitude based on number of assignments,
# branches, and conditions.
......@@ -516,8 +515,7 @@ Metrics/PerceivedComplexity:
Enabled: true
Max: 18
#################### Lint ################################
# Lint ########################################################################
# Checks for useless access modifiers.
Lint/UselessAccessModifier:
......@@ -679,8 +677,7 @@ Lint/UselessSetterCall:
Lint/Void:
Enabled: true
##################### Performance ############################
# Performance #################################################################
# Use `casecmp` rather than `downcase ==`.
Performance/Casecmp:
......@@ -718,8 +715,7 @@ Performance/StringReplacement:
Performance/TimesMap:
Enabled: true
##################### Rails ##################################
# Rails #######################################################################
# Enables Rails cops.
Rails:
......@@ -767,7 +763,7 @@ Rails/ReadWriteAttribute:
Rails/ScopeArgs:
Enabled: true
##################### RSpec ##################################
# RSpec #######################################################################
# Check that instances are not being stubbed globally.
RSpec/AnyInstance:
......@@ -828,3 +824,9 @@ RSpec/NotToNot:
# Prefer using verifying doubles over normal doubles.
RSpec/VerifiedDoubles:
Enabled: false
# Custom ######################################################################
# Disallow the `git` and `github` arguments in the Gemfile.
GemFetcher:
Enabled: true
......@@ -15,7 +15,7 @@
- [Issue weight](#issue-weight)
- [Regression issues](#regression-issues)
- [Technical debt](#technical-debt)
- [Stewardship][#stewardship]
- [Stewardship](#stewardship)
- [Merge requests](#merge-requests)
- [Merge request guidelines](#merge-request-guidelines)
- [Contribution acceptance criteria](#contribution-acceptance-criteria)
......
......@@ -284,7 +284,7 @@ group :development, :test do
gem 'rspec-retry', '~> 0.4.5'
gem 'spinach-rails', '~> 0.2.1'
gem 'spinach-rerun-reporter', '~> 0.0.2'
gem 'rspec_profiling'
gem 'rspec_profiling', '~> 0.0.5'
# Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826)
gem 'minitest', '~> 5.7.0'
......
......@@ -638,7 +638,7 @@ GEM
rspec-retry (0.4.5)
rspec-core
rspec-support (3.5.0)
rspec_profiling (0.0.4)
rspec_profiling (0.0.5)
activerecord
pg
rails
......@@ -738,7 +738,7 @@ GEM
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.3.11)
sqlite3 (1.3.13)
stackprof (0.2.10)
state_machines (0.4.0)
state_machines-activemodel (0.4.0)
......@@ -962,7 +962,7 @@ DEPENDENCIES
rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.5.0)
rspec-retry (~> 0.4.5)
rspec_profiling
rspec_profiling (~> 0.0.5)
rubocop (~> 0.46.0)
rubocop-rspec (~> 1.9.1)
ruby-fogbugz (~> 0.2.1)
......@@ -1011,4 +1011,4 @@ DEPENDENCIES
wikicloth (= 0.8.1)
BUNDLED WITH
1.14.2
1.14.3
Copyright (c) 2011-2016 GitLab B.V.
Copyright (c) 2011-2017 GitLab B.V.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
......@@ -76,7 +76,7 @@ require('./lib/utils/url_utility');
const diffFile = diffTitle.closest('.diff-file');
const nothingHereBlock = $('.nothing-here-block:visible', diffFile);
if (nothingHereBlock.length) {
const clickTarget = $('.file-title, .click-to-expand', diffFile);
const clickTarget = $('.js-file-title, .click-to-expand', diffFile);
diffFile.data('singleFileDiff').toggleDiff(clickTarget, () => {
this.highlighSelectedLine();
if (cb) cb();
......
/* eslint-disable comma-dangle, object-shorthand, func-names, no-else-return, quotes, no-lonely-if, max-len */
/* global Vue */
/* global CommentsStore */
const Vue = require('vue');
(() => {
const CommentAndResolveBtn = Vue.extend({
......@@ -9,13 +9,11 @@
},
data() {
return {
textareaIsEmpty: true
textareaIsEmpty: true,
discussion: {},
};
},
computed: {
discussion: function () {
return CommentsStore.state[this.discussionId];
},
showButton: function () {
if (this.discussion) {
return this.discussion.isResolvable();
......@@ -42,6 +40,9 @@
}
}
},
created() {
this.discussion = CommentsStore.state[this.discussionId];
},
mounted: function () {
const $textarea = $(`#new-discussion-note-form-${this.discussionId} .note-textarea`);
this.textareaIsEmpty = $textarea.val() === '';
......
/* eslint-disable comma-dangle, object-shorthand, func-names, no-else-return, guard-for-in, no-restricted-syntax, one-var, space-before-function-paren, no-lonely-if, no-continue, brace-style, max-len, quotes */
/* global Vue */
/* global DiscussionMixins */
/* global CommentsStore */
const Vue = require('vue');
(() => {
const JumpToDiscussion = Vue.extend({
......@@ -12,12 +12,10 @@
data: function () {
return {
discussions: CommentsStore.state,
discussion: {},
};
},
computed: {
discussion: function () {
return this.discussions[this.discussionId];
},
allResolved: function () {
return this.unresolvedDiscussionCount === 0;
},
......@@ -186,7 +184,10 @@
offset: -($('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight())
});
}
}
},
created() {
this.discussion = this.discussions[this.discussionId];
},
});
Vue.component('jump-to-discussion', JumpToDiscussion);
......
/* eslint-disable comma-dangle, object-shorthand, func-names, quote-props, no-else-return, camelcase, no-new, max-len */
/* global Vue */
/* global CommentsStore */
/* global ResolveService */
/* global Flash */
const Vue = require('vue');
(() => {
const ResolveBtn = Vue.extend({
......@@ -10,14 +10,14 @@
noteId: Number,
discussionId: String,
resolved: Boolean,
projectPath: String,
canResolve: Boolean,
resolvedBy: String
},
data: function () {
return {
discussions: CommentsStore.state,
loading: false
loading: false,
note: {},
};
},
watch: {
......@@ -30,13 +30,6 @@
discussion: function () {
return this.discussions[this.discussionId];
},
note: function () {
if (this.discussion) {
return this.discussion.getNote(this.noteId);
} else {
return undefined;
}
},
buttonText: function () {
if (this.isResolved) {
return `Resolved by ${this.resolvedByName}`;
......@@ -73,10 +66,10 @@
if (this.isResolved) {
promise = ResolveService
.unresolve(this.projectPath, this.noteId);
.unresolve(this.noteId);
} else {
promise = ResolveService
.resolve(this.projectPath, this.noteId);
.resolve(this.noteId);
}
promise.then((response) => {
......@@ -106,6 +99,8 @@
},
created: function () {
CommentsStore.create(this.discussionId, this.noteId, this.canResolve, this.resolved, this.resolvedBy);
this.note = this.discussion.getNote(this.noteId);
}
});
......
/* eslint-disable comma-dangle, object-shorthand, func-names, no-param-reassign */
/* global Vue */
/* global DiscussionMixins */
/* global CommentsStore */
const Vue = require('vue');
((w) => {
w.ResolveCount = Vue.extend({
......
/* eslint-disable object-shorthand, func-names, space-before-function-paren, comma-dangle, no-else-return, quotes, max-len */
/* global Vue */
/* global CommentsStore */
/* global ResolveService */
const Vue = require('vue');
(() => {
const ResolveDiscussionBtn = Vue.extend({
props: {
discussionId: String,
mergeRequestId: Number,
projectPath: String,
canResolve: Boolean,
},
data: function() {
return {
discussions: CommentsStore.state
discussion: {},
};
},
computed: {
discussion: function () {
return this.discussions[this.discussionId];
},
showButton: function () {
if (this.discussion) {
return this.discussion.isResolvable();
......@@ -51,11 +48,13 @@
},
methods: {
resolve: function () {
ResolveService.toggleResolveForDiscussion(this.projectPath, this.mergeRequestId, this.discussionId);
ResolveService.toggleResolveForDiscussion(this.mergeRequestId, this.discussionId);
}
},
created: function () {
CommentsStore.createDiscussion(this.discussionId, this.canResolve);
this.discussion = CommentsStore.state[this.discussionId];
}
});
......
......@@ -3,6 +3,7 @@
/* global ResolveCount */
function requireAll(context) { return context.keys().map(context); }
const Vue = require('vue');
requireAll(require.context('./models', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./stores', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./services', false, /^\.\/.*\.(js|es6)$/));
......@@ -10,11 +11,14 @@ requireAll(require.context('./mixins', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./components', false, /^\.\/.*\.(js|es6)$/));
$(() => {
const projectPath = document.querySelector('.merge-request').dataset.projectPath;
const COMPONENT_SELECTOR = 'resolve-btn, resolve-discussion-btn, jump-to-discussion, comment-and-resolve-btn';
window.gl = window.gl || {};
window.gl.diffNoteApps = {};
window.ResolveService = new gl.DiffNotesResolveServiceClass(projectPath);
gl.diffNotesCompileComponents = () => {
const $components = $(COMPONENT_SELECTOR).filter(function () {
return $(this).closest('resolve-count').length !== 1;
......
/* eslint-disable class-methods-use-this, one-var, camelcase, no-new, comma-dangle, no-param-reassign, max-len */
/* global Vue */
/* global Flash */
/* global CommentsStore */
((w) => {
class ResolveServiceClass {
constructor() {
this.noteResource = Vue.resource('notes{/noteId}/resolve');
this.discussionResource = Vue.resource('merge_requests{/mergeRequestId}/discussions{/discussionId}/resolve');
}
const Vue = window.Vue = require('vue');
window.Vue.use(require('vue-resource'));
require('../../vue_shared/vue_resource_interceptor');
setCSRF() {
Vue.http.headers.common['X-CSRF-Token'] = $.rails.csrfToken();
}
(() => {
window.gl = window.gl || {};
prepareRequest(root) {
this.setCSRF();
Vue.http.options.root = root;
class ResolveServiceClass {
constructor(root) {
this.noteResource = Vue.resource(`${root}/notes{/noteId}/resolve`);
this.discussionResource = Vue.resource(`${root}/merge_requests{/mergeRequestId}/discussions{/discussionId}/resolve`);
}
resolve(projectPath, noteId) {
this.prepareRequest(projectPath);
resolve(noteId) {
return this.noteResource.save({ noteId }, {});
}
unresolve(projectPath, noteId) {
this.prepareRequest(projectPath);
unresolve(noteId) {
return this.noteResource.delete({ noteId }, {});
}
toggleResolveForDiscussion(projectPath, mergeRequestId, discussionId) {
toggleResolveForDiscussion(mergeRequestId, discussionId) {
const discussion = CommentsStore.state[discussionId];
const isResolved = discussion.isResolved();
let promise;
if (isResolved) {
promise = this.unResolveAll(projectPath, mergeRequestId, discussionId);
promise = this.unResolveAll(mergeRequestId, discussionId);
} else {
promise = this.resolveAll(projectPath, mergeRequestId, discussionId);
promise = this.resolveAll(mergeRequestId, discussionId);
}
promise.then((response) => {
......@@ -62,11 +54,9 @@
});
}
resolveAll(projectPath, mergeRequestId, discussionId) {
resolveAll(mergeRequestId, discussionId) {
const discussion = CommentsStore.state[discussionId];
this.prepareRequest(projectPath);
discussion.loading = true;
return this.discussionResource.save({
......@@ -75,11 +65,9 @@
}, {});
}
unResolveAll(projectPath, mergeRequestId, discussionId) {
unResolveAll(mergeRequestId, discussionId) {
const discussion = CommentsStore.state[discussionId];
this.prepareRequest(projectPath);
discussion.loading = true;
return this.discussionResource.delete({
......@@ -89,5 +77,5 @@
}
}
w.ResolveService = new ResolveServiceClass();
})(window);
gl.DiffNotesResolveServiceClass = ResolveServiceClass;
})();
......@@ -4,7 +4,7 @@
class FilteredSearchDropdown {
constructor(droplab, dropdown, input, filter) {
this.droplab = droplab;
this.hookId = input.getAttribute('data-id');
this.hookId = input && input.getAttribute('data-id');
this.input = input;
this.filter = filter;
this.dropdown = dropdown;
......
......@@ -154,7 +154,7 @@ require('./smart_interval');
return $.getJSON(this.opts.ci_status_url, (function(_this) {
return function(data) {
var message, status, title;
if (data.status === '') {
if (!data.status) {
return;
}
if (data.environments && data.environments.length) _this.renderEnvironments(data.environments);
......
......@@ -455,7 +455,7 @@ require('vendor/task_list');
var mergeRequestId = $form.data('noteable-iid');
if (ResolveService != null) {
ResolveService.toggleResolveForDiscussion(projectPath, mergeRequestId, discussionId);
ResolveService.toggleResolveForDiscussion(mergeRequestId, discussionId);
}
}
......
......@@ -33,13 +33,13 @@
this.$toggleIcon.addClass('fa-caret-down');
}
$('.file-title, .click-to-expand', this.file).on('click', (function (e) {
$('.js-file-title, .click-to-expand', this.file).on('click', (function (e) {
this.toggleDiff($(e.target));
}).bind(this));
}
SingleFileDiff.prototype.toggleDiff = function($target, cb) {
if (!$target.hasClass('file-title') && !$target.hasClass('click-to-expand') && !$target.hasClass('diff-toggle-caret')) return;
if (!$target.hasClass('js-file-title') && !$target.hasClass('click-to-expand') && !$target.hasClass('diff-toggle-caret')) return;
this.isOpen = !this.isOpen;
if (!this.isOpen && !this.hasError) {
this.content.hide();
......
......@@ -9,6 +9,8 @@
}
.user-calendar-activities {
direction: ltr;
.str-truncated {
max-width: 70%;
}
......
......@@ -125,7 +125,6 @@
top: 100%;
left: 0;
z-index: 9;
max-width: 280px;
min-width: 240px;
margin-top: 2px;
margin-bottom: 0;
......@@ -137,6 +136,10 @@
border-radius: $border-radius-base;
box-shadow: 0 2px 4px $dropdown-shadow-color;
.filtered-search-input-container & {
max-width: 280px;
}
&.is-loading {
.dropdown-content {
display: none;
......
......@@ -231,3 +231,46 @@ span.idiff {
}
}
}
.file-title-flex-parent {
display: flex;
align-items: center;
justify-content: space-between;
background-color: $gray-light;
border-bottom: 1px solid $border-color;
padding: 5px $gl-padding;
margin: 0;
border-radius: 3px 3px 0 0;
.file-header-content {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding-right: 30px;
position: relative;
}
.btn-clipboard {
position: absolute;
right: 0;
}
a {
color: $gl-text-color;
}
small {
margin: 0 10px 0 0;
}
.file-actions {
white-space: nowrap;
.btn {
padding: 0 10px;
font-size: 13px;
line-height: 28px;
display: inline-block;
}
}
}
......@@ -34,9 +34,14 @@
}
}
.file-title {
.file-title,
.file-title-flex-parent {
cursor: pointer;
a:hover {
text-decoration: none;
}
&:hover {
background-color: $gray-normal;
}
......
......@@ -68,8 +68,12 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
def access_levels_options
{
push_access_levels: ProtectedBranch::PushAccessLevel.human_access_levels.map { |id, text| { id: id, text: text, before_divider: true } },
merge_access_levels: ProtectedBranch::MergeAccessLevel.human_access_levels.map { |id, text| { id: id, text: text, before_divider: true } }
push_access_levels: {
"Roles" => ProtectedBranch::PushAccessLevel.human_access_levels.map { |id, text| { id: id, text: text, before_divider: true } },
},
merge_access_levels: {
"Roles" => ProtectedBranch::MergeAccessLevel.human_access_levels.map { |id, text| { id: id, text: text, before_divider: true } }
}
}
end
......
......@@ -18,7 +18,7 @@
.tab-pane{ class: (klass == Gitlab::GitLogger ? 'active' : ''),
id: klass::file_name_noext }
.file-holder#README
.file-title
.js-file-title.file-title
%i.fa.fa-file
= klass::file_name
.pull-right
......
......@@ -11,7 +11,7 @@
.form-group
.col-sm-12
.file-holder
.file-title.clearfix
.js-file-title.file-title.clearfix
Content of .gitlab-ci.yml
#ci-editor.ci-editor= @content
= text_area_tag(:content, @content, class: 'hidden form-control span1', rows: 7, require: true)
......
......@@ -2,7 +2,7 @@
- blob = discussion.blob
.diff-file.file-holder
.file-title
.js-file-title.file-title
= render "projects/diffs/file_header", diff_file: diff_file, blob: blob, diff_commit: diff_file.content_commit, project: discussion.project, url: discussion_diff_path(discussion)
.diff-content.code.js-syntax-highlight
......
- if discussion.for_merge_request?
%resolve-discussion-btn{ ":project-path" => "'#{project_path(discussion.project)}'",
":discussion-id" => "'#{discussion.id}'",
%resolve-discussion-btn{ ":discussion-id" => "'#{discussion.id}'",
":merge-request-id" => discussion.noteable.iid,
":can-resolve" => discussion.can_resolve?(current_user),
"inline-template" => true }
......
......@@ -528,7 +528,7 @@
- blob = Snippet.new(content: "Wow\nSuch\nFile")
.example
.file-holder
.file-title
.js-file-title.file-title
Awesome file
.file-actions
.btn-group
......
......@@ -10,6 +10,7 @@
- if @project && event.project != @project
%span at
%strong= link_to_project event.project
= clipboard_button(clipboard_text: event.ref_name, class: 'btn-clipboard btn-transparent', title: 'Copy branch to clipboard')
#{time_ago_with_tooltip(event.created_at)}
.pull-right
......
......@@ -7,7 +7,7 @@
#blob-content-holder.tree-holder
.file-holder
.file-title
.js-file-title.file-title
= blob_icon @blob.mode, @blob.name
%strong
= @path
......
......@@ -24,7 +24,7 @@
#blob-content-holder.blob-content-holder
%article.file-holder
.file-title
.js-file-title.file-title
= blob_icon blob.mode, blob.name
%strong
= blob.name
......
.file-holder.file.append-bottom-default
.file-title.clearfix
.js-file-title.file-title.clearfix
.editor-ref
= icon('code-fork')
= ref
......
- environment = local_assigns.fetch(:environment, nil)
.diff-file.file-holder{ id: file_hash, data: diff_file_html_data(project, diff_file.file_path, diff_commit.id) }
.file-title
= render "projects/diffs/file_header", diff_file: diff_file, blob: blob, diff_commit: diff_commit, project: project, url: "##{file_hash}"
.js-file-title.file-title-flex-parent
.file-header-content
= render "projects/diffs/file_header", diff_file: diff_file, blob: blob, diff_commit: diff_commit, project: project, url: "##{file_hash}"
- unless diff_file.submodule?
.file-actions.hidden-xs
......
......@@ -10,13 +10,13 @@
- if diff_file.renamed_file
- old_path, new_path = mark_inline_diffs(diff_file.old_path, diff_file.new_path)
%strong
%strong.file-title-name.has-tooltip{ data: { title: old_path } }
= old_path
&rarr;
%strong
%strong.file-title-name.has-tooltip{ data: { title: new_path } }
= new_path
- else
%strong
%strong.file-title-name.has-tooltip{ data: { title: diff_file.new_path } }
= diff_file.new_path
- if diff_file.deleted_file
deleted
......
......@@ -3,10 +3,9 @@
- page_description @merge_request.description
- page_card_attributes @merge_request.card_attributes
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('lib_vue')
= page_specific_javascript_bundle_tag('diff_notes')
.merge-request{ 'data-url' => merge_request_path(@merge_request) }
.merge-request{ 'data-url' => merge_request_path(@merge_request), 'data-project-path' => project_path(@merge_request.project) }
= render "projects/merge_requests/show/mr_title"
.merge-request-details.issuable-details{ data: { id: @merge_request.project.id } }
......
......@@ -23,7 +23,7 @@
.files-wrapper{ "v-if" => "!isLoading && !hasError" }
.files
.diff-file.file-holder.conflict{ "v-for" => "file in conflictsData.files" }
.file-title
.js-file-title.file-title
%i.fa.fa-fw{ ":class" => "file.iconClass" }
%strong {{file.filePath}}
= render partial: 'projects/merge_requests/conflicts/file_actions'
......
......@@ -30,8 +30,7 @@
- if note.resolvable?
- can_resolve = can?(current_user, :resolve_note, note)
%resolve-btn{ "project-path" => "#{project_path(note.project)}",
"discussion-id" => "#{note.discussion_id}",
%resolve-btn{ "discussion-id" => "#{note.discussion_id}",
":note-id" => note.id,
":resolved" => note.resolved?,
":can-resolve" => can_resolve,
......
......@@ -4,7 +4,7 @@
.project-snippets
%article.file-holder.snippet-file-content
.file-title
.js-file-title.file-title
= blob_icon 0, @snippet.file_name
= @snippet.file_name
.file-actions
......
%article.file-holder.readme-holder
.file-title
.js-file-title.file-title
= blob_icon readme.mode, readme.name
= link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@ref, @path, readme.name)) do
%strong
......
- file_name, blob = blob
.blob-result
.file-holder
.file-title
.js-file-title.file-title
- ref = @search_results.repository_ref
- blob_link = namespace_project_blob_path(@project.namespace, @project, tree_join(ref, file_name))
= link_to blob_link do
......
......@@ -14,7 +14,7 @@
- snippet_path = reliable_snippet_path(snippet)
= link_to snippet_path do
.file-holder
.file-title
.js-file-title.file-title
%i.fa.fa-file
%strong= snippet.file_name
- if markup?(snippet.file_name)
......
- wiki_blob = parse_search_result(wiki_blob)
.blob-result
.file-holder
.file-title
.js-file-title.file-title
= link_to namespace_project_wiki_path(@project.namespace, @project, wiki_blob.basename) do
%i.fa.fa-file
%strong
......
......@@ -18,7 +18,7 @@
= f.label :file_name, "File", class: 'control-label'
.col-sm-10
.file-holder.snippet
.file-title
.js-file-title.file-title
= f.text_field :file_name, placeholder: "Optionally name this file to add code highlighting, e.g. example.rb for Ruby.", class: 'form-control snippet-file-name'
.file-content.code
%pre#editor= @snippet.content
......
......@@ -26,7 +26,7 @@
= @file_sample.events
%article.file-holder
.file-title
.js-file-title.file-title
%i.fa.fa-file-text-o.fa-fw
%strong
= @file_sample.file
......
......@@ -3,7 +3,7 @@
= render 'shared/snippets/header'
%article.file-holder.snippet-file-content
.file-title
.js-file-title.file-title
= blob_icon 0, @snippet.file_name
= @snippet.file_name
.file-actions
......
---
title: Responsive title in diffs inline, side by side, with and without sidebar
merge_request: 8475
author:
---
title: Fixes dropdown width in admin project page
merge_request: 9002
author:
---
title: Fix contribution activity alignment
merge_request:
author:
---
title: Added the ability to copy a branch name to the clipboard
merge_request: 9103
author: Glenn Sayers
---
title: Update API docs for new namespace format
merge_request: 9073
author: Markus Koller
---
title: Added headers to protected branch access dropdowns
merge_request:
author:
---
title: upgrade babel 5.8.x to babel 6.22.x
merge_request: 9072
author:
---
title: upgrade to webpack v2.2
merge_request: 9078
author:
......@@ -302,3 +302,21 @@
:why: https://github.com/dchest/tweetnacl-js/blob/master/LICENSE
:versions: []
:when: 2017-01-14 20:10:57.812077000 Z
- - :approve
- wordwrap
- :who: Mike Greiling
:why: https://github.com/substack/node-wordwrap/blob/0.0.3/LICENSE
:versions: []
:when: 2017-02-08 20:17:13.084968000 Z
- - :approve
- spdx-expression-parse
- :who: Mike Greiling
:why: https://github.com/kemitchell/spdx-expression-parse.js/blob/v1.0.4/LICENSE
:versions: []
:when: 2017-02-08 22:33:01.806977000 Z
- - :approve
- spdx-license-ids
- :who: Mike Greiling
:why: https://github.com/shinnn/spdx-license-ids/blob/v1.2.2/LICENSE
:versions: []
:when: 2017-02-08 22:35:00.225232000 Z
......@@ -48,26 +48,23 @@ var config = {
devtool: 'inline-source-map',
module: {
loaders: [
rules: [
{
test: /\.(js|es6)$/,
exclude: /(node_modules|vendor\/assets)/,
loader: 'babel-loader',
query: {
// 'use strict' was broken in sprockets-es6 due to sprockets concatination method.
// many es5 strict errors which were never caught ended up in our es6 assets as a result.
// this hack is necessary until they can be fixed.
blacklist: ['useStrict']
options: {
presets: [
["es2015", {"modules": false}],
'stage-2'
]
}
},
{
test: /\.(js|es6)$/,
exclude: /node_modules/,
loader: 'imports-loader',
query: 'this=>window'
},
{
test: /\.json$/,
loader: 'json-loader'
options: 'this=>window'
}
]
},
......@@ -88,7 +85,7 @@ var config = {
],
resolve: {
extensions: ['', '.js', '.es6', '.js.es6'],
extensions: ['.js', '.es6', '.js.es6'],
alias: {
'~': path.join(ROOT_PATH, 'app/assets/javascripts'),
'bootstrap/js': 'bootstrap-sass/assets/javascripts/bootstrap',
......@@ -104,14 +101,16 @@ if (IS_PRODUCTION) {
config.devtool = 'source-map';
config.plugins.push(
new webpack.NoErrorsPlugin(),
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false
}),
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false }
sourceMap: true
}),
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify('production') }
}),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurrenceOrderPlugin()
})
);
}
......
......@@ -106,15 +106,7 @@ Example response:
"id": 5,
"name": "Experimental",
"path": "h5bp",
"owner_id": null,
"created_at": "2016-04-05T21:40:49.152Z",
"updated_at": "2016-04-07T08:07:48.466Z",
"description": "foo",
"avatar": {
"url": null
},
"share_with_group_lock": false,
"visibility_level": 10
"kind": "group"
},
"avatar_url": null,
"star_count": 1,
......@@ -190,15 +182,7 @@ Example response:
"id": 4,
"name": "Twitter",
"path": "twitter",
"owner_id": null,
"created_at": "2016-06-17T07:47:24.216Z",
"updated_at": "2016-06-17T07:47:24.216Z",
"description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
"avatar": {
"url": null
},
"share_with_group_lock": false,
"visibility_level": 20
"kind": "group"
},
"avatar_url": null,
"star_count": 0,
......@@ -237,15 +221,7 @@ Example response:
"id": 4,
"name": "Twitter",
"path": "twitter",
"owner_id": null,
"created_at": "2016-06-17T07:47:24.216Z",
"updated_at": "2016-06-17T07:47:24.216Z",
"description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
"avatar": {
"url": null
},
"share_with_group_lock": false,
"visibility_level": 20
"kind": "group"
},
"avatar_url": null,
"star_count": 0,
......@@ -286,15 +262,7 @@ Example response:
"id": 5,
"name": "H5bp",
"path": "h5bp",
"owner_id": null,
"created_at": "2016-06-17T07:47:26.621Z",
"updated_at": "2016-06-17T07:47:26.621Z",
"description": "Id consequatur rem vel qui doloremque saepe.",
"avatar": {
"url": null
},
"share_with_group_lock": false,
"visibility_level": 20
"kind": "group"
},
"avatar_url": null,
"star_count": 0,
......@@ -416,15 +384,7 @@ Example response:
"id": 5,
"name": "Experimental",
"path": "h5bp",
"owner_id": null,
"created_at": "2016-04-05T21:40:49.152Z",
"updated_at": "2016-04-07T08:07:48.466Z",
"description": "foo",
"avatar": {
"url": null
},
"share_with_group_lock": false,
"visibility_level": 10
"kind": "group"
},
"avatar_url": null,
"star_count": 1,
......
......@@ -57,7 +57,7 @@ Once you have the authorization code you can request an `access_token` using the
```
parameters = 'client_id=APP_ID&client_secret=APP_SECRET&code=RETURNED_CODE&grant_type=authorization_code&redirect_uri=REDIRECT_URI'
RestClient.post 'http://localhost:3000/oauth/token', parameters
RestClient.post 'http://gitlab.example.com/oauth/token', parameters
# The response will be
{
......@@ -77,13 +77,13 @@ You can now make requests to the API with the access token returned.
The access token allows you to make requests to the API on a behalf of a user.
```
GET https://localhost:3000/api/v3/user?access_token=OAUTH-TOKEN
GET https://gitlab.example.com/api/v3/user?access_token=OAUTH-TOKEN
```
Or you can put the token to the Authorization header:
```
curl --header "Authorization: Bearer OAUTH-TOKEN" https://localhost:3000/api/v3/user
curl --header "Authorization: Bearer OAUTH-TOKEN" https://gitlab.example.com/api/v3/user
```
## Resource Owner Password Credentials
......
......@@ -72,13 +72,10 @@ Parameters:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
"created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 3,
"name": "Diaspora",
"owner_id": 1,
"path": "diaspora",
"updated_at": "2013-09-30T13:46:02Z"
"kind": "group"
},
"archived": false,
"avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png",
......@@ -125,13 +122,10 @@ Parameters:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
"created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 4,
"name": "Brightbox",
"owner_id": 1,
"path": "brightbox",
"updated_at": "2013-09-30T13:46:02Z"
"kind": "group"
},
"permissions": {
"project_access": {
......@@ -210,13 +204,10 @@ Parameters:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
"created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 3,
"name": "Diaspora",
"owner_id": 1,
"path": "diaspora",
"updated_at": "2013-09-30T13:46:02Z"
"kind": "group"
},
"archived": false,
"avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png",
......@@ -260,13 +251,10 @@ Parameters:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
"created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 4,
"name": "Brightbox",
"owner_id": 1,
"path": "brightbox",
"updated_at": "2013-09-30T13:46:02Z"
"kind": "group"
},
"permissions": {
"project_access": {
......@@ -398,13 +386,10 @@ Parameters:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
"created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 3,
"name": "Diaspora",
"owner_id": 1,
"path": "diaspora",
"updated_at": "2013-09-30T13:46:02Z"
"kind": "group"
},
"permissions": {
"project_access": {
......@@ -779,13 +764,10 @@ Example response:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
"created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 3,
"name": "Diaspora",
"owner_id": 1,
"path": "diaspora",
"updated_at": "2013-09-30T13:46:02Z"
"kind": "group"
},
"archived": true,
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
......@@ -847,13 +829,10 @@ Example response:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
"created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 3,
"name": "Diaspora",
"owner_id": 1,
"path": "diaspora",
"updated_at": "2013-09-30T13:46:02Z"
"kind": "group"
},
"archived": true,
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
......@@ -921,13 +900,10 @@ Example response:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
"created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 3,
"name": "Diaspora",
"owner_id": 1,
"path": "diaspora",
"updated_at": "2013-09-30T13:46:02Z"
"kind": "group"
},
"permissions": {
"project_access": {
......@@ -1006,13 +982,10 @@ Example response:
"last_activity_at": "2013-09-30T13:46:02Z",
"creator_id": 3,
"namespace": {
"created_at": "2013-09-30T13:46:02Z",
"description": "",
"id": 3,
"name": "Diaspora",
"owner_id": 1,
"path": "diaspora",
"updated_at": "2013-09-30T13:46:02Z"
"kind": "group"
},
"permissions": {
"project_access": {
......
@snippets
Feature: Snippets User
Background:
Given I sign in as a user
And I have public "Personal snippet one" snippet
And I have private "Personal snippet private" snippet
And I have internal "Personal snippet internal" snippet
Scenario: I should see all my snippets
Given I visit my snippets page
Then I should see "Personal snippet one" in snippets
And I should see "Personal snippet private" in snippets
And I should see "Personal snippet internal" in snippets
Scenario: I can see only my private snippets
Given I visit my snippets page
And I click "Private" filter
Then I should not see "Personal snippet one" in snippets
And I should not see "Personal snippet internal" in snippets
And I should see "Personal snippet private" in snippets
Scenario: I can see only my public snippets
Given I visit my snippets page
And I click "Public" filter
Then I should see "Personal snippet one" in snippets
And I should not see "Personal snippet private" in snippets
And I should not see "Personal snippet internal" in snippets
Scenario: I can see only my internal snippets
Given I visit my snippets page
And I click "Internal" filter
Then I should see "Personal snippet internal" in snippets
And I should not see "Personal snippet private" in snippets
And I should not see "Personal snippet one" in snippets
class Spinach::Features::SnippetsUser < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedSnippet
step 'I visit my snippets page' do
visit dashboard_snippets_path
end
step 'I should see "Personal snippet one" in snippets' do
expect(page).to have_content "Personal snippet one"
end
step 'I should see "Personal snippet private" in snippets' do
expect(page).to have_content "Personal snippet private"
end
step 'I should see "Personal snippet internal" in snippets' do
expect(page).to have_content "Personal snippet internal"
end
step 'I should not see "Personal snippet one" in snippets' do
expect(page).not_to have_content "Personal snippet one"
end
step 'I should not see "Personal snippet private" in snippets' do
expect(page).not_to have_content "Personal snippet private"
end
step 'I should not see "Personal snippet internal" in snippets' do
expect(page).not_to have_content "Personal snippet internal"
end
step 'I click "Internal" filter' do
page.within('.snippet-scope-menu') do
click_link "Internal"
end
end
step 'I click "Private" filter' do
page.within('.snippet-scope-menu') do
click_link "Private"
end
end
step 'I click "Public" filter' do
page.within('.snippet-scope-menu') do
click_link "Public"
end
end
def snippet
@snippet ||= PersonalSnippet.find_by!(title: "Personal snippet one")
end
end
module RuboCop
module Cop
# Cop that checks for all gems specified in the Gemfile, and will
# alert if any gem is to be fetched not from the RubyGems index.
# This enforcement is done so as to minimize external build
# dependencies and build times.
# This cop prevents usage of the `git` and `github` arguments to `gem` in a
# `Gemfile` in order to avoid additional points of failure beyond
# rubygems.org.
class GemFetcher < RuboCop::Cop::Cop
MSG = 'Do not use gems from git repositories, only use gems from RubyGems.'
GIT_KEYS = [:git, :github]
def on_send(node)
file_path = node.location.expression.source_buffer.name
return unless file_path.end_with?("Gemfile")
return unless gemfile?(node)
func_name = node.children[1]
return unless func_name == :gem
......@@ -19,10 +17,21 @@ module RuboCop
node.children.last.each_node(:pair) do |pair|
key_name = pair.children[0].children[0].to_sym
if GIT_KEYS.include?(key_name)
add_offense(node, :selector)
add_offense(node, pair.source_range, MSG)
end
end
end
private
def gemfile?(node)
node
.location
.expression
.source_buffer
.name
.end_with?("Gemfile")
end
end
end
end
require_relative 'cop/migration/add_index'
require_relative 'cop/gem_fetcher'
require_relative 'cop/migration/add_column'
require_relative 'cop/migration/add_column_with_default'
require_relative 'cop/gem_fetcher'
require_relative 'cop/migration/add_index'
......@@ -72,8 +72,8 @@ feature 'Expand and collapse diffs', js: true, feature: true do
it 'collapses large diffs for renamed files by default' do
expect(large_diff_renamed).not_to have_selector('.code')
expect(large_diff_renamed).to have_selector('.nothing-here-block')
expect(large_diff_renamed).to have_selector('.file-title .deletion')
expect(large_diff_renamed).to have_selector('.file-title .addition')
expect(large_diff_renamed).to have_selector('.js-file-title .deletion')
expect(large_diff_renamed).to have_selector('.js-file-title .addition')
end
it 'shows non-renderable diffs as such immediately, regardless of their size' do
......@@ -115,9 +115,9 @@ feature 'Expand and collapse diffs', js: true, feature: true do
context 'expanding a large diff' do
before do
# Wait for diffs
find('.file-title', match: :first)
find('.js-file-title', match: :first)
# Click `large_diff.md` title
all('.file-title')[1].click
all('.diff-toggle-caret')[1].click
wait_for_ajax
end
......@@ -159,9 +159,9 @@ feature 'Expand and collapse diffs', js: true, feature: true do
context 'expanding the diff' do
before do
# Wait for diffs
find('.file-title', match: :first)
find('.js-file-title', match: :first)
# Click `large_diff.md` title
all('.file-title')[1].click
all('.diff-toggle-caret')[1].click
wait_for_ajax
end
......@@ -181,9 +181,9 @@ feature 'Expand and collapse diffs', js: true, feature: true do
context 'collapsing an expanded diff' do
before do
# Wait for diffs
find('.file-title', match: :first)
find('.js-file-title', match: :first)
# Click `small_diff.md` title
all('.file-title')[3].click
all('.diff-toggle-caret')[3].click
end
it 'hides the diff content' do
......@@ -194,9 +194,9 @@ feature 'Expand and collapse diffs', js: true, feature: true do
context 're-expanding the same diff' do
before do
# Wait for diffs
find('.file-title', match: :first)
find('.js-file-title', match: :first)
# Click `small_diff.md` title
all('.file-title')[3].click
all('.diff-toggle-caret')[3].click
end
it 'shows the diff content' do
......@@ -290,9 +290,9 @@ feature 'Expand and collapse diffs', js: true, feature: true do
context 'collapsing an expanded diff' do
before do
# Wait for diffs
find('.file-title', match: :first)
find('.js-file-title', match: :first)
# Click `small_diff.md` title
all('.file-title')[3].click
all('.diff-toggle-caret')[3].click
end
it 'hides the diff content' do
......@@ -303,9 +303,9 @@ feature 'Expand and collapse diffs', js: true, feature: true do
context 're-expanding the same diff' do
before do
# Wait for diffs
find('.file-title', match: :first)
find('.js-file-title', match: :first)
# Click `small_diff.md` title
all('.file-title')[3].click
all('.diff-toggle-caret')[3].click
end
it 'shows the diff content' do
......
......@@ -22,7 +22,7 @@ feature 'Find file keyboard shortcuts', feature: true, js: true do
expect(page).to have_selector('.blob-content-holder')
page.within('.file-title') do
page.within('.js-file-title') do
expect(page).to have_content('CHANGELOG')
end
end
......@@ -35,7 +35,7 @@ feature 'Find file keyboard shortcuts', feature: true, js: true do
expect(page).to have_selector('.blob-content-holder')
page.within('.file-title') do
page.within('.js-file-title') do
expect(page).to have_content('application.js')
end
end
......
......@@ -26,7 +26,11 @@ RSpec.shared_examples "protected branches > access control > CE" do
within(".protected-branches-list") do
find(".js-allowed-to-push").click
within('.js-allowed-to-push-container') { click_on access_type_name }
within('.js-allowed-to-push-container') do
expect(first("li")).to have_content("Roles")
click_on access_type_name
end
end
wait_for_ajax
......@@ -61,7 +65,11 @@ RSpec.shared_examples "protected branches > access control > CE" do
within(".protected-branches-list") do
find(".js-allowed-to-merge").click
within('.js-allowed-to-merge-container') { click_on access_type_name }
within('.js-allowed-to-merge-container') do
expect(first("li")).to have_content("Roles")
click_on access_type_name
end
end
wait_for_ajax
......
require 'rails_helper'
feature 'User Snippets', feature: true do
let(:author) { create(:user) }
let!(:public_snippet) { create(:personal_snippet, :public, author: author, title: "This is a public snippet") }
let!(:internal_snippet) { create(:personal_snippet, :internal, author: author, title: "This is an internal snippet") }
let!(:private_snippet) { create(:personal_snippet, :private, author: author, title: "This is a private snippet") }
background do
login_as author
visit dashboard_snippets_path
end
scenario 'View all of my snippets' do
expect(page).to have_content(public_snippet.title)
expect(page).to have_content(internal_snippet.title)
expect(page).to have_content(private_snippet.title)
end
scenario 'View my public snippets' do
page.within('.snippet-scope-menu') do
click_link "Public"
end
expect(page).to have_content(public_snippet.title)
expect(page).not_to have_content(internal_snippet.title)
expect(page).not_to have_content(private_snippet.title)
end
scenario 'View my internal snippets' do
page.within('.snippet-scope-menu') do
click_link "Internal"
end
expect(page).not_to have_content(public_snippet.title)
expect(page).to have_content(internal_snippet.title)
expect(page).not_to have_content(private_snippet.title)
end
scenario 'View my private snippets' do
page.within('.snippet-scope-menu') do
click_link "Private"
end
expect(page).not_to have_content(public_snippet.title)
expect(page).not_to have_content(internal_snippet.title)
expect(page).to have_content(private_snippet.title)
end
end
......@@ -9,7 +9,7 @@ require('~/filtered_search/dropdown_user');
let dropdownUser;
beforeEach(() => {
spyOn(gl.FilteredSearchDropdown.prototype, 'constructor').and.callFake(() => {});
spyOn(gl.DropdownUser.prototype, 'bindEvents').and.callFake(() => {});
spyOn(gl.DropdownUser.prototype, 'getProjectId').and.callFake(() => {});
spyOn(gl.DropdownUtils, 'getSearchInput').and.callFake(() => {});
......@@ -39,7 +39,7 @@ require('~/filtered_search/dropdown_user');
describe('config droplabAjaxFilter\'s endpoint', () => {
beforeEach(() => {
spyOn(gl.FilteredSearchDropdown.prototype, 'constructor').and.callFake(() => {});
spyOn(gl.DropdownUser.prototype, 'bindEvents').and.callFake(() => {});
spyOn(gl.DropdownUser.prototype, 'getProjectId').and.callFake(() => {});
});
......
require 'spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/gem_fetcher'
describe RuboCop::Cop::GemFetcher do
include CopHelper
subject(:cop) { described_class.new }
context 'in Gemfile' do
before do
allow(cop).to receive(:gemfile?).and_return(true)
end
it 'registers an offense when a gem uses `git`' do
inspect_source(cop, 'gem "foo", git: "https://gitlab.com/foo/bar.git"')
aggregate_failures do
expect(cop.offenses.size).to eq(1)
expect(cop.offenses.map(&:line)).to eq([1])
expect(cop.highlights).to eq(['git: "https://gitlab.com/foo/bar.git"'])
end
end
it 'registers an offense when a gem uses `github`' do
inspect_source(cop, 'gem "foo", github: "foo/bar.git"')
aggregate_failures do
expect(cop.offenses.size).to eq(1)
expect(cop.offenses.map(&:line)).to eq([1])
expect(cop.highlights).to eq(['github: "foo/bar.git"'])
end
end
end
context 'outside of Gemfile' do
it 'registers no offense' do
inspect_source(cop, 'gem "foo", git: "https://gitlab.com/foo/bar.git"')
expect(cop.offenses.size).to eq(0)
end
end
end
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