sinonjs - 将时钟提前59分钟,实际等待1分钟

时间:2018-06-01 15:38:32

标签: javascript sinon

我有一个用于自动注销功能的Web组件,它在第59分钟显示带有消息的模态窗口,并在没有活动的情况下再保持一分钟。如果用户没有单击窗口上的任何位置,则注销用户。因此,一小时没有活动会自动注销用户。这很好。

现在,为了测试此功能,我尝试使用sinonjs。我使用FakeTimers但无法达到结果。我试图测试该模态窗口,并显示消息。

以下是代码:

const { When } = require('cucumber'); // eslint-disable-line import/no-extraneous-dependencies
const fs = require('fs');
const path = require('path');

let clock;    

async function setupSinon() {
  const sinonPath = require.resolve('sinon');

  const content = await new Promise((resolve, reject) => {
    fs.readFile(
      path.join(sinonPath, '../../pkg/sinon.js'),
      'utf-8',
      async (error, cont) => {
        if (error) return reject(error);
        resolve(cont);
      },
    );
  });
  // creating <script> element for sinonjs to execute on the page
  await browser.execute((content) => {
    const script = document.createElement('script');
    script.type = 'text/javascript';
    script.text = content;
    document.head.appendChild(script);
  }, content);
}

async function iWaitForNMinutes() {
  await setupSinon();
  await browser.execute(() => {
    before(() => {
      clock = sinon.useFakeTimers();
    });
    clock = sinon.useFakeTimers({
      now: Date.now(),
      shouldAdvanceTime: true,
      toFake: ['setTimeout'],
    });

    clock.tick('59:00'); // advancing the clock to 59 minutes so that auto-logout modal window popup, but this doesn't work

    after(() => {
      clock.restore();
    });

    setTimeout(() => {}, 60000);

  });
} 

When(/^I wait for minutes$/, iWaitForNMinutes);

module.exports = {      
  iWaitForNMinutes,
};

sinon 5.0.10

如何使用sinonjs FakeTimer将时间提前n分钟,然后实际等待n分钟?

2 个答案:

答案 0 :(得分:1)

Sinon的假定时器非常容易使用,是我最喜欢的sinon功能。

用法就是这样

在您的代码中

// in your code
eatCake() {
  setTimeout(function() {
    // eat cake after 10s
  }, 10000); // 10000 === 10s
}

在你的考试中

clock = sinon.useFakeTimers();
clock.tick(9000);
// check if cake is eaten - answer will be false
clock.tick(1000); // 9000 + 1000 === 10s
// check if cake is eaten - answer will be true

因此,sinon基本上快速转发(以编程方式)定时器,因此我们的测试可以在不实际等待时间的情况下检查所需的结果,因为所有测试框架通常都有2秒的等待超时,之后测试用例将失败。

在你的情况下,等待59分钟,你可以写

clock.tick(1000 * 60 * 59); // 59 minutes

// check if the modal has opened up

clock.tick(1000 * 60 * 1); // 1 minute

// check if the user is logged out

并且不要忘记在结束时恢复时钟,因为你已经完成了。

clock.restore();

答案 1 :(得分:0)

您的一般问题可能出在您的函数(await)之前的browser.execute中:

  • 之前提前时钟是没有意义的(关于内部诸如setTimeOut之类的东西)...因为尚未设置任何内部计时功能。
  • 在{em>之后提前时钟await <function>是没有意义的,因为实际上await将等待...

解决方案是与您的(async)函数一起使用await,但是将其像其他任何返回承诺的函数(实际上是任何异步函数)一样对待。

it('some test', async () => {

    await new Promise((resolve, reject) => {

        // normally used with await
        functionToBeTested(...some params).then(
            (value) => {
                log('now it happend')
                resolve()
            },
            (reason) => {
                reject(reason)
            }
        )

        // by not using await (despite deleteAction being an sync function)
        // but rather just chaining a then, this clock.tick gets run while
        // deleteAction is "running" resp. waiting for some timeout:
        clock.tick(1000)
    })

    ... some more asserts on the result...
    (we can be rest-assured the command under test is completed here)
})