Monday, March 23, 2015

Useful Visualforce Actions for any object

You may have come across a case where you need to create custom links in a Visualforce page to create, view edit any object or a link to open a object list page. Also, When you click on Cancel button from Create, View or edit pages it will automatically taken you back to the Originated page.

Here are the quick snippets for the same.

Create an Object: 

You can replace Contact with any other object.

<!-- Create New Contact Action -->
<apex:outputLink value="{!URLFOR($Action.Contact.NewContact)}">
Create a New Contact
</apex:outputLink>

<!-- Create New Contact Action -->
<apex:outputLink value="{!URLFOR($Action.CustomObject__c.NewCustomObject__c)}">
Create a New Custom Object
</apex:outputLink>

View an Object: 

<apex:outputLink value="{!URLFOR($Action.Contact.View, '003G0000016qPH5')}">
    Contact1
</apex:outputLink>

<apex:outputLink value="{!URLFOR($Action.CustomObject__c.View, 'a00900000016iUl')}">
CustomObject__c Record
</apex:outputLink>

Edit an Object: 

<apex:outputLink value="{!URLFOR($Action.Contact.Edit, '003G0000016qPH5')}">
    Edit Contact1
</apex:outputLink>

<apex:outputLink value="{!URLFOR($Action.CustomObject__c.Edit, 'a00900000016iUl')}">
CustomObject__c Record
</apex:outputLink>

Go to Object List Page: 

<!-- For Standard Object like Contact -->
<apex:outputLink value="{!URLFOR($Action.Contact.List,  $ObjectType.Contact)}">
Contact List
</apex:outputLink>

<!-- For Custom Object -->
<apex:outputLink value="{!URLFOR($Action.CustomObject__c.List,  $ObjectType.CustomObject__c)}">
CustomObject__c List
</apex:outputLink>

Friday, March 20, 2015

Creating an sObject Dynamically by passing an object type


The one liner code to create any type of sObject Dynamically - Replace/pass ObjectType:

sObject sObj = Schema.getGlobalDescribe().get(ObjectType).newSObject() ;
More formal implementation:

public class UndefinedSObjectTypeException extends Exception {}

// typeName must be a valid API name (i.e. custom objects should be suffixed with "__c"):
public static SObject newSObject(String typeName) {
    Schema.SObjectType targetType = Schema.getGlobalDescribe().get(typeName);
    if (targetType == null) {
        // calling code should usually handle this exception:
        throw new UndefinedSObjectTypeException('The requested SObject type [' + typeName + 
                '] cannot be constructed; it is not configured on this org.');
    }
    // SObjects offer the only way in Apex to instantiate an object with a type determined at 
    // runtime -- you can optionally pass an Id argument to instantiate an SObject for an 
    // existing record:
    return targetType.newSObject();
}

public static SObject newOpptyTeamMember() {
    return newSObject('OpptyTeamMember');
}

System.debug('Created new instance of: ' + newOpptyTeamMember().getSObjectType());

Thursday, March 6, 2014

Testing Salesforce1 applications using browser

Testing Salesforce1 applications using browser



Salesforce1 platform first released at Dreamforce 13, is wonderful and will open up a whole new world of functionality to Salesforce to be used from the mobile devices. Its very easy to add apps/menus to the Salesforce1 (Checkout some of the coolest features) platform but how about testing? Salesforce 1 application requires Latest versions of Android/iOS operating systems in the mobile devices to showcase the capabilities of the new platform.

To operate Salesforce1 app correctly, your mobile device need to run the following latest version of Android/iOS:
  • Android - Jelly Bean 4.2 Operating System or higher
  • iOS - iOS 6.0 Operating System or higher 
Most of the existing mobile devices with Android/iOS OS devices are running the older versions of operating systems. As a result, when you download and install the Salesforce1 application, you will receive a slimmed down version of Salesforce1 similar to the original Chatter Mobile app. If this is the case, we will not be able to test the latest functionality of Salesforce1.

