diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index f3d5b18e05c..5b99d0768ec 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -13,7 +13,6 @@
# WIP See https://gitlab.com/gitlab-org/gitlab/-/issues/322903
Graphql/Descriptions:
Exclude:
- - 'ee/app/graphql/types/health_status_enum.rb'
- 'ee/app/graphql/types/iteration_state_enum.rb'
- 'ee/app/graphql/types/requirements_management/requirement_state_enum.rb'
- 'ee/app/graphql/types/requirements_management/test_report_state_enum.rb'
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
index 11e6b4577e0..fde134f1440 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
@@ -221,7 +221,7 @@ export default {
}
if (this.visibilityLevel !== visibilityOptions.PUBLIC) {
- options.push([30, PAGE_FEATURE_ACCESS_LEVEL]);
+ options.push([visibilityOptions.PUBLIC, PAGE_FEATURE_ACCESS_LEVEL]);
}
}
return options;
diff --git a/app/assets/javascripts/repository/queries/commit.fragment.graphql b/app/assets/javascripts/repository/queries/commit.fragment.graphql
index be6897b9a16..b046fc1f730 100644
--- a/app/assets/javascripts/repository/queries/commit.fragment.graphql
+++ b/app/assets/javascripts/repository/queries/commit.fragment.graphql
@@ -5,5 +5,6 @@ fragment TreeEntryCommit on LogTreeCommit {
committedDate
commitPath
fileName
+ filePath
type
}
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index cbf92fce85d..305c0bba5e8 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -14595,9 +14595,9 @@ Health status of an issue or epic.
| Value | Description |
| ----- | ----------- |
-| `atRisk` | |
-| `needsAttention` | |
-| `onTrack` | |
+| `atRisk` | At risk. |
+| `needsAttention` | Needs attention. |
+| `onTrack` | On track. |
### `IssuableSearchableField`
diff --git a/doc/development/testing_guide/end_to_end/environment_selection.md b/doc/development/testing_guide/end_to_end/environment_selection.md
index bcdf0e104dd..02d8e0513a3 100644
--- a/doc/development/testing_guide/end_to_end/environment_selection.md
+++ b/doc/development/testing_guide/end_to_end/environment_selection.md
@@ -66,3 +66,24 @@ Similarly to specifying that a test should only run against a specific environme
test only when it runs against a specific environment. The syntax is exactly the same, except that the `only: { ... }`
hash is nested in the [`quarantine: { ... }`](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests) hash.
For instance, `quarantine: { only: { subdomain: :staging } }` only quarantines the test when run against staging.
+
+## Excluding a test from running in a particular job
+
+Sometimes we need to skip a test in a particular job but allow it to run in other jobs of the same pipeline or environment.
+We can do it with the help of `exclude` metadata.
+
+Examples:
+
+```ruby
+RSpec.describe 'Excluding' do
+ it 'skips given a single named job', exclude: { job: 'ee:instance-image' } do; end
+
+ it 'skips given a single regex pattern', exclude: { job: '.*:instance-image' } do; end
+
+ it 'skips given an array of jobs', exclude: { job: %w[ee:instance-image qa-schedules-browser_ui-3_create] } do; end
+
+ it 'skips given an array of regex patterns', exclude: { job: %w[ee:.* qa-schedules-browser_ui.*] } do; end
+
+ it 'skips given a mix of strings and regex patterns', exclude: { job: %w[ee:instance-image qa-schedules-browser_ui.*] } do; end
+end
+```
diff --git a/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md b/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md
index 8a929737ebe..9b28137c6d5 100644
--- a/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md
+++ b/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md
@@ -14,6 +14,7 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
| Tag | Description |
|-----|-------------|
| `:elasticsearch` | The test requires an Elasticsearch service. It is used by the [instance-level scenario](https://gitlab.com/gitlab-org/gitlab-qa#definitions) [`Test::Integration::Elasticsearch`](https://gitlab.com/gitlab-org/gitlab/-/blob/72b62b51bdf513e2936301cb6c7c91ec27c35b4d/qa/qa/ee/scenario/test/integration/elasticsearch.rb) to include only tests that require Elasticsearch. |
+| `:exclude` | The test is excluded from running in a specific job. See [Environment selection](environment_selection.md#excluding-a-test-from-running-in-a-particular-job) for more information. |
| `:geo` | The test requires two GitLab Geo instances - a primary and a secondary - to be spun up. |
| `:gitaly_cluster` | The test runs against a GitLab instance where repositories are stored on redundant Gitaly nodes behind a Praefect node. All nodes are [separate containers](../../../administration/gitaly/praefect.md#requirements-for-configuring-a-gitaly-cluster). Tests that use this tag have a longer setup time since there are three additional containers that need to be started. |
| `:github` | The test requires a GitHub personal access token. |
diff --git a/lib/gitlab/ci/templates/Security/DAST-On-Demand-Scan.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST-On-Demand-Scan.gitlab-ci.yml
index dc55158ead9..3e7ab9b5c3b 100644
--- a/lib/gitlab/ci/templates/Security/DAST-On-Demand-Scan.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST-On-Demand-Scan.gitlab-ci.yml
@@ -10,7 +10,7 @@ stages:
- dast
variables:
- DAST_VERSION: 1
+ DAST_VERSION: 2
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
diff --git a/qa/Dockerfile b/qa/Dockerfile
index 78f58e16e30..3b748f1a52c 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -6,9 +6,6 @@ ENV DOCKER_VERSION="17.09.0-ce"
# https://s3.amazonaws.com/gitlab-google-chrome-stable
ENV CHROME_VERSION="91.0.4472.77-1"
-
-# https://chromedriver.chromium.org/downloads
-ENV CHROME_DRIVER_VERSION="91.0.4472.101"
ENV CHROME_DEB="google-chrome-stable_${CHROME_VERSION}_amd64.deb"
ENV CHROME_URL="https://s3.amazonaws.com/gitlab-google-chrome-stable/${CHROME_DEB}"
@@ -34,13 +31,6 @@ RUN curl --silent --show-error --fail -O "${CHROME_URL}" && \
apt-get install -f -y && \
rm -f "./${CHROME_DEB}"
-##
-# Install chromedriver to make it work with Selenium
-#
-RUN wget -q "https://chromedriver.storage.googleapis.com/${CHROME_DRIVER_VERSION}/chromedriver_linux64.zip"
-RUN unzip chromedriver_linux64.zip -d /usr/local/bin
-RUN rm -f chromedriver_linux64.zip
-
##
# Install client certificate - Bug in Chrome Headless: https://gitlab.com/gitlab-org/gitlab/-/issues/331492
#
@@ -71,6 +61,7 @@ RUN export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)" && \
apt-get update -y && apt-get install google-cloud-sdk kubectl -y
WORKDIR /home/gitlab/qa
+
COPY ./qa/Gemfile* /home/gitlab/qa/
COPY ./config/initializers/0_inject_enterprise_edition_module.rb /home/gitlab/config/initializers/
# Copy VERSION to ensure the COPY succeeds to copy at least one file since ee/app/models/license.rb isn't present in FOSS
@@ -79,7 +70,13 @@ COPY VERSION ./ee/app/models/license.r[b] /home/gitlab/ee/app/models/
COPY ./lib/gitlab.rb /home/gitlab/lib/
COPY ./lib/gitlab/utils.rb /home/gitlab/lib/gitlab/
COPY ./INSTALLATION_TYPE ./VERSION /home/gitlab/
-RUN cd /home/gitlab/qa/ && bundle install --jobs=$(nproc) --retry=3 --without=development --quiet
+
+RUN bundle install --jobs=$(nproc) --retry=3 --without=development --quiet
+
COPY ./qa /home/gitlab/qa
+# Fetch chromedriver version based on version of chrome
+# https://github.com/titusfortner/webdrivers
+RUN bundle exec rake webdrivers:chromedriver:update
+
ENTRYPOINT ["bin/test"]
diff --git a/qa/Gemfile b/qa/Gemfile
index 75d4e2607ee..7bf436dce85 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -23,6 +23,7 @@ gem 'timecop', '~> 0.9.1'
gem 'parallel', '~> 1.19'
gem 'rspec-parameterized', '~> 0.4.2'
gem 'github_api', '~> 0.18.2'
+gem "webdrivers", "~> 4.6"
gem 'chemlab', '~> 0.7'
gem 'chemlab-library-www-gitlab-com', '~> 0.1'
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 5f12715d372..39da3534770 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -192,6 +192,10 @@ GEM
watir (6.19.1)
regexp_parser (>= 1.2, < 3)
selenium-webdriver (>= 3.142.7)
+ webdrivers (4.6.0)
+ nokogiri (~> 1.6)
+ rubyzip (>= 1.3.0)
+ selenium-webdriver (>= 3.0, < 4.0)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.4.2)
@@ -225,6 +229,7 @@ DEPENDENCIES
ruby-debug-ide (~> 0.7.0)
selenium-webdriver (~> 4.0.0.beta4)
timecop (~> 0.9.1)
+ webdrivers (~> 4.6)
BUNDLED WITH
2.2.22
diff --git a/qa/Rakefile b/qa/Rakefile
index 0a040f0aee7..489f3b9e12b 100644
--- a/qa/Rakefile
+++ b/qa/Rakefile
@@ -1,4 +1,8 @@
# frozen_string_literal: true
+# rubocop:disable Rails/RakeEnvironment
+
+require 'webdrivers'
+load 'webdrivers/Rakefile'
require_relative 'qa/tools/revoke_all_personal_access_tokens'
require_relative 'qa/tools/delete_subgroups'
@@ -34,7 +38,9 @@ task :run_artillery_load_tests do
urls_file = ENV['URLS_FILE_PATH'] || 'urls.yml'
unless File.exist?(urls_file)
- raise "\n#{urls_file} file is missing. Please provide correct URLS_FILE_PATH or all of HOST_URL, LARGE_ISSUE_URL and LARGE_MR_URL\n\n"
+ raise(<<~ERR)
+ #{urls_file} file is missing. Please provide correct URLS_FILE_PATH or all of HOST_URL, LARGE_ISSUE_URL and LARGE_MR_URL\n
+ ERR
end
urls = YAML.safe_load(File.read(urls_file))
@@ -59,3 +65,4 @@ desc "Deletes projects directly under the provided group"
task :delete_projects do
QA::Tools::DeleteProjects.new.run
end
+# rubocop:enable Rails/RakeEnvironment
diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb
index 9cc72ae64a5..e13061e2648 100644
--- a/qa/qa/runtime/browser.rb
+++ b/qa/qa/runtime/browser.rb
@@ -5,6 +5,8 @@ require 'rspec/expectations'
require 'capybara/rspec'
require 'capybara-screenshot/rspec'
require 'selenium-webdriver'
+require 'webdrivers/chromedriver'
+require 'webdrivers/geckodriver'
require 'gitlab_handbook'
diff --git a/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js b/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js
index 878721666ff..e427a029866 100644
--- a/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js
+++ b/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js
@@ -94,6 +94,8 @@ describe('Settings Panel', () => {
const findPackageSettings = () => wrapper.find({ ref: 'package-settings' });
const findPackagesEnabledInput = () => wrapper.find('[name="project[packages_enabled]"]');
const findPagesSettings = () => wrapper.find({ ref: 'pages-settings' });
+ const findPagesAccessLevels = () =>
+ wrapper.find('[name="project[project_feature_attributes][pages_access_level]"]');
const findEmailSettings = () => wrapper.find({ ref: 'email-settings' });
const findShowDefaultAwardEmojis = () =>
wrapper.find('input[name="project[project_setting_attributes][show_default_award_emojis]"]');
@@ -478,6 +480,29 @@ describe('Settings Panel', () => {
});
describe('Pages', () => {
+ it.each`
+ visibilityLevel | pagesAccessControlForced | output
+ ${visibilityOptions.PRIVATE} | ${true} | ${[[visibilityOptions.INTERNAL, 'Only Project Members'], [visibilityOptions.PUBLIC, 'Everyone With Access']]}
+ ${visibilityOptions.PRIVATE} | ${false} | ${[[visibilityOptions.INTERNAL, 'Only Project Members'], [visibilityOptions.PUBLIC, 'Everyone With Access'], [visibilityOptions.PUBLIC, 'Everyone']]}
+ ${visibilityOptions.INTERNAL} | ${true} | ${[[visibilityOptions.INTERNAL, 'Only Project Members'], [visibilityOptions.PUBLIC, 'Everyone With Access']]}
+ ${visibilityOptions.INTERNAL} | ${false} | ${[[visibilityOptions.INTERNAL, 'Only Project Members'], [visibilityOptions.PUBLIC, 'Everyone With Access'], [visibilityOptions.PUBLIC, 'Everyone']]}
+ ${visibilityOptions.PUBLIC} | ${true} | ${[[visibilityOptions.INTERNAL, 'Only Project Members'], [visibilityOptions.PUBLIC, 'Everyone With Access']]}
+ ${visibilityOptions.PUBLIC} | ${false} | ${[[visibilityOptions.INTERNAL, 'Only Project Members'], [visibilityOptions.PUBLIC, 'Everyone With Access'], [visibilityOptions.PUBLIC, 'Everyone']]}
+ `(
+ 'renders correct options when pagesAccessControlForced is $pagesAccessControlForced and visibilityLevel is $visibilityLevel',
+ async ({ visibilityLevel, pagesAccessControlForced, output }) => {
+ wrapper = mountComponent({
+ pagesAvailable: true,
+ pagesAccessControlEnabled: true,
+ pagesAccessControlForced,
+ });
+
+ await findProjectVisibilityLevelInput().trigger('change', visibilityLevel);
+
+ expect(findPagesAccessLevels().props('options')).toStrictEqual(output);
+ },
+ );
+
it.each`
pagesAvailable | pagesAccessControlEnabled | visibility
${true} | ${true} | ${'show'}
diff --git a/spec/frontend/repository/log_tree_spec.js b/spec/frontend/repository/log_tree_spec.js
index 8cabf902a4f..5186c9a8992 100644
--- a/spec/frontend/repository/log_tree_spec.js
+++ b/spec/frontend/repository/log_tree_spec.js
@@ -1,6 +1,10 @@
import MockAdapter from 'axios-mock-adapter';
+import { createMockClient } from 'helpers/mock_apollo_helper';
import axios from '~/lib/utils/axios_utils';
import { resolveCommit, fetchLogsTree } from '~/repository/log_tree';
+import commitsQuery from '~/repository/queries/commits.query.graphql';
+import projectPathQuery from '~/repository/queries/project_path.query.graphql';
+import refQuery from '~/repository/queries/ref.query.graphql';
const mockData = [
{
@@ -10,6 +14,7 @@ const mockData = [
committed_date: '2019-01-01',
},
commit_path: `https://test.com`,
+ commit_title_html: 'commit title',
file_name: 'index.js',
type: 'blob',
},
@@ -50,19 +55,15 @@ describe('fetchLogsTree', () => {
global.gon = { relative_url_root: '' };
- client = {
- readQuery: () => ({
- projectPath: 'gitlab-org/gitlab-foss',
- escapedRef: 'main',
- commits: [],
- }),
- writeQuery: jest.fn(),
- };
-
resolver = {
entry: { name: 'index.js', type: 'blob' },
resolve: jest.fn(),
};
+
+ client = createMockClient();
+ client.writeQuery({ query: projectPathQuery, data: { projectPath: 'gitlab-org/gitlab-foss' } });
+ client.writeQuery({ query: refQuery, data: { ref: 'main', escapedRef: 'main' } });
+ client.writeQuery({ query: commitsQuery, data: { commits: [] } });
});
afterEach(() => {
@@ -125,25 +126,19 @@ describe('fetchLogsTree', () => {
it('writes query to client', async () => {
await fetchLogsTree(client, '', '0', resolver);
- expect(client.writeQuery).toHaveBeenCalledWith({
- query: expect.anything(),
- data: {
- projectPath: 'gitlab-org/gitlab-foss',
- escapedRef: 'main',
- commits: [
- expect.objectContaining({
- __typename: 'LogTreeCommit',
- commitPath: 'https://test.com',
- committedDate: '2019-01-01',
- fileName: 'index.js',
- filePath: '/index.js',
- message: 'testing message',
- sha: '123',
- titleHtml: undefined,
- type: 'blob',
- }),
- ],
- },
+ expect(client.readQuery({ query: commitsQuery })).toEqual({
+ commits: [
+ expect.objectContaining({
+ commitPath: 'https://test.com',
+ committedDate: '2019-01-01',
+ fileName: 'index.js',
+ filePath: '/index.js',
+ message: 'testing message',
+ sha: '123',
+ titleHtml: 'commit title',
+ type: 'blob',
+ }),
+ ],
});
});
});