Language agnostic Salesforce Apex unit test

I was doing some work with packaging on Salesforce and used the dreamhouse-lwc repo as a foundation. When I was building package versions the Apex unit tests were failing as the SOQL queries is using WITH SECURITY_ENFORCED and the user running the queries did not have the right access. The solution was to update the unit test to create a user and assign the dreamhouse Permission Set but to create a user you need to set a Profile. Which one to pick? Easy – use the “Standard User” Profile which is easily accessible by SOQL:

SELECT Id FROM Profile WHERE Name='Standard User' LIMIT 1

This code failed however as the Profile couldn’t be found. It turned out to be because the scratch org created was in Danish so the Profile is called “Standard Bruger” instead. This could be solved by setting the language of the scratch org by using the language key in config/project-scratch-def.json but the repo maintainers didn’t want that. A more flexible and still language agnostic way was to query more intelligently for the Profile. The below SOQL query achieves the same result as above but without setting the org language.

SELECT Name, Id
FROM Profile
WHERE UserType = 'Standard' AND PermissionsPrivacyDataAccess = false AND PermissionsSubmitMacrosAllowed = true AND PermissionsMassInlineEdit = true LIMIT 1

Add language to Salesforce CLI scratch org definition from terminal

All my scratch orgs gets created with the user-language set to Danish which is a good guess but I cannot find anything in Setup that way. No Dev Hub setting I’ve found can change that but setting the language in the scratch org definition file will. That’s easily done from the terminal with jq.

cat config/project-scratch-def.json | jq '. += {"language": "en_US"}' > config/project-scratch-def-en_US.json

Video walkthru for the Salesforce Azure client_credentials Auth. Provider

Based on a number of comments I’ve added a video walkthru for the Azure Client Credentials Auth. Provider I have available on Github. The video is hosted on Youtube and besides a description of the elements used shows pushing the source to Salesforce, configuring the Auth. Provider in Salesforce as well as configuring the App Registration on Microsoft Azure.

See the post for the Auth. Provider (Custom Salesforce Auth. Provider for Microsoft Azure client_credentials flow) for a link to Github.

Deprecation and End Of Support for Platform API Legacy Versions

So this is finally happening. When I write finally it’s because I am sure this will lead to removing quite a lot of code in the Salesforce core application. With Summer 21 we are deprecating a bunch of API versions (see the release notes for more info) which means we will finally remove support for the API versions in Summer 22.

Below are the API versions that will be deprecated and ultimately removed:

SOAP AP: I7.0, 8.0, 9.0, 10.0, 11.0, 11.1, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0
REST API: 20.0
Bulk API: 16.0, 17.0, 18.0, 19.0, 20.0

Consider yourself notified… 🙂

Custom Salesforce Auth. Provider for Microsoft Azure client_credentials flow

When doing integrations from Salesforce you sometimes need to do this using single identity instead as in the context of the current user. Salesforce supports both through Named Credentials i.e. both working as the current user or as a Named Principal. Through the Named Credentials and Auth. Provider concepts from Salesforce you can setup a connection between Salesforce and an OAuth 2.0 enabled endpoint such as Microsoft Azure i.e. if needing the access the Microsoft Graph API. This can however be an issue as the target system (i.e. Microsoft Azure in this case) may not use a user that is able to login or you may not want to use a user license in the target system.

In this case you might want to use the client_credentials OAuth flow as that identifies the caller using a client_id and a client_secret instead of a user id. Unfortunately that OAuth flow type is not supported out-of-the-box with Salesforce. The reason is that the Auth. Providers in Salesforce usually deals with a user behind the keyboard. Due to this the OAuth 2.0 Auth. Provider flows was designed for a access_token / refresh_token World. This makes it impossible to use the built in capabilities for the client_credentials flow.

The solution is to write a custom Auth. Provider in Apex and use that from your Named Credential. To make this easier I’ve already implemented this for you. The code is available on Github in my salesforce-azure-clientcredentials-authprovider repo. This implementation just plays along with the access_token / refresh_token requirements and just requests a new access_token using the client_credentials flow whenever a (new) access_token is needed and hence do not need a user behind the keyboard.

The README.md in the repo has instructions for installing and configuring the code in the org. Once deployed you can create an Auth. Provider and a Named Credential. Please note you also need to create an App Registration in Azure Active Directory with the required Application Permissions.

Remove all padding in a Salesforce Experience Cloud Site

Note to self. When building non-LWR based Experience Cloud sites there is some padding that needs to be removed to make your site fill the entire display port. Put the following CSS classed in custom CSS for the Site to remove it.

.cCenterPanel {
padding: 0px;
margin: 0px;
}
.contentRegion {
padding: 0 !important;
}

YMMV

Unable to force:source:push ExperienceBundle from API version 50.0 with API version 51.0

Yesterday I was trying to deploy some source including an Experience Cloud Site (using ExperienceBundle) created with API version 50.0 to a scratch org but it failed when I updated the API version to 51.0 in sfdx-project.json . Deploying with API version 50.0 worked just fine. The deploy (w/ API version 51.0) failed with the following message:

Error  force-app/main/default/experiences/Digital_Capability_Assessment_Aura1.site-meta.xml  You seem to be missing the property configurationTags in Digital_Capability_Assessment_Aura1/routes/register.json with component ID: f7c5ea49-0bde-4848-a72f-82ace4ea6760

And the error message was right – that key is not in the file but that’s was also true for some of the other Experience Cloud files. Deploying with API version 50.0 and trying to pull with API version 51.0 didn’t change any source. Clever people told me that this was expected as nothing changed in the org (regardless of a publish or similar).

Solution was to deploy with force:source:push with API version 50.0 and then do a force:source:retrieve specifying API version 51.0 on the command line. Then afterwards toggle the API version in sfdx-project.json.

sfdx force:source:retrieve -u dca_scratch_comm -a 51.0 -m ExperienceBundle