[{"data":1,"prerenderedAt":466},["ShallowReactive",2],{"SiteFooter_cLEacilcm59lTjFJjLY6mXNWLL0ETtzOIiZwIHgDpy0":3,"doc-\u002Fdocs\u002Frecording\u002Fpractice":17,"docs-nav":334,"nav-compare":452,"editor-1ym9xww":462,"editor-z7s928":464},["Island",4],{"key":5,"result":6},"SiteFooter_cLEacilcm59lTjFJjLY6mXNWLL0ETtzOIiZwIHgDpy0",{"head":7},{"style":8},[9,11,13,15],{"innerHTML":10},".site-footer[data-v-8bb1d4ae]{border-top:1px solid var(--line);background:var(--chrome);padding:var(--sp-8) var(--gutter) var(--sp-10);gap:var(--sp-6);flex-direction:column;display:flex}.links[data-v-8bb1d4ae]{gap:var(--sp-4);grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));max-width:62rem;display:grid}.links a[data-v-8bb1d4ae]{align-items:flex-start;gap:var(--sp-3);padding:var(--sp-3);border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--panel);color:var(--ink);border-bottom:1px solid var(--line);display:flex}.links a[data-v-8bb1d4ae]:focus-visible,.links a[data-v-8bb1d4ae]:hover{border-color:var(--line-strong)}.links[data-v-8bb1d4ae] .mark,.links[data-v-8bb1d4ae] .rf-mark{width:1.35rem;height:1.35rem;color:var(--dim);flex:none;margin-top:.1rem}.links a[data-v-8bb1d4ae]:hover .mark,.links a[data-v-8bb1d4ae]:hover .rf-mark{color:var(--red)}.links span[data-v-8bb1d4ae]{flex-direction:column;gap:2px;min-width:0;display:flex}.links b[data-v-8bb1d4ae]{font-family:var(--font-display);font-size:.85rem;font-weight:400}.links small[data-v-8bb1d4ae]{color:var(--faint);font-size:.78rem}.colophon[data-v-8bb1d4ae]{color:var(--faint);margin:0;font-size:.75rem}@supports (corner-shape:bevel){.links a[data-v-8bb1d4ae]{corner-shape:bevel}}",{"innerHTML":12},".mark[data-v-cc0d96a5]{vertical-align:-.125em;flex:none;width:1em;height:1em}",{"innerHTML":14},".mark[data-v-26f5673d]{vertical-align:-.125em;flex:none;width:1em;height:1em}",{"innerHTML":16},".rf-mark[data-v-26317b3e]{fill:currentColor;stroke:none;flex:none}",{"id":18,"title":19,"body":20,"description":324,"extension":325,"meta":326,"navigation":327,"order":328,"path":329,"section":330,"seo":331,"stem":332,"__hash__":333},"docs\u002Fdocs\u002Frecording\u002Fpractice.md","Good practice and limits",{"type":21,"value":22,"toc":317},"minimark",[23,27,32,61,68,79,83,90,137,140,144,159,200,225,229,304,308,313],[24,25,26],"p",{},"The recorder gives you a first draft in seconds. Whether it becomes a keyword\nyour team keeps depends on a few habits.",[28,29,31],"h2",{"id":30},"record-small-keywords","Record small keywords",[24,33,34,35,39,40,43,44,47,48,51,52,56,57,60],{},"One keyword per step of your test design — ",[36,37,38],"code",{},"Log In",", ",[36,41,42],{},"Search Product",",\n",[36,45,46],{},"Add Product To Cart"," — not one keyword for the whole story. Small keywords are\neasy to name, easy to review and reusable in other tests. ",[36,49,50],{},"Record Keywords"," makes\nthis cheap: ",[53,54,55],"em",{},"Save",", move on, ",[53,58,59],{},"Record keyword",".",[24,62,63,67],{},[64,65,66],"strong",{},"Start from a known state."," Let the test do the setup — open the page, log in,\nload the data — and record from there. A keyword recorded from the middle of a\nhalf-finished manual session depends on whatever you did before.",[24,69,70,73,74,60],{},[64,71,72],{},"Check at the end."," Finish a keyword with an assertion from Playwright's\ntoolbar, so it proves it worked — see\n",[75,76,78],"a",{"href":77},"\u002Fdocs\u002Frecording\u002Fwhat-gets-recorded#assertions","Assertions",[28,80,82],{"id":81},"before-you-commit-a-recorded-keyword","Before you commit a recorded keyword",[24,84,85,86,89],{},"Every recorded keyword carries the tag ",[36,87,88],{},"recorded",". Treat it as \"not reviewed\nyet\", and remove the tag once you have checked:",[91,92,93,109,115,125,131],"ul",{},[94,95,96,99,100,104,105,60],"li",{},[64,97,98],{},"Values from the page."," Everything typed is recorded as typed — passwords\nincluded. Make secrets ",[75,101,103],{"href":102},"\u002Fdocs\u002Frecording\u002Farguments","arguments"," without a\ndefault, and pass them in as Robot Framework Secrets — see ",[75,106,108],{"href":107},"#secrets","below",[94,110,111,114],{},[64,112,113],{},"Selectors that will not last."," A name with a counter, a date or a generated\nid in it breaks on the next run. Shorten it, make the changing part an\nargument, or ask for a test id in the application.",[94,116,117,120,121,124],{},[64,118,119],{},"Placeholders."," An upload path starts with ",[36,122,123],{},"\u003Cdefine_path_to_file>"," until you\nfill it in.",[94,126,127,130],{},[64,128,129],{},"Notices."," A selector in Playwright-internal syntax, an action with no Browser\nkeyword — the toolbar told you while recording; the file shows the result.",[94,132,133,136],{},[64,134,135],{},"The name."," It should say what the keyword does for the test.",[24,138,139],{},"Run the keyword once on its own before you rely on it.",[28,141,143],{"id":142},"secrets","Secrets",[24,145,146,147,150,151,154,155,158],{},"Robot Framework 7.4 and newer have a ",[36,148,149],{},"Secret"," type: a value that never shows\nup in the log, created from the environment or a variable file. A recorded\n",[36,152,153],{},"Fill Text"," does not accept one, so change the password line to ",[36,156,157],{},"Fill Secret","\nand declare the argument as a Secret:",[160,161,166],"pre",{"className":162,"code":163,"language":164,"meta":165,"style":165},"language-robot shiki shiki-themes github-light github-dark","*** Keywords ***\nLog In As\n    [Arguments]    ${username}    ${password: Secret}\n    Fill Text      role=textbox[name*=\"username\"i]    ${username}\n    Fill Secret    role=textbox[name*=\"password\"i]    ${password}\n","robot","",[36,167,168,176,182,188,194],{"__ignoreMap":165},[169,170,173],"span",{"class":171,"line":172},"line",1,[169,174,175],{},"*** Keywords ***\n",[169,177,179],{"class":171,"line":178},2,[169,180,181],{},"Log In As\n",[169,183,185],{"class":171,"line":184},3,[169,186,187],{},"    [Arguments]    ${username}    ${password: Secret}\n",[169,189,191],{"class":171,"line":190},4,[169,192,193],{},"    Fill Text      role=textbox[name*=\"username\"i]    ${username}\n",[169,195,197],{"class":171,"line":196},5,[169,198,199],{},"    Fill Secret    role=textbox[name*=\"password\"i]    ${password}\n",[160,201,203],{"className":162,"code":202,"language":164,"meta":165,"style":165},"*** Test Cases ***\nLog In\n    VAR    ${password: Secret}    %{APP_PASSWORD}\n    Log In As    demo    ${password}\n",[36,204,205,210,215,220],{"__ignoreMap":165},[169,206,207],{"class":171,"line":172},[169,208,209],{},"*** Test Cases ***\n",[169,211,212],{"class":171,"line":178},[169,213,214],{},"Log In\n",[169,216,217],{"class":171,"line":184},[169,218,219],{},"    VAR    ${password: Secret}    %{APP_PASSWORD}\n",[169,221,222],{"class":171,"line":190},[169,223,224],{},"    Log In As    demo    ${password}\n",[28,226,228],{"id":227},"limits","Limits",[91,230,231,241,247,257,263,277,286,292,298],{},[94,232,233,236,237,240],{},[64,234,235],{},"A visible browser."," The recorder refuses a headless browser — nobody could\nuse the toolbar there. A browser attached with ",[36,238,239],{},"Connect To Browser"," counts as\nvisible.",[94,242,243,246],{},[64,244,245],{},"One browser context."," Only the context that was active when the recording\nstarted is recorded.",[94,248,249,252,253,256],{},[64,250,251],{},"Not everything is an action."," Hovering is not reported by Playwright and is\nnot recorded; add ",[36,254,255],{},"Hover"," by hand where a menu needs it.",[94,258,259,262],{},[64,260,261],{},"Playwright's toolbar stays."," It sits at the top centre of the page during\nthe session and cannot be hidden.",[94,264,265,268,269,272,273,276],{},[64,266,267],{},"Native modal dialogs"," (",[36,270,271],{},"showModal()",") make the toolbar inert until they are\nclosed. Other modals — the usual ",[36,274,275],{},"div"," with a backdrop — do not.",[94,278,279,282,283,60],{},[64,280,281],{},"Tabs without an id."," A tab that was open before the recording started, or\nthat you opened by hand, cannot be switched to by the keyword; an action there\nis recorded without ",[36,284,285],{},"Switch Page",[94,287,288,291],{},[64,289,290],{},"A few pages show no toolbar."," A page whose Content-Security-Policy allows\nonly the Trusted Types policies it names, and a document without a body, such\nas an SVG file. Pages that forbid inline styles or require Trusted Types —\nYouTube, Google sign-in — work.",[94,293,294,297],{},[64,295,296],{},"The page can see the toolbar."," Scripts on the pages of the context can read\nwhat is recorded and send toolbar commands. Record against applications you\ntrust, and review the result.",[94,299,300,303],{},[64,301,302],{},"Playwright's private recorder API."," Recording uses an interface Playwright\ndoes not publish, so a Playwright upgrade can affect it; Browser's tests check\nit with every upgrade.",[28,305,307],{"id":306},"when-something-goes-wrong","When something goes wrong",[309,310],"doc-table",{":head":311,":rows":312},"[\"You see\",\"Because\",\"Do\"]","[[\"`Recording needs a visible browser, but the active browser runs headless.`\",\"The browser was opened headless, the default.\",\"Open it with `New Browser` and `headless=False` before the page.\"],[\"No toolbar appears\",\"The page belongs to another browser context than the active one.\",\"`Switch Context` to the context you want to record, then start again.\"],[\"No toolbar on one page only\",\"Its Content-Security-Policy allows only the Trusted Types policies it names, or it is no HTML document, such as an SVG file.\",\"Record the steps on another page, or write them by hand.\"],[\"Clicks are not recorded\",\"The toolbar is picking a selector — its panel replaces the Keyword Calls.\",\"*Use* or *Cancel* the pick; recording goes on.\"],[\"A navigation has no `Go To`\",\"It followed a click, fill or key press within five seconds; it belongs to that action.\",\"Nothing — the recorded click navigates when the keyword runs.\"],[\"The name is rejected\",\"It exists in the file, was recorded in this session, shadows a keyword the suite can call, or is not a valid name.\",\"Choose another name; the dialog says which rule it broke.\"],[\"The recording ended by itself\",\"Nothing happened for `idle_timeout`.\",\"Raise `idle_timeout`; what was recorded is saved.\"],[\"`Cannot record into \u003Cfile>`\",\"The folder does not exist, or the file is read-only — checked before recording starts.\",\"Fix the path or the permission.\"],[\"`Could not write \u003Cfile>`\",\"The file became read-only or locked during the session, or is not valid UTF-8.\",\"Fix the file; the next action writes again. If it is still not writable at the end, the keyword fails and the recorded text is in the log.\"],[\"A selector with `internal:` in it\",\"The element has no role and is found by its `aria-label`; there is no public selector for that.\",\"It works as recorded. Prefer a test id if you can add one.\"]]",[314,315,316],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":165,"searchDepth":178,"depth":178,"links":318},[319,320,321,322,323],{"id":30,"depth":178,"text":31},{"id":81,"depth":178,"text":82},{"id":142,"depth":178,"text":143},{"id":227,"depth":178,"text":228},{"id":306,"depth":178,"text":307},"How to record keywords worth keeping, what to check before you commit one, what the recorder cannot do, and what to do when it goes wrong.","md",{},true,7,"\u002Fdocs\u002Frecording\u002Fpractice","recording",{"title":19,"description":324},"docs\u002Frecording\u002Fpractice","GeFi3POe0IOb6fuawY_RNcrQWxwiOxwHbqVNr0Vcp_M",[335,340,343,347,352,356,360,365,369,373,377,381,385,390,394,398,402,407,411,415,419,422,426,427,431,435,439,443,448],{"path":336,"title":337,"description":338,"section":339,"order":196},"\u002Fdocs\u002Fconcepts\u002Farchitecture","How Browser works","Python, a Node process and Playwright — what runs where, and where the files land.","concepts",{"path":341,"title":78,"description":342,"section":339,"order":184},"\u002Fdocs\u002Fconcepts\u002Fassertions","Almost every getter can assert, every assertion retries, and each return type allows different operators. The complete AssertionEngine reference.",{"path":344,"title":345,"description":346,"section":339,"order":172},"\u002Fdocs\u002Fconcepts\u002Fbrowser-context-page","Browser, context and page","The three layers Playwright is built on — and why a new context is the cheapest clean slate you will ever get.",{"path":348,"title":349,"description":350,"section":339,"order":351},"\u002Fdocs\u002Fconcepts\u002Flogging","Logging and debugging","Four places Browser tells you what happened — log.html, the Playwright log, traces and coverage.",6,{"path":353,"title":354,"description":355,"section":339,"order":178},"\u002Fdocs\u002Fconcepts\u002Fselectors","Finding elements","Which selector strategy to reach for, why the order matters, and how to chain across iframes and shadow DOM.",{"path":357,"title":358,"description":359,"section":339,"order":190},"\u002Fdocs\u002Fconcepts\u002Fwaiting","Waiting and promises","Most waiting is already done for you. This is the rest of it — Wait For Condition, and how to run keywords in parallel with Promise To.",{"path":361,"title":362,"description":363,"section":364,"order":196},"\u002Fdocs\u002Fextending\u002Fbrowser-as-a-base","Browser as a base","Own the Browser instance in your own library — what you get free, what one line restores, and what you build yourself.","extending",{"path":366,"title":367,"description":368,"section":364,"order":178},"\u002Fdocs\u002Fextending\u002Fjavascript-basics","Just enough JavaScript","The JavaScript you need to write extensions and Evaluate JavaScript, for people who write Python.",{"path":370,"title":371,"description":372,"section":364,"order":184},"\u002Fdocs\u002Fextending\u002Fjavascript-extensions","JavaScript extensions","Add keywords that run on the Node side with full Playwright access — and attach a debugger to them.",{"path":374,"title":375,"description":376,"section":364,"order":190},"\u002Fdocs\u002Fextending\u002Fpython-libraries","Your own Python library","Move business logic out of Robot Framework and keep Browser exactly as it is.",{"path":378,"title":379,"description":380,"section":364,"order":172},"\u002Fdocs\u002Fextending\u002Fpython-plugins","Python plugins","Add or replace keywords from Python, with access to the library's own API and to the Node side.",{"path":382,"title":383,"description":384,"section":364,"order":351},"\u002Fdocs\u002Fextending\u002Ftranslations","Translating keywords","Using a translation package to get keyword names and documentation in your language, and writing one for a language nobody has covered yet.",{"path":386,"title":387,"description":388,"section":389,"order":190},"\u002Fdocs\u002Fmobile\u002Fdevice-list","Every device descriptor","The full list of names Get Device accepts, with the viewport, pixel ratio, touch and engine each one sets — filterable and sortable.","mobile",{"path":391,"title":392,"description":393,"section":389,"order":178},"\u002Fdocs\u002Fmobile\u002Fdevices","Emulating a device","Device descriptors, what the six or seven properties they set actually change, and the one that emulation cannot give you.",{"path":395,"title":396,"description":397,"section":389,"order":172},"\u002Fdocs\u002Fmobile\u002Fresponsive","Testing responsive pages","Why a browser at a phone-sized viewport tests responsiveness properly, what emulation cannot tell you, and where real devices actually belong.",{"path":399,"title":400,"description":401,"section":389,"order":184},"\u002Fdocs\u002Fmobile\u002Ftouch","Touch, permissions and location","Tap and why it needs hasTouch, granting camera or notifications without a dialog, faking where the user is, and the gestures Browser has no keyword for.",{"path":403,"title":404,"description":405,"section":406,"order":184},"\u002Fdocs\u002Foperations\u002Fdocker","Running in Docker","The published Browser image, the four docker run flags that matter, and why running as root breaks Chromium.","operations",{"path":408,"title":409,"description":410,"section":406,"order":190},"\u002Fdocs\u002Foperations\u002Fdocker-images","Building your own image","Extending the published image with your dependencies, the version lock between Browser and Playwright, and using it as a CI job container.",{"path":412,"title":413,"description":414,"section":406,"order":178},"\u002Fdocs\u002Foperations\u002Fenvironment-variables","Environment variables","The variables that change how Browser behaves, which of them are safe in production, and the import parameters that should usually be preferred.",{"path":416,"title":417,"description":418,"section":406,"order":172},"\u002Fdocs\u002Foperations\u002Fnode-process","The Node process","Browser starts a Node process to talk to Playwright. What that costs, how to share one across parallel runs, and how to pass it Node flags.",{"path":102,"title":420,"description":421,"section":330,"order":184},"Keyword arguments","Turn a recorded value, part of it or part of a selector into an argument while you record — with or without a default, and everywhere it occurs.",{"path":423,"title":424,"description":425,"section":330,"order":196},"\u002Fdocs\u002Frecording\u002Ffiles","Where recorded keywords go","The suite file, a resource file or only the log; written live after every action; what the recorder changes in a file and what it never touches.",{"path":329,"title":19,"description":324,"section":330,"order":328},{"path":428,"title":429,"description":430,"section":330,"order":172},"\u002Fdocs\u002Frecording\u002Frecord-keywords","Recording keywords","Click through the page and get a reusable user keyword, written into your suite while you work. Record Keyword and Record Keywords in five minutes.",{"path":432,"title":433,"description":434,"section":330,"order":351},"\u002Fdocs\u002Frecording\u002Fselectors","Recording selectors","Pick an element in the live browser and get a selector for it — Playwright's or a CSS one, checked against the page while you edit it.",{"path":436,"title":437,"description":438,"section":330,"order":178},"\u002Fdocs\u002Frecording\u002Ftoolbar","The recorder toolbar","Name and start keywords, save, undo and discard them, end the session, and keep the toolbar out of the page's way.",{"path":440,"title":441,"description":442,"section":330,"order":190},"\u002Fdocs\u002Frecording\u002Fwhat-gets-recorded","What gets recorded","Which Browser keyword each action becomes, how popups, dialogs, downloads and uploads are handled, recording assertions, and the selectors the recorder writes.",{"path":444,"title":445,"description":446,"section":447,"order":178},"\u002Fdocs\u002Fstart\u002Fgetting-started","Getting started","Install Browser, write a first test, and run it.","start",{"path":449,"title":450,"description":451,"section":447,"order":172},"\u002Fdocs\u002Fstart\u002Finstallation","Installation","The two ways to install Browser — with a bundled Node.js runtime, or with one you provide yourself — and how to upgrade and remove each.",[453,456,459],{"to":454,"label":455},"\u002Fwhy\u002Fvs-cypress","vs Cypress",{"to":457,"label":458},"\u002Fwhy\u002Fvs-playwright","vs Playwright Test",{"to":460,"label":461},"\u002Fwhy\u002Fvs-seleniumlibrary","vs SeleniumLibrary",[463],"\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF6B5E;font-weight:bold\">*** Keywords ***\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">Log In As\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#C9A6E9\">    [Arguments]\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">    ${\u003C\u002Fspan>\u003Cspan style=\"color:#FFB86B\">username\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">}\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">    ${\u003C\u002Fspan>\u003Cspan style=\"color:#FFB86B\">password: Secret\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">    Fill Text\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\">      role=textbox[name*=\"username\"i]\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">    ${\u003C\u002Fspan>\u003Cspan style=\"color:#FFB86B\">username\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">    Fill Secret\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\">    role=textbox[name*=\"password\"i]\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">    ${\u003C\u002Fspan>\u003Cspan style=\"color:#FFB86B\">password\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">}\u003C\u002Fspan>\u003C\u002Fspan>",[465],"\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF6B5E;font-weight:bold\">*** Test Cases ***\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">Log In\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#C9A6E9\">    VAR\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">    ${\u003C\u002Fspan>\u003Cspan style=\"color:#FFB86B\">password: Secret\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">}\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">    %{\u003C\u002Fspan>\u003Cspan style=\"color:#FFB86B\">APP_PASSWORD}\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"line\">\u003Cspan style=\"color:#2BD9CC\">    Log In As\u003C\u002Fspan>\u003Cspan style=\"color:#E0D3A3\">    demo\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">    ${\u003C\u002Fspan>\u003Cspan style=\"color:#FFB86B\">password\u003C\u002Fspan>\u003Cspan style=\"color:#A9B4BA\">}\u003C\u002Fspan>\u003C\u002Fspan>",1793560509106]