Wednesday, September 25, 2013

Force.com #Tested, Way Beyond Code Coverage

Force.com gives developers a quick and easy way to not only deploy business automation but also to set up unit tests for acceptance testing and regression testing. The value of such testing cannot be underestimated, especially in large orgs with multiple admins, developers and outsourced partners.

While the ideals are good, there are many challenges preventing an organization from reaching these goals. Managers may not fully understand the benefits of unit testing, and as a result have little or no buy-in for the practice. Without buy-in from managers, there is no enforcement of consistent methodologies for internal and external developers. Frustrated developers who don't have management support, training or knowledge on unit tests only see the code coverage portion of unit testing and feel that the practice is a big pain with little gain.

But actually, proper and disciplined use of unit tests on Force.com allows a company to:
  • More reliably implement new features by explicitly testing for expected functionality using Apex
  • Simplify regression testing by allowing the system to automatically perform acceptance tests that were used when deploying previous features to production
  • More confidently allow developers to simultaneously tackle multiple work streams for different features, knowing that both each other's functionality and previous functionality will be validated together before new features goes live
  • Define functional specifications for external parties through unit tests, in addition to written requirements

This blog mini-series aims to address the challenges above by sequentially tackling the following topics, with new posts every 3 business days:
  1. Standard pattern for Apex unit tests
  2. Common database of test data for all Apex unit tests
  3. Using System.assert() and related methods to verify expected conditions for the test
  4. Using Test.startTest(), Test.stopTest() and other Test methods
  5. Using System.assert() and related methods for validating test results
  6. Apex unit tests for workflow rules, validation rules and system configurations
  7. How this standard pattern affects code coverage

Monday, September 9, 2013

Adding a Live Agent Chat Side Tab to All Pages in a Community

Chatter Communities gives administrators and web developers a method to implement more advanced customization of the UI, without resorting to fully custom pages or sites through Force.com Sites or Site.com. The means to achieve this customization is through an HTML header or footer, uploaded as a Document in Salesforce. The ability to customize the entire site with HTML gives web developers an easy way to add a Web 2.0 feature to an entire community: live chat side tab via Live Agent.


Similar to the Contact Us side tab shown on salesforce.com (screenshot above), the intent behind the live chat side tab is to enable the following functionality, no matter where a user is in a community:

  • Chat with a customer service agent live, if one available
  • If an agent is unavailable, quickly open a page to log a new case

The steps to achieving this are actually surprisingly simple, and can be tested through a brief tutorial with a new Developer Edition org. The high-level steps are:
  1. Enable Live Agent
  2. Create a Live Agent Deployment, copying the HTML code and pasting it into the community's custom HTML footer
  3. In the HTML footer, add a div with an inline style attribute to become the side tab
  4. Create a Live Agent Chat Button, copying the HTML code and pasting it into the side tab div
  5. Configure a new community to use the custom HTML footer, after uploading it

Tuesday, September 3, 2013

Listing Required Fields for an Object in Salesforce Using Apex Code

Sometimes it's desirable or necessary to get a list of all required fields for a particular Salesforce object, especially for subsequent processing in Apex. Instead of hard-coding this list, which is not sustainable or maintainable long-term, a better approach is to use Salesforce field describe results and the isNillable() method.

Below is sample code that demonstrates this approach, code that can be adapted for any standard or custom object.

Monday, September 2, 2013

Custom CSS for Chatter Communities

Chatter Communities allows an organization using Salesforce to quickly deploy a functional, branded portal experience for partners and customers. Communities conveniently allows for a custom HTML header and footer to be added to a community, but it appears that in the Summer '13 release of Salesforce there is no support for using merge fields or to easily pull in custom CSS styles into a community. If you're used to using the URLFOR() function with the apex:stylesheet element in Visualforce, you may feel like something's missing.

Without too much hacking, there are two HTML5-compliant ways to approach this problem in Summer '13:

<style scoped>...</style>

This approach is simple, and any styles defined should be applied to the div id="contentWrapper" element into which the community's HTML header and footer are inserted. The parent div pretty much includes all of the visual content on the page, which makes this approach fairly comprehensive in the scope of its effects.

JavaScript script to insert link elements

Typically in Visualforce, styles are applied through dynamic links to CSS stylesheets stored as static resources. However, to build that dynamic URL in static HTML requires manual construction based on knowledge of Salesforce's URL conventions.

A relative URL to a CSS stylesheet stored within a .zip file loaded as a static resource has the following components:
  • CommunityName: The keyword appended after ServerName, if applicable. This may be blank for a particular community.
  • ResourceNumber: A unique number assigned to a static resource by Salesforce
  • ResourceName: The name (case-sensitive) of the static resource
  • InsidePath: The path inside the .zip file to the CSS stylesheet
The full URL is then constructed by concatenating the following: '/' + CommunityName + '/resource/' + ResourceNumber + '/' + ResourceName + '/' + InsidePath

A few sample URL's are shown below:
  • /cirruscommunity/resource/1378136101000/CirrusStaticResource/styles/layout.css
  • /slalomcommunity/resource/1379138201002/SlalomStaticResource/css/common.css
ResourceNumber can be ascertained by opening the static resource and looking for the string of numbers in the "View file" link's URL. Right-clicking the "View file" link and copying the link address should easily grab the ResourceNumber for you.

Lastly, the following JavaScript script can be edited to add all of the stylesheets you want to the community.

<script type="text/javascript">
  function appendLinkToHead(path) {
    var link = document.createElement("link");
    link.setAttribute("rel", "stylesheet");
    link.setAttribute("type", "text/css");
    link.setAttribute("href", path);
   
    var head = document.getElementsByTagName("head")[0];
    head.appendChild(link);
  } // function appendCommunityLink(String)

  var communityName = "community";
  var resourceNo = "1378136101000";
  var resourceName = "CommunityResource";
 
  var resourcePath = "/" + communityName + "/resource/"
      + resourceNo + "/" + resourceName + "/";
 
  var stylesheets = [
      "library/css/brand.css",
      "library/css/layout.css",
      "library/css/reset.css"];

  for (var i = 0; i < stylesheets.length; i++)
    appendLinkToHead(resourcePath + stylesheets[i]);
</script>