I am currently working on a Python script using Playwright to automate the process of adding an iCal link to Google Calendar. The script successfully navigates through the authentication process, entering the login credentials, but encounters issues when attempting to input a URL on the Google Calendar 'Add by URL' page. It must be in headless = True
from playwright.sync_api import sync_playwright
import time
from playwright.sync_api import Page
with sync_playwright() as playwright:
browser = playwright.chromium.launch(headless=True, slow_mo=5000)
context = browser.new_context()
page = context.new_page()
page.goto("https://accounts.google.com/v3/signin/identifier?dsh=S1611624178:1665765818620%20318&continue=https://calendar.google.com/calendar/r&followup=https://calendar.google.com/calendar/r&osid=1&passive=1209600&service=cl&flowName=GlifWebSignIn&flowEntry=ServiceLogin&ifkv=AQDHYWrL2lk0_Bcr1n1Y-f-i1sNZRKJK8CNisliX9rpozkqKhY2Jby8gsVZ_wDz_oHqiWmN6uZ6s6g&ec=wgc-calendar-globalnav-signin")
userLogin = "username "
userPass = "password"
page.fill('input[type="email"]', userLogin)
page.wait_for_selector('#identifierNext >> button', state="visible")
page.wait_for_timeout(2000)
page.click('#identifierNext >> button')
page.evaluate('''() => {
const passwordInput = document.querySelector('input[type="password"]');
passwordInput.style.display = 'inline'; // or 'block' or 'inline-block'
}''')
password_input = page.wait_for_selector('input[type="password"]', state="visible")
password_input.fill(userPass)
page.click('button >> nth=1')
page.goto('https://calendar.google.com/calendar/u/0/r/settings/addbyurl')
url_to_inject = 'https://brightspace.uri.edu/d2l/le/calendar/feed/user/feed.ics?token=althvrqormrwijfhdbe8'
page.evaluate('''(url) => {
const inputField = document.querySelector('input[jsname="YPqjbf"]');
if (inputField) {
// Click on the input field
inputField.click();
inputField.focus();
inputField.click();
// Set the value
inputField.value = url;
}
}''', url_to_inject)
# Check if the attribute is set on the input field
attribute_value = page.evaluate('(url) => document.querySelector(\'input[jsname="YPqjbf"]\').getAttribute(\'data-injected\')', url_to_inject)
if attribute_value == 'true':
print("Script injection successful!")
else:
print("Script injection failed!")
error I get:
playwright._impl._api_types.Error: TypeError: Cannot read properties of null (reading 'style')
at eval (eval at evaluate (:208:30), <anonymous>:3:23)
at UtilityScript.evaluate (<anonymous>:215:19)
at UtilityScript.<anonymous> (<anonymous>:1:44)
HTML snippet of that input field:
<input type="text" value="" id="c67" jsname="YPqjbf" class="VfPpkd-fmcmS-wGMbrd " jsaction="focus:AHmuwe;blur:O22p3e;input:YPqjbf; mousedown:UX7yZ; mouseup:lbsD7e; pointerdown:QJflP; pointerup:HxTfMe; touchstart:p6p2H; touchend:yfqBxc;" aria-controls="c68" aria-describedby="c68" aria-labelledby="c64" maxlength="1024" autocomplete="off">
I have tried alot of ways and I understand its dynamic I was expecting it to input it and then I can get the embedded code after It does all the other actions:
#Checkbox after url input
# page.evaluate('''(selector) => {
# const checkbox = document.querySelector(selector);
# if (checkbox) {
# checkbox.checked = true;
# checkbox.dispatchEvent(new Event('change'));
# }
# }''', 'input[jsname="YPqjbf"][type="checkbox"]')
#Add button clicked
# page.evaluate('''(selector) => {
# const button = document.querySelector(selector);
# if (button) {
# button.click();
# }
# }''', 'button[jsname="V67aGc"]')
# page.get_by_text("All Courses - University of Rhode Island").click()
# page.get_by_role("treeitem", name="Integrate calendar").click()
#embedded code link
# dynamic_selector = '[jsname="YPqjbf"]'
# page.wait_for_selector(dynamic_selector, timeout=20000)
# embed_code_element = page.locator(dynamic_selector).nth(4)
# print(embed_code_element)
# element_html = str(embed_code_element.input_value())
# page.screenshot(path='screenshot.png')
# print(element_html)