diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-03 03:08:02 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-03 03:08:02 +0000 |
commit | 173b547fb98ab12ae41f295915453e598be3a647 (patch) | |
tree | 2ade7b72b501275292e6984c6cba2cbaba9d9aa6 /qa | |
parent | a77c9fccd057514a8b78a10642779f54a22f3f76 (diff) | |
download | gitlab-ce-173b547fb98ab12ae41f295915453e598be3a647.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'qa')
-rw-r--r-- | qa/qa/page/merge_request/show.rb | 5 | ||||
-rw-r--r-- | qa/qa/resource/api_fabricator.rb | 120 | ||||
-rw-r--r-- | qa/qa/resource/base.rb | 35 | ||||
-rw-r--r-- | qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb | 2 | ||||
-rw-r--r-- | qa/qa/tools/test_resource_data_processor.rb | 2 | ||||
-rw-r--r-- | qa/spec/resource/api_fabricator_spec.rb | 2 |
6 files changed, 100 insertions, 66 deletions
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb index 14faa6a2e05..dd26c2c3bf7 100644 --- a/qa/qa/page/merge_request/show.rb +++ b/qa/qa/page/merge_request/show.rb @@ -82,6 +82,7 @@ module QA element :merge_moment_dropdown element :merge_immediately_menu_item element :merged_status_content + element :auto_merge_helper_text end view 'app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue' do @@ -279,7 +280,7 @@ module QA def merge_when_pipeline_succeeds! wait_until_ready_to_merge - click_element(:merge_button, text: 'Merge when pipeline succeeds') + click_element(:merge_button, text: 'Set auto-merge') end def merged? @@ -365,7 +366,7 @@ module QA # Revisit after merge page re-architect is done https://gitlab.com/gitlab-org/gitlab/-/issues/300042 # To remove page refresh logic if possible wait_until_ready_to_merge - wait_until { !find_element(:merge_button).text.include?('when pipeline succeeds') } # rubocop:disable Rails/NegateInclude + wait_until { !has_element?(:auto_merge_helper_text) || !find_element(:auto_merge_helper_text).text.include?('when pipeline succeeds') } # rubocop:disable Rails/NegateInclude click_element(:merge_button) end diff --git a/qa/qa/resource/api_fabricator.rb b/qa/qa/resource/api_fabricator.rb index d7a220bc83f..cbb68cccdf1 100644 --- a/qa/qa/resource/api_fabricator.rb +++ b/qa/qa/resource/api_fabricator.rb @@ -10,6 +10,7 @@ module QA include Support::API include Errors + attr_reader :api_fabrication_http_method attr_writer :api_client attr_accessor :api_user, :api_resource, :api_response @@ -49,22 +50,6 @@ module QA end end - def api_put(body = api_put_body) - response = put( - Runtime::API::Request.new(api_client, api_put_path).url, - body) - - unless response.code == HTTP_STATUS_OK - raise ResourceFabricationFailedError, "Updating #{self.class.name} using the API failed (#{response.code}) with `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}" - end - - process_api_response(parse_body(response)) - end - - def api_fabrication_http_method - @api_fabrication_http_method ||= :post - end - # Checks if a resource already exists # # @return [Boolean] true if the resource returns HTTP status code 200 @@ -84,14 +69,15 @@ module QA private - def resource_web_url(resource) - resource.fetch(:web_url) do - raise ResourceURLMissingError, "API resource for #{self.class.name} does not expose a `web_url` property: `#{resource}`." - end - end - + # rubocop:disable Gitlab/ModuleWithInstanceVariables def api_get - process_api_response(parse_body(api_get_from(api_get_path))) + process_api_response(parse_body(api_get_from(api_get_path))).tap do + # Record method that was used to create certain resource + # :get - resource already existed in GitLab instance and was fetched via get request + # :post - resource was created from scratch using post request + # :put - resource was created from scratch using put request + @api_fabrication_http_method ||= :get + end end def api_get_from(get_path) @@ -100,27 +86,24 @@ module QA response = get(request.url) if response.code == HTTP_STATUS_SERVER_ERROR - raise InternalServerError, "Failed to GET #{request.mask_url} - (#{response.code}): `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}" + raise(InternalServerError, <<~MSG.strip) + Failed to GET #{request.mask_url} - (#{response.code}): `#{response}`. + #{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])} + MSG elsif response.code != HTTP_STATUS_OK - raise ResourceNotFoundError, "Resource at #{request.mask_url} could not be found (#{response.code}): `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}" + raise(ResourceNotFoundError, <<~MSG.strip) + Resource at #{request.mask_url} could not be found (#{response.code}): `#{response}`. + #{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])} + MSG end - @api_fabrication_http_method ||= :get # rubocop:disable Gitlab/ModuleWithInstanceVariables - response end - # Query parameters formatted as `?key1=value1&key2=value2...` - # - # @return [String] - def query_parameters_to_string - query_parameters.each_with_object([]) do |(k, v), arr| - arr << "#{k}=#{v}" - end.join('&').prepend('?').chomp('?') # prepend `?` unless the string is blank - end - def api_post - process_api_response(api_post_to(api_post_path, api_post_body)) + process_api_response(api_post_to(api_post_path, api_post_body)).tap do + @api_fabrication_http_method ||= :post + end end def api_post_to(post_path, post_body, args = {}) @@ -131,7 +114,7 @@ module QA body = flatten_hash(parse_body(graphql_response)) unless graphql_response.code == HTTP_STATUS_OK && (body[:errors].nil? || body[:errors].empty?) - raise(ResourceFabricationFailedError, <<~MSG) + raise(ResourceFabricationFailedError, <<~MSG.strip) Fabrication of #{self.class.name} using the API failed (#{graphql_response.code}) with `#{graphql_response}`. #{QA::Support::Loglinking.failure_metadata(graphql_response.headers[:x_request_id])} MSG @@ -144,36 +127,64 @@ module QA response = post(Runtime::API::Request.new(api_client, post_path).url, post_body, args) unless response.code == HTTP_STATUS_CREATED - raise( - ResourceFabricationFailedError, - "Fabrication of #{self.class.name} using the API failed (#{response.code}) with `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}" - ) + raise(ResourceFabricationFailedError, <<~MSG.strip) + Fabrication of #{self.class.name} using the API failed (#{response.code}) with `#{response}`. + #{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])} + MSG end parse_body(response) end end - def flatten_hash(param) - param.each_pair.reduce({}) do |a, (k, v)| - v.is_a?(Hash) ? a.merge(flatten_hash(v)) : a.merge(k.to_sym => v) + def api_put + process_api_response(api_put_to(api_put_path, api_put_body)).tap do + @api_fabrication_http_method ||= :put end end + def api_put_to(put_path, body) + response = put(Runtime::API::Request.new(api_client, put_path).url, body) + + unless response.code == HTTP_STATUS_OK + raise(ResourceFabricationFailedError, <<~MSG.strip) + Updating #{self.class.name} using the API failed (#{response.code}) with `#{response}`. + #{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])} + MSG + end + + parse_body(response) + end + def api_delete request = Runtime::API::Request.new(api_client, api_delete_path) response = delete(request.url) unless [HTTP_STATUS_NO_CONTENT, HTTP_STATUS_ACCEPTED].include? response.code - raise ResourceNotDeletedError, "Resource at #{request.mask_url} could not be deleted (#{response.code}): `#{response}`.\n#{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])}" + raise(ResourceNotDeletedError, <<~MSG.strip) + Resource at #{request.mask_url} could not be deleted (#{response.code}): `#{response}`. + #{QA::Support::Loglinking.failure_metadata(response.headers[:x_request_id])} + MSG end response end + def resource_web_url(resource) + resource.fetch(:web_url) do + raise ResourceURLMissingError, + "API resource for #{self.class.name} does not expose a `web_url` property: `#{resource}`." + end + end + def api_client - @api_client ||= Runtime::API::Client.new(:gitlab, is_new_session: !current_url.start_with?('http'), user: api_user) + @api_client ||= Runtime::API::Client.new( + :gitlab, + is_new_session: !current_url.start_with?('http'), + user: api_user + ) end + # rubocop:enable Gitlab/ModuleWithInstanceVariables def process_api_response(parsed_response) self.api_response = parsed_response @@ -191,6 +202,21 @@ module QA def request_url(path, **opts) Runtime::API::Request.new(api_client, path, **opts).url end + + # Query parameters formatted as `?key1=value1&key2=value2...` + # + # @return [String] + def query_parameters_to_string + query_parameters.each_with_object([]) do |(k, v), arr| + arr << "#{k}=#{v}" + end.join('&').prepend('?').chomp('?') # prepend `?` unless the string is blank + end + + def flatten_hash(param) + param.each_pair.reduce({}) do |a, (k, v)| + v.is_a?(Hash) ? a.merge(flatten_hash(v)) : a.merge(k.to_sym => v) + end + end end end end diff --git a/qa/qa/resource/base.rb b/qa/qa/resource/base.rb index 2abe1904c92..6c03f45bdfd 100644 --- a/qa/qa/resource/base.rb +++ b/qa/qa/resource/base.rb @@ -45,7 +45,7 @@ module QA resource = options.fetch(:resource) { new } parents = options.fetch(:parents) { [] } - do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do + do_fabricate!(resource: resource, prepare_block: prepare_block) do log_and_record_fabrication(:browser_ui, resource, parents, args) { resource.fabricate!(*args) } current_url @@ -61,7 +61,7 @@ module QA resource.eager_load_api_client! - do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do + do_fabricate!(resource: resource, prepare_block: prepare_block) do log_and_record_fabrication(:api, resource, parents, args) { resource.fabricate_via_api! } end end @@ -73,14 +73,14 @@ module QA resource.eager_load_api_client! - do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do + do_fabricate!(resource: resource, prepare_block: prepare_block) do log_and_record_fabrication(:api, resource, parents, args) { resource.remove_via_api! } end end private - def do_fabricate!(resource:, prepare_block:, parents: []) + def do_fabricate!(resource:, prepare_block:) prepare_block.call(resource) if prepare_block resource_web_url = yield @@ -89,17 +89,12 @@ module QA resource end - def log_and_record_fabrication(fabrication_method, resource, parents, args) + def log_and_record_fabrication(fabrication_method, resource, parents, _args) start = Time.now Support::FabricationTracker.start_fabrication result = yield.tap do fabrication_time = Time.now - start - fabrication_http_method = if resource.api_fabrication_http_method == :get || resource.retrieved_from_cache - "Retrieved" - else - "Built" - end Support::FabricationTracker.save_fabrication(:"#{fabrication_method}_fabrication", fabrication_time) @@ -114,7 +109,7 @@ module QA Runtime::Logger.info do msg = ["==#{'=' * parents.size}>"] - msg << "#{fabrication_http_method} a #{Rainbow(name).black.bg(:white)}" + msg << "#{fabrication_type(resource, fabrication_method)} a #{Rainbow(name).black.bg(:white)}" msg << resource.identifier msg << "as a dependency of #{parents.last}" if parents.any? msg << "via #{resource.retrieved_from_cache ? 'cache' : fabrication_method}" @@ -129,6 +124,19 @@ module QA result end + # Fetch type of fabrication, either resource was built or fetched + # + # @param [Resource] resource + # @param [Symbol] method + # @return [String] + def fabrication_type(resource, method) + return "Built" if method == :browser_ui || [:post, :put].include?(resource.api_fabrication_http_method) + return "Retrieved" if resource.api_fabrication_http_method == :get || resource.retrieved_from_cache + + Runtime::Logger.warn("Resource fabrication http method has not been set properly, assuming :get value!") + "Built" + end + # Define custom attribute # # @param [Symbol] name @@ -215,8 +223,7 @@ module QA def diff(other) return if self == other - diff_values = self.comparable.to_a - other.comparable.to_a - diff_values.to_h + (comparable.to_a - other.comparable.to_a).to_h end def identifier @@ -271,7 +278,7 @@ module QA def all_attributes @all_attributes ||= self.class.ancestors .select { |clazz| clazz <= QA::Resource::Base } - .map { |clazz| clazz.instance_variable_get(:@attribute_names) } + .map { |clazz| clazz.instance_variable_get(:@attribute_names) } # rubocop:disable Performance/FlatMap .flatten .compact end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb index 1b82543a5d4..366ced10af0 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb @@ -79,7 +79,7 @@ module QA mr.retry_until(reload: true, message: 'Wait until ready to click MWPS') do # Click the MWPS button if we can - break mr.merge_when_pipeline_succeeds! if mr.has_element?(:merge_button, text: 'Merge when pipeline succeeds') + break mr.merge_when_pipeline_succeeds! if mr.has_element?(:merge_button, text: 'Set auto-merge') # But fail if the button is missing because the pipeline is complete raise "The pipeline already finished before we could click MWPS" if mr.wait_until { project.pipelines.first }[:status] == 'success' diff --git a/qa/qa/tools/test_resource_data_processor.rb b/qa/qa/tools/test_resource_data_processor.rb index a86c94b4914..3312285ecc4 100644 --- a/qa/qa/tools/test_resource_data_processor.rb +++ b/qa/qa/tools/test_resource_data_processor.rb @@ -38,7 +38,7 @@ module QA api_path: api_path, fabrication_method: fabrication_method, fabrication_time: fabrication_time, - http_method: resource.api_fabrication_http_method, + http_method: resource.api_fabrication_http_method || :post, timestamp: Time.now.to_s } end diff --git a/qa/spec/resource/api_fabricator_spec.rb b/qa/spec/resource/api_fabricator_spec.rb index 337c6772a06..96823ea7ada 100644 --- a/qa/spec/resource/api_fabricator_spec.rb +++ b/qa/spec/resource/api_fabricator_spec.rb @@ -116,7 +116,7 @@ RSpec.describe QA::Resource::ApiFabricator do expect { subject.fabricate_via_api! }.to raise_error do |error| expect(error.class).to eql(described_class::ResourceFabricationFailedError) - expect(error.to_s).to eql(<<~ERROR.chomp) + expect(error.to_s).to eql(<<~ERROR.strip) Fabrication of FooBarResource using the API failed (400) with `#{raw_post}`.\n ERROR end |