JavaScript自動(dòng)化測(cè)試添加頁(yè)面DOM元素唯一ID方案示例
需求
測(cè)試編寫(xiě)測(cè)試自動(dòng)化腳本,需要定位到頁(yè)面元素。需要每個(gè)操作元素添加唯一標(biāo)識(shí)ID,并且每次前端構(gòu)建不能導(dǎo)致相同頁(yè)面相同元素的ID變化。方便測(cè)試快速寫(xiě)自動(dòng)化測(cè)試腳本。
解決方案1:處理渲染前的HTML根據(jù)正則去匹配操作元素,添加唯一id
webpack-loader打包的時(shí)候處理渲染前的HTML根據(jù)正則去匹配操作元素,添加唯一id。最后渲染出來(lái)的頁(yè)面操作元素有唯一id。
webpack-loader chainWebpack代碼:
chainWebpack: (config) => {
config.resolveLoader.alias.set('my-loader', path.resolve(__dirname, 'build/preLoader-makeId.js'))
config.module
.rule('vue').test(/\.vue$/)
.use('my-loader')
.loader('my-loader').end()
;
},preLoader-makeId.js文件:
module.exports = function (contentStr, val) {
var first = contentStr.indexOf('<template>')
var end = contentStr.indexOf('<script>')
content = contentStr.slice(first, end)
let returnContent = content.replace(/\r\n/g, ' ')
returnContent = returnContent.replace(/\r/g, ' ')
returnContent = returnContent.replace(/\n/g, ' ')
returnContent = returnContent.replace(/<\/el-/g, '\n</el-')
returnContent = returnContent.replace(/<el-/g, '\n<el-')
var regModule = /(model=\")([^\"]*)\"/g
var regId = /(id=\")([^\"]*)\"/g
var regBtn = /<(el-button)([^<>]*)>/g
var regInput = /<(el-input)([^<>]*)>/g
var regSele = /<(el-select)([^<>]*)>/g
var regDate = /<(el-date-picker)([^<>]*)>/g
var regInputNumber = /<(el-input-number)([^<>]*)>/g
function makeId_input(index, item) {
let id
let res = regModule.exec(item)
if (res && res.length > 0) {
id = res[0]
.replace('model="', '')
.replace(/\"/g, '')
.replace(/\./g, '_')
}
if (id) {
return id
} else {
return index
}
// return id || index
}
function makeId_btn(index, item) {
let id
let clickAllArr = item.split(/click=/g)
let subClick = ''
let subClickArr = []
if (clickAllArr.length > 1) {
subClick = clickAllArr[1].substring(1, clickAllArr[1].length)
subClickArr = subClick.split(/"/g)
if (subClickArr.length > 1) {
id = subClickArr[0]
.split(/\=/g)[0]
.split(/\(\"/g)[0]
.split(/\(\'/g)[0]
.split(/\(/g)[0]
} else {
id = index
}
} else {
id = index
}
if (id) {
return id
} else {
return index
}
}
let contentArr = returnContent.split('\n')
let resultArr = contentArr.map((item, index) => {
let id
if (!regId.test(item)) {
// 輸入框 - 數(shù)字
if (regInputNumber.test(item)) {
item =
'<el-input-number' +
' id="zgwww-input_number_' +
makeId_input(index, item) +
'"' +
item.substring('<el-input-number'.length, item.length) +
' '
} else if (regInput.test(item)) {
// 輸入框
item =
'<el-input' +
' id="zgwww-input_' +
makeId_input(index, item) +
'"' +
item.substring('<el-input'.length, item.length) +
' '
}
if (regSele.test(item)) {
// 選擇框
item =
'<el-select' +
' id="zgwww-select_' +
makeId_input(index, item) +
'"' +
item.substring('<el-select'.length, item.length) +
' '
}
if (regDate.test(item)) {
// 日期選擇
item =
'<el-date-picker' +
' id="zgwww-date_' +
makeId_input(index, item) +
'"' +
item.substring('<el-date-picker'.length, item.length) +
' '
}
if (regBtn.test(item)) {
// 按鈕
item =
'<el-button' +
' id="zgwww-btn_' +
makeId_btn(index, item) +
'"' +
item.substring('<el-button'.length, item.length) +
' '
}
}
// alert(1)
return item
})
return resultArr.join('\n') + '\n' + contentStr.slice(end)
// return contentStr
}結(jié)果:但是如果使用webpack-loader去處理vue文件里面的html-template。
會(huì)導(dǎo)致同一個(gè)頁(yè)面使用多個(gè)相同的前端組件-同一個(gè)vue文件。生成出來(lái)的ID一樣。
不符合測(cè)試要求的一個(gè)頁(yè)面每個(gè)操作DOM元素生成不同的ID。
解決方案2:監(jiān)聽(tīng)window瀏覽器地址欄事件
包括window.history.pushState,window.history.replaceState,window.onpopstate這三個(gè)window事件。
給頁(yè)面框架最外層盒子添加id-appmain,這里要用setTimeout宏任務(wù)進(jìn)行遞歸childNodes。因?yàn)閐ocument.getElementById('appmain')取得到的html-object對(duì)象是個(gè)異步的對(duì)象。
window.history.pushState = patchRouter(
window.history.pushState,
'micro_push'
);window.addEventListener('micro_push', turnApp);function turnApp() {
var that = this;
setTimeout(function () {
var appMain = document.getElementById('appmain');
var a = 0;
function forDom(root1) {
if (root1) {
if (root1.setAttribute) {
if (root1.id != 'appmain' && !root1.id) {
if (root1._prevClass) {
root1.setAttribute('id', root1._prevClass + a);
} else if (root1.nodeName) {
root1.setAttribute('id', root1.nodeName + a);
} else if (root1.localName) {
root1.setAttribute('id', root1.localName + a);
} else {
root1.setAttribute('id', 'Id' + a);
}
}
// console.log('root1', root1);
}
}
a = a + 1;
if (root1) {
if (root1.childNodes) {
if (root1.childNodes.length != 0) {
for (var i = 0; i < root1.childNodes.length; i++) {
forDom(root1.childNodes[i]);
}
}
}
}
}
forDom(appMain);
}, 3000);
}
對(duì)于一些點(diǎn)擊操作使用v-if重新改變頁(yè)面dom結(jié)構(gòu)的。
我們監(jiān)聽(tīng)window的click事件去重新觸發(fā)turnApp重新給頁(yè)面dom結(jié)構(gòu)添加id,對(duì)于一些頁(yè)面加載的時(shí)候已經(jīng)加載過(guò)id的,我們做判斷不重新賦值id。
window.addEventListener('click', turnApp);if (root1.id != 'appmain' && !root1.id) {
}總結(jié)
本文對(duì)測(cè)試自動(dòng)化測(cè)試-添加前端頁(yè)面DOM元素唯一ID進(jìn)行了解決方案與代碼實(shí)現(xiàn)。也對(duì)里面代碼實(shí)現(xiàn)的細(xì)節(jié)點(diǎn)進(jìn)行了詳細(xì)說(shuō)明。講解部分到此結(jié)束,謝謝閱讀!
更多關(guān)于JavaScript添加頁(yè)面DOM ID的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
ant-design的upload組件中實(shí)現(xiàn)粘貼上傳實(shí)例詳解
這篇文章主要為大家介紹了ant-design的upload組件中實(shí)現(xiàn)粘貼上傳實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
微信小程序(應(yīng)用號(hào))開(kāi)發(fā)新聞客戶(hù)端實(shí)例
這篇文章主要介紹了微信小程序(應(yīng)用號(hào))開(kāi)發(fā)新聞客戶(hù)端實(shí)例的相關(guān)資料,需要的朋友可以參考下2016-10-10
JavaScript設(shè)計(jì)模式之單例模式應(yīng)用場(chǎng)景案例詳解
這篇文章主要為大家介紹了JavaScript中單例模式的應(yīng)用場(chǎng)景案例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
TypeScript新語(yǔ)法之infer?extends示例詳解
這篇文章主要為大家介紹了TypeScript新語(yǔ)法之infer?extends示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08

