Skip to content

Commit 63503d0

Browse files
Merge pull request #8 from agile-learning-institute/API-Updates-for-SPA-work-
Api updates for spa work
2 parents 0c5fed1 + 163d83f commit 63503d0

File tree

9 files changed

+50
-41
lines changed

9 files changed

+50
-41
lines changed

docker-compose.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ services:
2828
environment:
2929
MONGO_CONNECTION_STRING: mongodb://mongodb:27017/?replicaSet=rs0
3030
MONGO_DB_NAME: test_database
31-
MONGODB_API_PORT: 8081
3231
AUTO_PROCESS: True
3332
LOAD_TEST_DATA: True
3433
depends_on:

docs/openapi.yaml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -366,14 +366,6 @@ components:
366366
- default
367367
- file
368368
- environment
369-
versions:
370-
type: array
371-
description: List of version information
372-
items:
373-
type: object
374-
enumerators:
375-
type: object
376-
description: Dictionary of enumerations
377369
token:
378370
type: object
379371
properties:

stage0_mongodb_api/routes/collection_routes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def process_collections():
5050
"message": str(e)
5151
}]), 500
5252

53-
@blueprint.route('/<collection_name>', methods=['GET'])
53+
@blueprint.route('/<collection_name>/', methods=['GET'])
5454
def get_collection(collection_name):
5555
"""Get a specific collection configuration"""
5656
token = create_flask_token()
@@ -74,7 +74,7 @@ def get_collection(collection_name):
7474
"message": str(e)
7575
}]), 500
7676

77-
@blueprint.route('/<collection_name>', methods=['POST'])
77+
@blueprint.route('/<collection_name>/', methods=['POST'])
7878
def process_collection(collection_name):
7979
"""Process a specific collection"""
8080
token = create_flask_token()

stage0_mongodb_api/server.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ def handle_exit(signum, frame):
3434
app = Flask(__name__)
3535
app.json = MongoJSONEncoder(app)
3636

37+
# Configure Flask to be strict about trailing slashes
38+
app.url_map.strict_slashes = False
39+
3740
# Auto-processing logic - runs when module is imported (including by Gunicorn)
3841
if config.AUTO_PROCESS:
3942
logger.info(f"============= Auto Processing is Enabled ===============")

stage0_mongodb_api/services/collection_service.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ class CollectionService:
2626
"""
2727

2828
@staticmethod
29-
def list_collections(token: Dict = None) -> Dict:
29+
def list_collections(token: Dict = None) -> List[Dict]:
3030
"""List all configured collections.
3131
3232
Args:
3333
token: Authentication token for RBAC enforcement
3434
3535
Returns:
36-
Dictionary of collection name: version string
36+
List of dictionaries with collection_name and version
3737
3838
Raises:
3939
CollectionProcessingError: If there are load or validation errors
@@ -49,10 +49,13 @@ def list_collections(token: Dict = None) -> Dict:
4949
if validation_errors:
5050
raise CollectionProcessingError("collections", validation_errors)
5151

52-
# Create a dict of collection name: version string
53-
collections = {}
52+
# Create a list of collection objects matching the OpenAPI schema
53+
collections = []
5454
for collection_name, collection in config_manager.collection_configs.items():
55-
collections[collection_name] = VersionManager.get_current_version(collection_name)
55+
collections.append({
56+
"collection_name": collection_name,
57+
"version": VersionManager.get_current_version(collection_name)
58+
})
5659
return collections
5760

5861
@staticmethod

tests/routes/test_collection_routes.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ def setUp(self):
1515
def test_list_collections_success(self, mock_collection_service):
1616
"""Test listing all collections successfully"""
1717
# Arrange
18-
mock_collections = {
19-
"users": "1.0.0.1",
20-
"organizations": "1.0.0.1"
21-
}
18+
mock_collections = [
19+
{"collection_name": "users", "version": "1.0.0.1"},
20+
{"collection_name": "organizations", "version": "1.0.0.1"}
21+
]
2222
mock_collection_service.list_collections.return_value = mock_collections
2323

2424
# Act
@@ -98,12 +98,12 @@ def test_get_collection_success(self, mock_collection_service):
9898
mock_collection_service.get_collection.return_value = mock_collection
9999

100100
# Act
101-
response = self.client.get(f'/api/collections/users')
101+
response = self.client.get(f'/api/collections/{collection_name}/')
102102

103103
# Assert
104104
self.assertEqual(response.status_code, 200)
105105
self.assertEqual(response.json, mock_collection)
106-
mock_collection_service.get_collection.assert_called_once()
106+
mock_collection_service.get_collection.assert_called_once_with(collection_name, mock_collection_service.get_collection.call_args[0][1])
107107

108108
@patch('stage0_mongodb_api.routes.collection_routes.CollectionService')
109109
def test_get_collection_not_found(self, mock_collection_service):
@@ -113,7 +113,7 @@ def test_get_collection_not_found(self, mock_collection_service):
113113
mock_collection_service.get_collection.side_effect = CollectionNotFoundError(collection_name)
114114

115115
# Act
116-
response = self.client.get(f'/api/collections/{collection_name}')
116+
response = self.client.get(f'/api/collections/{collection_name}/')
117117

