Let’s build a status page with Salesforce’s Force.com Sites

Disclaimer: Force.com sites might not be the best way to develop a status page because of the daily and monthly allocations. However, I think its a nice Visualforce and site development exercise. And since the page is public and we need the guest profile, we also deal a little bit with sharing and visibility.

At the end we should have something like this in our page:


Salesforce has a small snippet on how to add a Lightning component to a Visualforce page (here), but we want to use Lightning Out to add a component to a public website. To allow guest user access, there’s a catch: we need to implement the ltng:allowGuestAccess interface in our app:

<aura:application access="GLOBAL" extends="ltng:outApp" implements="ltng:allowGuestAccess">
    <aura:dependency resource="c:statusComponent"/>
</aura:application>

For starters, thinking about the data structure of a simple status page like this one, we have three obvious objects to deal with: the systems listed, the incidents (per system) and the incidents updates. We can assume there’s a master-detail relationship between a system and an incident, and another between the incident and the incident update. The system has a current status (available, with a performance degradation or unavailable), while the incidents and their updates can change this status.

No mystery regarding how the page works. It is a Visualforce which uses Lightning Out, which implements a Lightning App that has a component as dependency. This is a composed component, which means it uses another components to compose the view.

The main status component (statusComponent) queries the systems and instantiates a component (systemStatus) that is dedicated to show info regarding a specific system. This system status component queries the unresolved incidents of its system and instantiates the systemIncident component, which does pretty much the same thing to a systemIncidentUpdate component.


Now talking a little about the back-end of things: it would be nice if the user responsible for updating the incidents statuses could update the system and the incident statuses. This way, if an incident is resolved, the site can be instantly updated.


The source code can be found here: https://github.com/renatoliveira/force-com-status-page.

I’d like to list all the test classes in my Salesforce org, can I do that?

Yes, we can! But it is not as easy as typing a command to return a pretty JSON list with all the classes names.

First of all, we can’t query the ApexClass table directly using the IsTestClass field as criteria, because it doesn’t exist. The second problem is that we have differences between managed and unmanaged classes. The later one’s code isn’t accessible, so we can’t just search for the @IsTest annotation.

What do we do, then? Turn into one of Salesforce’s APIs: The Tooling API. It provides us with data that is interesting for a developer developing things for developers. 

Fortunately the Salesforce CLI supports this API. So we can query the ApexClass table using the Tooling API. It can return an object that represents information about the queried class. For example, the following query:

sfdx force:data:soql:query --query "SELECT Id, SymbolTable FROM ApexClass WHERE Name = 'SObjectUnitOfWorkTest'" --usetoolingapi --targetusername playground --json

It queries the SObjectUnitOfWorkTest class and its symbol table using the Tooling API for that. Don’t mind the “playground” thing, that’s what I call my personal dev org.

The output of this command should be a JSON of considerable size (depending on the size of the class as well). But we are interested in just one attribute of the response: the “methods” attribute of the SymbolTable attribute. This attribute contains a list of the methods in the class we queried, and the output is something like this:

"methods": [
  {
    "annotations": [
      {
        "name": "IsTest"
      }
    ],
    "location": {
      "column": 25,
      "line": 39
    },
    "modifiers": [
      "private",
      "static",
      "testMethod"
    ],
    "name": "test_inserts",
    "parameters": [],
    "references": [],
    "returnType": "void",
    "type": null
  },
  // and more methods below, if the class contains more than one method
]

Using a command line tool like jq we can easily extract the methods annotated with IsTest using a command like this:

cat test.apxc | jq '.result.records[0].SymbolTable.methods | .[] | select((.annotations | length > 0) and .annotations[0].name == "IsTest")'

If you just want the methods’ names, the command differs just a bit at the end:

cat test.apxc | jq '.result.records[0].SymbolTable.methods | .[] | select((.annotations | length > 0) and .annotations[0].name == "IsTest") | .name'

For the class I used before, I get the following output:

? cat test.apxc | jq '.result.records[0].SymbolTable.methods | .[] | select((.annotations | length > 0) and .annotations[0].name == "IsTest") | .name'
"test_inserts"
"test_updates"
"testUnitOfWorkEmail"
"testDerivedUnitOfWork_CommitDMLFail"
"testDerivedUnitOfWork_CommitDoWorkFail"

And that’s it! A not so easy way of extracting the test methods of a single class. But at least it can be automated.

But what if I want to get the methods for multiple classes at once?

It might take a while to run the query, but Salesforce definitely delivers a result to your terminal. Then the biggest issue is parsing the JSON result. I don’t know how to pretty parse and/or reshape the output using jq alone, but it definitely seems possible! And I’m sure that one can use a scripting language (like Python or PowerShell) to automate this.