regscale-cli 6.23.0.1__py3-none-any.whl → 6.24.0.0__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.

Files changed (43) hide show
  1. regscale/_version.py +1 -1
  2. regscale/core/app/application.py +2 -0
  3. regscale/integrations/commercial/__init__.py +1 -0
  4. regscale/integrations/commercial/sarif/sarif_converter.py +1 -1
  5. regscale/integrations/commercial/wizv2/click.py +109 -2
  6. regscale/integrations/commercial/wizv2/compliance_report.py +1485 -0
  7. regscale/integrations/commercial/wizv2/constants.py +72 -2
  8. regscale/integrations/commercial/wizv2/data_fetcher.py +61 -0
  9. regscale/integrations/commercial/wizv2/file_cleanup.py +104 -0
  10. regscale/integrations/commercial/wizv2/issue.py +775 -27
  11. regscale/integrations/commercial/wizv2/policy_compliance.py +599 -181
  12. regscale/integrations/commercial/wizv2/reports.py +243 -0
  13. regscale/integrations/commercial/wizv2/scanner.py +668 -245
  14. regscale/integrations/compliance_integration.py +304 -51
  15. regscale/integrations/due_date_handler.py +210 -0
  16. regscale/integrations/public/cci_importer.py +444 -0
  17. regscale/integrations/scanner_integration.py +718 -153
  18. regscale/models/integration_models/CCI_List.xml +1 -0
  19. regscale/models/integration_models/cisa_kev_data.json +18 -3
  20. regscale/models/integration_models/synqly_models/capabilities.json +1 -1
  21. regscale/models/regscale_models/form_field_value.py +1 -1
  22. regscale/models/regscale_models/milestone.py +1 -0
  23. regscale/models/regscale_models/regscale_model.py +225 -60
  24. regscale/models/regscale_models/security_plan.py +3 -2
  25. regscale/regscale.py +7 -0
  26. {regscale_cli-6.23.0.1.dist-info → regscale_cli-6.24.0.0.dist-info}/METADATA +9 -9
  27. {regscale_cli-6.23.0.1.dist-info → regscale_cli-6.24.0.0.dist-info}/RECORD +43 -26
  28. tests/fixtures/test_fixture.py +13 -8
  29. tests/regscale/integrations/public/__init__.py +0 -0
  30. tests/regscale/integrations/public/test_alienvault.py +220 -0
  31. tests/regscale/integrations/public/test_cci.py +458 -0
  32. tests/regscale/integrations/public/test_cisa.py +1021 -0
  33. tests/regscale/integrations/public/test_emass.py +518 -0
  34. tests/regscale/integrations/public/test_fedramp.py +851 -0
  35. tests/regscale/integrations/public/test_fedramp_cis_crm.py +3661 -0
  36. tests/regscale/integrations/public/test_file_uploads.py +506 -0
  37. tests/regscale/integrations/public/test_oscal.py +453 -0
  38. tests/regscale/models/test_form_field_value_integration.py +304 -0
  39. tests/regscale/models/test_module_integration.py +582 -0
  40. {regscale_cli-6.23.0.1.dist-info → regscale_cli-6.24.0.0.dist-info}/LICENSE +0 -0
  41. {regscale_cli-6.23.0.1.dist-info → regscale_cli-6.24.0.0.dist-info}/WHEEL +0 -0
  42. {regscale_cli-6.23.0.1.dist-info → regscale_cli-6.24.0.0.dist-info}/entry_points.txt +0 -0
  43. {regscale_cli-6.23.0.1.dist-info → regscale_cli-6.24.0.0.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