The good news is, you can test Salesforce1 app without a mobile device and using Google Chrome browser (may be other browser as well, I've tested with Chrome).

The following two URLs will be very useful in accomplishing the testing task.

1) https://<instancename>.salesforce.com/one/one.app
2) https://<instancename>.salesforce.com/one/admin.app

For example, go to https://login.salesforce.com and login to your Salesforce Organization (assuming that Salesforce1 is already enabled), When you are on the Home page the URL will be something like https://na15.salesforce.com/home/home.jsp. Replace/home/home.jsp with /one/one.app for enduser app or /one/admin.app for admin app. So your URL will be similar to https://na15.salesforce.com/one/one.app or https://na15.salesforce.com/one/admin.app

Screenshot of /one/one.app

     
       

Screenshot of /one/admin.app

         

The main benefits of this URLs are:

  • Testing – you can test the functionality and the look & feel of the UI
  • Easy to demo - anywhere boardroom, classroom, presentation etc.
  • Documentation - take the screenshots and add it your documentation.

Monday, October 7, 2013

Writing Apex Test method for insert attachment





Salesforce.com makes it extremely easy to add attachments to any record either programmatically or from the UI. Writing a test case for the insert attachment is little tricky. Below are the quick apex code snippets for inserting an attachment for use in a Apex Text method. This would be useful for ensuring sufficient code coverage for the Apex classes that depend on insert attachment functionality. 

Version 1: with 1 argument (object Id of an object to which the attachment is added or the parentId of the attachment)

    /**
     * test method for add attachment to any object by passing the object Id
     */
    private static void testAddAttachmentToObject(Id objectId) {
    Blob b = Blob.valueOf('Test Data');
   
    Attachment attachment = new Attachment();
    attachment.ParentId = objectId;
    attachment.Name = 'Test Attachment for Parent';
    attachment.Body = b;
   
    insert(attachment);

     List<Attachment> attachments=[select id, name from Attachment where parent.id=: objectId];
     System.assertEquals(1, attachments.size());
    }

Version 2: without any arguments

    /**
     * test method for add attachment to any object by creating an object 
     */
    private static void testAddAttachmentToObject() {

        Account acct = new Account(Name='Test Account'); 
       /*
            you should supply values for all mandatory fields 
            same way, you can create any other object
      */
        insert acct;

     Blob b = Blob.valueOf('Test Data');
      
     Attachment attachment = new Attachment();
     attachment.ParentId = acct.Id;
     attachment.Name = 'Test Attachment for Parent';
     attachment.Body = b;
    
     insert(attachment);

     List<Attachment> attachments=[select id, name from Attachment where parent.id=: acct.Id];
     System.assertEquals(1, attachments.size());
    }

Hope this is helpful.

Thursday, August 22, 2013

Display Chatter in Visualforce pages

               Display Chatter Widget in VisualForce Pages

Chatter is a very useful widget available to collaborate with other users or a group of users in your Salesforce Org. It is visible (at the bottom corner of the window on right hand side) in all standard Salesforce views. But it will not be visible on custom developed VisualForce pages by default. 

To enable it on VisualForce Pages you need to follow 2 steps.

1) change the default settings. 
    Go to Your Name-->Setup-->Customize-->Chatter-->Chat Settings
       You can see there two options
          1. Chat Settings.
          2. Visualforce Settings.
       Click on Edit & Check the box next to "Allow" under VisualForce Settings.  Click on Save.

2) Set Correct attributes to Visualforce Page <apex:page> tag. 

       You need to add "Showheader=ture" attrubute on the <apex:page> tag.
       If you don't want to show header but chatter widget must be shown, then you have to use two attributes.
           showheader=false
           showchat=true


