web/satellite: payment methods component divided into smaller ones

Change-Id: Ibecc3803878e0902d458c3b28613c4ffbec0c634
This commit is contained in:
VitaliiShpital 2020-04-03 15:03:45 +03:00 committed by Vitalii Shpital
parent 68946c86b4
commit 17ccf36c15
10 changed files with 565 additions and 345 deletions

View File

@ -0,0 +1,142 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="add-card-area">
<p class="add-card-area__label">Add Credit or Debit Card</p>
<StripeCardInput
class="add-card-area__stripe"
ref="stripeCardInput"
:on-stripe-response-callback="addCard"
/>
<div class="add-card-area__submit-area"/>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import StripeCardInput from '@/components/account/billing/paymentMethods/StripeCardInput.vue';
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
import { ProjectOwning } from '@/utils/projectOwning';
const {
ADD_CREDIT_CARD,
GET_CREDIT_CARDS,
GET_BILLING_HISTORY,
GET_BALANCE,
} = PAYMENTS_ACTIONS;
interface StripeForm {
onSubmit(): Promise<void>;
}
@Component({
components: {
StripeCardInput,
},
})
export default class AddCardForm extends Vue {
public $refs!: {
stripeCardInput: StripeCardInput & StripeForm;
};
/**
* Adds card after Stripe confirmation.
*
* @param token from Stripe
*/
public async addCard(token: string) {
this.$emit('toggleIsLoading');
try {
await this.$store.dispatch(ADD_CREDIT_CARD, token);
await this.$store.dispatch(GET_BILLING_HISTORY);
await this.$store.dispatch(GET_BALANCE);
} catch (error) {
await this.$notify.error(error.message);
this.$emit('toggleIsLoading');
return;
}
await this.$notify.success('Card successfully added');
this.$segment.track(SegmentEvent.PAYMENT_METHOD_ADDED, {
project_id: this.$store.getters.selectedProject.id,
});
try {
await this.$store.dispatch(GET_CREDIT_CARDS);
} catch (error) {
await this.$notify.error(error.message);
this.$emit('toggleIsLoading');
}
this.$emit('toggleIsLoading');
this.$emit('toggleIsLoaded');
if (!this.userHasOwnProject) {
await this.$store.dispatch(APP_STATE_ACTIONS.SHOW_CREATE_PROJECT_BUTTON);
}
setTimeout(() => {
this.$emit('cancel');
this.$emit('toggleIsLoaded');
setTimeout(() => {
if (!this.userHasOwnProject) {
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_PROJ);
}
}, 500);
}, 2000);
}
/**
* Provides card information to Stripe.
*/
public async onConfirmAddStripe(): Promise<void> {
await this.$refs.stripeCardInput.onSubmit();
this.$segment.track(SegmentEvent.PAYMENT_METHOD_ADDED, {
project_id: this.$store.getters.selectedProject.id,
});
}
/**
* Indicates if user has own project.
*/
private get userHasOwnProject(): boolean {
return new ProjectOwning(this.$store).userHasOwnProject();
}
}
</script>
<style scoped lang="scss">
.add-card-area {
margin-top: 44px;
display: flex;
max-height: 52px;
justify-content: space-between;
align-items: center;
font-family: 'font_regular', sans-serif;
&__label {
font-family: 'font_medium', sans-serif;
font-size: 21px;
}
&__stripe {
width: 60%;
min-width: 400px;
}
&__submit-area {
display: flex;
align-items: center;
min-width: 135px;
}
}
</style>

View File

