Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/438.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 我如何等待cookie设置完毕?_Javascript_Cookies_Cucumber_Graphql_Cypress - Fatal编程技术网

Javascript 我如何等待cookie设置完毕?

Javascript 我如何等待cookie设置完毕?,javascript,cookies,cucumber,graphql,cypress,Javascript,Cookies,Cucumber,Graphql,Cypress,我正在为我的应用程序的登录功能编写验收测试。在某个时刻,我想再次检查cookie的过期时间 单击“登录”按钮后,一个graphql查询被发送到我的服务器,服务器用Jwt进行响应。收到jwt后,应用程序将cookie设置为 document.cookie = ... 在Cypress测试中,我通过以下方式检查令牌: Then("sa session s'ouvre pour {SessionDurationType}", expectedDuration => { cy.get('@g

我正在为我的应用程序的登录功能编写验收测试。在某个时刻,我想再次检查cookie的过期时间

单击“登录”按钮后,一个graphql查询被发送到我的服务器,服务器用Jwt进行响应。收到jwt后,应用程序将cookie设置为

document.cookie = ...
在Cypress测试中,我通过以下方式检查令牌:

Then("sa session s'ouvre pour {SessionDurationType}", expectedDuration => {
  cy.get('@graphql').then(() => {
    cy.wait(1000)
    cy.getCookie('token').then(cookie => {
      const tokenDuration = getTokenDuration(cookie.value)
     expect(tokenDuration.asSeconds()).to.equal(expectedDuration.asSeconds())
    })
  })
})
使用
cy.get('@graphql')
,我正在等待graphql查询返回响应。别名的定义如下:

cy.stub(win, 'fetch', fetch).as('graphql')
cy.get('@graphql').then(() => {
  const handler = new TokenHandler
  handler.getToken().then(token => {
    const tokenDuration = getTokenDuration(token)
    expect(tokenDuration.asSeconds()).to.equal(expectedDuration.asSeconds())
  })
})
接收后,应用程序设置cookie

我的问题是我不喜欢下面的电话:

cy.wait(1000)
没有那个电话,我总是得到一个未定义的cookie


有没有一种方法可以在远低于1000毫秒的时间内得到饼干?我尝试了很多事情都没有成功

必须编写递归承诺函数,请尝试以下操作

function checkCookie() {
  // cy.getCookie returns a thenebale
  return cy.getCookie('token').then(cookie => {
    const tokenDuration = getTokenDuration(cookie.value);
    // it checks the seconds right now, without unnecessary waitings
    if(tokenDuration.asSeconds() !== expectedDuration.asSeconds()) {
      // waits for a fixed milliseconds amount
      cy.wait(100);
      // returns the same function recursively, the next `.then()` will be the checkCookie function itself
      return checkCookie();
    }
    // only when the condition passes returns a resolving promise
    return Promise.resolve(tokenDuration.asSeconds());
  })
}

Then("sa session s'ouvre pour {SessionDurationType}", expectedDuration => {
  cy.get('@graphql').then(() => {
    checkCookie()
      .then(seconds => {
        expect(seconds).to.equal(expectedDuration.asSeconds())
      })
  })
})

请注意,必须改进该功能,因为

  • 我没有将
    期望值
    等参数化(它不在演示如何实现的范围内)
  • 它将永远等待,而不进行循环计数器检查
但它是有效的(在回复您之前,我在另一个上下文中进行了检查),如果您还有一些问题,请共享一个“正在工作”的GitHub repo,这样我就可以克隆它并使用您自己的解决方案进行检查


如果不够清楚,请告诉我根据@NoriSte的回答,我想出了以下工作代码:

function awaitNonNullToken(elapsedTimeInMs = 0) {
  let timeDeltaInMs = 10

  if (elapsedTimeInMs > Cypress.env('timeoutInMs')) {
    return Promise.reject(new Error('Awaiting token timeout'))
  }

  return getTokenCookie().then(cookie => {
    if (cookie === null) {
      cy.wait(timeDeltaInMs)
      elapsedTimeInMs += timeDeltaInMs
      return awaitNonNullToken(elapsedTimeInMs)
    }
    return Promise.resolve(cookie.value)
  })
}
我将其转换为一个ES6类,我发现它更加优雅:

class TokenHandler {
  constructor () {
    this.TIME_DELTA_IN_MS = Cypress.env('timeDeltaInMs')
    this.TIMEOUT_IN_MS = Cypress.env('timeoutInMs')
    this.elapsedTimeInMs = 0
  }

  getToken () {
    if (this.elapsedTimeInMs > this.TIMEOUT_IN_MS) {
      return Promise.reject(new Error('Awaiting token timeout'))
    }
    return getTokenCookie().then(cookie => {
      if (cookie === null) {
        cy.wait(this.TIME_DELTA_IN_MS)
        this.elapsedTimeInMs += this.TIME_DELTA_IN_MS
        return this.getToken()
      }
      return Promise.resolve(cookie.value)
    })
  }
}
然后把我的步骤改成这样:

cy.stub(win, 'fetch', fetch).as('graphql')
cy.get('@graphql').then(() => {
  const handler = new TokenHandler
  handler.getToken().then(token => {
    const tokenDuration = getTokenDuration(token)
    expect(tokenDuration.asSeconds()).to.equal(expectedDuration.asSeconds())
  })
})

这是完美的工作,谢谢。

我不喜欢这个超时,我不得不说,对于dom更改。我已经基于@NoriSte Answer和dom提出了这个解决方案

getFileUploadItem().get(“.upload item--state i”)
.should(“have.class”,“ngx文件上传图标--开始”)
。然后(项目=>{
const iconEl=item.get(0);
常量状态:字符串[]=[];
返回新承诺((解决、拒绝)=>{
常量观察者=新的突变观察者((突变:突变记录[])=>{
常量mutationEl=突变[0]。目标为HtmleElement;
const className=mutationEl.getAttribute(“类”);
states.push(className);
if(className==“ngx文件上传图标——上传”){
决心(国家);
}
});
观察者,观察者{
子树:对,
属性:正确,
attributeFilter:[“类”]
});
});
})
.然后((值)=>expect(值).to.deep.equal(
[“ngx文件上传图标-进度”,“ngx文件上传图标-上传”])
);