2021-01-04 19:42:17 +00:00
|
|
|
import os
|
2020-12-29 15:12:31 +00:00
|
|
|
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
|
|
|
|
|
2021-01-04 19:42:17 +00:00
|
|
|
|
|
|
|
class BaseTester:
|
|
|
|
BASE_URL = "https://crm-dev.caat.org.uk/"
|
|
|
|
USERNAME = "roxie"
|
|
|
|
PASSWORD = ""
|
|
|
|
|
|
|
|
def __init__(self):
|
2021-01-15 11:37:26 +00:00
|
|
|
firefox_options = webdriver.FirefoxOptions()
|
|
|
|
firefox_options.headless = True
|
|
|
|
self.browser = webdriver.Firefox(options=firefox_options)
|
2021-01-04 19:42:17 +00:00
|
|
|
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.
|
2021-01-15 10:52:21 +00:00
|
|
|
# Waits for "Recent Items" part of sidebar which is unique when logged in
|
2021-01-04 19:42:17 +00:00
|
|
|
self.wait.until(
|
2021-01-15 10:52:21 +00:00
|
|
|
EC.visibility_of_element_located((By.ID, "block-civicrm-2"))
|
2020-12-29 15:12:31 +00:00
|
|
|
)
|
2021-01-04 19:42:17 +00:00
|
|
|
|
|
|
|
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"))
|
2020-12-29 15:12:31 +00:00
|
|
|
)
|
|
|
|
|
2021-01-04 19:42:17 +00:00
|
|
|
def find_element_by_id(self, *args, **kwargs):
|
|
|
|
return self.browser.find_element_by_id(*args, **kwargs)
|
2020-12-29 15:12:31 +00:00
|
|
|
|
2021-01-04 19:42:17 +00:00
|
|
|
def find_element_by_css_selector(self, *args, **kwargs):
|
|
|
|
return self.browser.find_element_by_css_selector(*args, **kwargs)
|
2020-12-29 15:12:31 +00:00
|
|
|
|
2021-01-04 19:42:17 +00:00
|
|
|
def wait_until_visible(self, locator):
|
|
|
|
return self.wait.until(EC.visibility_of_element_located(locator))
|
2020-12-29 15:12:31 +00:00
|
|
|
|
|
|
|
|
2021-01-04 19:42:17 +00:00
|
|
|
class ContactExport(BaseTester):
|
|
|
|
def __init__(self):
|
|
|
|
super().__init__()
|
2021-01-15 11:36:46 +00:00
|
|
|
self.search_url = self.BASE_URL + "/civicrm/contact/search"
|
2021-01-04 19:42:17 +00:00
|
|
|
|
|
|
|
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,
|
2021-01-15 11:36:46 +00:00
|
|
|
"entryURL": self.BASE_URL + "/civicrm/contact/search",
|
2021-01-04 19:42:17 +00:00
|
|
|
"_qf_Select_next": "Continue",
|
|
|
|
"exportOption": 1,
|
|
|
|
"mergeOption": 0,
|
|
|
|
"postal_greeting": 1,
|
|
|
|
"addressee": 1,
|
|
|
|
}
|
|
|
|
req = session.request(
|
2021-01-15 11:36:46 +00:00
|
|
|
"POST", self.BASE_URL + "/civicrm/contact/search", data=data
|
2021-01-04 19:42:17 +00:00
|
|
|
)
|
|
|
|
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")
|