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
13184d68
Commit
13184d68
authored
Dec 13, 2019
by
Alex Buijs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add order summary component for paid signup flow
This is part of the paid signup flow MR
parent
5cc1340c
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
518 additions
and
11 deletions
+518
-11
ee/app/assets/javascripts/subscriptions/new/components/order_summary.vue
...avascripts/subscriptions/new/components/order_summary.vue
+62
-0
ee/app/assets/javascripts/subscriptions/new/components/order_summary/summary_details.vue
...riptions/new/components/order_summary/summary_details.vue
+74
-0
ee/app/assets/javascripts/subscriptions/new/constants.js
ee/app/assets/javascripts/subscriptions/new/constants.js
+2
-1
ee/app/assets/javascripts/subscriptions/new/formatting_mixins.js
...assets/javascripts/subscriptions/new/formatting_mixins.js
+12
-0
ee/app/assets/javascripts/subscriptions/new/index.js
ee/app/assets/javascripts/subscriptions/new/index.js
+14
-2
ee/app/assets/javascripts/subscriptions/new/store/getters.js
ee/app/assets/javascripts/subscriptions/new/store/getters.js
+21
-0
ee/app/assets/javascripts/subscriptions/new/store/state.js
ee/app/assets/javascripts/subscriptions/new/store/state.js
+3
-1
ee/app/assets/stylesheets/pages/subscriptions.scss
ee/app/assets/stylesheets/pages/subscriptions.scss
+16
-4
ee/spec/frontend/subscriptions/new/components/checkout/order_summary_spec.js
...bscriptions/new/components/checkout/order_summary_spec.js
+218
-0
ee/spec/frontend/subscriptions/new/store/getters_spec.js
ee/spec/frontend/subscriptions/new/store/getters_spec.js
+55
-3
ee/spec/frontend/subscriptions/new/store/state_spec.js
ee/spec/frontend/subscriptions/new/store/state_spec.js
+17
-0
locale/gitlab.pot
locale/gitlab.pot
+24
-0
No files found.
ee/app/assets/javascripts/subscriptions/new/components/order_summary.vue
0 → 100644
View file @
13184d68
<
script
>
import
{
mapGetters
}
from
'
vuex
'
;
import
{
sprintf
,
s__
}
from
'
~/locale
'
;
import
{
GlIcon
}
from
'
@gitlab/ui
'
;
import
formattingMixins
from
'
../formatting_mixins
'
;
import
SummaryDetails
from
'
./order_summary/summary_details.vue
'
;
export
default
{
components
:
{
SummaryDetails
,
GlIcon
,
},
mixins
:
[
formattingMixins
],
data
()
{
return
{
collapsed
:
true
,
};
},
computed
:
{
...
mapGetters
([
'
totalAmount
'
,
'
name
'
,
'
usersPresent
'
]),
titleWithName
()
{
return
sprintf
(
this
.
$options
.
i18n
.
title
,
{
name
:
this
.
name
});
},
},
methods
:
{
toggleCollapse
()
{
this
.
collapsed
=
!
this
.
collapsed
;
},
},
i18n
:
{
title
:
s__
(
"
Checkout|%{name}'s GitLab subscription
"
),
},
};
</
script
>
<
template
>
<div
class=
"order-summary d-flex flex-column flex-grow-1 prepend-top-5 mt-lg-5"
>
<div
class=
"d-lg-none"
>
<div
@
click=
"toggleCollapse"
>
<h4
class=
"d-flex justify-content-between gl-font-size-16"
:class=
"
{ 'prepend-bottom-32': !collapsed }"
>
<div
class=
"d-flex"
>
<gl-icon
v-if=
"collapsed"
name=
"chevron-right"
:size=
"18"
/>
<gl-icon
v-else
name=
"chevron-down"
:size=
"18"
/>
<div>
{{
titleWithName
}}
</div>
</div>
<div
class=
"prepend-left-default"
>
{{
formatAmount
(
totalAmount
,
usersPresent
)
}}
</div>
</h4>
</div>
<summary-details
v-show=
"!collapsed"
/>
</div>
<div
class=
"d-none d-lg-block"
>
<div
class=
"append-bottom-20"
>
<h4
class=
"gl-font-size-20"
>
{{
titleWithName
}}
</h4>
</div>
<summary-details
/>
</div>
</div>
</
template
>
ee/app/assets/javascripts/subscriptions/new/components/order_summary/summary_details.vue
0 → 100644
View file @
13184d68
<
script
>
import
{
mapState
,
mapGetters
}
from
'
vuex
'
;
import
{
s__
}
from
'
~/locale
'
;
import
formattingMixins
from
'
../../formatting_mixins
'
;
export
default
{
mixins
:
[
formattingMixins
],
computed
:
{
...
mapState
([
'
startDate
'
,
'
taxRate
'
,
'
numberOfUsers
'
]),
...
mapGetters
([
'
selectedPlanText
'
,
'
selectedPlanPrice
'
,
'
endDate
'
,
'
totalExVat
'
,
'
vat
'
,
'
totalAmount
'
,
'
usersPresent
'
,
]),
},
i18n
:
{
selectedPlanText
:
s__
(
'
Checkout|%{selectedPlanText} plan
'
),
numberOfUsers
:
s__
(
'
Checkout|(x%{numberOfUsers})
'
),
pricePerUserPerYear
:
s__
(
'
Checkout|$%{selectedPlanPrice} per user per year
'
),
dates
:
s__
(
'
Checkout|%{startDate} - %{endDate}
'
),
subtotal
:
s__
(
'
Checkout|Subtotal
'
),
tax
:
s__
(
'
Checkout|Tax
'
),
total
:
s__
(
'
Checkout|Total
'
),
},
};
</
script
>
<
template
>
<div>
<div
class=
"d-flex justify-content-between bold prepend-top-10 append-bottom-8"
>
<div
class=
"js-selected-plan"
>
{{
sprintf
(
$options
.
i18n
.
selectedPlanText
,
{
selectedPlanText
}
)
}}
<
span
v
-
if
=
"
usersPresent
"
class
=
"
js-number-of-users
"
>
{{
sprintf
(
$options
.
i18n
.
numberOfUsers
,
{
numberOfUsers
}
)
}}
<
/span
>
<
/div
>
<
div
class
=
"
js-amount
"
>
{{
formatAmount
(
totalExVat
,
usersPresent
)
}}
<
/div
>
<
/div
>
<
div
class
=
"
text-secondary js-per-user
"
>
{{
sprintf
(
$options
.
i18n
.
pricePerUserPerYear
,
{
selectedPlanPrice
:
selectedPlanPrice
.
toLocaleString
(),
}
)
}}
<
/div
>
<
div
class
=
"
text-secondary js-dates
"
>
{{
sprintf
(
$options
.
i18n
.
dates
,
{
startDate
:
formatDate
(
startDate
),
endDate
:
formatDate
(
endDate
),
}
)
}}
<
/div
>
<
div
v
-
if
=
"
taxRate
"
>
<
div
class
=
"
border-bottom prepend-top-default append-bottom-default
"
><
/div
>
<
div
class
=
"
d-flex justify-content-between text-secondary
"
>
<
div
>
{{
$options
.
i18n
.
subtotal
}}
<
/div
>
<
div
class
=
"
js-total-ex-vat
"
>
{{
formatAmount
(
totalExVat
,
usersPresent
)
}}
<
/div
>
<
/div
>
<
div
class
=
"
d-flex justify-content-between text-secondary
"
>
<
div
>
{{
$options
.
i18n
.
tax
}}
<
/div
>
<
div
class
=
"
js-vat
"
>
{{
formatAmount
(
vat
,
usersPresent
)
}}
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"
border-bottom prepend-top-default append-bottom-default
"
><
/div
>
<
div
class
=
"
d-flex justify-content-between bold gl-font-size-large
"
>
<
div
>
{{
$options
.
i18n
.
total
}}
<
/div
>
<
div
class
=
"
js-total-amount
"
>
{{
formatAmount
(
totalAmount
,
usersPresent
)
}}
<
/div
>
<
/div
>
<
/div
>
<
/template
>
ee/app/assets/javascripts/subscriptions/new/constants.js
View file @
13184d68
/* eslint-disable import/prefer-default-export */
export
const
STEPS
=
[
'
subscriptionDetails
'
];
export
const
STEPS
=
[
'
subscriptionDetails
'
];
export
const
TAX_RATE
=
0
;
ee/app/assets/javascripts/subscriptions/new/formatting_mixins.js
0 → 100644
View file @
13184d68
import
dateFormat
from
'
dateformat
'
;
export
default
{
methods
:
{
formatAmount
(
amount
,
show
)
{
return
show
?
`$
${(
Math
.
round
(
amount
*
100
)
/
100
).
toLocaleString
()}
`
:
'
-
'
;
},
formatDate
(
date
)
{
return
dateFormat
(
date
,
'
mmm d, yyyy
'
);
},
},
};
ee/app/assets/javascripts/subscriptions/new/index.js
View file @
13184d68
import
Vue
from
'
vue
'
;
import
Vue
from
'
vue
'
;
import
createStore
from
'
./store
'
;
import
createStore
from
'
./store
'
;
import
Checkout
from
'
./components/checkout.vue
'
;
import
Checkout
from
'
./components/checkout.vue
'
;
import
OrderSummary
from
'
./components/order_summary.vue
'
;
export
default
()
=>
{
export
default
()
=>
{
const
checkoutEl
=
document
.
getElementById
(
'
checkout
'
);
const
checkoutEl
=
document
.
getElementById
(
'
checkout
'
);
const
summaryEl
=
document
.
getElementById
(
'
summary
'
);
const
store
=
createStore
(
checkoutEl
.
dataset
);
return
new
Vue
({
// eslint-disable-next-line no-new
new
Vue
({
el
:
checkoutEl
,
el
:
checkoutEl
,
store
:
createStore
(
checkoutEl
.
dataset
)
,
store
,
render
(
createElement
)
{
render
(
createElement
)
{
return
createElement
(
Checkout
);
return
createElement
(
Checkout
);
},
},
});
});
return
new
Vue
({
el
:
summaryEl
,
store
,
render
(
createElement
)
{
return
createElement
(
OrderSummary
);
},
});
};
};
ee/app/assets/javascripts/subscriptions/new/store/getters.js
View file @
13184d68
import
{
STEPS
}
from
'
../constants
'
;
import
{
STEPS
}
from
'
../constants
'
;
import
{
s__
}
from
'
~/locale
'
;
export
const
currentStep
=
state
=>
state
.
currentStep
;
export
const
currentStep
=
state
=>
state
.
currentStep
;
...
@@ -8,5 +9,25 @@ export const currentStepIndex = (state, getters) => getters.stepIndex(state.curr
...
@@ -8,5 +9,25 @@ export const currentStepIndex = (state, getters) => getters.stepIndex(state.curr
export
const
selectedPlanText
=
(
state
,
getters
)
=>
getters
.
selectedPlanDetails
.
text
;
export
const
selectedPlanText
=
(
state
,
getters
)
=>
getters
.
selectedPlanDetails
.
text
;
export
const
selectedPlanPrice
=
(
state
,
getters
)
=>
getters
.
selectedPlanDetails
.
pricePerUserPerYear
;
export
const
selectedPlanDetails
=
state
=>
export
const
selectedPlanDetails
=
state
=>
state
.
availablePlans
.
find
(
plan
=>
plan
.
value
===
state
.
selectedPlan
);
state
.
availablePlans
.
find
(
plan
=>
plan
.
value
===
state
.
selectedPlan
);
export
const
endDate
=
state
=>
new
Date
(
state
.
startDate
).
setFullYear
(
state
.
startDate
.
getFullYear
()
+
1
);
export
const
totalExVat
=
(
state
,
getters
)
=>
state
.
numberOfUsers
*
getters
.
selectedPlanPrice
;
export
const
vat
=
(
state
,
getters
)
=>
state
.
taxRate
*
getters
.
totalExVat
;
export
const
totalAmount
=
(
_
,
getters
)
=>
getters
.
totalExVat
+
getters
.
vat
;
export
const
name
=
state
=>
{
if
(
state
.
isSetupForCompany
&&
state
.
organizationName
)
return
state
.
organizationName
;
else
if
(
state
.
isSetupForCompany
)
return
s__
(
'
Checkout|Your organization
'
);
return
state
.
fullName
;
};
export
const
usersPresent
=
state
=>
state
.
numberOfUsers
>
0
;
ee/app/assets/javascripts/subscriptions/new/store/state.js
View file @
13184d68
import
{
capitalizeFirstCharacter
}
from
'
~/lib/utils/text_utility
'
;
import
{
capitalizeFirstCharacter
}
from
'
~/lib/utils/text_utility
'
;
import
{
parseBoolean
}
from
'
~/lib/utils/common_utils
'
;
import
{
parseBoolean
}
from
'
~/lib/utils/common_utils
'
;
import
{
STEPS
}
from
'
../constants
'
;
import
{
STEPS
,
TAX_RATE
}
from
'
../constants
'
;
const
parsePlanData
=
planData
=>
const
parsePlanData
=
planData
=>
JSON
.
parse
(
planData
).
map
(
plan
=>
({
JSON
.
parse
(
planData
).
map
(
plan
=>
({
...
@@ -27,5 +27,7 @@ export default ({ planData = '[]', planId, setupForCompany, fullName }) => {
...
@@ -27,5 +27,7 @@ export default ({ planData = '[]', planId, setupForCompany, fullName }) => {
fullName
,
fullName
,
organizationName
:
null
,
organizationName
:
null
,
numberOfUsers
:
parseBoolean
(
setupForCompany
)
?
0
:
1
,
numberOfUsers
:
parseBoolean
(
setupForCompany
)
?
0
:
1
,
taxRate
:
TAX_RATE
,
startDate
:
new
Date
(
Date
.
now
()),
};
};
};
};
ee/app/assets/stylesheets/pages/subscriptions.scss
View file @
13184d68
/* Checkout Page */
/* Checkout Page */
$subscriptions-form-group-width
:
420px
;
$subscriptions-full-width-md
:
$subscriptions-form-group-width
+
$gl-padding
*
2
+
2
;
$subscriptions-full-width-lg
:
541px
;
.subscriptions-layout-html
{
.subscriptions-layout-html
{
.container
{
.container
{
max-width
:
none
;
max-width
:
none
;
...
@@ -20,7 +24,7 @@
...
@@ -20,7 +24,7 @@
align-items
:
center
;
align-items
:
center
;
flex-grow
:
1
;
flex-grow
:
1
;
margin-top
:
$gl-padding
;
margin-top
:
$gl-padding
;
max-width
:
454px
;
max-width
:
$subscriptions-full-width-md
;
@media
(
min-width
:
map-get
(
$grid-breakpoints
,
lg
))
{
@media
(
min-width
:
map-get
(
$grid-breakpoints
,
lg
))
{
justify-content
:
inherit
!
important
;
justify-content
:
inherit
!
important
;
...
@@ -29,7 +33,7 @@
...
@@ -29,7 +33,7 @@
}
}
.full-width
{
.full-width
{
max-width
:
541px
;
max-width
:
$subscriptions-full-width-lg
;
width
:
100%
;
width
:
100%
;
}
}
}
}
...
@@ -67,10 +71,10 @@
...
@@ -67,10 +71,10 @@
margin-bottom
:
0
;
margin-bottom
:
0
;
min-height
:
32px
;
min-height
:
32px
;
padding
:
$gl-padding
;
padding
:
$gl-padding
;
max-width
:
541px
;
max-width
:
$subscriptions-full-width-lg
;
@media
(
min-width
:
map-get
(
$grid-breakpoints
,
lg
))
{
@media
(
min-width
:
map-get
(
$grid-breakpoints
,
lg
))
{
width
:
541px
;
width
:
$subscriptions-full-width-lg
;
}
}
}
}
...
@@ -125,4 +129,12 @@
...
@@ -125,4 +129,12 @@
}
}
}
}
}
}
.order-summary
{
max-width
:
$subscriptions-full-width-md
;
@media
(
min-width
:
map-get
(
$grid-breakpoints
,
lg
))
{
max-width
:
none
;
}
}
}
}
ee/spec/frontend/subscriptions/new/components/checkout/order_summary_spec.js
0 → 100644
View file @
13184d68
import
Vuex
from
'
vuex
'
;
import
{
mount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
createStore
from
'
ee/subscriptions/new/store
'
;
import
*
as
types
from
'
ee/subscriptions/new/store/mutation_types
'
;
import
Component
from
'
ee/subscriptions/new/components/order_summary.vue
'
;
describe
(
'
Order Summary
'
,
()
=>
{
const
localVue
=
createLocalVue
();
localVue
.
use
(
Vuex
);
let
wrapper
;
const
planData
=
[
{
id
:
'
firstPlanId
'
,
code
:
'
bronze
'
,
price_per_year
:
48
},
{
id
:
'
secondPlanId
'
,
code
:
'
silver
'
,
price_per_year
:
228
},
{
id
:
'
thirdPlanId
'
,
code
:
'
gold
'
,
price_per_year
:
1188
},
];
const
initialData
=
{
planData
:
JSON
.
stringify
(
planData
),
planId
:
'
thirdPlanId
'
,
fullName
:
'
Full Name
'
,
};
const
store
=
createStore
(
initialData
);
const
createComponent
=
(
opts
=
{})
=>
{
wrapper
=
mount
(
Component
,
{
localVue
,
store
,
...
opts
,
});
};
beforeEach
(()
=>
{
createComponent
();
});
afterEach
(()
=>
{
wrapper
.
destroy
();
});
describe
(
'
Changing the company name
'
,
()
=>
{
describe
(
'
When purchasing for a single user
'
,
()
=>
{
beforeEach
(()
=>
{
store
.
commit
(
types
.
UPDATE_IS_SETUP_FOR_COMPANY
,
false
);
});
it
(
'
should display the title with the passed name
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
h4
'
).
text
()).
toContain
(
"
Full Name's GitLab subscription
"
);
});
});
describe
(
'
When purchasing for a company or group
'
,
()
=>
{
beforeEach
(()
=>
{
store
.
commit
(
types
.
UPDATE_IS_SETUP_FOR_COMPANY
,
true
);
});
describe
(
'
Without a group name provided
'
,
()
=>
{
it
(
'
should display the title with the default name
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
h4
'
).
text
()).
toContain
(
"
Your organization's GitLab subscription
"
);
});
});
describe
(
'
With a group name provided
'
,
()
=>
{
beforeEach
(()
=>
{
store
.
commit
(
types
.
UPDATE_ORGANIZATION_NAME
,
'
My group
'
);
});
it
(
'
when given a group name, it should display the title with the group name
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
h4
'
).
text
()).
toContain
(
"
My group's GitLab subscription
"
);
});
});
});
});
describe
(
'
Changing the plan
'
,
()
=>
{
describe
(
'
the selected plan
'
,
()
=>
{
it
(
'
should display the chosen plan
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-selected-plan
'
).
text
()).
toContain
(
'
Gold plan
'
);
});
it
(
'
should display the correct formatted amount price per user
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-per-user
'
).
text
()).
toContain
(
'
$1,188 per user per year
'
);
});
});
describe
(
'
the default plan
'
,
()
=>
{
beforeEach
(()
=>
{
store
.
commit
(
types
.
UPDATE_SELECTED_PLAN
,
'
firstPlanId
'
);
store
.
commit
(
types
.
UPDATE_NUMBER_OF_USERS
,
1
);
});
it
(
'
should display the chosen plan
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-selected-plan
'
).
text
()).
toContain
(
'
Bronze plan
'
);
});
it
(
'
should display the correct formatted amount price per user
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-per-user
'
).
text
()).
toContain
(
'
$48 per user per year
'
);
});
it
(
'
should display the correct formatted total amount
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-total-amount
'
).
text
()).
toContain
(
'
$48
'
);
});
});
});
describe
(
'
Changing the number of users
'
,
()
=>
{
beforeEach
(()
=>
{
store
.
commit
(
types
.
UPDATE_SELECTED_PLAN
,
'
thirdPlanId
'
);
store
.
commit
(
types
.
UPDATE_NUMBER_OF_USERS
,
1
);
});
describe
(
'
the default of 1 selected user
'
,
()
=>
{
it
(
'
should display the correct number of users
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-number-of-users
'
).
text
()).
toContain
(
'
(x1)
'
);
});
it
(
'
should display the correct formatted amount price per user
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-per-user
'
).
text
()).
toContain
(
'
$1,188 per user per year
'
);
});
it
(
'
should display the correct multiplied formatted amount of the chosen plan
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-amount
'
).
text
()).
toContain
(
'
$1,188
'
);
});
it
(
'
should display the correct formatted total amount
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-total-amount
'
).
text
()).
toContain
(
'
$1,188
'
);
});
});
describe
(
'
3 selected users
'
,
()
=>
{
beforeEach
(()
=>
{
store
.
commit
(
types
.
UPDATE_SELECTED_PLAN
,
'
thirdPlanId
'
);
store
.
commit
(
types
.
UPDATE_NUMBER_OF_USERS
,
3
);
});
it
(
'
should display the correct number of users
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-number-of-users
'
).
text
()).
toContain
(
'
(x3)
'
);
});
it
(
'
should display the correct formatted amount price per user
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-per-user
'
).
text
()).
toContain
(
'
$1,188 per user per year
'
);
});
it
(
'
should display the correct multiplied formatted amount of the chosen plan
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-amount
'
).
text
()).
toContain
(
'
$3,564
'
);
});
it
(
'
should display the correct formatted total amount
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-total-amount
'
).
text
()).
toContain
(
'
$3,564
'
);
});
});
describe
(
'
no selected users
'
,
()
=>
{
beforeEach
(()
=>
{
store
.
commit
(
types
.
UPDATE_SELECTED_PLAN
,
'
thirdPlanId
'
);
store
.
commit
(
types
.
UPDATE_NUMBER_OF_USERS
,
0
);
});
it
(
'
should not display the number of users
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-number-of-users
'
).
exists
()).
toBe
(
false
);
});
it
(
'
should display the correct formatted amount price per user
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-per-user
'
).
text
()).
toContain
(
'
$1,188 per user per year
'
);
});
it
(
'
should not display the amount
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-amount
'
).
text
()).
toContain
(
'
-
'
);
});
it
(
'
should display the correct formatted total amount
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-total-amount
'
).
text
()).
toContain
(
'
-
'
);
});
});
describe
(
'
date range
'
,
()
=>
{
beforeEach
(()
=>
{
store
.
state
.
startDate
=
new
Date
(
'
2019-12-05
'
);
});
it
(
'
shows the formatted date range from the start date to one year in the future
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-dates
'
).
text
()).
toContain
(
'
Dec 5, 2019 - Dec 5, 2020
'
);
});
});
describe
(
'
tax rate
'
,
()
=>
{
describe
(
'
a tax rate of 0
'
,
()
=>
{
it
(
'
should not display the total amount excluding vat
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-total-ex-vat
'
).
exists
()).
toBe
(
false
);
});
it
(
'
should not display the vat amount
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-vat
'
).
exists
()).
toBe
(
false
);
});
});
describe
(
'
a tax rate of 8%
'
,
()
=>
{
beforeEach
(()
=>
{
store
.
state
.
taxRate
=
0.08
;
});
it
(
'
should display the total amount excluding vat
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-total-ex-vat
'
).
text
()).
toContain
(
'
$1,188
'
);
});
it
(
'
should display the vat amount
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-vat
'
).
text
()).
toContain
(
'
$95.04
'
);
});
it
(
'
should display the total amount including the vat
'
,
()
=>
{
expect
(
wrapper
.
find
(
'
.js-total-amount
'
).
text
()).
toContain
(
'
$1,283.04
'
);
});
});
});
});
});
ee/spec/frontend/subscriptions/new/store/getters_spec.js
View file @
13184d68
...
@@ -18,7 +18,7 @@ const state = {
...
@@ -18,7 +18,7 @@ const state = {
describe
(
'
Subscriptions Getters
'
,
()
=>
{
describe
(
'
Subscriptions Getters
'
,
()
=>
{
describe
(
'
currentStep
'
,
()
=>
{
describe
(
'
currentStep
'
,
()
=>
{
it
(
'
returns the states currentStep
'
,
()
=>
{
it
(
'
returns the states currentStep
'
,
()
=>
{
expect
(
getters
.
currentStep
(
state
)).
to
Equal
(
'
secondStep
'
);
expect
(
getters
.
currentStep
(
state
)).
to
Be
(
'
secondStep
'
);
});
});
});
});
...
@@ -28,7 +28,7 @@ describe('Subscriptions Getters', () => {
...
@@ -28,7 +28,7 @@ describe('Subscriptions Getters', () => {
});
});
it
(
'
returns a function that returns the index of the given step
'
,
()
=>
{
it
(
'
returns a function that returns the index of the given step
'
,
()
=>
{
expect
(
getters
.
stepIndex
()(
'
secondStep
'
)).
to
Equal
(
1
);
expect
(
getters
.
stepIndex
()(
'
secondStep
'
)).
to
Be
(
1
);
});
});
});
});
...
@@ -49,7 +49,7 @@ describe('Subscriptions Getters', () => {
...
@@ -49,7 +49,7 @@ describe('Subscriptions Getters', () => {
it
(
'
returns the text for selectedPlan
'
,
()
=>
{
it
(
'
returns the text for selectedPlan
'
,
()
=>
{
expect
(
expect
(
getters
.
selectedPlanText
(
state
,
{
selectedPlanDetails
:
{
text
:
'
selected plan
'
}
}),
getters
.
selectedPlanText
(
state
,
{
selectedPlanDetails
:
{
text
:
'
selected plan
'
}
}),
).
to
Equal
(
'
selected plan
'
);
).
to
Be
(
'
selected plan
'
);
});
});
});
});
...
@@ -61,4 +61,56 @@ describe('Subscriptions Getters', () => {
...
@@ -61,4 +61,56 @@ describe('Subscriptions Getters', () => {
});
});
});
});
});
});
describe
(
'
endDate
'
,
()
=>
{
it
(
'
returns a date 1 year after the startDate
'
,
()
=>
{
expect
(
getters
.
endDate
({
startDate
:
new
Date
(
'
2020-01-07
'
)
})).
toBe
(
new
Date
(
'
2021-01-07
'
).
getTime
(),
);
});
});
describe
(
'
totalExVat
'
,
()
=>
{
it
(
'
returns the number of users times the selected plan price
'
,
()
=>
{
expect
(
getters
.
totalExVat
({
numberOfUsers
:
5
},
{
selectedPlanPrice
:
10
})).
toBe
(
50
);
});
});
describe
(
'
vat
'
,
()
=>
{
it
(
'
returns the tax rate times the total ex vat
'
,
()
=>
{
expect
(
getters
.
vat
({
taxRate
:
0.08
},
{
totalExVat
:
100
})).
toBe
(
8
);
});
});
describe
(
'
totalAmount
'
,
()
=>
{
it
(
'
returns the total ex vat plus the vat
'
,
()
=>
{
expect
(
getters
.
totalAmount
({},
{
totalExVat
:
100
,
vat
:
8
})).
toBe
(
108
);
});
});
describe
(
'
name
'
,
()
=>
{
it
(
'
returns the organization name when setting up for a company and when it is present
'
,
()
=>
{
expect
(
getters
.
name
({
isSetupForCompany
:
true
,
organizationName
:
'
My organization
'
})).
toBe
(
'
My organization
'
,
);
});
it
(
'
returns the default text when setting up for a company and the organization name is not present
'
,
()
=>
{
expect
(
getters
.
name
({
isSetupForCompany
:
true
})).
toBe
(
'
Your organization
'
);
});
it
(
'
returns the full name when not setting up for a company
'
,
()
=>
{
expect
(
getters
.
name
({
isSetupForCompany
:
false
,
fullName
:
'
My name
'
})).
toBe
(
'
My name
'
);
});
});
describe
(
'
usersPresent
'
,
()
=>
{
it
(
'
returns true when the number of users is greater than zero
'
,
()
=>
{
expect
(
getters
.
usersPresent
({
numberOfUsers
:
1
})).
toBe
(
true
);
});
it
(
'
returns false when the number of users is zero
'
,
()
=>
{
expect
(
getters
.
usersPresent
({
numberOfUsers
:
0
})).
toBe
(
false
);
});
});
});
});
ee/spec/frontend/subscriptions/new/store/state_spec.js
View file @
13184d68
...
@@ -2,6 +2,7 @@ import createState from 'ee/subscriptions/new/store/state';
...
@@ -2,6 +2,7 @@ import createState from 'ee/subscriptions/new/store/state';
import
*
as
constants
from
'
ee/subscriptions/new/constants
'
;
import
*
as
constants
from
'
ee/subscriptions/new/constants
'
;
constants
.
STEPS
=
[
'
firstStep
'
,
'
secondStep
'
];
constants
.
STEPS
=
[
'
firstStep
'
,
'
secondStep
'
];
constants
.
TAX_RATE
=
0
;
describe
(
'
projectsSelector default state
'
,
()
=>
{
describe
(
'
projectsSelector default state
'
,
()
=>
{
const
planData
=
[
const
planData
=
[
...
@@ -16,6 +17,10 @@ describe('projectsSelector default state', () => {
...
@@ -16,6 +17,10 @@ describe('projectsSelector default state', () => {
fullName
:
'
Full Name
'
,
fullName
:
'
Full Name
'
,
};
};
const
currentDate
=
new
Date
(
'
2020-01-07T12:44:08.135Z
'
);
jest
.
spyOn
(
global
.
Date
,
'
now
'
).
mockImplementationOnce
(()
=>
currentDate
.
valueOf
());
const
state
=
createState
(
initialData
);
const
state
=
createState
(
initialData
);
it
(
'
sets the currentStep to the first item of the STEPS constant
'
,
()
=>
{
it
(
'
sets the currentStep to the first item of the STEPS constant
'
,
()
=>
{
...
@@ -92,4 +97,16 @@ describe('projectsSelector default state', () => {
...
@@ -92,4 +97,16 @@ describe('projectsSelector default state', () => {
expect
(
modifiedState
.
numberOfUsers
).
toEqual
(
1
);
expect
(
modifiedState
.
numberOfUsers
).
toEqual
(
1
);
});
});
});
});
describe
(
'
taxRate
'
,
()
=>
{
it
(
'
sets the taxRate to the TAX_RATE constant
'
,
()
=>
{
expect
(
state
.
taxRate
).
toEqual
(
0
);
});
});
describe
(
'
startDate
'
,
()
=>
{
it
(
'
sets the startDate to the current date
'
,
()
=>
{
expect
(
state
.
startDate
).
toEqual
(
currentDate
);
});
});
});
});
locale/gitlab.pot
View file @
13184d68
...
@@ -3305,9 +3305,21 @@ msgstr ""
...
@@ -3305,9 +3305,21 @@ msgstr ""
msgid "Checkout"
msgid "Checkout"
msgstr ""
msgstr ""
msgid "Checkout|$%{selectedPlanPrice} per user per year"
msgstr ""
msgid "Checkout|%{name}'s GitLab subscription"
msgstr ""
msgid "Checkout|%{selectedPlanText} plan"
msgid "Checkout|%{selectedPlanText} plan"
msgstr ""
msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
msgid "Checkout|(x%{numberOfUsers})"
msgstr ""
msgid "Checkout|1. Your profile"
msgid "Checkout|1. Your profile"
msgstr ""
msgstr ""
...
@@ -3344,9 +3356,21 @@ msgstr ""
...
@@ -3344,9 +3356,21 @@ msgstr ""
msgid "Checkout|Subscription details"
msgid "Checkout|Subscription details"
msgstr ""
msgstr ""
msgid "Checkout|Subtotal"
msgstr ""
msgid "Checkout|Tax"
msgstr ""
msgid "Checkout|Total"
msgstr ""
msgid "Checkout|Users"
msgid "Checkout|Users"
msgstr ""
msgstr ""
msgid "Checkout|Your organization"
msgstr ""
msgid "Checkout|company or team"
msgid "Checkout|company or team"
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