You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用ESLint的no-restricted-syntax禁止在it/test外使用screen?

ESLint no-restricted-syntax规则配置问题:禁止it()/test()块外使用screen

问题描述

我正尝试配置ESLint的no-restricted-syntax规则,此前未成功实现禁止screen.findByX不配合await使用的需求,现在有另一个场景:需要禁止在it()/test()块外使用screen——因为JSDOM环境是全局共享的,在外部渲染会导致DOM清理问题。

示例代码(希望其中的screen调用触发ESLint报错):

beforeEach(async() => {
  render(<MyLovelyComponent />);
  await waitForElementToBeRemoved(() => screen.getAllByText('dddd'));
});

我编写的规则配置如下,但并未生效:

'no-restricted-syntax':[
  'error',
  {
    message: 'No screen outside of it',
    selector: `FunctionCall[name!="it"] MemberExpression[object.name="screen"]`
  },
],

问题原因与解决方案

原配置的问题

原选择器FunctionCall[name!="it"] MemberExpression[object.name="screen"]存在两个核心缺陷:

  1. 匹配范围过窄:仅能匹配直接作为非it函数调用的直接子节点的screen调用,无法处理多层嵌套的情况(比如示例中screen嵌套在waitForElementToBeRemoved的回调函数里)。
  2. 覆盖场景不全:未考虑test函数(多数测试框架中test与it等价),也未处理箭头函数、普通函数作为it/test回调的嵌套结构。

正确的规则配置

可以通过AST选择器的否定逻辑,匹配所有screen的成员表达式调用,同时排除位于it()/test()回调内部的情况:

写法一(紧凑版)

'no-restricted-syntax': [
  'error',
  {
    message: '禁止在it()/test()块外使用screen',
    selector: 'MemberExpression[object.name="screen"]:not(:matches(FunctionExpression[parent.type="CallExpression"][parent.callee.name=/^(it|test)$/]), ArrowFunctionExpression[parent.type="CallExpression"][parent.callee.name=/^(it|test)$/])'
  }
]

写法二(易读版)

'no-restricted-syntax': [
  'error',
  {
    message: '禁止在it()/test()块外使用screen',
    selector: `
      MemberExpression[object.name="screen"]
      :not(
        :has(
          ancestor CallExpression[callee.name=/^(it|test)$/]
        )
      )
    `
  }
]

配置说明

  • 选择器MemberExpression[object.name="screen"]匹配所有screen.xxx()形式的调用。
  • :not(:has(ancestor CallExpression[callee.name=/^(it|test)$/]))用于排除那些上层作用域属于it()或test()函数回调的调用,无论嵌套多少层函数,只要归属于it/test的作用域,就不会触发报错。

内容的提问来源于stack exchange,提问作者AncientSwordRage

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 05:03:36