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
adef44af
Commit
adef44af
authored
Apr 12, 2021
by
Michael Lunøe
Committed by
David O'Regan
Apr 12, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Feat(Purchase flow): Add steps error handling
parent
dc0858ff
Changes
11
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
314 additions
and
261 deletions
+314
-261
ee/app/assets/javascripts/subscriptions/new/components/checkout/confirm_order.vue
...s/subscriptions/new/components/checkout/confirm_order.vue
+6
-1
ee/app/assets/javascripts/subscriptions/new/store/actions.js
ee/app/assets/javascripts/subscriptions/new/store/actions.js
+8
-3
ee/app/assets/javascripts/vue_shared/purchase_flow/components/step.vue
.../javascripts/vue_shared/purchase_flow/components/step.vue
+14
-0
ee/app/assets/javascripts/vue_shared/purchase_flow/constants.js
.../assets/javascripts/vue_shared/purchase_flow/constants.js
+5
-0
ee/changelogs/unreleased/321650-mlunoe-migrate-purchase-flow-components-follow-up.yml
...650-mlunoe-migrate-purchase-flow-components-follow-up.yml
+5
-0
ee/spec/frontend/subscriptions/new/components/checkout/confirm_order_spec.js
...bscriptions/new/components/checkout/confirm_order_spec.js
+42
-26
ee/spec/frontend/subscriptions/new/store/actions_spec.js
ee/spec/frontend/subscriptions/new/store/actions_spec.js
+147
-185
ee/spec/frontend/vue_shared/purchase_flow/components/step_spec.js
...frontend/vue_shared/purchase_flow/components/step_spec.js
+52
-8
ee/spec/frontend/vue_shared/purchase_flow/graphql/resolvers_spec.js
...ontend/vue_shared/purchase_flow/graphql/resolvers_spec.js
+31
-38
ee/spec/frontend/vue_shared/purchase_flow/mock_data.js
ee/spec/frontend/vue_shared/purchase_flow/mock_data.js
+1
-0
locale/gitlab.pot
locale/gitlab.pot
+3
-0
No files found.
ee/app/assets/javascripts/subscriptions/new/components/checkout/confirm_order.vue
View file @
adef44af
<
script
>
<
script
>
import
{
GlButton
,
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
{
GlButton
,
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
{
mapState
,
mapActions
}
from
'
vuex
'
;
import
{
mapState
,
mapActions
}
from
'
vuex
'
;
import
{
GENERAL_ERROR_MESSAGE
}
from
'
ee/vue_shared/purchase_flow/constants
'
;
import
activeStepQuery
from
'
ee/vue_shared/purchase_flow/graphql/queries/active_step.query.graphql
'
;
import
activeStepQuery
from
'
ee/vue_shared/purchase_flow/graphql/queries/active_step.query.graphql
'
;
import
createFlash
from
'
~/flash
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
STEPS
}
from
'
../../constants
'
;
import
{
STEPS
}
from
'
../../constants
'
;
...
@@ -18,7 +20,10 @@ export default {
...
@@ -18,7 +20,10 @@ export default {
apollo
:
{
apollo
:
{
isActive
:
{
isActive
:
{
query
:
activeStepQuery
,
query
:
activeStepQuery
,
update
:
({
activeStep
})
=>
activeStep
.
id
===
STEPS
[
3
].
id
,
update
:
({
activeStep
})
=>
activeStep
?.
id
===
STEPS
[
3
].
id
,
error
:
(
error
)
=>
{
createFlash
({
message
:
GENERAL_ERROR_MESSAGE
,
error
,
captureError
:
true
});
},
},
},
},
},
computed
:
{
computed
:
{
...
...
ee/app/assets/javascripts/subscriptions/new/store/actions.js
View file @
adef44af
import
Api
from
'
ee/api
'
;
import
Api
from
'
ee/api
'
;
import
{
GENERAL_ERROR_MESSAGE
}
from
'
ee/vue_shared/purchase_flow/constants
'
;
import
activateNextStepMutation
from
'
ee/vue_shared/purchase_flow/graphql/mutations/activate_next_step.mutation.graphql
'
;
import
activateNextStepMutation
from
'
ee/vue_shared/purchase_flow/graphql/mutations/activate_next_step.mutation.graphql
'
;
import
createFlash
from
'
~/flash
'
;
import
createFlash
from
'
~/flash
'
;
import
{
redirectTo
}
from
'
~/lib/utils/url_utility
'
;
import
{
redirectTo
}
from
'
~/lib/utils/url_utility
'
;
...
@@ -169,8 +170,12 @@ export const fetchPaymentMethodDetails = ({ state, dispatch, commit }) =>
...
@@ -169,8 +170,12 @@ export const fetchPaymentMethodDetails = ({ state, dispatch, commit }) =>
export
const
fetchPaymentMethodDetailsSuccess
=
({
commit
},
creditCardDetails
)
=>
{
export
const
fetchPaymentMethodDetailsSuccess
=
({
commit
},
creditCardDetails
)
=>
{
commit
(
types
.
UPDATE_CREDIT_CARD_DETAILS
,
creditCardDetails
);
commit
(
types
.
UPDATE_CREDIT_CARD_DETAILS
,
creditCardDetails
);
defaultClient
.
mutate
({
defaultClient
.
mutate
({
mutation
:
activateNextStepMutation
,
mutation
:
activateNextStepMutation
,
})
.
catch
((
error
)
=>
{
createFlash
({
message
:
GENERAL_ERROR_MESSAGE
,
error
,
captureError
:
true
});
});
});
};
};
...
...
ee/app/assets/javascripts/vue_shared/purchase_flow/components/step.vue
View file @
adef44af
...
@@ -4,7 +4,9 @@ import activateNextStepMutation from 'ee/vue_shared/purchase_flow/graphql/mutati
...
@@ -4,7 +4,9 @@ import activateNextStepMutation from 'ee/vue_shared/purchase_flow/graphql/mutati
import
updateStepMutation
from
'
ee/vue_shared/purchase_flow/graphql/mutations/update_active_step.mutation.graphql
'
;
import
updateStepMutation
from
'
ee/vue_shared/purchase_flow/graphql/mutations/update_active_step.mutation.graphql
'
;
import
activeStepQuery
from
'
ee/vue_shared/purchase_flow/graphql/queries/active_step.query.graphql
'
;
import
activeStepQuery
from
'
ee/vue_shared/purchase_flow/graphql/queries/active_step.query.graphql
'
;
import
stepListQuery
from
'
ee/vue_shared/purchase_flow/graphql/queries/step_list.query.graphql
'
;
import
stepListQuery
from
'
ee/vue_shared/purchase_flow/graphql/queries/step_list.query.graphql
'
;
import
createFlash
from
'
~/flash
'
;
import
{
convertToSnakeCase
,
dasherize
}
from
'
~/lib/utils/text_utility
'
;
import
{
convertToSnakeCase
,
dasherize
}
from
'
~/lib/utils/text_utility
'
;
import
{
GENERAL_ERROR_MESSAGE
}
from
'
../constants
'
;
import
StepHeader
from
'
./step_header.vue
'
;
import
StepHeader
from
'
./step_header.vue
'
;
import
StepSummary
from
'
./step_summary.vue
'
;
import
StepSummary
from
'
./step_summary.vue
'
;
...
@@ -44,6 +46,9 @@ export default {
...
@@ -44,6 +46,9 @@ export default {
apollo
:
{
apollo
:
{
activeStep
:
{
activeStep
:
{
query
:
activeStepQuery
,
query
:
activeStepQuery
,
error
(
error
)
{
this
.
handleError
(
error
);
},
},
},
stepList
:
{
stepList
:
{
query
:
stepListQuery
,
query
:
stepListQuery
,
...
@@ -66,6 +71,9 @@ export default {
...
@@ -66,6 +71,9 @@ export default {
},
},
},
},
methods
:
{
methods
:
{
handleError
(
error
)
{
createFlash
({
message
:
GENERAL_ERROR_MESSAGE
,
error
,
captureError
:
true
});
},
async
nextStep
()
{
async
nextStep
()
{
if
(
!
this
.
isValid
)
{
if
(
!
this
.
isValid
)
{
return
;
return
;
...
@@ -75,6 +83,9 @@ export default {
...
@@ -75,6 +83,9 @@ export default {
.
mutate
({
.
mutate
({
mutation
:
activateNextStepMutation
,
mutation
:
activateNextStepMutation
,
})
})
.
catch
((
error
)
=>
{
this
.
handleError
(
error
);
})
.
finally
(()
=>
{
.
finally
(()
=>
{
this
.
loading
=
false
;
this
.
loading
=
false
;
});
});
...
@@ -86,6 +97,9 @@ export default {
...
@@ -86,6 +97,9 @@ export default {
mutation
:
updateStepMutation
,
mutation
:
updateStepMutation
,
variables
:
{
id
:
this
.
stepId
},
variables
:
{
id
:
this
.
stepId
},
})
})
.
catch
((
error
)
=>
{
this
.
handleError
(
error
);
})
.
finally
(()
=>
{
.
finally
(()
=>
{
this
.
loading
=
false
;
this
.
loading
=
false
;
});
});
...
...
ee/app/assets/javascripts/vue_shared/purchase_flow/constants.js
0 → 100644
View file @
adef44af
import
{
s__
}
from
'
~/locale
'
;
export
const
GENERAL_ERROR_MESSAGE
=
s__
(
'
PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com.
'
,
);
ee/changelogs/unreleased/321650-mlunoe-migrate-purchase-flow-components-follow-up.yml
0 → 100644
View file @
adef44af
---
title
:
Add error handling feedback inside purchase flow
merge_request
:
58084
author
:
type
:
changed
ee/spec/frontend/subscriptions/new/components/checkout/confirm_order_spec.js
View file @
adef44af
...
@@ -6,8 +6,11 @@ import Api from 'ee/api';
...
@@ -6,8 +6,11 @@ import Api from 'ee/api';
import
ConfirmOrder
from
'
ee/subscriptions/new/components/checkout/confirm_order.vue
'
;
import
ConfirmOrder
from
'
ee/subscriptions/new/components/checkout/confirm_order.vue
'
;
import
{
STEPS
}
from
'
ee/subscriptions/new/constants
'
;
import
{
STEPS
}
from
'
ee/subscriptions/new/constants
'
;
import
createStore
from
'
ee/subscriptions/new/store
'
;
import
createStore
from
'
ee/subscriptions/new/store
'
;
import
updateStepMutation
from
'
ee/vue_shared/purchase_flow/graphql/mutations/update_active_step.mutation.graphql
'
;
import
{
GENERAL_ERROR_MESSAGE
}
from
'
ee/vue_shared/purchase_flow/constants
'
;
import
{
createMockApolloProvider
}
from
'
ee_jest/vue_shared/purchase_flow/spec_helper
'
;
import
{
createMockApolloProvider
}
from
'
ee_jest/vue_shared/purchase_flow/spec_helper
'
;
import
flash
from
'
~/flash
'
;
jest
.
mock
(
'
~/flash
'
);
describe
(
'
Confirm Order
'
,
()
=>
{
describe
(
'
Confirm Order
'
,
()
=>
{
const
localVue
=
createLocalVue
();
const
localVue
=
createLocalVue
();
...
@@ -15,19 +18,11 @@ describe('Confirm Order', () => {
...
@@ -15,19 +18,11 @@ describe('Confirm Order', () => {
localVue
.
use
(
VueApollo
);
localVue
.
use
(
VueApollo
);
let
wrapper
;
let
wrapper
;
let
mockApolloProvider
;
jest
.
mock
(
'
ee/api.js
'
);
jest
.
mock
(
'
ee/api.js
'
);
const
store
=
createStore
();
const
store
=
createStore
();
function
activateStep
(
stepId
)
{
return
mockApolloProvider
.
clients
.
defaultClient
.
mutate
({
mutation
:
updateStepMutation
,
variables
:
{
id
:
stepId
},
});
}
function
createComponent
(
options
=
{})
{
function
createComponent
(
options
=
{})
{
return
shallowMount
(
ConfirmOrder
,
{
return
shallowMount
(
ConfirmOrder
,
{
localVue
,
localVue
,
...
@@ -39,18 +34,15 @@ describe('Confirm Order', () => {
...
@@ -39,18 +34,15 @@ describe('Confirm Order', () => {
const
findConfirmButton
=
()
=>
wrapper
.
find
(
GlButton
);
const
findConfirmButton
=
()
=>
wrapper
.
find
(
GlButton
);
const
findLoadingIcon
=
()
=>
wrapper
.
find
(
GlLoadingIcon
);
const
findLoadingIcon
=
()
=>
wrapper
.
find
(
GlLoadingIcon
);
beforeEach
(()
=>
{
mockApolloProvider
=
createMockApolloProvider
(
STEPS
);
wrapper
=
createComponent
({
apolloProvider
:
mockApolloProvider
});
});
afterEach
(()
=>
{
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
.
destroy
();
});
});
describe
(
'
Active
'
,
()
=>
{
describe
(
'
Active
'
,
()
=>
{
describe
(
'
when receiving proper step data
'
,
()
=>
{
beforeEach
(
async
()
=>
{
beforeEach
(
async
()
=>
{
await
activateStep
(
STEPS
[
3
].
id
);
const
mockApolloProvider
=
createMockApolloProvider
(
STEPS
,
3
);
wrapper
=
createComponent
({
apolloProvider
:
mockApolloProvider
});
});
});
it
(
'
button should be visible
'
,
()
=>
{
it
(
'
button should be visible
'
,
()
=>
{
...
@@ -64,9 +56,12 @@ describe('Confirm Order', () => {
...
@@ -64,9 +56,12 @@ describe('Confirm Order', () => {
it
(
'
the loading indicator should not be visible
'
,
()
=>
{
it
(
'
the loading indicator should not be visible
'
,
()
=>
{
expect
(
findLoadingIcon
().
exists
()).
toBe
(
false
);
expect
(
findLoadingIcon
().
exists
()).
toBe
(
false
);
});
});
});
describe
(
'
Clicking the button
'
,
()
=>
{
describe
(
'
Clicking the button
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
const
mockApolloProvider
=
createMockApolloProvider
(
STEPS
,
3
);
wrapper
=
createComponent
({
apolloProvider
:
mockApolloProvider
});
Api
.
confirmOrder
=
jest
.
fn
().
mockReturnValue
(
new
Promise
(
jest
.
fn
()));
Api
.
confirmOrder
=
jest
.
fn
().
mockReturnValue
(
new
Promise
(
jest
.
fn
()));
findConfirmButton
().
vm
.
$emit
(
'
click
'
);
findConfirmButton
().
vm
.
$emit
(
'
click
'
);
...
@@ -84,11 +79,32 @@ describe('Confirm Order', () => {
...
@@ -84,11 +79,32 @@ describe('Confirm Order', () => {
expect
(
findLoadingIcon
().
exists
()).
toBe
(
true
);
expect
(
findLoadingIcon
().
exists
()).
toBe
(
true
);
});
});
});
});
describe
(
'
when failing to receive step data
'
,
()
=>
{
beforeEach
(
async
()
=>
{
const
mockApolloProvider
=
createMockApolloProvider
([]);
mockApolloProvider
.
clients
.
defaultClient
.
clearStore
();
wrapper
=
createComponent
({
apolloProvider
:
mockApolloProvider
});
});
afterEach
(()
=>
{
flash
.
mockClear
();
});
it
(
'
displays an error
'
,
()
=>
{
expect
(
flash
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
message
:
GENERAL_ERROR_MESSAGE
,
captureError
:
true
,
error
:
expect
.
any
(
Error
),
});
});
});
});
});
describe
(
'
Inactive
'
,
()
=>
{
describe
(
'
Inactive
'
,
()
=>
{
beforeEach
(
async
()
=>
{
beforeEach
(
async
()
=>
{
await
activateStep
(
STEPS
[
1
].
id
);
const
mockApolloProvider
=
createMockApolloProvider
(
STEPS
,
1
);
wrapper
=
createComponent
({
apolloProvider
:
mockApolloProvider
});
});
});
it
(
'
button should not be visible
'
,
()
=>
{
it
(
'
button should not be visible
'
,
()
=>
{
...
...
ee/spec/frontend/subscriptions/new/store/actions_spec.js
View file @
adef44af
This diff is collapsed.
Click to expand it.
ee/spec/frontend/vue_shared/purchase_flow/components/step_spec.js
View file @
adef44af
...
@@ -3,13 +3,18 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
...
@@ -3,13 +3,18 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import
VueApollo
from
'
vue-apollo
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
Step
from
'
ee/vue_shared/purchase_flow/components/step.vue
'
;
import
Step
from
'
ee/vue_shared/purchase_flow/components/step.vue
'
;
import
StepSummary
from
'
ee/vue_shared/purchase_flow/components/step_summary.vue
'
;
import
StepSummary
from
'
ee/vue_shared/purchase_flow/components/step_summary.vue
'
;
import
{
GENERAL_ERROR_MESSAGE
}
from
'
ee/vue_shared/purchase_flow/constants
'
;
import
updateStepMutation
from
'
ee/vue_shared/purchase_flow/graphql/mutations/update_active_step.mutation.graphql
'
;
import
updateStepMutation
from
'
ee/vue_shared/purchase_flow/graphql/mutations/update_active_step.mutation.graphql
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
import
flash
from
'
~/flash
'
;
import
{
STEPS
}
from
'
../mock_data
'
;
import
{
STEPS
}
from
'
../mock_data
'
;
import
{
createMockApolloProvider
}
from
'
../spec_helper
'
;
import
{
createMockApolloProvider
}
from
'
../spec_helper
'
;
const
localVue
=
createLocalVue
();
const
localVue
=
createLocalVue
();
localVue
.
use
(
VueApollo
);
localVue
.
use
(
VueApollo
);
jest
.
mock
(
'
~/flash
'
);
describe
(
'
Step
'
,
()
=>
{
describe
(
'
Step
'
,
()
=>
{
let
wrapper
;
let
wrapper
;
...
@@ -32,11 +37,15 @@ describe('Step', () => {
...
@@ -32,11 +37,15 @@ describe('Step', () => {
localVue
,
localVue
,
propsData
:
{
...
initialProps
,
...
propsData
},
propsData
:
{
...
initialProps
,
...
propsData
},
apolloProvider
,
apolloProvider
,
stubs
:
{
StepSummary
,
},
});
});
}
}
afterEach
(()
=>
{
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
.
destroy
();
flash
.
mockClear
();
});
});
describe
(
'
Step Body
'
,
()
=>
{
describe
(
'
Step Body
'
,
()
=>
{
...
@@ -61,7 +70,27 @@ describe('Step', () => {
...
@@ -61,7 +70,27 @@ describe('Step', () => {
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
1
);
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
1
);
await
activateFirstStep
(
mockApollo
);
await
activateFirstStep
(
mockApollo
);
wrapper
=
createComponent
({
apolloProvider
:
mockApollo
});
wrapper
=
createComponent
({
apolloProvider
:
mockApollo
});
expect
(
wrapper
.
find
(
StepSummary
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
findComponent
(
StepSummary
).
exists
()).
toBe
(
true
);
});
it
(
'
displays an error when editing a wrong step
'
,
async
()
=>
{
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
1
);
await
activateFirstStep
(
mockApollo
);
wrapper
=
createComponent
({
propsData
:
{
stepId
:
'
does not exist
'
},
apolloProvider
:
mockApollo
,
});
wrapper
.
findComponent
(
StepSummary
).
findComponent
(
GlButton
).
vm
.
$emit
(
'
click
'
);
await
waitForPromises
();
expect
(
flash
.
mock
.
calls
).
toHaveLength
(
1
);
expect
(
flash
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
message
:
GENERAL_ERROR_MESSAGE
,
captureError
:
true
,
error
:
expect
.
any
(
Error
),
});
});
});
it
(
'
should not be shown when this step is not valid and not active
'
,
async
()
=>
{
it
(
'
should not be shown when this step is not valid and not active
'
,
async
()
=>
{
...
@@ -69,21 +98,21 @@ describe('Step', () => {
...
@@ -69,21 +98,21 @@ describe('Step', () => {
await
activateFirstStep
(
mockApollo
);
await
activateFirstStep
(
mockApollo
);
wrapper
=
createComponent
({
propsData
:
{
isValid
:
false
},
apolloProvider
:
mockApollo
});
wrapper
=
createComponent
({
propsData
:
{
isValid
:
false
},
apolloProvider
:
mockApollo
});
expect
(
wrapper
.
find
(
StepSummary
).
exists
()).
toBe
(
false
);
expect
(
wrapper
.
find
Component
(
StepSummary
).
exists
()).
toBe
(
false
);
});
});
it
(
'
should not be shown when this step is valid and active
'
,
()
=>
{
it
(
'
should not be shown when this step is valid and active
'
,
()
=>
{
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
1
);
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
1
);
wrapper
=
createComponent
({
apolloProvider
:
mockApollo
});
wrapper
=
createComponent
({
apolloProvider
:
mockApollo
});
expect
(
wrapper
.
find
(
StepSummary
).
exists
()).
toBe
(
false
);
expect
(
wrapper
.
find
Component
(
StepSummary
).
exists
()).
toBe
(
false
);
});
});
it
(
'
should not be shown when this step is not valid and active
'
,
()
=>
{
it
(
'
should not be shown when this step is not valid and active
'
,
()
=>
{
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
1
);
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
1
);
wrapper
=
createComponent
({
propsData
:
{
isValid
:
false
},
apolloProvider
:
mockApollo
});
wrapper
=
createComponent
({
propsData
:
{
isValid
:
false
},
apolloProvider
:
mockApollo
});
expect
(
wrapper
.
find
(
StepSummary
).
exists
()).
toBe
(
false
);
expect
(
wrapper
.
find
Component
(
StepSummary
).
exists
()).
toBe
(
false
);
});
});
});
});
...
@@ -92,7 +121,7 @@ describe('Step', () => {
...
@@ -92,7 +121,7 @@ describe('Step', () => {
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
1
);
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
1
);
wrapper
=
createComponent
({
propsData
:
{
stepId
:
STEPS
[
0
].
id
},
apolloProvider
:
mockApollo
});
wrapper
=
createComponent
({
propsData
:
{
stepId
:
STEPS
[
0
].
id
},
apolloProvider
:
mockApollo
});
expect
(
wrapper
.
find
(
StepSummary
).
props
(
'
isEditable
'
)).
toBe
(
true
);
expect
(
wrapper
.
find
Component
(
StepSummary
).
props
(
'
isEditable
'
)).
toBe
(
true
);
});
});
});
});
...
@@ -102,14 +131,14 @@ describe('Step', () => {
...
@@ -102,14 +131,14 @@ describe('Step', () => {
await
activateFirstStep
(
mockApollo
);
await
activateFirstStep
(
mockApollo
);
wrapper
=
createComponent
({
apolloProvider
:
mockApollo
});
wrapper
=
createComponent
({
apolloProvider
:
mockApollo
});
expect
(
wrapper
.
find
(
StepSummary
).
exists
()).
toBe
(
true
);
expect
(
wrapper
.
find
Component
(
StepSummary
).
exists
()).
toBe
(
true
);
});
});
it
(
'
does not show the summary when this step is not finished
'
,
()
=>
{
it
(
'
does not show the summary when this step is not finished
'
,
()
=>
{
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
1
);
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
1
);
wrapper
=
createComponent
({
apolloProvider
:
mockApollo
});
wrapper
=
createComponent
({
apolloProvider
:
mockApollo
});
expect
(
wrapper
.
find
(
StepSummary
).
exists
()).
toBe
(
false
);
expect
(
wrapper
.
find
Component
(
StepSummary
).
exists
()).
toBe
(
false
);
});
});
});
});
...
@@ -135,7 +164,7 @@ describe('Step', () => {
...
@@ -135,7 +164,7 @@ describe('Step', () => {
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
1
);
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
1
);
wrapper
=
createComponent
({
propsData
:
{
isValid
:
false
},
apolloProvider
:
mockApollo
});
wrapper
=
createComponent
({
propsData
:
{
isValid
:
false
},
apolloProvider
:
mockApollo
});
expect
(
wrapper
.
find
(
GlButton
).
attributes
(
'
disabled
'
)).
toBe
(
'
true
'
);
expect
(
wrapper
.
find
Component
(
GlButton
).
attributes
(
'
disabled
'
)).
toBe
(
'
true
'
);
});
});
it
(
'
is enabled when this step is valid
'
,
()
=>
{
it
(
'
is enabled when this step is valid
'
,
()
=>
{
...
@@ -144,5 +173,20 @@ describe('Step', () => {
...
@@ -144,5 +173,20 @@ describe('Step', () => {
expect
(
wrapper
.
find
(
GlButton
).
attributes
(
'
disabled
'
)).
toBeUndefined
();
expect
(
wrapper
.
find
(
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
'
);
await
waitForPromises
();
expect
(
flash
.
mock
.
calls
).
toHaveLength
(
1
);
expect
(
flash
.
mock
.
calls
[
0
][
0
]).
toMatchObject
({
message
:
GENERAL_ERROR_MESSAGE
,
captureError
:
true
,
error
:
expect
.
any
(
Error
),
});
});
});
});
});
});
ee/spec/frontend/vue_shared/purchase_flow/graphql/resolvers_spec.js
View file @
adef44af
import
{
createMockClient
}
from
'
mock-apollo-client
'
;
import
activateNextStepMutation
from
'
ee/vue_shared/purchase_flow/graphql/mutations/activate_next_step.mutation.graphql
'
;
import
activateNextStepMutation
from
'
ee/vue_shared/purchase_flow/graphql/mutations/activate_next_step.mutation.graphql
'
;
import
updateStepMutation
from
'
ee/vue_shared/purchase_flow/graphql/mutations/update_active_step.mutation.graphql
'
;
import
updateStepMutation
from
'
ee/vue_shared/purchase_flow/graphql/mutations/update_active_step.mutation.graphql
'
;
import
activeStepQuery
from
'
ee/vue_shared/purchase_flow/graphql/queries/active_step.query.graphql
'
;
import
activeStepQuery
from
'
ee/vue_shared/purchase_flow/graphql/queries/active_step.query.graphql
'
;
import
stepListQuery
from
'
ee/vue_shared/purchase_flow/graphql/queries/step_list.query.graphql
'
;
import
stepListQuery
from
'
ee/vue_shared/purchase_flow/graphql/queries/step_list.query.graphql
'
;
import
resolvers
from
'
ee/vue_shared/purchase_flow/graphql/resolvers
'
;
import
typeDefs
from
'
ee/vue_shared/purchase_flow/graphql/typedefs.graphql
'
;
import
{
STEPS
}
from
'
../mock_data
'
;
import
{
STEPS
}
from
'
../mock_data
'
;
import
{
createMockApolloProvider
}
from
'
../spec_helper
'
;
describe
(
'
ee/vue_shared/purchase_flow/graphql/resolvers
'
,
()
=>
{
describe
(
'
ee/vue_shared/purchase_flow/graphql/resolvers
'
,
()
=>
{
let
mockClient
;
let
mock
Apollo
Client
;
describe
(
'
Query
'
,
()
=>
{
beforeEach
(
async
()
=>
{
beforeEach
(
async
()
=>
{
mockClient
=
createMockClient
({
resolvers
,
typeDefs
});
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
0
);
mockClient
.
cache
.
writeQuery
({
mockApolloClient
=
mockApollo
.
clients
.
defaultClient
;
query
:
stepListQuery
,
data
:
{
stepList
:
STEPS
,
},
});
mockClient
.
cache
.
writeQuery
({
query
:
activeStepQuery
,
data
:
{
activeStep
:
STEPS
[
0
],
},
});
});
});
describe
(
'
Query
'
,
()
=>
{
describe
(
'
stepListQuery
'
,
()
=>
{
describe
(
'
stepListQuery
'
,
()
=>
{
it
(
'
stores the stepList
'
,
async
()
=>
{
it
(
'
stores the stepList
'
,
async
()
=>
{
const
queryResult
=
await
mockClient
.
query
({
query
:
stepListQuery
});
const
queryResult
=
await
mock
Apollo
Client
.
query
({
query
:
stepListQuery
});
expect
(
queryResult
.
data
.
stepList
).
toMatchObject
(
expect
(
queryResult
.
data
.
stepList
).
toMatchObject
(
STEPS
.
map
(({
id
})
=>
{
STEPS
.
map
(({
id
})
=>
{
return
{
id
};
return
{
id
};
...
@@ -38,8 +25,8 @@ describe('ee/vue_shared/purchase_flow/graphql/resolvers', () => {
...
@@ -38,8 +25,8 @@ describe('ee/vue_shared/purchase_flow/graphql/resolvers', () => {
});
});
it
(
'
throws an error when cache is not initiated properly
'
,
async
()
=>
{
it
(
'
throws an error when cache is not initiated properly
'
,
async
()
=>
{
mockClient
.
clearStore
();
mock
Apollo
Client
.
clearStore
();
await
mockClient
.
query
({
query
:
stepListQuery
}).
catch
((
e
)
=>
{
await
mock
Apollo
Client
.
query
({
query
:
stepListQuery
}).
catch
((
e
)
=>
{
expect
(
e
instanceof
Error
).
toBe
(
true
);
expect
(
e
instanceof
Error
).
toBe
(
true
);
});
});
});
});
...
@@ -47,13 +34,13 @@ describe('ee/vue_shared/purchase_flow/graphql/resolvers', () => {
...
@@ -47,13 +34,13 @@ describe('ee/vue_shared/purchase_flow/graphql/resolvers', () => {
describe
(
'
activeStepQuery
'
,
()
=>
{
describe
(
'
activeStepQuery
'
,
()
=>
{
it
(
'
stores the activeStep
'
,
async
()
=>
{
it
(
'
stores the activeStep
'
,
async
()
=>
{
const
queryResult
=
await
mockClient
.
query
({
query
:
activeStepQuery
});
const
queryResult
=
await
mock
Apollo
Client
.
query
({
query
:
activeStepQuery
});
expect
(
queryResult
.
data
.
activeStep
).
toMatchObject
({
id
:
STEPS
[
0
].
id
});
expect
(
queryResult
.
data
.
activeStep
).
toMatchObject
({
id
:
STEPS
[
0
].
id
});
});
});
it
(
'
throws an error when cache is not initiated properly
'
,
async
()
=>
{
it
(
'
throws an error when cache is not initiated properly
'
,
async
()
=>
{
mockClient
.
clearStore
();
mock
Apollo
Client
.
clearStore
();
await
mockClient
.
query
({
query
:
activeStepQuery
}).
catch
((
e
)
=>
{
await
mock
Apollo
Client
.
query
({
query
:
activeStepQuery
}).
catch
((
e
)
=>
{
expect
(
e
instanceof
Error
).
toBe
(
true
);
expect
(
e
instanceof
Error
).
toBe
(
true
);
});
});
});
});
...
@@ -62,18 +49,23 @@ describe('ee/vue_shared/purchase_flow/graphql/resolvers', () => {
...
@@ -62,18 +49,23 @@ describe('ee/vue_shared/purchase_flow/graphql/resolvers', () => {
describe
(
'
Mutation
'
,
()
=>
{
describe
(
'
Mutation
'
,
()
=>
{
describe
(
'
updateActiveStep
'
,
()
=>
{
describe
(
'
updateActiveStep
'
,
()
=>
{
beforeEach
(
async
()
=>
{
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
0
);
mockApolloClient
=
mockApollo
.
clients
.
defaultClient
;
});
it
(
'
updates the active step
'
,
async
()
=>
{
it
(
'
updates the active step
'
,
async
()
=>
{
await
mockClient
.
mutate
({
await
mock
Apollo
Client
.
mutate
({
mutation
:
updateStepMutation
,
mutation
:
updateStepMutation
,
variables
:
{
id
:
STEPS
[
1
].
id
},
variables
:
{
id
:
STEPS
[
1
].
id
},
});
});
const
queryResult
=
await
mockClient
.
query
({
query
:
activeStepQuery
});
const
queryResult
=
await
mock
Apollo
Client
.
query
({
query
:
activeStepQuery
});
expect
(
queryResult
.
data
.
activeStep
).
toMatchObject
({
id
:
STEPS
[
1
].
id
});
expect
(
queryResult
.
data
.
activeStep
).
toMatchObject
({
id
:
STEPS
[
1
].
id
});
});
});
it
(
'
throws an error when STEP is not present
'
,
async
()
=>
{
it
(
'
throws an error when STEP is not present
'
,
async
()
=>
{
const
id
=
'
does not exist
'
;
const
id
=
'
does not exist
'
;
await
mockClient
await
mock
Apollo
Client
.
mutate
({
.
mutate
({
mutation
:
updateStepMutation
,
mutation
:
updateStepMutation
,
variables
:
{
id
},
variables
:
{
id
},
...
@@ -84,8 +76,8 @@ describe('ee/vue_shared/purchase_flow/graphql/resolvers', () => {
...
@@ -84,8 +76,8 @@ describe('ee/vue_shared/purchase_flow/graphql/resolvers', () => {
});
});
it
(
'
throws an error when cache is not initiated properly
'
,
async
()
=>
{
it
(
'
throws an error when cache is not initiated properly
'
,
async
()
=>
{
mockClient
.
clearStore
();
mock
Apollo
Client
.
clearStore
();
await
mockClient
await
mock
Apollo
Client
.
mutate
({
.
mutate
({
mutation
:
updateStepMutation
,
mutation
:
updateStepMutation
,
variables
:
{
id
:
STEPS
[
1
].
id
},
variables
:
{
id
:
STEPS
[
1
].
id
},
...
@@ -98,19 +90,20 @@ describe('ee/vue_shared/purchase_flow/graphql/resolvers', () => {
...
@@ -98,19 +90,20 @@ describe('ee/vue_shared/purchase_flow/graphql/resolvers', () => {
describe
(
'
activateNextStep
'
,
()
=>
{
describe
(
'
activateNextStep
'
,
()
=>
{
it
(
'
updates the active step to the next
'
,
async
()
=>
{
it
(
'
updates the active step to the next
'
,
async
()
=>
{
await
mockClient
.
mutate
({
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
0
);
mockApolloClient
=
mockApollo
.
clients
.
defaultClient
;
await
mockApolloClient
.
mutate
({
mutation
:
activateNextStepMutation
,
mutation
:
activateNextStepMutation
,
});
});
const
queryResult
=
await
mockClient
.
query
({
query
:
activeStepQuery
});
const
queryResult
=
await
mock
Apollo
Client
.
query
({
query
:
activeStepQuery
});
expect
(
queryResult
.
data
.
activeStep
).
toMatchObject
({
id
:
STEPS
[
1
].
id
});
expect
(
queryResult
.
data
.
activeStep
).
toMatchObject
({
id
:
STEPS
[
1
].
id
});
});
});
it
(
'
throws an error when out of bounds
'
,
async
()
=>
{
it
(
'
throws an error when out of bounds
'
,
async
()
=>
{
await
mockClient
.
mutate
({
const
mockApollo
=
createMockApolloProvider
(
STEPS
,
2
);
mutation
:
activateNextStepMutation
,
mockApolloClient
=
mockApollo
.
clients
.
defaultClient
;
});
await
mockClient
await
mock
Apollo
Client
.
mutate
({
.
mutate
({
mutation
:
activateNextStepMutation
,
mutation
:
activateNextStepMutation
,
})
})
...
@@ -120,8 +113,8 @@ describe('ee/vue_shared/purchase_flow/graphql/resolvers', () => {
...
@@ -120,8 +113,8 @@ describe('ee/vue_shared/purchase_flow/graphql/resolvers', () => {
});
});
it
(
'
throws an error when cache is not initiated properly
'
,
async
()
=>
{
it
(
'
throws an error when cache is not initiated properly
'
,
async
()
=>
{
mockClient
.
clearStore
();
mock
Apollo
Client
.
clearStore
();
await
mockClient
await
mock
Apollo
Client
.
mutate
({
.
mutate
({
mutation
:
activateNextStepMutation
,
mutation
:
activateNextStepMutation
,
})
})
...
...
ee/spec/frontend/vue_shared/purchase_flow/mock_data.js
View file @
adef44af
export
const
STEPS
=
[
export
const
STEPS
=
[
{
__typename
:
'
Step
'
,
id
:
'
firstStep
'
},
{
__typename
:
'
Step
'
,
id
:
'
firstStep
'
},
{
__typename
:
'
Step
'
,
id
:
'
secondStep
'
},
{
__typename
:
'
Step
'
,
id
:
'
secondStep
'
},
{
__typename
:
'
Step
'
,
id
:
'
finalStep
'
},
];
];
locale/gitlab.pot
View file @
adef44af
...
@@ -25443,6 +25443,9 @@ msgstr ""
...
@@ -25443,6 +25443,9 @@ msgstr ""
msgid "Purchase more storage"
msgid "Purchase more storage"
msgstr ""
msgstr ""
msgid "PurchaseStep|An error occured in the purchase step. If the problem persists please contact support@gitlab.com."
msgstr ""
msgid "Push"
msgid "Push"
msgstr ""
msgstr ""
...
...
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