This episode covers advanced browser actions: handling alerts, popups, frames, and windows, drag and drop, double click, hover, and keyboard actions, automating file upload and download, plus scrolling and viewport handling.

After mastering click, type, and submit in episode 4, you're ready for more challenging actions: advanced browser actions. Real applications have JavaScript alerts, iframes that hide content, new tabs that open, elements that must be dragged, files that must be uploaded, and long pages that must be scrolled. Episode 8 equips you with all of that control.
These actions are often the trickiest part of automation, because many of them can't be done with plain find_element and click. You'll need special objects like Alert, ActionChains, and an understanding of window handles. Let's break them down one by one.
Browser alerts are native dialogs that block the page. Selenium manages them through the Alert object:
from selenium.webdriver.common.alert import Alert
Alert(driver).accept()For alerts with input, use send_keys on the alert object then accept:
alert = driver.switch_to.alert
alert.send_keys("nama pengguna")
alert.accept()driver.switch_to.alert switches context to the active dialog, send_keys fills the prompt, and accept() confirms it. If a cancel button appears, dismiss() is the opposite.
When a click opens a new tab, the browser has more than one window handle:
sebelum = driver.current_window_handle
driver.find_element("id", "buka-tab").click()
for handle in driver.window_handles:
if handle != sebelum:
driver.switch_to.window(handle)
break
print("Judul tab baru:", driver.title)
driver.close()
driver.switch_to.window(sebelum)driver.window_handles returns the list of all tabs. The pattern above switches to the new tab, works there, closes it, then returns to the original tab.
Content inside <iframe> can't be found directly from the main page context. You must switch context first:
driver.switch_to.frame("payment-frame")
driver.find_element("id", "nomor-kartu").send_keys("4111111111111111")
driver.switch_to.default_content()driver.switch_to.frame("payment-frame") moves context into the iframe by id, name, or element. When done, default_content() returns context to the main page. Don't forget to exit the iframe before looking for elements on the main page.
ActionChains enables complex sequential actions:
from selenium.webdriver.common.action_chains import ActionChains
sumber = driver.find_element("id", "sumber")
target = driver.find_element("id", "target")
ActionChains(driver).drag_and_drop(sumber, target).perform()drag_and_drop(sumber, target) drags an element to a target. For other actions — hover to trigger a menu, double click, and right click — ActionChains also provides move_to_element, double_click, and context_click.
Key combinations like Ctrl+A and Enter can be sent through the Keys class:
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
inputan = driver.find_element("id", "editor")
inputan.send_keys(Keys.CONTROL, "a")
inputan.send_keys(Keys.BACKSPACE)
ActionChains(driver).send_keys(Keys.TAB).perform()Keys.CONTROL and Keys.BACKSPACE are examples of keyboard modifiers. ActionChains send_keys(Keys.TAB) sends keys at the page level, not to a specific element.
HTML file inputs hide the OS dialog, but Selenium can still send the path directly:
path = "/home/devnull/Documents/cv.pdf"
driver.find_element("id", "input-file").send_keys(path)send_keys(path_lengkap) on a file-type input element is the most stable upload method. Native dialogs can't be automated directly by Selenium, so never try to click a "Browse" button.
For downloads, set browser preferences so files go to the desired folder:
from selenium import webdriver
opsi = webdriver.ChromeOptions()
prefs = {"download.default_directory": "/tmp/download-test"}
opsi.add_experimental_option("prefs", prefs)
driver = webdriver.Chrome(options=opsi)prefs["download.default_directory"] sets the download destination folder. After triggering a download, wait for the file to actually appear in the folder before continuing with assertions.
Elements below the fold sometimes need scrolling before they can be interacted with. Either via JavaScript or a scroll action:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
driver.set_window_size(1440, 900)
driver.execute_script("arguments[0].scrollIntoView(true);", tombol)window.scrollTo(0, document.body.scrollHeight) scrolls to the bottom of the page, while scrollIntoView(true) brings a specific element into view. set_window_size(1440, 900) sets the viewport size for responsive tests.
Warning
Automatic clicks usually scroll the element into view. If an element is still covered by other elements, combine scrolling with an explicit wait for the element to be clickable before interacting.
Episode 8 extends the reach of your automation: page-blocking alerts, new tabs, iframes hiding content, drag and drop, hover, keyboard, file upload and download, and scrolling long pages — all now under your control.
Key takeaways:
driver.switch_to.alert; accept, dismiss, and input.switch_to.frame and returning via default_content.send_keys to a file input; download is configured via browser prefs.In episode 9 next, we'll cover data-driven and parameterized testing — using data providers for many test cases, parameterizing inputs and expected results, pulling data from CSV, JSON, and Excel, and expanding test coverage across many browsers and environments.