blessing-skin-server/resources/assets/tests/views/user/Closet.test.tsx

465 lines
15 KiB
TypeScript
Raw Normal View History

2020-02-11 16:40:26 +08:00
import React from 'react'
2020-03-28 12:18:52 +08:00
import { render, fireEvent, waitFor } from '@testing-library/react'
2020-05-13 10:54:35 +08:00
import { createPaginator } from '../../utils'
2020-02-11 16:40:26 +08:00
import $ from 'jquery'
import { t } from '@/scripts/i18n'
import * as fetch from '@/scripts/net'
2020-05-13 18:40:09 +08:00
import { ClosetItem, Player, TextureType } from '@/scripts/types'
2020-05-30 10:44:36 +08:00
import urls from '@/scripts/urls'
2020-02-11 16:40:26 +08:00
import Closet from '@/views/user/Closet'
jest.mock('@/scripts/net')
const fixtureSkin: Readonly<ClosetItem> = Object.freeze<ClosetItem>({
tid: 1,
name: 'skin',
2020-05-13 18:40:09 +08:00
type: TextureType.Steve,
2020-02-11 16:40:26 +08:00
hash: 'abc',
size: 2,
uploader: 1,
public: true,
upload_at: new Date().toString(),
likes: 1,
pivot: {
user_uid: 1,
texture_tid: 1,
item_name: 'closet_skin',
},
})
const fixtureCape: Readonly<ClosetItem> = Object.freeze<ClosetItem>({
tid: 2,
name: 'cape',
2020-05-13 18:40:09 +08:00
type: TextureType.Cape,
2020-02-11 16:40:26 +08:00
hash: 'def',
size: 2,
uploader: 1,
public: true,
upload_at: new Date().toString(),
likes: 1,
pivot: {
user_uid: 1,
texture_tid: 2,
item_name: 'closet_cape',
},
})
const fixturePlayer: Readonly<Player> = Object.freeze<Player>({
pid: 1,
name: 'kumiko',
uid: 1,
2020-02-11 16:40:26 +08:00
tid_skin: 1,
tid_cape: 2,
last_modified: new Date().toString(),
2020-02-11 16:40:26 +08:00
})
beforeEach(() => {
const container = document.createElement('div')
container.id = 'previewer'
document.body.appendChild(container)
})
afterEach(() => {
document.querySelector('#previewer')!.remove()
})
test('loading indicator', () => {
2020-03-20 19:03:10 +08:00
fetch.get.mockResolvedValue(createPaginator([]))
2020-02-11 16:40:26 +08:00
const { queryByTitle } = render(<Closet />)
expect(queryByTitle('Loading...')).toBeInTheDocument()
})
test('empty closet', async () => {
2020-03-20 19:03:10 +08:00
fetch.get.mockResolvedValue(createPaginator([]))
2020-02-11 16:40:26 +08:00
const { queryByText } = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
expect(queryByText(/skin library/i)).toBeInTheDocument()
})
test('categories', async () => {
fetch.get
2020-03-20 19:03:10 +08:00
.mockResolvedValueOnce(createPaginator([fixtureSkin]))
.mockResolvedValueOnce(createPaginator([fixtureCape]))
.mockResolvedValueOnce(createPaginator([fixtureSkin]))
2020-02-11 16:40:26 +08:00
const { getByText, queryByText } = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalled())
2020-02-11 16:40:26 +08:00
expect(queryByText(fixtureSkin.pivot.item_name)).toBeInTheDocument()
expect(queryByText(fixtureCape.pivot.item_name)).not.toBeInTheDocument()
fireEvent.click(getByText(t('general.cape')))
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalled())
2020-02-11 16:40:26 +08:00
expect(queryByText(fixtureSkin.pivot.item_name)).not.toBeInTheDocument()
expect(queryByText(fixtureCape.pivot.item_name)).toBeInTheDocument()
fireEvent.click(getByText(t('general.skin')))
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalled())
2020-02-11 16:40:26 +08:00
expect(queryByText(fixtureSkin.pivot.item_name)).toBeInTheDocument()
expect(queryByText(fixtureCape.pivot.item_name)).not.toBeInTheDocument()
})
test('search textures', async () => {
fetch.get
2020-03-20 19:03:10 +08:00
.mockResolvedValueOnce(createPaginator([fixtureSkin]))
.mockResolvedValueOnce(createPaginator([]))
2020-02-11 16:40:26 +08:00
2020-03-28 12:18:52 +08:00
const { getByPlaceholderText, findByText } = render(<Closet />)
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
fireEvent.input(getByPlaceholderText(t('user.typeToSearch')), {
target: { value: 'abc' },
})
2020-03-28 12:18:52 +08:00
expect(await findByText(/no result/i)).toBeInTheDocument()
2020-02-11 16:40:26 +08:00
})
test('switch page', async () => {
fetch.get
2020-03-20 19:03:10 +08:00
.mockResolvedValueOnce({ ...createPaginator([]), last_page: 2 })
.mockResolvedValueOnce({ ...createPaginator([fixtureSkin]), last_page: 2 })
2020-02-11 16:40:26 +08:00
2020-03-28 12:18:52 +08:00
const { getByText, findByText } = render(<Closet />)
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
fireEvent.click(getByText('2'))
2020-03-28 12:18:52 +08:00
expect(await findByText(fixtureSkin.pivot.item_name)).toBeInTheDocument()
2020-02-11 16:40:26 +08:00
})
describe('rename item', () => {
beforeEach(() => {
2020-03-20 19:03:10 +08:00
fetch.get.mockResolvedValue(createPaginator([fixtureSkin]))
2020-02-11 16:40:26 +08:00
})
it('succeeded', async () => {
2020-05-29 09:09:10 +08:00
fetch.put.mockResolvedValue({ code: 0, message: 'success' })
2020-02-11 16:40:26 +08:00
const { getByText, getByDisplayValue, getByRole, queryByText } = render(
<Closet />,
)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
fireEvent.click(getByText(t('user.renameItem')))
fireEvent.input(getByDisplayValue(fixtureSkin.pivot.item_name), {
target: { value: 'my skin' },
})
fireEvent.click(getByText(t('general.confirm')))
2020-03-28 12:18:52 +08:00
await waitFor(() =>
2020-05-30 10:44:36 +08:00
expect(fetch.put).toBeCalledWith(
urls.user.closet.rename(fixtureSkin.tid),
{ name: 'my skin' },
),
2020-02-11 16:40:26 +08:00
)
expect(queryByText('my skin')).toBeInTheDocument()
expect(queryByText('success')).toBeInTheDocument()
expect(getByRole('status')).toHaveClass('alert-success')
})
it('empty name', async () => {
const { getByText, getByDisplayValue, queryByText } = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
fireEvent.click(getByText(t('user.renameItem')))
fireEvent.input(getByDisplayValue(fixtureSkin.pivot.item_name), {
target: { value: '' },
})
fireEvent.click(getByText(t('general.confirm')))
2020-05-29 09:09:10 +08:00
await waitFor(() => expect(fetch.put).not.toBeCalled())
2020-02-11 16:40:26 +08:00
expect(queryByText(t('skinlib.emptyNewTextureName'))).toBeInTheDocument()
fireEvent.click(getByText(t('general.cancel')))
})
it('failed', async () => {
2020-05-29 09:09:10 +08:00
fetch.put.mockResolvedValue({ code: 1, message: 'failed' })
2020-02-11 16:40:26 +08:00
const { getByText, getByDisplayValue, getByRole, queryByText } = render(
<Closet />,
)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
fireEvent.click(getByText(t('user.renameItem')))
fireEvent.input(getByDisplayValue(fixtureSkin.pivot.item_name), {
target: { value: 'my skin' },
})
fireEvent.click(getByText(t('general.confirm')))
2020-03-28 12:18:52 +08:00
await waitFor(() =>
2020-05-30 10:44:36 +08:00
expect(fetch.put).toBeCalledWith(
urls.user.closet.rename(fixtureSkin.tid),
{ name: 'my skin' },
),
2020-02-11 16:40:26 +08:00
)
expect(queryByText(fixtureSkin.pivot.item_name)).toBeInTheDocument()
expect(queryByText('failed')).toBeInTheDocument()
expect(getByRole('alert')).toHaveClass('alert-danger')
})
})
describe('remove item', () => {
beforeEach(() => {
2020-03-20 19:03:10 +08:00
fetch.get.mockResolvedValue(createPaginator([fixtureSkin]))
2020-02-11 16:40:26 +08:00
})
it('succeeded', async () => {
2020-05-29 09:09:10 +08:00
fetch.del.mockResolvedValue({ code: 0, message: 'success' })
2020-02-11 16:40:26 +08:00
const { getByText, getByRole, queryByText } = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
fireEvent.click(getByText(t('user.removeItem')))
fireEvent.click(getByText(t('general.confirm')))
2020-03-28 12:18:52 +08:00
await waitFor(() =>
2020-05-30 10:44:36 +08:00
expect(fetch.del).toBeCalledWith(
urls.user.closet.remove(fixtureSkin.tid),
),
2020-03-28 12:18:52 +08:00
)
2020-02-11 16:40:26 +08:00
expect(queryByText(/skin library/i)).toBeInTheDocument()
expect(queryByText('success')).toBeInTheDocument()
expect(getByRole('status')).toHaveClass('alert-success')
})
it('failed', async () => {
2020-05-29 09:09:10 +08:00
fetch.del.mockResolvedValue({ code: 1, message: 'failed' })
2020-02-11 16:40:26 +08:00
const { getByText, getByRole, queryByText } = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
fireEvent.click(getByText(t('user.removeItem')))
fireEvent.click(getByText(t('general.confirm')))
2020-03-28 12:18:52 +08:00
await waitFor(() =>
2020-05-30 10:44:36 +08:00
expect(fetch.del).toBeCalledWith(
urls.user.closet.remove(fixtureSkin.tid),
),
2020-03-28 12:18:52 +08:00
)
2020-02-11 16:40:26 +08:00
expect(queryByText(fixtureSkin.pivot.item_name)).toBeInTheDocument()
expect(queryByText('failed')).toBeInTheDocument()
expect(getByRole('alert')).toHaveClass('alert-danger')
})
it('cancelled', async () => {
const { getByText, queryByText } = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
fireEvent.click(getByText(t('user.removeItem')))
fireEvent.click(getByText(t('general.cancel')))
2020-05-29 09:09:10 +08:00
await waitFor(() => expect(fetch.del).not.toBeCalled())
2020-02-11 16:40:26 +08:00
expect(queryByText(fixtureSkin.pivot.item_name)).toBeInTheDocument()
})
})
describe('select textures', () => {
beforeEach(() => {
fetch.get
2020-03-20 19:03:10 +08:00
.mockResolvedValueOnce(createPaginator([fixtureSkin]))
.mockResolvedValueOnce(createPaginator([fixtureCape]))
2020-02-11 16:40:26 +08:00
})
it('select skin', async () => {
const { getByAltText, queryAllByText } = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
fireEvent.click(getByAltText(fixtureSkin.pivot.item_name))
expect(queryAllByText(t('general.skin'))).toHaveLength(2)
})
it('select cape', async () => {
const { getByText, getByAltText, queryAllByText } = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalled())
2020-02-11 16:40:26 +08:00
fireEvent.click(getByText(t('general.cape')))
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalled())
2020-02-11 16:40:26 +08:00
fireEvent.click(getByAltText(fixtureCape.pivot.item_name))
expect(queryAllByText(t('general.cape'))).toHaveLength(2)
})
it('reset selected', async () => {
const { getByText, getByAltText, queryByText } = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalled())
2020-02-11 16:40:26 +08:00
fireEvent.click(getByAltText(fixtureSkin.pivot.item_name))
fireEvent.click(getByText(t('general.cape')))
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalled())
2020-02-11 16:40:26 +08:00
fireEvent.click(getByAltText(fixtureCape.pivot.item_name))
expect(
queryByText(`${t('general.skin')} & ${t('general.cape')}`),
).toBeInTheDocument()
fireEvent.click(getByText(t('user.resetSelected')))
expect(
queryByText(`${t('general.skin')} & ${t('general.cape')}`),
).not.toBeInTheDocument()
})
})
describe('set avatar', () => {
beforeEach(() => {
2020-03-20 19:03:10 +08:00
fetch.get.mockResolvedValue(createPaginator([fixtureSkin]))
2020-02-11 16:40:26 +08:00
const img = document.createElement('img')
img.alt = 'User Image'
document.body.appendChild(img)
})
afterEach(() => {
document.querySelector('[alt="User Image"]')!.remove()
})
it('succeeded', async () => {
fetch.post.mockResolvedValue({ code: 0, message: 'success' })
const { getByText, getByRole, queryByText } = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
fireEvent.click(getByText(t('user.setAsAvatar')))
fireEvent.click(getByText(t('general.confirm')))
2020-03-28 12:18:52 +08:00
await waitFor(() =>
2020-05-30 10:44:36 +08:00
expect(fetch.post).toBeCalledWith(urls.user.profile.avatar(), {
2020-03-28 12:18:52 +08:00
tid: fixtureSkin.tid,
}),
)
2020-02-11 16:40:26 +08:00
expect(queryByText('success')).toBeInTheDocument()
expect(getByRole('status')).toHaveClass('alert-success')
expect(document.querySelector('[alt="User Image"]')).toHaveAttribute('src')
})
it('failed', async () => {
fetch.post.mockResolvedValue({ code: 1, message: 'failed' })
const { getByText, getByRole, queryByText } = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
fireEvent.click(getByText(t('user.setAsAvatar')))
fireEvent.click(getByText(t('general.confirm')))
2020-03-28 12:18:52 +08:00
await waitFor(() =>
2020-05-30 10:44:36 +08:00
expect(fetch.post).toBeCalledWith(urls.user.profile.avatar(), {
2020-03-28 12:18:52 +08:00
tid: fixtureSkin.tid,
}),
)
2020-02-11 16:40:26 +08:00
expect(queryByText('failed')).toBeInTheDocument()
expect(getByRole('alert')).toHaveClass('alert-danger')
})
it('cancelled', async () => {
const { getByText } = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
fireEvent.click(getByText(t('user.setAsAvatar')))
fireEvent.click(getByText(t('general.cancel')))
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.post).not.toBeCalled())
2020-02-11 16:40:26 +08:00
})
})
describe('apply textures to player', () => {
it('selected nothing', async () => {
2020-03-20 19:03:10 +08:00
fetch.get.mockResolvedValue(createPaginator([]))
2020-02-11 16:40:26 +08:00
const { getByText, getByRole, queryByText } = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
fireEvent.click(getByText(t('user.useAs')))
expect(queryByText(t('user.emptySelectedTexture'))).toBeInTheDocument()
expect(getByRole('status')).toHaveClass('alert-info')
})
it('search players', async () => {
fetch.get
2020-03-20 19:03:10 +08:00
.mockResolvedValueOnce(createPaginator([fixtureSkin]))
2020-05-14 23:16:39 +08:00
.mockResolvedValueOnce([fixturePlayer])
2020-02-11 16:40:26 +08:00
const {
getByText,
getByAltText,
getAllByPlaceholderText,
queryByText,
2020-03-28 12:18:52 +08:00
findByText,
2020-02-11 16:40:26 +08:00
} = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
2020-02-11 16:40:26 +08:00
fireEvent.click(getByAltText(fixtureSkin.pivot.item_name))
fireEvent.click(getByText(t('user.useAs')))
2020-03-28 12:18:52 +08:00
expect(await findByText(fixturePlayer.name)).toBeInTheDocument()
2020-02-11 16:40:26 +08:00
fireEvent.input(getAllByPlaceholderText(t('user.typeToSearch'))[1], {
target: { value: 'reina' },
})
expect(queryByText(fixturePlayer.name)).not.toBeInTheDocument()
})
it('succeeded', async () => {
fetch.get
2020-03-20 19:03:10 +08:00
.mockResolvedValueOnce(createPaginator([fixtureSkin]))
2020-05-14 23:16:39 +08:00
.mockResolvedValueOnce([fixturePlayer])
2020-02-11 16:40:26 +08:00
fetch.post.mockResolvedValue({ code: 0, message: 'success' })
const {
getByText,
getByAltText,
getByTitle,
getByRole,
queryByText,
} = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalled())
2020-02-11 16:40:26 +08:00
fireEvent.click(getByAltText(fixtureSkin.pivot.item_name))
fireEvent.click(getByText(t('user.useAs')))
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalled())
2020-02-11 16:40:26 +08:00
fireEvent.click(getByTitle(fixturePlayer.name))
2020-03-28 12:18:52 +08:00
await waitFor(() =>
expect(fetch.post).toBeCalledWith(
2020-05-30 10:44:36 +08:00
urls.user.player.set(fixturePlayer.pid),
{ skin: fixtureSkin.tid },
2020-03-28 12:18:52 +08:00
),
)
2020-02-11 16:40:26 +08:00
expect(queryByText('success')).toBeInTheDocument()
expect(getByRole('status')).toHaveClass('alert-success')
})
it('failed', async () => {
fetch.get
2020-03-20 19:03:10 +08:00
.mockResolvedValueOnce(createPaginator([fixtureSkin]))
2020-05-14 23:16:39 +08:00
.mockResolvedValueOnce([fixturePlayer])
2020-02-11 16:40:26 +08:00
fetch.post.mockResolvedValue({ code: 1, message: 'failed' })
const {
getByText,
getByAltText,
getByTitle,
getByRole,
queryByText,
} = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalled())
2020-02-11 16:40:26 +08:00
fireEvent.click(getByAltText(fixtureSkin.pivot.item_name))
fireEvent.click(getByText(t('user.useAs')))
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalled())
2020-02-11 16:40:26 +08:00
fireEvent.click(getByTitle(fixturePlayer.name))
2020-03-28 12:18:52 +08:00
await waitFor(() =>
expect(fetch.post).toBeCalledWith(
2020-05-30 10:44:36 +08:00
urls.user.player.set(fixturePlayer.pid),
{ skin: fixtureSkin.tid },
2020-03-28 12:18:52 +08:00
),
)
2020-02-11 16:40:26 +08:00
expect(queryByText('failed')).toBeInTheDocument()
expect(getByRole('alert')).toHaveClass('alert-danger')
})
it('close dialog', async () => {
fetch.get
2020-03-20 19:03:10 +08:00
.mockResolvedValueOnce(createPaginator([fixtureSkin]))
2020-05-14 23:16:39 +08:00
.mockResolvedValueOnce([fixturePlayer])
2020-02-11 16:40:26 +08:00
const { getByText, getByAltText } = render(<Closet />)
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalled())
2020-02-11 16:40:26 +08:00
fireEvent.click(getByAltText(fixtureSkin.pivot.item_name))
fireEvent.click(getByText(t('user.useAs')))
2020-03-28 12:18:52 +08:00
await waitFor(() => expect(fetch.get).toBeCalled())
2020-02-11 16:40:26 +08:00
2020-03-28 12:18:52 +08:00
$('#modal-apply').modal('hide').trigger('hidden.bs.modal')
2020-02-11 16:40:26 +08:00
expect(fetch.post).not.toBeCalled()
})
})