lcc_tool/test/pages/calculation_page.py

157 lines
7.3 KiB
Python

# pages/calculation_page.py
from selenium.webdriver.common.by import By
from pages.base_page import BasePage
import logging
logger = logging.getLogger(__name__)
class CalculationPage(BasePage):
"""Page Object für die Berechnungsformulare"""
# WICHTIG: Verwende data-v-* Attribute NUR wenn sie WIRKLICH stabil sind
# Besser: Positionsbasierte Selektoren mit aussagekräftigen Parent-Elementen
FIELD_MAPPING = {
# Material-Sektion (erste Box)
"HS_CODE": (
By.XPATH,
"//div[contains(@class, 'master-data-item')][1]//div[contains(@class, 'caption-column')][text()='HS code']"
"/following-sibling::div//input[@class='input-field']"
),
"TARIFF_RATE": (
By.XPATH,
"//div[contains(@class, 'master-data-item')][1]//div[contains(@class, 'caption-column')][contains(text(), 'Tariff rate')]"
"/following-sibling::div//input[@class='input-field']"
),
# Price-Sektion (zweite Box)
"PRICE": (
By.XPATH,
"//div[contains(@class, 'master-data-item')][2]//div[contains(@class, 'caption-column')][text()='MEK_A [EUR]']"
"/following-sibling::div//input[@class='input-field']"
),
"OVERSEA_SHARE": (
By.XPATH,
"//div[contains(@class, 'master-data-item')][2]//div[contains(@class, 'caption-column')][contains(text(), 'Oversea share')]"
"/following-sibling::div//input[@class='input-field']"
),
# Handling Unit-Sektion (dritte Box)
"LENGTH": (
By.XPATH,
"//div[contains(@class, 'master-data-item')][3]//div[contains(@class, 'caption-column')][text()='HU length']"
"/following-sibling::div//input[@class='input-field']"
),
"WIDTH": (
By.XPATH,
"//div[contains(@class, 'master-data-item')][3]//div[contains(@class, 'caption-column')][text()='HU width']"
"/following-sibling::div//input[@class='input-field']"
),
"HEIGHT": (
By.XPATH,
"//div[contains(@class, 'master-data-item')][3]//div[contains(@class, 'caption-column')][text()='HU height']"
"/following-sibling::div//input[@class='input-field']"
),
"WEIGHT": (
By.XPATH,
"//div[contains(@class, 'master-data-item')][3]//div[contains(@class, 'caption-column')][text()='HU weight']"
"/following-sibling::div//input[@class='input-field']"
),
"PIECES_UNIT": (
By.XPATH,
"//div[contains(@class, 'master-data-item')][3]//div[contains(@class, 'caption-column')][text()='Pieces per HU']"
"/following-sibling::div//input[@class='input-field']"
),
# Dropdowns
"DIMENSION_UNIT": (
By.XPATH,
"//div[contains(@class, 'master-data-item')][3]//div[contains(@class, 'caption-column')][text()='Dimension unit']"
"/following-sibling::div//button[contains(@class, 'dropdown-trigger')]"
),
"WEIGHT_UNIT": (
By.XPATH,
"//div[contains(@class, 'master-data-item')][3]//div[contains(@class, 'caption-column')][text()='Weight unit']"
"/following-sibling::div//button[contains(@class, 'dropdown-trigger')]"
),
# Checkboxen
"FBA_FEE": (
By.XPATH,
"//div[contains(@class, 'master-data-item')][2]"
"//label[contains(@class, 'checkbox-item')]"
"[.//span[contains(@class, 'checkbox-label')][normalize-space(text())='']]"
),
"MIXED": (
By.XPATH,
"//label[contains(@class, 'checkbox-item')]"
"[.//span[contains(@class, 'checkbox-label')][text()='Mixable']]"
),
"STACKED": (
By.XPATH,
"//label[contains(@class, 'checkbox-item')]"
"[.//span[contains(@class, 'checkbox-label')][text()='Stackable']]"
),
}
DEST_FIELD_MAPPING = {
"NAME": (By.XPATH, "//input[@placeholder='Add new Destination ...']"),
"QUANTITY": (By.XPATH,
"//div[contains(@class, 'destination-edit-column-caption') and contains(text(), 'Annual quantity')]/following-sibling::div[1]//input[@class='input-field']")
"ROUTING": (By.XPATH,
"//input[@type='radio' and @name='model' and @value='routing']"),
"D2D": (By.XPATH,
"//input[@type='radio' and @name='model' and @value='d2d']"),
"ROUTE": (By.XPATH,
"//div[@class='destination-route-container']//div[contains(@class, 'destination-route-inner-container')][.//span[contains(text(), 'Ireland Su')] and .//span[contains(text(), 'WH ULHA')] and .//span[contains(text(), 'AB')]]")
"HANDLING_TAB": (By.XPATH, "//button[@class='tab-header' and text()='Handling & Repackaging']"),
"CUSTOM_HANDLING": (By.XPATH,
"//div[@class='destination-edit-handling-cost']//label[@class='checkbox-item']/input[@type='checkbox']"),
"REPACKING": (By.XPATH,
"//div[@class='destination-edit-column-caption' and contains(text(), 'Repackaging cost')]/following-sibling::div[@class='destination-edit-column-data'][1]//input[@class='input-field']"),
"HANDLING": (By.XPATH,
"//div[@class='destination-edit-column-caption' and contains(text(), 'Handling cost')]/following-sibling::div[@class='destination-edit-column-data'][1]//input[@class='input-field']"),
"DISPOSAL": (By.XPATH,
"//div[@class='destination-edit-column-caption' and contains(text(), 'Disposal cost')]/following-sibling::div[@class='destination-edit-column-data'][1]//input[@class='input-field']"),
}
# Buttons
CALCULATE_CLOSE_BUTTON = (By.XPATH, "//button[contains(., 'Calculate & close')]")
CLOSE_BUTTON = (By.XPATH, "//button[contains(., 'Close') and not(contains(., 'Calculate'))]")
def fill_form(self, data_dict):
"""Füllt das Formular mit Daten aus dem Excel"""
for field_name, locator in self.FIELD_MAPPING.items():
value = data_dict[field_name]
logger.info(f"Filling field: {field_name} = {value}")
try:
if field_name in ["FBA_FEE", "STACKED", "MIXED"]:
self.set_checkbox(*locator, str(value) == 'True')
elif field_name in ["DIMENSION_UNIT", "WEIGHT_UNIT"]:
self.select_dropdown_option(*locator, str(value))
else:
self.fill_input(*locator, str(value), check_existence=field_name in ["HS_CODE", "TARIFF_RATE"])
except Exception as e:
logger.error(f"Failed to fill field {field_name}: {e}")
self.driver.save_screenshot(f"failed_field_{field_name}.png")
raise Exception(f"Could not fill field '{field_name}': {e}") from e
def add_destination(self, data_dict):
self.search_and_select_autosuggest(*self.DEST_FIELD_MAPPING["NAME"], data_dict["NAME"])
def fill_destination(self, data_dict):
self.wait_for_element(*self.DEST_FIELD_MAPPING["QUANTITY"])
pass
def click_calculate_and_close(self):
"""Klickt auf 'Calculate & close' Button"""
self.click_button(*self.CALCULATE_CLOSE_BUTTON)
def click_close(self):
"""Klickt auf 'Close' Button"""
self.click_button(*self.CLOSE_BUTTON)