From 0fbbc01e590f5be082bcb7d663b603ae3c1ec2b1 Mon Sep 17 00:00:00 2001 From: D1mitrii Date: Wed, 25 Mar 2026 22:30:35 +0300 Subject: [PATCH 1/3] feat: tests dockerfiles --- Dockerfile.selenium | 11 +++++++++++ docker-compose.selenium.yml | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 Dockerfile.selenium create mode 100644 docker-compose.selenium.yml diff --git a/Dockerfile.selenium b/Dockerfile.selenium new file mode 100644 index 0000000..4fc1ca3 --- /dev/null +++ b/Dockerfile.selenium @@ -0,0 +1,11 @@ +FROM python:3.14.3-slim + +WORKDIR /tests + +COPY tests/requirements.txt . + +RUN pip install --no-cache-dir -r requirements.txt + +COPY tests/ . + +ENTRYPOINT [ "pytest", "-v" ] \ No newline at end of file diff --git a/docker-compose.selenium.yml b/docker-compose.selenium.yml new file mode 100644 index 0000000..8f2e4f8 --- /dev/null +++ b/docker-compose.selenium.yml @@ -0,0 +1,36 @@ +services: + web: + build: + context: . + dockerfile: Dockerfile + command: > + sh -c "sed -i 's|let recaptcha_site_key = .*|let recaptcha_site_key = \"${RECAPTCHA_SITE_KEY}\"|' /app/templater/static/js/main.js && + sed -i 's|recaptcha_key = .*|recaptcha_key = \"${RECAPTCHA_SECRET_KEY}\"|' /app/config.ini && + sed -i 's|RECAPTCHA_SITE_KEY|${RECAPTCHA_SITE_KEY}|' /app/templater/templates/layout.jinja2 && + sed -i 's|mongo_uri = .*|mongo_uri = mongodb://db:27017/templater|' /app/config.ini && + sed -i '/def recaptcha/,/return/c\def recaptcha(request):\\n return True' /app/templater/views/default.py && + python3 -u runapp.py" + ports: + - "127.0.0.1:8080:5000" + depends_on: + - db + + db: + image: mongo:8-noble + + tests: + build: + context: . + dockerfile: Dockerfile.selenium + depends_on: + - web + + selenium-hub: + image: selenium/hub:4.41.0-20260222 + ports: + - "127.0.0.1:4445:4444" + + chrome-node: + image: selenium/node-chrome:145.0-20260222 + environment: + - SE_EVENT_BUS_HOST=selenium-hub \ No newline at end of file From 39ddcf8066165af2f4c39abe82a91f69a01ac3e9 Mon Sep 17 00:00:00 2001 From: D1mitrii Date: Wed, 25 Mar 2026 22:31:18 +0300 Subject: [PATCH 2/3] feat: tests configs --- tests/conftest.py | 27 +++++++++++++++++++++++++++ tests/requirements.txt | Bin 0 -> 818 bytes 2 files changed, 27 insertions(+) create mode 100644 tests/conftest.py create mode 100644 tests/requirements.txt diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..0a16ef2 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,27 @@ +import pytest +from selenium import webdriver +from selenium.webdriver.remote.file_detector import LocalFileDetector + +GRID_URL = "http://selenium-hub:4444/wd/hub" +BASE_URL = "http://web:5000" + +@pytest.fixture +def driver(): + options = webdriver.ChromeOptions() + options.add_argument("--headless=new") + options.add_argument("--no-sandbox") + options.enable_downloads = True + + driver = webdriver.Remote( + command_executor=GRID_URL, + options=options + ) + driver.file_detector = LocalFileDetector() + + yield driver + + driver.quit() + +@pytest.fixture +def base_url(): + return BASE_URL \ No newline at end of file diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..082654ef95f6f5814c2b82b154a0ec30923f0143 GIT binary patch literal 818 zcmZXS-A;o*5QXR3#78M9P;0#K9ZY-xQ!7OxWr;v)Utayr4%=ePX4`~0bN=AxduJo( z(*}Fw6t=a@a_-u0?Z)<2F&nM11J@Dj8C8HP>~6*#76@%$8G^MIVA-RjGWQSRPOKS2`E;6Ut%1-RRvhUfd*}w2P?o)!1eEr=13mae2NynZP^q(^2d~?ac rgoBpTpioAH81-h#*y?}n71@MWSKg#r@HX{rolxpw4NU*G Date: Wed, 25 Mar 2026 22:32:03 +0300 Subject: [PATCH 3/3] feat: test template upload --- tests/data/templates/template.docx | Bin 0 -> 13570 bytes tests/pages/base_page.py | 51 +++++++++++++++++++++++++++++ tests/pages/upload_page.py | 36 ++++++++++++++++++++ tests/test_upload_template.py | 23 +++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 tests/data/templates/template.docx create mode 100644 tests/pages/base_page.py create mode 100644 tests/pages/upload_page.py create mode 100644 tests/test_upload_template.py diff --git a/tests/data/templates/template.docx b/tests/data/templates/template.docx new file mode 100644 index 0000000000000000000000000000000000000000..e7536bc283ad310eeede0ea22e314332ef707f29 GIT binary patch literal 13570 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 None: + self.driver = driver + self.wait = WebDriverWait( + driver, + timeout=10, + poll_frequency=2, + ignored_exceptions=[ + NoSuchElementException, + StaleElementReferenceException, + ElementNotInteractableException, + ], + ) + + def element(self, locator: tuple) -> WebElement: + self.wait.until(lambda driver: driver.find_element(*locator)) + return self.driver.find_element(*locator) + + def elements(self, locator: tuple) -> list[WebElement]: + return self.driver.find_elements(*locator) + + def hover(self, locator: tuple) -> None: + element = self.element(locator) + ActionChains(self.driver).move_to_element(element).perform() + + def click(self, locator: tuple) -> None: + element = self.element(locator) + element.click() + + def type(self, locator: tuple, value: str) -> None: + element = self.element(locator) + element.clear() + element.send_keys(value) + + def text(self, locator: tuple) -> str: + element = self.element(locator) + return element.text + + def open(self, url: str) -> None: + self.driver.get(url) diff --git a/tests/pages/upload_page.py b/tests/pages/upload_page.py new file mode 100644 index 0000000..fcdc544 --- /dev/null +++ b/tests/pages/upload_page.py @@ -0,0 +1,36 @@ +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC + +from .base_page import BasePage + +class UploadPage(BasePage): + template_input_by = (By.CSS_SELECTOR, "#template-file") + template_upload_btn_by = (By.CSS_SELECTOR, "#btn-upload-template") + + tempate_preview_by = (By.CSS_SELECTOR, "#preview-container") + + template_submit_btn_by = (By.CSS_SELECTOR, "#btn-use-template") + template_reupload_btn_by = (By.CSS_SELECTOR, "#btn-upload-template") + + datatable_tab_pill_by = (By.ID, "pills-datatable-tab") + + def upload_template(self, filepath): + self.element(self.template_input_by).send_keys(filepath) + + def click_upload(self): + self.click(self.template_upload_btn_by) + + def wait_preview(self): + return self.wait.until(EC.visibility_of_element_located(self.tempate_preview_by)) + + def click_use_template(self): + self.click(self.template_submit_btn_by) + + def wait_until_datatable_pill_active(self): + self.wait.until( + EC.text_to_be_present_in_element_attribute( + self.datatable_tab_pill_by, + "aria-selected", + "true" + ) + ) \ No newline at end of file diff --git a/tests/test_upload_template.py b/tests/test_upload_template.py new file mode 100644 index 0000000..bb76ed1 --- /dev/null +++ b/tests/test_upload_template.py @@ -0,0 +1,23 @@ +import os +from pages.upload_page import UploadPage +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.common.by import By + +def test_upload_template(driver, base_url): + page = UploadPage(driver) + + template_path = os.path.abspath("data/templates/template.docx") + print("PATH:", template_path) + + page.open(base_url) + + page.upload_template(template_path) + + page.click_upload() + + preview = page.wait_preview() + assert preview is not None + + page.click_use_template() + + page.wait_until_datatable_pill_active() \ No newline at end of file