mirror of
				https://github.com/dgtlmoon/changedetection.io.git
				synced 2025-11-04 08:34:57 +00:00 
			
		
		
		
	
		
			Some checks are pending
		
		
	
	Build and push containers / metadata (push) Waiting to run
				
			Build and push containers / build-push-containers (push) Waiting to run
				
			Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Waiting to run
				
			Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Test the built 📦 package works basically. (push) Blocked by required conditions
				
			Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Blocked by required conditions
				
			ChangeDetection.io App Test / lint-code (push) Waiting to run
				
			ChangeDetection.io App Test / test-application-3-10 (push) Blocked by required conditions
				
			ChangeDetection.io App Test / test-application-3-11 (push) Blocked by required conditions
				
			ChangeDetection.io App Test / test-application-3-12 (push) Blocked by required conditions
				
			ChangeDetection.io App Test / test-application-3-13 (push) Blocked by required conditions
				
			
		
			
				
	
	
		
			212 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			212 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import json
 | 
						|
from unittest.mock import patch
 | 
						|
 | 
						|
import pytest
 | 
						|
import requests
 | 
						|
from apprise.utils.parse import parse_url as apprise_parse_url
 | 
						|
 | 
						|
from ...apprise_plugin.custom_handlers import (
 | 
						|
    _get_auth,
 | 
						|
    _get_headers,
 | 
						|
    _get_params,
 | 
						|
    apprise_http_custom_handler,
 | 
						|
    SUPPORTED_HTTP_METHODS,
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize(
 | 
						|
    "url,expected_auth",
 | 
						|
    [
 | 
						|
        ("get://user:pass@localhost:9999", ("user", "pass")),
 | 
						|
        ("get://user@localhost:9999", "user"),
 | 
						|
        ("get://localhost:9999", ""),
 | 
						|
        ("get://user%20name:pass%20word@localhost:9999", ("user name", "pass word")),
 | 
						|
    ],
 | 
						|
)
 | 
						|
def test_get_auth(url, expected_auth):
 | 
						|
    """Test authentication extraction with various URL formats."""
 | 
						|
    parsed_url = apprise_parse_url(url)
 | 
						|
    assert _get_auth(parsed_url) == expected_auth
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize(
 | 
						|
    "url,body,expected_content_type",
 | 
						|
    [
 | 
						|
        (
 | 
						|
            "get://localhost:9999?+content-type=application/xml",
 | 
						|
            "test",
 | 
						|
            "application/xml",
 | 
						|
        ),
 | 
						|
        ("get://localhost:9999", '{"key": "value"}', "application/json; charset=utf-8"),
 | 
						|
        ("get://localhost:9999", "plain text", None),
 | 
						|
        ("get://localhost:9999?+content-type=text/plain", "test", "text/plain"),
 | 
						|
    ],
 | 
						|
)
 | 
						|
def test_get_headers(url, body, expected_content_type):
 | 
						|
    """Test header extraction and content type detection."""
 | 
						|
    parsed_url = apprise_parse_url(url)
 | 
						|
    headers = _get_headers(parsed_url, body)
 | 
						|
 | 
						|
    if expected_content_type:
 | 
						|
        assert headers.get("Content-Type") == expected_content_type
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize(
 | 
						|
    "url,expected_params",
 | 
						|
    [
 | 
						|
        ("get://localhost:9999?param1=value1", {"param1": "value1"}),
 | 
						|
        ("get://localhost:9999?param1=value1&-param2=ignored", {"param1": "value1"}),
 | 
						|
        ("get://localhost:9999?param1=value1&+header=test", {"param1": "value1"}),
 | 
						|
        (
 | 
						|
            "get://localhost:9999?encoded%20param=encoded%20value",
 | 
						|
            {"encoded param": "encoded value"},
 | 
						|
        ),
 | 
						|
    ],
 | 
						|
)
 | 
						|
def test_get_params(url, expected_params):
 | 
						|
    """Test parameter extraction with URL encoding and exclusion logic."""
 | 
						|
    parsed_url = apprise_parse_url(url)
 | 
						|
    params = _get_params(parsed_url)
 | 
						|
    assert dict(params) == expected_params
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize(
 | 
						|
    "url,schema,method",
 | 
						|
    [
 | 
						|
        ("get://localhost:9999", "get", "GET"),
 | 
						|
        ("post://localhost:9999", "post", "POST"),
 | 
						|
        ("delete://localhost:9999", "delete", "DELETE"),
 | 
						|
    ],
 | 
						|
)
 | 
						|
@patch("requests.request")
 | 
						|
def test_apprise_custom_api_call_success(mock_request, url, schema, method):
 | 
						|
    """Test successful API calls with different HTTP methods and schemas."""
 | 
						|
    mock_request.return_value.raise_for_status.return_value = None
 | 
						|
 | 
						|
    meta = {"url": url, "schema": schema}
 | 
						|
    result = apprise_http_custom_handler(
 | 
						|
        body="test body", title="Test Title", notify_type="info", meta=meta
 | 
						|
    )
 | 
						|
 | 
						|
    assert result is True
 | 
						|
    mock_request.assert_called_once()
 | 
						|
 | 
						|
    call_args = mock_request.call_args
 | 
						|
    assert call_args[1]["method"] == method.upper()
 | 
						|
    assert call_args[1]["url"].startswith("http")
 | 
						|
 | 
						|
 | 
						|
@patch("requests.request")
 | 
						|
def test_apprise_custom_api_call_with_auth(mock_request):
 | 
						|
    """Test API call with authentication."""
 | 
						|
    mock_request.return_value.raise_for_status.return_value = None
 | 
						|
 | 
						|
    url = "get://user:pass@localhost:9999/secure"
 | 
						|
    meta = {"url": url, "schema": "get"}
 | 
						|
 | 
						|
    result = apprise_http_custom_handler(
 | 
						|
        body=json.dumps({"key": "value"}),
 | 
						|
        title="Secure Test",
 | 
						|
        notify_type="info",
 | 
						|
        meta=meta,
 | 
						|
    )
 | 
						|
 | 
						|
    assert result is True
 | 
						|
    mock_request.assert_called_once()
 | 
						|
    call_args = mock_request.call_args
 | 
						|
    assert call_args[1]["auth"] == ("user", "pass")
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize(
 | 
						|
    "exception_type,expected_result",
 | 
						|
    [
 | 
						|
        (requests.RequestException, False),
 | 
						|
        (requests.HTTPError, False),
 | 
						|
        (Exception, False),
 | 
						|
    ],
 | 
						|
)
 | 
						|
@patch("requests.request")
 | 
						|
def test_apprise_custom_api_call_failure(mock_request, exception_type, expected_result):
 | 
						|
    """Test various failure scenarios."""
 | 
						|
    url = "get://localhost:9999/error"
 | 
						|
    meta = {"url": url, "schema": "get"}
 | 
						|
 | 
						|
    # Simulate different types of exceptions
 | 
						|
    mock_request.side_effect = exception_type("Error occurred")
 | 
						|
 | 
						|
    result = apprise_http_custom_handler(
 | 
						|
        body="error body", title="Error Test", notify_type="error", meta=meta
 | 
						|
    )
 | 
						|
 | 
						|
    assert result == expected_result
 | 
						|
 | 
						|
 | 
						|
def test_invalid_url_parsing():
 | 
						|
    """Test handling of invalid URL parsing."""
 | 
						|
    meta = {"url": "invalid://url", "schema": "invalid"}
 | 
						|
    result = apprise_http_custom_handler(
 | 
						|
        body="test", title="Invalid URL", notify_type="info", meta=meta
 | 
						|
    )
 | 
						|
 | 
						|
    assert result is False
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize(
 | 
						|
    "schema,expected_method",
 | 
						|
    [
 | 
						|
        (http_method, http_method.upper())
 | 
						|
        for http_method in SUPPORTED_HTTP_METHODS
 | 
						|
    ],
 | 
						|
)
 | 
						|
@patch("requests.request")
 | 
						|
def test_http_methods(mock_request, schema, expected_method):
 | 
						|
    """Test all supported HTTP methods."""
 | 
						|
    mock_request.return_value.raise_for_status.return_value = None
 | 
						|
 | 
						|
    url = f"{schema}://localhost:9999"
 | 
						|
 | 
						|
    result = apprise_http_custom_handler(
 | 
						|
        body="test body",
 | 
						|
        title="Test Title",
 | 
						|
        notify_type="info",
 | 
						|
        meta={"url": url, "schema": schema},
 | 
						|
    )
 | 
						|
 | 
						|
    assert result is True
 | 
						|
    mock_request.assert_called_once()
 | 
						|
 | 
						|
    call_args = mock_request.call_args
 | 
						|
    assert call_args[1]["method"] == expected_method
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize(
 | 
						|
    "input_schema,expected_method",
 | 
						|
    [
 | 
						|
        (f"{http_method}s", http_method.upper())
 | 
						|
        for http_method in SUPPORTED_HTTP_METHODS
 | 
						|
    ],
 | 
						|
)
 | 
						|
@patch("requests.request")
 | 
						|
def test_https_method_conversion(
 | 
						|
    mock_request, input_schema, expected_method
 | 
						|
):
 | 
						|
    """Validate that methods ending with 's' use HTTPS and correct HTTP method."""
 | 
						|
    mock_request.return_value.raise_for_status.return_value = None
 | 
						|
 | 
						|
    url = f"{input_schema}://localhost:9999"
 | 
						|
 | 
						|
    result = apprise_http_custom_handler(
 | 
						|
        body="test body",
 | 
						|
        title="Test Title",
 | 
						|
        notify_type="info",
 | 
						|
        meta={"url": url, "schema": input_schema},
 | 
						|
    )
 | 
						|
 | 
						|
    assert result is True
 | 
						|
    mock_request.assert_called_once()
 | 
						|
 | 
						|
    call_args = mock_request.call_args
 | 
						|
 | 
						|
    assert call_args[1]["method"] == expected_method
 | 
						|
    assert call_args[1]["url"].startswith("https")
 |