【问题标题】:Cypress: Cypress custom command's return value actually returns null in the test fileCypress:Cypress 自定义命令的返回值实际上在测试文件中返回 null
【发布时间】:2020-04-26 16:01:07
【问题描述】:

我创建了一个赛普拉斯自定义命令,它使用 console.log 显示值(所以我知道它有效)。但是,当我在赛普拉斯测试文件中调用自定义命令时,它返回空白/null。

支持/commands.js:

Cypress.Commands.add('scanAWSDb', (siteId) => {
 let siteName = null //default it to null
 ... some AWS SDK function which scans the DB and check for corresponding Name of the ID: 12345 ...
 siteName = <new value>
 console.log("Value returned is: " + siteName //This displays the value in the web console for the corresponding ID: 12345, let's say name is Taylor
 return siteName //Expected to return "Taylor" in the test file
})

集成/test1.spec.js:

describe('Display value from the Custom command that scanned the AWS DB', ()=> {
    it('Display value from the Custom command that scanned the AWS DB', () => {
        const siteId = "12345" 
        cy.scanAWSDb(siteId)
            .then((returned_value) => {
                cy.log(returned_value) //This displays a null value so it is not picking up the return value from the custom command which is supposedly Taylor
            })
    })
})

=== 更新:

这可行,但在尝试进行断言时,它不起作用,因为我无法Object Promise 转换为字符串

export const scanTable = async (tableName, recordId) => {
    const params = {
        TableName: tableName,
        FilterExpression: '#Id = :RecordId',
        ExpressionAttributeNames: {
            '#Id': 'Id',
        },
        ExpressionAttributeValues: {
            ':RecordId': recordId 
        }
    };

    let scanResults = []; 
    let items
    let index = 0
    do{
        items =  await docClient.scan(params).promise()
        items.Items.forEach((item) => scanResults.push(item))
        params.ExclusiveStartKey  = items.LastEvaluatedKey
        let scannedRecordId = JSON.stringify(items.Items[index].Id)
        cy.log('Record successfully found in table: ' + scannedRecordId )
        index += 1 
    }while(typeof items.LastEvaluatedKey != "undefined")

    return scannedRecordId;
};

Cypress.Commands.add('scanDB', (tableName, recordId, cb) => {
    const record = scanTable(tableName, recordId)
    cb(record) // Callback function
})

测试文件:

const tableName = 'table1';
let recordId = '';

cy.scanDB(tableName, recordId, $returnValue => {
cy.log($returnValue) //<-- THIS DISPLAYS THE OBJECT BUT I NEED TO CONVERT IT TO STRING SO I CAN DO ASSERTION like this:
//expect($returnValue).to.eq(recordId)
    })

===

更新#2:这会显示返回的值,但没有为断言拾取

aws.js 文件:

const AWS = require('aws-sdk')
const region = Cypress.env('aws_region')
const accessKeyId = Cypress.env('aws_access_key_id')
const secretAccessKey = Cypress.env('aws_secret_access_key')
const sessionToken = Cypress.env('aws_session_token')

let scannedRecordId = ''

AWS.config.update({region: region})
AWS.config.credentials = new AWS.Credentials(accessKeyId, secretAccessKey, sessionToken)

const docClient = new AWS.DynamoDB.DocumentClient();

export const scanTable = async (tableName, recordId) => {
    const params = {
        TableName: tableName,
        FilterExpression: '#Id = :RecordId',
        ExpressionAttributeNames: {
            '#Id': 'RecordId',
        },
        ExpressionAttributeValues: {
            ':RecordId': recordId // Check if Id is stored in DB
        }
    };

    let scanResults = []; 
    let items
    let index = 0
    do{
        items =  await docClient.scan(params).promise()
        items.Items.forEach((item) => scanResults.push(item))
        params.ExclusiveStartKey  = items.LastEvaluatedKey
        scannedRecordId = JSON.stringify(items.Items[index].Id)
        cy.log('Record successfully found in table: ' + scannedRecordId)
        index += 1 // This may not be required as the assumption is that only a unique record is found
    }while(typeof items.LastEvaluatedKey != "undefined")

    return scannedRecordId;
};

Cypress.Commands.add('scanDB', (tableName, recordId, cb) => {
    const record = scanTable(tableName, recordId)
    cb(record) // Callback function

    // const record = scanTable(tableName, recordId).then(record => { cb(record) }) //This does not work and returns a console error
})

awsTest.js 文件:

const tableName = 'random-dynamodb-table'
let myId = '12345'
it('Verify if ID is stored in AWS DynamoDB', () => {
cy.scanDB(tableName, myId, $returnValue => {
        cy.log($returnValue)
        cy.log(`Record ID: ${myId} is found in table: ` + $returnValue)
        expect($returnValue).to.deep.eq(myId) //This asserts that the Id is found
        })
    })

【问题讨论】:

标签: javascript amazon-dynamodb cypress aws-sdk-js


【解决方案1】:

如果这个 AWS 函数是异步的,你应该像 promise 那样处理它:

 let siteName = null //default it to null
 ... some AWS SDK function which scans the DB and check for corresponding Name of the ID: 12345 ...
 siteName = <new value>
AWSFunction().then((newValue) => {
  siteName = newValue
  console.log("Value returned is: " + siteName)
  return siteName
});

另外,如果在测试中你只需要读取这个值,你可以使用回调而不是承诺:例如

Cypress.Commands.add('scanAWSDb', (siteId, cb) => {
  AWSFunction().then((newValue) => {
    cb(newValue);
  })
})

// test
cy.scanAWSDb(siteId, (returned_value) => {
  cy.log(returned_value)
});

  • 更新:

要从对象断言字符串,您可以使用wrapinvoke cypress 方法:docs

scan 函数是异步的,所以你必须这样调用它:

Cypress.Commands.add('scanDB', (tableName, recordId, cb) => {
    const record = scanTable(tableName, recordId).then(record => { cb(record) };
})

【讨论】:

  • 谢谢。我不能让它工作。我得到未定义的“无法读取属性'项目”。基本上,我正在尝试调用 DynamoDB 并使用此处的解决方案返回一个值:link.
  • 我在我的帖子中提供了更新(请参阅更新部分),但我觉得我正在编写一个过度结构化的代码。如果你能看一看,那就太好了。我无法在赛普拉斯测试中将 Object 承诺转换为字符串。出于某种原因,我无法使 await.then 工作
  • 我添加了更新的部分,如果有帮助请告诉我
  • 感谢您的宝贵时间。但是,上面的const record = scanTable(tableName, recordId).then(record =&gt; { cb(record) 不起作用。我在控制台上收到错误消息:Uncaught (in promise) TypeError: Cannot read property 'recordId' of undefined at _callee$ 不是想被喂饱,但我尝试了 Cypress.Promise 上的所有可能性,按照文档进行包装和调用,但这个异步正在让我头疼。
  • 我需要更多细节来解决这个问题,完整的堆栈跟踪会有所帮助。
猜你喜欢
  • 2019-09-10
  • 1970-01-01
  • 2013-12-07
  • 1970-01-01
  • 2015-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-03
相关资源
最近更新 更多