bug-man/hf_shiny_web_automation
0
1import re2import time3from selenium import webdriver4from selenium.webdriver.chrome.service import Service5from selenium.webdriver.chrome.options import Options6from selenium.webdriver.support.ui import WebDriverWait7from selenium.webdriver.support import expected_conditions as EC8from selenium.webdriver.common.keys import Keys9from selenium.webdriver.common.by import By10from selenium.webdriver.support.ui import Select11from webdriver_manager.chrome import ChromeDriverManager12 13def create_webdriver():14 chrome_options = Options()15 chrome_options.add_argument("--headless") # Run in headless mode16 chrome_options.add_argument("--window-size=1920,1080") # Set window size to 1920x108017 # Create the WebDriver instance with options18 driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=chrome_options)19 ## Webdriver wait20 wait = WebDriverWait(driver, 20)21 return driver, wait22 23##24## Webdriver wait25 26 27# Your code continues here...28 29 30def login_and_startup(driver, wait, user_login, pass_login):31 32 # Open the Qualtrics login page33 driver.get("https://anheuserbusch.co1.qualtrics.com/login")34 35 # Find the username field and enter the username36 username = driver.find_element(By.ID, "UserName")37 username.send_keys(user_login)38 39 # Find the password field and enter the password40 password = driver.find_element(By.ID, "UserPassword")41 password.send_keys(pass_login)42 43 # Find the login button and click it44 element = wait.until(EC.element_to_be_clickable((By.ID, "loginButton")))45 element.click()46 time.sleep(5)47 48 49def create_survey(driver, wait, test_var, current_iteration):50 # Now find the button to create a new Survey51 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-testid='profile-data-create-new-button']")))52 element.click()53 54 # Now select maxdiff survey55 element = wait.until(EC.element_to_be_clickable((By.ID, 'GuidedProjects_ProductPrioritizationMaxDiff')))56 element.click()57 58 # Now select the 'Get started' button using CSS Selector59 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-testid='Catalog.DetailsPane.CallToAction']")))60 element.click()61 62 # Creating the Survey name variable with the current iteration63 survey_name = f"{test_var} - Concept {current_iteration} - Maxdiff"64 # Locate the textbox and paste the survey name from the input variable65 textbox_element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-testid='Catalog.GetStartedFlow.Name']")))66 textbox_element.send_keys(survey_name)67 68 max_retries = 369 attempt = 070 71 while attempt < max_retries:72 try:73 # Now click the 'Create project' button74 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-testid='Catalog.GetStartedFlow.Create']")))75 element.click()76 time.sleep(5)77 break # Exit the loop if successful78 except Exception as e:79 attempt += 180 print(f"Attempt {attempt} failed: {e}")81 if attempt == max_retries:82 print("Max retries reached. Giving up.")83 84 85def define_features(driver, wait, test_var, features_list, current_iteration):86 # Clicking define features for MaxdiffSurvey87 # Wait for the button to be clickable and then click it88 time.sleep(2)89 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-testid='overview-step-define-features']")))90 element.click()91 92 # Now import the features based on the name of the concept being tested:93 # Click the 'import features' button94 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-testid='import-features-button']")))95 element.click()96 time.sleep(2)97 98 # Now paste into textbox the features and the survey concept being tested99 # Creating the test feature variable with the current iteration100 test_feature_name = f"{test_var} Concept {current_iteration}"101 features_list_full = features_list + [test_feature_name]102 features_string = ', '.join(features_list_full)103 104 # Now applying it to textbox105 textbox_element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-testid='copy-paste-attributes-input']")))106 textbox_element.send_keys(features_string)107 108 # Now wait a few seconds and click 'Import'109 time.sleep(0.5)110 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-testid='import-modal-import-button']")))111 element.click()112 time.sleep(3)113 114 115 116 117def add_images(driver, wait, beverages):118 for index, beverage in enumerate(beverages):119 feature = beverage.get('feature', '')120 testid = str(beverage.get('number', index)) # Ensure this is a string121 img_src = beverage.get('image_id', '')122 123 time.sleep(2)124 125 ## Add images to features in try block126 try:127 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, f"[data-testid='add-image-{index}-button']")))128 element.click()129 time.sleep(2)130 131 # Select the dropdown menu132 element = wait.until(EC.element_to_be_clickable((By.ID, 'image-library-dropdown')))133 element.click()134 time.sleep(2)135 136 # Locate the dropdown element using a XPATH selector137 element = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="image-library-dropdown-menu"]/div/div[3]')))138 element.click()139 140 # For the first image, wait 60 seconds141 if index == 0:142 time.sleep(60)143 144 # Now find the image by ID145 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, f'div > img[src*="{img_src}"]')))146 element.click()147 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.upload-button")))148 element.click()149 time.sleep(2)150 151 except Exception as e:152 print(f"Failed to add image for {feature}: {e}")153 # Click Cancel and try again 1 time before moving on to next drink154 try:155 element = wait.until(EC.element_to_be_clickable((By.XPATH, "//button[@type='button' and contains(@class, 'cancel-button') and not(contains(@data-testid, 'cancel-setup-button'))]")))156 element.click()157 print(f"Successfully clicked Cancel for {feature}")158 except Exception as cancel_e:159 print(f"Failed to click Cancel for {feature}: {cancel_e}")160 continue161 162 163 164def finish_features(driver, wait):165 time.sleep(2)166 # Click Display Tab167 element = wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id='conjoint-overview-react']/div/div[1]/div[2]/a")))168 element.click()169 time.sleep(1)170 171 # Add the specified text to the first box172 input_xpath = "//*[@id='conjoint-overview-react']/div/div[2]/div/div[2]/label[1]/input"173 input_element = wait.until(EC.presence_of_element_located((By.XPATH, input_xpath)))174 input_element.send_keys(Keys.CONTROL, 'a')175 input_element.send_keys(Keys.BACK_SPACE)176 input_element.send_keys("From the beers shown below, choose the one you would most prefer and least prefer purchasing.")177 time.sleep(1)178 179 # Move on to the 'Advanced' tab180 element = wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id='conjoint-overview-react']/div/div[1]/div[3]/a")))181 element.click()182 time.sleep(1)183 184 # Set the Maxdiff questions per respondent to 6185 input_xpath = "//*[@id='conjoint-overview-react']/div/div[2]/div/div[2]/div[1]/label/input"186 input_element = wait.until(EC.presence_of_element_located((By.XPATH, input_xpath)))187 input_element.send_keys(Keys.CONTROL, 'a')188 input_element.send_keys(Keys.BACK_SPACE)189 input_element.send_keys("6")190 time.sleep(1)191 192 # Click the Anchored Maxdiff Question switch193 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "label[data-testid='anchored-maxdiff-switch']")))194 element.click()195 time.sleep(1)196 197 198 199 # Change the dialogue per Joe's example200 dialogues = {201 "all-important-input": "All of these are appealing",202 "some-important-input": "Some of these are appealing",203 "none-important-input": "None of these are appealing"204 }205 206 for input_id, text in dialogues.items():207 input_xpath = f"//*[@id='{input_id}']"208 input_element = wait.until(EC.presence_of_element_located((By.XPATH, input_xpath)))209 input_element.send_keys(Keys.CONTROL, 'a')210 input_element.send_keys(Keys.BACK_SPACE)211 input_element.send_keys(text)212 time.sleep(0.5)213 214 # Save the changes215 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-testid='save-setup-button']")))216 element.click()217 time.sleep(15) # Wait for 60 seconds to ensure changes are saved218 219 220 221 222 223def survey_flow(driver, wait, current_iteration, extracted_string):224 time.sleep(10)225 # Navigate to the 'Survey' tab and then to 'Survey Flow'226 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '[data-testid="gw-tab-SURVEY"]')))227 element.click()228 element = wait.until(EC.element_to_be_clickable((By.ID, "tab-button-surveyflow")))229 element.click()230 231 # Zoom out if necessary to avoid bugs (uncomment if needed)232 # driver.execute_script("document.body.style.zoom='0.67'")233 234 # Add Embedded Data fields235 fields = ['opp', 'RISN', 'rid', 'gid', 'Original RID', 'Gender', 'TargetAge', 'maxdiffconcept', 'Race', 'Segmentation', 'uid', 'PID', 'sname', 'P', 'transaction_id', 'cintid', 'Quota Age', 'SVID', 'Data Cut Age']236 xpath_elements = ["//span[text()='Add a New Element Here']", "//*[@id='surveyflowembeddeddata']"]237 238 for xpath in xpath_elements:239 time.sleep(1)240 element = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))241 element.click()242 243 for field in fields:244 textbox_element = driver.find_element(By.ID, "InlineEditorElement")245 textbox_element.send_keys(field)246 textbox_element.send_keys(Keys.ENTER)247 248 # Set maxdiffconcept to the current concept being tested249 element = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="Flow"]/div[1]/div/div/div[7]/div/div[1]/div/div[1]/div[2]/div[1]/div/div[2]/div[8]/span')))250 element.click()251 252 ## This is annoying, but it requires a double click253 element = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="Flow"]/div[1]/div/div/div[7]/div/div[1]/div/div[1]/div[2]/div[1]/div/div[2]/div[8]/span')))254 element.click()255 textbox_element = driver.find_element(By.ID, "InlineEditorElement")256 textbox_element.clear()257 textbox_element.send_keys(str(current_iteration))258 259 # Add 'Show Block: Block 1' and 'Group Block: Do Not Delete 1'260 # ... (rest of the code for adding blocks and groups)261 ## Now add a new 'Show Block: Block 1'262 ## First click 'Add element Label'263 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'span.add-element-label')))264 element.click()265 266 ## Now click Showblock267 element = wait.until(EC.element_to_be_clickable((By.ID, 'surveyflowblock')))268 element.click()269 270 ## Now select the block options using the xpath271 element = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="Flow"]/div[1]/div/div/div[9]/div/div[1]/div/div[1]/div[2]/div[1]/div/select')))272 273 # Create a Select object274 select = Select(element)275 # Select the option with visible text 'Block 1'276 select.select_by_visible_text('Block 1')277 278 ## Now add a new 'Group Block: Do Not Delete 1'279 ## First click 'Add element Label'280 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'span.add-element-label')))281 element.click()282 283 ## Now selecting Group box284 element = wait.until(EC.element_to_be_clickable((By.ID, "surveyflowgroup")))285 element.click()286 287 ## Now click the Untitled Group name to rename it288 element = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="Flow"]/div[1]/div/div/div[11]/div/div[1]/div/div[1]/div[2]/div[1]/div/span[2]/strong[2]')))289 element.click()290 291 # Search for the input field with the value "Untitled Group"292 input_xpath = '//input[@value="Untitled Group"]'293 input_element = wait.until(EC.presence_of_element_located((By.XPATH, input_xpath)))294 295 ## Now selecting all in the textbox296 input_element.send_keys(Keys.CONTROL, 'a')297 input_element.send_keys(Keys.BACK_SPACE)298 input_element.send_keys("Do Not Delete")299 300 ## Now click 'Done'301 element = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="Flow"]/div[1]/div/div/div[11]/div/div[1]/div/div[1]/div[2]/div[1]/div/span[2]/span/a')))302 element.click()303 304 ## Now add a new element to the Do Not Delete Group just created305 element = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="Flow"]/div[1]/div/div/div[11]/div/div[3]/div/div[1]/div/div[1]/div/div[1]/div/div/a/span[2]')))306 element.click()307 308 ## Now selecting Embedded data box309 element = wait.until(EC.element_to_be_clickable((By.ID, "surveyflowembeddeddata")))310 element.click()311 312 ## Now naming this one 'mc'313 textbox_element = driver.find_element(By.ID, "InlineEditorElement")314 textbox_element.send_keys('mc')315 textbox_element.send_keys(Keys.ENTER)316 317 ## Now to set value of MC to 1318 element = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="Flow"]/div[1]/div/div/div[11]/div/div[3]/div/div[1]/div/div[1]/div[2]/div[1]/div/div[2]/div[1]/span')))319 element.click()320 321 ## Double clicking322 element = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="Flow"]/div[1]/div/div/div[11]/div/div[3]/div/div[1]/div/div[1]/div[2]/div[1]/div/div[2]/div[1]/span')))323 element.click()324 325 textbox_element = driver.find_element(By.ID, "InlineEditorElement")326 textbox_element.clear()327 textbox_element.send_keys("1")328 329 330 ## Now I need to click the first blank box and create the 'End of Survey' box331 ## First click Delete on Showblock1 at the top332 element = wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id='Flow']/div[1]/div/div/div[3]/div/div[1]/div/div[1]/div[3]/a[4]")))333 element.click()334 335 ## Now clicking 'Ok' on the delete message336 ## Now selecting Embedded data box337 element = wait.until(EC.element_to_be_clickable((By.ID, "alertDialogOKButton")))338 element.click()339 340 341 ## Now to create end of survey block342 ## First click the bottom Add a New Element Box343 element = wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id='Flow']/div[1]/div/div/div[11]/div/div[1]/div/div[1]/div/div[1]/div/div/a/span[2]")))344 element.click()345 346 ## Now selecting Embedded data box347 element = wait.until(EC.element_to_be_clickable((By.ID, "surveyflowendsurvey")))348 element.click()349 350 # Customize the End of Survey box with the modified link351 original_link = "https://ca1.qualtrics.com/jfe/form/SV_0VxeY04VySm5pLE?P=2&V=${e://Field/V}&rid=${e://Field/rid}&RISN=${e://Field/RISN}&gid=${e://Field/gid}&sname=${e://Field/sname}&uid=${e://Field/uid}&PID=${e://Field/PID}&psid=${e://Field/psid}&cintid=${e://Field/cintid}&ID=${e://Field/ID}&OriginalRID=${e://Field/OriginalRID}&Gender=${e://Field/Gender}&Race=${e://Field/Race}&Segmentation=${e://Field/Segmentation}&maxdiffconcept=${e://Field/maxdiffconcept}&transaction_id=${e://Field/transaction_id}&SVID=${e://Field/SVID}&Quota Age=${e://Field/Quota Age}&Data Cut Age=${e://Field/Data Cut Age}&Design=${e://Field/Design}"352 modified_link = original_link.replace('SV_0VxeY04VySm5pLE', extracted_string)353 # The string you want to replace 'SV_0VxeY04VySm5pLE' with354 355 # Replace the specific part of the link356 modified_link = original_link.replace('SV_0VxeY04VySm5pLE', extracted_string)357 358 ## Now with our modified link, we can Customize the End of Survey box359 element = wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id='Flow']/div[1]/div/div/div[11]/div/div[1]/div/div[1]/div[3]/span/a")))360 element.click()361 362 ## Now select Override Survey Options363 element = wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id='overrideOptions']")))364 element.click()365 366 ## Now Click Redirect to a URL367 element = wait.until(EC.element_to_be_clickable((By.ID, "SurveyTerminationRedirect")))368 element.click()369 370 371 ## Now input into the textbox the modified link we created372 textbox_element = driver.find_element(By.XPATH, "//*[@id='customizeContent']/div/div/input[4]")373 textbox_element.clear()374 textbox_element.send_keys(modified_link)375 376 element = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[clickcallback='QSF_ElementView.customizeSave']")))377 element.click()378 379 ## Now apply and move back to the mains creen, and the program is complete380 element = wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id='SurveyEditorContainer']/div[2]/div/div[3]/div[4]/div/button[2]")))381 element.click()382 383 384 