Example 1:

  <apex:page standardController="Account" showHeader="true">
    <apex:form>
        <apex:pageBlock title="My Content" mode="edit">
            <apex:pageBlockButtons>
                <apex:commandButton action="{!save}" value="Save"/>
            </apex:pageBlockButtons>
            <apex:pageBlockSection title="My Content Section" columns="2">
                <apex:inputField value="{!account.name}"/>
                <apex:inputField value="{!account.site}"/>
                <apex:inputField value="{!account.type}"/>
                <apex:inputField value="{!account.accountNumber}"/>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Output of this page with chatter widget displaying @ the bottom right hand side corner of the window



Example 2:

<apex:page standardController="Account" showHeader="false" showChat="true">
    <apex:form>
        <apex:pageBlock title="My Content" mode="edit">
            <apex:pageBlockButtons>
                <apex:commandButton action="{!save}" value="Save"/>
            </apex:pageBlockButtons>
            <apex:pageBlockSection title="My Content Section" columns="2">
                <apex:inputField value="{!account.name}"/>
                <apex:inputField value="{!account.site}"/>
                <apex:inputField value="{!account.type}"/>
                <apex:inputField value="{!account.accountNumber}"/>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Output of this page with chatter widget displaying @ the bottom right hand side corner of the window



To prevent the chat widget from displaying on a specific Visualforce page, do any of the following:
  • Turn off the Salesforce tab header on your page by setting <apex:page showHeader=”false”>.
  • Set the page contentType to something other than text/html, for example, <apex:page contentType="text/plain">.


Monday, July 8, 2013

Apex Compile Error: Test methods must be in test classes

         Apex Compile Error: Test methods must be in test classes


            Have you ever got an error "Error: Compile Error: Test methods must be in test classes at line 37 column 28" while saving an Apex Class? and wondered why is it an error? It used to work without any error & now, it is not working! Nothing to worry, this is an update starting from Summer '13 release. Here is an excerpt from the release notes:

Test Methods Defined in Test Classes:


Starting in Summer ‘13, test methods can be defined only in test classes (classes annotated with @isTest). You can no longer add a test method in a non-test class. This change applies to new Apex code saved using Salesforce.com API version 28.0 and later. Apex code saved using earlier API versions isn’t affected. 

This change is in line with the Apex coding best practice of including test methods in test classes. Test classes don’t count toward your organization’s code size limit, so separating the test code from the product code enables you to write more Apex code. Also, Apex testing will be enhanced in future releases and this is a prerequisite for those planned enhancements.

Lets take an example TestController class (Prior to Salesforce.com API Version 28.0) it was allowed to have the test methods also in the same class as shown bellow. 


