From f0aaec1f670ca31d6d438556c3b7327699cbe8ef Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 27 May 2021 09:10:32 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .rubocop_manual_todo.yml | 5 +- GITALY_SERVER_VERSION | 2 +- .../forks/new/components/fork_form.vue | 8 +- .../base_data_fields.rb} | 8 +- .../concerns/integrations/has_data_fields.rb | 61 ++++++++++ app/models/integration.rb | 2 +- app/models/integrations/issue_tracker_data.rb | 11 ++ app/models/integrations/jira_tracker_data.rb | 14 +++ .../integrations/open_project_tracker_data.rb | 18 +++ app/models/project_services/data_fields.rb | 59 ---------- .../project_services/issue_tracker_data.rb | 9 -- .../project_services/jira_tracker_data.rb | 12 -- .../open_project_tracker_data.rb | 16 --- app/models/release.rb | 8 +- .../repository_storage_paths.md | 2 +- doc/ci/pipelines/job_artifacts.md | 8 +- spec/factories/integration_data.rb | 6 +- .../forks/new/components/fork_form_spec.js | 28 ++++- .../releases/__snapshots__/util_spec.js.snap | 4 +- .../integrations/has_data_fields_spec.rb} | 2 +- .../issue_tracker_data_spec.rb | 2 +- .../jira_tracker_data_spec.rb | 2 +- .../open_project_tracker_data_spec.rb | 2 +- .../api/graphql/project/releases_spec.rb | 106 +++++++++--------- 24 files changed, 211 insertions(+), 184 deletions(-) rename app/models/concerns/{services/data_fields.rb => integrations/base_data_fields.rb} (61%) create mode 100644 app/models/concerns/integrations/has_data_fields.rb create mode 100644 app/models/integrations/issue_tracker_data.rb create mode 100644 app/models/integrations/jira_tracker_data.rb create mode 100644 app/models/integrations/open_project_tracker_data.rb delete mode 100644 app/models/project_services/data_fields.rb delete mode 100644 app/models/project_services/issue_tracker_data.rb delete mode 100644 app/models/project_services/jira_tracker_data.rb delete mode 100644 app/models/project_services/open_project_tracker_data.rb rename spec/models/{project_services/data_fields_spec.rb => concerns/integrations/has_data_fields_spec.rb} (99%) rename spec/models/{project_services => integrations}/issue_tracker_data_spec.rb (74%) rename spec/models/{project_services => integrations}/jira_tracker_data_spec.rb (91%) rename spec/models/{project_services => integrations}/open_project_tracker_data_spec.rb (89%) diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml index fa81885e060..9d3fc7f956b 100644 --- a/.rubocop_manual_todo.yml +++ b/.rubocop_manual_todo.yml @@ -1650,14 +1650,11 @@ Gitlab/NamespacedClass: - 'app/models/project_services/chat_notification_service.rb' - 'app/models/project_services/discord_service.rb' - 'app/models/project_services/hangouts_chat_service.rb' - - 'app/models/project_services/issue_tracker_data.rb' - - 'app/models/project_services/jira_tracker_data.rb' - 'app/models/project_services/mattermost_service.rb' - 'app/models/project_services/mattermost_slash_commands_service.rb' - 'app/models/project_services/microsoft_teams_service.rb' - 'app/models/project_services/mock_monitoring_service.rb' - 'app/models/project_services/monitoring_service.rb' - - 'app/models/project_services/open_project_tracker_data.rb' - 'app/models/project_services/prometheus_service.rb' - 'app/models/project_services/pushover_service.rb' - 'app/models/project_services/slack_service.rb' @@ -2675,8 +2672,8 @@ Gitlab/DelegatePredicateMethods: - 'app/models/clusters/platforms/kubernetes.rb' - 'app/models/concerns/ci/metadatable.rb' - 'app/models/concerns/diff_positionable_note.rb' + - 'app/models/concerns/integrations/base_data_fields.rb' - 'app/models/concerns/resolvable_discussion.rb' - - 'app/models/concerns/services/data_fields.rb' - 'app/models/project.rb' - 'ee/app/models/concerns/ee/ci/metadatable.rb' - 'ee/app/models/ee/group.rb' diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index ffe37cdc2cf..fae5cc1a74c 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -c93530dd0922e7554d6d1e486e830f72980fe083 +6e58da454633a53c86d14a59587ee7a6a9d11031 diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue index 07cc0ce46bc..743706bae98 100644 --- a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue +++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue @@ -142,7 +142,9 @@ export default { text: s__('ForkProject|Private'), value: PRIVATE_VISIBILITY, icon: 'lock', - help: s__('ForkProject|The project can be accessed without any authentication.'), + help: s__( + 'ForkProject|Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group.', + ), disabled: this.isVisibilityLevelDisabled(PRIVATE_VISIBILITY), }, { @@ -156,9 +158,7 @@ export default { text: s__('ForkProject|Public'), value: PUBLIC_VISIBILITY, icon: 'earth', - help: s__( - 'ForkProject|Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group.', - ), + help: s__('ForkProject|The project can be accessed without any authentication.'), disabled: this.isVisibilityLevelDisabled(PUBLIC_VISIBILITY), }, ]; diff --git a/app/models/concerns/services/data_fields.rb b/app/models/concerns/integrations/base_data_fields.rb similarity index 61% rename from app/models/concerns/services/data_fields.rb rename to app/models/concerns/integrations/base_data_fields.rb index fd56af449bc..3cedb90756f 100644 --- a/app/models/concerns/services/data_fields.rb +++ b/app/models/concerns/integrations/base_data_fields.rb @@ -1,11 +1,13 @@ # frozen_string_literal: true -module Services - module DataFields +module Integrations + module BaseDataFields extend ActiveSupport::Concern included do - belongs_to :integration, inverse_of: self.name.underscore.to_sym, foreign_key: :service_id + # TODO: Once we rename the tables we can't rely on `table_name` anymore. + # https://gitlab.com/gitlab-org/gitlab/-/issues/331953 + belongs_to :integration, inverse_of: self.table_name.to_sym, foreign_key: :service_id delegate :activated?, to: :integration, allow_nil: true diff --git a/app/models/concerns/integrations/has_data_fields.rb b/app/models/concerns/integrations/has_data_fields.rb new file mode 100644 index 00000000000..e9aaaac8226 --- /dev/null +++ b/app/models/concerns/integrations/has_data_fields.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +module Integrations + module HasDataFields + extend ActiveSupport::Concern + + class_methods do + # Provide convenient accessor methods for data fields. + # TODO: Simplify as part of https://gitlab.com/gitlab-org/gitlab/issues/29404 + def data_field(*args) + args.each do |arg| + self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + unless method_defined?(arg) + def #{arg} + data_fields.send('#{arg}') || (properties && properties['#{arg}']) + end + end + + def #{arg}=(value) + @old_data_fields ||= {} + @old_data_fields['#{arg}'] ||= #{arg} # set only on the first assignment, IOW we remember the original value only + data_fields.send('#{arg}=', value) + end + + def #{arg}_touched? + @old_data_fields ||= {} + @old_data_fields.has_key?('#{arg}') + end + + def #{arg}_changed? + #{arg}_touched? && @old_data_fields['#{arg}'] != #{arg} + end + + def #{arg}_was + return unless #{arg}_touched? + return if data_fields.persisted? # arg_was does not work for attr_encrypted + + legacy_properties_data['#{arg}'] + end + RUBY + end + end + end + + included do + has_one :issue_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id, class_name: 'Integrations::IssueTrackerData' + has_one :jira_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id, class_name: 'Integrations::JiraTrackerData' + has_one :open_project_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id, class_name: 'Integrations::OpenProjectTrackerData' + + def data_fields + raise NotImplementedError + end + + def data_fields_present? + data_fields.present? + rescue NotImplementedError + false + end + end + end +end diff --git a/app/models/integration.rb b/app/models/integration.rb index 36f5a1ae3d0..47c12df4919 100644 --- a/app/models/integration.rb +++ b/app/models/integration.rb @@ -6,7 +6,7 @@ class Integration < ApplicationRecord include Sortable include Importable include ProjectServicesLoggable - include DataFields + include Integrations::HasDataFields include FromUnion include EachBatch diff --git a/app/models/integrations/issue_tracker_data.rb b/app/models/integrations/issue_tracker_data.rb new file mode 100644 index 00000000000..8749075149f --- /dev/null +++ b/app/models/integrations/issue_tracker_data.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Integrations + class IssueTrackerData < ApplicationRecord + include BaseDataFields + + attr_encrypted :project_url, encryption_options + attr_encrypted :issues_url, encryption_options + attr_encrypted :new_issue_url, encryption_options + end +end diff --git a/app/models/integrations/jira_tracker_data.rb b/app/models/integrations/jira_tracker_data.rb new file mode 100644 index 00000000000..74352393b43 --- /dev/null +++ b/app/models/integrations/jira_tracker_data.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Integrations + class JiraTrackerData < ApplicationRecord + include BaseDataFields + + attr_encrypted :url, encryption_options + attr_encrypted :api_url, encryption_options + attr_encrypted :username, encryption_options + attr_encrypted :password, encryption_options + + enum deployment_type: { unknown: 0, server: 1, cloud: 2 }, _prefix: :deployment + end +end diff --git a/app/models/integrations/open_project_tracker_data.rb b/app/models/integrations/open_project_tracker_data.rb new file mode 100644 index 00000000000..b3f2618b94f --- /dev/null +++ b/app/models/integrations/open_project_tracker_data.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module Integrations + class OpenProjectTrackerData < ApplicationRecord + include BaseDataFields + + # When the Open Project is fresh installed, the default closed status id is "13" based on current version: v8. + DEFAULT_CLOSED_STATUS_ID = "13" + + attr_encrypted :url, encryption_options + attr_encrypted :api_url, encryption_options + attr_encrypted :token, encryption_options + + def closed_status_id + super || DEFAULT_CLOSED_STATUS_ID + end + end +end diff --git a/app/models/project_services/data_fields.rb b/app/models/project_services/data_fields.rb deleted file mode 100644 index ca4dc0375fb..00000000000 --- a/app/models/project_services/data_fields.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: true - -module DataFields - extend ActiveSupport::Concern - - class_methods do - # Provide convenient accessor methods for data fields. - # TODO: Simplify as part of https://gitlab.com/gitlab-org/gitlab/issues/29404 - def data_field(*args) - args.each do |arg| - self.class_eval <<-RUBY, __FILE__, __LINE__ + 1 - unless method_defined?(arg) - def #{arg} - data_fields.send('#{arg}') || (properties && properties['#{arg}']) - end - end - - def #{arg}=(value) - @old_data_fields ||= {} - @old_data_fields['#{arg}'] ||= #{arg} # set only on the first assignment, IOW we remember the original value only - data_fields.send('#{arg}=', value) - end - - def #{arg}_touched? - @old_data_fields ||= {} - @old_data_fields.has_key?('#{arg}') - end - - def #{arg}_changed? - #{arg}_touched? && @old_data_fields['#{arg}'] != #{arg} - end - - def #{arg}_was - return unless #{arg}_touched? - return if data_fields.persisted? # arg_was does not work for attr_encrypted - - legacy_properties_data['#{arg}'] - end - RUBY - end - end - end - - included do - has_one :issue_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id - has_one :jira_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id - has_one :open_project_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id - - def data_fields - raise NotImplementedError - end - - def data_fields_present? - data_fields.present? - rescue NotImplementedError - false - end - end -end diff --git a/app/models/project_services/issue_tracker_data.rb b/app/models/project_services/issue_tracker_data.rb deleted file mode 100644 index 414f2c1da4d..00000000000 --- a/app/models/project_services/issue_tracker_data.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -class IssueTrackerData < ApplicationRecord - include Services::DataFields - - attr_encrypted :project_url, encryption_options - attr_encrypted :issues_url, encryption_options - attr_encrypted :new_issue_url, encryption_options -end diff --git a/app/models/project_services/jira_tracker_data.rb b/app/models/project_services/jira_tracker_data.rb deleted file mode 100644 index 00b6ab6a70f..00000000000 --- a/app/models/project_services/jira_tracker_data.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -class JiraTrackerData < ApplicationRecord - include Services::DataFields - - attr_encrypted :url, encryption_options - attr_encrypted :api_url, encryption_options - attr_encrypted :username, encryption_options - attr_encrypted :password, encryption_options - - enum deployment_type: { unknown: 0, server: 1, cloud: 2 }, _prefix: :deployment -end diff --git a/app/models/project_services/open_project_tracker_data.rb b/app/models/project_services/open_project_tracker_data.rb deleted file mode 100644 index 20de60e40c1..00000000000 --- a/app/models/project_services/open_project_tracker_data.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -class OpenProjectTrackerData < ApplicationRecord - include Services::DataFields - - # When the Open Project is fresh installed, the default closed status id is "13" based on current version: v8. - DEFAULT_CLOSED_STATUS_ID = "13" - - attr_encrypted :url, encryption_options - attr_encrypted :api_url, encryption_options - attr_encrypted :token, encryption_options - - def closed_status_id - super || DEFAULT_CLOSED_STATUS_ID - end -end diff --git a/app/models/release.rb b/app/models/release.rb index 1889a0707b4..aad1cbeabdb 100644 --- a/app/models/release.rb +++ b/app/models/release.rb @@ -39,10 +39,10 @@ class Release < ApplicationRecord scope :released_within_2hrs, -> { where(released_at: Time.zone.now - 1.hour..Time.zone.now + 1.hour) } # Sorting - scope :order_created, -> { reorder('created_at ASC') } - scope :order_created_desc, -> { reorder('created_at DESC') } - scope :order_released, -> { reorder('released_at ASC') } - scope :order_released_desc, -> { reorder('released_at DESC') } + scope :order_created, -> { reorder(created_at: :asc) } + scope :order_created_desc, -> { reorder(created_at: :desc) } + scope :order_released, -> { reorder(released_at: :asc) } + scope :order_released_desc, -> { reorder(released_at: :desc) } delegate :repository, to: :project diff --git a/doc/administration/repository_storage_paths.md b/doc/administration/repository_storage_paths.md index a0b4e339f2c..e46a010222f 100644 --- a/doc/administration/repository_storage_paths.md +++ b/doc/administration/repository_storage_paths.md @@ -11,7 +11,7 @@ GitLab stores [repositories](../user/project/repository/index.md) on repository storage is either: - A `gitaly_address`, which points to a [Gitaly node](gitaly/index.md). -- A `path`, which points directly a directory where the repositories are stored. This method is +- A `path`, which points directly to the directory where the repositories are stored. This method is deprecated and [scheduled to be removed](https://gitlab.com/gitlab-org/gitaly/-/issues/1690) in GitLab 14.0. diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md index b5150b9d1b7..0bb7007e7a9 100644 --- a/doc/ci/pipelines/job_artifacts.md +++ b/doc/ci/pipelines/job_artifacts.md @@ -140,10 +140,10 @@ namespace: https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/main/download?job=coverage ``` -To download the file `coverage/index.html` from the same artifacts: +To download the file `review/index.html` from the same artifacts: ```plaintext -https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/raw/coverage/index.html?job=coverage +https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/main/raw/review/index.html?job=coverage ``` To browse the latest job artifacts: @@ -155,7 +155,7 @@ https://example.com///-/jobs/artifacts//browse?job=//-/jobs/artifacts//file/?job For example, when a job `coverage` creates the artifact `htmlcov/index.html`: ```plaintext -https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/file/htmlcov/index.html?job=coverage +https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/main/file/htmlcov/index.html?job=coverage ``` ## When job artifacts are deleted diff --git a/spec/factories/integration_data.rb b/spec/factories/integration_data.rb index 2541a3d2da3..a6b2693b8df 100644 --- a/spec/factories/integration_data.rb +++ b/spec/factories/integration_data.rb @@ -3,15 +3,15 @@ # These factories should not be called directly unless we are testing a _tracker_data model. # The factories are used when creating integrations. FactoryBot.define do - factory :jira_tracker_data do + factory :jira_tracker_data, class: 'Integrations::JiraTrackerData' do integration factory: :jira_service end - factory :issue_tracker_data do + factory :issue_tracker_data, class: 'Integrations::IssueTrackerData' do integration end - factory :open_project_tracker_data do + factory :open_project_tracker_data, class: 'Integrations::OpenProjectTrackerData' do integration factory: :open_project_service url { 'http://openproject.example.com'} token { 'supersecret' } diff --git a/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js b/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js index 6d853120232..2513bb3bce1 100644 --- a/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js +++ b/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js @@ -1,4 +1,4 @@ -import { GlFormInputGroup, GlFormInput, GlForm } from '@gitlab/ui'; +import { GlFormInputGroup, GlFormInput, GlForm, GlFormRadio } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import axios from 'axios'; import AxiosMockAdapter from 'axios-mock-adapter'; @@ -15,6 +15,13 @@ describe('ForkForm component', () => { let wrapper; let axiosMock; + const PROJECT_VISIBILITY_TYPE = { + private: + 'Private Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group.', + internal: 'Internal The project can be accessed by any logged in user.', + public: 'Public The project can be accessed without any authentication.', + }; + const GON_GITLAB_URL = 'https://gitlab.com'; const GON_API_VERSION = 'v7'; @@ -61,6 +68,7 @@ describe('ForkForm component', () => { stubs: { GlFormInputGroup, GlFormInput, + GlFormRadio, }, }); }; @@ -203,6 +211,24 @@ describe('ForkForm component', () => { }); describe('visibility level', () => { + it('displays the correct description', () => { + mockGetRequest(); + createComponent(); + + const formRadios = wrapper.findAll(GlFormRadio); + + Object.keys(PROJECT_VISIBILITY_TYPE).forEach((visibilityType, index) => { + expect(formRadios.at(index).text()).toBe(PROJECT_VISIBILITY_TYPE[visibilityType]); + }); + }); + + it('displays all 3 visibility levels', () => { + mockGetRequest(); + createComponent(); + + expect(wrapper.findAll(GlFormRadio)).toHaveLength(3); + }); + it.each` project | namespace | privateIsDisabled | internalIsDisabled | publicIsDisabled ${'private'} | ${'private'} | ${undefined} | ${'true'} | ${'true'} diff --git a/spec/frontend/releases/__snapshots__/util_spec.js.snap b/spec/frontend/releases/__snapshots__/util_spec.js.snap index cad593b76ea..14f9e69f3f9 100644 --- a/spec/frontend/releases/__snapshots__/util_spec.js.snap +++ b/spec/frontend/releases/__snapshots__/util_spec.js.snap @@ -121,10 +121,10 @@ Object { }, ], "paginationInfo": Object { - "endCursor": "eyJpZCI6IjEifQ", + "endCursor": "eyJyZWxlYXNlZF9hdCI6IjIwMTgtMTItMTAgMDA6MDA6MDAuMDAwMDAwMDAwIFVUQyIsImlkIjoiMSJ9", "hasNextPage": false, "hasPreviousPage": false, - "startCursor": "eyJpZCI6IjEifQ", + "startCursor": "eyJyZWxlYXNlZF9hdCI6IjIwMTgtMTItMTAgMDA6MDA6MDAuMDAwMDAwMDAwIFVUQyIsImlkIjoiMSJ9", }, } `; diff --git a/spec/models/project_services/data_fields_spec.rb b/spec/models/concerns/integrations/has_data_fields_spec.rb similarity index 99% rename from spec/models/project_services/data_fields_spec.rb rename to spec/models/concerns/integrations/has_data_fields_spec.rb index 97f1dc59c7c..54e0ac9c5a5 100644 --- a/spec/models/project_services/data_fields_spec.rb +++ b/spec/models/concerns/integrations/has_data_fields_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe DataFields do +RSpec.describe Integrations::HasDataFields do let(:url) { 'http://url.com' } let(:username) { 'username_one' } let(:properties) do diff --git a/spec/models/project_services/issue_tracker_data_spec.rb b/spec/models/integrations/issue_tracker_data_spec.rb similarity index 74% rename from spec/models/project_services/issue_tracker_data_spec.rb rename to spec/models/integrations/issue_tracker_data_spec.rb index a229285f09b..597df237c67 100644 --- a/spec/models/project_services/issue_tracker_data_spec.rb +++ b/spec/models/integrations/issue_tracker_data_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe IssueTrackerData do +RSpec.describe Integrations::IssueTrackerData do describe 'associations' do it { is_expected.to belong_to :integration } end diff --git a/spec/models/project_services/jira_tracker_data_spec.rb b/spec/models/integrations/jira_tracker_data_spec.rb similarity index 91% rename from spec/models/project_services/jira_tracker_data_spec.rb rename to spec/models/integrations/jira_tracker_data_spec.rb index 72bdbe40a74..5430dd2eb52 100644 --- a/spec/models/project_services/jira_tracker_data_spec.rb +++ b/spec/models/integrations/jira_tracker_data_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe JiraTrackerData do +RSpec.describe Integrations::JiraTrackerData do describe 'associations' do it { is_expected.to belong_to(:integration) } end diff --git a/spec/models/project_services/open_project_tracker_data_spec.rb b/spec/models/integrations/open_project_tracker_data_spec.rb similarity index 89% rename from spec/models/project_services/open_project_tracker_data_spec.rb rename to spec/models/integrations/open_project_tracker_data_spec.rb index 1f7f01cfea4..41c913f978c 100644 --- a/spec/models/project_services/open_project_tracker_data_spec.rb +++ b/spec/models/integrations/open_project_tracker_data_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe OpenProjectTrackerData do +RSpec.describe Integrations::OpenProjectTrackerData do describe 'associations' do it { is_expected.to belong_to(:integration) } end diff --git a/spec/requests/api/graphql/project/releases_spec.rb b/spec/requests/api/graphql/project/releases_spec.rb index 43732c2ed18..8ccdb955ed9 100644 --- a/spec/requests/api/graphql/project/releases_spec.rb +++ b/spec/requests/api/graphql/project/releases_spec.rb @@ -295,75 +295,69 @@ RSpec.describe 'Query.project(fullPath).releases()' do end end - describe 'sorting behavior' do - let_it_be(:today) { Time.now } - let_it_be(:yesterday) { today - 1.day } - let_it_be(:tomorrow) { today + 1.day } + describe 'sorting and pagination' do + let_it_be(:sort_project) { create(:project, :public) } - let_it_be(:project) { create(:project, :repository, :public) } + let(:data_path) { [:project, :releases] } + let(:current_user) { developer } - let_it_be(:release_v1) { create(:release, project: project, tag: 'v1', released_at: yesterday, created_at: tomorrow) } - let_it_be(:release_v2) { create(:release, project: project, tag: 'v2', released_at: today, created_at: yesterday) } - let_it_be(:release_v3) { create(:release, project: project, tag: 'v3', released_at: tomorrow, created_at: today) } - - let(:current_user) { developer } - - let(:params) { nil } - - let(:sorted_tags) do - graphql_data.dig('project', 'releases', 'nodes').map { |release| release['tagName'] } + def pagination_query(params) + graphql_query_for( + :project, + { full_path: sort_project.full_path }, + query_graphql_field(:releases, params, "#{page_info} nodes { tagName }") + ) end - let(:query) do - graphql_query_for(:project, { fullPath: project.full_path }, - %{ - releases#{params ? "(#{params})" : ""} { - nodes { - tagName - } - } - }) + def pagination_results_data(nodes) + nodes.map { |release| release['tagName'] } end - before do - post_query - end + context 'when sorting by released_at' do + let_it_be(:release5) { create(:release, project: sort_project, tag: 'v5.5.0', released_at: 3.days.from_now) } + let_it_be(:release1) { create(:release, project: sort_project, tag: 'v5.1.0', released_at: 3.days.ago) } + let_it_be(:release4) { create(:release, project: sort_project, tag: 'v5.4.0', released_at: 2.days.from_now) } + let_it_be(:release2) { create(:release, project: sort_project, tag: 'v5.2.0', released_at: 2.days.ago) } + let_it_be(:release3) { create(:release, project: sort_project, tag: 'v5.3.0', released_at: 1.day.ago) } - context 'when no sort: parameter is provided' do - it 'returns the results with the default sort applied (sort: RELEASED_AT_DESC)' do - expect(sorted_tags).to eq(%w(v3 v2 v1)) + context 'when ascending' do + it_behaves_like 'sorted paginated query' do + let(:sort_param) { :RELEASED_AT_ASC } + let(:first_param) { 2 } + let(:expected_results) { [release1.tag, release2.tag, release3.tag, release4.tag, release5.tag] } + end + end + + context 'when descending' do + it_behaves_like 'sorted paginated query' do + let(:sort_param) { :RELEASED_AT_DESC } + let(:first_param) { 2 } + let(:expected_results) { [release5.tag, release4.tag, release3.tag, release2.tag, release1.tag] } + end end end - context 'with sort: RELEASED_AT_DESC' do - let(:params) { 'sort: RELEASED_AT_DESC' } + context 'when sorting by created_at' do + let_it_be(:release5) { create(:release, project: sort_project, tag: 'v5.5.0', created_at: 3.days.from_now) } + let_it_be(:release1) { create(:release, project: sort_project, tag: 'v5.1.0', created_at: 3.days.ago) } + let_it_be(:release4) { create(:release, project: sort_project, tag: 'v5.4.0', created_at: 2.days.from_now) } + let_it_be(:release2) { create(:release, project: sort_project, tag: 'v5.2.0', created_at: 2.days.ago) } + let_it_be(:release3) { create(:release, project: sort_project, tag: 'v5.3.0', created_at: 1.day.ago) } - it 'returns the releases ordered by released_at in descending order' do - expect(sorted_tags).to eq(%w(v3 v2 v1)) + context 'when ascending' do + it_behaves_like 'sorted paginated query' do + let(:sort_param) { :CREATED_ASC } + let(:first_param) { 2 } + let(:expected_results) { [release1.tag, release2.tag, release3.tag, release4.tag, release5.tag] } + end end - end - context 'with sort: RELEASED_AT_ASC' do - let(:params) { 'sort: RELEASED_AT_ASC' } - - it 'returns the releases ordered by released_at in ascending order' do - expect(sorted_tags).to eq(%w(v1 v2 v3)) - end - end - - context 'with sort: CREATED_DESC' do - let(:params) { 'sort: CREATED_DESC' } - - it 'returns the releases ordered by created_at in descending order' do - expect(sorted_tags).to eq(%w(v1 v3 v2)) - end - end - - context 'with sort: CREATED_ASC' do - let(:params) { 'sort: CREATED_ASC' } - - it 'returns the releases ordered by created_at in ascending order' do - expect(sorted_tags).to eq(%w(v2 v3 v1)) + context 'when descending' do + it_behaves_like 'sorted paginated query' do + let(:sort_param) { :CREATED_DESC } + let(:first_param) { 2 } + let(:expected_results) { [release5.tag, release4.tag, release3.tag, release2.tag, release1.tag] } + end end end end