Casperjs

Deleting all scheduled jobs in Salesforce with CasperJs

by Patrick Connelly posted on July 26, 2013

PREFACE

In a previous post, I talked about how to log in to Salesforce with CasperJs. At the time I did not have a good example of what to do next with it. Well, this week I had a need that is something that other people can relate to.

Casper Script

If you’ve ever done any Scheduled Apex work, then you know that if there are scheduled jobs for the class and you do a deployment, the deployment fails. To help negate this with automated installs I wrote the following CasperJs script does the following:

  1. Logs into Salesforce
  2. Navigates to the scheduled jobs page
  3. Gathers all the delete links for the jobs
  4. Deletes them
/*jslint browser: true, regexp: true */
/*global casper, require, jQuery*/

var BASE_URL, LOGIN_URL, LOGIN_USERNAME, LOGIN_PASSWORD, SCHEDULED_JOBS_URI, casp;

casp = require('casper').create({
     clientScripts: [
          'jquery.min.js'
     ],
     viewportSize: {
          width: 1024,
          height: 768
     },
     verbose: true,
     logLevel: 'info'
});

if (!casp.cli.has('username') && !casp.cli.has('password')) {
     casp.echo('Usage: $ casperjs deleteScheduledJobs.casper.js --username=USERNAME --password=PASSWORD [--prod]').exit(-1);
}

if (casp.cli.has('prod')) {
     LOGIN_URL = 'https://login.salesforce.com/';
} else {
     LOGIN_URL = 'https://test.salesforce.com/';
}

LOGIN_USERNAME = casp.cli.get('username');
LOGIN_PASSWORD = casp.cli.get('password');

SCHEDULED_JOBS_URI = '08e?setupid=ScheduledJobs';

casp.start(LOGIN_URL, function () {
     'use strict';

     this.log('Logging in', 'info');
     this.fill('form', {
          'username': LOGIN_USERNAME,
          'pw': LOGIN_PASSWORD
     }, true);

     this.log('Logged in', 'info');

     BASE_URL = casp.getCurrentUrl().split('.salesforce.com')[0] + '.salesforce.com/';

     casp.thenOpen(BASE_URL + SCHEDULED_JOBS_URI, function () {
          var deleteUrls;

          this.log('Fetching jobs to delete', 'info');

          deleteUrls = this.evaluate(function () {
               var urls, url;
               urls = [];

               jQuery('table.list tr.dataRow').each(function (i, item) {
                    url = {};
                    url.href = jQuery('td.actionColumn a.actionLink', item).attr('href').substring(1);
                    url.name = jQuery('th', item).html();
                    urls.push(url);
               });

               return urls;
          });

          this.each(deleteUrls, function (self, url) {
               this.log('Deleting "' + url.name + '"', 'info');
               self.thenOpen(BASE_URL + url.href, function () {
                    this.log('"' + url.name + '" deleted', 'info');
               }, function () {
                    this.log('Timed out deleting "' + url.name + '"', 'error');
               });
          });
     });
});

casp.run();

Then we can run it like all other CasperJs scripts

casperjs deleteScheduleJobs.casper.js --username=USERNAME --password=PASSWORD [--prod]

Logging into Salesforce with CasperJs

by Patrick Connelly posted on July 09, 2013

Preface

Anyone that has ever had to deal with editing multiple Entitlement Processes in Salesforce will know the pain of having to do this in multiple environments and making sure you don’t fat finger this manual process. In the past when I’ve had to do this, I’ve either sucked it up and did it manually, or did it with Selenium. I wasn’t a big fan of either of these solutions since I’m a command-line kinda guy. That’s when I was told about CasperJs and I think I’m in love.

CasperJs

CasperJs is a framework built on top of PhantomJs, and allows you to write JavaScript to web automation. Like with all Salesforce tasks, logging in is the first thing you need to do. Let’s take a look at the sfdclogin.casper.js.

/*jslint browser: true, regexp: true */
/*global casper, require */

var LOGIN_URL, LOGIN_USERNAME, LOGIN_PASSWORD, casp;

casp = require('casper').create({
     viewportSize: {
          width: 1024,
          height: 768
     },
     verbose: true,
     logLevel: 'warning'
});

if (!casp.cli.has('username') && !casp.cli.has('password')) {
     casp.echo('Usage: $ casperjs sfdclogin.casper.js --username=USERNAME --password=PASSWORD [--prod]').exit(-1);
}

if (casp.cli.has('prod')) {
     LOGIN_URL = 'https://login.salesforce.com/';
} else {
     LOGIN_URL = 'https://test.salesforce.com/';
}

LOGIN_USERNAME = casp.cli.get('username');
LOGIN_PASSWORD = casp.cli.get('password');

casp.start(LOGIN_URL, function () {
     'use strict';

     this.log('Logging in', 'debug');
     this.fill('form', {
          'username': LOGIN_USERNAME,
          'pw': LOGIN_PASSWORD
     }, true);

     this.log('Logged in', 'debug');
});

casp.then(function () {
     'use strict';

     this.echo('We\'re logged in.  Now we can do more stuff like take a screenshot!');

     this.waitForSelector('#userNavLabel', function () {
          this.captureSelector('test.png', 'html');
          this.log('saved screenshot of ' + this.getCurrentUrl() + 'to test.png', 'warning');
     }, function () {
          this.die('Timeout reached');
          this.exit();
     }, 12000);
});

casp.run();

To run this class we simply do

casperjs sfdclogin.casper.js --username=USERNAME --password=PASSWORD [--prod]

This JavaScript is pretty simple, but it gives us a base to build on top of. We first setup our CasperJs instance with our screen size, the verbosity and the log level. Then we get our parameters from the command-line for username and password, this allows us to not store these inside the js file. We then fill in the login form and submit it. Now we’re ready to do some actual work. In the above js file, all we are doing is taking a simple screenshot of the page, but we could do any number of things from the CaseperJs documentation.