• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

fiduswriter / fiduswriter / 24176504571

09 Apr 2026 06:44AM UTC coverage: 86.612% (-0.1%) from 86.723%
24176504571

push

github

web-flow
Merge pull request #1377 from fiduswriter/dependabot/pip/fiduswriter/django-6.0.4

Bump django from 6.0.3 to 6.0.4 in /fiduswriter

7776 of 8978 relevant lines covered (86.61%)

5.16 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.51
fiduswriter/testing/selenium_helper.py
1
import re
16✔
2
import os
16✔
3
import time
16✔
4
from urllib3.exceptions import MaxRetryError
16✔
5
from selenium.common.exceptions import ElementClickInterceptedException
16✔
6
from selenium.webdriver.support.wait import WebDriverWait
16✔
7
from selenium.webdriver.support import expected_conditions as EC
16✔
8
from selenium.webdriver.common.by import By
16✔
9
from selenium import webdriver
16✔
10
from selenium.webdriver.chrome.service import Service as ChromiumService
16✔
11
from webdriver_manager.chrome import ChromeDriverManager
16✔
12
from webdriver_manager.core.os_manager import ChromeType
16✔
13

14
from allauth.account.models import EmailAddress
16✔
15
from django.contrib.auth.hashers import make_password
16✔
16
from django.contrib.auth import get_user_model
16✔
17
from django.conf import settings
16✔
18
from django.test import Client
16✔
19
from django.contrib.contenttypes.models import ContentType
16✔
20
import logging
16✔
21

22
logger = logging.getLogger(__name__)
16✔
23

24

25
class SeleniumHelper:
16✔
26
    """
27
    Methods for manipulating django and the browser for testing purposes.
28
    """
29

30
    login_page = "/"
16✔
31

32
    def find_urls(self, string):
16✔
33
        return re.findall(
2✔
34
            (
35
                "http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*(),]|"
36
                "(?:%[0-9a-fA-F][0-9a-fA-F]))+"
37
            ),
38
            string,
39
        )
40

41
    # create django data
42
    def create_user(
16✔
43
        self, username="User", email="test@example.com", passtext="p4ssw0rd"
44
    ):
45
        User = get_user_model()
15✔
46
        user = User.objects.create(
15✔
47
            username=username,
48
            email=email,
49
            password=make_password(passtext),
50
            is_active=True,
51
        )
52
        user.save()
15✔
53

54
        # avoid the unverified-email login trap
55
        EmailAddress.objects.create(
15✔
56
            user=user, email=email, verified=True, primary=True
57
        ).save()
58

59
        return user
15✔
60

61
    # drive browser
62
    def login_user(self, user, driver, client):
16✔
63
        client.force_login(user=user)
10✔
64
        cookie = client.cookies[settings.SESSION_COOKIE_NAME]
10✔
65
        # output the cookie to the console for debugging
66
        logger.debug("cookie: %s" % cookie.value)
10✔
67
        if driver.current_url == "data:,":
10✔
68
            # To set the cookie at the right domain we load the front page.
69
            driver.get(f"{self.live_server_url}{self.login_page}")
10✔
70
            WebDriverWait(driver, self.wait_time).until(
10✔
71
                EC.presence_of_element_located((By.ID, "id-login"))
72
            )
73
        driver.add_cookie(
10✔
74
            {
75
                "name": settings.SESSION_COOKIE_NAME,
76
                "value": cookie.value,
77
                "secure": False,
78
                "path": "/",
79
            }
80
        )
81

82
    def login_user_manually(self, user, driver, passtext="p4ssw0rd"):
16✔
83
        username = user.username
×
84
        driver.delete_cookie(settings.SESSION_COOKIE_NAME)
×
85
        driver.get("{}{}".format(self.live_server_url, "/"))
×
86
        driver.find_element(By.ID, "id-login").send_keys(username)
×
87
        driver.find_element(By.ID, "id-password").send_keys(passtext)
×
88
        driver.find_element(By.ID, "login-submit").click()
×
89
        # Wait until there is an element with the ID user-preferences
90
        # which is only present on the dashboard.
91
        WebDriverWait(driver, self.wait_time).until(
×
92
            EC.presence_of_element_located((By.ID, "user-preferences"))
93
        )
94

95
    def logout_user(self, driver, client):
16✔
96
        client.logout()
1✔
97
        driver.delete_cookie(settings.SESSION_COOKIE_NAME)
1✔
98

99
    def wait_until_file_exists(self, path, wait_time):
16✔
100
        count = 0
4✔
101
        while not os.path.exists(path):
4✔
102
            time.sleep(1)
