147 lines
5.4 KiB
Python
147 lines
5.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Integration tests for TMTT Defect Analysis API routes."""
|
|
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
import pandas as pd
|
|
|
|
|
|
class TestTmttDefectAnalysisEndpoint(unittest.TestCase):
|
|
"""Test GET /api/tmtt-defect/analysis endpoint."""
|
|
|
|
def setUp(self):
|
|
from mes_dashboard.core import database as db
|
|
db._ENGINE = None
|
|
|
|
from mes_dashboard.app import create_app
|
|
self.app = create_app()
|
|
self.client = self.app.test_client()
|
|
|
|
def test_missing_start_date(self):
|
|
resp = self.client.get('/api/tmtt-defect/analysis?end_date=2025-01-31')
|
|
self.assertEqual(resp.status_code, 400)
|
|
data = resp.get_json()
|
|
self.assertFalse(data['success'])
|
|
|
|
def test_missing_end_date(self):
|
|
resp = self.client.get('/api/tmtt-defect/analysis?start_date=2025-01-01')
|
|
self.assertEqual(resp.status_code, 400)
|
|
data = resp.get_json()
|
|
self.assertFalse(data['success'])
|
|
|
|
def test_missing_both_dates(self):
|
|
resp = self.client.get('/api/tmtt-defect/analysis')
|
|
self.assertEqual(resp.status_code, 400)
|
|
|
|
@patch('mes_dashboard.routes.tmtt_defect_routes.query_tmtt_defect_analysis')
|
|
def test_invalid_date_format(self, mock_query):
|
|
mock_query.return_value = {'error': '日期格式無效,請使用 YYYY-MM-DD'}
|
|
resp = self.client.get(
|
|
'/api/tmtt-defect/analysis?start_date=invalid&end_date=2025-01-31'
|
|
)
|
|
self.assertEqual(resp.status_code, 400)
|
|
data = resp.get_json()
|
|
self.assertFalse(data['success'])
|
|
self.assertIn('格式', data['error'])
|
|
|
|
@patch('mes_dashboard.routes.tmtt_defect_routes.query_tmtt_defect_analysis')
|
|
def test_exceeds_180_days(self, mock_query):
|
|
mock_query.return_value = {'error': '查詢範圍不能超過 180 天'}
|
|
resp = self.client.get(
|
|
'/api/tmtt-defect/analysis?start_date=2025-01-01&end_date=2025-12-31'
|
|
)
|
|
self.assertEqual(resp.status_code, 400)
|
|
data = resp.get_json()
|
|
self.assertIn('180', data['error'])
|
|
|
|
@patch('mes_dashboard.routes.tmtt_defect_routes.query_tmtt_defect_analysis')
|
|
def test_successful_query(self, mock_query):
|
|
mock_query.return_value = {
|
|
'kpi': {
|
|
'total_input': 1000, 'lot_count': 10,
|
|
'print_defect_qty': 5, 'print_defect_rate': 0.5,
|
|
'lead_defect_qty': 3, 'lead_defect_rate': 0.3,
|
|
},
|
|
'charts': {
|
|
'by_workflow': [], 'by_package': [], 'by_type': [],
|
|
'by_tmtt_machine': [], 'by_mold_machine': [],
|
|
},
|
|
'detail': [],
|
|
}
|
|
|
|
resp = self.client.get(
|
|
'/api/tmtt-defect/analysis?start_date=2025-01-01&end_date=2025-01-31'
|
|
)
|
|
self.assertEqual(resp.status_code, 200)
|
|
data = resp.get_json()
|
|
self.assertTrue(data['success'])
|
|
self.assertIn('kpi', data['data'])
|
|
self.assertIn('charts', data['data'])
|
|
self.assertIn('detail', data['data'])
|
|
|
|
# Verify separate defect rates
|
|
kpi = data['data']['kpi']
|
|
self.assertEqual(kpi['print_defect_qty'], 5)
|
|
self.assertEqual(kpi['lead_defect_qty'], 3)
|
|
|
|
@patch('mes_dashboard.routes.tmtt_defect_routes.query_tmtt_defect_analysis')
|
|
def test_query_failure_returns_500(self, mock_query):
|
|
mock_query.return_value = None
|
|
resp = self.client.get(
|
|
'/api/tmtt-defect/analysis?start_date=2025-01-01&end_date=2025-01-31'
|
|
)
|
|
self.assertEqual(resp.status_code, 500)
|
|
|
|
|
|
class TestTmttDefectExportEndpoint(unittest.TestCase):
|
|
"""Test GET /api/tmtt-defect/export endpoint."""
|
|
|
|
def setUp(self):
|
|
from mes_dashboard.core import database as db
|
|
db._ENGINE = None
|
|
|
|
from mes_dashboard.app import create_app
|
|
self.app = create_app()
|
|
self.client = self.app.test_client()
|
|
|
|
def test_missing_dates(self):
|
|
resp = self.client.get('/api/tmtt-defect/export')
|
|
self.assertEqual(resp.status_code, 400)
|
|
|
|
@patch('mes_dashboard.routes.tmtt_defect_routes.export_csv')
|
|
def test_export_csv(self, mock_export):
|
|
mock_export.return_value = iter([
|
|
'\ufeff',
|
|
'LOT ID,TYPE,PACKAGE,WORKFLOW,完工流水碼,TMTT設備,MOLD設備,'
|
|
'投入數,印字不良數,印字不良率(%),腳型不良數,腳型不良率(%)\r\n',
|
|
])
|
|
resp = self.client.get(
|
|
'/api/tmtt-defect/export?start_date=2025-01-01&end_date=2025-01-31'
|
|
)
|
|
self.assertEqual(resp.status_code, 200)
|
|
self.assertIn('text/csv', resp.content_type)
|
|
self.assertIn('attachment', resp.headers.get('Content-Disposition', ''))
|
|
|
|
|
|
class TestTmttDefectPageRoute(unittest.TestCase):
|
|
"""Test page route."""
|
|
|
|
def setUp(self):
|
|
from mes_dashboard.core import database as db
|
|
db._ENGINE = None
|
|
|
|
from mes_dashboard.app import create_app
|
|
self.app = create_app()
|
|
self.client = self.app.test_client()
|
|
|
|
def test_page_requires_auth_when_dev(self):
|
|
"""Page in 'dev' status returns 403 for unauthenticated users."""
|
|
resp = self.client.get('/tmtt-defect')
|
|
# 403 because page_status is 'dev' and user is not admin
|
|
self.assertIn(resp.status_code, [200, 403])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|