web/satellite: migrate ProjectMemberListItem component to use SFC composition api

Change-Id: I232f06b5828c9f93917070621de66463c479d8fe
This commit is contained in:
Vitalii 2023-04-04 16:34:39 +03:00 committed by Vitalii Shpital
parent d0620405e5
commit a5d9caa5a5
2 changed files with 185 additions and 19 deletions

View File

@ -13,33 +13,34 @@
/> />
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { Component, Prop } from 'vue-property-decorator'; import { computed } from 'vue';
import { ProjectMember } from '@/types/projectMembers'; import { ProjectMember } from '@/types/projectMembers';
import { useResize } from '@/composables/resize';
import { useStore } from '@/utils/hooks';
import TableItem from '@/components/common/TableItem.vue'; import TableItem from '@/components/common/TableItem.vue';
import Resizable from '@/components/common/Resizable.vue';
// @vue/component const { isMobile, isTablet } = useResize();
@Component({ const store = useStore();
components: { TableItem },
})
export default class ProjectMemberListItem extends Resizable {
@Prop({ default: new ProjectMember('', '', '', new Date(), '') })
public itemData: ProjectMember;
public get isProjectOwner(): boolean { const props = withDefaults(defineProps<{
return this.itemData.user.id === this.$store.getters.selectedProject.ownerId; itemData: ProjectMember;
} }>(), {
itemData: () => new ProjectMember('', '', '', new Date(), ''),
});
public get itemToRender(): { [key: string]: string | string[] } { const isProjectOwner = computed((): boolean => {
if (!this.isMobile && !this.isTablet) return { name: this.itemData.name, date: this.itemData.localDate(), email: this.itemData.email }; return props.itemData.user.id === store.getters.selectedProject.ownerId;
});
// TODO: change after adding actions button to list item const itemToRender = computed((): { [key: string]: string | string[] } => {
return { name: this.itemData.name, email: this.itemData.email }; if (!isMobile.value && !isTablet.value) return { name: props.itemData.name, date: props.itemData.localDate(), email: props.itemData.email };
}
} // TODO: change after adding actions button to list item
return { name: props.itemData.name, email: props.itemData.email };
});
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -0,0 +1,165 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import { ProjectMembersApiMock } from 'tests/unit/mock/api/projectMembers';
import { ProjectsApiMock } from 'tests/unit/mock/api/projects';
import { FrontendConfigApiMock } from 'tests/unit/mock/api/config';
import { makeAppStateModule } from '@/store/modules/appState';
import { makeProjectMembersModule, PROJECT_MEMBER_MUTATIONS } from '@/store/modules/projectMembers';
import { makeProjectsModule } from '@/store/modules/projects';
import { ProjectMember, ProjectMembersPage } from '@/types/projectMembers';
import { Project } from '@/types/projects';
import ProjectMembersArea from '@/components/team/ProjectMembersArea.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
const appStateModule = makeAppStateModule(new FrontendConfigApiMock());
const pmApi = new ProjectMembersApiMock();
const projectMembersModule = makeProjectMembersModule(pmApi);
const projectsApi = new ProjectsApiMock();
const projectsModule = makeProjectsModule(projectsApi);
const { FETCH } = PROJECT_MEMBER_MUTATIONS;
const store = new Vuex.Store({ modules: { projectsModule, projectMembersModule, appStateModule } });
describe('ProjectMembersArea.vue', () => {
const project = new Project('id', 'projectName', 'projectDescription', 'test', 'testOwnerId', true);
projectsApi.setMockProjects([project]);
const date = new Date(0);
const projectMember1 = new ProjectMember('testFullName1', 'testShortName1', 'test1@example.com', date, '1');
const projectMember2 = new ProjectMember('testFullName2', 'testShortName2', 'test2@example.com', date, '2');
const testProjectMembersPage = new ProjectMembersPage();
testProjectMembersPage.projectMembers = [projectMember1];
testProjectMembersPage.totalCount = 1;
testProjectMembersPage.pageCount = 1;
pmApi.setMockPage(testProjectMembersPage);
it('renders correctly', async (): Promise<void> => {
const wrapper = shallowMount<ProjectMembersArea>(ProjectMembersArea, {
store,
localVue,
});
await wrapper.setData({ areMembersFetching: false });
expect(wrapper).toMatchSnapshot();
});
it('function fetchProjectMembers works correctly', () => {
store.commit(FETCH, testProjectMembersPage);
const wrapper = shallowMount<ProjectMembersArea>(ProjectMembersArea, {
store,
localVue,
});
expect(wrapper.vm.projectMembers).toEqual([projectMember1]);
});
it('team area renders correctly', async (): Promise<void> => {
store.commit(FETCH, testProjectMembersPage);
const wrapper = shallowMount<ProjectMembersArea>(ProjectMembersArea, {
store,
localVue,
});
await wrapper.setData({ areMembersFetching: false });
const emptySearchResultArea = wrapper.findAll('.team-area__empty-search-result-area');
expect(emptySearchResultArea.length).toBe(0);
const teamContainer = wrapper.findAll('.team-area__table');
expect(teamContainer.length).toBe(1);
expect(wrapper).toMatchSnapshot();
});
it('action on toggle works correctly', () => {
store.commit(FETCH, testProjectMembersPage);
const wrapper = shallowMount<ProjectMembersArea>(ProjectMembersArea, {
store,
localVue,
});
wrapper.vm.onMemberCheckChange(projectMember1);
expect(store.getters.selectedProjectMembers.length).toBe(1);
});
it('clear selection works correctly', () => {
const date = new Date(0);
const projectMember3 = new ProjectMember('testFullName1', 'testShortName1', 'test1@example.com', date, '1');
projectMember3.isSelected = true;
const testProjectMembersPage = new ProjectMembersPage();
testProjectMembersPage.projectMembers = [projectMember3];
testProjectMembersPage.totalCount = 1;
testProjectMembersPage.pageCount = 1;
store.commit(FETCH, testProjectMembersPage);
const wrapper = shallowMount<ProjectMembersArea>(ProjectMembersArea, {
store,
localVue,
});
wrapper.vm.onMemberCheckChange(projectMember3);
expect(store.getters.selectedProjectMembers.length).toBe(0);
});
it('Reversing list order triggers rerender', () => {
const testPage = new ProjectMembersPage();
testPage.projectMembers = [projectMember1, projectMember2];
testPage.totalCount = 2;
testPage.pageCount = 1;
pmApi.setMockPage(testPage);
store.commit(FETCH, testPage);
const wrapper = shallowMount<ProjectMembersArea>(ProjectMembersArea, {
store,
localVue,
});
expect(wrapper.vm.projectMembers[0].user.id).toBe(projectMember1.user.id);
testProjectMembersPage.projectMembers = [projectMember2, projectMember1];
store.commit(FETCH, testProjectMembersPage);
expect(wrapper.vm.projectMembers[0].user.id).toBe(projectMember2.user.id);
});
it('empty search result area render correctly', async (): Promise<void> => {
const testPage1 = new ProjectMembersPage();
testPage1.projectMembers = [];
testPage1.totalCount = 0;
testPage1.pageCount = 0;
testPage1.search = 'testSearch';
pmApi.setMockPage(testPage1);
store.commit(FETCH, testPage1);
const wrapper = shallowMount<ProjectMembersArea>(ProjectMembersArea, {
store,
localVue,
});
await wrapper.setData({ areMembersFetching: false });
const emptySearchResultArea = wrapper.findAll('.team-area__empty-search-result-area');
expect(emptySearchResultArea.length).toBe(1);
const teamContainer = wrapper.findAll('.team-area__container');
expect(teamContainer.length).toBe(0);
expect(wrapper).toMatchSnapshot();
});
});