Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
75f1f22a
Commit
75f1f22a
authored
Oct 08, 2021
by
Angelo Gulina
Committed by
Nicolò Maria Mezzopera
Oct 08, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use account id as part of the namespace to init Zuora iframe
parent
27b2b7df
Changes
30
Hide whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
247 additions
and
78 deletions
+247
-78
ee/app/assets/javascripts/subscriptions/buy_addons_shared/components/order_summary.vue
...scriptions/buy_addons_shared/components/order_summary.vue
+6
-7
ee/app/assets/javascripts/subscriptions/buy_addons_shared/constants.js
.../javascripts/subscriptions/buy_addons_shared/constants.js
+1
-1
ee/app/assets/javascripts/subscriptions/buy_addons_shared/graphql.js
...ts/javascripts/subscriptions/buy_addons_shared/graphql.js
+3
-3
ee/app/assets/javascripts/subscriptions/buy_addons_shared/graphql/resolvers.js
...ipts/subscriptions/buy_addons_shared/graphql/resolvers.js
+0
-2
ee/app/assets/javascripts/subscriptions/buy_addons_shared/utils.js
...sets/javascripts/subscriptions/buy_addons_shared/utils.js
+4
-3
ee/app/assets/javascripts/subscriptions/buy_minutes/components/app.vue
.../javascripts/subscriptions/buy_minutes/components/app.vue
+2
-3
ee/app/assets/javascripts/subscriptions/buy_minutes/index.js
ee/app/assets/javascripts/subscriptions/buy_minutes/index.js
+1
-0
ee/app/assets/javascripts/subscriptions/buy_storage/components/app.vue
.../javascripts/subscriptions/buy_storage/components/app.vue
+2
-2
ee/app/assets/javascripts/subscriptions/graphql/queries/state.query.graphql
...scripts/subscriptions/graphql/queries/state.query.graphql
+3
-2
ee/app/assets/javascripts/vue_shared/purchase_flow/components/checkout/payment_method.vue
...ared/purchase_flow/components/checkout/payment_method.vue
+14
-3
ee/app/assets/javascripts/vue_shared/purchase_flow/components/checkout/zuora.vue
...ts/vue_shared/purchase_flow/components/checkout/zuora.vue
+15
-3
ee/app/helpers/subscriptions_helper.rb
ee/app/helpers/subscriptions_helper.rb
+1
-0
ee/spec/frontend/subscriptions/buy_addons_shared/components/order_summary_spec.js
...ptions/buy_addons_shared/components/order_summary_spec.js
+13
-16
ee/spec/frontend/subscriptions/buy_addons_shared/resolvers_spec.js
...rontend/subscriptions/buy_addons_shared/resolvers_spec.js
+0
-0
ee/spec/frontend/subscriptions/buy_addons_shared/utils_spec.js
...ec/frontend/subscriptions/buy_addons_shared/utils_spec.js
+3
-3
ee/spec/frontend/subscriptions/buy_minutes/components/checkout/billing_address_spec.js
...s/buy_minutes/components/checkout/billing_address_spec.js
+1
-1
ee/spec/frontend/subscriptions/buy_minutes/components/checkout/confirm_order_spec.js
...ons/buy_minutes/components/checkout/confirm_order_spec.js
+4
-5
ee/spec/frontend/subscriptions/buy_minutes/mock_data.js
ee/spec/frontend/subscriptions/buy_minutes/mock_data.js
+13
-9
ee/spec/frontend/subscriptions/buy_minutes/spec_helper.js
ee/spec/frontend/subscriptions/buy_minutes/spec_helper.js
+3
-2
ee/spec/frontend/subscriptions/new/components/checkout/billing_address_spec.js
...criptions/new/components/checkout/billing_address_spec.js
+1
-1
ee/spec/frontend/subscriptions/new/components/checkout/confirm_order_spec.js
...bscriptions/new/components/checkout/confirm_order_spec.js
+2
-2
ee/spec/frontend/subscriptions/new/components/checkout/payment_method_spec.js
...scriptions/new/components/checkout/payment_method_spec.js
+1
-1
ee/spec/frontend/subscriptions/new/components/checkout/subscription_details_spec.js
...ions/new/components/checkout/subscription_details_spec.js
+1
-1
ee/spec/frontend/subscriptions/new/components/checkout/zuora_spec.js
...ntend/subscriptions/new/components/checkout/zuora_spec.js
+1
-1
ee/spec/frontend/subscriptions/new/components/checkout_spec.js
...ec/frontend/subscriptions/new/components/checkout_spec.js
+1
-1
ee/spec/frontend/vue_shared/purchase_flow/components/checkout/payment_method_spec.js
.../purchase_flow/components/checkout/payment_method_spec.js
+120
-0
ee/spec/frontend/vue_shared/purchase_flow/components/checkout/zuora_spec.js
...ue_shared/purchase_flow/components/checkout/zuora_spec.js
+24
-2
ee/spec/frontend/vue_shared/purchase_flow/components/step_spec.js
...frontend/vue_shared/purchase_flow/components/step_spec.js
+2
-2
ee/spec/helpers/subscriptions_helper_spec.rb
ee/spec/helpers/subscriptions_helper_spec.rb
+2
-2
spec/frontend/__helpers__/flush_promises.js
spec/frontend/__helpers__/flush_promises.js
+3
-0
No files found.
ee/app/assets/javascripts/subscriptions/buy_addons_shared/components/order_summary.vue
View file @
75f1f22a
<
script
>
import
{
GlIcon
,
GlCollapse
,
GlCollapseToggleDirective
}
from
'
@gitlab/ui
'
;
import
find
from
'
lodash/find
'
;
import
stateQuery
from
'
ee/subscriptions/graphql/queries/state.query.graphql
'
;
import
{
TAX_RATE
}
from
'
ee/subscriptions/new/constants
'
;
import
formattingMixins
from
'
ee/subscriptions/new/formatting_mixins
'
;
...
...
@@ -35,25 +36,23 @@ export default {
query
:
stateQuery
,
manual
:
true
,
result
({
data
})
{
this
.
namespaces
=
data
.
namespaces
;
const
id
=
Number
(
data
.
selectedNamespaceId
);
this
.
selectedNamespace
=
find
(
data
.
eligibleNamespaces
,
{
id
});
this
.
subscription
=
data
.
subscription
;
},
},
},
data
()
{
return
{
subscription
:
{},
namespaces
:
[],
isBottomSummaryVisible
:
false
,
selectedNamespace
:
{},
subscription
:
{},
};
},
computed
:
{
selectedPlanPrice
()
{
return
this
.
plan
.
pricePerYear
;
},
selectedGroup
()
{
return
this
.
namespaces
.
find
((
group
)
=>
group
.
id
===
Number
(
this
.
subscription
.
namespaceId
));
},
totalExVat
()
{
return
this
.
subscription
.
quantity
*
this
.
selectedPlanPrice
;
},
...
...
@@ -67,7 +66,7 @@ export default {
return
this
.
subscription
.
quantity
>
0
;
},
namespaceName
()
{
return
this
.
selected
Group
.
name
;
return
this
.
selected
Namespace
.
name
;
},
titleWithName
()
{
return
sprintf
(
this
.
title
,
{
name
:
this
.
namespaceName
});
...
...
ee/app/assets/javascripts/subscriptions/buy_addons_shared/constants.js
View file @
75f1f22a
...
...
@@ -6,7 +6,7 @@ export const planTags = {
STORAGE_PLAN
:
'
STORAGE_PLAN
'
,
};
/* eslint-enable @gitlab/require-i18n-strings */
export
const
CUSTOMER
_CLIENT
=
'
customer
Client
'
;
export
const
CUSTOMER
SDOT_CLIENT
=
'
customersDot
Client
'
;
export
const
GITLAB_CLIENT
=
'
gitlabClient
'
;
export
const
CI_MINUTES_PER_PACK
=
1000
;
...
...
ee/app/assets/javascripts/subscriptions/buy_addons_shared/graphql.js
View file @
75f1f22a
...
...
@@ -4,7 +4,7 @@ import VueApollo from 'vue-apollo';
import
purchaseFlowResolvers
from
'
ee/vue_shared/purchase_flow/graphql/resolvers
'
;
import
typeDefs
from
'
ee/vue_shared/purchase_flow/graphql/typedefs.graphql
'
;
import
createClient
from
'
~/lib/graphql
'
;
import
{
GITLAB_CLIENT
,
CUSTOMER_CLIENT
}
from
'
./constants
'
;
import
{
GITLAB_CLIENT
,
CUSTOMER
SDOT
_CLIENT
}
from
'
./constants
'
;
import
{
resolvers
}
from
'
./graphql/resolvers
'
;
Vue
.
use
(
VueApollo
);
...
...
@@ -13,7 +13,7 @@ const gitlabClient = createClient(merge({}, resolvers, purchaseFlowResolvers), {
typeDefs
,
assumeImmutableResults
:
true
,
});
const
customerClient
=
createClient
(
const
customer
sDot
Client
=
createClient
(
{},
{
path
:
'
/-/customers_dot/proxy/graphql
'
,
...
...
@@ -26,6 +26,6 @@ export default new VueApollo({
defaultClient
:
gitlabClient
,
clients
:
{
[
GITLAB_CLIENT
]:
gitlabClient
,
[
CUSTOMER
_CLIENT
]:
customer
Client
,
[
CUSTOMER
SDOT_CLIENT
]:
customersDot
Client
,
},
});
ee/app/assets/javascripts/subscriptions/buy_addons_shared/graphql/resolvers.js
View file @
75f1f22a
...
...
@@ -39,11 +39,9 @@ export const resolvers = {
},
updateState
:
(
_
,
{
input
},
{
cache
})
=>
{
const
oldState
=
cache
.
readQuery
({
query
:
stateQuery
});
const
state
=
produce
(
oldState
,
(
draftState
)
=>
{
merge
(
draftState
,
input
);
});
cache
.
writeQuery
({
query
:
stateQuery
,
data
:
state
});
},
},
...
...
ee/app/assets/javascripts/subscriptions/buy_addons_shared/utils.js
View file @
75f1f22a
...
...
@@ -12,8 +12,9 @@ function arrayToGraphqlArray(arr, typename) {
export
function
writeInitialDataToApolloCache
(
apolloProvider
,
dataset
)
{
const
{
groupData
,
namespaceId
,
redirectAfterSuccess
,
subscriptionQuantity
}
=
dataset
;
// eslint-disable-next-line @gitlab/require-i18n-strings
const
n
amespaces
=
arrayToGraphqlArray
(
JSON
.
parse
(
groupData
),
'
Namespace
'
);
const
eligibleN
amespaces
=
arrayToGraphqlArray
(
JSON
.
parse
(
groupData
),
'
Namespace
'
);
const
quantity
=
subscriptionQuantity
||
1
;
apolloProvider
.
clients
.
defaultClient
.
cache
.
writeQuery
({
...
...
@@ -23,11 +24,11 @@ export function writeInitialDataToApolloCache(apolloProvider, dataset) {
fullName
:
null
,
isSetupForCompany
:
false
,
selectedPlanId
:
null
,
n
amespaces
,
eligibleN
amespaces
,
redirectAfterSuccess
,
selectedNamespaceId
:
namespaceId
,
subscription
:
{
quantity
,
namespaceId
,
// eslint-disable-next-line @gitlab/require-i18n-strings
__typename
:
'
Subscription
'
,
},
...
...
ee/app/assets/javascripts/subscriptions/buy_minutes/components/app.vue
View file @
75f1f22a
...
...
@@ -20,14 +20,13 @@ import {
I18N_CI_MINUTES_PRICE_PRE_UNIT
,
I18N_CI_MINUTES_TITLE
,
planTags
,
CUSTOMER_CLIENT
,
CUSTOMER
SDOT
_CLIENT
,
CI_MINUTES_PER_PACK
,
}
from
'
../../buy_addons_shared/constants
'
;
import
plansQuery
from
'
../../graphql/queries/plans.customer.query.graphql
'
;
export
default
{
name
:
'
BuyCIMinutesApp
'
,
components
:
{
Checkout
,
GlEmptyState
,
...
...
@@ -93,7 +92,7 @@ export default {
},
apollo
:
{
plans
:
{
client
:
CUSTOMER_CLIENT
,
client
:
CUSTOMER
SDOT
_CLIENT
,
query
:
plansQuery
,
variables
:
{
tags
:
[
planTags
.
CI_1000_MINUTES_PLAN
],
...
...
ee/app/assets/javascripts/subscriptions/buy_minutes/index.js
View file @
75f1f22a
...
...
@@ -17,6 +17,7 @@ export default (el) => {
return
new
Vue
({
el
,
name
:
'
BuyCIMinutes
'
,
apolloProvider
,
render
(
createElement
)
{
return
createElement
(
extendedApp
);
...
...
ee/app/assets/javascripts/subscriptions/buy_storage/components/app.vue
View file @
75f1f22a
...
...
@@ -20,7 +20,7 @@ import {
I18N_STORAGE_PRICE_PRE_UNIT
,
I18N_STORAGE_TOOLTIP_NOTE
,
planTags
,
CUSTOMER_CLIENT
,
CUSTOMER
SDOT
_CLIENT
,
STORAGE_PER_PACK
,
}
from
'
../../buy_addons_shared/constants
'
;
import
plansQuery
from
'
../../graphql/queries/plans.customer.query.graphql
'
;
...
...
@@ -94,7 +94,7 @@ export default {
},
apollo
:
{
plans
:
{
client
:
CUSTOMER_CLIENT
,
client
:
CUSTOMER
SDOT
_CLIENT
,
query
:
plansQuery
,
variables
:
{
tags
:
[
planTags
.
STORAGE_PLAN
],
...
...
ee/app/assets/javascripts/subscriptions/graphql/queries/state.query.graphql
View file @
75f1f22a
query
State
{
n
amespaces
@client
{
eligibleN
amespaces
@client
{
id
accountId
name
users
}
...
...
@@ -8,6 +9,7 @@ query State {
fullName
@client
isSetupForCompany
@client
selectedPlanId
@client
selectedNamespaceId
@client
redirectAfterSuccess
@client
customer
@client
{
country
...
...
@@ -27,7 +29,6 @@ query State {
}
subscription
@client
{
quantity
namespaceId
}
activeStep
@client
{
id
...
...
ee/app/assets/javascripts/vue_shared/purchase_flow/components/checkout/payment_method.vue
View file @
75f1f22a
<
script
>
import
{
GlSprintf
}
from
'
@gitlab/ui
'
;
import
find
from
'
lodash/find
'
;
import
{
STEPS
}
from
'
ee/subscriptions/constants
'
;
import
stateQuery
from
'
ee/subscriptions/graphql/queries/state.query.graphql
'
;
import
Step
from
'
ee/vue_shared/purchase_flow/components/step.vue
'
;
...
...
@@ -17,8 +18,18 @@ export default {
query
:
stateQuery
,
update
:
(
data
)
=>
data
.
paymentMethod
,
},
selectedNamespace
:
{
query
:
stateQuery
,
update
:
({
eligibleNamespaces
,
selectedNamespaceId
})
=>
{
const
id
=
Number
(
selectedNamespaceId
);
return
find
(
eligibleNamespaces
,
{
id
});
},
},
},
computed
:
{
accountId
()
{
return
this
.
selectedNamespace
?.
accountId
||
''
;
},
isValid
()
{
return
Boolean
(
this
.
paymentMethod
.
id
);
},
...
...
@@ -40,10 +51,10 @@ export default {
<
template
>
<step
:step-id=
"$options.stepId"
:title=
"$options.i18n.stepTitle"
:is-valid=
"isValid"
>
<template
#body
="
{ active }">
<zuora
:active=
"active"
/>
<zuora
:active=
"active"
:account-id=
"accountId"
/>
</
template
>
<
template
#summary
>
<div
class=
"js-summary-line-1
"
>
<div
data-testid=
"card-details
"
>
<gl-sprintf
:message=
"$options.i18n.paymentMethod"
>
<template
#cardType
>
{{
paymentMethod
.
creditCardType
}}
...
...
@@ -53,7 +64,7 @@ export default {
</
template
>
</gl-sprintf>
</div>
<div
class=
"js-summary-line-2
"
>
<div
data-testid=
"card-expiration
"
>
{{ expirationDate }}
</div>
</template>
...
...
ee/app/assets/javascripts/vue_shared/purchase_flow/components/checkout/zuora.vue
View file @
75f1f22a
...
...
@@ -23,11 +23,16 @@ export default {
type
:
Boolean
,
required
:
true
,
},
accountId
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
},
data
()
{
return
{
isLoading
:
false
,
paymentFormParams
:
null
,
paymentFormParams
:
{}
,
zuoraLoaded
:
false
,
zuoraScriptEl
:
null
,
};
...
...
@@ -36,6 +41,14 @@ export default {
shouldShowZuoraFrame
()
{
return
this
.
active
&&
this
.
zuoraLoaded
&&
!
this
.
isLoading
;
},
renderParams
()
{
return
{
...
this
.
paymentFormParams
,
...
ZUORA_IFRAME_OVERRIDE_PARAMS
,
// @TODO: should the component handle re-rendering the form in case this changes?
field_accountId
:
this
.
accountId
,
};
},
},
mounted
()
{
this
.
loadZuoraScript
();
...
...
@@ -94,9 +107,8 @@ export default {
});
},
renderZuoraIframe
()
{
const
params
=
{
...
this
.
paymentFormParams
,
...
ZUORA_IFRAME_OVERRIDE_PARAMS
};
window
.
Z
.
runAfterRender
(
this
.
zuoraIframeRendered
);
window
.
Z
.
render
(
p
arams
,
{},
this
.
paymentFormSubmitted
);
window
.
Z
.
render
(
this
.
renderP
arams
,
{},
this
.
paymentFormSubmitted
);
},
activateNextStep
()
{
return
this
.
$apollo
...
...
ee/app/helpers/subscriptions_helper.rb
View file @
75f1f22a
...
...
@@ -60,6 +60,7 @@ module SubscriptionsHelper
def
present_group
(
namespace
)
{
id:
namespace
.
id
,
account_id:
nil
,
name:
namespace
.
name
,
users:
namespace
.
member_count
,
guests:
namespace
.
guest_count
...
...
ee/spec/frontend/subscriptions/buy_addons_shared/components/order_summary_spec.js
View file @
75f1f22a
import
{
shallowMount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
{
createLocalVue
}
from
'
@vue/test-utils
'
;
import
{
merge
}
from
'
lodash
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
{
shallowMountExtended
}
from
'
helpers/vue_test_utils_helper
'
;
import
OrderSummary
from
'
ee/subscriptions/buy_addons_shared/components/order_summary.vue
'
;
import
subscriptionsResolvers
from
'
ee/subscriptions/buy_addons_shared/graphql/resolvers
'
;
import
stateQuery
from
'
ee/subscriptions/graphql/queries/state.query.graphql
'
;
...
...
@@ -17,32 +18,30 @@ localVue.use(VueApollo);
describe
(
'
Order Summary
'
,
()
=>
{
const
resolvers
=
{
...
purchaseFlowResolvers
,
...
subscriptionsResolvers
};
const
selectedNamespaceId
=
mockParsedNamespaces
[
0
].
id
;
const
initialStateData
=
{
selectedPlanId
:
'
ciMinutesPackPlanId
'
,
namespaces
:
[
mockParsedNamespaces
[
0
]],
subscription
:
{
namespaceId
:
mockParsedNamespaces
[
0
].
id
,
},
eligibleNamespaces
:
mockParsedNamespaces
,
selectedNamespaceId
,
subscription
:
{},
};
let
wrapper
;
const
findAmount
=
()
=>
wrapper
.
findByTestId
(
'
amount
'
);
const
findTitle
=
()
=>
wrapper
.
findByTestId
(
'
title
'
);
const
createMockApolloProvider
=
(
stateData
=
{})
=>
{
const
mockApollo
=
createMockApollo
([],
resolvers
);
const
data
=
merge
({},
mockStateData
,
initialStateData
,
stateData
);
mockApollo
.
clients
.
defaultClient
.
cache
.
writeQuery
({
query
:
stateQuery
,
data
,
});
return
mockApollo
;
};
const
createComponent
=
(
stateData
)
=>
{
const
apolloProvider
=
createMockApolloProvider
(
stateData
);
wrapper
=
shallowMount
(
OrderSummary
,
{
wrapper
=
shallowMountExtended
(
OrderSummary
,
{
localVue
,
apolloProvider
,
propsData
:
{
...
...
@@ -65,9 +64,7 @@ describe('Order Summary', () => {
});
it
(
'
displays the title
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
[data-testid="title"]
'
).
text
()).
toMatchInterpolatedText
(
"
Gitlab Org's CI minutes
"
,
);
expect
(
findTitle
().
text
()).
toMatchInterpolatedText
(
"
Gitlab Org's CI minutes
"
);
});
});
...
...
@@ -79,7 +76,7 @@ describe('Order Summary', () => {
});
it
(
'
renders amount
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
[data-testid="amount"]
'
).
text
()).
toBe
(
'
$30
'
);
expect
(
findAmount
(
).
text
()).
toBe
(
'
$30
'
);
});
});
...
...
@@ -91,7 +88,7 @@ describe('Order Summary', () => {
});
it
(
'
does not render amount
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
[data-testid="amount"]
'
).
text
()).
toBe
(
'
-
'
);
expect
(
findAmount
(
).
text
()).
toBe
(
'
-
'
);
});
});
});
ee/spec/frontend/subscriptions/buy_
minutes/graphql
/resolvers_spec.js
→
ee/spec/frontend/subscriptions/buy_
addons_shared
/resolvers_spec.js
View file @
75f1f22a
File moved
ee/spec/frontend/subscriptions/buy_
minutes
/utils_spec.js
→
ee/spec/frontend/subscriptions/buy_
addons_shared
/utils_spec.js
View file @
75f1f22a
import
apolloProvider
from
'
ee/subscriptions/buy_addons_shared/graphql
'
;
import
{
writeInitialDataToApolloCache
}
from
'
ee/subscriptions/buy_addons_shared/utils
'
;
import
stateQuery
from
'
ee/subscriptions/graphql/queries/state.query.graphql
'
;
import
{
mockNamespaces
,
mockParsedNamespaces
}
from
'
./mock_data
'
;
import
{
mockNamespaces
,
mockParsedNamespaces
}
from
'
.
./buy_minutes
/mock_data
'
;
const
DEFAULT_DATA
=
{
groupData
:
mockNamespaces
,
...
...
@@ -26,7 +26,7 @@ describe('utils', () => {
${
''
}
|
${{}}
|
$
{
true
}
${
mockNamespaces
}
|
${
mockParsedNamespaces
}
|
${
false
}
`
(
'
parameter decoding
'
,
({
namespaces
,
parsedNamespaces
,
throws
})
=>
{
it
(
`decodes
$
{
namespaces
}
to
${
parsedNamespaces
}
`
,
async
()
=>
{
it
(
`decodes $
namespaces to $parsedNamespaces
`
,
async
()
=>
{
if
(
throws
)
{
expect
(()
=>
{
writeInitialDataToApolloCache
(
apolloProvider
,
{
groupData
:
namespaces
});
...
...
@@ -39,7 +39,7 @@ describe('utils', () => {
const
sourceData
=
await
apolloProvider
.
clients
.
defaultClient
.
query
({
query
:
stateQuery
,
});
expect
(
sourceData
.
data
.
n
amespaces
).
toStrictEqual
(
parsedNamespaces
);
expect
(
sourceData
.
data
.
eligibleN
amespaces
).
toStrictEqual
(
parsedNamespaces
);
}
});
});
...
...
ee/spec/frontend/subscriptions/buy_minutes/components/checkout/billing_address_spec.js
View file @
75f1f22a
...
...
@@ -61,7 +61,7 @@ describe('Billing Address', () => {
});
describe
(
'
validations
'
,
()
=>
{
const
isStepValid
=
()
=>
wrapper
.
find
(
Step
).
props
(
'
isValid
'
);
const
isStepValid
=
()
=>
wrapper
.
find
Component
(
Step
).
props
(
'
isValid
'
);
const
customerData
=
{
country
:
'
US
'
,
address1
:
'
address line 1
'
,
...
...
ee/spec/frontend/subscriptions/buy_minutes/components/checkout/confirm_order_spec.js
View file @
75f1f22a
...
...
@@ -11,20 +11,19 @@ import { createMockApolloProvider } from 'ee_jest/vue_shared/purchase_flow/spec_
import
{
extendedWrapper
}
from
'
helpers/vue_test_utils_helper
'
;
import
flash
from
'
~/flash
'
;
import
*
as
UrlUtility
from
'
~/lib/utils/url_utility
'
;
import
flushPromises
from
'
helpers/flush_promises
'
;
jest
.
mock
(
'
~/lib/utils/url_utility
'
);
jest
.
mock
(
'
~/flash
'
);
jest
.
mock
(
'
ee/api.js
'
);
const
flushPromises
=
()
=>
new
Promise
(
setImmediate
);
describe
(
'
Confirm Order
'
,
()
=>
{
let
mockApolloProvider
;
let
wrapper
;
const
findRootElement
=
()
=>
wrapper
.
findByTestId
(
'
confirm-order-root
'
);
const
findConfirmButton
=
()
=>
wrapper
.
find
(
GlButton
);
const
findLoadingIcon
=
()
=>
wrapper
.
find
(
GlLoadingIcon
);
const
findConfirmButton
=
()
=>
wrapper
.
find
Component
(
GlButton
);
const
findLoadingIcon
=
()
=>
wrapper
.
find
Component
(
GlLoadingIcon
);
const
localVue
=
createLocalVue
();
localVue
.
use
(
VueApollo
);
...
...
@@ -77,7 +76,7 @@ describe('Confirm Order', () => {
expect
(
Api
.
confirmOrder
).
toHaveBeenCalledTimes
(
1
);
expect
(
Api
.
confirmOrder
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
setup_for_company
:
true
,
selected_group
:
null
,
selected_group
:
undefined
,
new_user
:
false
,
redirect_after_success
:
'
/path/to/redirect/
'
,
customer
:
{
...
...
ee/spec/frontend/subscriptions/buy_minutes/mock_data.js
View file @
75f1f22a
import
{
STEPS
}
from
'
ee/subscriptions/constants
'
;
export
const
accountId
=
'
111111111111
'
;
export
const
mockCiMinutesPlans
=
[
{
id
:
'
ciMinutesPackPlanId
'
,
...
...
@@ -9,16 +11,18 @@ export const mockCiMinutesPlans = [
__typename
:
'
Plan
'
,
},
];
export
const
mockNamespaces
=
'
[{"id":132,"name":"Gitlab Org","users":3},{"id":483,"name":"Gnuwget","users":12}]
'
;
export
const
mockParsedNamespaces
=
[
{
__typename
:
'
Namespace
'
,
id
:
132
,
name
:
'
Gitlab Org
'
,
users
:
3
},
{
__typename
:
'
Namespace
'
,
id
:
483
,
name
:
'
Gnuwget
'
,
users
:
12
},
];
export
const
mockNamespaces
=
`
[{"id":132,"accountId":"
${
accountId
}
","name":"Gitlab Org","users":3},
{"id":483,"accountId":null,"name":"Gnuwget","users":12}]
`
;
export
const
mockParsedNamespaces
=
JSON
.
parse
(
mockNamespaces
).
map
((
namespace
)
=>
({
...
namespace
,
__typename
:
'
Namespace
'
,
}));
export
const
mockNewUser
=
'
false
'
;
export
const
mockFullName
=
'
John Admin
'
;
export
const
mockSetupForCompany
=
'
true
'
;
export
const
mockDefaultCache
=
{
...
...
@@ -28,13 +32,13 @@ export const mockDefaultCache = {
};
export
const
stateData
=
{
n
amespaces
:
[],
eligibleN
amespaces
:
[],
subscription
:
{
quantity
:
1
,
namespaceId
:
null
,
__typename
:
'
Subscription
'
,
},
redirectAfterSuccess
:
'
/path/to/redirect/
'
,
selectedNamespaceId
:
null
,
selectedPlanId
:
null
,
paymentMethod
:
{
id
:
null
,
...
...
ee/spec/frontend/subscriptions/buy_minutes/spec_helper.js
View file @
75f1f22a
...
...
@@ -2,6 +2,7 @@ import VueApollo from 'vue-apollo';
import
{
writeInitialDataToApolloCache
}
from
'
ee/subscriptions/buy_addons_shared/utils
'
;
import
plansQuery
from
'
ee/subscriptions/graphql/queries/plans.customer.query.graphql
'
;
import
{
createMockClient
}
from
'
helpers/mock_apollo_helper
'
;
import
{
CUSTOMERSDOT_CLIENT
}
from
'
ee/subscriptions/buy_addons_shared/constants
'
;
import
{
mockCiMinutesPlans
,
mockDefaultCache
}
from
'
./mock_data
'
;
export
function
createMockApolloProvider
(
mockResponses
=
{},
dataset
=
{})
{
...
...
@@ -12,11 +13,11 @@ export function createMockApolloProvider(mockResponses = {}, dataset = {}) {
const
{
quantity
}
=
dataset
;
const
mockDefaultClient
=
createMockClient
();
const
mockCustomerClient
=
createMockClient
([[
plansQuery
,
plansQueryMock
]]);
const
mockCustomer
sDot
Client
=
createMockClient
([[
plansQuery
,
plansQueryMock
]]);
const
apolloProvider
=
new
VueApollo
({
defaultClient
:
mockDefaultClient
,
clients
:
{
customerClient
:
mockCustomer
Client
},
clients
:
{
[
CUSTOMERSDOT_CLIENT
]:
mockCustomersDot
Client
},
});
writeInitialDataToApolloCache
(
apolloProvider
,
{
...
...
ee/spec/frontend/subscriptions/new/components/checkout/billing_address_spec.js
View file @
75f1f22a
...
...
@@ -85,7 +85,7 @@ describe('Billing Address', () => {
});
describe
(
'
validations
'
,
()
=>
{
const
isStepValid
=
()
=>
wrapper
.
find
(
Step
).
props
(
'
isValid
'
);
const
isStepValid
=
()
=>
wrapper
.
find
Component
(
Step
).
props
(
'
isValid
'
);
beforeEach
(()
=>
{
store
.
commit
(
types
.
UPDATE_COUNTRY
,
'
country
'
);
...
...
ee/spec/frontend/subscriptions/new/components/checkout/confirm_order_spec.js
View file @
75f1f22a
...
...
@@ -31,8 +31,8 @@ describe('Confirm Order', () => {
});
}
const
findConfirmButton
=
()
=>
wrapper
.
find
(
GlButton
);
const
findLoadingIcon
=
()
=>
wrapper
.
find
(
GlLoadingIcon
);
const
findConfirmButton
=
()
=>
wrapper
.
find
Component
(
GlButton
);
const
findLoadingIcon
=
()
=>
wrapper
.
find
Component
(
GlLoadingIcon
);
afterEach
(()
=>
{
wrapper
.
destroy
();
...
...
ee/spec/frontend/subscriptions/new/components/checkout/payment_method_spec.js
View file @
75f1f22a
...
...
@@ -44,7 +44,7 @@ describe('Payment Method', () => {
});
describe
(
'
validations
'
,
()
=>
{
const
isStepValid
=
()
=>
wrapper
.
find
(
Step
).
props
(
'
isValid
'
);
const
isStepValid
=
()
=>
wrapper
.
find
Component
(
Step
).
props
(
'
isValid
'
);
it
(
'
should be valid when paymentMethodId is defined
'
,
()
=>
{
expect
(
isStepValid
()).
toBe
(
true
);
...
...
ee/spec/frontend/subscriptions/new/components/checkout/subscription_details_spec.js
View file @
75f1f22a
...
...
@@ -263,7 +263,7 @@ describe('Subscription Details', () => {
});
describe
(
'
validations
'
,
()
=>
{
const
isStepValid
=
()
=>
wrapper
.
find
(
Step
).
props
(
'
isValid
'
);
const
isStepValid
=
()
=>
wrapper
.
find
Component
(
Step
).
props
(
'
isValid
'
);
let
store
;
beforeEach
(()
=>
{
...
...
ee/spec/frontend/subscriptions/new/components/checkout/zuora_spec.js
View file @
75f1f22a
...
...
@@ -39,7 +39,7 @@ describe('Zuora', () => {
});
};
const
findLoading
=
()
=>
wrapper
.
find
(
GlLoadingIcon
);
const
findLoading
=
()
=>
wrapper
.
find
Component
(
GlLoadingIcon
);
const
findZuoraPayment
=
()
=>
wrapper
.
find
(
'
#zuora_payment
'
);
beforeEach
(()
=>
{
...
...
ee/spec/frontend/subscriptions/new/components/checkout_spec.js
View file @
75f1f22a
...
...
@@ -17,7 +17,7 @@ describe('Checkout', () => {
});
};
const
findProgressBar
=
()
=>
wrapper
.
find
(
ProgressBar
);
const
findProgressBar
=
()
=>
wrapper
.
find
Component
(
ProgressBar
);
beforeEach
(()
=>
{
store
=
createStore
();
...
...
ee/spec/frontend/
subscriptions/buy_minutes
/components/checkout/payment_method_spec.js
→
ee/spec/frontend/
vue_shared/purchase_flow
/components/checkout/payment_method_spec.js
View file @
75f1f22a
import
{
mount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
{
createLocalVue
}
from
'
@vue/test-utils
'
;
import
{
merge
}
from
'
lodash
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
{
resolvers
}
from
'
ee/subscriptions/buy_addons_shared/graphql/resolvers
'
;
...
...
@@ -6,8 +6,13 @@ import { STEPS } from 'ee/subscriptions/constants';
import
stateQuery
from
'
ee/subscriptions/graphql/queries/state.query.graphql
'
;
import
PaymentMethod
from
'
ee/vue_shared/purchase_flow/components/checkout/payment_method.vue
'
;
import
Step
from
'
ee/vue_shared/purchase_flow/components/step.vue
'
;
import
{
stateData
as
initialStateData
}
from
'
ee_jest/subscriptions/buy_minutes/mock_data
'
;
import
{
mockParsedNamespaces
,
stateData
as
initialStateData
,
}
from
'
ee_jest/subscriptions/buy_minutes/mock_data
'
;
import
{
createMockApolloProvider
}
from
'
ee_jest/vue_shared/purchase_flow/spec_helper
'
;
import
Zuora
from
'
ee/vue_shared/purchase_flow/components/checkout/zuora.vue
'
;
import
{
mountExtended
}
from
'
helpers/vue_test_utils_helper
'
;
const
localVue
=
createLocalVue
();
localVue
.
use
(
VueApollo
);
...
...
@@ -15,6 +20,12 @@ localVue.use(VueApollo);
describe
(
'
Payment Method
'
,
()
=>
{
let
wrapper
;
const
findCCDetails
=
()
=>
wrapper
.
findByTestId
(
'
card-details
'
);
const
findCCExpiration
=
()
=>
wrapper
.
findByTestId
(
'
card-expiration
'
);
const
findZuora
=
()
=>
wrapper
.
findComponent
(
Zuora
);
const
isStepValid
=
()
=>
wrapper
.
findComponent
(
Step
).
props
(
'
isValid
'
);
const
createComponent
=
(
apolloLocalState
=
{})
=>
{
const
apolloProvider
=
createMockApolloProvider
(
STEPS
,
STEPS
[
2
],
{
...
resolvers
,
...
...
@@ -24,7 +35,7 @@ describe('Payment Method', () => {
data
:
merge
({},
initialStateData
,
apolloLocalState
),
});
return
mount
(
PaymentMethod
,
{
return
mount
Extended
(
PaymentMethod
,
{
localVue
,
apolloProvider
,
});
...
...
@@ -46,14 +57,12 @@ describe('Payment Method', () => {
wrapper
.
destroy
();
});
describe
(
'
validations
'
,
()
=>
{
const
isStepValid
=
()
=>
wrapper
.
find
(
Step
).
props
(
'
isValid
'
);
it
(
'
should be valid when paymentMethodId is defined
'
,
()
=>
{
describe
(
'
payment method step
'
,
()
=>
{
it
(
'
is valid when paymentMethodId is defined
'
,
()
=>
{
expect
(
isStepValid
()).
toBe
(
true
);
});
it
(
'
should be
invalid when paymentMethodId is undefined
'
,
()
=>
{
it
(
'
is
invalid when paymentMethodId is undefined
'
,
()
=>
{
wrapper
=
createComponent
({
paymentMethod
:
{
id
:
null
},
});
...
...
@@ -62,15 +71,50 @@ describe('Payment Method', () => {
});
});
describe
(
'
showing the summary
'
,
()
=>
{
it
(
'
should show the entered credit card details
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-summary-line-1
'
).
text
()).
toMatchInterpolatedText
(
'
Visa ending in 4242
'
,
);
describe
(
'
summary
'
,
()
=>
{
it
(
'
shows the entered credit card details
'
,
()
=>
{
expect
(
findCCDetails
().
text
()).
toMatchInterpolatedText
(
'
Visa ending in 4242
'
);
});
it
(
'
shows the entered credit card expiration date
'
,
()
=>
{
expect
(
findCCExpiration
().
text
()).
toBe
(
'
Exp 12/09
'
);
});
});
describe
(
'
Zuora Component
'
,
()
=>
{
const
eligibleNamespaces
=
mockParsedNamespaces
;
const
active
=
true
;
const
activeStep
=
STEPS
[
2
];
describe
(
'
when the selected namespace exists
'
,
()
=>
{
describe
(
'
when it has an account id
'
,
()
=>
{
it
(
'
has the selected account id
'
,
()
=>
{
const
{
accountId
,
id
}
=
mockParsedNamespaces
[
0
];
const
selectedNamespaceId
=
`
${
id
}
`
;
wrapper
=
createComponent
({
eligibleNamespaces
,
selectedNamespaceId
,
activeStep
});
expect
(
findZuora
().
props
()).
toMatchObject
({
active
,
accountId
});
});
});
describe
(
'
when it has no account id
'
,
()
=>
{
it
(
'
has the default account id
'
,
()
=>
{
const
{
id
}
=
mockParsedNamespaces
[
1
];
const
selectedNamespaceId
=
`
${
id
}
`
;
wrapper
=
createComponent
({
eligibleNamespaces
,
selectedNamespaceId
,
activeStep
});
expect
(
findZuora
().
props
()).
toMatchObject
({
active
,
accountId
:
''
});
});
});
});
it
(
'
should show the entered credit card expiration date
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-summary-line-2
'
).
text
()).
toBe
(
'
Exp 12/09
'
);
describe
(
'
when the selected namespace does not exists
'
,
()
=>
{
it
(
'
has the default account id
'
,
()
=>
{
const
selectedNamespaceId
=
`000`
;
wrapper
=
createComponent
({
eligibleNamespaces
,
selectedNamespaceId
,
activeStep
});
expect
(
findZuora
().
props
()).
toMatchObject
({
active
,
accountId
:
''
});
});
});
});
});
ee/spec/frontend/
subscriptions/buy_minutes
/components/checkout/zuora_spec.js
→
ee/spec/frontend/
vue_shared/purchase_flow
/components/checkout/zuora_spec.js
View file @
75f1f22a
...
...
@@ -10,6 +10,7 @@ import Zuora from 'ee/vue_shared/purchase_flow/components/checkout/zuora.vue';
import
{
stateData
as
initialStateData
}
from
'
ee_jest/subscriptions/buy_minutes/mock_data
'
;
import
{
createMockApolloProvider
}
from
'
ee_jest/vue_shared/purchase_flow/spec_helper
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
flushPromises
from
'
helpers/flush_promises
'
;
const
localVue
=
createLocalVue
();
localVue
.
use
(
VueApollo
);
...
...
@@ -39,7 +40,7 @@ describe('Zuora', () => {
});
};
const
findLoading
=
()
=>
wrapper
.
find
(
GlLoadingIcon
);
const
findLoading
=
()
=>
wrapper
.
find
Component
(
GlLoadingIcon
);
const
findZuoraPayment
=
()
=>
wrapper
.
find
(
'
#zuora_payment
'
);
beforeEach
(()
=>
{
...
...
@@ -47,7 +48,7 @@ describe('Zuora', () => {
runAfterRender
(
fn
)
{
return
Promise
.
resolve
().
then
(
fn
);
},
render
()
{}
,
render
:
jest
.
fn
()
,
};
axiosMock
=
new
AxiosMockAdapter
(
axios
);
...
...
@@ -97,4 +98,25 @@ describe('Zuora', () => {
expect
(
findZuoraPayment
().
isVisible
()).
toBe
(
false
);
});
});
describe
.
each
([
''
,
'
111111
'
])(
'
when rendering the iframe with account id: %s
'
,
(
id
)
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({
accountId
:
id
},
{
isLoading
:
false
});
wrapper
.
vm
.
zuoraScriptEl
.
onload
();
return
flushPromises
();
});
it
(
`calls render with
${
id
}
`
,
()
=>
{
expect
(
window
.
Z
.
render
).
toHaveBeenCalledWith
(
{
field_accountId
:
id
,
retainValues
:
'
true
'
,
style
:
'
inline
'
,
submitEnabled
:
'
true
'
,
},
{},
expect
.
any
(
Function
),
);
});
});
});
ee/spec/frontend/vue_shared/purchase_flow/components/step_spec.js
View file @
75f1f22a
...
...
@@ -171,14 +171,14 @@ describe('Step', () => {
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
1
);
wrapper
=
createComponent
({
apolloProvider
:
mockApollo
});
expect
(
wrapper
.
find
(
GlButton
).
attributes
(
'
disabled
'
)).
toBeUndefined
();
expect
(
wrapper
.
find
Component
(
GlButton
).
attributes
(
'
disabled
'
)).
toBeUndefined
();
});
it
(
'
displays an error if navigating too far
'
,
async
()
=>
{
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
2
);
wrapper
=
createComponent
({
propsData
:
{
stepId
:
STEPS
[
2
].
id
},
apolloProvider
:
mockApollo
});
wrapper
.
find
(
GlButton
).
vm
.
$emit
(
'
click
'
);
wrapper
.
find
Component
(
GlButton
).
vm
.
$emit
(
'
click
'
);
await
waitForPromises
();
expect
(
flash
.
mock
.
calls
).
toHaveLength
(
1
);
...
...
ee/spec/helpers/subscriptions_helper_spec.rb
View file @
75f1f22a
...
...
@@ -51,7 +51,7 @@ RSpec.describe SubscriptionsHelper do
it
{
is_expected
.
to
include
(
plan_id:
'bronze_id'
)
}
it
{
is_expected
.
to
include
(
namespace_id:
group
.
id
.
to_s
)
}
it
{
is_expected
.
to
include
(
source:
'some_source'
)
}
it
{
is_expected
.
to
include
(
group_data:
%Q{[{"id":
#{
group
.
id
}
,"name":"My Namespace","users":2,"guests":1}]}
)
}
it
{
is_expected
.
to
include
(
group_data:
%Q{[{"id":
#{
group
.
id
}
,"
account_id":null,"
name":"My Namespace","users":2,"guests":1}]}
)
}
describe
'new_user'
do
where
(
:referer
,
:expected_result
)
do
...
...
@@ -150,7 +150,7 @@ RSpec.describe SubscriptionsHelper do
it
{
is_expected
.
to
include
(
namespace_id:
group
.
id
.
to_s
)
}
it
{
is_expected
.
to
include
(
source:
'some_source'
)
}
it
{
is_expected
.
to
include
(
group_data:
%Q{[{"id":
#{
group
.
id
}
,"name":"My Namespace","users":1,"guests":0}]}
)
}
it
{
is_expected
.
to
include
(
group_data:
%Q{[{"id":
#{
group
.
id
}
,"
account_id":null,"
name":"My Namespace","users":1,"guests":0}]}
)
}
it
{
is_expected
.
to
include
(
redirect_after_success:
group_usage_quotas_path
(
group
,
anchor:
anchor
,
purchased_product:
purchased_product
))
}
end
end
spec/frontend/__helpers__/flush_promises.js
0 → 100644
View file @
75f1f22a
export
default
function
flushPromises
()
{
return
new
Promise
(
setImmediate
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment