Commit 8b325d3b authored by Andrejs Cunskis's avatar Andrejs Cunskis

Validate iterations migration

Add Iteration migration validation

Improve ApiFabricator to allow usage of graphql query

Minor code formatting improvements
parent 6176f4e8
......@@ -20,9 +20,29 @@ module QA
end
end
# Get group iterations
#
# @return [Array<QA::EE::Resource::GroupIteration>]
def iterations
parse_body(api_get_from(api_iterations_path)).map do |iteration|
GroupIteration.init do |resource|
resource.group = self
resource.api_client = api_client
resource.id = iteration[:id]
resource.iid = iteration[:iid]
resource.title = iteration[:title]
resource.description = iteration[:description]
end
end
end
def api_epics_path
"#{api_get_path}/epics"
end
def api_iterations_path
"#{api_get_path}/iterations"
end
end
end
end
......
......@@ -6,19 +6,21 @@ module QA
class GroupIteration < QA::Resource::Base
include Support::Dates
attr_accessor :title
attribute :group do
QA::Resource::Group.fabricate_via_api! do |group|
group.path = "group-to-test-iterations-#{SecureRandom.hex(8)}"
end
end
attribute :id
attribute :start_date
attribute :due_date
attribute :description
attribute :title
attributes :id,
:iid,
:description,
:title,
:state,
:start_date,
:due_date,
:created_at,
:updated_at
def initialize
@start_date = current_date_yyyy_mm_dd
......@@ -34,23 +36,68 @@ module QA
QA::EE::Page::Group::Iteration::Index.perform(&:click_new_iteration_button)
QA::EE::Page::Group::Iteration::New.perform do |new|
new.fill_title(@title)
new.fill_description(@description)
new.fill_start_date(@start_date)
new.fill_due_date(@due_date)
new.click_create_iteration_button
QA::EE::Page::Group::Iteration::New.perform do |iteration_page|
iteration_page.fill_title(@title)
iteration_page.fill_description(@description)
iteration_page.fill_start_date(@start_date)
iteration_page.fill_due_date(@due_date)
iteration_page.click_create_iteration_button
end
end
# Iteration attributes
#
# @return [String]
def gql_attributes
@gql_attributes ||= <<~GQL
id
iid
description
title
state
startDate
dueDate
createdAt
updatedAt
webUrl
GQL
end
# Path for fetching iteration
#
# @return [String]
def api_get_path
"gid://gitlab/Iteration/#{id}"
"/graphql"
end
# Fetch iteration
#
# @return [Hash]
def api_get
process_api_response(
api_post_to(
api_get_path,
<<~GQL
query {
iteration(id: "gid://gitlab/Iteration/#{id}") {
#{gql_attributes}
}
}
GQL
)
)
end
# Path to create iteration
#
# @return [String]
def api_post_path
"/graphql"
end
# Graphql mutation for iteration creation
#
# @return [String]
def api_post_body
<<~GQL
mutation {
......@@ -62,18 +109,45 @@ module QA
dueDate: "#{@due_date}"
}) {
iteration {
id
title
description
startDate
dueDate
webUrl
#{gql_attributes}
}
errors
}
}
GQL
end
# Object comparison
#
# @param [QA::EE::Resource::GroupIteration] other
# @return [Boolean]
def ==(other)
other.is_a?(GroupIteration) && comparable_iteration == other.comparable_iteration
end
# Override inspect for a better rspec failure diff output
#
# @return [String]
def inspect
JSON.pretty_generate(comparable_iteration)
end
protected
# Return subset of fields for comparing iterations
#
# @return [Hash]
def comparable_iteration
reload! unless api_response
api_response.slice(
:title,
:description,
:state,
:due_date,
:start_date
)
end
end
end
end
......
......@@ -96,31 +96,35 @@ module QA
end
def api_post
if api_post_path == "/graphql"
graphql_response = post(
Runtime::API::Request.new(api_client, api_post_path).url,
query: api_post_body)
process_api_response(api_post_to(api_post_path, api_post_body))
end
def api_post_to(post_path, post_body)
if post_path == "/graphql"
graphql_response = post(Runtime::API::Request.new(api_client, post_path).url, query: post_body)
flattened_response = flatten_hash(parse_body(graphql_response))
body = flatten_hash(parse_body(graphql_response))
unless graphql_response.code == HTTP_STATUS_OK && flattened_response[:errors].empty?
raise ResourceFabricationFailedError, "Fabrication of #{self.class.name} using the API failed (#{graphql_response.code}) with `#{graphql_response}`."
unless graphql_response.code == HTTP_STATUS_OK && (body[:errors].nil? || body[:errors].empty?)
raise(ResourceFabricationFailedError, <<~MSG)
Fabrication of #{self.class.name} using the API failed (#{graphql_response.code}) with `#{graphql_response}`.
MSG
end
flattened_response[:web_url] = flattened_response.delete(:webUrl)
flattened_response[:id] = flattened_response.fetch(:id).split('/')[-1]
body[:id] = body.fetch(:id).split('/').last
process_api_response(flattened_response)
body.transform_keys { |key| key.to_s.underscore.to_sym }
else
response = post(
Runtime::API::Request.new(api_client, api_post_path).url,
api_post_body)
response = post(Runtime::API::Request.new(api_client, post_path).url, post_body)
unless response.code == HTTP_STATUS_CREATED
raise ResourceFabricationFailedError, "Fabrication of #{self.class.name} using the API failed (#{response.code}) with `#{response}`."
raise(
ResourceFabricationFailedError,
"Fabrication of #{self.class.name} using the API failed (#{response.code}) with `#{response}`."
)
end
process_api_response(parse_body(response))
parse_body(response)
end
end
......
......@@ -6,6 +6,7 @@ module QA
describe 'Bulk group import' do
let(:admin_api_client) { Runtime::API::Client.as_admin }
let(:api_client) { Runtime::API::Client.new(user: user) }
# validate different epic author is migrated correctly
let(:author_api_client) { Runtime::API::Client.new(user: author) }
let(:user) do
......@@ -46,6 +47,13 @@ module QA
let(:source_epics) { source_group.epics }
let(:imported_epics) { imported_group.epics }
let(:source_iteration) do
EE::Resource::GroupIteration.fabricate_via_api! do |iteration|
iteration.api_client = api_client
iteration.group = source_group
end
end
# Find epic by title
#
# @param [Array] epics
......@@ -76,6 +84,8 @@ module QA
child_epic.award_emoji('thumbsup')
child_epic.award_emoji('thumbsdown')
source_iteration
end
after do
......@@ -83,7 +93,10 @@ module QA
author.remove_via_api!
end
it 'imports group epics', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1921' do
it(
'imports group epics and iterations',
testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1921'
) do
expect { imported_group.import_status }.to(
eventually_eq('finished').within(max_duration: 300, sleep_interval: 2)
)
......@@ -91,11 +104,17 @@ module QA
source_parent_epic = find_epic(source_epics, 'Parent epic')
imported_parent_epic = find_epic(imported_epics, 'Parent epic')
imported_child_epic = find_epic(imported_epics, 'Child epic')
imported_iteration = imported_group.reload!.iterations.find { |ml| ml.title == source_iteration.title }
aggregate_failures 'epics imported incorrectly' do
aggregate_failures do
expect(imported_epics).to eq(source_epics)
expect(imported_child_epic.parent_id).to eq(imported_parent_epic.id)
expect(imported_parent_epic.author).to eq(source_parent_epic.author)
expect(imported_iteration).to eq(source_iteration)
expect(imported_iteration.iid).to eq(source_iteration.iid)
expect(imported_iteration.created_at).to eq(source_iteration.created_at)
expect(imported_iteration.updated_at).to eq(source_iteration.updated_at)
end
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment