Encountering an error page after clicking the checkout button in a headless Ruby-Selenium browser

I am in the process of automating a Walmart shopping cart workflow, from product selection to the full checkout procedure. I am using a headless version of Chrome in Ruby Selenium for this task. However, an issue arises when I click the ‘Checkout’ button after adding an item to my cart; I end up on an ‘Error page’ and the page title shown is ‘Walmart Omnivore’. This interrupts the checkout process, which works seamlessly when performed with a visible browser session. My problem is strictly related to the checkout phase in headless mode.

My setup includes:

  • Ruby version: 2.4.3
  • Selenium Gem: selenium-webdriver-3.5.2
  • Chrome version: 67.0.3396.99 (Official Build) (64-bit)

Here’s a revised version of my code:

require 'selenium-webdriver'

class HeadlessShoppingAutomator

  chrome_driver_path = 'chromedriver.exe'  # Path to the ChromeDriver executable

  Selenium::WebDriver::Chrome.driver_path = chrome_driver_path
  options = Selenium::WebDriver::Chrome::Options.new
  options.add_argument('--headless')

  driver = Selenium::WebDriver.for :chrome, options: options

  driver.get 'https://www.walmart.com/'

  puts driver.title

  driver.save_screenshot('initial_test.png')
  sleep 5

  search_box = driver.find_element(:id, 'global-search-input')
  search_box.click
  search_box.send_keys('623649985')
  search_box.submit

  sleep 5
  driver.save_screenshot('after_search.png')

  puts driver.title

  product_image = driver.find_element(:xpath, "//img[@class='Tile-img']")
  product_image.click

  sleep 5
  driver.save_screenshot('product_view.png')
  puts driver.title

  puts 'Item is being added to the cart'
  add_to_cart_button = driver.find_element(:xpath, "//button[text()='Add to Cart']")
  add_to_cart_button.click
  sleep 3

  driver.save_screenshot('added_to_cart.png')
  puts driver.title

  proceed_checkout_button = driver.find_element(:xpath, "//div[@class='Cart-PACModal-POSContainer']/descendant::button[text()='Check Out']")
  proceed_checkout_button.click

  driver.save_screenshot('before_error.png')
  sleep 4
  driver.save_screenshot('error_page.png')
  puts driver.title
  puts 'process complete'

end

Note: I have also attempted to click the Checkout button after logging in as a Walmart user, but encountered the same issue.

It sounds like the headless mode might be affecting how scripts run on the checkout page. Here are a few tweaks you can try:

  1. Update Chrome Options: Add additional options to improve compatibility.
    options.add_argument('--headless')
    options.add_argument('--disable-gpu')
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--no-sandbox')
    options.add_argument('--window-size=1920,1080')
    options.add_argument('user-agent=Mozilla/5.0 ...')
        
  2. Implement Explicit Waits: Make sure elements are fully loaded before interacting.
    wait = Selenium::WebDriver::Wait.new(timeout: 10)
    proceed_checkout_button = wait.until {
      driver.find_element(:xpath, "//div[@class='Cart-PACModal-POSContainer']/descendant::button[text()='Check Out']")
    }
    proceed_checkout_button.click
        

These changes might help address issues related to headless mode limitations. Ensure all resources are properly rendered before click actions.

It seems like the error page issue in your headless Chrome setup while automating the Walmart checkout process might be related to the way some scripts run differently in headless mode compared to a standard session. Here’s a structured approach to resolve the problem:

Solution Steps:

  1. Verify Headless Options: Sometimes, certain functionalities might not render correctly in headless mode. Modify your Chrome options to ensure maximum compatibility.
    options = Selenium::WebDriver::Chrome::Options.new
    options.add_argument('--headless')
    options.add_argument('--disable-gpu') # Temporarily needed for Chrome versions < 66
    options.add_argument('--disable-dev-shm-usage') # Overcomes limited resource problems
    options.add_argument('--no-sandbox') # Bypass OS security model
    options.add_argument('--window-size=1920,1080')
  2. JavaScript Execution: Confirm if some JavaScript executions are delayed or timeout due to headless restrictions. You can increase wait times or explicitly wait using Selenium.
    wait = Selenium::WebDriver::Wait.new(timeout: 10) # seconds
    proceed_checkout_button = wait.until {
      driver.find_element(:xpath, "//div[@class='Cart-PACModal-POSContainer']/descendant::button[text()='Check Out']")
    }
    proceed_checkout_button.click
  3. Pop-Ups and Modals: Handle any pop-ups or modal windows that may need interaction but are not visible in headless mode. Check for banners, modals, or login prompts manually using screenshots.
  4. User-Agent Adjustment: Some websites have different scripts for headless browsers. Spoofing a regular browser user-agent might help:
    options.add_argument('user-agent=Mozilla/5.0 ...') # Use a standard browser user-agent string
  5. Stick with Recent Versions: Ensure you have the latest versions of Chrome and Selenium, as updates often fix headless mode issues.

Try these adjustments in your code and see if it resolves the error. Headless sessions sometimes miss rendering parts of the JavaScript-dependent pages, which can be crucial for checkout processes.

When running automated tests or workflows with Selenium in headless mode, encountering issues like the Walmart checkout error page is not uncommon, as some functionalities behave differently without a visible UI. Here are some detailed strategies to troubleshoot and potentially resolve this issue:

Suggested Solutions:

  1. Modify Chrome Options: While the headless mode is effective, it may require specific configurations for compatibility, especially with dynamic content.
    options = Selenium::WebDriver::Chrome::Options.new
    options.add_argument('--headless')
    options.add_argument('--disable-gpu') # Needed for older Chrome versions
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--no-sandbox')
    options.add_argument('--window-size=1920,1080')
    options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3')
        
  2. Implement Explicit Waits: Ensure that elements are ready for interaction by using explicit waits. This reduces the likelihood of attempting interactions before a page is fully loaded.
    wait = Selenium::WebDriver::Wait.new(timeout: 15) # Increase the timeout if necessary
    proceed_checkout_button = wait.until {
      driver.find_element(:xpath, "//div[@class='Cart-PACModal-POSContainer']/descendant::button[text()='Check Out']")
    }
    proceed_checkout_button.click
        
  3. Investigate JavaScript Execution: Certain JavaScript functions may not execute in headless mode as they do in a normal browser session. Use screenshots or logs to diagnose untriggered scripts.
  4. Bypass Potential Restrictions: Web applications might use scripts to detect headless browsing and restrict actions. Spoofing the user-agent mimics a real browser session as seen from the server side.
  5. Update Dependencies: Ensure you are using the latest version of both Chrome and the Selenium WebDriver. Compatibility improvements and bug fixes are frequently included in new releases.
  6. Debug with Headed Mode: Run the test in non-headless mode occasionally to capture specific behavior that doesn't translate to headless mode. Compare the post-click aftermath using screenshots.

Applying these adjustments should enhance headless Selenium's robustness with complex web pages like Walmart's checkout system. Keep iterating with these settings until you achieve a seamless transition through the checkout phase.