-
-
Notifications
You must be signed in to change notification settings - Fork 47
Expand file tree
/
Copy pathconftest.py
More file actions
181 lines (132 loc) · 5.46 KB
/
Copy pathconftest.py
File metadata and controls
181 lines (132 loc) · 5.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
"""Shared pytest fixtures for Sagemcom API client tests."""
# pylint: disable=redefined-outer-name,duplicate-code
import json
from pathlib import Path
from typing import Any
from unittest.mock import AsyncMock, MagicMock
import pytest
from aiohttp import ClientSession
from sagemcom_api.client import SagemcomClient
from sagemcom_api.enums import EncryptionMethod
# Fixture directory path
FIXTURES_DIR = Path(__file__).parent / "fixtures"
def load_fixture(filename: str) -> dict[str, Any]:
"""Load a JSON fixture file.
:param filename: Name of the fixture file (e.g., 'login_success.json')
:return: Parsed JSON data as dict
"""
fixture_path = FIXTURES_DIR / filename
with open(fixture_path, encoding="utf-8") as f:
return json.load(f)
@pytest.fixture
def login_success_response() -> dict[str, Any]:
"""Mock response for successful login."""
return load_fixture("login_success.json")
@pytest.fixture
def login_auth_error_response() -> dict[str, Any]:
"""Mock response for authentication error."""
return load_fixture("login_auth_error.json")
@pytest.fixture
def login_invalid_session_response() -> dict[str, Any]:
"""Mock response for invalid session error."""
return load_fixture("login_invalid_session.json")
@pytest.fixture
def device_info_response() -> dict[str, Any]:
"""Mock response for device info query."""
return load_fixture("device_info.json")
@pytest.fixture
def hosts_response() -> dict[str, Any]:
"""Mock response for hosts query."""
return load_fixture("hosts.json")
@pytest.fixture
def xpath_value_response() -> dict[str, Any]:
"""Mock response for generic XPath getValue."""
return load_fixture("xpath_value.json")
@pytest.fixture
def xpath_unknown_path_error_response() -> dict[str, Any]:
"""Mock response for XPath query that returns XMO_UNKNOWN_PATH_ERR."""
return load_fixture("xpath_unknown_path_error.json")
@pytest.fixture
def xpaths_mixed_errors_response() -> dict[str, Any]:
"""Mock response for multi-XPath query with one success and one unknown-path error."""
return load_fixture("xpaths_mixed_errors.json")
@pytest.fixture
def mock_session_factory():
"""Create a factory for mock aiohttp ClientSession.
Returns a factory function that creates a mock session with configurable responses.
Mock responses are consumed in sequence (first call gets first response, etc.).
Usage:
mock_session = mock_session_factory([response1, response2])
# First POST call returns response1, second returns response2
:return: Factory function that takes list of response dicts
"""
def _create_mock_session(responses: list[dict[str, Any]]) -> ClientSession:
"""Create a mock ClientSession with specified responses.
:param responses: List of response dictionaries to return in sequence
:return: Mock ClientSession
"""
mock_session = MagicMock(spec=ClientSession)
# Create async context manager mock for session.post()
mock_post = MagicMock()
mock_session.post = mock_post
# Create response mocks for each configured response
mock_responses = []
for response_data in responses:
mock_response = AsyncMock()
mock_response.status = 200
mock_response.json = AsyncMock(return_value=response_data)
mock_response.text = AsyncMock(return_value=json.dumps(response_data))
mock_response.__aenter__ = AsyncMock(return_value=mock_response)
mock_response.__aexit__ = AsyncMock(return_value=None)
mock_responses.append(mock_response)
# Configure post() to return responses in sequence
if len(mock_responses) == 1:
mock_post.return_value = mock_responses[0]
else:
mock_post.side_effect = mock_responses
# Mock close method
mock_session.close = AsyncMock()
return mock_session
return _create_mock_session
@pytest.fixture
def mock_client_md5(mock_session_factory, login_success_response):
"""Create a SagemcomClient with MD5 encryption and mocked session.
Pre-configured with successful login response.
:return: SagemcomClient instance
"""
mock_session = mock_session_factory([login_success_response])
return SagemcomClient(
host="192.168.1.1",
username="admin",
password="admin",
authentication_method=EncryptionMethod.MD5,
session=mock_session,
)
@pytest.fixture
def mock_client_sha512(mock_session_factory, login_success_response):
"""Create a SagemcomClient with SHA512 encryption and mocked session.
Pre-configured with successful login response.
:return: SagemcomClient instance
"""
mock_session = mock_session_factory([login_success_response])
return SagemcomClient(
host="192.168.1.1",
username="admin",
password="admin",
authentication_method=EncryptionMethod.SHA512,
session=mock_session,
)
@pytest.fixture
def mock_client_md5_nonce(mock_session_factory, login_success_response):
"""Create a SagemcomClient with MD5_NONCE encryption and mocked session.
Pre-configured with successful login response.
:return: SagemcomClient instance
"""
mock_session = mock_session_factory([login_success_response])
return SagemcomClient(
host="192.168.1.1",
username="admin",
password="admin",
authentication_method=EncryptionMethod.MD5_NONCE,
session=mock_session,
)