@ -0,0 +1,182 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="add-storj-area">
<div class="add-storj-area__selection-container">
<p class="add-storj-area__selection-container__label">Deposit STORJ Tokens via Coin Payments</p>
<TokenDepositSelection
class="add-storj-area__selection-container__form"
@onChangeTokenValue="onChangeTokenValue"
/>
</div>
<div class="add-storj-area__submit-area">
<img
v-if="isLoading"
class="loading-image"
src="@/../static/images/account/billing/loading.gif"
alt="loading gif"
>
<VButton
class="confirm-add-storj-button"
label="Continue to Coin Payments"
width="251px"
height="48px"
:on-press="onConfirmAddSTORJ"
:is-disabled="isLoading"
/>
</div>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import TokenDepositSelection from '@/components/account/billing/paymentMethods/TokenDepositSelection.vue';
import VButton from '@/components/common/VButton.vue';
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
import { ProjectOwning } from '@/utils/projectOwning';
const {
MAKE_TOKEN_DEPOSIT,
GET_BILLING_HISTORY,
} = PAYMENTS_ACTIONS;
@Component({
components: {
TokenDepositSelection,
VButton,
},
})
export default class AddStorjForm extends Vue {
private readonly DEFAULT_TOKEN_DEPOSIT_VALUE = 50; // in dollars.
private readonly MAX_TOKEN_AMOUNT = 1000000; // in dollars.
private tokenDepositValue: number = this.DEFAULT_TOKEN_DEPOSIT_VALUE;
@Prop({ default: false })
public readonly isLoading: boolean;
/**
* onConfirmAddSTORJ checks if amount is valid and if so process token.
* payment and return state to default
*/
public async onConfirmAddSTORJ(): Promise<void> {
this.$emit('toggleIsLoading');
if (!this.isDepositValueValid) return;
try {
const tokenResponse = await this.$store.dispatch(MAKE_TOKEN_DEPOSIT, this.tokenDepositValue * 100);
await this.$notify.success(`Successfully created new deposit transaction! \nAddress:${tokenResponse.address} \nAmount:${tokenResponse.amount}`);
const depositWindow = window.open(tokenResponse.link, '_blank');
if (depositWindow) {
depositWindow.focus();
}
} catch (error) {
await this.$notify.error(error.message);
this.$emit('toggleIsLoading');
}
this.$segment.track(SegmentEvent.PAYMENT_METHOD_ADDED, {
project_id: this.$store.getters.selectedProject.id,
});
this.tokenDepositValue = this.DEFAULT_TOKEN_DEPOSIT_VALUE;
try {
await this.$store.dispatch(GET_BILLING_HISTORY);
} catch (error) {
await this.$notify.error(error.message);
this.$emit('toggleIsLoading');
}
this.$emit('toggleIsLoading');
this.$emit('cancel');
}
/**
* Event for changing token deposit value.
*/
public onChangeTokenValue(value: number): void {
this.tokenDepositValue = value;
}
/**
* Indicates if user has own project.
*/
private get userHasOwnProject(): boolean {
return new ProjectOwning(this.$store).userHasOwnProject();
}
/**
* Indicates if deposit value is valid.
*/
private get isDepositValueValid(): boolean {
switch (true) {
case (this.tokenDepositValue < 50 || this.tokenDepositValue >= this.MAX_TOKEN_AMOUNT) && !this.userHasOwnProject:
this.$notify.error('First deposit amount must be more than 50 and less than 1000000');
this.setDefault();
return false;
case this.tokenDepositValue >= this.MAX_TOKEN_AMOUNT || this.tokenDepositValue === 0:
this.$notify.error('Deposit amount must be more than 0 and less than 1000000');
this.setDefault();
return false;
default:
return true;
}
}
/**
* Sets adding payment method state to default.
*/
private setDefault(): void {
this.tokenDepositValue = this.DEFAULT_TOKEN_DEPOSIT_VALUE;
this.$emit('toggleIsLoading');
this.$emit('cancel');
}
}
</script>
<style scoped lang="scss">
p {
margin: 0;
}
.add-storj-area {
margin-top: 44px;
font-family: 'font_regular', sans-serif;
display: flex;
max-height: 52px;
justify-content: space-between;
align-items: center;
&__selection-container {
display: flex;
align-items: center;
&__label {
margin-right: 30px;
max-width: 215px;
}
&__form {
width: 60%;
}
}
&__submit-area {
display: flex;
align-items: center;
min-width: 135px;
}
}
.loading-image {
width: 18px;
height: 18px;
margin-right: 5px;
}
</style>

View File

