Search code examples
javascriptautomationsalesforcecypressjsforce

How can I use SFDX with Cypress?


I'm currently able to connect my salesforce inside of my cypress folder. The problem is that I'm not able to use both tools inside of a spec file. Also, I'm trying to use jsforce, but I don't have any idea of how to do an integration with cypress.

Does anyone have a good idea to do this?

Example:

const jsforce = require('jsforce');
require('dotenv').config()

const {SF_LOGIN_URL, USER_NAME, PASSWORD, SECURITY_TOKEN} = process.env
const conn = new jsforce.Connection({
    loginUrl: SF_LOGIN_URL
})

conn.login(USER_NAME, PASSWORD+SECURITY_TOKEN, (err, userInfo)=>{
    if(err){
        console.error(err)
    } 

    conn.query('SELECT Id, Name FROM Opportunity', function(err, opportunity){
        if(err){ return console.error(err);}
        console.log(opportunity.records)
    });
});


Solution

  • If you go to the JSForce page, the code you've used is under the Node.js tab.

    Anything that requires Node to run must be put into a task, so off the top of my head

    /cypress/plugins/index.js

    module.exports = (on, config) => {
      on('task', {
        loginJSForce() {
    
          const jsforce = require('jsforce');
          require('dotenv').config();
    
          const {SF_LOGIN_URL, USER_NAME, PASSWORD, SECURITY_TOKEN} = process.env;
          const conn = new jsforce.Connection({
            loginUrl: SF_LOGIN_URL
          })
    
          conn.login(USER_NAME, PASSWORD+SECURITY_TOKEN, (err, userInfo) => {
    
            if (err) {
              console.error(err)
            } 
    
            conn.query('SELECT Id, Name FROM Opportunity', (err, opportunity) => {
              if (err) { 
                return console.error(err); 
              }
              console.log(opportunity.records)
            });
          });
    
          return null
        },
      })
    }
    

    Test

    cy.task('loginJSForce');
    

    I'm guessing you want to run some assertions against opportunity.records in the test, in which case you need at minimum to return them (instead of return null).

    Based on this example Return number of files in the folder, that needs a Promise and might look like this

    /cypress/plugins/index.js

    module.exports = (on, config) => {
      on('task', {
        loginJSForce() {
    
          const jsforce = require('jsforce');
          require('dotenv').config();
    
          const {SF_LOGIN_URL, USER_NAME, PASSWORD, SECURITY_TOKEN} = process.env;
          const conn = new jsforce.Connection({ loginUrl: SF_LOGIN_URL });
    
          return new Promise((resolve, reject) => {
    
            conn.login(USER_NAME, PASSWORD+SECURITY_TOKEN, (err, userInfo) => {
    
              if (err) {
                return reject(err);
              } 
    
              conn.query('SELECT Id, Name FROM Opportunity', (err, opportunity) => {
                if (err) { 
                  return reject(err);
                }
    
                return resolve(opportunity.records)
              })
            })
          })
        },
      })
    }
    

    Test

    cy.task('loginJSForce')
      .then(records => console.log(records));
    

    There's some things in the example that are not consistent, for example return reject(err) but no return on resolve(files.length). I'd expect them to be treated the same.

    You can try out both with and without return on a working system, see which way works.


    You could also try to adapt the code on the Web Browser tab to run in the test script, but since you use dotenv and process.env you probably still need a task to access those env variables.