0

I am testing an angular js salesforce application using protractor. I need to query for ids using SOQL and jsforce however when I call the query method from another class the return result is undefined. When I print out the log in the method it does show the id I am looking for just seems to get lost in the return statement.

var jsforce = require('jsforce');

function querySF() {
  var conn = new jsforce.Connection({
    // you can change loginUrl to connect to sandbox or prerelease env.
    loginUrl: 'https://www.salesforce.com'
  });
  conn.login('some username', 'some password', function(err, userInfo) {
    if (err) {
      return console.error(err);
    }
    // Now you can get the access token and instance URL information.
    // Save them to establish connection next time.
    console.log(conn.accessToken);
    console.log(conn.instanceUrl);
    // logged in user property
    console.log("User ID: " + userInfo.id);
    console.log("Org ID: " + userInfo.organizationId);
    // ...
  }).then(function() {
    conn.query("SELECT Id FROM anObject__c Where name = 'the name'", function(err, result) {
      if (err) {
        return console.error(err);
      }
      var records = [];
      console.log("total : " + result.totalSize);
      console.log("fetched : " + result.records.length);
      // is returning the id
      console.log(result.records[0].Id);
      // the class that calls the methods saves it to a variable, the variable is undefined
      return result.records[0].Id;
    });
  });


}
After updating my code to match Thomas' answer the below is the error I am receiving

Failed: Helper.querySF is not a function TypeError: Helper.querySF is not a function at Object.it (C:\LimService\LSApp\tests\specs\bookingEvents\EditBookingEventTest.js:23:12) at C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\jasminewd2\index.js:112:25 at new ManagedPromise (C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:1067:7) at ControlFlow.promise (C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:2396:12) at schedulerExecute (C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\jasminewd2\index.js:95:18) at TaskQueue.execute_ (C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:2970:14) at TaskQueue.executeNext_ (C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:2953:27) at asyncRun (C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:2860:25) at C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:676:7

Nicole Phillips
  • 753
  • 1
  • 18
  • 41
  • Could you share how you're consuming this piece of code in the other class? – maazadeeb May 23 '17 at 17:00
  • `return conn.login(...).then(...)` and `return conn.query(...)` – Thomas May 23 '17 at 17:51
  • @Maazsyedadeeb var theId = Helper.querySF; – Nicole Phillips May 23 '17 at 19:29
  • @NicolePhillips the Error says `Helper.querySF` is not a function. What is `Helper` in `EditBookingEventTest.js` line 23? – Thomas May 24 '17 at 14:25
  • @Thomas it is the class name in which the method is located. – Nicole Phillips May 24 '17 at 14:30
  • That's what you assume it is, but have you checked it? And are you sure that the class exposes the `querySF` method? That's what Imeant with the last question. Have you checked what exactly is referenced under the name of `Helper` in that file, at that line? – Thomas May 24 '17 at 15:17
  • We access about 30 different methods the same way on the class. At the bottom of the helper class we export the method like this: exports.querySF = querySF(); – Nicole Phillips May 24 '17 at 15:24
  • `exports.querySF = querySF;` not the result of the function called. – Thomas May 24 '17 at 20:49
  • @Thomas You must forgive me as I am coming off of C# automation with Selenium and just starting with angular js and do not have much knowledge on the matter. You may need to do crude laymans terms with me to understand what you are asking. – Nicole Phillips May 25 '17 at 12:40

1 Answers1

2

As mentioned in the comment, you forgot a few return statements.

Besides that, don't mix promises and callbacks. Especially don't use both to process the same result.

var jsforce = require('jsforce');

function querySF() {
    var conn = new jsforce.Connection({
        // you can change loginUrl to connect to sandbox or prerelease env.
        loginUrl: 'https://www.salesforce.com'
    });

    return conn.login('some username', 'some password')
        .then(function(userInfo) { 
            // Now you can get the access token and instance URL information.
            // Save them to establish connection next time.
            console.log(conn.accessToken);
            console.log(conn.instanceUrl);
            // logged in user property
            console.log("User ID: " + userInfo.id);
            console.log("Org ID: " + userInfo.organizationId);
            // ...

            return conn.query("SELECT Id FROM anObject__c Where name = 'the name'")
        })
        .then(function(result){
              console.log("total : " + result.totalSize);
              console.log("fetched : " + result.records.length);
              // is returning the id
              console.log(result.records[0].Id);
              // the class that calls the methods saves it to a variable, the variable is undefined
              return result.records[0].Id;
        })
        .catch(function(err){
            console.error(err);
        });
}

This seems to work however it returns a promise.

That's the point of async code, that the result you want ain't there (yet) when the function returns; so you have to deal with a value that will be available at some point in the future.

One way to do that is by returning a Promise.

Maybe you should read this: How do I return the response from an asynchronous call?

It looks as though there are 3 promises being returned, or 3 values at least, the 3rd value is the value i need.

No, this is just a Promise chain. Only a single value can be returned, and a Promise also, can only resolve to a single value; although that single value may be an Array.

You should get used to Promises. They are handier than the callback syntax.

I'm not sure how to access that value.

like this:

querySF().then(function(id){
    console.log("result: ", id);
});
Thomas
  • 11,958
  • 1
  • 14
  • 23
  • This seems to work however it returns a promise. I debugged and I can see the value I am looking for however I'm not sure how to access that value. It looks as though there are 3 promises being returned, or 3 values at least, the 3rd value is the value i need. – Nicole Phillips May 23 '17 at 19:24
  • @NicolePhillips it's `querySF()` not `querrySF()` – Thomas May 24 '17 at 13:54
  • That was a typo on my part. I have it listed as querySF() in the js class. – Nicole Phillips May 24 '17 at 13:56
  • I have updated my answer to show the new error after using your sln. – Nicole Phillips May 24 '17 at 14:01
  • I am marking this as correct as this does answer my question however I do not yet understand promises so have moved to a different thread. Thanks for your help. – Nicole Phillips May 25 '17 at 13:25