mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Explore Test Automation (#320)
* config jest and add setup for unittest * config jest coverage * example of unit testing a Status widget/component * add license for test file * add test/run command in the .travis.yml * add mock store and i18n for vue jest * add mock file missing * add mock router * add lincence to mock file & decodeHtml to setup file * add mock axios instance & fix eslint on tests folder * add test components > views > ActionButton component * fix for test coverage success * refactor test file * add test Views > Autogenview.vue (Navigation Guard, Watchers, Computed) * history mode mockRouter, refactor test code, test Autogenview > fetchData (routeName) * test Views > AutogenView.vue (processing 31%) * add mock router exception & test Views > AutogenView.vue (processing 43%) * test Views > AutogenView (processing 65%), add test onSearch, closeAction, execAction, listUuidOpts * refactor and add comment test files * test Views > AutogenView (processing 91%) * add comment file AutogenView.spec.js * test Views > AutogenView.vue (handleSubmit method) Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
parent
64d95fb6e3
commit
338de72665
7
ui/.babelrc
Normal file
7
ui/.babelrc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"test": {
|
||||||
|
"plugins": ["require-context-hook"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -22,3 +22,4 @@ cache:
|
|||||||
npm: false
|
npm: false
|
||||||
script:
|
script:
|
||||||
- npm run lint && npm run build
|
- npm run lint && npm run build
|
||||||
|
- npm run test:unit
|
||||||
|
|||||||
@ -15,10 +15,11 @@
|
|||||||
// specific language governing permissions and limitations
|
// specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
module.exports = {
|
const babelConfig = {
|
||||||
presets: [
|
presets: [
|
||||||
'@vue/app'
|
'@vue/app'
|
||||||
]
|
],
|
||||||
|
plugins: []
|
||||||
// if your use import on Demand, Use this code
|
// if your use import on Demand, Use this code
|
||||||
// ,
|
// ,
|
||||||
// plugins: [
|
// plugins: [
|
||||||
@ -29,3 +30,9 @@ module.exports = {
|
|||||||
// } ]
|
// } ]
|
||||||
// ]
|
// ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'test') {
|
||||||
|
babelConfig.plugins.push('require-context-hook')
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = babelConfig
|
||||||
|
|||||||
@ -16,6 +16,8 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
testURL: 'http://localhost/',
|
||||||
|
setupFiles: ['<rootDir>/tests/setup.js'],
|
||||||
moduleFileExtensions: [
|
moduleFileExtensions: [
|
||||||
'js',
|
'js',
|
||||||
'jsx',
|
'jsx',
|
||||||
@ -24,11 +26,13 @@ module.exports = {
|
|||||||
],
|
],
|
||||||
transform: {
|
transform: {
|
||||||
'^.+\\.vue$': 'vue-jest',
|
'^.+\\.vue$': 'vue-jest',
|
||||||
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
|
'.+\\.(css|styl|less|sass|scss|png|svg|jpg|ttf|woff|woff2)?$': 'jest-transform-stub',
|
||||||
'^.+\\.jsx?$': 'babel-jest'
|
'^.+\\.jsx?$': 'babel-jest'
|
||||||
},
|
},
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'^@/(.*)$': '<rootDir>/src/$1'
|
'.+\\.svg?.+$': 'jest-transform-stub',
|
||||||
|
'^@/(.*)$': '<rootDir>/src/$1',
|
||||||
|
'^@public/(.*)$': '<rootDir>/public/$1'
|
||||||
},
|
},
|
||||||
snapshotSerializers: [
|
snapshotSerializers: [
|
||||||
'jest-serializer-vue'
|
'jest-serializer-vue'
|
||||||
@ -36,5 +40,14 @@ module.exports = {
|
|||||||
testMatch: [
|
testMatch: [
|
||||||
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
|
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
|
||||||
],
|
],
|
||||||
testURL: 'http://localhost/'
|
transformIgnorePatterns: [
|
||||||
|
'<rootDir>/node_modules/(?!ant-design-vue|vue)'
|
||||||
|
],
|
||||||
|
collectCoverage: true,
|
||||||
|
collectCoverageFrom: [
|
||||||
|
'<rootDir>/src/**/*.{js,vue}',
|
||||||
|
'!**/node_modules/**',
|
||||||
|
'!<rootDir>/src/locales/*.{js, json}'
|
||||||
|
],
|
||||||
|
coverageReporters: ['html', 'text-summary']
|
||||||
}
|
}
|
||||||
|
|||||||
63
ui/package-lock.json
generated
63
ui/package-lock.json
generated
@ -3803,6 +3803,7 @@
|
|||||||
"vue-loader": "^15.9.2",
|
"vue-loader": "^15.9.2",
|
||||||
"vue-style-loader": "^4.1.2",
|
"vue-style-loader": "^4.1.2",
|
||||||
"webpack": "^4.0.0",
|
"webpack": "^4.0.0",
|
||||||
|
"webpack-bundle-analyzer": "^3.8.0",
|
||||||
"webpack-chain": "^6.4.0",
|
"webpack-chain": "^6.4.0",
|
||||||
"webpack-dev-server": "^3.11.0",
|
"webpack-dev-server": "^3.11.0",
|
||||||
"webpack-merge": "^4.2.2"
|
"webpack-merge": "^4.2.2"
|
||||||
@ -10190,9 +10191,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"duplexer": {
|
"duplexer": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||||
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
|
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"duplexer3": {
|
"duplexer3": {
|
||||||
@ -18055,9 +18056,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"opener": {
|
"opener": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
|
||||||
"integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==",
|
"integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"opn": {
|
"opn": {
|
||||||
@ -24873,6 +24874,56 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"webpack-bundle-analyzer": {
|
||||||
|
"version": "3.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.0.tgz",
|
||||||
|
"integrity": "sha512-Ob8amZfCm3rMB1ScjQVlbYYUEJyEjdEtQ92jqiFUYt5VkEeO2v5UMbv49P/gnmCZm3A6yaFQzCBvpZqN4MUsdA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"acorn": "^7.1.1",
|
||||||
|
"acorn-walk": "^7.1.1",
|
||||||
|
"bfj": "^6.1.1",
|
||||||
|
"chalk": "^2.4.1",
|
||||||
|
"commander": "^2.18.0",
|
||||||
|
"ejs": "^2.6.1",
|
||||||
|
"express": "^4.16.3",
|
||||||
|
"filesize": "^3.6.1",
|
||||||
|
"gzip-size": "^5.0.0",
|
||||||
|
"lodash": "^4.17.19",
|
||||||
|
"mkdirp": "^0.5.1",
|
||||||
|
"opener": "^1.5.1",
|
||||||
|
"ws": "^6.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"acorn": {
|
||||||
|
"version": "7.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
|
||||||
|
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"acorn-walk": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"commander": {
|
||||||
|
"version": "2.20.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||||
|
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"mkdirp": {
|
||||||
|
"version": "0.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
|
||||||
|
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"minimist": "^1.2.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"webpack-chain": {
|
"webpack-chain": {
|
||||||
"version": "6.5.1",
|
"version": "6.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.5.1.tgz",
|
||||||
|
|||||||
@ -39,6 +39,7 @@
|
|||||||
"ant-design-vue": "~1.6.2",
|
"ant-design-vue": "~1.6.2",
|
||||||
"antd-theme-webpack-plugin": "^1.3.4",
|
"antd-theme-webpack-plugin": "^1.3.4",
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
|
"babel-plugin-require-context-hook": "^1.0.0",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"enquire.js": "^2.1.6",
|
"enquire.js": "^2.1.6",
|
||||||
"js-cookie": "^2.2.1",
|
"js-cookie": "^2.2.1",
|
||||||
@ -153,6 +154,9 @@
|
|||||||
"autoprefixer": {}
|
"autoprefixer": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"jest": {
|
||||||
|
"testEnvironment": "node"
|
||||||
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"> 1%",
|
"> 1%",
|
||||||
"last 2 versions",
|
"last 2 versions",
|
||||||
|
|||||||
@ -80,7 +80,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
actionBadge: []
|
actionBadge: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
@ -132,7 +132,7 @@ export default {
|
|||||||
this.$emit('exec-action', action)
|
this.$emit('exec-action', action)
|
||||||
},
|
},
|
||||||
handleShowBadge () {
|
handleShowBadge () {
|
||||||
const dataBadge = {}
|
this.actionBadge = {}
|
||||||
const arrAsync = []
|
const arrAsync = []
|
||||||
const actionBadge = this.actions.filter(action => action.showBadge === true)
|
const actionBadge = this.actions.filter(action => action.showBadge === true)
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json[responseJsonName].count && json[responseJsonName].count > 0) {
|
if (json[responseJsonName] && json[responseJsonName].count && json[responseJsonName].count > 0) {
|
||||||
response.count = json[responseJsonName].count
|
response.count = json[responseJsonName].count
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,12 +170,10 @@ export default {
|
|||||||
|
|
||||||
Promise.all(arrAsync).then(response => {
|
Promise.all(arrAsync).then(response => {
|
||||||
for (let j = 0; j < response.length; j++) {
|
for (let j = 0; j < response.length; j++) {
|
||||||
this.$set(dataBadge, response[j].api, {})
|
this.$set(this.actionBadge, response[j].api, {})
|
||||||
this.$set(dataBadge[response[j].api], 'badgeNum', response[j].count)
|
this.$set(this.actionBadge[response[j].api], 'badgeNum', response[j].count)
|
||||||
}
|
}
|
||||||
})
|
}).catch(() => {})
|
||||||
|
|
||||||
this.actionBadge = dataBadge
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -164,19 +164,19 @@ export default {
|
|||||||
jobId: jobid,
|
jobId: jobid,
|
||||||
successMessage: `${this.$t('message.success.migrating')} ${this.resource.name}`,
|
successMessage: `${this.$t('message.success.migrating')} ${this.resource.name}`,
|
||||||
successMethod: () => {
|
successMethod: () => {
|
||||||
this.$parent.$parent.close()
|
this.$emit('close-action')
|
||||||
},
|
},
|
||||||
errorMessage: this.$t('message.migrating.failed'),
|
errorMessage: this.$t('message.migrating.failed'),
|
||||||
errorMethod: () => {
|
errorMethod: () => {
|
||||||
this.$parent.$parent.close()
|
this.$emit('close-action')
|
||||||
},
|
},
|
||||||
loadingMessage: `${this.$t('message.migrating.processing')} ${this.resource.name}`,
|
loadingMessage: `${this.$t('message.migrating.processing')} ${this.resource.name}`,
|
||||||
catchMessage: this.$t('error.fetching.async.job.result'),
|
catchMessage: this.$t('error.fetching.async.job.result'),
|
||||||
catchMethod: () => {
|
catchMethod: () => {
|
||||||
this.$parent.$parent.close()
|
this.$emit('close-action')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.$parent.$parent.close()
|
this.$emit('close-action')
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.$notification.error({
|
this.$notification.error({
|
||||||
message: this.$t('message.request.failed'),
|
message: this.$t('message.request.failed'),
|
||||||
|
|||||||
88
ui/tests/common/index.js
Normal file
88
ui/tests/common/index.js
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
// or more contributor license agreements. See the NOTICE file
|
||||||
|
// distributed with this work for additional information
|
||||||
|
// regarding copyright ownership. The ASF licenses this file
|
||||||
|
// to you under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in compliance
|
||||||
|
// with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing,
|
||||||
|
// software distributed under the License is distributed on an
|
||||||
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
// KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
import mockI18n from '../mock/mockI18n'
|
||||||
|
import mockStore from '../mock/mockStore'
|
||||||
|
import mockRouter from '../mock/mockRouter'
|
||||||
|
|
||||||
|
import localVue from '../setup'
|
||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import { pollJobPlugin, notifierPlugin } from '@/utils/plugins'
|
||||||
|
|
||||||
|
localVue.use(pollJobPlugin)
|
||||||
|
localVue.use(notifierPlugin)
|
||||||
|
|
||||||
|
function createMockRouter (newRoutes = []) {
|
||||||
|
let routes = []
|
||||||
|
if (!newRoutes || Object.keys(newRoutes).length === 0) {
|
||||||
|
return mockRouter.mock(routes)
|
||||||
|
}
|
||||||
|
|
||||||
|
routes = [...newRoutes]
|
||||||
|
|
||||||
|
return mockRouter.mock(routes)
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMockI18n (locale = 'en', messages = {}) {
|
||||||
|
return mockI18n.mock(locale, messages)
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMockStore (state = {}, actions = {}) {
|
||||||
|
return mockStore.mock(state, actions)
|
||||||
|
}
|
||||||
|
|
||||||
|
function decodeHtml (html) {
|
||||||
|
const text = document.createElement('textarea')
|
||||||
|
text.innerHTML = html
|
||||||
|
|
||||||
|
return text.value
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFactory (component, options) {
|
||||||
|
var {
|
||||||
|
router = null,
|
||||||
|
i18n = null,
|
||||||
|
store = null,
|
||||||
|
props = {},
|
||||||
|
data = {},
|
||||||
|
mocks = {}
|
||||||
|
} = options
|
||||||
|
|
||||||
|
if (!router) router = createMockRouter()
|
||||||
|
if (!i18n) i18n = createMockI18n()
|
||||||
|
if (!store) store = createMockStore()
|
||||||
|
|
||||||
|
return mount(component, {
|
||||||
|
localVue,
|
||||||
|
router,
|
||||||
|
i18n,
|
||||||
|
store,
|
||||||
|
propsData: props,
|
||||||
|
mocks,
|
||||||
|
data () {
|
||||||
|
return { ...data }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createFactory,
|
||||||
|
createMockRouter,
|
||||||
|
createMockI18n,
|
||||||
|
createMockStore,
|
||||||
|
decodeHtml
|
||||||
|
}
|
||||||
22
ui/tests/mock/mockAxios.js
Normal file
22
ui/tests/mock/mockAxios.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
// or more contributor license agreements. See the NOTICE file
|
||||||
|
// distributed with this work for additional information
|
||||||
|
// regarding copyright ownership. The ASF licenses this file
|
||||||
|
// to you under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in compliance
|
||||||
|
// with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing,
|
||||||
|
// software distributed under the License is distributed on an
|
||||||
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
// KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
const mockAxios = jest.genMockFromModule('axios')
|
||||||
|
|
||||||
|
mockAxios.create = jest.fn(() => mockAxios)
|
||||||
|
|
||||||
|
export default mockAxios
|
||||||
29
ui/tests/mock/mockI18n.js
Normal file
29
ui/tests/mock/mockI18n.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
// or more contributor license agreements. See the NOTICE file
|
||||||
|
// distributed with this work for additional information
|
||||||
|
// regarding copyright ownership. The ASF licenses this file
|
||||||
|
// to you under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in compliance
|
||||||
|
// with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing,
|
||||||
|
// software distributed under the License is distributed on an
|
||||||
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
// KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
import VueI18n from 'vue-i18n'
|
||||||
|
|
||||||
|
const mockI18n = {
|
||||||
|
mock: (locale = 'en', message = {}) => {
|
||||||
|
return new VueI18n({
|
||||||
|
locale: locale,
|
||||||
|
messages: message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default mockI18n
|
||||||
64
ui/tests/mock/mockRouter.js
Normal file
64
ui/tests/mock/mockRouter.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
// or more contributor license agreements. See the NOTICE file
|
||||||
|
// distributed with this work for additional information
|
||||||
|
// regarding copyright ownership. The ASF licenses this file
|
||||||
|
// to you under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in compliance
|
||||||
|
// with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing,
|
||||||
|
// software distributed under the License is distributed on an
|
||||||
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
// KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
import VueRouter from 'vue-router'
|
||||||
|
|
||||||
|
const mockRouter = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
name: 'home',
|
||||||
|
meta: { icon: 'home' },
|
||||||
|
children: []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
mock: (routes = []) => {
|
||||||
|
mockRouter.routes[0].children = [
|
||||||
|
{
|
||||||
|
path: '/exception',
|
||||||
|
name: 'exception',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/exception/403',
|
||||||
|
name: 403,
|
||||||
|
hidden: true,
|
||||||
|
meta: { icon: 'icon-error-test' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/exception/404',
|
||||||
|
name: 404,
|
||||||
|
hidden: true,
|
||||||
|
meta: { icon: 'icon-error-test' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/exception/500',
|
||||||
|
name: 500,
|
||||||
|
hidden: true,
|
||||||
|
meta: { icon: 'icon-error-test' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
if (routes && routes.length > 0) {
|
||||||
|
mockRouter.routes[0].children = [...mockRouter.routes[0].children, ...routes]
|
||||||
|
}
|
||||||
|
|
||||||
|
return new VueRouter({ routes: mockRouter.routes, mode: 'history' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default mockRouter
|
||||||
50
ui/tests/mock/mockStore.js
Normal file
50
ui/tests/mock/mockStore.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
// or more contributor license agreements. See the NOTICE file
|
||||||
|
// distributed with this work for additional information
|
||||||
|
// regarding copyright ownership. The ASF licenses this file
|
||||||
|
// to you under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in compliance
|
||||||
|
// with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing,
|
||||||
|
// software distributed under the License is distributed on an
|
||||||
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
// KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
import Vuex from 'vuex'
|
||||||
|
|
||||||
|
const mockStore = {
|
||||||
|
state: {},
|
||||||
|
mock: (state, actions) => {
|
||||||
|
mockStore.state = {
|
||||||
|
app: {
|
||||||
|
device: 'desktop'
|
||||||
|
},
|
||||||
|
user: {},
|
||||||
|
permission: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state && Object.keys(state).length > 0) {
|
||||||
|
mockStore.state = { ...mockStore.state, ...state }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!actions) {
|
||||||
|
actions = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Vuex.Store({
|
||||||
|
state: mockStore.state,
|
||||||
|
getters: {
|
||||||
|
apis: () => mockStore.state.user.apis,
|
||||||
|
userInfo: () => mockStore.state.user.info
|
||||||
|
},
|
||||||
|
actions
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default mockStore
|
||||||
30
ui/tests/mockData/ActionButton.mock.json
Normal file
30
ui/tests/mockData/ActionButton.mock.json
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"messages": {
|
||||||
|
"en": { "label.action": "action-en" },
|
||||||
|
"de": { "label.action": "action-de" }
|
||||||
|
},
|
||||||
|
"apis": {
|
||||||
|
"test-api-case-1": {},
|
||||||
|
"test-api-case-2": {},
|
||||||
|
"test-api-case-3": {},
|
||||||
|
"test-api-case-4": {},
|
||||||
|
"test-api-case-5": {},
|
||||||
|
"test-api-case-6": {}
|
||||||
|
},
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"name": "testRouter1",
|
||||||
|
"path": "/test-router-1",
|
||||||
|
"meta": {
|
||||||
|
"name": "systemvm"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "testRouter2",
|
||||||
|
"path": "/test-router-2",
|
||||||
|
"meta": {
|
||||||
|
"name": "test-name"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
198
ui/tests/mockData/AutogenView.mock.json
Normal file
198
ui/tests/mockData/AutogenView.mock.json
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
{
|
||||||
|
"messages": {
|
||||||
|
"en": {
|
||||||
|
"labelname": "test-name-en",
|
||||||
|
"displaytext": "description-en",
|
||||||
|
"label.column1": "column1-en",
|
||||||
|
"label.column2": "column2-en",
|
||||||
|
"label.column3": "column3-en",
|
||||||
|
"label.id": "uuid-en",
|
||||||
|
"label.name": "name-en",
|
||||||
|
"label.domainid": "domain-en",
|
||||||
|
"label.self": "self-en",
|
||||||
|
"label.all": "all-en",
|
||||||
|
"label.tags": "tags-en",
|
||||||
|
"label.account": "account-en",
|
||||||
|
"label.domainids": "domainids-en",
|
||||||
|
"label.keypair": "keypair-en",
|
||||||
|
"label.filterby": "filterby-en",
|
||||||
|
"label.refresh": "refresh-en",
|
||||||
|
"message.error.required.input": "required-en",
|
||||||
|
"message.error.select": "select-en",
|
||||||
|
"label.search": "search-en",
|
||||||
|
"label.quota.configuration": "quota-configuration-en",
|
||||||
|
"label.quota.value": "quota-value-en",
|
||||||
|
"label.quota.tariff.effectivedate": "quota-effectivedate-en",
|
||||||
|
"label.confirmpassword": "confirmpassword-en",
|
||||||
|
"label.confirmpassword.description": "confirmpassword-description-en",
|
||||||
|
"label.open.documentation": "open",
|
||||||
|
"label.metrics": "metrics",
|
||||||
|
"label.showing": "Showing",
|
||||||
|
"label.of": "of",
|
||||||
|
"label.items": "items",
|
||||||
|
"label.page": "page",
|
||||||
|
"label.view.console": "view-console-en",
|
||||||
|
"error.fetching.async.job.result": "Error encountered while fetching async job result",
|
||||||
|
"label.cancel": "cancel",
|
||||||
|
"label.ok": "ok"
|
||||||
|
},
|
||||||
|
"de": {
|
||||||
|
"labelname": "test-name-de",
|
||||||
|
"displaytext": "description-de",
|
||||||
|
"label.column1": "column1-de",
|
||||||
|
"label.column2": "column2-de",
|
||||||
|
"label.column3": "column3-de",
|
||||||
|
"label.id": "uuid-de",
|
||||||
|
"label.name": "name-de",
|
||||||
|
"label.domainid": "domain-de",
|
||||||
|
"label.self": "self-de",
|
||||||
|
"label.all": "all-de",
|
||||||
|
"label.tags": "tags-de",
|
||||||
|
"label.account": "account-de",
|
||||||
|
"label.domainids": "domainids-de",
|
||||||
|
"label.keypair": "keypair-de",
|
||||||
|
"label.filterby": "filterby-de",
|
||||||
|
"label.refresh": "refresh-de",
|
||||||
|
"message.error.required.input": "required-de",
|
||||||
|
"message.error.select": "select-de",
|
||||||
|
"label.search": "search-de",
|
||||||
|
"label.quota.configuration": "quota-configuration-de",
|
||||||
|
"label.quota.value": "quota-value-de",
|
||||||
|
"label.quota.tariff.effectivedate": "quota-effectivedate-de",
|
||||||
|
"label.confirmpassword": "confirmpassword-de",
|
||||||
|
"label.confirmpassword.description": "confirmpassword-description-de",
|
||||||
|
"label.open.documentation": "open",
|
||||||
|
"label.metrics": "metrics",
|
||||||
|
"label.showing": "Showing",
|
||||||
|
"label.of": "of",
|
||||||
|
"label.items": "items",
|
||||||
|
"label.page": "page",
|
||||||
|
"label.view.console": "view-console-de",
|
||||||
|
"error.fetching.async.job.result": "Error encountered while fetching async job result",
|
||||||
|
"label.cancel": "cancel",
|
||||||
|
"label.ok": "ok"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"apis": {
|
||||||
|
"testApiNameCase1": {
|
||||||
|
"params": {},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
"testApiNameCase2": {
|
||||||
|
"params": {},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
"testApiNameCase3": {
|
||||||
|
"params": {},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
"testApiNameCase4": {
|
||||||
|
"params": {},
|
||||||
|
"response": [
|
||||||
|
{
|
||||||
|
"name": "column2",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "column1",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "column3",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"testApiNameCase5": {
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "column2",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "column1",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "column3",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
"testApiNameCase6": {
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"type": "uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tags",
|
||||||
|
"type": "list"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "column1",
|
||||||
|
"type": "list"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "column2",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "account",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "confirmpassword",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
"listTemplates": {
|
||||||
|
"params": {},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
"listIsos": {
|
||||||
|
"params": {},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
"listRoles": {
|
||||||
|
"params": {},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
"listHosts": {
|
||||||
|
"params": {},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
"listTestApiNames": {
|
||||||
|
"params": {},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
"createAccount": {
|
||||||
|
"params": {},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
"addAccountToProject": {
|
||||||
|
"params": {},
|
||||||
|
"response": []
|
||||||
|
},
|
||||||
|
"quotaEmailTemplateList": {
|
||||||
|
"params": {},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"info": {
|
||||||
|
"roletype": "Normal",
|
||||||
|
"account": "test-account",
|
||||||
|
"domainid": "test-domain-id"
|
||||||
|
}
|
||||||
|
}
|
||||||
24
ui/tests/mockData/MigrateWizard.mock.json
Normal file
24
ui/tests/mockData/MigrateWizard.mock.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"messages": {
|
||||||
|
"en": {
|
||||||
|
"name": "name-en",
|
||||||
|
"Suitability": "Suitability-en",
|
||||||
|
"cpuused": "cpuused-en",
|
||||||
|
"memused": "memused-en",
|
||||||
|
"select": "select-en",
|
||||||
|
"ok": "ok-en",
|
||||||
|
"message.load.host.failed": "Failed to load hosts",
|
||||||
|
"message.migrating.vm.to.host.failed": "Failed to migrate VM to host"
|
||||||
|
},
|
||||||
|
"de": {
|
||||||
|
"name": "name-de",
|
||||||
|
"Suitability": "Suitability-de",
|
||||||
|
"cpuused": "cpuused-de",
|
||||||
|
"memused": "memused-de",
|
||||||
|
"select": "select-de",
|
||||||
|
"ok": "ok-de",
|
||||||
|
"message.load.host.failed": "Failed to load hosts",
|
||||||
|
"message.migrating.vm.to.host.failed": "Failed to migrate VM to host"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
ui/tests/mockData/Status.mock.json
Normal file
38
ui/tests/mockData/Status.mock.json
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"messages": {
|
||||||
|
"en": {
|
||||||
|
"state.running": "Running",
|
||||||
|
"state.migrating": "Migrating",
|
||||||
|
"state.stopped": "Stopped",
|
||||||
|
"state.starting": "Starting",
|
||||||
|
"state.stopping": "Stopping",
|
||||||
|
"state.suspended": "Suspended",
|
||||||
|
"state.pending": "Pending",
|
||||||
|
"state.expunging": "Expunging",
|
||||||
|
"state.error": "Error",
|
||||||
|
"message.publicip.state.allocated": "Allocated",
|
||||||
|
"message.publicip.state.created": "Created",
|
||||||
|
"message.vmsnapshot.state.active": "Active",
|
||||||
|
"message.vm.state.active": "Active",
|
||||||
|
"message.volume.state.active": "Active",
|
||||||
|
"message.guestnetwork.state.active": "Active",
|
||||||
|
"message.publicip.state.active": "Active",
|
||||||
|
"Created": "Created",
|
||||||
|
"Active": "Active",
|
||||||
|
"Allocated": "Allocated",
|
||||||
|
"Error": "Error",
|
||||||
|
"Expunging": "Expunging",
|
||||||
|
"Suspended": "Suspended",
|
||||||
|
"Pending": "Pending",
|
||||||
|
"Running": "Running",
|
||||||
|
"Starting": "Starting",
|
||||||
|
"Another": "Another",
|
||||||
|
"Ready": "Ready",
|
||||||
|
"Disabled": "Disabled",
|
||||||
|
"Migrating": "Migrating",
|
||||||
|
"Stopping": "Stopping",
|
||||||
|
"Alert": "Alert",
|
||||||
|
"Stopped": "Stopped"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
49
ui/tests/setup.js
Normal file
49
ui/tests/setup.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
// or more contributor license agreements. See the NOTICE file
|
||||||
|
// distributed with this work for additional information
|
||||||
|
// regarding copyright ownership. The ASF licenses this file
|
||||||
|
// to you under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in compliance
|
||||||
|
// with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing,
|
||||||
|
// software distributed under the License is distributed on an
|
||||||
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
// KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
import Vue from 'vue'
|
||||||
|
import Vuex from 'vuex'
|
||||||
|
import Antd from 'ant-design-vue'
|
||||||
|
import VueRouter from 'vue-router'
|
||||||
|
import VueI18n from 'vue-i18n'
|
||||||
|
import VueStorage from 'vue-ls'
|
||||||
|
import VueClipboard from 'vue-clipboard2'
|
||||||
|
import config from '@/config/settings'
|
||||||
|
import { createLocalVue } from '@vue/test-utils'
|
||||||
|
import registerRequireContextHook from 'babel-plugin-require-context-hook/register'
|
||||||
|
|
||||||
|
const localVue = createLocalVue()
|
||||||
|
|
||||||
|
Vue.use(Antd)
|
||||||
|
Vue.use(VueStorage, config.storageOptions)
|
||||||
|
|
||||||
|
localVue.use(VueRouter)
|
||||||
|
localVue.use(VueI18n)
|
||||||
|
localVue.use(Vuex)
|
||||||
|
localVue.use(VueClipboard)
|
||||||
|
|
||||||
|
registerRequireContextHook()
|
||||||
|
|
||||||
|
window.matchMedia = window.matchMedia || function () {
|
||||||
|
return {
|
||||||
|
matches: false,
|
||||||
|
addListener: function () {},
|
||||||
|
removeListener: function () {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = localVue
|
||||||
337
ui/tests/unit/components/view/ActionButton.spec.js
Normal file
337
ui/tests/unit/components/view/ActionButton.spec.js
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
// Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
// or more contributor license agreements. See the NOTICE file
|
||||||
|
// distributed with this work for additional information
|
||||||
|
// regarding copyright ownership. The ASF licenses this file
|
||||||
|
// to you under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in compliance
|
||||||
|
// with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing,
|
||||||
|
// software distributed under the License is distributed on an
|
||||||
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
// KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
import mockAxios from '../../../mock/mockAxios'
|
||||||
|
import ActionButton from '@/components/view/ActionButton'
|
||||||
|
import common from '../../../common'
|
||||||
|
import mockData from '../../../mockData/ActionButton.mock.json'
|
||||||
|
|
||||||
|
jest.mock('axios', () => mockAxios)
|
||||||
|
|
||||||
|
let router, store, i18n
|
||||||
|
const state = {
|
||||||
|
user: {
|
||||||
|
apis: mockData.apis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
router = common.createMockRouter(mockData.routes)
|
||||||
|
store = common.createMockStore(state)
|
||||||
|
i18n = common.createMockI18n('en', mockData.messages)
|
||||||
|
|
||||||
|
const factory = (opts = {}) => {
|
||||||
|
router = opts.router || router
|
||||||
|
store = opts.store || store
|
||||||
|
i18n = opts.i18n || i18n
|
||||||
|
|
||||||
|
return common.createFactory(ActionButton, {
|
||||||
|
router,
|
||||||
|
store,
|
||||||
|
i18n,
|
||||||
|
props: opts.props || {},
|
||||||
|
data: opts.data || {}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Components > View > ActionButton.vue', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Template', () => {
|
||||||
|
it('Button action is show', () => {
|
||||||
|
const expected = '<i aria-label="icon: plus" class="anticon anticon-plus">'
|
||||||
|
const wrapper = factory()
|
||||||
|
|
||||||
|
wrapper.vm.$nextTick(() => {
|
||||||
|
const received = wrapper.html()
|
||||||
|
|
||||||
|
expect(received).not.toContain(expected)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Normal button action is show', () => {
|
||||||
|
const expected = '<i aria-label="icon: plus" class="anticon anticon-plus">'
|
||||||
|
const propsData = {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
label: 'label.action',
|
||||||
|
api: 'test-api-case-1',
|
||||||
|
showBadge: false,
|
||||||
|
icon: 'plus',
|
||||||
|
dataView: false,
|
||||||
|
listView: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
dataView: false,
|
||||||
|
listView: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
|
||||||
|
wrapper.vm.$nextTick(() => {
|
||||||
|
const received = wrapper.html()
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Badge button action is show', (done) => {
|
||||||
|
const expected = '<span class="button-action-badge ant-badge">'
|
||||||
|
const propsData = {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
label: 'label.action',
|
||||||
|
api: 'test-api-case-2',
|
||||||
|
showBadge: true,
|
||||||
|
icon: 'plus',
|
||||||
|
dataView: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
dataView: true
|
||||||
|
}
|
||||||
|
const dataMock = {
|
||||||
|
testapinameresponse: {
|
||||||
|
count: 0,
|
||||||
|
testapiname: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mockAxios.mockImplementation(() => Promise.resolve(dataMock))
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
|
||||||
|
wrapper.vm.$nextTick(() => {
|
||||||
|
const wrapperHtml = wrapper.html()
|
||||||
|
const received = common.decodeHtml(wrapperHtml)
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Method', () => {
|
||||||
|
describe('handleShowBadge()', () => {
|
||||||
|
it('check the api is called and returned is not null', (done) => {
|
||||||
|
const postData = new URLSearchParams()
|
||||||
|
const expected = { 'test-api-case-3': { badgeNum: 2 } }
|
||||||
|
const dataMock = { testapinameresponse: { count: 2 } }
|
||||||
|
const propsData = {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
label: 'label.action',
|
||||||
|
api: 'test-api-case-3',
|
||||||
|
showBadge: true,
|
||||||
|
icon: 'plus',
|
||||||
|
dataView: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
dataView: true
|
||||||
|
}
|
||||||
|
|
||||||
|
mockAxios.mockResolvedValue(dataMock)
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(mockAxios).toHaveBeenCalledTimes(1)
|
||||||
|
expect(mockAxios).toHaveBeenCalledWith({
|
||||||
|
data: postData,
|
||||||
|
method: 'GET',
|
||||||
|
params: {
|
||||||
|
command: 'test-api-case-3',
|
||||||
|
response: 'json'
|
||||||
|
},
|
||||||
|
url: '/'
|
||||||
|
})
|
||||||
|
expect(wrapper.vm.actionBadge).toEqual(expected)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check the api is called returned is null', (done) => {
|
||||||
|
const postData = new URLSearchParams()
|
||||||
|
const expected = { 'test-api-case-4': { badgeNum: 0 } }
|
||||||
|
const dataMock = { data: [] }
|
||||||
|
const propsData = {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
label: 'label.action',
|
||||||
|
api: 'test-api-case-4',
|
||||||
|
showBadge: true,
|
||||||
|
icon: 'plus',
|
||||||
|
dataView: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
dataView: true
|
||||||
|
}
|
||||||
|
|
||||||
|
mockAxios.mockResolvedValue(dataMock)
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(mockAxios).toHaveBeenCalledTimes(1)
|
||||||
|
expect(mockAxios).toHaveBeenCalledWith({
|
||||||
|
data: postData,
|
||||||
|
method: 'GET',
|
||||||
|
params: {
|
||||||
|
command: 'test-api-case-4',
|
||||||
|
response: 'json'
|
||||||
|
},
|
||||||
|
url: '/'
|
||||||
|
})
|
||||||
|
expect(wrapper.vm.actionBadge).toEqual(expected)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check the api is called and throws error', (done) => {
|
||||||
|
const postData = new URLSearchParams()
|
||||||
|
const propsData = {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
label: 'label.action',
|
||||||
|
api: 'test-api-case-5',
|
||||||
|
showBadge: true,
|
||||||
|
icon: 'plus',
|
||||||
|
dataView: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
dataView: true
|
||||||
|
}
|
||||||
|
const errorMessage = 'errMethodMessage'
|
||||||
|
|
||||||
|
mockAxios.mockImplementationOnce(() => Promise.reject(errorMessage))
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(mockAxios).toHaveBeenCalledTimes(1)
|
||||||
|
expect(mockAxios).toHaveBeenCalledWith({
|
||||||
|
data: postData,
|
||||||
|
method: 'GET',
|
||||||
|
params: {
|
||||||
|
command: 'test-api-case-5',
|
||||||
|
response: 'json'
|
||||||
|
},
|
||||||
|
url: '/'
|
||||||
|
})
|
||||||
|
expect(wrapper.vm.actionBadge).toEqual({})
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('execAction()', () => {
|
||||||
|
it('check emitted events are executed', async () => {
|
||||||
|
const expected = {
|
||||||
|
icon: 'plus',
|
||||||
|
label: 'label.action',
|
||||||
|
api: 'test-api-case-6',
|
||||||
|
showBadge: false,
|
||||||
|
dataView: true,
|
||||||
|
resource: {
|
||||||
|
id: 'test-resource-id'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const propsData = {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
icon: 'plus',
|
||||||
|
label: 'label.action',
|
||||||
|
api: 'test-api-case-6',
|
||||||
|
showBadge: false,
|
||||||
|
dataView: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
dataView: true,
|
||||||
|
resource: {
|
||||||
|
id: 'test-resource-id'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
|
||||||
|
await wrapper.find('button').trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
expect(wrapper.emitted()['exec-action'][0]).toEqual([expected])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Watcher', () => {
|
||||||
|
describe('handleShowBadge()', () => {
|
||||||
|
it('check handleShowBadge() is not called with empty resource', async () => {
|
||||||
|
const wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: {
|
||||||
|
id: 'test-resource-id'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const handleShowBadge = jest.spyOn(wrapper.vm, 'handleShowBadge')
|
||||||
|
wrapper.setProps({
|
||||||
|
resource: null
|
||||||
|
})
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
expect(handleShowBadge).not.toBeCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check handleShowBadge() is not called with resource containing id null', async () => {
|
||||||
|
const wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: {
|
||||||
|
id: 'test-resource-id'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleShowBadge = jest.spyOn(wrapper.vm, 'handleShowBadge')
|
||||||
|
wrapper.setProps({
|
||||||
|
resource: { id: null }
|
||||||
|
})
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
expect(handleShowBadge).not.toBeCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check handleShowBadge() is not called with changed resource data', async () => {
|
||||||
|
const wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: {
|
||||||
|
id: 'test-resource-id-1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
wrapper.setProps({
|
||||||
|
resource: {
|
||||||
|
id: 'test-resource-id-2'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const handleShowBadge = jest.spyOn(wrapper.vm, 'handleShowBadge')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
expect(handleShowBadge).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
395
ui/tests/unit/components/widgets/Status.spec.js
Normal file
395
ui/tests/unit/components/widgets/Status.spec.js
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
// Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
// or more contributor license agreements. See the NOTICE file
|
||||||
|
// distributed with this work for additional information
|
||||||
|
// regarding copyright ownership. The ASF licenses this file
|
||||||
|
// to you under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in compliance
|
||||||
|
// with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing,
|
||||||
|
// software distributed under the License is distributed on an
|
||||||
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
// KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
import Status from '@/components/widgets/Status'
|
||||||
|
import common from '../../../common'
|
||||||
|
import mockData from '../../../mockData/Status.mock.json'
|
||||||
|
|
||||||
|
let router, i18n
|
||||||
|
|
||||||
|
router = common.createMockRouter()
|
||||||
|
i18n = common.createMockI18n('en', mockData.messages)
|
||||||
|
|
||||||
|
const factory = (opts = {}) => {
|
||||||
|
router = opts.router || router
|
||||||
|
i18n = opts.i18n || i18n
|
||||||
|
|
||||||
|
return common.createFactory(Status, {
|
||||||
|
router,
|
||||||
|
i18n,
|
||||||
|
props: opts.props || {},
|
||||||
|
data: opts.data || {}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Components > Widgets > Status.vue', () => {
|
||||||
|
describe('Methods', () => {
|
||||||
|
describe('getText()', () => {
|
||||||
|
it('getText() is called and the value returned is null', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Running',
|
||||||
|
displayText: false
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge-status-text"></span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getText() is called with state equal Running', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Running',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge-status-text">Running</span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getText() is called with state equal Stopped', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Stopped',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge-status-text">Stopped</span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getText() is called with state equal Starting', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Starting',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge-status-text">Starting</span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getText() is called with state equal Stopping', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Stopping',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge-status-text">Stopping</span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getText() is called with state equal Suspended', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Suspended',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge-status-text">Suspended</span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getText() is called with state equal Pending', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Pending',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge-status-text">Pending</span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getText() is called with state equal Expunging', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Expunging',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge-status-text">Expunging</span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getText() is called with state equal Error', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Error',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge-status-text">Error</span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('getBadgeStatus()', () => {
|
||||||
|
it('getBadgeStatus() is called and the value returned is default status', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Another',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge-status-dot ant-badge-status-default"></span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getBadgeStatus() is called and the value returned is success status', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Active',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge-status-dot ant-badge-status-success"></span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getBadgeStatus() is called and the value returned is error status', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Disabled',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge-status-dot ant-badge-status-error"></span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getBadgeStatus() is called and the value returned is processing status', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Migrating',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge-status-dot ant-badge-status-processing"></span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getBadgeStatus() is called and the value returned is error status', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Alert',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge ant-badge-status ant-badge-not-a-wrapper" style="display: inline-flex;"><span class="ant-badge-status-dot ant-badge-status-error"></span><span class="ant-badge-status-text">Alert</span></span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getBadgeStatus() is called and the value returned is warning status with state equal Allocated', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Allocated',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge ant-badge-status ant-badge-not-a-wrapper" style="display: inline-flex;"><span class="ant-badge-status-dot ant-badge-status-warning"></span><span class="ant-badge-status-text">Allocated</span></span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getBadgeStatus() is called and the value returned is success status with state equal Allocated', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Allocated',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
router = common.createMockRouter([{
|
||||||
|
name: 'testRouter1',
|
||||||
|
path: '/publicip',
|
||||||
|
meta: {
|
||||||
|
icon: 'test-router-1'
|
||||||
|
}
|
||||||
|
}])
|
||||||
|
router.push({ name: 'testRouter1' })
|
||||||
|
|
||||||
|
const wrapper = factory({ router: router, props: propsData })
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge ant-badge-status ant-badge-not-a-wrapper" style="display: inline-flex;"><span class="ant-badge-status-dot ant-badge-status-success"></span><span class="ant-badge-status-text">Allocated</span></span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getBadgeStatus() is called and the value returned is warning status with state equal Created', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Created',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = factory({ props: propsData })
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge ant-badge-status ant-badge-not-a-wrapper" style="display: inline-flex;"><span class="ant-badge-status-dot ant-badge-status-warning"></span><span class="ant-badge-status-text">Created</span></span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('getTooltip()', () => {
|
||||||
|
it('getTooltip() is called with `$route.path` equal `/vmsnapshot`', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Active',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
router = common.createMockRouter([{
|
||||||
|
name: 'testRouter1',
|
||||||
|
path: '/vmsnapshot',
|
||||||
|
meta: {
|
||||||
|
icon: 'test-router-1'
|
||||||
|
}
|
||||||
|
}])
|
||||||
|
router.push({ name: 'testRouter1' })
|
||||||
|
|
||||||
|
const wrapper = factory({ router: router, props: propsData })
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge ant-badge-status ant-badge-not-a-wrapper" style="display: inline-flex;"><span class="ant-badge-status-dot ant-badge-status-success"></span><span class="ant-badge-status-text">Active</span></span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getTooltip() is called with `$route.path` equal `/vm`', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Active',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
router = common.createMockRouter([{
|
||||||
|
name: 'testRouter1',
|
||||||
|
path: '/vm',
|
||||||
|
meta: {
|
||||||
|
icon: 'test-router-1'
|
||||||
|
}
|
||||||
|
}])
|
||||||
|
router.push({ name: 'testRouter1' })
|
||||||
|
|
||||||
|
const wrapper = factory({ router: router, props: propsData })
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge ant-badge-status ant-badge-not-a-wrapper" style="display: inline-flex;"><span class="ant-badge-status-dot ant-badge-status-success"></span><span class="ant-badge-status-text">Active</span></span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getTooltip() is called with `$route.path` equal `/volume`', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Active',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
router = common.createMockRouter([{
|
||||||
|
name: 'testRouter1',
|
||||||
|
path: '/volume',
|
||||||
|
meta: {
|
||||||
|
icon: 'test-router-1'
|
||||||
|
}
|
||||||
|
}])
|
||||||
|
router.push({ name: 'testRouter1' })
|
||||||
|
|
||||||
|
const wrapper = factory({ router: router, props: propsData })
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge ant-badge-status ant-badge-not-a-wrapper" style="display: inline-flex;"><span class="ant-badge-status-dot ant-badge-status-success"></span><span class="ant-badge-status-text">Active</span></span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getTooltip() is called with `$route.path` equal `/guestnetwork`', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Active',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
router = common.createMockRouter([{
|
||||||
|
name: 'testRouter1',
|
||||||
|
path: '/guestnetwork',
|
||||||
|
meta: {
|
||||||
|
icon: 'test-router-1'
|
||||||
|
}
|
||||||
|
}])
|
||||||
|
router.push({ name: 'testRouter1' })
|
||||||
|
|
||||||
|
const wrapper = factory({ router: router, props: propsData })
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge ant-badge-status ant-badge-not-a-wrapper" style="display: inline-flex;"><span class="ant-badge-status-dot ant-badge-status-success"></span><span class="ant-badge-status-text">Active</span></span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getTooltip() is called with `$route.path` equal `/publicip`', () => {
|
||||||
|
const propsData = {
|
||||||
|
text: 'Active',
|
||||||
|
displayText: true
|
||||||
|
}
|
||||||
|
|
||||||
|
router = common.createMockRouter([{
|
||||||
|
name: 'testRouter1',
|
||||||
|
path: '/publicip',
|
||||||
|
meta: {
|
||||||
|
icon: 'test-router-1'
|
||||||
|
}
|
||||||
|
}])
|
||||||
|
router.push({ name: 'testRouter1' })
|
||||||
|
|
||||||
|
const wrapper = factory({ router: router, props: propsData })
|
||||||
|
const received = wrapper.html()
|
||||||
|
const expected = '<span class="ant-badge ant-badge-status ant-badge-not-a-wrapper" style="display: inline-flex;"><span class="ant-badge-status-dot ant-badge-status-success"></span><span class="ant-badge-status-text">Active</span></span>'
|
||||||
|
|
||||||
|
expect(received).toContain(expected)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
2939
ui/tests/unit/views/AutogenView.spec.js
Normal file
2939
ui/tests/unit/views/AutogenView.spec.js
Normal file
File diff suppressed because it is too large
Load Diff
686
ui/tests/unit/views/compute/MigrateWizard.spec.js
Normal file
686
ui/tests/unit/views/compute/MigrateWizard.spec.js
Normal file
@ -0,0 +1,686 @@
|
|||||||
|
// Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
// or more contributor license agreements. See the NOTICE file
|
||||||
|
// distributed with this work for additional information
|
||||||
|
// regarding copyright ownership. The ASF licenses this file
|
||||||
|
// to you under the Apache License, Version 2.0 (the
|
||||||
|
// "License"); you may not use this file except in compliance
|
||||||
|
// with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing,
|
||||||
|
// software distributed under the License is distributed on an
|
||||||
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
// KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
import mockAxios from '../../../mock/mockAxios'
|
||||||
|
import MigrateWizard from '@/views/compute/MigrateWizard'
|
||||||
|
import common from '../../../common'
|
||||||
|
import mockData from '../../../mockData/MigrateWizard.mock'
|
||||||
|
|
||||||
|
jest.mock('axios', () => mockAxios)
|
||||||
|
|
||||||
|
let wrapper, i18n, store, mocks
|
||||||
|
|
||||||
|
const state = {}
|
||||||
|
const actions = {
|
||||||
|
AddAsyncJob: jest.fn((jobObject) => {})
|
||||||
|
}
|
||||||
|
mocks = {
|
||||||
|
$message: {
|
||||||
|
error: jest.fn((message) => {})
|
||||||
|
},
|
||||||
|
$notification: {
|
||||||
|
error: jest.fn((message) => {})
|
||||||
|
},
|
||||||
|
$pollJob: jest.fn((obj) => {
|
||||||
|
switch (obj.jobId) {
|
||||||
|
case 'test-job-id-case-1':
|
||||||
|
if ('successMethod' in obj) {
|
||||||
|
obj.successMethod()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'test-job-id-case-2':
|
||||||
|
if ('errorMethod' in obj) {
|
||||||
|
obj.errorMethod()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'test-job-id-case-3':
|
||||||
|
if ('catchMethod' in obj) {
|
||||||
|
obj.catchMethod()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
i18n = common.createMockI18n('en', mockData.messages)
|
||||||
|
store = common.createMockStore(state, actions)
|
||||||
|
|
||||||
|
const factory = (opts = {}) => {
|
||||||
|
i18n = opts.i18n || i18n
|
||||||
|
store = opts.store || store
|
||||||
|
mocks = opts.mocks || mocks
|
||||||
|
|
||||||
|
return common.createFactory(MigrateWizard, {
|
||||||
|
i18n,
|
||||||
|
store,
|
||||||
|
mocks,
|
||||||
|
props: opts.props || {},
|
||||||
|
data: opts.data || {}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Views > compute > MigrateWizard.vue', () => {
|
||||||
|
jest.spyOn(console, 'warn').mockImplementation(() => {})
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
|
||||||
|
if (wrapper) {
|
||||||
|
wrapper.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i18n.locale !== 'en') {
|
||||||
|
i18n.locale = 'en'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Methods', () => {
|
||||||
|
describe('fetchData()', () => {
|
||||||
|
it('check api is called with resource is empty and searchQuery is null', () => {
|
||||||
|
const mockData = {
|
||||||
|
findhostsformigrationresponse: {
|
||||||
|
count: 0,
|
||||||
|
host: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mockAxios.mockResolvedValue(mockData)
|
||||||
|
wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
wrapper.vm.$nextTick(() => {
|
||||||
|
expect(mockAxios).toHaveBeenCalled()
|
||||||
|
expect(mockAxios).toHaveBeenCalledWith({
|
||||||
|
url: '/',
|
||||||
|
method: 'GET',
|
||||||
|
data: new URLSearchParams(),
|
||||||
|
params: {
|
||||||
|
command: 'findHostsForMigration',
|
||||||
|
virtualmachineid: undefined,
|
||||||
|
keyword: '',
|
||||||
|
page: 1,
|
||||||
|
pagesize: 10,
|
||||||
|
response: 'json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check api is called with resource.id is null and searchQuery is null', () => {
|
||||||
|
const mockData = {
|
||||||
|
findhostsformigrationresponse: {
|
||||||
|
count: 0,
|
||||||
|
host: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mockAxios.mockResolvedValue(mockData)
|
||||||
|
wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: { id: null }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
wrapper.vm.$nextTick(() => {
|
||||||
|
expect(mockAxios).toHaveBeenCalled()
|
||||||
|
expect(mockAxios).toHaveBeenCalledWith({
|
||||||
|
url: '/',
|
||||||
|
method: 'GET',
|
||||||
|
data: new URLSearchParams(),
|
||||||
|
params: {
|
||||||
|
command: 'findHostsForMigration',
|
||||||
|
virtualmachineid: null,
|
||||||
|
keyword: '',
|
||||||
|
page: 1,
|
||||||
|
pagesize: 10,
|
||||||
|
response: 'json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check api is called with resource.id is not null and searchQuery is null', () => {
|
||||||
|
const mockData = {
|
||||||
|
findhostsformigrationresponse: {
|
||||||
|
count: 0,
|
||||||
|
host: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mockAxios.mockResolvedValue(mockData)
|
||||||
|
wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: { id: 'test-id-value' }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
wrapper.vm.$nextTick(() => {
|
||||||
|
expect(mockAxios).toHaveBeenCalled()
|
||||||
|
expect(mockAxios).toHaveBeenCalledWith({
|
||||||
|
url: '/',
|
||||||
|
method: 'GET',
|
||||||
|
data: new URLSearchParams(),
|
||||||
|
params: {
|
||||||
|
command: 'findHostsForMigration',
|
||||||
|
virtualmachineid: 'test-id-value',
|
||||||
|
keyword: '',
|
||||||
|
page: 1,
|
||||||
|
pagesize: 10,
|
||||||
|
response: 'json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check api is called with resource.id is not null and searchQuery is not null', () => {
|
||||||
|
const mockData = {
|
||||||
|
findhostsformigrationresponse: {
|
||||||
|
count: 0,
|
||||||
|
host: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mockAxios.mockResolvedValue(mockData)
|
||||||
|
wrapper = factory({
|
||||||
|
props: { resource: { id: 'test-id-value' } },
|
||||||
|
data: { searchQuery: 'test-query-value' }
|
||||||
|
})
|
||||||
|
|
||||||
|
wrapper.vm.$nextTick(() => {
|
||||||
|
expect(mockAxios).toHaveBeenCalled()
|
||||||
|
expect(mockAxios).toHaveBeenCalledWith({
|
||||||
|
url: '/',
|
||||||
|
method: 'GET',
|
||||||
|
data: new URLSearchParams(),
|
||||||
|
params: {
|
||||||
|
command: 'findHostsForMigration',
|
||||||
|
virtualmachineid: 'test-id-value',
|
||||||
|
keyword: 'test-query-value',
|
||||||
|
page: 1,
|
||||||
|
pagesize: 10,
|
||||||
|
response: 'json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check api is called with params assign by resource, searchQuery, page, pageSize', () => {
|
||||||
|
const mockData = {
|
||||||
|
findhostsformigrationresponse: {
|
||||||
|
count: 0,
|
||||||
|
host: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mockAxios.mockResolvedValue(mockData)
|
||||||
|
wrapper = factory({
|
||||||
|
props: { resource: { id: 'test-id-value' } },
|
||||||
|
data: {
|
||||||
|
searchQuery: 'test-query-value',
|
||||||
|
page: 2,
|
||||||
|
pageSize: 20
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
wrapper.vm.$nextTick(() => {
|
||||||
|
expect(mockAxios).toHaveBeenCalled()
|
||||||
|
expect(mockAxios).toHaveBeenCalledWith({
|
||||||
|
url: '/',
|
||||||
|
method: 'GET',
|
||||||
|
data: new URLSearchParams(),
|
||||||
|
params: {
|
||||||
|
command: 'findHostsForMigration',
|
||||||
|
virtualmachineid: 'test-id-value',
|
||||||
|
keyword: 'test-query-value',
|
||||||
|
page: 2,
|
||||||
|
pagesize: 20,
|
||||||
|
response: 'json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check hosts, totalCount when api is called with response result is empty', async (done) => {
|
||||||
|
const mockData = {
|
||||||
|
findhostsformigrationresponse: {
|
||||||
|
count: 0,
|
||||||
|
host: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mockAxios.mockResolvedValue(mockData)
|
||||||
|
wrapper = factory({ props: { resource: {} } })
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(wrapper.vm.hosts).toEqual([])
|
||||||
|
expect(wrapper.vm.totalCount).toEqual(0)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check hosts, totalCount when api is called with response result is not empty', async (done) => {
|
||||||
|
const mockData = {
|
||||||
|
findhostsformigrationresponse: {
|
||||||
|
count: 1,
|
||||||
|
host: [{
|
||||||
|
id: 'test-host-id',
|
||||||
|
name: 'test-host-name',
|
||||||
|
suitability: 'test-host-suitability',
|
||||||
|
cpuused: 'test-host-cpuused',
|
||||||
|
memused: 'test-host-memused',
|
||||||
|
select: 'test-host-select'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mockAxios.mockResolvedValue(mockData)
|
||||||
|
wrapper = factory({ props: { resource: {} } })
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(wrapper.vm.hosts).toEqual([{
|
||||||
|
id: 'test-host-id',
|
||||||
|
name: 'test-host-name',
|
||||||
|
suitability: 'test-host-suitability',
|
||||||
|
cpuused: 'test-host-cpuused',
|
||||||
|
memused: 'test-host-memused',
|
||||||
|
select: 'test-host-select'
|
||||||
|
}])
|
||||||
|
expect(wrapper.vm.totalCount).toEqual(1)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check $message.error is called when api is called with throw error', async (done) => {
|
||||||
|
const mockError = 'Error: throw error message'
|
||||||
|
console.error = jest.fn()
|
||||||
|
|
||||||
|
mockAxios.mockRejectedValue(mockError)
|
||||||
|
wrapper = factory({ props: { resource: {} } })
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(mocks.$message.error).toHaveBeenCalled()
|
||||||
|
expect(mocks.$message.error).toHaveBeenCalledWith(`${i18n.t('message.load.host.failed')}: ${mockError}`)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('submitForm()', () => {
|
||||||
|
it('check api is called when selectedHost.requiresStorageMotion is true', async (done) => {
|
||||||
|
const mockData = {
|
||||||
|
migratevirtualmachineresponse: {
|
||||||
|
jobid: 'test-job-id'
|
||||||
|
},
|
||||||
|
queryasyncjobresultresponse: {
|
||||||
|
jobstatus: 1,
|
||||||
|
jobresult: {
|
||||||
|
name: 'test-name-value'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: {
|
||||||
|
id: 'test-resource-id',
|
||||||
|
name: 'test-resource-name'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
selectedHost: {
|
||||||
|
requiresStorageMotion: true,
|
||||||
|
id: 'test-host-id',
|
||||||
|
name: 'test-host-name'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
jest.spyOn(wrapper.vm, 'fetchData').mockImplementation(() => {})
|
||||||
|
mockAxios.mockResolvedValue(mockData)
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
await wrapper.vm.submitForm()
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(mockAxios).toHaveBeenCalled()
|
||||||
|
expect(mockAxios).toHaveBeenCalledWith({
|
||||||
|
url: '/',
|
||||||
|
method: 'GET',
|
||||||
|
data: new URLSearchParams(),
|
||||||
|
params: {
|
||||||
|
command: 'migrateVirtualMachineWithVolume',
|
||||||
|
hostid: 'test-host-id',
|
||||||
|
virtualmachineid: 'test-resource-id',
|
||||||
|
response: 'json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check api is called when selectedHost.requiresStorageMotion is false', async (done) => {
|
||||||
|
const mockData = {
|
||||||
|
migratevirtualmachineresponse: {
|
||||||
|
jobid: 'test-job-id'
|
||||||
|
},
|
||||||
|
queryasyncjobresultresponse: {
|
||||||
|
jobstatus: 1,
|
||||||
|
jobresult: {
|
||||||
|
name: 'test-name-value'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: {
|
||||||
|
id: 'test-resource-id',
|
||||||
|
name: 'test-resource-name'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
selectedHost: {
|
||||||
|
requiresStorageMotion: false,
|
||||||
|
id: 'test-host-id',
|
||||||
|
name: 'test-host-name'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
jest.spyOn(wrapper.vm, 'fetchData').mockImplementation(() => {})
|
||||||
|
|
||||||
|
mockAxios.mockResolvedValue(mockData)
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
await wrapper.vm.submitForm()
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(mockAxios).toHaveBeenCalled()
|
||||||
|
expect(mockAxios).toHaveBeenCalledWith({
|
||||||
|
url: '/',
|
||||||
|
method: 'GET',
|
||||||
|
data: new URLSearchParams(),
|
||||||
|
params: {
|
||||||
|
command: 'migrateVirtualMachine',
|
||||||
|
hostid: 'test-host-id',
|
||||||
|
virtualmachineid: 'test-resource-id',
|
||||||
|
response: 'json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check store dispatch `AddAsyncJob` and $pollJob have successMethod() is called with requiresStorageMotion is true', async (done) => {
|
||||||
|
const mockData = {
|
||||||
|
migratevirtualmachinewithvolumeresponse: {
|
||||||
|
jobid: 'test-job-id-case-1'
|
||||||
|
},
|
||||||
|
queryasyncjobresultresponse: {
|
||||||
|
jobstatus: 1,
|
||||||
|
jobresult: {
|
||||||
|
name: 'test-name-value'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: {
|
||||||
|
id: 'test-resource-id',
|
||||||
|
name: 'test-resource-name'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
selectedHost: {
|
||||||
|
requiresStorageMotion: true,
|
||||||
|
id: 'test-host-id',
|
||||||
|
name: 'test-host-name'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
jest.spyOn(wrapper.vm, 'fetchData').mockImplementation(() => {})
|
||||||
|
|
||||||
|
mockAxios.mockResolvedValue(mockData)
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
await wrapper.vm.submitForm()
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(actions.AddAsyncJob).toHaveBeenCalled()
|
||||||
|
expect(mocks.$pollJob).toHaveBeenCalled()
|
||||||
|
expect(wrapper.emitted()['close-action'][0]).toEqual([])
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check store dispatch `AddAsyncJob` and $pollJob have successMethod() is called with requiresStorageMotion is false', async (done) => {
|
||||||
|
const mockData = {
|
||||||
|
migratevirtualmachineresponse: {
|
||||||
|
jobid: 'test-job-id-case-2'
|
||||||
|
},
|
||||||
|
queryasyncjobresultresponse: {
|
||||||
|
jobstatus: 1,
|
||||||
|
jobresult: {
|
||||||
|
name: 'test-name-value'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: {
|
||||||
|
id: 'test-resource-id',
|
||||||
|
name: 'test-resource-name'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
selectedHost: {
|
||||||
|
requiresStorageMotion: false,
|
||||||
|
id: 'test-host-id',
|
||||||
|
name: 'test-host-name'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
jest.spyOn(wrapper.vm, 'fetchData').mockImplementation(() => {})
|
||||||
|
|
||||||
|
mockAxios.mockResolvedValue(mockData)
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
await wrapper.vm.submitForm()
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(actions.AddAsyncJob).toHaveBeenCalled()
|
||||||
|
expect(mocks.$pollJob).toHaveBeenCalled()
|
||||||
|
expect(wrapper.emitted()['close-action'][0]).toEqual([])
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check store dispatch `AddAsyncJob` and $pollJob have errorMethod() is called', async (done) => {
|
||||||
|
const mockData = {
|
||||||
|
migratevirtualmachinewithvolumeresponse: {
|
||||||
|
jobid: 'test-job-id-case-3'
|
||||||
|
},
|
||||||
|
queryasyncjobresultresponse: {
|
||||||
|
jobstatus: 2,
|
||||||
|
jobresult: {
|
||||||
|
errortext: 'test-error-message'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: {
|
||||||
|
id: 'test-resource-id',
|
||||||
|
name: 'test-resource-name'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
selectedHost: {
|
||||||
|
requiresStorageMotion: true,
|
||||||
|
id: 'test-host-id',
|
||||||
|
name: 'test-host-name'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
jest.spyOn(wrapper.vm, 'fetchData').mockImplementation(() => {})
|
||||||
|
|
||||||
|
mockAxios.mockResolvedValue(mockData)
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
await wrapper.vm.submitForm()
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(actions.AddAsyncJob).toHaveBeenCalled()
|
||||||
|
expect(mocks.$pollJob).toHaveBeenCalled()
|
||||||
|
expect(wrapper.emitted()['close-action'][0]).toEqual([])
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check store dispatch `AddAsyncJob` and $pollJob have catchMethod() is called', async (done) => {
|
||||||
|
const mockData = {
|
||||||
|
migratevirtualmachinewithvolumeresponse: {
|
||||||
|
jobid: 'test-job-id-case-4'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: {
|
||||||
|
id: 'test-resource-id',
|
||||||
|
name: 'test-resource-name'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
selectedHost: {
|
||||||
|
requiresStorageMotion: true,
|
||||||
|
id: 'test-host-id',
|
||||||
|
name: 'test-host-name'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
jest.spyOn(wrapper.vm, 'fetchData').mockImplementation(() => {})
|
||||||
|
|
||||||
|
mockAxios.mockResolvedValue(mockData)
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
await wrapper.vm.submitForm()
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(actions.AddAsyncJob).toHaveBeenCalled()
|
||||||
|
expect(mocks.$pollJob).toHaveBeenCalled()
|
||||||
|
expect(wrapper.emitted()['close-action'][0]).toEqual([])
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check $message.error is called when api is called with throw error', async (done) => {
|
||||||
|
const mockError = {
|
||||||
|
message: 'Error: throw error message'
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: {}
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
selectedHost: {
|
||||||
|
requiresStorageMotion: true,
|
||||||
|
id: 'test-host-id',
|
||||||
|
name: 'test-host-name'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
jest.spyOn(wrapper.vm, 'fetchData').mockImplementation(() => {})
|
||||||
|
|
||||||
|
mockAxios.mockRejectedValue(mockError)
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
await wrapper.vm.submitForm()
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(mocks.$notification.error).toHaveBeenCalled()
|
||||||
|
expect(mocks.$notification.error).toHaveBeenCalledWith({
|
||||||
|
message: i18n.t('message.request.failed'),
|
||||||
|
description: 'Error: throw error message',
|
||||||
|
duration: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('handleChangePage()', () => {
|
||||||
|
it('check page, pageSize and fetchData() when handleChangePage() is called', () => {
|
||||||
|
wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: {}
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const spyFetchData = jest.spyOn(wrapper.vm, 'fetchData').mockImplementation(() => {})
|
||||||
|
|
||||||
|
wrapper.vm.$nextTick(() => {
|
||||||
|
wrapper.vm.handleChangePage(2, 20)
|
||||||
|
|
||||||
|
expect(wrapper.vm.page).toEqual(2)
|
||||||
|
expect(wrapper.vm.pageSize).toEqual(20)
|
||||||
|
expect(spyFetchData).toBeCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('handleChangePageSize()', () => {
|
||||||
|
it('check page, pageSize and fetchData() when handleChangePageSize() is called', () => {
|
||||||
|
wrapper = factory({
|
||||||
|
props: {
|
||||||
|
resource: {}
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const spyFetchData = jest.spyOn(wrapper.vm, 'fetchData').mockImplementation(() => {})
|
||||||
|
|
||||||
|
wrapper.vm.$nextTick(() => {
|
||||||
|
wrapper.vm.handleChangePageSize(2, 20)
|
||||||
|
|
||||||
|
expect(wrapper.vm.page).toEqual(2)
|
||||||
|
expect(wrapper.vm.pageSize).toEqual(20)
|
||||||
|
expect(spyFetchData).toBeCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
Loading…
x
Reference in New Issue
Block a user