Skip to content
Snippets Groups Projects
Commit 26384c9a authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 79cbe31b
No related branches found
No related tags found
No related merge requests found
Showing
with 357 additions and 206 deletions
Loading
Loading
@@ -291,15 +291,9 @@ As the DAST job belongs to a separate `dast` stage that runs after all
[default stages](../../../ci/yaml/README.md#stages),
don't forget to add `stage: dast` when you override the template job definition.
 
## Available variables
### Available variables
 
DAST can be [configured](#customizing-the-dast-settings) using environment variables.
Since it's a wrapper around the ZAP scanning scripts
([baseline](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan)
or [full](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) scan), it
accepts all arguments those scripts recognize (the arguments are the same).
The choice of the scan type depends on the `DAST_FULL_SCAN_ENABLED` environment
variable value.
 
| Environment variable | Required | Description |
|-----------------------------| ----------|--------------------------------------------------------------------------------|
Loading
Loading
@@ -314,14 +308,83 @@ variable value.
| `DAST_FULL_SCAN_ENABLED` | no | Switches the tool to execute [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) instead of [ZAP Baseline Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan). Boolean. `true`, `True`, or `1` are considered as true value, otherwise false. Defaults to `false`. |
| `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` | no | Requires [domain validation](#domain-validation) when running DAST full scans. Boolean. `true`, `True`, or `1` are considered as true value, otherwise false. Defaults to `false`. |
 
## Reports JSON format
### DAST command-line options
Not all DAST configuration is available via environment variables. To find out all possible options, run the following configuration.
Available command-line options will be printed to the job log:
```yaml
include:
template: DAST.gitlab-ci.yml
dast:
script:
- /analyze --help
```
You must then overwrite the `script` command to pass in the appropriate argument. For example, AJAX spidering can be enabled by using `-j`, as shown in the following configuration:
```yaml
include:
template: DAST.gitlab-ci.yml
dast:
script:
- export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)}
- /analyze -j -t $DAST_WEBSITE
```
### Custom ZAProxy configuration
The ZAProxy server contains many [useful configurable values](https://gitlab.com/gitlab-org/gitlab/issues/36437#note_245801885).
Many key/values for `-config` remain undocumented, but there is an untested list of [possible keys](https://gitlab.com/gitlab-org/gitlab/issues/36437#note_244981023).
Note that these options are not supported by DAST, and may break the DAST scan when used. An example of how to rewrite the Authorization header value with `TOKEN` follows:
```yaml
include:
template: DAST.gitlab-ci.yml
dast:
script:
- export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)}
- /analyze -z"-config replacer.full_list\(0\).description=auth -config replacer.full_list\(0\).enabled=true -config replacer.full_list\(0\).matchtype=REQ_HEADER -config replacer.full_list\(0\).matchstr=Authorization -config replacer.full_list\(0\).regex=false -config replacer.full_list\(0\).replacement=TOKEN" -t $DAST_WEBSITE
```
## Reports
The DAST job can emit various reports.
### JSON
 
CAUTION: **Caution:**
The JSON report artifacts are not a public API of DAST and their format may change in the future.
The JSON report artifacts are not a public API of DAST and their format is expected to change in the future.
The DAST tool always emits a JSON report report file called `gl-dast-report.json` and sample reports can be found in the [DAST repository](https://gitlab.com/gitlab-org/security-products/dast/tree/master/test/end-to-end/expect).
There are two formats of data in the JSON report that are used side by side: the proprietary ZAP format which will be eventually deprecated, and a "common" format which will be the default in the future.
 
The DAST tool emits a JSON report report file. Sample report files can be found in the [DAST repository](https://gitlab.com/gitlab-org/security-products/dast/tree/master/test/end-to-end/expect).
### Other formats
 
There are two formats of data in the JSON document that are used side by side: the proprietary ZAP format which will be eventually deprecated, and a "common" format which will be the default in the future.
Reports can also be generated in Markdown, HTML, and XML.
Reports can be published as artifacts using the following configuration:
```yaml
include:
template: DAST.gitlab-ci.yml
dast:
script:
- export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)}
- /analyze -r report.html -w report.md -x report.xml -t $DAST_WEBSITE
- cp /zap/wrk/report.{html,md,xml} "$PWD"
artifacts:
paths:
- report.html
- report.md
- report.xml
- gl-dast-report.json
```
 
## Security Dashboard
 
Loading
Loading
@@ -329,6 +392,20 @@ The Security Dashboard is a good place to get an overview of all the security
vulnerabilities in your groups, projects and pipelines. Read more about the
[Security Dashboard](../security_dashboard/index.md).
 
## Bleeding-edge vulnerability definitions
ZAProxy first creates rules in the `alpha` class. After a testing period with the community, they are promoted to `beta`. DAST uses `beta` definitions by default. To request `alpha` definitions, use `-a` as shown in the following configuration:
```yaml
include:
template: DAST.gitlab-ci.yml
dast:
script:
- export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)}
- /analyze -a -t $DAST_WEBSITE
```
## Interacting with the vulnerabilities
 
Once a vulnerability is found, you can interact with it. Read more on how to
Loading
Loading
Loading
Loading
@@ -695,14 +695,33 @@ Major upgrades might require additional setup steps, please consult
the official [upgrade guide](https://docs.cilium.io/en/stable/install/upgrade/) for more
information.
 
By default, the drop log for traffic is logged out by the
By default, Cilium will drop all non-whitelisted packets upon policy
deployment. The audit mode is scheduled for release in
[Cilium 1.8](https://github.com/cilium/cilium/pull/9970). In the audit
mode non-whitelisted packets will not be dropped, instead audit
notifications will be generated. GitLab provides alternative Docker
images for Cilium with the audit patch included. You can switch to the
custom build and enable the audit mode by adding the following to
`.gitlab/managed-apps/cilium/values.yaml`:
```yml
global:
registry: registry.gitlab.com/gitlab-org/defend/cilium
policyAuditMode: true
agent:
monitor:
eventTypes: ["drop", "audit"]
```
The Cilium monitor log for traffic is logged out by the
`cilium-monitor` sidecar container. You can check these logs via:
 
```shell
kubectl -n gitlab-managed-apps logs cilium-XXXX cilium-monitor
```
 
Drop logging can be disabled via `.gitlab/managed-apps/cilium/values.yaml`:
You can disable the monitor log via `.gitlab/managed-apps/cilium/values.yaml`:
 
```yml
agent:
Loading
Loading
# frozen_string_literal: true
module Gitlab
module Kubernetes
class GenericSecret
attr_reader :name, :data, :namespace_name
def initialize(name, data, namespace_name)
@name = name
@data = data
@namespace_name = namespace_name
end
def generate
::Kubeclient::Resource.new(
type: generic_secret_type,
metadata: metadata,
data: data
)
end
private
def generic_secret_type
'Opaque'
end
def metadata
{
name: name,
namespace: namespace_name
}
end
end
end
end
# frozen_string_literal: true
module Gitlab
module Kubernetes
class TlsSecret
attr_reader :name, :cert, :key, :namespace_name
def initialize(name, cert, key, namespace_name)
@name = name
@cert = cert
@key = key
@namespace_name = namespace_name
end
def generate
::Kubeclient::Resource.new(
type: tls_secret_type,
metadata: metadata,
data: data
)
end
private
def tls_secret_type
'kubernetes.io/tls'
end
def metadata
{
name: name,
namespace: namespace_name
}
end
def data
{
'tls.crt': Base64.strict_encode64(cert),
'tls.key': Base64.strict_encode64(key)
}
end
end
end
end
Loading
Loading
@@ -13,8 +13,8 @@ module Gitlab
 
def initialize(root, max_size: DEFAULT_MAX_SIZE, max_depth: DEFAULT_MAX_DEPTH)
@root = root
@max_size = max_size
@max_depth = max_depth
@max_size = max_size || DEFAULT_MAX_SIZE
@max_depth = max_depth || DEFAULT_MAX_DEPTH
@size = 0
@depth = 0
 
Loading
Loading
Loading
Loading
@@ -8292,11 +8292,6 @@ msgstr ""
msgid "Fetching licenses failed. You are not permitted to perform this action."
msgstr ""
 
msgid "File"
msgid_plural "Files"
msgstr[0] ""
msgstr[1] ""
msgid "File Hooks"
msgstr ""
 
Loading
Loading
@@ -11931,10 +11926,10 @@ msgstr ""
msgid "MergeRequest|Error loading full diff. Please try again."
msgstr ""
 
msgid "MergeRequest|Filter files or search with %{modifier_key}+p"
msgid "MergeRequest|No files found"
msgstr ""
 
msgid "MergeRequest|No files found"
msgid "MergeRequest|Search files (%{modifier_key}P)"
msgstr ""
 
msgid "Merged"
Loading
Loading
@@ -22185,6 +22180,9 @@ msgstr ""
msgid "among other things"
msgstr ""
 
msgid "and"
msgstr ""
msgid "any-approver for the merge request already exists"
msgstr ""
 
Loading
Loading
@@ -22615,6 +22613,11 @@ msgstr ""
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
 
msgid "file"
msgid_plural "files"
msgstr[0] ""
msgstr[1] ""
msgid "finding is not found or is already attached to a vulnerability"
msgstr ""
 
Loading
Loading
Loading
Loading
@@ -3,10 +3,6 @@
require 'spec_helper'
 
describe ConfirmEmailWarning do
before do
stub_feature_flags(soft_email_confirmation: true)
end
controller(ApplicationController) do
# `described_class` is not available in this context
include ConfirmEmailWarning
Loading
Loading
Loading
Loading
@@ -17,5 +17,14 @@ describe Dashboard::SnippetsController do
create(:personal_snippet, :public, author: user)
end
end
it 'fetches snippet counts via the snippet count service' do
service = double(:count_service, execute: {})
expect(Snippets::CountService)
.to receive(:new).with(user, author: user)
.and_return(service)
get :index
end
end
end
Loading
Loading
@@ -27,6 +27,15 @@ describe Projects::SnippetsController do
end
end
 
it 'fetches snippet counts via the snippet count service' do
service = double(:count_service, execute: {})
expect(Snippets::CountService)
.to receive(:new).with(nil, project: project)
.and_return(service)
get :index, params: { namespace_id: project.namespace, project_id: project }
end
context 'when the project snippet is private' do
let!(:project_snippet) { create(:project_snippet, :private, project: project, author: user) }
 
Loading
Loading
Loading
Loading
@@ -77,34 +77,14 @@ describe RegistrationsController do
context 'when send_user_confirmation_email is true' do
before do
stub_application_setting(send_user_confirmation_email: true)
allow(User).to receive(:allow_unconfirmed_access_for).and_return 2.days
end
 
context 'when soft email confirmation is not enabled' do
before do
stub_feature_flags(soft_email_confirmation: false)
allow(User).to receive(:allow_unconfirmed_access_for).and_return 0
end
it 'does not authenticate the user and sends a confirmation email' do
post(:create, params: user_params)
expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email])
expect(subject.current_user).to be_nil
end
end
it 'authenticates the user and sends a confirmation email' do
post(:create, params: user_params)
 
context 'when soft email confirmation is enabled' do
before do
stub_feature_flags(soft_email_confirmation: true)
allow(User).to receive(:allow_unconfirmed_access_for).and_return 2.days
end
it 'authenticates the user and sends a confirmation email' do
post(:create, params: user_params)
expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email])
expect(response).to redirect_to(dashboard_projects_path)
end
expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email])
expect(response).to redirect_to(dashboard_projects_path)
end
end
 
Loading
Loading
Loading
Loading
@@ -5,5 +5,41 @@ FactoryBot.define do
pages_domain { create(:pages_domain) }
knative { create(:clusters_applications_knative) }
creator { create(:user) }
certificate do
'-----BEGIN CERTIFICATE-----
MIICGzCCAYSgAwIBAgIBATANBgkqhkiG9w0BAQUFADAbMRkwFwYDVQQDExB0ZXN0
LWNlcnRpZmljYXRlMB4XDTE2MDIxMjE0MzIwMFoXDTIwMDQxMjE0MzIwMFowGzEZ
MBcGA1UEAxMQdGVzdC1jZXJ0aWZpY2F0ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
gYkCgYEApL4J9L0ZxFJ1hI1LPIflAlAGvm6ZEvoT4qKU5Xf2JgU7/2geNR1qlNFa
SvCc08Knupp5yTgmvyK/Xi09U0N82vvp4Zvr/diSc4A/RA6Mta6egLySNT438kdT
nY2tR5feoTLwQpX0t4IMlwGQGT5h6Of2fKmDxzuwuyffcIHqLdsCAwEAAaNvMG0w
DAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUxl9WSxBprB0z0ibJs3rXEk0+95AwCwYD
VR0PBAQDAgXgMBEGCWCGSAGG+EIBAQQEAwIGQDAeBglghkgBhvhCAQ0EERYPeGNh
IGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4GBAGC4T8SlFHK0yPSa+idGLQFQ
joZp2JHYvNlTPkRJ/J4TcXxBTJmArcQgTIuNoBtC+0A/SwdK4MfTCUY4vNWNdese
5A4K65Nb7Oh1AdQieTBHNXXCdyFsva9/ScfQGEl7p55a52jOPs0StPd7g64uvjlg
YHi2yesCrOvVXt+lgPTd
-----END CERTIFICATE-----'
end
key do
'-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKS+CfS9GcRSdYSN
SzyH5QJQBr5umRL6E+KilOV39iYFO/9oHjUdapTRWkrwnNPCp7qaeck4Jr8iv14t
PVNDfNr76eGb6/3YknOAP0QOjLWunoC8kjU+N/JHU52NrUeX3qEy8EKV9LeCDJcB
kBk+Yejn9nypg8c7sLsn33CB6i3bAgMBAAECgYA2D26w80T7WZvazYr86BNMePpd
j2mIAqx32KZHzt/lhh40J/SRtX9+Kl0Y7nBoRR5Ja9u/HkAIxNxLiUjwg9r6cpg/
uITEF5nMt7lAk391BuI+7VOZZGbJDsq2ulPd6lO+C8Kq/PI/e4kXcIjeH6KwQsuR
5vrXfBZ3sQfflaiN4QJBANBt8JY2LIGQF8o89qwUpRL5vbnKQ4IzZ5+TOl4RLR7O
AQpJ81tGuINghO7aunctb6rrcKJrxmEH1whzComybrMCQQDKV49nOBudRBAIgG4K
EnLzsRKISUHMZSJiYTYnablof8cKw1JaQduw7zgrUlLwnroSaAGX88+Jw1f5n2Lh
Vlg5AkBDdUGnrDLtYBCDEQYZHblrkc7ZAeCllDOWjxUV+uMqlCv8A4Ey6omvY57C
m6I8DkWVAQx8VPtozhvHjUw80rZHAkB55HWHAM3h13axKG0htCt7klhPsZHpx6MH
EPjGlXIT+aW2XiPmK3ZlCDcWIenE+lmtbOpI159Wpk8BGXs/s/xBAkEAlAY3ymgx
63BDJEwvOb2IaP8lDDxNsXx9XJNVvQbv5n15vNsLHbjslHfAhAbxnLQ1fLhUPqSi
nNp/xedE1YxutQ==
-----END PRIVATE KEY-----'
end
end
end
Loading
Loading
@@ -59,6 +59,10 @@ describe 'Dashboard snippets' do
visit dashboard_snippets_path
end
 
it_behaves_like 'tabs with counts' do
let_it_be(:counts) { { all: '3', public: '1', private: '1', internal: '1' } }
end
it 'contains all snippets of logged user' do
expect(page).to have_selector('.snippet-row', count: 3)
 
Loading
Loading
Loading
Loading
@@ -153,24 +153,6 @@ describe 'Invites' do
context 'email confirmation enabled' do
let(:send_email_confirmation) { true }
 
context 'when soft email confirmation is not enabled' do
before do
# stub_feature_flags(soft_email_confirmation: false)
allow(User).to receive(:allow_unconfirmed_access_for).and_return 0
end
it 'signs up and redirects to root page with all the project/groups invitation automatically accepted' do
fill_in_sign_up_form(new_user)
confirm_email(new_user)
fill_in_sign_in_form(new_user)
expect(current_path).to eq(root_path)
expect(page).to have_content(project.full_name)
visit group_path(group)
expect(page).to have_content(group.full_name)
end
end
context 'when soft email confirmation is enabled' do
before do
allow(User).to receive(:allow_unconfirmed_access_for).and_return 2.days
Loading
Loading
@@ -198,32 +180,14 @@ describe 'Invites' do
context 'the user sign-up using a different email address' do
let(:invite_email) { build_stubbed(:user).email }
 
context 'when soft email confirmation is not enabled' do
before do
stub_feature_flags(soft_email_confirmation: false)
allow(User).to receive(:allow_unconfirmed_access_for).and_return 0
end
it 'signs up and redirects to the invitation page' do
fill_in_sign_up_form(new_user)
confirm_email(new_user)
fill_in_sign_in_form(new_user)
expect(current_path).to eq(invite_path(group_invite.raw_invite_token))
end
before do
allow(User).to receive(:allow_unconfirmed_access_for).and_return 2.days
end
 
context 'when soft email confirmation is enabled' do
before do
stub_feature_flags(soft_email_confirmation: true)
allow(User).to receive(:allow_unconfirmed_access_for).and_return 2.days
end
it 'signs up and redirects to the invitation page' do
fill_in_sign_up_form(new_user)
it 'signs up and redirects to the invitation page' do
fill_in_sign_up_form(new_user)
 
expect(current_path).to eq(invite_path(group_invite.raw_invite_token))
end
expect(current_path).to eq(invite_path(group_invite.raw_invite_token))
end
end
end
Loading
Loading
Loading
Loading
@@ -50,7 +50,7 @@ describe 'Merge request > User sees versions', :js do
expect(page).to have_content 'latest version'
end
 
expect(page).to have_content '8 Files'
expect(page).to have_content '8 files'
end
 
it_behaves_like 'allows commenting',
Loading
Loading
@@ -84,7 +84,7 @@ describe 'Merge request > User sees versions', :js do
end
 
it 'shows comments that were last relevant at that version' do
expect(page).to have_content '5 Files'
expect(page).to have_content '5 files'
 
position = Gitlab::Diff::Position.new(
old_path: ".gitmodules",
Loading
Loading
@@ -128,12 +128,10 @@ describe 'Merge request > User sees versions', :js do
diff_id: merge_request_diff3.id,
start_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9'
)
expect(page).to have_content '4 Files'
expect(page).to have_content '4 files'
 
additions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group svg.ic-file-addition')
.ancestor('.diff-stats-group').text
deletions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group svg.ic-file-deletion')
.ancestor('.diff-stats-group').text
additions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group .js-file-addition-line').text
deletions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group .js-file-deletion-line').text
 
expect(additions_content).to eq '15'
expect(deletions_content).to eq '6'
Loading
Loading
@@ -156,12 +154,10 @@ describe 'Merge request > User sees versions', :js do
end
 
it 'show diff between new and old version' do
additions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group svg.ic-file-addition')
.ancestor('.diff-stats-group').text
deletions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group svg.ic-file-deletion')
.ancestor('.diff-stats-group').text
additions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group .js-file-addition-line').text
deletions_content = page.find('.diff-stats.is-compare-versions-header .diff-stats-group .js-file-deletion-line').text
 
expect(page).to have_content '4 Files'
expect(page).to have_content '4 files'
expect(additions_content).to eq '15'
expect(deletions_content).to eq '6'
end
Loading
Loading
@@ -171,7 +167,7 @@ describe 'Merge request > User sees versions', :js do
page.within '.mr-version-dropdown' do
expect(page).to have_content 'latest version'
end
expect(page).to have_content '8 Files'
expect(page).to have_content '8 files'
end
 
it_behaves_like 'allows commenting',
Loading
Loading
@@ -197,7 +193,7 @@ describe 'Merge request > User sees versions', :js do
find('.btn-default').click
click_link 'version 1'
end
expect(page).to have_content '0 Files'
expect(page).to have_content '0 files'
end
end
 
Loading
Loading
@@ -223,7 +219,7 @@ describe 'Merge request > User sees versions', :js do
expect(page).to have_content 'version 1'
end
 
expect(page).to have_content '0 Files'
expect(page).to have_content '0 files'
end
end
 
Loading
Loading
Loading
Loading
@@ -31,6 +31,16 @@ describe 'Projects > Snippets > User views snippets' do
it_behaves_like 'paginated snippets'
end
 
context 'filtering by visibility' do
before do
visit_project_snippets
end
it_behaves_like 'tabs with counts' do
let_it_be(:counts) { { all: '1', public: '0', private: '1', internal: '0' } }
end
end
it 'shows snippets' do
visit_project_snippets
 
Loading
Loading
Loading
Loading
@@ -797,7 +797,6 @@ describe 'Login' do
 
before do
stub_application_setting(send_user_confirmation_email: true)
stub_feature_flags(soft_email_confirmation: true)
allow(User).to receive(:allow_unconfirmed_access_for).and_return grace_period
end
 
Loading
Loading
Loading
Loading
@@ -129,63 +129,29 @@ shared_examples 'Signup' do
stub_application_setting(send_user_confirmation_email: true)
end
 
context 'when soft email confirmation is not enabled' do
before do
stub_feature_flags(soft_email_confirmation: false)
end
it 'creates the user account and sends a confirmation email' do
visit new_user_registration_path
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
if Gitlab::Experimentation.enabled?(:signup_flow)
fill_in 'new_user_first_name', with: new_user.first_name
fill_in 'new_user_last_name', with: new_user.last_name
else
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
expect { click_button 'Register' }.to change { User.count }.by(1)
it 'creates the user account and sends a confirmation email' do
visit new_user_registration_path
 
expect(current_path).to eq users_almost_there_path
expect(page).to have_content('Please check your email to confirm your account')
end
end
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
 
context 'when soft email confirmation is enabled' do
before do
stub_feature_flags(soft_email_confirmation: true)
if Gitlab::Experimentation.enabled?(:signup_flow)
fill_in 'new_user_first_name', with: new_user.first_name
fill_in 'new_user_last_name', with: new_user.last_name
else
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_email_confirmation', with: new_user.email
end
 
it 'creates the user account and sends a confirmation email' do
visit new_user_registration_path
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
if Gitlab::Experimentation.enabled?(:signup_flow)
fill_in 'new_user_first_name', with: new_user.first_name
fill_in 'new_user_last_name', with: new_user.last_name
else
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
fill_in 'new_user_password', with: new_user.password
 
expect { click_button 'Register' }.to change { User.count }.by(1)
expect { click_button 'Register' }.to change { User.count }.by(1)
 
if Gitlab::Experimentation.enabled?(:signup_flow)
expect(current_path).to eq users_sign_up_welcome_path
else
expect(current_path).to eq dashboard_projects_path
expect(page).to have_content("Please check your email (#{new_user.email}) to verify that you own this address and unlock the power of CI/CD.")
end
if Gitlab::Experimentation.enabled?(:signup_flow)
expect(current_path).to eq users_sign_up_welcome_path
else
expect(current_path).to eq dashboard_projects_path
expect(page).to have_content("Please check your email (#{new_user.email}) to verify that you own this address and unlock the power of CI/CD.")
end
end
end
Loading
Loading
Loading
Loading
@@ -49,8 +49,7 @@ describe('CompareVersions', () => {
 
expect(treeListBtn.exists()).toBe(true);
expect(treeListBtn.attributes('title')).toBe('Hide file browser');
expect(treeListBtn.findAll(Icon).length).not.toBe(0);
expect(treeListBtn.find(Icon).props('name')).toBe('collapse-left');
expect(treeListBtn.find(Icon).props('name')).toBe('file-tree');
});
 
it('should render comparison dropdowns with correct values', () => {
Loading
Loading
import { shallowMount } from '@vue/test-utils';
import Icon from '~/vue_shared/components/icon.vue';
import DiffStats from '~/diffs/components/diff_stats.vue';
import Icon from '~/vue_shared/components/icon.vue';
 
describe('diff_stats', () => {
it('does not render a group if diffFileLengths is empty', () => {
Loading
Loading
@@ -37,18 +37,18 @@ describe('diff_stats', () => {
},
});
 
const findFileLine = name => wrapper.find(name);
const findIcon = name =>
wrapper
.findAll(Icon)
.filter(c => c.attributes('name') === name)
.at(0).element.parentNode;
const additions = findIcon('file-addition');
const deletions = findIcon('file-deletion');
const additions = findFileLine('.js-file-addition-line');
const deletions = findFileLine('.js-file-deletion-line');
const filesChanged = findIcon('doc-code');
 
expect(additions.textContent).toContain('100');
expect(deletions.textContent).toContain('200');
expect(additions.text()).toBe('100');
expect(deletions.text()).toBe('200');
expect(filesChanged.textContent).toContain('300');
});
});
Loading
Loading
@@ -37,14 +37,13 @@ describe('ErrorDetails', () => {
projectPath: '/root/gitlab-test',
listPath: '/error_tracking',
issueUpdatePath: '/123',
issueDetailsPath: '/123/details',
issueStackTracePath: '/stacktrace',
projectIssuesPath: '/test-project/issues/',
csrfToken: 'fakeToken',
},
});
wrapper.setData({
GQLerror: {
error: {
id: 'gid://gitlab/Gitlab::ErrorTracking::DetailedError/129381',
sentryId: 129381,
title: 'Issue title',
Loading
Loading
@@ -59,7 +58,6 @@ describe('ErrorDetails', () => {
 
beforeEach(() => {
actions = {
startPollingDetails: () => {},
startPollingStacktrace: () => {},
updateIgnoreStatus: jest.fn(),
updateResolveStatus: jest.fn().mockResolvedValue({ closed_issue_iid: 1 }),
Loading
Loading
@@ -71,8 +69,6 @@ describe('ErrorDetails', () => {
};
 
const state = {
error: {},
loading: true,
stacktraceData: {},
loadingStacktrace: true,
};
Loading
Loading
@@ -93,7 +89,7 @@ describe('ErrorDetails', () => {
$apollo: {
query,
queries: {
GQLerror: {
error: {
loading: true,
stopPolling: jest.fn(),
},
Loading
Loading
@@ -122,9 +118,7 @@ describe('ErrorDetails', () => {
 
describe('Error details', () => {
beforeEach(() => {
store.state.details.loading = false;
store.state.details.error.id = 1;
mocks.$apollo.queries.GQLerror.loading = false;
mocks.$apollo.queries.error.loading = false;
mountComponent();
});
 
Loading
Loading
@@ -138,16 +132,22 @@ describe('ErrorDetails', () => {
 
describe('Badges', () => {
it('should show language and error level badges', () => {
store.state.details.error.tags = { level: 'error', logger: 'ruby' };
mountComponent();
wrapper.setData({
error: {
tags: { level: 'error', logger: 'ruby' },
},
});
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.findAll(GlBadge).length).toBe(2);
});
});
 
it('should NOT show the badge if the tag is not present', () => {
store.state.details.error.tags = { level: 'error' };
mountComponent();
wrapper.setData({
error: {
tags: { level: 'error' },
},
});
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.findAll(GlBadge).length).toBe(1);
});
Loading
Loading
@@ -156,8 +156,11 @@ describe('ErrorDetails', () => {
it.each(Object.keys(severityLevel))(
'should set correct severity level variant for %s badge',
level => {
store.state.details.error.tags = { level: severityLevel[level] };
mountComponent();
wrapper.setData({
error: {
tags: { level: severityLevel[level] },
},
});
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(GlBadge).attributes('variant')).toEqual(
severityLevelVariant[severityLevel[level]],
Loading
Loading
@@ -167,8 +170,11 @@ describe('ErrorDetails', () => {
);
 
it('should fallback for ERROR severityLevelVariant when severityLevel is unknown', () => {
store.state.details.error.tags = { level: 'someNewErrorLevel' };
mountComponent();
wrapper.setData({
error: {
tags: { level: 'someNewErrorLevel' },
},
});
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(GlBadge).attributes('variant')).toEqual(
severityLevelVariant[severityLevel.ERROR],
Loading
Loading
@@ -180,7 +186,6 @@ describe('ErrorDetails', () => {
describe('Stacktrace', () => {
it('should show stacktrace', () => {
store.state.details.loadingStacktrace = false;
mountComponent();
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(Stacktrace).exists()).toBe(true);
Loading
Loading
@@ -190,9 +195,10 @@ describe('ErrorDetails', () => {
it('should NOT show stacktrace if no entries', () => {
store.state.details.loadingStacktrace = false;
store.getters = { 'details/sentryUrl': () => 'sentry.io', 'details/stacktrace': () => [] };
mountComponent();
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(Stacktrace).exists()).toBe(false);
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(Stacktrace).exists()).toBe(false);
});
});
});
 
Loading
Loading
@@ -331,19 +337,18 @@ describe('ErrorDetails', () => {
});
 
describe('GitLab issue link', () => {
const gitlabIssue = 'https://gitlab.example.com/issues/1';
const findGitLabLink = () => wrapper.find(`[href="${gitlabIssue}"]`);
const gitlabIssuePath = 'https://gitlab.example.com/issues/1';
const findGitLabLink = () => wrapper.find(`[href="${gitlabIssuePath}"]`);
const findCreateIssueButton = () => wrapper.find('[data-qa-selector="create_issue_button"]');
const findViewIssueButton = () => wrapper.find('[data-qa-selector="view_issue_button"]');
 
describe('is present', () => {
beforeEach(() => {
store.state.details.loading = false;
store.state.details.error = {
id: 1,
gitlab_issue: gitlabIssue,
};
mountComponent();
wrapper.setData({
error: {
gitlabIssuePath,
},
});
});
 
it('should display the View issue button', () => {
Loading
Loading
@@ -361,12 +366,11 @@ describe('ErrorDetails', () => {
 
describe('is not present', () => {
beforeEach(() => {
store.state.details.loading = false;
store.state.details.error = {
id: 1,
gitlab_issue: null,
};
mountComponent();
wrapper.setData({
error: {
gitlabIssuePath: null,
},
});
});
 
it('should not display the View issue button', () => {
Loading
Loading
@@ -390,9 +394,9 @@ describe('ErrorDetails', () => {
const findGitLabCommitLink = () => wrapper.find(`[href$="${gitlabCommitPath}"]`);
 
it('should display a link', () => {
mocks.$apollo.queries.GQLerror.loading = false;
mocks.$apollo.queries.error.loading = false;
wrapper.setData({
GQLerror: {
error: {
gitlabCommit,
gitlabCommitPath,
},
Loading
Loading
@@ -403,9 +407,9 @@ describe('ErrorDetails', () => {
});
 
it('should not display a link', () => {
mocks.$apollo.queries.GQLerror.loading = false;
mocks.$apollo.queries.error.loading = false;
wrapper.setData({
GQLerror: {
error: {
gitlabCommit: null,
},
});
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment