Lightning Web Component for Dynamic SOQL Queries in Salesforce
The Query Viewer component includes an advanced “Run As” feature that allows administrators and privileged users to validate query results in the context of another user’s permissions. It supports two modes:
Both modes use System.runAs() in an @IsTest context, invoked via the Salesforce Tooling API. This is not a simple USER_MODE query — it is actual permission impersonation through a pre-compiled test class.
Named User flow:
JT_RunAsTestExecutor.executeAsUser() creates a JT_RunAsTest_Execution__c recordJT_RunAsTestEnqueuer calls Tooling API runTestsSynchronous → JT_GenericRunAsTestJT_GenericRunAsTest fetches the real User from the DB, calls System.runAs(realUser), and executes the queryPersona flow:
JT_RunAsTestExecutor.executeAsPersona() creates the execution record with Persona_Developer_Name__cJT_RunAsTestEnqueuer reads JT_PersonaConfig__mdt to decide which test class to invokeUser (inserted in @IsTest context, rolled back after), assigns Permission Sets, and calls System.runAs(syntheticUser)System.runAs() impersonation — respects FLS, CRUD, object access, and sharing rulesseeAllData=false option (Persona mode): validates access without requiring real data in orgSeeAllData=true is required when validating that a user sees real records (not just access errors)See_All_Data__c = falseThe Run As feature is available to users with:
Check permissions:
Boolean canUse = JT_QueryViewerController.canUseRunAs();
Test if a specific user can see certain records:
1. Select user: "Sales Rep - John Doe"
2. Execute query: SELECT Id, Name FROM Account
3. Result shows only accounts John has access to
Investigate why a user can’t see expected records:
1. User reports: "I can't see Account X"
2. Admin selects that user in Run As
3. Executes query to verify sharing rules
4. Identifies permission gap
Show different user perspectives:
1. Demo to stakeholders
2. Switch between user contexts
3. Demonstrate how permissions work
<div class="run-as-container">
<lightning-icon icon-name="utility:user"></lightning-icon>
Run As User (Advanced)
<lightning-combobox
label="Search User"
placeholder="Type to search users..."
oninput="{handleUserSearch}"
>
</lightning-combobox>
</div>
Removes the selected Run As user to return to normal execution.
canUseRunAs()@AuraEnabled(cacheable=true)
public static Boolean canUseRunAs()
Returns true if current user can use the Run As feature.
searchUsers(String searchTerm)@AuraEnabled(cacheable=true)
public static List<UserOption> searchUsers(String searchTerm)
Searches for users matching the search term.
executeQuery(String devName, String bindingsJson, String runAsUserId)@AuraEnabled
public static QueryResult executeQuery(String devName, String bindingsJson, String runAsUserId)
Executes query with optional Run As user validation.
// Query always uses USER_MODE
AccessLevel accessMode = enforceSecurity ? AccessLevel.USER_MODE : AccessLevel.SYSTEM_MODE;
return Database.queryWithBinds(
config.JT_BaseQuery__c,
bindings,
accessMode // <- Always respects security
);
System.runAs()For more comprehensive testing:
“You do not have permission to use the Run As feature”
“Selected user not found”
“Cannot run as inactive user”
E2E tests included:
npm run test:e2e
Tests cover:
Persona mode allows testing without a real named user. Instead, define an archetype in JT_PersonaConfig__mdt and the framework creates a synthetic user in the @IsTest context.
| Scenario | Recommendation |
|---|---|
| ISV org with no real QA users | ✅ Persona mode |
| Scarce user licenses | ✅ Persona mode |
| Validate FLS/CRUD only (no data needed) | ✅ Persona mode, See_All_Data__c = false |
| Validate real record visibility for a specific person | Named User mode |
| CI/CD permission regression tests | ✅ Persona mode |
Go to Setup → Custom Metadata Types → JT Persona Config → Manage Records and create a record:
| Field | Example | Description |
|---|---|---|
| Label | Sales Rep - Territory |
Display name in UI selector |
| DeveloperName | Sales_Rep_Territory |
API name |
| Profile API Name | Standard User |
Exact Profile Name from Setup |
| Permission Sets | Territory_Manager,Pipeline_Access |
Comma-separated PS API names |
| See All Data | false |
FLS/CRUD only; true = real data volume |
| Description | Sales rep with territory access |
Shown in combobox |
Governor Limit Note: Maximum 10 Permission Sets per persona recommended to stay within DML row limits in
@IsTestcontext.
The jtRunAsSection component now shows a mode toggle:
[ Specific User ] [ Persona ]
JT_PersonaConfig__mdt records in the combobox// Get persona options for LWC combobox
List<JT_RunAsTestExecutor.PersonaOption> options = JT_RunAsTestExecutor.getPersonaOptions();
// Execute as persona
JT_RunAsTestExecutor.TestExecutionResult result = JT_RunAsTestExecutor.executeAsPersona(
'Sales_Rep_Territory', // DeveloperName of JT_PersonaConfig__mdt
'Account_By_Name', // Config name
'{"name": "Acme"}' // Bindings JSON
);
See_All_Data__c |
Test class used | What is validated |
|---|---|---|
false |
JT_GenericPersonaTest (@IsTest(SeeAllData=false)) |
FLS, CRUD, object access only |
true |
JT_GenericRunAsTest (@IsTest(SeeAllData=true)) |
FLS, CRUD, access + real record count |
When seeAllData=false, a result of 0 records is considered a successful test (the query ran without access errors). This is ideal for ISV orgs where no data exists in the installation org.
The Run As feature gives administrators and ISV developers two complementary tools:
For questions or issues, please refer to the main project documentation or create an issue in the repository.