diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-09-30 12:09:43 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-09-30 12:09:43 +0300 |
commit | 14846d722eb52ea70bc3092eb5da80ce1c2e9750 (patch) | |
tree | 34700bc9c8c7cddbf955bc079a174ca75e099903 | |
parent | bfb305ef516d8d6c07e91024a16772070d09afe0 (diff) |
Add latest changes from gitlab-org/gitlab@master
30 files changed, 438 insertions, 385 deletions
diff --git a/.rubocop_todo/rspec/described_class.yml b/.rubocop_todo/rspec/described_class.yml index 8304704985b..516eda12675 100644 --- a/.rubocop_todo/rspec/described_class.yml +++ b/.rubocop_todo/rspec/described_class.yml @@ -69,7 +69,6 @@ RSpec/DescribedClass: - 'ee/spec/services/resource_access_tokens/create_service_spec.rb' - 'ee/spec/services/security/ingestion/tasks/update_vulnerability_uuids_spec.rb' - 'ee/spec/services/users/captcha_challenge_service_spec.rb' - - 'ee/spec/services/vulnerabilities/create_from_security_finding_service_spec.rb' - 'ee/spec/workers/concerns/elastic/indexing_control_spec.rb' - 'ee/spec/workers/elastic/migration_worker_spec.rb' - 'ee/spec/workers/geo/secondary/registry_consistency_worker_spec.rb' diff --git a/.rubocop_todo/rspec/predicate_matcher.yml b/.rubocop_todo/rspec/predicate_matcher.yml index 53ee031b8ee..e4215a0e6d0 100644 --- a/.rubocop_todo/rspec/predicate_matcher.yml +++ b/.rubocop_todo/rspec/predicate_matcher.yml @@ -99,8 +99,6 @@ RSpec/PredicateMatcher: - 'ee/spec/services/jira/requests/issues/list_service_spec.rb' - 'ee/spec/services/milestones/promote_service_spec.rb' - 'ee/spec/services/protected_environments/create_service_spec.rb' - - 'ee/spec/services/vulnerabilities/create_from_security_finding_service_spec.rb' - - 'ee/spec/services/vulnerabilities/findings/create_from_security_finding_service_spec.rb' - 'ee/spec/services/vulnerabilities/manually_create_service_spec.rb' - 'ee/spec/services/vulnerability_exports/export_service_spec.rb' - 'ee/spec/support/shared_examples/graphql/mutations/dast_on_demand_scans_shared_examples.rb' diff --git a/.rubocop_todo/rspec/scattered_let.yml b/.rubocop_todo/rspec/scattered_let.yml index faf2000253a..61f1a09589f 100644 --- a/.rubocop_todo/rspec/scattered_let.yml +++ b/.rubocop_todo/rspec/scattered_let.yml @@ -98,8 +98,6 @@ RSpec/ScatteredLet: - 'ee/spec/services/personal_access_tokens/groups/update_lifetime_service_spec.rb' - 'ee/spec/services/sbom/ingestion/occurrence_map_spec.rb' - 'ee/spec/services/security/report_summary_service_spec.rb' - - 'ee/spec/services/vulnerabilities/create_from_security_finding_service_spec.rb' - - 'ee/spec/services/vulnerabilities/findings/create_from_security_finding_service_spec.rb' - 'ee/spec/services/vulnerabilities/security_finding/create_issue_service_spec.rb' - 'ee/spec/views/subscriptions/groups/edit.html.haml_spec.rb' - 'ee/spec/workers/concerns/update_orchestration_policy_configuration_spec.rb' diff --git a/.rubocop_todo/style/format_string.yml b/.rubocop_todo/style/format_string.yml index 66c368a7a52..adcb8b70f5a 100644 --- a/.rubocop_todo/style/format_string.yml +++ b/.rubocop_todo/style/format_string.yml @@ -265,7 +265,6 @@ Style/FormatString: - 'ee/app/services/vulnerabilities/destroy_dismissal_feedback_service.rb' - 'ee/app/services/vulnerabilities/dismiss_service.rb' - 'ee/app/services/vulnerabilities/finding_dismiss_service.rb' - - 'ee/app/services/vulnerabilities/findings/create_from_security_finding_service.rb' - 'ee/app/services/vulnerabilities/historical_statistics/adjustment_service.rb' - 'ee/app/services/vulnerabilities/statistics/adjustment_service.rb' - 'ee/app/services/vulnerability_external_issue_links/create_service.rb' diff --git a/app/graphql/graphql_triggers.rb b/app/graphql/graphql_triggers.rb index 2d25a675a46..02b05a24578 100644 --- a/app/graphql/graphql_triggers.rb +++ b/app/graphql/graphql_triggers.rb @@ -24,6 +24,14 @@ module GraphqlTriggers def self.issuable_dates_updated(issuable) GitlabSchema.subscriptions.trigger('issuableDatesUpdated', { issuable_id: issuable.to_gid }, issuable) end + + def self.merge_request_reviewers_updated(merge_request) + GitlabSchema.subscriptions.trigger( + 'mergeRequestReviewersUpdated', + { issuable_id: merge_request.to_gid }, + merge_request + ) + end end GraphqlTriggers.prepend_mod diff --git a/app/models/concerns/timebox.rb b/app/models/concerns/timebox.rb index d53594eb5af..5b74e88429c 100644 --- a/app/models/concerns/timebox.rb +++ b/app/models/concerns/timebox.rb @@ -3,13 +3,10 @@ module Timebox extend ActiveSupport::Concern - include AtomicInternalId include CacheMarkdownField include Gitlab::SQL::Pattern - include IidRoutes include Referable include StripAttribute - include FromUnion TimeboxStruct = Struct.new(:title, :name, :id, :class_name) do # Ensure these models match the interface required for exporting @@ -42,39 +39,19 @@ module Timebox alias_method :timebox_id, :id - validates :group, presence: true, unless: :project - validates :project, presence: true, unless: :group - - validate :timebox_type_check validate :start_date_should_be_less_than_due_date, if: proc { |m| m.start_date.present? && m.due_date.present? } validate :dates_within_4_digits cache_markdown_field :title, pipeline: :single_line cache_markdown_field :description, issuable_reference_expansion_enabled: true - belongs_to :project - belongs_to :group - has_many :issues has_many :labels, -> { distinct.reorder('labels.title') }, through: :issues has_many :merge_requests - scope :of_projects, ->(ids) { where(project_id: ids) } - scope :of_groups, ->(ids) { where(group_id: ids) } scope :closed, -> { with_state(:closed) } - scope :for_projects, -> { where(group: nil).includes(:project) } scope :with_title, -> (title) { where(title: title) } - scope :for_projects_and_groups, -> (projects, groups) do - projects = projects.compact if projects.is_a? Array - projects = [] if projects.nil? - - groups = groups.compact if groups.is_a? Array - groups = [] if groups.nil? - - from_union([where(project_id: projects), where(group_id: groups)], remove_duplicates: false) - end - # A timebox is within the timeframe (start_date, end_date) if it overlaps # with that timeframe: # @@ -132,10 +109,6 @@ module Timebox end end - def count_by_state - reorder(nil).group(:state).count - end - def predefined_id?(id) [Any.id, None.id, Upcoming.id, Started.id].include?(id) end @@ -145,29 +118,8 @@ module Timebox end end - ## - # Returns the String necessary to reference a Timebox in Markdown. Group - # timeboxes only support name references, and do not support cross-project - # references. - # - # format - Symbol format to use (default: :iid, optional: :name) - # - # Examples: - # - # Milestone.first.to_reference # => "%1" - # Iteration.first.to_reference(format: :name) # => "*iteration:\"goal\"" - # Milestone.first.to_reference(cross_namespace_project) # => "gitlab-org/gitlab-foss%1" - # Iteration.first.to_reference(same_namespace_project) # => "gitlab-foss*iteration:1" - # - def to_reference(from = nil, format: :name, full: false) - format_reference = timebox_format_reference(format) - reference = "#{self.class.reference_prefix}#{format_reference}" - - if project - "#{project.to_reference_base(from, full: full)}#{reference}" - else - reference - end + def to_reference + raise NotImplementedError end def reference_link_text(from = nil) @@ -182,20 +134,12 @@ module Timebox model_name.singular end - def group_timebox? - group_id.present? - end - - def project_timebox? - project_id.present? - end - def safe_title title.to_slug.normalize.to_s end def resource_parent - group || project + raise NotImplementedError end def to_ability_name @@ -203,13 +147,7 @@ module Timebox end def merge_requests_enabled? - if group_timebox? - # Assume that groups have at least one project with merge requests enabled. - # Otherwise, we would need to load all of the projects from the database. - true - elsif project_timebox? - project&.merge_requests_enabled? - end + raise NotImplementedError end def weight_available? @@ -218,28 +156,6 @@ module Timebox private - def timebox_format_reference(format = :iid) - raise ArgumentError, _('Unknown format') unless [:iid, :name].include?(format) - - if group_timebox? && format == :iid - raise ArgumentError, _('Cannot refer to a group %{timebox_type} by an internal id!') % { timebox_type: timebox_name } - end - - if format == :name && !name.include?('"') - %("#{name}") - else - iid - end - end - - # Timebox should be either a project timebox or a group timebox - def timebox_type_check - if group_id && project_id - field = project_id_changed? ? :project_id : :group_id - errors.add(field, _("%{timebox_name} should belong either to a project or a group.") % { timebox_name: timebox_name }) - end - end - def start_date_should_be_less_than_due_date if due_date <= start_date errors.add(:due_date, _("must be greater than start date")) diff --git a/app/models/iteration.rb b/app/models/iteration.rb index 71ecbcf1c1a..ed73793c78f 100644 --- a/app/models/iteration.rb +++ b/app/models/iteration.rb @@ -2,6 +2,12 @@ # Placeholder class for model that is implemented in EE class Iteration < ApplicationRecord + include IgnorableColumns + + # TODO https://gitlab.com/gitlab-org/gitlab/-/issues/372125 + # TODO https://gitlab.com/gitlab-org/gitlab/-/issues/372126 + ignore_column :project_id, remove_with: '15.6', remove_after: '2022-09-17' + self.table_name = 'sprints' def self.reference_prefix diff --git a/app/models/milestone.rb b/app/models/milestone.rb index ff4fadb0f13..da07d8dd9fc 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -1,11 +1,13 @@ # frozen_string_literal: true class Milestone < ApplicationRecord + include AtomicInternalId include Sortable include Timebox include Milestoneish include FromUnion include Importable + include IidRoutes prepend_mod_with('Milestone') # rubocop: disable Cop/InjectEnterpriseEditionModule @@ -13,6 +15,9 @@ class Milestone < ApplicationRecord ALL = [::Timebox::None, ::Timebox::Any, ::Timebox::Started, ::Timebox::Upcoming].freeze end + belongs_to :project + belongs_to :group + has_many :milestone_releases has_many :releases, through: :milestone_releases @@ -30,13 +35,28 @@ class Milestone < ApplicationRecord .order(:project_id, :group_id, :due_date) end + scope :of_projects, ->(ids) { where(project_id: ids) } + scope :for_projects, -> { where(group: nil).includes(:project) } + scope :for_projects_and_groups, -> (projects, groups) do + projects = projects.compact if projects.is_a? Array + projects = [] if projects.nil? + + groups = groups.compact if groups.is_a? Array + groups = [] if groups.nil? + + from_union([where(project_id: projects), where(group_id: groups)], remove_duplicates: false) + end + scope :order_by_name_asc, -> { order(Arel::Nodes::Ascending.new(arel_table[:title].lower)) } scope :reorder_by_due_date_asc, -> { reorder(arel_table[:due_date].asc.nulls_last) } scope :with_api_entity_associations, -> { preload(project: [:project_feature, :route, namespace: :route]) } scope :order_by_dates_and_title, -> { order(due_date: :asc, start_date: :asc, title: :asc) } + validates :group, presence: true, unless: :project + validates :project, presence: true, unless: :group validates :title, presence: true validates_associated :milestone_releases, message: -> (_, obj) { obj[:value].map(&:errors).map(&:full_messages).join(",") } + validate :parent_type_check validate :uniqueness_of_title, if: :title_changed? state_machine :state, initial: :active do @@ -176,10 +196,18 @@ class Milestone < ApplicationRecord # TODO: remove after all code paths use `timebox_id` # https://gitlab.com/gitlab-org/gitlab/-/issues/215688 alias_method :milestoneish_id, :timebox_id - # TODO: remove after all code paths use (group|project)_timebox? - # https://gitlab.com/gitlab-org/gitlab/-/issues/215690 - alias_method :group_milestone?, :group_timebox? - alias_method :project_milestone?, :project_timebox? + + def group_milestone? + group_id.present? + end + + def project_milestone? + project_id.present? + end + + def resource_parent + group || project + end def parent if group_milestone? @@ -193,8 +221,63 @@ class Milestone < ApplicationRecord group_milestone? && parent.subgroup? end + def merge_requests_enabled? + if group_milestone? + # Assume that groups have at least one project with merge requests enabled. + # Otherwise, we would need to load all of the projects from the database. + true + elsif project_milestone? + project&.merge_requests_enabled? + end + end + + ## + # Returns the String necessary to reference a milestone in Markdown. Group + # milestones only support name references, and do not support cross-project + # references. + # + # format - Symbol format to use (default: :iid, optional: :name) + # + # Examples: + # + # Milestone.first.to_reference # => "%1" + # Milestone.first.to_reference(cross_namespace_project) # => "gitlab-org/gitlab-foss%1" + # + def to_reference(from = nil, format: :name, full: false) + format_reference = timebox_format_reference(format) + reference = "#{self.class.reference_prefix}#{format_reference}" + + if project + "#{project.to_reference_base(from, full: full)}#{reference}" + else + reference + end + end + private + def timebox_format_reference(format = :iid) + raise ArgumentError, _('Unknown format') unless [:iid, :name].include?(format) + + if group_milestone? && format == :iid + raise ArgumentError, _('Cannot refer to a group milestone by an internal id!') + end + + if format == :name && !name.include?('"') + %("#{name}") + else + iid + end + end + + # Milestone should be either a project milestone or a group milestone + def parent_type_check + return unless group_id && project_id + + field = project_id_changed? ? :project_id : :group_id + errors.add(field, _("milestone should belong either to a project or a group.") % { timebox_name: timebox_name }) + end + def issues_finder_params { project_id: project_id, group_id: group_id, include_subgroups: group_id.present? }.compact end diff --git a/app/models/project.rb b/app/models/project.rb index fcf7f71aa75..88cecc4770d 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -263,7 +263,6 @@ class Project < ApplicationRecord has_many :integrations has_many :events has_many :milestones - has_many :iterations # Projects with a very large number of notes may time out destroying them # through the foreign key. Additionally, the deprecated attachment uploader diff --git a/app/models/user_detail.rb b/app/models/user_detail.rb index b9b69d12729..3787ad1c380 100644 --- a/app/models/user_detail.rb +++ b/app/models/user_detail.rb @@ -2,9 +2,6 @@ class UserDetail < ApplicationRecord extend ::Gitlab::Utils::Override - include IgnorableColumns - - ignore_columns :other_role, remove_after: '2022-07-22', remove_with: '15.3' REGISTRATION_OBJECTIVE_PAIRS = { basics: 0, move_repository: 1, code_storage: 2, exploring: 3, ci: 4, other: 5, joining_team: 6 }.freeze diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb index 6cefd9169f5..a848053ecaf 100644 --- a/app/services/merge_requests/base_service.rb +++ b/app/services/merge_requests/base_service.rb @@ -58,6 +58,7 @@ module MergeRequests new_reviewers = merge_request.reviewers - old_reviewers merge_request_activity_counter.track_users_review_requested(users: new_reviewers) merge_request_activity_counter.track_reviewers_changed_action(user: current_user) + GraphqlTriggers.merge_request_reviewers_updated(merge_request) end def cleanup_environments(merge_request) diff --git a/config/feature_flags/development/operational_vulnerabilities_filters.yml b/config/feature_flags/development/operational_vulnerabilities_filters.yml index 0a96954ef66..93206935a94 100644 --- a/config/feature_flags/development/operational_vulnerabilities_filters.yml +++ b/config/feature_flags/development/operational_vulnerabilities_filters.yml @@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365986 milestone: '15.2' type: development group: group::container security -default_enabled: false +default_enabled: true diff --git a/config/feature_flags/development/scan_execution_rule_mode.yml b/config/feature_flags/development/scan_execution_rule_mode.yml index 44c985d6814..6e3dd6acf92 100644 --- a/config/feature_flags/development/scan_execution_rule_mode.yml +++ b/config/feature_flags/development/scan_execution_rule_mode.yml @@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/359883 milestone: '15.2' type: development group: group::container security -default_enabled: false +default_enabled: true diff --git a/doc/api/groups.md b/doc/api/groups.md index 61f7a38d272..56f1b7f7d7e 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -125,13 +125,16 @@ GET /groups?custom_attributes[key]=value&custom_attributes[other_key]=other_valu ## List a group's subgroups -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15142) in GitLab 10.3. - Get a list of visible direct subgroups in this group. -When accessed without authentication, only public groups are returned. By default, this request returns 20 results at a time because the API results [are paginated](index.md#pagination). +If you request this list as: + +- An unauthenticated user, the response returns only public groups. +- An authenticated user, the response returns only the groups you're +a member of and does not include public groups. + Parameters: | Attribute | Type | Required | Description | diff --git a/doc/user/application_security/generate_test_vulnerabilities/index.md b/doc/user/application_security/generate_test_vulnerabilities/index.md index 11efedabff8..90cfc6f2147 100644 --- a/doc/user/application_security/generate_test_vulnerabilities/index.md +++ b/doc/user/application_security/generate_test_vulnerabilities/index.md @@ -7,22 +7,26 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Generate test vulnerabilities -You can generate test vulnerabilities when you work on the [Vulnerability Report](../vulnerability_report/index.md). +You can generate test vulnerabilities for the [Vulnerability Report](../vulnerability_report/index.md) to test GitLab +vulnerability management features without running a pipeline. +1. Login in to GitLab. 1. Go to `/-/profile/personal_access_tokens` and generate a personal access token with `api` permissions. 1. Go to your project page and find the project ID. You can find the project ID below the project title. -1. Open a terminal and go to the `gitlab/qa` directory. +1. [Clone the GitLab repository](../../../gitlab-basics/start-using-git.md#clone-a-repository) to your local machine. +1. Open a terminal and go to `gitlab/qa` directory. +1. Run `bundle install` 1. Run the following command: ```shell -GITLAB_QA_ACCESS_TOKEN=<your_personal_access_token> GITLAB_URL="http://localhost:3000" bundle exec rake vulnerabilities:setup\[<your_project_id>,<vulnerability_count>\] --trace +GITLAB_QA_ACCESS_TOKEN=<your_personal_access_token> GITLAB_URL="<address:port>" bundle exec rake vulnerabilities:setup\[<your_project_id>,<vulnerability_count>\] --trace ``` Make sure you do the following: - Replace `<your_personal_access_token>` with the token you generated in step one. -- Double check the `GITLAB_URL`. It should point to the running local instance. -- Replace `<your_project_id>` with the ID you obtained in step two. +- Double check the `GITLAB_URL`. It should point to address and port of your GitLab instance, for example `http://localhost:3000` if you are running GDK +- Replace `<your_project_id>` with the ID you obtained in step three above. - Replace `<vulnerability_count>` with the number of vulnerabilities you'd like to generate. -The script creates the specified amount of vulnerabilities in the project. +The script creates the specified number of placeholder vulnerabilities in the project. diff --git a/doc/user/project/insights/index.md b/doc/user/project/insights/index.md index 1107e91c33e..8e08d82c067 100644 --- a/doc/user/project/insights/index.md +++ b/doc/user/project/insights/index.md @@ -95,8 +95,9 @@ The following table lists the chart parameters: ### `title` -`title` is the title of the chart as it displays on the Insights page. -For example: +Use `title` to update the chart title. The title displays on the insights report. + +**Example:** ```yaml monthlyBugsCreated: @@ -105,8 +106,9 @@ monthlyBugsCreated: ### `description` -The `description` text is displayed above the chart, but below the title. It's used -to give extra details regarding the chart, for example: +Use `description` to add a description of the chart. The description displays above the chart, below the title. + +**Example:** ```yaml monthlyBugsCreated: @@ -116,33 +118,32 @@ monthlyBugsCreated: ### `type` -`type` is the chart type. +Use `type` to define the chart type. -For example: +**Supported values:** -```yaml -monthlyBugsCreated: - title: "Monthly bugs created" - type: bar -``` - -Supported values are: - -| Name | Example | +| Name | Example: | | ----- | ------- | | `bar` | ![Insights example bar chart](img/insights_example_bar_chart.png) | | `bar` (time series, that is when `group_by` is used) | ![Insights example bar time series chart](img/insights_example_bar_time_series_chart.png) | | `line` | ![Insights example stacked bar chart](img/insights_example_line_chart.png) | | `stacked-bar` | ![Insights example stacked bar chart](img/insights_example_stacked_bar_chart.png) | -NOTE: -The `dora` data source supports the `bar` and `line` chart types. +The `dora` data source supports the `bar` and `line` [chart types](#type). + +**Example:** + +```yaml +monthlyBugsCreated: + title: "Monthly bugs created" + type: bar +``` ### `query` -`query` allows to define the data source and various filtering conditions for the chart. +Use `query` to define the data source and filtering conditions for the chart. -Example: +**Example:** ```yaml monthlyBugsCreated: @@ -190,46 +191,46 @@ monthlyBugsCreated: > [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in GitLab 15.3. -The `data_source` parameter was introduced to allow visualizing data from different data sources. +Use `data_source` to define the data source that exposes the data. -Supported values are: +**Supported values:** - `issuables`: Exposes merge request or issue data. -- `dora`: Exposes DORA metrics data. +- `dora`: Exposes DORA metrics. -#### `Issuable` query parameters +#### `issuable` query parameters ##### `query.params.issuable_type` -Defines the type of "issuable" you want to create a chart for. +Use `query.params.issuable_type` to define the type of issuable to create a chart for. -Supported values are: +**Supported values:** - `issue`: The chart displays issues' data. - `merge_request`: The chart displays merge requests' data. ##### `query.params.issuable_state` -Filter by the current state of the queried "issuable". +Use `query.params.issuable_state` to filter by the current state of the queried issuable. By default, the `opened` state filter is applied. -Supported values are: +**Supported values:** -- `opened`: Open issues / merge requests. -- `closed`: Closed Open issues / merge requests. -- `locked`: Issues / merge requests that have their discussion locked. +- `opened`: Open issues or merge requests. +- `closed`: Closed issues or merge requests. +- `locked`: Issues or merge requests that have their discussion locked. - `merged`: Merged merge requests. -- `all`: Issues / merge requests in all states +- `all`: Issues or merge requests in all states. ##### `query.params.filter_labels` -Filter by labels currently applied to the queried "issuable". +Use `query.params.filter_labels` to filter by labels applied to the queried issuable. -By default, no labels filter is applied. All the defined labels must be -currently applied to the "issuable" in order for it to be selected. +By default, no label filter is applied. All defined labels must +be applied to the issuable for it to be selected. -Example: +**Example:**: ```yaml monthlyBugsCreated: @@ -247,12 +248,13 @@ monthlyBugsCreated: ##### `query.params.collection_labels` -Group "issuable" by the configured labels. +Use `query.params.collection_labels` to group issuables by the configured labels. +Grouping is not applied by default. -By default, no grouping is done. When using this keyword, you need to -set `type` to either `line` or `stacked-bar`. +When using this parameter, you must +set `type` to `line` or `stacked-bar`. -Example: +**Example:** ```yaml weeklyBugsBySeverity: @@ -274,9 +276,9 @@ weeklyBugsBySeverity: ##### `query.group_by` -Define the X-axis of your chart. +Use `query.group_by` to define the X-axis of the chart. -Supported values are: +**Supported values:** - `day`: Group data per day. - `week`: Group data per week. @@ -284,11 +286,10 @@ Supported values are: ##### `query.period_limit` -Define how far "issuables" are queried in the past (using the `query.period_field`). +Use `query.period_limit` to define how far back in time to query issuables (using the `query.period_field`). -The unit is related to the `query.group_by` you defined. For instance if you -defined `query.group_by: 'day'` then `query.period_limit: 365` would mean -"Gather and display data for the last 365 days". +The unit is related to the value defined in `query.group_by`. For example, if you +defined `query.group_by: 'day'`, and `query.period_limit: 365`, the chart displays data from the last 365 days. By default, default values are applied depending on the `query.group_by` you defined. @@ -301,9 +302,9 @@ you defined. #### `query.period_field` -Define the timestamp field used to group "issuables". +Use `query.period_field` to define the timestamp field by which to group issuables. -Supported values are: +**Supported values:** - `created_at` (default): Group data using the `created_at` field. - `closed_at`: Group data using the `closed_at` field (for issues only). @@ -323,7 +324,9 @@ you may see `created_at` in place of `merged_at`. `created_at` is used instead. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/367248) in GitLab 15.3. -An example DORA chart definition: +Use DORA-specific queries with the `dora` data source to create a DORA chart definition. + +**Example:** ```yaml dora: @@ -355,53 +358,59 @@ dora: ##### `query.metric` -Defines which DORA metric to query. The available values are: +Use `query.metric` to define the [DORA metrics](../../../api/dora/metrics.md#the-value-field) to query. + +**Supported values:** - `deployment_frequency` (default) - `lead_time_for_changes` - `time_to_restore_service` - `change_failure_rate` -The metrics are described on the [DORA API](../../../api/dora/metrics.md#the-value-field) page. - ##### `query.group_by` -Define the X-axis of your chart. +Use `query.group_by` to define the X-axis of your chart. -Supported values are: +**Supported values:** - `day` (default): Group data per day. - `month`: Group data per month. ##### `query.period_limit` -Define how far the metrics are queried in the past (default: 15). Maximum lookback period is 180 days or 6 months. +Use `query.period_limit` to define how far the metrics are queried in the past (default: 15). The maximum period is 180 days or 6 months. ##### `query.environment_tiers` -An array of environments to include into the calculation (default: production). Available options: `production`, `staging`, `testing`, `development`, `other`. +Use `query.environment_tiers` to define an array of environments to include the calculation. + +**Supported values:** + +- `production`(default) +- `staging` +- `testing` +- `development` +- `other` ### `projects` -You can limit where the "issuables" can be queried from: +Use `projects` to limit where issuables are queried from: -- If `.gitlab/insights.yml` is used for a [group's insights](../../group/insights/index.md#configure-your-insights), with `projects`, you can limit the projects to be queried. By default, all projects currently under the group are used. -- If `.gitlab/insights.yml` is used for a project's insights, specifying any other projects yields no results. By default, the project itself is used. +- If `.gitlab/insights.yml` is used for a [group's insights](../../group/insights/index.md#configure-your-insights), use `projects` to define the projects from which to query issuables. By default, all projects under the group are used. +- If `.gitlab/insights.yml` is used for a project's insights, specifying other projects does not yield results. By default, the project is used. #### `projects.only` -The `projects.only` option specifies the projects which the "issuables" -should be queried from. +Use `projects.only` to specify the projects from which issuables +are queried. -Projects listed here are ignored when: +Projects listed in this parameter are ignored when: - They don't exist. - The current user doesn't have sufficient permissions to read them. -- They are outside of the group. +- They are outside the group. -In the following `insights.yml` example, we specify the projects -the queries are used on. This example is useful when setting -a group's insights: +**Example:** ```yaml monthlyBugsCreated: @@ -423,7 +432,7 @@ monthlyBugsCreated: - groupB/project # Projects outside the group will be ignored ``` -## Complete example +## Complete insights configuration example ```yaml .projectsOnly: &projectsOnly diff --git a/jest.config.base.js b/jest.config.base.js index b631c2009d9..a6c22a8877c 100644 --- a/jest.config.base.js +++ b/jest.config.base.js @@ -174,7 +174,7 @@ module.exports = (path, options = {}) => { restoreMocks: true, slowTestThreshold: process.env.CI ? 6000 : 500, transform: { - '^.+\\.(gql|graphql)$': 'jest-transform-graphql', + '^.+\\.(gql|graphql)$': './spec/frontend/__helpers__/graphql_transformer.js', '^.+_worker\\.js$': './spec/frontend/__helpers__/web_worker_transformer.js', '^.+\\.js$': 'babel-jest', '^.+\\.vue$': '@vue/vue2-jest', diff --git a/locale/gitlab.pot b/locale/gitlab.pot index f291aa69443..291644836db 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -1101,9 +1101,6 @@ msgstr "" msgid "%{text} is available" msgstr "" -msgid "%{timebox_name} should belong either to a project or a group." -msgstr "" - msgid "%{timebox_type} does not support burnup charts" msgstr "" @@ -7578,7 +7575,7 @@ msgstr "" msgid "Cannot promote issue due to insufficient permissions." msgstr "" -msgid "Cannot refer to a group %{timebox_type} by an internal id!" +msgid "Cannot refer to a group milestone by an internal id!" msgstr "" msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above." @@ -47595,9 +47592,6 @@ msgstr "" msgid "is not allowed. Please use your regular email address." msgstr "" -msgid "is not allowed. We do not currently support project-level iterations" -msgstr "" - msgid "is not in the group enforcing Group Managed Account" msgstr "" @@ -47730,6 +47724,9 @@ msgstr "" msgid "metric_id must be unique across a project" msgstr "" +msgid "milestone should belong either to a project or a group." +msgstr "" + msgid "missing" msgstr "" diff --git a/package.json b/package.json index 4d13824ae9c..9083678d9db 100644 --- a/package.json +++ b/package.json @@ -236,7 +236,6 @@ "jest-jasmine2": "^27.5.1", "jest-junit": "^12.0.0", "jest-raw-loader": "^1.0.1", - "jest-transform-graphql": "^2.1.0", "jest-util": "^27.5.1", "jsonlint": "^1.6.3", "markdownlint-cli": "0.32.2", diff --git a/spec/features/issues/related_issues_spec.rb b/spec/features/issues/related_issues_spec.rb index 818e99f2ec9..62127295a7c 100644 --- a/spec/features/issues/related_issues_spec.rb +++ b/spec/features/issues/related_issues_spec.rb @@ -3,42 +3,41 @@ require 'spec_helper' RSpec.describe 'Related issues', :js do - let(:user) { create(:user) } - let(:project) { create(:project_empty_repo, :public) } - let(:project_b) { create(:project_empty_repo, :public) } - let(:project_unauthorized) { create(:project_empty_repo, :public) } - let(:issue_a) { create(:issue, project: project) } - let(:issue_b) { create(:issue, project: project) } - let(:issue_c) { create(:issue, project: project) } - let(:issue_d) { create(:issue, project: project) } - let(:issue_project_b_a) { create(:issue, project: project_b) } - let(:issue_project_unauthorized_a) { create(:issue, project: project_unauthorized) } + let_it_be(:user) { create(:user) } + + let_it_be(:project) { create(:project_empty_repo, :public) } + let_it_be(:project_b) { create(:project_empty_repo, :public) } + let_it_be(:project_unauthorized) { create(:project_empty_repo, :public) } + let_it_be(:internal_project) { create(:project_empty_repo, :internal) } + let_it_be(:private_project) { create(:project_empty_repo, :private) } + let_it_be(:public_project) { create(:project_empty_repo, :public) } + + let_it_be(:issue_a) { create(:issue, project: project) } + let_it_be(:issue_b) { create(:issue, project: project) } + let_it_be(:issue_c) { create(:issue, project: project) } + let_it_be(:issue_d) { create(:issue, project: project) } + let_it_be(:issue_project_b_a) { create(:issue, project: project_b) } + let_it_be(:issue_project_unauthorized_a) { create(:issue, project: project_unauthorized) } + let_it_be(:internal_issue) { create(:issue, project: internal_project) } + let_it_be(:private_issue) { create(:issue, project: private_project) } + let_it_be(:public_issue) { create(:issue, project: public_project) } context 'widget visibility' do context 'when not logged in' do it 'does not show widget when internal project' do - project = create :project_empty_repo, :internal - issue = create :issue, project: project - - visit project_issue_path(project, issue) + visit project_issue_path(internal_project, internal_issue) expect(page).not_to have_css('.related-issues-block') end it 'does not show widget when private project' do - project = create :project_empty_repo, :private - issue = create :issue, project: project - - visit project_issue_path(project, issue) + visit project_issue_path(private_project, private_issue) expect(page).not_to have_css('.related-issues-block') end it 'shows widget when public project' do - project = create :project_empty_repo, :public - issue = create :issue, project: project - - visit project_issue_path(project, issue) + visit project_issue_path(public_project, public_issue) expect(page).to have_css('.related-issues-block') expect(page).not_to have_button 'Add a related issue' @@ -51,39 +50,29 @@ RSpec.describe 'Related issues', :js do end it 'shows widget when internal project' do - project = create :project_empty_repo, :internal - issue = create :issue, project: project - - visit project_issue_path(project, issue) + visit project_issue_path(internal_project, internal_issue) expect(page).to have_css('.related-issues-block') expect(page).not_to have_button 'Add a related issue' end it 'does not show widget when private project' do - project = create :project_empty_repo, :private - issue = create :issue, project: project - - visit project_issue_path(project, issue) + visit project_issue_path(private_project, private_issue) expect(page).not_to have_css('.related-issues-block') end it 'shows widget when public project' do - project = create :project_empty_repo, :public - issue = create :issue, project: project - - visit project_issue_path(project, issue) + visit project_issue_path(public_project, public_issue) expect(page).to have_css('.related-issues-block') expect(page).not_to have_button 'Add a related issue' end it 'shows widget on their own public issue' do - project = create :project_empty_repo, :public - issue = create :issue, project: project, author: user + issue = create :issue, project: public_project, author: user - visit project_issue_path(project, issue) + visit project_issue_path(public_project, issue) expect(page).to have_css('.related-issues-block') expect(page).not_to have_button 'Add a related issue' @@ -96,33 +85,27 @@ RSpec.describe 'Related issues', :js do end it 'shows widget when internal project' do - project = create :project_empty_repo, :internal - issue = create :issue, project: project - project.add_guest(user) + internal_project.add_guest(user) - visit project_issue_path(project, issue) + visit project_issue_path(internal_project, internal_issue) expect(page).to have_css('.related-issues-block') expect(page).not_to have_button 'Add a related issue' end it 'shows widget when private project' do - project = create :project_empty_repo, :private - issue = create :issue, project: project - project.add_guest(user) + private_project.add_guest(user) - visit project_issue_path(project, issue) + visit project_issue_path(private_project, private_issue) expect(page).to have_css('.related-issues-block') expect(page).not_to have_button 'Add a related issue' end it 'shows widget when public project' do - project = create :project_empty_repo, :public - issue = create :issue, project: project - project.add_guest(user) + public_project.add_guest(user) - visit project_issue_path(project, issue) + visit project_issue_path(public_project, public_issue) expect(page).to have_css('.related-issues-block') expect(page).not_to have_button 'Add a related issue' @@ -135,44 +118,37 @@ RSpec.describe 'Related issues', :js do end it 'shows widget when internal project' do - project = create :project_empty_repo, :internal - issue = create :issue, project: project - project.add_reporter(user) + internal_project.add_reporter(user) - visit project_issue_path(project, issue) + visit project_issue_path(internal_project, internal_issue) expect(page).to have_css('.related-issues-block') expect(page).to have_button 'Add a related issue' end it 'shows widget when private project' do - project = create :project_empty_repo, :private - issue = create :issue, project: project - project.add_reporter(user) + private_project.add_reporter(user) - visit project_issue_path(project, issue) + visit project_issue_path(private_project, private_issue) expect(page).to have_css('.related-issues-block') expect(page).to have_button 'Add a related issue' end it 'shows widget when public project' do - project = create :project_empty_repo, :public - issue = create :issue, project: project - project.add_reporter(user) + public_project.add_reporter(user) - visit project_issue_path(project, issue) + visit project_issue_path(public_project, public_issue) expect(page).to have_css('.related-issues-block') expect(page).to have_button 'Add a related issue' end it 'shows widget on their own public issue' do - project = create :project_empty_repo, :public - issue = create :issue, project: project, author: user - project.add_reporter(user) + issue = create :issue, project: public_project, author: user + public_project.add_reporter(user) - visit project_issue_path(project, issue) + visit project_issue_path(public_project, issue) expect(page).to have_css('.related-issues-block') expect(page).to have_button 'Add a related issue' @@ -184,8 +160,11 @@ RSpec.describe 'Related issues', :js do let!(:issue_link_b) { create :issue_link, source: issue_a, target: issue_b } let!(:issue_link_c) { create :issue_link, source: issue_a, target: issue_c } - before do + before_all do project.add_guest(user) + end + + before do sign_in(user) end @@ -213,9 +192,12 @@ RSpec.describe 'Related issues', :js do end context 'when user has permission to manage related issues' do - before do + before_all do project.add_maintainer(user) project_b.add_maintainer(user) + end + + before do sign_in(user) end diff --git a/spec/features/projects/ci/lint_spec.rb b/spec/features/projects/ci/lint_spec.rb index 608511ae5a5..8d5f62d8a06 100644 --- a/spec/features/projects/ci/lint_spec.rb +++ b/spec/features/projects/ci/lint_spec.rb @@ -5,13 +5,16 @@ require 'spec_helper' RSpec.describe 'CI Lint', :js do include Spec::Support::Helpers::Features::SourceEditorSpecHelpers - let(:project) { create(:project, :repository) } - let(:user) { create(:user) } + let_it_be(:project) { create(:project, :repository) } + let_it_be(:user) { create(:user) } let(:content_selector) { '.content .view-lines' } - before do + before_all do project.add_developer(user) + end + + before do sign_in(user) visit project_ci_lint_path(project) diff --git a/spec/frontend/__helpers__/graphql_transformer.js b/spec/frontend/__helpers__/graphql_transformer.js new file mode 100644 index 00000000000..e776e2ea6ac --- /dev/null +++ b/spec/frontend/__helpers__/graphql_transformer.js @@ -0,0 +1,8 @@ +/* eslint-disable import/no-commonjs */ +const loader = require('graphql-tag/loader'); + +module.exports = { + process(src) { + return loader.call({ cacheable() {} }, src); + }, +}; diff --git a/spec/graphql/graphql_triggers_spec.rb b/spec/graphql/graphql_triggers_spec.rb index 4d155a6c5f0..0de287370ba 100644 --- a/spec/graphql/graphql_triggers_spec.rb +++ b/spec/graphql/graphql_triggers_spec.rb @@ -75,4 +75,18 @@ RSpec.describe GraphqlTriggers do GraphqlTriggers.issuable_dates_updated(work_item) end end + + describe '.merge_request_reviewers_updated' do + it 'triggers the mergeRequestReviewersUpdated subscription' do + merge_request = build_stubbed(:merge_request) + + expect(GitlabSchema.subscriptions).to receive(:trigger).with( + 'mergeRequestReviewersUpdated', + { issuable_id: merge_request.to_gid }, + merge_request + ).and_call_original + + GraphqlTriggers.merge_request_reviewers_updated(merge_request) + end + end end diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb index af1383b68bf..9f6b1f8016b 100644 --- a/spec/models/milestone_spec.rb +++ b/spec/models/milestone_spec.rb @@ -5,9 +5,35 @@ require 'spec_helper' RSpec.describe Milestone do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, :public) } + let_it_be(:group) { create(:group) } let_it_be(:issue) { create(:issue, project: project) } + describe 'modules' do + context 'with a project' do + it_behaves_like 'AtomicInternalId' do + let(:internal_id_attribute) { :iid } + let(:instance) { build(:milestone, project: create(:project), group: nil) } + let(:scope) { :project } + let(:scope_attrs) { { project: instance.project } } + let(:usage) { :milestones } + end + end + + context 'with a group' do + it_behaves_like 'AtomicInternalId' do + let(:internal_id_attribute) { :iid } + let(:instance) { build(:milestone, project: nil, group: create(:group)) } + let(:scope) { :group } + let(:scope_attrs) { { namespace: instance.group } } + let(:usage) { :milestones } + end + end + end + it_behaves_like 'a timebox', :milestone do + let(:project) { create(:project, :public) } + let(:timebox) { create(:milestone, project: project) } + describe "#uniqueness_of_title" do context "per project" do it "does not accept the same title in a project twice" do @@ -25,7 +51,7 @@ RSpec.describe Milestone do end context "per group" do - let(:timebox) { create(:milestone, *timebox_args, group: group) } + let(:timebox) { create(:milestone, group: group) } before do project.update!(group: group) @@ -96,9 +122,22 @@ RSpec.describe Milestone do end end end + + describe '#parent_type_check' do + let(:milestone) { build(:milestone, group: group) } + + it 'is invalid if it has both project_id and group_id' do + milestone.project = project + + expect(milestone).not_to be_valid + expect(milestone.errors[:project_id]).to include("milestone should belong either to a project or a group.") + end + end end describe "Associations" do + it { is_expected.to belong_to(:project) } + it { is_expected.to belong_to(:group) } it { is_expected.to have_many(:releases) } it { is_expected.to have_many(:milestone_releases) } end @@ -562,6 +601,57 @@ RSpec.describe Milestone do it { is_expected.not_to match("gitlab-org/gitlab-ce/milestones/123") } end + describe '#merge_requests_enabled?' do + context "per project" do + it "is true for projects with MRs enabled" do + project = create(:project, :merge_requests_enabled) + milestone = build(:milestone, project: project) + + expect(milestone.merge_requests_enabled?).to be_truthy + end + + it "is false for projects with MRs disabled" do + project = create(:project, :repository_enabled, :merge_requests_disabled) + milestone = build(:milestone, project: project) + + expect(milestone.merge_requests_enabled?).to be_falsey + end + + it "is false for projects with repository disabled" do + project = create(:project, :repository_disabled) + milestone = build(:milestone, project: project) + + expect(milestone.merge_requests_enabled?).to be_falsey + end + end + + context "per group" do + let(:milestone) { build(:milestone, group: group) } + + it "is always true for groups, for performance reasons" do + expect(milestone.merge_requests_enabled?).to be_truthy + end + end + end + + describe '#resource_parent' do + context 'when group is present' do + let(:milestone) { build(:milestone, group: group) } + + it 'returns the group' do + expect(milestone.resource_parent).to eq(group) + end + end + + context 'when project is present' do + let(:milestone) { build(:milestone, project: project) } + + it 'returns the project' do + expect(milestone.resource_parent).to eq(project) + end + end + end + describe '#parent' do context 'with group' do it 'returns the expected parent' do @@ -598,4 +688,40 @@ RSpec.describe Milestone do end end end + + describe '#project_milestone?' do + context 'when project_id is present' do + let(:milestone) { build(:milestone, project: project) } + + it 'returns true' do + expect(milestone.project_milestone?).to be_truthy + end + end + + context 'when project_id is not present' do + let(:milestone) { build(:milestone, group: group) } + + it 'returns false' do + expect(milestone.project_milestone?).to be_falsey + end + end + end + + describe '#group_milestone?' do + context 'when group_id is present' do + let(:milestone) { build(:milestone, group: group) } + + it 'returns true' do + expect(milestone.group_milestone?).to be_truthy + end + end + + context 'when group_id is not present' do + let(:milestone) { build(:milestone, project: project) } + + it 'returns false' do + expect(milestone.group_milestone?).to be_falsey + end + end + end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 6c85c66c6eb..20e8245dc2e 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -28,7 +28,6 @@ RSpec.describe Project, factory_default: :keep do it { is_expected.to have_many(:issues) } it { is_expected.to have_many(:incident_management_issuable_escalation_statuses).through(:issues).inverse_of(:project).class_name('IncidentManagement::IssuableEscalationStatus') } it { is_expected.to have_many(:milestones) } - it { is_expected.to have_many(:iterations) } it { is_expected.to have_many(:project_members).dependent(:delete_all) } it { is_expected.to have_many(:users).through(:project_members) } it { is_expected.to have_many(:requesters).dependent(:delete_all) } diff --git a/spec/services/merge_requests/update_reviewers_service_spec.rb b/spec/services/merge_requests/update_reviewers_service_spec.rb index 8920141adbb..96824ea6974 100644 --- a/spec/services/merge_requests/update_reviewers_service_spec.rb +++ b/spec/services/merge_requests/update_reviewers_service_spec.rb @@ -128,6 +128,12 @@ RSpec.describe MergeRequests::UpdateReviewersService do set_reviewers end + it 'triggers graphql subscription mergeRequestReviewersUpdated' do + expect(GraphqlTriggers).to receive(:merge_request_reviewers_updated).with(merge_request) + + set_reviewers + end + it 'calls MergeRequest::ResolveTodosService#async_execute' do expect_next_instance_of(MergeRequests::ResolveTodosService, merge_request, user) do |service| expect(service).to receive(:async_execute) @@ -149,6 +155,16 @@ RSpec.describe MergeRequests::UpdateReviewersService do set_reviewers end + context 'when reviewers did not change' do + let(:opts) { { reviewer_ids: merge_request.reviewer_ids } } + + it 'does not trigger graphql subscription mergeRequestReviewersUpdated' do + expect(GraphqlTriggers).not_to receive(:merge_request_reviewers_updated) + + set_reviewers + end + end + it 'does not update the reviewers if they do not have access' do opts[:reviewer_ids] = [create(:user).id] diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index 5d76fb051f2..473b7fa8f17 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -711,6 +711,20 @@ RSpec.describe MergeRequests::UpdateService, :mailer do expect(user2.review_requested_open_merge_requests_count).to eq(1) expect(user3.review_requested_open_merge_requests_count).to eq(0) end + + it 'triggers graphql subscription mergeRequestReviewersUpdated' do + expect(GraphqlTriggers).to receive(:merge_request_reviewers_updated).with(merge_request) + + update_merge_request({ reviewer_ids: [user2.id] }) + end + end + + context 'when reviewers did not change' do + it 'does not trigger graphql subscription mergeRequestReviewersUpdated' do + expect(GraphqlTriggers).not_to receive(:merge_request_reviewers_updated) + + update_merge_request({ reviewer_ids: [merge_request.reviewer_ids] }) + end end context 'when the milestone is removed' do diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml index d2e9313f660..b3b2376c1a8 100644 --- a/spec/support/rspec_order_todo.yml +++ b/spec/support/rspec_order_todo.yml @@ -3263,12 +3263,10 @@ - './ee/spec/services/users_ops_dashboard_projects/destroy_service_spec.rb' - './ee/spec/services/users/update_highest_member_role_service_spec.rb' - './ee/spec/services/vulnerabilities/confirm_service_spec.rb' -- './ee/spec/services/vulnerabilities/create_from_security_finding_service_spec.rb' - './ee/spec/services/vulnerabilities/create_service_spec.rb' - './ee/spec/services/vulnerabilities/destroy_dismissal_feedback_service_spec.rb' - './ee/spec/services/vulnerabilities/dismiss_service_spec.rb' - './ee/spec/services/vulnerabilities/finding_dismiss_service_spec.rb' -- './ee/spec/services/vulnerabilities/findings/create_from_security_finding_service_spec.rb' - './ee/spec/services/vulnerabilities/historical_statistics/adjustment_service_spec.rb' - './ee/spec/services/vulnerabilities/historical_statistics/deletion_service_spec.rb' - './ee/spec/services/vulnerabilities/manually_create_service_spec.rb' diff --git a/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb b/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb index d06e8391a9a..e4958779957 100644 --- a/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb +++ b/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb @@ -1,10 +1,7 @@ # frozen_string_literal: true RSpec.shared_examples 'a timebox' do |timebox_type| - let(:project) { create(:project, :public) } - let(:group) { create(:group) } let(:timebox_args) { [] } - let(:timebox) { create(timebox_type, *timebox_args, project: project) } let(:issue) { create(:issue, project: project) } let(:user) { create(:user) } let(:timebox_table_name) { timebox_type.to_s.pluralize.to_sym } @@ -14,28 +11,6 @@ RSpec.shared_examples 'a timebox' do |timebox_type| let(:open_on_left) { nil } let(:open_on_right) { nil } - describe 'modules' do - context 'with a project' do - it_behaves_like 'AtomicInternalId' do - let(:internal_id_attribute) { :iid } - let(:instance) { build(timebox_type, *timebox_args, project: create(:project), group: nil) } - let(:scope) { :project } - let(:scope_attrs) { { project: instance.project } } - let(:usage) { timebox_table_name } - end - end - - context 'with a group' do - it_behaves_like 'AtomicInternalId' do - let(:internal_id_attribute) { :iid } - let(:instance) { build(timebox_type, *timebox_args, project: nil, group: create(:group)) } - let(:scope) { :group } - let(:scope_attrs) { { namespace: instance.group } } - let(:usage) { timebox_table_name } - end - end - end - describe "Validation" do before do allow(subject).to receive(:set_iid).and_return(false) @@ -65,21 +40,9 @@ RSpec.shared_examples 'a timebox' do |timebox_type| expect(timebox.errors[:due_date]).to include("date must not be after 9999-12-31") end end - - describe '#timebox_type_check' do - it 'is invalid if it has both project_id and group_id' do - timebox = build(timebox_type, *timebox_args, group: group) - timebox.project = project - - expect(timebox).not_to be_valid - expect(timebox.errors[:project_id]).to include("#{timebox_type} should belong either to a project or a group.") - end - end end describe "Associations" do - it { is_expected.to belong_to(:project) } - it { is_expected.to belong_to(:group) } it { is_expected.to have_many(:issues) } it { is_expected.to have_many(:merge_requests) } it { is_expected.to have_many(:labels).through(:issues) } @@ -91,38 +54,6 @@ RSpec.shared_examples 'a timebox' do |timebox_type| end end - describe '#project_timebox?' do - context 'when project_id is present' do - it 'returns true' do - expect(timebox.project_timebox?).to be_truthy - end - end - - context 'when project_id is not present' do - let(:timebox) { build(timebox_type, *timebox_args, group: group) } - - it 'returns false' do - expect(timebox.project_timebox?).to be_falsey - end - end - end - - describe '#group_timebox?' do - context 'when group_id is present' do - let(:timebox) { build(timebox_type, *timebox_args, group: group) } - - it 'returns true' do - expect(timebox.group_timebox?).to be_truthy - end - end - - context 'when group_id is not present' do - it 'returns false' do - expect(timebox.group_timebox?).to be_falsey - end - end - end - describe '#safe_title' do let(:timebox) { create(timebox_type, *timebox_args, title: "<b>foo & bar -> 2.2</b>") } @@ -131,22 +62,6 @@ RSpec.shared_examples 'a timebox' do |timebox_type| end end - describe '#resource_parent' do - context 'when group is present' do - let(:timebox) { build(timebox_type, *timebox_args, group: group) } - - it 'returns the group' do - expect(timebox.resource_parent).to eq(group) - end - end - - context 'when project is present' do - it 'returns the project' do - expect(timebox.resource_parent).to eq(project) - end - end - end - describe "#title" do let(:timebox) { create(timebox_type, *timebox_args, title: "<b>foo & bar -> 2.2</b>") } @@ -155,39 +70,6 @@ RSpec.shared_examples 'a timebox' do |timebox_type| end end - describe '#merge_requests_enabled?' do - context "per project" do - it "is true for projects with MRs enabled" do - project = create(:project, :merge_requests_enabled) - timebox = create(timebox_type, *timebox_args, project: project) - - expect(timebox.merge_requests_enabled?).to be_truthy - end - - it "is false for projects with MRs disabled" do - project = create(:project, :repository_enabled, :merge_requests_disabled) - timebox = create(timebox_type, *timebox_args, project: project) - - expect(timebox.merge_requests_enabled?).to be_falsey - end - - it "is false for projects with repository disabled" do - project = create(:project, :repository_disabled) - timebox = create(timebox_type, *timebox_args, project: project) - - expect(timebox.merge_requests_enabled?).to be_falsey - end - end - - context "per group" do - let(:timebox) { create(timebox_type, *timebox_args, group: group) } - - it "is always true for groups, for performance reasons" do - expect(timebox.merge_requests_enabled?).to be_truthy - end - end - end - describe '#to_ability_name' do it 'returns timebox' do timebox = build(timebox_type, *timebox_args) diff --git a/yarn.lock b/yarn.lock index 0614b2285a3..a6b5192a8ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7578,11 +7578,6 @@ jest-snapshot@^27.5.1: pretty-format "^27.5.1" semver "^7.3.2" -jest-transform-graphql@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/jest-transform-graphql/-/jest-transform-graphql-2.1.0.tgz#903cb66bb27bc2772fd3e5dd4f7e9b57230f5829" - integrity sha1-kDy2a7J7wncv0+XdT36bVyMPWCk= - jest-util@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" |