Upload profile picture on Microsoft with selenium, python () - python

So, what I'm trying to do is to automate a process which opens the Microsoft login page, enters the login information and then logs in. After that it clicks on the profile and then clicks on change profile picture button.
Now, I'm having trouble with the next part....which is to upload a picture and set it as profile picture.
I searched all over the internet but can't find a solution.
My code till now is -
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from selenium.webdriver import ActionChains
chromedriver = 'C:\\Users\\verma\\Downloads\\chromedriver.exe'
browser = webdriver.Chrome(chromedriver)
action = ActionChains(browser)
#1. Open Microsoft Login Page
browser.get('https://www.microsoft.com/en-in/?wa=wsignin1.0')
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID,"mectrl_headerPicture"))).click()
#2. Login with Username and Password
user = (By.ID,"i0116")
WebDriverWait(browser, 10).until(EC.element_to_be_clickable(user)).send_keys("emailid#outlook.com")
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID,"idSIButton9"))).click()
password = (By.ID,"i0118")
WebDriverWait(browser, 10).until(EC.element_to_be_clickable(password)).send_keys("password")
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID,"idSIButton9"))).click()
#3. Click on Profile and then Click on Change Picture
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID,"mectrl_headerPicture"))).click()
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID,"mectrl_currentAccount_picture_profile_picture"))).click()
#4. Upload Picture
time.sleep(5)
browser.quit()
What I have tried is -
#4. Upload Picture
WebDriverWait(browser, 30).until(EC.element_to_be_clickable((By.ID,"id__62"))).click()
The windows file chooser is not popping up. My guess is that I gave wrong ID for "Choose File" button/link to selenium and that's why it gives TimeoutException since it cant find the element.
But I cant seem find the correct ID. I also want to know how to upload the picture after the File Chooser pops up successfully.
EDIT: Screenshot of the HTML code (Through Inspect)
HTML Code

There are few steps that you need to follow in order to upload a pic :
you need to switch driver focus to new tab
Click on Add a photo.
Upload a pic.
Assert Successful Message.
Code :
#4. Upload Picture
windows_before = browser.current_window_handle
WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID,"mectrl_currentAccount_picture_profile_picture"))).click() # this is from #3
windows_after = browser.window_handles
new_window = [x for x in windows_after if x != windows_before][0]
browser.switch_to.window(new_window)
browser.find_element(By.CSS_SELECTOR, "button[id='profile.profile-page.profile-pic-section.edit-picture']").click()
browser.find_element(By.CSS_SELECTOR, "button[id='button[id='profile.edit-picture.upload-button']']").click()
browser.find_element(By.CSS_SELECTOR, "input[type='file']").send_keys("path of the file to be uploaded")
#Assert your msg

Related

Selenium ChromeDriver not interacting with Chrome Print Dialog

I'm new to web scraping, and I have recently tried to create a web scraper that prints out my online Calendar. I have been able to work out how to get to the print prompt with Selenium, but I cannot interact with the actual print window when I try to programmatically click the Print & Cancel buttons.
The print prompt does take a second or two to load, and I already have the print window selected as the current window by Webdriver (accomplished using the below code)
whandles = driver.window_handles
print("About to switch window handle to print window, should be: " + whandles[1])
driver.switch_to.window(whandles[1])
But when I try:
printBtnFinal = WebDriverWait(driver,100).until(EC.element_to_be_clickable((By.CLASS_NAME,'action-button'))).click()
nothing happens, the program times out (I'm assuming because the element never was found).
How can I successfully interact with the Chrome Print Window?
Any help is appreciated.
Problem Explanation
You do not need to switch to Print Modal pop up. Because it is not a new windows/tab neither it is in frame. So switching is the culprit here.
Solution
I would recommend you to use WebDriverWait which is an explicit waits in Selenium library.
to click on Print which is in top right corner use this xpath and code :
wait = WebDriverWait(driver, 20)
wait.until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Print']/ancestor::button"))).click()
Once this is clicked you'd see a new pop up with Print and Cancel button.
to click on Print in the pop up, the below code should help you past the issue that you've been facing.
wait.until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Print']/ancestor::button[contains(#class,'action')]"))).click()
Imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Update 1 :
driver = webdriver.Chrome(driver_path)
driver.maximize_window()
driver.implicitly_wait(50)
driver.get("https://outlook.live.com/owa/?state=1&redirectTo=aHR0cHM6Ly9vdXRsb29rLmxpdmUuY29tL2NhbGVuZGFyLw&nlp=1")
wait = WebDriverWait(driver, 20)
#User Must place Email:
USER_EMAIL = 'user name should be given here'
USER_PASSWORD = 'password should be here'
emailField = WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[type='email']")))
emailField.clear()
emailField.send_keys(USER_EMAIL)
submitEmail= WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[type='submit']"))).click()
#Dismiss "It looks like this email is used with more than one account from Microsoft" screen
#personalAccount = WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"div[id='msaTile']"))).click()
#Enter Password
passwordField = WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[type='password']")))
passwordField.clear()
passwordField.send_keys(USER_PASSWORD)
submitPassword = WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[type='submit']"))).click()
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.table-row"))).click()
time.sleep(30)
wait.until(EC.element_to_be_clickable((By.ID, "idSubmit_SAOTCC_Continue"))).click()
#Dismiss StaySignedIn
staySignedIn = WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[id='idBtn_Back']"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a[title='Calendar']"))).click()
printBtn1 = WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Print']/ancestor::button"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Print']/ancestor::button[contains(#role,'menuitem')=false]"))).click()

Selenium script to locate textarea element not working

I am trying to automate posting into my social media account. I have successfully written the script to log in, after login in I am having difficulty locating the textarea element with which to pass my post, after which I will try to attach an image to my post, make the post and log out. But for now, I am stuck at the locating the textarea after login in. This is the code
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
usernameStr = 'JonJames3872#gmail.com'
passwordStr = 'JamesJon'
textStr = 'Testing my Post'
browser = webdriver.Chrome()
browser.get(('https://accounts.kingsch.at/?client_id=com.kingschat&scopes=%5B%22kingschat%22%5D&redirect_uri=https%3A%2F%2Fweb.kingsch.at%2F'))
# fill in username and password
password = browser.find_element_by_name('password')
password.send_keys(passwordStr)
username = browser.find_element_by_class_name('field')
username.send_keys(usernameStr)
signInButton = browser.find_element_by_class_name('submit-btn')
signInButton.click()
# I HAVE LOGGED IN, NOW THIS IS WHERE MY CODE HAS A PROBLEM
text = browser.find_element_by_xpath("/html/body/div[1]/div/div[2]/div/div[2]/div/div[1]/div/div/div[1]/textarea")
text.send_keys(textStr)
This is the element, from inspect element:
<textarea placeholder="What's happening?" class="KingingBox__input"></textarea>
Textarea HTML Screenshot
URL: https://accounts.kingsch.at/?client_id=com.kingschat&scopes=%5B%22kingschat%22%5D&redirect_uri=https%3A%2F%2Fweb.kingsch.at%2F
Sample User name: JonJames3872#gmail.com (strangely here username is case sensitive)
Sample password: JamesJon
Notification Screenshot
I inserted code to write something in the text area
I inserted code to upload a photo
I inserted code to post your own post
I think 3 out of the 3 questions are all done.
Try this code:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import os
path = '/home/avionerman/Documents/stack'
browser = webdriver.Firefox(path)
browser.implicitly_wait(10)
usernameStr = 'JonJames3872#gmail.com'
passwordStr = 'JamesJon'
textStr = 'Testing my Post'
browser.get(('https://accounts.kingsch.at/?client_id=com.kingschat&scopes=%5B%22kingschat%22%5D&redirect_uri=https%3A%2F%2Fweb.kingsch.at%2F'))
# fill in username and password
password = browser.find_element_by_name('password')
password.send_keys(passwordStr)
username = browser.find_element_by_class_name('field')
username.send_keys(usernameStr)
signInButton = browser.find_element_by_class_name('submit-btn')
signInButton.click()
text = browser.find_element_by_class_name('KingingBox__input')
text.clear()
text.send_keys(textStr)
time.sleep(5)
image = browser.find_element_by_class_name('KingingBox__attachment-input').send_keys('/here/path/of_yours/th_574e7c36606306d94a4.jpg')
time.sleep(5)
inserted_photo = browser.find_element_by_class_name('KingingBox__attachments-list')
if inserted_photo.is_displayed():
print("Element found, photo uploaded successfully")
browser.find_element_by_css_selector('.KingingBox__submit-btn').click()
else:
print("Element not found")
At this line:
browser.implicitly_wait(10)
we determine that the browser will wait a max time of 10 seconds for each element to be visible. If the textarea will make more than 10 seconds to appear, the the script will stop. If you see enormous delays increase the seconds of waiting.
Also, as you can see I used this line:
text = browser.find_element_by_class_name('KingingBox__input')
in order to locate the textarea.
In this line:
image = browser.find_element_by_class_name('KingingBox__attachment-input').send_keys('/here/path/of_yours/th_574e7c36606306d94a4.jpg')
I locate the input tag which is responsible for accepting uploades and then I send on it the exact path of the file that I want to upload.
In the last part:
inserted_photo = browser.find_element_by_class_name('KingingBox__attachments-list')
if inserted_photo.is_displayed():
print("Element found, photo uploaded successfully")
browser.find_element_by_css_selector('.KingingBox__submit-btn').click()
else:
print("Element not found")
I save into the inserted_photo variable the element which shows me that the photo uploaded successfully. Then if this variable is displayed this means that the photo uploaded properly. Thus, since we have the text and the photo we are ready to click on the 'Post' button.
Try to use static attributes that are not dynamic and there is no danger of future changes. This way you create stability to your code. Because choosing such an xpath like in your example, is risky. If a div or another tag is going to be excluded or included immediately the xpath is not useful.
PS: I uploaded two posts because of testing, so sorry I couldn't try it other way.

Landing Page Not Loading - Selenium Web Form Automation

Creating a script that will log in into the site below and automatically log values into a web form. The problem is that once I login, the landing page is blank (i.e it loads headers but that's it). My code is below:
profile = webdriver.FirefoxProfile()
profile.accept_untrusted_certs = True
browser = webdriver.Firefox(profile)
browser.get('https://cmsdb.darkcosmos.org/experiments/run/new')
print('Connected to Server')
time.sleep(2) # Wait for page to load
login_button = browser.find_element_by_xpath('/html/body/div/div[5]/main/div/div[1]/div/div[3]/button')
login_button.click()
time.sleep(2) # Wait for pop-out to load
browser.find_element_by_xpath('//*[#id="username"]').send_keys(username)
browser.find_element_by_xpath('//*[#id="password"]').send_keys(password)
login_attempt = browser.find_element_by_xpath('/html/body/div/div[4]/div/div/div/div/div/form/button[1]')
login_attempt.submit()
print('Logged In')
time.sleep(2) # Wait for new page to load
browser.find_element_by_xpath('//*[#id="title"]').send_keys('Title') # Code breaks here. It cannot find the title entry area because the new page is blank.
I've tried making a Firefox profile, giving the page time to load, and turning certificates off. It loads just fine when I manual login. Thanks in advance for the help!
To login within the url https://cmsdb.darkcosmos.org/experiments/run/new and provide the username and password using a new FirefoxProfile you need to induce WebDriverWait for the desired elements to be clickable and you can use the following solution:
Code Block:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
profile = webdriver.FirefoxProfile()
profile.accept_untrusted_certs = True
browser = webdriver.Firefox(firefox_profile=profile, executable_path=r'C:\Utility\BrowserDrivers\geckodriver.exe')
browser.get('https://cmsdb.darkcosmos.org/experiments/run/new')
print('Connected to Server')
login_button = browser.find_element_by_xpath('/html/body/div/div[5]/main/div/div[1]/div/div[3]/button')
WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.v-content__wrap button.v-btn.v-btn--flat.theme--light.primary--text"))).click()
WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input#username"))).send_keys("clcarver")
browser.find_element_by_css_selector("input#password").send_keys("clcarver")
login_attempt = browser.find_element_by_css_selector("div.v-btn__content>i.v-icon.pr-1.mdi.mdi-lock-open-outline.theme--light").click()
Console Output:
Connected to Server
Browser Screenshot:

Selenium not able to open new Window/Tab

I am currently trying to crawl a website using selenium.
I have a table with elements and I want to click on each element, open the link in a new window/tab, process this window/tab, close it and click on the next element etc. So far I can click on the elements of the table, open the link and process the page.
Unfortunately I can not open the link in a new window or tab.
I can not send keyboard commands to the elements.
I have also tried
action = ActionChains(self.driver)
action.move_to_element(ele)\
.key_down(Keys.SHIFT)\
.click(ele)\
.key_up(Keys.SHIFT)\
.perform()
This somehow does only open the link in the current window (I dont't get a new window handle, still just one).
I would be very grateful for any help.
Edit: Also I am not able to open the link in a new window/tab manually with the browser.
To access the URL e.g. https://www.google.co.in then to click on an element e.g. link with text as Gmail to open the link in a new window/tab you can use action_chains class as per the solution below :
Code Block :
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_argument('disable-infobars')
driver=webdriver.Chrome(chrome_options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
driver.get('https://www.google.co.in')
print("Page Title is : %s" %driver.title)
mail_link = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.LINK_TEXT, "Gmail")))
ActionChains(driver).key_down(Keys.CONTROL).click(mail_link).key_up(Keys.CONTROL).perform()
Browser Snapshot :
As Gmail is an 'a' tag, first get that a tag like below and perform an actionchain
from selenium.webdriver.common.action_chains import ActionChains
gmailtag = webdriver.find_element_by_xpath('path to gmail') # you can use any other methods to get it.
#Now you can run this to open the gmailtag in a new tab
ActionChains(webdriver).key_down(Keys.CONTROL).click(gmailtag).perform()
# this also worked for me
gmailtag.send_keys(Keys.CONTROL+Keys.ENTER)
It would open Gmail in a new tab. It worked for me.

Python selenium issue: able to find element but not send_keys

I am trying to login into the ESPN footytips website so that I can scrape information for one of my leagues.
I am having no issues opening an instance of Chrome and navigating to the homepage (which contains the login form) and can even select the username field but I cannot for the life of me send my login details to the form.
In debugging I know I can find and select the form submit button and the issue seems to be in passing my login details using send_keys as my exception rule always triggers after I attempt call send_keys.
Any suggestions on how to resolve would be welcomed! My script is below:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
login_address = "http://www.footytips.com.au/home"
me_login = "test#test.com"
me_password = "N0TMYR3#LP#S5W0RD"
browser = webdriver.Chrome()
browser.get(login_address)
try:
login_field = browser.find_element_by_id("ft_username")
password_field = browser.find_element_by_id("ft_password")
print("User login fields found")
login_field.send_keys(me_login)
password_field.send_keys(me_password)
print("Entered login data")
submit_button = browser.find_element_by_id("signin-ft")
print("Submit button found")
submit_button.submit()
except:
print("Error: unable to enter form data")
The locators you have used doesn't uniquely identifies the login_field and the password_field. Additionally you need to wait for the respective WebElements to be visible. Here is your own code with some tweaks :
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
#lines of code
login_address = "http://www.footytips.com.au/home"
me_login = "test#test.com"
me_password = "N0TMYR3#LP#S5W0RD"
browser.get(login_address)
login_field = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.XPATH,"//div[#class='login-form']//input[#id='ft_username']")))
password_field = browser.find_element_by_xpath("//div[#class='login-form']//input[#id='ft_password']")
login_field.send_keys(me_login)
password_field.send_keys(me_password)
print("Entered login data")

Categories

Resources