web/satellite: project limits
Change-Id: Ia9c3ee9b5bc3dc1bc03e613c8715d299fce569dc
This commit is contained in:
parent
ab777e823e
commit
11db709066
@ -2,9 +2,14 @@
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import { BaseGql } from '@/api/baseGql';
|
||||
import { CreateProjectModel, Project, ProjectsApi } from '@/types/projects';
|
||||
import { ErrorUnauthorized } from '@/api/errors/ErrorUnauthorized';
|
||||
import { CreateProjectModel, Project, ProjectLimits, ProjectsApi } from '@/types/projects';
|
||||
import { HttpClient } from '@/utils/httpClient';
|
||||
|
||||
export class ProjectsApiGql extends BaseGql implements ProjectsApi {
|
||||
private readonly http: HttpClient = new HttpClient();
|
||||
private readonly ROOT_PATH: string = '/api/v0/projects';
|
||||
|
||||
/**
|
||||
* Creates project
|
||||
*
|
||||
@ -51,7 +56,15 @@ export class ProjectsApiGql extends BaseGql implements ProjectsApi {
|
||||
|
||||
const response = await this.query(query);
|
||||
|
||||
return response.data.myProjects;
|
||||
return response.data.myProjects.map((project: Project) => {
|
||||
return new Project(
|
||||
project.id,
|
||||
project.name,
|
||||
project.description,
|
||||
project.createdAt,
|
||||
project.ownerId,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,4 +112,32 @@ export class ProjectsApiGql extends BaseGql implements ProjectsApi {
|
||||
|
||||
await this.mutate(query, variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get project limits
|
||||
*
|
||||
* @param projectId- project ID
|
||||
* throws Error
|
||||
*/
|
||||
public async getLimits(projectId): Promise<ProjectLimits> {
|
||||
const path = `${this.ROOT_PATH}/${projectId}/usage-limits`;
|
||||
const response = await this.http.get(path, true);
|
||||
|
||||
if (response.ok) {
|
||||
const limits = await response.json();
|
||||
|
||||
return new ProjectLimits(
|
||||
limits.bandwidthLimit,
|
||||
limits.bandwidthUsed,
|
||||
limits.storageLimit,
|
||||
limits.storageUsed,
|
||||
);
|
||||
}
|
||||
|
||||
if (response.status === 401) {
|
||||
throw new ErrorUnauthorized();
|
||||
}
|
||||
|
||||
throw new Error('can not get usage limits');
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,18 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project-details-info-container">
|
||||
<ProjectLimitsArea />
|
||||
</div>
|
||||
<p class="project-details__limits-increase-text">
|
||||
To increase your limits please contact us at
|
||||
<a
|
||||
href="mailto:support@tardigrade.io"
|
||||
class="project-details__limits-increase-text__link"
|
||||
>
|
||||
support@tardigrade.io
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -60,6 +72,7 @@ import EmptyState from '@/components/common/EmptyStateArea.vue';
|
||||
import HeaderedInput from '@/components/common/HeaderedInput.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
import DeleteProjectPopup from '@/components/project/DeleteProjectPopup.vue';
|
||||
import ProjectLimitsArea from '@/components/project/ProjectLimitsArea.vue';
|
||||
|
||||
import EditIcon from '@/../static/images/project/edit.svg';
|
||||
|
||||
@ -77,6 +90,7 @@ import { LocalData } from '@/utils/localData';
|
||||
EmptyState,
|
||||
DeleteProjectPopup,
|
||||
EditIcon,
|
||||
ProjectLimitsArea,
|
||||
},
|
||||
})
|
||||
export default class ProjectDetailsArea extends Vue {
|
||||
@ -174,6 +188,18 @@ export default class ProjectDetailsArea extends Vue {
|
||||
margin-top: 3vh;
|
||||
margin-bottom: 100px;
|
||||
}
|
||||
|
||||
&__limits-increase-text {
|
||||
font-family: 'font_regular', sans-serif;
|
||||
font-size: 16px;
|
||||
color: #afb7c1;
|
||||
margin-top: 42px;
|
||||
|
||||
&__link {
|
||||
text-decoration: underline;
|
||||
color: #2683ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.project-details-info-container {
|
||||
|
118
web/satellite/src/components/project/ProjectLimitsArea.vue
Normal file
118
web/satellite/src/components/project/ProjectLimitsArea.vue
Normal file
@ -0,0 +1,118 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="limits-container">
|
||||
<div class="limits-container__item">
|
||||
<p class="limits-container__item__title">Egress limits used</p>
|
||||
<div class="limits-container__item__values-container">
|
||||
<p class="limits-container__item__values-container__remaining">{{ bandwidthUsed }}</p>
|
||||
<p class="limits-container__item__values-container__total">/ {{ bandwidthLimit }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="limits-container__item">
|
||||
<p class="limits-container__item__title">Storage limits used</p>
|
||||
<div class="limits-container__item__values-container">
|
||||
<p class="limits-container__item__values-container__remaining">{{ storageUsed }}</p>
|
||||
<p class="limits-container__item__values-container__total">/ {{ storageLimit }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
|
||||
import { Dimensions, Size } from '@/utils/bytesSize';
|
||||
|
||||
@Component
|
||||
export default class ProjectLimitsArea extends Vue {
|
||||
public async mounted() {
|
||||
await this.$store.dispatch(PROJECTS_ACTIONS.GET_LIMITS, this.$store.getters.selectedProject.id);
|
||||
}
|
||||
|
||||
public get bandwidthUsed(): string {
|
||||
const bandwidthUsed = new Size(this.$store.getters.selectedProject.limits.bandwidthUsed);
|
||||
|
||||
return this.getFormattedLimit(bandwidthUsed);
|
||||
}
|
||||
|
||||
public get bandwidthLimit(): string {
|
||||
const bandwidthLimit = new Size(this.$store.getters.selectedProject.limits.bandwidthLimit);
|
||||
|
||||
return this.getFormattedLimit(bandwidthLimit);
|
||||
}
|
||||
|
||||
public get storageUsed(): string {
|
||||
const storageUsed = new Size(this.$store.getters.selectedProject.limits.storageUsed);
|
||||
|
||||
return this.getFormattedLimit(storageUsed);
|
||||
}
|
||||
|
||||
public get storageLimit(): string {
|
||||
const storageLimit = new Size(this.$store.getters.selectedProject.limits.storageLimit);
|
||||
|
||||
return this.getFormattedLimit(storageLimit);
|
||||
}
|
||||
|
||||
private getFormattedLimit(limit: Size): string {
|
||||
switch (limit.label) {
|
||||
case Dimensions.Bytes:
|
||||
case Dimensions.KB:
|
||||
return '0';
|
||||
default:
|
||||
return `${limit.formattedBytes.replace(/\\.0+$/, '')} ${limit.label}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.limits-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
&__item {
|
||||
padding: 37px 28px;
|
||||
width: calc(49% - 56px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
background-color: #fff;
|
||||
border-radius: 6px;
|
||||
|
||||
&__title {
|
||||
font-family: 'font_regular', sans-serif;
|
||||
font-size: 16px;
|
||||
text-align: left;
|
||||
color: #afb7c1;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__values-container {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
margin-top: 10px;
|
||||
|
||||
&__remaining {
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-size: 36px;
|
||||
color: #39464f;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__total {
|
||||
font-family: 'font_medium', sans-serif;
|
||||
font-size: 36px;
|
||||
color: #afb7c1;
|
||||
margin: 0 0 0 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -2,7 +2,7 @@
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import { StoreModule } from '@/store';
|
||||
import { CreateProjectModel, Project, ProjectsApi, UpdateProjectModel } from '@/types/projects';
|
||||
import { CreateProjectModel, Project, ProjectLimits, ProjectsApi, UpdateProjectModel } from '@/types/projects';
|
||||
|
||||
export const PROJECTS_ACTIONS = {
|
||||
FETCH: 'fetchProjects',
|
||||
@ -11,6 +11,7 @@ export const PROJECTS_ACTIONS = {
|
||||
UPDATE: 'updateProject',
|
||||
DELETE: 'deleteProject',
|
||||
CLEAR: 'clearProjects',
|
||||
GET_LIMITS: 'getProjectLimits',
|
||||
};
|
||||
|
||||
export const PROJECTS_MUTATIONS = {
|
||||
@ -20,6 +21,7 @@ export const PROJECTS_MUTATIONS = {
|
||||
SET_PROJECTS: 'SET_PROJECTS',
|
||||
SELECT_PROJECT: 'SELECT_PROJECT',
|
||||
CLEAR_PROJECTS: 'CLEAR_PROJECTS',
|
||||
SET_LIMITS: 'SET_PROJECT_LIMITS',
|
||||
};
|
||||
|
||||
const defaultSelectedProject = new Project('', '', '', '', '', true);
|
||||
@ -36,6 +38,7 @@ const {
|
||||
UPDATE,
|
||||
DELETE,
|
||||
CLEAR,
|
||||
GET_LIMITS,
|
||||
} = PROJECTS_ACTIONS;
|
||||
|
||||
const {
|
||||
@ -45,6 +48,7 @@ const {
|
||||
SET_PROJECTS,
|
||||
SELECT_PROJECT,
|
||||
CLEAR_PROJECTS,
|
||||
SET_LIMITS,
|
||||
} = PROJECTS_MUTATIONS;
|
||||
|
||||
export function makeProjectsModule(api: ProjectsApi): StoreModule<ProjectsState> {
|
||||
@ -101,17 +105,26 @@ export function makeProjectsModule(api: ProjectsApi): StoreModule<ProjectsState>
|
||||
state.selectedProject = new Project();
|
||||
}
|
||||
},
|
||||
[SET_LIMITS](state: ProjectsState, limits: ProjectLimits): void {
|
||||
state.selectedProject.setLimits(limits);
|
||||
},
|
||||
[CLEAR_PROJECTS](state: ProjectsState): void {
|
||||
state.projects = [];
|
||||
state.selectedProject = defaultSelectedProject;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
[FETCH]: async function ({commit}: any): Promise<Project[]> {
|
||||
[FETCH]: async function ({commit, state}: any): Promise<Project[]> {
|
||||
const projects = await api.get();
|
||||
|
||||
commit(SET_PROJECTS, projects);
|
||||
|
||||
if (state.selectedProject.id) {
|
||||
const limits = await api.getLimits(state.selectedProject.id);
|
||||
|
||||
commit(SET_LIMITS, limits);
|
||||
}
|
||||
|
||||
return projects;
|
||||
},
|
||||
[CREATE]: async function ({commit}: any, createProjectModel: CreateProjectModel): Promise<Project> {
|
||||
@ -121,8 +134,12 @@ export function makeProjectsModule(api: ProjectsApi): StoreModule<ProjectsState>
|
||||
|
||||
return project;
|
||||
},
|
||||
[SELECT]: function ({commit}: any, projectID: string): void {
|
||||
[SELECT]: async function ({commit}: any, projectID: string): Promise<void> {
|
||||
commit(SELECT_PROJECT, projectID);
|
||||
|
||||
const limits = await api.getLimits(projectID);
|
||||
|
||||
commit(SET_LIMITS, limits);
|
||||
},
|
||||
[UPDATE]: async function ({commit}: any, updateProjectModel: UpdateProjectModel): Promise<void> {
|
||||
await api.update(updateProjectModel.id, updateProjectModel.description);
|
||||
@ -134,6 +151,13 @@ export function makeProjectsModule(api: ProjectsApi): StoreModule<ProjectsState>
|
||||
|
||||
commit(REMOVE, projectID);
|
||||
},
|
||||
[GET_LIMITS]: async function ({commit}: any, projectID: string): Promise<ProjectLimits> {
|
||||
const limits = await api.getLimits(projectID);
|
||||
|
||||
commit(SET_LIMITS, limits);
|
||||
|
||||
return limits;
|
||||
},
|
||||
[CLEAR]: function({commit}: any): void {
|
||||
commit(CLEAR_PROJECTS);
|
||||
},
|
||||
|
@ -35,26 +35,30 @@ export interface ProjectsApi {
|
||||
* @throws Error
|
||||
*/
|
||||
delete(projectId: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Get project limits
|
||||
*
|
||||
* @param projectId- project ID
|
||||
* throws Error
|
||||
*/
|
||||
getLimits(projectId: string): Promise<ProjectLimits>;
|
||||
}
|
||||
|
||||
// Project is a type, used for creating new project in backend
|
||||
export class Project {
|
||||
public id: string;
|
||||
public constructor(
|
||||
public id: string = '',
|
||||
public name: string = '',
|
||||
public description: string = '',
|
||||
public createdAt: string = '',
|
||||
public ownerId: string = '',
|
||||
public isSelected: boolean = false,
|
||||
public limits: ProjectLimits = new ProjectLimits(),
|
||||
) {}
|
||||
|
||||
public name: string;
|
||||
public description: string;
|
||||
public createdAt: string;
|
||||
public ownerId: string;
|
||||
|
||||
public isSelected: boolean;
|
||||
|
||||
public constructor(id: string = '', name: string = '', description: string = '', createdAt: string = '', ownerId: string = '', isSelected: boolean = false) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.createdAt = createdAt;
|
||||
this.isSelected = isSelected;
|
||||
this.ownerId = ownerId;
|
||||
public setLimits(limits: ProjectLimits): void {
|
||||
this.limits = limits;
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,3 +78,12 @@ export class CreateProjectModel {
|
||||
public name: string;
|
||||
public description: string;
|
||||
}
|
||||
|
||||
export class ProjectLimits {
|
||||
constructor(
|
||||
public bandwidthLimit = 0,
|
||||
public bandwidthUsed = 0,
|
||||
public storageLimit = 0,
|
||||
public storageUsed = 0,
|
||||
) {}
|
||||
}
|
||||
|
@ -12,8 +12,8 @@ export class ProjectUsage {
|
||||
public before: Date;
|
||||
|
||||
public constructor(storage: number, egress: number, objectCount: number, since: Date, before: Date) {
|
||||
this.storage = new Size(storage);
|
||||
this.egress = new Size(egress);
|
||||
this.storage = new Size(storage, 4);
|
||||
this.egress = new Size(egress, 4);
|
||||
this.objectCount = objectCount;
|
||||
this.since = since;
|
||||
this.before = before;
|
||||
|
@ -10,7 +10,7 @@ enum Memory {
|
||||
PB = 1e15,
|
||||
}
|
||||
|
||||
enum Dimensions {
|
||||
export enum Dimensions {
|
||||
Bytes = 'Bytes',
|
||||
KB = 'KB',
|
||||
MB = 'MB',
|
||||
@ -20,14 +20,15 @@ enum Dimensions {
|
||||
}
|
||||
|
||||
export class Size {
|
||||
private readonly precision: number = 4;
|
||||
private readonly precision: number;
|
||||
public readonly bytes: number;
|
||||
public readonly formattedBytes: string;
|
||||
public readonly label: Dimensions;
|
||||
|
||||
public constructor(bytes: number) {
|
||||
public constructor(bytes: number, precision: number = 0) {
|
||||
const _bytes = Math.ceil(bytes);
|
||||
this.bytes = bytes;
|
||||
this.precision = precision;
|
||||
|
||||
switch (true) {
|
||||
case _bytes === 0:
|
||||
|
@ -6,7 +6,7 @@ import Vuex from 'vuex';
|
||||
import NavigationArea from '@/components/navigation/NavigationArea.vue';
|
||||
|
||||
import { RouteConfig } from '@/router';
|
||||
import { makeProjectsModule } from '@/store/modules/projects';
|
||||
import { makeProjectsModule, PROJECTS_MUTATIONS } from '@/store/modules/projects';
|
||||
import { NavigationLink } from '@/types/navigation';
|
||||
import { Project } from '@/types/projects';
|
||||
import { createLocalVue, shallowMount } from '@vue/test-utils';
|
||||
@ -51,7 +51,7 @@ describe('NavigationArea', () => {
|
||||
|
||||
it('snapshot not changed with project', async () => {
|
||||
const projects = await store.dispatch('fetchProjects');
|
||||
await store.dispatch('selectProject', projects[0].id);
|
||||
store.commit(PROJECTS_MUTATIONS.SELECT_PROJECT, projects[0].id);
|
||||
|
||||
const wrapper = shallowMount(NavigationArea, {
|
||||
store,
|
||||
|
@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import ProjectLimitsArea from '@/components/project/ProjectLimitsArea.vue';
|
||||
|
||||
import { makeProjectsModule } from '@/store/modules/projects';
|
||||
import { createLocalVue, shallowMount } from '@vue/test-utils';
|
||||
|
||||
import { ProjectsApiMock } from '../../mock/api/projects';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
const projectsApi = new ProjectsApiMock();
|
||||
const projectsModule = makeProjectsModule(projectsApi);
|
||||
const store = new Vuex.Store({ modules: { projectsModule }});
|
||||
|
||||
describe('ProjectLimitsArea', () => {
|
||||
it('snapshot not changed', () => {
|
||||
const wrapper = shallowMount(ProjectLimitsArea, {
|
||||
store,
|
||||
localVue,
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,20 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ProjectLimitsArea snapshot not changed 1`] = `
|
||||
<div class="limits-container">
|
||||
<div class="limits-container__item">
|
||||
<p class="limits-container__item__title">Egress limits used</p>
|
||||
<div class="limits-container__item__values-container">
|
||||
<p class="limits-container__item__values-container__remaining">0</p>
|
||||
<p class="limits-container__item__values-container__total">/ 0</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="limits-container__item">
|
||||
<p class="limits-container__item__title">Storage limits used</p>
|
||||
<div class="limits-container__item__values-container">
|
||||
<p class="limits-container__item__values-container__remaining">0</p>
|
||||
<p class="limits-container__item__values-container__total">/ 0</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -1,18 +1,23 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import { CreateProjectModel, Project, ProjectsApi } from '@/types/projects';
|
||||
import { CreateProjectModel, Project, ProjectLimits, ProjectsApi } from '@/types/projects';
|
||||
|
||||
/**
|
||||
* Mock for ProjectsApi
|
||||
*/
|
||||
export class ProjectsApiMock implements ProjectsApi {
|
||||
private mockProjects: Project[];
|
||||
private mockLimits: ProjectLimits;
|
||||
|
||||
public setMockProjects(mockProjects: Project[]): void {
|
||||
this.mockProjects = mockProjects;
|
||||
}
|
||||
|
||||
public setMockLimits(mockLimits: ProjectLimits): void {
|
||||
this.mockLimits = mockLimits;
|
||||
}
|
||||
|
||||
create(createProjectModel: CreateProjectModel): Promise<Project> {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
@ -28,4 +33,8 @@ export class ProjectsApiMock implements ProjectsApi {
|
||||
update(projectId: string, description: string): Promise<void> {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
getLimits(projectId: string): Promise<ProjectLimits> {
|
||||
throw Promise.resolve(this.mockLimits);
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,13 @@ import Vuex from 'vuex';
|
||||
|
||||
import { ProjectsApiGql } from '@/api/projects';
|
||||
import { makeProjectsModule, PROJECTS_ACTIONS, PROJECTS_MUTATIONS } from '@/store/modules/projects';
|
||||
import { Project } from '@/types/projects';
|
||||
import { Project, ProjectLimits } from '@/types/projects';
|
||||
import { createLocalVue } from '@vue/test-utils';
|
||||
|
||||
const Vue = createLocalVue();
|
||||
const projectsApi = new ProjectsApiGql();
|
||||
const { FETCH, CREATE, SELECT, DELETE, CLEAR, UPDATE } = PROJECTS_ACTIONS;
|
||||
const { ADD, SET_PROJECTS, SELECT_PROJECT, UPDATE_PROJECT, REMOVE, CLEAR_PROJECTS } = PROJECTS_MUTATIONS;
|
||||
const { FETCH, CREATE, SELECT, DELETE, CLEAR, UPDATE, GET_LIMITS } = PROJECTS_ACTIONS;
|
||||
const { ADD, SET_PROJECTS, SELECT_PROJECT, UPDATE_PROJECT, REMOVE, CLEAR_PROJECTS, SET_LIMITS } = PROJECTS_MUTATIONS;
|
||||
|
||||
const projectsModule = makeProjectsModule(projectsApi);
|
||||
const selectedProject = new Project('1', '', '', '');
|
||||
@ -24,10 +24,28 @@ const store = new Vuex.Store({ modules: { projectsModule } });
|
||||
const state = (store.state as any).projectsModule;
|
||||
|
||||
const projects = [
|
||||
new Project('11', 'name', 'descr', '23', 'testOwnerId'),
|
||||
new Project('1', 'name2', 'descr2', '24', 'testOwnerId1'),
|
||||
new Project(
|
||||
'11',
|
||||
'name',
|
||||
'descr',
|
||||
'23',
|
||||
'testOwnerId',
|
||||
false,
|
||||
new ProjectLimits(1, 2, 3, 4),
|
||||
),
|
||||
new Project(
|
||||
'1',
|
||||
'name2',
|
||||
'descr2',
|
||||
'24',
|
||||
'testOwnerId1',
|
||||
false,
|
||||
new ProjectLimits(5, 6, 7, 8),
|
||||
),
|
||||
];
|
||||
|
||||
const limits = new ProjectLimits(15, 12, 14, 13);
|
||||
|
||||
const project = new Project('11', 'name', 'descr', '23', 'testOwnerId');
|
||||
|
||||
describe('mutations', () => {
|
||||
@ -58,6 +76,7 @@ describe('mutations', () => {
|
||||
|
||||
store.commit(SELECT_PROJECT, '11');
|
||||
expect(state.selectedProject.id).toBe('11');
|
||||
expect(state.selectedProject.limits.bandwidthLimit).toBe(1);
|
||||
});
|
||||
|
||||
it('update project', () => {
|
||||
@ -79,6 +98,17 @@ describe('mutations', () => {
|
||||
expect(state.projects[0].id).toBe('1');
|
||||
});
|
||||
|
||||
it('set limits', () => {
|
||||
state.projects = projects;
|
||||
|
||||
store.commit(SET_LIMITS, limits);
|
||||
|
||||
expect(state.selectedProject.limits.bandwidthUsed).toBe(12);
|
||||
expect(state.selectedProject.limits.bandwidthLimit).toBe(15);
|
||||
expect(state.selectedProject.limits.storageUsed).toBe(13);
|
||||
expect(state.selectedProject.limits.storageLimit).toBe(14);
|
||||
});
|
||||
|
||||
it('clear projects', () => {
|
||||
state.projects = projects;
|
||||
|
||||
@ -112,6 +142,7 @@ describe('actions', () => {
|
||||
await store.dispatch(FETCH);
|
||||
} catch (error) {
|
||||
expect(state.projects.length).toBe(0);
|
||||
expect(state.selectedProject.limits.bandwidthLimit).toBe(0);
|
||||
}
|
||||
});
|
||||
|
||||
@ -123,6 +154,7 @@ describe('actions', () => {
|
||||
|
||||
await store.dispatch(CREATE, {name: '', description: ''});
|
||||
expect(state.projects.length).toBe(1);
|
||||
expect(state.selectedProject.limits.bandwidthLimit).toBe(0);
|
||||
});
|
||||
|
||||
it('create throws an error when create api call fails', async () => {
|
||||
@ -134,6 +166,7 @@ describe('actions', () => {
|
||||
expect(true).toBe(false);
|
||||
} catch (error) {
|
||||
expect(state.projects.length).toBe(0);
|
||||
expect(state.selectedProject.limits.bandwidthLimit).toBe(0);
|
||||
}
|
||||
});
|
||||
|
||||
@ -169,6 +202,7 @@ describe('actions', () => {
|
||||
store.dispatch(SELECT, '1');
|
||||
|
||||
expect(state.selectedProject.id).toEqual('1');
|
||||
expect(state.selectedProject.limits.bandwidthLimit).toBe(5);
|
||||
});
|
||||
|
||||
it('success update project', async () => {
|
||||
@ -198,6 +232,21 @@ describe('actions', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('success get project limits', async () => {
|
||||
jest.spyOn(projectsApi, 'getLimits').mockReturnValue(
|
||||
Promise.resolve(limits),
|
||||
);
|
||||
|
||||
state.projects = projects;
|
||||
|
||||
await store.dispatch(GET_LIMITS, state.selectedProject.id);
|
||||
|
||||
expect(state.selectedProject.limits.bandwidthUsed).toBe(12);
|
||||
expect(state.selectedProject.limits.bandwidthLimit).toBe(15);
|
||||
expect(state.selectedProject.limits.storageUsed).toBe(13);
|
||||
expect(state.selectedProject.limits.storageLimit).toBe(14);
|
||||
});
|
||||
|
||||
it('success clearProjects', () => {
|
||||
state.projects = projects;
|
||||
store.dispatch(CLEAR);
|
||||
|
Loading…
Reference in New Issue
Block a user