//This class will give Compilation error "Test methods must be in test classes at line 25 column 28"  
public class TestController { //Declarations private Integer inventoryCount = 100; // Instance method public String DisplayStatus() { String status = 'Current inventory status: ' + inventoryCount + ' records.'; System.debug(LoggingLevel.INFO, status); return status; } // Static method public static Id InsertAccount(String aName, String bCity) { Account a = new Account(Name=aName, BillingCity=bCity); insert a; return a.Id; } /* *Unit test methods **/ static testmethod void testDisplayStatus() { // To call the instance method, you must first create an instance of the class. TestController m = new TestController(); String s = m.DisplayStatus(); // Verify status message System.assertNotEquals(null, s); } static testmethod void testInsertRecord() { // Call the static method Id accountID = TestController.InsertRecord('Acme','New York'); // Verify record got inserted System.assert(accountID != null); Account a = [SELECT Name,BillingCity FROM Account WHERE Id=:accountID]; System.assertEquals('Acme',a.Name); System.assertEquals('New York',a.BillingCity); } }

We can resolve this compilation error by moving all the test methods to new Test class "TestContollerTest.cls"

1. Create a new (test) class & name it "TestContollerTest". This class should have @isTest annotation to indicate this is a test class
2. Remove all methods from the Original class and add (Cut & Paste) them in the new Test class. (Note: if you have used keywords like "this" to reference the static variables and/or methods you should remove those references. For e.g.: this.<methodName> to <className>.<methodName> etc.)

The following example shows how to add test methods in a separate test class, TestControllerTest for the main class TestController.

public class TestController { //Declarations private Integer inventoryCount = 100; // Instance method public String DisplayStatus() { String status = 'Current inventory status: ' + inventoryCount + ' records.'; System.debug(LoggingLevel.INFO, status); return status; } // Static method public static Id InsertAccount(String aName, String bCity) { Account a = new Account(Name=aName, BillingCity=bCity); insert a; return a.Id; } }

@isTest private class TestControllerTest { static testmethod void testDisplayStatus() { // To call the instance method, you must first create an instance of the class. TestController m = new TestController(); String s = m.DisplayStatus(); // Verify status message System.assertNotEquals(null, s); } static testmethod void testInsertAccount() { // Call the static method Id accountID = TestController.InsertAccount('Acme','New York'); // Verify record got inserted System.assert(accountID != null); Account a = [SELECT Name,BillingCity FROM Account WHERE Id=:accountID]; System.assertEquals('Acme',a.Name); System.assertEquals('New York',a.BillingCity); } }

Friday, June 28, 2013

Introduction to new Visualforce tag



Introduction to new VisualForce Tag support:clickToDial

Summer ’13 introduced a new computer-telephony integration (CTI) Visualforce component—support:clickToDial. The support:clickToDial component lets you add a phone field to custom Visualforce detail and edit pages. When users in organizations with Open CTI or Salesforce CRM Call Center click on the phone field, the phone number is dialed automatically and connects to the SoftPhone. Use this to, for example, specify which phone fields on custom pages users can click to automatically call customers.

The following examples will guide you through the usage of the new CTI tag.

Example1: Using it in the pageblocktable with in <apex:column> tag:


<apex:page standardController="Account">

    <apex:includeScript value="/support/console/24.0/integration.js"/> <!-- you need to include this in your page for the new tag to work -->
    <apex:pageBlock title="My Content">

        <apex:pageBlockTable value="{!account.Contacts}" var="item">

            <apex:column value="{!item.name}"/> 
            <apex:column value="{!item.Title}" />
            <apex:column value="{!item.Email}" />
            <apex:column headerValue="Phone"> <support:clickToDial number="{!item.Phone}" entityId="{!item.Id}" /> </apex:column>
            <apex:column value="{!item.Phone}" /> <!-- this field is added only to show the difference -->

        </apex:pageBlockTable> 

    </apex:pageBlock> 

</apex:page>

How to run the code:

This page uses Account Standard Controller & shows the list of contacts of the account in the pageBlock Table. Copy & paste the above code into a VisualForce page named Test1. You can test the page by opening it in a browser as https://c.<na1>.visual.force.com/apex/Test1?Id=<AccountId>

Example2: Using it in a details page :

I have tried using it with <apex:outputField>, but was not successful.


<apex:page standardController="Account" tabStyle="Account">

    <apex:includeScript value="/support/console/24.0/integration.js"/><!-- you need to include this in your page for the new tag to work -->
    
    <apex:pageBlock >
        <apex:pageBlockSection title="Account Information">
            <apex:outputField value="{!account.name}"/>             
            <apex:outputField value="{!account.industry}"/>
            <!-- may be we need to apply CSS to align this properly -->
            Phone: <support:clickToDial number="{!account.phone}" entityId="{!account.Id}" />
            <apex:outputLabel value="Phone"><support:clickToDial number="{!account.phone}" entityId="{!account.Id}" /> </apex:outputLabel>
        </apex:pageBlockSection>
    </apex:pageBlock>

</apex:page>


How to run the code:

This page uses Account Standard Controller & shows the details the account in the pageBlock. Copy & paste the above code into a VisualForce page named Test2. You can test the page by opening it in a browser as https://c.<na1>.visual.force.com/apex/Test2?Id=<AccountId>

Hope this helps. Happy experimenting with support:clickToDial. I'll keep posting if I find any other successful usage of support:clickToDial.