Commit d15b00e7 authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch 'master' into fl-eslint-vue-house-keeping-ee

* master:
  Assignee lists docs
  Fix parsing of vulnerabilities file lines
  Loosen the 'newly created MR' matcher
  Ensure we look into the correct setion only when expanding a settings' section
parents aa5b5bdb 44389a14
......@@ -169,7 +169,7 @@
.settings-content
= render 'logging'
%section.settings.as-repository-storage.no-animate#js-repository-storage-settings{ class: ('expanded' if expanded) }
%section.qa-repository-storage-settings.settings.as-repository-storage.no-animate#js-repository-storage-settings{ class: ('expanded' if expanded) }
.settings-header
%h4
= _('Repository storage')
......
- expanded = Rails.env.test?
%section.settings.no-animate{ class: ('expanded' if expanded) }
%section.qa-deploy-keys-settings.settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4
Deploy Keys
......
......@@ -82,7 +82,7 @@
= render_if_exists 'projects/issues_settings'
%section.settings.merge-requests-feature.no-animate{ class: [('expanded' if expanded), ('hidden' if @project.project_feature.send(:merge_requests_access_level) == 0)] }
%section.qa-merge-request-settings.settings.merge-requests-feature.no-animate{ class: [('expanded' if expanded), ('hidden' if @project.project_feature.send(:merge_requests_access_level) == 0)] }
.settings-header
%h4
Merge request
......@@ -101,7 +101,7 @@
= render 'export', project: @project
%section.settings.advanced-settings.no-animate{ class: ('expanded' if expanded) }
%section.qa-advanced-settings.settings.advanced-settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4
Advanced
......
- expanded = Rails.env.test?
%section.settings.no-animate{ class: ('expanded' if expanded) }
%section.qa-protected-branches-settings.settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4
Protected Branches
......
......@@ -16,7 +16,7 @@
.settings-content
= render 'form'
%section.settings#autodevops-settings.no-animate{ class: ('expanded' if expanded) }
%section.qa-autodevops-settings.settings#autodevops-settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4
= s_('CICD|Auto DevOps')
......@@ -28,7 +28,7 @@
.settings-content
= render 'autodevops_form'
%section.settings.no-animate{ class: ('expanded' if expanded) }
%section.qa-runners-settings.settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4
Runners
......@@ -39,7 +39,7 @@
.settings-content
= render 'projects/runners/index'
%section.settings.no-animate{ class: ('expanded' if expanded) }
%section.qa-variables-settings.settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4
= _('Variables')
......
......@@ -40,9 +40,6 @@ organized from a broader perspective with one Issue Board per project,
but also allow your team members to organize their own workflow by creating
multiple Issue Boards within the same project.
[GitLab Premium] adds even more powerful ways to work with Issue Boards by
allowing you to have assignee lists as well as label lists.
## Use cases
You can see below a few different use cases for GitLab's Issue Boards.
......@@ -345,6 +342,29 @@ navigation level. A group-level issue board allows you to view all issues from a
boards. When updating milestones and labels for an issue through the sidebar update mechanism, again only
group-level objects are available.
## Assignee Lists **[PREMIUM]**
> Introduced in GitLab 11.0 Premium
An assignee list shows all issues for the given assignee. You add an assignee list using the same button as adding
a label list. There's an additional tab to select assignee list, where you specify a user to be the assignee. You remove an assignee
list the same way as a label list, by clicking the Trash icon.
You can have a board with both label lists and assignee lists.
![Assignee lists](img/assignee_lists.png)
## Dragging Issues Between Lists
When dragging issues between lists, different behavior occurs depending on the source list and the target list.
| | To Backlog | To Closed | To label `B` list | To assignee `Bob` list |
| --- | --- | --- | --- | --- |
| From Backlog | - | Issue closed | `B` added | `Bob` assigned |
| From Closed | Issue reopened | - | Issue reopened<br/>`B` added | Issue reopened<br/>`Bob` assigned |
| From label `A` list | `A` removed | Issue closed | `A` removed<br/>`B` added | `Bob` assigned |
| From assignee `Alice` list | `Alice` unassigned | Issue closed | `B` added | `Alice` unassigned<br/>`Bob` assigned |
## Features per tier
Different issue board features are available in different [GitLab tiers](https://about.gitlab.com/pricing/), as shown in the following table:
......
......@@ -47,9 +47,9 @@ function enrichVulnerabilityWithfeedback(vulnerability, feedback = []) {
*/
function fileUrl(location, pathPrefix) {
let lineSuffix = '';
if (!_.isEmpty(location.start_line)) {
if (location.start_line) {
lineSuffix += `#L${location.start_line}`;
if (!_.isEmpty(location.end_line)) {
if (location.end_line) {
lineSuffix += `-${location.end_line}`;
}
}
......@@ -82,7 +82,7 @@ function adaptDeprecatedFormat(issue) {
// Add the new location property
location: {
file: adapted.file,
start_line: adapted.line,
start_line: adapted.line ? parseInt(adapted.line, 10) : undefined,
},
links,
});
......
......@@ -6,11 +6,11 @@ module QA
include QA::Page::Settings::Common
view 'app/views/admin/application_settings/show.html.haml' do
element :advanced_settings_section, 'Repository storage'
element :repository_storage_settings
end
def expand_repository_storage(&block)
expand_section('Repository storage') do
expand_section(:repository_storage_settings) do
RepositoryStorage.perform(&block)
end
end
......
......@@ -4,9 +4,9 @@ module QA
module Settings
class Advanced < Page::Base
view 'app/views/projects/edit.html.haml' do
element :project_path_field, 'f.text_field :path'
element :project_name_field, 'f.text_field :name'
element :rename_project_button, "f.submit 'Rename project'"
element :project_path_field, 'text_field :path'
element :project_name_field, 'text_field :name'
element :rename_project_button, "submit 'Rename project'"
end
def rename_to(path)
......
......@@ -6,31 +6,33 @@ module QA # rubocop:disable Naming/FileName
include Common
view 'app/views/projects/settings/ci_cd/show.html.haml' do
element :runners_settings, 'Runners'
element :secret_variables, 'Variables'
element :auto_devops_section, 'Auto DevOps'
element :autodevops_settings
element :runners_settings
element :variables_settings
end
view 'app/views/projects/settings/ci_cd/_autodevops_form.html.haml' do
element :enable_auto_devops_button, 'Enable Auto DevOps'
element :domain_input, 'Domain'
element :enable_auto_devops_field, 'radio_button :enabled'
element :domain_field, 'text_field :domain'
element :enable_auto_devops_button, "%strong= s_('CICD|Enable Auto DevOps')"
element :domain_input, "%strong= _('Domain')"
element :save_changes_button, "submit 'Save changes'"
end
def expand_runners_settings(&block)
expand_section('Runners') do
expand_section(:runners_settings) do
Settings::Runners.perform(&block)
end
end
def expand_secret_variables(&block)
expand_section('Variables') do
expand_section(:variables_settings) do
Settings::SecretVariables.perform(&block)
end
end
def enable_auto_devops_with_domain(domain)
expand_section('Auto DevOps') do
expand_section(:autodevops_settings) do
choose 'Enable Auto DevOps'
fill_in 'Domain', with: domain
click_on 'Save changes'
......
......@@ -6,11 +6,11 @@ module QA
include Common
view 'app/views/projects/edit.html.haml' do
element :advanced_settings_section, 'Advanced'
element :advanced_settings
end
def expand_advanced_settings(&block)
expand_section('Advanced settings') do
expand_section(:advanced_settings) do
Advanced.perform(&block)
end
end
......
......@@ -5,17 +5,17 @@ module QA
class MergeRequest < QA::Page::Base
include Common
view 'app/views/projects/_merge_request_merge_method_settings.html.haml' do
element :radio_button_merge_ff
end
view 'app/views/projects/edit.html.haml' do
element :merge_request_settings, 'Merge request'
element :merge_request_settings
element :save_merge_request_changes
end
view 'app/views/projects/_merge_request_merge_method_settings.html.haml' do
element :radio_button_merge_ff
end
def enable_ff_only
expand_section('Merge request') do
expand_section(:merge_request_settings) do
click_element :radio_button_merge_ff
click_element :save_merge_request_changes
end
......
......@@ -6,17 +6,21 @@ module QA
include Common
view 'app/views/projects/deploy_keys/_index.html.haml' do
element :deploy_keys_section, 'Deploy Keys'
element :deploy_keys_settings
end
view 'app/views/projects/protected_branches/shared/_index.html.haml' do
element :protected_branches_settings
end
def expand_deploy_keys(&block)
expand_section('Deploy Keys') do
expand_section(:deploy_keys_settings) do
DeployKeys.perform(&block)
end
end
def expand_protected_branches(&block)
expand_section('Protected Branches') do
expand_section(:protected_branches_settings) do
ProtectedBranches.perform(&block)
end
end
......
......@@ -4,19 +4,17 @@ module QA
module Common
# Click the Expand button present in the specified section
#
# @param [String] name present in the container in the DOM
def expand_section(name)
page.within('#content-body') do
page.within('section', text: name) do
# Because it is possible to click the button before the JS toggle code is bound
wait(reload: false) do
click_button 'Expand' unless first('button', text: 'Collapse')
# @param [Symbol] and `element` name defined in a `view` block
def expand_section(element_name)
within_element(element_name) do
# Because it is possible to click the button before the JS toggle code is bound
wait(reload: false) do
click_button 'Expand' unless first('button', text: 'Collapse')
page.has_content?('Collapse')
end
yield if block_given?
page.has_content?('Collapse')
end
yield if block_given?
end
end
end
......
......@@ -11,7 +11,7 @@ module QA
expect(page).to have_content('This is a merge request')
expect(page).to have_content('Great feature')
expect(page).to have_content(/Opened [\w\s]+ a minute ago/)
expect(page).to have_content(/Opened [\w\s]+ ago/)
end
end
end
......@@ -46,6 +46,8 @@ export const sastIssues = [
solution: 'upgrade to ~> 3.2.21, ~> 4.0.11.1, ~> 4.0.12, ~> 4.1.7.1, >= 4.1.8',
location: {
file: 'Gemfile.lock',
start_line: 5,
end_line: 10,
},
links: [{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
......@@ -106,6 +108,7 @@ export const oldSastIssues = [
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
cve: 'CVE-2014-7829',
file: 'Gemfile.lock',
line: '5',
solution: 'upgrade to ~> 3.2.21, ~> 4.0.11.1, ~> 4.0.12, ~> 4.1.7.1, >= 4.1.8',
},
];
......@@ -120,6 +123,8 @@ export const sastIssuesBase = [
'upgrade to >= 5.0.0.beta1.1, >= 4.2.5.1, ~> 4.2.5, >= 4.1.14.1, ~> 4.1.14, ~> 3.2.22.1',
location: {
file: 'Gemfile.lock',
start_line: 5,
end_line: 10,
},
links: [{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
......@@ -161,11 +166,13 @@ export const parsedSastIssuesStore = [
solution: 'upgrade to ~> 3.2.21, ~> 4.0.11.1, ~> 4.0.12, ~> 4.1.7.1, >= 4.1.8',
title: 'Arbitrary file existence disclosure in Action Pack',
path: 'Gemfile.lock',
urlPath: 'path/Gemfile.lock',
urlPath: 'path/Gemfile.lock#L5-10',
category: 'sast',
project_fingerprint: 'f55331d66fd4f3bfb4237d48e9c9fa8704bd33c6',
location: {
file: 'Gemfile.lock',
start_line: 5,
end_line: 10,
},
links: [{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
......@@ -235,11 +242,13 @@ export const parsedSastIssuesHead = [
solution: 'upgrade to ~> 3.2.21, ~> 4.0.11.1, ~> 4.0.12, ~> 4.1.7.1, >= 4.1.8',
title: 'Arbitrary file existence disclosure in Action Pack',
path: 'Gemfile.lock',
urlPath: 'path/Gemfile.lock',
urlPath: 'path/Gemfile.lock#L5-10',
category: 'sast',
project_fingerprint: 'f55331d66fd4f3bfb4237d48e9c9fa8704bd33c6',
location: {
file: 'Gemfile.lock',
start_line: 5,
end_line: 10,
},
links: [{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
......@@ -286,11 +295,13 @@ export const parsedSastBaseStore = [
solution:
'upgrade to >= 5.0.0.beta1.1, >= 4.2.5.1, ~> 4.2.5, >= 4.1.14.1, ~> 4.1.14, ~> 3.2.22.1',
path: 'Gemfile.lock',
urlPath: 'path/Gemfile.lock',
urlPath: 'path/Gemfile.lock#L5-10',
category: 'sast',
project_fingerprint: '3f5608c99f0c7442ba59bc6c0c1864d0000f8e1a',
location: {
file: 'Gemfile.lock',
start_line: 5,
end_line: 10,
},
links: [{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
......@@ -311,6 +322,7 @@ export const dependencyScanningIssues = [
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
cve: 'CVE-2014-7829',
file: 'Gemfile.lock',
line: '5',
solution: 'upgrade to ~> 3.2.21, ~> 4.0.11.1, ~> 4.0.12, ~> 4.1.7.1, >= 4.1.8',
},
{
......@@ -361,15 +373,16 @@ export const parsedDependencyScanningIssuesStore = [
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
cve: 'CVE-2014-7829',
file: 'Gemfile.lock',
line: '5',
solution: 'upgrade to ~> 3.2.21, ~> 4.0.11.1, ~> 4.0.12, ~> 4.1.7.1, >= 4.1.8',
title: 'Arbitrary file existence disclosure in Action Pack',
path: 'Gemfile.lock',
urlPath: 'path/Gemfile.lock',
urlPath: 'path/Gemfile.lock#L5',
category: 'dependency_scanning',
project_fingerprint: 'f55331d66fd4f3bfb4237d48e9c9fa8704bd33c6',
location: {
file: 'Gemfile.lock',
start_line: undefined,
start_line: 5,
},
links: [{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
......@@ -426,15 +439,16 @@ export const parsedDependencyScanningIssuesHead = [
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
cve: 'CVE-2014-7829',
file: 'Gemfile.lock',
line: '5',
solution: 'upgrade to ~> 3.2.21, ~> 4.0.11.1, ~> 4.0.12, ~> 4.1.7.1, >= 4.1.8',
title: 'Arbitrary file existence disclosure in Action Pack',
path: 'Gemfile.lock',
urlPath: 'path/Gemfile.lock',
urlPath: 'path/Gemfile.lock#L5',
category: 'dependency_scanning',
project_fingerprint: 'f55331d66fd4f3bfb4237d48e9c9fa8704bd33c6',
location: {
file: 'Gemfile.lock',
start_line: undefined,
start_line: 5,
},
links: [{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
......
......@@ -57,6 +57,9 @@ describe('security reports utils', () => {
const parsed = parseSastIssues(oldSastIssues, [], 'path')[0];
expect(parsed.title).toEqual(sastIssues[0].message);
expect(parsed.path).toEqual(sastIssues[0].location.file);
expect(parsed.location.start_line).toEqual(sastIssues[0].location.start_line);
expect(parsed.location.end_line).toBeUndefined();
expect(parsed.urlPath).toEqual('path/Gemfile.lock#L5');
expect(parsed.project_fingerprint).toEqual(sha1(sastIssues[0].cve));
});
......@@ -64,9 +67,17 @@ describe('security reports utils', () => {
const parsed = parseSastIssues(sastIssues, [], 'path')[0];
expect(parsed.title).toEqual(sastIssues[0].message);
expect(parsed.path).toEqual(sastIssues[0].location.file);
expect(parsed.location.start_line).toEqual(sastIssues[0].location.start_line);
expect(parsed.location.end_line).toEqual(sastIssues[0].location.end_line);
expect(parsed.urlPath).toEqual('path/Gemfile.lock#L5-10');
expect(parsed.project_fingerprint).toEqual(sha1(sastIssues[0].cve));
});
it('generate correct path to file when there is no line', () => {
const parsed = parseSastIssues(sastIssues, [], 'path')[1];
expect(parsed.urlPath).toEqual('path/Gemfile.lock');
});
it('includes vulnerability feedbacks', () => {
const parsed = parseSastIssues(
sastIssues,
......@@ -85,9 +96,17 @@ describe('security reports utils', () => {
const parsed = parseDependencyScanningIssues(dependencyScanningIssues, [], 'path')[0];
expect(parsed.title).toEqual(dependencyScanningIssues[0].message);
expect(parsed.path).toEqual(dependencyScanningIssues[0].file);
expect(parsed.location.start_line).toEqual(sastIssues[0].location.start_line);
expect(parsed.location.end_line).toBeUndefined();
expect(parsed.urlPath).toEqual('path/Gemfile.lock#L5');
expect(parsed.project_fingerprint).toEqual(sha1(dependencyScanningIssues[0].cve));
});
it('generate correct path to file when there is no line', () => {
const parsed = parseDependencyScanningIssues(dependencyScanningIssues, [], 'path')[1];
expect(parsed.urlPath).toEqual('path/Gemfile.lock');
});
it('uses message to generate sha1 when cve is undefined', () => {
const issuesWithoutCve = dependencyScanningIssues.map(issue => ({
...issue,
......
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