{"revision":"c10276e953456835cdbb1f3a60d58ae1980be353","document":{"id":390,"path":"api-reference/developer-guides/r_run_ui_test_script_sn_atf.md","title":null,"bundle":null,"doc_type":null,"release":null,"body":"---\ntitle: sn\\_atf — utility APIs\ndescription: The sn\\_atf API provides utility methods for a Run UI Test Script step: navigation, page evaluation, impersonation, file uploads, and shadow-DOM utilities.\nlocale: en-US\ncanonical_url: https://www.servicenow.com/docs/r/australia/api-reference/developer-guides/r\\_run\\_ui\\_test\\_script\\_sn\\_atf.html\nrelease: australia\nproduct: Developer Guides\nclassification: developer-guides\ntopic_type: reference\nlast_updated: \"2026-06-25\"\nreading_time_minutes: 3\nkeywords: [sn\\_atf, navigate, evaluate, impersonate, upload, Run UI Test Script]\nbreadcrumb: [Run UI Test Script Developer Guide, Developer guides, API implementation and reference]\n---\n\n# sn\\_atf — utility APIs\n\nThe sn\\_atf API provides utility methods for a **Run UI Test Script** step: navigation, page evaluation, impersonation, file uploads, and shadow-DOM utilities.\n\n## Navigation\n\n|Method|Description|\n|------|-----------|\n|sn\\_atf.navigate\\(url\\)|Navigate the tested iframe to a URL, relative or absolute. Awaits full page load.|\n|sn\\_atf.reload\\(\\)|Reload the current page in the iframe.|\n|sn\\_atf.goBack\\(\\)|Go to the previous page in the navigation history managed by this step.|\n|sn\\_atf.goForward\\(\\)|Go to the next page in the navigation history.|\n\nAll navigation methods return Promises and resolve when the `load` event of the new page fires. The `screen` object automatically retargets to the new document body after navigation.\n\n```\nawait sn_atf.navigate('/now/nav/ui/classic/params/target/incident_list.do');\nconst row = await screen.findByRole('row', { name: /INC0001234/ });\nawait user.click(row);\nawait screen.findByRole('heading', { name: /INC0001234/ });\n```\n\n## sn\\_atf.evaluate\\(fn, arg?\\)\n\nRuns `fn` inside the JavaScript realm of the tested iframe and returns a Promise with the result. This method mirrors the `page.evaluate()` contract in Playwright.\n\n```\n// Read a value from the iframe's context\nconst title = await sn_atf.evaluate(() => document.title);\n\n// Pass an argument into the iframe context\nconst attr = await sn_atf.evaluate((sel) => document.querySelector(sel)?.dataset.state, '[data-testid=\"status\"]');\n```\n\nThe function is serialized through `.toString()` and evaluated in the iframe, so it can't close over variables from the test script scope. Pass data through the `arg` parameter instead.\n\n`fn` can return a plain value or a Promise. When it returns a Promise, `evaluate` awaits it.\n\n## sn\\_atf.impersonate\\(userId\\)\n\nImpersonates a user for the remainder of the step. Accepts a `sys_id` or `user_name`. The iframe reloads automatically after impersonation succeeds, and the original session is always restored when the step ends, whether the step passes, fails, or times out.\n\n```\nawait sn_atf.impersonate('fred.luddy');\n// Or by sys_id:\nawait sn_atf.impersonate('6816f79cc0a8016401c5a33be04be441');\n\n// Now interact as that user\nconst btn = await screen.findByRole('button', { name: 'Create Incident' });\nexpect(btn).toBeEnabled();\n```\n\nImpersonation requires the ATF runner session to have the `impersonator` role.\n\n## File uploads\n\n|Method|Signature|Description|\n|------|---------|-----------|\n|`sn_atf.upload(source)`|`upload(sysId | File)`|Upload to the current classic ServiceNow form. Pass a `sys_attachment` sys\\_id to copy server-side, with no bytes transferred, or pass a `File` object to upload through REST.|\n|`sn_atf.uploadInWS(source, table?, sysId?)`|`uploadInWS(sysId | File, tableName?, recordSysId?)`|Upload to a Workspace record. `table` and `sysId` are inferred from the current URL when omitted.|\n|`sn_atf.uploadInSP(source, table?, sysId?)`|`uploadInSP(sysId | File, tableName?, recordSysId?)`|Upload to a Service Portal form record. `table` and `sysId` are read from the URL query parameters when omitted.|\n|`sn_atf.uploadInSCVariable(source, variableName)`|`uploadInSCVariable(sysId | File, variableName)`|Upload to a service catalog attachment variable in the classic catalog. `variableName` is the column name, for example `'proof_of_id'`.|\n|`sn_atf.uploadInSPVariable(source, variableName, opts?)`|`uploadInSPVariable(sysId | File, variableName, { timeout? })`|Upload to a Service Portal catalog attachment variable. `variableName` is the column name without the `sp_formfield_` prefix.|\n\nsn\\_atf.upload\\(\\) returns Promise&lt;void&gt;, not Promise&lt;\\{ sysId, name, size \\}&gt;. Only uploadInWS, uploadInSP, uploadInSCVariable, and uploadInSPVariable return \\{ sysId, name, size \\}.\n\n```\n// Copy an existing attachment to the current form (no bytes transferred)\nawait sn_atf.upload('a1b2c3d4e5f67890a1b2c3d4e5f67890');\n\n// Upload a File retrieved from another attachment\nconst file = await sn_atf.getAttachmentFile('a1b2c3d4e5f67890a1b2c3d4e5f67890');\nawait sn_atf.uploadInWS(file);\n```\n\n## sn\\_atf.getAttachmentFile\\(sysId\\)\n\nFetches the bytes of a `sys_attachment` record through the REST API and returns a `Promise<File>` with the correct name and content type. Use this method to read an attachment from one record and upload it to another.\n\n```\nconst file = await sn_atf.getAttachmentFile('a1b2c3d4e5f67890a1b2c3d4e5f67890');\nawait sn_atf.upload(file);\n```\n\n## DOM utilities\n\n|Method|Description|\n|------|-----------|\n|`sn_atf.querySelector(root, selector)`|Shadow-DOM-piercing `querySelector`. Finds the first element that matches `selector` under `root`, crossing shadow boundaries.|\n|`sn_atf.querySelectorAll(root, selector)`|Shadow-DOM-piercing `querySelectorAll`. Returns all matching elements.|\n|`sn_atf.getActiveElement(root?)`|Returns the currently focused element, piercing shadow roots and iframes.|\n|`sn_atf.waitForElementToBeRemoved(element, opts?)`|Waits until `element` is removed from the DOM. Resolves immediately if the element is already disconnected.|\n|`sn_atf.delay(ms)`|Returns a Promise that resolves after `ms` milliseconds. Prefer `waitFor` or `findBy*` for dynamic waits, and use `delay` only when a fixed pause is unavoidable.|\n\n"}}