{"revision":"c10276e953456835cdbb1f3a60d58ae1980be353","document":{"id":385,"path":"api-reference/developer-guides/r_run_ui_test_script_examples.md","title":"UI Test Script examples","bundle":null,"doc_type":null,"release":"australia","body":"\n# UI Test Script examples\n\nReference example scripts to use in a Run UI Test Script step.\n\nThese examples include:\n\n-   Element verification,\n-   filling and saving records,\n-   waiting for async conditions,\n-   impersonation,\n-   file uploads,\n-   step outputs,\n-   parameter values,\n-   and scoped queries.\n\n## Assert that a heading is visible on the current page\n\n```\nconst heading = screen.getByRole('heading', { name: 'My Application' });\nexpect(heading).toBeVisible();\n```\n\n## Navigate to a record, fill a field, and save\n\n```\nawait sn_atf.navigate('/incident.do?sys_id=-1');\n\n// Update Caller\nconst caller = screen.getByRole('searchbox', { name: 'Caller' });\nawait user.click(caller);\nawait user.type(caller, 'Abel Tuter');\nawait user.tab();\n\n// Update Short description\nconst short_desc = screen.getByRole('textbox', { name: 'Short description' });\nawait user.click(short_desc);\nawait user.type(short_desc, 'Cannot connect to VPN');\n\n// Click Submit\nawait sn_atf.delay(1000);\nconst [submitBtn] = screen.getAllByRole('button', { name: 'Submit' });\nawait user.click(submitBtn);\nawait waitFor(() => {\n  const numField = screen.getBySelector('[name=\"incident.number\"]');\n  expect(numField.value).toMatch(/^INC/);\n}, { timeout: 10000 });\n```\n\n## Test as an impersonated user\n\n```\n// Accepts a user_name or sys_id. The iframe reloads automatically.\n// The original session is always restored when the step ends.\nawait sn_atf.impersonate('beth.anglin');\nawait sn_atf.navigate('/now/sow/home');\nconst listTab = await screen.findByRole('tab', { name: 'List', timeout: 10000 });\nawait user.click(listTab);\nconst incidentItem = await screen.findByRole('treeitem', { name: 'Incidents', timeout: 10000 });\nexpect(incidentItem).toBeVisible();\n```\n\n## Upload an attachment to the current form\n\n```\n// Pass a sys_id to copy an existing attachment server-side (no file bytes transferred).\n// Pass a File object (from sn_atf.getAttachmentFile) to upload through REST.\nawait sn_atf.navigate('/incident.do?sys_id=' + steps('PREVIOUS_STEP_SYS_ID').record_id);\nawait sn_atf.upload(steps('PREVIOUS_STEP_SYS_ID').attachment_sys_id);\nawait screen.findByText('evidence.pdf');\n```\n\n## Wait for an async condition by using waitFor\n\n```\nawait sn_atf.navigate('/incident.do?sys_id=<sys_id>');\nawait screen.findByRole('heading', { name: /INC/ });\nconst [updateBtn] = screen.getAllByRole('button', { name: 'Update' });\nawait waitFor(\n  () => expect(updateBtn).toBeEnabled(),\n  { timeout: 10000 }\n);\n```\n\n## Access step outputs and parameter values\n\n```\n// steps() retrieves output variables from a prior step by its sys_id.\n// params() retrieves parameter values when running a parameterized test.\n// Both support dotwalking for reference fields, for example\n// steps('...').assigned_to.department.name.\n// Use == or String() for comparisons — not ===.\nconst dept = String(steps('PREVIOUS_STEP_SYS_ID').assigned_to.department.name);\nconst expected = String(params('expected_department'));\nexpect(dept == expected).toBe(true);\n```\n\n**Note:**\n\n`steps(SYS_ID)` takes the sys\\_id of the step record, not the step result. Find it in the URL when you open the step record.\n\n## Verify an element on a classic form\n\n```\nawait sn_atf.navigate('/incident.do?sys_id=<sys_id>');\nconst heading = await screen.findByRole('heading', { name: /INC/ });\nexpect(heading).toBeVisible();\nconst shortDesc = screen.getByRole('textbox', { name: 'Short description' });\nexpect(shortDesc).toBeVisible();\n```\n\n## Navigate to a record, fill a field, and save\n\n```\nawait sn_atf.navigate('/incident.do?sys_id=<sys_id>');\nawait screen.findByRole('heading', { name: /INC/ });\nconst shortDesc = screen.getByRole('textbox', { name: 'Short description' });\nawait user.tripleClick(shortDesc);\nawait user.type(shortDesc, 'Updated by ATF');\nconst [updateBtn] = screen.getAllByRole('button', { name: 'Update' });\nawait user.click(updateBtn);\nawait screen.findByRole('heading', { name: /INC/ });\n```\n\n**Note:**\n\nOn classic forms, `findByLabelText` can throw a \"found multiple elements\" error because ServiceNow uses both `<label for>` and `aria-labelledby` associations at the same time. Prefer `getByRole('textbox', { name: '...' })` for text inputs, or `getByRole('searchbox', { name: '...' })` for reference fields. Classic forms also render every action button — Submit, Update, Delete — in both the header and the footer. Use `getAllByRole` and destructure to take the first one.\n\n## Wait for an async condition\n\nUse `waitFor` to poll a condition that is not simply a new element appearing. The callback is retried until it stops throwing or the timeout expires.\n\n```\nawait sn_atf.navigate('/incident.do?sys_id=<sys_id>');\nawait screen.findByRole('heading', { name: /INC/ });\nconst [updateBtn] = screen.getAllByRole('button', { name: 'Update' });\nawait waitFor(\n  () => expect(updateBtn).toBeEnabled(),\n  { timeout: 10000 }\n);\n```\n\n## Test as an impersonated user\n\n```\nawait sn_atf.impersonate('beth.anglin');\nawait sn_atf.navigate('/now/sow/home');\nconst listTab = await screen.findByRole('tab', { name: 'List', timeout: 10000 });\nawait user.click(listTab);\nconst incidentItem = await screen.findByRole('treeitem', { name: 'Incidents', timeout: 10000 });\nexpect(incidentItem).toBeVisible();\n```\n\n## Upload an attachment\n\n```\n// Copy an existing attachment to the current form (no file bytes transferred)\nawait sn_atf.navigate('/incident.do?sys_id=<sys_id>');\nawait sn_atf.upload('<source_attachment_sys_id>');\nawait screen.findByText('<file_name>;);\n```\n\n## Upload to a Workspace record\n\n```\nawait sn_atf.navigate('/now/sow/record/incident/<sys_id>');\nconst result = await sn_atf.uploadInWS('<source_attachment_sys_id>');\nexpect(result.name).toBe('evidence.pdf');\n```\n\n## Use step outputs with dotwalking\n\n```\n// steps(<step_sys_id>) — use the sys_id shown in the step record's URL\nconst assigneeDept = String(steps('abc123def456abc123def456abc12345').assigned_to.department.name);\nexpect(assigneeDept).toBe('IT');\n```\n\n## Use parameter set values\n\n```\n// In a parameterized test, read values from the active parameter row\nawait sn_atf.navigate('/incident.do?sys_id=-1');\nconst shortDesc = screen.getByRole('textbox', { name: 'Short description' });\nawait user.type(shortDesc, String(params('description')));\nconst [submitBtn] = screen.getAllByRole('button', { name: 'Submit' });\nawait user.click(submitBtn);\nawait waitFor(() => {\n  const numField = screen.getBySelector('[name=\"incident.number\"]');\n  expect(numField.value).toMatch(/^INC/);\n}, { timeout: 10000 });\n```\n\n## Use within to scope queries\n\n```\n// Scope queries to a specific section of the page to avoid ambiguous matches\nconst form = screen.getBySelector('form');\nconst shortDesc = within(form).getByRole('textbox', { name: 'Short description' });\nexpect(shortDesc).toBeVisible();\n```\n\n## Find the visible instance of a duplicated element\n\n```\n// The page renders two elements with the same text; find the visible one\nconst matches = await screen.findAllByText('Number');\nconst label = matches.find(el => isVisible(el));\nexpect(label).toBeTruthy();\n```\n\n"}}