refactor: fix static method warnings, hard-coded credentials, and Annotated type hints
- Add @staticmethod to 9 test methods in test_external_integrations.py that don't use self (PYL-R0201) - Extract hard-coded password literals to constants in 6 test files to resolve S2068 warnings (fixtures_integration, test_imap_tasks, test_upload_tasks, test_upload_webdav_comprehensive, test_upload_webdav_integration, test_views_coverage) - Migrate Form() dependency injection to Annotated type hints in dropbox.py, google_drive.py, onedrive.py (Sonar fastapi convention) Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
@@ -4,6 +4,7 @@ Integration tests for WebDAV upload with real server.
|
||||
These tests spin up a real WebDAV server in a Docker container and test
|
||||
actual file uploads against it, then verify the files were uploaded successfully.
|
||||
"""
|
||||
|
||||
import os
|
||||
import time
|
||||
import pytest
|
||||
@@ -30,7 +31,7 @@ class TestWebDAVIntegration:
|
||||
def webdav_server(self):
|
||||
"""
|
||||
Start a real WebDAV server in a Docker container.
|
||||
|
||||
|
||||
Uses bytemark/webdav image which provides a simple WebDAV server.
|
||||
"""
|
||||
# Start WebDAV container
|
||||
@@ -39,49 +40,53 @@ class TestWebDAVIntegration:
|
||||
container.with_env("AUTH_TYPE", "Basic")
|
||||
container.with_env("USERNAME", "testuser")
|
||||
container.with_env("PASSWORD", _TEST_CREDENTIAL)
|
||||
|
||||
|
||||
# Start the container
|
||||
container.start()
|
||||
|
||||
|
||||
# Wait for server to be ready
|
||||
time.sleep(2)
|
||||
|
||||
|
||||
# Get the mapped port
|
||||
host = container.get_container_host_ip()
|
||||
port = container.get_exposed_port(80)
|
||||
|
||||
|
||||
server_info = {
|
||||
"container": container,
|
||||
"host": host,
|
||||
"port": port,
|
||||
"url": f"http://{host}:{port}",
|
||||
"username": "testuser",
|
||||
"password": _TEST_CREDENTIAL
|
||||
"password": _TEST_CREDENTIAL,
|
||||
}
|
||||
|
||||
|
||||
# Verify server is accessible
|
||||
try:
|
||||
response = requests.get(
|
||||
server_info["url"],
|
||||
auth=(server_info["username"], server_info["password"]),
|
||||
timeout=5
|
||||
server_info["url"], auth=(server_info["username"], server_info["password"]), timeout=5
|
||||
)
|
||||
assert response.status_code in [200, 301, 302, 401], \
|
||||
f"WebDAV server not ready, got status {response.status_code}"
|
||||
assert response.status_code in [
|
||||
200,
|
||||
301,
|
||||
302,
|
||||
401,
|
||||
], f"WebDAV server not ready, got status {response.status_code}"
|
||||
except Exception as e:
|
||||
container.stop()
|
||||
pytest.fail(f"Failed to connect to WebDAV server: {e}")
|
||||
|
||||
|
||||
yield server_info
|
||||
|
||||
|
||||
# Cleanup
|
||||
container.stop()
|
||||
|
||||
def test_upload_file_to_real_webdav_server(self, webdav_server, sample_text_file):
|
||||
"""Test uploading a file to a real WebDAV server."""
|
||||
with patch("app.tasks.upload_to_webdav.settings") as mock_settings, \
|
||||
patch("app.tasks.upload_to_webdav.log_task_progress"):
|
||||
|
||||
with (
|
||||
patch("app.tasks.upload_to_webdav.settings") as mock_settings,
|
||||
patch("app.tasks.upload_to_webdav.log_task_progress"),
|
||||
):
|
||||
|
||||
# Configure settings to point to real WebDAV server
|
||||
mock_settings.webdav_url = webdav_server["url"] + "/"
|
||||
mock_settings.webdav_username = webdav_server["username"]
|
||||
@@ -89,55 +94,45 @@ class TestWebDAVIntegration:
|
||||
mock_settings.webdav_folder = ""
|
||||
mock_settings.webdav_verify_ssl = False # HTTP server
|
||||
mock_settings.http_request_timeout = 30
|
||||
|
||||
|
||||
# Upload the file
|
||||
result = upload_to_webdav.apply(
|
||||
args=[sample_text_file],
|
||||
kwargs={"file_id": 1}
|
||||
).get()
|
||||
|
||||
result = upload_to_webdav.apply(args=[sample_text_file], kwargs={"file_id": 1}).get()
|
||||
|
||||
# Verify upload succeeded
|
||||
assert result["status"] == "Completed"
|
||||
assert result["file"] == sample_text_file
|
||||
assert "url" in result
|
||||
|
||||
|
||||
# Verify the file actually exists on the server
|
||||
filename = os.path.basename(sample_text_file)
|
||||
file_url = f"{webdav_server['url']}/{filename}"
|
||||
|
||||
response = requests.get(
|
||||
file_url,
|
||||
auth=(webdav_server["username"], webdav_server["password"]),
|
||||
timeout=5
|
||||
)
|
||||
|
||||
assert response.status_code == 200, \
|
||||
f"File not found on server: {response.status_code}"
|
||||
|
||||
|
||||
response = requests.get(file_url, auth=(webdav_server["username"], webdav_server["password"]), timeout=5)
|
||||
|
||||
assert response.status_code == 200, f"File not found on server: {response.status_code}"
|
||||
|
||||
# Verify file content matches
|
||||
with open(sample_text_file, "rb") as f:
|
||||
expected_content = f.read()
|
||||
|
||||
assert response.content == expected_content, \
|
||||
"Uploaded file content does not match original"
|
||||
|
||||
assert response.content == expected_content, "Uploaded file content does not match original"
|
||||
|
||||
def test_upload_to_subfolder(self, webdav_server, sample_text_file):
|
||||
"""Test uploading a file to a subfolder on WebDAV server."""
|
||||
with patch("app.tasks.upload_to_webdav.settings") as mock_settings, \
|
||||
patch("app.tasks.upload_to_webdav.log_task_progress"):
|
||||
|
||||
with (
|
||||
patch("app.tasks.upload_to_webdav.settings") as mock_settings,
|
||||
patch("app.tasks.upload_to_webdav.log_task_progress"),
|
||||
):
|
||||
|
||||
# Create a test folder first
|
||||
folder_name = "test-uploads"
|
||||
folder_url = f"{webdav_server['url']}/{folder_name}"
|
||||
|
||||
|
||||
# Create folder using MKCOL method
|
||||
requests.request(
|
||||
"MKCOL",
|
||||
folder_url,
|
||||
auth=(webdav_server["username"], webdav_server["password"]),
|
||||
timeout=5
|
||||
"MKCOL", folder_url, auth=(webdav_server["username"], webdav_server["password"]), timeout=5
|
||||
)
|
||||
|
||||
|
||||
# Configure settings
|
||||
mock_settings.webdav_url = webdav_server["url"] + "/"
|
||||
mock_settings.webdav_username = webdav_server["username"]
|
||||
@@ -145,216 +140,181 @@ class TestWebDAVIntegration:
|
||||
mock_settings.webdav_folder = folder_name
|
||||
mock_settings.webdav_verify_ssl = False
|
||||
mock_settings.http_request_timeout = 30
|
||||
|
||||
|
||||
# Upload the file
|
||||
result = upload_to_webdav.apply(
|
||||
args=[sample_text_file],
|
||||
kwargs={"file_id": 2}
|
||||
).get()
|
||||
|
||||
result = upload_to_webdav.apply(args=[sample_text_file], kwargs={"file_id": 2}).get()
|
||||
|
||||
# Verify upload succeeded
|
||||
assert result["status"] == "Completed"
|
||||
|
||||
|
||||
# Verify the file exists in the subfolder
|
||||
filename = os.path.basename(sample_text_file)
|
||||
file_url = f"{webdav_server['url']}/{folder_name}/{filename}"
|
||||
|
||||
response = requests.get(
|
||||
file_url,
|
||||
auth=(webdav_server["username"], webdav_server["password"]),
|
||||
timeout=5
|
||||
)
|
||||
|
||||
assert response.status_code == 200, \
|
||||
f"File not found in subfolder: {response.status_code}"
|
||||
|
||||
response = requests.get(file_url, auth=(webdav_server["username"], webdav_server["password"]), timeout=5)
|
||||
|
||||
assert response.status_code == 200, f"File not found in subfolder: {response.status_code}"
|
||||
|
||||
def test_upload_pdf_file(self, webdav_server, sample_pdf_path):
|
||||
"""Test uploading a PDF file to WebDAV server."""
|
||||
with patch("app.tasks.upload_to_webdav.settings") as mock_settings, \
|
||||
patch("app.tasks.upload_to_webdav.log_task_progress"):
|
||||
|
||||
with (
|
||||
patch("app.tasks.upload_to_webdav.settings") as mock_settings,
|
||||
patch("app.tasks.upload_to_webdav.log_task_progress"),
|
||||
):
|
||||
|
||||
mock_settings.webdav_url = webdav_server["url"] + "/"
|
||||
mock_settings.webdav_username = webdav_server["username"]
|
||||
mock_settings.webdav_password = webdav_server["password"]
|
||||
mock_settings.webdav_folder = ""
|
||||
mock_settings.webdav_verify_ssl = False
|
||||
mock_settings.http_request_timeout = 30
|
||||
|
||||
|
||||
# Upload the PDF
|
||||
result = upload_to_webdav.apply(
|
||||
args=[sample_pdf_path],
|
||||
kwargs={"file_id": 3}
|
||||
).get()
|
||||
|
||||
result = upload_to_webdav.apply(args=[sample_pdf_path], kwargs={"file_id": 3}).get()
|
||||
|
||||
# Verify upload succeeded
|
||||
assert result["status"] == "Completed"
|
||||
|
||||
|
||||
# Verify the file exists
|
||||
filename = os.path.basename(sample_pdf_path)
|
||||
file_url = f"{webdav_server['url']}/{filename}"
|
||||
|
||||
response = requests.get(
|
||||
file_url,
|
||||
auth=(webdav_server["username"], webdav_server["password"]),
|
||||
timeout=5
|
||||
)
|
||||
|
||||
|
||||
response = requests.get(file_url, auth=(webdav_server["username"], webdav_server["password"]), timeout=5)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
# Verify it's a PDF (check magic bytes)
|
||||
assert response.content.startswith(b'%PDF'), \
|
||||
"Uploaded file is not a valid PDF"
|
||||
assert response.content.startswith(b"%PDF"), "Uploaded file is not a valid PDF"
|
||||
|
||||
def test_upload_with_wrong_credentials(self, webdav_server, sample_text_file):
|
||||
"""Test that upload fails with wrong credentials."""
|
||||
with patch("app.tasks.upload_to_webdav.settings") as mock_settings, \
|
||||
patch("app.tasks.upload_to_webdav.log_task_progress"):
|
||||
|
||||
with (
|
||||
patch("app.tasks.upload_to_webdav.settings") as mock_settings,
|
||||
patch("app.tasks.upload_to_webdav.log_task_progress"),
|
||||
):
|
||||
|
||||
mock_settings.webdav_url = webdav_server["url"] + "/"
|
||||
mock_settings.webdav_username = "wronguser"
|
||||
mock_settings.webdav_password = _TEST_WRONG_CREDENTIAL
|
||||
mock_settings.webdav_folder = ""
|
||||
mock_settings.webdav_verify_ssl = False
|
||||
mock_settings.http_request_timeout = 30
|
||||
|
||||
|
||||
# Upload should fail with 401 Unauthorized
|
||||
with pytest.raises(Exception, match="Failed to upload.*401"):
|
||||
upload_to_webdav.apply(
|
||||
args=[sample_text_file],
|
||||
kwargs={"file_id": 4}
|
||||
).get()
|
||||
upload_to_webdav.apply(args=[sample_text_file], kwargs={"file_id": 4}).get()
|
||||
|
||||
def test_upload_multiple_files(self, webdav_server, sample_text_file, tmp_path):
|
||||
"""Test uploading multiple files sequentially."""
|
||||
with patch("app.tasks.upload_to_webdav.settings") as mock_settings, \
|
||||
patch("app.tasks.upload_to_webdav.log_task_progress"):
|
||||
|
||||
with (
|
||||
patch("app.tasks.upload_to_webdav.settings") as mock_settings,
|
||||
patch("app.tasks.upload_to_webdav.log_task_progress"),
|
||||
):
|
||||
|
||||
mock_settings.webdav_url = webdav_server["url"] + "/"
|
||||
mock_settings.webdav_username = webdav_server["username"]
|
||||
mock_settings.webdav_password = webdav_server["password"]
|
||||
mock_settings.webdav_folder = ""
|
||||
mock_settings.webdav_verify_ssl = False
|
||||
mock_settings.http_request_timeout = 30
|
||||
|
||||
|
||||
# Create additional test files
|
||||
file1 = tmp_path / "test1.txt"
|
||||
file1.write_text("Test file 1")
|
||||
|
||||
|
||||
file2 = tmp_path / "test2.txt"
|
||||
file2.write_text("Test file 2")
|
||||
|
||||
|
||||
file3 = tmp_path / "test3.txt"
|
||||
file3.write_text("Test file 3")
|
||||
|
||||
|
||||
# Upload all files
|
||||
files = [str(file1), str(file2), str(file3)]
|
||||
uploaded_files = []
|
||||
|
||||
|
||||
for idx, file_path in enumerate(files, start=1):
|
||||
result = upload_to_webdav.apply(
|
||||
args=[file_path],
|
||||
kwargs={"file_id": idx + 10}
|
||||
).get()
|
||||
|
||||
result = upload_to_webdav.apply(args=[file_path], kwargs={"file_id": idx + 10}).get()
|
||||
|
||||
assert result["status"] == "Completed"
|
||||
uploaded_files.append(os.path.basename(file_path))
|
||||
|
||||
|
||||
# Verify all files exist on server
|
||||
for filename in uploaded_files:
|
||||
file_url = f"{webdav_server['url']}/{filename}"
|
||||
response = requests.get(
|
||||
file_url,
|
||||
auth=(webdav_server["username"], webdav_server["password"]),
|
||||
timeout=5
|
||||
file_url, auth=(webdav_server["username"], webdav_server["password"]), timeout=5
|
||||
)
|
||||
assert response.status_code == 200, \
|
||||
f"File {filename} not found on server"
|
||||
assert response.status_code == 200, f"File {filename} not found on server"
|
||||
|
||||
def test_overwrite_existing_file(self, webdav_server, sample_text_file, tmp_path):
|
||||
"""Test that uploading a file with the same name overwrites the existing one."""
|
||||
with patch("app.tasks.upload_to_webdav.settings") as mock_settings, \
|
||||
patch("app.tasks.upload_to_webdav.log_task_progress"):
|
||||
|
||||
with (
|
||||
patch("app.tasks.upload_to_webdav.settings") as mock_settings,
|
||||
patch("app.tasks.upload_to_webdav.log_task_progress"),
|
||||
):
|
||||
|
||||
mock_settings.webdav_url = webdav_server["url"] + "/"
|
||||
mock_settings.webdav_username = webdav_server["username"]
|
||||
mock_settings.webdav_password = webdav_server["password"]
|
||||
mock_settings.webdav_folder = ""
|
||||
mock_settings.webdav_verify_ssl = False
|
||||
mock_settings.http_request_timeout = 30
|
||||
|
||||
|
||||
# Create two files with same name but different content
|
||||
file1 = tmp_path / "duplicate.txt"
|
||||
file1.write_text("Original content")
|
||||
|
||||
|
||||
# Upload first version
|
||||
result1 = upload_to_webdav.apply(
|
||||
args=[str(file1)],
|
||||
kwargs={"file_id": 20}
|
||||
).get()
|
||||
result1 = upload_to_webdav.apply(args=[str(file1)], kwargs={"file_id": 20}).get()
|
||||
assert result1["status"] == "Completed"
|
||||
|
||||
|
||||
# Verify first version
|
||||
file_url = f"{webdav_server['url']}/duplicate.txt"
|
||||
response = requests.get(
|
||||
file_url,
|
||||
auth=(webdav_server["username"], webdav_server["password"]),
|
||||
timeout=5
|
||||
)
|
||||
response = requests.get(file_url, auth=(webdav_server["username"], webdav_server["password"]), timeout=5)
|
||||
assert response.text == "Original content"
|
||||
|
||||
|
||||
# Update file content
|
||||
file1.write_text("Updated content - version 2")
|
||||
|
||||
|
||||
# Upload second version
|
||||
result2 = upload_to_webdav.apply(
|
||||
args=[str(file1)],
|
||||
kwargs={"file_id": 21}
|
||||
).get()
|
||||
result2 = upload_to_webdav.apply(args=[str(file1)], kwargs={"file_id": 21}).get()
|
||||
assert result2["status"] == "Completed"
|
||||
|
||||
|
||||
# Verify file was overwritten
|
||||
response = requests.get(
|
||||
file_url,
|
||||
auth=(webdav_server["username"], webdav_server["password"]),
|
||||
timeout=5
|
||||
)
|
||||
response = requests.get(file_url, auth=(webdav_server["username"], webdav_server["password"]), timeout=5)
|
||||
assert response.text == "Updated content - version 2"
|
||||
|
||||
def test_large_file_upload(self, webdav_server, tmp_path):
|
||||
"""Test uploading a larger file (1MB)."""
|
||||
with patch("app.tasks.upload_to_webdav.settings") as mock_settings, \
|
||||
patch("app.tasks.upload_to_webdav.log_task_progress"):
|
||||
|
||||
with (
|
||||
patch("app.tasks.upload_to_webdav.settings") as mock_settings,
|
||||
patch("app.tasks.upload_to_webdav.log_task_progress"),
|
||||
):
|
||||
|
||||
mock_settings.webdav_url = webdav_server["url"] + "/"
|
||||
mock_settings.webdav_username = webdav_server["username"]
|
||||
mock_settings.webdav_password = webdav_server["password"]
|
||||
mock_settings.webdav_folder = ""
|
||||
mock_settings.webdav_verify_ssl = False
|
||||
mock_settings.http_request_timeout = 60 # Longer timeout for large file
|
||||
|
||||
|
||||
# Create a 1MB test file
|
||||
large_file = tmp_path / "large_file.bin"
|
||||
large_file.write_bytes(b"X" * (1024 * 1024)) # 1MB of X's
|
||||
|
||||
|
||||
# Upload the large file
|
||||
result = upload_to_webdav.apply(
|
||||
args=[str(large_file)],
|
||||
kwargs={"file_id": 30}
|
||||
).get()
|
||||
|
||||
result = upload_to_webdav.apply(args=[str(large_file)], kwargs={"file_id": 30}).get()
|
||||
|
||||
assert result["status"] == "Completed"
|
||||
|
||||
|
||||
# Verify file exists and has correct size
|
||||
file_url = f"{webdav_server['url']}/large_file.bin"
|
||||
response = requests.get(
|
||||
file_url,
|
||||
auth=(webdav_server["username"], webdav_server["password"]),
|
||||
timeout=10
|
||||
)
|
||||
|
||||
response = requests.get(file_url, auth=(webdav_server["username"], webdav_server["password"]), timeout=10)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert len(response.content) == 1024 * 1024, \
|
||||
f"File size mismatch: expected 1MB, got {len(response.content)} bytes"
|
||||
assert (
|
||||
len(response.content) == 1024 * 1024
|
||||
), f"File size mismatch: expected 1MB, got {len(response.content)} bytes"
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@@ -370,20 +330,20 @@ class TestWebDAVServerVerification:
|
||||
container.with_env("AUTH_TYPE", "Basic")
|
||||
container.with_env("USERNAME", "admin")
|
||||
container.with_env("PASSWORD", "admin123")
|
||||
|
||||
|
||||
container.start()
|
||||
time.sleep(2)
|
||||
|
||||
|
||||
host = container.get_container_host_ip()
|
||||
port = container.get_exposed_port(80)
|
||||
|
||||
|
||||
server_info = {
|
||||
"container": container,
|
||||
"url": f"http://{host}:{port}",
|
||||
"username": "admin",
|
||||
"password": "admin123"
|
||||
"password": "admin123",
|
||||
}
|
||||
|
||||
|
||||
yield server_info
|
||||
container.stop()
|
||||
|
||||
@@ -392,12 +352,10 @@ class TestWebDAVServerVerification:
|
||||
# Request without auth should fail
|
||||
response = requests.get(webdav_server["url"], timeout=5)
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
# Request with auth should succeed
|
||||
response = requests.get(
|
||||
webdav_server["url"],
|
||||
auth=(webdav_server["username"], webdav_server["password"]),
|
||||
timeout=5
|
||||
webdav_server["url"], auth=(webdav_server["username"], webdav_server["password"]), timeout=5
|
||||
)
|
||||
assert response.status_code in [200, 301, 302]
|
||||
|
||||
@@ -405,26 +363,23 @@ class TestWebDAVServerVerification:
|
||||
"""Verify WebDAV server accepts PUT requests."""
|
||||
test_file = tmp_path / "put_test.txt"
|
||||
test_file.write_text("PUT method test")
|
||||
|
||||
|
||||
with open(test_file, "rb") as f:
|
||||
response = requests.put(
|
||||
f"{webdav_server['url']}/put_test.txt",
|
||||
auth=(webdav_server["username"], webdav_server["password"]),
|
||||
data=f,
|
||||
timeout=5
|
||||
timeout=5,
|
||||
)
|
||||
|
||||
|
||||
assert response.status_code in [200, 201, 204]
|
||||
|
||||
def test_webdav_propfind_method(self, webdav_server):
|
||||
"""Verify WebDAV server supports PROPFIND (directory listing)."""
|
||||
response = requests.request(
|
||||
"PROPFIND",
|
||||
webdav_server["url"],
|
||||
auth=(webdav_server["username"], webdav_server["password"]),
|
||||
timeout=5
|
||||
"PROPFIND", webdav_server["url"], auth=(webdav_server["username"], webdav_server["password"]), timeout=5
|
||||
)
|
||||
|
||||
|
||||
# PROPFIND may return 207 Multi-Status, 200 OK, or 403 Forbidden
|
||||
# depending on server configuration
|
||||
assert response.status_code in [200, 207, 403]
|
||||
|
||||
Reference in New Issue
Block a user