web/storagenode: all stats held history

Change-Id: Ief40a97a7e120dccefc04c3c2eb78b8492dff17d
This commit is contained in:
NickolaiYurchenko 2020-07-02 17:44:41 +03:00
parent 6ec7bc8b5d
commit 14bb00f713
25 changed files with 829 additions and 164 deletions

View File

@ -153,6 +153,9 @@ export default class SNOHeader extends Vue {
await this.$router.replace('/');
}
/**
* Refreshes all needed data from server.
*/
public async onRefresh(): Promise<void> {
await this.$store.dispatch(APPSTATE_ACTIONS.SET_LOADING, true);
@ -162,7 +165,6 @@ export default class SNOHeader extends Vue {
try {
await this.$store.dispatch(GET_NODE_INFO);
await this.$store.dispatch(SELECT_SATELLITE, selectedSatellite);
await this.$store.dispatch(PAYOUT_ACTIONS.GET_TOTAL);
} catch (error) {
console.error(`${error.message} satellite data.`);
}
@ -174,6 +176,25 @@ export default class SNOHeader extends Vue {
}
await this.$store.dispatch(APPSTATE_ACTIONS.SET_LOADING, false);
try {
await this.$store.dispatch(PAYOUT_ACTIONS.GET_HELD_INFO, selectedSatellite);
await this.$store.dispatch(PAYOUT_ACTIONS.GET_TOTAL);
} catch (error) {
console.error(error.message);
}
try {
await this.$store.dispatch(NOTIFICATIONS_ACTIONS.GET_NOTIFICATIONS, new NotificationsCursor(1));
} catch (error) {
console.error(error.message);
}
try {
await this.$store.dispatch(PAYOUT_ACTIONS.GET_HELD_HISTORY);
} catch (error) {
console.error(error.message);
}
}
}
</script>

View File

@ -0,0 +1,114 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
@Component
export default class BaseHeldHistoryTable extends Vue {}
</script>
<style scoped lang="scss">
.held-history-table-container--large {
&__labels-area {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
margin-top: 17px;
padding: 0 16px;
width: calc(100% - 32px);
height: 36px;
background: var(--table-header-color);
&__text {
font-family: 'font_medium', sans-serif;
font-size: 14px;
color: #909bad;
}
}
&__info-area {
padding: 11px 16px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
min-height: 34px;
height: auto;
border-bottom: 1px solid rgba(169, 181, 193, 0.3);
&:last-of-type {
border-bottom: none;
}
&__text {
font-family: 'font_regular', sans-serif;
font-size: 14px;
color: var(--regular-text-color);
max-width: 100%;
word-break: break-word;
}
&__months {
font-family: 'font_regular', sans-serif;
font-size: 11px;
color: #9b9db1;
margin-top: 3px;
}
}
}
.held-history-table-container--small {
display: none;
}
.column {
display: flex;
flex-direction: row;
align-items: center;
}
.justify-start {
justify-content: flex-start;
}
.justify-end {
justify-content: flex-end;
}
.column-1 {
width: 37%;
}
.column-2,
.column-3,
.column-4 {
width: 21%;
}
@media screen and (max-width: 720px) {
.column-1 {
width: 31%;
}
.column-2,
.column-3,
.column-4 {
width: 23%;
}
}
@media screen and (max-width: 600px) {
.held-history-table-container--large {
display: none;
}
.held-history-table-container--small {
display: block;
}
}
</style>

View File

