summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/finders/milestones_finder_spec.rb44
-rw-r--r--spec/frontend/monitoring/components/charts/stacked_column_spec.js45
-rw-r--r--spec/frontend/monitoring/mock_data.js47
-rw-r--r--spec/graphql/resolvers/milestone_resolver_spec.rb93
-rw-r--r--spec/lib/gitlab/search/found_blob_spec.rb10
-rw-r--r--spec/lib/gitlab/search/found_wiki_page_spec.rb18
-rw-r--r--spec/models/abuse_report_spec.rb4
-rw-r--r--spec/models/award_emoji_spec.rb4
-rw-r--r--spec/models/blob_viewer/gitlab_ci_yml_spec.rb5
-rw-r--r--spec/models/ci/artifact_blob_spec.rb4
-rw-r--r--spec/models/ci/pipeline_spec.rb4
-rw-r--r--spec/models/clusters/cluster_spec.rb2
-rw-r--r--spec/models/commit_spec.rb2
-rw-r--r--spec/models/commit_status_spec.rb4
-rw-r--r--spec/models/concerns/batch_destroy_dependent_associations_spec.rb8
-rw-r--r--spec/models/identity_spec.rb2
-rw-r--r--spec/models/label_note_spec.rb12
-rw-r--r--spec/models/lfs_file_lock_spec.rb2
-rw-r--r--spec/models/lfs_object_spec.rb10
-rw-r--r--spec/models/lfs_objects_project_spec.rb2
-rw-r--r--spec/models/merge_request_diff_spec.rb14
-rw-r--r--spec/models/merge_request_spec.rb4
-rw-r--r--spec/models/milestone_spec.rb17
-rw-r--r--spec/models/project_auto_devops_spec.rb2
-rw-r--r--spec/models/repository_spec.rb12
-rw-r--r--spec/models/sent_notification_spec.rb4
-rw-r--r--spec/models/user_spec.rb2
-rw-r--r--spec/presenters/milestone_presenter_spec.rb20
-rw-r--r--spec/requests/api/graphql/group/milestones_spec.rb85
-rw-r--r--spec/requests/api/projects_spec.rb17
-rw-r--r--spec/requests/api/runner_spec.rb42
-rw-r--r--spec/services/ci/create_job_artifacts_service_spec.rb121
-rw-r--r--spec/support/helpers/graphql_helpers.rb3
-rw-r--r--spec/support/shared_examples/policies/within_timeframe_shared_examples.rb23
34 files changed, 621 insertions, 67 deletions
diff --git a/spec/finders/milestones_finder_spec.rb b/spec/finders/milestones_finder_spec.rb
index 3545ff35ed8..3402eb39b3b 100644
--- a/spec/finders/milestones_finder_spec.rb
+++ b/spec/finders/milestones_finder_spec.rb
@@ -3,13 +3,14 @@
require 'spec_helper'
describe MilestonesFinder do
+ let(:now) { Time.now }
let(:group) { create(:group) }
let(:project_1) { create(:project, namespace: group) }
let(:project_2) { create(:project, namespace: group) }
- let!(:milestone_1) { create(:milestone, group: group, title: 'one test', due_date: Date.today) }
- let!(:milestone_2) { create(:milestone, group: group) }
- let!(:milestone_3) { create(:milestone, project: project_1, state: 'active', due_date: Date.tomorrow) }
- let!(:milestone_4) { create(:milestone, project: project_2, state: 'active') }
+ let!(:milestone_1) { create(:milestone, group: group, title: 'one test', start_date: now - 1.day, due_date: now) }
+ let!(:milestone_2) { create(:milestone, group: group, start_date: now + 1.day, due_date: now + 2.days) }
+ let!(:milestone_3) { create(:milestone, project: project_1, state: 'active', start_date: now + 2.days, due_date: now + 3.days) }
+ let!(:milestone_4) { create(:milestone, project: project_2, state: 'active', start_date: now + 4.days, due_date: now + 5.days) }
it 'returns milestones for projects' do
result = described_class.new(project_ids: [project_1.id, project_2.id], state: 'all').execute
@@ -33,8 +34,11 @@ describe MilestonesFinder do
end
it 'orders milestones by due date' do
- expect(result.first).to eq(milestone_1)
- expect(result.second).to eq(milestone_3)
+ milestone = create(:milestone, group: group, due_date: now - 2.days)
+
+ expect(result.first).to eq(milestone)
+ expect(result.second).to eq(milestone_1)
+ expect(result.third).to eq(milestone_2)
end
end
@@ -77,6 +81,34 @@ describe MilestonesFinder do
expect(result.to_a).to contain_exactly(milestone_1)
end
+
+ context 'by timeframe' do
+ it 'returns milestones with start_date and due_date between timeframe' do
+ params.merge!(start_date: now - 1.day, end_date: now + 3.days)
+
+ milestones = described_class.new(params).execute
+
+ expect(milestones).to match_array([milestone_1, milestone_2, milestone_3])
+ end
+
+ it 'returns milestones which starts before the timeframe' do
+ milestone = create(:milestone, project: project_2, start_date: now - 5.days)
+ params.merge!(start_date: now - 3.days, end_date: now - 2.days)
+
+ milestones = described_class.new(params).execute
+
+ expect(milestones).to match_array([milestone])
+ end
+
+ it 'returns milestones which ends after the timeframe' do
+ milestone = create(:milestone, project: project_2, due_date: now + 6.days)
+ params.merge!(start_date: now + 6.days, end_date: now + 7.days)
+
+ milestones = described_class.new(params).execute
+
+ expect(milestones).to match_array([milestone])
+ end
+ end
end
describe '#find_by' do
diff --git a/spec/frontend/monitoring/components/charts/stacked_column_spec.js b/spec/frontend/monitoring/components/charts/stacked_column_spec.js
new file mode 100644
index 00000000000..abb89ac15ef
--- /dev/null
+++ b/spec/frontend/monitoring/components/charts/stacked_column_spec.js
@@ -0,0 +1,45 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlStackedColumnChart } from '@gitlab/ui/dist/charts';
+import StackedColumnChart from '~/monitoring/components/charts/stacked_column.vue';
+import { stackedColumnMockedData } from '../../mock_data';
+
+jest.mock('~/lib/utils/icon_utils', () => ({
+ getSvgIconPathContent: jest.fn().mockResolvedValue('mockSvgPathContent'),
+}));
+
+describe('Stacked column chart component', () => {
+ let wrapper;
+ const glStackedColumnChart = () => wrapper.find(GlStackedColumnChart);
+
+ beforeEach(() => {
+ wrapper = shallowMount(StackedColumnChart, {
+ propsData: {
+ graphData: stackedColumnMockedData,
+ },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('with graphData present', () => {
+ it('is a Vue instance', () => {
+ expect(glStackedColumnChart().exists()).toBe(true);
+ });
+
+ it('should contain the same number of elements in the seriesNames computed prop as the graphData metrics prop', () =>
+ wrapper.vm
+ .$nextTick()
+ .then(expect(wrapper.vm.seriesNames).toHaveLength(stackedColumnMockedData.metrics.length)));
+
+ it('should contain the same number of elements in the groupBy computed prop as the graphData result prop', () =>
+ wrapper.vm
+ .$nextTick()
+ .then(
+ expect(wrapper.vm.groupBy).toHaveLength(
+ stackedColumnMockedData.metrics[0].result[0].values.length,
+ ),
+ ));
+ });
+});
diff --git a/spec/frontend/monitoring/mock_data.js b/spec/frontend/monitoring/mock_data.js
index 5fd73b73e0d..0c985ba4fca 100644
--- a/spec/frontend/monitoring/mock_data.js
+++ b/spec/frontend/monitoring/mock_data.js
@@ -665,3 +665,50 @@ export const graphDataPrometheusQueryRangeMultiTrack = {
},
],
};
+
+export const stackedColumnMockedData = {
+ title: 'memories',
+ type: 'stacked-column',
+ x_label: 'x label',
+ y_label: 'y label',
+ metrics: [
+ {
+ label: 'memory_1024',
+ unit: 'count',
+ series_name: 'group 1',
+ prometheus_endpoint_path:
+ '/root/autodevops-deploy-6/-/environments/24/prometheus/api/v1/query_range?query=avg%28sum%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+by+%28job%29%29+without+%28job%29+%2F+count%28avg%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+without+%28job%29%29+%2F1024%2F1024',
+ metric_id: 'undefined_metric_of_ages_1024',
+ metricId: 'undefined_metric_of_ages_1024',
+ result: [
+ {
+ metric: {},
+ values: [
+ ['2020-01-30 12:00:00', '5'],
+ ['2020-01-30 12:01:00', '10'],
+ ['2020-01-30 12:02:00', '15'],
+ ],
+ },
+ ],
+ },
+ {
+ label: 'memory_1000',
+ unit: 'count',
+ series_name: 'group 2',
+ prometheus_endpoint_path:
+ '/root/autodevops-deploy-6/-/environments/24/prometheus/api/v1/query_range?query=avg%28sum%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+by+%28job%29%29+without+%28job%29+%2F+count%28avg%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+without+%28job%29%29+%2F1024%2F1024',
+ metric_id: 'undefined_metric_of_ages_1000',
+ metricId: 'undefined_metric_of_ages_1000',
+ result: [
+ {
+ metric: {},
+ values: [
+ ['2020-01-30 12:00:00', '20'],
+ ['2020-01-30 12:01:00', '25'],
+ ['2020-01-30 12:02:00', '30'],
+ ],
+ },
+ ],
+ },
+ ],
+};
diff --git a/spec/graphql/resolvers/milestone_resolver_spec.rb b/spec/graphql/resolvers/milestone_resolver_spec.rb
new file mode 100644
index 00000000000..297130c2027
--- /dev/null
+++ b/spec/graphql/resolvers/milestone_resolver_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::MilestoneResolver do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ let_it_be(:current_user) { create(:user) }
+
+ context 'for group milestones' do
+ let_it_be(:now) { Time.now }
+ let_it_be(:group) { create(:group, :private) }
+
+ def resolve_group_milestones(args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: group, args: args, ctx: context)
+ end
+
+ before do
+ group.add_developer(current_user)
+ end
+
+ it 'calls MilestonesFinder#execute' do
+ expect_next_instance_of(MilestonesFinder) do |finder|
+ expect(finder).to receive(:execute)
+ end
+
+ resolve_group_milestones
+ end
+
+ context 'without parameters' do
+ it 'calls MilestonesFinder to retrieve all milestones' do
+ expect(MilestonesFinder).to receive(:new)
+ .with(group_ids: group.id, state: 'all', start_date: nil, end_date: nil)
+ .and_call_original
+
+ resolve_group_milestones
+ end
+ end
+
+ context 'with parameters' do
+ it 'calls MilestonesFinder with correct parameters' do
+ start_date = now
+ end_date = start_date + 1.hour
+
+ expect(MilestonesFinder).to receive(:new)
+ .with(group_ids: group.id, state: 'closed', start_date: start_date, end_date: end_date)
+ .and_call_original
+
+ resolve_group_milestones(start_date: start_date, end_date: end_date, state: 'closed')
+ end
+ end
+
+ context 'by timeframe' do
+ context 'when start_date and end_date are present' do
+ context 'when start date is after end_date' do
+ it 'raises error' do
+ expect do
+ resolve_group_milestones(start_date: now, end_date: now - 2.days)
+ end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, "startDate is after endDate")
+ end
+ end
+ end
+
+ context 'when only start_date is present' do
+ it 'raises error' do
+ expect do
+ resolve_group_milestones(start_date: now)
+ end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/)
+ end
+ end
+
+ context 'when only end_date is present' do
+ it 'raises error' do
+ expect do
+ resolve_group_milestones(end_date: now)
+ end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/)
+ end
+ end
+ end
+
+ context 'when user cannot read milestones' do
+ it 'raises error' do
+ unauthorized_user = create(:user)
+
+ expect do
+ resolve_group_milestones({}, { current_user: unauthorized_user })
+ end.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/search/found_blob_spec.rb b/spec/lib/gitlab/search/found_blob_spec.rb
index 07842faa638..ce6a54100a5 100644
--- a/spec/lib/gitlab/search/found_blob_spec.rb
+++ b/spec/lib/gitlab/search/found_blob_spec.rb
@@ -156,4 +156,14 @@ describe Gitlab::Search::FoundBlob do
end
end
end
+
+ describe 'policy' do
+ let(:project) { build(:project, :repository) }
+
+ subject { described_class.new(project: project) }
+
+ it 'works with policy' do
+ expect(Ability.allowed?(project.creator, :read_blob, subject)).to be_truthy
+ end
+ end
end
diff --git a/spec/lib/gitlab/search/found_wiki_page_spec.rb b/spec/lib/gitlab/search/found_wiki_page_spec.rb
new file mode 100644
index 00000000000..e8b6728aba5
--- /dev/null
+++ b/spec/lib/gitlab/search/found_wiki_page_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Search::FoundWikiPage do
+ let(:project) { create(:project, :public, :repository) }
+
+ describe 'policy' do
+ let(:project) { build(:project, :repository) }
+ let(:found_blob) { Gitlab::Search::FoundBlob.new(project: project) }
+
+ subject { described_class.new(found_blob) }
+
+ it 'works with policy' do
+ expect(Ability.allowed?(project.creator, :read_wiki_page, subject)).to be_truthy
+ end
+ end
+end
diff --git a/spec/models/abuse_report_spec.rb b/spec/models/abuse_report_spec.rb
index 814df472389..2c4fa398636 100644
--- a/spec/models/abuse_report_spec.rb
+++ b/spec/models/abuse_report_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
describe AbuseReport do
- set(:report) { create(:abuse_report) }
- set(:user) { create(:admin) }
+ let_it_be(:report, reload: true) { create(:abuse_report) }
+ let_it_be(:user, reload: true) { create(:admin) }
subject { report }
it { expect(subject).to be_valid }
diff --git a/spec/models/award_emoji_spec.rb b/spec/models/award_emoji_spec.rb
index b15b26b1630..b2d58dd95ad 100644
--- a/spec/models/award_emoji_spec.rb
+++ b/spec/models/award_emoji_spec.rb
@@ -45,8 +45,8 @@ describe AwardEmoji do
end
describe 'scopes' do
- set(:thumbsup) { create(:award_emoji, name: 'thumbsup') }
- set(:thumbsdown) { create(:award_emoji, name: 'thumbsdown') }
+ let_it_be(:thumbsup) { create(:award_emoji, name: 'thumbsup') }
+ let_it_be(:thumbsdown) { create(:award_emoji, name: 'thumbsdown') }
describe '.upvotes' do
it { expect(described_class.upvotes).to contain_exactly(thumbsup) }
diff --git a/spec/models/blob_viewer/gitlab_ci_yml_spec.rb b/spec/models/blob_viewer/gitlab_ci_yml_spec.rb
index 02993052124..e645733e02d 100644
--- a/spec/models/blob_viewer/gitlab_ci_yml_spec.rb
+++ b/spec/models/blob_viewer/gitlab_ci_yml_spec.rb
@@ -6,9 +6,8 @@ describe BlobViewer::GitlabCiYml do
include FakeBlobHelpers
include RepoHelpers
- set(:project) { create(:project, :repository) }
- set(:user) { create(:user) }
-
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
let(:data) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) }
let(:blob) { fake_blob(path: '.gitlab-ci.yml', data: data) }
let(:sha) { sample_commit.id }
diff --git a/spec/models/ci/artifact_blob_spec.rb b/spec/models/ci/artifact_blob_spec.rb
index f63816fd92a..8a66b55cc15 100644
--- a/spec/models/ci/artifact_blob_spec.rb
+++ b/spec/models/ci/artifact_blob_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
describe Ci::ArtifactBlob do
- set(:project) { create(:project, :public) }
- set(:build) { create(:ci_build, :artifacts, project: project) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:build) { create(:ci_build, :artifacts, project: project) }
let(:entry) { build.artifacts_metadata_entry('other_artifacts_0.1.2/another-subdirectory/banana_sample.gif') }
subject { described_class.new(entry) }
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 013581c0d94..09d6d661d81 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -7,7 +7,7 @@ describe Ci::Pipeline, :mailer do
include StubRequests
let(:user) { create(:user) }
- set(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
let(:pipeline) do
create(:ci_empty_pipeline, status: :created, project: project)
@@ -231,7 +231,7 @@ describe Ci::Pipeline, :mailer do
describe '#legacy_detached_merge_request_pipeline?' do
subject { pipeline.legacy_detached_merge_request_pipeline? }
- set(:merge_request) { create(:merge_request) }
+ let_it_be(:merge_request) { create(:merge_request) }
let(:ref) { 'feature' }
let(:target_sha) { nil }
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index 44ca4a06e2d..85860da38ad 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -544,7 +544,7 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end
describe '#applications' do
- set(:cluster) { create(:cluster) }
+ let_it_be(:cluster, reload: true) { create(:cluster) }
subject { cluster.applications }
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index 782d1ac4552..c09f5bc4f4d 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -17,7 +17,7 @@ describe Commit do
end
describe '.lazy' do
- set(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
context 'when the commits are found' do
let(:oids) do
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 40652614101..e1a748da7fd 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
describe CommitStatus do
- set(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
- set(:pipeline) do
+ let_it_be(:pipeline) do
create(:ci_pipeline, project: project, sha: project.commit.id)
end
diff --git a/spec/models/concerns/batch_destroy_dependent_associations_spec.rb b/spec/models/concerns/batch_destroy_dependent_associations_spec.rb
index 1fe90d3cc9a..d2373926802 100644
--- a/spec/models/concerns/batch_destroy_dependent_associations_spec.rb
+++ b/spec/models/concerns/batch_destroy_dependent_associations_spec.rb
@@ -15,7 +15,7 @@ describe BatchDestroyDependentAssociations do
end
describe '#dependent_associations_to_destroy' do
- set(:project) { TestProject.new }
+ let_it_be(:project) { TestProject.new }
it 'returns the right associations' do
expect(project.dependent_associations_to_destroy.map(&:name)).to match_array([:builds])
@@ -23,9 +23,9 @@ describe BatchDestroyDependentAssociations do
end
describe '#destroy_dependent_associations_in_batches' do
- set(:project) { create(:project) }
- set(:build) { create(:ci_build, project: project) }
- set(:notification_setting) { create(:notification_setting, project: project) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:build) { create(:ci_build, project: project) }
+ let_it_be(:notification_setting) { create(:notification_setting, project: project) }
let!(:todos) { create(:todo, project: project) }
it 'destroys multiple builds' do
diff --git a/spec/models/identity_spec.rb b/spec/models/identity_spec.rb
index 74ddc2d6284..9f120775a3c 100644
--- a/spec/models/identity_spec.rb
+++ b/spec/models/identity_spec.rb
@@ -13,7 +13,7 @@ describe Identity do
end
describe 'validations' do
- set(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
context 'with existing user and provider' do
before do
diff --git a/spec/models/label_note_spec.rb b/spec/models/label_note_spec.rb
index dd2c702a7a9..34560acfa9e 100644
--- a/spec/models/label_note_spec.rb
+++ b/spec/models/label_note_spec.rb
@@ -3,20 +3,20 @@
require 'spec_helper'
describe LabelNote do
- set(:project) { create(:project, :repository) }
- set(:user) { create(:user) }
- set(:label) { create(:label, project: project) }
- set(:label2) { create(:label, project: project) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:label) { create(:label, project: project) }
+ let_it_be(:label2) { create(:label, project: project) }
let(:resource_parent) { project }
context 'when resource is issue' do
- set(:resource) { create(:issue, project: project) }
+ let_it_be(:resource) { create(:issue, project: project) }
it_behaves_like 'label note created from events'
end
context 'when resource is merge request' do
- set(:resource) { create(:merge_request, source_project: project, target_project: project) }
+ let_it_be(:resource) { create(:merge_request, source_project: project, target_project: project) }
it_behaves_like 'label note created from events'
end
diff --git a/spec/models/lfs_file_lock_spec.rb b/spec/models/lfs_file_lock_spec.rb
index a42346c341d..0a47ded43fb 100644
--- a/spec/models/lfs_file_lock_spec.rb
+++ b/spec/models/lfs_file_lock_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
describe LfsFileLock do
- set(:lfs_file_lock) { create(:lfs_file_lock) }
+ let_it_be(:lfs_file_lock, reload: true) { create(:lfs_file_lock) }
subject { lfs_file_lock }
it { is_expected.to belong_to(:project) }
diff --git a/spec/models/lfs_object_spec.rb b/spec/models/lfs_object_spec.rb
index 44445429d3e..51713906d06 100644
--- a/spec/models/lfs_object_spec.rb
+++ b/spec/models/lfs_object_spec.rb
@@ -44,8 +44,8 @@ describe LfsObject do
end
describe '#project_allowed_access?' do
- set(:lfs_object) { create(:lfs_objects_project).lfs_object }
- set(:project) { create(:project) }
+ let_it_be(:lfs_object) { create(:lfs_objects_project).lfs_object }
+ let_it_be(:project, reload: true) { create(:project) }
it 'returns true when project is linked' do
create(:lfs_objects_project, lfs_object: lfs_object, project: project)
@@ -58,9 +58,9 @@ describe LfsObject do
end
context 'when project is a member of a fork network' do
- set(:fork_network) { create(:fork_network) }
- set(:fork_network_root_project) { fork_network.root_project }
- set(:fork_network_membership) { create(:fork_network_member, project: project, fork_network: fork_network) }
+ let_it_be(:fork_network) { create(:fork_network) }
+ let_it_be(:fork_network_root_project, reload: true) { fork_network.root_project }
+ let_it_be(:fork_network_membership) { create(:fork_network_member, project: project, fork_network: fork_network) }
it 'returns true for all members when forked project is linked' do
create(:lfs_objects_project, lfs_object: lfs_object, project: project)
diff --git a/spec/models/lfs_objects_project_spec.rb b/spec/models/lfs_objects_project_spec.rb
index e320f873989..31300828a43 100644
--- a/spec/models/lfs_objects_project_spec.rb
+++ b/spec/models/lfs_objects_project_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
describe LfsObjectsProject do
- set(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
subject do
create(:lfs_objects_project, project: project)
diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb
index 78b9e8bc217..8167241faa8 100644
--- a/spec/models/merge_request_diff_spec.rb
+++ b/spec/models/merge_request_diff_spec.rb
@@ -54,20 +54,20 @@ describe MergeRequestDiff do
end
describe '.ids_for_external_storage_migration' do
- set(:merge_request) { create(:merge_request) }
- set(:outdated) { merge_request.merge_request_diff }
- set(:latest) { merge_request.create_merge_request_diff }
+ let_it_be(:merge_request) { create(:merge_request) }
+ let_it_be(:outdated) { merge_request.merge_request_diff }
+ let_it_be(:latest) { merge_request.create_merge_request_diff }
- set(:closed_mr) { create(:merge_request, :closed_last_month) }
+ let_it_be(:closed_mr) { create(:merge_request, :closed_last_month) }
let(:closed) { closed_mr.merge_request_diff }
- set(:merged_mr) { create(:merge_request, :merged_last_month) }
+ let_it_be(:merged_mr) { create(:merge_request, :merged_last_month) }
let(:merged) { merged_mr.merge_request_diff }
- set(:recently_closed_mr) { create(:merge_request, :closed) }
+ let_it_be(:recently_closed_mr) { create(:merge_request, :closed) }
let(:closed_recently) { recently_closed_mr.merge_request_diff }
- set(:recently_merged_mr) { create(:merge_request, :merged) }
+ let_it_be(:recently_merged_mr) { create(:merge_request, :merged) }
let(:merged_recently) { recently_merged_mr.merge_request_diff }
before do
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 470b67afe07..08348e3767a 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -1091,8 +1091,8 @@ describe MergeRequest do
end
describe '#can_remove_source_branch?' do
- set(:user) { create(:user) }
- set(:merge_request) { create(:merge_request, :simple) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:merge_request, reload: true) { create(:merge_request, :simple) }
subject { merge_request }
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index d84a8665dc8..04587ef4240 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -197,6 +197,15 @@ describe Milestone do
end
end
+ it_behaves_like 'within_timeframe scope' do
+ let_it_be(:now) { Time.now }
+ let_it_be(:project) { create(:project, :empty_repo) }
+ let_it_be(:resource_1) { create(:milestone, project: project, start_date: now - 1.day, due_date: now + 1.day) }
+ let_it_be(:resource_2) { create(:milestone, project: project, start_date: now + 2.days, due_date: now + 3.days) }
+ let_it_be(:resource_3) { create(:milestone, project: project, due_date: now) }
+ let_it_be(:resource_4) { create(:milestone, project: project, start_date: now) }
+ end
+
describe "#percent_complete" do
it "does not count open issues" do
milestone.issues << issue
@@ -517,9 +526,9 @@ describe Milestone do
end
describe '.sort_by_attribute' do
- set(:milestone_1) { create(:milestone, title: 'Foo') }
- set(:milestone_2) { create(:milestone, title: 'Bar') }
- set(:milestone_3) { create(:milestone, title: 'Zoo') }
+ let_it_be(:milestone_1) { create(:milestone, title: 'Foo') }
+ let_it_be(:milestone_2) { create(:milestone, title: 'Bar') }
+ let_it_be(:milestone_3) { create(:milestone, title: 'Zoo') }
context 'ordering by name ascending' do
it 'sorts by title ascending' do
@@ -555,7 +564,7 @@ describe Milestone do
end
it 'returns the quantity of milestones in each possible state' do
- expected_count = { opened: 5, closed: 6, all: 11 }
+ expected_count = { opened: 2, closed: 6, all: 8 }
count = described_class.states_count(Project.all, Group.all)
expect(count).to eq(expected_count)
diff --git a/spec/models/project_auto_devops_spec.rb b/spec/models/project_auto_devops_spec.rb
index 2a821b20aa8..5af25ac1437 100644
--- a/spec/models/project_auto_devops_spec.rb
+++ b/spec/models/project_auto_devops_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
describe ProjectAutoDevops do
- set(:project) { build(:project) }
+ let_it_be(:project) { build(:project) }
it_behaves_like 'having unique enum values'
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 679e6142416..fdacfbe24d1 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -40,7 +40,7 @@ describe Repository do
end
describe '#branch_names_contains' do
- set(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
let(:repository) { project.repository }
subject { repository.branch_names_contains(sample_commit.id) }
@@ -328,7 +328,7 @@ describe Repository do
end
describe '#new_commits' do
- set(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
let(:repository) { project.repository }
subject { repository.new_commits(rev) }
@@ -356,7 +356,7 @@ describe Repository do
end
describe '#commits_by' do
- set(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
let(:oids) { TestEnv::BRANCH_SHA.values }
subject { project.repository.commits_by(oids: oids) }
@@ -2575,7 +2575,7 @@ describe Repository do
end
describe 'commit cache' do
- set(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
it 'caches based on SHA' do
# Gets the commit oid, and warms the cache
@@ -2723,7 +2723,7 @@ describe Repository do
end
describe '#merge_base' do
- set(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
subject(:repository) { project.repository }
it 'only makes one gitaly call' do
@@ -2782,7 +2782,7 @@ describe Repository do
end
describe "#blobs_metadata" do
- set(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
let(:repository) { project.repository }
def expect_metadata_blob(thing)
diff --git a/spec/models/sent_notification_spec.rb b/spec/models/sent_notification_spec.rb
index 7539bf1e957..fedaae372c4 100644
--- a/spec/models/sent_notification_spec.rb
+++ b/spec/models/sent_notification_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
describe SentNotification do
- set(:user) { create(:user) }
- set(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
describe 'validation' do
describe 'note validity' do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index d14de7e99de..f2b95e00b5e 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -2196,7 +2196,7 @@ describe User, :do_not_mock_admin_mode do
describe '.find_by_private_commit_email' do
context 'with email' do
- set(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
it 'returns user through private commit email' do
expect(described_class.find_by_private_commit_email(user.private_commit_email)).to eq(user)
diff --git a/spec/presenters/milestone_presenter_spec.rb b/spec/presenters/milestone_presenter_spec.rb
new file mode 100644
index 00000000000..3d7b3ad6d78
--- /dev/null
+++ b/spec/presenters/milestone_presenter_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe MilestonePresenter do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:milestone) { create(:milestone, group: group) }
+ let_it_be(:presenter) { described_class.new(milestone, current_user: user) }
+
+ before do
+ group.add_developer(user)
+ end
+
+ describe '#milestone_path' do
+ it 'returns correct path' do
+ expect(presenter.milestone_path).to eq("/groups/#{group.full_path}/-/milestones/#{milestone.iid}")
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/group/milestones_spec.rb b/spec/requests/api/graphql/group/milestones_spec.rb
new file mode 100644
index 00000000000..84b14470fd1
--- /dev/null
+++ b/spec/requests/api/graphql/group/milestones_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Milestones through GroupQuery' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:now) { Time.now }
+ let_it_be(:group) { create(:group, :private) }
+ let_it_be(:milestone_1) { create(:milestone, group: group) }
+ let_it_be(:milestone_2) { create(:milestone, group: group, state: :closed, start_date: now, due_date: now + 1.day) }
+ let_it_be(:milestone_3) { create(:milestone, group: group, start_date: now, due_date: now + 2.days) }
+ let_it_be(:milestone_4) { create(:milestone, group: group, state: :closed, start_date: now - 2.days, due_date: now - 1.day) }
+ let_it_be(:milestone_from_other_group) { create(:milestone, group: create(:group)) }
+
+ let(:milestone_data) { graphql_data['group']['milestones']['edges'] }
+
+ describe 'Get list of milestones from a group' do
+ before do
+ group.add_developer(user)
+ end
+
+ context 'when the request is correct' do
+ before do
+ fetch_milestones(user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ it 'returns milestones successfully' do
+ expect(response).to have_gitlab_http_status(200)
+ expect(graphql_errors).to be_nil
+ expect_array_response(milestone_1.to_global_id.to_s, milestone_2.to_global_id.to_s, milestone_3.to_global_id.to_s, milestone_4.to_global_id.to_s)
+ end
+ end
+
+ context 'when filtering by timeframe' do
+ it 'fetches milestones between start_date and due_date' do
+ fetch_milestones(user, { start_date: now.to_s, end_date: (now + 2.days).to_s })
+
+ expect_array_response(milestone_2.to_global_id.to_s, milestone_3.to_global_id.to_s)
+ end
+ end
+
+ context 'when filtering by state' do
+ it 'returns milestones with given state' do
+ fetch_milestones(user, { state: :active })
+
+ expect_array_response(milestone_1.to_global_id.to_s, milestone_3.to_global_id.to_s)
+ end
+ end
+
+ def fetch_milestones(user = nil, args = {})
+ post_graphql(milestones_query(args), current_user: user)
+ end
+
+ def milestones_query(args = {})
+ milestone_node = <<~NODE
+ edges {
+ node {
+ id
+ title
+ state
+ }
+ }
+ NODE
+
+ graphql_query_for("group",
+ { full_path: group.full_path },
+ [query_graphql_field("milestones", args, milestone_node)]
+ )
+ end
+
+ def expect_array_response(*items)
+ expect(response).to have_gitlab_http_status(:success)
+ expect(milestone_data).to be_an Array
+ expect(milestone_node_array('id')).to match_array(items)
+ end
+
+ def milestone_node_array(extract_attribute = nil)
+ node_array(milestone_data, extract_attribute)
+ end
+ end
+end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index e88209081d4..2b9ec4319f5 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -1402,6 +1402,7 @@ describe API::Projects do
expect(json_response['merge_requests_access_level']).to be_present
expect(json_response['wiki_access_level']).to be_present
expect(json_response['builds_access_level']).to be_present
+ expect(json_response).to have_key('emails_disabled')
expect(json_response['resolve_outdated_diff_discussions']).to eq(project.resolve_outdated_diff_discussions)
expect(json_response['remove_source_branch_after_merge']).to be_truthy
expect(json_response['container_registry_enabled']).to be_present
@@ -1412,18 +1413,18 @@ describe API::Projects do
expect(json_response['namespace']).to be_present
expect(json_response['import_status']).to be_present
expect(json_response).to include("import_error")
- expect(json_response['avatar_url']).to be_nil
+ expect(json_response).to have_key('avatar_url')
expect(json_response['star_count']).to be_present
expect(json_response['forks_count']).to be_present
expect(json_response['public_jobs']).to be_present
- expect(json_response['ci_config_path']).to be_nil
+ expect(json_response).to have_key('ci_config_path')
expect(json_response['shared_with_groups']).to be_an Array
expect(json_response['shared_with_groups'].length).to eq(1)
expect(json_response['shared_with_groups'][0]['group_id']).to eq(group.id)
expect(json_response['shared_with_groups'][0]['group_name']).to eq(group.name)
expect(json_response['shared_with_groups'][0]['group_full_path']).to eq(group.full_path)
expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access)
- expect(json_response['shared_with_groups'][0]['expires_at']).to be_nil
+ expect(json_response['shared_with_groups'][0]).to have_key('expires_at')
expect(json_response['only_allow_merge_if_pipeline_succeeds']).to eq(project.only_allow_merge_if_pipeline_succeeds)
expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to eq(project.only_allow_merge_if_all_discussions_are_resolved)
expect(json_response['ci_default_git_depth']).to eq(project.ci_default_git_depth)
@@ -2243,6 +2244,16 @@ describe API::Projects do
expect(json_response['pages_access_level']).to eq('private')
end
+ it 'updates emails_disabled' do
+ project_param = { emails_disabled: true }
+
+ put api("/projects/#{project3.id}", user), params: project_param
+
+ expect(response).to have_gitlab_http_status(200)
+
+ expect(json_response['emails_disabled']).to eq(true)
+ end
+
it 'updates build_git_strategy' do
project_param = { build_git_strategy: 'clone' }
diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb
index e3ba366dfcc..23ce17b14fc 100644
--- a/spec/requests/api/runner_spec.rb
+++ b/spec/requests/api/runner_spec.rb
@@ -1607,7 +1607,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
it_behaves_like 'successful artifacts upload'
end
- context 'for file stored remotelly' do
+ context 'for file stored remotely' do
let!(:fog_connection) do
stub_artifacts_object_storage(direct_upload: true)
end
@@ -1894,6 +1894,46 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
end
+ context 'when artifacts already exist for the job' do
+ let(:params) do
+ {
+ artifact_type: :archive,
+ artifact_format: :zip,
+ 'file.sha256' => uploaded_sha256
+ }
+ end
+
+ let(:existing_sha256) { '0' * 64 }
+
+ let!(:existing_artifact) do
+ create(:ci_job_artifact, :archive, file_sha256: existing_sha256, job: job)
+ end
+
+ context 'when sha256 is the same of the existing artifact' do
+ let(:uploaded_sha256) { existing_sha256 }
+
+ it 'ignores the new artifact' do
+ upload_artifacts(file_upload, headers_with_token, params)
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(job.reload.job_artifacts_archive).to eq(existing_artifact)
+ end
+ end
+
+ context 'when sha256 is different than the existing artifact' do
+ let(:uploaded_sha256) { '1' * 64 }
+
+ it 'logs and returns an error' do
+ expect(Gitlab::ErrorTracking).to receive(:track_exception)
+
+ upload_artifacts(file_upload, headers_with_token, params)
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(job.reload.job_artifacts_archive).to eq(existing_artifact)
+ end
+ end
+ end
+
context 'when artifacts are being stored outside of tmp path' do
let(:new_tmpdir) { Dir.mktmpdir }
diff --git a/spec/services/ci/create_job_artifacts_service_spec.rb b/spec/services/ci/create_job_artifacts_service_spec.rb
new file mode 100644
index 00000000000..e1146fc3df6
--- /dev/null
+++ b/spec/services/ci/create_job_artifacts_service_spec.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Ci::CreateJobArtifactsService do
+ let(:service) { described_class.new }
+ let(:job) { create(:ci_build) }
+ let(:artifacts_sha256) { '0' * 64 }
+ let(:metadata_file) { nil }
+
+ let(:artifacts_file) do
+ file_to_upload('spec/fixtures/ci_build_artifacts.zip', sha256: artifacts_sha256)
+ end
+
+ let(:params) do
+ {
+ 'artifact_type' => 'archive',
+ 'artifact_format' => 'zip'
+ }
+ end
+
+ def file_to_upload(path, params = {})
+ upload = Tempfile.new('upload')
+ FileUtils.copy(path, upload.path)
+
+ UploadedFile.new(upload.path, params)
+ end
+
+ describe '#execute' do
+ subject { service.execute(job, artifacts_file, params, metadata_file: metadata_file) }
+
+ context 'when artifacts file is uploaded' do
+ it 'saves artifact for the given type' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(1)
+
+ new_artifact = job.job_artifacts.last
+ expect(new_artifact.project).to eq(job.project)
+ expect(new_artifact.file).to be_present
+ expect(new_artifact.file_type).to eq(params['artifact_type'])
+ expect(new_artifact.file_format).to eq(params['artifact_format'])
+ expect(new_artifact.file_sha256).to eq(artifacts_sha256)
+ end
+
+ context 'when metadata file is also uploaded' do
+ let(:metadata_file) do
+ file_to_upload('spec/fixtures/ci_build_artifacts_metadata.gz', sha256: artifacts_sha256)
+ end
+
+ before do
+ stub_application_setting(default_artifacts_expire_in: '1 day')
+ end
+
+ it 'saves metadata artifact' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(2)
+
+ new_artifact = job.job_artifacts.last
+ expect(new_artifact.project).to eq(job.project)
+ expect(new_artifact.file).to be_present
+ expect(new_artifact.file_type).to eq('metadata')
+ expect(new_artifact.file_format).to eq('gzip')
+ expect(new_artifact.file_sha256).to eq(artifacts_sha256)
+ end
+
+ it 'sets expiration date according to application settings' do
+ expected_expire_at = 1.day.from_now
+
+ expect(subject).to be_truthy
+ archive_artifact, metadata_artifact = job.job_artifacts.last(2)
+
+ expect(job.artifacts_expire_at).to be_within(1.minute).of(expected_expire_at)
+ expect(archive_artifact.expire_at).to be_within(1.minute).of(expected_expire_at)
+ expect(metadata_artifact.expire_at).to be_within(1.minute).of(expected_expire_at)
+ end
+
+ context 'when expire_in params is set' do
+ before do
+ params.merge!('expire_in' => '2 hours')
+ end
+
+ it 'sets expiration date according to the parameter' do
+ expected_expire_at = 2.hours.from_now
+
+ expect(subject).to be_truthy
+ archive_artifact, metadata_artifact = job.job_artifacts.last(2)
+
+ expect(job.artifacts_expire_at).to be_within(1.minute).of(expected_expire_at)
+ expect(archive_artifact.expire_at).to be_within(1.minute).of(expected_expire_at)
+ expect(metadata_artifact.expire_at).to be_within(1.minute).of(expected_expire_at)
+ end
+ end
+ end
+ end
+
+ context 'when artifacts file already exists' do
+ let!(:existing_artifact) do
+ create(:ci_job_artifact, :archive, file_sha256: existing_sha256, job: job)
+ end
+
+ context 'when sha256 of uploading artifact is the same of the existing one' do
+ let(:existing_sha256) { artifacts_sha256 }
+
+ it 'ignores the changes' do
+ expect { subject }.not_to change { Ci::JobArtifact.count }
+ expect(subject).to be_truthy
+ end
+ end
+
+ context 'when sha256 of uploading artifact is different than the existing one' do
+ let(:existing_sha256) { '1' * 64 }
+
+ it 'returns false and logs the error' do
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).and_call_original
+
+ expect { subject }.not_to change { Ci::JobArtifact.count }
+ expect(subject).to be_falsey
+ expect(job.errors[:base]).to contain_exactly('another artifact of the same type already exists')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index 8dc99e4e042..35b1b802f35 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -185,12 +185,13 @@ module GraphqlHelpers
end
# Fairly dumb Ruby => GraphQL rendering function. Only suitable for testing.
- # Missing support for Enums (feel free to add if you need it).
+ # Use symbol for Enum values
def as_graphql_literal(value)
case value
when Array then "[#{value.map { |v| as_graphql_literal(v) }.join(',')}]"
when Integer, Float then value.to_s
when String then "\"#{value.gsub(/"/, '\\"')}\""
+ when Symbol then value
when nil then 'null'
when true then 'true'
when false then 'false'
diff --git a/spec/support/shared_examples/policies/within_timeframe_shared_examples.rb b/spec/support/shared_examples/policies/within_timeframe_shared_examples.rb
new file mode 100644
index 00000000000..918db6886d3
--- /dev/null
+++ b/spec/support/shared_examples/policies/within_timeframe_shared_examples.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'within_timeframe scope' do
+ describe '.within_timeframe' do
+ it 'returns resources with start_date and/or end_date between timeframe' do
+ resources = described_class.within_timeframe(now + 2.days, now + 3.days)
+
+ expect(resources).to match_array([resource_2, resource_4])
+ end
+
+ it 'returns resources which starts before the timeframe' do
+ resources = described_class.within_timeframe(now, now + 1.day)
+
+ expect(resources).to match_array([resource_1, resource_3, resource_4])
+ end
+
+ it 'returns resources which ends after the timeframe' do
+ resources = described_class.within_timeframe(now + 3.days, now + 5.days)
+
+ expect(resources).to match_array([resource_2, resource_4])
+ end
+ end
+end