如何在返回值之前等待 Cypress then() 命令完成?
How to wait for Cypress then() command to finish before returning a value?
我正在尝试在 .then() 命令中设置一个变量,该命令在其外部声明,并且在整个块完成后(.then())我正在 return值。
问题是,当我 return 值时,变量未定义,但在 .then() 块中,变量被加载。
示例代码如下:
public getValueFromElement(): string {
cy.log("Obtaining the Value");
let myNumber: string; // Here I'm declaring my variable
cy.get(this.labelWithText).then(($element) => {
let originalLabelText: string = $element.text();
let splittedText: string[];
splittedText = originalLabelText.split(": ");
myNumber = splittedText[1]; // Here I'm assigning the value
cy.log("Inside the THEN" + myNumber); //This logs the number correctly
});
return myNumber; // But after I return it using the function, the value is `undefined`!
}
我假设这可能与异步/同步问题有关,因为调用函数时会立即执行 return
语句,并且 .then()
创建的承诺是仍然 运行,但我不知道如何解决这个问题。
你知道我如何等待 .then()
先完成然后再 return 计算值吗?
谢谢!!
你说“问题是,当我 return 值时,变量是未定义的”。
那是因为 return myNumber
行在 之前运行 cy.get(this.labelWithText).then(($element) => {
完成,因为命令是 运行 异步。
您需要 return 命令本身,派生的 myNumber
是从 .then()
.
内部 return 编辑的
public getValueFromElement(): Chainable<string> { // cannot return the raw string
cy.log("Obtaining the Value");
return cy.get(this.labelWithText).then(($element) => {
...
const myNumber = splittedText[1];
cy.log("Inside the THEN " + myNumber)
return myNumber
})
}
这样使用
getValueFromElement().then(myNumber => {
cy.log("Outside the function " + myNumber)
})
这是一个错误的答案,但出于教育目的,我将其保留在这里,以防其他人偶然发现同样的问题。
您可以不像这样使用await
:
public async getValueFromElement(): string {
cy.log("Obtaining the Value");
let myNumber: string; // Here I'm declaring my variable
let $element = await cy.get(this.labelWithText);
let originalLabelText: string = $element.text();
let splittedText: string[];
splittedText = originalLabelText.split(": ");
myNumber = splittedText[1];
return myNumber
}
但请注意,现在这个函数是异步的,它本身 returns 是一个承诺。
为什么?
文档是这样说的:
If you're a modern JS programmer you might hear "asynchronous" and think: why can't I just use async/await instead of learning some proprietary API?
Cypress's APIs are built very differently from what you're likely used to: but these design patterns are incredibly intentional. We'll go into more detail later in this guide.
你可以这样同步
public getValueFromElement(): string {
cy.log("Obtaining the Value");
const $element = Cypress.$(this.labelWithText)
const originalLabelText: string = $element.text()
const splitText = originalLabelText.split(": ")
const myNumber = splitText[1]
return myNumber
}
在这里你牺牲了异步命令中内置的重试选项。
Cypress 表示只有当您确定该元素已经存在时才使用它,这取决于您文本的上下文。
@MikhailBolotov 的确如此。这就是你的处理方式
cy.get("myOpenElementSelector").click() // async code
.then(() => { // must wrap sync code in then
const myNumber = getValueFromElement() // to ensure correct sequence
expect(+myNumber).to.eq(64)
})
@Mihi 有惯用的方法,但是在编写页面对象方法时有时会遇到困难。
我得出的结论是:
public async getTheNumber(): Promise<string> {
return new Promise((resolve, reject) => {
cy.log("Retrieving the number");
cy.get(this.selector).then(($element) => {
let myNumber = $element.text().split(": ")[1];
cy.log(`The Number is ${myNumber}`);
resolve(myNumber);
});
});
}
当我从测试中读取它时,我正在这样做:
myNumberAtTestLevel = await myObject.getTheNumber();
事情是我已经看到我必须将我的 it()
方法更改为 async
才能使其工作。
但是,我看到了 Cypress 的文档:
https://docs.cypress.io/api/utilities/promise#Syntax
我正在尝试使用 Cypress.Promises
实现相同的功能,但我做不到。
有什么想法吗?
我正在尝试在 .then() 命令中设置一个变量,该命令在其外部声明,并且在整个块完成后(.then())我正在 return值。
问题是,当我 return 值时,变量未定义,但在 .then() 块中,变量被加载。
示例代码如下:
public getValueFromElement(): string {
cy.log("Obtaining the Value");
let myNumber: string; // Here I'm declaring my variable
cy.get(this.labelWithText).then(($element) => {
let originalLabelText: string = $element.text();
let splittedText: string[];
splittedText = originalLabelText.split(": ");
myNumber = splittedText[1]; // Here I'm assigning the value
cy.log("Inside the THEN" + myNumber); //This logs the number correctly
});
return myNumber; // But after I return it using the function, the value is `undefined`!
}
我假设这可能与异步/同步问题有关,因为调用函数时会立即执行 return
语句,并且 .then()
创建的承诺是仍然 运行,但我不知道如何解决这个问题。
你知道我如何等待 .then()
先完成然后再 return 计算值吗?
谢谢!!
你说“问题是,当我 return 值时,变量是未定义的”。
那是因为 return myNumber
行在 之前运行 cy.get(this.labelWithText).then(($element) => {
完成,因为命令是 运行 异步。
您需要 return 命令本身,派生的 myNumber
是从 .then()
.
public getValueFromElement(): Chainable<string> { // cannot return the raw string
cy.log("Obtaining the Value");
return cy.get(this.labelWithText).then(($element) => {
...
const myNumber = splittedText[1];
cy.log("Inside the THEN " + myNumber)
return myNumber
})
}
这样使用
getValueFromElement().then(myNumber => {
cy.log("Outside the function " + myNumber)
})
这是一个错误的答案,但出于教育目的,我将其保留在这里,以防其他人偶然发现同样的问题。
您可以不像这样使用await
:
public async getValueFromElement(): string {
cy.log("Obtaining the Value");
let myNumber: string; // Here I'm declaring my variable
let $element = await cy.get(this.labelWithText);
let originalLabelText: string = $element.text();
let splittedText: string[];
splittedText = originalLabelText.split(": ");
myNumber = splittedText[1];
return myNumber
}
但请注意,现在这个函数是异步的,它本身 returns 是一个承诺。
为什么?
文档是这样说的:
If you're a modern JS programmer you might hear "asynchronous" and think: why can't I just use async/await instead of learning some proprietary API?
Cypress's APIs are built very differently from what you're likely used to: but these design patterns are incredibly intentional. We'll go into more detail later in this guide.
你可以这样同步
public getValueFromElement(): string {
cy.log("Obtaining the Value");
const $element = Cypress.$(this.labelWithText)
const originalLabelText: string = $element.text()
const splitText = originalLabelText.split(": ")
const myNumber = splitText[1]
return myNumber
}
在这里你牺牲了异步命令中内置的重试选项。
Cypress 表示只有当您确定该元素已经存在时才使用它,这取决于您文本的上下文。
@MikhailBolotov 的确如此。这就是你的处理方式
cy.get("myOpenElementSelector").click() // async code
.then(() => { // must wrap sync code in then
const myNumber = getValueFromElement() // to ensure correct sequence
expect(+myNumber).to.eq(64)
})
@Mihi 有惯用的方法,但是在编写页面对象方法时有时会遇到困难。
我得出的结论是:
public async getTheNumber(): Promise<string> {
return new Promise((resolve, reject) => {
cy.log("Retrieving the number");
cy.get(this.selector).then(($element) => {
let myNumber = $element.text().split(": ")[1];
cy.log(`The Number is ${myNumber}`);
resolve(myNumber);
});
});
}
当我从测试中读取它时,我正在这样做:
myNumberAtTestLevel = await myObject.getTheNumber();
事情是我已经看到我必须将我的 it()
方法更改为 async
才能使其工作。
但是,我看到了 Cypress 的文档: https://docs.cypress.io/api/utilities/promise#Syntax
我正在尝试使用 Cypress.Promises
实现相同的功能,但我做不到。
有什么想法吗?