Commit 68e9372a authored by Phil Hughes's avatar Phil Hughes

Merge branch 'master' into breadcrumbs-improvements

parents df35410a d0f5b3c2
...@@ -212,7 +212,6 @@ update-tests-metadata: ...@@ -212,7 +212,6 @@ update-tests-metadata:
flaky-examples-check: flaky-examples-check:
<<: *dedicated-runner <<: *dedicated-runner
<<: *except-docs
image: ruby:2.3-alpine image: ruby:2.3-alpine
services: [] services: []
before_script: [] before_script: []
...@@ -227,6 +226,7 @@ flaky-examples-check: ...@@ -227,6 +226,7 @@ flaky-examples-check:
- branches - branches
except: except:
- master - master
- /(^docs[\/-].*|.*-docs$)/
artifacts: artifacts:
expire_in: 30d expire_in: 30d
paths: paths:
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
[![Build status](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/build.svg)](https://gitlab.com/gitlab-org/gitlab-ce/commits/master) [![Build status](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/build.svg)](https://gitlab.com/gitlab-org/gitlab-ce/commits/master)
[![Overall test coverage](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg)](https://gitlab.com/gitlab-org/gitlab-ce/pipelines) [![Overall test coverage](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg)](https://gitlab.com/gitlab-org/gitlab-ce/pipelines)
[![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.svg)](https://gemnasium.com/gitlabhq/gitlabhq)
[![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq) [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq)
[![Core Infrastructure Initiative Best Practices](https://bestpractices.coreinfrastructure.org/projects/42/badge)](https://bestpractices.coreinfrastructure.org/projects/42) [![Core Infrastructure Initiative Best Practices](https://bestpractices.coreinfrastructure.org/projects/42/badge)](https://bestpractices.coreinfrastructure.org/projects/42)
[![Gitter](https://badges.gitter.im/gitlabhq/gitlabhq.svg)](https://gitter.im/gitlabhq/gitlabhq?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Gitter](https://badges.gitter.im/gitlabhq/gitlabhq.svg)](https://gitter.im/gitlabhq/gitlabhq?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
......
...@@ -53,10 +53,6 @@ import Cookies from 'js-cookie'; ...@@ -53,10 +53,6 @@ import Cookies from 'js-cookie';
return _this.changeProject($(e.currentTarget).val()); return _this.changeProject($(e.currentTarget).val());
}; };
})(this)); })(this));
return $('.js-projects-dropdown-toggle').on('click', function(e) {
e.preventDefault();
return $('.js-projects-dropdown').select2('open');
});
}; };
Project.prototype.changeProject = function(url) { Project.prototype.changeProject = function(url) {
......
...@@ -5,48 +5,6 @@ import ProjectSelectComboButton from './project_select_combo_button'; ...@@ -5,48 +5,6 @@ import ProjectSelectComboButton from './project_select_combo_button';
(function() { (function() {
this.ProjectSelect = (function() { this.ProjectSelect = (function() {
function ProjectSelect() { function ProjectSelect() {
$('.js-projects-dropdown-toggle').each(function(i, dropdown) {
var $dropdown;
$dropdown = $(dropdown);
return $dropdown.glDropdown({
filterable: true,
filterRemote: true,
search: {
fields: ['name_with_namespace']
},
data: function(term, callback) {
var finalCallback, projectsCallback;
var orderBy = $dropdown.data('order-by');
finalCallback = function(projects) {
return callback(projects);
};
if (this.includeGroups) {
projectsCallback = function(projects) {
var groupsCallback;
groupsCallback = function(groups) {
var data;
data = groups.concat(projects);
return finalCallback(data);
};
return Api.groups(term, {}, groupsCallback);
};
} else {
projectsCallback = finalCallback;
}
if (this.groupId) {
return Api.groupProjects(this.groupId, term, projectsCallback);
} else {
return Api.projects(term, { order_by: orderBy }, projectsCallback);
}
},
url: function(project) {
return project.web_url;
},
text: function(project) {
return project.name_with_namespace;
}
});
});
$('.ajax-project-select').each(function(i, select) { $('.ajax-project-select').each(function(i, select) {
var placeholder; var placeholder;
this.groupId = $(select).data('group-id'); this.groupId = $(select).data('group-id');
......
...@@ -75,18 +75,20 @@ export default { ...@@ -75,18 +75,20 @@ export default {
class="btn btn-small inline"> class="btn btn-small inline">
Check out branch Check out branch
</a> </a>
<span class="dropdown inline prepend-left-10"> <span class="dropdown prepend-left-10">
<a <a
class="btn btn-xs dropdown-toggle" class="btn btn-small inline dropdown-toggle"
data-toggle="dropdown" data-toggle="dropdown"
aria-label="Download as" aria-label="Download as"
role="button"> role="button">
<i <i
class="fa fa-download" class="fa fa-download"
aria-hidden="true" /> aria-hidden="true">
</i>
<i <i
class="fa fa-caret-down" class="fa fa-caret-down"
aria-hidden="true" /> aria-hidden="true">
</i>
</a> </a>
<ul class="dropdown-menu dropdown-menu-align-right"> <ul class="dropdown-menu dropdown-menu-align-right">
<li> <li>
......
...@@ -267,6 +267,7 @@ ...@@ -267,6 +267,7 @@
// TODO: change global style // TODO: change global style
.ajax-project-dropdown, .ajax-project-dropdown,
.ajax-users-dropdown,
body[data-page="projects:edit"] #select2-drop, body[data-page="projects:edit"] #select2-drop,
body[data-page="projects:new"] #select2-drop, body[data-page="projects:new"] #select2-drop,
body[data-page="projects:merge_requests:edit"] #select2-drop, body[data-page="projects:merge_requests:edit"] #select2-drop,
......
...@@ -36,6 +36,34 @@ module IssuableCollections ...@@ -36,6 +36,34 @@ module IssuableCollections
@merge_requests_finder ||= issuable_finder_for(MergeRequestsFinder) @merge_requests_finder ||= issuable_finder_for(MergeRequestsFinder)
end end
def redirect_out_of_range(relation, total_pages)
return false if total_pages.zero?
out_of_range = relation.current_page > total_pages
if out_of_range
redirect_to(url_for(params.merge(page: total_pages, only_path: true)))
end
out_of_range
end
def issues_page_count(relation)
page_count_for_relation(relation, issues_finder.row_count)
end
def merge_requests_page_count(relation)
page_count_for_relation(relation, merge_requests_finder.row_count)
end
def page_count_for_relation(relation, row_count)
limit = relation.limit_value.to_f
return 1 if limit.zero?
(row_count.to_f / limit).ceil
end
def issuable_finder_for(finder_class) def issuable_finder_for(finder_class)
finder_class.new(current_user, filter_params) finder_class.new(current_user, filter_params)
end end
......
...@@ -27,10 +27,9 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -27,10 +27,9 @@ class Projects::IssuesController < Projects::ApplicationController
@issues = issues_collection @issues = issues_collection
@issues = @issues.page(params[:page]) @issues = @issues.page(params[:page])
@issuable_meta_data = issuable_meta_data(@issues, @collection_type) @issuable_meta_data = issuable_meta_data(@issues, @collection_type)
@total_pages = issues_page_count(@issues)
if @issues.out_of_range? && @issues.total_pages != 0 return if redirect_out_of_range(@issues, @total_pages)
return redirect_to url_for(params.merge(page: @issues.total_pages, only_path: true))
end
if params[:label_name].present? if params[:label_name].present?
@labels = LabelsFinder.new(current_user, project_id: @project.id, title: params[:label_name]).execute @labels = LabelsFinder.new(current_user, project_id: @project.id, title: params[:label_name]).execute
......
...@@ -18,10 +18,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo ...@@ -18,10 +18,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
@merge_requests = @merge_requests.page(params[:page]) @merge_requests = @merge_requests.page(params[:page])
@merge_requests = @merge_requests.preload(merge_request_diff: :merge_request) @merge_requests = @merge_requests.preload(merge_request_diff: :merge_request)
@issuable_meta_data = issuable_meta_data(@merge_requests, @collection_type) @issuable_meta_data = issuable_meta_data(@merge_requests, @collection_type)
@total_pages = merge_requests_page_count(@merge_requests)
if @merge_requests.out_of_range? && @merge_requests.total_pages != 0 return if redirect_out_of_range(@merge_requests, @total_pages)
return redirect_to url_for(params.merge(page: @merge_requests.total_pages, only_path: true))
end
if params[:label_name].present? if params[:label_name].present?
labels_params = { project_id: @project.id, title: params[:label_name] } labels_params = { project_id: @project.id, title: params[:label_name] }
......
...@@ -61,6 +61,10 @@ class IssuableFinder ...@@ -61,6 +61,10 @@ class IssuableFinder
execute.find_by(*params) execute.find_by(*params)
end end
def row_count
Gitlab::IssuablesCountForState.new(self).for_state_or_opened(params[:state])
end
# We often get counts for each state by running a query per state, and # We often get counts for each state by running a query per state, and
# counting those results. This is typically slower than running one query # counting those results. This is typically slower than running one query
# (even if that query is slower than any of the individual state queries) and # (even if that query is slower than any of the individual state queries) and
......
...@@ -249,7 +249,8 @@ module IssuablesHelper ...@@ -249,7 +249,8 @@ module IssuablesHelper
def issuables_count_for_state(issuable_type, state) def issuables_count_for_state(issuable_type, state)
finder = public_send("#{issuable_type}_finder") # rubocop:disable GitlabSecurity/PublicSend finder = public_send("#{issuable_type}_finder") # rubocop:disable GitlabSecurity/PublicSend
finder.count_by_state[state]
Gitlab::IssuablesCountForState.new(finder)[state]
end end
def close_issuable_url(issuable) def close_issuable_url(issuable)
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
= link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', title: 'Groups' do = link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', title: 'Groups' do
Groups Groups
= nav_link(path: 'dashboard#activity', html_options: { class: "hidden-xs hidden-sm" }) do = nav_link(path: 'dashboard#activity', html_options: { class: "hidden-xs hidden-sm hidden-md" }) do
= link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
Activity Activity
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
= icon("chevron-down", class: "dropdown-chevron") = icon("chevron-down", class: "dropdown-chevron")
.dropdown-menu .dropdown-menu
%ul %ul
= nav_link(path: 'dashboard#activity', html_options: { class: "visible-xs visible-sm" }) do = nav_link(path: 'dashboard#activity', html_options: { class: "visible-xs visible-sm visible-md" }) do
= link_to activity_dashboard_path, title: 'Activity' do = link_to activity_dashboard_path, title: 'Activity' do
Activity Activity
......
...@@ -14,12 +14,4 @@ ...@@ -14,12 +14,4 @@
:javascript :javascript
window.uploads_path = "#{project_uploads_path(project)}"; window.uploads_path = "#{project_uploads_path(project)}";
- content_for :header_content do
.js-dropdown-menu-projects
.dropdown-menu.dropdown-select.dropdown-menu-projects
= dropdown_title("Go to a project")
= dropdown_filter("Search your projects")
= dropdown_content
= dropdown_loading
= render template: "layouts/application" = render template: "layouts/application"
...@@ -4,4 +4,4 @@ ...@@ -4,4 +4,4 @@
= render 'shared/empty_states/issues' = render 'shared/empty_states/issues'
- if @issues.present? - if @issues.present?
= paginate @issues, theme: "gitlab" = paginate @issues, theme: "gitlab", total_pages: @total_pages
...@@ -5,4 +5,4 @@ ...@@ -5,4 +5,4 @@
= render 'shared/empty_states/merge_requests' = render 'shared/empty_states/merge_requests'
- if @merge_requests.present? - if @merge_requests.present?
= paginate @merge_requests, theme: "gitlab" = paginate @merge_requests, theme: "gitlab", total_pages: @total_pages
---
title: Remove project select dropdown from breadcrumb
merge_request: 14010
author:
type: changed
---
title: Fix new navigation wrapping and causing height to grow
merge_request:
author:
type: fixed
---
title: Fix buttons with different height in merge request widget
merge_request:
author:
type: fixed
---
title: Add badge for dependency status
merge_request: 13588
author: Markus Koller
type: other
---
title: Re-use issue/MR counts for the pagination system
merge_request:
author:
type: other
...@@ -21,16 +21,16 @@ The following table depicts the various user permission levels in a project. ...@@ -21,16 +21,16 @@ The following table depicts the various user permission levels in a project.
| Action | Guest | Reporter | Developer | Master | Owner | | Action | Guest | Reporter | Developer | Master | Owner |
|---------------------------------------|---------|------------|-------------|----------|--------| |---------------------------------------|---------|------------|-------------|----------|--------|
| Create new issue | ✓ | ✓ | ✓ | ✓ | ✓ | | Create new issue | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
| Create confidential issue | ✓ | ✓ | ✓ | ✓ | ✓ | | Create confidential issue | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
| View confidential issues | (✓) [^1] | ✓ | ✓ | ✓ | ✓ | | View confidential issues | (✓) [^2] | ✓ | ✓ | ✓ | ✓ |
| Leave comments | ✓ | ✓ | ✓ | ✓ | ✓ | | Leave comments | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
| See a list of jobs | ✓ [^2] | ✓ | ✓ | ✓ | ✓ | | See a list of jobs | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
| See a job log | ✓ [^2] | ✓ | ✓ | ✓ | ✓ | | See a job log | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
| Download and browse job artifacts | ✓ [^2] | ✓ | ✓ | ✓ | ✓ | | Download and browse job artifacts | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
| View wiki pages | ✓ | ✓ | ✓ | ✓ | ✓ | | View wiki pages | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
| Pull project code | | ✓ | ✓ | ✓ | ✓ | | Pull project code | [^1] | ✓ | ✓ | ✓ | ✓ |
| Download project | | ✓ | ✓ | ✓ | ✓ | | Download project | [^1] | ✓ | ✓ | ✓ | ✓ |
| Create code snippets | | ✓ | ✓ | ✓ | ✓ | | Create code snippets | | ✓ | ✓ | ✓ | ✓ |
| Manage issue tracker | | ✓ | ✓ | ✓ | ✓ | | Manage issue tracker | | ✓ | ✓ | ✓ | ✓ |
| Manage labels | | ✓ | ✓ | ✓ | ✓ | | Manage labels | | ✓ | ✓ | ✓ | ✓ |
...@@ -71,8 +71,8 @@ The following table depicts the various user permission levels in a project. ...@@ -71,8 +71,8 @@ The following table depicts the various user permission levels in a project.
| Switch visibility level | | | | | ✓ | | Switch visibility level | | | | | ✓ |
| Transfer project to another namespace | | | | | ✓ | | Transfer project to another namespace | | | | | ✓ |
| Remove project | | | | | ✓ | | Remove project | | | | | ✓ |
| Force push to protected branches [^3] | | | | | | | Force push to protected branches [^4] | | | | | |
| Remove protected branches [^3] | | | | | | | Remove protected branches [^4] | | | | | |
| Remove pages | | | | | ✓ | | Remove pages | | | | | ✓ |
## Project features permissions ## Project features permissions
...@@ -215,13 +215,13 @@ users: ...@@ -215,13 +215,13 @@ users:
| Run CI job | | ✓ | ✓ | ✓ | | Run CI job | | ✓ | ✓ | ✓ |
| Clone source and LFS from current project | | ✓ | ✓ | ✓ | | Clone source and LFS from current project | | ✓ | ✓ | ✓ |
| Clone source and LFS from public projects | | ✓ | ✓ | ✓ | | Clone source and LFS from public projects | | ✓ | ✓ | ✓ |
| Clone source and LFS from internal projects | | ✓ [^4] | ✓ [^4] | ✓ | | Clone source and LFS from internal projects | | ✓ [^5] | ✓ [^5] | ✓ |
| Clone source and LFS from private projects | | ✓ [^5] | ✓ [^5] | ✓ [^5] | | Clone source and LFS from private projects | | ✓ [^6] | ✓ [^6] | ✓ [^6] |
| Push source and LFS | | | | | | Push source and LFS | | | | |
| Pull container images from current project | | ✓ | ✓ | ✓ | | Pull container images from current project | | ✓ | ✓ | ✓ |
| Pull container images from public projects | | ✓ | ✓ | ✓ | | Pull container images from public projects | | ✓ | ✓ | ✓ |
| Pull container images from internal projects| | ✓ [^4] | ✓ [^4] | ✓ | | Pull container images from internal projects| | ✓ [^5] | ✓ [^5] | ✓ |
| Pull container images from private projects | | ✓ [^5] | ✓ [^5] | ✓ [^5] | | Pull container images from private projects | | ✓ [^6] | ✓ [^6] | ✓ [^6] |
| Push container images to current project | | ✓ | ✓ | ✓ | | Push container images to current project | | ✓ | ✓ | ✓ |
| Push container images to other projects | | | | | | Push container images to other projects | | | | |
...@@ -243,12 +243,11 @@ with the permissions described on the documentation on [auditor users permission ...@@ -243,12 +243,11 @@ with the permissions described on the documentation on [auditor users permission
Auditor users are available in [GitLab Enterprise Edition Premium](https://about.gitlab.com/gitlab-ee/) Auditor users are available in [GitLab Enterprise Edition Premium](https://about.gitlab.com/gitlab-ee/)
only. only.
---- [^1]: On public and internal projects, all users are able to perform this action.
[^2]: Guest users can only view the confidential issues they created themselves
[^1]: Guest users can only view the confidential issues they created themselves [^3]: If **Public pipelines** is enabled in **Project Settings > Pipelines**
[^2]: If **Public pipelines** is enabled in **Project Settings > Pipelines** [^4]: Not allowed for Guest, Reporter, Developer, Master, or Owner
[^3]: Not allowed for Guest, Reporter, Developer, Master, or Owner [^5]: Only if user is not external one.
[^4]: Only if user is not external one. [^6]: Only if user is a member of the project.
[^5]: Only if user is a member of the project.
[ce-18994]: https://gitlab.com/gitlab-org/gitlab-ce/issues/18994 [ce-18994]: https://gitlab.com/gitlab-org/gitlab-ce/issues/18994
[new-mod]: project/new_ci_build_permissions_model.md [new-mod]: project/new_ci_build_permissions_model.md
module Gitlab
# Class for counting and caching the number of issuables per state.
class IssuablesCountForState
# The name of the RequestStore cache key.
CACHE_KEY = :issuables_count_for_state
# The state values that can be safely casted to a Symbol.
STATES = %w[opened closed merged all].freeze
# finder - The finder class to use for retrieving the issuables.
def initialize(finder)
@finder = finder
@cache =
if RequestStore.active?
RequestStore[CACHE_KEY] ||= initialize_cache
else
initialize_cache
end
end
def for_state_or_opened(state = nil)
self[state || :opened]
end
# Returns the count for the given state.
#
# state - The name of the state as either a String or a Symbol.
#
# Returns an Integer.
def [](state)
state = state.to_sym if cast_state_to_symbol?(state)
cache_for_finder[state] || 0
end
private
def cache_for_finder
@cache[@finder]
end
def cast_state_to_symbol?(state)
state.is_a?(String) && STATES.include?(state)
end
def initialize_cache
Hash.new { |hash, finder| hash[finder] = finder.count_by_state }
end
end
end
require "gettext_i18n_rails/tasks" require "gettext_i18n_rails/tasks"
require 'simple_po_parser'
namespace :gettext do namespace :gettext do
# Customize list of translatable files # Customize list of translatable files
...@@ -23,6 +22,8 @@ namespace :gettext do ...@@ -23,6 +22,8 @@ namespace :gettext do
desc 'Lint all po files in `locale/' desc 'Lint all po files in `locale/'
task lint: :environment do task lint: :environment do
require 'simple_po_parser'
FastGettext.silence_errors FastGettext.silence_errors
files = Dir.glob(Rails.root.join('locale/*/gitlab.po')) files = Dir.glob(Rails.root.join('locale/*/gitlab.po'))
......
require 'spec_helper'
describe IssuableCollections do
let(:user) { create(:user) }
let(:controller) do
klass = Class.new do
def self.helper_method(name); end
include IssuableCollections
end
controller = klass.new
allow(controller).to receive(:params).and_return(state: 'opened')
controller
end
describe '#redirect_out_of_range' do
before do
allow(controller).to receive(:url_for)
end
it 'returns true and redirects if the offset is out of range' do
relation = double(:relation, current_page: 10)
expect(controller).to receive(:redirect_to)
expect(controller.send(:redirect_out_of_range, relation, 2)).to eq(true)
end
it 'returns false if the offset is not out of range' do
relation = double(:relation, current_page: 1)
expect(controller).not_to receive(:redirect_to)
expect(controller.send(:redirect_out_of_range, relation, 2)).to eq(false)
end
end
describe '#issues_page_count' do
it 'returns the number of issue pages' do
project = create(:project, :public)
create(:issue, project: project)
finder = IssuesFinder.new(user)
issues = finder.execute
allow(controller).to receive(:issues_finder)
.and_return(finder)
expect(controller.send(:issues_page_count, issues)).to eq(1)
end
end
describe '#merge_requests_page_count' do
it 'returns the number of merge request pages' do
project = create(:project, :public)
create(:merge_request, source_project: project, target_project: project)
finder = MergeRequestsFinder.new(user)
merge_requests = finder.execute
allow(controller).to receive(:merge_requests_finder)
.and_return(finder)
pages = controller.send(:merge_requests_page_count, merge_requests)
expect(pages).to eq(1)
end
end
describe '#page_count_for_relation' do
it 'returns the number of pages' do
relation = double(:relation, limit_value: 20)
pages = controller.send(:page_count_for_relation, relation, 28)
expect(pages).to eq(2)
end
end
end
...@@ -15,8 +15,8 @@ describe IssuesFinder do ...@@ -15,8 +15,8 @@ describe IssuesFinder do
set(:award_emoji3) { create(:award_emoji, name: 'thumbsdown', user: user, awardable: issue3) } set(:award_emoji3) { create(:award_emoji, name: 'thumbsdown', user: user, awardable: issue3) }
describe '#execute' do describe '#execute' do
set(:closed_issue) { create(:issue, author: user2, assignees: [user2], project: project2, state: 'closed') } let!(:closed_issue) { create(:issue, author: user2, assignees: [user2], project: project2, state: 'closed') }
set(:label_link) { create(:label_link, label: label, target: issue2) } let!(:label_link) { create(:label_link, label: label, target: issue2) }
let(:search_user) { user } let(:search_user) { user }
let(:params) { {} } let(:params) { {} }
let(:issues) { described_class.new(search_user, params.reverse_merge(scope: scope, state: 'opened')).execute } let(:issues) { described_class.new(search_user, params.reverse_merge(scope: scope, state: 'opened')).execute }
...@@ -347,6 +347,20 @@ describe IssuesFinder do ...@@ -347,6 +347,20 @@ describe IssuesFinder do
end end
end end
describe '#row_count', :request_store do
it 'returns the number of rows for the default state' do
finder = described_class.new(user)
expect(finder.row_count).to eq(3)
end
it 'returns the number of rows for a given state' do
finder = described_class.new(user, state: 'closed')
expect(finder.row_count).to be_zero
end
end
describe '#with_confidentiality_access_check' do describe '#with_confidentiality_access_check' do
let(:guest) { create(:user) } let(:guest) { create(:user) }
set(:authorized_user) { create(:user) } set(:authorized_user) { create(:user) }
......
...@@ -108,4 +108,18 @@ describe MergeRequestsFinder do ...@@ -108,4 +108,18 @@ describe MergeRequestsFinder do
end end
end end
end end
describe '#row_count', :request_store do
it 'returns the number of rows for the default state' do
finder = described_class.new(user)
expect(finder.row_count).to eq(3)
end
it 'returns the number of rows for a given state' do
finder = described_class.new(user, state: 'closed')
expect(finder.row_count).to eq(1)
end
end
end end
...@@ -12,21 +12,13 @@ FREQUENT_PROJECTS.MAX_COUNT = 3; ...@@ -12,21 +12,13 @@ FREQUENT_PROJECTS.MAX_COUNT = 3;
describe('ProjectsService', () => { describe('ProjectsService', () => {
let service; let service;
let originalGon;
beforeEach(() => { beforeEach(() => {
originalGon = window.gon; gon.api_version = currentSession.apiVersion;
gon.current_user_id = 1;
window.gon = Object.assign({}, {
api_version: currentSession.apiVersion,
});
service = new ProjectsService(currentSession.username); service = new ProjectsService(currentSession.username);
}); });
afterEach(() => {
window.gon = originalGon;
});
describe('contructor', () => { describe('contructor', () => {
it('should initialize default properties of class', () => { it('should initialize default properties of class', () => {
expect(service.isLocalStorageAvailable).toBeTruthy(); expect(service.isLocalStorageAvailable).toBeTruthy();
...@@ -44,7 +36,7 @@ describe('ProjectsService', () => { ...@@ -44,7 +36,7 @@ describe('ProjectsService', () => {
const queryParams = { const queryParams = {
simple: false, simple: false,
per_page: 20, per_page: 20,
membership: false, membership: true,
order_by: 'last_activity_at', order_by: 'last_activity_at',
search: searchQuery, search: searchQuery,
}; };
......
require 'spec_helper'
describe Gitlab::IssuablesCountForState do
let(:finder) do
double(:finder, count_by_state: { opened: 2, closed: 1 })
end
let(:counter) { described_class.new(finder) }
describe '#for_state_or_opened' do
it 'returns the number of issuables for the given state' do
expect(counter.for_state_or_opened(:closed)).to eq(1)
end
it 'returns the number of open issuables when no state is given' do
expect(counter.for_state_or_opened).to eq(2)
end
it 'returns the number of open issuables when a nil value is given' do
expect(counter.for_state_or_opened(nil)).to eq(2)
end
end
describe '#[]' do
it 'returns the number of issuables for the given state' do
expect(counter[:closed]).to eq(1)
end
it 'casts valid states from Strings to Symbols' do
expect(counter['closed']).to eq(1)
end
it 'returns 0 when using an invalid state name as a String' do
expect(counter['kittens']).to be_zero
end
end
end
...@@ -31,7 +31,7 @@ cmake-build-debug/ ...@@ -31,7 +31,7 @@ cmake-build-debug/
## Plugin-specific files: ## Plugin-specific files:
# IntelliJ # IntelliJ
/out/ out/
# mpeltonen/sbt-idea plugin # mpeltonen/sbt-idea plugin
.idea_modules/ .idea_modules/
......
...@@ -18,3 +18,4 @@ cabal.sandbox.config ...@@ -18,3 +18,4 @@ cabal.sandbox.config
.stack-work/ .stack-work/
cabal.project.local cabal.project.local
.HTF/ .HTF/
.ghc.environment.*
...@@ -7,8 +7,10 @@ config/settings.*.php ...@@ -7,8 +7,10 @@ config/settings.*.php
# The following files are generated by PrestaShop. # The following files are generated by PrestaShop.
admin-dev/autoupgrade/ admin-dev/autoupgrade/
/cache/ /cache/*
!/cache/index.php !/cache/index.php
!/cache/*/
/cache/*/*
!/cache/cachefs/index.php !/cache/cachefs/index.php
!/cache/purifier/index.php !/cache/purifier/index.php
!/cache/push/index.php !/cache/push/index.php
......
...@@ -13,6 +13,10 @@ SqueakDebug.log ...@@ -13,6 +13,10 @@ SqueakDebug.log
# Monticello package cache # Monticello package cache
/package-cache /package-cache
# playground cache
/play-cache
/play-stash
# Metacello-github cache # Metacello-github cache
/github-cache /github-cache
github-*.zip github-*.zip
...@@ -39,3 +39,6 @@ ...@@ -39,3 +39,6 @@
# Backup entities generated with doctrine:generate:entities command # Backup entities generated with doctrine:generate:entities command
**/Entity/*~ **/Entity/*~
# Embedded web-server pid file
/.web-server-pid
...@@ -151,7 +151,7 @@ publish/ ...@@ -151,7 +151,7 @@ publish/
# Publish Web Output # Publish Web Output
*.[Pp]ublish.xml *.[Pp]ublish.xml
*.azurePubxml *.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings # Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted # but database connection strings (with potential passwords) will be unencrypted
*.pubxml *.pubxml
*.publishproj *.publishproj
......
image: golang:latest image: golang:latest
variables:
# Please edit to your GitLab project
REPO_NAME: gitlab.com/namespace/project
# The problem is that to be able to use go get, one needs to put # The problem is that to be able to use go get, one needs to put
# the repository in the $GOPATH. So for example if your gitlab domain # the repository in the $GOPATH. So for example if your gitlab domain
# is mydomainperso.com, and that your repository is repos/projectname, and # is gitlab.com, and that your repository is namespace/project, and
# the default GOPATH being /go, then you'd need to have your # the default GOPATH being /go, then you'd need to have your
# repository in /go/src/mydomainperso.com/repos/projectname # repository in /go/src/gitlab.com/namespace/project
# Thus, making a symbolic link corrects this. # Thus, making a symbolic link corrects this.
before_script: before_script:
- ln -s /builds /go/src/mydomainperso.com - mkdir -p $GOPATH/src/$REPO_NAME
- cd /go/src/mydomainperso.com/repos/projectname - ln -svf $CI_PROJECT_DIR/* $GOPATH/src/$REPO_NAME
- cd $GOPATH/src/$REPO_NAME
stages: stages:
- test - test
...@@ -17,21 +22,14 @@ stages: ...@@ -17,21 +22,14 @@ stages:
format: format:
stage: test stage: test
script: script:
# Add here all the dependencies, or use glide/govendor to get - go fmt $(go list ./... | grep -v /vendor/)
# them automatically. - go vet $(go list ./... | grep -v /vendor/)
# - curl https://glide.sh/get | sh - go test -race $(go list ./... | grep -v /vendor/)
- go get github.com/alecthomas/kingpin
- go tool vet -composites=false -shadow=true *.go
- go test -race $(go list ./... | grep -v /vendor/)
compile: compile:
stage: build stage: build
script: script:
# Add here all the dependencies, or use glide/govendor/... - go build -race -ldflags "-extldflags '-static'" -o mybinary
# to get them automatically.
- go get github.com/alecthomas/kingpin
# Better put this in a Makefile
- go build -race -ldflags "-extldflags '-static'" -o mybinary
artifacts: artifacts:
paths: paths:
- mybinary - mybinary
# This template uses the java:8 docker image because there isn't any
# official Gradle image at this moment
#
# This is the Gradle build system for JVM applications # This is the Gradle build system for JVM applications
# https://gradle.org/ # https://gradle.org/
# https://github.com/gradle/gradle # https://github.com/gradle/gradle
image: java:8 image: gradle:alpine
# Disable the Gradle daemon for Continuous Integration servers as correctness # Disable the Gradle daemon for Continuous Integration servers as correctness
# is usually a priority over speed in CI environments. Using a fresh # is usually a priority over speed in CI environments. Using a fresh
# runtime for each build is more reliable since the runtime is completely # runtime for each build is more reliable since the runtime is completely
# isolated from any previous builds. # isolated from any previous builds.
variables: variables:
GRADLE_OPTS: "-Dorg.gradle.daemon=false" GRADLE_OPTS: "-Dorg.gradle.daemon=false"
# Make the gradle wrapper executable. This essentially downloads a copy of
# Gradle to build the project with.
# https://docs.gradle.org/current/userguide/gradle_wrapper.html
# It is expected that any modern gradle project has a wrapper
before_script: before_script:
- chmod +x gradlew - export GRADLE_USER_HOME=`pwd`/.gradle
# We redirect the gradle user home using -g so that it caches the
# wrapper and dependencies.
# https://docs.gradle.org/current/userguide/gradle_command_line.html
#
# Unfortunately it also caches the build output so
# cleaning removes reminants of any cached builds.
# The assemble task actually builds the project.
# If it fails here, the tests can't run.
build: build:
stage: build stage: build
script: script: gradle --build-cache assemble
- ./gradlew -g /cache/.gradle clean assemble cache:
allow_failure: false key: "$CI_COMMIT_REF_NAME"
policy: push
paths:
- build
- .gradle
# Use the generated build output to run the tests.
test: test:
stage: test stage: test
script: script: gradle check
- ./gradlew -g /cache/.gradle check cache:
key: "$CI_COMMIT_REF_NAME"
policy: pull
paths:
- build
- .gradle
...@@ -34,6 +34,10 @@ before_script: ...@@ -34,6 +34,10 @@ before_script:
# Install php extensions # Install php extensions
- docker-php-ext-install mbstring mcrypt pdo_mysql curl json intl gd xml zip bz2 opcache - docker-php-ext-install mbstring mcrypt pdo_mysql curl json intl gd xml zip bz2 opcache
# Install & enable Xdebug for code coverage reports
- pecl install xdebug
- docker-php-ext-enable xdebug
# Install Composer and project dependencies. # Install Composer and project dependencies.
- curl -sS https://getcomposer.org/installer | php - curl -sS https://getcomposer.org/installer | php
- php composer.phar install - php composer.phar install
......
...@@ -11,6 +11,9 @@ before_script: ...@@ -11,6 +11,9 @@ before_script:
- apt-get install -yqq git libmcrypt-dev libpq-dev libcurl4-gnutls-dev libicu-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libsqlite3-dev libaspell-dev libsnmp-dev libpcre3-dev libtidy-dev - apt-get install -yqq git libmcrypt-dev libpq-dev libcurl4-gnutls-dev libicu-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libsqlite3-dev libaspell-dev libsnmp-dev libpcre3-dev libtidy-dev
# Install PHP extensions # Install PHP extensions
- docker-php-ext-install mbstring mcrypt pdo_pgsql curl json intl gd xml zip bz2 opcache - docker-php-ext-install mbstring mcrypt pdo_pgsql curl json intl gd xml zip bz2 opcache
# Install & enable Xdebug for code coverage reports
- pecl install xdebug
- docker-php-ext-enable xdebug
# Install and run Composer # Install and run Composer
- curl -sS https://getcomposer.org/installer | php - curl -sS https://getcomposer.org/installer | php
- php composer.phar install - php composer.phar install
......
# Official language image. Look for the different tagged releases at: # Official language image. Look for the different tagged releases at:
# https://hub.docker.com/r/library/ruby/tags/ # https://hub.docker.com/r/library/ruby/tags/
image: "ruby:2.3" image: "ruby:2.4"
# Pick zero or more services to be used on all builds. # Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in. # Only needed when using a docker container to run your tests in.
...@@ -40,9 +40,9 @@ rails: ...@@ -40,9 +40,9 @@ rails:
variables: variables:
DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB" DATABASE_URL: "postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB"
script: script:
- bundle exec rake db:migrate - rails db:migrate
- bundle exec rake db:seed - rails db:seed
- bundle exec rake test - rails test
# This deploy job uses a simple deploy flow to Heroku, other providers, e.g. AWS Elastic Beanstalk # This deploy job uses a simple deploy flow to Heroku, other providers, e.g. AWS Elastic Beanstalk
# are supported too: https://github.com/travis-ci/dpl # are supported too: https://github.com/travis-ci/dpl
......
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