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', + }), + ], }); }); });