@ -1,59 +1,19 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="held-history-table-container--small__item">
<div class="held-history-table-container--small__item__satellite-info">
<div>
<p class="held-history-table-container--small__item__satellite-info__name">{{ heldHistoryItem.satelliteName }}</p>
<p class="held-history-table-container--small__item__satellite-info__months">{{ heldHistoryItem.age }} month</p>
</div>
<div class="held-history-table-container--small__item__satellite-info__button">
<div class="icon hide" @click="hide" v-if="isExpanded">
<blue-hide-icon></blue-hide-icon>
</div>
<div class="icon expand" @click="expand" v-else>
<blue-expand-icon></blue-expand-icon>
</div>
</div>
</div>
<transition name="fade">
<div class="held-history-table-container--small__item__held-info" v-if="isExpanded">
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">Month 1-3</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{ heldHistoryItem.firstPeriod | centsToDollars }}</p>
</div>
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">Month 4-6</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{ heldHistoryItem.secondPeriod | centsToDollars }}</p>
</div>
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">Month 7-9</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{ heldHistoryItem.thirdPeriod | centsToDollars }}</p>
</div>
</div>
</transition>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { Component, Vue } from 'vue-property-decorator';
import BlueHideIcon from '@/../static/images/common/BlueMinus.svg';
import BlueExpandIcon from '@/../static/images/common/BluePlus.svg';
import { HeldHistoryMonthlyBreakdownItem } from '@/app/types/payout';
@Component({
components: {
BlueExpandIcon,
BlueHideIcon,
},
})
export default class HeldHistoryMonthlyBreakdownTableSmall extends Vue {
@Prop({default: () => new HeldHistoryMonthlyBreakdownItem()})
public readonly heldHistoryItem: HeldHistoryMonthlyBreakdownItem;
export default class BaseSmallHeldHistoryTable extends Vue {
/**
* Indicates if held info should be rendered.
*/

View File

@ -0,0 +1,68 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div>
<div class="held-history-table-container--large">
<div class="held-history-table-container--large__labels-area">
<div class="column justify-start column-1">
<p class="held-history-table-container--large__labels-area__text">Satellite</p>
</div>
<div class="column justify-end column-2">
<p class="held-history-table-container--large__labels-area__text">First Contact</p>
</div>
<div class="column justify-end column-3">
<p class="held-history-table-container--large__labels-area__text">Held Total</p>
</div>
<div class="column justify-end column-4">
<p class="held-history-table-container--large__labels-area__text">Held Returned</p>
</div>
</div>
<div v-for="item in allStats" class="held-history-table-container--large__info-area" :key="item.satelliteID">
<div class="justify-start column-1">
<p class="held-history-table-container--large__info-area__text">{{ item.satelliteName }}</p>
<p class="held-history-table-container--large__info-area__months">{{ item.age }} month</p>
</div>
<div class="column justify-end column-2">
<p class="held-history-table-container--large__info-area__text">{{ item.joinedAt.toISOString().split('T')[0] }}</p>
</div>
<div class="column justify-end column-3">
<p class="held-history-table-container--large__info-area__text">{{ item.totalHeld | centsToDollars }}</p>
</div>
<div class="column justify-end column-4">
<p class="held-history-table-container--large__info-area__text">{{ item.totalDisposed | centsToDollars }}</p>
</div>
</div>
</div>
<div class="held-history-table-container--small">
<HeldHistoryAllStatsTableItemSmall
v-for="item in allStats"
:held-history-item="item"
:key="item.satelliteID"
/>
</div>
</div>
</template>
<script lang="ts">
import { Component } from 'vue-property-decorator';
import BaseHeldHistoryTable from '@/app/components/payments/BaseHeldHistoryTable.vue';
import HeldHistoryAllStatsTableItemSmall from '@/app/components/payments/HeldHistoryAllStatsTableItemSmall.vue';
import { HeldHistoryAllStatItem } from '@/app/types/payout';
@Component({
components: {
HeldHistoryAllStatsTableItemSmall,
},
})
export default class HeldHistoryAllStatsTable extends BaseHeldHistoryTable {
/**
* Returns list of satellite held history items by periods from store.
*/
public get allStats(): HeldHistoryAllStatItem[] {
return this.$store.state.payoutModule.heldHistory.allStats;
}
}
</script>

View File

@ -0,0 +1,51 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="held-history-table-container--small__item">
<div class="held-history-table-container--small__item__satellite-info">
<div>
<p class="held-history-table-container--small__item__satellite-info__name">{{ heldHistoryItem.satelliteName }}</p>
<p class="held-history-table-container--small__item__satellite-info__months">{{ heldHistoryItem.age }} month</p>
</div>
<div class="held-history-table-container--small__item__satellite-info__button">
<div class="icon hide" @click="hide" v-if="isExpanded">
<blue-hide-icon></blue-hide-icon>
</div>
<div class="icon expand" @click="expand" v-else>
<blue-expand-icon></blue-expand-icon>
</div>
</div>
</div>
<transition name="fade">
<div class="held-history-table-container--small__item__held-info" v-if="isExpanded">
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">First Contact</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{ heldHistoryItem.joinedAt.toISOString().split('T')[0] }}</p>
</div>
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">Held Total</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{ heldHistoryItem.totalHeld | centsToDollars }}</p>
</div>
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">Held Returned</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{ heldHistoryItem.totalDisposed | centsToDollars }}</p>
</div>
</div>
</transition>
</div>
</template>
<script lang="ts">
import { Component, Prop } from 'vue-property-decorator';
import BaseSmallHeldHistoryTable from '@/app/components/payments/BaseSmallHeldHistoryTable.vue';
import { HeldHistoryAllStatItem } from '@/app/types/payout';
@Component
export default class HeldHistoryAllStatsTableSmall extends BaseSmallHeldHistoryTable {
@Prop({default: () => new HeldHistoryAllStatItem()})
public readonly heldHistoryItem: HeldHistoryAllStatItem;
}
</script>

View File

@ -5,25 +5,53 @@
<section class="held-history-container">
<div class="held-history-container__header">
<p class="held-history-container__header__title">Held Amount History</p>
<div class="held-history-container__header__selection-area">
<div
class="held-history-container__header__selection-area__item"
:class="{ active: isAllStatsShown }"
@click="showAllStats"
>
<p class="held-history-container__header__selection-area__item__label">
All Stats
</p>
</div>
<div
class="held-history-container__header__selection-area__item"
:class="{ active: !isAllStatsShown }"
@click="showMonthlyBreakdown"
>
<p class="held-history-container__header__selection-area__item__label">
Monthly Breakdown
</p>
</div>
</div>
</div>
<div class="held-history-container__divider"></div>
<HeldHistoryMonthlyBreakdownTable />
<HeldHistoryAllStatsTable v-if="isAllStatsShown"/>
<HeldHistoryMonthlyBreakdownTable v-else/>
</section>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import HeldHistoryAllStatsTable from '@/app/components/payments/HeldHistoryAllStatsTable.vue';
import HeldHistoryMonthlyBreakdownTable from '@/app/components/payments/HeldHistoryMonthlyBreakdownTable.vue';
import { PAYOUT_ACTIONS } from '@/app/store/modules/payout';
@Component({
components: {
HeldHistoryAllStatsTable,
HeldHistoryMonthlyBreakdownTable,
},
})
export default class HeldHistoryArea extends Vue {
/**
* Indicates if All Stats state is active.
*/
public isAllStatsShown: boolean = true;
/**
* Lifecycle hook before component render.
* Fetches held history information.
@ -31,6 +59,20 @@ export default class HeldHistoryArea extends Vue {
public beforeMount(): void {
this.$store.dispatch(PAYOUT_ACTIONS.GET_HELD_HISTORY);
}
/**
* Sets held history table state to All Stats.
*/
public showAllStats(): void {
this.isAllStatsShown = true;
}
/**
* Sets held history table state to Monthly Breakdown.
*/
public showMonthlyBreakdown(): void {
this.isAllStatsShown = false;
}
}
</script>
@ -48,21 +90,88 @@ export default class HeldHistoryArea extends Vue {
&__header {
display: flex;
flex-direction: row;
align-items: center;
align-items: flex-start;
justify-content: space-between;
height: 40px;
&__title {
font-family: 'font_medium', sans-serif;
font-size: 18px;
color: var(--regular-text-color);
}
&__selection-area {
display: flex;
align-items: center;
justify-content: flex-end;
height: 100%;
&__item {
display: flex;
align-items: flex-start;
justify-content: center;
cursor: pointer;
height: 100%;
padding: 0 20px;
border-bottom: 3px solid transparent;
z-index: 102;
&__label {
text-align: center;
font-size: 16px;
color: var(--regular-text-color);
}
&.active {
border-bottom: 3px solid var(--navigation-link-color);
&__label {
font-size: 16px;
color: var(--regular-text-color);
}
}
}
}
}
&__divider {
width: 100%;
height: 1px;
margin-top: 18px;
background-color: #eaeaea;
}
}
@media screen and (max-width: 870px) {
.held-history-container {
&__divider {
display: none;
}
&__header {
flex-direction: column;
align-items: flex-start;
height: auto;
&__selection-area {
width: 100%;
height: 41px;
margin: 20px 0;
&__item {
width: calc(50% - 40px);
border-bottom: 3px solid #eaeaea;
}
}
}
}
}
@media screen and (max-width: 600px) {
.held-history-container {
padding: 28px 20px 10px 20px;
}
}
</style>

View File

@ -35,7 +35,7 @@
</div>
</div>
<div class="held-history-table-container--small">
<HeldHistoryMonthlyBreakdownTableSmall
<HeldHistoryMonthlyBreakdownTableItemSmall
v-for="item in monthlyBreakdown"
:held-history-item="item"
:key="item.satelliteID"
@ -47,16 +47,17 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import HeldHistoryMonthlyBreakdownTableSmall from '@/app/components/payments/HeldHistoryMonthlyBreakdownTableSmall.vue';
import BaseHeldHistoryTable from '@/app/components/payments/BaseHeldHistoryTable.vue';
import HeldHistoryMonthlyBreakdownTableItemSmall from '@/app/components/payments/HeldHistoryMonthlyBreakdownTableItemSmall.vue';
import { HeldHistoryMonthlyBreakdownItem } from '@/app/types/payout';
@Component({
components: {
HeldHistoryMonthlyBreakdownTableSmall,
HeldHistoryMonthlyBreakdownTableItemSmall,
},
})
export default class HeldHistoryMonthlyBreakdownTable extends Vue {
export default class HeldHistoryMonthlyBreakdownTable extends BaseHeldHistoryTable {
/**
* Returns list of satellite held history items by periods from store.
*/
@ -65,95 +66,3 @@ export default class HeldHistoryMonthlyBreakdownTable extends Vue {
}
}
</script>
<style scoped lang="scss">
.held-history-table-container--large {
&__labels-area {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
margin-top: 17px;
padding: 0 16px;
width: calc(100% - 32px);
height: 36px;
background: var(--table-header-color);
&__text {
font-family: 'font_medium', sans-serif;
font-size: 14px;
color: #909bad;
}
}
&__info-area {
padding: 11px 16px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
min-height: 34px;
height: auto;
border-bottom: 1px solid rgba(169, 181, 193, 0.3);
&:last-of-type {
border-bottom: none;
}
&__text {
font-family: 'font_regular', sans-serif;
font-size: 14px;
color: var(--regular-text-color);
max-width: 100%;
word-break: break-word;
}
&__months {
font-family: 'font_regular', sans-serif;
font-size: 11px;
color: #9b9db1;
margin-top: 3px;
}
}
}
.held-history-table-container--small {
display: none;
}
.column {
display: flex;
flex-direction: row;
align-items: center;
}
.justify-start {
justify-content: flex-start;
}
.justify-end {
justify-content: flex-end;
}
.column-1 {
width: 37%;
}
.column-2,
.column-3,
.column-4 {
width: 21%;
}
@media screen and (max-width: 600px) {
.held-history-table-container--large {
display: none;
}
.held-history-table-container--small {
display: block;
}
}
</style>

View File

@ -0,0 +1,51 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="held-history-table-container--small__item">
<div class="held-history-table-container--small__item__satellite-info">
<div>
<p class="held-history-table-container--small__item__satellite-info__name">{{ heldHistoryItem.satelliteName }}</p>
<p class="held-history-table-container--small__item__satellite-info__months">{{ heldHistoryItem.age }} month</p>
</div>
<div class="held-history-table-container--small__item__satellite-info__button">
<div class="icon hide" @click="hide" v-if="isExpanded">
<blue-hide-icon></blue-hide-icon>
</div>
<div class="icon expand" @click="expand" v-else>
<blue-expand-icon></blue-expand-icon>
</div>
</div>
</div>
<transition name="fade">
<div class="held-history-table-container--small__item__held-info" v-if="isExpanded">
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">Month 1-3</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{ heldHistoryItem.firstPeriod | centsToDollars }}</p>
</div>
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">Month 4-6</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{ heldHistoryItem.secondPeriod | centsToDollars }}</p>
</div>
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">Month 7-9</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{ heldHistoryItem.thirdPeriod | centsToDollars }}</p>
</div>
</div>
</transition>
</div>
</template>
<script lang="ts">
import { Component, Prop } from 'vue-property-decorator';
import BaseSmallHeldHistoryTable from '@/app/components/payments/BaseSmallHeldHistoryTable.vue';
import { HeldHistoryMonthlyBreakdownItem } from '@/app/types/payout';
@Component
export default class HeldHistoryMonthlyBreakdownTableSmall extends BaseSmallHeldHistoryTable {
@Prop({default: () => new HeldHistoryMonthlyBreakdownItem()})
public readonly heldHistoryItem: HeldHistoryMonthlyBreakdownItem;
}
</script>

View File

@ -146,6 +146,7 @@ export interface PayoutApi {
export class HeldHistory {
public constructor(
public monthlyBreakdown: HeldHistoryMonthlyBreakdownItem[] = [],
public allStats: HeldHistoryAllStatItem[] = [],
) {}
}
@ -160,7 +161,20 @@ export class HeldHistoryMonthlyBreakdownItem {
public firstPeriod: number = 0,
public secondPeriod: number = 0,
public thirdPeriod: number = 0,
public fourthPeriod: number = 0,
) {}
}
/**
* Contains held information summary of satellite grouped by periods.
*/
export class HeldHistoryAllStatItem {
public constructor(
public satelliteID: string = '',
public satelliteName: string = '',
public age: number = 1,
public totalHeld: number = 0,
public totalDisposed: number = 0,
public joinedAt: Date = new Date(),
) {}
}

View File

@ -4,6 +4,7 @@
import {
EstimatedPayout,
HeldHistory,
HeldHistoryAllStatItem,
HeldHistoryMonthlyBreakdownItem,
HeldInfo,
PaymentInfoParameters,
@ -161,11 +162,21 @@ export class PayoutHttpApi implements PayoutApi {
historyItem.firstPeriod / this.PRICE_DIVIDER,
historyItem.secondPeriod / this.PRICE_DIVIDER,
historyItem.thirdPeriod / this.PRICE_DIVIDER,
historyItem.fourthPeriod / this.PRICE_DIVIDER,
);
});
return new HeldHistory(monthlyBreakdown);
const allStats = data.map((historyItem: any) => {
return new HeldHistoryAllStatItem(
historyItem.satelliteID,
historyItem.satelliteName,
historyItem.age,
historyItem.totalHeld,
historyItem.totalDisposed,
new Date(historyItem.joinedAt),
);
});
return new HeldHistory(monthlyBreakdown, allStats);
}
/**

View File

@ -0,0 +1,44 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
import Vuex from 'vuex';
import HeldHistoryAllStatsTable from '@/app/components/payments/HeldHistoryAllStatsTable.vue';
import { makePayoutModule, PAYOUT_MUTATIONS } from '@/app/store/modules/payout';
import { HeldHistory, HeldHistoryAllStatItem } from '@/app/types/payout';
import { PayoutHttpApi } from '@/storagenode/api/payout';
import { createLocalVue, shallowMount } from '@vue/test-utils';
const localVue = createLocalVue();
localVue.use(Vuex);
localVue.filter('centsToDollars', (cents: number): string => {
return `$${(cents / 100).toFixed(2)}`;
});
const payoutApi = new PayoutHttpApi();
const payoutModule = makePayoutModule(payoutApi);
const store = new Vuex.Store({ modules: { payoutModule }});
describe('HeldHistoryAllStatsTable', (): void => {
it('renders correctly with actual values', async (): Promise<void> => {
const wrapper = shallowMount(HeldHistoryAllStatsTable, {
store,
localVue,
});
const testJoinAt = new Date(Date.UTC(2020, 0, 30));
await store.commit(PAYOUT_MUTATIONS.SET_HELD_HISTORY, new HeldHistory(
[],
[
new HeldHistoryAllStatItem('1', 'name1', 1, 50000, 20000, testJoinAt),
new HeldHistoryAllStatItem('2', 'name2', 5, 40000, 30000, testJoinAt),
],
));
expect(wrapper).toMatchSnapshot();
});
});

View File

@ -0,0 +1,47 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
import HeldHistoryAllStatsTableItemSmall from '@/app/components/payments/HeldHistoryAllStatsTableItemSmall.vue';
import { HeldHistoryAllStatItem } from '@/app/types/payout';
import { createLocalVue, shallowMount } from '@vue/test-utils';
const localVue = createLocalVue();
localVue.filter('centsToDollars', (cents: number): string => {
return `$${(cents / 100).toFixed(2)}`;
});
describe('HeldHistoryAllStatsTableItemSmall', (): void => {
it('renders correctly with actual values', async (): Promise<void> => {
const testJoinAt = new Date(Date.UTC(2020, 0, 27));
const wrapper = shallowMount(HeldHistoryAllStatsTableItemSmall, {
propsData: {
heldHistoryItem: new HeldHistoryAllStatItem(
'1',
'name1',
7,
45000,
8000,
testJoinAt,
),
},
localVue,
});
expect(wrapper).toMatchSnapshot();
wrapper.find('.expand').trigger('click');
await localVue.nextTick();
expect(wrapper).toMatchSnapshot();
wrapper.find('.hide').trigger('click');
await localVue.nextTick();
expect(wrapper).toMatchSnapshot();
});
});

View File

@ -0,0 +1,50 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
import Vuex from 'vuex';
import HeldHistoryArea from '@/app/components/payments/HeldHistoryArea.vue';
import { makePayoutModule } from '@/app/store/modules/payout';
import { PayoutHttpApi } from '@/storagenode/api/payout';
import { createLocalVue, shallowMount } from '@vue/test-utils';
const localVue = createLocalVue();
localVue.use(Vuex);
const payoutApi = new PayoutHttpApi();
const payoutModule = makePayoutModule(payoutApi);
const store = new Vuex.Store({ modules: { payoutModule }});
describe('HeldHistoryArea', (): void => {
it('renders correctly', async (): Promise<void> => {
const wrapper = shallowMount(HeldHistoryArea, {
store,
localVue,
});
await localVue.nextTick();
expect(wrapper).toMatchSnapshot();
});
it('changes state correctly', async (): Promise<void> => {
const wrapper = shallowMount(HeldHistoryArea, {
store,
localVue,
});
wrapper.findAll('.held-history-container__header__selection-area__item').at(1).trigger('click');
await localVue.nextTick();
expect(wrapper).toMatchSnapshot();
wrapper.findAll('.held-history-container__header__selection-area__item').at(0).trigger('click');
await localVue.nextTick();
expect(wrapper).toMatchSnapshot();
});
});

View File

@ -30,9 +30,9 @@ describe('HeldHistoryMonthlyBreakdownTable', (): void => {
});
await store.commit(PAYOUT_MUTATIONS.SET_HELD_HISTORY, new HeldHistory([
new HeldHistoryMonthlyBreakdownItem('1', 'name1', 1, 50000, 0, 0, 0),
new HeldHistoryMonthlyBreakdownItem('2', 'name2', 5, 50000, 422280, 0, 0),
new HeldHistoryMonthlyBreakdownItem('3', 'name3', 6, 50000, 7333880, 7852235, 0),
new HeldHistoryMonthlyBreakdownItem('1', 'name1', 1, 50000, 0, 0),
new HeldHistoryMonthlyBreakdownItem('2', 'name2', 5, 50000, 422280, 0),
new HeldHistoryMonthlyBreakdownItem('3', 'name3', 6, 50000, 7333880, 7852235),
]));
expect(wrapper).toMatchSnapshot();

View File

@ -1,7 +1,7 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
import HeldHistoryMonthlyBreakdownTableSmall from '@/app/components/payments/HeldHistoryMonthlyBreakdownTableSmall.vue';
import HeldHistoryMonthlyBreakdownTableItemSmall from '@/app/components/payments/HeldHistoryMonthlyBreakdownTableItemSmall.vue';
import { HeldHistoryMonthlyBreakdownItem } from '@/app/types/payout';
import { createLocalVue, shallowMount } from '@vue/test-utils';
@ -14,7 +14,7 @@ localVue.filter('centsToDollars', (cents: number): string => {
describe('HeldHistoryMonthlyBreakdownTableSmall', (): void => {
it('renders correctly with actual values', async (): Promise<void> => {
const wrapper = shallowMount(HeldHistoryMonthlyBreakdownTableSmall, {
const wrapper = shallowMount(HeldHistoryMonthlyBreakdownTableItemSmall, {
propsData: {
heldHistoryItem: new HeldHistoryMonthlyBreakdownItem(
'1',
@ -23,7 +23,6 @@ describe('HeldHistoryMonthlyBreakdownTableSmall', (): void => {
50000,
7333880,
7852235,
0,
),
},
localVue,

View File

@ -0,0 +1,56 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`HeldHistoryAllStatsTable renders correctly with actual values 1`] = `
<div>
<div class="held-history-table-container--large">
<div class="held-history-table-container--large__labels-area">
<div class="column justify-start column-1">
<p class="held-history-table-container--large__labels-area__text">Satellite</p>
</div>
<div class="column justify-end column-2">
<p class="held-history-table-container--large__labels-area__text">First Contact</p>
</div>
<div class="column justify-end column-3">
<p class="held-history-table-container--large__labels-area__text">Held Total</p>
</div>
<div class="column justify-end column-4">
<p class="held-history-table-container--large__labels-area__text">Held Returned</p>
</div>
</div>
<div class="held-history-table-container--large__info-area">
<div class="justify-start column-1">
<p class="held-history-table-container--large__info-area__text">name1</p>
<p class="held-history-table-container--large__info-area__months">1 month</p>
</div>
<div class="column justify-end column-2">
<p class="held-history-table-container--large__info-area__text">2020-01-30</p>
</div>
<div class="column justify-end column-3">
<p class="held-history-table-container--large__info-area__text">$500.00</p>
</div>
<div class="column justify-end column-4">
<p class="held-history-table-container--large__info-area__text">$200.00</p>
</div>
</div>
<div class="held-history-table-container--large__info-area">
<div class="justify-start column-1">
<p class="held-history-table-container--large__info-area__text">name2</p>
<p class="held-history-table-container--large__info-area__months">5 month</p>
</div>
<div class="column justify-end column-2">
<p class="held-history-table-container--large__info-area__text">2020-01-30</p>
</div>
<div class="column justify-end column-3">
<p class="held-history-table-container--large__info-area__text">$400.00</p>
</div>
<div class="column justify-end column-4">
<p class="held-history-table-container--large__info-area__text">$300.00</p>
</div>
</div>
</div>
<div class="held-history-table-container--small">
<heldhistoryallstatstableitemsmall-stub heldhistoryitem="[object Object]"></heldhistoryallstatstableitemsmall-stub>
<heldhistoryallstatstableitemsmall-stub heldhistoryitem="[object Object]"></heldhistoryallstatstableitemsmall-stub>
</div>
</div>
`;

View File

@ -0,0 +1,71 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`HeldHistoryAllStatsTableItemSmall renders correctly with actual values 1`] = `
<div class="held-history-table-container--small__item">
<div class="held-history-table-container--small__item__satellite-info">
<div>
<p class="held-history-table-container--small__item__satellite-info__name">name1</p>
<p class="held-history-table-container--small__item__satellite-info__months">7 month</p>
</div>
<div class="held-history-table-container--small__item__satellite-info__button">
<div class="icon expand">
<blue-expand-icon-stub></blue-expand-icon-stub>
</div>
</div>
</div>
<transition-stub name="fade">
<!---->
</transition-stub>
</div>
`;
exports[`HeldHistoryAllStatsTableItemSmall renders correctly with actual values 2`] = `
<div class="held-history-table-container--small__item">
<div class="held-history-table-container--small__item__satellite-info">
<div>
<p class="held-history-table-container--small__item__satellite-info__name">name1</p>
<p class="held-history-table-container--small__item__satellite-info__months">7 month</p>
</div>
<div class="held-history-table-container--small__item__satellite-info__button">
<div class="icon hide">
<blue-hide-icon-stub></blue-hide-icon-stub>
</div>
</div>
</div>
<transition-stub name="fade">
<div class="held-history-table-container--small__item__held-info">
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">First Contact</p>
<p class="held-history-table-container--small__item__held-info__item__value">2020-01-27</p>
</div>
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">Held Total</p>
<p class="held-history-table-container--small__item__held-info__item__value">$450.00</p>
</div>
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">Held Returned</p>
<p class="held-history-table-container--small__item__held-info__item__value">$80.00</p>
</div>
</div>
</transition-stub>
</div>
`;
exports[`HeldHistoryAllStatsTableItemSmall renders correctly with actual values 3`] = `
<div class="held-history-table-container--small__item">
<div class="held-history-table-container--small__item__satellite-info">
<div>
<p class="held-history-table-container--small__item__satellite-info__name">name1</p>
<p class="held-history-table-container--small__item__satellite-info__months">7 month</p>
</div>
<div class="held-history-table-container--small__item__satellite-info__button">
<div class="icon expand">
<blue-expand-icon-stub></blue-expand-icon-stub>
</div>
</div>
</div>
<transition-stub name="fade">
<!---->
</transition-stub>
</div>
`;

View File

@ -0,0 +1,67 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`HeldHistoryArea changes state correctly 1`] = `
<section class="held-history-container">
<div class="held-history-container__header">
<p class="held-history-container__header__title">Held Amount History</p>
<div class="held-history-container__header__selection-area">
<div class="held-history-container__header__selection-area__item">
<p class="held-history-container__header__selection-area__item__label">
All Stats
</p>
</div>
<div class="held-history-container__header__selection-area__item active">
<p class="held-history-container__header__selection-area__item__label">
Monthly Breakdown
</p>
</div>
</div>
</div>
<div class="held-history-container__divider"></div>
<heldhistorymonthlybreakdowntable-stub></heldhistorymonthlybreakdowntable-stub>
</section>
`;
exports[`HeldHistoryArea changes state correctly 2`] = `
<section class="held-history-container">
<div class="held-history-container__header">
<p class="held-history-container__header__title">Held Amount History</p>
<div class="held-history-container__header__selection-area">
<div class="held-history-container__header__selection-area__item active">
<p class="held-history-container__header__selection-area__item__label">
All Stats
</p>
</div>
<div class="held-history-container__header__selection-area__item">
<p class="held-history-container__header__selection-area__item__label">
Monthly Breakdown
</p>
</div>
</div>
</div>
<div class="held-history-container__divider"></div>
<heldhistoryallstatstable-stub></heldhistoryallstatstable-stub>
</section>
`;
exports[`HeldHistoryArea renders correctly 1`] = `
<section class="held-history-container">
<div class="held-history-container__header">
<p class="held-history-container__header__title">Held Amount History</p>
<div class="held-history-container__header__selection-area">
<div class="held-history-container__header__selection-area__item active">
<p class="held-history-container__header__selection-area__item__label">
All Stats
</p>
</div>
<div class="held-history-container__header__selection-area__item">
<p class="held-history-container__header__selection-area__item__label">
Monthly Breakdown
</p>
</div>
</div>
</div>
<div class="held-history-container__divider"></div>
<heldhistoryallstatstable-stub></heldhistoryallstatstable-stub>
</section>
`;

View File

@ -64,9 +64,9 @@ exports[`HeldHistoryMonthlyBreakdownTable renders correctly with actual values 1
</div>
</div>
<div class="held-history-table-container--small">
<heldhistorymonthlybreakdowntablesmall-stub heldhistoryitem="[object Object]"></heldhistorymonthlybreakdowntablesmall-stub>
<heldhistorymonthlybreakdowntablesmall-stub heldhistoryitem="[object Object]"></heldhistorymonthlybreakdowntablesmall-stub>
<heldhistorymonthlybreakdowntablesmall-stub heldhistoryitem="[object Object]"></heldhistorymonthlybreakdowntablesmall-stub>
<heldhistorymonthlybreakdowntableitemsmall-stub heldhistoryitem="[object Object]"></heldhistorymonthlybreakdowntableitemsmall-stub>
<heldhistorymonthlybreakdowntableitemsmall-stub heldhistoryitem="[object Object]"></heldhistorymonthlybreakdowntableitemsmall-stub>
<heldhistorymonthlybreakdowntableitemsmall-stub heldhistoryitem="[object Object]"></heldhistorymonthlybreakdowntableitemsmall-stub>
</div>
</div>
`;

View File

@ -8,6 +8,7 @@ import { makePayoutModule, PAYOUT_ACTIONS, PAYOUT_MUTATIONS } from '@/app/store/
import {
EstimatedPayout,
HeldHistory,
HeldHistoryAllStatItem,
HeldHistoryMonthlyBreakdownItem,
HeldInfo,
PayoutInfoRange,
@ -80,16 +81,27 @@ describe('mutations', (): void => {
});
it('sets held history', (): void => {
const testHeldHistory = new HeldHistory([
new HeldHistoryMonthlyBreakdownItem('1', 'name1', 1, 50000, 0, 0, 0),
new HeldHistoryMonthlyBreakdownItem('2', 'name2', 5, 50000, 422280, 0, 0),
new HeldHistoryMonthlyBreakdownItem('3', 'name3', 6, 50000, 7333880, 7852235, 0),
]);
const testJoinAt = new Date(Date.UTC(2020, 0, 30));
const testHeldHistory = new HeldHistory(
[
new HeldHistoryMonthlyBreakdownItem('1', 'name1', 1, 50000, 0, 0),
new HeldHistoryMonthlyBreakdownItem('2', 'name2', 5, 50000, 422280, 0),
new HeldHistoryMonthlyBreakdownItem('3', 'name3', 6, 50000, 7333880, 7852235),
],
[
new HeldHistoryAllStatItem('1', 'name1', 1, 100, 0, testJoinAt),
new HeldHistoryAllStatItem('2', 'name2', 5, 30, 20, testJoinAt),
],
);
store.commit(PAYOUT_MUTATIONS.SET_HELD_HISTORY, testHeldHistory);
expect(state.payoutModule.heldHistory.monthlyBreakdown.length).toBe(testHeldHistory.monthlyBreakdown.length);
expect(state.payoutModule.heldHistory.monthlyBreakdown[1].satelliteName).toBe(testHeldHistory.monthlyBreakdown[1].satelliteName);
expect(state.payoutModule.heldHistory.allStats.length).toBe(testHeldHistory.allStats.length);
expect(state.payoutModule.heldHistory.allStats[0].joinedAt).toBe(testJoinAt);
expect(state.payoutModule.heldHistory.allStats[1].totalHeld).toBe(30);
});
it('sets estimated payout information', (): void => {
@ -252,18 +264,29 @@ describe('actions', () => {
});
it('success get held history', async (): Promise<void> => {
const testJoinAt = new Date(Date.UTC(2020, 0, 30));
jest.spyOn(payoutApi, 'getHeldHistory').mockReturnValue(
Promise.resolve(new HeldHistory([
new HeldHistoryMonthlyBreakdownItem('1', 'name1', 1, 50000, 0, 0, 0),
new HeldHistoryMonthlyBreakdownItem('2', 'name2', 5, 50000, 422280, 0, 0),
new HeldHistoryMonthlyBreakdownItem('3', 'name3', 6, 50000, 7333880, 7852235, 0),
])),
Promise.resolve(new HeldHistory(
[
new HeldHistoryMonthlyBreakdownItem('1', 'name1', 1, 50000, 0, 0),
new HeldHistoryMonthlyBreakdownItem('2', 'name2', 5, 50000, 422280, 0),
new HeldHistoryMonthlyBreakdownItem('3', 'name3', 6, 50000, 7333880, 7852235),
],
[
new HeldHistoryAllStatItem('1', 'name1', 1, 100, 0, testJoinAt),
new HeldHistoryAllStatItem('2', 'name2', 5, 30, 20, testJoinAt),
],
)),
);
await store.dispatch(PAYOUT_ACTIONS.GET_HELD_HISTORY);
expect(state.payoutModule.heldHistory.monthlyBreakdown.length).toBe(3);
expect(state.payoutModule.heldHistory.monthlyBreakdown[1].satelliteName).toBe('name2');
expect(state.payoutModule.heldHistory.allStats.length).toBe(2);
expect(state.payoutModule.heldHistory.allStats[0].joinedAt).toBe(testJoinAt);
expect(state.payoutModule.heldHistory.allStats[1].totalHeld).toBe(30);
});
it('get total throws an error when api call fails', async (): Promise<void> => {