regscale-cli 6.23.0.1__py3-none-any.whl → 6.24.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of regscale-cli might be problematic. Click here for more details.
- regscale/_version.py +1 -1
- regscale/core/app/application.py +2 -0
- regscale/integrations/commercial/__init__.py +1 -0
- regscale/integrations/commercial/jira.py +95 -22
- regscale/integrations/commercial/sarif/sarif_converter.py +1 -1
- regscale/integrations/commercial/wizv2/click.py +132 -2
- regscale/integrations/commercial/wizv2/compliance_report.py +1574 -0
- regscale/integrations/commercial/wizv2/constants.py +72 -2
- regscale/integrations/commercial/wizv2/data_fetcher.py +61 -0
- regscale/integrations/commercial/wizv2/file_cleanup.py +104 -0
- regscale/integrations/commercial/wizv2/issue.py +775 -27
- regscale/integrations/commercial/wizv2/policy_compliance.py +599 -181
- regscale/integrations/commercial/wizv2/reports.py +243 -0
- regscale/integrations/commercial/wizv2/scanner.py +668 -245
- regscale/integrations/compliance_integration.py +534 -56
- regscale/integrations/due_date_handler.py +210 -0
- regscale/integrations/public/cci_importer.py +444 -0
- regscale/integrations/scanner_integration.py +718 -153
- regscale/models/integration_models/CCI_List.xml +1 -0
- regscale/models/integration_models/cisa_kev_data.json +18 -3
- regscale/models/integration_models/synqly_models/capabilities.json +1 -1
- regscale/models/regscale_models/control_implementation.py +13 -3
- regscale/models/regscale_models/form_field_value.py +1 -1
- regscale/models/regscale_models/milestone.py +1 -0
- regscale/models/regscale_models/regscale_model.py +225 -60
- regscale/models/regscale_models/security_plan.py +3 -2
- regscale/regscale.py +7 -0
- {regscale_cli-6.23.0.1.dist-info → regscale_cli-6.24.0.1.dist-info}/METADATA +17 -17
- {regscale_cli-6.23.0.1.dist-info → regscale_cli-6.24.0.1.dist-info}/RECORD +45 -28
- tests/fixtures/test_fixture.py +13 -8
- tests/regscale/integrations/public/__init__.py +0 -0
- tests/regscale/integrations/public/test_alienvault.py +220 -0
- tests/regscale/integrations/public/test_cci.py +458 -0
- tests/regscale/integrations/public/test_cisa.py +1021 -0
- tests/regscale/integrations/public/test_emass.py +518 -0
- tests/regscale/integrations/public/test_fedramp.py +851 -0
- tests/regscale/integrations/public/test_fedramp_cis_crm.py +3661 -0
- tests/regscale/integrations/public/test_file_uploads.py +506 -0
- tests/regscale/integrations/public/test_oscal.py +453 -0
- tests/regscale/models/test_form_field_value_integration.py +304 -0
- tests/regscale/models/test_module_integration.py +582 -0
- {regscale_cli-6.23.0.1.dist-info → regscale_cli-6.24.0.1.dist-info}/LICENSE +0 -0
- {regscale_cli-6.23.0.1.dist-info → regscale_cli-6.24.0.1.dist-info}/WHEEL +0 -0
- {regscale_cli-6.23.0.1.dist-info → regscale_cli-6.24.0.1.dist-info}/entry_points.txt +0 -0
- {regscale_cli-6.23.0.1.dist-info → regscale_cli-6.24.0.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Integration tests for FormFieldValue model API endpoints"""
|
|
4
|
+
|
|
5
|
+
from typing import List
|
|
6
|
+
from unittest.mock import MagicMock, patch
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
from requests import Response
|
|
10
|
+
|
|
11
|
+
from regscale.models.regscale_models.form_field_value import FormFieldValue
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TestFormFieldValueIntegration:
|
|
15
|
+
"""Integration tests for FormFieldValue model covering all API endpoints"""
|
|
16
|
+
|
|
17
|
+
@pytest.fixture
|
|
18
|
+
def mock_api_handler(self):
|
|
19
|
+
"""Mock API handler for testing"""
|
|
20
|
+
with patch("regscale.models.regscale_models.form_field_value.FormFieldValue._get_api_handler") as mock:
|
|
21
|
+
yield mock.return_value
|
|
22
|
+
|
|
23
|
+
@pytest.fixture
|
|
24
|
+
def sample_form_field_data(self):
|
|
25
|
+
"""Sample form field data for testing"""
|
|
26
|
+
return [{"formFieldId": 1, "data": "Test Value 1"}, {"formFieldId": 2, "data": "Test Value 2"}]
|
|
27
|
+
|
|
28
|
+
@pytest.fixture
|
|
29
|
+
def sample_form_field_values(self):
|
|
30
|
+
"""Sample FormFieldValue objects for testing"""
|
|
31
|
+
return [FormFieldValue(formFieldId=1, data="Test Value 1"), FormFieldValue(formFieldId=2, data="Test Value 2")]
|
|
32
|
+
|
|
33
|
+
def test_save_custom_data_success(self, mock_api_handler, sample_form_field_values):
|
|
34
|
+
"""Test POST /api/formFieldValue/saveFormFields/{recordId}/{moduleName} - Success"""
|
|
35
|
+
# Setup
|
|
36
|
+
mock_response = MagicMock(spec=Response)
|
|
37
|
+
mock_response.ok = True
|
|
38
|
+
mock_api_handler.post.return_value = mock_response
|
|
39
|
+
|
|
40
|
+
record_id = 123
|
|
41
|
+
module_name = "cases"
|
|
42
|
+
|
|
43
|
+
# Execute
|
|
44
|
+
result = FormFieldValue.save_custom_data(record_id, module_name, sample_form_field_values)
|
|
45
|
+
|
|
46
|
+
# Assert
|
|
47
|
+
assert result is True
|
|
48
|
+
mock_api_handler.post.assert_called_once()
|
|
49
|
+
|
|
50
|
+
call_args = mock_api_handler.post.call_args
|
|
51
|
+
assert call_args[1]["endpoint"] == "/api/formFieldValue/saveFormFields/123/cases"
|
|
52
|
+
|
|
53
|
+
# Check that data was filtered to only include formFieldId and data
|
|
54
|
+
expected_data = [{"formFieldId": 1, "data": "Test Value 1"}, {"formFieldId": 2, "data": "Test Value 2"}]
|
|
55
|
+
assert call_args[1]["data"] == expected_data
|
|
56
|
+
|
|
57
|
+
def test_save_custom_data_failure(self, mock_api_handler, sample_form_field_values):
|
|
58
|
+
"""Test POST /api/formFieldValue/saveFormFields/{recordId}/{moduleName} - Failure"""
|
|
59
|
+
# Setup
|
|
60
|
+
mock_response = MagicMock(spec=Response)
|
|
61
|
+
mock_response.ok = False
|
|
62
|
+
mock_api_handler.post.return_value = mock_response
|
|
63
|
+
|
|
64
|
+
record_id = 123
|
|
65
|
+
module_name = "cases"
|
|
66
|
+
|
|
67
|
+
# Mock log_response_error
|
|
68
|
+
with patch.object(FormFieldValue, "log_response_error") as mock_log:
|
|
69
|
+
# Execute
|
|
70
|
+
result = FormFieldValue.save_custom_data(record_id, module_name, sample_form_field_values)
|
|
71
|
+
|
|
72
|
+
# Assert
|
|
73
|
+
assert result is False
|
|
74
|
+
mock_log.assert_called_once_with(response=mock_response)
|
|
75
|
+
|
|
76
|
+
def test_save_custom_data_empty_data(self, mock_api_handler):
|
|
77
|
+
"""Test save_custom_data with empty data list"""
|
|
78
|
+
# Setup
|
|
79
|
+
mock_response = MagicMock(spec=Response)
|
|
80
|
+
mock_response.ok = True
|
|
81
|
+
mock_api_handler.post.return_value = mock_response
|
|
82
|
+
|
|
83
|
+
# Execute
|
|
84
|
+
result = FormFieldValue.save_custom_data(123, "cases", [])
|
|
85
|
+
|
|
86
|
+
# Assert
|
|
87
|
+
assert result is True
|
|
88
|
+
mock_api_handler.post.assert_called_once()
|
|
89
|
+
call_args = mock_api_handler.post.call_args
|
|
90
|
+
assert call_args[1]["data"] == []
|
|
91
|
+
|
|
92
|
+
def test_get_field_values_success(self, mock_api_handler):
|
|
93
|
+
"""Test GET /api/formFieldValue/getFieldValues/{recordId}/{moduleName}/{formId} - Success"""
|
|
94
|
+
# Setup
|
|
95
|
+
mock_response = MagicMock(spec=Response)
|
|
96
|
+
mock_response.ok = True
|
|
97
|
+
mock_response.json.return_value = [
|
|
98
|
+
{"formFieldName": "Field1", "formFieldId": 1, "data": "Value1"},
|
|
99
|
+
{"formFieldName": "Field2", "formFieldId": 2, "data": "Value2"},
|
|
100
|
+
]
|
|
101
|
+
mock_api_handler.get.return_value = mock_response
|
|
102
|
+
|
|
103
|
+
record_id = 123
|
|
104
|
+
module_name = "cases"
|
|
105
|
+
form_id = 456
|
|
106
|
+
|
|
107
|
+
# Execute
|
|
108
|
+
result = FormFieldValue.get_field_values(record_id, module_name, form_id)
|
|
109
|
+
|
|
110
|
+
# Assert
|
|
111
|
+
assert len(result) == 2
|
|
112
|
+
assert all(isinstance(item, FormFieldValue) for item in result)
|
|
113
|
+
assert result[0].formFieldId == 1
|
|
114
|
+
assert result[0].data == "Value1"
|
|
115
|
+
assert result[1].formFieldId == 2
|
|
116
|
+
assert result[1].data == "Value2"
|
|
117
|
+
|
|
118
|
+
mock_api_handler.get.assert_called_once()
|
|
119
|
+
call_args = mock_api_handler.get.call_args
|
|
120
|
+
assert call_args[1]["endpoint"] == "/api/formFieldValue/getFieldValues/123/cases/456"
|
|
121
|
+
|
|
122
|
+
def test_get_field_values_failure(self, mock_api_handler):
|
|
123
|
+
"""Test GET /api/formFieldValue/getFieldValues/{recordId}/{moduleName}/{formId} - Failure"""
|
|
124
|
+
# Setup
|
|
125
|
+
mock_response = MagicMock(spec=Response)
|
|
126
|
+
mock_response.ok = False
|
|
127
|
+
mock_api_handler.get.return_value = mock_response
|
|
128
|
+
|
|
129
|
+
# Mock log_response_error
|
|
130
|
+
with patch.object(FormFieldValue, "log_response_error") as mock_log:
|
|
131
|
+
# Execute
|
|
132
|
+
result = FormFieldValue.get_field_values(123, "cases", 456)
|
|
133
|
+
|
|
134
|
+
# Assert
|
|
135
|
+
assert result == []
|
|
136
|
+
mock_log.assert_called_once_with(response=mock_response)
|
|
137
|
+
|
|
138
|
+
def test_get_field_values_empty_response(self, mock_api_handler):
|
|
139
|
+
"""Test get_field_values with empty response"""
|
|
140
|
+
# Setup
|
|
141
|
+
mock_response = MagicMock(spec=Response)
|
|
142
|
+
mock_response.ok = True
|
|
143
|
+
mock_response.json.return_value = []
|
|
144
|
+
mock_api_handler.get.return_value = mock_response
|
|
145
|
+
|
|
146
|
+
# Execute
|
|
147
|
+
result = FormFieldValue.get_field_values(123, "cases", 456)
|
|
148
|
+
|
|
149
|
+
# Assert
|
|
150
|
+
assert result == []
|
|
151
|
+
|
|
152
|
+
def test_get_field_values_by_name_endpoint(self, mock_api_handler):
|
|
153
|
+
"""Test that the missing getFieldValuesByName endpoint would work if implemented"""
|
|
154
|
+
# Note: This endpoint is mentioned in the requirements but not implemented in the model
|
|
155
|
+
# This test demonstrates how it would be tested if implemented
|
|
156
|
+
|
|
157
|
+
# Setup - Mock the endpoint as if it were implemented
|
|
158
|
+
with patch.object(FormFieldValue, "_get_additional_endpoints") as mock_endpoints:
|
|
159
|
+
mock_endpoints.return_value = {
|
|
160
|
+
"get_field_values_by_name": "/api/{model_slug}/getFieldValuesByName/{recordId}/{moduleName}/{regscaleId}"
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
mock_response = MagicMock(spec=Response)
|
|
164
|
+
mock_response.ok = True
|
|
165
|
+
mock_response.json.return_value = [{"formFieldName": "TestField", "formFieldId": 1, "data": "TestValue"}]
|
|
166
|
+
mock_api_handler.get.return_value = mock_response
|
|
167
|
+
|
|
168
|
+
# This would be the method if implemented
|
|
169
|
+
def get_field_values_by_name(
|
|
170
|
+
cls, record_id: int, module_name: str, regscale_id: str
|
|
171
|
+
) -> List[FormFieldValue]:
|
|
172
|
+
result = cls._get_api_handler().get(
|
|
173
|
+
endpoint=cls.get_endpoint("get_field_values_by_name").format(
|
|
174
|
+
model_slug=cls.get_module_slug(),
|
|
175
|
+
recordId=record_id,
|
|
176
|
+
moduleName=module_name,
|
|
177
|
+
regscaleId=regscale_id,
|
|
178
|
+
)
|
|
179
|
+
)
|
|
180
|
+
if result and result.ok:
|
|
181
|
+
return [cls(**o) for o in result.json()]
|
|
182
|
+
return []
|
|
183
|
+
|
|
184
|
+
# Add method to class temporarily for testing
|
|
185
|
+
FormFieldValue.get_field_values_by_name = classmethod(get_field_values_by_name)
|
|
186
|
+
|
|
187
|
+
try:
|
|
188
|
+
# Execute
|
|
189
|
+
result = FormFieldValue.get_field_values_by_name(123, "cases", "test-regscale-id")
|
|
190
|
+
|
|
191
|
+
# Assert
|
|
192
|
+
assert len(result) == 1
|
|
193
|
+
assert isinstance(result[0], FormFieldValue)
|
|
194
|
+
mock_api_handler.get.assert_called_once()
|
|
195
|
+
call_args = mock_api_handler.get.call_args
|
|
196
|
+
expected_endpoint = "/api/formFieldValue/getFieldValuesByName/123/cases/test-regscale-id"
|
|
197
|
+
assert call_args[1]["endpoint"] == expected_endpoint
|
|
198
|
+
finally:
|
|
199
|
+
# Clean up
|
|
200
|
+
delattr(FormFieldValue, "get_field_values_by_name")
|
|
201
|
+
|
|
202
|
+
def test_filter_dict_keys(self):
|
|
203
|
+
"""Test the filter_dict_keys static method"""
|
|
204
|
+
# Setup
|
|
205
|
+
data = {
|
|
206
|
+
"formFieldId": 1,
|
|
207
|
+
"data": "test value",
|
|
208
|
+
"extra_field": "should be filtered out",
|
|
209
|
+
"another_field": "also filtered",
|
|
210
|
+
}
|
|
211
|
+
allowed_fields = ["formFieldId", "data"]
|
|
212
|
+
|
|
213
|
+
# Execute
|
|
214
|
+
result = FormFieldValue.filter_dict_keys(data, allowed_fields)
|
|
215
|
+
|
|
216
|
+
# Assert
|
|
217
|
+
assert result == {"formFieldId": 1, "data": "test value"}
|
|
218
|
+
assert "extra_field" not in result
|
|
219
|
+
assert "another_field" not in result
|
|
220
|
+
|
|
221
|
+
def test_filter_dict_keys_empty_data(self):
|
|
222
|
+
"""Test filter_dict_keys with empty data"""
|
|
223
|
+
result = FormFieldValue.filter_dict_keys({}, ["formFieldId", "data"])
|
|
224
|
+
assert result == {}
|
|
225
|
+
|
|
226
|
+
def test_filter_dict_keys_empty_allowed_fields(self):
|
|
227
|
+
"""Test filter_dict_keys with empty allowed fields"""
|
|
228
|
+
data = {"formFieldId": 1, "data": "test"}
|
|
229
|
+
result = FormFieldValue.filter_dict_keys(data, [])
|
|
230
|
+
assert result == {}
|
|
231
|
+
|
|
232
|
+
def test_module_slug(self):
|
|
233
|
+
"""Test that the module slug is correctly set"""
|
|
234
|
+
assert FormFieldValue._module_slug == "formFieldValue"
|
|
235
|
+
|
|
236
|
+
def test_additional_endpoints(self):
|
|
237
|
+
"""Test that additional endpoints are correctly defined"""
|
|
238
|
+
endpoints = FormFieldValue._get_additional_endpoints()
|
|
239
|
+
|
|
240
|
+
assert "post_save_form_fields" in endpoints
|
|
241
|
+
assert "get_field_value" in endpoints
|
|
242
|
+
|
|
243
|
+
assert endpoints["post_save_form_fields"] == "/api/{model_slug}/saveFormFields/{recordId}/{moduleName}"
|
|
244
|
+
assert endpoints["get_field_value"] == "/api/{model_slug}/getFieldValues/{recordId}/{moduleName}/{formId}"
|
|
245
|
+
|
|
246
|
+
def test_field_aliases(self):
|
|
247
|
+
"""Test that field aliases work correctly"""
|
|
248
|
+
# Test that 'data' field can be set via 'fieldValue' alias
|
|
249
|
+
form_field = FormFieldValue(formFieldId=1, fieldValue="test value")
|
|
250
|
+
assert form_field.data == "test value"
|
|
251
|
+
|
|
252
|
+
# Test dict creation with alias
|
|
253
|
+
form_field_dict = form_field.dict(by_alias=True)
|
|
254
|
+
assert "fieldValue" in form_field_dict
|
|
255
|
+
assert form_field_dict["fieldValue"] == "test value"
|
|
256
|
+
|
|
257
|
+
@pytest.mark.parametrize(
|
|
258
|
+
"record_id,module_name,expected_endpoint",
|
|
259
|
+
[
|
|
260
|
+
(123, "cases", "/api/formFieldValue/saveFormFields/123/cases"),
|
|
261
|
+
(456, "assets", "/api/formFieldValue/saveFormFields/456/assets"),
|
|
262
|
+
(789, "issues", "/api/formFieldValue/saveFormFields/789/issues"),
|
|
263
|
+
],
|
|
264
|
+
)
|
|
265
|
+
def test_save_custom_data_endpoint_formation(
|
|
266
|
+
self, mock_api_handler, sample_form_field_values, record_id, module_name, expected_endpoint
|
|
267
|
+
):
|
|
268
|
+
"""Test endpoint formation for different parameters"""
|
|
269
|
+
# Setup
|
|
270
|
+
mock_response = MagicMock(spec=Response)
|
|
271
|
+
mock_response.ok = True
|
|
272
|
+
mock_api_handler.post.return_value = mock_response
|
|
273
|
+
|
|
274
|
+
# Execute
|
|
275
|
+
FormFieldValue.save_custom_data(record_id, module_name, sample_form_field_values)
|
|
276
|
+
|
|
277
|
+
# Assert
|
|
278
|
+
call_args = mock_api_handler.post.call_args
|
|
279
|
+
assert call_args[1]["endpoint"] == expected_endpoint
|
|
280
|
+
|
|
281
|
+
@pytest.mark.parametrize(
|
|
282
|
+
"record_id,module_name,form_id,expected_endpoint",
|
|
283
|
+
[
|
|
284
|
+
(123, "cases", 456, "/api/formFieldValue/getFieldValues/123/cases/456"),
|
|
285
|
+
(789, "assets", 101, "/api/formFieldValue/getFieldValues/789/assets/101"),
|
|
286
|
+
(999, "issues", 202, "/api/formFieldValue/getFieldValues/999/issues/202"),
|
|
287
|
+
],
|
|
288
|
+
)
|
|
289
|
+
def test_get_field_values_endpoint_formation(
|
|
290
|
+
self, mock_api_handler, record_id, module_name, form_id, expected_endpoint
|
|
291
|
+
):
|
|
292
|
+
"""Test endpoint formation for get_field_values with different parameters"""
|
|
293
|
+
# Setup
|
|
294
|
+
mock_response = MagicMock(spec=Response)
|
|
295
|
+
mock_response.ok = True
|
|
296
|
+
mock_response.json.return_value = []
|
|
297
|
+
mock_api_handler.get.return_value = mock_response
|
|
298
|
+
|
|
299
|
+
# Execute
|
|
300
|
+
FormFieldValue.get_field_values(record_id, module_name, form_id)
|
|
301
|
+
|
|
302
|
+
# Assert
|
|
303
|
+
call_args = mock_api_handler.get.call_args
|
|
304
|
+
assert call_args[1]["endpoint"] == expected_endpoint
|