Provide managers with a dedicated page to analyze hold lots across all stations. Extends existing service functions (get_hold_detail_summary, get_hold_detail_lots, get_wip_matrix) with optional parameters for backward compatibility, adds one new function (get_hold_overview_treemap), and registers the page in the portal navigation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
69 lines
2.4 KiB
Python
69 lines
2.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Route-level rate limit behavior tests."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import patch
|
|
|
|
import mes_dashboard.core.database as db
|
|
from mes_dashboard.app import create_app
|
|
|
|
|
|
def _client():
|
|
db._ENGINE = None
|
|
app = create_app('testing')
|
|
app.config['TESTING'] = True
|
|
return app.test_client()
|
|
|
|
|
|
@patch('mes_dashboard.services.resource_service.get_merged_resource_status')
|
|
@patch('mes_dashboard.core.rate_limit.check_and_record', return_value=(True, 5))
|
|
def test_resource_status_rate_limit_returns_429(_mock_limit, mock_service):
|
|
client = _client()
|
|
response = client.get('/api/resource/status')
|
|
|
|
assert response.status_code == 429
|
|
payload = response.get_json()
|
|
assert payload['error']['code'] == 'TOO_MANY_REQUESTS'
|
|
assert response.headers.get('Retry-After') == '5'
|
|
mock_service.assert_not_called()
|
|
|
|
|
|
@patch('mes_dashboard.services.wip_service.get_hold_detail_lots')
|
|
@patch('mes_dashboard.core.rate_limit.check_and_record', return_value=(True, 4))
|
|
def test_hold_detail_lots_rate_limit_returns_429(_mock_limit, mock_service):
|
|
client = _client()
|
|
response = client.get('/api/wip/hold-detail/lots?reason=YieldLimit')
|
|
|
|
assert response.status_code == 429
|
|
payload = response.get_json()
|
|
assert payload['error']['code'] == 'TOO_MANY_REQUESTS'
|
|
assert response.headers.get('Retry-After') == '4'
|
|
mock_service.assert_not_called()
|
|
|
|
|
|
@patch('mes_dashboard.routes.hold_overview_routes.get_wip_matrix')
|
|
@patch('mes_dashboard.core.rate_limit.check_and_record', return_value=(True, 6))
|
|
def test_hold_overview_matrix_rate_limit_returns_429(_mock_limit, mock_service):
|
|
client = _client()
|
|
response = client.get('/api/hold-overview/matrix')
|
|
|
|
assert response.status_code == 429
|
|
payload = response.get_json()
|
|
assert payload['error']['code'] == 'TOO_MANY_REQUESTS'
|
|
assert response.headers.get('Retry-After') == '6'
|
|
mock_service.assert_not_called()
|
|
|
|
|
|
@patch('mes_dashboard.routes.hold_overview_routes.get_hold_detail_lots')
|
|
@patch('mes_dashboard.core.rate_limit.check_and_record', return_value=(True, 3))
|
|
def test_hold_overview_lots_rate_limit_returns_429(_mock_limit, mock_service):
|
|
client = _client()
|
|
response = client.get('/api/hold-overview/lots')
|
|
|
|
assert response.status_code == 429
|
|
payload = response.get_json()
|
|
assert payload['error']['code'] == 'TOO_MANY_REQUESTS'
|
|
assert response.headers.get('Retry-After') == '3'
|
|
mock_service.assert_not_called()
|