diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-01 03:09:59 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-01 03:09:59 +0300 |
commit | 3795b229ab9d63846002ebb9b95073c3cbf5ab98 (patch) | |
tree | cb407d4e4d2d6a1b2f1f3f5850dccfe423eed302 | |
parent | 3aeda4e6146bea1920c3283e98b01ca4fcf796a8 (diff) |
Add latest changes from gitlab-org/gitlab@master
83 files changed, 549 insertions, 409 deletions
diff --git a/app/models/concerns/timebox.rb b/app/models/concerns/timebox.rb new file mode 100644 index 00000000000..7b518d3dda3 --- /dev/null +++ b/app/models/concerns/timebox.rb @@ -0,0 +1,139 @@ +# frozen_string_literal: true + +module Timebox + extend ActiveSupport::Concern + + include AtomicInternalId + include CacheMarkdownField + include IidRoutes + include StripAttribute + + included do + alias_method :timebox_id, :id + + validates :group, presence: true, unless: :project + validates :project, presence: true, unless: :group + validates :title, presence: true + + validate :uniqueness_of_title, if: :title_changed? + 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 + + 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 :active, -> { with_state(:active) } + scope :closed, -> { with_state(:closed) } + 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? + + where(project_id: projects).or(where(group_id: groups)) + end + + scope :within_timeframe, -> (start_date, end_date) do + where('start_date is not NULL or due_date is not NULL') + .where('start_date is NULL or start_date <= ?', end_date) + .where('due_date is NULL or due_date >= ?', start_date) + end + + strip_attributes :title + + alias_attribute :name, :title + end + + def title=(value) + write_attribute(:title, sanitize_title(value)) if value.present? + end + + def timebox_name + 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 + end + + def to_ability_name + model_name.singular + 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 + end + + private + + # Timebox titles must be unique across project and group timeboxes + def uniqueness_of_title + if project + relation = self.class.for_projects_and_groups([project_id], [project.group&.id]) + elsif group + relation = self.class.for_projects_and_groups(group.projects.select(:id), [group.id]) + end + + title_exists = relation.find_by_title(title) + errors.add(:title, _("already being used for another group or project %{timebox_name}.") % { timebox_name: timebox_name }) if title_exists + 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")) + end + end + + def dates_within_4_digits + if start_date && start_date > Date.new(9999, 12, 31) + errors.add(:start_date, _("date must not be after 9999-12-31")) + end + + if due_date && due_date > Date.new(9999, 12, 31) + errors.add(:due_date, _("date must not be after 9999-12-31")) + end + end + + def sanitize_title(value) + CGI.unescape_html(Sanitize.clean(value.to_s)) + end +end diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb index d0cec0e9fc6..34c8d19ba46 100644 --- a/app/models/global_milestone.rb +++ b/app/models/global_milestone.rb @@ -11,7 +11,7 @@ class GlobalMilestone delegate :title, :state, :due_date, :start_date, :participants, :project, :group, :expires_at, :closed?, :iid, :group_milestone?, :safe_title, - :milestoneish_id, :resource_parent, :releases, to: :milestone + :timebox_id, :milestoneish_id, :resource_parent, :releases, to: :milestone def to_hash { diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 4ccfe314526..d37e86cd3d9 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -15,12 +15,9 @@ class Milestone < ApplicationRecord Upcoming = MilestoneStruct.new('Upcoming', '#upcoming', -2) Started = MilestoneStruct.new('Started', '#started', -3) - include CacheMarkdownField - include AtomicInternalId - include IidRoutes include Sortable include Referable - include StripAttribute + include Timebox include Milestoneish include FromUnion include Importable @@ -28,61 +25,21 @@ class Milestone < ApplicationRecord prepend_if_ee('::EE::Milestone') # rubocop: disable Cop/InjectEnterpriseEditionModule - cache_markdown_field :title, pipeline: :single_line - cache_markdown_field :description - - belongs_to :project - belongs_to :group - has_many :milestone_releases has_many :releases, through: :milestone_releases has_internal_id :iid, scope: :project, track_if: -> { !importing? }, init: ->(s) { s&.project&.milestones&.maximum(:iid) } has_internal_id :iid, scope: :group, track_if: -> { !importing? }, init: ->(s) { s&.group&.milestones&.maximum(:iid) } - has_many :issues - has_many :labels, -> { distinct.reorder('labels.title') }, through: :issues - has_many :merge_requests has_many :events, as: :target, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent - scope :of_projects, ->(ids) { where(project_id: ids) } - scope :of_groups, ->(ids) { where(group_id: ids) } - scope :active, -> { with_state(:active) } - scope :closed, -> { with_state(:closed) } - scope :for_projects, -> { where(group: nil).includes(:project) } scope :started, -> { active.where('milestones.start_date <= CURRENT_DATE') } - 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? - - where(project_id: projects).or(where(group_id: groups)) - end - - scope :within_timeframe, -> (start_date, end_date) do - where('start_date is not NULL or due_date is not NULL') - .where('start_date is NULL or start_date <= ?', end_date) - .where('due_date is NULL or due_date >= ?', start_date) - end - scope :order_by_name_asc, -> { order(Arel::Nodes::Ascending.new(arel_table[:title].lower)) } scope :reorder_by_due_date_asc, -> { reorder(Gitlab::Database.nulls_last_order('due_date', 'ASC')) } - validates :group, presence: true, unless: :project - validates :project, presence: true, unless: :group - validates :title, presence: true - - validate :uniqueness_of_title, if: :title_changed? - validate :milestone_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 validates_associated :milestone_releases, message: -> (_, obj) { obj[:value].map(&:errors).map(&:full_messages).join(",") } - strip_attributes :title - state_machine :state, initial: :active do event :close do transition active: :closed @@ -97,8 +54,6 @@ class Milestone < ApplicationRecord state :active end - alias_attribute :name, :title - class << self # Searches for milestones with a matching title or description. # @@ -220,7 +175,7 @@ class Milestone < ApplicationRecord end ## - # Returns the String necessary to reference this Milestone in Markdown. Group + # Returns the String necessary to reference a Milestone in Markdown. Group # milestones only support name references, and do not support cross-project # references. # @@ -248,10 +203,6 @@ class Milestone < ApplicationRecord self.class.reference_prefix + self.title end - def milestoneish_id - id - end - def for_display self end @@ -264,62 +215,16 @@ class Milestone < ApplicationRecord nil end - def title=(value) - write_attribute(:title, sanitize_title(value)) if value.present? - end - - def safe_title - title.to_slug.normalize.to_s - end - - def resource_parent - group || project - end - - def to_ability_name - model_name.singular - end - - def group_milestone? - group_id.present? - end - - def project_milestone? - project_id.present? - 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 + # 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? private - # Milestone titles must be unique across project milestones and group milestones - def uniqueness_of_title - if project - relation = Milestone.for_projects_and_groups([project_id], [project.group&.id]) - elsif group - relation = Milestone.for_projects_and_groups(group.projects.select(:id), [group.id]) - end - - title_exists = relation.find_by_title(title) - errors.add(:title, _("already being used for another group or project milestone.")) if title_exists - end - - # Milestone should be either a project milestone or a group milestone - def milestone_type_check - if 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.")) - end - end - def milestone_format_reference(format = :iid) raise ArgumentError, _('Unknown format') unless [:iid, :name].include?(format) @@ -334,26 +239,6 @@ class Milestone < ApplicationRecord end end - def sanitize_title(value) - CGI.unescape_html(Sanitize.clean(value.to_s)) - 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")) - end - end - - def dates_within_4_digits - if start_date && start_date > Date.new(9999, 12, 31) - errors.add(:start_date, _("date must not be after 9999-12-31")) - end - - if due_date && due_date > Date.new(9999, 12, 31) - errors.add(:due_date, _("date must not be after 9999-12-31")) - end - 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/sprint.rb b/app/models/sprint.rb index 10bf5c6ea16..82a5dfebce2 100644 --- a/app/models/sprint.rb +++ b/app/models/sprint.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Sprint < ApplicationRecord + include Timebox + STATE_ID_MAP = { active: 1, closed: 2 @@ -16,4 +18,17 @@ class Sprint < ApplicationRecord has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.sprints&.maximum(:iid) } has_internal_id :iid, scope: :group, init: ->(s) { s&.group&.sprints&.maximum(:iid) } + + state_machine :state, initial: :active do + event :close do + transition active: :closed + end + + event :activate do + transition closed: :active + end + + state :active, value: Sprint::STATE_ID_MAP[:active] + state :closed, value: Sprint::STATE_ID_MAP[:closed] + end end diff --git a/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md b/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md index f8dc3366904..48d21ccfb1b 100644 --- a/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md +++ b/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md @@ -14,3 +14,4 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec | `:reliable` | The test has been [promoted to a reliable test](https://about.gitlab.com/handbook/engineering/quality/guidelines/reliable-tests/#promoting-an-existing-test-to-reliable) meaning it passes consistently in all pipelines, including merge requests. | | `:requires_admin` | The test requires an admin account. Tests with the tag are excluded when run against Canary and Production environments. | | `:runner` | The test depends on and will set up a GitLab Runner instance, typically to run a pipeline. | +| `:skip_live_env` | The test will be excluded when run against live deployed environments such as Staging, Canary, and Production. | diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb index 31272c537a3..b05e82a541d 100644 --- a/lib/api/helpers/internal_helpers.rb +++ b/lib/api/helpers/internal_helpers.rb @@ -51,7 +51,7 @@ module API def parse_env return {} if params[:env].blank? - JSON.parse(params[:env]) + Gitlab::Json.parse(params[:env]) rescue JSON::ParserError {} end diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb index 56f556c229a..fdd889f5416 100644 --- a/lib/container_registry/client.rb +++ b/lib/container_registry/client.rb @@ -83,7 +83,7 @@ module ContainerRegistry image = { config: {} } - image, image_digest = upload_raw_blob(path, JSON.pretty_generate(image)) + image, image_digest = upload_raw_blob(path, Gitlab::Json.pretty_generate(image)) return unless image { @@ -109,7 +109,7 @@ module ContainerRegistry def put_tag(name, reference, manifest) response = faraday.put("/v2/#{name}/manifests/#{reference}") do |req| req.headers['Content-Type'] = DOCKER_DISTRIBUTION_MANIFEST_V2_TYPE - req.body = JSON.pretty_generate(manifest) + req.body = Gitlab::Json.pretty_generate(manifest) end response.headers['docker-content-digest'] if response.success? diff --git a/lib/container_registry/config.rb b/lib/container_registry/config.rb index 740c0e13da0..40dd92befd2 100644 --- a/lib/container_registry/config.rb +++ b/lib/container_registry/config.rb @@ -6,7 +6,7 @@ module ContainerRegistry def initialize(tag, blob) @tag, @blob = tag, blob - @data = JSON.parse(blob.data) + @data = Gitlab::Json.parse(blob.data) end def [](key) diff --git a/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data.rb b/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data.rb index 14e14f28439..956f9daa493 100644 --- a/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data.rb +++ b/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data.rb @@ -79,7 +79,7 @@ module Gitlab data = { 'jira_tracker_data' => [], 'issue_tracker_data' => [] } select_all(query).each do |service| begin - properties = JSON.parse(service['properties']) + properties = Gitlab::Json.parse(service['properties']) rescue JSON::ParserError logger.warn( message: 'Properties data not parsed - invalid json', diff --git a/lib/gitlab/chat_name_token.rb b/lib/gitlab/chat_name_token.rb index 8b3c5dc9e8b..9b4cb9d0134 100644 --- a/lib/gitlab/chat_name_token.rb +++ b/lib/gitlab/chat_name_token.rb @@ -16,7 +16,7 @@ module Gitlab def get Gitlab::Redis::SharedState.with do |redis| data = redis.get(redis_shared_state_key) - JSON.parse(data, symbolize_names: true) if data + Gitlab::Json.parse(data, symbolize_names: true) if data end end diff --git a/lib/gitlab/ci/ansi2html.rb b/lib/gitlab/ci/ansi2html.rb index 3a05feee156..e145bd2e9df 100644 --- a/lib/gitlab/ci/ansi2html.rb +++ b/lib/gitlab/ci/ansi2html.rb @@ -353,7 +353,7 @@ module Gitlab def restore_state(new_state, stream) state = Base64.urlsafe_decode64(new_state) - state = JSON.parse(state, symbolize_names: true) + state = Gitlab::Json.parse(state, symbolize_names: true) return if state[:offset].to_i > stream.size STATE_PARAMS.each do |param| diff --git a/lib/gitlab/ci/ansi2json/state.rb b/lib/gitlab/ci/ansi2json/state.rb index 7e1a8102a35..38d36e6950c 100644 --- a/lib/gitlab/ci/ansi2json/state.rb +++ b/lib/gitlab/ci/ansi2json/state.rb @@ -90,7 +90,7 @@ module Gitlab decoded_state = Base64.urlsafe_decode64(state) return unless decoded_state.present? - JSON.parse(decoded_state) + Gitlab::Json.parse(decoded_state) end end end diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index 1c3ce08be76..c5afb16ab1a 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -32,7 +32,7 @@ module Gitlab raise ParserError, 'Errors field not found!' unless errors begin - JSON.parse(errors) + Gitlab::Json.parse(errors) rescue JSON::ParserError raise ParserError, 'Invalid errors field!' end @@ -71,7 +71,7 @@ module Gitlab next unless path =~ match_pattern next if path =~ INVALID_PATH_PATTERN - entries[path] = JSON.parse(meta, symbolize_names: true) + entries[path] = Gitlab::Json.parse(meta, symbolize_names: true) rescue JSON::ParserError, Encoding::CompatibilityError next end diff --git a/lib/gitlab/ci/parsers/terraform/tfplan.rb b/lib/gitlab/ci/parsers/terraform/tfplan.rb index eddd8b4c665..26a18c6603e 100644 --- a/lib/gitlab/ci/parsers/terraform/tfplan.rb +++ b/lib/gitlab/ci/parsers/terraform/tfplan.rb @@ -8,7 +8,7 @@ module Gitlab TfplanParserError = Class.new(Gitlab::Ci::Parsers::ParserError) def parse!(json_data, terraform_reports, artifact:) - tfplan = JSON.parse(json_data).tap do |parsed_data| + tfplan = Gitlab::Json.parse(json_data).tap do |parsed_data| parsed_data['job_path'] = Gitlab::Routing.url_helpers.project_job_path( artifact.job.project, artifact.job ) diff --git a/lib/gitlab/danger/emoji_checker.rb b/lib/gitlab/danger/emoji_checker.rb index e31a6ae5011..a2867087428 100644 --- a/lib/gitlab/danger/emoji_checker.rb +++ b/lib/gitlab/danger/emoji_checker.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'json' +require_relative '../json' module Gitlab module Danger @@ -25,8 +25,8 @@ module Gitlab )}x.freeze def initialize - names = JSON.parse(File.read(DIGESTS)).keys + - JSON.parse(File.read(ALIASES)).keys + names = Gitlab::Json.parse(File.read(DIGESTS)).keys + + Gitlab::Json.parse(File.read(ALIASES)).keys @emoji = names.map { |name| ":#{name}:" } end diff --git a/lib/gitlab/danger/request_helper.rb b/lib/gitlab/danger/request_helper.rb index 06da4ed9ad3..ef51c3f2052 100644 --- a/lib/gitlab/danger/request_helper.rb +++ b/lib/gitlab/danger/request_helper.rb @@ -16,7 +16,7 @@ module Gitlab raise HTTPError, "Failed to read #{url}: #{rsp.code} #{rsp.message}" end - JSON.parse(rsp.body) + Gitlab::Json.parse(rsp.body) end end end diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb index 565f34b78b7..2c9d0d6c0d1 100644 --- a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb +++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb @@ -157,7 +157,7 @@ module Gitlab failed_reverts = [] while rename_info = redis.lpop(key) - path_before_rename, path_after_rename = JSON.parse(rename_info) + path_before_rename, path_after_rename = Gitlab::Json.parse(rename_info) say "renaming #{type} from #{path_after_rename} back to #{path_before_rename}" begin yield(path_before_rename, path_after_rename) diff --git a/lib/gitlab/dependency_linker/json_linker.rb b/lib/gitlab/dependency_linker/json_linker.rb index 298d214df61..86dc7efb0d9 100644 --- a/lib/gitlab/dependency_linker/json_linker.rb +++ b/lib/gitlab/dependency_linker/json_linker.rb @@ -39,7 +39,7 @@ module Gitlab end def json - @json ||= JSON.parse(plain_text) rescue nil + @json ||= Gitlab::Json.parse(plain_text) rescue nil end end end diff --git a/lib/gitlab/diff/highlight_cache.rb b/lib/gitlab/diff/highlight_cache.rb index 01ec9798fe4..ccf09b37b9b 100644 --- a/lib/gitlab/diff/highlight_cache.rb +++ b/lib/gitlab/diff/highlight_cache.rb @@ -156,7 +156,7 @@ module Gitlab end results.map! do |result| - JSON.parse(extract_data(result), symbolize_names: true) unless result.nil? + Gitlab::Json.parse(extract_data(result), symbolize_names: true) unless result.nil? end file_paths.zip(results).to_h diff --git a/lib/gitlab/diff/position.rb b/lib/gitlab/diff/position.rb index 8b99fd5cd42..10ad23b7774 100644 --- a/lib/gitlab/diff/position.rb +++ b/lib/gitlab/diff/position.rb @@ -68,7 +68,7 @@ module Gitlab end def to_json(opts = nil) - JSON.generate(formatter.to_h, opts) + Gitlab::Json.generate(formatter.to_h, opts) end def as_json(opts = nil) diff --git a/lib/gitlab/discussions_diff/highlight_cache.rb b/lib/gitlab/discussions_diff/highlight_cache.rb index 1f64883cb69..75d5a5df74b 100644 --- a/lib/gitlab/discussions_diff/highlight_cache.rb +++ b/lib/gitlab/discussions_diff/highlight_cache.rb @@ -42,7 +42,7 @@ module Gitlab content.map! do |lines| next unless lines - JSON.parse(lines).map! do |line| + Gitlab::Json.parse(lines).map! do |line| Gitlab::Diff::Line.safe_init_from_hash(line) end end diff --git a/lib/gitlab/emoji.rb b/lib/gitlab/emoji.rb index 305bcada2f5..bcf92b35720 100644 --- a/lib/gitlab/emoji.rb +++ b/lib/gitlab/emoji.rb @@ -21,7 +21,7 @@ module Gitlab end def emojis_aliases - @emoji_aliases ||= JSON.parse(File.read(Rails.root.join('fixtures', 'emojis', 'aliases.json'))) + @emoji_aliases ||= Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'aliases.json'))) end def emoji_filename(name) @@ -63,7 +63,7 @@ module Gitlab def emoji_unicode_versions_by_name @emoji_unicode_versions_by_name ||= - JSON.parse(File.read(Rails.root.join('fixtures', 'emojis', 'emoji-unicode-version-map.json'))) + Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'emoji-unicode-version-map.json'))) end end end diff --git a/lib/gitlab/external_authorization/response.rb b/lib/gitlab/external_authorization/response.rb index 4f3fe5882db..04f9688fad0 100644 --- a/lib/gitlab/external_authorization/response.rb +++ b/lib/gitlab/external_authorization/response.rb @@ -28,7 +28,7 @@ module Gitlab end def parse_response! - JSON.parse(@excon_response.body) + Gitlab::Json.parse(@excon_response.body) rescue JSON::JSONError # The JSON response is optional, so don't fail when it's missing nil diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb index 79ea3d2de6c..3aaed0edb87 100644 --- a/lib/gitlab/gitaly_client.rb +++ b/lib/gitlab/gitaly_client.rb @@ -130,7 +130,7 @@ module Gitlab end def self.address_metadata(storage) - Base64.strict_encode64(JSON.dump(storage => connection_data(storage))) + Base64.strict_encode64(Gitlab::Json.dump(storage => connection_data(storage))) end def self.connection_data(storage) @@ -458,7 +458,7 @@ module Gitlab def self.filesystem_id_from_disk(storage) metadata_file = File.read(storage_metadata_file_path(storage)) - metadata_hash = JSON.parse(metadata_file) + metadata_hash = Gitlab::Json.parse(metadata_file) metadata_hash['gitaly_filesystem_id'] rescue Errno::ENOENT, Errno::EACCES, JSON::ParserError nil diff --git a/lib/gitlab/graphql/pagination/keyset/connection.rb b/lib/gitlab/graphql/pagination/keyset/connection.rb index 5466924a794..1a32ab468b1 100644 --- a/lib/gitlab/graphql/pagination/keyset/connection.rb +++ b/lib/gitlab/graphql/pagination/keyset/connection.rb @@ -128,7 +128,7 @@ module Gitlab end def ordering_from_encoded_json(cursor) - JSON.parse(decode(cursor)) + Gitlab::Json.parse(decode(cursor)) rescue JSON::ParserError raise Gitlab::Graphql::Errors::ArgumentError, "Please provide a valid cursor" end diff --git a/lib/gitlab/graphql/variables.rb b/lib/gitlab/graphql/variables.rb index b13ea37c21f..1c6fb011012 100644 --- a/lib/gitlab/graphql/variables.rb +++ b/lib/gitlab/graphql/variables.rb @@ -20,7 +20,7 @@ module Gitlab case ambiguous_param when String if ambiguous_param.present? - ensure_hash(JSON.parse(ambiguous_param)) + ensure_hash(Gitlab::Json.parse(ambiguous_param)) else {} end diff --git a/lib/gitlab/health_checks/puma_check.rb b/lib/gitlab/health_checks/puma_check.rb index 9f09070a57d..2dc8a093572 100644 --- a/lib/gitlab/health_checks/puma_check.rb +++ b/lib/gitlab/health_checks/puma_check.rb @@ -21,7 +21,7 @@ module Gitlab return unless Gitlab::Runtime.puma? stats = Puma.stats - stats = JSON.parse(stats) + stats = Gitlab::Json.parse(stats) # If `workers` is missing this means that # Puma server is running in single mode diff --git a/lib/gitlab/metrics/samplers/puma_sampler.rb b/lib/gitlab/metrics/samplers/puma_sampler.rb index f788f51b1ce..98dd517ee3b 100644 --- a/lib/gitlab/metrics/samplers/puma_sampler.rb +++ b/lib/gitlab/metrics/samplers/puma_sampler.rb @@ -26,7 +26,7 @@ module Gitlab json_stats = puma_stats return unless json_stats - stats = JSON.parse(json_stats) + stats = Gitlab::Json.parse(json_stats) if cluster?(stats) sample_cluster(stats) diff --git a/lib/gitlab/phabricator_import/conduit/response.rb b/lib/gitlab/phabricator_import/conduit/response.rb index 6053ecfbd5e..1b03cfa05e6 100644 --- a/lib/gitlab/phabricator_import/conduit/response.rb +++ b/lib/gitlab/phabricator_import/conduit/response.rb @@ -9,7 +9,7 @@ module Gitlab "Phabricator responded with #{http_response.status}" end - response = new(JSON.parse(http_response.body)) + response = new(Gitlab::Json.parse(http_response.body)) unless response.success? raise ResponseError, diff --git a/lib/gitlab/prometheus_client.rb b/lib/gitlab/prometheus_client.rb index 71a0d528bd7..e3559644142 100644 --- a/lib/gitlab/prometheus_client.rb +++ b/lib/gitlab/prometheus_client.rb @@ -163,7 +163,7 @@ module Gitlab end def parse_json(response_body) - JSON.parse(response_body) + Gitlab::Json.parse(response_body) rescue JSON::ParserError raise PrometheusClient::Error, 'Parsing response failed' end diff --git a/lib/gitlab/sanitizers/exif.rb b/lib/gitlab/sanitizers/exif.rb index 5eeb8b00ff3..7e22bf4d7df 100644 --- a/lib/gitlab/sanitizers/exif.rb +++ b/lib/gitlab/sanitizers/exif.rb @@ -152,7 +152,7 @@ module Gitlab raise "failed to get exif tags: #{output}" if status != 0 - JSON.parse(output).first + Gitlab::Json.parse(output).first end end end diff --git a/lib/gitlab/sidekiq_daemon/monitor.rb b/lib/gitlab/sidekiq_daemon/monitor.rb index 0723b514c90..1f1d63877b5 100644 --- a/lib/gitlab/sidekiq_daemon/monitor.rb +++ b/lib/gitlab/sidekiq_daemon/monitor.rb @@ -134,7 +134,7 @@ module Gitlab end def safe_parse(message) - JSON.parse(message) + Gitlab::Json.parse(message) rescue JSON::ParserError end diff --git a/lib/gitlab/sidekiq_middleware/arguments_logger.rb b/lib/gitlab/sidekiq_middleware/arguments_logger.rb index 2859aa5f4a6..fe5213fc5d7 100644 --- a/lib/gitlab/sidekiq_middleware/arguments_logger.rb +++ b/lib/gitlab/sidekiq_middleware/arguments_logger.rb @@ -4,7 +4,7 @@ module Gitlab module SidekiqMiddleware class ArgumentsLogger def call(worker, job, queue) - Sidekiq.logger.info "arguments: #{JSON.dump(job['args'])}" + Sidekiq.logger.info "arguments: #{Gitlab::Json.dump(job['args'])}" yield end end diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index acec7cb30a6..75196a03edc 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -205,7 +205,7 @@ module Gitlab # This is the outermost encoding of a senddata: header. It is safe for # inclusion in HTTP response headers def encode(hash) - Base64.urlsafe_encode64(JSON.dump(hash)) + Base64.urlsafe_encode64(Gitlab::Json.dump(hash)) end # This is for encoding individual fields inside the senddata JSON that diff --git a/lib/mattermost/client.rb b/lib/mattermost/client.rb index 293d0c563c5..01a9567491f 100644 --- a/lib/mattermost/client.rb +++ b/lib/mattermost/client.rb @@ -49,7 +49,7 @@ module Mattermost end def json_response(response) - json_response = JSON.parse(response.body) + json_response = Gitlab::Json.parse(response.body) unless response.success? raise Mattermost::ClientError.new(json_response['message'] || 'Undefined error') diff --git a/lib/quality/helm3_client.rb b/lib/quality/helm3_client.rb index afea73cbc50..28ff3ef0271 100644 --- a/lib/quality/helm3_client.rb +++ b/lib/quality/helm3_client.rb @@ -65,7 +65,7 @@ module Quality %(--output json), *args ] - releases = JSON.parse(run_command(command)) + releases = Gitlab::Json.parse(run_command(command)) releases.map do |release| Release.new(*release.values_at(*RELEASE_JSON_ATTRIBUTES)) diff --git a/lib/rspec_flaky/listener.rb b/lib/rspec_flaky/listener.rb index bf15130d17e..37e4e16e87e 100644 --- a/lib/rspec_flaky/listener.rb +++ b/lib/rspec_flaky/listener.rb @@ -40,7 +40,7 @@ module RspecFlaky new_flaky_examples = flaky_examples - suite_flaky_examples if new_flaky_examples.any? Rails.logger.warn "\nNew flaky examples detected:\n" - Rails.logger.warn JSON.pretty_generate(new_flaky_examples.to_h) + Rails.logger.warn Gitlab::Json.pretty_generate(new_flaky_examples.to_h) RspecFlaky::Report.new(new_flaky_examples).write(RspecFlaky::Config.new_flaky_examples_report_path) # write_report_file(new_flaky_examples, RspecFlaky::Config.new_flaky_examples_report_path) diff --git a/lib/rspec_flaky/report.rb b/lib/rspec_flaky/report.rb index 73f30362cfe..c7860f35f62 100644 --- a/lib/rspec_flaky/report.rb +++ b/lib/rspec_flaky/report.rb @@ -19,7 +19,7 @@ module RspecFlaky end def self.load_json(json) - new(RspecFlaky::FlakyExamplesCollection.new(JSON.parse(json))) + new(RspecFlaky::FlakyExamplesCollection.new(Gitlab::Json.parse(json))) end def initialize(flaky_examples) @@ -40,7 +40,7 @@ module RspecFlaky report_path_dir = File.dirname(file_path) FileUtils.mkdir_p(report_path_dir) unless Dir.exist?(report_path_dir) - File.write(file_path, JSON.pretty_generate(flaky_examples.to_h)) + File.write(file_path, Gitlab::Json.pretty_generate(flaky_examples.to_h)) end def prune_outdated(days: OUTDATED_DAYS_THRESHOLD) diff --git a/lib/tasks/gemojione.rake b/lib/tasks/gemojione.rake index 8cf7c9e89f0..3833689e07e 100644 --- a/lib/tasks/gemojione.rake +++ b/lib/tasks/gemojione.rake @@ -7,7 +7,7 @@ namespace :gemojione do aliases = {} index_file = File.join(Rails.root, 'fixtures', 'emojis', 'index.json') - index = JSON.parse(File.read(index_file)) + index = Gitlab::Json.parse(File.read(index_file)) index.each_pair do |key, data| data['aliases'].each do |a| @@ -19,7 +19,7 @@ namespace :gemojione do out = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json') File.open(out, 'w') do |handle| - handle.write(JSON.pretty_generate(aliases, indent: ' ', space: '', space_before: '')) + handle.write(Gitlab::Json.pretty_generate(aliases, indent: ' ', space: '', space_before: '')) end end @@ -58,7 +58,7 @@ namespace :gemojione do out = File.join(Rails.root, 'fixtures', 'emojis', 'digests.json') File.open(out, 'w') do |handle| - handle.write(JSON.pretty_generate(resultant_emoji_map)) + handle.write(Gitlab::Json.pretty_generate(resultant_emoji_map)) end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 37b1459886d..262a7e227ab 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -516,6 +516,9 @@ msgstr[1] "" msgid "%{text} is available" msgstr "" +msgid "%{timebox_name} should belong either to a project or a group." +msgstr "" + msgid "%{title} %{operator} %{threshold}" msgstr "" @@ -24503,7 +24506,7 @@ msgstr "" msgid "allowed to fail" msgstr "" -msgid "already being used for another group or project milestone." +msgid "already being used for another group or project %{timebox_name}." msgstr "" msgid "already has a \"created\" issue link" @@ -25116,9 +25119,6 @@ msgstr[1] "" msgid "merged %{time_ago}" msgstr "" -msgid "milestone should belong either to a project or a group." -msgstr "" - msgid "missing" msgstr "" diff --git a/qa/qa/specs/runner.rb b/qa/qa/specs/runner.rb index ac73cc00dbf..afeddeaa5d5 100644 --- a/qa/qa/specs/runner.rb +++ b/qa/qa/specs/runner.rb @@ -42,6 +42,8 @@ module QA tags_for_rspec.push(%w[--tag ~skip_signup_disabled]) if QA::Runtime::Env.signup_disabled? + tags_for_rspec.push(%w[--tag ~skip_live_env]) if QA::Runtime::Env.dot_com? + QA::Runtime::Env.supported_features.each_key do |key| tags_for_rspec.push(%W[--tag ~requires_#{key}]) unless QA::Runtime::Env.can_test? key end diff --git a/qa/spec/specs/runner_spec.rb b/qa/spec/specs/runner_spec.rb index 1a3efe0b46c..361588fa14f 100644 --- a/qa/spec/specs/runner_spec.rb +++ b/qa/spec/specs/runner_spec.rb @@ -14,6 +14,8 @@ describe QA::Specs::Runner do describe '#perform' do before do allow(QA::Runtime::Browser).to receive(:configure!) + + QA::Runtime::Scenario.define(:gitlab_address, "http://gitlab.test") end it_behaves_like 'excludes orchestrated' @@ -80,6 +82,18 @@ describe QA::Specs::Runner do end end + context 'when running against live environment' do + before do + QA::Runtime::Scenario.define(:gitlab_address, "https://staging.gitlab.com") + end + + it 'includes default args and excludes the skip_live_env tag' do + expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~skip_live_env', *described_class::DEFAULT_TEST_PATH_ARGS]) + + subject.perform + end + end + context 'testable features' do shared_examples 'one supported feature' do |feature| before do diff --git a/spec/lib/bitbucket_server/representation/activity_spec.rb b/spec/lib/bitbucket_server/representation/activity_spec.rb index b548dedadfb..6988e77ad25 100644 --- a/spec/lib/bitbucket_server/representation/activity_spec.rb +++ b/spec/lib/bitbucket_server/representation/activity_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe BitbucketServer::Representation::Activity do - let(:activities) { JSON.parse(fixture_file('importers/bitbucket_server/activities.json'))['values'] } + let(:activities) { Gitlab::Json.parse(fixture_file('importers/bitbucket_server/activities.json'))['values'] } let(:inline_comment) { activities.first } let(:comment) { activities[3] } let(:merge_event) { activities[4] } diff --git a/spec/lib/bitbucket_server/representation/comment_spec.rb b/spec/lib/bitbucket_server/representation/comment_spec.rb index f8c73c3da35..ecaf6a843ae 100644 --- a/spec/lib/bitbucket_server/representation/comment_spec.rb +++ b/spec/lib/bitbucket_server/representation/comment_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe BitbucketServer::Representation::Comment do - let(:activities) { JSON.parse(fixture_file('importers/bitbucket_server/activities.json'))['values'] } + let(:activities) { Gitlab::Json.parse(fixture_file('importers/bitbucket_server/activities.json'))['values'] } let(:comment) { activities.first } subject { described_class.new(comment) } diff --git a/spec/lib/bitbucket_server/representation/pull_request_comment_spec.rb b/spec/lib/bitbucket_server/representation/pull_request_comment_spec.rb index db43e990812..aa3eddf305a 100644 --- a/spec/lib/bitbucket_server/representation/pull_request_comment_spec.rb +++ b/spec/lib/bitbucket_server/representation/pull_request_comment_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe BitbucketServer::Representation::PullRequestComment do - let(:activities) { JSON.parse(fixture_file('importers/bitbucket_server/activities.json'))['values'] } + let(:activities) { Gitlab::Json.parse(fixture_file('importers/bitbucket_server/activities.json'))['values'] } let(:comment) { activities.second } subject { described_class.new(comment) } diff --git a/spec/lib/bitbucket_server/representation/pull_request_spec.rb b/spec/lib/bitbucket_server/representation/pull_request_spec.rb index e091890041e..7e72da05cb1 100644 --- a/spec/lib/bitbucket_server/representation/pull_request_spec.rb +++ b/spec/lib/bitbucket_server/representation/pull_request_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe BitbucketServer::Representation::PullRequest do - let(:sample_data) { JSON.parse(fixture_file('importers/bitbucket_server/pull_request.json')) } + let(:sample_data) { Gitlab::Json.parse(fixture_file('importers/bitbucket_server/pull_request.json')) } subject { described_class.new(sample_data) } diff --git a/spec/lib/bitbucket_server/representation/repo_spec.rb b/spec/lib/bitbucket_server/representation/repo_spec.rb index 801de247d73..429b6d36c59 100644 --- a/spec/lib/bitbucket_server/representation/repo_spec.rb +++ b/spec/lib/bitbucket_server/representation/repo_spec.rb @@ -50,7 +50,7 @@ describe BitbucketServer::Representation::Repo do DATA end - subject { described_class.new(JSON.parse(sample_data)) } + subject { described_class.new(Gitlab::Json.parse(sample_data)) } describe '#project_key' do it { expect(subject.project_key).to eq('TEST') } diff --git a/spec/lib/gitlab/app_json_logger_spec.rb b/spec/lib/gitlab/app_json_logger_spec.rb index 22a398f8bca..d11456236cc 100644 --- a/spec/lib/gitlab/app_json_logger_spec.rb +++ b/spec/lib/gitlab/app_json_logger_spec.rb @@ -9,10 +9,10 @@ describe Gitlab::AppJsonLogger do let(:string_message) { 'Information' } it 'logs a hash as a JSON' do - expect(JSON.parse(subject.format_message('INFO', Time.now, nil, hash_message))).to include(hash_message) + expect(Gitlab::Json.parse(subject.format_message('INFO', Time.now, nil, hash_message))).to include(hash_message) end it 'logs a string as a JSON' do - expect(JSON.parse(subject.format_message('INFO', Time.now, nil, string_message))).to include('message' => string_message) + expect(Gitlab::Json.parse(subject.format_message('INFO', Time.now, nil, string_message))).to include('message' => string_message) end end diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb index 7b8437e4874..fae57996fb6 100644 --- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb +++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb @@ -242,7 +242,7 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameBase, :delete old_path, new_path = [nil, nil] Gitlab::Redis::SharedState.with do |redis| rename_info = redis.lpop(key) - old_path, new_path = JSON.parse(rename_info) + old_path, new_path = Gitlab::Json.parse(rename_info) end expect(old_path).to eq('path/to/namespace') @@ -278,7 +278,7 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameBase, :delete end expect(rename_count).to eq(1) - expect(JSON.parse(stored_renames.first)).to eq(%w(old_path new_path)) + expect(Gitlab::Json.parse(stored_renames.first)).to eq(%w(old_path new_path)) end end end diff --git a/spec/lib/gitlab/diff/position_spec.rb b/spec/lib/gitlab/diff/position_spec.rb index a83c0f35d92..10749ec024d 100644 --- a/spec/lib/gitlab/diff/position_spec.rb +++ b/spec/lib/gitlab/diff/position_spec.rb @@ -639,11 +639,11 @@ describe Gitlab::Diff::Position do let(:diff_position) { described_class.new(args) } it "returns the position as JSON" do - expect(JSON.parse(diff_position.to_json)).to eq(args.stringify_keys) + expect(Gitlab::Json.parse(diff_position.to_json)).to eq(args.stringify_keys) end it "works when nested under another hash" do - expect(JSON.parse(JSON.generate(pos: diff_position))).to eq('pos' => args.stringify_keys) + expect(Gitlab::Json.parse(Gitlab::Json.generate(pos: diff_position))).to eq('pos' => args.stringify_keys) end end diff --git a/spec/lib/gitlab/elasticsearch/logs/lines_spec.rb b/spec/lib/gitlab/elasticsearch/logs/lines_spec.rb index ccf38b7f688..0561133f17e 100644 --- a/spec/lib/gitlab/elasticsearch/logs/lines_spec.rb +++ b/spec/lib/gitlab/elasticsearch/logs/lines_spec.rb @@ -10,7 +10,7 @@ describe Gitlab::Elasticsearch::Logs::Lines do let(:es_message_3) { { timestamp: "2019-12-13T14:35:36.034Z", pod: "production-6866bc8974-m4sk4", message: "10.8.2.1 - - [04/Nov/2019:23:09:24 UTC] \"GET / HTTP/1.1\" 200 13" } } let(:es_message_4) { { timestamp: "2019-12-13T14:35:37.034Z", pod: "production-6866bc8974-m4sk4", message: "- -\u003e /" } } - let(:es_response) { JSON.parse(fixture_file('lib/elasticsearch/logs_response.json')) } + let(:es_response) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/logs_response.json')) } subject { described_class.new(client) } @@ -22,14 +22,14 @@ describe Gitlab::Elasticsearch::Logs::Lines do let(:end_time) { "2019-12-13T14:35:34.034Z" } let(:cursor) { "9999934,1572449784442" } - let(:body) { JSON.parse(fixture_file('lib/elasticsearch/query.json')) } - let(:body_with_container) { JSON.parse(fixture_file('lib/elasticsearch/query_with_container.json')) } - let(:body_with_search) { JSON.parse(fixture_file('lib/elasticsearch/query_with_search.json')) } - let(:body_with_times) { JSON.parse(fixture_file('lib/elasticsearch/query_with_times.json')) } - let(:body_with_start_time) { JSON.parse(fixture_file('lib/elasticsearch/query_with_start_time.json')) } - let(:body_with_end_time) { JSON.parse(fixture_file('lib/elasticsearch/query_with_end_time.json')) } - let(:body_with_cursor) { JSON.parse(fixture_file('lib/elasticsearch/query_with_cursor.json')) } - let(:body_with_filebeat_6) { JSON.parse(fixture_file('lib/elasticsearch/query_with_filebeat_6.json')) } + let(:body) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query.json')) } + let(:body_with_container) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query_with_container.json')) } + let(:body_with_search) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query_with_search.json')) } + let(:body_with_times) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query_with_times.json')) } + let(:body_with_start_time) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query_with_start_time.json')) } + let(:body_with_end_time) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query_with_end_time.json')) } + let(:body_with_cursor) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query_with_cursor.json')) } + let(:body_with_filebeat_6) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query_with_filebeat_6.json')) } RSpec::Matchers.define :a_hash_equal_to_json do |expected| match do |actual| diff --git a/spec/lib/gitlab/elasticsearch/logs/pods_spec.rb b/spec/lib/gitlab/elasticsearch/logs/pods_spec.rb index 0a4ab0780c5..c2c3074e965 100644 --- a/spec/lib/gitlab/elasticsearch/logs/pods_spec.rb +++ b/spec/lib/gitlab/elasticsearch/logs/pods_spec.rb @@ -5,8 +5,8 @@ require 'spec_helper' describe Gitlab::Elasticsearch::Logs::Pods do let(:client) { Elasticsearch::Transport::Client } - let(:es_query) { JSON.parse(fixture_file('lib/elasticsearch/pods_query.json'), symbolize_names: true) } - let(:es_response) { JSON.parse(fixture_file('lib/elasticsearch/pods_response.json')) } + let(:es_query) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/pods_query.json'), symbolize_names: true) } + let(:es_response) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/pods_response.json')) } let(:namespace) { "autodevops-deploy-9-production" } subject { described_class.new(client) } diff --git a/spec/lib/gitlab/google_code_import/client_spec.rb b/spec/lib/gitlab/google_code_import/client_spec.rb index 2e929a62ebc..fb1c7085017 100644 --- a/spec/lib/gitlab/google_code_import/client_spec.rb +++ b/spec/lib/gitlab/google_code_import/client_spec.rb @@ -3,7 +3,7 @@ require "spec_helper" describe Gitlab::GoogleCodeImport::Client do - let(:raw_data) { JSON.parse(fixture_file("GoogleCodeProjectHosting.json")) } + let(:raw_data) { Gitlab::Json.parse(fixture_file("GoogleCodeProjectHosting.json")) } subject { described_class.new(raw_data) } diff --git a/spec/lib/gitlab/google_code_import/importer_spec.rb b/spec/lib/gitlab/google_code_import/importer_spec.rb index 7055df89c09..3118671bb5e 100644 --- a/spec/lib/gitlab/google_code_import/importer_spec.rb +++ b/spec/lib/gitlab/google_code_import/importer_spec.rb @@ -4,7 +4,7 @@ require "spec_helper" describe Gitlab::GoogleCodeImport::Importer do let(:mapped_user) { create(:user, username: "thilo123") } - let(:raw_data) { JSON.parse(fixture_file("GoogleCodeProjectHosting.json")) } + let(:raw_data) { Gitlab::Json.parse(fixture_file("GoogleCodeProjectHosting.json")) } let(:client) { Gitlab::GoogleCodeImport::Client.new(raw_data) } let(:import_data) do { diff --git a/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb b/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb index d3b108f60ff..84f23bb2ad9 100644 --- a/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb +++ b/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb @@ -30,7 +30,7 @@ describe Gitlab::GrapeLogging::Formatters::LogrageWithTimestamp do } end let(:time) { Time.now } - let(:result) { JSON.parse(subject) } + let(:result) { Gitlab::Json.parse(subject) } subject { described_class.new.call(:info, time, nil, log_entry) } diff --git a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb index fdacecbaca6..bdf43a438f3 100644 --- a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb +++ b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb @@ -18,7 +18,7 @@ describe Gitlab::Graphql::Pagination::Keyset::Connection do end def decoded_cursor(cursor) - JSON.parse(Base64Bp.urlsafe_decode64(cursor)) + Gitlab::Json.parse(Base64Bp.urlsafe_decode64(cursor)) end describe '#cursor_for' do diff --git a/spec/lib/gitlab/graphql_logger_spec.rb b/spec/lib/gitlab/graphql_logger_spec.rb index 4977f98b83e..86cb8cbedad 100644 --- a/spec/lib/gitlab/graphql_logger_spec.rb +++ b/spec/lib/gitlab/graphql_logger_spec.rb @@ -28,7 +28,7 @@ describe Gitlab::GraphqlLogger do output = subject.format_message('INFO', now, 'test', analyzer_memo) - data = JSON.parse(output) + data = Gitlab::Json.parse(output) expect(data['severity']).to eq('INFO') expect(data['time']).to eq(now.utc.iso8601(3)) expect(data['complexity']).to eq(181) diff --git a/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb b/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb index 15058684229..916ed692a05 100644 --- a/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb +++ b/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb @@ -8,7 +8,7 @@ describe Gitlab::ImportExport::FastHashSerializer do # Wrapping the result into JSON generating/parsing is for making # the testing more convenient. Doing this, we can check that # all items are properly serialized while traversing the simple hash. - subject { JSON.parse(JSON.generate(described_class.new(project, tree).execute)) } + subject { Gitlab::Json.parse(Gitlab::Json.generate(described_class.new(project, tree).execute)) } let!(:project) { setup_project } let(:user) { create(:user) } diff --git a/spec/lib/gitlab/import_export/import_export_equivalence_spec.rb b/spec/lib/gitlab/import_export/import_export_equivalence_spec.rb index 707975f20b6..95df9cd0e6e 100644 --- a/spec/lib/gitlab/import_export/import_export_equivalence_spec.rb +++ b/spec/lib/gitlab/import_export/import_export_equivalence_spec.rb @@ -46,8 +46,8 @@ describe Gitlab::ImportExport do export_path: test_tmp_path) ).to be true - imported_json = JSON.parse(File.read("#{test_fixture_path}/project.json")) - exported_json = JSON.parse(File.read("#{test_tmp_path}/project.json")) + imported_json = Gitlab::Json.parse(File.read("#{test_fixture_path}/project.json")) + exported_json = Gitlab::Json.parse(File.read("#{test_tmp_path}/project.json")) assert_relations_match(imported_json, exported_json) end diff --git a/spec/lib/gitlab/import_export/json/legacy_reader/file_spec.rb b/spec/lib/gitlab/import_export/json/legacy_reader/file_spec.rb index 1021ce3cd50..99932404fd9 100644 --- a/spec/lib/gitlab/import_export/json/legacy_reader/file_spec.rb +++ b/spec/lib/gitlab/import_export/json/legacy_reader/file_spec.rb @@ -7,7 +7,7 @@ describe Gitlab::ImportExport::JSON::LegacyReader::File do it_behaves_like 'import/export json legacy reader' do let(:valid_path) { 'spec/fixtures/lib/gitlab/import_export/light/project.json' } let(:data) { valid_path } - let(:json_data) { JSON.parse(File.read(valid_path)) } + let(:json_data) { Gitlab::Json.parse(File.read(valid_path)) } end describe '#exist?' do diff --git a/spec/lib/gitlab/import_export/json/legacy_reader/hash_spec.rb b/spec/lib/gitlab/import_export/json/legacy_reader/hash_spec.rb index 8c4dfd2f356..e793dc7339d 100644 --- a/spec/lib/gitlab/import_export/json/legacy_reader/hash_spec.rb +++ b/spec/lib/gitlab/import_export/json/legacy_reader/hash_spec.rb @@ -9,8 +9,8 @@ describe Gitlab::ImportExport::JSON::LegacyReader::Hash do # the hash is modified by the `LegacyReader` # we need to deep-dup it - let(:json_data) { JSON.parse(File.read(path)) } - let(:data) { JSON.parse(File.read(path)) } + let(:json_data) { Gitlab::Json.parse(File.read(path)) } + let(:data) { Gitlab::Json.parse(File.read(path)) } end describe '#exist?' do diff --git a/spec/lib/gitlab/import_export/json/ndjson_reader_spec.rb b/spec/lib/gitlab/import_export/json/ndjson_reader_spec.rb index 17d0546a0a7..34e8b1ddd59 100644 --- a/spec/lib/gitlab/import_export/json/ndjson_reader_spec.rb +++ b/spec/lib/gitlab/import_export/json/ndjson_reader_spec.rb @@ -6,7 +6,7 @@ describe Gitlab::ImportExport::JSON::NdjsonReader do include ImportExport::CommonUtil let(:fixture) { 'spec/fixtures/lib/gitlab/import_export/light/tree' } - let(:root_tree) { JSON.parse(File.read(File.join(fixture, 'project.json'))) } + let(:root_tree) { Gitlab::Json.parse(File.read(File.join(fixture, 'project.json'))) } let(:ndjson_reader) { described_class.new(dir_path) } let(:importable_path) { 'project' } @@ -93,8 +93,8 @@ describe Gitlab::ImportExport::JSON::NdjsonReader do context 'relation file contains multiple lines' do let(:key) { 'custom_attributes' } - let(:attr_1) { JSON.parse('{"id":201,"project_id":5,"created_at":"2016-06-14T15:01:51.315Z","updated_at":"2016-06-14T15:01:51.315Z","key":"color","value":"red"}') } - let(:attr_2) { JSON.parse('{"id":202,"project_id":5,"created_at":"2016-06-14T15:01:51.315Z","updated_at":"2016-06-14T15:01:51.315Z","key":"size","value":"small"}') } + let(:attr_1) { Gitlab::Json.parse('{"id":201,"project_id":5,"created_at":"2016-06-14T15:01:51.315Z","updated_at":"2016-06-14T15:01:51.315Z","key":"color","value":"red"}') } + let(:attr_2) { Gitlab::Json.parse('{"id":202,"project_id":5,"created_at":"2016-06-14T15:01:51.315Z","updated_at":"2016-06-14T15:01:51.315Z","key":"size","value":"small"}') } it 'yields every relation value to the Enumerator' do expect(subject.to_a).to eq([[attr_1, 0], [attr_2, 1]]) diff --git a/spec/lib/gitlab/import_export/lfs_saver_spec.rb b/spec/lib/gitlab/import_export/lfs_saver_spec.rb index a8ff7867410..e9d06573e70 100644 --- a/spec/lib/gitlab/import_export/lfs_saver_spec.rb +++ b/spec/lib/gitlab/import_export/lfs_saver_spec.rb @@ -26,7 +26,7 @@ describe Gitlab::ImportExport::LfsSaver do let(:lfs_json_file) { File.join(shared.export_path, Gitlab::ImportExport.lfs_objects_filename) } def lfs_json - JSON.parse(IO.read(lfs_json_file)) + Gitlab::Json.parse(IO.read(lfs_json_file)) end before do diff --git a/spec/lib/gitlab/json_logger_spec.rb b/spec/lib/gitlab/json_logger_spec.rb index 5d544198c40..41dafc84ef2 100644 --- a/spec/lib/gitlab/json_logger_spec.rb +++ b/spec/lib/gitlab/json_logger_spec.rb @@ -14,7 +14,7 @@ describe Gitlab::JsonLogger do it 'formats strings' do output = subject.format_message('INFO', now, 'test', 'Hello world') - data = JSON.parse(output) + data = Gitlab::Json.parse(output) expect(data['severity']).to eq('INFO') expect(data['time']).to eq(now.utc.iso8601(3)) @@ -24,7 +24,7 @@ describe Gitlab::JsonLogger do it 'formats hashes' do output = subject.format_message('INFO', now, 'test', { hello: 1 }) - data = JSON.parse(output) + data = Gitlab::Json.parse(output) expect(data['severity']).to eq('INFO') expect(data['time']).to eq(now.utc.iso8601(3)) diff --git a/spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb b/spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb index e41004bb57e..5d4bd4512e3 100644 --- a/spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb @@ -9,9 +9,9 @@ describe Gitlab::Metrics::Dashboard::Stages::GrafanaFormatter do let_it_be(:project) { create(:project, namespace: namespace, name: 'bar') } describe '#transform!' do - let(:grafana_dashboard) { JSON.parse(fixture_file('grafana/simplified_dashboard_response.json'), symbolize_names: true) } - let(:datasource) { JSON.parse(fixture_file('grafana/datasource_response.json'), symbolize_names: true) } - let(:expected_dashboard) { JSON.parse(fixture_file('grafana/expected_grafana_embed.json'), symbolize_names: true) } + let(:grafana_dashboard) { Gitlab::Json.parse(fixture_file('grafana/simplified_dashboard_response.json'), symbolize_names: true) } + let(:datasource) { Gitlab::Json.parse(fixture_file('grafana/datasource_response.json'), symbolize_names: true) } + let(:expected_dashboard) { Gitlab::Json.parse(fixture_file('grafana/expected_grafana_embed.json'), symbolize_names: true) } subject(:dashboard) { described_class.new(project, {}, params).transform! } diff --git a/spec/lib/gitlab/phabricator_import/conduit/response_spec.rb b/spec/lib/gitlab/phabricator_import/conduit/response_spec.rb index a8596968f14..1ffb811cbc1 100644 --- a/spec/lib/gitlab/phabricator_import/conduit/response_spec.rb +++ b/spec/lib/gitlab/phabricator_import/conduit/response_spec.rb @@ -2,8 +2,8 @@ require 'spec_helper' describe Gitlab::PhabricatorImport::Conduit::Response do - let(:response) { described_class.new(JSON.parse(fixture_file('phabricator_responses/maniphest.search.json')))} - let(:error_response) { described_class.new(JSON.parse(fixture_file('phabricator_responses/auth_failed.json'))) } + let(:response) { described_class.new(Gitlab::Json.parse(fixture_file('phabricator_responses/maniphest.search.json')))} + let(:error_response) { described_class.new(Gitlab::Json.parse(fixture_file('phabricator_responses/auth_failed.json'))) } describe '.parse!' do it 'raises a ResponseError if the http response was not successfull' do diff --git a/spec/lib/gitlab/phabricator_import/conduit/tasks_response_spec.rb b/spec/lib/gitlab/phabricator_import/conduit/tasks_response_spec.rb index 4b4c2a6276e..2cc12ee0165 100644 --- a/spec/lib/gitlab/phabricator_import/conduit/tasks_response_spec.rb +++ b/spec/lib/gitlab/phabricator_import/conduit/tasks_response_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' describe Gitlab::PhabricatorImport::Conduit::TasksResponse do let(:conduit_response) do Gitlab::PhabricatorImport::Conduit::Response - .new(JSON.parse(fixture_file('phabricator_responses/maniphest.search.json'))) + .new(Gitlab::Json.parse(fixture_file('phabricator_responses/maniphest.search.json'))) end subject(:response) { described_class.new(conduit_response) } diff --git a/spec/lib/gitlab/phabricator_import/conduit/users_response_spec.rb b/spec/lib/gitlab/phabricator_import/conduit/users_response_spec.rb index 00778ad90fd..999a986b73c 100644 --- a/spec/lib/gitlab/phabricator_import/conduit/users_response_spec.rb +++ b/spec/lib/gitlab/phabricator_import/conduit/users_response_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' describe Gitlab::PhabricatorImport::Conduit::UsersResponse do let(:conduit_response) do Gitlab::PhabricatorImport::Conduit::Response - .new(JSON.parse(fixture_file('phabricator_responses/user.search.json'))) + .new(Gitlab::Json.parse(fixture_file('phabricator_responses/user.search.json'))) end subject(:response) { described_class.new(conduit_response) } diff --git a/spec/lib/gitlab/phabricator_import/issues/importer_spec.rb b/spec/lib/gitlab/phabricator_import/issues/importer_spec.rb index 667321409da..02dafd4bb3b 100644 --- a/spec/lib/gitlab/phabricator_import/issues/importer_spec.rb +++ b/spec/lib/gitlab/phabricator_import/issues/importer_spec.rb @@ -7,7 +7,7 @@ describe Gitlab::PhabricatorImport::Issues::Importer do let(:response) do Gitlab::PhabricatorImport::Conduit::TasksResponse.new( Gitlab::PhabricatorImport::Conduit::Response - .new(JSON.parse(fixture_file('phabricator_responses/maniphest.search.json'))) + .new(Gitlab::Json.parse(fixture_file('phabricator_responses/maniphest.search.json'))) ) end diff --git a/spec/lib/gitlab/prometheus_client_spec.rb b/spec/lib/gitlab/prometheus_client_spec.rb index e869a384b29..4ff53b50a50 100644 --- a/spec/lib/gitlab/prometheus_client_spec.rb +++ b/spec/lib/gitlab/prometheus_client_spec.rb @@ -313,7 +313,7 @@ describe Gitlab::PrometheusClient do req_stub = stub_prometheus_request(query_url, body: prometheus_value_body('vector')) response = subject.proxy('query', { query: prometheus_query }) - json_response = JSON.parse(response.body) + json_response = Gitlab::Json.parse(response.body) expect(response.code).to eq(200) expect(json_response).to eq({ @@ -332,7 +332,7 @@ describe Gitlab::PrometheusClient do req_stub = stub_prometheus_request(query_url, status: 400, body: { error: 'error' }) response = subject.proxy('query', { query: prometheus_query }) - json_response = JSON.parse(response.body) + json_response = Gitlab::Json.parse(response.body) expect(req_stub).to have_been_requested expect(response.code).to eq(400) diff --git a/spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb b/spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb index 2f5343627d8..8c55cc21f2c 100644 --- a/spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb +++ b/spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb @@ -9,7 +9,7 @@ describe Gitlab::SidekiqLogging::JSONFormatter do let(:timestamp_iso8601) { now.iso8601(3) } describe 'with a Hash' do - subject { JSON.parse(described_class.new.call('INFO', now, 'my program', hash_input)) } + subject { Gitlab::Json.parse(described_class.new.call('INFO', now, 'my program', hash_input)) } let(:hash_input) do { @@ -63,7 +63,7 @@ describe Gitlab::SidekiqLogging::JSONFormatter do it 'accepts strings with no changes' do result = subject.call('DEBUG', now, 'my string', message) - data = JSON.parse(result) + data = Gitlab::Json.parse(result) expected_output = { severity: 'DEBUG', time: timestamp_iso8601, diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb index d12a2823d0e..53b6f461a48 100644 --- a/spec/lib/gitlab/workhorse_spec.rb +++ b/spec/lib/gitlab/workhorse_spec.rb @@ -9,7 +9,7 @@ describe Gitlab::Workhorse do def decode_workhorse_header(array) key, value = array command, encoded_params = value.split(":") - params = JSON.parse(Base64.urlsafe_decode64(encoded_params)) + params = Gitlab::Json.parse(Base64.urlsafe_decode64(encoded_params)) [key, command, params] end diff --git a/spec/lib/grafana/validator_spec.rb b/spec/lib/grafana/validator_spec.rb index 603e27fd0c0..a048a1f3470 100644 --- a/spec/lib/grafana/validator_spec.rb +++ b/spec/lib/grafana/validator_spec.rb @@ -3,8 +3,8 @@ require 'spec_helper' describe Grafana::Validator do - let(:grafana_dashboard) { JSON.parse(fixture_file('grafana/simplified_dashboard_response.json'), symbolize_names: true) } - let(:datasource) { JSON.parse(fixture_file('grafana/datasource_response.json'), symbolize_names: true) } + let(:grafana_dashboard) { Gitlab::Json.parse(fixture_file('grafana/simplified_dashboard_response.json'), symbolize_names: true) } + let(:datasource) { Gitlab::Json.parse(fixture_file('grafana/datasource_response.json'), symbolize_names: true) } let(:panel) { grafana_dashboard[:dashboard][:panels].first } let(:query_params) do diff --git a/spec/lib/rspec_flaky/report_spec.rb b/spec/lib/rspec_flaky/report_spec.rb index 1f0eff83db0..37330f39e1c 100644 --- a/spec/lib/rspec_flaky/report_spec.rb +++ b/spec/lib/rspec_flaky/report_spec.rb @@ -31,7 +31,7 @@ describe RspecFlaky::Report, :aggregate_failures do describe '.load' do let!(:report_file) do Tempfile.new(%w[rspec_flaky_report .json]).tap do |f| - f.write(JSON.pretty_generate(suite_flaky_example_report)) + f.write(Gitlab::Json.pretty_generate(suite_flaky_example_report)) f.rewind end end @@ -48,7 +48,7 @@ describe RspecFlaky::Report, :aggregate_failures do describe '.load_json' do let(:report_json) do - JSON.pretty_generate(suite_flaky_example_report) + Gitlab::Json.pretty_generate(suite_flaky_example_report) end it 'loads the report file' do @@ -103,7 +103,7 @@ describe RspecFlaky::Report, :aggregate_failures do expect(File.exist?(report_file_path)).to be(true) expect(File.read(report_file_path)) - .to eq(JSON.pretty_generate(report.flaky_examples.to_h)) + .to eq(Gitlab::Json.pretty_generate(report.flaky_examples.to_h)) end end end diff --git a/spec/lib/sentry/client/event_spec.rb b/spec/lib/sentry/client/event_spec.rb index c8604d72ada..58891895bfa 100644 --- a/spec/lib/sentry/client/event_spec.rb +++ b/spec/lib/sentry/client/event_spec.rb @@ -18,7 +18,7 @@ describe Sentry::Client do describe '#issue_latest_event' do let(:sample_response) do Gitlab::Utils.deep_indifferent_access( - JSON.parse(fixture_file('sentry/issue_latest_event_sample_response.json')) + Gitlab::Json.parse(fixture_file('sentry/issue_latest_event_sample_response.json')) ) end let(:issue_id) { '1234' } diff --git a/spec/lib/sentry/client/issue_link_spec.rb b/spec/lib/sentry/client/issue_link_spec.rb index 3434e93365e..293937f6100 100644 --- a/spec/lib/sentry/client/issue_link_spec.rb +++ b/spec/lib/sentry/client/issue_link_spec.rb @@ -16,7 +16,7 @@ describe Sentry::Client::IssueLink do let(:sentry_issue_link_url) { "https://sentrytest.gitlab.com/api/0/groups/#{sentry_issue_id}/integrations/#{integration_id}/" } let(:integration_id) { 44444 } - let(:issue_link_sample_response) { JSON.parse(fixture_file('sentry/global_integration_link_sample_response.json')) } + let(:issue_link_sample_response) { Gitlab::Json.parse(fixture_file('sentry/global_integration_link_sample_response.json')) } let(:sentry_api_response) { issue_link_sample_response } let!(:sentry_api_request) { stub_sentry_request(sentry_issue_link_url, :put, body: sentry_api_response, status: 201) } @@ -42,7 +42,7 @@ describe Sentry::Client::IssueLink do let(:sentry_issue_link_url) { "https://sentrytest.gitlab.com/api/0/issues/#{sentry_issue_id}/plugins/gitlab/link/" } let(:integration_id) { nil } - let(:issue_link_sample_response) { JSON.parse(fixture_file('sentry/plugin_link_sample_response.json')) } + let(:issue_link_sample_response) { Gitlab::Json.parse(fixture_file('sentry/plugin_link_sample_response.json')) } let!(:sentry_api_request) { stub_sentry_request(sentry_issue_link_url, :post, body: sentry_api_response) } it_behaves_like 'calls sentry api' diff --git a/spec/lib/sentry/client/issue_spec.rb b/spec/lib/sentry/client/issue_spec.rb index 0f57d38d290..b683ad6d4a9 100644 --- a/spec/lib/sentry/client/issue_spec.rb +++ b/spec/lib/sentry/client/issue_spec.rb @@ -23,7 +23,7 @@ describe Sentry::Client::Issue do let(:issues_sample_response) do Gitlab::Utils.deep_indifferent_access( - JSON.parse(fixture_file('sentry/issues_sample_response.json')) + Gitlab::Json.parse(fixture_file('sentry/issues_sample_response.json')) ) end @@ -201,7 +201,7 @@ describe Sentry::Client::Issue do describe '#issue_details' do let(:issue_sample_response) do Gitlab::Utils.deep_indifferent_access( - JSON.parse(fixture_file('sentry/issue_sample_response.json')) + Gitlab::Json.parse(fixture_file('sentry/issue_sample_response.json')) ) end diff --git a/spec/lib/sentry/client/projects_spec.rb b/spec/lib/sentry/client/projects_spec.rb index 6183d4c5816..1b5bbb8f81a 100644 --- a/spec/lib/sentry/client/projects_spec.rb +++ b/spec/lib/sentry/client/projects_spec.rb @@ -10,7 +10,7 @@ describe Sentry::Client::Projects do let(:client) { Sentry::Client.new(sentry_url, token) } let(:projects_sample_response) do Gitlab::Utils.deep_indifferent_access( - JSON.parse(fixture_file('sentry/list_projects_sample_response.json')) + Gitlab::Json.parse(fixture_file('sentry/list_projects_sample_response.json')) ) end diff --git a/spec/lib/sentry/client/repo_spec.rb b/spec/lib/sentry/client/repo_spec.rb index 7bc2811ef03..524dca8dcf6 100644 --- a/spec/lib/sentry/client/repo_spec.rb +++ b/spec/lib/sentry/client/repo_spec.rb @@ -8,7 +8,7 @@ describe Sentry::Client::Repo do let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' } let(:token) { 'test-token' } let(:client) { Sentry::Client.new(sentry_url, token) } - let(:repos_sample_response) { JSON.parse(fixture_file('sentry/repos_sample_response.json')) } + let(:repos_sample_response) { Gitlab::Json.parse(fixture_file('sentry/repos_sample_response.json')) } describe '#repos' do let(:organization_slug) { 'gitlab' } diff --git a/spec/lib/serializers/json_spec.rb b/spec/lib/serializers/json_spec.rb index a8d82d70e89..dfe85d3f362 100644 --- a/spec/lib/serializers/json_spec.rb +++ b/spec/lib/serializers/json_spec.rb @@ -15,7 +15,7 @@ describe Serializers::JSON do describe '.load' do let(:data_string) { '{"key":"value","variables":[{"key":"VAR1","value":"VALUE1"}]}' } - let(:data_hash) { JSON.parse(data_string) } + let(:data_hash) { Gitlab::Json.parse(data_string) } context 'when loading a hash' do subject { described_class.load(data_hash) } diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb index ee4c35ebddd..e6544fda640 100644 --- a/spec/models/milestone_spec.rb +++ b/spec/models/milestone_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' describe Milestone do + it_behaves_like 'a timebox', :milestone + describe 'MilestoneStruct#serializable_hash' do let(:predefined_milestone) { described_class::MilestoneStruct.new('Test Milestone', '#test', 1) } @@ -15,69 +17,11 @@ describe Milestone do end end - describe 'modules' do - context 'with a project' do - it_behaves_like 'AtomicInternalId' do - let(:internal_id_attribute) { :iid } - let(:instance) { build(:milestone, project: build(: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: build(:group)) } - let(:scope) { :group } - let(:scope_attrs) { { namespace: instance.group } } - let(:usage) { :milestones } - end - end - end - describe "Validation" do before do allow(subject).to receive(:set_iid).and_return(false) end - describe 'start_date' do - it 'adds an error when start_date is greater then due_date' do - milestone = build(:milestone, start_date: Date.tomorrow, due_date: Date.yesterday) - - expect(milestone).not_to be_valid - expect(milestone.errors[:due_date]).to include("must be greater than start date") - end - - it 'adds an error when start_date is greater than 9999-12-31' do - milestone = build(:milestone, start_date: Date.new(10000, 1, 1)) - - expect(milestone).not_to be_valid - expect(milestone.errors[:start_date]).to include("date must not be after 9999-12-31") - end - end - - describe 'due_date' do - it 'adds an error when due_date is greater than 9999-12-31' do - milestone = build(:milestone, due_date: Date.new(10000, 1, 1)) - - expect(milestone).not_to be_valid - expect(milestone.errors[:due_date]).to include("date must not be after 9999-12-31") - end - end - - describe 'title' do - it { is_expected.to validate_presence_of(:title) } - - it 'is invalid if title would be empty after sanitation' do - milestone = build(:milestone, project: project, title: '<img src=x onerror=prompt(1)>') - - expect(milestone).not_to be_valid - expect(milestone.errors[:title]).to include("can't be blank") - end - end - describe 'milestone_releases' do let(:milestone) { build(:milestone, project: project) } @@ -99,8 +43,6 @@ describe Milestone do end describe "Associations" do - it { is_expected.to belong_to(:project) } - it { is_expected.to have_many(:issues) } it { is_expected.to have_many(:releases) } it { is_expected.to have_many(:milestone_releases) } end @@ -110,87 +52,6 @@ describe Milestone do let(:issue) { create(:issue, project: project) } let(:user) { create(:user) } - describe "#title" do - let(:milestone) { create(:milestone, title: "<b>foo & bar -> 2.2</b>") } - - it "sanitizes title" do - expect(milestone.title).to eq("foo & bar -> 2.2") - 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) - milestone = create(:milestone, project: project) - - expect(milestone.merge_requests_enabled?).to be(true) - end - - it "is false for projects with MRs disabled" do - project = create(:project, :repository_enabled, :merge_requests_disabled) - milestone = create(:milestone, project: project) - - expect(milestone.merge_requests_enabled?).to be(false) - end - - it "is false for projects with repository disabled" do - project = create(:project, :repository_disabled) - milestone = create(:milestone, project: project) - - expect(milestone.merge_requests_enabled?).to be(false) - end - end - - context "per group" do - let(:group) { create(:group) } - let(:milestone) { create(:milestone, group: group) } - - it "is always true for groups, for performance reasons" do - expect(milestone.merge_requests_enabled?).to be(true) - end - end - end - - describe "unique milestone title" do - context "per project" do - it "does not accept the same title in a project twice" do - new_milestone = described_class.new(project: milestone.project, title: milestone.title) - expect(new_milestone).not_to be_valid - end - - it "accepts the same title in another project" do - project = create(:project) - new_milestone = described_class.new(project: project, title: milestone.title) - - expect(new_milestone).to be_valid - end - end - - context "per group" do - let(:group) { create(:group) } - let(:milestone) { create(:milestone, group: group) } - - before do - project.update(group: group) - end - - it "does not accept the same title in a group twice" do - new_milestone = described_class.new(group: group, title: milestone.title) - - expect(new_milestone).not_to be_valid - end - - it "does not accept the same title of a child project milestone" do - create(:milestone, project: group.projects.first) - - new_milestone = described_class.new(group: group, title: milestone.title) - - expect(new_milestone).not_to be_valid - end - end - end - describe '.predefined_id?' do it 'returns true for a predefined Milestone ID' do expect(Milestone.predefined_id?(described_class::Upcoming.id)).to be true diff --git a/spec/models/sprint_spec.rb b/spec/models/sprint_spec.rb index 965e711a51c..fb3136764cd 100644 --- a/spec/models/sprint_spec.rb +++ b/spec/models/sprint_spec.rb @@ -3,39 +3,12 @@ require 'spec_helper' describe Sprint do - let!(:project) { create(:project) } - let!(:group) { create(:group) } - - describe 'modules' do - context 'with a project' do - it_behaves_like 'AtomicInternalId' do - let(:internal_id_attribute) { :iid } - let(:instance) { build(:sprint, project: build(:project), group: nil) } - let(:scope) { :project } - let(:scope_attrs) { { project: instance.project } } - let(:usage) {:sprints } - end - end - - context 'with a group' do - it_behaves_like 'AtomicInternalId' do - let(:internal_id_attribute) { :iid } - let(:instance) { build(:sprint, project: nil, group: build(:group)) } - let(:scope) { :group } - let(:scope_attrs) { { namespace: instance.group } } - let(:usage) {:sprints } - 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) } - end + it_behaves_like 'a timebox', :sprint describe "#iid" do + let!(:project) { create(:project) } + let!(:group) { create(:group) } + it "is properly scoped on project and group" do sprint1 = create(:sprint, project: project) sprint2 = create(:sprint, project: project) diff --git a/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb b/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb new file mode 100644 index 00000000000..4f61599bb51 --- /dev/null +++ b/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb @@ -0,0 +1,250 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'a timebox' do |timebox_type| + let(:project) { create(:project, :public) } + let(:group) { create(:group) } + let(:timebox) { create(timebox_type, project: project) } + let(:issue) { create(:issue, project: project) } + let(:user) { create(:user) } + let(:timebox_table_name) { timebox_type.to_s.pluralize.to_sym } + + describe 'modules' do + context 'with a project' do + it_behaves_like 'AtomicInternalId' do + let(:internal_id_attribute) { :iid } + let(:instance) { build(timebox_type, project: build(: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, project: nil, group: build(: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) + end + + describe 'start_date' do + it 'adds an error when start_date is greater then due_date' do + timebox = build(timebox_type, start_date: Date.tomorrow, due_date: Date.yesterday) + + expect(timebox).not_to be_valid + expect(timebox.errors[:due_date]).to include("must be greater than start date") + end + + it 'adds an error when start_date is greater than 9999-12-31' do + timebox = build(timebox_type, start_date: Date.new(10000, 1, 1)) + + expect(timebox).not_to be_valid + expect(timebox.errors[:start_date]).to include("date must not be after 9999-12-31") + end + end + + describe 'due_date' do + it 'adds an error when due_date is greater than 9999-12-31' do + timebox = build(timebox_type, due_date: Date.new(10000, 1, 1)) + + expect(timebox).not_to be_valid + expect(timebox.errors[:due_date]).to include("date must not be after 9999-12-31") + end + end + + describe 'title' do + it { is_expected.to validate_presence_of(:title) } + + it 'is invalid if title would be empty after sanitation' do + timebox = build(timebox_type, project: project, title: '<img src=x onerror=prompt(1)>') + + expect(timebox).not_to be_valid + expect(timebox.errors[:title]).to include("can't be blank") + end + end + + describe '#timebox_type_check' do + it 'is invalid if it has both project_id and group_id' do + timebox = build(timebox_type, 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 + + describe "#uniqueness_of_title" do + context "per project" do + it "does not accept the same title in a project twice" do + new_timebox = described_class.new(project: timebox.project, title: timebox.title) + expect(new_timebox).not_to be_valid + end + + it "accepts the same title in another project" do + project = create(:project) + new_timebox = described_class.new(project: project, title: timebox.title) + + expect(new_timebox).to be_valid + end + end + + context "per group" do + let(:timebox) { create(timebox_type, group: group) } + + before do + project.update(group: group) + end + + it "does not accept the same title in a group twice" do + new_timebox = described_class.new(group: group, title: timebox.title) + + expect(new_timebox).not_to be_valid + end + + it "does not accept the same title of a child project timebox" do + create(timebox_type, project: group.projects.first) + + new_timebox = described_class.new(group: group, title: timebox.title) + + expect(new_timebox).not_to be_valid + end + 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) } + end + + describe '#timebox_name' do + it 'returns the name of the model' do + expect(timebox.timebox_name).to eq(timebox_type.to_s) + 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, 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, 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, title: "<b>foo & bar -> 2.2</b>") } + + it 'normalizes the title for use as a slug' do + expect(timebox.safe_title).to eq('foo-bar-22') + end + end + + describe '#resource_parent' do + context 'when group is present' do + let(:timebox) { build(timebox_type, 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, title: "<b>foo & bar -> 2.2</b>") } + + it "sanitizes title" do + expect(timebox.title).to eq("foo & bar -> 2.2") + 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, 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, 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, project: project) + + expect(timebox.merge_requests_enabled?).to be_falsey + end + end + + context "per group" do + let(:timebox) { create(timebox_type, group: group) } + + it "is always true for groups, for performance reasons" do + expect(timebox.merge_requests_enabled?).to be_truthy + end + 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(timebox_type, project: project, start_date: now - 1.day, due_date: now + 1.day) } + let_it_be(:resource_2) { create(timebox_type, project: project, start_date: now + 2.days, due_date: now + 3.days) } + let_it_be(:resource_3) { create(timebox_type, project: project, due_date: now) } + let_it_be(:resource_4) { create(timebox_type, project: project, start_date: now) } + end + + describe '#to_ability_name' do + it 'returns timebox' do + timebox = build(timebox_type) + + expect(timebox.to_ability_name).to eq(timebox_type.to_s) + end + end +end |