Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
03c84e0de5
commit
f0aaec1f67
|
@ -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'
|
||||
|
|
|
@ -1 +1 @@
|
|||
c93530dd0922e7554d6d1e486e830f72980fe083
|
||||
6e58da454633a53c86d14a59587ee7a6a9d11031
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
];
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -6,7 +6,7 @@ class Integration < ApplicationRecord
|
|||
include Sortable
|
||||
include Importable
|
||||
include ProjectServicesLoggable
|
||||
include DataFields
|
||||
include Integrations::HasDataFields
|
||||
include FromUnion
|
||||
include EachBatch
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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/<namespace>/<project>/-/jobs/artifacts/<ref>/browse?job=<job
|
|||
For example:
|
||||
|
||||
```plaintext
|
||||
https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/browse?job=coverage
|
||||
https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/main/browse?job=coverage
|
||||
```
|
||||
|
||||
To download specific files, including HTML files that
|
||||
|
@ -168,7 +168,7 @@ https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/file/<path>?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
|
||||
|
|
|
@ -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' }
|
||||
|
|
|
@ -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'}
|
||||
|
|
|
@ -121,10 +121,10 @@ Object {
|
|||
},
|
||||
],
|
||||
"paginationInfo": Object {
|
||||
"endCursor": "eyJpZCI6IjEifQ",
|
||||
"endCursor": "eyJyZWxlYXNlZF9hdCI6IjIwMTgtMTItMTAgMDA6MDA6MDAuMDAwMDAwMDAwIFVUQyIsImlkIjoiMSJ9",
|
||||
"hasNextPage": false,
|
||||
"hasPreviousPage": false,
|
||||
"startCursor": "eyJpZCI6IjEifQ",
|
||||
"startCursor": "eyJyZWxlYXNlZF9hdCI6IjIwMTgtMTItMTAgMDA6MDA6MDAuMDAwMDAwMDAwIFVUQyIsImlkIjoiMSJ9",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue