Skip to content

Commit 711d42d

Browse files
committed
created tests
1 parent 802dc6b commit 711d42d

File tree

3 files changed

+731
-12
lines changed

3 files changed

+731
-12
lines changed

tests/test_cft_methods.py

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
"""Test Custom File Transfer (CFT) methods"""
2+
3+
import pytest
4+
import responses
5+
import tempfile
6+
import os
7+
from unittest.mock import Mock, patch, mock_open
8+
from jupiterone.client import JupiterOneClient
9+
from jupiterone.errors import JupiterOneApiError
10+
from jupiterone.constants import INVOKE_INTEGRATION_INSTANCE
11+
12+
13+
class TestCFTMethods:
14+
"""Test Custom File Transfer (CFT) methods"""
15+
16+
def setup_method(self):
17+
"""Set up test fixtures"""
18+
self.client = JupiterOneClient(account="test-account", token="test-token")
19+
self.integration_instance_id = "test-integration-instance-123"
20+
self.dataset_id = "test-dataset-456"
21+
self.filename = "test_data.csv"
22+
23+
@patch('jupiterone.client.JupiterOneClient._execute_query')
24+
def test_get_cft_upload_url_success(self, mock_execute_query):
25+
"""Test successful CFT upload URL retrieval"""
26+
mock_response = {
27+
"data": {
28+
"integrationFileTransferUploadUrl": {
29+
"uploadUrl": "https://s3.amazonaws.com/test-bucket/test-file.csv",
30+
"expiresAt": "2024-01-01T12:00:00Z"
31+
}
32+
}
33+
}
34+
mock_execute_query.return_value = mock_response
35+
36+
result = self.client.get_cft_upload_url(
37+
integration_instance_id=self.integration_instance_id,
38+
filename=self.filename,
39+
dataset_id=self.dataset_id
40+
)
41+
42+
assert result == mock_response["data"]["integrationFileTransferUploadUrl"]
43+
mock_execute_query.assert_called_once()
44+
45+
@patch('jupiterone.client.JupiterOneClient._execute_query')
46+
def test_get_cft_upload_url_error(self, mock_execute_query):
47+
"""Test CFT upload URL retrieval with error"""
48+
mock_execute_query.side_effect = JupiterOneApiError("API Error")
49+
50+
with pytest.raises(JupiterOneApiError):
51+
self.client.get_cft_upload_url(
52+
integration_instance_id=self.integration_instance_id,
53+
filename=self.filename,
54+
dataset_id=self.dataset_id
55+
)
56+
57+
@patch('jupiterone.client.JupiterOneClient._execute_query')
58+
def test_get_cft_upload_url_missing_data(self, mock_execute_query):
59+
"""Test CFT upload URL retrieval with missing data in response"""
60+
mock_response = {
61+
"data": {
62+
"integrationFileTransferUploadUrl": None
63+
}
64+
}
65+
mock_execute_query.return_value = mock_response
66+
67+
result = self.client.get_cft_upload_url(
68+
integration_instance_id=self.integration_instance_id,
69+
filename=self.filename,
70+
dataset_id=self.dataset_id
71+
)
72+
73+
assert result is None
74+
75+
@patch('builtins.open', new_callable=mock_open, read_data="test,csv,data")
76+
@patch('requests.Session.put')
77+
def test_upload_cft_file_csv_success(self, mock_put, mock_file):
78+
"""Test successful CSV file upload"""
79+
# Mock successful HTTP response
80+
mock_response = Mock()
81+
mock_response.status_code = 200
82+
mock_response.headers = {'Content-Type': 'text/csv'}
83+
mock_response.text = '{"status": "success"}'
84+
mock_response.json.return_value = {"status": "success"}
85+
mock_put.return_value = mock_response
86+
87+
# Create a temporary file path
88+
with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as temp_file:
89+
temp_file.write(b"test,csv,data")
90+
temp_file_path = temp_file.name
91+
92+
try:
93+
result = self.client.upload_cft_file(
94+
upload_url="https://s3.amazonaws.com/test-bucket/test-file.csv",
95+
file_path=temp_file_path
96+
)
97+
98+
# Verify the result structure
99+
assert result['status_code'] == 200
100+
assert result['success'] is True
101+
assert result['response_data'] == {"status": "success"}
102+
assert 'Content-Type' in result['headers']
103+
assert result['headers']['Content-Type'] == 'text/csv'
104+
105+
# Verify the PUT request was made correctly
106+
mock_put.assert_called_once()
107+
call_args = mock_put.call_args
108+
assert call_args[0][0] == "https://s3.amazonaws.com/test-bucket/test-file.csv"
109+
assert call_args[1]['headers']['Content-Type'] == 'text/csv'
110+
assert call_args[1]['timeout'] == 300
111+
112+
finally:
113+
# Clean up temporary file
114+
os.unlink(temp_file_path)
115+
116+
@patch('builtins.open', new_callable=mock_open, read_data="test,csv,data")
117+
@patch('requests.Session.put')
118+
def test_upload_cft_file_csv_error_response(self, mock_put, mock_file):
119+
"""Test CSV file upload with error response"""
120+
# Mock error HTTP response
121+
mock_response = Mock()
122+
mock_response.status_code = 400
123+
mock_response.headers = {'Content-Type': 'application/json'}
124+
mock_response.text = '{"error": "Bad Request"}'
125+
mock_response.json.return_value = {"error": "Bad Request"}
126+
mock_put.return_value = mock_response
127+
128+
# Create a temporary file path
129+
with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as temp_file:
130+
temp_file.write(b"test,csv,data")
131+
temp_file_path = temp_file.name
132+
133+
try:
134+
result = self.client.upload_cft_file(
135+
upload_url="https://s3.amazonaws.com/test-bucket/test-file.csv",
136+
file_path=temp_file_path
137+
)
138+
139+
# Verify the result structure for error case
140+
assert result['status_code'] == 400
141+
assert result['success'] is False
142+
assert result['response_data'] == {"error": "Bad Request"}
143+
144+
finally:
145+
# Clean up temporary file
146+
os.unlink(temp_file_path)
147+
148+
def test_upload_cft_file_nonexistent_file(self):
149+
"""Test CSV file upload with nonexistent file"""
150+
with pytest.raises(FileNotFoundError):
151+
self.client.upload_cft_file(
152+
upload_url="https://s3.amazonaws.com/test-bucket/test-file.csv",
153+
file_path="/nonexistent/file.csv"
154+
)
155+
156+
def test_upload_cft_file_non_csv_extension(self):
157+
"""Test file upload with non-CSV extension"""
158+
with tempfile.NamedTemporaryFile(suffix='.txt', delete=False) as temp_file:
159+
temp_file.write(b"test data")
160+
temp_file_path = temp_file.name
161+
162+
try:
163+
with pytest.raises(ValueError, match="Only CSV files are supported"):
164+
self.client.upload_cft_file(
165+
upload_url="https://s3.amazonaws.com/test-bucket/test-file.csv",
166+
file_path=temp_file_path
167+
)
168+
finally:
169+
os.unlink(temp_file_path)
170+
171+
def test_upload_cft_file_csv_extension_case_insensitive(self):
172+
"""Test file upload with CSV extension in different cases"""
173+
# Test uppercase .CSV
174+
with tempfile.NamedTemporaryFile(suffix='.CSV', delete=False) as temp_file:
175+
temp_file.write(b"test,csv,data")
176+
temp_file_path = temp_file.name
177+
178+
try:
179+
with patch('requests.Session.put') as mock_put:
180+
mock_response = Mock()
181+
mock_response.status_code = 200
182+
mock_response.headers = {'Content-Type': 'text/csv'}
183+
mock_response.text = '{"status": "success"}'
184+
mock_response.json.return_value = {"status": "success"}
185+
mock_put.return_value = mock_response
186+
187+
result = self.client.upload_cft_file(
188+
upload_url="https://s3.amazonaws.com/test-bucket/test-file.csv",
189+
file_path=temp_file_path
190+
)
191+
192+
assert result['success'] is True
193+
194+
finally:
195+
os.unlink(temp_file_path)
196+
197+
@patch('jupiterone.client.JupiterOneClient._execute_query')
198+
def test_invoke_cft_integration_success(self, mock_execute_query):
199+
"""Test successful CFT integration invocation"""
200+
mock_response = {
201+
"data": {
202+
"invokeIntegrationInstance": {
203+
"success": True,
204+
"integrationJobId": "job-123"
205+
}
206+
}
207+
}
208+
mock_execute_query.return_value = mock_response
209+
210+
result = self.client.invoke_cft_integration(self.integration_instance_id)
211+
212+
assert result == "job-123"
213+
mock_execute_query.assert_called_once_with(
214+
INVOKE_INTEGRATION_INSTANCE,
215+
{"id": self.integration_instance_id}
216+
)
217+
218+
@patch('jupiterone.client.JupiterOneClient._execute_query')
219+
def test_invoke_cft_integration_already_executing(self, mock_execute_query):
220+
"""Test CFT integration invocation when already executing"""
221+
mock_response = {
222+
"data": {
223+
"invokeIntegrationInstance": {
224+
"success": False,
225+
"integrationJobId": None
226+
}
227+
}
228+
}
229+
mock_execute_query.return_value = mock_response
230+
231+
result = self.client.invoke_cft_integration(self.integration_instance_id)
232+
233+
assert result is False
234+
mock_execute_query.assert_called_once()
235+
236+
@patch('jupiterone.client.JupiterOneClient._execute_query')
237+
def test_invoke_cft_integration_api_error(self, mock_execute_query):
238+
"""Test CFT integration invocation with API error"""
239+
mock_execute_query.side_effect = JupiterOneApiError("API Error")
240+
241+
with pytest.raises(JupiterOneApiError):
242+
self.client.invoke_cft_integration(self.integration_instance_id)
243+
244+
@patch('jupiterone.client.JupiterOneClient._execute_query')
245+
def test_invoke_cft_integration_unexpected_response(self, mock_execute_query):
246+
"""Test CFT integration invocation with unexpected response structure"""
247+
mock_response = {
248+
"data": {
249+
"invokeIntegrationInstance": {
250+
"success": True,
251+
"integrationJobId": None # Unexpected: success but no job ID
252+
}
253+
}
254+
}
255+
mock_execute_query.return_value = mock_response
256+
257+
result = self.client.invoke_cft_integration(self.integration_instance_id)
258+
259+
# Should return False when success is True but no job ID
260+
assert result is False
261+
262+
def test_invoke_cft_integration_empty_instance_id(self):
263+
"""Test CFT integration invocation with empty instance ID"""
264+
with pytest.raises(ValueError, match="integration_instance_id is required"):
265+
self.client.invoke_cft_integration("")
266+
267+
def test_invoke_cft_integration_none_instance_id(self):
268+
"""Test CFT integration invocation with None instance ID"""
269+
with pytest.raises(ValueError, match="integration_instance_id is required"):
270+
self.client.invoke_cft_integration(None)

0 commit comments

Comments
 (0)