Commit ca3aa6e0 authored by Dan Davison's avatar Dan Davison

Merge branch 'e2e-ci-purchase-flow' into 'master'

Add e2e tests for purchasing CI minutes

See merge request gitlab-org/gitlab!70734
parents 42d44783 82eb4da2
...@@ -18,6 +18,7 @@ module Gitlab ...@@ -18,6 +18,7 @@ module Gitlab
module Group module Group
module Settings module Settings
autoload :Billing, 'gitlab/page/group/settings/billing' autoload :Billing, 'gitlab/page/group/settings/billing'
autoload :UsageQuotas, 'gitlab/page/group/settings/usage_quotas'
end end
end end
end end
......
# frozen_string_literal: true
module Gitlab
module Page
module Group
module Settings
module UsageQuota
# @note Defined as +link :pipeline_tab+
# Clicks +pipeline_tab+
def pipeline_tab
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota.pipeline_tab_element).to exist
# end
# @return [Watir::Link] The raw +Link+ element
def pipeline_tab_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota).to be_pipeline_tab
# end
# @return [Boolean] true if the +pipeline_tab+ element is present on the page
def pipeline_tab?
# This is a stub, used for indexing. The method is dynamically generated.
end
# @note Defined as +link :storage_tab+
# Clicks +storage_tab+
def storage_tab
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota.storage_tab_element).to exist
# end
# @return [Watir::Link] The raw +Link+ element
def storage_tab_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota).to be_storage_tab
# end
# @return [Boolean] true if the +storage_tab+ element is present on the page
def storage_tab?
# This is a stub, used for indexing. The method is dynamically generated.
end
# @note Defined as +link :buy_ci_minutes+
# Clicks +buy_ci_minutes+
def buy_ci_minutes
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota.buy_ci_minutes_element).to exist
# end
# @return [Watir::Link] The raw +Link+ element
def buy_ci_minutes_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota).to be_buy_ci_minutes
# end
# @return [Boolean] true if the +buy_ci_minutes+ element is present on the page
def buy_ci_minutes?
# This is a stub, used for indexing. The method is dynamically generated.
end
# @note Defined as +link :buy_storage+
# Clicks +buy_storage+
def buy_storage
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota.buy_storage_element).to exist
# end
# @return [Watir::Link] The raw +Link+ element
def buy_storage_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota).to be_buy_storage
# end
# @return [Boolean] true if the +buy_storage+ element is present on the page
def buy_storage?
# This is a stub, used for indexing. The method is dynamically generated.
end
# @note Defined as +strong :additional_minutes+
# @return [String] The text content or value of +additional_minutes+
def additional_minutes
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota.additional_minutes_element).to exist
# end
# @return [Watir::Strong] The raw +Strong+ element
def additional_minutes_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota).to be_additional_minutes
# end
# @return [Boolean] true if the +additional_minutes+ element is present on the page
def additional_minutes?
# This is a stub, used for indexing. The method is dynamically generated.
end
# @note Defined as +div :additional_minutes_usage+
# @return [String] The text content or value of +additional_minutes_usage+
def additional_minutes_usage
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota.additional_minutes_usage_element).to exist
# end
# @return [Watir::Div] The raw +Div+ element
def additional_minutes_usage_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota).to be_additional_minutes_usage
# end
# @return [Boolean] true if the +additional_minutes_usage+ element is present on the page
def additional_minutes_usage?
# This is a stub, used for indexing. The method is dynamically generated.
end
# @note Defined as +strong :plan_minutes+
# @return [String] The text content or value of +plan_minutes+
def plan_minutes
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota.plan_minutes_element).to exist
# end
# @return [Watir::Strong] The raw +Strong+ element
def plan_minutes_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota).to be_plan_minutes
# end
# @return [Boolean] true if the +plan_minutes+ element is present on the page
def plan_minutes?
# This is a stub, used for indexing. The method is dynamically generated.
end
# @note Defined as +div :plan_minutes_usage+
# @return [String] The text content or value of +plan_minutes_usage+
def plan_minutes_usage
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota.plan_minutes_usage_element).to exist
# end
# @return [Watir::Div] The raw +Div+ element
def plan_minutes_usage_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota).to be_plan_minutes_usage
# end
# @return [Boolean] true if the +plan_minutes_usage+ element is present on the page
def plan_minutes_usage?
# This is a stub, used for indexing. The method is dynamically generated.
end
# @note Defined as +div :purchase_successful_alert+
# @return [String] The text content or value of +purchase_successful_alert+
def purchase_successful_alert
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota.purchase_successful_alert_element).to exist
# end
# @return [Watir::Div] The raw +Div+ element
def purchase_successful_alert_element
# This is a stub, used for indexing. The method is dynamically generated.
end
# @example
# Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota|
# expect(usage_quota).to be_purchase_successful_alert
# end
# @return [Boolean] true if the +purchase_successful_alert+ element is present on the page
def purchase_successful_alert?
# This is a stub, used for indexing. The method is dynamically generated.
end
end
end
end
end
end
# frozen_string_literal: true
module Gitlab
module Page
module Group
module Settings
class UsageQuotas < Chemlab::Page
link :pipeline_tab, id: 'pipelines-quota'
link :storage_tab, id: 'storage-quota'
link :buy_ci_minutes, text: 'Buy additional minutes'
link :buy_storage, text: /Purchase more storage/
strong :additional_minutes, text: 'Additional minutes'
div(:additional_minutes_usage) { additional_minutes_element.following_sibling.span }
div :purchase_successful_alert, text: /You have successfully purchased CI minutes/
def plan_minutes_limits
plan_minutes_usage[%r{([^/ ]+)$}]
end
def additional_limits
additional_minutes_usage[%r{([^/ ]+)$}]
end
# TODO: Refactor/Remove this method once https://gitlab.com/gitlab-org/quality/chemlab/-/merge_requests/28 is merged
def additional_minutes_exist?
has_element?(:strong, :additional_minutes, text: 'Additional minutes')
end
end
end
end
end
end
...@@ -6,10 +6,11 @@ module Gitlab ...@@ -6,10 +6,11 @@ module Gitlab
class New < Chemlab::Page class New < Chemlab::Page
path '/subscriptions/new' path '/subscriptions/new'
# Subscription Details # Purchase Details
select :plan_name select :plan_name
select :group_name select :group_name
text_field :number_of_users text_field :number_of_users
text_field :quantity
button :continue_to_billing, text: /Continue to billing/ button :continue_to_billing, text: /Continue to billing/
# Billing address # Billing address
...@@ -35,6 +36,10 @@ module Gitlab ...@@ -35,6 +36,10 @@ module Gitlab
# Confirmation # Confirmation
button :confirm_purchase, text: /Confirm purchase/ button :confirm_purchase, text: /Confirm purchase/
# Order Summary
div :selected_plan, 'data-testid': 'selected-plan'
div :order_total, 'data-testid': 'total-amount'
end end
end end
end end
......
...@@ -108,6 +108,14 @@ module QA ...@@ -108,6 +108,14 @@ module QA
end end
end end
def go_to_usage_quotas
hover_group_settings do
within_submenu do
click_element(:sidebar_menu_item_link, menu_item: 'Usage Quotas')
end
end
end
private private
def hover_security_and_compliance def hover_security_and_compliance
......
# frozen_string_literal: true
module QA
RSpec.describe 'Fulfillment', :requires_admin, only: { subdomain: :staging } do
context 'Purchase CI minutes' do
# the quantity of products to purchase
let(:purchase_quantity) { 5 }
let(:hash) { SecureRandom.hex(4) }
let(:user) do
Resource::User.fabricate_via_api! do |user|
user.email = "test-user-#{hash}@gitlab.com"
user.api_client = Runtime::API::Client.as_admin
user.hard_delete_on_api_removal = true
end
end
let(:group) do
Resource::Sandbox.fabricate_via_api! do |sandbox|
sandbox.path = "gitlab-qa-group-#{hash}"
sandbox.api_client = Runtime::API::Client.as_admin
end
end
before do
Runtime::Feature.enable(:top_level_group_creation_enabled)
group.add_member(user, Resource::Members::AccessLevel::OWNER)
# A group project is required for additional CI Minutes to show up
Resource::Project.fabricate_via_api! do |project|
project.name = 'ci-minutes'
project.group = group
project.initialize_with_readme = true
project.api_client = Runtime::API::Client.as_admin
end
Flow::Login.sign_in(as: user)
group.visit!
end
after do
user.remove_via_api!
Runtime::Feature.disable(:top_level_group_creation_enabled)
end
it 'adds additional minutes to group namespace', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2660' do
Page::Group::Menu.perform(&:go_to_usage_quotas)
Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quota|
usage_quota.pipeline_tab
usage_quota.buy_ci_minutes
end
Gitlab::Page::Subscriptions::New.perform do |ci_minutes|
ci_minutes.quantity = purchase_quantity
ci_minutes.continue_to_billing
ci_minutes.country = user_billing_info[:country]
ci_minutes.street_address_1 = user_billing_info[:address_1]
ci_minutes.street_address_2 = user_billing_info[:address_2]
ci_minutes.city = user_billing_info[:city]
ci_minutes.state = user_billing_info[:state]
ci_minutes.zip_code = user_billing_info[:zip]
ci_minutes.continue_to_payment
ci_minutes.name_on_card = credit_card_info[:name]
ci_minutes.card_number = credit_card_info[:number]
ci_minutes.expiration_month = credit_card_info[:month]
ci_minutes.expiration_year = credit_card_info[:year]
ci_minutes.cvv = credit_card_info[:cvv]
ci_minutes.review_your_order
ci_minutes.confirm_purchase
end
Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quota|
expected_minutes = ci_product[:minutes] * purchase_quantity
expect(usage_quota.purchase_successful_alert?).to be true
expect { usage_quota.additional_minutes_exist? }.to eventually_be_truthy.within(max_duration: 120, max_attempts: 60, reload_page: page)
expect(usage_quota.additional_limits).to eq(expected_minutes.to_s)
end
end
private
# Hash presentation of CI minutes addon
# @return [Hash] CI Minutes addon
def ci_product
{
name: 'CI Minutes', # the name as it appears to purchase in GitLab
price: 10, # unit price in USD
minutes: 1000 # additional CI minutes per pack
}.freeze
end
def credit_card_info
{
name: 'QA Test',
number: '4111111111111111',
month: '01',
year: '2025',
cvv: '232'
}.freeze
end
def user_billing_info
{
country: 'United States of America',
address_1: 'Address 1',
address_2: 'Address 2',
city: 'San Francisco',
state: 'California',
zip: '94102'
}.freeze
end
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