better-scroll 在 UI 自动化测试中的问题

349 阅读5分钟

在移动端开发中,BetterScroll 是一个非常流行的滚动插件,它提供了流畅的滚动体验和丰富的交互功能。然而,在某些情况下,这些配置可能会导致点击事件不生效的问题。本文将详细介绍 BetterScroll 的配置优化方法,以及如何解决点击事件不生效的问题。

提高页面流畅度的配置项

在使用 BetterScroll 时,可以通过以下配置项来优化页面的流畅度:

1. probeType

probeType 用于控制 BetterScroll 对滚动事件的探测频率。较高的值意味着更频繁的事件触发,适用于需要实时反馈的场景。

const scroll = new BScroll('.wrapper', {
  probeType: 3,
});

2. click

启用 click 选项可以让 BetterScroll 支持点击事件。默认情况下,BetterScroll 会阻止点击事件以防止误触。

const scroll = new BScroll('.wrapper', {
  click: true,
});

3. preventDefault

preventDefault 默认为 true,用于防止滑动过程中的默认行为。在某些情况下,可以将其设置为 false 来允许默认行为。

const scroll = new BScroll('.wrapper', {
  preventDefault: false,
});

4. wheel

wheel 插件用于处理鼠标滚轮事件,使 BetterScroll 在桌面端也能提供平滑的滚动效果。

import Slide from '@better-scroll/slide';
import Wheel from '@better-scroll/wheel';

const scroll = new BScroll('.wrapper', {
  wheel: true,
  plugins: [Slide(), Wheel()],
});

可能存在的问题及对应场景

尽管上述配置可以提高页面的流畅度,但在某些情况下,它们可能会导致点击事件不生效的问题。特别是在 UI 自动化测试中,这些问题尤为突出。

1. 自动化测试中的点击不生效

在自动化测试中,由于 BetterScroll 的默认行为是阻止点击事件,这可能导致自动化脚本无法正常执行点击操作。

场景示例

假设你在编写自动化测试脚本时,需要点击某个元素来验证功能。由于 BetterScroll 阻止了点击事件,脚本可能无法触发预期的点击操作。

2. 滚动插件导致的点击不生效

当 BetterScroll 配置了 wheel 插件或其他滚动插件时,可能会进一步阻止点击事件的触发。

场景示例

在使用日期选择器等组件时,由于 BetterScroll 阻止了点击事件,用户可能无法通过点击来选择日期。

解决方案

针对上述问题,可以采用以下几种解决方案:

1. 坐标点击

在自动化测试中,可以使用坐标点击来模拟用户的点击操作。这种方法通过模拟原生的 tap 或 touch 事件来触发点击。

await driver.touchAction({
  action: 'tap',
  x: 100, // 目标元素的 x 坐标
  y: 200, // 目标元素的 y 坐标
});

2. 模拟滚动

通过模拟实际的滑动动作,可以绕过 BetterScroll 对点击事件的拦截。可以使用 Puppeteer 结合 Chrome DevTools Protocol(CDP)来实现模拟滑动。

await page.evaluate(() => {
  const element = document.querySelector('.scrollable-element');
  element.dispatchEvent(new Event('touchstart'));
  element.dispatchEvent(new Event('touchmove', { clientX: 100, clientY: 200 }));
  element.dispatchEvent(new Event('touchend'));
});

3. 手动派发 Touch 事件

在某些情况下,可以通过手动派发 touchstart 和 touchend 事件来模拟点击操作。

async function setDate() {
  let dateEl = document.querySelector('#date-element');
  dateEl.dispatchEvent(new TouchEvent('touchstart', { bubbles: true }));
  await sleep(1000);
  dateEl.dispatchEvent(new TouchEvent('touchend', { bubbles: true }));
}

function sleep(delay = 300) {
  return new Promise(resolve => setTimeout(resolve, delay));
}

4. 自定义事件处理逻辑,以确保在滑动结束后允许点击事件触发

  • 滚动结束后立即需要点击的场景

