Dynamically retrieving the approver user in ATF and impersonating them
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
2 hours ago
Hello community — I'm facing an issue with ATF impersonation and hope someone can point out what I might be missing.
Environment & context
I have an ATF test where:
Step 36 is a Record Query that successfully returns a sysapproval_approver record (I can see the approval record sys_id in Step 36 output).
Step 37 is a Run Server-side Script that should read the Step 36 output, query sysapproval_approver, extract the approver (a reference to sys_user), and return a record output in the format the Impersonate step expects:
outputs.record = { document_id: "<sys_user_sys_id>", table: "sys_user" }
What I expect to happen
Step 37 prepares outputs.record with the approver sys_user id.
Step 38 (Impersonate) is configured to use {{Step 37: Run Server Side Script.Record}} (dot-walk → Step 37 → Record → document_id) and should impersonate that user so the remaining ATF steps run in that user's context.
What actually happens
Step 37 executes successfully (no script error).
However, Step 38 fails with:
User to impersonate not specifiedIn Step 38 I selected the user via the dot-walk UI (Step 37 → Record → document_id). The Impersonate field shows that reference, but the step fails at runtime.
What I tried already
I made the Step 37 script robust so it detects either steps[36].first_record.document_id or steps[36].record_id (I log both).
I tried returning outputs.record as shown above.
I also tried returning an alternative name (outputs.user) and other shapes, but Impersonate only accepts a dot-walkable Record → document_id.
Here´s the code - Step 37 script (full) that I used
(function(outputs, steps, stepResult) {
try {
gs.info("ATF Step 37: starting - reading Step 36 outputs...");
var approvalRecordSysId = null;
if (steps[36] && steps[36].first_record && steps[36].first_record.document_id) {
approvalRecordSysId = steps[36].first_record.document_id;
gs.info("ATF Step 37 debug: found steps[36].first_record.document_id = " + approvalRecordSysId);
} else if (steps[36] && steps[36].record_id) {
approvalRecordSysId = steps[36].record_id;
gs.info("ATF Step 37 debug: found steps[36].record_id = " + approvalRecordSysId);
} else if (steps[36] && steps[36].first_record) {
approvalRecordSysId = steps[36].first_record;
gs.info("ATF Step 37 debug: found steps[36].first_record (fallback) = " + approvalRecordSysId);
}
if (!approvalRecordSysId) {
stepResult.setFailed("Step 37 failed: could not read approval record id from Step 36. Inspect Step 36 outputs.");
return;
}
var grApproval = new GlideRecord("sysapproval_approver");
if (!grApproval.get(approvalRecordSysId)) {
stepResult.setFailed("Step 37 failed: sysapproval_approver record not found for id: " + approvalRecordSysId);
return;
}
var approverSysId = grApproval.getValue("approver");
if (!approverSysId) {
stepResult.setFailed("Step 37 failed: 'approver' field is empty on sysapproval_approver record: " + approvalRecordSysId);
return;
}
gs.info("ATF Step 37 debug: approver sys_id = " + approverSysId);
outputs.record = {
document_id: approverSysId,
table: "sys_user"
};
outputs.record_id = approverSysId;
outputs.record_table = "sys_user";
stepResult.setOutputMessage("Step 37 succeeded: prepared outputs.record for sys_user " + approverSysId);
} catch (ex) {
stepResult.setFailed("Step 37 exception: " + ex.message);
}
})(outputs, steps, stepResult);
Important: If I manually enter the approver’s username in the Impersonate step, the test runs successfully until the end. This confirms that Step 36 is correct and is returning the sys_id of the approval record.
Here´s some prints that might me usefull.
Step 38 failed: User to impersonate not specified
Is the outputs.record = { document_id: "<sys_id>", table: "sys_user" } shape definitely the correct format for the ATF Impersonate step to consume?
Could there be a timing/serialization issue where the Impersonate step evaluates the dot-walk reference before the Run Script outputs are fully available? If so, any workaround?
Has anyone seen the Impersonate step return “User to impersonate not specified” even though the preceding Run Script produced outputs.record? If so, what fixed it?
Thank you in advance for any help or pointers. Any sample working snippet or a note about version-specific behavior would be very appreciated.
Kind regards,
Rafael