summaryrefslogtreecommitdiff
path: root/qa/qa/resource
diff options
context:
space:
mode:
Diffstat (limited to 'qa/qa/resource')
-rw-r--r--qa/qa/resource/clusters/agent_token.rb2
-rw-r--r--qa/qa/resource/members.rb13
-rw-r--r--qa/qa/resource/merge_request.rb10
-rw-r--r--qa/qa/resource/personal_access_token.rb52
-rw-r--r--qa/qa/resource/project.rb14
-rw-r--r--qa/qa/resource/project_imported_from_github.rb4
-rw-r--r--qa/qa/resource/project_snippet.rb6
-rw-r--r--qa/qa/resource/registry_repository.rb53
-rw-r--r--qa/qa/resource/snippet.rb37
-rw-r--r--qa/qa/resource/user.rb15
-rw-r--r--qa/qa/resource/wiki/group_page.rb48
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