js实现按键精灵——尝试前端实现自动化测试(一)下

简介: js实现按键精灵——尝试前端实现自动化测试(一)下

页面滚动(场景比较复杂)

代码


dom:


<div class="scroll-container">
    <div class="scroll-content">
        <div class="scroll-inner">
            内部滚动测试
        </div>
    </div>
</div>


css:


body {
    height: 1800px;
}
.scroll-container {
    max-height: 500px;
    background: pink;
    overflow: auto;
}
.scroll-content {
    height: 800px;
}
.scroll-inner {
    width: 300px;
    height: 300px;
    background-color: purple;
}


js:


let mouseX = 0;
let mouseY = 0;
let scrollStartEl = null; //用于记录滚动的起始元素,为了保证重现操作时为元素设置scrollTop时不出现偏差
let scrollRecordList = [];
let scrollElementSet = new Set();
// 通用节流方法
const throttle = function (cb, delay = 100) {
    let timer = null;
    return (ev) => {
        if (timer) {
            clearTimeout(timer)
        }
        timer = setTimeout(() => {
            cb && cb(ev);
        }, delay)
    };
}
// 绑定滚动事件
setScrollWatcher = function (ev) {
    mouseX = ev && ev.clientX || mouseX;
    mouseY = ev && ev.clientY || mouseY;
    scrollStartEl = document.elementFromPoint(mouseX, mouseY);
    let el = scrollStartEl;
    while (el) {
        if (scrollElementSet.has(el)) {
            el = null;
        } else {
            el.onscroll = throttle(recordScrollInfo);
            scrollElementSet.add(el);
            el = el.parentNode;
        }
    }
};
// 记录滚动信息
recordScrollInfo = function (ev) {
    let el = scrollStartEl;
    // 单纯的滚动也可能引起鼠标对应的dom的变化,滚动结束也需要setScrollWatcher
    setScrollWatcher();
    let scrollRecordInfo = {
        mouseX: mouseX,
        mouseY: mouseY,
        scrollTopList: []
    }
    while (el) {
        scrollRecordInfo.scrollTopList.push(el.scrollTop);
        el = el.parentNode;
    }
    scrollRecordList.push(scrollRecordInfo);
    console.log(scrollRecordList)
}
// 绑定鼠标移动事件
document.onmousemove = throttle(setScrollWatcher);


讲解


这里大家请跟着我的思路一步一步来:


  1. 首先我给document绑定了鼠标移动事件,并且为其设置了节流


// 绑定鼠标移动事件
document.onmousemove = throttle(setScrollWatcher);


我现在得到了鼠标最后停止的位置,我的思路是,如果现在用户开始滚动鼠标滚轮,那么页面可能发生的滚动可能就出现在,鼠标悬停位置对应的元素及其所有祖先元素上!


  1. 正如前面的介绍,我现在要做的就是给鼠标悬停位置对应的元素及其所有祖先元素绑定滚动事件,即setScrollWatcher方法所做的事情。


let mouseX = 0;
let mouseY = 0;
let scrollStartEl = null; //用于记录滚动的起始元素,为了保证重现操作时为元素设置scrollTop时不出现偏差
let scrollElementSet = new Set();
// 绑定滚动事件
setScrollWatcher = function (ev) {
    mouseX = ev && ev.clientX || mouseX;
    mouseY = ev && ev.clientY || mouseY;
    scrollStartEl = document.elementFromPoint(mouseX, mouseY);
    let el = scrollStartEl;
    while (el) {
        if (scrollElementSet.has(el)) {
            el = null;
        } else {
            el.onscroll = throttle(recordScrollInfo);
            scrollElementSet.add(el);
            el = el.parentNode;
        }
    }
};


大家看的应该也不是很费劲,首先鼠标停下来了,我就记录一下现在鼠标所在的元素存在scrollStartEl中,之后为它以及他的所有祖先元素设置滚动事件(当然滚动事件也做了节流处理~)。

