Fix linting errors

This commit is contained in:
Pig Fang 2019-03-17 10:21:18 +08:00
parent a1cfbe7f5b
commit 9872221dc3
29 changed files with 192 additions and 1 deletions

View File

@ -53,6 +53,7 @@
"eslint": "^5.14.0",
"eslint-config-gplane": "^5.1.3",
"eslint-formatter-beauty": "^3.0.0",
"eslint-plugin-project": "^0.2.2",
"eslint-plugin-vue": "^5.2.2",
"file-loader": "^3.0.1",
"jest": "^24.5.0",
@ -80,6 +81,14 @@
"not ie 11",
"Chrome > 52"
],
"prettier": {
"printWidth": 80,
"semi": false,
"singleQuote": true,
"trailingComma": "es5",
"arrowParens": "avoid",
"tabWidth": 2
},
"eslintConfig": {
"root": true,
"extends": [
@ -100,6 +109,12 @@
"globals": {
"blessing": "readonly"
},
"plugins": [
"project"
],
"settings": {
"projectRulesDir": "resources/assets/eslint-rules"
},
"rules": {
"camelcase": [
2,
@ -113,7 +128,8 @@
120
],
"prefer-object-spread": 0,
"import/no-unresolved": 0
"import/no-unresolved": 0,
"project/linebreak-between-tests": 2
}
},
"jest": {

View File

@ -0,0 +1,27 @@
module.exports = {
create(context) {
return {
CallExpression(node) {
const args = node.arguments
if (
node.callee.name === 'test' &&
args[0].type === 'Literal' &&
args[1].type === 'ArrowFunctionExpression'
) {
const next = context.getTokenAfter(node)
if (
next &&
next.value === 'test' &&
node.loc.end.line + 1 === next.loc.start.line
) {
context.report({
node: context.getLastToken(node),
message: 'Linebreak should be inserted between test blocks.',
fix: fixer => fixer.insertTextAfter(node, '\n'),
})
}
}
},
}
},
}

View File

@ -12,6 +12,7 @@ test('preview color', () => {
expect(document.body.classList.contains('skin-blue')).toBeFalse()
expect(document.body.classList.contains('skin-yellow')).toBeTrue()
})
test('submit color', () => {
Vue.prototype.$http.post.mockResolvedValue({ errno: 0, msg: '' })
const wrapper = mount(Customization)

View File

@ -23,6 +23,7 @@ test('render dependencies', async () => {
expect(wrapper.find('span.label.bg-green').text()).toBe('a: ^1.0.0')
expect(wrapper.find('span.label.bg-red').text()).toBe('c: ^2.0.0')
})
test('render operation buttons', async () => {
Vue.prototype.$http.get.mockResolvedValue([
{
@ -47,6 +48,7 @@ test('render operation buttons', async () => {
expect(tbody.find('tr:nth-child(3)').text()).toContain('admin.enablePlugin')
expect(tbody.find('tr:nth-child(4)').text()).toContain('admin.installPlugin')
})
test('install plugin', async () => {
Vue.prototype.$http.get.mockResolvedValue([
{
@ -70,6 +72,7 @@ test('install plugin', async () => {
await wrapper.vm.$nextTick()
expect(wrapper.text()).toContain('admin.enablePlugin')
})
test('update plugin', async () => {
Vue.prototype.$http.get.mockResolvedValue([
{

View File

@ -85,6 +85,7 @@ test('change texture', async () => {
expect(wrapper.html()).toContain('/preview/64/5.png')
expect(window.$).toBeCalledWith('.modal')
})
test('change player name', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -117,6 +118,7 @@ test('change player name', async () => {
await flushPromises()
expect(wrapper.text()).toContain('new')
})
test('change owner', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -146,6 +148,7 @@ test('change owner', async () => {
await flushPromises()
expect(wrapper.text()).toContain('3')
})
test('delete player', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [

View File

@ -24,6 +24,7 @@ test('render dependencies', async () => {
expect(wrapper.find('span.label.bg-green').text()).toBe('a: ^1.0.0')
expect(wrapper.find('span.label.bg-red').text()).toBe('c: ^2.0.0')
})
test('render operation buttons', async () => {
Vue.prototype.$http.get.mockResolvedValue([
{
@ -46,6 +47,7 @@ test('render operation buttons', async () => {
expect(tbody.find('tr:nth-child(3)').text()).toContain('admin.enablePlugin')
expect(tbody.find('tr:nth-child(3)').text()).toContain('admin.deletePlugin')
})
test('enable plugin', async () => {
Vue.prototype.$http.get.mockResolvedValue([
{
@ -95,6 +97,7 @@ test('enable plugin', async () => {
await flushPromises()
expect(wrapper.text()).toContain('admin.disablePlugin')
})
test('disable plugin', async () => {
jest.spyOn(toastr, 'success')
Vue.prototype.$http.get.mockResolvedValue([
@ -120,6 +123,7 @@ test('disable plugin', async () => {
expect(toastr.success).toBeCalledWith('0')
expect(wrapper.text()).toContain('admin.enablePlugin')
})
test('delete plugin', async () => {
jest.spyOn(toastr, 'success')
Vue.prototype.$http.get.mockResolvedValue([

View File

@ -14,6 +14,7 @@ test('button should be disabled if update is unavailable', () => {
const wrapper = mount(Update)
expect(wrapper.find('.btn').attributes('disabled')).toBe('disabled')
})
test('perform update', async () => {
window.$ = jest.fn(() => ({
modal() {},

View File

@ -75,6 +75,7 @@ test('humanize permission', async () => {
expect(text).toContain('admin.admin')
expect(text).toContain('admin.superAdmin')
})
test('generate players page link', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -85,6 +86,7 @@ test('generate players page link', async () => {
await wrapper.vm.$nextTick()
expect(wrapper.find('[data-toggle="tooltip"]').attributes('href')).toBe('/admin/players?uid=1')
})
test('admin option should not be displayed for super admins', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -97,6 +99,7 @@ test('admin option should not be displayed for super admins', async () => {
expect(text).not.toContain('admin.setAdmin')
expect(text).not.toContain('admin.unsetAdmin')
})
test('banning option should not be displayed for super admins', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -109,6 +112,7 @@ test('banning option should not be displayed for super admins', async () => {
expect(text).not.toContain('admin.ban')
expect(text).not.toContain('admin.unban')
})
test('admin option should be displayed for admin as super admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -123,6 +127,7 @@ test('admin option should be displayed for admin as super admin', async () => {
expect(text).toContain('admin.unsetAdmin')
expect(text).not.toContain('admin.setAdmin')
})
test('banning option should not be displayed for admin as super admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -137,6 +142,7 @@ test('banning option should not be displayed for admin as super admin', async ()
expect(text).not.toContain('admin.ban')
expect(text).not.toContain('admin.unban')
})
test('admin option should be displayed for normal users as super admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -151,6 +157,7 @@ test('admin option should be displayed for normal users as super admin', async (
expect(text).toContain('admin.setAdmin')
expect(text).not.toContain('admin.unsetAdmin')
})
test('banning option should be displayed for normal users as super admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -165,6 +172,7 @@ test('banning option should be displayed for normal users as super admin', async
expect(text).toContain('admin.ban')
expect(text).not.toContain('admin.unban')
})
test('admin option should not be displayed for banned users as super admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -179,6 +187,7 @@ test('admin option should not be displayed for banned users as super admin', asy
expect(text).not.toContain('admin.setAdmin')
expect(text).not.toContain('admin.unsetAdmin')
})
test('banning option should be displayed for banned users as super admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -192,6 +201,7 @@ test('banning option should be displayed for banned users as super admin', async
const text = wrapper.find('.vgt-table').text()
expect(text).toContain('admin.unban')
})
test('admin option should not be displayed for other admins as admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -206,6 +216,7 @@ test('admin option should not be displayed for other admins as admin', async ()
expect(text).not.toContain('admin.setAdmin')
expect(text).not.toContain('admin.unsetAdmin')
})
test('banning option should not be displayed for other admins as admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -220,6 +231,7 @@ test('banning option should not be displayed for other admins as admin', async (
expect(text).not.toContain('admin.ban')
expect(text).not.toContain('admin.unban')
})
test('admin option should not be displayed for normal users as admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -234,6 +246,7 @@ test('admin option should not be displayed for normal users as admin', async ()
expect(text).not.toContain('admin.setAdmin')
expect(text).not.toContain('admin.unsetAdmin')
})
test('banning option should be displayed for normal users as admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -248,6 +261,7 @@ test('banning option should be displayed for normal users as admin', async () =>
expect(text).toContain('admin.ban')
expect(text).not.toContain('admin.unban')
})
test('admin option should not be displayed for banned users as admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -262,6 +276,7 @@ test('admin option should not be displayed for banned users as admin', async ()
expect(text).not.toContain('admin.setAdmin')
expect(text).not.toContain('admin.unsetAdmin')
})
test('banning option should be displayed for banned users as admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -275,6 +290,7 @@ test('banning option should be displayed for banned users as admin', async () =>
const text = wrapper.find('.vgt-table').text()
expect(text).toContain('admin.unban')
})
test('deletion button should not be displayed for super admins', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -285,6 +301,7 @@ test('deletion button should not be displayed for super admins', async () => {
await wrapper.vm.$nextTick()
expect(wrapper.find('.btn-danger').attributes('disabled')).toBe('disabled')
})
test('deletion button should be displayed for admins as super admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -297,6 +314,7 @@ test('deletion button should be displayed for admins as super admin', async () =
await wrapper.vm.$nextTick()
expect(wrapper.find('.btn-danger').attributes('disabled')).toBeNil()
})
test('deletion button should be displayed for normal users as super admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -309,6 +327,7 @@ test('deletion button should be displayed for normal users as super admin', asyn
await wrapper.vm.$nextTick()
expect(wrapper.find('.btn-danger').attributes('disabled')).toBeNil()
})
test('deletion button should be displayed for banned users as super admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -321,6 +340,7 @@ test('deletion button should be displayed for banned users as super admin', asyn
await wrapper.vm.$nextTick()
expect(wrapper.find('.btn-danger').attributes('disabled')).toBeNil()
})
test('deletion button should not be displayed for other admins as admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -333,6 +353,7 @@ test('deletion button should not be displayed for other admins as admin', async
await wrapper.vm.$nextTick()
expect(wrapper.find('.btn-danger').attributes('disabled')).toBe('disabled')
})
test('deletion button should be displayed for normal users as admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -345,6 +366,7 @@ test('deletion button should be displayed for normal users as admin', async () =
await wrapper.vm.$nextTick()
expect(wrapper.find('.btn-danger').attributes('disabled')).toBeNil()
})
test('deletion button should be displayed for banned users as admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -357,6 +379,7 @@ test('deletion button should be displayed for banned users as admin', async () =
await wrapper.vm.$nextTick()
expect(wrapper.find('.btn-danger').attributes('disabled')).toBeNil()
})
test('change email', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -391,6 +414,7 @@ test('change email', async () => {
await flushPromises()
expect(wrapper.text()).toContain('d@e.f')
})
test('toggle verification', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -415,6 +439,7 @@ test('toggle verification', async () => {
await flushPromises()
expect(wrapper.text()).toContain('admin.verified')
})
test('change nickname', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -449,6 +474,7 @@ test('change nickname', async () => {
await flushPromises()
expect(wrapper.text()).toContain('new')
})
test('change password', async () => {
jest.spyOn(toastr, 'success')
jest.spyOn(toastr, 'warning')
@ -484,6 +510,7 @@ test('change password', async () => {
await flushPromises()
expect(toastr.warning).toBeCalledWith('1')
})
test('change score', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -515,6 +542,7 @@ test('change score', async () => {
await flushPromises()
expect(wrapper.text()).toContain('45')
})
test('toggle admin', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -547,6 +575,7 @@ test('toggle admin', async () => {
await flushPromises()
expect(wrapper.text()).toContain('admin.normal')
})
test('toggle ban', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [
@ -579,6 +608,7 @@ test('toggle ban', async () => {
await flushPromises()
expect(wrapper.text()).toContain('admin.ban')
})
test('delete user', async () => {
Vue.prototype.$http.get.mockResolvedValue({
data: [

View File

@ -8,6 +8,7 @@ test('click to refresh captcha', () => {
wrapper.find('img').trigger('click')
expect(Date.now).toBeCalledTimes(2)
})
test('submit forgot form', async () => {
jest.spyOn(Date, 'now')
Vue.prototype.$http.post

View File

@ -10,6 +10,7 @@ test('show captcha if too many login fails', () => {
const wrapper = mount(Login)
expect(wrapper.find('img').attributes('src')).toMatch(/\/auth\/captcha\?v=\d+/)
})
test('click to refresh captcha', () => {
window.blessing.extra = { tooManyFails: true }
jest.spyOn(Date, 'now')
@ -17,6 +18,7 @@ test('click to refresh captcha', () => {
wrapper.find('img').trigger('click')
expect(Date.now).toBeCalledTimes(2)
})
test('login', async () => {
window.blessing.extra = { tooManyFails: false }
Vue.prototype.$http.post

View File

@ -13,6 +13,7 @@ test('click to refresh captcha', () => {
wrapper.find('img').trigger('click')
expect(Date.now).toBeCalledTimes(2)
})
test('require player name', () => {
window.blessing.extra = { player: true }
@ -22,6 +23,7 @@ test('require player name', () => {
window.blessing.extra = { player: false }
})
test('register', async () => {
jest.spyOn(Date, 'now')
Vue.prototype.$http.post
@ -97,6 +99,7 @@ test('register', async () => {
jest.runAllTimers()
expect(swal).toBeCalledWith({ type: 'success', text: 'ok' })
})
test('register with player name', async () => {
window.blessing.extra = { player: true }
Vue.prototype.$http.post.mockResolvedValue({ errno: 0, msg: 'ok' })

View File

@ -12,21 +12,25 @@ test('initialize skinview3d', () => {
expect(wrapper.vm.viewer.camera.position.z).toBe(70)
expect(stub).toBeCalledWith(expect.any(HTMLElement))
})
test('dispose viewer before destroy', () => {
const wrapper = mount(Previewer)
wrapper.destroy()
expect(wrapper.vm.viewer.disposed).toBeTrue()
})
test('skin URL should be updated', () => {
const wrapper = mount(Previewer)
wrapper.setProps({ skin: 'abc' })
expect(wrapper.vm.viewer.skinUrl).toBe('abc')
})
test('cape URL should be updated', () => {
const wrapper = mount(Previewer)
wrapper.setProps({ cape: 'abc' })
expect(wrapper.vm.viewer.capeUrl).toBe('abc')
})
test('`footer` slot', () => {
const wrapper = mount(Previewer, {
slots: {
@ -35,10 +39,12 @@ test('`footer` slot', () => {
})
expect(wrapper.find('#footer').exists()).toBeTrue()
})
test('disable closet mode', () => {
const wrapper = mount(Previewer)
expect(wrapper.find('.badge').text()).toBe('')
})
test('enable closet mode', () => {
const wrapper = mount(Previewer, {
propsData: {
@ -56,6 +62,7 @@ test('enable closet mode', () => {
wrapper.setProps({ skin: 'abc', cape: 'abc' })
expect(wrapper.find('.badge').text()).toBe('general.skin & general.cape')
})
test('toggle pause', () => {
const wrapper = mount(Previewer)
const pauseButton = wrapper.find('.fa-pause')
@ -64,17 +71,20 @@ test('toggle pause', () => {
expect(wrapper.find('.fa-play').exists()).toBeTrue()
expect(wrapper.find('.fa-pause').exists()).toBeFalse()
})
test('toggle run', () => {
const wrapper = mount(Previewer)
wrapper.find('.fa-forward').trigger('click')
expect(wrapper.vm.handles.run.paused).toBeFalse()
expect(wrapper.vm.handles.walk.paused).toBeTrue()
})
test('toggle rotate', () => {
const wrapper = mount(Previewer)
wrapper.find('.fa-redo-alt').trigger('click')
expect(wrapper.vm.handles.rotate.paused).toBeTrue()
})
test('reset', () => {
mockedSkinview3d.SkinViewer.prototype.dispose = jest.fn(function () {
this.disposed = true
@ -83,6 +93,7 @@ test('reset', () => {
wrapper.find('.fa-stop').trigger('click')
expect(mockedSkinview3d.SkinViewer.prototype.dispose).toBeCalled()
})
test('custom title', () => {
const wrapper = mount(Previewer, { propsData: { title: 'custom-title' } })
expect(wrapper.text()).toContain('custom-title')

View File

@ -22,6 +22,7 @@ test('empty skin library', () => {
const wrapper = mount(List)
expect(wrapper.text()).toContain('general.noResult')
})
test('toggle texture type', () => {
Vue.prototype.$http.get.mockResolvedValue({
items: [], total_pages: 0, current_uid: 0,
@ -114,6 +115,7 @@ test('sort items', () => {
)
expect(wrapper.text()).toContain('skinlib.sort.time')
})
test('search by keyword', () => {
Vue.prototype.$http.get.mockResolvedValue({
items: [], total_pages: 0, current_uid: 0,
@ -162,6 +164,7 @@ test('reset all filters', () => {
wrapper.find('.btn-warning').trigger('click')
expect(Vue.prototype.$http.get).toBeCalledTimes(1)
})
test('is anonymous', () => {
Vue.prototype.$http.get.mockResolvedValue({
items: [], total_pages: 0, current_uid: 0,
@ -169,6 +172,7 @@ test('is anonymous', () => {
const wrapper = mount(List)
expect(wrapper.vm.anonymous).toBeTrue()
})
test('on page changed', () => {
Vue.prototype.$http.get.mockResolvedValue({
items: [], total_pages: 0, current_uid: 0,

View File

@ -32,6 +32,7 @@ test('button for adding to closet should be disabled if not auth', () => {
})
expect(wrapper.find('.btn-primary').attributes('disabled')).toBe('disabled')
})
test('button for adding to closet should be disabled if auth', () => {
Vue.prototype.$http.get.mockResolvedValue({})
Object.assign(window.blessing.extra, { inCloset: true, currentUid: 1 })
@ -43,6 +44,7 @@ test('button for adding to closet should be disabled if auth', () => {
})
expect(wrapper.find('.btn-primary').text()).toBe('skinlib.removeFromCloset')
})
test('likes count indicator', async () => {
Vue.prototype.$http.get.mockResolvedValue({ likes: 2 })
const wrapper = mount(Show, {
@ -55,6 +57,7 @@ test('likes count indicator', async () => {
expect(wrapper.find('.likes').attributes('style')).toContain('color: rgb(224, 53, 59)')
expect(wrapper.find('.likes').text()).toContain('2')
})
test('render basic information', async () => {
Vue.prototype.$http.get.mockResolvedValue({
name: 'my-texture',
@ -77,6 +80,7 @@ test('render basic information', async () => {
expect(text).toContain('2018')
expect(text).toContain('author')
})
test('render action text of editing texture name', async () => {
Object.assign(window.blessing.extra, { admin: true })
Vue.prototype.$http.get.mockResolvedValue({ uploader: 1, name: 'name' })
@ -98,6 +102,7 @@ test('render action text of editing texture name', async () => {
await wrapper.vm.$nextTick()
expect(wrapper.contains('small')).toBeFalse()
})
test('render nickname of uploader', () => {
Object.assign(window.blessing.extra, { nickname: null })
Vue.prototype.$http.get.mockResolvedValue({})
@ -108,6 +113,7 @@ test('render nickname of uploader', () => {
})
expect(wrapper.text()).toContain('general.unexistent-user')
})
test('operation panel should not be rendered if not auth', () => {
Object.assign(window.blessing.extra, { currentUid: 0 })
Vue.prototype.$http.get.mockResolvedValue({})
@ -118,6 +124,7 @@ test('operation panel should not be rendered if not auth', () => {
})
expect(wrapper.contains('.box-warning')).toBeFalse()
})
test('link to downloading texture', async () => {
Object.assign(window.blessing.extra, { download: false })
Vue.prototype.$http.get.mockResolvedValue({ hash: '123' })
@ -130,6 +137,7 @@ test('link to downloading texture', async () => {
expect(wrapper.contains('a[title="123"]')).toBeFalse()
expect(wrapper.contains('span[title="123"]')).toBeTrue()
})
test('set as avatar', () => {
Object.assign(window.blessing.extra, { currentUid: 1, inCloset: true })
Vue.prototype.$http.get.mockResolvedValueOnce({ type: 'steve' })
@ -151,6 +159,7 @@ test('set as avatar', () => {
})
expect(noSetAsAvatar.find('button.btn-default').isEmpty()).toBeTrue()
})
test('add to closet', async () => {
Object.assign(window.blessing.extra, { currentUid: 1, inCloset: false })
Vue.prototype.$http.get.mockResolvedValue({ name: 'wow', likes: 2 })
@ -190,6 +199,7 @@ test('add to closet', async () => {
expect(wrapper.vm.likes).toBe(3)
expect(wrapper.vm.liked).toBeTrue()
})
test('remove from closet', async () => {
Object.assign(window.blessing.extra, { currentUid: 1, inCloset: true })
Vue.prototype.$http.get.mockResolvedValue({ likes: 2 })
@ -223,6 +233,7 @@ test('remove from closet', async () => {
expect(wrapper.vm.likes).toBe(1)
expect(wrapper.vm.liked).toBeFalse()
})
test('change texture name', async () => {
Object.assign(window.blessing.extra, { admin: true })
Vue.prototype.$http.get.mockResolvedValue({ name: 'old-name' })
@ -259,6 +270,7 @@ test('change texture name', async () => {
await flushPromises()
expect(wrapper.vm.name).toBe('new-name')
})
test('change texture model', async () => {
Vue.prototype.$http.get.mockResolvedValue({ type: 'steve' })
Vue.prototype.$http.post
@ -291,6 +303,7 @@ test('change texture model', async () => {
await flushPromises()
expect(wrapper.vm.type).toBe('alex')
})
test('toggle privacy', async () => {
Vue.prototype.$http.get.mockResolvedValue({ public: true })
Vue.prototype.$http.post
@ -326,6 +339,7 @@ test('toggle privacy', async () => {
await flushPromises()
expect(wrapper.vm.public).toBeTrue()
})
test('delete texture', async () => {
Vue.prototype.$http.get.mockResolvedValue({})
Vue.prototype.$http.post

View File

@ -15,6 +15,7 @@ test('urls', () => {
expect(wrapper.find('a').attributes('href')).toBe('/skinlib/show/1')
expect(wrapper.find('img').attributes('src')).toBe('/preview/1.png')
})
test('render basic information', () => {
const wrapper = mount(SkinLibItem, {
propsData: {
@ -26,6 +27,7 @@ test('render basic information', () => {
expect(wrapper.text()).toContain('test')
expect(wrapper.text()).toContain('skinlib.filter.steve')
})
test('anonymous user', () => {
const wrapper = mount(SkinLibItem, {
propsData: { anonymous: true },
@ -35,6 +37,7 @@ test('anonymous user', () => {
button.trigger('click')
expect(Vue.prototype.$http.post).not.toBeCalled()
})
test('private texture', () => {
const wrapper = mount(SkinLibItem, {
propsData: { isPublic: false },
@ -44,6 +47,7 @@ test('private texture', () => {
wrapper.setProps({ isPublic: true })
expect(wrapper.text()).not.toContain('skinlib.private')
})
test('liked state', () => {
const wrapper = mount(SkinLibItem, {
propsData: { liked: true, anonymous: false },
@ -57,6 +61,7 @@ test('liked state', () => {
expect(button.attributes('title')).toBe('skinlib.addToCloset')
expect(button.classes('liked')).toBeFalse()
})
test('remove from closet', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
@ -86,6 +91,7 @@ test('remove from closet', async () => {
await flushPromises()
expect(wrapper.emitted('like-toggled')[0]).toEqual([false])
})
test('add to closet', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })

View File

@ -30,6 +30,7 @@ test('display drap and drop notice', () => {
wrapper.setData({ files: [{}] })
expect(wrapper.contains('img')).toBeTrue()
})
test('button for removing texture', () => {
const wrapper = mount(Upload, {
stubs: ['file-upload'],
@ -46,6 +47,7 @@ test('button for removing texture', () => {
button.trigger('click')
expect(wrapper.vm.texture).toBe('')
})
test('notice should be display if texture is private', () => {
const wrapper = mount(Upload, {
stubs: ['file-upload'],
@ -54,6 +56,7 @@ test('notice should be display if texture is private', () => {
wrapper.find('[type=checkbox]').setChecked()
expect(wrapper.find('.callout').text()).toBe('privacyNotice')
})
test('display score cost', () => {
const origin = Vue.prototype.$t
Vue.prototype.$t = (key, args) => `${key}${JSON.stringify(args)}`
@ -67,6 +70,7 @@ test('display score cost', () => {
Vue.prototype.$t = origin
})
test('process input file', () => {
window.URL.createObjectURL = jest.fn().mockReturnValue('file-url')
jest.spyOn(window, 'Image')
@ -107,6 +111,7 @@ test('process input file', () => {
window.Image.mockRestore()
})
test('upload file', async () => {
window.Request = jest.fn()
Vue.prototype.$http.post

View File

@ -74,6 +74,7 @@ test('different categories', () => {
.classes('active')).toBeTrue()
expect(wrapper.find('#cape-category').classes('active')).toBeTrue()
})
test('search textures', () => {
Vue.prototype.$http.get.mockResolvedValue({})
@ -100,6 +101,7 @@ test('empty closet', () => {
wrapper.setData({ category: 'cape' })
expect(wrapper.find('#cape-category').text()).toContain('user.emptyClosetMsg')
})
test('no matched search result', () => {
Vue.prototype.$http.get.mockResolvedValue({})
const wrapper = mount(Closet)
@ -108,6 +110,7 @@ test('no matched search result', () => {
wrapper.setData({ category: 'cape' })
expect(wrapper.find('#cape-category').text()).toContain('general.noResult')
})
test('render items', async () => {
Vue.prototype.$http.get.mockResolvedValue({
items: [
@ -121,6 +124,7 @@ test('render items', async () => {
await wrapper.vm.$nextTick()
expect(wrapper.findAll(ClosetItem)).toHaveLength(2)
})
test('reload closet when page changed', () => {
Vue.prototype.$http.get.mockResolvedValue({})
const wrapper = mount(Closet)
@ -128,6 +132,7 @@ test('reload closet when page changed', () => {
jest.runAllTicks()
expect(Vue.prototype.$http.get).toBeCalledTimes(2)
})
test('remove skin item', () => {
Vue.prototype.$http.get.mockResolvedValue({})
const wrapper = mount(Closet)
@ -135,6 +140,7 @@ test('remove skin item', () => {
wrapper.vm.removeSkinItem(0)
expect(wrapper.find('#skin-category').text()).toContain('user.emptyClosetMsg')
})
test('remove cape item', () => {
Vue.prototype.$http.get.mockResolvedValue({})
const wrapper = mount(Closet)
@ -142,12 +148,14 @@ test('remove cape item', () => {
wrapper.vm.removeCapeItem(0)
expect(wrapper.find('#cape-category').text()).toContain('user.emptyClosetMsg')
})
test('compute avatar URL', () => {
Vue.prototype.$http.get.mockResolvedValue({})
const wrapper = mount(Closet)
const { avatarUrl } = wrapper.vm
expect(avatarUrl({ tid_skin: 1 })).toBe('/avatar/35/1')
})
test('select texture', async () => {
Vue.prototype.$http.get
.mockResolvedValueOnce({})
@ -169,6 +177,7 @@ test('select texture', async () => {
expect(Vue.prototype.$http.get).toBeCalledWith('/skinlib/info/2')
expect(wrapper.vm.capeUrl).toBe('/textures/b')
})
test('apply texture', async () => {
window.$ = jest.fn(() => ({
iCheck: () => ({
@ -203,6 +212,7 @@ test('apply texture', async () => {
expect(wrapper.find('.modal-body').text()).toContain('name')
jest.runAllTimers()
})
test('submit applying texture', async () => {
window.$ = jest.fn(() => ({ modal() {} }))
jest.spyOn(toastr, 'info')
@ -246,6 +256,7 @@ test('submit applying texture', async () => {
await wrapper.vm.$nextTick()
expect(swal).toBeCalledWith({ type: 'success', text: 'ok' })
})
test('reset selected texture', () => {
Vue.prototype.$http.get.mockResolvedValue({})
const wrapper = mount(Closet)
@ -265,6 +276,7 @@ test('reset selected texture', () => {
capeUrl: '',
}))
})
test('select specified texture initially', async () => {
window.history.pushState({}, 'title', `${location.href}?tid=1`)
window.$ = jest.fn(() => ({

View File

@ -20,10 +20,12 @@ test('computed values', () => {
expect(wrapper.find('img').attributes('src')).toBe('/preview/1.png')
expect(wrapper.find('a.more').attributes('href')).toBe('/skinlib/show/1')
})
test('selected item', () => {
const wrapper = mount(ClosetItem, { propsData: factory({ selected: true }) })
expect(wrapper.find('.item').classes('item-selected')).toBeTrue()
})
test('click item body', () => {
const wrapper = mount(ClosetItem, { propsData: factory() })
@ -33,6 +35,7 @@ test('click item body', () => {
wrapper.find('.item-body').trigger('click')
expect(wrapper.emitted().select).toBeTruthy()
})
test('rename texture', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 0 })

View File

@ -31,6 +31,7 @@ test('fetch score info', () => {
mount(Dashboard)
expect(Vue.prototype.$http.get).toBeCalledWith('/user/score-info')
})
test('players usage', async () => {
Vue.prototype.$http.get.mockResolvedValue(scoreInfo())
const wrapper = mount(Dashboard)
@ -38,6 +39,7 @@ test('players usage', async () => {
expect(wrapper.text()).toContain('3 / 15')
expect(wrapper.find('.progress-bar-aqua').attributes('style')).toBe('width: 20%;')
})
test('storage usage', async () => {
Vue.prototype.$http.get
.mockResolvedValueOnce(scoreInfo())
@ -61,12 +63,14 @@ test('storage usage', async () => {
expect(wrapper.text()).toContain('2 / 4 MB')
expect(wrapper.find('.progress-bar-yellow').attributes('style')).toBe('width: 50%;')
})
test('display score', async () => {
Vue.prototype.$http.get.mockResolvedValue(scoreInfo())
const wrapper = mount(Dashboard)
await wrapper.vm.$nextTick()
expect(wrapper.find('#score').text()).toContain('835')
})
test('button `sign` state', async () => {
Vue.prototype.$http.get
.mockResolvedValueOnce(scoreInfo({ signAfterZero: true }))
@ -93,6 +97,7 @@ test('button `sign` state', async () => {
await wrapper.vm.$nextTick()
expect(wrapper.find('button').attributes('disabled')).toBe('disabled')
})
test('remaining time', async () => {
const origin = Vue.prototype.$t
Vue.prototype.$t = (key, args) => key + JSON.stringify(args)
@ -117,6 +122,7 @@ test('remaining time', async () => {
Vue.prototype.$t = origin
})
test('sign', async () => {
jest.spyOn(toastr, 'warning')
swal.mockResolvedValue()

View File

@ -10,6 +10,7 @@ test('message box should not be render if verified', () => {
const wrapper = mount(EmailVerification)
expect(wrapper.isEmpty()).toBeTrue()
})
test('resend email', async () => {
window.blessing.extra = { unverified: true }
Vue.prototype.$http.post

View File

@ -18,11 +18,13 @@ test('display player name constraints', () => {
expect(text).toContain('rule')
expect(text).toContain('length')
})
test('fetch players data before mount', () => {
Vue.prototype.$http.get.mockResolvedValue([])
mount(Players)
expect(Vue.prototype.$http.get).toBeCalledWith('/user/player/list')
})
test('click to preview player', async () => {
Vue.prototype.$http.get
.mockResolvedValueOnce([
@ -56,6 +58,7 @@ test('click to preview player', async () => {
await flushPromises()
expect(Vue.prototype.$http.get).toBeCalledWith('/skinlib/info/2')
})
test('change player name', async () => {
Vue.prototype.$http.get
.mockResolvedValueOnce([
@ -89,6 +92,7 @@ test('change player name', async () => {
await flushPromises()
expect(wrapper.text()).toContain('new-name')
})
test('load iCheck', async () => {
Vue.prototype.$http.get
.mockResolvedValueOnce([
@ -109,6 +113,7 @@ test('load iCheck', async () => {
wrapper.find('.btn-warning').trigger('click')
expect(window.$).toBeCalled()
})
test('delete player', async () => {
Vue.prototype.$http.get
.mockResolvedValueOnce([
@ -133,12 +138,14 @@ test('delete player', async () => {
await flushPromises()
expect(wrapper.text()).not.toContain('to-be-deleted')
})
test('toggle preview mode', () => {
Vue.prototype.$http.get.mockResolvedValueOnce([])
const wrapper = mount(Players)
wrapper.find('[data-test="to2d"]').trigger('click')
expect(wrapper.text()).toContain('user.player.texture-empty')
})
test('add player', async () => {
window.$ = jest.fn(() => ({ modal() {} }))
Vue.prototype.$http.get.mockResolvedValueOnce([])
@ -163,6 +170,7 @@ test('add player', async () => {
await flushPromises()
expect(Vue.prototype.$http.get).toBeCalledTimes(2)
})
test('clear texture', async () => {
window.$ = jest.fn(() => ({ modal() {} }))
Vue.prototype.$http.get.mockResolvedValueOnce([

View File

@ -17,6 +17,7 @@ test('computed values', () => {
window.blessing.extra = { admin: false }
expect(mount(Profile).vm.isAdmin).toBeFalse()
})
test('convert linebreak', () => {
const wrapper = mount(Profile)
expect(wrapper.vm.nl2br('a\nb\nc')).toBe('a<br>b<br>c')
@ -87,6 +88,7 @@ test('change password', async () => {
await wrapper.vm.$nextTick()
expect(swal).toBeCalledWith({ type: 'success', text: 'o' })
})
test('change nickname', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: 'w' })
@ -129,6 +131,7 @@ test('change nickname', async () => {
await flushPromises()
expect(swal).toBeCalledWith({ type: 'success', text: 'o' })
})
test('change email', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: 'w' })
@ -171,6 +174,7 @@ test('change email', async () => {
await flushPromises()
expect(swal).toBeCalledWith({ type: 'success', text: 'o' })
})
test('delete account', async () => {
window.blessing.extra = { admin: true }
swal.mockResolvedValue()

View File

@ -30,6 +30,7 @@ test('check for BS updates', async () => {
await checkForUpdates()
expect(document.querySelector('a').innerHTML).toContain('4.0.0')
})
test('check for plugins updates', async () => {
window.fetch = jest.fn()
.mockResolvedValueOnce({ ok: false })

View File

@ -3,6 +3,7 @@ import * as emitter from '@/js/event'
test('mount variable to global', () => {
expect(window.bsEmitter).toBeFrozen()
})
test('add listener and emit event', () => {
const mockA = jest.fn()
const mockB = jest.fn()

View File

@ -4,6 +4,7 @@ import Vue from 'vue'
test('mount to global', () => {
expect(window.trans).toBe(trans)
})
test('translate text', () => {
window.blessing.i18n = { a: { b: { c: 'text', d: 'Hi, :name!' } } }
expect(trans('a.b.c')).toBe('text')
@ -11,6 +12,7 @@ test('translate text', () => {
expect(trans('a.b.d', { name: 'me' })).toBe('Hi, me!')
expect(trans('d.e')).toBe('d.e')
})
test('Vue directive', () => {
const byString = Vue.extend({
render(h) {

View File

@ -33,6 +33,7 @@ test('the GET method', async () => {
await net.get('/abc')
expect(window.fetch.mock.calls[1][0].url).toBe('/abc')
})
test('the POST method', async () => {
window.fetch = jest.fn()
.mockResolvedValue({
@ -74,6 +75,7 @@ test('the POST method', async () => {
await net.post('/abc')
expect(window.fetch.mock.calls[2][0].body).toBe('{}')
})
test('low level fetch', async () => {
const json = jest.fn().mockResolvedValue({})
window.fetch = jest.fn()

View File

@ -18,6 +18,7 @@ test('show message', () => {
expect(element.hasClass('callout-info')).toBeTrue()
expect(element.html()).toBe('hi')
})
test('show AJAX error', () => {
$.fn.modal = function () {
document.body.innerHTML = this.html()
@ -25,6 +26,7 @@ test('show AJAX error', () => {
notify.showAjaxError(new Error('an-error'))
expect(document.body.innerHTML).toContain('an-error')
})
test('show modal', () => {
notify.showModal('message')
expect($('.modal-title').html()).toBe('Message')
@ -34,6 +36,7 @@ test('show modal', () => {
destroyOnClose: false,
})
})
test('show sweetalert', () => {
jest.spyOn(Swal, 'fire')
notify.swal({})

View File

@ -10,12 +10,14 @@ test('debounce', () => {
jest.runAllTimers()
expect(stub).toBeCalledTimes(1)
})
test('queryString', () => {
history.pushState({}, 'page', `${location.href}?key=value`)
expect(utils.queryString('key')).toBe('value')
expect(utils.queryString('a')).toBeUndefined()
expect(utils.queryString('a', 'b')).toBe('b')
})
test('queryStringify', () => {
expect(utils.queryStringify({ a: 'b', c: 'd' })).toBe('a=b&c=d')
})

View File

@ -3222,6 +3222,13 @@ eslint-plugin-node@^8.0.1:
resolve "^1.8.1"
semver "^5.5.0"
eslint-plugin-project@^0.2.2:
version "0.2.2"
resolved "https://registry.npmjs.org/eslint-plugin-project/-/eslint-plugin-project-0.2.2.tgz#aace7d7d252dc2403a3167cecf59228b80d983f3"
integrity sha512-76UJdTXg3+y0ix/xRjG2DjWumxV6oUYe7q/rEPDddGgxUpv08ybn4DNzm3h5MOqIZ9qY+m6CG1x6o/fAvQZusQ==
dependencies:
js-yaml "^3.12.1"
eslint-plugin-vue@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-5.2.2.tgz#86601823b7721b70bc92d54f1728cfc03b36283c"
@ -5132,6 +5139,14 @@ js-yaml@^3.12.0, js-yaml@^3.5.2, js-yaml@^3.9.0:
argparse "^1.0.7"
esprima "^4.0.0"
js-yaml@^3.12.1:
version "3.12.2"
resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.2.tgz#ef1d067c5a9d9cb65bd72f285b5d8105c77f14fc"
integrity sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
js-yaml@~3.10.0:
version "3.10.0"
resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc"