civicrm-update-tester/main.py

156 lines
5.8 KiB
Python

import os
import re
import csv
import urllib.parse as urlparse
from urllib.parse import parse_qs
import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
class BaseTester:
BASE_URL = "https://crm-dev.caat.org.uk/"
USERNAME = "roxie"
PASSWORD = ""
def __init__(self):
firefox_options = webdriver.FirefoxOptions()
firefox_options.headless = True
self.browser = webdriver.Firefox(options=firefox_options)
self.wait = WebDriverWait(self.browser, 20)
def login(self):
""" Login to civicrm so we can continue with the proper cookies """
self.browser.get(self.BASE_URL)
username = self.browser.find_element_by_id("edit-name")
password = self.browser.find_element_by_id("edit-pass")
submit = self.browser.find_element_by_id("edit-submit")
username.send_keys(self.USERNAME)
password.send_keys(self.PASSWORD)
submit.click()
# Wait for the js elements load so we know the cookies are good.
# Waits for "Recent Items" part of sidebar which is unique when logged in
self.wait.until(
EC.visibility_of_element_located((By.ID, "block-civicrm-2"))
)
def logout(self):
self.browser.get(self.BASE_URL + "/user/logout")
# Wait for the next page to load to finish logging out
self.wait.until(
EC.visibility_of_element_located((By.ID, "tabs-wrapper"))
)
def find_element_by_id(self, *args, **kwargs):
return self.browser.find_element_by_id(*args, **kwargs)
def find_element_by_css_selector(self, *args, **kwargs):
return self.browser.find_element_by_css_selector(*args, **kwargs)
def wait_until_visible(self, locator):
return self.wait.until(EC.visibility_of_element_located(locator))
class ContactExport(BaseTester):
def __init__(self):
super().__init__()
self.search_url = self.BASE_URL + "/civicrm/contact/search"
self.contact_selectall_id = "CIVICRM_QFID_ts_all_4"
self.contact_dropdown_id = "select2-chosen-4"
self.contact_exportoption_id = "select2-result-label-15"
def download_csv(self):
session_cookie = {}
for cookie in self.browser.get_cookies():
if re.findall(r"^SSESS.*", cookie.get("name")):
session_cookie = cookie
if not session_cookie:
print("NO SESSION COOKIE FOUND. Are you logged in?")
raise RuntimeError("No session cookie found.")
session = requests.Session()
session.cookies.update(
{session_cookie["name"]: session_cookie["value"]}
)
qf_key = self.get_export_id()
data = {
"qfKey": qf_key,
"entryURL": self.BASE_URL + "/civicrm/contact/search",
"_qf_Select_next": "Continue",
"exportOption": 1,
"mergeOption": 0,
"postal_greeting": 1,
"addressee": 1,
}
req = session.request(
"POST", self.BASE_URL + "/civicrm/contact/search", data=data
)
return req
def calculate_exported_contacts_number(self):
req = self.download_csv()
file_name = "/tmp/exportedRecords.csv"
with open(file_name, "w") as csv_file:
csv_file.write(req.text)
with open(file_name, "r") as csv_file:
# Dict reader should remove headers
exported_csv = csv.DictReader(csv_file)
exported_number_exports = sum(1 for row in exported_csv)
os.remove(file_name)
return exported_number_exports
def get_export_id(self) -> str:
export_page_url = self.browser.current_url
parsed = urlparse.urlparse(export_page_url)
return parse_qs(parsed.query)['qfKey']
def test(self, search_term: str):
try:
self.login()
self.browser.get(self.search_url)
search_box = self.find_element_by_id("sort_name")
search_box.send_keys(search_term)
search_box.send_keys(Keys.ENTER)
self.wait_until_visible(
(By.ID, "alpha-filter")
) #wait for table to load
results_text = self.find_element_by_css_selector(
".form-layout-compressed > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(2) > label:nth-child(2)"
).text
matches = re.findall(
r"(\d+)", results_text
) # Should just be one match in normal cases
result_no = int(matches[0])
self.find_element_by_id(self.contact_selectall_id).click()
self.find_element_by_id(self.contact_dropdown_id).click()
self.find_element_by_id(self.contact_exportoption_id).click()
self.wait_until_visible((By.CSS_SELECTOR, ".crm-block"))
req = self.download_csv()
exported_number_exports = self.calculate_exported_contacts_number()
if exported_number_exports == (result_no):
print(
"TEST PASSED: Number of expected contact exports for '{}' matches actual number of exports - Expected: {}, Actual: {}"
.format(search_term, result_no, exported_number_exports)
)
else:
print(
"TEST FAILED: Number of expected contact exports for '{}' WAS NOT EQUAL to actual number of exports - Expected: {}, Actual: {}"
.format(search_term, result_no, exported_number_exports)
)
finally:
self.logout()
self.browser.close()
if __name__ == "__main__":
ContactExport().test("John")