Commit d6b7ec8d authored by Mark Lapierre's avatar Mark Lapierre

Merge branch '1667_sast_enable_ui_e2e_spec' into 'master'

Add an Enable SAST from UI configuration end to end spec

See merge request gitlab-org/gitlab!56117
parents 05a6be0c 4815f907
......@@ -23,7 +23,7 @@
%strong.file-title-name.has-tooltip.gl-word-break-all{ data: { title: diff_file.new_path, container: 'body' } }
= new_path
- else
%strong.file-title-name.has-tooltip.gl-word-break-all{ data: { title: diff_file.file_path, container: 'body' } }
%strong.file-title-name.has-tooltip.gl-word-break-all{ data: { title: diff_file.file_path, container: 'body', qa_selector: 'file_name_content' } }
= diff_file.file_path
- if diff_file.deleted_file?
......@@ -37,3 +37,4 @@
- if diff_file.stored_externally? && diff_file.external_storage == :lfs
%span.badge.label-lfs.gl-mr-2 LFS
......@@ -33,7 +33,7 @@
Pipelines
%span.badge.badge-pill= @pipelines.size
%li.diffs-tab
= link_to url_for(safe_params.merge(action: 'diffs')), data: {target: 'div#diffs', action: 'diffs', toggle: 'tabvue'} do
= link_to url_for(safe_params.merge(action: 'diffs')), data: {target: 'div#diffs', action: 'diffs', toggle: 'tabvue', qa_selector: 'diffs_tab'} do
Changes
%span.badge.badge-pill= @merge_request.diff_size
......
......@@ -19,9 +19,10 @@
= render layout: 'shared/md_preview', locals: { url: preview_url, referenced_users: true } do
= render 'shared/zen', f: form, attr: :description,
classes: 'note-textarea qa-issuable-form-description rspec-issuable-form-description',
classes: 'note-textarea rspec-issuable-form-description',
placeholder: placeholder,
supports_quick_actions: supports_quick_actions
supports_quick_actions: supports_quick_actions,
qa_selector: 'issuable_form_description'
= render 'shared/notes/hints', supports_quick_actions: supports_quick_actions
.clearfix
.error-alert
......@@ -89,6 +89,7 @@ export default {
:gitlab-ci-present="gitlabCiPresent"
:gitlab-ci-history-path="gitlabCiHistoryPath"
:auto-devops-enabled="autoDevopsEnabled"
:data-qa-selector="`${item.type}_status`"
/>
</template>
......
......@@ -14,7 +14,6 @@ const scannerComponentMap = {
};
export default {
inheritAttrs: false,
props: propsUnion([StatusGeneric, ...Object.values(scannerComponentMap)]),
computed: {
statusComponent() {
......
......@@ -89,6 +89,7 @@ export default {
:value="value"
:disabled="disabled"
:placeholder="placeholder"
:data-qa-selector="`${field}_field`"
@input="$emit('input', $event)"
/>
......
......@@ -47,6 +47,7 @@ export default {
category="primary"
:href="feature.configuration_path"
data-testid="enableButton"
:data-qa-selector="`${feature.type}_enable_button`"
>{{ s__('SecurityConfiguration|Enable') }}</gl-button
>
</template>
......@@ -2,7 +2,6 @@
import { s__ } from '~/locale';
export default {
inheritAttrs: false,
i18n: {
availableForOnDemand: s__('SecurityConfiguration|Available for on-demand DAST'),
},
......
......@@ -2,7 +2,6 @@
import { s__ } from '~/locale';
export default {
inheritAttrs: false,
props: {
feature: {
type: Object,
......
......@@ -7,7 +7,6 @@ export default {
GlLink,
StatusGeneric,
},
inheritAttrs: false,
props: {
feature: {
type: Object,
......
......@@ -46,7 +46,12 @@ export default {
<template>
<gl-form-group>
<gl-form-checkbox :id="entity.name" :checked="entity.enabled" @input="onToggle">
<gl-form-checkbox
:id="entity.name"
:checked="entity.enabled"
:data-qa-selector="`${entity.name}_checkbox`"
@input="onToggle"
>
<span class="gl-font-weight-bold">{{ entity.label }}</span>
<span v-if="entity.description" class="gl-text-gray-500">({{ entity.description }})</span>
</gl-form-checkbox>
......
......@@ -156,6 +156,7 @@ export default {
v-if="shouldRenderAnalyzersSection"
class="gl-mb-5"
data-testid="analyzers-section"
data-qa-selector="analyzer_settings_content"
>
<template #heading>
{{ $options.i18n.analyzersHeading }}
......@@ -208,6 +209,7 @@ export default {
type="submit"
variant="success"
category="primary"
data-qa-selector="submit_button"
>{{ $options.i18n.submitButton }}</gl-button
>
......
......@@ -17,7 +17,7 @@ const props = {
};
const attrs = {
'data-foo': 'bar',
'data-qa-selector': 'foo',
};
describe('FeatureStatus component', () => {
......@@ -31,6 +31,17 @@ describe('FeatureStatus component', () => {
wrapper.destroy();
});
describe('always', () => {
beforeEach(() => {
const [feature] = generateFeatures(1);
createComponent({ attrs, propsData: { feature, ...props } });
});
it('passes through attributes to the expected component', () => {
expect(wrapper.attributes()).toMatchObject(attrs);
});
});
describe.each`
type | expectedComponent
${REPORT_TYPE_SAST} | ${StatusSast}
......@@ -43,10 +54,7 @@ describe('FeatureStatus component', () => {
beforeEach(() => {
[feature] = generateFeatures(1, { type });
createComponent({
propsData: { feature, ...props },
attrs,
});
createComponent({ propsData: { feature, ...props } });
component = wrapper.findComponent(expectedComponent);
});
......
......@@ -166,6 +166,7 @@ module QA
autoload :SecurityDashboard, 'qa/ee/page/project/secure/security_dashboard'
autoload :VulnerabilityDetails, 'qa/ee/page/project/secure/vulnerability_details'
autoload :LicenseCompliance, 'qa/ee/page/project/secure/license_compliance'
autoload :ConfigurationForm, 'qa/ee/page/project/secure/configuration_form'
end
module PathLocks
......
include:
template: License-Scanning.gitlab-ci.yml
.sast-analyzer:
tags:
- qa
- test
script:
- echo "Skipped"
artifacts:
reports:
sast: gl-sast-report.json
license_scanning:
tags:
- qa
- test
script:
- echo "Skipped"
artifacts:
reports:
license_scanning: gl-license-scanning-report.json
# frozen_string_literal: true
source 'https://rubygems.org'
gem 'pry'
# frozen_string_literal: true
module QA
module EE
module Page
module Project
module Secure
class ConfigurationForm < QA::Page::Base
include QA::Page::Component::Select2
include QA::Page::Settings::Common
view 'ee/app/assets/javascripts/security_configuration/sast/components/configuration_form.vue' do
element :submit_button
end
def click_expand_button
expand_content(:analyzer_settings_content)
end
def click_submit_button
click_element(:submit_button)
end
def click_sast_enable_button
click_element('sast_enable_button')
end
def fill_dynamic_field(field_name, content)
fill_element("#{field_name}_field", content)
end
def unselect_dynamic_checkbox(checkbox_name)
# Workaround until https://gitlab.com/gitlab-org/gitlab/-/issues/323297 is resolved
# uncheck_element("#{checkbox_name}_checkbox")
page.driver.browser.action.move_to(find_element("#{checkbox_name}_checkbox", visible: false).native).click.perform
end
def has_sast_status?(status_text)
within_element('sast_status') do
has_text?(status_text)
end
end
end
end
end
end
end
end
......@@ -41,6 +41,14 @@ module QA
end
end
def click_on_security_configuration_link
hover_security_compliance do
within_submenu do
click_element(:security_configuration_link)
end
end
end
def hover_security_compliance
within_sidebar do
find_element(:security_dashboard_link).hover
......
......@@ -8,8 +8,33 @@ module QA
element :issuable_create_button, required: true
end
view 'app/views/shared/form_elements/_description.html.haml' do
element :issuable_form_description
end
view 'app/views/projects/merge_requests/show.html.haml' do
element :diffs_tab
end
view 'app/assets/javascripts/diffs/components/diff_file_header.vue' do
element :file_name_content
end
def create_merge_request
click_element :issuable_create_button, Page::MergeRequest::Show
click_element(:issuable_create_button, Page::MergeRequest::Show)
end
def has_description?(description)
has_element?(:issuable_form_description, text: description)
end
def click_diffs_tab
click_element(:diffs_tab)
click_element(:dismiss_popover_button) if has_element?(:dismiss_popover_button, wait: 1)
end
def has_file?(file_name)
has_element?(:file_name_content, text: file_name)
end
end
end
......
# frozen_string_literal: true
require 'pathname'
module QA
RSpec.describe 'Secure', :runner do
describe 'Enable SAST from UI' do
let(:merge_request_description) do
<<~DESCRIPTION.tr("\n", ' ').strip
Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can
[add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings)
to customize SAST settings.
DESCRIPTION
end
let(:test_data_string_fields_array) do
[
%w(SECURE_ANALYZERS_PREFIX registry.example.com),
%w(SAST_EXCLUDED_PATHS foo,\ bar),
%w(SAST_ANALYZER_IMAGE_TAG latest),
%w(SAST_BANDIT_EXCLUDED_PATHS exclude_path_a,\ exclude_path_b)
]
end
let(:test_data_int_fields_array) do
[
%w(SEARCH_MAX_DEPTH 42),
%w(SAST_BRAKEMAN_LEVEL 43),
%w(SAST_GOSEC_LEVEL 7)
]
end
let(:test_data_checkbox_exclude_array) do
%w(eslint kubesec nodejs-scan phpcs-security-audit)
end
let(:test_stage_name) do
'test_all_the_things'
end
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'project-with-secure'
project.description = 'Project with Secure'
end
end
let!(:runner) do
Resource::Runner.fabricate! do |runner|
runner.project = project
runner.name = "runner-for-#{project.name}"
runner.tags = %w[qa test]
end
end
after do
runner&.remove_via_api!
end
before do
# Push fixture to generate Secure reports
Resource::Repository::ProjectPush.fabricate! do |project_push|
project_push.project = project
project_push.directory = Pathname
.new(__dir__)
.join('../../../../../ee/fixtures/secure_sast_enable_from_ui_files')
project_push.commit_message = 'Create Secure compatible application to serve premade reports'
end
Flow::Login.sign_in_unless_signed_in
project.visit!
end
it 'runs sast job when enabled from configuration', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1667' do
Flow::Pipeline.visit_latest_pipeline
# Baseline that we do not initially have a sast job
Page::Project::Pipeline::Show.perform do |pipeline|
expect(pipeline).to have_no_job('brakeman-sast')
end
Page::Project::Menu.perform(&:click_on_security_configuration_link)
EE::Page::Project::Secure::ConfigurationForm.perform do |config_form|
expect(config_form).to have_sast_status('Not enabled')
config_form.click_sast_enable_button
config_form.click_expand_button
test_data_string_fields_array.each do |test_data_string_array|
config_form.fill_dynamic_field(test_data_string_array.first, test_data_string_array[1])
end
test_data_int_fields_array.each do |test_data_int_array|
config_form.fill_dynamic_field(test_data_int_array.first, test_data_int_array[1])
end
test_data_checkbox_exclude_array.each do |test_data_checkbox|
config_form.unselect_dynamic_checkbox(test_data_checkbox)
end
config_form.fill_dynamic_field('stage', test_stage_name)
config_form.click_submit_button
end
Page::MergeRequest::New.perform do |new_merge_request|
expect(new_merge_request).to have_description(merge_request_description)
new_merge_request.click_diffs_tab
aggregate_failures "test Merge Request contents" do
expect(new_merge_request).to have_file('.gitlab-ci.yml')
test_data_string_fields_array.each do |test_data_string_array|
expect(new_merge_request).to have_content("#{test_data_string_array.first}: #{test_data_string_array[1]}")
end
test_data_int_fields_array.each do |test_data_int_array|
expect(new_merge_request).to have_content("#{test_data_int_array.first}: '#{test_data_int_array[1]}'")
end
expect(new_merge_request).to have_content("stages: - test - #{test_stage_name}")
expect(new_merge_request).to have_content("SAST_EXCLUDED_ANALYZERS: #{test_data_checkbox_exclude_array.join(', ')}")
end
new_merge_request.create_merge_request
end
Page::MergeRequest::Show.perform do |merge_request|
merge_request.try_to_merge!
end
Flow::Pipeline.visit_latest_pipeline
Page::Project::Pipeline::Show.perform do |pipeline|
expect(pipeline).to have_job('brakeman-sast')
end
Page::Project::Menu.perform(&:click_on_security_configuration_link)
EE::Page::Project::Secure::ConfigurationForm.perform do |config_form|
aggregate_failures "test SAST status is Enabled" do
expect(config_form).to have_sast_status('Enabled')
expect(config_form).not_to have_sast_status('Not enabled')
end
end
end
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