web/storagenode: dependencies for testing and payout store tests added
Change-Id: Iae18d073ba35ba8ac48e2d4c88476b38b96bbd9b
This commit is contained in:
parent
9b4a3f8fcc
commit
51bf2b6155
@ -2,7 +2,5 @@
|
|||||||
// See LICENSE for copying information.
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
presets: [
|
presets: [ [ "@vue/app", { useBuiltIns: "entry" } ] ]
|
||||||
'@vue/app'
|
};
|
||||||
]
|
|
||||||
}
|
|
||||||
|
9
web/storagenode/jestSetup.ts
Normal file
9
web/storagenode/jestSetup.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (C) 2019 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
import { GlobalWithFetchMock } from 'jest-fetch-mock';
|
||||||
|
|
||||||
|
const customGlobal: GlobalWithFetchMock = global as GlobalWithFetchMock;
|
||||||
|
|
||||||
|
customGlobal.fetch = require('jest-fetch-mock');
|
||||||
|
customGlobal.fetchMock = customGlobal.fetch;
|
5377
web/storagenode/package-lock.json
generated
5377
web/storagenode/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -6,17 +6,15 @@
|
|||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
"lint": "vue-cli-service lint && stylelint '**/*.{vue,scss}' --fix",
|
"lint": "vue-cli-service lint && stylelint '**/*.{vue,scss}' --fix",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build",
|
||||||
"debug": "vue-cli-service build --mode development"
|
"debug": "vue-cli-service build --mode development",
|
||||||
|
"test": "vue-cli-service test:unit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chart.js": "2.9.3",
|
"chart.js": "2.9.3",
|
||||||
"stylelint": "13.0.0",
|
|
||||||
"stylelint-config-standard": "19.0.0",
|
|
||||||
"stylelint-scss": "3.14.2",
|
|
||||||
"stylelint-webpack-plugin": "1.2.1",
|
|
||||||
"vue": "2.6.11",
|
"vue": "2.6.11",
|
||||||
"vue-chartjs": "3.5.0",
|
"vue-chartjs": "3.5.0",
|
||||||
"vue-class-component": "7.2.2",
|
"vue-class-component": "7.2.2",
|
||||||
|
"vue-jest": "3.0.5",
|
||||||
"vue-property-decorator": "8.3.0",
|
"vue-property-decorator": "8.3.0",
|
||||||
"vue-router": "3.1.5",
|
"vue-router": "3.1.5",
|
||||||
"vuex": "3.1.2"
|
"vuex": "3.1.2"
|
||||||
@ -24,18 +22,27 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.8.4",
|
"@babel/core": "7.8.4",
|
||||||
"@babel/plugin-proposal-object-rest-spread": "7.8.3",
|
"@babel/plugin-proposal-object-rest-spread": "7.8.3",
|
||||||
"@types/sinon": "7.5.1",
|
"@vue/cli-plugin-babel": "4.1.1",
|
||||||
"@vue/cli-plugin-babel": "4.1.2",
|
"@vue/cli-plugin-typescript": "4.1.1",
|
||||||
"@vue/cli-plugin-typescript": "4.1.2",
|
"@vue/cli-plugin-unit-jest": "4.1.1",
|
||||||
"@vue/cli-plugin-unit-jest": "4.1.2",
|
"@vue/cli-service": "4.1.1",
|
||||||
"@vue/cli-service": "4.2.3",
|
"@vue/test-utils": "1.0.0-beta.30",
|
||||||
"babel-core": "7.0.0-bridge.0",
|
"babel-core": "7.0.0-bridge.0",
|
||||||
|
"compression-webpack-plugin": "3.0.1",
|
||||||
|
"core-js": "3.6.5",
|
||||||
|
"jest-fetch-mock": "3.0.0",
|
||||||
"node-sass": "4.13.1",
|
"node-sass": "4.13.1",
|
||||||
"sass-loader": "8.0.2",
|
"sass-loader": "8.0.0",
|
||||||
"tslint": "6.0.0",
|
"sinon": "7.5.0",
|
||||||
|
"stylelint": "12.0.1",
|
||||||
|
"stylelint-config-standard": "19.0.0",
|
||||||
|
"stylelint-scss": "3.13.0",
|
||||||
|
"stylelint-webpack-plugin": "1.2.1",
|
||||||
|
"ts-jest": "24.2.0",
|
||||||
|
"tslint": "5.20.1",
|
||||||
"tslint-consistent-codestyle": "1.16.0",
|
"tslint-consistent-codestyle": "1.16.0",
|
||||||
"tslint-loader": "3.5.4",
|
"tslint-loader": "3.5.4",
|
||||||
"typescript": "3.7.5",
|
"typescript": "3.7.4",
|
||||||
"vue-svg-loader": "0.15.0",
|
"vue-svg-loader": "0.15.0",
|
||||||
"vue-template-compiler": "2.6.11",
|
"vue-template-compiler": "2.6.11",
|
||||||
"vue-tslint": "0.3.2",
|
"vue-tslint": "0.3.2",
|
||||||
@ -87,5 +94,45 @@
|
|||||||
"media-feature-colon-space-before": "never",
|
"media-feature-colon-space-before": "never",
|
||||||
"media-feature-colon-space-after": "always"
|
"media-feature-colon-space-after": "always"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"automock": false,
|
||||||
|
"setupFiles": [
|
||||||
|
"./jestSetup.ts"
|
||||||
|
],
|
||||||
|
"globals": {
|
||||||
|
"ts-jest": {
|
||||||
|
"diagnostics": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"moduleFileExtensions": [
|
||||||
|
"js",
|
||||||
|
"jsx",
|
||||||
|
"json",
|
||||||
|
"vue",
|
||||||
|
"ts",
|
||||||
|
"tsx"
|
||||||
|
],
|
||||||
|
"collectCoverage": true,
|
||||||
|
"transform": {
|
||||||
|
"^.+\\.js$": "babel-jest",
|
||||||
|
"^.+\\.vue$": "vue-jest",
|
||||||
|
".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub",
|
||||||
|
"^.+\\.tsx?$": "ts-jest",
|
||||||
|
"^.+\\.svg$": "<rootDir>/tests/unit/mock/svgTransform.js"
|
||||||
|
},
|
||||||
|
"transformIgnorePatterns": [
|
||||||
|
"/node_modules/(?!(apollo-client|apollo-link))"
|
||||||
|
],
|
||||||
|
"moduleNameMapper": {
|
||||||
|
"^@/(.*)$": "<rootDir>/src/$1"
|
||||||
|
},
|
||||||
|
"snapshotSerializers": [
|
||||||
|
"jest-serializer-vue"
|
||||||
|
],
|
||||||
|
"testMatch": [
|
||||||
|
"**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"
|
||||||
|
],
|
||||||
|
"testURL": "http://localhost/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import { SNO_THEME } from '@/app/types/theme';
|
|||||||
components: {
|
components: {
|
||||||
SunIcon,
|
SunIcon,
|
||||||
MoonIcon,
|
MoonIcon,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
export default class OptionsDropdown extends Vue {
|
export default class OptionsDropdown extends Vue {
|
||||||
/**
|
/**
|
||||||
|
@ -29,7 +29,7 @@ import WalletIcon from '@/../static/images/wallet.svg';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
WalletIcon
|
WalletIcon,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class PayoutArea extends Vue {
|
export default class PayoutArea extends Vue {
|
||||||
|
@ -475,7 +475,7 @@ export default class SNOContentFilling extends Vue {
|
|||||||
line-height: 21px;
|
line-height: 21px;
|
||||||
|
|
||||||
&__link {
|
&__link {
|
||||||
color: var(--navigation-link-color)
|
color: var(--navigation-link-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -501,7 +501,7 @@ export default class SNOContentFilling extends Vue {
|
|||||||
line-height: 21px;
|
line-height: 21px;
|
||||||
|
|
||||||
&__link {
|
&__link {
|
||||||
color: var(--navigation-link-color)
|
color: var(--navigation-link-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ export default class SNOContentTitle extends Vue {
|
|||||||
|
|
||||||
public get currentMonth(): string {
|
public get currentMonth(): string {
|
||||||
const monthNames = ['January', 'February', 'March', 'April', 'May', 'June',
|
const monthNames = ['January', 'February', 'March', 'April', 'May', 'June',
|
||||||
'July', 'August', 'September', 'October', 'November', 'December'
|
'July', 'August', 'September', 'October', 'November', 'December',
|
||||||
];
|
];
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@ class DayShowingConditions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
extends: VueChart.Line
|
extends: VueChart.Line,
|
||||||
})
|
})
|
||||||
export default class VChart extends Vue {
|
export default class VChart extends Vue {
|
||||||
@Prop({default: '$'})
|
@Prop({default: '$'})
|
||||||
private readonly currency: string;
|
private readonly currency: string;
|
||||||
@Prop({default: () => { console.error('Tooltip constructor is undefined'); }, })
|
@Prop({default: () => { console.error('Tooltip constructor is undefined'); } })
|
||||||
private tooltipConstructor: (tooltipModel) => void;
|
private tooltipConstructor: (tooltipModel) => void;
|
||||||
@Prop({default: {}})
|
@Prop({default: {}})
|
||||||
private readonly chartData: ChartData;
|
private readonly chartData: ChartData;
|
||||||
@ -69,7 +69,7 @@ export default class VChart extends Vue {
|
|||||||
radius: 0,
|
radius: 0,
|
||||||
hoverRadius: 0,
|
hoverRadius: 0,
|
||||||
hitRadius: 500,
|
hitRadius: 500,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
scales: {
|
scales: {
|
||||||
yAxes: [{
|
yAxes: [{
|
||||||
@ -80,8 +80,8 @@ export default class VChart extends Vue {
|
|||||||
},
|
},
|
||||||
gridLines: {
|
gridLines: {
|
||||||
borderDash: [2, 5],
|
borderDash: [2, 5],
|
||||||
drawBorder: false
|
drawBorder: false,
|
||||||
}
|
},
|
||||||
}],
|
}],
|
||||||
xAxes: [{
|
xAxes: [{
|
||||||
display: true,
|
display: true,
|
||||||
@ -100,7 +100,7 @@ export default class VChart extends Vue {
|
|||||||
layout: {
|
layout: {
|
||||||
padding: {
|
padding: {
|
||||||
left: 25,
|
left: 25,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
tooltips: {
|
tooltips: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
@ -111,8 +111,8 @@ export default class VChart extends Vue {
|
|||||||
|
|
||||||
labels: {
|
labels: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ import { RouteConfig } from '@/app/router';
|
|||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
SNONotification,
|
SNONotification,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
export default class NotificationsPopup extends Vue {
|
export default class NotificationsPopup extends Vue {
|
||||||
/**
|
/**
|
||||||
|
@ -39,7 +39,7 @@ const monthNames = [
|
|||||||
PayoutPeriodCalendar,
|
PayoutPeriodCalendar,
|
||||||
BlackArrowExpand,
|
BlackArrowExpand,
|
||||||
BlackArrowHide,
|
BlackArrowHide,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
export default class EstimationPeriodDropdown extends Vue {
|
export default class EstimationPeriodDropdown extends Vue {
|
||||||
/**
|
/**
|
||||||
|
@ -77,7 +77,7 @@ class MonthButton {
|
|||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
GrayArrowLeftIcon,
|
GrayArrowLeftIcon,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
export default class PayoutPeriodCalendar extends Vue {
|
export default class PayoutPeriodCalendar extends Vue {
|
||||||
private now: Date = new Date();
|
private now: Date = new Date();
|
||||||
|
@ -28,22 +28,22 @@ export const router = new Router({
|
|||||||
{
|
{
|
||||||
path: RouteConfig.Root.path,
|
path: RouteConfig.Root.path,
|
||||||
name: RouteConfig.Root.name,
|
name: RouteConfig.Root.name,
|
||||||
component: DashboardArea
|
component: DashboardArea,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: RouteConfig.Notifications.path,
|
path: RouteConfig.Notifications.path,
|
||||||
name: RouteConfig.Notifications.name,
|
name: RouteConfig.Notifications.name,
|
||||||
component: NotificationsArea
|
component: NotificationsArea,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: RouteConfig.Payout.path,
|
path: RouteConfig.Payout.path,
|
||||||
name: RouteConfig.Payout.name,
|
name: RouteConfig.Payout.name,
|
||||||
component: PayoutArea
|
component: PayoutArea,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '*',
|
path: '*',
|
||||||
name: '404',
|
name: '404',
|
||||||
component: Page404,
|
component: Page404,
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
});
|
});
|
||||||
|
@ -8,12 +8,14 @@ import { makeNotificationsModule } from '@/app/store/modules/notifications';
|
|||||||
import { makePayoutModule } from '@/app/store/modules/payout';
|
import { makePayoutModule } from '@/app/store/modules/payout';
|
||||||
import { NotificationsHttpApi } from '@/storagenode/api/notifications';
|
import { NotificationsHttpApi } from '@/storagenode/api/notifications';
|
||||||
import { PayoutHttpApi } from '@/storagenode/api/payout';
|
import { PayoutHttpApi } from '@/storagenode/api/payout';
|
||||||
|
import { SNOApi } from '@/storagenode/api/storagenode';
|
||||||
|
|
||||||
import { appStateModule } from './modules/appState';
|
import { appStateModule } from './modules/appState';
|
||||||
import { node } from './modules/node';
|
import { makeNodeModule } from './modules/node';
|
||||||
|
|
||||||
const notificationsApi = new NotificationsHttpApi();
|
const notificationsApi = new NotificationsHttpApi();
|
||||||
const payoutApi = new PayoutHttpApi();
|
const payoutApi = new PayoutHttpApi();
|
||||||
|
const nodeApi = new SNOApi();
|
||||||
|
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
|
|
||||||
@ -22,7 +24,7 @@ Vue.use(Vuex);
|
|||||||
*/
|
*/
|
||||||
export const store = new Vuex.Store({
|
export const store = new Vuex.Store({
|
||||||
modules: {
|
modules: {
|
||||||
node,
|
node: makeNodeModule(nodeApi),
|
||||||
appStateModule,
|
appStateModule,
|
||||||
notificationsModule: makeNotificationsModule(notificationsApi),
|
notificationsModule: makeNotificationsModule(notificationsApi),
|
||||||
payoutModule: makePayoutModule(payoutApi),
|
payoutModule: makePayoutModule(payoutApi),
|
||||||
|
@ -29,9 +29,9 @@ const {
|
|||||||
} = NODE_MUTATIONS;
|
} = NODE_MUTATIONS;
|
||||||
|
|
||||||
const statusThreshHoldMinutes = 120;
|
const statusThreshHoldMinutes = 120;
|
||||||
const snoAPI = new SNOApi();
|
|
||||||
|
|
||||||
export const node = {
|
export function makeNodeModule(api: SNOApi) {
|
||||||
|
return {
|
||||||
state: {
|
state: {
|
||||||
info: {
|
info: {
|
||||||
id: '',
|
id: '',
|
||||||
@ -41,7 +41,7 @@ export const node = {
|
|||||||
version: '',
|
version: '',
|
||||||
allowedVersion: '',
|
allowedVersion: '',
|
||||||
wallet: '',
|
wallet: '',
|
||||||
isLastVersion: false
|
isLastVersion: false,
|
||||||
},
|
},
|
||||||
utilization: {
|
utilization: {
|
||||||
bandwidth: {
|
bandwidth: {
|
||||||
@ -118,7 +118,7 @@ export const node = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
state.checks.audit = parseFloat(parseFloat(`${satelliteInfo.audit.score * 100}`).toFixed(1));
|
state.checks.audit = parseFloat(parseFloat(`${satelliteInfo.audit.score * 100}`).toFixed(1));
|
||||||
state.checks.uptime = satelliteInfo.uptime.totalCount ? 100 : satelliteInfo.uptime.successCount / satelliteInfo.uptime.totalCount * 100;
|
state.checks.uptime = satelliteInfo.uptime.totalCount === 0 ? 100 : satelliteInfo.uptime.successCount / satelliteInfo.uptime.totalCount * 100;
|
||||||
},
|
},
|
||||||
[SELECT_ALL_SATELLITES](state: any, satelliteInfo: Satellites): void {
|
[SELECT_ALL_SATELLITES](state: any, satelliteInfo: Satellites): void {
|
||||||
state.selectedSatellite = {
|
state.selectedSatellite = {
|
||||||
@ -139,18 +139,18 @@ export const node = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
[NODE_ACTIONS.GET_NODE_INFO]: async function ({ commit }: any): Promise<void> {
|
[NODE_ACTIONS.GET_NODE_INFO]: async function ({commit}: any): Promise<void> {
|
||||||
const response = await snoAPI.dashboard();
|
const response = await api.dashboard();
|
||||||
|
|
||||||
commit(NODE_MUTATIONS.POPULATE_STORE, response);
|
commit(NODE_MUTATIONS.POPULATE_STORE, response);
|
||||||
},
|
},
|
||||||
[NODE_ACTIONS.SELECT_SATELLITE]: async function ({ commit }, id?: string): Promise<void> {
|
[NODE_ACTIONS.SELECT_SATELLITE]: async function ({commit}, id?: string): Promise<void> {
|
||||||
let response: Satellite | Satellites;
|
let response: Satellite | Satellites;
|
||||||
if (id) {
|
if (id) {
|
||||||
response = await snoAPI.satellite(id);
|
response = await api.satellite(id);
|
||||||
commit(NODE_MUTATIONS.SELECT_SATELLITE, response);
|
commit(NODE_MUTATIONS.SELECT_SATELLITE, response);
|
||||||
} else {
|
} else {
|
||||||
response = await snoAPI.satellites();
|
response = await api.satellites();
|
||||||
commit(NODE_MUTATIONS.SELECT_ALL_SATELLITES, response);
|
commit(NODE_MUTATIONS.SELECT_ALL_SATELLITES, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,4 +166,5 @@ export const node = {
|
|||||||
return Math.ceil(differenceInSeconds / secondsInMonthApproximately);
|
return Math.ceil(differenceInSeconds / secondsInMonthApproximately);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
@ -5,8 +5,10 @@ import {
|
|||||||
HeldInfo,
|
HeldInfo,
|
||||||
PaymentInfoParameters,
|
PaymentInfoParameters,
|
||||||
PayoutApi,
|
PayoutApi,
|
||||||
PayoutInfoRange, PayoutPeriod,
|
PayoutInfoRange,
|
||||||
PayoutState, TotalPayoutInfo,
|
PayoutPeriod,
|
||||||
|
PayoutState,
|
||||||
|
TotalPayoutInfo,
|
||||||
} from '@/app/types/payout';
|
} from '@/app/types/payout';
|
||||||
import { TB } from '@/app/utils/converter';
|
import { TB } from '@/app/utils/converter';
|
||||||
|
|
||||||
@ -104,7 +106,7 @@ export function makePayoutModule(api: PayoutApi) {
|
|||||||
* Returns held percentage depends on number of months that node is online.
|
* Returns held percentage depends on number of months that node is online.
|
||||||
* @param startedAt date since node is online.
|
* @param startedAt date since node is online.
|
||||||
*/
|
*/
|
||||||
function getHeldPercentage(startedAt: Date): number {
|
export function getHeldPercentage(startedAt: Date): number {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const secondsInMonthApproximately = 2628000;
|
const secondsInMonthApproximately = 2628000;
|
||||||
const differenceInSeconds = (now.getTime() - startedAt.getTime()) / 1000;
|
const differenceInSeconds = (now.getTime() - startedAt.getTime()) / 1000;
|
||||||
|
@ -41,7 +41,7 @@ export class NotificationsHttpApi implements NotificationsApi {
|
|||||||
item.message,
|
item.message,
|
||||||
!!item.readAt,
|
!!item.readAt,
|
||||||
new Date(item.createdAt),
|
new Date(item.createdAt),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
pageCount = notificationResponse.page.pageCount;
|
pageCount = notificationResponse.page.pageCount;
|
||||||
|
@ -104,7 +104,7 @@ export class PayoutHttpApi implements PayoutApi {
|
|||||||
* @returns total payout information
|
* @returns total payout information
|
||||||
* @throws Error
|
* @throws Error
|
||||||
*/
|
*/
|
||||||
private async getHeld(path): Promise<HeldInfo> {
|
public async getHeld(path): Promise<HeldInfo> {
|
||||||
const response = await this.client.get(path);
|
const response = await this.client.get(path);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
|
26
web/storagenode/tests/unit/mock/api/payout.ts
Normal file
26
web/storagenode/tests/unit/mock/api/payout.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright (C) 2019 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
import {
|
||||||
|
HeldInfo,
|
||||||
|
PaymentInfoParameters,
|
||||||
|
PayoutApi,
|
||||||
|
TotalPayoutInfo,
|
||||||
|
} from '@/app/types/payout';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mock for PayoutApi.
|
||||||
|
*/
|
||||||
|
export class PayoutApiMock implements PayoutApi {
|
||||||
|
public getHeldInfoByMonth(paymentInfoParameters: PaymentInfoParameters): Promise<HeldInfo> {
|
||||||
|
return Promise.resolve(new HeldInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
public getHeldInfoByPeriod(paymentInfoParameters: PaymentInfoParameters): Promise<HeldInfo> {
|
||||||
|
return Promise.resolve(new HeldInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTotal(paymentInfoParameters: PaymentInfoParameters): Promise<TotalPayoutInfo> {
|
||||||
|
return Promise.resolve(new TotalPayoutInfo());
|
||||||
|
}
|
||||||
|
}
|
17
web/storagenode/tests/unit/mock/svgTransform.js
Normal file
17
web/storagenode/tests/unit/mock/svgTransform.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (C) 2019 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
const vueJest = require('vue-jest/lib/template-compiler');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
process(content) {
|
||||||
|
const { render } = vueJest({
|
||||||
|
content,
|
||||||
|
attrs: {
|
||||||
|
functional: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return `module.exports = { render: ${render} }`;
|
||||||
|
},
|
||||||
|
};
|
182
web/storagenode/tests/unit/store/payout.spec.ts
Normal file
182
web/storagenode/tests/unit/store/payout.spec.ts
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
// Copyright (C) 2020 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
import Vuex from 'vuex';
|
||||||
|
|
||||||
|
import { makeNodeModule } from '@/app/store/modules/node';
|
||||||
|
import { getHeldPercentage, makePayoutModule, PAYOUT_ACTIONS, PAYOUT_MUTATIONS } from '@/app/store/modules/payout';
|
||||||
|
import { HeldInfo, PayoutInfoRange, PayoutPeriod, TotalPayoutInfo } from '@/app/types/payout';
|
||||||
|
import { PayoutHttpApi } from '@/storagenode/api/payout';
|
||||||
|
import { SNOApi } from '@/storagenode/api/storagenode';
|
||||||
|
import { createLocalVue } from '@vue/test-utils';
|
||||||
|
|
||||||
|
const Vue = createLocalVue();
|
||||||
|
const payoutApi = new PayoutHttpApi();
|
||||||
|
const payoutModule = makePayoutModule(payoutApi);
|
||||||
|
|
||||||
|
const nodeApi = new SNOApi();
|
||||||
|
const nodeModule = makeNodeModule(nodeApi);
|
||||||
|
|
||||||
|
Vue.use(Vuex);
|
||||||
|
|
||||||
|
const store = new Vuex.Store({ modules: { payoutModule, node: nodeModule } });
|
||||||
|
|
||||||
|
const state = store.state as any;
|
||||||
|
|
||||||
|
describe('mutations', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
createLocalVue().use(Vuex);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets held information', () => {
|
||||||
|
const heldInfo = new HeldInfo(13, 12, 11);
|
||||||
|
|
||||||
|
store.commit(PAYOUT_MUTATIONS.SET_HELD_INFO, heldInfo);
|
||||||
|
|
||||||
|
expect(state.payoutModule.heldInfo.usageAtRest).toBe(13);
|
||||||
|
expect(state.payoutModule.heldInfo.usageGet).toBe(12);
|
||||||
|
expect(state.payoutModule.heldInfo.usagePut).toBe(11);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets total payout information', () => {
|
||||||
|
const totalInfo = new TotalPayoutInfo(50, 100);
|
||||||
|
|
||||||
|
store.commit(PAYOUT_MUTATIONS.SET_TOTAL, totalInfo);
|
||||||
|
|
||||||
|
expect(state.payoutModule.totalHeldAmount).toBe(50);
|
||||||
|
expect(state.payoutModule.totalEarnings).toBe(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets period range', () => {
|
||||||
|
const range = new PayoutInfoRange(new PayoutPeriod(2019, 2), new PayoutPeriod(2020, 3));
|
||||||
|
|
||||||
|
store.commit(PAYOUT_MUTATIONS.SET_RANGE, range);
|
||||||
|
|
||||||
|
if (!state.payoutModule.periodRange.start) {
|
||||||
|
fail('periodRange.start is null');
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(state.payoutModule.periodRange.start.period).toBe('2019-03');
|
||||||
|
expect(state.payoutModule.periodRange.end.period).toBe('2020-04');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets held percentage', () => {
|
||||||
|
const expectedHeldPercentage = 75;
|
||||||
|
|
||||||
|
store.commit(PAYOUT_MUTATIONS.SET_HELD_PERCENT, expectedHeldPercentage);
|
||||||
|
|
||||||
|
expect(state.payoutModule.heldPercentage).toBe(expectedHeldPercentage);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('actions', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.resetAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('success get held info by month', async () => {
|
||||||
|
jest.spyOn(payoutApi, 'getHeldInfoByMonth').mockReturnValue(
|
||||||
|
Promise.resolve(new HeldInfo(1, 2 , 3, 4, 5)),
|
||||||
|
);
|
||||||
|
|
||||||
|
const range = new PayoutInfoRange(null, new PayoutPeriod(2020, 3));
|
||||||
|
|
||||||
|
store.commit(PAYOUT_MUTATIONS.SET_RANGE, range);
|
||||||
|
|
||||||
|
await store.dispatch(PAYOUT_ACTIONS.GET_HELD_INFO);
|
||||||
|
|
||||||
|
expect(state.payoutModule.heldInfo.usagePut).toBe(3);
|
||||||
|
expect(state.payoutModule.heldInfo.held).toBe(0);
|
||||||
|
expect(state.payoutModule.heldPercentage).toBe(getHeldPercentage(new Date()));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('get held info by month throws an error when api call fails', async () => {
|
||||||
|
jest.spyOn(payoutApi, 'getHeldInfoByMonth').mockImplementation(() => { throw new Error(); });
|
||||||
|
|
||||||
|
try {
|
||||||
|
await store.dispatch(PAYOUT_ACTIONS.GET_HELD_INFO);
|
||||||
|
expect(true).toBe(false);
|
||||||
|
} catch (error) {
|
||||||
|
expect(state.payoutModule.heldInfo.usagePut).toBe(3);
|
||||||
|
expect(state.payoutModule.heldInfo.held).toBe(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('success get held info by period', async () => {
|
||||||
|
jest.spyOn(payoutApi, 'getHeldInfoByPeriod').mockReturnValue(
|
||||||
|
Promise.resolve(new HeldInfo(1, 2 , 3, 4, 5)),
|
||||||
|
);
|
||||||
|
|
||||||
|
const range = new PayoutInfoRange(new PayoutPeriod(2019, 2), new PayoutPeriod(2020, 3));
|
||||||
|
|
||||||
|
store.commit(PAYOUT_MUTATIONS.SET_RANGE, range);
|
||||||
|
|
||||||
|
await store.dispatch(PAYOUT_ACTIONS.GET_HELD_INFO);
|
||||||
|
|
||||||
|
expect(state.payoutModule.heldInfo.usagePut).toBe(3);
|
||||||
|
expect(state.payoutModule.heldInfo.held).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('get held info by period throws an error when api call fails', async () => {
|
||||||
|
jest.spyOn(payoutApi, 'getHeldInfoByPeriod').mockImplementation(() => { throw new Error(); });
|
||||||
|
|
||||||
|
try {
|
||||||
|
await store.dispatch(PAYOUT_ACTIONS.GET_HELD_INFO);
|
||||||
|
expect(true).toBe(false);
|
||||||
|
} catch (error) {
|
||||||
|
expect(state.payoutModule.heldInfo.usagePut).toBe(3);
|
||||||
|
expect(state.payoutModule.heldInfo.held).toBe(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('success get total', async () => {
|
||||||
|
jest.spyOn(payoutApi, 'getTotal').mockReturnValue(
|
||||||
|
Promise.resolve(new TotalPayoutInfo(10, 20)),
|
||||||
|
);
|
||||||
|
|
||||||
|
await store.dispatch(PAYOUT_ACTIONS.GET_TOTAL);
|
||||||
|
|
||||||
|
expect(state.payoutModule.totalHeldAmount).toBe(10);
|
||||||
|
expect(state.payoutModule.totalEarnings).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('get total throws an error when api call fails', async () => {
|
||||||
|
jest.spyOn(payoutApi, 'getTotal').mockImplementation(() => { throw new Error(); });
|
||||||
|
|
||||||
|
try {
|
||||||
|
await store.dispatch(PAYOUT_ACTIONS.GET_TOTAL);
|
||||||
|
expect(true).toBe(false);
|
||||||
|
} catch (error) {
|
||||||
|
expect(state.payoutModule.totalHeldAmount).toBe(10);
|
||||||
|
expect(state.payoutModule.totalEarnings).toBe(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('success sets period range', async () => {
|
||||||
|
await store.dispatch(
|
||||||
|
PAYOUT_ACTIONS.SET_PERIODS_RANGE,
|
||||||
|
new PayoutInfoRange(
|
||||||
|
new PayoutPeriod(2020, 1),
|
||||||
|
new PayoutPeriod(2020, 2),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(state.payoutModule.periodRange.start.period).toBe('2020-02');
|
||||||
|
expect(state.payoutModule.periodRange.end.period).toBe('2020-03');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('utils functions', () => {
|
||||||
|
it('get correct help percentage', () => {
|
||||||
|
const nowTime = new Date().getTime();
|
||||||
|
const testDifferencesInMilliseconds: number[] = [5e9, 1.4e10, 2.3e10, 4e10];
|
||||||
|
const expectedHeldPercentages: number[] = [75, 50, 25, 0];
|
||||||
|
|
||||||
|
for (let i = 0; i < testDifferencesInMilliseconds.length; i++) {
|
||||||
|
const date = new Date(nowTime - testDifferencesInMilliseconds[i]);
|
||||||
|
const heldPercentage = getHeldPercentage(date);
|
||||||
|
|
||||||
|
expect(heldPercentage).toBe(expectedHeldPercentages[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@ -14,7 +14,8 @@
|
|||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"strictPropertyInitialization": false,
|
"strictPropertyInitialization": false,
|
||||||
"types": [
|
"types": [
|
||||||
"webpack-env"
|
"webpack-env",
|
||||||
|
"jest"
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": [
|
"@/*": [
|
||||||
@ -32,7 +33,9 @@
|
|||||||
"src/**/*.ts",
|
"src/**/*.ts",
|
||||||
"src/**/*.tsx",
|
"src/**/*.tsx",
|
||||||
"src/**/*.vue",
|
"src/**/*.vue",
|
||||||
"src/app/types/svg.d.ts"
|
"src/app/types/svg.d.ts",
|
||||||
|
"tests/**/*.ts",
|
||||||
|
"tests/**/*.tsx"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
|
@ -35,7 +35,9 @@
|
|||||||
"no-eval": true,
|
"no-eval": true,
|
||||||
"no-invalid-template-strings": true,
|
"no-invalid-template-strings": true,
|
||||||
"no-invalid-this": true,
|
"no-invalid-this": true,
|
||||||
|
"no-misused-new": true,
|
||||||
"no-static-this": true,
|
"no-static-this": true,
|
||||||
|
"no-trailing-whitespace": true,
|
||||||
"no-var-keyword": true,
|
"no-var-keyword": true,
|
||||||
"newline-before-return": true,
|
"newline-before-return": true,
|
||||||
"object-literal-sort-keys": false,
|
"object-literal-sort-keys": false,
|
||||||
@ -64,11 +66,14 @@
|
|||||||
}]
|
}]
|
||||||
}],
|
}],
|
||||||
"prefer-const": true,
|
"prefer-const": true,
|
||||||
|
"prefer-method-signature": true,
|
||||||
"prefer-switch": [true, {"min-cases": 2}],
|
"prefer-switch": [true, {"min-cases": 2}],
|
||||||
"prefer-while": true,
|
"prefer-while": true,
|
||||||
"quotemark": [true, "single", "avoid-escape"],
|
"quotemark": [true, "single", "avoid-escape"],
|
||||||
"semicolon": [true, "always"],
|
"semicolon": [true, "always"],
|
||||||
|
"space-within-parens": 0,
|
||||||
"static-this": true,
|
"static-this": true,
|
||||||
|
"trailing-comma": [true, {"multiline": "always", "singleline": "never"}],
|
||||||
"triple-equals": true,
|
"triple-equals": true,
|
||||||
"typedef": [
|
"typedef": [
|
||||||
true,
|
true,
|
||||||
@ -80,11 +85,13 @@
|
|||||||
true,
|
true,
|
||||||
"check-branch",
|
"check-branch",
|
||||||
"check-decl",
|
"check-decl",
|
||||||
"check-operator",
|
|
||||||
"check-module",
|
"check-module",
|
||||||
|
"check-operator",
|
||||||
|
"check-preblock",
|
||||||
|
"check-rest-spread",
|
||||||
"check-separator",
|
"check-separator",
|
||||||
"check-type-operator",
|
"check-type",
|
||||||
"check-preblock"
|
"check-type-operator"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user