Remove "toastr" and "sweetalert2"

This commit is contained in:
Pig Fang 2019-03-25 22:01:57 +08:00
parent 51713c5b16
commit c168970723
59 changed files with 1174 additions and 686 deletions

View File

@ -13,6 +13,7 @@ module.exports = api => ({
helpers: true,
regenerator: true,
}],
'@babel/plugin-proposal-optional-catch-binding',
],
},
development: {
@ -24,6 +25,7 @@ module.exports = api => ({
],
plugins: [
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-proposal-optional-catch-binding',
],
},
test: {
@ -35,6 +37,7 @@ module.exports = api => ({
],
plugins: [
'babel-plugin-dynamic-import-node',
'@babel/plugin-proposal-optional-catch-binding',
],
},
})[api.env()]

View File

@ -21,11 +21,11 @@
"@fortawesome/fontawesome-free": "^5.7.2",
"admin-lte": "^2.4.10",
"echarts": "^4.1.0",
"element-theme-chalk": "^2.6.3",
"element-ui": "^2.6.3",
"icheck": "^1.0.2",
"jquery": "^3.3.1",
"skinview3d": "^1.1.0",
"sweetalert2": "^8.4.0",
"toastr": "^2.1.4",
"vue": "^2.6.9",
"vue-good-table": "^2.16.3",
"vue-recaptcha": "^1.1.1",
@ -34,6 +34,7 @@
},
"devDependencies": {
"@babel/core": "^7.3.4",
"@babel/plugin-proposal-optional-catch-binding": "^7.2.0",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-transform-runtime": "^7.3.4",
"@babel/preset-env": "^7.3.4",
@ -42,7 +43,6 @@
"@types/echarts": "^4.1.7",
"@types/jest": "^24.0.11",
"@types/jquery": "^3.3.9",
"@types/toastr": "^2.1.36",
"@types/webpack": "^4.4.25",
"@typescript-eslint/eslint-plugin": "^1.4.2",
"@typescript-eslint/parser": "^1.4.2",
@ -69,8 +69,10 @@
"jest-extended": "^0.11.1",
"json-loader": "^0.5.7",
"mini-css-extract-plugin": "^0.5.0",
"node-sass": "^4.11.0",
"postcss-loader": "^3.0.0",
"rimraf": "^2.6.3",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.2",

View File

@ -33,8 +33,6 @@
</template>
<script>
import toastr from 'toastr'
import { swal } from '../js/notify'
import setAsAvatar from './mixins/setAsAvatar'
import removeClosetItem from './mixins/removeClosetItem'
@ -74,14 +72,17 @@ export default {
},
methods: {
async rename() {
const { value: newTextureName, dismiss } = await swal({
title: this.$t('user.renameClosetItem'),
input: 'text',
inputValue: this.textureName,
showCancelButton: true,
inputValidator: value => !value && this.$t('skinlib.emptyNewTextureName'),
})
if (dismiss) {
let newTextureName
try {
({ value: newTextureName } = await this.$prompt(
this.$t('user.renameClosetItem'),
{
inputValue: this.textureName,
showCancelButton: true,
inputValidator: value => !!value || this.$t('skinlib.emptyNewTextureName'),
}
))
} catch {
return
}
@ -91,9 +92,9 @@ export default {
)
if (errno === 0) {
this.textureName = newTextureName
toastr.success(msg)
this.$message.success(msg)
} else {
toastr.warning(msg)
this.$message.warning(msg)
}
},
},

View File

@ -15,8 +15,6 @@
</template>
<script>
import { swal } from '../js/notify'
export default {
name: 'EmailVerification',
data() {
@ -29,7 +27,11 @@ export default {
async resend() {
this.pending = true
const { errno, msg } = await this.$http.post('/user/email-verification')
swal({ type: errno === 0 ? 'success' : 'warning', text: msg })
if (errno === 0) {
this.$message.success(msg)
} else {
this.$message.error(msg)
}
this.pending = false
},
},

View File

@ -1,6 +1,5 @@
import Vue from 'vue'
import toastr from 'toastr'
import { swal } from '../../js/notify'
import { MessageBoxInputData } from 'element-ui/types/message-box'
export default Vue.extend<{
name: string,
@ -8,15 +7,18 @@ export default Vue.extend<{
}, { addClosetItem(): Promise<void> }, {}>({
methods: {
async addClosetItem() {
const { dismiss, value } = await swal({
title: this.$t('skinlib.setItemName'),
text: this.$t('skinlib.applyNotice'),
inputValue: this.name,
input: 'text',
showCancelButton: true,
inputValidator: val => (!val && this.$t('skinlib.emptyItemName')) || null,
})
if (dismiss) {
let value: string
try {
({ value } = await this.$prompt(
this.$t('skinlib.applyNotice'),
{
title: this.$t('skinlib.setItemName'),
inputValue: this.name,
showCancelButton: true,
inputValidator: val => !!val || this.$t('skinlib.emptyItemName'),
}
) as MessageBoxInputData)
} catch {
return
}
@ -25,10 +27,10 @@ export default Vue.extend<{
{ tid: this.tid, name: value }
)
if (errno === 0) {
swal({ type: 'success', text: msg })
this.$message.success(msg!)
this.$emit('like-toggled', true)
} else {
toastr.warning(msg!)
this.$message.warning(msg!)
}
},
},

View File

@ -1,6 +1,4 @@
import Vue from 'vue'
import toastr from 'toastr'
import { swal } from '../../js/notify'
export default Vue.extend<{
name: string,
@ -8,12 +6,12 @@ export default Vue.extend<{
}, { removeClosetItem(): Promise<void> }, {}>({
methods: {
async removeClosetItem() {
const { dismiss } = await swal({
text: this.$t('user.removeFromClosetNotice'),
type: 'warning',
showCancelButton: true,
})
if (dismiss) {
try {
await this.$confirm(
this.$t('user.removeFromClosetNotice'),
{ type: 'warning' }
)
} catch {
return
}
@ -23,9 +21,9 @@ export default Vue.extend<{
)
if (errno === 0) {
this.$emit('item-removed')
swal({ type: 'success', text: msg })
this.$message.success(msg!)
} else {
toastr.warning(msg!)
this.$message.warning(msg!)
}
},
},

View File

@ -1,19 +1,16 @@
import Vue from 'vue'
import toastr from 'toastr'
import { swal } from '../../js/notify'
export default Vue.extend<{
tid: number
}, { setAsAvatar(): Promise<void> }, {}>({
methods: {
async setAsAvatar() {
const { dismiss } = await swal({
title: this.$t('user.setAvatar'),
text: this.$t('user.setAvatarNotice'),
type: 'question',
showCancelButton: true,
})
if (dismiss) {
try {
await this.$confirm(
this.$t('user.setAvatarNotice'),
this.$t('user.setAvatar')
)
} catch {
return
}
@ -22,12 +19,12 @@ export default Vue.extend<{
{ tid: this.tid }
)
if (errno === 0) {
toastr.success(msg!)
this.$message.success(msg!)
Array.from(document.querySelectorAll<HTMLImageElement>('[alt="User Image"]'))
.forEach(el => (el.src += `?${new Date().getTime()}`))
} else {
toastr.warning(msg!)
this.$message.warning(msg!)
}
},
},

View File

@ -0,0 +1,2 @@
@import '~element-theme-chalk/src/message.scss';
@import '~element-theme-chalk/src/message-box.scss';

6
resources/assets/src/js/element.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
/* eslint-disable import/no-mutable-exports */
import { ElMessage } from 'element-ui/types/message'
import { ElMessageBox } from 'element-ui/types/message-box'
export let Message: ElMessage
export let MessageBox: ElMessageBox

View File

@ -0,0 +1,16 @@
import Vue from 'vue'
import Message from 'element-ui/lib/message'
import MessageBox from 'element-ui/lib/message-box'
Vue.prototype.$message = Message
Vue.prototype.$msgbox = MessageBox
Vue.prototype.$alert = MessageBox.alert
Vue.prototype.$confirm = MessageBox.confirm
Vue.prototype.$prompt = MessageBox.prompt
window.MessageBox = MessageBox
export {
Message,
MessageBox,
}

View File

@ -2,6 +2,7 @@ import './public-path' // Must be first
import './i18n'
import './net'
import './event'
import './element'
import './layout'
import './logout'
import './check-updates'

View File

@ -1,22 +1,19 @@
import { Message, MessageBox } from './element'
import { post } from './net'
import { swal } from './notify'
import { trans } from './i18n'
export async function logout() {
const { dismiss } = await swal({
text: trans('general.confirmLogout'),
type: 'warning',
showCancelButton: true,
confirmButtonText: trans('general.confirm'),
cancelButtonText: trans('general.cancel'),
})
if (dismiss) {
try {
await MessageBox.confirm(trans('general.confirmLogout'), {
type: 'warning',
})
} catch {
return
}
const { msg } = await post('/auth/logout')
setTimeout(() => (window.location.href = blessing.base_url), 1000)
swal({ type: 'success', text: msg })
Message.success(msg)
}
const button = document.querySelector('#logout-button')

View File

@ -1,7 +1,5 @@
/* eslint-disable max-params */
import $ from 'jquery'
import Swal from 'sweetalert2'
import toastr from 'toastr'
import { ModalOptions } from '../shims'
import { trans } from './i18n'
@ -49,14 +47,4 @@ export function showModal(
.modal(options)
}
const swalInstance = Swal.mixin({
confirmButtonText: trans('general.confirm'),
cancelButtonText: trans('general.cancel'),
})
export function swal(options: import('sweetalert2').SweetAlertOptions) {
return swalInstance.fire(options)
}
Object.assign(window, { toastr, swal })
Object.assign(blessing, { notify: { showModal } })

View File

@ -1,5 +1,6 @@
/* eslint-disable camelcase */
import Vue from 'vue'
import { Message, MessageBox } from 'element-ui'
import * as JQuery from 'jquery'
declare global {

View File

@ -22,9 +22,6 @@ body, h1, h2, h3, h4, h5, h6
opacity 1
filter 'alpha(opacity=100)'
.swal2-popup
font-size 1.6rem !important
.item
display block
background #EFF1F0

View File

@ -33,8 +33,6 @@
</template>
<script>
import toastr from 'toastr'
export default {
name: 'Customization',
data() {
@ -52,7 +50,7 @@ export default {
const { msg } = await this.$http.post('/admin/customize?action=color', {
color_scheme: this.currentSkin,
})
toastr.success(msg)
this.$message.success(msg)
},
},
}

View File

@ -73,8 +73,6 @@
<script>
import { VueGoodTable } from 'vue-good-table'
import 'vue-good-table/dist/vue-good-table.min.css'
import toastr from 'toastr'
import { swal } from '../../js/notify'
import tableOptions from '../../components/mixins/tableOptions'
export default {
@ -134,24 +132,23 @@ export default {
{ name }
)
if (errno === 0) {
toastr.success(msg)
this.$message.success(msg)
this.plugins[originalIndex].update_available = false
this.plugins[originalIndex].installed = true
} else {
swal({ type: 'warning', text: msg })
this.$message.warning(msg)
}
this.installing = ''
},
async updatePlugin(plugin) {
const { dismiss } = await swal({
text: this.$t('admin.confirmUpdate', {
plugin: plugin.title, old: plugin.installed, new: plugin.version,
}),
type: 'question',
showCancelButton: true,
})
if (dismiss) {
try {
await this.$confirm(
this.$t('admin.confirmUpdate', {
plugin: plugin.title, old: plugin.installed, new: plugin.version,
})
)
} catch {
return
}
@ -161,12 +158,12 @@ export default {
name, dependencies: { requirements }, originalIndex,
}) {
if (requirements.length === 0) {
const { dismiss } = await swal({
text: this.$t('admin.noDependenciesNotice'),
type: 'warning',
showCancelButton: true,
})
if (dismiss) {
try {
await this.$confirm(
this.$t('admin.noDependenciesNotice'),
{ type: 'warning' }
)
} catch {
return
}
}
@ -178,7 +175,7 @@ export default {
{ action: 'enable', name }
)
if (errno === 0) {
toastr.success(msg)
this.$message.success(msg)
this.$set(this.plugins[originalIndex], 'enabled', true)
} else {
const div = document.createElement('div')
@ -192,9 +189,9 @@ export default {
ul.appendChild(li)
})
div.appendChild(ul)
swal({
this.$alert(div.innerHTML.replace(/`([\w-_]+)`/g, '<code>$1</code>'), {
dangerouslyUseHTMLString: true,
type: 'warning',
html: div.innerHTML.replace(/`([\w-_]+)`/g, '<code>$1</code>'),
})
}
},

View File

@ -118,8 +118,6 @@
<script>
import { VueGoodTable } from 'vue-good-table'
import 'vue-good-table/dist/vue-good-table.min.css'
import toastr from 'toastr'
import { swal } from '../../js/notify'
import tableOptions from '../../components/mixins/tableOptions'
import serverTable from '../../components/mixins/serverTable'
@ -188,20 +186,20 @@ export default {
)
if (errno === 0) {
player[`tid_${type}`] = tid
toastr.success(msg)
this.$message.success(msg)
$('.modal').modal('hide')
} else {
toastr.warning(msg)
this.$message.warning(msg)
}
},
async changeName(player) {
const { dismiss, value } = await swal({
text: this.$t('admin.changePlayerNameNotice'),
input: 'text',
inputValue: player.name,
inputValidator: name => !name && this.$t('admin.emptyPlayerName'),
})
if (dismiss) {
let value
try {
({ value } = await this.$prompt(this.$t('admin.changePlayerNameNotice'), {
inputValue: player.name,
inputValidator: name => !!name || this.$t('admin.emptyPlayerName'),
}))
} catch {
return
}
@ -211,18 +209,18 @@ export default {
)
if (errno === 0) {
player.name = value
toastr.success(msg)
this.$message.success(msg)
} else {
toastr.warning(msg)
this.$message.warning(msg)
}
},
async changeOwner(player) {
const { dismiss, value } = await swal({
text: this.$t('admin.changePlayerOwner'),
input: 'number',
inputValue: player.uid,
})
if (dismiss) {
let value
try {
({ value } = await this.$prompt(this.$t('admin.changePlayerOwner'), {
inputValue: player.uid,
}))
} catch {
return
}
@ -232,18 +230,17 @@ export default {
)
if (errno === 0) {
player.uid = value
toastr.success(msg)
this.$message.success(msg)
} else {
toastr.warning(msg)
this.$message.warning(msg)
}
},
async deletePlayer({ pid, originalIndex }) {
const { dismiss } = await swal({
text: this.$t('admin.deletePlayerNotice'),
type: 'warning',
showCancelButton: true,
})
if (dismiss) {
try {
await this.$confirm(this.$t('admin.deletePlayerNotice'), {
type: 'warning',
})
} catch {
return
}
@ -253,9 +250,9 @@ export default {
)
if (errno === 0) {
this.$delete(this.players, originalIndex)
toastr.success(msg)
this.$message.success(msg)
} else {
toastr.warning(msg)
this.$message.warning(msg)
}
},
},

View File

@ -77,8 +77,6 @@
<script>
import { VueGoodTable } from 'vue-good-table'
import 'vue-good-table/dist/vue-good-table.min.css'
import toastr from 'toastr'
import { swal } from '../../js/notify'
import tableOptions from '../../components/mixins/tableOptions'
export default {
@ -131,12 +129,12 @@ export default {
name, dependencies: { requirements }, originalIndex,
}) {
if (requirements.length === 0) {
const { dismiss } = await swal({
text: this.$t('admin.noDependenciesNotice'),
type: 'warning',
showCancelButton: true,
})
if (dismiss) {
try {
await this.$confirm(
this.$t('admin.noDependenciesNotice'),
{ type: 'warning' }
)
} catch {
return
}
}
@ -148,7 +146,7 @@ export default {
{ action: 'enable', name }
)
if (errno === 0) {
toastr.success(msg)
this.$message.success(msg)
this.$set(this.plugins[originalIndex], 'enabled', true)
} else {
const div = document.createElement('div')
@ -162,9 +160,9 @@ export default {
ul.appendChild(li)
})
div.appendChild(ul)
swal({
this.$alert(div.innerHTML.replace(/`([\w-_]+)`/g, '<code>$1</code>'), {
dangerouslyUseHTMLString: true,
type: 'warning',
html: div.innerHTML.replace(/`([\w-_]+)`/g, '<code>$1</code>'),
})
}
},
@ -174,19 +172,16 @@ export default {
{ action: 'disable', name }
)
if (errno === 0) {
toastr.success(msg)
this.$message.success(msg)
this.plugins[originalIndex].enabled = false
} else {
swal({ type: 'warning', text: msg })
this.$message.warning(msg)
}
},
async deletePlugin({ name, originalIndex }) {
const { dismiss } = await swal({
text: this.$t('admin.confirmDeletion'),
type: 'warning',
showCancelButton: true,
})
if (dismiss) {
try {
await this.$confirm(this.$t('admin.confirmDeletion'), { type: 'warning' })
} catch {
return
}
@ -196,9 +191,9 @@ export default {
)
if (errno === 0) {
this.$delete(this.plugins, originalIndex)
toastr.success(msg)
this.$message.success(msg)
} else {
swal({ type: 'warning', text: msg })
this.$message.warning(msg)
}
},
},

View File

@ -49,8 +49,6 @@
</template>
<script>
import { swal } from '../../js/notify'
const POLLING_INTERVAL = 500
export default {
@ -85,7 +83,7 @@ export default {
this.updating = false
if (this.downloaded) {
await swal({ type: 'success', text: this.$t('admin.updateCompleted') })
await this.$alert(this.$t('admin.updateCompleted'), { type: 'success' })
window.location = blessing.base_url
}
},
@ -94,7 +92,7 @@ export default {
action,
})
if (errno) {
swal({ type: 'error', text: msg })
this.$alert(msg, { type: 'error' })
this.updating = false
}
},

View File

@ -88,9 +88,7 @@
<script>
import { VueGoodTable } from 'vue-good-table'
import 'vue-good-table/dist/vue-good-table.min.css'
import toastr from 'toastr'
import { trans } from '../../js/i18n'
import { swal } from '../../js/notify'
import tableOptions from '../../components/mixins/tableOptions'
import serverTable from '../../components/mixins/serverTable'
@ -165,14 +163,13 @@ export default {
this.users = data
},
async changeEmail(user) {
const { dismiss, value } = await swal({
text: this.$t('admin.newUserEmail'),
showCancelButton: true,
input: 'email',
inputValue: user.email,
inputValidator: val => !val && this.$t('auth.emptyEmail'),
})
if (dismiss) {
let value
try {
({ value } = await this.$prompt(this.$t('admin.newUserEmail'), {
inputValue: user.email,
inputValidator: val => !!val || this.$t('auth.emptyEmail'),
}))
} catch {
return
}
@ -182,9 +179,9 @@ export default {
)
if (errno === 0) {
user.email = value
toastr.success(msg)
this.$message.success(msg)
} else {
toastr.warning(msg)
this.$message.warning(msg)
}
},
async toggleVerification(user) {
@ -194,20 +191,19 @@ export default {
)
if (errno === 0) {
user.verified = !user.verified
toastr.success(msg)
this.$message.success(msg)
} else {
toastr.warning(msg)
this.$message.warning(msg)
}
},
async changeNickName(user) {
const { dismiss, value } = await swal({
text: this.$t('admin.newUserNickname'),
showCancelButton: true,
input: 'text',
inputValue: user.nickname,
inputValidator: val => !val && this.$t('auth.emptyNickname'),
})
if (dismiss) {
let value
try {
({ value } = await this.$prompt(this.$t('admin.newUserNickname'), {
inputValue: user.nickname,
inputValidator: val => !!val || this.$t('auth.emptyNickname'),
}))
} catch {
return
}
@ -217,18 +213,18 @@ export default {
)
if (errno === 0) {
user.nickname = value
toastr.success(msg)
this.$message.success(msg)
} else {
toastr.warning(msg)
this.$message.warning(msg)
}
},
async changePassword(user) {
const { dismiss, value } = await swal({
text: this.$t('admin.newUserPassword'),
showCancelButton: true,
input: 'password',
})
if (dismiss) {
let value
try {
({ value } = await this.$prompt(this.$t('admin.newUserPassword'), {
inputType: 'password',
}))
} catch {
return
}
@ -236,16 +232,16 @@ export default {
'/admin/users?action=password',
{ uid: user.uid, password: value }
)
errno === 0 ? toastr.success(msg) : toastr.warning(msg)
errno === 0 ? this.$message.success(msg) : this.$message.warning(msg)
},
async changeScore(user) {
const { dismiss, value } = await swal({
text: this.$t('admin.newScore'),
showCancelButton: true,
input: 'number',
inputValue: user.score,
})
if (dismiss) {
let value
try {
({ value } = await this.$prompt(this.$t('admin.newScore'), {
inputType: 'number',
inputValue: user.score,
}))
} catch {
return
}
const score = Number.parseInt(value)
@ -256,30 +252,39 @@ export default {
)
if (errno === 0) {
user.score = score
toastr.success(msg)
this.$message.success(msg)
} else {
toastr.warning(msg)
this.$message.warning(msg)
}
},
async changePermission(user) {
const operator = user.operations
const options = {
'-1': this.$t('admin.banned'),
0: this.$t('admin.normal'),
}
const options = [
this.$t('admin.banned'),
this.$t('admin.normal'),
]
if (operator === 2) {
options[1] = this.$t('admin.admin')
options.push(this.$t('admin.admin'))
}
const h = this.$createElement
const vnode = h('div', null, [
h('span', null, this.$t('admin.newPermission')),
h(
'select',
{ attrs: { selectedIndex: 0 } },
options.map(option => h('option', null, option))
),
])
const { dismiss, value } = await swal({
text: this.$t('admin.newPermission'),
input: 'radio',
inputOptions: options,
showCancelButton: true,
})
if (dismiss) {
try {
await this.$msgbox({
message: vnode,
showCancelButton: true,
})
} catch {
return
}
const value = vnode.children[1].elm.selectedIndex - 1
const { errno, msg } = await this.$http.post('/admin/users?action=permission', {
uid: user.uid,
@ -287,18 +292,17 @@ export default {
})
if (errno === 0) {
user.permission = +value
toastr.success(msg)
this.$message.success(msg)
} else {
toastr.warning(msg)
this.$message.warning(msg)
}
},
async deleteUser({ uid, originalIndex }) {
const { dismiss } = await swal({
text: this.$t('admin.deleteUserNotice'),
type: 'warning',
showCancelButton: true,
})
if (dismiss) {
try {
await this.$confirm(this.$t('admin.deleteUserNotice'), {
type: 'warning',
})
} catch {
return
}
@ -308,9 +312,9 @@ export default {
)
if (errno === 0) {
this.$delete(this.users, originalIndex)
toastr.success(msg)
this.$message.success(msg)
} else {
toastr.warning(msg)
this.$message.warning(msg)
}
},
},

View File

@ -57,7 +57,6 @@
</template>
<script>
import { swal } from '../../js/notify'
import Captcha from '../../components/Captcha.vue'
export default {
@ -115,13 +114,13 @@ export default {
}
)
if (errno === 0) {
swal({ type: 'success', text: msg })
this.$message.success(msg)
setTimeout(() => {
window.location = `${blessing.base_url}/${blessing.redirect_to || 'user'}`
}, 1000)
} else {
if (loginFails > 3 && !this.tooManyFails) {
swal({ type: 'error', text: this.$t('auth.tooManyFails') })
this.$alert(this.$t('auth.tooManyFails'), { type: 'error' })
this.tooManyFails = true
}
this.infoMsg = ''

View File

@ -90,7 +90,6 @@
</template>
<script>
import { swal } from '../../js/notify'
import Captcha from '../../components/Captcha.vue'
export default {
@ -173,7 +172,7 @@ export default {
}, this.requirePlayer ? { player_name: playerName } : { nickname })
)
if (errno === 0) {
swal({ type: 'success', text: msg })
this.$message.success(msg)
setTimeout(() => {
window.location = `${blessing.base_url}/user`
}, 1000)

View File

@ -39,8 +39,6 @@
</template>
<script>
import { swal } from '../../js/notify'
export default {
name: 'Reset',
data() {
@ -81,7 +79,7 @@ export default {
{ password }
)
if (errno === 0) {
await swal({ type: 'success', text: msg })
this.$message.success(msg)
window.location = `${blessing.base_url}/auth/login`
} else {
this.infoMsg = ''

View File

@ -139,8 +139,6 @@
</template>
<script>
import toastr from 'toastr'
import { swal } from '../../js/notify'
import setAsAvatar from '../../components/mixins/setAsAvatar'
import addClosetItem from '../../components/mixins/addClosetItem'
import removeClosetItem from '../../components/mixins/removeClosetItem'
@ -220,14 +218,13 @@ export default {
await this.removeClosetItem()
},
async changeTextureName() {
const { dismiss, value } = await swal({
text: this.$t('skinlib.setNewTextureName'),
input: 'text',
inputValue: this.name,
showCancelButton: true,
inputValidator: name => !name && this.$t('skinlib.emptyNewTextureName'),
})
if (dismiss) {
let value
try {
({ value } = await this.$prompt(this.$t('skinlib.setNewTextureName'), {
inputValue: this.name,
inputValidator: name => !!name || this.$t('skinlib.emptyNewTextureName'),
}))
} catch {
return
}
@ -237,27 +234,30 @@ export default {
)
if (errno === 0) {
this.name = value
toastr.success(msg)
this.$message.success(msg)
} else {
toastr.warning(msg)
this.$message.error(msg)
}
},
async changeModel() {
const { dismiss, value } = await swal({
text: this.$t('skinlib.setNewTextureModel'),
input: 'select',
inputValue: this.type,
inputOptions: {
steve: 'Steve',
alex: 'Alex',
cape: this.$t('general.cape'),
},
showCancelButton: true,
inputClass: 'form-control',
})
if (dismiss) {
const h = this.$createElement
const vnode = h('div', null, [
h('span', null, this.$t('skinlib.setNewTextureModel')),
h('select', { attrs: { selectedIndex: 0 } }, [
h('option', { attrs: { value: 'steve' } }, 'Steve'),
h('option', { attrs: { value: 'alex' } }, 'Alex'),
h('option', { attrs: { value: 'cape' } }, this.$t('general.cape')),
]),
])
try {
await this.$msgbox({
message: vnode,
showCancelButton: true,
})
} catch {
return
}
const value = ['steve', 'alex', 'cape'][vnode.children[1].elm.selectedIndex]
const { errno, msg } = await this.$http.post(
'/skinlib/model',
@ -265,20 +265,20 @@ export default {
)
if (errno === 0) {
this.type = value
toastr.success(msg)
this.$message.success(msg)
} else {
toastr.warning(msg)
this.$message.warning(msg)
}
},
async togglePrivacy() {
const { dismiss } = await swal({
text: this.public
? this.$t('skinlib.setPrivateNotice')
: this.$t('skinlib.setPublicNotice'),
type: 'warning',
showCancelButton: true,
})
if (dismiss) {
try {
await this.$confirm(
this.public
? this.$t('skinlib.setPrivateNotice')
: this.$t('skinlib.setPublicNotice'),
{ type: 'warning' }
)
} catch {
return
}
@ -287,19 +287,19 @@ export default {
{ tid: this.tid }
)
if (errno === 0) {
toastr.success(msg)
this.$message.success(msg)
this.public = !this.public
} else {
toastr.warning(msg)
this.$message.warning(msg)
}
},
async deleteTexture() {
const { dismiss } = await swal({
text: this.$t('skinlib.deleteNotice'),
type: 'warning',
showCancelButton: true,
})
if (dismiss) {
try {
await this.$confirm(
this.$t('skinlib.deleteNotice'),
{ type: 'warning' }
)
} catch {
return
}
@ -308,10 +308,10 @@ export default {
{ tid: this.tid }
)
if (errno === 0) {
await swal({ type: 'success', text: msg })
window.location = `${this.baseUrl}/skinlib`
this.$message.success(msg)
setTimeout(() => (window.location = `${this.baseUrl}/skinlib`), 1000)
} else {
swal({ type: 'warning', text: msg })
this.$message.warning(msg)
}
},
},

View File

@ -112,8 +112,6 @@
<script>
import FileUpload from 'vue-upload-component'
import toastr from 'toastr'
import { swal } from '../../js/notify'
export default {
name: 'Upload',
@ -149,17 +147,17 @@ export default {
methods: {
async upload() {
if (!this.hasFile) {
toastr.info(this.$t('skinlib.emptyUploadFile'))
this.$message.error(this.$t('skinlib.emptyUploadFile'))
return
}
if (!this.name) {
toastr.info(this.$t('skinlib.emptyTextureName'))
this.$message.error(this.$t('skinlib.emptyTextureName'))
return
}
if (!/image\/(x-)?png/.test(this.files[0].type)) {
toastr.info(this.$t('skinlib.fileExtError'))
this.$message.error(this.$t('skinlib.fileExtError'))
return
}
@ -174,13 +172,12 @@ export default {
errno, msg, tid,
} = await this.$http.post('/skinlib/upload', data)
if (errno === 0) {
await swal({ type: 'success', text: msg })
toastr.info(this.$t('skinlib.redirecting'))
this.$message.success(msg)
setTimeout(() => {
window.location = `${blessing.base_url}/skinlib/show/${tid}`
}, 1000)
} else {
await swal({ type: 'warning', text: msg })
this.$message.error(msg)
this.uploading = false
}
},

View File

@ -37,8 +37,6 @@
</template>
<script>
import { swal } from '../../js/notify'
export default {
name: 'BindPlayer',
data() {
@ -66,7 +64,7 @@ export default {
)
this.pending = false
if (errno === 0) {
await swal({ text: msg, type: 'success' })
await this.$alert({ message: msg, type: 'success' })
window.location.href = `${blessing.base_url}/user`
} else {
this.message = msg

View File

@ -191,10 +191,8 @@
</template>
<script>
import toastr from 'toastr'
import Paginate from 'vuejs-paginate'
import { debounce, queryString } from '../../js/utils'
import { swal } from '../../js/notify'
import ClosetItem from '../../components/ClosetItem.vue'
import EmailVerification from '../../components/EmailVerification.vue'
@ -296,11 +294,11 @@ export default {
},
async submitApplyTexture() {
if (!this.selectedPlayer) {
return toastr.info(this.$t('user.emptySelectedPlayer'))
return this.$message.info(this.$t('user.emptySelectedPlayer'))
}
if (!this.selectedSkin && !this.selectedCape) {
return toastr.info(this.$t('user.emptySelectedTexture'))
return this.$message.info(this.$t('user.emptySelectedTexture'))
}
const { errno, msg } = await this.$http.post(
@ -314,10 +312,10 @@ export default {
}
)
if (errno === 0) {
swal({ type: 'success', text: msg })
this.$message.success(msg)
$('#modal-use-as').modal('hide')
} else {
toastr.warning(msg)
this.$message.warning(msg)
}
},
resetSelected() {

View File

@ -65,8 +65,6 @@
</template>
<script>
import toastr from 'toastr'
import { swal } from '../../js/notify'
import EmailVerification from '../../components/EmailVerification.vue'
const ONE_DAY = 24 * 3600 * 1000
@ -138,14 +136,13 @@ export default {
const result = await this.$http.post('/user/sign')
if (result.errno === 0) {
swal({ type: 'success', text: result.msg })
this.$message.success(result.msg)
this.score = result.score
this.lastSignAt = new Date()
this.storageUsed = result.storage.used
this.storageTotal = result.storage.total
} else {
toastr.warning(result.msg)
this.$message.warning(result.msg)
}
},
},

View File

@ -219,9 +219,6 @@
</template>
<script>
import toastr from 'toastr'
import { swal } from '../../js/notify'
export default {
name: 'Players',
components: {
@ -283,14 +280,13 @@ export default {
}
},
async changeName(player) {
const { dismiss, value } = await swal({
title: this.$t('user.changePlayerName'),
inputValue: player.name,
input: 'text',
showCancelButton: true,
inputValidator: val => !val && this.$t('user.emptyPlayerName'),
})
if (dismiss) {
let value
try {
({ value } = await this.$prompt(this.$t('user.changePlayerName'), {
inputValue: player.name,
inputValidator: val => !!val || this.$t('user.emptyPlayerName'),
}))
} catch {
return
}
@ -299,10 +295,10 @@ export default {
{ pid: player.pid, new_player_name: value }
)
if (errno === 0) {
swal({ type: 'success', text: msg })
this.$message.success(msg)
player.name = value
} else {
swal({ type: 'warning', text: msg })
this.$message.warning(msg)
}
},
loadICheck() {
@ -317,7 +313,7 @@ export default {
},
async clearTexture() {
if (Object.values(this.clear).every(value => !value)) {
return toastr.warning(this.$t('user.noClearChoice'))
return this.$message.warning(this.$t('user.noClearChoice'))
}
const { errno, msg } = await this.$http.post(
@ -326,25 +322,22 @@ export default {
)
if (errno === 0) {
$('.modal').modal('hide')
swal({ type: 'success', text: msg })
this.$message.success(msg)
const player = this.players.find(({ pid }) => pid === this.selected)
Object.keys(this.clear)
.filter(type => this.clear[type])
.forEach(type => (player[`tid_${type}`] = 0))
} else {
swal({ type: 'warning', text: msg })
this.$message.warning(msg)
}
},
async deletePlayer(player, index) {
const { dismiss } = await swal({
title: this.$t('user.deletePlayer'),
text: this.$t('user.deletePlayerNotice'),
type: 'warning',
showCancelButton: true,
cancelButtonColor: '#3085d6',
confirmButtonColor: '#d33',
})
if (dismiss) {
try {
await this.$confirm(this.$t('user.deletePlayerNotice'), {
title: this.$t('user.deletePlayer'),
type: 'warning',
})
} catch {
return
}
@ -354,9 +347,9 @@ export default {
)
if (errno === 0) {
this.$delete(this.players, index)
swal({ type: 'success', text: msg })
this.$message.success(msg)
} else {
swal({ type: 'warning', text: msg })
this.$message.warning(msg)
}
},
async addPlayer() {
@ -366,10 +359,10 @@ export default {
{ player_name: this.newPlayer }
)
if (errno === 0) {
await swal({ type: 'success', text: msg })
this.$message.success(msg)
this.fetchPlayers()
} else {
swal({ type: 'warning', text: msg })
this.$message.warning(msg)
}
},
},

View File

@ -202,8 +202,6 @@
</template>
<script>
import toastr from 'toastr'
import { swal } from '../../js/notify'
import EmailVerification from '../../components/EmailVerification.vue'
export default {
@ -225,12 +223,9 @@ export default {
methods: {
nl2br: str => str.replace(/\n/g, '<br>'),
async resetAvatar() {
const { dismiss } = await swal({
title: this.$t('user.resetAvatarConfirm'),
type: 'question',
showCancelButton: true,
})
if (dismiss) {
try {
await this.$confirm(this.$t('user.resetAvatarConfirm'))
} catch {
return
}
@ -238,7 +233,7 @@ export default {
'/user/profile/avatar',
{ tid: 0 }
)
toastr.success(msg)
this.$message.success(msg)
Array.from(document.querySelectorAll('[alt="User Image"]'))
.forEach(el => (el.src += `?${new Date().getTime()}`))
},
@ -248,25 +243,25 @@ export default {
} = this
if (!oldPassword) {
toastr.info(this.$t('user.emptyPassword'))
this.$message.error(this.$t('user.emptyPassword'))
this.$refs.oldPassword.focus()
return
}
if (!newPassword) {
toastr.info(this.$t('user.emptyNewPassword'))
this.$message.error(this.$t('user.emptyNewPassword'))
this.$refs.newPassword.focus()
return
}
if (!confirmPassword) {
toastr.info(this.$t('auth.emptyConfirmPwd'))
this.$message.error(this.$t('auth.emptyConfirmPwd'))
this.$refs.confirmPassword.focus()
return
}
if (newPassword !== confirmPassword) {
toastr.info(this.$t('auth.invalidConfirmPwd'))
this.$message.error(this.$t('auth.invalidConfirmPwd'))
this.$refs.confirmPassword.focus()
return
}
@ -276,24 +271,21 @@ export default {
{ current_password: oldPassword, new_password: newPassword }
)
if (errno === 0) {
await swal({ type: 'success', text: msg })
await this.$alert(msg)
return (window.location = `${blessing.base_url}/auth/login`)
}
return swal({ type: 'warning', text: msg })
return this.$alert(msg, { type: 'warning' })
},
async changeNickName() {
const { nickname } = this
if (!nickname) {
return swal({ type: 'error', text: this.$t('user.emptyNewNickName') })
return this.$alert(this.$t('user.emptyNewNickName'), { type: 'error' })
}
const { dismiss } = await swal({
text: this.$t('user.changeNickName', { new_nickname: nickname }),
type: 'question',
showCancelButton: true,
})
if (dismiss) {
try {
await this.$confirm(this.$t('user.changeNickName', { new_nickname: nickname }))
} catch {
return
}
@ -304,27 +296,24 @@ export default {
if (errno === 0) {
Array.from(document.querySelectorAll('.nickname'))
.forEach(el => (el.textContent = nickname))
return swal({ type: 'success', text: msg })
return this.$message.success(msg)
}
return swal({ type: 'warning', text: msg })
return this.$alert(msg, { type: 'warning' })
},
async changeEmail() {
const { email } = this
if (!email) {
return swal({ type: 'error', text: this.$t('user.emptyNewEmail') })
return this.$alert(this.$t('user.emptyNewEmail'), { type: 'error' })
}
if (!/\S+@\S+\.\S+/.test(email)) {
return swal({ type: 'warning', text: this.$t('auth.invalidEmail') })
return this.$alert(this.$t('auth.invalidEmail'), { type: 'warning' })
}
const { dismiss } = await swal({
text: this.$t('user.changeEmail', { new_email: email }),
type: 'question',
showCancelButton: true,
})
if (dismiss) {
try {
await this.$confirm(this.$t('user.changeEmail', { new_email: email }))
} catch {
return
}
@ -333,16 +322,16 @@ export default {
{ new_email: email, password: this.currentPassword }
)
if (errno === 0) {
await swal({ type: 'success', text: msg })
await this.$message.success(msg)
return (window.location = `${blessing.base_url}/auth/login`)
}
return swal({ type: 'warning', text: msg })
return this.$alert(msg, { type: 'warning' })
},
async deleteAccount() {
const { deleteConfirm: password } = this
if (!password) {
return swal({ type: 'warning', text: this.$t('user.emptyDeletePassword') })
return this.$alert(this.$t('user.emptyDeletePassword'), { type: 'error' })
}
const { errno, msg } = await this.$http.post(
@ -350,13 +339,10 @@ export default {
{ password }
)
if (errno === 0) {
await swal({
type: 'success',
text: msg,
})
await this.$alert(msg, { type: 'success' })
window.location = `${blessing.base_url}/auth/login`
} else {
return swal({ type: 'warning', text: msg })
return this.$alert(msg, { type: 'warning' })
}
},
},

View File

@ -5,3 +5,4 @@ rules:
no-empty-function: 0
func-names: 0
no-extra-parens: 0
prefer-promise-reject-errors: 0

View File

@ -1,10 +1,8 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import { MessageBoxData } from 'element-ui/types/message-box'
import { flushPromises } from '../utils'
import ClosetItem from '@/components/ClosetItem.vue'
import { swal } from '@/js/notify'
jest.mock('@/js/notify')
function factory(opt = {}) {
return {
@ -40,13 +38,13 @@ test('rename texture', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 0 })
.mockResolvedValueOnce({ errno: 1 })
swal.mockImplementationOnce(() => Promise.resolve({ dismiss: 1 }))
.mockImplementation(options => {
Vue.prototype.$prompt.mockImplementationOnce(() => Promise.reject(new Error()))
.mockImplementation((_, options) => {
if (options.inputValidator) {
options.inputValidator('name')
options.inputValidator('')
}
return Promise.resolve({ value: 'new-name' })
return Promise.resolve({ value: 'new-name' } as MessageBoxData)
})
const wrapper = mount(ClosetItem, { propsData: factory() })
const button = wrapper.findAll('.dropdown-menu > li').at(0)
@ -72,9 +70,9 @@ test('remove texture', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 0 })
.mockResolvedValueOnce({ errno: 1 })
swal
.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({})
Vue.prototype.$confirm
.mockRejectedValueOnce({})
.mockResolvedValue('confirm')
const wrapper = mount(ClosetItem, { propsData: factory() })
const button = wrapper.findAll('.dropdown-menu > li').at(1)
@ -97,9 +95,9 @@ test('set as avatar', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 0 })
.mockResolvedValueOnce({ errno: 1 })
swal
.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({})
Vue.prototype.$confirm
.mockRejectedValueOnce({})
.mockResolvedValue('confirm')
const wrapper = mount(ClosetItem, { propsData: factory() })
const button = wrapper.findAll('.dropdown-menu > li').at(2)

View File

@ -1,9 +1,6 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import EmailVerification from '@/components/EmailVerification.vue'
import { swal } from '@/js/notify'
jest.mock('@/js/notify')
test('message box should not be render if verified', () => {
window.blessing.extra = { unverified: false }
@ -21,9 +18,9 @@ test('resend email', async () => {
button.trigger('click')
await wrapper.vm.$nextTick()
expect(swal).toBeCalledWith({ type: 'warning', text: '1' })
expect(Vue.prototype.$message.error).toBeCalledWith('1')
button.trigger('click')
await wrapper.vm.$nextTick()
expect(swal).toBeCalledWith({ type: 'success', text: '0' })
expect(Vue.prototype.$message.success).toBeCalledWith('0')
})

View File

@ -1,12 +1,8 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import SkinLibItem from '@/components/SkinLibItem.vue'
import toastr from 'toastr'
import { MessageBoxData } from 'element-ui/types/message-box'
import { flushPromises } from '../utils'
import { swal } from '@/js/notify'
jest.mock('@/js/notify')
jest.mock('toastr')
test('urls', () => {
const wrapper = mount(SkinLibItem, {
@ -64,7 +60,7 @@ test('liked state', () => {
test('remove from closet', async () => {
Vue.prototype.$http.post.mockResolvedValue({ errno: 0 })
swal.mockResolvedValue({})
Vue.prototype.$confirm.mockResolvedValue('confirm')
const wrapper = mount(SkinLibItem, {
propsData: {
tid: 1, liked: true, anonymous: false,
@ -79,15 +75,15 @@ test('add to closet', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValue({ errno: 0 })
swal.mockImplementationOnce(() => Promise.resolve({ dismiss: 1 }))
.mockImplementation(({ inputValidator }) => {
Vue.prototype.$prompt
.mockImplementationOnce(() => Promise.reject())
.mockImplementation((_, { inputValidator }) => {
if (inputValidator) {
inputValidator('')
inputValidator('name')
}
return Promise.resolve({ value: 'name' })
return Promise.resolve({ value: 'name' } as MessageBoxData)
})
jest.spyOn(toastr, 'warning')
const wrapper = mount(SkinLibItem, {
propsData: {
tid: 1, liked: false, anonymous: false,
@ -104,7 +100,7 @@ test('add to closet', async () => {
'/user/closet/add',
{ tid: 1, name: 'name' }
)
expect(toastr.warning).toBeCalledWith('1')
expect(Vue.prototype.$message.warning).toBeCalledWith('1')
button.trigger('click')
await flushPromises()

View File

@ -1,12 +1,14 @@
import { logout } from '@/js/logout'
import { post } from '@/js/net'
import { swal } from '@/js/notify'
import { MessageBox } from '@/js/element'
jest.mock('@/js/net')
jest.mock('@/js/notify')
jest.mock('@/js/element')
test('log out', async () => {
swal.mockResolvedValueOnce({ dismiss: 1 }).mockResolvedValueOnce({})
MessageBox.confirm
.mockRejectedValueOnce('cancel')
.mockResolvedValue('confirm')
post.mockResolvedValue({ msg: '' })
await logout()

View File

@ -1,14 +1,6 @@
import $ from 'jquery'
import Swal from 'sweetalert2'
import * as notify from '@/js/notify'
jest.mock('sweetalert2', () => ({
mixin() {
return this
},
fire() {},
}))
test('show AJAX error', () => {
// @ts-ignore
$.fn.modal = function () {
@ -27,9 +19,3 @@ test('show modal', () => {
destroyOnClose: false,
})
})
test('show sweetalert', () => {
jest.spyOn(Swal, 'fire')
notify.swal({})
expect(Swal.fire).toBeCalled()
})

View File

@ -34,3 +34,14 @@ Vue.prototype.$http = {
get: jest.fn(),
post: jest.fn(),
}
Vue.prototype.$message = {
info: jest.fn(),
success: jest.fn(),
warning: jest.fn(),
error: jest.fn(),
}
Vue.prototype.$msgbox = jest.fn()
Vue.prototype.$alert = jest.fn()
Vue.prototype.$confirm = jest.fn()
Vue.prototype.$prompt = jest.fn()

View File

@ -1,4 +1,6 @@
import Vue from 'vue'
import { Message, MessageBox } from 'element-ui'
import { ElMessageBoxOptions } from 'element-ui/types/message-box'
declare module 'vue/types/vue' {
interface VueConstructor {
@ -6,7 +8,17 @@ declare module 'vue/types/vue' {
$http: {
get: jest.Mock<any>
post: jest.Mock<any>
},
$message: {
info: jest.Mock<ReturnType<typeof Message>, Parameters<typeof Message>>
success: jest.Mock<ReturnType<typeof Message>, Parameters<typeof Message>>
warning: jest.Mock<ReturnType<typeof Message>, Parameters<typeof Message>>
error: jest.Mock<ReturnType<typeof Message>, Parameters<typeof Message>>
}
$msgbox: jest.Mock<ReturnType<typeof MessageBox>, [ElMessageBoxOptions]>
$alert: jest.Mock<ReturnType<typeof MessageBox>, [string, ElMessageBoxOptions]>
$confirm: jest.Mock<ReturnType<typeof MessageBox>, [string, ElMessageBoxOptions]>
$prompt: jest.Mock<ReturnType<typeof MessageBox>, [string, ElMessageBoxOptions]>
}
}
}

View File

@ -0,0 +1,9 @@
import { ElMessage } from 'element-ui/types/message'
import { ElMessageBox } from 'element-ui/types/message-box'
export const Message = {} as jest.Mock<ReturnType<ElMessage>, Parameters<ElMessage>>
export const MessageBox = {} as jest.Mock<ReturnType<ElMessageBox>, Parameters<ElMessageBox>> & {
alert: jest.Mock<ReturnType<ElMessageBox>, Parameters<ElMessageBox>>,
confirm: jest.Mock<ReturnType<ElMessageBox>, Parameters<ElMessageBox>>,
prompt: jest.Mock<ReturnType<ElMessageBox>, Parameters<ElMessageBox>>
}

View File

@ -9,8 +9,3 @@ export const showModal = {} as jest.Mock<
ReturnType<typeof notify.showModal>,
Parameters<typeof notify.showModal>
>
export const swal = {} as jest.Mock<
ReturnType<typeof notify.swal>,
Parameters<typeof notify.swal>
>

View File

@ -2,9 +2,6 @@ import Vue from 'vue'
import { mount } from '@vue/test-utils'
import Market from '@/views/admin/Market.vue'
import { flushPromises } from '../../utils'
import { swal } from '@/js/notify'
jest.mock('@/js/notify')
test('render dependencies', async () => {
Vue.prototype.$http.get.mockResolvedValue([
@ -85,8 +82,9 @@ test('update plugin', async () => {
])
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
swal.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({})
Vue.prototype.$confirm
.mockRejectedValueOnce('')
.mockResolvedValue('confirm')
const wrapper = mount(Market)
await flushPromises()
const button = wrapper.find('button')
@ -117,19 +115,19 @@ test('enable installed plugin', async () => {
errno: 1, msg: '1', reason: ['`a<div></div>`b'],
})
.mockResolvedValue({ errno: 0, msg: '0' })
swal.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValueOnce({})
Vue.prototype.$confirm
.mockRejectedValueOnce('')
.mockResolvedValue('confirm')
const wrapper = mount(Market)
await flushPromises()
const buttons = wrapper.findAll('button')
buttons.at(0).trigger('click')
await flushPromises()
expect(swal).toBeCalledWith({
text: 'admin.noDependenciesNotice',
type: 'warning',
showCancelButton: true,
})
expect(Vue.prototype.$confirm).toBeCalledWith(
'admin.noDependenciesNotice',
{ type: 'warning' }
)
expect(Vue.prototype.$http.post).not.toBeCalled()
buttons.at(0).trigger('click')
@ -138,10 +136,13 @@ test('enable installed plugin', async () => {
'/admin/plugins/manage',
{ action: 'enable', name: 'a' }
)
expect(swal).toBeCalledWith({
type: 'warning',
html: '<p>1</p><ul><li>`a&lt;div&gt;&lt;/div&gt;`b</li></ul>',
})
expect(Vue.prototype.$alert).toBeCalledWith(
'<p>1</p><ul><li>`a&lt;div&gt;&lt;/div&gt;`b</li></ul>',
{
type: 'warning',
dangerouslyUseHTMLString: true,
}
)
buttons.at(1).trigger('click')
await flushPromises()

View File

@ -1,10 +1,8 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import { MessageBoxData } from 'element-ui/types/message-box'
import { flushPromises } from '../../utils'
import Players from '@/views/admin/Players.vue'
import { swal } from '@/js/notify'
jest.mock('@/js/notify')
test('fetch data after initializing', () => {
Vue.prototype.$http.get.mockResolvedValue({ data: [] })
@ -59,13 +57,14 @@ test('change player name', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValueOnce({ errno: 0, msg: '0' })
swal.mockImplementationOnce(() => Promise.resolve({ dismiss: 1 }))
.mockImplementation(options => {
Vue.prototype.$prompt
.mockImplementationOnce(() => Promise.reject())
.mockImplementation((_, options) => {
if (options.inputValidator) {
options.inputValidator('')
options.inputValidator('new')
}
return Promise.resolve({ value: 'new' })
return Promise.resolve({ value: 'new' } as MessageBoxData)
})
const wrapper = mount(Players)
await wrapper.vm.$nextTick()
@ -94,8 +93,9 @@ test('change owner', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValueOnce({ errno: 0, msg: '0' })
swal.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({ value: '3' })
Vue.prototype.$prompt
.mockRejectedValueOnce('')
.mockResolvedValue({ value: '3' } as MessageBoxData)
const wrapper = mount(Players)
await wrapper.vm.$nextTick()
@ -124,8 +124,9 @@ test('delete player', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValueOnce({ errno: 0, msg: '0' })
swal.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({})
Vue.prototype.$confirm
.mockRejectedValueOnce('')
.mockResolvedValue('confirm')
const wrapper = mount(Players)
await wrapper.vm.$nextTick()

View File

@ -1,9 +1,7 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import Plugins from '@/views/admin/Plugins.vue'
import toastr from 'toastr'
import { flushPromises } from '../../utils'
import { swal } from '@/js/notify'
jest.mock('@/js/notify')
@ -62,8 +60,9 @@ test('enable plugin', async () => {
errno: 1, msg: '1', reason: ['`a<div></div>`b'],
})
.mockResolvedValue({ errno: 0, msg: '0' })
swal.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValueOnce({})
Vue.prototype.$confirm
.mockRejectedValueOnce('')
.mockResolvedValue('confirm')
const wrapper = mount(Plugins)
await flushPromises()
@ -71,10 +70,8 @@ test('enable plugin', async () => {
.find('a')
.trigger('click')
await flushPromises()
expect(swal).toBeCalledWith({
text: 'admin.noDependenciesNotice',
expect(Vue.prototype.$confirm).toBeCalledWith('admin.noDependenciesNotice', {
type: 'warning',
showCancelButton: true,
})
expect(Vue.prototype.$http.post).not.toBeCalled()
@ -86,10 +83,13 @@ test('enable plugin', async () => {
'/admin/plugins/manage',
{ action: 'enable', name: 'a' }
)
expect(swal).toBeCalledWith({
type: 'warning',
html: '<p>1</p><ul><li>`a&lt;div&gt;&lt;/div&gt;`b</li></ul>',
})
expect(Vue.prototype.$alert).toBeCalledWith(
'<p>1</p><ul><li>`a&lt;div&gt;&lt;/div&gt;`b</li></ul>',
{
type: 'warning',
dangerouslyUseHTMLString: true,
}
)
wrapper.findAll('.actions').at(1)
.find('a')
@ -99,7 +99,6 @@ test('enable plugin', async () => {
})
test('disable plugin', async () => {
jest.spyOn(toastr, 'success')
Vue.prototype.$http.get.mockResolvedValue([
{
name: 'a', dependencies: { requirements: [] }, enabled: true, config: false,
@ -120,12 +119,11 @@ test('disable plugin', async () => {
)
button.trigger('click')
await flushPromises()
expect(toastr.success).toBeCalledWith('0')
expect(Vue.prototype.$message.success).toBeCalledWith('0')
expect(wrapper.text()).toContain('admin.enablePlugin')
})
test('delete plugin', async () => {
jest.spyOn(toastr, 'success')
Vue.prototype.$http.get.mockResolvedValue([
{
name: 'a', dependencies: { requirements: [] }, enabled: false,
@ -134,8 +132,9 @@ test('delete plugin', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValue({ errno: 0, msg: '0' })
swal.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({})
Vue.prototype.$confirm
.mockRejectedValueOnce('')
.mockResolvedValue('confirm')
const wrapper = mount(Plugins)
await flushPromises()
const button = wrapper.find('.actions').findAll('a')
@ -143,10 +142,8 @@ test('delete plugin', async () => {
button.trigger('click')
await flushPromises()
expect(swal).toBeCalledWith({
text: 'admin.confirmDeletion',
expect(Vue.prototype.$confirm).toBeCalledWith('admin.confirmDeletion', {
type: 'warning',
showCancelButton: true,
})
expect(Vue.prototype.$http.post).not.toBeCalled()
@ -156,7 +153,7 @@ test('delete plugin', async () => {
'/admin/plugins/manage',
{ action: 'delete', name: 'a' }
)
expect(swal).toBeCalledWith({ type: 'warning', text: '1' })
expect(Vue.prototype.$message.warning).toBeCalledWith('1')
button.trigger('click')
await flushPromises()

View File

@ -2,9 +2,6 @@ import Vue from 'vue'
import { mount } from '@vue/test-utils'
import { flushPromises } from '../../utils'
import Update from '@/views/admin/Update.vue'
import '@/js/notify'
jest.mock('@/js/notify')
afterEach(() => {
window.blessing.extra = { canUpdate: true }

View File

@ -1,12 +1,10 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import Users from '@/views/admin/Users.vue'
import toastr from 'toastr'
import { swal } from '@/js/notify'
import '@/js/i18n'
import { MessageBoxData } from 'element-ui/types/message-box'
import { flushPromises } from '../../utils'
jest.mock('@/js/notify')
jest.mock('@/js/i18n', () => ({
trans: (key: string) => key,
}))
@ -238,13 +236,14 @@ test('change email', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValueOnce({ errno: 0, msg: '0' })
swal.mockImplementationOnce(() => Promise.resolve({ dismiss: 1 }))
.mockImplementation(options => {
Vue.prototype.$prompt
.mockImplementationOnce(() => Promise.reject())
.mockImplementation((_, options) => {
if (options.inputValidator) {
options.inputValidator('')
options.inputValidator('value')
}
return Promise.resolve({ value: 'd@e.f' })
return Promise.resolve({ value: 'd@e.f' } as MessageBoxData)
})
const wrapper = mount(Users)
await wrapper.vm.$nextTick()
@ -300,13 +299,14 @@ test('change nickname', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValueOnce({ errno: 0, msg: '0' })
swal.mockImplementationOnce(() => Promise.resolve({ dismiss: 1 }))
.mockImplementation(options => {
Vue.prototype.$prompt
.mockImplementationOnce(() => Promise.reject())
.mockImplementation((_, options) => {
if (options.inputValidator) {
options.inputValidator('')
options.inputValidator('value')
}
return Promise.resolve({ value: 'new' })
return Promise.resolve({ value: 'new' } as MessageBoxData)
})
const wrapper = mount(Users)
await wrapper.vm.$nextTick()
@ -329,8 +329,6 @@ test('change nickname', async () => {
})
test('change password', async () => {
jest.spyOn(toastr, 'success')
jest.spyOn(toastr, 'warning')
Vue.prototype.$http.get.mockResolvedValue({
data: [
{ uid: 1 },
@ -339,8 +337,9 @@ test('change password', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 0, msg: '0' })
.mockResolvedValueOnce({ errno: 1, msg: '1' })
swal.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({ value: 'password' })
Vue.prototype.$prompt
.mockRejectedValueOnce('')
.mockResolvedValue({ value: 'password' }as MessageBoxData)
const wrapper = mount(Users)
await wrapper.vm.$nextTick()
@ -356,12 +355,12 @@ test('change password', async () => {
{ uid: 1, password: 'password' }
)
await flushPromises()
expect(toastr.success).toBeCalledWith('0')
expect(Vue.prototype.$message.success).toBeCalledWith('0')
button.trigger('click')
await flushPromises()
expect(toastr.warning).toBeCalledWith('1')
expect(Vue.prototype.$message.warning).toBeCalledWith('1')
})
test('change score', async () => {
@ -373,8 +372,9 @@ test('change score', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValueOnce({ errno: 0, msg: '0' })
swal.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({ value: '45' })
Vue.prototype.$prompt
.mockRejectedValueOnce('')
.mockResolvedValue({ value: '45' }as MessageBoxData)
const wrapper = mount(Users)
await wrapper.vm.$nextTick()
@ -415,21 +415,37 @@ test('change permission', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValue({ errno: 0, msg: '0' })
swal
.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValueOnce({ value: 1 })
.mockResolvedValueOnce({ value: -1 })
Vue.prototype.$msgbox
.mockImplementationOnce(() => Promise.reject())
.mockImplementationOnce(options => {
if (options.message) {
const vnode = options.message as Vue.VNode
const elm = document.createElement('select')
elm.appendChild(document.createElement('option'))
elm.appendChild(document.createElement('option'))
elm.appendChild(document.createElement('option'))
elm.selectedIndex = 2
;(vnode.children as Vue.VNode[])[1].elm = elm
}
return Promise.resolve({} as MessageBoxData)
})
.mockImplementation(options => {
if (options.message) {
const vnode = options.message as Vue.VNode
const elm = document.createElement('select')
elm.appendChild(document.createElement('option'))
elm.appendChild(document.createElement('option'))
elm.selectedIndex = 0
;(vnode.children as Vue.VNode[])[1].elm = elm
}
return Promise.resolve({} as MessageBoxData)
})
let wrapper = mount(Users)
await wrapper.vm.$nextTick()
let button = wrapper.find('[data-test=permission]')
button.trigger('click')
expect(swal.mock.calls[0][0].inputOptions).toStrictEqual({
'-1': 'admin.banned',
0: 'admin.normal',
1: 'admin.admin',
})
expect(Vue.prototype.$http.post).not.toBeCalled()
button.trigger('click')
@ -445,10 +461,6 @@ test('change permission', async () => {
button = wrapper.find('[data-test=permission]')
button.trigger('click')
expect(swal.mock.calls[2][0].inputOptions).toStrictEqual({
'-1': 'admin.banned',
0: 'admin.normal',
})
await flushPromises()
expect(wrapper.text()).toContain('admin.banned')
})
@ -462,8 +474,9 @@ test('delete user', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValue({ errno: 0, msg: '0' })
swal.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({})
Vue.prototype.$confirm
.mockRejectedValueOnce('')
.mockResolvedValue('confirm')
const wrapper = mount(Users)
await wrapper.vm.$nextTick()

View File

@ -1,9 +1,6 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import Login from '@/views/auth/Login.vue'
import { swal } from '@/js/notify'
jest.mock('@/js/notify')
const Captcha = Vue.extend({
methods: {
@ -54,7 +51,7 @@ test('login', async () => {
form.trigger('submit')
await wrapper.vm.$nextTick()
expect(swal).toBeCalledWith({ type: 'error', text: 'auth.tooManyFails' })
expect(Vue.prototype.$alert).toBeCalledWith('auth.tooManyFails', { type: 'error' })
expect(wrapper.find('img').exists()).toBeTrue()
wrapper.find('[type="checkbox"]').setChecked()
@ -68,5 +65,5 @@ test('login', async () => {
)
await wrapper.vm.$nextTick()
jest.runAllTimers()
expect(swal).toBeCalledWith({ type: 'success', text: 'ok' })
expect(Vue.prototype.$message.success).toBeCalledWith('ok')
})

View File

@ -1,11 +1,8 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import Register from '@/views/auth/Register.vue'
import { swal } from '@/js/notify'
import { flushPromises } from '../../utils'
jest.mock('@/js/notify')
window.blessing.extra = { player: false }
const Captcha = Vue.extend({
@ -94,7 +91,7 @@ test('register', async () => {
form.trigger('submit')
await flushPromises()
jest.runAllTimers()
expect(swal).toBeCalledWith({ type: 'success', text: 'ok' })
expect(Vue.prototype.$message.success).toBeCalledWith('ok')
})
test('register with player name', async () => {

View File

@ -1,9 +1,6 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import Reset from '@/views/auth/Reset.vue'
import { swal } from '@/js/notify'
jest.mock('@/js/notify')
test('reset password', async () => {
Vue.prototype.$http.post
@ -52,5 +49,5 @@ test('reset password', async () => {
button.trigger('click')
await wrapper.vm.$nextTick()
expect(swal).toBeCalledWith({ type: 'success', text: 'ok' })
expect(Vue.prototype.$message.success).toBeCalledWith('ok')
})

View File

@ -1,11 +1,8 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import Show from '@/views/skinlib/Show.vue'
import toastr from 'toastr'
import { MessageBoxData } from 'element-ui/types/message-box'
import { flushPromises } from '../../utils'
import { swal } from '@/js/notify'
jest.mock('@/js/notify')
type Component = Vue & {
liked: boolean
@ -156,7 +153,7 @@ test('set as avatar', () => {
stubs: { previewer },
})
wrapper.find('button.btn-default').trigger('click')
expect(swal).toBeCalled()
expect(Vue.prototype.$confirm).toBeCalled()
const noSetAsAvatar = mount(Show, {
mocks: {
@ -171,7 +168,7 @@ test('add to closet', async () => {
Object.assign(window.blessing.extra, { currentUid: 1, inCloset: false })
Vue.prototype.$http.get.mockResolvedValue({ name: 'wow', likes: 2 })
Vue.prototype.$http.post.mockResolvedValue({ errno: 0, msg: '' })
swal.mockResolvedValue({})
Vue.prototype.$prompt.mockResolvedValue({ value: 'a' } as MessageBoxData)
const wrapper = mount<Component>(Show, {
mocks: {
$route: ['/skinlib/show/1', '1'],
@ -188,7 +185,6 @@ test('remove from closet', async () => {
Object.assign(window.blessing.extra, { currentUid: 1, inCloset: true })
Vue.prototype.$http.get.mockResolvedValue({ likes: 2 })
Vue.prototype.$http.post.mockResolvedValue({ errno: 0 })
swal.mockResolvedValue({})
const wrapper = mount<Component>(Show, {
mocks: {
$route: ['/skinlib/show/1', '1'],
@ -207,14 +203,14 @@ test('change texture name', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValue({ errno: 0, msg: '0' })
jest.spyOn(toastr, 'warning')
swal.mockImplementationOnce(() => Promise.resolve({ dismiss: 1 }))
.mockImplementation(({ inputValidator }) => {
Vue.prototype.$prompt
.mockImplementationOnce(() => Promise.reject('cancel'))
.mockImplementation((_, { inputValidator }) => {
if (inputValidator) {
inputValidator('')
inputValidator('new-name')
}
return Promise.resolve({ value: 'new-name' })
return Promise.resolve({ value: 'new-name' } as MessageBoxData)
})
const wrapper = mount<Component>(Show, {
mocks: {
@ -233,7 +229,7 @@ test('change texture name', async () => {
'/skinlib/rename',
{ tid: 1, new_name: 'new-name' }
)
expect(toastr.warning).toBeCalledWith('1')
expect(Vue.prototype.$message.error).toBeCalledWith('1')
button.trigger('click')
await flushPromises()
@ -245,9 +241,19 @@ test('change texture model', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValue({ errno: 0, msg: '0' })
jest.spyOn(toastr, 'warning')
swal.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({ value: 'alex' })
Vue.prototype.$msgbox
.mockImplementationOnce(() => Promise.reject())
.mockImplementation(options => {
if (options.message) {
const vnode = options.message as Vue.VNode
const elm = document.createElement('select')
elm.appendChild(document.createElement('option'))
elm.appendChild(document.createElement('option'))
elm.selectedIndex = 1
;(vnode.children as Vue.VNode[])[1].elm = elm
}
return Promise.resolve({} as MessageBoxData)
})
const wrapper = mount<Component>(Show, {
mocks: {
$route: ['/skinlib/show/1', '1'],
@ -266,7 +272,7 @@ test('change texture model', async () => {
'/skinlib/model',
{ tid: 1, model: 'alex' }
)
expect(toastr.warning).toBeCalledWith('1')
expect(Vue.prototype.$message.warning).toBeCalledWith('1')
button.trigger('click')
await flushPromises()
@ -278,9 +284,9 @@ test('toggle privacy', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValue({ errno: 0, msg: '0' })
jest.spyOn(toastr, 'warning')
swal.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({})
Vue.prototype.$confirm
.mockRejectedValueOnce('')
.mockResolvedValue('confirm')
const wrapper = mount<Component>(Show, {
mocks: {
$route: ['/skinlib/show/1', '1'],
@ -298,7 +304,7 @@ test('toggle privacy', async () => {
'/skinlib/privacy',
{ tid: 1 }
)
expect(toastr.warning).toBeCalledWith('1')
expect(Vue.prototype.$message.warning).toBeCalledWith('1')
button.trigger('click')
await flushPromises()
@ -314,8 +320,9 @@ test('delete texture', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValue({ errno: 0, msg: '0' })
swal.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({})
Vue.prototype.$confirm
.mockRejectedValueOnce('')
.mockResolvedValue('confirm')
const wrapper = mount(Show, {
mocks: {
$route: ['/skinlib/show/1', '1'],
@ -333,9 +340,10 @@ test('delete texture', async () => {
'/skinlib/delete',
{ tid: 1 }
)
expect(swal).toBeCalledWith({ type: 'warning', text: '1' })
expect(Vue.prototype.$message.warning).toBeCalledWith('1')
button.trigger('click')
await flushPromises()
expect(swal).toBeCalledWith({ type: 'success', text: '0' })
jest.runAllTimers()
expect(Vue.prototype.$message.success).toBeCalledWith('0')
})

View File

@ -3,11 +3,6 @@ import Vue from 'vue'
import { mount } from '@vue/test-utils'
import Upload from '@/views/skinlib/Upload.vue'
import { flushPromises } from '../../utils'
import toastr from 'toastr'
import { swal } from '@/js/notify'
jest.mock('toastr')
jest.mock('@/js/notify')
window.blessing.extra = {
textureNameRule: 'rule',
@ -122,8 +117,6 @@ test('upload file', async () => {
.mockResolvedValueOnce({
errno: 0, msg: '0', tid: 1,
})
jest.spyOn(toastr, 'info')
swal.mockReturnValue(Promise.resolve({}))
const wrapper = mount(Upload, {
stubs: ['file-upload'],
@ -132,7 +125,7 @@ test('upload file', async () => {
button.trigger('click')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(toastr.info).toBeCalledWith('skinlib.emptyUploadFile')
expect(Vue.prototype.$message.error).toBeCalledWith('skinlib.emptyUploadFile')
wrapper.setData({
files: [{
@ -141,12 +134,12 @@ test('upload file', async () => {
})
button.trigger('click')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(toastr.info).toBeCalledWith('skinlib.emptyTextureName')
expect(Vue.prototype.$message.error).toBeCalledWith('skinlib.emptyTextureName')
wrapper.find('[type=text]').setValue('t')
button.trigger('click')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(toastr.info).toBeCalledWith('skinlib.fileExtError')
expect(Vue.prototype.$message.error).toBeCalledWith('skinlib.fileExtError')
wrapper.setData({
files: [{
@ -156,13 +149,12 @@ test('upload file', async () => {
button.trigger('click')
await flushPromises()
expect(Vue.prototype.$http.post).toBeCalledWith('/skinlib/upload', expect.any(FormData))
expect(swal).toBeCalledWith({ type: 'warning', text: '1' })
expect(Vue.prototype.$message.error).toBeCalledWith('1')
button.trigger('click')
await flushPromises()
jest.runAllTimers()
expect(swal).toBeCalledWith({ type: 'success', text: '0' })
expect(toastr.info).toBeCalledWith('skinlib.redirecting')
expect(Vue.prototype.$message.success).toBeCalledWith('0')
})
test('show notice about awarding', () => {

View File

@ -1,9 +1,6 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import Bind from '@/views/user/Bind.vue'
import { swal } from '@/js/notify'
jest.mock('@/js/notify')
test('list existed players', async () => {
Vue.prototype.$http.get
@ -27,7 +24,6 @@ test('submit', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: 'fail' })
.mockResolvedValueOnce({ errno: 0, msg: 'ok' })
swal.mockResolvedValue({})
const wrapper = mount(Bind)
wrapper.find('input').setValue('abc')
@ -38,5 +34,5 @@ test('submit', async () => {
wrapper.find('button').trigger('click')
await wrapper.vm.$nextTick()
expect(swal).toBeCalledWith({ text: 'ok', type: 'success' })
expect(Vue.prototype.$alert).toBeCalledWith({ message: 'ok', type: 'success' })
})

View File

@ -3,10 +3,6 @@ import { mount } from '@vue/test-utils'
import Closet from '@/views/user/Closet.vue'
import ClosetItem from '@/components/ClosetItem.vue'
import Previewer from '@/components/Previewer.vue'
import toastr from 'toastr'
import { swal } from '@/js/notify'
jest.mock('@/js/notify')
window.blessing.extra = { unverified: false }
@ -216,7 +212,6 @@ test('apply texture', async () => {
test('submit applying texture', async () => {
window.$ = jest.fn(() => ({ modal() {} }))
jest.spyOn(toastr, 'info')
Vue.prototype.$http.get.mockResolvedValue({})
Vue.prototype.$http.post.mockResolvedValueOnce({ errno: 1 })
.mockResolvedValue({ errno: 0, msg: 'ok' })
@ -224,11 +219,11 @@ test('submit applying texture', async () => {
const button = wrapper.find('.modal-footer > a:nth-child(2)')
button.trigger('click')
expect(toastr.info).toBeCalledWith('user.emptySelectedPlayer')
expect(Vue.prototype.$message.info).toBeCalledWith('user.emptySelectedPlayer')
wrapper.setData({ selectedPlayer: 1 })
button.trigger('click')
expect(toastr.info).toBeCalledWith('user.emptySelectedTexture')
expect(Vue.prototype.$message.info).toBeCalledWith('user.emptySelectedTexture')
wrapper.setData({ selectedSkin: 1 })
button.trigger('click')
@ -255,7 +250,7 @@ test('submit applying texture', async () => {
}
)
await wrapper.vm.$nextTick()
expect(swal).toBeCalledWith({ type: 'success', text: 'ok' })
expect(Vue.prototype.$message.success).toBeCalledWith('ok')
})
test('reset selected texture', () => {

View File

@ -2,10 +2,6 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import Dashboard from '@/views/user/Dashboard.vue'
import toastr from 'toastr'
import { swal } from '@/js/notify'
jest.mock('@/js/notify')
window.blessing.extra = { unverified: false }
@ -124,8 +120,6 @@ test('remaining time', async () => {
})
test('sign', async () => {
jest.spyOn(toastr, 'warning')
swal.mockResolvedValue({})
Vue.prototype.$http.get.mockResolvedValue(scoreInfo({
user: { lastSignAt: Date.now() - 30 * 3600 * 1000 },
}))
@ -143,7 +137,7 @@ test('sign', async () => {
button.trigger('click')
await wrapper.vm.$nextTick()
expect(Vue.prototype.$http.post).toBeCalledWith('/user/sign')
expect(toastr.warning).toBeCalledWith('1')
expect(Vue.prototype.$message.warning).toBeCalledWith('1')
button.trigger('click')
await wrapper.vm.$nextTick()

View File

@ -1,11 +1,8 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import { MessageBoxData } from 'element-ui/types/message-box'
import { flushPromises } from '../../utils'
import Players from '@/views/user/Players.vue'
import { swal } from '@/js/notify'
jest.mock('toastr')
jest.mock('@/js/notify')
window.blessing.extra = {
rule: 'rule',
@ -67,13 +64,13 @@ test('change player name', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1 })
.mockResolvedValue({ errno: 0 })
swal.mockImplementationOnce(() => Promise.resolve({ dismiss: 1 }))
.mockImplementation(({ inputValidator }) => {
Vue.prototype.$prompt.mockImplementationOnce(() => Promise.reject('cancel'))
.mockImplementation((_, { inputValidator }) => {
if (inputValidator) {
inputValidator('')
inputValidator('new-name')
}
return Promise.resolve({ value: 'new-name' })
return Promise.resolve({ value: 'new-name' } as MessageBoxData)
})
const wrapper = mount(Players)
await wrapper.vm.$nextTick()
@ -122,8 +119,9 @@ test('delete player', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1 })
.mockResolvedValue({ errno: 0 })
swal.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({})
Vue.prototype.$confirm
.mockRejectedValueOnce({})
.mockResolvedValue('confirm')
const wrapper = mount(Players)
await wrapper.vm.$nextTick()
const button = wrapper.find('.btn-danger')
@ -201,5 +199,5 @@ test('clear texture', async () => {
)
button.trigger('click')
await flushPromises()
expect(swal).toBeCalledWith({ type: 'success', text: 'ok' })
expect(Vue.prototype.$message.success).toBeCalledWith('ok')
})

View File

@ -2,10 +2,6 @@ import Vue from 'vue'
import { mount } from '@vue/test-utils'
import { flushPromises } from '../../utils'
import Profile from '@/views/user/Profile.vue'
import toastr from 'toastr'
import { swal } from '@/js/notify'
jest.mock('@/js/notify')
window.blessing.extra = { unverified: false }
@ -24,10 +20,9 @@ test('convert linebreak', () => {
})
test('reset avatar', async () => {
jest.spyOn(toastr, 'success')
swal.mockResolvedValueOnce({})
.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({})
Vue.prototype.$confirm
.mockRejectedValueOnce('close')
.mockResolvedValue('confirm')
Vue.prototype.$http.post.mockResolvedValue({ msg: 'ok' })
const wrapper = mount(Profile)
const button = wrapper.find('[data-test=resetAvatar]')
@ -43,36 +38,34 @@ test('reset avatar', async () => {
{ tid: 0 }
)
await flushPromises()
expect(toastr.success).toBeCalledWith('ok')
expect(Vue.prototype.$message.success).toBeCalledWith('ok')
expect(document.querySelector('img')!.src).toMatch(/\d+$/)
})
test('change password', async () => {
jest.spyOn(toastr, 'info')
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: 'w' })
.mockResolvedValueOnce({ errno: 0, msg: 'o' })
swal.mockResolvedValue({})
const wrapper = mount(Profile)
const button = wrapper.find('[data-test=changePassword]')
button.trigger('click')
expect(toastr.info).toBeCalledWith('user.emptyPassword')
expect(Vue.prototype.$message.error).toBeCalledWith('user.emptyPassword')
expect(Vue.prototype.$http.post).not.toBeCalled()
wrapper.setData({ oldPassword: '1' })
button.trigger('click')
expect(toastr.info).toBeCalledWith('user.emptyNewPassword')
expect(Vue.prototype.$message.error).toBeCalledWith('user.emptyNewPassword')
expect(Vue.prototype.$http.post).not.toBeCalled()
wrapper.setData({ newPassword: '1' })
button.trigger('click')
expect(toastr.info).toBeCalledWith('auth.emptyConfirmPwd')
expect(Vue.prototype.$message.error).toBeCalledWith('auth.emptyConfirmPwd')
expect(Vue.prototype.$http.post).not.toBeCalled()
wrapper.setData({ confirmPassword: '2' })
button.trigger('click')
expect(toastr.info).toBeCalledWith('auth.invalidConfirmPwd')
expect(Vue.prototype.$message.error).toBeCalledWith('auth.invalidConfirmPwd')
expect(Vue.prototype.$http.post).not.toBeCalled()
wrapper.setData({ confirmPassword: '1' })
@ -82,36 +75,32 @@ test('change password', async () => {
'/user/profile?action=password',
{ current_password: '1', new_password: '1' }
)
expect(swal).toBeCalledWith({ type: 'warning', text: 'w' })
expect(Vue.prototype.$alert).toBeCalledWith('w', { type: 'warning' })
button.trigger('click')
await wrapper.vm.$nextTick()
expect(swal).toBeCalledWith({ type: 'success', text: 'o' })
expect(Vue.prototype.$alert).toBeCalledWith('o')
})
test('change nickname', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: 'w' })
.mockResolvedValue({ errno: 0, msg: 'o' })
swal.mockResolvedValueOnce({})
.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({})
Vue.prototype.$confirm
.mockRejectedValueOnce('close')
.mockResolvedValue('confirm')
const wrapper = mount(Profile)
const button = wrapper.find('[data-test=changeNickName]')
document.body.innerHTML += '<span class="nickname"></span>'
button.trigger('click')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(swal).toBeCalledWith({ type: 'error', text: 'user.emptyNewNickName' })
expect(Vue.prototype.$alert).toBeCalledWith('user.emptyNewNickName', { type: 'error' })
wrapper.setData({ nickname: 'nickname' })
button.trigger('click')
expect(Vue.prototype.$http.post).not.toBeCalled()
expect(swal).toBeCalledWith({
text: 'user.changeNickName',
type: 'question',
showCancelButton: true,
})
expect(Vue.prototype.$confirm).toBeCalledWith('user.changeNickName')
button.trigger('click')
await wrapper.vm.$nextTick()
@ -120,11 +109,11 @@ test('change nickname', async () => {
{ new_nickname: 'nickname' }
)
await wrapper.vm.$nextTick()
expect(swal).toBeCalledWith({ type: 'warning', text: 'w' })
expect(Vue.prototype.$alert).toBeCalledWith('w', { type: 'warning' })
button.trigger('click')
await flushPromises()
expect(swal).toBeCalledWith({ type: 'success', text: 'o' })
expect(Vue.prototype.$message.success).toBeCalledWith('o')
expect(document.querySelector('.nickname')!.textContent).toBe('nickname')
})
@ -132,29 +121,24 @@ test('change email', async () => {
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: 'w' })
.mockResolvedValue({ errno: 0, msg: 'o' })
swal.mockResolvedValueOnce({})
.mockResolvedValueOnce({})
.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({})
Vue.prototype.$confirm
.mockRejectedValueOnce('close')
.mockResolvedValue('confirm')
const wrapper = mount(Profile)
const button = wrapper.find('[data-test=changeEmail]')
button.trigger('click')
expect(swal).toBeCalledWith({ type: 'error', text: 'user.emptyNewEmail' })
expect(Vue.prototype.$alert).toBeCalledWith('user.emptyNewEmail', { type: 'error' })
expect(Vue.prototype.$http.post).not.toBeCalled()
wrapper.setData({ email: 'e' })
button.trigger('click')
expect(swal).toBeCalledWith({ type: 'warning', text: 'auth.invalidEmail' })
expect(Vue.prototype.$alert).toBeCalledWith('auth.invalidEmail', { type: 'warning' })
expect(Vue.prototype.$http.post).not.toBeCalled()
wrapper.setData({ email: 'a@b.c', currentPassword: 'abc' })
button.trigger('click')
expect(swal).toBeCalledWith({
text: 'user.changeEmail',
type: 'question',
showCancelButton: true,
})
expect(Vue.prototype.$confirm).toBeCalledWith('user.changeEmail')
expect(Vue.prototype.$http.post).not.toBeCalled()
button.trigger('click')
@ -164,16 +148,15 @@ test('change email', async () => {
{ new_email: 'a@b.c', password: 'abc' }
)
await wrapper.vm.$nextTick()
expect(swal).toBeCalledWith({ type: 'warning', text: 'w' })
expect(Vue.prototype.$alert).toBeCalledWith('w', { type: 'warning' })
button.trigger('click')
await flushPromises()
expect(swal).toBeCalledWith({ type: 'success', text: 'o' })
expect(Vue.prototype.$message.success).toBeCalledWith('o')
})
test('delete account', async () => {
window.blessing.extra = { admin: true }
swal.mockResolvedValue({})
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: 'w' })
.mockResolvedValue({ errno: 0, msg: 'o' })
@ -181,7 +164,7 @@ test('delete account', async () => {
const button = wrapper.find('[data-test=deleteAccount]')
button.trigger('click')
expect(swal).toBeCalledWith({ type: 'warning', text: 'user.emptyDeletePassword' })
expect(Vue.prototype.$alert).toBeCalledWith('user.emptyDeletePassword', { type: 'error' })
expect(Vue.prototype.$http.post).not.toBeCalled()
wrapper.setData({ deleteConfirm: 'abc' })
@ -191,9 +174,9 @@ test('delete account', async () => {
{ password: 'abc' }
)
await wrapper.vm.$nextTick()
expect(swal).toBeCalledWith({ type: 'warning', text: 'w' })
expect(Vue.prototype.$alert).toBeCalledWith('w', { type: 'warning' })
button.trigger('click')
await wrapper.vm.$nextTick()
expect(swal).toBeCalledWith({ type: 'success', text: 'o' })
expect(Vue.prototype.$alert).toBeCalledWith('o', { type: 'success' })
})

View File

@ -1,4 +1,7 @@
<!-- Bundled styles -->
@if (app()->environment('development'))
<script src="{{ webpack_assets('style.js') }}"></script>
@endif
<link rel="stylesheet" href="{{ webpack_assets('style.css') }}">
<!-- AdminLTE color scheme -->
<link rel="stylesheet" href="{{ webpack_assets('skins/'.option('color_scheme').'.min.css') }}">

View File

@ -15,12 +15,12 @@ const config = {
style: [
'bootstrap/dist/css/bootstrap.min.css',
'admin-lte/dist/css/AdminLTE.min.css',
'element-ui/lib/theme-chalk/base.css',
'./resources/assets/src/element.scss',
'@fortawesome/fontawesome-free/css/fontawesome.min.css',
'@fortawesome/fontawesome-free/css/regular.min.css',
'@fortawesome/fontawesome-free/css/solid.min.css',
'icheck/skins/square/blue.css',
'toastr/build/toastr.min.css',
'sweetalert2/dist/sweetalert2.min.css',
'./resources/assets/src/stylus/common.styl',
],
setup: './resources/assets/src/stylus/setup.styl',
@ -54,11 +54,12 @@ const config = {
],
},
{
test: /node_modules.*\.css$/,
test: /((node_modules.*)|element)\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { importLoaders: 1 } },
'csso-loader?-comments',
devMode ? 'style-loader?hmr=true' : MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { importLoaders: 2 } },
'postcss-loader',
'sass-loader',
],
},
{
@ -84,7 +85,7 @@ const config = {
},
{
test: /\.(svg|woff2?|eot|ttf)$/,
loader: 'file-loader',
loader: devMode ? 'url-loader' : 'file-loader',
},
{
test: require.resolve('jquery'),

666
yarn.lock

File diff suppressed because it is too large Load Diff