0

I created a Cypress custom command which displays the value using console.log (so I know it works). However, when I call the custom command in my Cypress test file, it returns blank / null.

support/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
})

integration/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
            })
    })
})

=== Update:

This worked but when trying to do an assertion, it does not work as I am unable to convert an Object Promise to a string.

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
})

Test file:

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)
    })

===

Update#2: This displays the returned value but not picked up for assertion

aws.js file:

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 file:

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
        })
    })
ebanster
  • 886
  • 1
  • 12
  • 29

1 Answers1

0

If this AWS function is async you should handle it like promise so instead:

 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
});

Also if in test you need to only read this value you can use callback instead of promise: e.g.

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

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

  • Updated:

To assert string from object you can use wrap and invoke cypress methods: docs

scan function is async, so you have to call it like this:

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

Przemyslaw Jan Beigert
  • 2,351
  • 3
  • 14
  • 19
  • Thanks for this. I cant make it work though. I get "Cannot read property 'Items" of undefined. Basically, I am making trying to make call to DynamoDB and return a value using the solution here: [link](https://stackoverflow.com/questions/44589967/how-to-fetch-scan-all-items-from-aws-dynamodb-using-node-js). – ebanster Mar 12 '20 at 04:35
  • I provided an update on my post (see **Update** section) but I felt I am doing an overly-structured code. If you can have a look, that would be great. I cant make the Object promise converted into string in my Cypress test. For some reason, I cannot make the `await` or `.then` work – ebanster Mar 12 '20 at 07:27
  • I added updated section, pls let me know if that helps – Przemyslaw Jan Beigert Mar 12 '20 at 08:29
  • Thanks and appreciate your time on this. However, the above `const record = scanTable(tableName, recordId).then(record => { cb(record)` does not work. I get the error on console: `Uncaught (in promise) TypeError: Cannot read property 'recordId' of undefined at _callee$` Not trying to be spoonfed but I tried every possibilities on Cypress.Promise, wrap, and invoke as per docs but this async is doing my head in. – ebanster Mar 15 '20 at 10:57
  • I need more details to solve this, full stack trace will be helpful. – Przemyslaw Jan Beigert Mar 16 '20 at 20:42
  • Pls paste console error from ` // const record = scanTable(tableName, recordId).then(record => { cb(record) }) //This does not work and returns a console error` – Przemyslaw Jan Beigert Mar 19 '20 at 11:36
  • Sorry, based on the updated code I used above, no errors were shown in the console. The `cy.log` to display the texts are also not appearing. Just shows `No commands were issued in this test.` I think I encountered the error `TypeError: Cannot read property 'recordId' of undefined at _callee$` when trying to use the `wrap` and `invoke` function which I cant make work. – ebanster Mar 20 '20 at 01:05
  • No errors but it is still not being captured for assertion. – ebanster Mar 21 '20 at 11:57