assert_
glossary ↓ downloads
cheatsheet · suite 03

Web fundamentals

every pattern from this suite, one pageCtrl+P prints it clean
CSS selectors
#login-button              by id (best)
.form_input                by class
.input_error.form_input    both classes (no space)
[data-test="username"]     by attribute
form input                 descendant (space)
form > input               direct child
[id^="login"] [id$="btn"] [class*="err"]  partial
.item:nth-child(2)         position — LAST resort
XPath
//input[@id='user-name']         by attribute
//button[text()='Checkout']      by exact text
//a[contains(text(),'Terms')]    partial text
//*[contains(@class,'error')]    any tag
//span[text()='X']/../..         up two levels
//div[text()='X']/ancestor::div[@class='card']//button
(//button[@class='b'])[3]        position — last resort
Test live in DevTools console
$$("#login-button")          CSS matches
$x("//button[text()='Go']")  XPath matches
$$(".form_input").length     uniqueness check -> want 1
Elements panel + Ctrl+F      accepts both dialects
Locator priority
  • 1. id → 2. data-test → 3. meaningful class/attr
  • 4. hierarchy → 5. position (avoid)
  • Never trust DevTools 'Copy XPath' — absolute = brittle
  • Good locator = unique + stable + readable
Choosing the dialect
know the id / attribute?   CSS   #id  [data-test='x']
need the visible text?     XPath //b[text()='Checkout']
need to climb UP?          XPath ancestor::div[...]
repeated cards / tables?   text -> ancestor -> descendant
everything else            CSS (shorter, faster)
saucedemo locator inventory
#user-name   #password   #login-button
[data-test='error']              login error box
.title                           page header
#add-to-cart-sauce-labs-backpack
.shopping_cart_badge   .shopping_cart_link
#checkout   #first-name  #last-name  #postal-code
#continue   #finish      .complete-header
When 0 matches lies to you
  • element inside an <iframe> — console targets the top document
  • page re-rendered after you looked — run the query again
  • typo or case — ids are case-sensitive
  • $$ / $x exist ONLY in the DevTools console, never in code
Practice targets
saucedemo.com          standard_user / secret_sauce
                       locked_out_user (error flows)
the-internet.herokuapp.com/dynamic_loading  (waits)