Commit 855e13ca authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents d0f5ddc0 0716b8a1
......@@ -65,33 +65,6 @@
display: inline;
}
.branch-link {
margin-bottom: 2px;
}
.limit-box {
cursor: pointer;
display: inline-flex;
align-items: center;
background-color: $red-100;
border-radius: $border-radius-default;
text-align: center;
&:hover {
background-color: $red-200;
}
.limit-icon {
margin: 0 4px;
}
.limit-message {
line-height: 16px;
margin-right: 8px;
font-size: 12px;
}
}
svg {
vertical-align: text-top;
}
......
......@@ -73,9 +73,7 @@ module CommitsHelper
# Returns a link formatted as a commit branch link
def commit_branch_link(url, text)
link_to(url, class: 'badge badge-gray ref-name branch-link') do
sprite_icon('branch', size: 12, css_class: 'fork-svg') + "#{text}"
end
gl_badge_tag(text, { variant: :info, icon: 'branch' }, { href: url, class: 'gl-font-monospace gl-mb-1' })
end
# Returns the sorted alphabetically links to branches, separated by a comma
......@@ -87,9 +85,7 @@ module CommitsHelper
# Returns a link formatted as a commit tag link
def commit_tag_link(url, text)
link_to(url, class: 'badge badge-gray ref-name') do
sprite_icon('tag', size: 12, css_class: 'gl-mr-2 vertical-align-middle') + "#{text}"
end
gl_badge_tag(text, { variant: :info, icon: 'tag' }, { href: url, class: 'gl-font-monospace' })
end
# Returns the sorted links to tags, separated by a comma
......
.has-tooltip{ class: "limit-box limit-box-#{objects} gl-ml-2", data: { title: _('Project has too many %{label_for_message} to search') % { label_for_message: label_for_message } } }
.limit-icon
- if objects == :branch
= sprite_icon('fork', size: 12)
- else
= sprite_icon('tag')
.limit-message
%span= _('%{label_for_message} unavailable') % { label_for_message: label_for_message.capitalize }
- icon = objects == :branch ? 'fork' : 'tag'
- text = _('%{label_for_message} unavailable') % { label_for_message: label_for_message.capitalize }
- tooltip_title = _('Project has too many %{label_for_message} to search') % { label_for_message: label_for_message }
= gl_badge_tag(text, { variant: :danger, icon: icon }, { class: 'has-tooltip gl-ml-2', data: { title: tooltip_title } })
......@@ -6,8 +6,9 @@
- if @branches.any? || @tags.any? || @tags_limit_exceeded
%span
= link_to "#", class: "js-details-expand badge badge-gray ref-name" do
= sprite_icon('ellipsis_h', size: 12, css_class: 'vertical-align-middle')
= gl_badge_tag(_("Expand"),
{ variant: :info, icon: 'ellipsis_h', icon_only: true },
{ href: '#', class: 'js-details-expand gl-font-monospace' })
%span.js-details-content.hide
= commit_branches_links(@project, @branches)
- if @tags_limit_exceeded
......
......@@ -22,7 +22,7 @@
.row
.form-group.col-sm-12
= f.label :role, _('Role'), class: 'label-bold'
= f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, { include_blank: _('Select a role') }, class: 'form-control js-user-role-dropdown', autofocus: true, required: true
= f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, { include_blank: _('Select a role') }, class: 'form-control js-user-role-dropdown', autofocus: true, required: true, data: { qa_selector: 'role_dropdown' }
- if Feature.enabled?(:user_other_role_details)
.row
.form-group.col-sm-12.js-other-role-group.hidden
......
......@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56296
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321948
milestone: '13.11'
type: development
group: group::access
group: group::workspace
default_enabled: false
......@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67652
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340159
milestone: '14.3'
type: development
group: group::access
group: group::workspace
default_enabled: false
......@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57137
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334952
milestone: '13.12'
type: development
group: group::access
group: group::workspace
default_enabled: false
......@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72662
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343619
milestone: '14.6'
type: development
group: group::access
group: group::workspace
default_enabled: false
......@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61163
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331907
milestone: '14.0'
type: development
group: group::access
group: group::workspace
default_enabled: false
......@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67650
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345666
milestone: '14.6'
type: development
group: group::access
group: group::workspace
default_enabled: false
......@@ -42,6 +42,13 @@ export const POLICY_TYPE_COMPONENT_OPTIONS = {
urlParameter: 'scan_execution_policy',
value: 'scanExecution',
},
scanResult: {
component: 'scan-result-policy-editor',
text: s__('SecurityOrchestration|Scan Result'),
typeName: 'ScanResultPolicy',
urlParameter: 'scan_result_policy',
value: 'scanResult',
},
};
export const POLICY_TYPE_OPTIONS = {
......@@ -53,6 +60,10 @@ export const POLICY_TYPE_OPTIONS = {
value: 'POLICY_TYPE_SCAN_EXECUTION',
text: s__('SecurityOrchestration|Scan execution'),
},
POLICY_TYPE_SCAN_RESULT: {
value: 'POLICY_TYPE_SCAN_RESULT',
text: s__('SecurityOrchestration|Scan result'),
},
ALL: {
value: '',
text: s__('SecurityOrchestration|All policies'),
......
......@@ -14,8 +14,10 @@ import createFlash from '~/flash';
import { getTimeago } from '~/lib/utils/datetime_utility';
import { setUrlFragment, mergeUrlParams } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import networkPoliciesQuery from '../../graphql/queries/network_policies.query.graphql';
import scanExecutionPoliciesQuery from '../../graphql/queries/scan_execution_policies.query.graphql';
import scanResultPoliciesQuery from '../../graphql/queries/scan_result_policies.query.graphql';
import { getPolicyType } from '../../utils';
import { POLICY_TYPE_COMPONENT_OPTIONS, POLICY_TYPE_OPTIONS } from '../constants';
import EnvironmentPicker from '../environment_picker.vue';
......@@ -57,6 +59,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
mixins: [glFeatureFlagMixin()],
inject: ['documentationPath', 'projectPath', 'newPolicyPath'],
props: {
shouldUpdatePolicyList: {
......@@ -100,12 +103,25 @@ export default {
},
error: createPolicyFetchError,
},
scanResultPolicies: {
query: scanResultPoliciesQuery,
variables() {
return {
fullPath: this.projectPath,
};
},
update(data) {
return data?.project?.scanResultPolicies?.nodes ?? [];
},
error: createPolicyFetchError,
},
},
data() {
return {
selectedPolicy: null,
networkPolicies: [],
scanExecutionPolicies: [],
scanResultPolicies: [],
selectedPolicyType: POLICY_TYPE_OPTIONS.ALL.value,
};
},
......@@ -113,10 +129,14 @@ export default {
...mapState('threatMonitoring', ['allEnvironments', 'currentEnvironmentId', 'hasEnvironment']),
...mapGetters('threatMonitoring', ['currentEnvironmentGid']),
allPolicyTypes() {
return {
const allTypes = {
[POLICY_TYPE_OPTIONS.POLICY_TYPE_NETWORK.value]: this.networkPolicies,
[POLICY_TYPE_OPTIONS.POLICY_TYPE_SCAN_EXECUTION.value]: this.scanExecutionPolicies,
};
if (this.isFeatureEnabled) {
allTypes[POLICY_TYPE_OPTIONS.POLICY_TYPE_SCAN_RESULT.value] = this.scanResultPolicies;
}
return allTypes;
},
documentationFullPath() {
return setUrlFragment(this.documentationPath, 'container-network-policy');
......@@ -141,7 +161,8 @@ export default {
isLoadingPolicies() {
return (
this.$apollo.queries.networkPolicies.loading ||
this.$apollo.queries.scanExecutionPolicies.loading
this.$apollo.queries.scanExecutionPolicies.loading ||
this.$apollo.queries.scanResultPolicies.loading
);
},
hasSelectedPolicy() {
......@@ -207,11 +228,15 @@ export default {
return fields;
},
isFeatureEnabled() {
return this.glFeatures.scanResultPolicy;
},
},
watch: {
shouldUpdatePolicyList(newShouldUpdatePolicyList) {
if (newShouldUpdatePolicyList) {
this.$apollo.queries.scanExecutionPolicies.refetch();
this.$apollo.queries.scanResultPolicies.refetch();
this.$emit('update-policy-list', false);
}
},
......
<script>
import { GlFormGroup, GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { __ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { POLICY_TYPE_OPTIONS } from './constants';
export default {
......@@ -10,6 +11,7 @@ export default {
GlDropdown,
GlDropdownItem,
},
mixins: [glFeatureFlagMixin()],
props: {
value: {
type: String,
......@@ -24,6 +26,16 @@ export default {
selectedValueText() {
return Object.values(POLICY_TYPE_OPTIONS).find(({ value }) => value === this.value).text;
},
isFeatureEnabled() {
return this.glFeatures.scanResultPolicy;
},
policyTypeOptions() {
const policyType = POLICY_TYPE_OPTIONS;
if (!this.isFeatureEnabled) {
delete policyType.POLICY_TYPE_SCAN_RESULT;
}
return policyType;
},
},
methods: {
setPolicyType({ value }) {
......@@ -51,7 +63,7 @@ export default {
:text="selectedValueText"
>
<gl-dropdown-item
v-for="option in $options.POLICY_TYPE_OPTIONS"
v-for="option in policyTypeOptions"
:key="option.value"
:data-testid="`policy-type-${option.value}-option`"
@click="setPolicyType(option)"
......
query scanResultPolicies($fullPath: ID!) {
project(fullPath: $fullPath) {
id
scanResultPolicies {
nodes {
name
yaml
enabled
updatedAt
}
}
}
}
......@@ -25,6 +25,9 @@ export const getPolicyType = (typeName = '') => {
if (typeName === POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.typeName) {
return POLICY_TYPE_COMPONENT_OPTIONS.scanExecution.value;
}
if (typeName === POLICY_TYPE_COMPONENT_OPTIONS.scanResult.typeName) {
return POLICY_TYPE_COMPONENT_OPTIONS.scanResult.value;
}
return null;
};
......
......@@ -8,7 +8,7 @@
= f.label :setup_for_company, setup_for_company_label_text, class: 'label-bold'
.gl-display-flex.gl-flex-direction-column.gl-lg-flex-direction-row
.gl-flex-grow-1
= f.radio_button :setup_for_company, true, class: 'js-setup-for-company', required: true
= f.radio_button :setup_for_company, true, class: 'js-setup-for-company', required: true, data: { qa_selector: 'setup_for_company_radio' }
= f.label :setup_for_company, _('My company or team'), class: 'normal', value: 'true'
.gl-flex-grow-1
= f.radio_button :setup_for_company, false, class: 'js-setup-for-me', required: true
......
......@@ -8,15 +8,21 @@ import PolicyDrawer from 'ee/threat_monitoring/components/policy_drawer/policy_d
import { PREDEFINED_NETWORK_POLICIES } from 'ee/threat_monitoring/constants';
import networkPoliciesQuery from 'ee/threat_monitoring/graphql/queries/network_policies.query.graphql';
import scanExecutionPoliciesQuery from 'ee/threat_monitoring/graphql/queries/scan_execution_policies.query.graphql';
import scanResultPoliciesQuery from 'ee/threat_monitoring/graphql/queries/scan_result_policies.query.graphql';
import createStore from 'ee/threat_monitoring/store';
import createMockApollo from 'helpers/mock_apollo_helper';
import { stubComponent } from 'helpers/stub_component';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { networkPolicies, scanExecutionPolicies } from '../../mocks/mock_apollo';
import {
networkPolicies,
scanExecutionPolicies,
scanResultPolicies,
} from '../../mocks/mock_apollo';
import {
mockNetworkPoliciesResponse,
mockScanExecutionPoliciesResponse,
mockScanResultPoliciesResponse,
} from '../../mocks/mock_data';
const localVue = createLocalVue();
......@@ -35,9 +41,11 @@ const environments = [
];
const networkPoliciesSpy = networkPolicies(mockNetworkPoliciesResponse);
const scanExecutionPoliciesSpy = scanExecutionPolicies(mockScanExecutionPoliciesResponse);
const scanResultPoliciesSpy = scanResultPolicies(mockScanResultPoliciesResponse);
const defaultRequestHandlers = {
networkPolicies: networkPoliciesSpy,
scanExecutionPolicies: scanExecutionPoliciesSpy,
scanResultPolicies: scanResultPoliciesSpy,
};
const pendingHandler = jest.fn(() => new Promise(() => {}));
......@@ -81,10 +89,12 @@ describe('PoliciesList component', () => {
documentationPath: 'path/to/docs',
newPolicyPath: 'path/to/policy',
projectPath: fullPath,
glFeatures: { scanResultPolicy: true },
},
apolloProvider: createMockApollo([
[networkPoliciesQuery, requestHandlers.networkPolicies],
[scanExecutionPoliciesQuery, requestHandlers.scanExecutionPolicies],
[scanResultPoliciesQuery, requestHandlers.scanResultPolicies],
]),
stubs: {
PolicyDrawer: stubComponent(PolicyDrawer, {
......@@ -163,7 +173,7 @@ describe('PoliciesList component', () => {
});
it('does render default network policies', () => {
expect(findPolicyStatusCells()).toHaveLength(5);
expect(findPolicyStatusCells()).toHaveLength(6);
});
it('fetches network policies on environment change', async () => {
......@@ -190,9 +200,10 @@ describe('PoliciesList component', () => {
describe.each`
rowIndex | expectedPolicyName | expectedPolicyType
${1} | ${mockScanExecutionPoliciesResponse[0].name} | ${'Scan execution'}
${3} | ${mockNetworkPoliciesResponse[0].name} | ${'Network'}
${4} | ${PREDEFINED_NETWORK_POLICIES[0].name} | ${'Network'}
${5} | ${PREDEFINED_NETWORK_POLICIES[1].name} | ${'Network'}
${2} | ${mockScanResultPoliciesResponse[0].name} | ${'Scan result'}
${3} | ${mockNetworkPoliciesResponse[1].name} | ${'Network'}
${4} | ${mockNetworkPoliciesResponse[0].name} | ${'Network'}
${5} | ${PREDEFINED_NETWORK_POLICIES[0].name} | ${'Network'}
`('policy in row #$rowIndex', ({ rowIndex, expectedPolicyName, expectedPolicyType }) => {
let row;
......@@ -211,8 +222,9 @@ describe('PoliciesList component', () => {
it.each`
description | filterBy | hiddenTypes
${'network'} | ${POLICY_TYPE_OPTIONS.POLICY_TYPE_NETWORK} | ${[POLICY_TYPE_OPTIONS.POLICY_TYPE_SCAN_EXECUTION]}
${'scan execution'} | ${POLICY_TYPE_OPTIONS.POLICY_TYPE_SCAN_EXECUTION} | ${[POLICY_TYPE_OPTIONS.POLICY_TYPE_NETWORK]}
${'network'} | ${POLICY_TYPE_OPTIONS.POLICY_TYPE_NETWORK} | ${[POLICY_TYPE_OPTIONS.POLICY_TYPE_SCAN_EXECUTION, POLICY_TYPE_OPTIONS.POLICY_TYPE_SCAN_RESULT]}
${'scan execution'} | ${POLICY_TYPE_OPTIONS.POLICY_TYPE_SCAN_EXECUTION} | ${[POLICY_TYPE_OPTIONS.POLICY_TYPE_NETWORK, POLICY_TYPE_OPTIONS.POLICY_TYPE_SCAN_RESULT]}
${'scan result'} | ${POLICY_TYPE_OPTIONS.POLICY_TYPE_SCAN_RESULT} | ${[POLICY_TYPE_OPTIONS.POLICY_TYPE_NETWORK, POLICY_TYPE_OPTIONS.POLICY_TYPE_SCAN_EXECUTION]}
`('policies filtered by $description type', async ({ filterBy, hiddenTypes }) => {
findPolicyTypeFilter().vm.$emit('input', filterBy.value);
await wrapper.vm.$nextTick();
......@@ -258,7 +270,7 @@ describe('PoliciesList component', () => {
});
it('renders a "Disabled" label for screen readers for disabled policies', () => {
const span = findPolicyStatusCells().at(3).find('span');
const span = findPolicyStatusCells().at(4).find('span');
expect(span.exists()).toBe(true);
expect(span.attributes('class')).toBe('gl-sr-only');
......@@ -284,6 +296,7 @@ describe('PoliciesList component', () => {
${PREDEFINED_NETWORK_POLICIES[0].name} | ${PREDEFINED_NETWORK_POLICIES[0]} | ${'container'} | ${'path/to/policy?environment_id=2&type=container_policy&kind=CiliumNetworkPolicy'}
${PREDEFINED_NETWORK_POLICIES[1].name} | ${PREDEFINED_NETWORK_POLICIES[1]} | ${'container'} | ${'path/to/policy?environment_id=2&type=container_policy&kind=CiliumNetworkPolicy'}
${'scan execution'} | ${mockScanExecutionPoliciesResponse[0]} | ${'scanExecution'} | ${'path/to/policy?environment_id=2&type=scan_execution_policy'}
${'scan result'} | ${mockScanResultPoliciesResponse[0]} | ${'scanResult'} | ${'path/to/policy?environment_id=2&type=scan_result_policy'}
`('given there is a $description policy selected', ({ policy, policyType, editPolicyPath }) => {
beforeEach(() => {
mountShallowWrapper();
......@@ -331,7 +344,7 @@ describe('PoliciesList component', () => {
});
it('does not render default network policies', () => {
expect(findPolicyStatusCells()).toHaveLength(1);
expect(findPolicyStatusCells()).toHaveLength(2);
});
});
});
......@@ -57,6 +57,18 @@ export const scanExecutionPolicies = (nodes) =>
},
});
export const scanResultPolicies = (nodes) =>
jest.fn().mockResolvedValue({
data: {
project: {
id: '3',
scanResultPolicies: {
nodes,
},
},
},
});
export const mockLinkSecurityPolicyProjectResponses = {
success: jest.fn().mockResolvedValue({ data: { securityPolicyProjectAssign: { errors: [] } } }),
failure: jest
......
......@@ -200,8 +200,40 @@ export const mockScanExecutionPolicy = {
latestScan: { date: new Date('2021-06-07T00:00:00.000Z'), pipelineUrl: 'path/to/pipeline' },
};
export const mockScanResultManifest = `type: scan_execution_policy
name: critical vulnerability CS approvals
description: This policy enforces critical vulnerability CS approvals
enabled: true
rules:
- type: scan_finding
branches:
- master
scanners:
- container_scanning
vulnerability_allowed: 1
severity_levels:
- critical
vulnerability_states:
- newly_added
actions:
- type: require_approval
approvals_required: 1
user_approvers:
- the.one
`;
export const mockScanResultPolicy = {
__typename: 'ScanResultPolicy',
name: 'critical vulnerability CS approvals',
updatedAt: new Date('2021-06-07T00:00:00.000Z'),
yaml: mockScanResultManifest,
enabled: true,
};
export const mockScanExecutionPoliciesResponse = [mockScanExecutionPolicy];
export const mockScanResultPoliciesResponse = [mockScanResultPolicy];
export const mockNominalHistory = [
['2019-12-04T00:00:00.000Z', 56],
['2019-12-05T00:00:00.000Z', 2647],
......
......@@ -31642,12 +31642,18 @@ msgstr ""
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
msgid "SecurityOrchestration|Scan Result"
msgstr ""
msgid "SecurityOrchestration|Scan execution"
msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
msgid "SecurityOrchestration|Scan result"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
......
# frozen_string_literal: true
module Gitlab
module Page
module Main
class Welcome < Chemlab::Page
path '/users/sign_up/welcome'
button :get_started_button
end
end
end
end
# frozen_string_literal: true
module Gitlab
module Page
module Main
module Welcome
# @note Defined as +button :get_started_button+
# Clicks +get_started_button+
def get_started_button
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Main::Welcome.perform do |welcome|
# expect(welcome.get_started_button_element).to exist
# end
# @return [Watir::Button] The raw +Button+ element
def get_started_button_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Main::Welcome.perform do |welcome|
# expect(welcome).to be_get_started_button
# end
# @return [Boolean] true if the +get_started_button+ element is present on the page
def get_started_button?
# This is a stub, used for indexing. The method is dynamically generated.
end
end
end
end
end
......@@ -7,13 +7,24 @@ module QA
module Welcome
extend QA::Page::PageConcern
def self.included(base)
def self.prepended(base)
super
base.view 'ee/app/views/registrations/welcome/_button.html.haml' do
element :get_started_button
base.class_eval do
view 'ee/app/views/registrations/welcome/_button.html.haml' do
element :get_started_button
end
view 'ee/app/views/registrations/welcome/_setup_for_company.html.haml' do
element :setup_for_company_radio
end
end
end
# setup_for_company_radio is only shown in development environment and .com
def choose_setup_for_company_if_available
choose_element(:setup_for_company_radio) if QA::Runtime::Env.running_on_dev_or_dot_com?
end
end
end
end
......
......@@ -26,9 +26,12 @@ module QA
sign_up.click_new_user_register_button
end
Page::Registration::Welcome.perform(&:click_get_started_button_if_available)
Flow::UserOnboarding.onboard_user
success = if user.expect_fabrication_success
# In development env and .com the user is asked to create a group and a project which can be skipped for
# the purpose of signing up
Runtime::Browser.visit(:gitlab, Page::Dashboard::Welcome)
Page::Main::Menu.perform(&:has_personal_area?)
else
Page::Main::Menu.perform(&:not_signed_in?)
......
# frozen_string_literal: true
module QA
module Flow
module UserOnboarding
module_function
def onboard_user
Page::Registration::Welcome.perform do |welcome_page|
if welcome_page.has_get_started_button?
welcome_page.select_role('Other')
welcome_page.choose_setup_for_company_if_available
welcome_page.click_get_started_button
end
end
end
end
end
end
......@@ -11,6 +11,10 @@ module QA
def has_welcome_title?(text)
has_element?(:welcome_title_content, text: text)
end
def self.path
'/'
end
end
end
end
......
......@@ -16,10 +16,6 @@ module QA
element :new_user_username_field
end
view 'app/views/registrations/welcome/show.html.haml' do
element :get_started_button
end
def fill_new_user_first_name_field(first_name)
fill_element :new_user_first_name_field, first_name
end
......
......@@ -6,14 +6,25 @@ module QA
class Welcome < Page::Base
view 'app/views/registrations/welcome/show.html.haml' do
element :get_started_button
element :role_dropdown
end
def click_get_started_button_if_available
if has_element?(:get_started_button)
Support::Retrier.retry_until do
click_element :get_started_button
has_no_element?(:get_started_button)
end
def has_get_started_button?
has_element?(:get_started_button)
end
def select_role(role)
select_element(:role_dropdown, role)
end
def choose_setup_for_company_if_available
# Only implemented in EE
end
def click_get_started_button
Support::Retrier.retry_until do
click_element :get_started_button
has_no_element?(:get_started_button)
end
end
end
......
......@@ -90,6 +90,20 @@ module QA
enabled?(ENV['ACCEPT_INSECURE_CERTS'])
end
def running_on_dot_com?
uri = URI.parse(Runtime::Scenario.gitlab_address)
uri.host.include?('.com')
end
def running_on_dev?
uri = URI.parse(Runtime::Scenario.gitlab_address)
uri.port != 80 && uri.port != 443
end
def running_on_dev_or_dot_com?
running_on_dev? || running_on_dot_com?
end
def running_in_ci?
ENV['CI'] || ENV['CI_SERVER']
end
......
......@@ -118,11 +118,12 @@ module QA
Flow::Login.sign_in(as: @user, skip_page_validation: true)
Page::Registration::Welcome.perform(&:click_get_started_button_if_available)
Flow::UserOnboarding.onboard_user
Page::Main::Menu.perform do |menu|
expect(menu).to have_personal_area
end
# In development env and .com the user is asked to create a group and a project which can be skipped for
# the purpose of this test
Runtime::Browser.visit(:gitlab, Page::Dashboard::Welcome)
Page::Main::Menu.perform(&:has_personal_area?)
end
after do
......
......@@ -20,6 +20,7 @@ module QA
before do
# Enable sign-ups
Runtime::ApplicationSettings.set_application_settings(signup_enabled: true)
Runtime::ApplicationSettings.set_application_settings(require_admin_approval_after_user_signup: true)
# Register the new user through the registration page
Gitlab::Page::Main::SignUp.perform do |sign_up|
......@@ -27,10 +28,7 @@ module QA
sign_up.register_user(user)
end
# Click the Get Started button on the welcome page if it presents itself
Gitlab::Page::Main::Welcome.perform do |welcome|
welcome.get_started_button if welcome.get_started_button?
end
Flow::UserOnboarding.onboard_user
end
after do
......
......@@ -83,6 +83,46 @@ RSpec.describe QA::Runtime::Env do
end
end
describe '.running_on_dot_com?' do
using RSpec::Parameterized::TableSyntax
where(:url, :result) do
'https://www.gitlab.com' | true
'https://staging.gitlab.com' | true
'http://www.gitlab.com' | true
'http://localhost:3000' | false
'http://localhost' | false
'http://gdk.test:3000' | false
end
with_them do
before do
QA::Runtime::Scenario.define(:gitlab_address, url)
end
it { expect(described_class.running_on_dot_com?).to eq result }
end
end
describe '.running_on_dev?' do
using RSpec::Parameterized::TableSyntax
where(:url, :result) do
'https://www.gitlab.com' | false
'http://localhost:3000' | true
'http://localhost' | false
'http://gdk.test:3000' | true
end
with_them do
before do
QA::Runtime::Scenario.define(:gitlab_address, url)
end
it { expect(described_class.running_on_dev?).to eq result }
end
end
describe '.personal_access_token' do
around do |example|
described_class.instance_variable_set(:@personal_access_token, nil)
......
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