Backend Testing
Overview
The backend testing suite validates the API endpoints that serve data to the Digital Landscape application. These tests ensure that the backend correctly processes requests, applies filters, and returns properly structured data.
Test Implementation
The backend tests are implemented in the testing/backend/
directory using the pytest framework and the requests library to make HTTP calls to the API endpoints. The tests are organized into three main files:
test_main.py
- Tests for core API endpoints
test_admin.py
- Tests for admin API endpoints
test_review.py
- Tests for review API endpoints
Base Configuration
All tests use a common base URL configuration:
BASE_URL = "http://localhost:5001"
Running Tests
The testing framework provides several commands for running tests:
# Run all tests
make test
# Run only main API tests
make test-main
# Run only admin API tests
make test-admin
# Run only review API tests
make test-review
Health Check Tests
The health check endpoint test verifies that the server is operational and returns basic health metrics:
Test the health check endpoint functionality.
This test verifies that the health check endpoint is operational and returns
the expected health status information about the server. It checks for the
presence of essential health metrics and status indicators.
Endpoint
GET /api/health
Expects
- 200 status code
- JSON response containing:
- "healthy" status indicator
- Current timestamp
- Server uptime in seconds
- Memory usage statistics
- Process ID
Source code in testing/backend/test_main.py
| def test_health_check():
"""Test the health check endpoint functionality.
This test verifies that the health check endpoint is operational and returns
the expected health status information about the server. It checks for the
presence of essential health metrics and status indicators.
Endpoint:
GET /api/health
Expects:
- 200 status code
- JSON response containing:
- "healthy" status indicator
- Current timestamp
- Server uptime in seconds
- Memory usage statistics
- Process ID
"""
response = requests.get(f"{BASE_URL}/api/health", timeout=10)
assert response.status_code == 200
data = response.json()
assert data["status"] == "healthy"
assert "timestamp" in data
assert "uptime" in data
assert "memory" in data
assert "pid" in data
|
Project Data Tests
The CSV endpoint test verifies that project data is correctly retrieved and formatted:
Test the CSV data endpoint functionality.
This test verifies that the CSV endpoint correctly returns parsed CSV data
from the S3 bucket. It checks that the data is properly formatted and
contains the expected structure.
Endpoint
GET /api/csv
Expects
- 200 status code
- JSON array response
- Non-empty data entries
- Each entry should be a dictionary with multiple fields
- No empty or malformed entries
Source code in testing/backend/test_main.py
| def test_csv_endpoint():
"""Test the CSV data endpoint functionality.
This test verifies that the CSV endpoint correctly returns parsed CSV data
from the S3 bucket. It checks that the data is properly formatted and
contains the expected structure.
Endpoint:
GET /api/csv
Expects:
- 200 status code
- JSON array response
- Non-empty data entries
- Each entry should be a dictionary with multiple fields
- No empty or malformed entries
"""
response = requests.get(f"{BASE_URL}/api/csv", timeout=10)
assert response.status_code == 200
data = response.json()
assert isinstance(data, list)
if len(data) > 0:
first_item = data[0]
assert isinstance(first_item, dict)
assert len(first_item.keys()) > 1 # Verify it's not empty
|
Tech Radar Data Tests
The Tech Radar JSON endpoint test verifies that the radar configuration data is correctly retrieved:
Test the tech radar JSON endpoint functionality.
This test verifies that the tech radar endpoint correctly returns the
radar configuration data from the S3 bucket. The data defines the structure
and content of the technology radar visualization.
Endpoint
GET /api/tech-radar/json
Expects
- 200 status code
- JSON object response
- Non-empty configuration data
- Multiple configuration keys present
Source code in testing/backend/test_main.py
| def test_tech_radar_json_endpoint():
"""Test the tech radar JSON endpoint functionality.
This test verifies that the tech radar endpoint correctly returns the
radar configuration data from the S3 bucket. The data defines the structure
and content of the technology radar visualization.
Endpoint:
GET /api/tech-radar/json
Expects:
- 200 status code
- JSON object response
- Non-empty configuration data
- Multiple configuration keys present
"""
response = requests.get(f"{BASE_URL}/api/tech-radar/json", timeout=10)
assert response.status_code == 200
data = response.json()
assert isinstance(data, dict)
assert len(data.keys()) > 1 # Verify it's not empty
|
Repository Statistics Tests
Basic Statistics
Tests the default behavior with no filters:
Test the JSON endpoint without query parameters.
This test verifies the default behavior of the JSON endpoint when no
filters are applied. It checks that the endpoint returns complete
repository statistics and metadata.
Endpoint
GET /api/json
Expects
- 200 status code
- JSON response containing:
- Repository statistics
- Language usage statistics
- Metadata information
- Complete stats structure with:
- Total repository count
- Private repository count
- Public repository count
- Internal repository count
Source code in testing/backend/test_main.py
| def test_json_endpoint_no_params():
"""Test the JSON endpoint without query parameters.
This test verifies the default behavior of the JSON endpoint when no
filters are applied. It checks that the endpoint returns complete
repository statistics and metadata.
Endpoint:
GET /api/json
Expects:
- 200 status code
- JSON response containing:
- Repository statistics
- Language usage statistics
- Metadata information
- Complete stats structure with:
- Total repository count
- Private repository count
- Public repository count
- Internal repository count
"""
response = requests.get(f"{BASE_URL}/api/json", timeout=10)
assert response.status_code == 200
data = response.json()
assert "stats" in data
assert "language_statistics" in data
assert "metadata" in data
stats = data["stats"]
assert "total_repos" in stats
assert "total_private_repos" in stats
assert "total_public_repos" in stats
assert "total_internal_repos" in stats
|
Date Filtering
Tests filtering repositories by a specific date:
Test the JSON endpoint with datetime filtering.
This test verifies that the endpoint correctly filters repository data
based on a specified datetime parameter. It checks repositories modified
within the last 7 days.
Parameters:
Name |
Type |
Description |
Default |
datetime |
str
|
ISO formatted datetime string for filtering
|
required
|
Example
GET /api/json?datetime=2024-03-20T00:00:00Z
Expects
- 200 status code
- Filtered repository data
- Metadata containing the applied datetime filter
Source code in testing/backend/test_main.py
| def test_json_endpoint_with_datetime():
"""Test the JSON endpoint with datetime filtering.
This test verifies that the endpoint correctly filters repository data
based on a specified datetime parameter. It checks repositories modified
within the last 7 days.
Parameters:
datetime (str): ISO formatted datetime string for filtering
Example:
GET /api/json?datetime=2024-03-20T00:00:00Z
Expects:
- 200 status code
- Filtered repository data
- Metadata containing the applied datetime filter
"""
seven_days_ago = (datetime.now() - timedelta(days=7)).isoformat()
response = requests.get(f"{BASE_URL}/api/json",
params={"datetime": seven_days_ago}, timeout=10)
assert response.status_code == 200
data = response.json()
assert data["metadata"]["filter_date"] == seven_days_ago
|
Archived Status Filtering
Tests filtering repositories by archived status:
Test the JSON endpoint with archived status filtering.
This test verifies that the endpoint correctly filters repositories
based on their archived status. It tests both archived and non-archived
filtering options.
Parameters:
Name |
Type |
Description |
Default |
archived |
str
|
"true" or "false" to filter archived status
|
required
|
Example
GET /api/json?archived=false
Expects
- 200 status code for both archived and non-archived queries
- Filtered repository data based on archived status
Source code in testing/backend/test_main.py
| def test_json_endpoint_with_archived():
"""Test the JSON endpoint with archived status filtering.
This test verifies that the endpoint correctly filters repositories
based on their archived status. It tests both archived and non-archived
filtering options.
Parameters:
archived (str): "true" or "false" to filter archived status
Example:
GET /api/json?archived=false
Expects:
- 200 status code for both archived and non-archived queries
- Filtered repository data based on archived status
"""
response = requests.get(f"{BASE_URL}/api/json",
params={"archived": "true"}, timeout=10)
assert response.status_code == 200
response = requests.get(f"{BASE_URL}/api/json",
params={"archived": "false"}, timeout=10)
assert response.status_code == 200
|
Combined Filtering
Tests applying multiple filters simultaneously:
Test the JSON endpoint with multiple filter parameters.
This test verifies that the endpoint correctly handles multiple filter
parameters simultaneously, including datetime and archived status filters.
It ensures all filters are properly applied and reflected in the response.
Parameters:
Name |
Type |
Description |
Default |
datetime |
str
|
ISO formatted datetime string for filtering
|
required
|
archived |
str
|
"true" or "false" to filter archived status
|
required
|
Example
GET /api/json?datetime=2024-03-20T00:00:00Z&archived=false
Expects
- 200 status code
- Repository data filtered by all parameters
- Metadata reflecting the applied datetime filter
Source code in testing/backend/test_main.py
| def test_json_endpoint_combined_params():
"""Test the JSON endpoint with multiple filter parameters.
This test verifies that the endpoint correctly handles multiple filter
parameters simultaneously, including datetime and archived status filters.
It ensures all filters are properly applied and reflected in the response.
Parameters:
datetime (str): ISO formatted datetime string for filtering
archived (str): "true" or "false" to filter archived status
Example:
GET /api/json?datetime=2024-03-20T00:00:00Z&archived=false
Expects:
- 200 status code
- Repository data filtered by all parameters
- Metadata reflecting the applied datetime filter
"""
seven_days_ago = (datetime.now() - timedelta(days=7)).isoformat()
params = {
"datetime": seven_days_ago,
"archived": "false"
}
response = requests.get(f"{BASE_URL}/api/json", params=params, timeout=10)
assert response.status_code == 200
data = response.json()
assert data["metadata"]["filter_date"] == seven_days_ago
|
Repository Project Tests
Error Handling
Tests the endpoint's response when required parameters are missing:
Test the repository project JSON endpoint error handling for missing parameters.
This test verifies that the endpoint correctly handles the case when no
repositories are specified in the request parameters. It should return
a 400 Bad Request status code with an appropriate error message.
Expects
- 400 status code
- JSON response with error message
- Error message indicating no repositories specified
Source code in testing/backend/test_main.py
| def test_repository_project_json_no_params():
"""Test the repository project JSON endpoint error handling for missing parameters.
This test verifies that the endpoint correctly handles the case when no
repositories are specified in the request parameters. It should return
a 400 Bad Request status code with an appropriate error message.
Expects:
- 400 status code
- JSON response with error message
- Error message indicating no repositories specified
"""
response = requests.get(
f"{BASE_URL}/api/repository/project/json", timeout=10)
assert response.status_code == 400
data = response.json()
assert "error" in data
assert data["error"] == "No repositories specified"
|
Single Repository
Tests retrieving data for a single repository:
Test the repository project JSON endpoint with a valid repository parameter.
This test verifies the endpoint's basic functionality when requesting data
for a single repository. It checks the complete response structure including
repository data, statistics, and metadata.
Parameters:
Name |
Type |
Description |
Default |
repositories |
str
|
Name of the repository to query (e.g., "tech-radar")
|
required
|
Expects
- 200 status code
- JSON response with complete repository data
- Valid statistics for the repository
- Correct metadata including requested repository names
- Language statistics if available
Source code in testing/backend/test_main.py
| def test_repository_project_json_with_repos():
"""Test the repository project JSON endpoint with a valid repository parameter.
This test verifies the endpoint's basic functionality when requesting data
for a single repository. It checks the complete response structure including
repository data, statistics, and metadata.
Parameters:
repositories (str): Name of the repository to query (e.g., "tech-radar")
Expects:
- 200 status code
- JSON response with complete repository data
- Valid statistics for the repository
- Correct metadata including requested repository names
- Language statistics if available
"""
response = requests.get(f"{BASE_URL}/api/repository/project/json",
params={"repositories": "tech-radar"}, timeout=10)
assert response.status_code == 200
data = response.json()
# Verify response structure
assert "repositories" in data
assert "stats" in data
assert "language_statistics" in data
assert "metadata" in data
# Verify stats structure
stats = data["stats"]
assert "total_repos" in stats
assert "total_private_repos" in stats
assert "total_public_repos" in stats
assert "total_internal_repos" in stats
# Verify metadata
metadata = data["metadata"]
assert "requested_repos" in metadata
assert "found_repos" in metadata
assert metadata["requested_repos"] == ["tech-radar"]
|
Multiple Repositories
Tests retrieving data for multiple repositories:
Test the repository project JSON endpoint with multiple repositories.
This test verifies that the endpoint correctly handles requests for
multiple repositories in a single call. It checks that all requested
repositories are processed and included in the response.
Parameters:
Name |
Type |
Description |
Default |
repositories |
str
|
Comma-separated list of repository names
|
required
|
Example
GET /api/repository/project/json?repositories=tech-radar,another-repo
Expects
- 200 status code
- Data for all requested repositories
- Metadata containing all requested repository names
- Aggregated statistics across all repositories
Source code in testing/backend/test_main.py
| def test_repository_project_json_multiple_repos():
"""Test the repository project JSON endpoint with multiple repositories.
This test verifies that the endpoint correctly handles requests for
multiple repositories in a single call. It checks that all requested
repositories are processed and included in the response.
Parameters:
repositories (str): Comma-separated list of repository names
Example:
GET /api/repository/project/json?repositories=tech-radar,another-repo
Expects:
- 200 status code
- Data for all requested repositories
- Metadata containing all requested repository names
- Aggregated statistics across all repositories
"""
params = {
"repositories": "tech-radar,another-repo"
}
response = requests.get(
f"{BASE_URL}/api/repository/project/json", params=params, timeout=10)
assert response.status_code == 200
data = response.json()
# Verify the requested repos are in metadata
assert len(data["metadata"]["requested_repos"]) == 2
assert "tech-radar" in data["metadata"]["requested_repos"]
assert "another-repo" in data["metadata"]["requested_repos"]
|
Tech Radar Update Tests
These tests are located in test_review.py
and verify the review API endpoints.
Missing Entries
Tests handling of missing entries data:
Test the tech radar update endpoint with missing entries.
This test verifies that the endpoint correctly handles requests with
missing entries data by returning an appropriate error response.
Endpoint
POST /review/api/tech-radar/update
Expects
- 400 status code
- JSON response with error message
- Error message indicating invalid or missing title
Source code in testing/backend/test_review.py
| def test_tech_radar_update_no_entries():
"""Test the tech radar update endpoint with missing entries.
This test verifies that the endpoint correctly handles requests with
missing entries data by returning an appropriate error response.
Endpoint:
POST /review/api/tech-radar/update
Expects:
- 400 status code
- JSON response with error message
- Error message indicating invalid or missing title
"""
response = requests.post(
f"{BASE_URL}/review/api/tech-radar/update", json={}, timeout=10)
assert response.status_code == 400
data = response.json()
assert "error" in data
assert data["error"] == "Invalid or empty entries data"
|
Partial Updates
Tests processing of partial updates:
Test the tech radar update endpoint with a partial update.
This test verifies that the endpoint correctly processes updates
when provided with the complete tech radar structure.
Endpoint
POST /review/api/tech-radar/update
Test Data
- Complete tech radar structure
- Valid entries with all required fields
Expects
- 200 status code
- Successful update of entries
- Correct structure in stored data
Source code in testing/backend/test_review.py
| def test_tech_radar_update_partial():
"""Test the tech radar update endpoint with a partial update.
This test verifies that the endpoint correctly processes updates
when provided with the complete tech radar structure.
Endpoint:
POST /review/api/tech-radar/update
Test Data:
- Complete tech radar structure
- Valid entries with all required fields
Expects:
- 200 status code
- Successful update of entries
- Correct structure in stored data
"""
random_number = random.randint(100, 1000)
test_data = {
"entries": [
{
"id": "test-entry-partial-1",
"title": "Test Entry Partial 1",
"description": "Languages",
"key": "test1",
"url": "#",
"quadrant": "1",
"timeline": [
{
"moved": 0,
"ringId": "ignore",
"date": "2000-01-01",
"description": f"For testing purposes [CASE:{random_number}:1]"
}
],
"links": []
}
]
}
response = requests.post(
f"{BASE_URL}/review/api/tech-radar/update",
json=test_data,
timeout=10
)
assert response.status_code == 200
# Verify the updates
get_response = requests.get(f"{BASE_URL}/api/tech-radar/json", timeout=10)
assert get_response.status_code == 200
updated_data = get_response.json()
# Verify our entry exists and is correct
updated_entries = {entry["id"]: entry for entry in updated_data["entries"]}
assert "test-entry-partial-1" in updated_entries
assert updated_entries["test-entry-partial-1"]["timeline"][0]["ringId"] == "ignore"
assert updated_entries["test-entry-partial-1"]["quadrant"] == "1"
|
Invalid Entries
Tests validation of invalid entries:
Test the tech radar update endpoint with invalid entries format.
This test verifies that the endpoint correctly handles requests with
invalid entries data format by returning an appropriate error response.
Endpoint
POST /review/api/tech-radar/update
Test Data
- Invalid entries format
- Missing required fields
- Malformed data structures
Expects
- 400 status code
- Error message for invalid data
- No changes to existing entries
Source code in testing/backend/test_review.py
| def test_tech_radar_update_invalid_entries():
"""Test the tech radar update endpoint with invalid entries format.
This test verifies that the endpoint correctly handles requests with
invalid entries data format by returning an appropriate error response.
Endpoint:
POST /review/api/tech-radar/update
Test Data:
- Invalid entries format
- Missing required fields
- Malformed data structures
Expects:
- 400 status code
- Error message for invalid data
- No changes to existing entries
"""
# Test with missing title
response = requests.post(
f"{BASE_URL}/review/api/tech-radar/update",
json={"entries": "not_an_array"},
timeout=10
)
assert response.status_code == 400
assert response.json()["error"] == "Invalid or empty entries data"
|
Valid Structure
Tests updating the Tech Radar with valid data:
Test the tech radar update endpoint with valid complete structure.
This test verifies that the endpoint correctly processes a complete
tech radar update with valid structure for all components.
Endpoint
POST /review/api/tech-radar/update
Test Data
- Valid title
- Valid quadrants with required fields
- Valid rings with required fields
- Valid entries with required fields
Expects
- 200 status code
- Successful update confirmation
- Correct structure in stored data
Source code in testing/backend/test_review.py
| def test_tech_radar_update_valid_structure():
"""Test the tech radar update endpoint with valid complete structure.
This test verifies that the endpoint correctly processes a complete
tech radar update with valid structure for all components.
Endpoint:
POST /review/api/tech-radar/update
Test Data:
- Valid title
- Valid quadrants with required fields
- Valid rings with required fields
- Valid entries with required fields
Expects:
- 200 status code
- Successful update confirmation
- Correct structure in stored data
"""
random_number = random.randint(100, 1000)
test_data = {
"entries": [
{
"id": "test-entry-1",
"title": "Test Entry 1",
"description": "Languages",
"key": "test1",
"url": "#",
"quadrant": "1",
"timeline": [
{
"moved": 0,
"ringId": "ignore",
"date": "2000-01-01",
"description": f"For testing purposes [CASE:{random_number}:2]"
}
],
"links": []
}
]
}
response = requests.post(
f"{BASE_URL}/review/api/tech-radar/update",
json=test_data,
timeout=10
)
assert response.status_code == 200
assert response.json()["message"] == "Tech radar updated successfully"
# Verify the update
get_response = requests.get(f"{BASE_URL}/api/tech-radar/json", timeout=10)
assert get_response.status_code == 200
updated_data = get_response.json()
# Verify entry structure
entries = updated_data["entries"]
test_entry = next(
(entry for entry in entries if entry["id"] == "test-entry-1"), None)
assert test_entry is not None, "No entry with id 'test-entry-1' found"
assert str(
random_number) in test_entry["timeline"][0]["description"], "Entry with id 'test-entry-1' does not have the expected description"
|
Invalid Structure
Tests the endpoint's handling of invalid data structures:
Test the tech radar update endpoint with invalid structure.
This test verifies that the endpoint correctly validates the complete
structure of the tech radar data, including title, quadrants, rings,
and entries.
Endpoint
POST /review/api/tech-radar/update
Test Data
- Missing title
- Invalid quadrants structure
- Invalid rings structure
- Invalid entries structure
Expects
- 400 status code for each invalid case
- Appropriate error messages
- No changes to existing data
Source code in testing/backend/test_review.py
| def test_tech_radar_update_invalid_structure():
"""Test the tech radar update endpoint with invalid structure.
This test verifies that the endpoint correctly validates the complete
structure of the tech radar data, including title, quadrants, rings,
and entries.
Endpoint:
POST /review/api/tech-radar/update
Test Data:
- Missing title
- Invalid quadrants structure
- Invalid rings structure
- Invalid entries structure
Expects:
- 400 status code for each invalid case
- Appropriate error messages
- No changes to existing data
"""
# Test missing title
response = requests.post(
f"{BASE_URL}/review/api/tech-radar/update",
json={
"quadrants": [],
"rings": [],
"entries": []
},
timeout=10
)
assert response.status_code == 400
assert response.json()["error"] == "Invalid or empty entries data"
# Test invalid quadrants
response = requests.post(
f"{BASE_URL}/review/api/tech-radar/update",
json={
"title": "Test Radar",
"quadrants": [{"invalid": "structure"}],
"rings": [],
"entries": []
},
timeout=10
)
assert response.status_code == 400
assert response.json()["error"] == "Invalid or empty entries data"
# Test invalid rings
response = requests.post(
f"{BASE_URL}/review/api/tech-radar/update",
json={
"title": "Test Radar",
"quadrants": [{"id": "1", "name": "Test"}],
"rings": [{"invalid": "structure"}],
"entries": []
},
timeout=10
)
assert response.status_code == 400
assert response.json()["error"] == "Invalid or empty entries data"
|
Invalid References
Tests validation of references between entries and quadrants/rings:
Test the tech radar update endpoint with invalid references.
This test verifies that the endpoint correctly validates references
between entries and their quadrants/rings.
Endpoint
POST /review/api/tech-radar/update
Test Data
- Entry with invalid quadrant reference
- Entry with invalid ring reference
- Entry with missing required fields
Expects
- 400 status code
- Appropriate error messages
- No changes to existing data
Source code in testing/backend/test_review.py
| def test_tech_radar_update_invalid_references():
"""Test the tech radar update endpoint with invalid references.
This test verifies that the endpoint correctly validates references
between entries and their quadrants/rings.
Endpoint:
POST /review/api/tech-radar/update
Test Data:
- Entry with invalid quadrant reference
- Entry with invalid ring reference
- Entry with missing required fields
Expects:
- 400 status code
- Appropriate error messages
- No changes to existing data
"""
test_data = {
"title": "ONS Tech Radar",
"quadrants": [
{"id": "1", "name": "Languages"}
],
"rings": [
{"id": "adopt", "name": "ADOPT", "color": "#008a00"}
],
"entries": [
{
"id": "test-entry",
"title": "Test Entry",
"quadrant": "invalid", # Invalid quadrant reference
"timeline": [
{
"moved": 0,
"ringId": "invalid", # Invalid ring reference
"date": "2024-03",
"description": "Test"
}
]
}
]
}
response = requests.post(
f"{BASE_URL}/review/api/tech-radar/update",
json=test_data,
timeout=10
)
assert response.status_code == 400
assert "Invalid entry structure" in response.json()["error"]
|
Admin API Tests
These tests are located in test_admin.py
and verify the admin API endpoints.
Banner Retrieval
Tests retrieving banner messages:
Test the admin banners endpoint for retrieving banner messages.
This test verifies that the endpoint correctly returns banner messages
from the S3 bucket. It checks the structure of the response and ensures
the messages array is present.
Endpoint
GET /admin/api/banners
Expects
- 200 status code
- JSON response containing a messages array
- Valid structure that can be parsed by the admin UI
Source code in testing/backend/test_admin.py
| def test_admin_banner_get():
"""Test the admin banners endpoint for retrieving banner messages.
This test verifies that the endpoint correctly returns banner messages
from the S3 bucket. It checks the structure of the response and ensures
the messages array is present.
Endpoint:
GET /admin/api/banners
Expects:
- 200 status code
- JSON response containing a messages array
- Valid structure that can be parsed by the admin UI
"""
response = requests.get(f"{BASE_URL}/admin/api/banners", timeout=10)
assert response.status_code == 200
data = response.json()
# Verify the response structure
assert "messages" in data
assert isinstance(data["messages"], list)
|
Banner Creation
Tests creating new banner messages:
Test the admin banners update endpoint.
This test verifies that the endpoint correctly processes banner
updates with valid data and saves them to the S3 bucket.
Endpoint
POST /admin/api/banners/update
Test Data
- Valid banner message
- Array of pages where the banner should appear
- Optional banner title and type
Expects
- 200 status code
- Success message confirming the banner was added
- Banner should be retrievable in subsequent GET requests
Source code in testing/backend/test_admin.py
| def test_admin_banner_update():
"""Test the admin banners update endpoint.
This test verifies that the endpoint correctly processes banner
updates with valid data and saves them to the S3 bucket.
Endpoint:
POST /admin/api/banners/update
Test Data:
- Valid banner message
- Array of pages where the banner should appear
- Optional banner title and type
Expects:
- 200 status code
- Success message confirming the banner was added
- Banner should be retrievable in subsequent GET requests
"""
test_data = {
"banner": {
"message": "Test Banner Message",
"title": "Test Banner",
"type": "info",
"pages": ["radar", "statistics"],
"show": True
}
}
response = requests.post(
f"{BASE_URL}/admin/api/banners/update",
json=test_data,
timeout=10
)
assert response.status_code == 200
data = response.json()
assert "message" in data
assert data["message"] == "Banner added successfully"
# Verify the banner was added
get_response = requests.get(f"{BASE_URL}/admin/api/banners", timeout=10)
assert get_response.status_code == 200
get_data = get_response.json()
assert "messages" in get_data
# Find the added banner by message
added_banner = next((banner for banner in get_data["messages"]
if banner["message"] == "Test Banner Message"), None)
assert added_banner is not None
assert added_banner["title"] == "Test Banner"
assert added_banner["type"] == "info"
assert "radar" in added_banner["pages"]
assert "statistics" in added_banner["pages"]
assert added_banner["show"] is True
|
Banner Creation Validation
Tests validation of banner creation requests:
Test the admin banners update endpoint with invalid data.
This test verifies that the endpoint correctly validates banner data
and returns appropriate error responses for invalid inputs.
Endpoint
POST /admin/api/banners/update
Test Data
- Missing message field
- Empty pages array
- Malformed banner object
Expects
- 400 status code
- Error message indicating invalid banner data
Source code in testing/backend/test_admin.py
| def test_admin_banner_update_invalid():
"""Test the admin banners update endpoint with invalid data.
This test verifies that the endpoint correctly validates banner data
and returns appropriate error responses for invalid inputs.
Endpoint:
POST /admin/api/banners/update
Test Data:
- Missing message field
- Empty pages array
- Malformed banner object
Expects:
- 400 status code
- Error message indicating invalid banner data
"""
# Test with missing message
response = requests.post(
f"{BASE_URL}/admin/api/banners/update",
json={"banner": {"pages": ["radar"]}},
timeout=10
)
assert response.status_code == 400
assert response.json()["error"] == "Invalid banner data"
# Test with empty pages array
response = requests.post(
f"{BASE_URL}/admin/api/banners/update",
json={"banner": {"message": "Test", "pages": []}},
timeout=10
)
assert response.status_code == 400
assert response.json()["error"] == "Invalid banner data"
# Test with malformed request body
response = requests.post(
f"{BASE_URL}/admin/api/banners/update",
json={"not_banner": {}},
timeout=10
)
assert response.status_code == 400
assert response.json()["error"] == "Invalid banner data"
|
Banner Visibility Toggle
Tests toggling banner visibility:
Test the admin banners toggle endpoint.
This test verifies that the endpoint correctly toggles banner visibility
by updating the 'show' property in the S3 bucket.
Endpoint
POST /admin/api/banners/toggle
Test Data
- Valid index of an existing banner
- New visibility state
Expects
- 200 status code
- Success message confirming the visibility update
- Banner visibility should be updated in subsequent GET requests
Source code in testing/backend/test_admin.py
| def test_admin_banner_toggle():
"""Test the admin banners toggle endpoint.
This test verifies that the endpoint correctly toggles banner visibility
by updating the 'show' property in the S3 bucket.
Endpoint:
POST /admin/api/banners/toggle
Test Data:
- Valid index of an existing banner
- New visibility state
Expects:
- 200 status code
- Success message confirming the visibility update
- Banner visibility should be updated in subsequent GET requests
"""
# First, add a test banner
test_data = {
"banner": {
"message": "Toggle Test Banner",
"pages": ["radar"],
"show": True
}
}
# Add the banner
requests.post(
f"{BASE_URL}/admin/api/banners/update",
json=test_data,
timeout=10
)
# Get all banners
get_response = requests.get(f"{BASE_URL}/admin/api/banners", timeout=10)
assert get_response.status_code == 200
banners = get_response.json()["messages"]
# Find the index of our test banner
test_banner_index = next((i for i, banner in enumerate(banners)
if banner["message"] == "Toggle Test Banner"), None)
assert test_banner_index is not None
# Toggle the banner visibility
toggle_data = {
"index": test_banner_index,
"show": False
}
response = requests.post(
f"{BASE_URL}/admin/api/banners/toggle",
json=toggle_data,
timeout=10
)
assert response.status_code == 200
data = response.json()
assert data["message"] == "Banner visibility updated successfully"
# Verify the banner was toggled
get_response = requests.get(f"{BASE_URL}/admin/api/banners", timeout=10)
updated_banners = get_response.json()["messages"]
assert updated_banners[test_banner_index]["show"] is False
|
Banner Visibility Toggle Validation
Tests validation of banner toggle requests:
Test the admin banners toggle endpoint with invalid data.
This test verifies that the endpoint correctly validates toggle data
and returns appropriate error responses for invalid inputs.
Endpoint
POST /admin/api/banners/toggle
Test Data
- Invalid index (non-numeric)
- Out of range index
- Missing index
Expects
- 400 status code
- Error message indicating invalid index
Source code in testing/backend/test_admin.py
| def test_admin_banner_toggle_invalid():
"""Test the admin banners toggle endpoint with invalid data.
This test verifies that the endpoint correctly validates toggle data
and returns appropriate error responses for invalid inputs.
Endpoint:
POST /admin/api/banners/toggle
Test Data:
- Invalid index (non-numeric)
- Out of range index
- Missing index
Expects:
- 400 status code
- Error message indicating invalid index
"""
# Test with string index
response = requests.post(
f"{BASE_URL}/admin/api/banners/toggle",
json={"index": "not-a-number", "show": True},
timeout=10
)
assert response.status_code == 400
assert "Invalid banner index" in response.json()["error"]
# Test with missing index
response = requests.post(
f"{BASE_URL}/admin/api/banners/toggle",
json={"show": True},
timeout=10
)
assert response.status_code == 400
assert "Invalid banner index" in response.json()["error"]
|
Banner Deletion
Tests deleting banner messages:
Test the admin banners delete endpoint.
This test verifies that the endpoint correctly deletes banners
from the S3 bucket based on their index.
Endpoint
POST /admin/api/banners/delete
Test Data
- Valid index of an existing banner
Expects
- 200 status code
- Success message confirming deletion
- Banner should be removed in subsequent GET requests
Source code in testing/backend/test_admin.py
| def test_admin_banner_delete():
"""Test the admin banners delete endpoint.
This test verifies that the endpoint correctly deletes banners
from the S3 bucket based on their index.
Endpoint:
POST /admin/api/banners/delete
Test Data:
- Valid index of an existing banner
Expects:
- 200 status code
- Success message confirming deletion
- Banner should be removed in subsequent GET requests
"""
# First, add a test banner to delete
test_data = {
"banner": {
"message": "Delete Test Banner",
"pages": ["radar"]
}
}
# Add the banner
requests.post(
f"{BASE_URL}/admin/api/banners/update",
json=test_data,
timeout=10
)
# Get all banners
get_response = requests.get(f"{BASE_URL}/admin/api/banners", timeout=10)
assert get_response.status_code == 200
banners = get_response.json()["messages"]
# Find the index of our test banner
test_banner_index = next((i for i, banner in enumerate(banners)
if banner["message"] == "Delete Test Banner"), None)
assert test_banner_index is not None
# Delete the banner
delete_data = {
"index": test_banner_index
}
response = requests.post(
f"{BASE_URL}/admin/api/banners/delete",
json=delete_data,
timeout=10
)
assert response.status_code == 200
data = response.json()
assert data["message"] == "Banner deleted successfully"
# Verify the banner was deleted
get_response = requests.get(f"{BASE_URL}/admin/api/banners", timeout=10)
updated_banners = get_response.json()["messages"]
# The banner should no longer exist
deleted_banner = next((banner for banner in updated_banners
if banner["message"] == "Delete Test Banner"), None)
assert deleted_banner is None
|
Banner Deletion Validation
Tests validation of banner deletion requests:
Test the admin banners delete endpoint with invalid data.
This test verifies that the endpoint correctly validates delete data
and returns appropriate error responses for invalid inputs.
Endpoint
POST /admin/api/banners/delete
Test Data
- Invalid index (non-numeric)
- Out of range index
- Missing index
Expects
- 400 status code
- Error message indicating invalid index
Source code in testing/backend/test_admin.py
| def test_admin_banner_delete_invalid():
"""Test the admin banners delete endpoint with invalid data.
This test verifies that the endpoint correctly validates delete data
and returns appropriate error responses for invalid inputs.
Endpoint:
POST /admin/api/banners/delete
Test Data:
- Invalid index (non-numeric)
- Out of range index
- Missing index
Expects:
- 400 status code
- Error message indicating invalid index
"""
# Test with string index
response = requests.post(
f"{BASE_URL}/admin/api/banners/delete",
json={"index": "not-a-number"},
timeout=10
)
assert response.status_code == 400
assert "Invalid banner index" in response.json()["error"]
# Test with missing index
response = requests.post(
f"{BASE_URL}/admin/api/banners/delete",
json={},
timeout=10
)
assert response.status_code == 400
assert "Invalid banner index" in response.json()["error"]
|
Banner Endpoints
Tests the banner message endpoints for retrieving active and all banners:
Test the banner message endpoints.
This test verifies that both banner endpoints (/api/banners and /api/banners/all)
return the expected response structure and properly filter active banners.
Tests
- /api/banners endpoint returns active banners only
- /api/banners/all endpoint returns all banners
- Both endpoints handle missing messages.json gracefully
- Response structure is consistent and valid
Source code in testing/backend/test_main.py
| def test_banner_endpoints():
"""Test the banner message endpoints.
This test verifies that both banner endpoints (/api/banners and /api/banners/all)
return the expected response structure and properly filter active banners.
Tests:
- /api/banners endpoint returns active banners only
- /api/banners/all endpoint returns all banners
- Both endpoints handle missing messages.json gracefully
- Response structure is consistent and valid
"""
# Test /api/banners endpoint
response = requests.get(f"{BASE_URL}/api/banners", timeout=10)
assert response.status_code == 200
data = response.json()
assert "messages" in data
assert isinstance(data["messages"], list)
# Verify active banners only
for banner in data["messages"]:
assert banner.get("show", True) is True
# Test /api/banners/all endpoint
response = requests.get(f"{BASE_URL}/api/banners/all", timeout=10)
assert response.status_code == 200
data = response.json()
assert "messages" in data
assert isinstance(data["messages"], list)
# Test error case with non-existent endpoint
response = requests.get(f"{BASE_URL}/api/banners/nonexistent", timeout=10)
assert response.status_code in [404, 500]
|
The banner endpoint tests verify:
- Active banners are correctly filtered in the /api/banners endpoint
- All banners (active and inactive) are returned by /api/banners/all
- Missing messages.json is handled gracefully
- Response structure is consistent and valid
- Error cases are properly handled with appropriate status codes
Error Handling Tests
Invalid Endpoints
Tests the server's response to non-existent endpoints:
Test error handling for invalid endpoints.
This test verifies that the server properly handles requests to
non-existent endpoints by returning appropriate error status codes.
Example
GET /api/nonexistent
Expects
- Either 404 (Not Found) or 500 (Internal Server Error) status code
- Proper error handling for invalid routes
Source code in testing/backend/test_main.py
| def test_invalid_endpoint():
"""Test error handling for invalid endpoints.
This test verifies that the server properly handles requests to
non-existent endpoints by returning appropriate error status codes.
Example:
GET /api/nonexistent
Expects:
- Either 404 (Not Found) or 500 (Internal Server Error) status code
- Proper error handling for invalid routes
"""
response = requests.get(f"{BASE_URL}/api/nonexistent", timeout=10)
assert response.status_code in [404, 500] # Either is acceptable
|
Invalid Parameters
Tests the server's handling of invalid parameter values:
Test the JSON endpoint's handling of invalid date parameters.
This test verifies that the endpoint gracefully handles invalid datetime
parameters without failing. It should ignore the invalid date and return
unfiltered results.
Parameters:
Name |
Type |
Description |
Default |
datetime |
str
|
An invalid datetime string
|
required
|
Example
GET /api/json?datetime=invalid-date
Expects
- 200 status code (graceful handling)
- Null filter_date in metadata
- Valid response with unfiltered stats
- Complete language statistics
Source code in testing/backend/test_main.py
| def test_json_endpoint_invalid_date():
"""Test the JSON endpoint's handling of invalid date parameters.
This test verifies that the endpoint gracefully handles invalid datetime
parameters without failing. It should ignore the invalid date and return
unfiltered results.
Parameters:
datetime (str): An invalid datetime string
Example:
GET /api/json?datetime=invalid-date
Expects:
- 200 status code (graceful handling)
- Null filter_date in metadata
- Valid response with unfiltered stats
- Complete language statistics
"""
response = requests.get(f"{BASE_URL}/api/json",
params={"datetime": "invalid-date"}, timeout=10)
assert response.status_code == 200 # Backend handles invalid dates gracefully
data = response.json()
assert data["metadata"]["filter_date"] is None
assert "stats" in data
assert "language_statistics" in data
|
Test Execution Flow
The backend tests follow this general execution flow:
- Setup: Configure the test environment and parameters
- Request: Make an HTTP request to the target endpoint
- Validation: Assert that the response status code is as expected
- Data Verification: Assert that the response data structure is correct
- Content Verification: Assert that the response data contains the expected values
Integration with Frontend Utilities
These backend tests validate the same endpoints that are used by the frontend utilities:
- Project Data Utility: The
test_csv_endpoint()
test validates the endpoint used by fetchCSVFromS3()
- Repository Data Utility: The repository project tests validate the endpoint used by
fetchRepositoryData()
- Tech Radar Data Utility: The
test_tech_radar_json_endpoint()
test validates the endpoint used by fetchTechRadarJSONFromS3()
- Admin Utilities: The admin API tests validate the endpoints used by the admin interface for banner management