Chai expect() 在第二个对象的 forEach() 中失败

Chai expect() fails in forEach() on 2nd object

我正在 cypress 中实现一个测试用例,我想在其中将 dateTime 值列表与 RegEx 模式相匹配。 所有这些都在 forEach 循环中完成。它适用于第一个项目并在第二个项目上失败,即使它们是相同的。

复制代码如下:

const array = [
    "2022-05-23 14:39:43.145",
    "2022-05-23 14:39:43.145",
    "2022-05-23 14:39:43.120",
    "2022-05-23 14:39:43.120",
    "2022-05-23 14:39:43.096",
    "2022-05-23 14:39:43.096",
    "2022-05-23 14:39:43.074",
    "2022-05-23 14:39:43.074",
];
const dateTime = new RegExp(/\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d\.\d\d\d/gm);

describe('tesst',() => {
    it('should work', function() {
        array.forEach((object) => {
            expect(object).to.match(dateTime);
        })
    });
})

编辑 看起来这个错误是 RegEx 模式的全局标志 (/g)。但是我不明白为什么这是一个问题。非常感谢您的解释:)

您可以简化示例以帮助消除因素,

it('tests with regex', function() {
  expect("2022-05-23 14:39:43.145").to.match(dateTime)  // passes
  expect("2022-05-23 14:39:43.120").to.match(dateTime)  // fails
})

如果您查看 chaijs 库,这就是 to.match() 的实现方式

function assertMatch(re, msg) {
  if (msg) flag(this, 'message', msg);
  var obj = flag(this, 'object');
  this.assert(
      re.exec(obj)
    , 'expected #{this} to match ' + re
    , 'expected #{this} not to match ' + re
  );
}

所以活性成分是 re.exec(obj),等同于 dateTime.exec("2022-05-23 14:39:43.145"),如果你 console.log 那个表达式,第一次调用成功,第二个 returns null - which chai 解释为失败。

it('tests with regex', function() {
  console.log(dateTime.exec("2022-05-23 14:39:43.145"))  // ['2022-05-23 14:39:43.145', index: 0...
  console.log(dateTime.exec("2022-05-23 14:39:43.120"))  // null
})

原因可以参考MDN RegExp.prototype.exec() Finding successive matches

If your regular expression uses the "g" flag, you can use the exec() method multiple times to find successive matches in the same string.

When you do so, the search starts at the substring of str specified by the regular expression's lastIndex property (test() will also advance the lastIndex property).

Note that the lastIndex property will not be reset when searching a different string, it will start its search at its existing lastIndex .

如果我们在每个步骤后检查 lastIndex 属性 并重复几次,则每 2 个日期都会失败。

但失败后 lastIndex 会重置,下一次测试会成功。

it('tests with regex', function() {
  console.log(dateTime.exec("2022-05-23 14:39:43.145"))  // ['2022-05-23 14:39:43.145', index: 0...
  console.log(dateTime.lastIndex)                        // 23
  console.log(dateTime.exec("2022-05-23 14:39:43.120"))  // null
  console.log(dateTime.lastIndex)                        // 0
  console.log(dateTime.exec("2022-05-23 14:39:43.096"))  // ['2022-05-23 14:39:43.096', index: 0...
  console.log(dateTime.lastIndex)                        // 23
  console.log(dateTime.exec("2022-05-23 14:39:43.074"))  // null
  console.log(dateTime.lastIndex)                        // 0
})

因此您可以通过手动重置 lastIndex

让您的循环工作
it('should work', function() {
  array.forEach(object => {
    expect(object).to.match(dateTime);  // passes every date
    dateTime.lastIndex = 0;
  })
})

(或删除 /g 标志)