Skip to content

Commit fa14790

Browse files
authored
feat(components): refactor lifecycle hooks (#995)
* feat(components): refactor lifecycle hooks - Replace watch with onMounted in AddToCollections - Remove unnecessary watch in OrganizationDetail - Simplify OrganizationSettings onMounted logic - Update EvaluationTable to use onMounted - Change ResourceConsoleIndex to use onMounted - Refactor Profile to remove watch for username * update fetchUserInfo in profile * feat(tests): improve Profile component tests - Refactor user store data creation - Mock UserStore in beforeEach - Update test cases for current user checks - Enhance API call assertions in tests
1 parent b68aa5b commit fa14790

File tree

7 files changed

+128
-157
lines changed

7 files changed

+128
-157
lines changed
Lines changed: 103 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,68 @@
1-
import {
2-
describe,
3-
it,
4-
expect,
5-
beforeEach,
6-
vi,
7-
afterEach,
8-
} from 'vitest'
1+
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest'
92
import { mount } from '@vue/test-utils'
103
import Profile from '../../user_settings/Profile.vue'
114
import { reactive } from 'vue'
125

13-
// Mock vue3-cookies
14-
// let mockCookieGetFn = vi.fn()
15-
let { mockCookieGetFn } = vi.hoisted(() => {
16-
return { mockCookieGetFn: vi.fn() }
17-
})
18-
mockCookieGetFn.mockImplementation(() => ({
19-
cookies: {
20-
get: (key) => '123'
21-
}
22-
}))
23-
vi.mock('vue3-cookies', () => ({
24-
useCookies: mockCookieGetFn
25-
}))
26-
27-
// mock, actually redefine window.location
286
const mockLocation = {
29-
href: 'http://localhost:3000/profile/test_user',
7+
href: 'http://localhost:3000/profile/current_user',
308
search: ''
319
}
3210
Object.defineProperty(window, 'location', {
3311
value: mockLocation,
3412
writable: true
3513
})
3614

37-
let userStoreData = reactive({
38-
uuid: 'current_user',
39-
username: 'current_user',
40-
nickname: 'current_user',
41-
42-
avatar: 'current_user.com',
43-
roles: ['admin'],
44-
initialized: true,
45-
orgs: [
46-
{
47-
path: 'org_one',
48-
logo: 'org_one.png'
15+
const createUserStore = (overrides = {}) =>
16+
reactive({
17+
uuid: 'current_user',
18+
username: 'current_user',
19+
nickname: 'current_user',
20+
21+
avatar: 'current_user.com',
22+
roles: ['admin'],
23+
initialized: true,
24+
orgs: [
25+
{
26+
path: 'org_one',
27+
logo: 'org_one.png'
28+
}
29+
],
30+
lastLoginTime: '2023-09-11',
31+
phone: '123456',
32+
...overrides
33+
})
34+
35+
const getApiMockFn = vi.fn().mockResolvedValue({
36+
data: {
37+
value: {
38+
data: {
39+
id: 16,
40+
username: 'testuser',
41+
nickname: 'TestUser',
42+
phone: '123456',
43+
44+
uuid: 'ddfbb27b',
45+
avatar: 'https://example.com/avatar.jpg',
46+
bio: 'my bio',
47+
homepage: 'mm.com',
48+
roles: ['admin', 'super_user'],
49+
orgs: [
50+
{
51+
path: 'power',
52+
name: '联合力量',
53+
homepage: 'https://baidu.com',
54+
logo: 'https://example.com/logo.jpg',
55+
org_type: '社区组织',
56+
verified: false,
57+
user_id: 16
58+
}
59+
]
60+
}
4961
}
50-
],
51-
lastLoginTime: '2023-09-11',
52-
phone: '123456'
62+
},
63+
error: { value: null }
5364
})
54-
vi.mock('../../../stores/UserStore', () => ({
55-
default: () => userStoreData
56-
}))
5765

58-
let getApiMockFn = vi.fn().mockImplementation(() =>
59-
Promise.resolve({
60-
data: {
61-
value: {
62-
data: {
63-
id: 16,
64-
username: 'testuser',
65-
nickname: 'TestUser',
66-
phone: '123456',
67-
68-
uuid: 'ddfbb27b',
69-
avatar:
70-
'https://opencsg-public-resource.oss-cn-beijing.aliyuncs.com/comment/21b4d6ca-213e-48fc-9aba-aeed122633ef',
71-
bio: 'mya ',
72-
homepage: 'mm.com',
73-
roles: ['admin', 'super_user'],
74-
orgs: [
75-
{
76-
path: 'power',
77-
name: '联合力量',
78-
homepage: 'https://baidu.com',
79-
logo: 'https://opencsg-test.oss-cn-beijing.aliyuncs.com/org_logo/8d8aa331-54b7-453e-9d0b-d253a706ae27',
80-
org_type: '社区组织',
81-
verified: false,
82-
user_id: 16
83-
}
84-
]
85-
}
86-
}
87-
},
88-
error: { value: null }
89-
})
90-
)
9166
vi.mock('../../../packs/useFetchApi', () => ({
9267
default: () => ({
9368
json: getApiMockFn
@@ -96,73 +71,93 @@ vi.mock('../../../packs/useFetchApi', () => ({
9671

9772
describe('Profile', () => {
9873
let wrapper
74+
let originalLocalStorage
9975

10076
beforeEach(() => {
77+
originalLocalStorage = { ...localStorage }
78+
localStorage.clear()
10179
vi.clearAllMocks()
102-
wrapper = mount(Profile, {
103-
props: {
104-
name: 'test_name'
105-
}
106-
})
80+
81+
vi.mock('../../../stores/UserStore', () => ({
82+
default: () => createUserStore()
83+
}))
10784
})
10885

10986
afterEach(() => {
87+
localStorage.clear()
88+
Object.entries(originalLocalStorage).forEach(([key, value]) => {
89+
localStorage.setItem(key, value)
90+
})
91+
11092
if (wrapper) {
11193
wrapper.unmount()
11294
}
11395
})
11496

115-
describe('mount', () => {
116-
it('mounts correctly', () => {
117-
console.log('mount correctly')
118-
expect(wrapper.exists()).toBe(true)
119-
expect(getApiMockFn).toHaveBeenCalledTimes(0)
120-
})
121-
})
122-
12397
describe('logged in', () => {
12498
describe('is current user', () => {
125-
it('will not fetch user info from api', async () => {
126-
userStoreData.username = 'test_user'
99+
it('should not call profile API', async () => {
100+
window.location.href = 'http://localhost:3000/profile/current_user'
101+
102+
vi.doMock('../../../stores/UserStore', () => ({
103+
default: () =>
104+
createUserStore({
105+
username: 'current_user',
106+
uuid: 'current_user'
107+
})
108+
}))
109+
110+
wrapper = mount(Profile, { props: { name: 'current_user' } })
127111
await wrapper.vm.$nextTick()
128-
expect(getApiMockFn).toHaveBeenCalledTimes(0)
112+
113+
expect(getApiMockFn).not.toHaveBeenCalled()
129114
})
130115
})
131116

132117
describe('is not current user', () => {
133-
it('fetch user info from api', async () => {
134-
userStoreData.username = 'not_test_user'
118+
it('should call profile API', async () => {
119+
window.location.href = 'http://localhost:3000/profile/other_user'
120+
121+
vi.doMock('../../../stores/UserStore', () => ({
122+
default: () =>
123+
createUserStore({
124+
username: 'current_user',
125+
uuid: 'current_user'
126+
})
127+
}))
128+
129+
wrapper = mount(Profile, { props: { name: 'other_user' } })
135130
await wrapper.vm.$nextTick()
131+
136132
expect(getApiMockFn).toHaveBeenCalledTimes(1)
137133
})
138134
})
139-
140135
})
141136

142-
describe('without logged in', () => {
137+
describe('not logged in', () => {
143138
beforeEach(() => {
144-
mockCookieGetFn.mockImplementation(() => ({
145-
cookies: {
146-
get: (key) => null
147-
}
139+
vi.doMock('../../../stores/UserStore', () => ({
140+
default: () =>
141+
createUserStore({
142+
uuid: '',
143+
username: '',
144+
initialized: true
145+
})
148146
}))
149-
userStoreData = {}
150-
wrapper = mount(Profile, {
151-
props: {
152-
name: 'test_name'
153-
}
154-
})
155147
})
156148

157-
it('fetchs user info from api', async () => {
149+
it('should call profile API', async () => {
150+
wrapper = mount(Profile, { props: { name: 'testuser' } })
158151
await wrapper.vm.$nextTick()
152+
159153
expect(getApiMockFn).toHaveBeenCalledTimes(1)
160154
})
161155

162-
it('renders user info from api', async () => {
156+
it('should not be current user', async () => {
157+
wrapper = mount(Profile, { props: { name: 'testuser' } })
163158
await wrapper.vm.$nextTick()
159+
164160
expect(wrapper.vm.isCurrentUser).toBe(false)
165-
expect(wrapper.vm.username).toBe('testuser')
166161
})
167162
})
168163
})

frontend/src/components/collections/AddToCollections.vue

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
</div>
7979
</template>
8080
<script setup>
81-
import { ref, watch } from 'vue'
81+
import { ref, onMounted } from 'vue'
8282
import { ElMessage } from 'element-plus'
8383
import { useI18n } from 'vue-i18n'
8484
import useFetchApi from '../../packs/useFetchApi';
@@ -94,7 +94,6 @@
9494
const dialogVisible = ref(false)
9595
const collectionsList = ref([])
9696
const collectionsIdsInput = ref('')
97-
const isLogged = ref(false)
9897
const fetchCollectionsList = async () => {
9998
const url = `/user/${userStore.username}/collections`
10099
const { data, error } = await useFetchApi(url).json()
@@ -107,7 +106,7 @@
107106
}
108107
109108
const openAddCollections = () => {
110-
if(isLogged.value) {
109+
if(userStore.isLoggedIn) {
111110
dialogVisible.value = true
112111
} else {
113112
ToLoginPage()
@@ -146,11 +145,10 @@
146145
}
147146
}
148147
149-
watch(() => userStore.isLoggedIn, () => {
150-
isLogged.value = userStore.isLoggedIn
151-
})
152-
watch(() => userStore.username, () => {
153-
fetchCollectionsList()
148+
onMounted(() => {
149+
if (userStore.isLoggedIn) {
150+
fetchCollectionsList()
151+
}
154152
})
155153
</script>
156154
<style scoped>

frontend/src/components/organizations/OrganizationDetail.vue

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,11 @@
164164
}
165165
}
166166
167-
watch(() => userStore.username, () => {
168-
currentUserRole()
169-
})
170-
171167
onMounted(() => {
172168
fetchOrgDetail()
173169
fetchOrgMemberList()
170+
if (userStore.isLoggedIn) {
171+
currentUserRole()
172+
}
174173
})
175174
</script>

frontend/src/components/organizations/OrganizationSettings.vue

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import OrganizationEdit from './OrganizationEdit.vue'
3333
import OrganizationMembers from './OrganizationMembers.vue'
3434
import useFetchApi from "../../packs/useFetchApi"
35-
import { ref, onMounted, watch } from 'vue'
35+
import { ref, onMounted } from 'vue'
3636
import { ElMessage } from 'element-plus'
3737
import useUserStore from '../../stores/UserStore'
3838
@@ -54,13 +54,6 @@
5454
5555
const role =ref('')
5656
57-
watch(
58-
() => userStore.username,
59-
() => {
60-
currentUserRole()
61-
}
62-
)
63-
6457
const fetchOrgDetail = async () => {
6558
const orgDetailEndpoint = `/organization/${props.name}`
6659
const { data, error } = await useFetchApi(orgDetailEndpoint).json()
@@ -105,8 +98,6 @@
10598
10699
onMounted(() => {
107100
fetchOrgDetail()
108-
if (userStore.initialized) {
109-
currentUserRole()
110-
}
101+
currentUserRole()
111102
})
112103
</script>

frontend/src/components/resource_console/EvaluationTable.vue

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@
188188
</template>
189189

190190
<script setup>
191-
import { ref, watch } from 'vue'
191+
import { ref, onMounted } from 'vue'
192192
import { formatDate } from '../../packs/datetimeUtils'
193193
import useFetchApi from '../../packs/useFetchApi'
194194
import useUserStore from '../../stores/UserStore.js'
@@ -258,12 +258,9 @@
258258
}
259259
}
260260
261-
watch(
262-
() => userStore.username,
263-
() => {
264-
fetchEvaluations()
265-
}
266-
)
261+
onMounted(() => {
262+
fetchEvaluations()
263+
})
267264
</script>
268265

269266
<style lang="less">

0 commit comments

Comments
 (0)