mirror of
https://github.com/koel/koel
synced 2024-11-10 06:34:14 +00:00
feat(test): add userStore tests
This commit is contained in:
parent
c915507c1a
commit
ec49c29c0d
3 changed files with 148 additions and 31 deletions
|
@ -1,28 +1,148 @@
|
|||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import data from '@/__tests__/blobs/data'
|
||||
import { expect, it } from 'vitest'
|
||||
import { userStore } from '@/stores/userStore'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { CreateUserData, UpdateCurrentProfileData, UpdateUserData, userStore } from '@/stores/userStore'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { httpService } from '@/services'
|
||||
|
||||
const { users, currentUser } = data
|
||||
const currentUser = factory<User>('user', {
|
||||
id: 1,
|
||||
name: 'John Doe',
|
||||
email: 'john@doe.com',
|
||||
is_admin: true
|
||||
})
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected beforeEach () {
|
||||
super.beforeEach(() => userStore.init(currentUser))
|
||||
super.beforeEach(() => {
|
||||
userStore.vault.clear()
|
||||
userStore.init(currentUser)
|
||||
})
|
||||
}
|
||||
|
||||
protected test () {
|
||||
it('sets data state', () => {
|
||||
expect(userStore.state.users).toEqual(users)
|
||||
expect(userStore.state.current).toEqual(currentUser)
|
||||
it('initializes with current user', () => {
|
||||
expect(userStore.current).toEqual(currentUser)
|
||||
expect(userStore.vault.size).toBe(1)
|
||||
})
|
||||
|
||||
it('returns all users', () => expect(userStore.all).toEqual(users))
|
||||
it('gets a user by ID', () => expect(userStore.byId(1)).toEqual(users[0]))
|
||||
it('gets the current user', () => expect(userStore.current.id).toBe(1))
|
||||
it('syncs with vault', () => {
|
||||
const user = factory<User>('user')
|
||||
|
||||
it('sets the current user', () => {
|
||||
userStore.current = users[1]
|
||||
expect(userStore.current.id).toBe(2)
|
||||
expect(userStore.syncWithVault(user)).toEqual([user])
|
||||
expect(userStore.vault.size).toBe(2)
|
||||
expect(userStore.vault.get(user.id)).toEqual(user)
|
||||
})
|
||||
|
||||
it('fetches users', async () => {
|
||||
const users = factory<User[]>('user', 3)
|
||||
const getMock = this.mock(httpService, 'get').mockResolvedValue(users)
|
||||
|
||||
await userStore.fetch()
|
||||
|
||||
expect(getMock).toHaveBeenCalledWith('users')
|
||||
expect(userStore.vault.size).toBe(4)
|
||||
})
|
||||
|
||||
it('gets user by id', () => {
|
||||
const user = factory<User>('user', { id: 2 })
|
||||
userStore.syncWithVault(user)
|
||||
|
||||
expect(userStore.byId(2)).toEqual(user)
|
||||
})
|
||||
|
||||
it('logs in', async () => {
|
||||
const postMock = this.mock(httpService, 'post')
|
||||
await userStore.login('john@doe.com', 'curry-wurst')
|
||||
|
||||
expect(postMock).toHaveBeenCalledWith('me', { email: 'john@doe.com', password: 'curry-wurst' })
|
||||
})
|
||||
|
||||
it('logs out', async () => {
|
||||
const deleteMock = this.mock(httpService, 'delete')
|
||||
await userStore.logout()
|
||||
|
||||
expect(deleteMock).toHaveBeenCalledWith('me')
|
||||
})
|
||||
|
||||
it('gets profile', async () => {
|
||||
const getMock = this.mock(httpService, 'get')
|
||||
await userStore.getProfile()
|
||||
|
||||
expect(getMock).toHaveBeenCalledWith('me')
|
||||
})
|
||||
|
||||
it('updates profile', async () => {
|
||||
const updated = factory<User>('user', {
|
||||
id: 1,
|
||||
name: 'Jane Doe',
|
||||
email: 'jane@doe.com'
|
||||
})
|
||||
|
||||
const putMock = this.mock(httpService, 'put').mockResolvedValue(updated)
|
||||
|
||||
const data: UpdateCurrentProfileData = {
|
||||
current_password: 'curry-wurst',
|
||||
name: 'Jane Doe',
|
||||
email: 'jane@doe.com'
|
||||
}
|
||||
|
||||
await userStore.updateProfile(data)
|
||||
|
||||
expect(putMock).toHaveBeenCalledWith('me', data)
|
||||
expect(userStore.current.name).toBe('Jane Doe')
|
||||
expect(userStore.current.email).toBe('jane@doe.com')
|
||||
})
|
||||
|
||||
it('creates a user', async () => {
|
||||
const data: CreateUserData = {
|
||||
is_admin: false,
|
||||
password: 'bratwurst',
|
||||
name: 'Jane Doe',
|
||||
email: 'jane@doe.com'
|
||||
}
|
||||
|
||||
const user = factory<User>('user', data)
|
||||
const postMock = this.mock(httpService, 'post').mockResolvedValue(user)
|
||||
|
||||
expect(await userStore.store(data)).toEqual(user)
|
||||
expect(postMock).toHaveBeenCalledWith('users', data)
|
||||
expect(userStore.vault.size).toBe(2)
|
||||
expect(userStore.state.users).toHaveLength(2)
|
||||
})
|
||||
|
||||
it('updates a user', async () => {
|
||||
const user = factory<User>('user', { id: 2 })
|
||||
userStore.state.users.push(...userStore.syncWithVault(user))
|
||||
|
||||
const data: UpdateUserData = {
|
||||
is_admin: true,
|
||||
password: 'bratwurst',
|
||||
name: 'Jane Doe',
|
||||
email: 'jane@doe.com'
|
||||
}
|
||||
|
||||
const updated = { ...user, ...data }
|
||||
const putMock = this.mock(httpService, 'put').mockResolvedValue(updated)
|
||||
|
||||
await userStore.update(user, data)
|
||||
|
||||
expect(putMock).toHaveBeenCalledWith('users/2', data)
|
||||
expect(userStore.vault.get(2)).toEqual(updated)
|
||||
})
|
||||
|
||||
it('deletes a user', async () => {
|
||||
const deleteMock = this.mock(httpService, 'delete')
|
||||
|
||||
const user = factory<User>('user', { id: 2 })
|
||||
userStore.state.users.push(...userStore.syncWithVault(user))
|
||||
expect(userStore.vault.has(2)).toBe(true)
|
||||
|
||||
expect(await userStore.destroy(user))
|
||||
|
||||
expect(deleteMock).toHaveBeenCalledWith('users/2')
|
||||
expect(userStore.vault.size).toBe(1)
|
||||
expect(userStore.state.users).toHaveLength(1)
|
||||
expect(userStore.vault.has(2)).toBe(false)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { differenceBy } from 'lodash'
|
||||
import { differenceBy, merge } from 'lodash'
|
||||
import { httpService } from '@/services'
|
||||
import { reactive } from 'vue'
|
||||
import { arrayify } from '@/utils'
|
||||
import { UnwrapNestedRefs } from '@vue/reactivity'
|
||||
|
||||
export interface UpdateCurrentProfileData {
|
||||
current_password: string | null
|
||||
|
@ -26,7 +27,7 @@ export interface UpdateUserData extends UserFormData {
|
|||
}
|
||||
|
||||
export const userStore = {
|
||||
vault: new Map<number, User>(),
|
||||
vault: new Map<number, UnwrapNestedRefs<User>>(),
|
||||
|
||||
state: reactive({
|
||||
users: [] as User[],
|
||||
|
@ -36,20 +37,20 @@ export const userStore = {
|
|||
syncWithVault (users: User | User[]) {
|
||||
return arrayify(users).map(user => {
|
||||
let local = this.byId(user.id)
|
||||
local = reactive(local ? Object.assign(local, user) : user)
|
||||
local = reactive(local ? merge(local, user) : user)
|
||||
this.vault.set(user.id, local)
|
||||
|
||||
return local
|
||||
})
|
||||
},
|
||||
|
||||
async fetch () {
|
||||
this.state.users = this.syncWithVault(await httpService.get<User[]>('users'))
|
||||
init (currentUser: User) {
|
||||
this.state.users = this.syncWithVault(currentUser)
|
||||
this.state.current = this.state.users[0]
|
||||
},
|
||||
|
||||
init (currentUser: User) {
|
||||
this.current = currentUser
|
||||
this.state.users = this.syncWithVault(this.current)
|
||||
async fetch () {
|
||||
this.state.users = this.syncWithVault(await httpService.get<User[]>('users'))
|
||||
},
|
||||
|
||||
byId (id: number) {
|
||||
|
@ -60,30 +61,26 @@ export const userStore = {
|
|||
return this.state.current
|
||||
},
|
||||
|
||||
set current (user: User) {
|
||||
this.state.current = user
|
||||
},
|
||||
|
||||
login: async (email: string, password: string) => await httpService.post<User>('me', { email, password }),
|
||||
logout: async () => await httpService.delete('me'),
|
||||
getProfile: async () => await httpService.get<User>('me'),
|
||||
|
||||
async updateProfile (data: UpdateCurrentProfileData) {
|
||||
Object.assign(this.current, (await httpService.put<User>('me', data)))
|
||||
merge(this.current, (await httpService.put<User>('me', data)))
|
||||
},
|
||||
|
||||
async store (data: CreateUserData) {
|
||||
const user = await httpService.post<User>('user', data)
|
||||
const user = await httpService.post<User>('users', data)
|
||||
this.state.users.push(...this.syncWithVault(user))
|
||||
return this.byId(user.id)
|
||||
},
|
||||
|
||||
async update (user: User, data: UpdateUserData) {
|
||||
this.syncWithVault(await httpService.put<User>(`user/${user.id}`, data))
|
||||
this.syncWithVault(await httpService.put<User>(`users/${user.id}`, data))
|
||||
},
|
||||
|
||||
async destroy (user: User) {
|
||||
await httpService.delete(`user/${user.id}`)
|
||||
await httpService.delete(`users/${user.id}`)
|
||||
this.state.users = differenceBy(this.state.users, [user], 'id')
|
||||
this.vault.delete(user.id)
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ Route::prefix('api')->middleware('api')->group(static function (): void {
|
|||
|
||||
Route::apiResource('songs', SongController::class);
|
||||
|
||||
Route::get('users', [UserController::class, 'index']);
|
||||
Route::apiResource('users', UserController::class);
|
||||
|
||||
Route::get('search', ExcerptSearchController::class);
|
||||
Route::get('search/songs', SongSearchController::class);
|
||||
|
|
Loading…
Reference in a new issue