优化:其中为了防止重复绑定滚动事件,也做了一定的优化,引入了一个scrollElementSet,如果set中存在这个元素,那么直接结束循环。(tip:因为一个元素只会有一个直接父元素


  1. 下一步就显而易见了,就是要在滚动事件结束之后对其进行记录~


recordScrollInfo = function (ev) {
    let el = scrollStartEl;
    // 单纯的滚动也可能引起鼠标对应的dom的变化,滚动结束也需要setScrollWatcher
    setScrollWatcher();
    let scrollRecordInfo = {
        mouseX: mouseX,
        mouseY: mouseY,
        scrollTopList: []
    }
    while (el) {
        scrollRecordInfo.scrollTopList.push(el.scrollTop);
        el = el.parentNode;
    }
    scrollRecordList.push(scrollRecordInfo);
    console.log(scrollRecordList)
}


我只需要记录滚动开始鼠标所在元素scrollStartEl及其所有祖先元素的scrollTop就可以了,之后在复线操作的过程中,根据记录的mouseXmouseY找到滚动开始元素,并为其以及其所有祖先元素设置scrollTop即可~

注意

  1. 单纯的滚动也可能引起鼠标对应的dom的变化,滚动结束也需要setScrollWatcher
  2. 因为滚动结束后鼠标位置对应的元素可能会变,所以确实需要在滚动前记录滚动开始元素,防止复现操作时出现元素层级不一致问题。


我感觉这个滚动的记录还是有点骚的,哈哈哈,我就是这么臭不要脸,哈哈哈~


完整代码【方便查看】


完整的测试代码在此,如果上github不方便,可以直接复制粘贴试一下~


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style type="text/css">
        body {
            height: 1800px;
        }
        .scroll-container {
            max-height: 500px;
            background: pink;
            overflow: auto;
        }
        .scroll-content {
            height: 800px;
        }
        .scroll-inner {
            width: 300px;
            height: 300px;
            background-color: purple;
        }
        .btn {
            margin-top: 1000px;
        }
    </style>
</head>
<body>
    <!-用于测试多种类型的点击事件可否派发-->
    <label><input name="Fruit" type="radio" value="" class="aaa" />苹果 </label>
    <label><input name="Fruit" type="radio" value="" class="bbb" />桃子 </label>
    <label><input name="Fruit" type="radio" value="" />香蕉 </label>
    <label><input name="Fruit" type="radio" value="" />梨 </label>
    <label><input name="Fruit" type="radio" value="" />其它 </label>
    <!-用于测试keydown事件-->
    <input class ="inputTest" />
    <button class="btn">
        nihao
    </button>
    <div class="scroll-container">
        <div class="scroll-content">
            <div class="scroll-inner">
                内部滚动测试
            </div>
        </div>
    </div>
    <script>
        /*
        * 第一步:完成点击事件,滚动事件,键盘输入事件的记录和重现。
        * TODO:待办:拖拽事件?
        */
        const clickEvent = new MouseEvent('click');
        const focusEvent = new FocusEvent('focus',{
            view: window
        });
        // 通用节流方法
        const throttle = function (cb, delay = 100) {
            let timer = null;
            return (ev) => {
                if (timer) {
                    clearTimeout(timer)
                }
                timer = setTimeout(() => {
                    cb && cb(ev);
                }, delay)
            };
        }
        //TODO: 所有点击事件,滚动事件,键盘输入事件都需要记录时间点,相对最开始时间偏移,以正确重现
        // 测试点击事件
        document.onclick = function (ev) {
            const x = ev.clientX;
            const y = ev.clientY;
            setTimeout(() => {
                document.elementFromPoint(x, y).dispatchEvent(clickEvent);
            }, 2000)
        }
        document.getElementsByClassName('btn')[0].onclick = function () {
            console.log(11, 1)
        }
        // TODO:(待验证)测试重现滚动事件
        let mouseX = 0;
        let mouseY = 0;
        let scrollStartEl = null; //用于记录滚动的起始元素,为了保证重现操作时为元素设置scrollTop时不出现偏差
        let scrollRecordList = [];
        let scrollElementSet = new Set();
        setScrollWatcher = function (ev) {
            mouseX = ev && ev.clientX || mouseX;
            mouseY = ev && ev.clientY || mouseY;
            scrollStartEl = document.elementFromPoint(mouseX, mouseY);
            let el = scrollStartEl;
            while (el) {
                if (scrollElementSet.has(el)) {
                    el = null;
                } else {
                    el.onscroll = throttle(recordScrollInfo);
                    scrollElementSet.add(el);
                    el = el.parentNode;
                }
            }
        };
        recordScrollInfo = function (ev) {
            let el = scrollStartEl;
            // 单纯的滚动也可能引起鼠标对应的dom的变化,滚动结束也需要setScrollWatcher
            setScrollWatcher();
            let scrollRecordInfo = {
                mouseX: mouseX,
                mouseY: mouseY,
                scrollTopList: []
            }
            while (el) {
                scrollRecordInfo.scrollTopList.push(el.scrollTop);
                el = el.parentNode;
            }
            scrollRecordList.push(scrollRecordInfo);
            console.log(scrollRecordList)
        }
        // 绑定鼠标移动事件
        document.onmousemove = throttle(setScrollWatcher);
        // 测试键盘输入事件
        // 做法:假定,持续的键盘输入都是对同一个 input的输入,
        // 那我需要做的就是保存输入顺序,并记录上一刻点击的元素,并改变其value!!判断是不是input(有没有value属性来判断),如果不是用innerHtml/innerText去塞!!!为了支持富文本
        document.onkeydown = function (ev) {
            console.log(ev)
        }
        const keyTestEl = document.getElementsByClassName('inputTest')[0];
        keyTestEl.dispatchEvent(clickEvent)
        console.log(keyTestEl, focusEvent)
        keyTestEl.dispatchEvent(focusEvent)
        // const keyEvent = new KeyboardEvent('keypress',{'key':'a'})
        //keyTestEl.dispatchEvent(keyEvent)
        //keyTestEl.value = '11111'
        // 测试radio的点击事件是否可以派发
        document.getElementsByClassName('bbb')[0].dispatchEvent(clickEvent)
        document.getElementsByClassName('aaa')[0].dispatchEvent(focusEvent)
    </script>
</body>
</html>


结束语


网络异常,图片无法展示
|


眼里要有小星星,生活才能亮晶晶~

感谢大家阅读,都要快乐生活哦~

下一篇文章,故事继续哈

相关文章
|
1月前
|
JavaScript 前端开发 程序员
前端原生Js批量修改页面元素属性的2个方法
原生 Js 的 getElementsByClassName 和 querySelectorAll 都能获取批量的页面元素,但是它们之间有些细微的差别,稍不注意,就很容易弄错!
|
1月前
|
前端开发 JavaScript 测试技术
前端测试技术中,如何提高集成测试的效率?
前端测试技术中,如何提高集成测试的效率?
|
4天前
|
数据采集 人工智能 自然语言处理
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
Midscene.js 是一款基于 AI 技术的 UI 自动化测试框架,通过自然语言交互简化测试流程,支持动作执行、数据查询和页面断言,提供可视化报告,适用于多种应用场景。
69 1
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
|
1月前
|
JavaScript 前端开发 Java
springboot解决js前端跨域问题,javascript跨域问题解决
本文介绍了如何在Spring Boot项目中编写Filter过滤器以处理跨域问题,并通过一个示例展示了使用JavaScript进行跨域请求的方法。首先,在Spring Boot应用中添加一个实现了`Filter`接口的类,设置响应头允许所有来源的跨域请求。接着,通过一个简单的HTML页面和jQuery发送AJAX请求到指定URL,验证跨域请求是否成功。文中还提供了请求成功的响应数据样例及请求效果截图。
springboot解决js前端跨域问题,javascript跨域问题解决
|
28天前
|
前端开发 JavaScript 测试技术
前端自动化测试
前端自动化测试是通过使用工具和脚本自动执行测试用例的过程,旨在提高测试效率、减少人为错误,并确保Web应用的功能在不同环境和设备上的一致性与稳定性。
|
1月前
|
JSON 前端开发 JavaScript
聊聊 Go 语言中的 JSON 序列化与 js 前端交互类型失真问题
在Web开发中,后端与前端的数据交换常使用JSON格式,但JavaScript的数字类型仅能安全处理-2^53到2^53间的整数,超出此范围会导致精度丢失。本文通过Go语言的`encoding/json`包,介绍如何通过将大整数以字符串形式序列化和反序列化,有效解决这一问题,确保前后端数据交换的准确性。
54 4
|
1月前
|
数据采集 存储 监控
实现自动化数据抓取:使用Node.js操控鼠标点击与位置坐标
本文介绍了如何使用Node.js和Puppeteer实现自动化数据抓取,特别是针对新闻网站“澎湃新闻”。通过设置代理IP、User-Agent和Cookie,提高爬虫的效率和隐蔽性,避免被网站封锁。代码示例展示了如何模拟鼠标点击、键盘输入等操作,抓取并整理新闻数据,适用于需要规避IP限制和突破频率限制的场景。
102 10
|
1月前
|
前端开发 JavaScript 测试技术
前端小白逆袭之路:如何快速掌握前端测试技术,确保代码质量无忧!
【10月更文挑战第30天】前端开发技术迭代迅速,新手如何快速掌握前端测试以确保代码质量?本文将介绍前端测试的基础知识,包括单元测试、集成测试和端到端测试,以及常用的测试工具如Jest、Mocha、Cypress等。通过实践和学习,你也能成为前端测试高手。
55 4
|
1月前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
148 1
|
1月前
|
移动开发 前端开发 JavaScript
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
于辰在大学期间带领团队参考网易游戏官网的部分游戏页面,开发了一系列前端实训作品。项目包括首页、2021校园招聘页面和明日之后游戏页面,涉及多种特效实现,如动态图片切换和人物聚合效果。作品源码已上传至CSDN,视频效果可在CSDN预览。
45 0