web/satellite: onboarding tour: create project step
Change-Id: If091fd7f703e61c402a6bbdd80d98b0ce7b2bfd6
This commit is contained in:
parent
f54a4960a8
commit
4e5e6c8e5c
@ -21,6 +21,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import VInfo from '@/components/common/VInfo.vue';
|
||||
import NewProjectPopup from '@/components/project/NewProjectPopup.vue';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { ProjectOwning } from '@/utils/projectOwning';
|
||||
|
||||
@ -37,7 +38,7 @@ export default class NewProjectArea extends Vue {
|
||||
* Toggles new project button visibility depending on user having his own project or payment method.
|
||||
*/
|
||||
public beforeMount(): void {
|
||||
if (this.userHasOwnProject || !this.$store.getters.canUserCreateFirstProject) {
|
||||
if (this.userHasOwnProject || !this.$store.getters.canUserCreateFirstProject || this.isOnboardingTour) {
|
||||
this.$store.dispatch(APP_STATE_ACTIONS.HIDE_CREATE_PROJECT_BUTTON);
|
||||
|
||||
return;
|
||||
@ -67,6 +68,13 @@ export default class NewProjectArea extends Vue {
|
||||
return this.$store.state.appStateModule.appState.isCreateProjectButtonShown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if current route is onboarding tour.
|
||||
*/
|
||||
public get isOnboardingTour(): boolean {
|
||||
return this.$route.name === RouteConfig.OnboardingTour.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if user has own project.
|
||||
*/
|
||||
|
@ -3,13 +3,19 @@
|
||||
|
||||
<template>
|
||||
<div class="tour-area">
|
||||
<ProgressBar/>
|
||||
<ProgressBar
|
||||
:is-create-project-step="isCreateProjectState"
|
||||
/>
|
||||
<OverviewStep
|
||||
v-if="isDefaultState"
|
||||
@setAddPaymentState="setAddPaymentState"
|
||||
/>
|
||||
<AddPaymentStep
|
||||
v-if="isAddPaymentState"
|
||||
@setProjectState="setCreateProjectState"
|
||||
/>
|
||||
<CreateProjectStep
|
||||
v-if="isCreateProjectState"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -19,6 +25,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import ProgressBar from '@/components/onboardingTour/ProgressBar.vue';
|
||||
import AddPaymentStep from '@/components/onboardingTour/steps/AddPaymentStep.vue';
|
||||
import CreateProjectStep from '@/components/onboardingTour/steps/CreateProjectStep.vue';
|
||||
import OverviewStep from '@/components/onboardingTour/steps/OverviewStep.vue';
|
||||
|
||||
import CheckedImage from '@/../static/images/common/checked.svg';
|
||||
@ -28,6 +35,7 @@ import { TourState } from '@/utils/constants/onboardingTourEnums';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
CreateProjectStep,
|
||||
AddPaymentStep,
|
||||
ProgressBar,
|
||||
OverviewStep,
|
||||
@ -53,6 +61,10 @@ export default class OnboardingTourArea extends Vue {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.$store.state.paymentsModule.creditCards.length > 0) {
|
||||
this.setCreateProjectState();
|
||||
}
|
||||
|
||||
if (this.$store.getters.isTransactionProcessing || this.$store.getters.isTransactionCompleted) {
|
||||
this.setAddPaymentState();
|
||||
}
|
||||
@ -66,18 +78,32 @@ export default class OnboardingTourArea extends Vue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if area is adding payment method state.
|
||||
* Indicates if area is in adding payment method state.
|
||||
*/
|
||||
public get isAddPaymentState(): boolean {
|
||||
return this.areaState === TourState.ADDING_PAYMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if area is in creating project state.
|
||||
*/
|
||||
public get isCreateProjectState(): boolean {
|
||||
return this.areaState === TourState.PROJECT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets area's state to adding payment method state.
|
||||
*/
|
||||
public setAddPaymentState(): void {
|
||||
this.areaState = TourState.ADDING_PAYMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets area's state to creating project state.
|
||||
*/
|
||||
public setCreateProjectState(): void {
|
||||
this.areaState = TourState.PROJECT;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
<template>
|
||||
<div class="progress-bar-container">
|
||||
<div class="progress-bar-container__progress-area">
|
||||
<div class="progress-bar-container__progress-area__circle">
|
||||
<div class="progress-bar-container__progress-area__circle" :class="{ 'completed-step': isCreateProjectStep }">
|
||||
<CheckedImage/>
|
||||
</div>
|
||||
<div class="progress-bar-container__progress-area__bar"/>
|
||||
@ -17,7 +17,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-bar-container__titles-area">
|
||||
<span class="progress-bar-container__titles-area__title">Name Your Project</span>
|
||||
<span class="progress-bar-container__titles-area__title" :class="{ 'completed-font-color': isCreateProjectStep }">
|
||||
Name Your Project
|
||||
</span>
|
||||
<span class="progress-bar-container__titles-area__title api-key-title">Create an API Key</span>
|
||||
<span class="progress-bar-container__titles-area__title">Upload Data</span>
|
||||
</div>
|
||||
@ -25,7 +27,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
|
||||
import CheckedImage from '@/../static/images/common/checked.svg';
|
||||
|
||||
@ -35,7 +37,10 @@ import CheckedImage from '@/../static/images/common/checked.svg';
|
||||
},
|
||||
})
|
||||
|
||||
export default class ProgressBar extends Vue {}
|
||||
export default class ProgressBar extends Vue {
|
||||
@Prop({ default: false })
|
||||
public readonly isCreateProjectStep: boolean;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -77,6 +82,7 @@ export default class ProgressBar extends Vue {}
|
||||
font-size: 10px;
|
||||
line-height: 15px;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,6 +91,14 @@ export default class ProgressBar extends Vue {}
|
||||
padding: 0 15px 0 0;
|
||||
}
|
||||
|
||||
.completed-step {
|
||||
background-color: #2683ff;
|
||||
}
|
||||
|
||||
.completed-font-color {
|
||||
color: #2683ff;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
|
||||
.progress-bar-container {
|
||||
|
@ -32,10 +32,12 @@
|
||||
<AddCardState
|
||||
v-if="isAddCardState"
|
||||
@toggleIsLoading="toggleIsLoading"
|
||||
@setProjectState="setProjectState"
|
||||
/>
|
||||
<AddStorjState
|
||||
v-if="isAddStorjState"
|
||||
@toggleIsLoading="toggleIsLoading"
|
||||
@setProjectState="setProjectState"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -103,6 +105,13 @@ export default class AddPaymentStep extends Vue {
|
||||
public toggleIsLoading(): void {
|
||||
this.isLoading = !this.isLoading;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets tour area to creating project state.
|
||||
*/
|
||||
public setProjectState(): void {
|
||||
this.$emit('setProjectState');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -0,0 +1,291 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="new-project-step">
|
||||
<h1 class="new-project-step__title">Name Your Project</h1>
|
||||
<p class="new-project-step__sub-title">
|
||||
Projects are where buckets are created for storing data. Within a Project, usage is tracked at the bucket
|
||||
level and aggregated for billing.
|
||||
</p>
|
||||
<div class="new-project-step__container">
|
||||
<div class="new-project-step__container__title-area">
|
||||
<h2 class="new-project-step__container__title-area__title">Project Details</h2>
|
||||
<img
|
||||
v-if="isLoading"
|
||||
class="new-project-step__container__title-area__loading-image"
|
||||
src="@/../static/images/account/billing/loading.gif"
|
||||
alt="loading gif"
|
||||
>
|
||||
</div>
|
||||
<HeaderedInput
|
||||
label="Project Name"
|
||||
additional-label="Up To 20 Characters"
|
||||
placeholder="Enter Project Name"
|
||||
class="full-input"
|
||||
width="100%"
|
||||
max-symbols="20"
|
||||
:error="nameError"
|
||||
@setData="setProjectName"
|
||||
/>
|
||||
<HeaderedInput
|
||||
label="Description"
|
||||
placeholder="Enter Project Description"
|
||||
additional-label="Optional"
|
||||
class="full-input"
|
||||
is-multiline="true"
|
||||
height="100px"
|
||||
width="100%"
|
||||
@setData="setProjectDescription"
|
||||
/>
|
||||
<div class="new-project-step__container__blur" v-if="isLoading"/>
|
||||
</div>
|
||||
<VButton
|
||||
class="create-project-button"
|
||||
width="156px"
|
||||
height="48px"
|
||||
label="Create Project"
|
||||
:on-press="createProjectClick"
|
||||
:is-disabled="!projectName"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import HeaderedInput from '@/components/common/HeaderedInput.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { CreateProjectModel, Project } from '@/types/projects';
|
||||
import { PM_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { anyCharactersButSlash } from '@/utils/validation';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
VButton,
|
||||
HeaderedInput,
|
||||
},
|
||||
})
|
||||
export default class CreateProjectStep extends Vue {
|
||||
private description: string = '';
|
||||
|
||||
public projectName: string = '';
|
||||
public isLoading: boolean = false;
|
||||
public nameError: string = '';
|
||||
|
||||
/**
|
||||
* Sets project name from input value.
|
||||
*/
|
||||
public setProjectName(value: string): void {
|
||||
this.projectName = value;
|
||||
this.nameError = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets project description from input value.
|
||||
*/
|
||||
public setProjectDescription(value: string): void {
|
||||
this.description = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates project and refreshes store.
|
||||
*/
|
||||
public async createProjectClick(): Promise<void> {
|
||||
if (this.isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
|
||||
if (!this.isProjectNameValid()) {
|
||||
this.isLoading = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let createdProjectId: string = '';
|
||||
|
||||
try {
|
||||
const project = await this.createProject();
|
||||
createdProjectId = project.id;
|
||||
this.$segment.track(SegmentEvent.PROJECT_CREATED, {
|
||||
project_id: createdProjectId,
|
||||
});
|
||||
await this.$notify.success('Project created successfully!');
|
||||
} catch (error) {
|
||||
this.isLoading = false;
|
||||
await this.$notify.error(error.message);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.SELECT, createdProjectId);
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(PM_ACTIONS.FETCH, 1);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to get project members. ${error.message}`);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(PAYMENTS_ACTIONS.GET_BILLING_HISTORY);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to get billing history. ${error.message}`);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(PAYMENTS_ACTIONS.GET_BALANCE);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to get account balance. ${error.message}`);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(PAYMENTS_ACTIONS.GET_PROJECT_USAGE_AND_CHARGES_CURRENT_ROLLUP);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to get project usage and charges for current rollup. ${error.message}`);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.GET_LIMITS, createdProjectId);
|
||||
} catch (error) {
|
||||
await this.$notify.error(`Unable to get project limits. ${error.message}`);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
|
||||
// TODO: rework after adding third step of onboarding tour
|
||||
await this.$router.push(RouteConfig.ApiKeys.path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates input value to satisfy project name rules.
|
||||
*/
|
||||
private isProjectNameValid(): boolean {
|
||||
this.projectName.trim();
|
||||
|
||||
if (!anyCharactersButSlash(this.projectName)) {
|
||||
this.nameError = 'Name for project is invalid!';
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.projectName.length > 20) {
|
||||
this.nameError = 'Name should be less than 21 character!';
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes create project request.
|
||||
*/
|
||||
private async createProject(): Promise<Project> {
|
||||
const project: CreateProjectModel = {
|
||||
name: this.projectName,
|
||||
description: this.description,
|
||||
ownerId: this.$store.getters.user.id,
|
||||
};
|
||||
|
||||
return await this.$store.dispatch(PROJECTS_ACTIONS.CREATE, project);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
h1,
|
||||
h2,
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.new-project-step {
|
||||
font-family: 'font_regular', sans-serif;
|
||||
margin-top: 75px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 200px;
|
||||
|
||||
&__title {
|
||||
font-size: 32px;
|
||||
line-height: 39px;
|
||||
color: #1b2533;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
&__sub-title {
|
||||
font-size: 16px;
|
||||
line-height: 19px;
|
||||
color: #354049;
|
||||
margin-bottom: 35px;
|
||||
text-align: center;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
&__container {
|
||||
padding: 50px;
|
||||
width: calc(100% - 100px);
|
||||
border-radius: 8px;
|
||||
background-color: #fff;
|
||||
position: relative;
|
||||
margin-bottom: 30px;
|
||||
|
||||
&__title-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&__title {
|
||||
font-family: 'font_medium', sans-serif;
|
||||
font-size: 22px;
|
||||
line-height: 27px;
|
||||
color: #354049;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
&__loading-image {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
&__blur {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: rgba(229, 229, 229, 0.2);
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.full-input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1450px) {
|
||||
|
||||
.new-project-step {
|
||||
padding: 0 150px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
|
||||
.new-project-step {
|
||||
padding: 0 50px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -36,7 +36,6 @@ import StripeCardInput from '@/components/account/billing/paymentMethods/StripeC
|
||||
import LockImage from '@/../static/images/account/billing/lock.svg';
|
||||
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
|
||||
|
||||
const {
|
||||
@ -104,8 +103,7 @@ export default class AddCardState extends Vue {
|
||||
|
||||
this.setDefaultState();
|
||||
|
||||
// TODO: rework after adding next step
|
||||
await this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_PROJ);
|
||||
this.$emit('setProjectState');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,7 +147,7 @@ export default class AddStorjState extends Vue {
|
||||
* Starts creating project process.
|
||||
*/
|
||||
public createProject(): void {
|
||||
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_PROJ);
|
||||
this.$emit('setProjectState');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -63,7 +63,6 @@ import VButton from '@/components/common/VButton.vue';
|
||||
import CloseCrossIcon from '@/../static/images/common/closeCross.svg';
|
||||
import SuccessIcon from '@/../static/images/project/success.svg';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
|
||||
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
@ -86,10 +85,11 @@ import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
|
||||
export default class NewProjectPopup extends Vue {
|
||||
private projectName: string = '';
|
||||
private description: string = '';
|
||||
private nameError: string = '';
|
||||
private createdProjectId: string = '';
|
||||
private isLoading: boolean = false;
|
||||
|
||||
public nameError: string = '';
|
||||
|
||||
/**
|
||||
* Indicates if popup is shown.
|
||||
*/
|
||||
@ -175,9 +175,6 @@ export default class NewProjectPopup extends Vue {
|
||||
this.checkIfUsersFirstProject();
|
||||
|
||||
this.isLoading = false;
|
||||
|
||||
// TODO: remove after adding second step of onboarding tour
|
||||
await this.$router.push(RouteConfig.ProjectDashboard.path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -11,3 +11,9 @@ export function validateEmail(email: string): boolean {
|
||||
export function validatePassword(password: string): boolean {
|
||||
return typeof password !== 'undefined' && password.length >= 6;
|
||||
}
|
||||
|
||||
export function anyCharactersButSlash(string: string): boolean {
|
||||
const rgx = /^[^\/]+$/;
|
||||
|
||||
return rgx.test(string);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import Vuex from 'vuex';
|
||||
|
||||
import NewProjectArea from '@/components/header/NewProjectArea.vue';
|
||||
|
||||
import { router } from '@/router';
|
||||
import { appStateModule } from '@/store/modules/appState';
|
||||
import { makePaymentsModule, PAYMENTS_MUTATIONS } from '@/store/modules/payments';
|
||||
import { makeProjectsModule, PROJECTS_MUTATIONS } from '@/store/modules/projects';
|
||||
@ -36,6 +37,7 @@ describe('NewProjectArea', () => {
|
||||
const wrapper = mount(NewProjectArea, {
|
||||
store,
|
||||
localVue,
|
||||
router,
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
@ -50,6 +52,7 @@ describe('NewProjectArea', () => {
|
||||
const wrapper = mount(NewProjectArea, {
|
||||
store,
|
||||
localVue,
|
||||
router,
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
@ -70,6 +73,7 @@ describe('NewProjectArea', () => {
|
||||
const wrapper = mount(NewProjectArea, {
|
||||
store,
|
||||
localVue,
|
||||
router,
|
||||
});
|
||||
|
||||
expect(wrapper.findAll('.new-project-button-container').length).toBe(1);
|
||||
@ -85,6 +89,7 @@ describe('NewProjectArea', () => {
|
||||
const wrapper = mount(NewProjectArea, {
|
||||
store,
|
||||
localVue,
|
||||
router,
|
||||
});
|
||||
|
||||
expect(wrapper.findAll('.new-project-button-container').length).toBe(0);
|
||||
|
@ -15,6 +15,8 @@ exports[`ProgressBar.vue renders correctly 1`] = `
|
||||
<path d="M7.61854 0.302314C8.02258 -0.100771 8.67764 -0.100771 9.08163 0.302314C9.48569 0.705397 9.48569 1.35893 9.08163 1.76202L4.20463 6.62768C3.8006 7.03077 3.14555 7.03077 2.74152 6.62768L0.303018 4.19485C-0.101006 3.79177 -0.101006 3.13823 0.303018 2.73515C0.707044 2.33206 1.3621 2.33206 1.76612 2.73515L3.47307 4.43813L7.61854 0.302314Z" fill="white"></path>
|
||||
</svg></div>
|
||||
</div>
|
||||
<div class="progress-bar-container__titles-area"><span class="progress-bar-container__titles-area__title">Name Your Project</span> <span class="progress-bar-container__titles-area__title api-key-title">Create an API Key</span> <span class="progress-bar-container__titles-area__title">Upload Data</span></div>
|
||||
<div class="progress-bar-container__titles-area"><span class="progress-bar-container__titles-area__title">
|
||||
Name Your Project
|
||||
</span> <span class="progress-bar-container__titles-area__title api-key-title">Create an API Key</span> <span class="progress-bar-container__titles-area__title">Upload Data</span></div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -5,5 +5,6 @@ exports[`OnboardingTourArea.vue renders correctly 1`] = `
|
||||
<progressbar-stub></progressbar-stub>
|
||||
<overviewstep-stub></overviewstep-stub>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
`;
|
||||
|
@ -0,0 +1,55 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import sinon from 'sinon';
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import CreateProjectStep from '@/components/onboardingTour/steps/CreateProjectStep.vue';
|
||||
|
||||
import { PaymentsHttpApi } from '@/api/payments';
|
||||
import { makePaymentsModule } from '@/store/modules/payments';
|
||||
import { makeProjectsModule } from '@/store/modules/projects';
|
||||
import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
|
||||
|
||||
import { ProjectsApiMock } from '../../mock/api/projects';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
const paymentsApi = new PaymentsHttpApi();
|
||||
const paymentsModule = makePaymentsModule(paymentsApi);
|
||||
const projectsApi = new ProjectsApiMock();
|
||||
const projectsModule = makeProjectsModule(projectsApi);
|
||||
|
||||
const store = new Vuex.Store({ modules: { paymentsModule, projectsModule }});
|
||||
|
||||
describe('CreateProjectStep.vue', () => {
|
||||
it('renders correctly', (): void => {
|
||||
const wrapper = shallowMount(CreateProjectStep, {
|
||||
store,
|
||||
localVue,
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('click works correctly', async (): Promise<void> => {
|
||||
const clickSpy = sinon.spy();
|
||||
const wrapper = mount(CreateProjectStep, {
|
||||
store,
|
||||
localVue,
|
||||
methods: {
|
||||
createProjectClick: clickSpy,
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.findAll('.disabled').length).toBe(1);
|
||||
|
||||
await wrapper.vm.setProjectName('test');
|
||||
|
||||
expect(wrapper.findAll('.disabled').length).toBe(0);
|
||||
|
||||
await wrapper.find('.create-project-button').trigger('click');
|
||||
|
||||
expect(clickSpy.callCount).toBe(1);
|
||||
});
|
||||
});
|
@ -0,0 +1,21 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CreateProjectStep.vue renders correctly 1`] = `
|
||||
<div class="new-project-step">
|
||||
<h1 class="new-project-step__title">Name Your Project</h1>
|
||||
<p class="new-project-step__sub-title">
|
||||
Projects are where buckets are created for storing data. Within a Project, usage is tracked at the bucket
|
||||
level and aggregated for billing.
|
||||
</p>
|
||||
<div class="new-project-step__container">
|
||||
<div class="new-project-step__container__title-area">
|
||||
<h2 class="new-project-step__container__title-area__title">Project Details</h2>
|
||||
<!---->
|
||||
</div>
|
||||
<headeredinput-stub label="Project Name" placeholder="Enter Project Name" height="48px" width="100%" error="" maxsymbols="20" initvalue="" additionallabel="Up To 20 Characters" class="full-input"></headeredinput-stub>
|
||||
<headeredinput-stub label="Description" placeholder="Enter Project Description" height="100px" width="100%" error="" maxsymbols="9007199254740991" initvalue="" additionallabel="Optional" ismultiline="true" class="full-input"></headeredinput-stub>
|
||||
<!---->
|
||||
</div>
|
||||
<vbutton-stub label="Create Project" width="156px" height="48px" isdisabled="true" onpress="function () { [native code] }" class="create-project-button"></vbutton-stub>
|
||||
</div>
|
||||
`;
|
Loading…
Reference in New Issue
Block a user