Skip to content

Commit

Permalink
Merge branch 'develop' into grievance_na_upd
Browse files Browse the repository at this point in the history
  • Loading branch information
pavlo-mk authored Jul 12, 2024
2 parents 4faa648 + 36a0e53 commit 77182cb
Show file tree
Hide file tree
Showing 13 changed files with 410 additions and 35 deletions.
4 changes: 4 additions & 0 deletions backend/selenium_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ def driver() -> Chrome:
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--enable-logging")
chrome_options.add_argument("--window-size=1920,1080")
if not os.path.exists("./report/downloads/"):
os.makedirs("./report/downloads/")
prefs = {"download.default_directory": "./report/downloads/"}
chrome_options.add_experimental_option("prefs", prefs)
yield webdriver.Chrome(options=chrome_options)


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
from datetime import timedelta

from django.utils import timezone

import pytest
from page_object.grievance.details_grievance_page import GrievanceDetailsPage
from page_object.grievance.grievance_dashboard import GrievanceDashboard
from page_object.grievance.grievance_tickets import GrievanceTickets

from hct_mis_api.apps.account.models import User
from hct_mis_api.apps.core.models import BusinessArea
Expand Down Expand Up @@ -42,10 +48,40 @@ def add_grievances() -> None:
GrievanceTicket._meta.get_field("created_at").auto_now_add = True


@pytest.fixture
def grievances() -> [GrievanceTicket]:
GrievanceTicket._meta.get_field("created_at").auto_now_add = False
GrievanceTicket._meta.get_field("updated_at").auto_now = False
grievances = list()
grievances.append(
generate_grievance(
created_at=str(timezone.now() - timedelta(days=20)),
updated_at=str(timezone.now()),
status=GrievanceTicket.STATUS_NEW,
)
)
grievances.append(
generate_grievance(
created_at=str(timezone.now() - timedelta(days=40)),
status=GrievanceTicket.STATUS_NEW,
)
)
grievances.append(
generate_grievance(
created_at=str(timezone.now() - timedelta(days=60)),
status=GrievanceTicket.STATUS_NEW,
category=GrievanceTicket.CATEGORY_NEEDS_ADJUDICATION,
)
)
GrievanceTicket._meta.get_field("created_at").auto_now_add = True
GrievanceTicket._meta.get_field("updated_at").auto_now = True
return grievances