在一些应用中,用户可能在滚动结束后立即需要进行点击操作。例如,在滚动查看商品列表后,用户可能需要点击某个商品进行购买。

处理方法

可以通过监听 BetterScroll 的 scrollEnd 事件来判断滑动是否结束,并在滑动结束后重新启用点击事件。

示例代码

import BScroll from '@better-scroll/core';
import Slide from '@better-scroll/slide';

const scroll = new BScroll('.wrapper', {
  scrollX: false,
  scrollY: true,
  slide: {
    loop: true,
    threshold: 100,
  },
  momentum: false,
  bounce: false,
  probeType: 3,
});

// 监听滑动结束事件
scroll.on('scrollEnd', () => {
  // 恢复点击事件
  document.querySelector('.clickable-element').addEventListener('click', handleClick);
});

// 滚动开始时移除点击事件
scroll.on('beforeScrollStart', () => {
  document.querySelector('.clickable-element').removeEventListener('click', handleClick);
});

function handleClick(event) {
  console.log('Clicked:', event.target);
  // 处理点击逻辑
}
  • 滚动结束后需要延迟触发点击的场景

在某些情况下,为了防止滑动过程中的误触,可以在滑动结束后延迟一段时间再允许点击事件触发。

处理方法

可以在 scrollEnd 事件中使用 setTimeout 来延迟添加点击事件监听器。

示例代码

import BScroll from '@better-scroll/core';
import Slide from '@better-scroll/slide';

const scroll = new BScroll('.wrapper', {
  scrollX: false,
  scrollY: true,
  slide: {
    loop: true,
    threshold: 100,
  },
  momentum: false,
  bounce: false,
  probeType: 3,
});

let clickableElement = document.querySelector('.clickable-element');
let isScrolling = false;

// 滚动开始时标记为正在滑动
scroll.on('beforeScrollStart', () => {
  isScrolling = true;
  clickableElement.removeEventListener('click', handleClick);
});

// 滚动结束时延迟恢复点击事件
scroll.on('scrollEnd', () => {
  isScrolling = false;
  setTimeout(() => {
    if (!isScrolling) {
      clickableElement.addEventListener('click', handleClick);
    }
  }, 300); // 延迟时间可以根据需求调整
});

function handleClick(event) {
  console.log('Clicked:', event.target);
  // 处理点击逻辑
}
  • 滚动结束后需要特定条件才允许点击的场景

在某些复杂的应用中,可能需要在滑动结束后满足特定条件才允许点击事件触发。例如,只有在用户选择了某个选项后才允许点击。

处理方法

可以在 scrollEnd 事件中添加条件判断,只有满足条件时才恢复点击事件。

示例代码

import BScroll from '@better-scroll/core';
import Slide from '@better-scroll/slide';

const scroll = new BScroll('.wrapper', {
  scrollX: false,
  scrollY: true,
  slide: {
    loop: true,
    threshold: 100,
  },
  momentum: false,
  bounce: false,
  probeType: 3,
});

let clickableElement = document.querySelector('.clickable-element');
let selectionMade = false;

// 滚动开始时移除点击事件
scroll.on('beforeScrollStart', () => {
  clickableElement.removeEventListener('click', handleClick);
});

// 滚动结束时根据条件恢复点击事件
scroll.on('scrollEnd', () => {
  if (selectionMade) {
    clickableElement.addEventListener('click', handleClick);
  }
});

function handleSelection() {
  selectionMade = true;
  // 其他处理逻辑
}

function handleClick(event) {
  console.log('Clicked:', event.target);
  // 处理点击逻辑
}

通过这些自定义事件处理逻辑,可以在滑动结束后灵活地控制点击事件的触发,从而提升用户体验。

总结

通过上述解决方案,可以在保持 BetterScroll 的流畅性的同时,确保点击事件能够正常触发,从而提升用户体验和自动化测试的可靠性。