4✔
103
            count += 1
4✔
104
            if count > wait_time:
4✔
105
                break
×
106

107
    def retry_click(self, driver, selector, retries=5):
16✔
108
        count = 0
1✔
109
        while count < retries:
1✔
110
            try:
1✔
111
                WebDriverWait(driver, self.wait_time).until(
1✔
112
                    EC.element_to_be_clickable(selector)
113
                ).click()
114
                break
1✔
115
            except ElementClickInterceptedException:
1✔
116
                count += 1
1✔
117
                time.sleep(1)
1✔
118

119
    @classmethod
16✔
120
    def get_drivers(cls, number, download_dir=False, user_agent=False):
16✔
121
        # django native clients, to be used for faster login.
122
        clients = []
16✔
123
        for i in range(number):
16✔
124
            clients.append(Client())
16✔
125
        drivers = []
16✔
126
        wait_time = 0
16✔
127
        options = webdriver.ChromeOptions()
16✔
128
        options.add_argument("--kiosk-printing")
16✔
129
        options.add_argument("--safebrowsing-disable-download-protection")
16✔
130
        options.add_argument("--safebrowsing-disable-extension-blacklist")
16✔
131
        options.add_argument("--window-size=1920,1080")
16✔
132
        prefs = {
16✔
133
            "profile.password_manager_leak_detection": False,
134
        }
135
        if download_dir:
16✔
136
            prefs["download.default_directory"] = download_dir
5✔
137
            prefs["download.prompt_for_download"] = False
5✔
138
            prefs["download.directory_upgrade"] = True
5✔
139
        options.add_experimental_option("prefs", prefs)
16✔
140
        if user_agent:
16✔
141
            options.add_argument(f"user-agent={user_agent}")
1✔
142
        if os.getenv("CI"):
16✔
143
            options.binary_location = "/usr/bin/google-chrome-stable"
16✔
144
            if os.getenv("DEBUG_MODE") != "1":
16✔
145
                options.add_argument("--headless=new")
16✔
146
            options.add_argument("--disable-gpu")
16✔
147
            wait_time = 20
16✔
148
        else:
149
            wait_time = 6
×
150
        for i in range(number):
16✔
151
            driver_env = os.environ.copy()
16✔
152
            if os.getenv("CI") and os.getenv("DEBUG_MODE") == "1" and i < 2:
16✔
153
                driver_env["DISPLAY"] = f":{99 - i}"
×
154
            driver = webdriver.Chrome(
16✔
155
                service=ChromiumService(
156
                    ChromeDriverManager(
157
                        chrome_type=ChromeType.GOOGLE
158
                    ).install(),
159
                    env=driver_env,
160
                ),
161
                options=options,
162
            )
163
            # Set sizes of browsers so that all buttons are visible.
164
            driver.set_window_position(0, 0)
16✔
165
            driver.set_window_size(1920, 1080)
16✔
166
            drivers.append(driver)
16✔
167
        cls.drivers = drivers
16✔
168
        return {"clients": clients, "drivers": drivers, "wait_time": wait_time}
16✔
169

170
    def setUp(self):
16✔
171
        # Clear ContentType cache during testing to prevent FK constraint errors
172
        # Content types get new IDs after each test but cached values don't update
173
        ContentType.objects.clear_cache()
10✔
174
        self.addCleanup(ContentType.objects.clear_cache)
10✔
175
        return super().setUp()
10✔
176

177
    def tearDown(self):
16✔
178
        # Source: https://stackoverflow.com/a/39606065
179
        result = self._outcome.result
16✔
180
        ok = all(
16✔
181
            test != self for test, text in result.errors + result.failures
182
        )
183
        if ok:
16✔
184
            for driver in self.drivers:
16✔
185
                self.leave_site(driver)
16✔
186
        else:
187
            if not os.path.exists("screenshots"):
×
188
                os.makedirs("screenshots")
×
189
            for id, driver in enumerate(self.drivers, start=1):
×
190
                screenshotfile = (
×
191
                    f"screenshots/driver{id}-{self._testMethodName}.png"
192
                )
193
                logger.info(f"Saving {screenshotfile}")
×
194
                driver.save_screenshot(screenshotfile)
×
195
                self.leave_site(driver)
×
196
        return super().tearDown()
16✔
197

198
    def leave_site(self, driver):
16✔
199
        try:
16✔
200
            driver.execute_script(
16✔
201
                "if (window.theApp) {window.theApp.page = null;}"
202
            )
203
            driver.get("data:,")
16✔
204
        except MaxRetryError:
1✔
205
            pass
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc