| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- """
- Unit tests for OpenAPI schema generation.
- Refs: #20638
- """
- import json
- from django.test import TestCase
- class OpenAPISchemaTestCase(TestCase):
- """Tests for OpenAPI schema generation."""
- def setUp(self):
- """Fetch schema via API endpoint."""
- response = self.client.get('/api/schema/', {'format': 'json'})
- self.assertEqual(response.status_code, 200)
- self.schema = json.loads(response.content)
- def test_post_operation_documents_single_or_array(self):
- """
- POST operations on NetBoxModelViewSet endpoints should document
- support for both single objects and arrays via oneOf.
- Refs: #20638
- """
- # Test representative endpoints across different apps
- test_paths = [
- '/api/core/data-sources/',
- '/api/dcim/sites/',
- '/api/users/users/',
- '/api/ipam/ip-addresses/',
- ]
- for path in test_paths:
- with self.subTest(path=path):
- operation = self.schema['paths'][path]['post']
- # Get the request body schema
- request_schema = operation['requestBody']['content']['application/json']['schema']
- # Should have oneOf with two options
- self.assertIn('oneOf', request_schema, f"POST {path} should have oneOf schema")
- self.assertEqual(
- len(request_schema['oneOf']), 2,
- f"POST {path} oneOf should have exactly 2 options"
- )
- # First option: single object (has $ref or properties)
- single_schema = request_schema['oneOf'][0]
- self.assertTrue(
- '$ref' in single_schema or 'properties' in single_schema,
- f"POST {path} first oneOf option should be single object"
- )
- # Second option: array of objects
- array_schema = request_schema['oneOf'][1]
- self.assertEqual(
- array_schema['type'], 'array',
- f"POST {path} second oneOf option should be array"
- )
- self.assertIn('items', array_schema, f"POST {path} array should have items")
- def test_bulk_update_operations_require_array_only(self):
- """
- Bulk update/patch operations should require arrays only, not oneOf.
- They don't support single object input.
- Refs: #20638
- """
- test_paths = [
- '/api/dcim/sites/',
- '/api/users/users/',
- ]
- for path in test_paths:
- for method in ['put', 'patch']:
- with self.subTest(path=path, method=method):
- operation = self.schema['paths'][path][method]
- request_schema = operation['requestBody']['content']['application/json']['schema']
- # Should be array-only, not oneOf
- self.assertNotIn(
- 'oneOf', request_schema,
- f"{method.upper()} {path} should NOT have oneOf (array-only)"
- )
- self.assertEqual(
- request_schema['type'], 'array',
- f"{method.upper()} {path} should require array"
- )
- self.assertIn(
- 'items', request_schema,
- f"{method.upper()} {path} array should have items"
- )
- def test_bulk_delete_requires_array(self):
- """
- Bulk delete operations should require arrays.
- Refs: #20638
- """
- path = '/api/dcim/sites/'
- operation = self.schema['paths'][path]['delete']
- request_schema = operation['requestBody']['content']['application/json']['schema']
- # Should be array-only
- self.assertNotIn('oneOf', request_schema, "DELETE should NOT have oneOf")
- self.assertEqual(request_schema['type'], 'array', "DELETE should require array")
- self.assertIn('items', request_schema, "DELETE array should have items")
|