Selenium click on ng-click button

Tags: , , , ,



I am trying to automate a website with selenium to download an excel file. I have the following HTML for the button:

<div class="row ng-scope" ng-if="!model.update_rota">
              <div class="col-sm-12 hidden-xs hidden-sm">
                <button type="button" class="btn btn-success btn-block" title="יצא לאקסל" ng-click="excelRota();" ng-disabled="!model.rota.id || model.rotaLoading">
                  <i class="fa fa-file-excel-o fa-lg"></i>&nbsp;אקסל
                </button>
              </div>
              <!-- ngIf: model.features.reports.attributes.availability_shifts_report.value == 'True' -->
              <!-- ngIf: model.features.tips.is_active && model.features.tips.attributes.tips_calculate.value == 'True' -->
              <div class="col-sm-12">
                <div class="btn-group btn-block visible-xs-block visible-sm-block">
                  <button type="button" class="btn btn-info btn-block dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" ng-disabled="model.rotaLoading">
                    <i class="fa fa-bars fa-lg"></i>&nbsp;אפשרויות
                  </button>
                  <ul class="dropdown-menu">
                    <!-- ngIf: model.features.tips.is_active && model.features.tips.attributes.tips_calculate.value == 'True' -->
                    <li ng-class="{'disabled': !model.rota.id}" class="" style=""><a href="#" ng-click="excelRota();"><i class="fa fa-file-excel-o text-success"></i>&nbsp;יצא סידור לאקסל</a></li>
                    <!-- ngIf: model.features.reports.attributes.availability_shifts_report.value == 'True' -->
                  </ul>
                </div>
              </div>
            </div>

I have tried clicking on the button with the following find element by class:

driver.find_element_by_class_name('btn btn-success btn-block').click()

The error message I get is:

selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".btn btn-success btn-block"}

I have also tried:

driver.execute_script("excelRota();")

And received the following error:

selenium.common.exceptions.JavascriptException: Message: javascript error: excelRota is not defined

I have logged in this website successfully and worked my way around the site up until the excel file page, but I can’t figure out how to click this button.

I have written my script as headless chrome if it makes any difference.

Update:

This is my whole code:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.common.by import By
import os
import time
import pandas as pd
from tkinter import *
import datetime


excel_shifts_download_url = 'https://app.shiftorganizer.com/excel/rota/125102/?'
download_dir = "C:\Users\Documents\Python Scripts\projects\shifts_script"
driver_path = "C:\Users\Documents\Python Scripts\projects\shifts_script\chromedriver.exe"
shiftorgnizer_login_url = 'https://app.shiftorganizer.com/login/?lang=he&previous=homepage&greeting=true'

# enabling headless chrome
def setting_chrome_options():
    chrome_options = Options()
    chrome_options.add_argument("--headless")
    chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument('--disable-gpu')
    chrome_options.add_argument('--disable-software-rasterizer')
    return chrome_options

driver = webdriver.Chrome(executable_path=driver_path, options=setting_chrome_options()) 

# Login GUI
def login_gui():
    
    root = Tk()
    root.title('Shifter')
    root.geometry("250x130")
    root.focus_force()
    global entry_company_id
    global entry_username
    global entry_password
    global checkbox_var
    checkbox_var = IntVar()
    
    # Text near text box username & password
    label_company_id = Label(root, text='Company ID')
    label_username = Label(root, text='Username')
    label_password = Label(root, text='Password')
    

    # Textbox for username & password
    entry_company_id = Entry(root)
    entry_username = Entry(root)
    entry_password = Entry(root)

    # Positioning of text
    label_company_id.grid(row=0, sticky=E)
    label_username.grid(row=1, sticky=E)
    label_password.grid(row=2, sticky=E)
    
    # Positioning of textboxes
    entry_company_id.grid(row=0, column=1)
    entry_username.grid(row=1, column=1)
    entry_password.grid(row=2, column=1) 

    # Login button
    root.bind('<Return>', site_login)
    b = Button(root, text='Login', command=site_login)
    b.grid(row=4, column=1)
    checkbox = Checkbutton(root, text='Get next week Shifts', variable=checkbox_var)
    checkbox.grid(row=3, column=1)
    
    root.mainloop()

current_day_date = datetime.date.today()
next_sunday_date = current_day_date + datetime.timedelta( (6 - current_day_date.weekday()) % 7 )
# Site login with user's credentials
def site_login():

    global company_id
    global username
    global password
    username = str(entry_username.get())
    password = str(entry_password.get())
    company_id = str(entry_company_id.get())

    driver.get (shiftorgnizer_login_url)
    driver.implicitly_wait(20)
    driver.find_element_by_id('company').send_keys(company_id)
    driver.find_element_by_id ('username').send_keys(username)
    driver.find_element_by_id ('password').send_keys(password)
    driver.find_element_by_id('log-in').click()
    
    # downloading shifts file
    enable_download(driver)
    WebDriverWait(driver, 10).until(EC.title_contains("בית | ShiftOrganizer"))
    driver.get('https://app.shiftorganizer.com/app/rota')
    WebDriverWait(driver, 10).until(EC.title_contains("סידור | ShiftOrganizer"))
    WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,".btn.btn-success.btn-block"))).click()
    # if checkbox_var.get() == 0:
    #     driver.find_element_by_class_name('col-sm-12 hidden-xs hidden-sm').click()
    # elif checkbox_var.get() == 1:
    #     driver.get('https://app.shiftorganizer.com/app/rota'+'?date='+next_sunday_date)
    #     WebDriverWait(driver, 10).until(EC.title_contains("סידור | ShiftOrganizer"))
    #     driver.get(excel_shifts_download_url)

    isFileDownloaded()

# permission to download file via Selenium
def enable_download(driver):
    driver.command_executor._commands["send_command"] = ("POST", '/session/$sessionId/chromium/send_command')
    params = {'cmd':'Page.setDownloadBehavior', 'params': {'behavior': 'allow', 'downloadPath': download_dir}}
    driver.execute("send_command", params)

# check if file has been downloaded
def isFileDownloaded():
    file_path = download_dir+"\schedule.xlsx"
    while not os.path.exists(file_path):
        time.sleep(1)
    if os.path.isfile(file_path):
        print("File Downloaded Successfully")

login_gui()

When I disable headless chrome option the file is being downloaded

Answer

find_element_by_class_name() doesn’t accepts multiple class name. Instead you can use css selector.

To avoid synchronization issue Induce WebDriverWait() and wait for element_to_be_clickable() and following css selector.

WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,".btn.btn-success.btn-block"))).click()

You need to import below libraries.

from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

Reference link for css selector



Source: stackoverflow