diff options
Diffstat (limited to 'qa/qa/resource')
-rw-r--r-- | qa/qa/resource/clusters/agent_token.rb | 2 | ||||
-rw-r--r-- | qa/qa/resource/members.rb | 13 | ||||
-rw-r--r-- | qa/qa/resource/merge_request.rb | 10 | ||||
-rw-r--r-- | qa/qa/resource/personal_access_token.rb | 52 | ||||
-rw-r--r-- | qa/qa/resource/project.rb | 14 | ||||
-rw-r--r-- | qa/qa/resource/project_imported_from_github.rb | 4 | ||||
-rw-r--r-- | qa/qa/resource/project_snippet.rb | 6 | ||||
-rw-r--r-- | qa/qa/resource/registry_repository.rb | 53 | ||||
-rw-r--r-- | qa/qa/resource/snippet.rb | 37 | ||||
-rw-r--r-- | qa/qa/resource/user.rb | 15 | ||||
-rw-r--r-- | qa/qa/resource/wiki/group_page.rb | 48 |
11 files changed, 236 insertions, 18 deletions
diff --git a/qa/qa/resource/clusters/agent_token.rb b/qa/qa/resource/clusters/agent_token.rb index 6a5e861b650..3286f46cdb2 100644 --- a/qa/qa/resource/clusters/agent_token.rb +++ b/qa/qa/resource/clusters/agent_token.rb @@ -32,7 +32,7 @@ module QA def api_post_body <<~GQL mutation createToken { - clusterAgentTokenCreate(input: { clusterAgentId: "gid://gitlab/Clusters::Agent/#{agent.id}" }) { + clusterAgentTokenCreate(input: { clusterAgentId: "gid://gitlab/Clusters::Agent/#{agent.id}" name: "token-#{agent.id}" }) { secret # This is the value you need to use on the next step token { createdAt diff --git a/qa/qa/resource/members.rb b/qa/qa/resource/members.rb index a88980f26d8..c8f9feeca15 100644 --- a/qa/qa/resource/members.rb +++ b/qa/qa/resource/members.rb @@ -26,10 +26,23 @@ module QA JSON.parse(get(Runtime::API::Request.new(api_client, api_members_path).url).body) end + def invite_group(group, access_level = AccessLevel::GUEST) + Support::Retrier.retry_until do + QA::Runtime::Logger.debug(%Q[Sharing #{self.class.name} with #{group.name}]) + + response = post Runtime::API::Request.new(api_client, api_share_path).url, { group_id: group.id, group_access: access_level } + response.code == QA::Support::Api::HTTP_STATUS_CREATED + end + end + def api_members_path "#{api_get_path}/members" end + def api_share_path + "#{api_get_path}/share" + end + class AccessLevel NO_ACCESS = 0 MINIMAL_ACCESS = 5 diff --git a/qa/qa/resource/merge_request.rb b/qa/qa/resource/merge_request.rb index fd5f454f134..fb450a61c9a 100644 --- a/qa/qa/resource/merge_request.rb +++ b/qa/qa/resource/merge_request.rb @@ -75,7 +75,7 @@ module QA Page::MergeRequest::New.perform do |new_page| new_page.fill_title(@title) new_page.choose_template(@template) if @template - new_page.fill_description(@description) unless @template + new_page.fill_description(@description) if @description && !@template new_page.choose_milestone(@milestone) if @milestone new_page.assign_to_me if @assignee == 'me' labels.each do |label| @@ -140,6 +140,14 @@ module QA end end + def reload! + # Refabricate so that we can return a new object with updated attributes + self.class.fabricate_via_api! do |resource| + resource.project = project + resource.id = api_resource[:iid] + end + end + private def transform_api_resource(api_resource) diff --git a/qa/qa/resource/personal_access_token.rb b/qa/qa/resource/personal_access_token.rb index 6b2301ba916..59ae8f4de7a 100644 --- a/qa/qa/resource/personal_access_token.rb +++ b/qa/qa/resource/personal_access_token.rb @@ -4,17 +4,59 @@ require 'date' module QA module Resource - ## - # Create a personal access token that can be used by the api - # class PersonalAccessToken < Base attr_accessor :name - attribute :access_token do + # The user for which the personal access token is to be created + # This *could* be different than the api_client.user or the api_user provided by the QA::Resource::ApiFabricator module + attr_writer :user + + attribute :token do Page::Profile::PersonalAccessTokens.perform(&:created_access_token) end + # Only Admins can create PAT via the API. + # If Runtime::Env.admin_personal_access_token is provided, fabricate via the API, + # else, fabricate via the browser. + def fabricate_via_api! + if Runtime::Env.admin_personal_access_token && !@user.nil? + self.api_client = Runtime::API::Client.as_admin + + super + else + fabricate! + end + end + + # When a user is not provided, use default user + def user + @user || Resource::User.default + end + + def api_post_path + "/users/#{user.api_resource[:id]}/personal_access_tokens" + end + + def api_get_path + '/personal_access_tokens' + end + + def api_post_body + { + name: name || 'api-test-token', + scopes: ["api"] + } + end + + def resource_web_url(resource) + super + rescue ResourceURLMissingError + # this particular resource does not expose a web_url property + end + def fabricate! + Flow::Login.sign_in_unless_signed_in(as: user) + Page::Main::Menu.perform(&:click_edit_profile_link) Page::Profile::Menu.perform(&:click_access_tokens) @@ -22,7 +64,7 @@ module QA token_page.fill_token_name(name || 'api-test-token') token_page.check_api # Expire in 2 days just in case the token is created just before midnight - token_page.fill_expiry_date(Date.today + 2) + token_page.fill_expiry_date(Time.now.utc.to_date + 2) token_page.click_create_token_button end end diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb index efb6c2c0591..23e2ec07491 100644 --- a/qa/qa/resource/project.rb +++ b/qa/qa/resource/project.rb @@ -151,6 +151,10 @@ module QA "#{api_get_path}/runners" end + def api_registry_repositories_path + "#{api_get_path}/registry/repositories" + end + def api_commits_path "#{api_get_path}/repository/commits" end @@ -256,6 +260,12 @@ module QA parse_body(response) end + def registry_repositories + response = get Runtime::API::Request.new(api_client, "#{api_registry_repositories_path}").url + + parse_body(response) + end + def repository_branches parse_body(get(Runtime::API::Request.new(api_client, api_repository_branches_path).url)) end @@ -272,10 +282,6 @@ module QA parse_body(get(Runtime::API::Request.new(api_client, api_pipelines_path).url)) end - def share_with_group(invitee, access_level = Resource::Members::AccessLevel::DEVELOPER) - post Runtime::API::Request.new(api_client, "/projects/#{id}/share").url, { group_id: invitee.id, group_access: access_level } - end - private def transform_api_resource(api_resource) diff --git a/qa/qa/resource/project_imported_from_github.rb b/qa/qa/resource/project_imported_from_github.rb index 0b817b345fd..b06a7fe4e3d 100644 --- a/qa/qa/resource/project_imported_from_github.rb +++ b/qa/qa/resource/project_imported_from_github.rb @@ -12,7 +12,7 @@ module QA group.visit! Page::Group::Show.perform(&:go_to_new_project) - go_to_import_tab + go_to_import_page Page::Project::New.perform(&:click_github_link) Page::Project::Import::Github.perform do |import_page| @@ -21,7 +21,7 @@ module QA end end - def go_to_import_tab + def go_to_import_page Page::Project::New.perform(&:click_import_project) end end diff --git a/qa/qa/resource/project_snippet.rb b/qa/qa/resource/project_snippet.rb index c262499664e..9ab4612d117 100644 --- a/qa/qa/resource/project_snippet.rb +++ b/qa/qa/resource/project_snippet.rb @@ -33,12 +33,16 @@ module QA end def api_get_path - "/projects/#{project.id}/snippets/#{snippet_id}" + "/projects/#{project.id}/snippets/#{id}" end def api_post_path "/projects/#{project.id}/snippets" end + + def api_delete_path + "/projects/#{project.id}/snippets/#{id}" + end end end end diff --git a/qa/qa/resource/registry_repository.rb b/qa/qa/resource/registry_repository.rb new file mode 100644 index 00000000000..1e43d93a784 --- /dev/null +++ b/qa/qa/resource/registry_repository.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require 'securerandom' + +module QA + module Resource + class RegistryRepository < Base + attr_accessor :name, + :repository_id + + attribute :project do + Project.fabricate_via_api! do |resource| + resource.name = 'project-with-registry' + resource.description = 'Project with Registry' + end + end + + def initialize + @name = project.path_with_namespace + @repository_id = nil + end + + def fabricate! + end + + def fabricate_via_api! + resource_web_url(api_get) + rescue ResourceNotFoundError + super + end + + def remove_via_api! + registry_repositories = project.registry_repositories + if registry_repositories && !registry_repositories.empty? + this_registry_repository = registry_repositories.find { |registry_repository| registry_repository[:path] == name } + + @repository_id = this_registry_repository[:id] + + QA::Runtime::Logger.debug("Deleting registry '#{name}'") + super + end + end + + def api_delete_path + "/projects/#{project.id}/registry/repositories/#{@repository_id}" + end + + def api_get_path + "/projects/#{project.id}/registry/repositories" + end + end + end +end diff --git a/qa/qa/resource/snippet.rb b/qa/qa/resource/snippet.rb index 6fdcb1cd29b..6423dc7a41c 100644 --- a/qa/qa/resource/snippet.rb +++ b/qa/qa/resource/snippet.rb @@ -3,7 +3,10 @@ module QA module Resource class Snippet < Base - attr_accessor :title, :description, :file_content, :visibility, :file_name, :snippet_id + attr_accessor :title, :description, :file_content, :visibility, :file_name + + attribute :id + attribute :http_url_to_repo def initialize @title = 'New snippet title' @@ -44,13 +47,17 @@ module QA end def api_get_path - "/snippets/#{snippet_id}" + "/snippets/#{id}" end def api_post_path '/snippets' end + def api_put_path + "/snippets/#{id}" + end + def api_post_body { title: title, @@ -60,12 +67,38 @@ module QA } end + def api_delete_path + "/snippets/#{id}" + end + def all_file_contents @files.insert(0, { name: @file_name, content: @file_content }) @files.each do |file| file[:file_path] = file.delete(:name) end end + + def has_file?(file_path) + response = get Runtime::API::Request.new(api_client, api_get_path).url + + raise ResourceNotFoundError, "Request returned (#{response.code}): `#{response}`." if response.code == HTTP_STATUS_NOT_FOUND + + file_output = parse_body(response)[:files] + file_output.any? { |file| file[:path] == file_path } + end + + def change_repository_storage(new_storage) + post_body = { destination_storage_name: new_storage } + response = post Runtime::API::Request.new(api_client, "/snippets/#{id}/repository_storage_moves").url, post_body + + unless response.code.between?(200, 300) + raise ResourceUpdateFailedError, "Could not change repository storage to #{new_storage}. Request returned (#{response.code}): `#{response}`." + end + + wait_until(sleep_interval: 1) { Runtime::API::RepositoryStorageMoves.has_status?(self, 'finished', new_storage) } + rescue Support::Repeater::RepeaterConditionExceededError + raise Runtime::API::RepositoryStorageMoves::RepositoryStorageMovesError, 'Timed out while waiting for the snippet repository storage move to finish' + end end end end diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb index f95a68918dc..d1a310c7c43 100644 --- a/qa/qa/resource/user.rb +++ b/qa/qa/resource/user.rb @@ -5,6 +5,8 @@ require 'securerandom' module QA module Resource class User < Base + InvalidUserError = Class.new(RuntimeError) + attr_reader :unique_id attr_writer :username, :password attr_accessor :admin, :provider, :extern_uid, :expect_fabrication_success @@ -21,6 +23,13 @@ module QA @expect_fabrication_success = true end + def self.default + Resource::User.new.tap do |user| + user.username = Runtime::User.ldap_user? ? Runtime::User.ldap_username : Runtime::User.username + user.password = Runtime::User.ldap_user? ? Runtime::User.ldap_password : Runtime::User.password + end + end + def admin? api_resource&.dig(:is_admin) || false end @@ -28,10 +37,12 @@ module QA def username @username || "qa-user-#{unique_id}" end + alias_method :ldap_username, :username def password @password || 'password' end + alias_method :ldap_password, :password def name @name ||= api_resource&.dig(:name) || "QA User #{unique_id}" @@ -138,8 +149,8 @@ module QA return {} unless extern_uid && provider { - extern_uid: extern_uid, - provider: provider + extern_uid: extern_uid, + provider: provider } end diff --git a/qa/qa/resource/wiki/group_page.rb b/qa/qa/resource/wiki/group_page.rb new file mode 100644 index 00000000000..27150ecf6c7 --- /dev/null +++ b/qa/qa/resource/wiki/group_page.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require 'securerandom' + +module QA + module Resource + module Wiki + class GroupPage < Base + attribute :title + attribute :content + attribute :slug + + attribute :group do + Group.fabricate_via_api! do |group| + group.path = "group-with-wiki-#{SecureRandom.hex(8)}" + end + end + + def initialize + @title = 'Home' + @content = 'This wiki page is created via API' + end + + def resource_web_url(resource) + super + rescue ResourceURLMissingError + "#{group.web_url}/-/wikis/#{slug}" + end + + def api_get_path + "/groups/#{group.id}/wikis/#{slug}" + end + + def api_post_path + "/groups/#{group.id}/wikis" + end + + def api_post_body + { + id: group.id, + content: content, + title: title + } + end + end + end + end +end |