BigW Consortium Gitlab

Commit fbdd8e50 by James Lopez

Merge branch 'master' into 8-16-stable

parents 1f661926 1028b111
/* global Vue, VueResource, gl */
/*= require vue_common_component/commit */
/*= require vue_pagination/index */
/*= require vue-resource
/*= require boards/vue_resource_interceptor */
/*= require ./status.js.es6 */
......
......@@ -3,14 +3,24 @@
/*= require vue_realtime_listener/index.js */
((gl) => {
const pageValues = headers => ({
perPage: +headers['X-Per-Page'],
page: +headers['X-Page'],
total: +headers['X-Total'],
totalPages: +headers['X-Total-Pages'],
nextPage: +headers['X-Next-Page'],
previousPage: +headers['X-Prev-Page'],
});
const pageValues = (headers) => {
const normalizedHeaders = {};
Object.keys(headers).forEach((e) => {
normalizedHeaders[e.toUpperCase()] = headers[e];
});
const paginationInfo = {
perPage: +normalizedHeaders['X-PER-PAGE'],
page: +normalizedHeaders['X-PAGE'],
total: +normalizedHeaders['X-TOTAL'],
totalPages: +normalizedHeaders['X-TOTAL-PAGES'],
nextPage: +normalizedHeaders['X-NEXT-PAGE'],
previousPage: +normalizedHeaders['X-PREV-PAGE'],
};
return paginationInfo;
};
gl.PipelineStore = class {
fetchDataLoop(Vue, pageNum, url, apiScope) {
......
......@@ -109,6 +109,10 @@
.avatar {
float: none;
}
> a:not(:last-of-type) {
margin-right: 5px;
}
}
}
......
......@@ -137,4 +137,10 @@ class CommitStatus < ActiveRecord::Base
.new(self, current_user)
.fabricate!
end
def sortable_name
name.split(/(\d+)/).map do |v|
v =~ /\d+/ ? v.to_i : v
end
end
end
......@@ -32,6 +32,6 @@ module ProjectFeaturesCompatibility
build_project_feature unless project_feature
access_level = Gitlab::Utils.to_boolean(value) ? ProjectFeature::ENABLED : ProjectFeature::DISABLED
project_feature.update_attribute(field, access_level)
project_feature.send(:write_attribute, field, access_level)
end
end
class ForkedProjectLink < ActiveRecord::Base
belongs_to :forked_to_project, class_name: Project
belongs_to :forked_from_project, class_name: Project
belongs_to :forked_to_project, class_name: 'Project'
belongs_to :forked_from_project, class_name: 'Project'
end
......@@ -122,7 +122,7 @@ class Project < ActiveRecord::Base
# Merge Requests for target project should be removed with it
has_many :merge_requests, dependent: :destroy, foreign_key: 'target_project_id'
# Merge requests from source project should be kept when source project was removed
has_many :fork_merge_requests, foreign_key: 'source_project_id', class_name: MergeRequest
has_many :fork_merge_requests, foreign_key: 'source_project_id', class_name: 'MergeRequest'
has_many :issues, dependent: :destroy
has_many :labels, dependent: :destroy, class_name: 'ProjectLabel'
has_many :services, dependent: :destroy
......@@ -1032,7 +1032,7 @@ class Project < ActiveRecord::Base
"refs/heads/#{branch}",
force: true)
repository.copy_gitattributes(branch)
repository.expire_avatar_cache
repository.after_change_head
reload_default_branch
end
......
......@@ -439,6 +439,11 @@ class Repository
expire_content_cache
end
# Runs code after the HEAD of a repository is changed.
def after_change_head
expire_method_caches(METHOD_CACHES_FOR_FILE_TYPES.keys)
end
# Runs code after a repository has been forked/imported.
def after_import
expire_content_cache
......
......@@ -8,16 +8,16 @@ class CommitEntity < API::Entities::RepoCommit
end
expose :commit_url do |commit|
namespace_project_tree_url(
namespace_project_commit_url(
request.project.namespace,
request.project,
id: commit.id)
commit)
end
expose :commit_path do |commit|
namespace_project_tree_path(
namespace_project_commit_path(
request.project.namespace,
request.project,
id: commit.id)
commit)
end
end
......@@ -52,7 +52,7 @@
git push -u origin master
%fieldset
%h5 Existing folder or Git repository
%h5 Existing folder
%pre.light-well
:preserve
cd existing_folder
......@@ -62,6 +62,15 @@
git commit
git push -u origin master
%fieldset
%h5 Existing Git repository
%pre.light-well
:preserve
cd existing_repo
git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')}
git push -u origin --all
git push -u origin --tags
- if can? current_user, :remove_project, @project
.prepend-top-20
= link_to 'Remove project', [@project.namespace.becomes(Namespace), @project], data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-remove pull-right"
......@@ -7,20 +7,21 @@
%p
= @teams.one? ? 'The team' : 'Select the team'
where the slash commands will be used in
- selected_id = @teams.keys.first if @teams.one?
- selected_id = @teams.one? ? @teams.keys.first : 0
- options = mattermost_teams_options(@teams)
- options = options_for_select(options, selected_id)
= f.select(:team_id, options, {}, { class: 'form-control', selected: "#{selected_id}" })
= f.select(:team_id, options, {}, { class: 'form-control', disabled: @teams.one?, selected: selected_id })
= f.hidden_field(:team_id, value: selected_id) if @teams.one?
.help-block
- if @teams.one?
This is the only team where you are an administrator.
This is the only available team.
- else
The list shows teams where you are administrator
To create a team, ask your Mattermost system administrator.
The list shows all available teams.
To create a team,
= link_to "#{Gitlab.config.mattermost.host}/create_team" do
use Mattermost's interface
= icon('external-link')
or ask your Mattermost system administrator.
%hr
%h4 Command trigger word
%p Choose the word that will trigger commands
......
......@@ -64,5 +64,4 @@
.vue-pipelines-index
= page_specific_javascript_tag('vue_pagination/index.js')
= page_specific_javascript_tag('vue_pipelines_index/index.js')
- stage = local_assigns.fetch(:stage)
- statuses = stage.statuses.latest
- status_groups = statuses.sort_by(&:name).group_by(&:group_name)
- status_groups = statuses.sort_by(&:sortable_name).group_by(&:group_name)
%li.stage-column
.stage-name
%a{ name: stage.name }
......
---
title: Check for env[Grape::Env::GRAPE_ROUTING_ARGS] instead of endpoint.route
merge_request: 8544
author:
---
title: Allow to use + symbol in filenames
merge_request: 6644
author: blackst0ne
---
title: Mutate the attribute instead of issuing a write operation to the DB in `ProjectFeaturesCompatibility`
concern.
merge_request: 8552
author:
---
title: Allow API query to find projects with dots in their name
merge_request:
author: Bruno Melli
---
title: Allow to use ENV variables in redis config
merge_request: 8073
author: Semyon Pupkov
---
title: Sort numbers in build names more intelligently
merge_request: 8277
author:
---
title: Fix links to commits pages on pipelines list page
merge_request: 8558
author:
---
title: Expire related caches after changing HEAD
merge_request:
author: Minqi Pan
......@@ -111,7 +111,6 @@ module Gitlab
config.assets.precompile << "lib/*.js"
config.assets.precompile << "u2f.js"
config.assets.precompile << "vue_pipelines_index/index.js"
config.assets.precompile << "vue_pagination/index.js"
config.assets.precompile << "vendor/assets/fonts/*"
# Version of your assets, change this if you want to expire all your assets
......
......@@ -14,16 +14,25 @@ class RemoveDotGitFromUsernames < ActiveRecord::Migration
namespace_id = user['namespace_id']
path_was = user['username']
path_was_wildcard = quote_string("#{path_was}/%")
path = quote_string(new_path(path_was))
path = move_namespace(namespace_id, path_was, path)
move_namespace(namespace_id, path_was, path)
execute "UPDATE routes SET path = '#{path}' WHERE source_type = 'Namespace' AND source_id = #{namespace_id}"
execute "UPDATE namespaces SET path = '#{path}' WHERE id = #{namespace_id}"
execute "UPDATE users SET username = '#{path}' WHERE id = #{id}"
begin
execute "UPDATE routes SET path = '#{path}' WHERE source_type = 'Namespace' AND source_id = #{namespace_id}"
execute "UPDATE namespaces SET path = '#{path}' WHERE id = #{namespace_id}"
execute "UPDATE users SET username = '#{path}' WHERE id = #{id}"
select_all("SELECT id, path FROM routes WHERE path LIKE '#{path_was_wildcard}'").each do |route|
new_path = "#{path}/#{route['path'].split('/').last}"
execute "UPDATE routes SET path = '#{new_path}' WHERE id = #{route['id']}"
select_all("SELECT id, path FROM routes WHERE path LIKE '#{path_was_wildcard}'").each do |route|
new_path = "#{path}/#{route['path'].split('/').last}"
execute "UPDATE routes SET path = '#{new_path}' WHERE id = #{route['id']}"
end
rescue => e
say("Couldn't update routes for path #{path_was} to #{path}")
# Move namespace back
move_namespace(namespace_id, path, path_was)
raise e
end
end
end
......@@ -44,23 +53,30 @@ class RemoveDotGitFromUsernames < ActiveRecord::Migration
select_all("SELECT id, path FROM routes WHERE path = '#{quote_string(path)}'").present?
end
def path_exists?(repository_storage_path, path)
gitlab_shell.exists?(repository_storage_path, path)
def path_exists?(path, repository_storage_path)
repository_storage_path && gitlab_shell.exists?(repository_storage_path, path)
end
# Accepts invalid path like test.git and returns test_git or
# test_git1 if test_git already taken
def rename_path(repository_storage_path, path)
def new_path(path)
# To stay closer with original name and reduce risk of duplicates
# we rename suffix instead of removing it
path = path.sub(/\.git\z/, '_git')
counter = 0
base = path
check_routes(path.dup, 0, path)
end
def check_routes(base, counter, path)
route_exists = route_exists?(path)
while route_exists?(path) || path_exists?(repository_storage_path, path)
counter += 1
path = "#{base}#{counter}"
Gitlab.config.repositories.storages.each_value do |storage|
if route_exists || path_exists?(path, storage)
counter += 1
path = "#{base}#{counter}"
return check_route(base, counter, path)
end
end
path
......@@ -76,8 +92,6 @@ class RemoveDotGitFromUsernames < ActiveRecord::Migration
# Ensure old directory exists before moving it
gitlab_shell.add_namespace(repository_storage_path, path_was)
path = quote_string(rename_path(repository_storage_path, path_was))
unless gitlab_shell.mv_namespace(repository_storage_path, path_was, path)
Rails.logger.error "Exception moving path #{repository_storage_path} from #{path_was} to #{path}"
......@@ -87,8 +101,14 @@ class RemoveDotGitFromUsernames < ActiveRecord::Migration
end
end
Gitlab::UploadsTransfer.new.rename_namespace(path_was, path)
path
begin
Gitlab::UploadsTransfer.new.rename_namespace(path_was, path)
rescue => e
if path.nil?
say("Couldn't find a storage path for #{namespace_id}, #{path_was} -- skipping")
else
raise e
end
end
end
end
......@@ -601,6 +601,12 @@ If you want to connect the Redis server via socket, then use the "unix:" URL sch
production:
url: unix:/path/to/redis/socket
Also you can use environment variables in the `config/resque.yml` file:
# example
production:
url: <%= ENV.fetch('GITLAB_REDIS_URL') %>
### Custom SSH Connection
If you are running SSH on a non-standard port, you must change the GitLab user's SSH config.
......
......@@ -6,7 +6,7 @@ Slack commands give users an extra interface to perform common operations
from the chat environment. This allows one to, for example, create an issue as
soon as the idea was discussed in chat.
For all available commands try the help subcommand, for example: `/gitlab help`,
all review the [full list of commands](../integrations/chat_commands.md).
all review the [full list of commands](../integration/chat_commands.md).
## Prerequisites
......
@admin
Feature: Admin Groups
Background:
Given I sign in as an admin
And I have group with projects
And User "John Doe" exists
And I visit admin groups page
Scenario: See group list
Then I should be all groups
Scenario: Create a group
When I click new group link
And submit form with new group info
Then I should be redirected to group page
And I should see newly created group
@javascript
Scenario: Add user into projects in group
When I visit admin group page
When I select user "John Doe" from user list as "Reporter"
Then I should see "John Doe" in team list in every project as "Reporter"
Scenario: Shared projects
Given group has shared projects
When I visit group page
Then I should see project shared with group
@javascript
Scenario: Invite user to a group by e-mail
When I visit admin group page
When I select user "johndoe@gitlab.com" from user list as "Reporter"
Then I should see "johndoe@gitlab.com" in team list in every project as "Reporter"
@javascript
Scenario: Signed in admin should be able to add himself to a group
Given "John Doe" is owner of group "Owned"
When I visit group "Owned" members page
When I select current user as "Developer"
Then I should see current user as "Developer"
@javascript
Scenario: Signed in admin should be able to remove himself from group
Given current user is developer of group "Owned"
When I visit group "Owned" members page
Then I should see current user as "Developer"
When I click on the "Remove User From Group" button for current user
When I visit group "Owned" members page
Then I should not see current user as "Developer"
class Spinach::Features::AdminGroups < Spinach::FeatureSteps
include SharedAuthentication
include SharedGroup
include SharedPaths
include SharedUser
include SharedActiveTab
include Select2Helper
When 'I visit admin group page' do
visit admin_group_path(current_group)
end
When 'I click new group link' do
click_link "New Group"
end
step 'I have group with projects' do
@group = create(:group)
@project = create(:project, group: @group)
@event = create(:closed_issue_event, project: @project)
@project.team << [current_user, :master]
end
step 'submit form with new group info' do
fill_in 'group_path', with: 'gitlab'
fill_in 'group_description', with: 'Group description'
click_button "Create group"
end
step 'I should see newly created group' do
expect(page).to have_content "Group: gitlab"
expect(page).to have_content "Group description"
end
step 'I should be redirected to group page' do
expect(current_path).to eq admin_group_path(Group.find_by(path: 'gitlab'))
end
When 'I select user "John Doe" from user list as "Reporter"' do
select2(user_john.id, from: "#user_ids", multiple: true)
page.within "#new_project_member" do
select "Reporter", from: "access_level"
end
click_button "Add users to group"
end
When 'I select user "johndoe@gitlab.com" from user list as "Reporter"' do
select2('johndoe@gitlab.com', from: "#user_ids", multiple: true)
page.within "#new_project_member" do
select "Reporter", from: "access_level"
end
click_button "Add users to group"
end
step 'I should see "John Doe" in team list in every project as "Reporter"' do
page.within ".group-users-list" do
expect(page).to have_content "John Doe"
expect(page).to have_content "Reporter"
end
end
step 'I should see "johndoe@gitlab.com" in team list in every project as "Reporter"' do
page.within ".group-users-list" do
expect(page).to have_content "johndoe@gitlab.com"
expect(page).to have_content "Invited by"
expect(page).to have_content "Reporter"
end
end
step 'I should be all groups' do
Group.all.each do |group|
expect(page).to have_content group.name
end
end
step 'group has shared projects' do
share_link = shared_project.project_group_links.new(group_access: Gitlab::Access::MASTER)
share_link.group_id = current_group.id
share_link.save!
end
step 'I visit group page' do
visit admin_group_path(current_group)
end
step 'I should see project shared with group' do
expect(page).to have_content(shared_project.name_with_namespace)
expect(page).to have_content "Projects shared with"
end
step 'we have user "John Doe" in group' do
current_group.add_reporter(user_john)
end
step 'I should not see "John Doe" in team list' do
page.within ".group-users-list" do
expect(page).not_to have_content "John Doe"
end
end
step 'I select current user as "Developer"' do
page.within ".users-group-form" do
select2(current_user.id, from: "#user_ids", multiple: true)
select "Developer", from: "access_level"
end
click_button "Add to group"
end
step 'I should see current user as "Developer"' do
page.within '.content-list' do
expect(page).to have_content(current_user.name)
expect(page).to have_content('Developer')
end
end
step 'I click on the "Remove User From Group" button for current user' do
find(:css, 'li', text: current_user.name).find(:css, 'a.btn-remove').click
# poltergeist always confirms popups.
end
step 'I should not see current user as "Developer"' do
page.within '.content-list' do
expect(page).not_to have_content(current_user.name)
expect(page).not_to have_content('Developer')
end
end
protected
def current_group
@group ||= Group.first
end
def shared_project
@shared_project ||= create(:empty_project)
end
def user_john
@user_john ||= User.find_by(name: "John Doe")
end
end
......@@ -191,10 +191,6 @@ module SharedPaths
visit admin_background_jobs_path
end
step 'I visit admin groups page' do
visit admin_groups_path
end
step 'I visit admin teams page' do
visit admin_teams_path
end
......
......@@ -294,7 +294,7 @@ module API
header['X-Sendfile'] = path
body
else
file FileStreamer.new(path)
path
end
end
......
......@@ -159,7 +159,7 @@ module API
use :sort_params
use :pagination
end
get "/search/:query" do
get "/search/:query", requirements: { query: /[^\/]+/ } do
search_service = Search::GlobalService.new(current_user, search: params[:query]).execute
projects = search_service.objects('projects', params[:page])
projects = projects.reorder(params[:order_by] => params[:sort])
......
......@@ -30,9 +30,9 @@ module Gitlab
return unless @branch_name
return unless project.protected_branch?(@branch_name)
if forced_push? && user_access.cannot_do_action?(:force_push_code_to_protected_branches)
if forced_push?
return "You are not allowed to force push code to a protected branch on this project."
elsif Gitlab::Git.blank_ref?(@newrev) && user_access.cannot_do_action?(:remove_protected_branches)
elsif Gitlab::Git.blank_ref?(@newrev)
return "You are not allowed to delete protected branches from this project."
end
......
......@@ -71,10 +71,17 @@ module Gitlab
def tag_endpoint(trans, env)
endpoint = env[ENDPOINT_KEY]
# endpoint.route is nil in the case of a 405 response
if endpoint.route
path = endpoint_paths_cache[endpoint.route.request_method][endpoint.route.path]
trans.action = "Grape##{endpoint.route.request_method} #{path}"
begin
route = endpoint.route
rescue
# endpoint.route is calling env[Grape::Env::GRAPE_ROUTING_ARGS][:route_info]
# but env[Grape::Env::GRAPE_ROUTING_ARGS] is nil in the case of a 405 response
# so we're rescuing exceptions and bailing out
end
if route
path = endpoint_paths_cache[route.request_method][route.path]
trans.action = "Grape##{route.request_method} #{path}"
end
end
......
......@@ -42,7 +42,7 @@ module Gitlab
return @_raw_config if defined?(@_raw_config)
begin
@_raw_config = File.read(CONFIG_FILE).freeze
@_raw_config = ERB.new(File.read(CONFIG_FILE)).result.freeze
rescue Errno::ENOENT
@_raw_config = false
end
......
......@@ -61,11 +61,11 @@ module Gitlab
end
def file_name_regex
@file_name_regex ||= /\A[[[:alnum:]]_\-\.\@]*\z/.freeze
@file_name_regex ||= /\A[[[:alnum:]]_\-\.\@\+]*\z/.freeze
end
def file_name_regex_message
"can contain only letters, digits, '_', '-', '@' and '.'."
"can contain only letters, digits, '_', '-', '@', '+' and '.'."
end
def file_path_regex
......
#!/bin/bash
#!/bin/sh
# Sends Slack notification ERROR_MSG to CHANNEL
# An env. variable CI_SLACK_WEBHOOK_URL needs to be set.
......
require 'spec_helper'
feature 'Admin Groups', feature: true do
include Select2Helper
let(:internal) { Gitlab::VisibilityLevel::INTERNAL }
let(:user) { create :user }
let!(:group) { create :group }
let!(:current_user) { login_as :admin }
before do
login_as(:admin)
stub_application_setting(default_group_visibility: internal)
end
describe 'list' do
it 'renders groups' do
visit admin_groups_path
expect(page).to have_content(group.name)
end
end
describe 'create a group' do
it 'creates new group' do
visit admin_groups_path
click_link "New Group"
fill_in 'group_path', with: 'gitlab'
fill_in 'group_description', with: 'Group description'
click_button "Create group"
expect(current_path).to eq admin_group_path(Group.find_by(path: 'gitlab'))
expect(page).to have_content('Group: gitlab')
expect(page).to have_content('Group description')
end
scenario 'shows the visibility level radio populated with the default value' do
visit new_admin_group_path
......@@ -37,6 +61,91 @@ feature 'Admin Groups', feature: true do
end
end
describe 'add user into a group', js: true do
shared_context 'adds user into a group' do
it do
visit admin_group_path(group)
select2(user_selector, from: '#user_ids', multiple: true)
page.within '#new_project_member' do
select2(Gitlab::Access::REPORTER, from: '#access_level')
end
click_button "Add users to group"
page.within ".group-users-list" do
expect(page).to have_content(user.name)
expect(page).to have_content('Reporter')
end
end
end
it_behaves_like 'adds user into a group' do
let(:user_selector) { user.id }
end
it_behaves_like 'adds user into a group' do
let(:user_selector) { user.email }
end
end
describe 'add admin himself to a group' do
before do
group.add_user(:user, Gitlab::Access::OWNER)
end
it 'adds admin a to a group as developer', js: true do
visit group_group_members_path(group)
page.within '.users-group-form' do
select2(current_user.id, from: '#user_ids', multiple: true)
select 'Developer', from: 'access_level'
end
click_button 'Add to group'
page.within '.content-list' do
expect(page).to have_content(current_user.name)
expect(page).to have_content('Developer')
end
end
end
describe 'admin remove himself from a group', js: true do
it 'removes admin from the group' do
group.add_user(current_user, Gitlab::Access::DEVELOPER)
visit group_group_members_path(group)
page.within '.content-list' do
expect(page).to have_content(current_user.name)
expect(page).to have_content('Developer')
end
find(:css, 'li', text: current_user.name).find(:css, 'a.btn-remove').click
visit group_group_members_path(group)
page.within '.content-list' do
expect(page).not_to have_content(current_user.name)
expect(page).not_to have_content('Developer')
end
end
end
describe 'shared projects' do
it 'renders shared project' do
empty_project = create(:empty_project)
empty_project.project_group_links.create!(
group_access: Gitlab::Access::MASTER,
group: group
)
visit admin_group_path(group)
expect(page).to have_content(empty_project.name_with_namespace)
expect(page).to have_content('Projects shared with')
end
end
def expect_selected_visibility(level)
selector = "#group_visibility_level_#{level}[checked=checked]"
......
......@@ -33,10 +33,89 @@ feature 'Setup Mattermost slash commands', feature: true do
expect(value).to eq(token)
end
describe 'mattermost service is enabled' do
it 'shows the add to mattermost button' do
expect(page).to have_link 'Add to Mattermost'
it 'shows the add to mattermost button' do
expect(page).to have_link('Add to Mattermost')
end
it 'shows an explanation if user is a member of no teams' do
stub_teams(count: 0)
click_link 'Add to Mattermost'
expect(page).to have_content('You aren’t a member of any team on the Mattermost instance')
expect(page).to have_link('join a team', href: "#{Gitlab.config.mattermost.host}/select_team")
end
it 'shows an explanation if user is a member of 1 team' do
stub_teams(count: 1)
click_link 'Add to Mattermost'
expect(page).to have_content('The team where the slash commands will be used in')
expect(page).to have_content('This is the only available team.')
end
it 'shows a disabled prefilled select if user is a member of 1 team' do
teams = stub_teams(count: 1)
click_link 'Add to Mattermost'
team_name = teams.first[1]['display_name']
select_element = find('select#mattermost_team_id')
selected_option = select_element.find('option[selected]')
expect(select_element['disabled']).to be(true)
expect(selected_option).to have_content(team_name.to_s)
end
it 'has a hidden input for the prefilled value if user is a member of 1 team' do
teams = stub_teams(count: 1)
click_link 'Add to Mattermost'
expect(find('input#mattermost_team_id', visible: false).value).to eq(teams.first[0].to_s)
end
it 'shows an explanation user is a member of multiple teams' do
stub_teams(count: 2)
click_link 'Add to Mattermost'
expect(page).to have_content('Select the team where the slash commands will be used in')
expect(page).to have_content('The list shows all available teams.')
end
it 'shows a select with team options user is a member of multiple teams' do
stub_teams(count: 2)
click_link 'Add to Mattermost'
select_element = find('select#mattermost_team_id')
selected_option = select_element.find('option[selected]')
expect(select_element['disabled']).to be(false)
expect(selected_option).to have_content('Select team...')
# The 'Select team...' placeholder is item `0`.
expect(select_element.all('option').count).to eq(3)
end
def stub_teams(count: 0)
teams = create_teams(count)
allow_any_instance_of(MattermostSlashCommandsService).to receive(:list_teams) { teams }
teams
end
def create_teams(count = 0)
teams = {}
count.times do |i|
i += 1
teams[i] = { id: i, display_name: i }
end
teams
end
describe 'mattermost service is not enabled' do
......
......@@ -17,4 +17,18 @@ feature 'Create Snippet', feature: true do
expect(page).to have_content('My Snippet Title')
expect(page).to have_content('Hello World!')
end
scenario 'Authenticated user creates a snippet with + in filename' do
fill_in 'personal_snippet_title', with: 'My Snippet Title'
page.within('.file-editor') do
find(:xpath, "//input[@id='personal_snippet_file_name']").set 'snippet+file+name'
find(:xpath, "//input[@id='personal_snippet_content']").set 'Hello World!'
end
click_button 'Create snippet'
expect(page).to have_content('My Snippet Title')
expect(page).to have_content('snippet+file+name')
expect(page).to have_content('Hello World!')
end
end
test:
url: <%= ENV['TEST_GITLAB_REDIS_URL'] %>
......@@ -56,7 +56,6 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
it 'returns an error if the user is not allowed to do forced pushes to protected branches' do
expect(Gitlab::Checks::ForcePush).to receive(:force_push?).and_return(true)
expect(user_access).to receive(:can_do_action?).with(:force_push_code_to_protected_branches).and_return(false)
expect(subject.status).to be(false)
expect(subject.message).to eq('You are not allowed to force push code to a protected branch on this project.')
......@@ -88,8 +87,6 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
end
it 'returns an error if the user is not allowed to delete protected branches' do
expect(user_access).to receive(:can_do_action?).with(:remove_protected_branches).and_return(false)
expect(subject.status).to be(false)
expect(subject.message).to eq('You are not allowed to delete protected branches from this project.')
end
......
......@@ -126,5 +126,16 @@ describe Gitlab::Metrics::RackMiddleware do
expect(transaction.action).to eq('Grape#GET /projects/:id/archive')
end
it 'does not tag a transaction if route infos are missing' do
endpoint = double(:endpoint)
allow(endpoint).to receive(:route).and_raise
env['api.endpoint'] = endpoint
middleware.tag_endpoint(transaction, env)
expect(transaction.action).to be_nil
end
end
end
require 'spec_helper'
describe Gitlab::Redis do
let(:redis_config) { Rails.root.join('config', 'resque.yml').to_s }
include StubENV
before(:each) { clear_raw_config }
after(:each) { clear_raw_config }
......@@ -72,6 +72,20 @@ describe Gitlab::Redis do
expect(url2).not_to end_with('foobar')
end
context 'when yml file with env variable' do
let(:redis_config) { Rails.root.join('spec/fixtures/config/redis_config_with_env.yml') }
before do
stub_env('TEST_GITLAB_REDIS_URL', 'redis://redishost:6379')
end
it 'reads redis url from env variable' do
stub_const("#{described_class}::CONFIG_FILE", redis_config)
expect(described_class.url).to eq 'redis://redishost:6379'
end
end
end
describe '._raw_config' do
......
......@@ -243,4 +243,23 @@ describe CommitStatus, models: true do
.to be_a Gitlab::Ci::Status::Success
end
end
describe '#sortable_name' do
tests = {
'karma' => ['karma'],
'karma 0 20' => ['karma ', 0, ' ', 20],
'karma 10 20' => ['karma ', 10, ' ', 20],
'karma 50:100' => ['karma ', 50, ':', 100],
'karma 1.10' => ['karma ', 1, '.', 10],
'karma 1.5.1' => ['karma ', 1, '.', 5, '.', 1],
'karma 1 a' => ['karma ', 1, ' a']
}
tests.each do |name, sortable_name|
it "'#{name}' sorts as '#{sortable_name}'" do
commit_status.name = name
expect(commit_status.sortable_name).to eq(sortable_name)
end
end
end
end
......@@ -1545,11 +1545,13 @@ describe Project, models: true do
end
end
describe 'change_head' do
describe '#change_head' do
let(:project) { create(:project) }
it 'calls the before_change_head method' do
it 'calls the before_change_head and after_change_head methods' do
expect(project.repository).to receive(:before_change_head)
expect(project.repository).to receive(:after_change_head)
project.change_head(project.default_branch)
end
......@@ -1565,11 +1567,6 @@ describe Project, models: true do
project.change_head(project.default_branch)
end
it 'expires the avatar cache' do
expect(project.repository).to receive(:expire_avatar_cache)
project.change_head(project.default_branch)
end
it 'reloads the default branch' do
expect(project).to receive(:reload_default_branch)
project.change_head(project.default_branch)
......
......@@ -1150,6 +1150,24 @@ describe Repository, models: true do
end
end
describe '#after_change_head' do
it 'flushes the readme cache' do
expect(repository).to receive(:expire_method_caches).with([
:readme,
:changelog,
:license,
:contributing,
:version,
:gitignore,
:koding,
:gitlab_ci,
:avatar
])
repository.after_change_head
end
end
describe '#before_push_tag' do
it 'flushes the cache' do
expect(repository).to receive(:expire_statistics_caches)
......@@ -1513,14 +1531,6 @@ describe Repository, models: true do
end
end
describe '#expire_avatar_cache' do
it 'expires the cache' do
expect(repository).to receive(:expire_method_caches).with(%i(avatar))
repository.expire_avatar_cache
end
end
describe '#file_on_head' do
context 'with a non-existing repository' do
it 'returns nil' do
......
......@@ -1085,7 +1085,7 @@ describe API::Projects, api: true do
end
describe 'GET /projects/search/:query' do
let!(:query) { 'query'}
let!(:query) { 'query'}
let!(:search) { create(:empty_project, name: query, creator_id: user.id, namespace: user.namespace) }
let!(:pre) { create(:empty_project, name: "pre_#{query}", creator_id: user.id, namespace: user.namespace) }
let!(:post) { create(:empty_project, name: "#{query}_post", creator_id: user.id, namespace: user.namespace) }
......@@ -1095,32 +1095,37 @@ describe API::Projects, api: true do
let!(:unfound_internal) { create(:empty_project, :internal, name: 'unfound internal') }
let!(:public) { create(:empty_project, :public, name: "public #{query}") }
let!(:unfound_public) { create(:empty_project, :public, name: 'unfound public') }
let!(:one_dot_two) { create(:empty_project, :public, name: "one.dot.two") }
shared_examples_for 'project search response' do |args = {}|
it 'returns project search responses' do
get api("/projects/search/#{query}", current_user)
get api("/projects/search/#{args[:query]}", current_user)
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.size).to eq(args[:results])
json_response.each { |project| expect(project['name']).to match(args[:match_regex] || /.*query.*/) }
json_response.each { |project| expect(project['name']).to match(args[:match_regex] || /.*#{args[:query]}.*/) }
end
end
context 'when unauthenticated' do
it_behaves_like 'project search response', results: 1 do
it_behaves_like 'project search response', query: 'query', results: 1 do
let(:current_user) { nil }
end
end
context 'when authenticated' do
it_behaves_like 'project search response', results: 6 do
it_behaves_like 'project search response', query: 'query', results: 6 do
let(:current_user) { user }
end
it_behaves_like 'project search response', query: 'one.dot.two', results: 1 do
let(:current_user) { user }
end
end
context 'when authenticated as a different user' do
it_behaves_like 'project search response', results: 2, match_regex: /(internal|public) query/ do
it_behaves_like 'project search response', query: 'query', results: 2, match_regex: /(internal|public) query/ do
let(:current_user) { user2 }
end
end
......
......@@ -33,10 +33,12 @@ describe CommitEntity do
it 'contains path to commit' do
expect(subject).to include(:commit_path)
expect(subject[:commit_path]).to include "commit/#{commit.id}"
end
it 'contains URL to commit' do
expect(subject).to include(:commit_url)
expect(subject[:commit_path]).to include "commit/#{commit.id}"
end
it 'needs to receive project in the request' 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