118118
# Assert
119119
self.assertEqual(response.status_code, 404)
@@ -128,7 +128,7 @@ def test_get_collection_processing_error(self, mock_collection_service):
128128
mock_collection_service.get_collection.side_effect = CollectionProcessingError(collection_name, errors)
129129

130130
# Act
131-
response = self.client.get(f'/api/collections/{collection_name}')
131+
response = self.client.get(f'/api/collections/{collection_name}/')
132132

133133
# Assert
134134
self.assertEqual(response.status_code, 500)
@@ -147,12 +147,12 @@ def test_process_specific_collection_success(self, mock_collection_service):
147147
mock_collection_service.process_collection.return_value = mock_result
148148

149149
# Act
150-
response = self.client.post(f'/api/collections/{collection_name}')
150+
response = self.client.post(f'/api/collections/{collection_name}/')
151151

152152
# Assert
153153
self.assertEqual(response.status_code, 200)
154154
self.assertEqual(response.json, mock_result)
155-
mock_collection_service.process_collection.assert_called_once()
155+
mock_collection_service.process_collection.assert_called_once_with(collection_name, mock_collection_service.process_collection.call_args[0][1])
156156

157157
@patch('stage0_mongodb_api.routes.collection_routes.CollectionService')
158158
def test_process_specific_collection_not_found(self, mock_collection_service):
@@ -162,7 +162,7 @@ def test_process_specific_collection_not_found(self, mock_collection_service):
162162
mock_collection_service.process_collection.side_effect = CollectionNotFoundError(collection_name)
163163

164164
# Act
165-
response = self.client.post(f'/api/collections/{collection_name}')
165+
response = self.client.post(f'/api/collections/{collection_name}/')
166166

167167
# Assert
168168
self.assertEqual(response.status_code, 404)
@@ -177,7 +177,7 @@ def test_process_specific_collection_processing_error(self, mock_collection_serv
177177
mock_collection_service.process_collection.side_effect = CollectionProcessingError(collection_name, errors)
178178

179179
# Act
180-
response = self.client.post(f'/api/collections/{collection_name}')
180+
response = self.client.post(f'/api/collections/{collection_name}/')
181181

182182
# Assert
183183
self.assertEqual(response.status_code, 500)
@@ -191,7 +191,7 @@ def test_process_specific_collection_unexpected_error(self, mock_collection_serv
191191
mock_collection_service.process_collection.side_effect = Exception("Unexpected error")
192192

193193
# Act
194-
response = self.client.post(f'/api/collections/{collection_name}')
194+
response = self.client.post(f'/api/collections/{collection_name}/')
195195

196196
# Assert
197197
self.assertEqual(response.status_code, 500)

tests/services/test_collection_services.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ def test_list_collections_success(self, mock_config_manager):
1818
mock_config_manager.return_value.load_errors = None
1919
mock_config_manager.return_value.validate_configs.return_value = []
2020
with patch('stage0_mongodb_api.services.collection_service.VersionManager') as mock_version_manager:
21-
mock_version_manager.get_version_string.return_value = "simple.1.0.0.1"
21+
mock_version_manager.get_current_version.return_value = "simple.1.0.0.1"
2222
result = CollectionService.list_collections()
2323
self.assertEqual(len(result), 1)
24-
self.assertIsInstance(result, dict)
25-
self.assertIn("simple", result)
24+
self.assertIsInstance(result, list)
25+
self.assertEqual(result[0]["collection_name"], "simple")
26+
self.assertEqual(result[0]["version"], "simple.1.0.0.1")
2627

2728
@patch('stage0_mongodb_api.services.collection_service.ConfigManager')
2829
def test_list_collections_load_error(self, mock_config_manager):

tests/stepci/small_sample.yaml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,17 @@ tests:
1414
check:
1515
status: /200/
1616
schema:
17-
type: "object"
18-
properties:
19-
simple:
20-
type: "string"
17+
type: "array"
18+
items:
19+
type: "object"
20+
properties:
21+
collection_name:
22+
type: "string"
23+
version:
24+
type: "string"
25+
required:
26+
- collection_name
27+
- version
2128
- name: GET A Collection
2229
http:
2330
url: http://${{env.host}}/api/collections/simple

tests/test_server.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ class TestServer(unittest.TestCase):
2222
def setUp(self):
2323
"""Set up test fixtures."""
2424
self.app = app.test_client()
25+
# Patch MongoIO for every test to ensure no real DB connection
26+
patcher = patch('stage0_py_utils.MongoIO.get_instance', return_value=MagicMock())
27+
self.addCleanup(patcher.stop)
28+
self.mock_mongo = patcher.start()
2529

2630
def test_app_initialization(self):
2731
"""Test Flask app initialization."""
@@ -47,11 +51,11 @@ def test_config_routes_registered(self):
4751

4852
def test_collection_routes_registered(self):
4953
"""Test collection routes are registered."""
50-
# Act
51-
response = self.app.get('/api/collections')
52-
53-
# Assert
54-
self.assertNotEqual(response.status_code, 404)
54+
with patch('stage0_mongodb_api.routes.collection_routes.CollectionService.list_collections', return_value=[{"collection_name": "dummy", "version": "1.0.0"}]):
55+
# Act
56+
response = self.app.get('/api/collections/')
57+
# Assert
58+
self.assertEqual(response.status_code, 200)
5559

5660
def test_render_routes_registered(self):
5761
"""Test render routes are registered."""

0 commit comments

Comments
 (0)