From 96138c6cadc2e21b7c7aafe4412f5b96a53fcb13 Mon Sep 17 00:00:00 2001
From: Harsh-Microsoft
Date: Wed, 4 Jun 2025 11:53:20 +0530
Subject: [PATCH 1/4] added e2e test automation scripts and pipeline
---
.github/workflows/test-automation.yml | 144 ++++++++++
tests/e2e-test/.gitignore | 169 +++++++++++
tests/e2e-test/base/__init__.py | 0
tests/e2e-test/base/base.py | 10 +
tests/e2e-test/config/constants.py | 8 +
tests/e2e-test/pages/HomePage.py | 266 ++++++++++++++++++
tests/e2e-test/pages/__init__.py | 0
tests/e2e-test/pages/loginPage.py | 36 +++
tests/e2e-test/pytest.ini | 6 +
tests/e2e-test/readme.MD | 35 +++
tests/e2e-test/requirements.txt | 6 +
tests/e2e-test/testdata/ClaimForm_1.pdf | Bin 0 -> 214534 bytes
tests/e2e-test/testdata/FabrikamInvoice_1.pdf | Bin 0 -> 116738 bytes
tests/e2e-test/tests/__init__.py | 0
tests/e2e-test/tests/conftest.py | 53 ++++
.../tests/test_contentProcessing_gp_tc.py | 41 +++
16 files changed, 774 insertions(+)
create mode 100644 .github/workflows/test-automation.yml
create mode 100644 tests/e2e-test/.gitignore
create mode 100644 tests/e2e-test/base/__init__.py
create mode 100644 tests/e2e-test/base/base.py
create mode 100644 tests/e2e-test/config/constants.py
create mode 100644 tests/e2e-test/pages/HomePage.py
create mode 100644 tests/e2e-test/pages/__init__.py
create mode 100644 tests/e2e-test/pages/loginPage.py
create mode 100644 tests/e2e-test/pytest.ini
create mode 100644 tests/e2e-test/readme.MD
create mode 100644 tests/e2e-test/requirements.txt
create mode 100644 tests/e2e-test/testdata/ClaimForm_1.pdf
create mode 100644 tests/e2e-test/testdata/FabrikamInvoice_1.pdf
create mode 100644 tests/e2e-test/tests/__init__.py
create mode 100644 tests/e2e-test/tests/conftest.py
create mode 100644 tests/e2e-test/tests/test_contentProcessing_gp_tc.py
diff --git a/.github/workflows/test-automation.yml b/.github/workflows/test-automation.yml
new file mode 100644
index 00000000..ac3937ea
--- /dev/null
+++ b/.github/workflows/test-automation.yml
@@ -0,0 +1,144 @@
+name: Test Automation Content Processing
+
+on:
+ push:
+ branches:
+ - main
+ - dev
+ - migrate-test-automation
+ # paths:
+ # - 'tests/e2e-test/**'
+ schedule:
+ - cron: '0 13 * * *' # Runs at 1 PM UTC
+ workflow_dispatch:
+
+env:
+ # url: ${{ vars.CP_WEB_URL }}
+ url: https://ca-cps-7kptilcf2uq4-web.politefield-0ff1aa7e.francecentral.azurecontainerapps.io
+ accelerator_name: "Content Processing"
+
+jobs:
+ test:
+ permissions:
+ id-token: write
+ contents: read
+
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Set up Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: '3.12'
+
+ - name: Azure CLI Login
+ uses: azure/login@v2
+ with:
+ creds: '{"clientId":"${{ secrets.AZURE_CLIENT_ID }}","clientSecret":"${{ secrets.AZURE_CLIENT_SECRET }}","subscriptionId":"${{ secrets.AZURE_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.AZURE_TENANT_ID }}"}'
+
+ - name: Start Container App
+ id: start-container-app
+ uses: azure/cli@v2
+ with:
+ azcliversion: 'latest'
+ inlineScript: |
+ # az rest -m post -u "/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ vars.CP_RG }}/providers/Microsoft.App/containerApps/${{ vars.CP_CONTAINERAPP_PREFIX }}-app/start?api-version=2025-01-01"
+ # az rest -m post -u "/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ vars.CP_RG }}/providers/Microsoft.App/containerApps/${{ vars.CP_CONTAINERAPP_PREFIX }}-api/start?api-version=2025-01-01"
+ # az rest -m post -u "/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ vars.CP_RG }}/providers/Microsoft.App/containerApps/${{ vars.CP_CONTAINERAPP_PREFIX }}-web/start?api-version=2025-01-01"
+ az rest -m post -u "/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/rg-cps-gp-testautomation/providers/Microsoft.App/containerApps/ca-cps-7kptilcf2uq4-app/start?api-version=2025-01-01"
+ az rest -m post -u "/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/rg-cps-gp-testautomation/providers/Microsoft.App/containerApps/ca-cps-7kptilcf2uq4-api/start?api-version=2025-01-01"
+ az rest -m post -u "/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/rg-cps-gp-testautomation/providers/Microsoft.App/containerApps/ca-cps-7kptilcf2uq4-web/start?api-version=2025-01-01"
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install -r tests/e2e-test/requirements.txt
+
+ - name: Ensure browsers are installed
+ run: python -m playwright install --with-deps chromium
+
+ - name: Run tests(1)
+ id: test1
+ run: |
+ xvfb-run pytest --headed --html=report/report.html --self-contained-html
+ working-directory: tests/e2e-test
+ continue-on-error: true
+
+ - name: Sleep for 30 seconds
+ if: ${{ steps.test1.outcome == 'failure' }}
+ run: sleep 30s
+ shell: bash
+
+ - name: Run tests(2)
+ id: test2
+ if: ${{ steps.test1.outcome == 'failure' }}
+ run: |
+ xvfb-run pytest --headed --html=report/report.html --self-contained-html
+ working-directory: tests/e2e-test
+ continue-on-error: true
+
+ - name: Sleep for 60 seconds
+ if: ${{ steps.test2.outcome == 'failure' }}
+ run: sleep 60s
+ shell: bash
+
+ - name: Run tests(3)
+ id: test3
+ if: ${{ steps.test2.outcome == 'failure' }}
+ run: |
+ xvfb-run pytest --headed --html=report/report.html --self-contained-html
+ working-directory: tests/e2e-test
+
+ - name: Upload test report
+ id: upload_report
+ uses: actions/upload-artifact@v4
+ if: ${{ !cancelled() }}
+ with:
+ name: test-report
+ path: tests/e2e-test/report/*
+
+ - name: Send Notification
+ if: always()
+ run: |
+ RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
+ REPORT_URL=${{ steps.upload_report.outputs.artifact-url }}
+ IS_SUCCESS=${{ steps.test1.outcome == 'success' || steps.test2.outcome == 'success' || steps.test3.outcome == 'success' }}
+ # Construct the email body
+ if [ "$IS_SUCCESS" = "true" ]; then
+ EMAIL_BODY=$(cat <Dear Team,
We would like to inform you that the ${{ env.accelerator_name }} Test Automation process has completed successfully.
Run URL: ${RUN_URL}
Test Report: ${REPORT_URL}
Best regards,
Your Automation Team
",
+ "subject": "${{ env.accelerator_name }} Test Automation - Success"
+ }
+ EOF
+ )
+ else
+ EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the ${{ env.accelerator_name }} Test Automation process has encountered an issue and has failed to complete successfully.
Run URL: ${RUN_URL}
${OUTPUT}
Test Report: ${REPORT_URL}
Please investigate the matter at your earliest convenience.
Best regards,
Your Automation Team
",
+ "subject": "${{ env.accelerator_name }} Test Automation - Failure"
+ }
+ EOF
+ )
+ fi
+
+ # Send the notification
+ curl -X POST "${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}" \
+ -H "Content-Type: application/json" \
+ -d "$EMAIL_BODY" || echo "Failed to send notification"
+
+ - name: Stop Container App
+ if: always()
+ uses: azure/cli@v2
+ with:
+ azcliversion: 'latest'
+ inlineScript: |
+ # az rest -m post -u "/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ vars.CP_RG }}/providers/Microsoft.App/containerApps/${{ vars.CP_CONTAINERAPP_PREFIX }}-app/stop?api-version=2025-01-01"
+ # az rest -m post -u "/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ vars.CP_RG }}/providers/Microsoft.App/containerApps/${{ vars.CP_CONTAINERAPP_PREFIX }}-api/stop?api-version=2025-01-01"
+ # az rest -m post -u "/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ vars.CP_RG }}/providers/Microsoft.App/containerApps/${{ vars.CP_CONTAINERAPP_PREFIX }}-web/stop?api-version=2025-01-01"
+ az rest -m post -u "/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/rg-cps-gp-testautomation/providers/Microsoft.App/containerApps/ca-cps-7kptilcf2uq4-app/stop?api-version=2025-01-01"
+ az rest -m post -u "/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/rg-cps-gp-testautomation/providers/Microsoft.App/containerApps/ca-cps-7kptilcf2uq4-api/stop?api-version=2025-01-01"
+ az rest -m post -u "/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/rg-cps-gp-testautomation/providers/Microsoft.App/containerApps/ca-cps-7kptilcf2uq4-web/stop?api-version=2025-01-01"
+ az logout
\ No newline at end of file
diff --git a/tests/e2e-test/.gitignore b/tests/e2e-test/.gitignore
new file mode 100644
index 00000000..79644b65
--- /dev/null
+++ b/tests/e2e-test/.gitignore
@@ -0,0 +1,169 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+# in version control.
+# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
+.pdm.toml
+.pdm-python
+.pdm-build/
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+microsoft/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+# and can be added to the global gitignore or merged into this file. For a more nuclear
+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
+.idea/
+archive/
+report/
+screenshots/
+report.html
+assets/
+.vscode/
diff --git a/tests/e2e-test/base/__init__.py b/tests/e2e-test/base/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/e2e-test/base/base.py b/tests/e2e-test/base/base.py
new file mode 100644
index 00000000..5992ab6a
--- /dev/null
+++ b/tests/e2e-test/base/base.py
@@ -0,0 +1,10 @@
+class BasePage:
+ def __init__(self, page):
+ self.page = page
+
+ def scroll_into_view(self, locator):
+ reference_list = locator
+ locator.nth(reference_list.count() - 1).scroll_into_view_if_needed()
+
+ def is_visible(self, locator):
+ locator.is_visible()
diff --git a/tests/e2e-test/config/constants.py b/tests/e2e-test/config/constants.py
new file mode 100644
index 00000000..f5f4c9ac
--- /dev/null
+++ b/tests/e2e-test/config/constants.py
@@ -0,0 +1,8 @@
+import os
+
+from dotenv import load_dotenv
+
+load_dotenv()
+URL = os.getenv("url")
+if URL.endswith("/"):
+ URL = URL[:-1]
diff --git a/tests/e2e-test/pages/HomePage.py b/tests/e2e-test/pages/HomePage.py
new file mode 100644
index 00000000..ce091f44
--- /dev/null
+++ b/tests/e2e-test/pages/HomePage.py
@@ -0,0 +1,266 @@
+import os.path
+
+from base.base import BasePage
+from playwright.sync_api import expect
+
+
+class HomePage(BasePage):
+ TITLE_TEXT = "//span[normalize-space()='Processing Queue']"
+ SELECT_SCHEMA = "//input[@placeholder='Select Schema']"
+ IMPORT_CONTENT = "//button[normalize-space()='Import Content']"
+ REFRESH = "//button[normalize-space()='Refresh']"
+ BROWSE_FILES = "//button[normalize-space()='Browse Files']"
+ UPLOAD_BTN = "//button[normalize-space()='Upload']"
+ SUCCESS_MSG = "/div[@class='file-item']//*[name()='svg']"
+ CLOSE_BTN = "//button[normalize-space()='Close']"
+ STATUS = "//div[@role='cell']"
+ PROCESS_STEPS = "//button[@value='process-history']"
+ EXTRACT = "//span[normalize-space()='extract']"
+ MAP = "//span[normalize-space()='map']"
+ EVALUATE = "//span[normalize-space()='evaluate']"
+ EXTRACTED_RESULT = "//button[@value='extracted-results']"
+ COMMENTS = "//textarea"
+ SAVE_BTN = "//button[normalize-space()='Save']"
+ EDIT_CONFIRM = "//div[@class='jer-confirm-buttons']//div[1]"
+ SHIPPING_ADD_STREET = "//textarea[@id='shipping_address.street_textarea']"
+ DELETE_FILE = "//button[@aria-haspopup='menu']"
+
+ # INVOICE_JSON_ENTITIES
+ CUSTOMER_NAME = "//div[@id='customer_name_display']"
+ CUSTOMER_STREET = "//div[@id='customer_address.street_display']"
+ CUSTOMER_CITY = "//div[@id='customer_address.city_display']"
+ CUSTOMER_ZIP_CODE = "//div[@id='customer_address.postal_code_display']"
+ CUSTOMER_COUNTRY = "//div[@id='customer_address.country_display']"
+ SHIPPING_STREET = "//div[@id='shipping_address.street_display']"
+ SHIPPING_CITY = "//div[@id='shipping_address.city_display']"
+ SHIPPING_POSTAL_CODE = "//div[@id='shipping_address.postal_code_display']"
+ SHIPPING_COUNTRY = "//div[@id='shipping_address.country_display']"
+ PURCHASE_ORDER = "//div[@id='purchase_order_display']"
+ INVOICE_ID = "//div[@id='invoice_id_display']"
+ INVOICE_DATE = "//div[@id='invoice_date_display']"
+ payable_by = "//div[@id='payable_by_display']"
+ vendor_name = "//div[@id='vendor_name_display']"
+ v_street = "//div[@id='vendor_address.street_display']"
+ v_city = "//div[@id='vendor_address.city_display']"
+ v_state = "//div[@id='vendor_address.state_display']"
+ v_zip_code = "//div[@id='vendor_address.postal_code_display']"
+ vendor_tax_id = "//div[@id='vendor_tax_id_display']"
+ SUBTOTAL = "//span[normalize-space()='16859.1']"
+ TOTAL_TAX = "//span[normalize-space()='11286']"
+ INVOICE_TOTAL = "//span[normalize-space()='22516.08']"
+ PAYMENT_TERMS = "//div[@id='payment_terms_display']"
+ product_code1 = "//div[@id='items.0.product_code_display']"
+ p1_description = "//div[@id='items.0.description_display']"
+ p1_quantity = "//span[normalize-space()='163']"
+ p1_tax = "//span[normalize-space()='2934']"
+ p1_unit_price = "//span[normalize-space()='2.5']"
+ p1_total = "//span[normalize-space()='407.5']"
+
+ # PROPERTY_JSON_DATA
+
+ first_name = "//div[@id='policy_claim_info.first_name_display']"
+ last_name = "//div[@id='policy_claim_info.last_name_display']"
+ tel_no = "//div[@id='policy_claim_info.telephone_number_display']"
+ policy_no = "//div[@id='policy_claim_info.policy_number_display']"
+ coverage_type = "//div[@id='policy_claim_info.coverage_type_display']"
+ claim_number = "//div[@id='policy_claim_info.claim_number_display']"
+ policy_effective_date = (
+ "//div[@id='policy_claim_info.policy_effective_date_display']"
+ )
+ policy_expiration_date = (
+ "//div[@id='policy_claim_info.policy_expiration_date_display']"
+ )
+ damage_deductible = "//span[normalize-space()='1000']"
+ damage_deductible_currency = (
+ "//div[@id='policy_claim_info.damage_deductible_currency_display']"
+ )
+ date_of_damage_loss = "//div[@id='policy_claim_info.date_of_damage_loss_display']"
+ time_of_loss = "//div[@id='policy_claim_info.time_of_loss_display']"
+ date_prepared = "//div[@id='policy_claim_info.date_prepared_display']"
+ item = "//div[@id='property_claim_details.0.item_display']"
+ description = "//div[@id='property_claim_details.0.description_display']"
+ date_acquired = "//div[@id='property_claim_details.0.date_acquired_display']"
+ cost_new = "//body[1]/div[1]/div[1]/div[1]/div[1]/main[1]/div[1]/div[2]/div[2]/div[2]/div[3]/div[1]/div[1]/div[2]/div[1]/div[1]/div[3]/div[2]/div[1]/div[3]/div[1]/div[1]/div[3]/div[4]/div[1]/div[1]/div[1]/div[1]/span[1]"
+ cost_new_currency = (
+ "//div[@id='property_claim_details.0.cost_new_currency_display']"
+ )
+ replacement_repair = "//span[normalize-space()='350']"
+ replacement_repair_currency = (
+ "//div[@id='property_claim_details.0.replacement_repair_currency_display']"
+ )
+
+ def __init__(self, page):
+ self.page = page
+
+ def validate_home_page(self):
+ expect(self.page.locator(self.TITLE_TEXT)).to_be_visible()
+ self.page.wait_for_timeout(2000)
+
+ def select_schema(self, SchemaName):
+ self.page.wait_for_timeout(5000)
+ self.page.locator(self.SELECT_SCHEMA).click()
+ if SchemaName == "Invoice":
+ self.page.get_by_role("option", name="Invoice").click()
+ else:
+ self.page.get_by_role("option", name="Property Loss Damage Claim").click()
+
+ def upload_files(self, schemaType):
+ with self.page.expect_file_chooser() as fc_info:
+ self.page.locator(self.IMPORT_CONTENT).click()
+ self.page.locator(self.BROWSE_FILES).click()
+ self.page.wait_for_timeout(5000)
+ # self.page.wait_for_load_state('networkidle')
+ file_chooser = fc_info.value
+ current_working_dir = os.getcwd()
+ file_path1 = os.path.join(
+ current_working_dir, "testdata", "FabrikamInvoice_1.pdf"
+ )
+ file_path2 = os.path.join(current_working_dir, "testdata", "ClaimForm_1.pdf")
+
+ if schemaType == "Invoice":
+ file_chooser.set_files([file_path1])
+ else:
+ file_chooser.set_files([file_path2])
+ self.page.wait_for_timeout(5000)
+ self.page.wait_for_load_state("networkidle")
+ self.page.locator(self.UPLOAD_BTN).click()
+ self.page.wait_for_timeout(10000)
+ expect(
+ self.page.get_by_role("alertdialog", name="Import Content")
+ .locator("path")
+ .nth(1)
+ ).to_be_visible()
+ self.page.locator(self.CLOSE_BTN).click()
+
+ def refresh(self):
+ status_ele = self.page.locator(self.STATUS).nth(2)
+ max_retries = 15
+
+ for i in range(max_retries):
+ status_text = status_ele.inner_text().strip()
+
+ if status_text == "Completed":
+ break
+ elif status_text == "Error":
+ raise Exception(
+ f"Process failed with status: 'Error' after {i + 1} retries."
+ )
+
+ self.page.locator(self.REFRESH).click()
+ self.page.wait_for_timeout(5000)
+ else:
+ # Executed only if the loop did not break (i.e., status is neither Completed nor Error)
+ raise Exception(
+ f"Process did not complete. Final status was '{status_text}' after {max_retries} retries."
+ )
+
+ def validate_invoice_extracted_result(self):
+ expect(self.page.locator(self.CUSTOMER_NAME)).to_contain_text(
+ "Paris Fashion Group SARL"
+ )
+ expect(self.page.locator(self.CUSTOMER_STREET)).to_contain_text(
+ "10 Rue de Rivoli"
+ )
+ expect(self.page.locator(self.CUSTOMER_CITY)).to_contain_text("Paris")
+ expect(self.page.locator(self.CUSTOMER_ZIP_CODE)).to_contain_text("75001")
+ expect(self.page.locator(self.CUSTOMER_COUNTRY)).to_contain_text("France")
+ expect(self.page.locator(self.SHIPPING_STREET)).to_contain_text(
+ "25 Avenue Montaigne"
+ )
+ expect(self.page.locator(self.SHIPPING_CITY)).to_contain_text("Paris")
+ expect(self.page.locator(self.SHIPPING_POSTAL_CODE)).to_contain_text("75008")
+ expect(self.page.locator(self.SHIPPING_COUNTRY)).to_contain_text("France")
+ expect(self.page.locator(self.PURCHASE_ORDER)).to_contain_text("PO-34567")
+ expect(self.page.locator(self.INVOICE_ID)).to_contain_text("INV-20231005")
+ expect(self.page.locator(self.INVOICE_DATE)).to_contain_text("2023-10-05")
+ expect(self.page.locator(self.INVOICE_DATE)).to_contain_text("2023-10-05")
+ expect(self.page.locator(self.payable_by)).to_contain_text("2023-11-04")
+ expect(self.page.locator(self.vendor_name)).to_contain_text(
+ "Fabrikam Unlimited Company"
+ )
+ expect(self.page.locator(self.v_street)).to_contain_text("Wilton Place")
+ expect(self.page.locator(self.v_city)).to_contain_text("Brooklyn")
+ expect(self.page.locator(self.v_state)).to_contain_text("NY")
+ expect(self.page.locator(self.v_zip_code)).to_contain_text("22345")
+ expect(self.page.locator(self.vendor_tax_id)).to_contain_text("FR123456789")
+ expect(self.page.locator(self.SUBTOTAL)).to_contain_text("16859.1")
+ expect(self.page.locator(self.TOTAL_TAX)).to_contain_text("11286")
+ expect(self.page.locator(self.INVOICE_TOTAL)).to_contain_text("22516.08")
+ expect(self.page.locator(self.PAYMENT_TERMS)).to_contain_text("Net 30")
+ expect(self.page.locator(self.product_code1)).to_contain_text("EM032")
+ expect(self.page.locator(self.p1_description)).to_contain_text(
+ "Item: Terminal Lug"
+ )
+ expect(self.page.locator(self.p1_quantity)).to_contain_text("163")
+ expect(self.page.locator(self.p1_tax)).to_contain_text("2934")
+ expect(self.page.locator(self.p1_unit_price)).to_contain_text("2.5")
+ expect(self.page.locator(self.p1_total)).to_contain_text("407.5")
+
+ def modify_and_submit_extracted_data(self):
+ self.page.get_by_text('"25 Avenue Montaigne"').dblclick()
+ self.page.locator(self.SHIPPING_ADD_STREET).fill("25 Avenue Montaigne updated")
+ self.page.locator(self.EDIT_CONFIRM).click()
+ self.page.locator(self.COMMENTS).fill("Updated Shipping street address")
+ self.page.locator(self.SAVE_BTN).click()
+ self.page.wait_for_timeout(6000)
+
+ def validate_process_steps(self):
+ self.page.locator(self.PROCESS_STEPS).click()
+ self.page.locator(self.EXTRACT).click()
+ self.page.wait_for_timeout(3000)
+ expect(self.page.get_by_text('"extract"')).to_be_visible()
+ expect(self.page.get_by_text('"Succeeded"')).to_be_visible()
+ self.page.locator(self.EXTRACT).click()
+ self.page.wait_for_timeout(3000)
+ self.page.locator(self.MAP).click()
+ self.page.wait_for_timeout(3000)
+ expect(self.page.get_by_text('"map"')).to_be_visible()
+ self.page.locator(self.MAP).click()
+ self.page.wait_for_timeout(3000)
+ self.page.locator(self.EVALUATE).click()
+ self.page.wait_for_timeout(3000)
+ expect(self.page.get_by_text('"evaluate"')).to_be_visible()
+ self.page.locator(self.EVALUATE).click()
+ self.page.wait_for_timeout(3000)
+ self.page.locator(self.EXTRACTED_RESULT).click()
+ self.page.wait_for_timeout(3000)
+
+ def validate_property_extracted_result(self):
+ expect(self.page.locator(self.first_name)).to_contain_text("Sophia")
+ expect(self.page.locator(self.last_name)).to_contain_text("Kim")
+ expect(self.page.locator(self.tel_no)).to_contain_text("646-555-0789")
+ expect(self.page.locator(self.policy_no)).to_contain_text("PH5678901")
+ expect(self.page.locator(self.coverage_type)).to_contain_text("Homeowners")
+ expect(self.page.locator(self.claim_number)).to_contain_text("CLM5432109")
+ expect(self.page.locator(self.policy_effective_date)).to_contain_text(
+ "2022-07-01"
+ )
+ expect(self.page.locator(self.policy_expiration_date)).to_contain_text(
+ "2023-07-01"
+ )
+ expect(self.page.locator(self.damage_deductible)).to_contain_text("1000")
+ expect(self.page.locator(self.damage_deductible_currency)).to_contain_text(
+ "USD"
+ )
+ expect(self.page.locator(self.date_of_damage_loss)).to_contain_text(
+ "2023-05-10"
+ )
+ expect(self.page.locator(self.time_of_loss)).to_contain_text("13:20")
+ expect(self.page.locator(self.date_prepared)).to_contain_text("2023-05-11")
+ expect(self.page.locator(self.item)).to_contain_text("Apple")
+ expect(self.page.locator(self.description)).to_contain_text(
+ '"High-performance tablet with a large, vibrant display'
+ )
+ expect(self.page.locator(self.date_acquired)).to_contain_text("2022-01-20")
+ expect(self.page.locator(self.cost_new)).to_contain_text("1100")
+ expect(self.page.locator(self.cost_new_currency)).to_contain_text("USD")
+ expect(self.page.locator(self.replacement_repair)).to_contain_text("350")
+ expect(self.page.locator(self.replacement_repair_currency)).to_contain_text(
+ "USD"
+ )
+
+ def delete_files(self):
+ self.page.locator(self.DELETE_FILE).nth(0).click()
+ self.page.get_by_role("menuitem", name="Delete").click()
+ self.page.get_by_role("button", name="Confirm").click()
+ self.page.wait_for_timeout(6000)
diff --git a/tests/e2e-test/pages/__init__.py b/tests/e2e-test/pages/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/e2e-test/pages/loginPage.py b/tests/e2e-test/pages/loginPage.py
new file mode 100644
index 00000000..0b412556
--- /dev/null
+++ b/tests/e2e-test/pages/loginPage.py
@@ -0,0 +1,36 @@
+from base.base import BasePage
+
+
+class LoginPage(BasePage):
+
+ EMAIL_TEXT_BOX = "//input[@type='email']"
+ NEXT_BUTTON = "//input[@type='submit']"
+ PASSWORD_TEXT_BOX = "//input[@type='password']"
+ SIGNIN_BUTTON = "//input[@id='idSIButton9']"
+ YES_BUTTON = "//input[@id='idSIButton9']"
+ PERMISSION_ACCEPT_BUTTON = "//input[@type='submit']"
+
+ def __init__(self, page):
+ self.page = page
+
+ def authenticate(self, username, password):
+ # login with username and password in web url
+ self.page.locator(self.EMAIL_TEXT_BOX).fill(username)
+ self.page.locator(self.NEXT_BUTTON).click()
+ # Wait for the password input field to be available and fill it
+ self.page.wait_for_load_state("networkidle")
+ # Enter password
+ self.page.locator(self.PASSWORD_TEXT_BOX).fill(password)
+ # Click on SignIn button
+ self.page.locator(self.SIGNIN_BUTTON).click()
+ # Wait for 5 seconds to ensure the login process completes
+ self.page.wait_for_timeout(20000) # Wait for 20 seconds
+ if self.page.locator(self.PERMISSION_ACCEPT_BUTTON).is_visible():
+ self.page.locator(self.PERMISSION_ACCEPT_BUTTON).click()
+ self.page.wait_for_timeout(10000)
+ else:
+ # Click on YES button
+ self.page.locator(self.YES_BUTTON).click()
+ self.page.wait_for_timeout(10000)
+ # Wait for the "Articles" button to be available and click it
+ self.page.wait_for_load_state("networkidle")
diff --git a/tests/e2e-test/pytest.ini b/tests/e2e-test/pytest.ini
new file mode 100644
index 00000000..76eb64fc
--- /dev/null
+++ b/tests/e2e-test/pytest.ini
@@ -0,0 +1,6 @@
+[pytest]
+log_cli = true
+log_cli_level = INFO
+log_file = logs/tests.log
+log_file_level = INFO
+addopts = -p no:warnings
diff --git a/tests/e2e-test/readme.MD b/tests/e2e-test/readme.MD
new file mode 100644
index 00000000..941d3653
--- /dev/null
+++ b/tests/e2e-test/readme.MD
@@ -0,0 +1,35 @@
+# cto-test-automation
+
+Write end-to-end tests for your web apps with [Playwright](https://github.com/microsoft/playwright-python) and [pytest](https://docs.pytest.org/en/stable/).
+
+- Support for **all modern browsers** including Chromium, WebKit and Firefox.
+- Support for **headless and headed** execution.
+- **Built-in fixtures** that provide browser primitives to test functions.
+
+Pre-Requisites:
+
+- Install Visual Studio Code: Download and Install Visual Studio Code(VSCode).
+- Install NodeJS: Download and Install Node JS
+
+Create and Activate Python Virtual Environment
+
+- From your directory open and run cmd : "python -m venv microsoft"
+This will create a virtual environment directory named microsoft inside your current directory
+- To enable virtual environment, copy location for "microsoft\Scripts\activate.bat" and run from cmd
+
+Installing Playwright Pytest from Virtual Environment
+
+- To install libraries run "pip install -r requirements.txt"
+- Install the required browsers "playwright install"
+
+Run test cases
+
+- To run test cases from your 'tests' folder : "pytest --html=report.html --self-contained-html"
+
+Create .env file in project root level with web app url and client credentials
+
+- create a .env file in project root level and the application url. please refer 'sample_dotenv_file.txt' file.
+
+## Documentation
+
+See on [playwright.dev](https://playwright.dev/python/docs/test-runners) for examples and more detailed information.
diff --git a/tests/e2e-test/requirements.txt b/tests/e2e-test/requirements.txt
new file mode 100644
index 00000000..7aad0cfb
--- /dev/null
+++ b/tests/e2e-test/requirements.txt
@@ -0,0 +1,6 @@
+pytest-playwright
+pytest-reporter-html1
+python-dotenv
+pytest-check
+pytest-html
+py
\ No newline at end of file
diff --git a/tests/e2e-test/testdata/ClaimForm_1.pdf b/tests/e2e-test/testdata/ClaimForm_1.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..85be1dbf02511f5c9e9e7c1839dfc3e2b78650de
GIT binary patch
literal 214534
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