@ -5,11 +5,11 @@
<div class="payment-methods-area">
<div class="payment-methods-area__functional-area" :class="functionalAreaClassName">
<div class="payment-methods-area__functional-area__top-container">
<h1 class="payment-methods-area__functional-area__title text">Payment Method</h1>
<h1 class="payment-methods-area__functional-area__title">Payment Method</h1>
<div class="payment-methods-area__functional-area__button-area">
<div class="payment-methods-area__functional-area__button-area__default-buttons" v-if="!areAddButtonsClicked">
<VButton
class="button"
class="add-storj-button"
label="Add STORJ"
width="123px"
height="48px"
@ -32,37 +32,20 @@
:any-credit-cards="true"
class="payment-methods-area__functional-area__bonus"
/>
<div class="payment-methods-area__functional-area__adding-container" v-if="isAddingStorjState">
<div class="storj-container">
<p class="storj-container__label">Deposit STORJ Tokens via Coin Payments</p>
<TokenDepositSelection class="form" @onChangeTokenValue="onChangeTokenValue"/>
</div>
<div class="payment-methods-area__functional-area__adding-container__submit-area">
<img
v-if="isLoading"
class="payment-loading-image"
src="@/../static/images/account/billing/loading.gif"
alt="loading gif"
>
<VButton
class="confirm-add-storj-button"
label="Continue to Coin Payments"
width="251px"
height="48px"
:on-press="onConfirmAddSTORJ"
:is-disabled="isLoading"
/>
</div>
</div>
<div class="payment-methods-area__functional-area__adding-container" v-if="isAddingCardState">
<p class="payment-methods-area__functional-area__adding-container__label">Add Credit or Debit Card</p>
<StripeCardInput
class="payment-methods-area__functional-area__adding-container__stripe"
ref="stripeCardInput"
:on-stripe-response-callback="addCard"
/>
<div class="payment-methods-area__functional-area__adding-container__submit-area"/>
</div>
<AddStorjForm
ref="addStorj"
v-if="isAddingStorjState"
:is-loading="isLoading"
@toggleIsLoading="toggleIsLoading"
@cancel="onCancel"
/>
<AddCardForm
ref="addCard"
v-if="isAddingCardState"
@toggleIsLoading="toggleIsLoading"
@toggleIsLoaded="toggleIsLoaded"
@cancel="onCancel"
/>
<div
v-if="!isAddStorjClicked"
class="add-card-button"
@ -102,10 +85,10 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import AddCardForm from '@/components/account/billing/paymentMethods/AddCardForm.vue';
import AddStorjForm from '@/components/account/billing/paymentMethods/AddStorjForm.vue';
import CardComponent from '@/components/account/billing/paymentMethods/CardComponent.vue';
import PaymentsBonus from '@/components/account/billing/paymentMethods/PaymentsBonus.vue';
import StripeCardInput from '@/components/account/billing/paymentMethods/StripeCardInput.vue';
import TokenDepositSelection from '@/components/account/billing/paymentMethods/TokenDepositSelection.vue';
import VButton from '@/components/common/VButton.vue';
import LockImage from '@/../static/images/account/billing/lock.svg';
@ -113,29 +96,25 @@ import SuccessImage from '@/../static/images/account/billing/success.svg';
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
import { CreditCard } from '@/types/payments';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
import { PaymentMethodsBlockState } from '@/utils/constants/billingEnums';
import { ProjectOwning } from '@/utils/projectOwning';
const {
ADD_CREDIT_CARD,
GET_CREDIT_CARDS,
MAKE_TOKEN_DEPOSIT,
GET_BILLING_HISTORY,
GET_BALANCE,
} = PAYMENTS_ACTIONS;
interface StripeForm {
onSubmit(): Promise<void>;
interface AddCardConfirm {
onConfirmAddStripe(): Promise<void>;
}
@Component({
components: {
AddStorjForm,
AddCardForm,
VButton,
CardComponent,
TokenDepositSelection,
StripeCardInput,
PaymentsBonus,
LockImage,
SuccessImage,
@ -143,9 +122,6 @@ interface StripeForm {
})
export default class PaymentMethods extends Vue {
private areaState: number = PaymentMethodsBlockState.DEFAULT;
private readonly DEFAULT_TOKEN_DEPOSIT_VALUE = 50; // in dollars.
private readonly MAX_TOKEN_AMOUNT = 1000000; // in dollars.
private tokenDepositValue: number = this.DEFAULT_TOKEN_DEPOSIT_VALUE;
public isLoading: boolean = false;
public isLoaded: boolean = false;
@ -167,7 +143,7 @@ export default class PaymentMethods extends Vue {
}
public $refs!: {
stripeCardInput: StripeCardInput & StripeForm;
addCard: AddCardForm & AddCardConfirm;
};
/**
@ -240,13 +216,6 @@ export default class PaymentMethods extends Vue {
return this.$store.state.paymentsModule.creditCards.length === 0;
}
/**
* Event for changing token deposit value.
*/
public onChangeTokenValue(value: number): void {
this.tokenDepositValue = value;
}
/**
* Changes area state to adding tokens state.
*/
@ -262,7 +231,7 @@ export default class PaymentMethods extends Vue {
*/
public async onAddCard(): Promise<void> {
if (this.isAddCardClicked) {
await this.onConfirmAddStripe();
await this.onConfirmAddCard();
return;
}
@ -282,117 +251,20 @@ export default class PaymentMethods extends Vue {
this.isAddCardClicked = false;
this.isAddStorjClicked = false;
this.areaState = PaymentMethodsBlockState.DEFAULT;
this.tokenDepositValue = this.DEFAULT_TOKEN_DEPOSIT_VALUE;
}
/**
* onConfirmAddSTORJ checks if amount is valid and if so process token.
* payment and return state to default
* Toggles loading state.
*/
public async onConfirmAddSTORJ(): Promise<void> {
if (this.isLoading) return;
this.isLoading = true;
if ((this.tokenDepositValue < 50 || this.tokenDepositValue >= this.MAX_TOKEN_AMOUNT) && !this.userHasOwnProject && this.noCreditCards) {
await this.$notify.error('First deposit amount must be more than 50 and less than 1000000');
this.tokenDepositValue = this.DEFAULT_TOKEN_DEPOSIT_VALUE;
this.areaState = PaymentMethodsBlockState.DEFAULT;
this.isAddStorjClicked = false;
this.isLoading = false;
return;
}
if (this.tokenDepositValue >= this.MAX_TOKEN_AMOUNT || this.tokenDepositValue === 0) {
await this.$notify.error('Deposit amount must be more than 0 and less than 1000000');
this.tokenDepositValue = this.DEFAULT_TOKEN_DEPOSIT_VALUE;
this.areaState = PaymentMethodsBlockState.DEFAULT;
this.isAddStorjClicked = false;
this.isLoading = false;
return;
}
try {
const tokenResponse = await this.$store.dispatch(MAKE_TOKEN_DEPOSIT, this.tokenDepositValue * 100);
await this.$notify.success(`Successfully created new deposit transaction! \nAddress:${tokenResponse.address} \nAmount:${tokenResponse.amount}`);
const depositWindow = window.open(tokenResponse.link, '_blank');
if (depositWindow) {
depositWindow.focus();
}
} catch (error) {
await this.$notify.error(error.message);
this.isLoading = false;
}
this.$segment.track(SegmentEvent.PAYMENT_METHOD_ADDED, {
project_id: this.$store.getters.selectedProject.id,
});
this.tokenDepositValue = this.DEFAULT_TOKEN_DEPOSIT_VALUE;
try {
await this.$store.dispatch(GET_BILLING_HISTORY);
} catch (error) {
await this.$notify.error(error.message);
this.isLoading = false;
}
this.areaState = PaymentMethodsBlockState.DEFAULT;
this.isAddStorjClicked = false;
this.isLoading = false;
public toggleIsLoading(): void {
this.isLoading = !this.isLoading;
}
/**
* Adds card after Stripe confirmation.
*
* @param token from Stripe
* Toggles loaded state.
*/
public async addCard(token: string) {
if (this.isLoading) return;
this.isLoading = true;
try {
await this.$store.dispatch(ADD_CREDIT_CARD, token);
await this.$store.dispatch(GET_BILLING_HISTORY);
await this.$store.dispatch(GET_BALANCE);
} catch (error) {
await this.$notify.error(error.message);
this.isLoading = false;
return;
}
await this.$notify.success('Card successfully added');
this.$segment.track(SegmentEvent.PAYMENT_METHOD_ADDED, {
project_id: this.$store.getters.selectedProject.id,
});
try {
await this.$store.dispatch(GET_CREDIT_CARDS);
} catch (error) {
await this.$notify.error(error.message);
this.isLoading = false;
}
this.isLoading = false;
this.isLoaded = true;
if (!this.userHasOwnProject) {
await this.$store.dispatch(APP_STATE_ACTIONS.SHOW_CREATE_PROJECT_BUTTON);
}
setTimeout(() => {
this.onCancel();
this.isLoaded = false;
setTimeout(() => {
if (!this.userHasOwnProject) {
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_PROJ);
}
}, 500);
}, 2000);
public toggleIsLoaded(): void {
this.isLoaded = !this.isLoaded;
}
/**
@ -402,36 +274,16 @@ export default class PaymentMethods extends Vue {
return this.areaState === PaymentMethodsBlockState.DEFAULT;
}
/**
* Indicates if user has own project.
*/
private get userHasOwnProject(): boolean {
return new ProjectOwning(this.$store).userHasOwnProject();
}
/**
* Provides card information to Stripe.
*/
private async onConfirmAddStripe(): Promise<void> {
await this.$refs.stripeCardInput.onSubmit();
this.$segment.track(SegmentEvent.PAYMENT_METHOD_ADDED, {
project_id: this.$store.getters.selectedProject.id,
});
private async onConfirmAddCard(): Promise<void> {
await this.$refs.addCard.onConfirmAddStripe();
}
}
</script>
<style scoped lang="scss">
.text {
margin: 0;
color: #354049;
}
.form {
width: 60%;
}
.add-card-button {
display: flex;
justify-content: center;
@ -490,6 +342,7 @@ export default class PaymentMethods extends Vue {
}
&__title {
margin: 0;
font-family: 'font_bold', sans-serif;
font-size: 28px;
line-height: 42px;
@ -520,30 +373,6 @@ export default class PaymentMethods extends Vue {
}
}
}
&__adding-container {
margin-top: 44px;
display: flex;
max-height: 52px;
justify-content: space-between;
align-items: center;
&__label {
font-family: 'font_medium', sans-serif;
font-size: 21px;
}
&__stripe {
width: 60%;
min-width: 400px;
}
&__submit-area {
display: flex;
align-items: center;
min-width: 135px;
}
}
}
&__security-info-container {
@ -583,15 +412,6 @@ export default class PaymentMethods extends Vue {
}
}
.storj-container {
display: flex;
align-items: center;
&__label {
margin-right: 30px;
}
}
.payment-loading-image {
width: 18px;
height: 18px;

View File

@ -7,10 +7,10 @@
<CardIcon class="banner-gift-svg" v-else />
<div class="payments-bonus-container__text-container" v-if="anyCreditCards">
<p class="payments-bonus-container__text-container__main-text">
Get free credits for paying in STORJ!
Get free credits for paying in STORJ Token
</p>
<p class="payments-bonus-container__text-container__additional-text">
Deposit STORJ tokens to your account and receive a 10% bonus, or $10 for every $100.
Deposit STORJ Token to your account and receive a 10% bonus, or $10 for every $100.
</p>
</div>
<div class="payments-bonus-container__text-container" v-else >

View File

@ -0,0 +1,21 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
import AddCardForm from '@/components/account/billing/paymentMethods/AddCardForm.vue';
import { NotificatorPlugin } from '@/utils/plugins/notificator';
import { createLocalVue, mount } from '@vue/test-utils';
const localVue = createLocalVue();
const notificationsPlugin = new NotificatorPlugin();
localVue.use(notificationsPlugin);
describe('AddCardForm', () => {
it('renders correctly', () => {
const wrapper = mount(AddCardForm, {
localVue,
});
expect(wrapper).toMatchSnapshot();
});
});

View File

@ -0,0 +1,108 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
import Vuex from 'vuex';
import AddStorjForm from '@/components/account/billing/paymentMethods/AddStorjForm.vue';
import { appStateModule } from '@/store/modules/appState';
import { makeNotificationsModule } from '@/store/modules/notifications';
import { makePaymentsModule, PAYMENTS_MUTATIONS } from '@/store/modules/payments';
import { makeProjectsModule, PROJECTS_MUTATIONS } from '@/store/modules/projects';
import { makeUsersModule, USER_MUTATIONS } from '@/store/modules/users';
import { NOTIFICATION_MUTATIONS } from '@/store/mutationConstants';
import { BillingHistoryItem, BillingHistoryItemStatus, BillingHistoryItemType } from '@/types/payments';
import { Project } from '@/types/projects';
import { User } from '@/types/users';
import { Notificator } from '@/utils/plugins/notificator';
import { SegmentioPlugin } from '@/utils/plugins/segment';
import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
import { PaymentsMock } from '../../../mock/api/payments';
import { ProjectsApiMock } from '../../../mock/api/projects';
import { UsersApiMock } from '../../../mock/api/users';
const localVue = createLocalVue();
const segmentioPlugin = new SegmentioPlugin();
localVue.use(Vuex);
localVue.use(segmentioPlugin);
const paymentsApi = new PaymentsMock();
const paymentsModule = makePaymentsModule(paymentsApi);
const usersApi = new UsersApiMock();
const usersModule = makeUsersModule(usersApi);
const projectsApi = new ProjectsApiMock();
const projectsModule = makeProjectsModule(projectsApi);
const notificationsModule = makeNotificationsModule();
const store = new Vuex.Store({ modules: { usersModule, paymentsModule, projectsModule, appStateModule, notificationsModule }});
store.commit(USER_MUTATIONS.SET_USER, new User('id', 'name', 'short', 'test@test.test', 'partner', 'pass'));
class NotificatorPlugin {
public install() {
localVue.prototype.$notify = new Notificator(store);
}
}
const notificationsPlugin = new NotificatorPlugin();
localVue.use(notificationsPlugin);
describe('AddStorjForm', () => {
it('renders correctly', () => {
const wrapper = mount(AddStorjForm, {
store,
localVue,
});
expect(wrapper).toMatchSnapshot();
});
it('user is unable to add less than 50$ or more than 999999$ for the first time', async () => {
const wrapper = mount(AddStorjForm, {
store,
localVue,
});
wrapper.vm.$data.tokenDepositValue = 30;
await wrapper.vm.onConfirmAddSTORJ();
expect((store.state as any).notificationsModule.notificationQueue[0].message).toMatch('First deposit amount must be more than 50 and less than 1000000');
wrapper.vm.$data.tokenDepositValue = 1000000;
await wrapper.vm.onConfirmAddSTORJ();
expect((store.state as any).notificationsModule.notificationQueue[1].message).toMatch('First deposit amount must be more than 50 and less than 1000000');
});
it('user is able to add less than 50$ after coupon is applied', async () => {
window.open = jest.fn();
const billingTransactionItem = new BillingHistoryItem('itemId', 'test', 50, 50,
BillingHistoryItemStatus.Completed, 'test', new Date(), new Date(), BillingHistoryItemType.Transaction);
const project = new Project('testId', 'test', 'test', 'test', 'id', true);
store.commit(NOTIFICATION_MUTATIONS.CLEAR);
store.commit(PAYMENTS_MUTATIONS.SET_BILLING_HISTORY, [billingTransactionItem]);
store.commit(PROJECTS_MUTATIONS.ADD, project);
const wrapper = mount(AddStorjForm, {
store,
localVue,
});
wrapper.vm.$data.tokenDepositValue = 30;
await wrapper.vm.onConfirmAddSTORJ();
expect((store.state as any).notificationsModule.notificationQueue[0].type).toMatch('SUCCESS');
});
it('renders correctly after continue To Coin Payments click', () => {
window.open = jest.fn();
const wrapper = shallowMount(AddStorjForm, {
store,
localVue,
propsData: {
isLoading: true,
},
});
expect(wrapper).toMatchSnapshot();
});
});

View File

@ -8,11 +8,9 @@ import PaymentMethods from '@/components/account/billing/paymentMethods/PaymentM
import { appStateModule } from '@/store/modules/appState';
import { makeNotificationsModule } from '@/store/modules/notifications';
import { makePaymentsModule, PAYMENTS_MUTATIONS } from '@/store/modules/payments';
import { makeProjectsModule, PROJECTS_MUTATIONS } from '@/store/modules/projects';
import { makeProjectsModule } from '@/store/modules/projects';
import { makeUsersModule, USER_MUTATIONS } from '@/store/modules/users';
import { NOTIFICATION_MUTATIONS } from '@/store/mutationConstants';
import { BillingHistoryItem, BillingHistoryItemStatus, BillingHistoryItemType, CreditCard } from '@/types/payments';
import { Project } from '@/types/projects';
import { CreditCard } from '@/types/payments';
import { User } from '@/types/users';
import { Notificator } from '@/utils/plugins/notificator';
import { SegmentioPlugin } from '@/utils/plugins/segment';
@ -45,7 +43,6 @@ class NotificatorPlugin {
}
const notificationsPlugin = new NotificatorPlugin();
localVue.use(notificationsPlugin);
describe('PaymentMethods', () => {
@ -58,42 +55,6 @@ describe('PaymentMethods', () => {
expect(wrapper).toMatchSnapshot();
});
it('user is unable to add less than 50$ or more than 999999$ for the first time', async () => {
const wrapper = mount(PaymentMethods, {
store,
localVue,
});
wrapper.vm.$data.tokenDepositValue = 30;
await wrapper.vm.onConfirmAddSTORJ();
expect((store.state as any).notificationsModule.notificationQueue[0].message).toMatch('First deposit amount must be more than 50 and less than 1000000');
wrapper.vm.$data.tokenDepositValue = 1000000;
await wrapper.vm.onConfirmAddSTORJ();
expect((store.state as any).notificationsModule.notificationQueue[1].message).toMatch('First deposit amount must be more than 50 and less than 1000000');
});
it('user is able to add less than 50$ after coupon is applied', async () => {
window.open = jest.fn();
const billingTransactionItem = new BillingHistoryItem('itemId', 'test', 50, 50,
BillingHistoryItemStatus.Completed, 'test', new Date(), new Date(), BillingHistoryItemType.Transaction);
const project = new Project('testId', 'test', 'test', 'test', 'id', true);
store.commit(NOTIFICATION_MUTATIONS.CLEAR);
store.commit(PAYMENTS_MUTATIONS.SET_BILLING_HISTORY, [billingTransactionItem]);
store.commit(PROJECTS_MUTATIONS.ADD, project);
const wrapper = mount(PaymentMethods, {
store,
localVue,
});
wrapper.vm.$data.tokenDepositValue = 30;
await wrapper.vm.onConfirmAddSTORJ();
expect((store.state as any).notificationsModule.notificationQueue[0].type).toMatch('SUCCESS');
});
it('renders correctly after add card and cancel click', async (done) => {
const wrapper = shallowMount(PaymentMethods, {
store,
@ -122,7 +83,7 @@ describe('PaymentMethods', () => {
localVue,
});
await wrapper.find('.button').trigger('click');
await wrapper.find('.add-storj-button').trigger('click');
await new Promise(resolve => {
setTimeout(() => {
@ -138,30 +99,6 @@ describe('PaymentMethods', () => {
});
});
it('renders correctly after continue To Coin Payments click', async (done) => {
const project = new Project('id', 'test', 'test', 'test', 'test', true);
store.commit(PROJECTS_MUTATIONS.ADD, project);
const wrapper = mount(PaymentMethods, {
store,
localVue,
});
await wrapper.find('.button').trigger('click');
await new Promise(resolve => {
setTimeout(() => {
resolve();
wrapper.find('.confirm-add-storj-button').trigger('click');
setTimeout(() => {
expect(wrapper).toMatchSnapshot();
done();
}, 500);
}, 500);
});
});
it('renders correctly with card', () => {
const card = new CreditCard('cardId', 12, 2100, 'test', '0000', true);
store.commit(PAYMENTS_MUTATIONS.SET_CREDIT_CARDS, [card]);

View File

@ -0,0 +1,14 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`AddCardForm renders correctly 1`] = `
<div class="add-card-area">
<p class="add-card-area__label">Add Credit or Debit Card</p>
<form id="payment-form" class="add-card-area__stripe">
<div class="form-row">
<div id="card-element"></div>
<div id="card-errors" role="alert"></div>
</div>
</form>
<div class="add-card-area__submit-area"></div>
</div>
`;

View File

@ -0,0 +1,40 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`AddStorjForm renders correctly 1`] = `
<div class="add-storj-area">
<div class="add-storj-area__selection-container">
<p class="add-storj-area__selection-container__label">Deposit STORJ Tokens via Coin Payments</p>
<div class="form-container add-storj-area__selection-container__form">
<div class="selected-container">
<div id="paymentSelectButton" class="selected-container__label-container">
<p class="selected-container__label-container__label">USD $50</p>
<div class="selected-container__label-container__svg"><svg width="14" height="8" viewBox="0 0 14 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.372773 0.338888C0.869804 -0.112963 1.67565 -0.112963 2.17268 0.338888L7 4.72741L11.8273 0.338888C12.3243 -0.112963 13.1302 -0.112963 13.6272 0.338888C14.1243 0.790739 14.1243 1.52333 13.6272 1.97519L7 8L0.372773 1.97519C-0.124258 1.52333 -0.124258 0.790739 0.372773 0.338888Z" fill="#2683FF"></path>
</svg></div>
</div>
</div>
<!---->
<!---->
<!---->
</div>
</div>
<div class="add-storj-area__submit-area">
<!---->
<div class="confirm-add-storj-button container" style="width: 251px; height: 48px;">
<h1 class="label">Continue to Coin Payments</h1>
</div>
</div>
</div>
`;
exports[`AddStorjForm renders correctly after continue To Coin Payments click 1`] = `
<div class="add-storj-area">
<div class="add-storj-area__selection-container">
<p class="add-storj-area__selection-container__label">Deposit STORJ Tokens via Coin Payments</p>
<tokendepositselection-stub class="add-storj-area__selection-container__form"></tokendepositselection-stub>
</div>
<div class="add-storj-area__submit-area"><img src="@/../static/images/account/billing/loading.gif" alt="loading gif" class="loading-image">
<vbutton-stub label="Continue to Coin Payments" width="251px" height="48px" isdisabled="true" onpress="function () { [native code] }" class="confirm-add-storj-button"></vbutton-stub>
</div>
</div>
`;

View File

@ -4,7 +4,7 @@ exports[`PaymentMethods renders correctly after add STORJ and cancel click 1`] =
<div class="payment-methods-area">
<div class="payment-methods-area__functional-area extended">
<div class="payment-methods-area__functional-area__top-container">
<h1 class="payment-methods-area__functional-area__title text">Payment Method</h1>
<h1 class="payment-methods-area__functional-area__title">Payment Method</h1>
<div class="payment-methods-area__functional-area__button-area">
<div class="payment-methods-area__functional-area__button-area__cancel">
<p class="payment-methods-area__functional-area__button-area__cancel__text">Cancel</p>
@ -23,17 +23,17 @@ exports[`PaymentMethods renders correctly after add STORJ and cancel click 1`] =
</svg>
<div class="payments-bonus-container__text-container">
<p class="payments-bonus-container__text-container__main-text">
Get free credits for paying in STORJ!
Get free credits for paying in STORJ Token
</p>
<p class="payments-bonus-container__text-container__additional-text">
Deposit STORJ tokens to your account and receive a 10% bonus, or $10 for every $100.
Deposit STORJ Token to your account and receive a 10% bonus, or $10 for every $100.
</p>
</div>
</div>
<div class="payment-methods-area__functional-area__adding-container">
<div class="storj-container">
<p class="storj-container__label">Deposit STORJ Tokens via Coin Payments</p>
<div class="form-container form">
<div class="add-storj-area">
<div class="add-storj-area__selection-container">
<p class="add-storj-area__selection-container__label">Deposit STORJ Tokens via Coin Payments</p>
<div class="form-container add-storj-area__selection-container__form">
<div class="selected-container">
<div id="paymentSelectButton" class="selected-container__label-container">
<p class="selected-container__label-container__label">USD $50</p>
@ -47,7 +47,7 @@ exports[`PaymentMethods renders correctly after add STORJ and cancel click 1`] =
<!---->
</div>
</div>
<div class="payment-methods-area__functional-area__adding-container__submit-area">
<div class="add-storj-area__submit-area">
<!---->
<div class="confirm-add-storj-button container" style="width: 251px; height: 48px;">
<h1 class="label">Continue to Coin Payments</h1>
@ -67,10 +67,10 @@ exports[`PaymentMethods renders correctly after add STORJ and cancel click 2`] =
<div class="payment-methods-area">
<div class="payment-methods-area__functional-area">
<div class="payment-methods-area__functional-area__top-container">
<h1 class="payment-methods-area__functional-area__title text">Payment Method</h1>
<h1 class="payment-methods-area__functional-area__title">Payment Method</h1>
<div class="payment-methods-area__functional-area__button-area">
<div class="payment-methods-area__functional-area__button-area__default-buttons">
<div class="button container blue-white" style="width: 123px; height: 48px;">
<div class="add-storj-button container blue-white" style="width: 123px; height: 48px;">
<h1 class="label">Add STORJ</h1>
</div>
</div>
@ -107,7 +107,7 @@ exports[`PaymentMethods renders correctly after add card and cancel click 1`] =
<div class="payment-methods-area">
<div class="payment-methods-area__functional-area reduced">
<div class="payment-methods-area__functional-area__top-container">
<h1 class="payment-methods-area__functional-area__title text">Payment Method</h1>
<h1 class="payment-methods-area__functional-area__title">Payment Method</h1>
<div class="payment-methods-area__functional-area__button-area">
<div class="payment-methods-area__functional-area__button-area__cancel">
<p class="payment-methods-area__functional-area__button-area__cancel__text">Cancel</p>
@ -116,11 +116,7 @@ exports[`PaymentMethods renders correctly after add card and cancel click 1`] =
</div>
<!---->
<!---->
<div class="payment-methods-area__functional-area__adding-container">
<p class="payment-methods-area__functional-area__adding-container__label">Add Credit or Debit Card</p>
<stripecardinput-stub onstriperesponsecallback="function () { [native code] }" class="payment-methods-area__functional-area__adding-container__stripe"></stripecardinput-stub>
<div class="payment-methods-area__functional-area__adding-container__submit-area"></div>
</div>
<addcardform-stub></addcardform-stub>
<div class="add-card-button button-moved">
<!---->
<!----> <span>Add Card</span></div>
@ -139,10 +135,10 @@ exports[`PaymentMethods renders correctly after add card and cancel click 2`] =
<div class="payment-methods-area">
<div class="payment-methods-area__functional-area">
<div class="payment-methods-area__functional-area__top-container">
<h1 class="payment-methods-area__functional-area__title text">Payment Method</h1>
<h1 class="payment-methods-area__functional-area__title">Payment Method</h1>
<div class="payment-methods-area__functional-area__button-area">
<div class="payment-methods-area__functional-area__button-area__default-buttons">
<vbutton-stub label="Add STORJ" width="123px" height="48px" isbluewhite="true" onpress="function () { [native code] }" class="button"></vbutton-stub>
<vbutton-stub label="Add STORJ" width="123px" height="48px" isbluewhite="true" onpress="function () { [native code] }" class="add-storj-button"></vbutton-stub>
</div>
</div>
</div>
@ -159,54 +155,14 @@ exports[`PaymentMethods renders correctly after add card and cancel click 2`] =
</div>
`;
exports[`PaymentMethods renders correctly after continue To Coin Payments click 1`] = `
<div class="payment-methods-area">
<div class="payment-methods-area__functional-area">
<div class="payment-methods-area__functional-area__top-container">
<h1 class="payment-methods-area__functional-area__title text">Payment Method</h1>
<div class="payment-methods-area__functional-area__button-area">
<div class="payment-methods-area__functional-area__button-area__default-buttons">
<div class="button container blue-white" style="width: 123px; height: 48px;">
<h1 class="label">Add STORJ</h1>
</div>
</div>
</div>
</div>
<div class="payments-bonus-container payment-methods-area__functional-area__bonus"><svg width="64" height="50" viewBox="0 0 61 47" fill="none" xmlns="http://www.w3.org/2000/svg" class="banner-gift-svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M36.8378 12.7027C36.8378 19.0167 41.9563 24.1351 48.2703 24.1351V41.9189C48.2703 44.0236 46.5641 45.7297 44.4594 45.7297H5.08107C2.97642 45.7297 1.27026 44.0236 1.27026 41.9189V16.5135C1.27026 14.4089 2.97642 12.7027 5.08107 12.7027H36.8378Z" stroke="#2683FF" stroke-width="2"></path>
<path fill-rule="evenodd" clip-rule="evenodd" d="M48.2703 24.1352V27.946H1.27026V20.3243L39.7496 20.3251C41.8429 22.6636 44.8847 24.1352 48.2703 24.1352Z" fill="#2683FF"></path>
<path d="M48.2703 24.1351C54.5842 24.1351 59.7027 19.0167 59.7027 12.7027C59.7027 6.38875 54.5842 1.27028 48.2703 1.27028C41.9563 1.27028 36.8378 6.38875 36.8378 12.7027C36.8378 19.0167 41.9563 24.1351 48.2703 24.1351Z" stroke="#2683FF" stroke-width="2"></path>
<path d="M48.2703 5.71622V19.5737M41.3415 12.645H55.199H41.3415Z" stroke="#2683FF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<div class="payments-bonus-container__text-container">
<p class="payments-bonus-container__text-container__main-text">
Add a Payment Method to Get Started
</p>
<p class="payments-bonus-container__text-container__additional-text">
Your first 5GB are free. You will not be charged until you use more than 5GB.
</p>
</div>
</div>
<!---->
<!---->
<div class="add-card-button">
<!---->
<!----> <span>Add Card</span></div>
</div>
<!---->
<!---->
<!---->
</div>
`;
exports[`PaymentMethods renders correctly with card 1`] = `
<div class="payment-methods-area">
<div class="payment-methods-area__functional-area">
<div class="payment-methods-area__functional-area__top-container">
<h1 class="payment-methods-area__functional-area__title text">Payment Method</h1>
<h1 class="payment-methods-area__functional-area__title">Payment Method</h1>
<div class="payment-methods-area__functional-area__button-area">
<div class="payment-methods-area__functional-area__button-area__default-buttons">
<div class="button container blue-white" style="width: 123px; height: 48px;">
<div class="add-storj-button container blue-white" style="width: 123px; height: 48px;">
<h1 class="label">Add STORJ</h1>
</div>
</div>
@ -224,10 +180,10 @@ exports[`PaymentMethods renders correctly with card 1`] = `
</svg>
<div class="payments-bonus-container__text-container">
<p class="payments-bonus-container__text-container__main-text">
Get free credits for paying in STORJ!
Get free credits for paying in STORJ Token
</p>
<p class="payments-bonus-container__text-container__additional-text">
Deposit STORJ tokens to your account and receive a 10% bonus, or $10 for every $100.
Deposit STORJ Token to your account and receive a 10% bonus, or $10 for every $100.
</p>
</div>
</div>
@ -273,10 +229,10 @@ exports[`PaymentMethods renders correctly without card 1`] = `
<div class="payment-methods-area">
<div class="payment-methods-area__functional-area">
<div class="payment-methods-area__functional-area__top-container">
<h1 class="payment-methods-area__functional-area__title text">Payment Method</h1>
<h1 class="payment-methods-area__functional-area__title">Payment Method</h1>
<div class="payment-methods-area__functional-area__button-area">
<div class="payment-methods-area__functional-area__button-area__default-buttons">
<div class="button container blue-white" style="width: 123px; height: 48px;">
<div class="add-storj-button container blue-white" style="width: 123px; height: 48px;">
<h1 class="label">Add STORJ</h1>
</div>
</div>