def generate_grievance(
unicef_id: str,
unicef_id: str = "GRV-0000001",
status: int = GrievanceTicket.STATUS_NEW,
category: int = GrievanceTicket.CATEGORY_POSITIVE_FEEDBACK,
category: int = GrievanceTicket.CATEGORY_REFERRAL,
created_by: User | None = None,
assigned_to: User | None = None,
business_area: BusinessArea | None = None,
Expand All @@ -54,11 +90,11 @@ def generate_grievance(
household_unicef_id: str = "HH-20-0000.0001",
updated_at: str = "2023-09-27T11:26:33.846Z",
created_at: str = "2022-04-30T09:54:07.827000",
) -> None:
) -> GrievanceTicket:
created_by = User.objects.first() if created_by is None else created_by
assigned_to = User.objects.first() if assigned_to is None else assigned_to
business_area = BusinessArea.objects.filter(slug="afghanistan").first() if business_area is None else business_area
GrievanceTicket.objects.create(
grievance_ticket = GrievanceTicket.objects.create(
**{
"business_area": business_area,
"unicef_id": unicef_id,
Expand All @@ -77,6 +113,14 @@ def generate_grievance(
}
)

from hct_mis_api.apps.grievance.models import TicketReferralDetails

TicketReferralDetails.objects.create(
ticket=grievance_ticket,
)

return grievance_ticket


@pytest.mark.usefixtures("login")
class TestSmokeGrievanceDashboard:
Expand Down Expand Up @@ -105,3 +149,49 @@ def test_smoke_grievance_dashboard(
"365 days" in pageGrievanceDashboard.getLabelizedFieldContainerTicketsAverageResolutionUserGenerated().text
)
GrievanceTicket._meta.get_field("updated_at").auto_now = True

def test_grievance_dashboard_happy_path(
self,
active_program: Program,
grievances: [GrievanceTicket],
pageGrievanceDashboard: GrievanceDashboard,
pageGrievanceTickets: GrievanceTickets,
pageGrievanceDetailsPage: GrievanceDetailsPage,
) -> None:
pageGrievanceTickets.getNavGrievance().click()
pageGrievanceDashboard.getNavGrievanceDashboard().click()
assert "Grievance Dashboard" in pageGrievanceDashboard.getPageHeaderTitle().text
assert "3" in pageGrievanceDashboard.getTotalNumberOfTicketsTopNumber().text
assert "1" in pageGrievanceDashboard.getLabelizedFieldContainerTotalNumberOfTicketsSystemGenerated().text
assert "2" in pageGrievanceDashboard.getLabelizedFieldContainerTotalNumberOfTicketsUserGenerated().text
assert "0" in pageGrievanceDashboard.getTotalNumberOfClosedTicketsTopNumber().text
assert "0" in pageGrievanceDashboard.getLabelizedFieldContainerTotalNumberOfClosedTicketsSystemGenerated().text
assert "0" in pageGrievanceDashboard.getLabelizedFieldContainerTotalNumberOfClosedTicketsUserGenerated().text
assert "0 days" in pageGrievanceDashboard.getTicketsAverageResolutionTopNumber().text
assert (
"0 days" in pageGrievanceDashboard.getLabelizedFieldContainerTicketsAverageResolutionSystemGenerated().text
)
assert "0 days" in pageGrievanceDashboard.getLabelizedFieldContainerTicketsAverageResolutionUserGenerated().text

pageGrievanceTickets.getNavGrievance().click()
pageGrievanceTickets.getTicketListRow()[0].click()
pageGrievanceDetailsPage.getButtonAssignToMe().click()
pageGrievanceDetailsPage.getButtonSetInProgress().click()
pageGrievanceDetailsPage.getButtonCloseTicket().click()
pageGrievanceTickets.getButtonConfirm().click()
pageGrievanceTickets.getNavGrievance().click()
pageGrievanceTickets.getNavGrievance().click()
pageGrievanceDashboard.getNavGrievanceDashboard().click()
assert "3" in pageGrievanceDashboard.getTotalNumberOfTicketsTopNumber().text
assert "1" in pageGrievanceDashboard.getLabelizedFieldContainerTotalNumberOfTicketsSystemGenerated().text
assert "2" in pageGrievanceDashboard.getLabelizedFieldContainerTotalNumberOfTicketsUserGenerated().text
assert "0" in pageGrievanceDashboard.getLabelizedFieldContainerTotalNumberOfClosedTicketsSystemGenerated().text
assert "1" in pageGrievanceDashboard.getLabelizedFieldContainerTotalNumberOfClosedTicketsUserGenerated().text
assert "20.00 days" in pageGrievanceDashboard.getTicketsAverageResolutionTopNumber().text
assert (
"0 days" in pageGrievanceDashboard.getLabelizedFieldContainerTicketsAverageResolutionSystemGenerated().text
)
assert (
"20 days" in pageGrievanceDashboard.getLabelizedFieldContainerTicketsAverageResolutionUserGenerated().text
)
assert "1" in pageGrievanceDashboard.getTotalNumberOfClosedTicketsTopNumber().text
18 changes: 14 additions & 4 deletions backend/selenium_tests/helpers/date_time_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,30 @@


class FormatTime:
def __init__(self, day: int, month: int, year: int, hour: int = 0, minute: int = 0):
def __init__(
self,
day: int = 0,
month: int = 0,
year: int = 0,
hour: int = 0,
minute: int = 0,
time: datetime | None = None,
):
self._datetime = time
self.day = day
self.month = month
self.year = year
self.hour = hour
self.minute = minute
self.datetime = datetime(year, month, day, hour, minute)
if self.year != 0:
self._datetime = datetime(self.year, self.month, self.day, self.hour, self.minute)

@property
def numerically_formatted_date(self) -> str:
# date format YYYY-MM-DD
return str(self.datetime.strftime("%Y-%m-%d"))
return str(self._datetime.strftime("%Y-%m-%d"))

@property
def date_in_text_format(self) -> str:
# date format -d Mon YYYY
return str(self.datetime.strftime("%-d %b %Y"))
return str(self._datetime.strftime("%-d %b %Y"))
6 changes: 4 additions & 2 deletions backend/selenium_tests/helpers/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,10 @@ def check_page_after_click(self, button: WebElement, url_fragment: str) -> None:
button.click()
assert url_fragment in self.wait_for_new_url(programme_creation_url).split("/")[-1]

def upload_file(self, upload_file: str, xpath: str = "//input[@type='file']") -> None:
self._wait().until(EC.presence_of_element_located((By.XPATH, xpath))).send_keys(upload_file)
def upload_file(
self, upload_file: str, xpath: str = "//input[@type='file']", timeout: int = DEFAULT_TIMEOUT
) -> None:
self._wait(timeout).until(EC.presence_of_element_located((By.XPATH, xpath))).send_keys(upload_file)

def select_option_by_name(self, optionName: str) -> None:
selectOption = f'li[data-cy="select-option-{optionName}"]'
Expand Down
13 changes: 13 additions & 0 deletions backend/selenium_tests/page_object/base_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class BaseComponents(Common):
globalProgramFilterSearchButton = 'button[data-cy="search-icon"]'
globalProgramFilterClearButton = 'button[data-cy="clear-icon"]'
rows = 'tr[role="checkbox"]'
alert = '[role="alert"]'
breadcrumbsChevronIcon = 'svg[data-cy="breadcrumbs-chevron-icon"]'
arrowBack = 'div[data-cy="arrow_back"]'

Expand Down Expand Up @@ -188,6 +189,18 @@ def getNavProgramLog(self) -> WebElement:
def getRows(self) -> [WebElement]:
return self.get_elements(self.rows)

def getAlert(self) -> WebElement:
self.wait_for(self.alert)
return self.wait_for(self.alert)

def checkAlert(self, text: str) -> None:
self.getAlert()
for _ in range(10):
if text in self.getAlert().text:
break
sleep(1)
assert text in self.getAlert().text

def waitForNumberOfRows(self, number: int) -> bool:
for _ in range(5):
if len(self.getRows()) == number:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,14 @@ def getPageHeaderContainer(self) -> WebElement:
def getTitle(self) -> WebElement:
return self.wait_for(self.title)

def getButtonCloseTicket(self) -> WebElement:
return self.wait_for(self.buttonCloseTicket)

def getButtonAssignToMe(self) -> WebElement:
return self.wait_for(self.buttonAssignToMe)

def getButtonCloseTicket(self) -> WebElement:
return self.wait_for(self.buttonCloseTicket)
def getButtonSetInProgress(self) -> WebElement:
return self.wait_for(self.buttonSetInProgress)

def getButtonSendBack(self) -> WebElement:
return self.wait_for(self.buttonSendBack)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class GrievanceTickets(BaseComponents):
familyName = 'li[data-value="full_name"]'
tabSystemGenerated = 'button[data-cy="tab-SYSTEM-GENERATED"]'
tabUserGenerated = 'button[data-cy="tab-USER-GENERATED"]'
buttonCloseTicket = 'button[data-cy="button-close-ticket"]'
buttonConfirm = 'button[data-cy="button-confirm"]'
creationDateFromFilter = 'div[data-cy="filters-creation-date-from"]'
creationDateToFilter = 'div[data-cy="filters-creation-date-to"]'
statusFilter = 'div[data-cy="filters-status"]'
Expand Down Expand Up @@ -210,3 +212,9 @@ def getButtonSetUrgency(self) -> WebElement:

def getButtonAddNote(self) -> WebElement:
return self.wait_for(self.buttonAddNote)

def getButtonCloseTicket(self) -> WebElement:
return self.wait_for(self.buttonCloseTicket)

def getButtonConfirm(self) -> WebElement:
return self.wait_for(self.buttonConfirm)
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from page_object.base_components import BaseComponents
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webelement import WebElement


Expand Down Expand Up @@ -30,16 +31,18 @@ def getSelectTargetingid(self) -> WebElement:
return self.wait_for(self.selectTargetingid)

def getInputStartDate(self) -> WebElement:
return self.wait_for(self.inputStartDate)
self.wait_for(self.inputStartDate)
return self.wait_for(self.inputStartDate).find_elements(By.TAG_NAME, "input")[0]

def getInputEndDate(self) -> WebElement:
return self.wait_for(self.inputEndDate)
self.wait_for(self.inputEndDate)
return self.wait_for(self.inputEndDate).find_elements(By.TAG_NAME, "input")[0]

def getInputCurrency(self) -> WebElement:
return self.wait_for(self.inputCurrency)

def getInputDispersionStartDate(self) -> WebElement:
return self.wait_for(self.inputDispersionStartDate)
return self.wait_for(self.inputDispersionStartDate).find_elements(By.TAG_NAME, "input")[0]

def getInputDispersionEndDate(self) -> WebElement:
return self.wait_for(self.inputDispersionEndDate)
return self.wait_for(self.inputDispersionEndDate).find_elements(By.TAG_NAME, "input")[0]
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from time import sleep

from page_object.base_components import BaseComponents
from selenium.webdriver.remote.webelement import WebElement

Expand All @@ -8,6 +10,7 @@ class PaymentModuleDetails(BaseComponents):
ppUnicefId = 'span[data-cy="pp-unicef-id"]'
statusContainer = 'div[data-cy="status-container"]'
buttonExportXlsx = 'button[data-cy="button-export-xlsx"]'
buttonDownloadXlsx = 'a[data-cy="button-download-xlsx"]'
labelCreatedBy = 'div[data-cy="label-Created By"]'
labelProgramme = 'div[data-cy="label-Programme"]'
labelTargetPopulation = 'div[data-cy="label-Target Population"]'
Expand Down Expand Up @@ -40,6 +43,27 @@ class PaymentModuleDetails(BaseComponents):
labelPending = 'div[data-cy="label-Pending"]'
labelNumberOfPayments = 'div[data-cy="label-Number of payments"]'
labelReconciled = 'div[data-cy="label-Reconciled"]'
labelTotalEntitledQuantity = 'div[data-cy="label-Total Entitled Quantity"]'
buttonLockPlan = 'button[data-cy="button-lock-plan"'
buttonSubmit = 'button[data-cy="button-submit"]'
inputEntitlementFormula = 'div[data-cy="input-entitlement-formula"]'
buttonApplySteficon = 'button[data-cy="button-apply-steficon"]'
selectDeliveryMechanism = 'div[data-cy="select-deliveryMechanisms[0].deliveryMechanism"]'
selectDeliveryMechanismsFSP = 'div[data-cy="select-deliveryMechanisms[0].fsp"]'
buttonNextSave = 'button[data-cy="button-next-save"]'
buttonSendForApproval = 'button[data-cy="button-send-for-approval"]'
buttonApprove = 'button[data-cy="button-approve"]'
buttonAuthorize = 'button[data-cy="button-authorize"]'
buttonMarkAsReleased = 'button[data-cy="button-mark-as-released"]'
buttonUploadReconciliationInfo = 'button[data-cy="button-import"]'
buttonImportSubmit = 'button[data-cy="button-import-submit"]'
errorsContainer = 'div[data-cy="errors-container"]'

def getButtonLockPlan(self) -> WebElement:
return self.wait_for(self.buttonLockPlan)

def getButtonSubmit(self) -> WebElement:
return self.wait_for(self.buttonSubmit)

def getPageHeaderContainer(self) -> WebElement:
return self.wait_for(self.pageHeaderContainer)
Expand All @@ -56,6 +80,18 @@ def getStatusContainer(self) -> WebElement:
def getButtonExportXlsx(self) -> WebElement:
return self.wait_for(self.buttonExportXlsx)

def getButtonDownloadXlsx(self) -> WebElement:
return self.wait_for(self.buttonDownloadXlsx)

def getButtonUploadReconciliationInfo(self) -> WebElement:
return self.wait_for(self.buttonUploadReconciliationInfo)

def getErrorsContainer(self) -> WebElement:
return self.wait_for(self.errorsContainer)

def getButtonImportSubmit(self) -> WebElement:
return self.wait_for(self.buttonImportSubmit)

def getLabelCreatedBy(self) -> WebElement:
return self.wait_for(self.labelCreatedBy)

Expand Down Expand Up @@ -151,3 +187,40 @@ def getLabelNumberOfPayments(self) -> WebElement:

def getLabelReconciled(self) -> WebElement:
return self.wait_for(self.labelReconciled)

def getLabelTotalEntitledQuantity(self) -> WebElement:
return self.wait_for(self.labelTotalEntitledQuantity)

def getInputEntitlementFormula(self) -> WebElement:
return self.wait_for(self.inputEntitlementFormula)

def getButtonApplySteficon(self) -> WebElement:
return self.wait_for(self.buttonApplySteficon)

def getSelectDeliveryMechanism(self) -> WebElement:
return self.wait_for(self.selectDeliveryMechanism)

def getSelectDeliveryMechanismFSP(self) -> WebElement:
return self.wait_for(self.selectDeliveryMechanismsFSP)

def getButtonNextSave(self) -> WebElement:
return self.wait_for(self.buttonNextSave)

def getButtonSendForApproval(self) -> WebElement:
return self.wait_for(self.buttonSendForApproval)

def getButtonApprove(self) -> WebElement:
return self.wait_for(self.buttonApprove)

def getButtonAuthorize(self) -> WebElement:
return self.wait_for(self.buttonAuthorize)

def getButtonMarkAsReleased(self) -> WebElement:
return self.wait_for(self.buttonMarkAsReleased)

def checkStatus(self, status: str) -> None:
for _ in range(30):
if status == self.getStatusContainer().text:
break
sleep(1)
assert status in self.getStatusContainer().text
Loading

0 comments on commit 77182cb

Please sign in to comment.