diff options
-rw-r--r-- | app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue | 83 | ||||
-rw-r--r-- | app/finders/issuable_finder.rb | 8 | ||||
-rw-r--r-- | app/finders/issuable_finder/params.rb | 33 | ||||
-rw-r--r-- | app/services/issues/close_service.rb | 2 | ||||
-rw-r--r-- | app/services/notification_service.rb | 4 | ||||
-rw-r--r-- | changelogs/unreleased/hide-inoperable-group-search-releases-filter-backend.yml | 5 | ||||
-rw-r--r-- | doc/development/product_analytics/usage_ping.md | 7 | ||||
-rw-r--r-- | lib/api/helpers/pagination.rb | 4 | ||||
-rw-r--r-- | locale/gitlab.pot | 2 | ||||
-rw-r--r-- | spec/finders/issues_finder_spec.rb | 120 | ||||
-rw-r--r-- | spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js | 4 | ||||
-rw-r--r-- | spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb | 48 |
12 files changed, 225 insertions, 95 deletions
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue index 278dcc38c69..1ac2802c367 100644 --- a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue +++ b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue @@ -1,5 +1,4 @@ <script> -import { isEmpty } from 'lodash'; import { GlAlert } from '@gitlab/ui'; import { __ } from '~/locale'; import JobPill from './job_pill.vue'; @@ -22,8 +21,6 @@ export default { errorTexts: { [DRAW_FAILURE]: __('Could not draw the lines for job relationships'), [DEFAULT]: __('An unknown error occurred.'), - }, - warningTexts: { [EMPTY_PIPELINE_DATA]: __( 'The visualization will appear in this tab when the CI/CD configuration file is populated with valid syntax.', ), @@ -46,24 +43,24 @@ export default { }; }, computed: { + hideGraph() { + // We won't even try to render the graph with these condition + // because it would cause additional errors down the line for the user + // which is confusing. + return this.isPipelineDataEmpty || this.isInvalidCiConfig; + }, pipelineStages() { return this.pipelineData?.stages || []; }, isPipelineDataEmpty() { - return !this.isInvalidCiConfig && isEmpty(this.pipelineStages); + return !this.isInvalidCiConfig && this.pipelineStages.length === 0; }, isInvalidCiConfig() { return this.pipelineData?.status === CI_CONFIG_STATUS_INVALID; }, - showAlert() { - return this.hasError || this.hasWarning; - }, hasError() { return this.failureType; }, - hasWarning() { - return this.warning; - }, hasHighlightedJob() { return Boolean(this.highlightedJob); }, @@ -75,26 +72,32 @@ export default { return this.warning; }, failure() { - const text = this.$options.errorTexts[this.failureType] || this.$options.errorTexts[DEFAULT]; - - return { text, variant: 'danger', dismissible: true }; - }, - warning() { - if (this.isPipelineDataEmpty) { - return { - text: this.$options.warningTexts[EMPTY_PIPELINE_DATA], - variant: 'tip', - dismissible: false, - }; - } else if (this.isInvalidCiConfig) { - return { - text: this.$options.warningTexts[INVALID_CI_CONFIG], - variant: 'danger', - dismissible: false, - }; + switch (this.failureType) { + case DRAW_FAILURE: + return { + text: this.$options.errorTexts[DRAW_FAILURE], + variant: 'danger', + dismissible: true, + }; + case EMPTY_PIPELINE_DATA: + return { + text: this.$options.errorTexts[EMPTY_PIPELINE_DATA], + variant: 'tip', + dismissible: false, + }; + case INVALID_CI_CONFIG: + return { + text: this.$options.errorTexts[INVALID_CI_CONFIG], + variant: 'danger', + dismissible: false, + }; + default: + return { + text: this.$options.errorTexts[DEFAULT], + variant: 'danger', + dismissible: true, + }; } - - return null; }, viewBox() { return [0, 0, this.width, this.height]; @@ -122,6 +125,24 @@ export default { return []; }, }, + watch: { + isPipelineDataEmpty: { + immediate: true, + handler(isDataEmpty) { + if (isDataEmpty) { + this.reportFailure(EMPTY_PIPELINE_DATA); + } + }, + }, + isInvalidCiConfig: { + immediate: true, + handler(isInvalid) { + if (isInvalid) { + this.reportFailure(INVALID_CI_CONFIG); + } + }, + }, + }, mounted() { if (!this.isPipelineDataEmpty && !this.isInvalidCiConfig) { // This guarantee that all sub-elements are rendered @@ -201,7 +222,7 @@ export default { <template> <div> <gl-alert - v-if="showAlert" + v-if="hasError" :variant="alert.variant" :dismissible="alert.dismissible" @dismiss="alert.dismissible ? resetFailure : null" @@ -209,7 +230,7 @@ export default { {{ alert.text }} </gl-alert> <div - v-if="!hasWarning" + v-if="!hideGraph" :id="$options.CONTAINER_ID" :ref="$options.CONTAINER_REF" class="gl-display-flex gl-bg-gray-50 gl-px-4 gl-overflow-auto gl-relative gl-py-7" diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index 922b53b514d..fc03d5cd90c 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -4,6 +4,9 @@ # # Used to filter Issues and MergeRequests collections by set of params # +# Note: This class is NOT meant to be instantiated. Instead you should +# look at IssuesFinder or EpicsFinder, which inherit from this. +# # Arguments: # klass - actual class like Issue or MergeRequest # current_user - which user use @@ -92,6 +95,10 @@ class IssuableFinder IssuableFinder::Params end + def klass + raise NotImplementedError + end + def initialize(current_user, params = {}) @current_user = current_user @params = params_class.new(params, current_user, klass) @@ -451,6 +458,7 @@ class IssuableFinder def by_release(items) return items unless params.releases? + return items if params.group? # don't allow release filtering at group level if params.filter_by_no_release? items.without_release diff --git a/app/finders/issuable_finder/params.rb b/app/finders/issuable_finder/params.rb index b481afee338..803b30e86ac 100644 --- a/app/finders/issuable_finder/params.rb +++ b/app/finders/issuable_finder/params.rb @@ -108,16 +108,8 @@ class IssuableFinder project_id.present? end - def group - strong_memoize(:group) do - if params[:group_id].is_a?(Group) - params[:group_id] - elsif params[:group_id].present? - Group.find(params[:group_id]) - else - nil - end - end + def group? + group_id.present? end def related_groups @@ -143,10 +135,25 @@ class IssuableFinder end end + def group + strong_memoize(:group) do + next nil unless group? + + group = group_id.is_a?(Group) ? group_id : Group.find(group_id) + group = nil unless Ability.allowed?(current_user, :read_group, group) + + group + end + end + def project_id params[:project_id] end + def group_id + params[:group_id] + end + def projects strong_memoize(:projects) do next [project] if project? @@ -216,14 +223,14 @@ class IssuableFinder strong_memoize(:milestones) do if milestones? if project? - group_id = project.group&.id + project_group_id = project.group&.id project_id = project.id end - group_id = group.id if group + project_group_id = group.id if group search_params = - { title: params[:milestone_title], project_ids: project_id, group_ids: group_id } + { title: params[:milestone_title], project_ids: project_id, group_ids: project_group_id } MilestonesFinder.new(search_params).execute # rubocop: disable CodeReuse/Finder else diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb index c3677de015f..c723f6058e9 100644 --- a/app/services/issues/close_service.rb +++ b/app/services/issues/close_service.rb @@ -31,7 +31,7 @@ module Issues closed_via = _("commit %{commit_id}") % { commit_id: closed_via.id } if closed_via.is_a?(Commit) - notification_service.async.close_issue(issue, current_user, closed_via: closed_via) if notifications + notification_service.async.close_issue(issue, current_user, { closed_via: closed_via }) if notifications todo_service.close_issue(issue, current_user) resolve_alert(issue) execute_hooks(issue, 'close') diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 4ff462191fe..d0bd3206556 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -118,8 +118,8 @@ class NotificationService # * project team members with notification level higher then Participating # * users with custom level checked with "close issue" # - def close_issue(issue, current_user, closed_via: nil) - close_resource_email(issue, current_user, :closed_issue_email, closed_via: closed_via) + def close_issue(issue, current_user, params = {}) + close_resource_email(issue, current_user, :closed_issue_email, closed_via: params[:closed_via]) end # When we reassign an issue we should send an email to: diff --git a/changelogs/unreleased/hide-inoperable-group-search-releases-filter-backend.yml b/changelogs/unreleased/hide-inoperable-group-search-releases-filter-backend.yml new file mode 100644 index 00000000000..08b3da1ca48 --- /dev/null +++ b/changelogs/unreleased/hide-inoperable-group-search-releases-filter-backend.yml @@ -0,0 +1,5 @@ +--- +title: Don't allow filtering by release tag on groups. +merge_request: 50457 +author: +type: fixed diff --git a/doc/development/product_analytics/usage_ping.md b/doc/development/product_analytics/usage_ping.md index 535c8d9fe9d..98682ebfd76 100644 --- a/doc/development/product_analytics/usage_ping.md +++ b/doc/development/product_analytics/usage_ping.md @@ -541,13 +541,16 @@ To enable or disable tracking for specific event within <https://gitlab.com> or /chatops run feature set <feature_name> false ``` -##### Known events in usage data payload +##### Known events are added automatically in usage data payload All events added in [`known_events/common.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml) are automatically added to usage data generation under the `redis_hll_counters` key. This column is stored in [version-app as a JSON](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L209). For each event we add metrics for the weekly and monthly time frames, and totals for each where applicable: - `#{event_name}_weekly`: Data for 7 days for daily [aggregation](#adding-new-events) events and data for the last complete week for weekly [aggregation](#adding-new-events) events. - `#{event_name}_monthly`: Data for 28 days for daily [aggregation](#adding-new-events) events and data for the last 4 complete weeks for weekly [aggregation](#adding-new-events) events. + +Redis HLL implementation calculates automatic total metrics, if there are more than one metric for the same category, aggregation and Redis slot. + - `#{category}_total_unique_counts_weekly`: Total unique counts for events in the same category for the last 7 days or the last complete week, if events are in the same Redis slot and we have more than one metric. - `#{category}_total_unique_counts_monthly`: Total unique counts for events in same category for the last 28 days or the last 4 complete weeks, if events are in the same Redis slot and we have more than one metric. @@ -792,7 +795,7 @@ In order to add data for aggregated metrics into Usage Ping payload you should a - operator: operator that defines how aggregated metric data is counted. Available operators are: - `OR`: removes duplicates and counts all entries that triggered any of listed events - `AND`: removes duplicates and counts all elements that were observed triggering all of following events -- events: list of events names (from [`known_events.yml`](#known-events-in-usage-data-payload)) to aggregate into metric. All events in this list must have the same `redis_slot` and `aggregation` attributes. +- events: list of events names (from [`known_events.yml`](#known-events-are-added-automatically-in-usage-data-payload)) to aggregate into metric. All events in this list must have the same `redis_slot` and `aggregation` attributes. - feature_flag: name of [development feature flag](../feature_flags/development.md#development-type) that is checked before metrics aggregation is performed. Corresponding feature flag should have `default_enabled` attribute set to `false`. `feature_flag` attribute is **OPTIONAL** and can be omitted, when `feature_flag` is missing no feature flag is checked. diff --git a/lib/api/helpers/pagination.rb b/lib/api/helpers/pagination.rb index 227aec224e5..48618e7d26d 100644 --- a/lib/api/helpers/pagination.rb +++ b/lib/api/helpers/pagination.rb @@ -3,8 +3,8 @@ module API module Helpers module Pagination - def paginate(*args) - Gitlab::Pagination::OffsetPagination.new(self).paginate(*args) + def paginate(*args, **kwargs) + Gitlab::Pagination::OffsetPagination.new(self).paginate(*args, **kwargs) end end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d87fac90360..c8941299841 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -29037,7 +29037,7 @@ msgstr "" msgid "ThreatMonitoring|Time" msgstr "" -msgid "ThreatMonitoring|To view this data, ensure you have configured an environment for this project and that at least one threat monitoring feature is enabled." +msgid "ThreatMonitoring|To view this data, ensure you have configured an environment for this project and that at least one threat monitoring feature is enabled. %{linkStart}More information%{linkEnd}" msgstr "" msgid "ThreatMonitoring|Total Packets" diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb index 0def3412aa7..d990cae61ca 100644 --- a/spec/finders/issues_finder_spec.rb +++ b/spec/finders/issues_finder_spec.rb @@ -13,7 +13,27 @@ RSpec.describe IssuesFinder do let(:scope) { 'all' } it 'returns all issues' do - expect(issues).to contain_exactly(issue1, issue2, issue3, issue4) + expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, issue5) + end + + context 'user does not have read permissions' do + let(:search_user) { user2 } + + context 'when filtering by project id' do + let(:params) { { project_id: project1.id } } + + it 'returns no issues' do + expect(issues).to be_empty + end + end + + context 'when filtering by group id' do + let(:params) { { group_id: group.id } } + + it 'returns no issues' do + expect(issues).to be_empty + end + end end context 'assignee filtering' do @@ -21,7 +41,7 @@ RSpec.describe IssuesFinder do it_behaves_like 'assignee ID filter' do let(:params) { { assignee_id: user.id } } - let(:expected_issuables) { [issue1, issue2] } + let(:expected_issuables) { [issue1, issue2, issue5] } end it_behaves_like 'assignee NOT ID filter' do @@ -59,7 +79,25 @@ RSpec.describe IssuesFinder do end it_behaves_like 'any assignee filter' do - let(:expected_issuables) { [issue1, issue2, issue3] } + let(:expected_issuables) { [issue1, issue2, issue3, issue5] } + end + end + + context 'filtering by release' do + context 'when the release tag is none' do + let(:params) { { release_tag: 'none' } } + + it 'returns issues without releases' do + expect(issues).to contain_exactly(issue2, issue3, issue4, issue5) + end + end + + context 'when the release tag exists' do + let(:params) { { project_id: project1.id, release_tag: release.tag } } + + it 'returns the issues associated with that release' do + expect(issues).to contain_exactly(issue1) + end end end @@ -68,7 +106,7 @@ RSpec.describe IssuesFinder do let(:params) { { projects: [project1.id] } } it 'returns the issue belonging to the projects' do - expect(issues).to contain_exactly(issue1) + expect(issues).to contain_exactly(issue1, issue5) end end @@ -76,7 +114,7 @@ RSpec.describe IssuesFinder do let(:params) { { projects: Project.id_in(project1.id) } } it 'returns the issue belonging to the projects' do - expect(issues).to contain_exactly(issue1) + expect(issues).to contain_exactly(issue1, issue5) end end end @@ -86,7 +124,7 @@ RSpec.describe IssuesFinder do context 'when include_subgroup param not set' do it 'returns all group issues' do - expect(issues).to contain_exactly(issue1) + expect(issues).to contain_exactly(issue1, issue5) end context 'when projects outside the group are passed' do @@ -101,7 +139,7 @@ RSpec.describe IssuesFinder do let(:params) { { group_id: group.id, projects: [project1.id] } } it 'returns the issue within the group and projects' do - expect(issues).to contain_exactly(issue1) + expect(issues).to contain_exactly(issue1, issue5) end end @@ -109,7 +147,15 @@ RSpec.describe IssuesFinder do let(:params) { { group_id: group.id, projects: Project.id_in(project1.id) } } it 'returns the issue within the group and projects' do - expect(issues).to contain_exactly(issue1) + expect(issues).to contain_exactly(issue1, issue5) + end + end + + context 'when release_tag is passed as a parameter' do + let(:params) { { group_id: group.id, release_tag: 'dne-release-tag' } } + + it 'ignores the release_tag parameter' do + expect(issues).to contain_exactly(issue1, issue5) end end end @@ -120,7 +166,7 @@ RSpec.describe IssuesFinder do end it 'returns all group and subgroup issues' do - expect(issues).to contain_exactly(issue1, issue4) + expect(issues).to contain_exactly(issue1, issue4, issue5) end context 'when mixed projects are passed' do @@ -145,7 +191,7 @@ RSpec.describe IssuesFinder do let(:params) { { not: { author_id: user2.id } } } it 'returns issues not created by that user' do - expect(issues).to contain_exactly(issue1, issue2, issue4) + expect(issues).to contain_exactly(issue1, issue2, issue4, issue5) end end @@ -175,7 +221,7 @@ RSpec.describe IssuesFinder do let(:params) { { not: { milestone_title: milestone.title } } } it 'returns issues not assigned to that milestone' do - expect(issues).to contain_exactly(issue2, issue3, issue4) + expect(issues).to contain_exactly(issue2, issue3, issue4, issue5) end end @@ -199,7 +245,7 @@ RSpec.describe IssuesFinder do let(:params) { { not: { milestone_title: group_milestone.title } } } it 'returns issues not assigned to that group milestone' do - expect(issues).to contain_exactly(issue1, issue4) + expect(issues).to contain_exactly(issue1, issue4, issue5) end end end @@ -208,13 +254,13 @@ RSpec.describe IssuesFinder do let(:params) { { milestone_title: 'None' } } it 'returns issues with no milestone' do - expect(issues).to contain_exactly(issue2, issue3, issue4) + expect(issues).to contain_exactly(issue2, issue3, issue4, issue5) end it 'returns issues with no milestone (deprecated)' do params[:milestone_title] = Milestone::None.title - expect(issues).to contain_exactly(issue2, issue3, issue4) + expect(issues).to contain_exactly(issue2, issue3, issue4, issue5) end end @@ -343,7 +389,7 @@ RSpec.describe IssuesFinder do let(:params) { { not: { label_name: label.title } } } it 'returns issues that do not have that label' do - expect(issues).to contain_exactly(issue1, issue3, issue4) + expect(issues).to contain_exactly(issue1, issue3, issue4, issue5) end # IssuableFinder first filters using the outer params (the ones not inside the `not` key.) @@ -383,7 +429,7 @@ RSpec.describe IssuesFinder do let(:params) { { not: { label_name: [label.title, label2.title].join(',') } } } it 'returns issues that do not have any of the labels provided' do - expect(issues).to contain_exactly(issue1, issue4) + expect(issues).to contain_exactly(issue1, issue4, issue5) end end end @@ -405,7 +451,7 @@ RSpec.describe IssuesFinder do let(:params) { { not: { label_name: [label.title, label2.title].join(',') } } } it 'returns issues that do not have ANY ONE of the labels provided' do - expect(issues).to contain_exactly(issue1, issue4) + expect(issues).to contain_exactly(issue1, issue4, issue5) end end end @@ -414,7 +460,7 @@ RSpec.describe IssuesFinder do let(:params) { { label_name: described_class::Params::FILTER_NONE } } it 'returns issues with no labels' do - expect(issues).to contain_exactly(issue1, issue4) + expect(issues).to contain_exactly(issue1, issue4, issue5) end end @@ -483,14 +529,14 @@ RSpec.describe IssuesFinder do end context 'filtering by issues iids' do - let(:params) { { iids: issue3.iid } } + let(:params) { { iids: [issue3.iid] } } - it 'returns issues with iids match' do - expect(issues).to contain_exactly(issue3) + it 'returns issues where iids match' do + expect(issues).to contain_exactly(issue3, issue5) end context 'using NOT' do - let(:params) { { not: { iids: issue3.iid } } } + let(:params) { { not: { iids: [issue3.iid] } } } it 'returns issues with no iids match' do expect(issues).to contain_exactly(issue1, issue2, issue4) @@ -503,7 +549,7 @@ RSpec.describe IssuesFinder do let(:params) { { state: 'opened' } } it 'returns only opened issues' do - expect(issues).to contain_exactly(issue1, issue2, issue3, issue4) + expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, issue5) end end @@ -519,7 +565,7 @@ RSpec.describe IssuesFinder do let(:params) { { state: 'all' } } it 'returns all issues' do - expect(issues).to contain_exactly(issue1, issue2, issue3, closed_issue, issue4) + expect(issues).to contain_exactly(issue1, issue2, issue3, closed_issue, issue4, issue5) end end @@ -527,7 +573,7 @@ RSpec.describe IssuesFinder do let(:params) { { state: 'invalid_state' } } it 'returns all issues' do - expect(issues).to contain_exactly(issue1, issue2, issue3, closed_issue, issue4) + expect(issues).to contain_exactly(issue1, issue2, issue3, closed_issue, issue4, issue5) end end end @@ -619,7 +665,7 @@ RSpec.describe IssuesFinder do let(:params) { { my_reaction_emoji: 'None' } } it 'returns issues that the user did not react to' do - expect(issues).to contain_exactly(issue2, issue4) + expect(issues).to contain_exactly(issue2, issue4, issue5) end end @@ -642,7 +688,7 @@ RSpec.describe IssuesFinder do let(:params) { { not: { my_reaction_emoji: 'thumbsup' } } } it 'returns issues that the user did not thumbsup to' do - expect(issues).to contain_exactly(issue2, issue3, issue4) + expect(issues).to contain_exactly(issue2, issue3, issue4, issue5) end end end @@ -676,7 +722,7 @@ RSpec.describe IssuesFinder do let(:params) { { not: { my_reaction_emoji: 'thumbsdown' } } } it 'returns issues that the user thumbsdown to' do - expect(issues).to contain_exactly(issue1, issue2, issue4) + expect(issues).to contain_exactly(issue1, issue2, issue4, issue5) end end end @@ -687,7 +733,7 @@ RSpec.describe IssuesFinder do context 'no filtering' do it 'returns all issues' do - expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, confidential_issue) + expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, issue5, confidential_issue) end end @@ -703,7 +749,7 @@ RSpec.describe IssuesFinder do let(:params) { { confidential: false } } it 'returns only confdential issues' do - expect(issues).to contain_exactly(issue1, issue2, issue3, issue4) + expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, issue5) end end end @@ -715,7 +761,7 @@ RSpec.describe IssuesFinder do let(:params) { { issue_types: [] } } it 'returns all issues' do - expect(issues).to contain_exactly(incident_issue, issue1, issue2, issue3, issue4) + expect(issues).to contain_exactly(incident_issue, issue1, issue2, issue3, issue4, issue5) end end @@ -731,7 +777,7 @@ RSpec.describe IssuesFinder do let(:params) { { issue_types: ['issue'] } } it 'returns all issues with type issue' do - expect(issues).to contain_exactly(issue1, issue2, issue3, issue4) + expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, issue5) end end @@ -739,7 +785,7 @@ RSpec.describe IssuesFinder do let(:params) { { issue_types: %w(issue incident) } } it 'returns all issues' do - expect(issues).to contain_exactly(incident_issue, issue1, issue2, issue3, issue4) + expect(issues).to contain_exactly(incident_issue, issue1, issue2, issue3, issue4, issue5) end end @@ -790,14 +836,14 @@ RSpec.describe IssuesFinder do let(:scope) { 'assigned_to_me' } it 'returns issue assigned to the user' do - expect(issues).to contain_exactly(issue1, issue2) + expect(issues).to contain_exactly(issue1, issue2, issue5) end context 'filtering by project' do let(:params) { { project_id: project1.id } } it 'returns issues assigned to the user in that project' do - expect(issues).to contain_exactly(issue1) + expect(issues).to contain_exactly(issue1, issue5) end end end @@ -839,7 +885,7 @@ RSpec.describe IssuesFinder do let(:params) { base_params.merge(due_date: Issue::NoDueDate.name) } it 'returns issues with no due date' do - expect(issues).to contain_exactly(issue1) + expect(issues).to contain_exactly(issue1, issue5) end end @@ -875,7 +921,7 @@ RSpec.describe IssuesFinder do it 'returns the number of rows for the default state' do finder = described_class.new(admin) - expect(finder.row_count).to eq(4) + expect(finder.row_count).to eq(5) end it 'returns the number of rows for a given state' do diff --git a/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js b/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js index 5b1abdf10cf..b6b0a964383 100644 --- a/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js +++ b/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js @@ -37,7 +37,7 @@ describe('pipeline graph component', () => { }); it('renders an empty section', () => { - expect(wrapper.text()).toBe(wrapper.vm.$options.warningTexts[EMPTY_PIPELINE_DATA]); + expect(wrapper.text()).toBe(wrapper.vm.$options.errorTexts[EMPTY_PIPELINE_DATA]); expect(findPipelineGraph().exists()).toBe(false); expect(findAllStagePills()).toHaveLength(0); expect(findAllJobPills()).toHaveLength(0); @@ -51,7 +51,7 @@ describe('pipeline graph component', () => { it('renders an error message and does not render the graph', () => { expect(findAlert().exists()).toBe(true); - expect(findAlert().text()).toBe(wrapper.vm.$options.warningTexts[INVALID_CI_CONFIG]); + expect(findAlert().text()).toBe(wrapper.vm.$options.errorTexts[INVALID_CI_CONFIG]); expect(findPipelineGraph().exists()).toBe(false); }); }); diff --git a/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb index 9ffde54c84a..d9cbea58406 100644 --- a/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb +++ b/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb @@ -8,13 +8,53 @@ RSpec.shared_context 'IssuesFinder context' do let_it_be(:project1, reload: true) { create(:project, group: group) } let_it_be(:project2, reload: true) { create(:project) } let_it_be(:project3, reload: true) { create(:project, group: subgroup) } - let_it_be(:milestone) { create(:milestone, project: project1) } + let_it_be(:release) { create(:release, project: project1, tag: 'v1.0.0') } + let_it_be(:milestone) { create(:milestone, project: project1, releases: [release]) } let_it_be(:label) { create(:label, project: project2) } let_it_be(:label2) { create(:label, project: project2) } - let_it_be(:issue1, reload: true) { create(:issue, author: user, assignees: [user], project: project1, milestone: milestone, title: 'gitlab', created_at: 1.week.ago, updated_at: 1.week.ago) } - let_it_be(:issue2, reload: true) { create(:issue, author: user, assignees: [user], project: project2, description: 'gitlab', created_at: 1.week.from_now, updated_at: 1.week.from_now) } - let_it_be(:issue3, reload: true) { create(:issue, author: user2, assignees: [user2], project: project2, title: 'tanuki', description: 'tanuki', created_at: 2.weeks.from_now, updated_at: 2.weeks.from_now) } + let_it_be(:issue1, reload: true) do + create(:issue, + author: user, + assignees: [user], + project: project1, + milestone: milestone, + title: 'gitlab', + created_at: 1.week.ago, + updated_at: 1.week.ago) + end + + let_it_be(:issue2, reload: true) do + create(:issue, + author: user, + assignees: [user], + project: project2, + description: 'gitlab', + created_at: 1.week.from_now, + updated_at: 1.week.from_now) + end + + let_it_be(:issue3, reload: true) do + create(:issue, + author: user2, + assignees: [user2], + project: project2, + title: 'tanuki', + description: 'tanuki', + created_at: 2.weeks.from_now, + updated_at: 2.weeks.from_now) + end + let_it_be(:issue4, reload: true) { create(:issue, project: project3) } + let_it_be(:issue5, reload: true) do + create(:issue, + author: user, + assignees: [user], + project: project1, + title: 'wotnot', + created_at: 3.days.ago, + updated_at: 3.days.ago) + end + let_it_be(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: issue1) } let_it_be(:award_emoji2) { create(:award_emoji, name: 'thumbsup', user: user2, awardable: issue2) } let_it_be(:award_emoji3) { create(:award_emoji, name: 'thumbsdown', user: user, awardable: issue3) } |