Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selenium: Payment Verification tests #4318

Merged
merged 29 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0adb10b
Init
szymon-kellton Oct 11, 2024
9c4f1ae
Fix test_payment_plan_delete
szymon-kellton Oct 14, 2024
4878261
Fixtures
szymon-kellton Oct 14, 2024
fcb3ad2
Added tests
szymon-kellton Oct 17, 2024
56e8a90
Merge remote-tracking branch 'origin/develop' into selenium/payment_v…
szymon-kellton Oct 17, 2024
4f8c93a
Black
szymon-kellton Oct 17, 2024
1dfc784
Add tests
szymon-kellton Oct 18, 2024
0ab4670
Merge remote-tracking branch 'origin/develop' into selenium/payment_v…
szymon-kellton Oct 18, 2024
b70d344
Add tests
szymon-kellton Oct 21, 2024
11c1e18
Merge remote-tracking branch 'origin/develop' into selenium/payment_v…
szymon-kellton Oct 22, 2024
8919e64
Fix test_payment_verification_edit
szymon-kellton Oct 22, 2024
babe265
Add tests
szymon-kellton Oct 24, 2024
397fd94
Merge remote-tracking branch 'origin/develop' into selenium/payment_v…
szymon-kellton Oct 24, 2024
597c601
Add tests
szymon-kellton Oct 28, 2024
a267ae4
Merge remote-tracking branch 'origin/develop' into selenium/payment_v…
szymon-kellton Oct 29, 2024
c3707de
Add tests
szymon-kellton Oct 29, 2024
b53a45d
Add tests
szymon-kellton Oct 29, 2024
f05ca22
Add tests
szymon-kellton Oct 29, 2024
6daf3dc
black
szymon-kellton Oct 30, 2024
be2e150
black
szymon-kellton Oct 30, 2024
afa44db
Fix test_grievance_tickets_create_new_ticket_Data_Change_Add_Individu…
szymon-kellton Oct 30, 2024
4faad3e
Fix test_grievance_tickets_create_new_ticket_Data_Change_Add_Individu…
szymon-kellton Oct 31, 2024
69e8257
Merge remote-tracking branch 'origin/develop' into selenium/payment_v…
szymon-kellton Oct 31, 2024
d9903a3
yarn test -u
szymon-kellton Oct 31, 2024
20d9db6
yarn test -u
szymon-kellton Oct 31, 2024
911e8d2
yarn lint --fix
szymon-kellton Oct 31, 2024
39e6b63
Fix test_payment_verification_xlsx_partially_successful
szymon-kellton Oct 31, 2024
c934f06
Fix test_smoke_new_payment_plan
szymon-kellton Oct 31, 2024
0cad8b5
Fixes after review
szymon-kellton Nov 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export function PaymentGrievanceDetails({
{canApprovePaymentVerification &&
ticket.status === GRIEVANCE_TICKET_STATES.FOR_APPROVAL ? (
<Button
data-cy="grievance-approve"
onClick={() =>
confirm({
title: t('Approve'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ exports[`components/grievances/PaymentGrievanceDetails should render with data 1
</h6>
<button
class="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeMedium MuiButton-containedSizeMedium MuiButton-colorPrimary MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeMedium MuiButton-containedSizeMedium MuiButton-colorPrimary css-dl1jos-MuiButtonBase-root-MuiButton-root"
data-cy="grievance-approve"
tabindex="0"
type="button"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export function VerifyPaymentGrievance({
<Button
color="primary"
variant="contained"
data-cy="grievance-verify"
onClick={() => setVerifyManualDialogOpen(true)}
>
{t('Verify')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ exports[`components/grievances/VerifyPaymentGrievance should render with data 1`
>
<button
class="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeMedium MuiButton-containedSizeMedium MuiButton-colorPrimary MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeMedium MuiButton-containedSizeMedium MuiButton-colorPrimary css-dl1jos-MuiButtonBase-root-MuiButton-root"
data-cy="grievance-verify"
tabindex="0"
type="button"
>
Expand Down
19 changes: 10 additions & 9 deletions src/frontend/src/components/payments/CreateVerificationPlan.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,8 @@ export const CreateVerificationPlan = ({
variant="fullWidth"
aria-label="full width tabs example"
>
<Tab label={t('FULL LIST')} />
<Tab label={t('RANDOM SAMPLING')} />
<Tab data-cy="tab-full-list" label={t('FULL LIST')} />
<Tab data-cy="tab-random-sampling" label={t('RANDOM SAMPLING')} />
</StyledTabs>
</TabsContainer>
<TabPanel value={selectedTab} index={0}>
Expand Down Expand Up @@ -340,10 +340,11 @@ export const CreateVerificationPlan = ({
name="verificationChannel"
label={t('Verification Channel')}
style={{ flexDirection: 'row' }}
data-cy="checkbox-verification-channel"
choices={[
{ value: 'RAPIDPRO', name: 'RAPIDPRO' },
{ value: 'XLSX', name: 'XLSX' },
{ value: 'MANUAL', name: 'MANUAL' },
{ value: 'RAPIDPRO', name: 'RAPIDPRO', dataCy: 'radio-rapidpro' },
{ value: 'XLSX', name: 'XLSX', dataCy: 'radio-xlsx' },
{ value: 'MANUAL', name: 'MANUAL', dataCy: 'radio-manual' },
]}
component={FormikRadioGroup}
alignItems="center"
Expand Down Expand Up @@ -480,9 +481,9 @@ export const CreateVerificationPlan = ({
style={{ flexDirection: 'row' }}
alignItems="center"
choices={[
{ value: 'RAPIDPRO', name: 'RAPIDPRO' },
{ value: 'XLSX', name: 'XLSX' },
{ value: 'MANUAL', name: 'MANUAL' },
{ value: 'RAPIDPRO', name: 'RAPIDPRO', dataCy: 'radio-rapidpro' },
{ value: 'XLSX', name: 'XLSX', dataCy: 'radio-xlsx' },
{ value: 'MANUAL', name: 'MANUAL', dataCy: 'radio-manual' },
]}
component={FormikRadioGroup}
/>
Expand All @@ -508,7 +509,7 @@ export const CreateVerificationPlan = ({
</DialogContent>
<DialogFooter>
<DialogActions>
<Button onClick={() => setOpen(false)}>CANCEL</Button>
<Button data-cy="button-cancel" onClick={() => setOpen(false)}>CANCEL</Button>
<LoadingButton
loading={loading}
type="submit"
Expand Down
16 changes: 8 additions & 8 deletions src/frontend/src/components/payments/EditVerificationPlan.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,8 @@ export const EditVerificationPlan = ({
variant="fullWidth"
aria-label="full width tabs example"
>
<Tab label={t('FULL LIST')} />
<Tab label={t('RANDOM SAMPLING')} />
<Tab data-cy="tab-full-list" label={t('FULL LIST')} />
<Tab data-cy="tab-random-sampling" label={t('RANDOM SAMPLING')} />
</StyledTabs>
</TabsContainer>
<TabPanel value={selectedTab} index={0}>
Expand Down Expand Up @@ -351,9 +351,9 @@ export const EditVerificationPlan = ({
label={t('Verification Channel')}
style={{ flexDirection: 'row', alignItems: 'center' }}
choices={[
{ value: 'RAPIDPRO', name: 'RAPIDPRO' },
{ value: 'XLSX', name: 'XLSX' },
{ value: 'MANUAL', name: 'MANUAL' },
{ value: 'RAPIDPRO', name: 'RAPIDPRO', dataCy: 'radio-rapidpro' },
{ value: 'XLSX', name: 'XLSX', dataCy: 'radio-xlsx' },
{ value: 'MANUAL', name: 'MANUAL', dataCy: 'radio-manual' },
]}
component={FormikRadioGroup}
alignItems="center"
Expand Down Expand Up @@ -500,9 +500,9 @@ export const EditVerificationPlan = ({
}}
alignItems="center"
choices={[
{ value: 'RAPIDPRO', name: 'RAPIDPRO' },
{ value: 'XLSX', name: 'XLSX' },
{ value: 'MANUAL', name: 'MANUAL' },
{ value: 'RAPIDPRO', name: 'RAPIDPRO', dataCy: 'radio-rapidpro' },
{ value: 'XLSX', name: 'XLSX', dataCy: 'radio-xlsx' },
{ value: 'MANUAL', name: 'MANUAL', dataCy: 'radio-manual' },
]}
component={FormikRadioGroup}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export function VerificationPlanActions({
color="primary"
variant="outlined"
startIcon={<GetApp />}
data-cy="export-xlsx"
onClick={async () => {
try {
await mutateExport({
Expand Down Expand Up @@ -171,6 +172,7 @@ export function VerificationPlanActions({
<Button
color="primary"
variant="outlined"
data-cy="download-xlsx"
startIcon={<GetApp />}
>
{t('Download Xlsx')}
Expand All @@ -180,7 +182,7 @@ export function VerificationPlanActions({
)}

{canImport && (
<Box p={2}>
<Box p={2} data-cy="import-xlsx">
<ImportXlsx
paymentVerificationPlanId={verificationPlan.id}
cashOrPaymentPlanId={planNode.id}
Expand All @@ -204,6 +206,7 @@ export function VerificationPlanActions({
loading={loadingInvalid}
color="primary"
variant="outlined"
data-cy="button-mark-as-invalid"
onClick={async () => {
try {
await mutateInvalid({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function VerificationPlanDetails({
<Container>
<Box display="flex" alignItems="center" justifyContent="space-between">
<Title>
<Typography variant="h6">
<Typography data-cy={`verification-plan-${verificationPlan.unicefId}`} variant="h6">
{t('Verification Plan')} #{verificationPlan.unicefId}
<AdminButton adminUrl={verificationPlan.adminUrl} sx={{ ml: 2 }} />
</Typography>
Expand Down
4 changes: 2 additions & 2 deletions src/frontend/src/components/payments/VerifyManual.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ export function VerifyManual({
label="Status"
style={{ flexDirection: 'row' }}
choices={[
{ value: 'RECEIVED', name: t('Received') },
{ value: 'NOT_RECEIVED', name: t('Not Received') },
{ value: 'RECEIVED', name: t('Received'), dataCy: 'choice-received' },
{ value: 'NOT_RECEIVED', name: t('Not Received'), dataCy: 'choice-not-received' },
]}
component={FormikRadioGroup}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,15 @@ export function FormikRadioGroup({
value: string;
optionLabel?: string | ReactElement;
name: string;
dataCy?: string;
}) => (
<Box p={2} mb={2} key={each.value}>
<Box display="flex" alignItems={alignItems}>
<Radio
color="primary"
value={each.value}
checked={field.value === each.value}
data-cy={each?.dataCy}
/>
{withGreyBox ? (
<GreyBox p={2}>
Expand Down
8 changes: 8 additions & 0 deletions tests/selenium/filters/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,3 +546,11 @@ def test_grievance_tickets_filters_of_households_and_individuals(
pageGrievanceTickets.getNavGrievance().click()
assert "Grievance Tickets" in pageGrievanceTickets.getGrievanceTitle().text
pageGrievanceTickets.getButtonNewTicket().click()

@pytest.mark.skip("ToDo")
def test_payment_verification_details_filters(
self,
pageGrievanceTickets: GrievanceTickets,
filters: Filters,
) -> None:
pageGrievanceTickets.getNavPaymentVerification().click()
22 changes: 19 additions & 3 deletions tests/selenium/helpers/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import Literal, Union

from selenium.common import NoSuchElementException
from selenium.common.exceptions import TimeoutException
from selenium.webdriver import Chrome, Keys
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
Expand Down Expand Up @@ -42,8 +43,6 @@ def get_elements(self, locator: str, element_type: str = By.CSS_SELECTOR, attemp
raise Exception("No elements found")

def wait_for(self, locator: str, element_type: str = By.CSS_SELECTOR, timeout: int = DEFAULT_TIMEOUT) -> WebElement:
from selenium.common.exceptions import TimeoutException

try:
return self._wait(timeout).until(EC.visibility_of_element_located((element_type, locator)))
except TimeoutException:
Expand All @@ -63,7 +62,14 @@ def wait_for_text_disappear(
def wait_for_text(
self, text: str, locator: str, element_type: str = By.CSS_SELECTOR, timeout: int = DEFAULT_TIMEOUT
) -> Union[Literal[False, True], bool]:
return self._wait(timeout).until(EC.text_to_be_present_in_element((element_type, locator), text))
try:
return self._wait(timeout).until(EC.text_to_be_present_in_element((element_type, locator), text))
except TimeoutException:
pass
raise NoSuchElementException(
f"Element: {text} not found in {locator}. Displayed text:"
f" {self.driver.find_element(element_type, locator).text}"
)

def wait_for_new_url(self, old_url: str, retry: int = 5) -> str:
for _ in range(retry):
Expand Down Expand Up @@ -171,6 +177,16 @@ def screenshot(
sleep(delay_sec)
self.driver.get_screenshot_as_file(os.path.join(f"{file_path}", f"{file_name}.{file_type}"))

def scroll(self, scroll_by: int = 600, wait_after_start_scrolling: int = 2, execute: int = 1) -> None:
for _ in range(execute):
self.driver.execute_script( # type: ignore
f"""
container = document.querySelector("div[data-cy='main-content']")
container.scrollBy(0,{scroll_by})
"""
)
sleep(wait_after_start_scrolling)

def get_value_of_attributes(self, attribute: str = "data-cy") -> None:
sleep(1)
ids = self.driver.find_elements(By.XPATH, f"//*[@{attribute}]")
Expand Down
9 changes: 9 additions & 0 deletions tests/selenium/page_object/base_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from selenium.webdriver.remote.webelement import WebElement

from hct_mis_api.apps.core.utils import encode_id_base64
from tests.selenium.helpers.helper import Common


Expand Down Expand Up @@ -56,6 +57,13 @@ class BaseComponents(Common):
# Text
globalProgramFilterText = "All Programmes"

def navigate_to_page(self, business_area_slug: str, program_id: str) -> None:
self.driver.get(self.get_page_url(business_area_slug, program_id))

def get_page_url(self, business_area_slug: str, program_id: str) -> str:
encoded_program_id = encode_id_base64(program_id, "Program")
return f"{self.driver.live_server.url}/{business_area_slug}/programs/{encoded_program_id}"

def getMainContent(self) -> WebElement:
return self.wait_for(self.mainContent)

Expand Down Expand Up @@ -190,6 +198,7 @@ def getBreadcrumbsChevronIcon(self) -> WebElement:
return self.wait_for(self.breadcrumbsChevronIcon)

def getArrowBack(self) -> WebElement:
self.scroll(scroll_by=-600)
return self.wait_for(self.arrowBack)

def getNavProgramLog(self) -> WebElement:
Expand Down
16 changes: 16 additions & 0 deletions tests/selenium/page_object/grievance/details_grievance_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ class GrievanceDetailsPage(BaseComponents):
logRow = 'div[data-cy="log-row"]'
paymentRecord = 'span[data-cy="payment-record"]'
labelGender = 'div[data-cy="label-GENDER"]'
grievanceVerify = '[data-cy="grievance-verify"]'
inputNewReceivedAmount = '[data-cy="input-newReceivedAmount"]'
buttonSubmit = 'button[data-cy="button-submit"]'
grievanceApprove = '[data-cy="grievance-approve"]'

# Texts
textTitle = "Ticket ID: "
Expand Down Expand Up @@ -676,6 +680,18 @@ def getButtonRotateImage(self) -> WebElement:
def getLinkShowPhoto(self) -> WebElement:
return self.wait_for(self.linkShowPhoto)

def getGrievanceVerify(self) -> WebElement:
return self.wait_for(self.grievanceVerify)

def getInputNewReceivedAmount(self) -> WebElement:
return self.wait_for(self.inputNewReceivedAmount)

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

def getGrievanceApprove(self) -> WebElement:
return self.wait_for(self.grievanceApprove)

def getLabelStatus(self) -> WebElement:
return self.wait_for(self.labelStatus)

Expand Down
2 changes: 2 additions & 0 deletions tests/selenium/page_object/payment_module/payment_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,11 @@ def getTablePagination(self) -> WebElement:
return self.wait_for(self.tablePagination)

def getRows(self) -> [WebElement]:
self.wait_for(self.rows)
return self.get_elements(self.rows)

def getRow(self, number: int) -> WebElement:
self.wait_for(self.rows)
try:
sleep(0.5)
return self.get_elements(self.rows)[number]
Expand Down
11 changes: 11 additions & 0 deletions tests/selenium/page_object/payment_verification/payment_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class PaymentRecord(BaseComponents):
labelFsp = 'div[data-cy="label-FSP"]'
buttonSubmit = 'button[data-cy="button-submit"]'
inputReceivedamount = 'input[data-cy="input-receivedAmount"]'
choiceNotReceived = '[data-cy="choice-not-received"]'

def getInputReceivedamount(self) -> WebElement:
return self.wait_for(self.inputReceivedamount)
Expand All @@ -52,9 +53,16 @@ def getButtonEdPlan(self) -> WebElement:
def getLabelStatus(self) -> [WebElement]:
return self.get_elements(self.labelStatus)

def getStatus(self) -> [WebElement]:
self.wait_for(self.statusContainer)
return self.get_elements(self.statusContainer)

def getStatusContainer(self) -> WebElement:
return self.wait_for(self.statusContainer)

def waitForStatusContainer(self, status: str) -> []:
return self.wait_for_text(status, self.statusContainer)

def getLabelHousehold(self) -> WebElement:
return self.wait_for(self.labelHousehold)

Expand Down Expand Up @@ -111,3 +119,6 @@ def getLabelFsp(self) -> WebElement:

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

def getChoiceNotReceived(self) -> WebElement:
return self.wait_for(self.choiceNotReceived)
Loading
Loading