forked from erp-dev/erp
286 lines
11 KiB
Python
286 lines
11 KiB
Python
"""
|
|
工艺参数 API 测试
|
|
"""
|
|
from django.test import TestCase
|
|
from django.contrib.auth import get_user_model
|
|
from rest_framework.test import APIClient
|
|
from rest_framework import status
|
|
from stateflow.models import StateParameter, State
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
class StateParameterAPITestCase(TestCase):
|
|
"""工艺参数 API 测试"""
|
|
|
|
def setUp(self):
|
|
"""设置测试数据"""
|
|
# 创建用户
|
|
self.user = User.objects.create_user(username='testuser', password='testpass123')
|
|
|
|
# 创建多个工艺参数
|
|
self.param1 = StateParameter.objects.create(
|
|
key='color',
|
|
value='红色',
|
|
description='颜色参数',
|
|
is_required=True,
|
|
is_image_path=False
|
|
)
|
|
self.param2 = StateParameter.objects.create(
|
|
key='size',
|
|
value='大号',
|
|
description='尺寸参数',
|
|
is_required=False,
|
|
is_image_path=False
|
|
)
|
|
self.param3 = StateParameter.objects.create(
|
|
key='logo_image',
|
|
value='/images/logo.png',
|
|
description='Logo图片',
|
|
is_required=True,
|
|
is_image_path=True
|
|
)
|
|
self.param4 = StateParameter.objects.create(
|
|
key='material',
|
|
value='纯棉',
|
|
description='材料参数',
|
|
is_required=False,
|
|
is_image_path=False
|
|
)
|
|
|
|
# 创建状态并关联参数
|
|
self.state1 = State.objects.create(
|
|
name='设计状态',
|
|
description='设计阶段'
|
|
)
|
|
self.state1.parameters.add(self.param1, self.param3)
|
|
|
|
self.state2 = State.objects.create(
|
|
name='生产状态',
|
|
description='生产阶段'
|
|
)
|
|
self.state2.parameters.add(self.param2, self.param4)
|
|
|
|
# 配置 API 客户端
|
|
self.client = APIClient()
|
|
self.client.force_authenticate(user=self.user)
|
|
|
|
def test_list_parameters(self):
|
|
"""测试获取工艺参数列表"""
|
|
response = self.client.get('/api/v1/parameters/')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(len(response.data), 4)
|
|
|
|
# 验证返回的数据结构
|
|
for item in response.data:
|
|
self.assertIn('id', item)
|
|
self.assertIn('key', item)
|
|
self.assertIn('value', item)
|
|
self.assertIn('description', item)
|
|
self.assertIn('is_required', item)
|
|
self.assertIn('is_image_path', item)
|
|
self.assertIn('attachment', item)
|
|
self.assertIn('attachment_url', item)
|
|
|
|
def test_retrieve_parameter(self):
|
|
"""测试获取单个工艺参数详情"""
|
|
response = self.client.get(f'/api/v1/parameters/{self.param1.id}/')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(response.data['key'], 'color')
|
|
self.assertEqual(response.data['value'], '红色')
|
|
self.assertEqual(response.data['description'], '颜色参数')
|
|
self.assertEqual(response.data['is_required'], True)
|
|
self.assertEqual(response.data['is_image_path'], False)
|
|
|
|
def test_create_parameter(self):
|
|
"""测试创建工艺参数"""
|
|
data = {
|
|
'key': 'weight',
|
|
'value': '500g',
|
|
'description': '重量参数',
|
|
'is_required': False,
|
|
'is_image_path': False
|
|
}
|
|
response = self.client.post('/api/v1/parameters/', data)
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
|
self.assertEqual(response.data['key'], 'weight')
|
|
self.assertEqual(response.data['value'], '500g')
|
|
self.assertEqual(response.data['description'], '重量参数')
|
|
|
|
# 验证数据库中是否创建成功
|
|
self.assertTrue(StateParameter.objects.filter(key='weight').exists())
|
|
|
|
def test_create_parameter_duplicate_key(self):
|
|
"""测试创建重复 key 的参数(应该失败)"""
|
|
data = {
|
|
'key': 'color', # 已存在
|
|
'value': '蓝色',
|
|
'description': '另一个颜色参数',
|
|
'is_required': False,
|
|
'is_image_path': False
|
|
}
|
|
response = self.client.post('/api/v1/parameters/', data)
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
self.assertIn('key', response.data)
|
|
|
|
def test_update_parameter_full(self):
|
|
"""测试完整更新工艺参数 (PUT)"""
|
|
data = {
|
|
'key': 'color_updated',
|
|
'value': '蓝色',
|
|
'description': '更新后的颜色参数',
|
|
'is_required': False,
|
|
'is_image_path': False
|
|
}
|
|
response = self.client.put(f'/api/v1/parameters/{self.param1.id}/', data)
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(response.data['key'], 'color_updated')
|
|
self.assertEqual(response.data['value'], '蓝色')
|
|
self.assertEqual(response.data['is_required'], False)
|
|
|
|
# 验证数据库中的更新
|
|
self.param1.refresh_from_db()
|
|
self.assertEqual(self.param1.key, 'color_updated')
|
|
self.assertEqual(self.param1.value, '蓝色')
|
|
|
|
def test_update_parameter_partial(self):
|
|
"""测试部分更新工艺参数 (PATCH)"""
|
|
data = {
|
|
'value': '绿色',
|
|
'description': '修改后的描述'
|
|
}
|
|
response = self.client.patch(f'/api/v1/parameters/{self.param1.id}/', data)
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(response.data['key'], 'color') # key 未改变
|
|
self.assertEqual(response.data['value'], '绿色') # value 已改变
|
|
self.assertEqual(response.data['description'], '修改后的描述')
|
|
|
|
# 验证数据库中的更新
|
|
self.param1.refresh_from_db()
|
|
self.assertEqual(self.param1.key, 'color')
|
|
self.assertEqual(self.param1.value, '绿色')
|
|
|
|
def test_delete_parameter_not_allowed(self):
|
|
"""测试删除工艺参数(应该被禁止)"""
|
|
response = self.client.delete(f'/api/v1/parameters/{self.param1.id}/')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
|
|
self.assertIn('detail', response.data)
|
|
|
|
# 验证数据库中参数仍然存在
|
|
self.assertTrue(StateParameter.objects.filter(id=self.param1.id).exists())
|
|
|
|
def test_search_parameters(self):
|
|
"""测试搜索工艺参数"""
|
|
response = self.client.get('/api/v1/parameters/?search=颜色')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(len(response.data), 1)
|
|
self.assertEqual(response.data[0]['key'], 'color')
|
|
|
|
def test_search_parameters_by_key(self):
|
|
"""测试按 key 搜索工艺参数"""
|
|
response = self.client.get('/api/v1/parameters/?search=size')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(len(response.data), 1)
|
|
self.assertEqual(response.data[0]['key'], 'size')
|
|
|
|
def test_filter_required_parameters(self):
|
|
"""测试筛选必填参数"""
|
|
response = self.client.get('/api/v1/parameters/?is_required=true')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(len(response.data), 2) # color 和 logo_image
|
|
for item in response.data:
|
|
self.assertTrue(item['is_required'])
|
|
|
|
def test_filter_optional_parameters(self):
|
|
"""测试筛选可选参数"""
|
|
response = self.client.get('/api/v1/parameters/?is_required=false')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(len(response.data), 2) # size 和 material
|
|
for item in response.data:
|
|
self.assertFalse(item['is_required'])
|
|
|
|
def test_filter_image_path_parameters(self):
|
|
"""测试筛选图片路径参数"""
|
|
response = self.client.get('/api/v1/parameters/?is_image_path=true')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(len(response.data), 1)
|
|
self.assertEqual(response.data[0]['key'], 'logo_image')
|
|
self.assertTrue(response.data[0]['is_image_path'])
|
|
|
|
def test_get_required_parameters_action(self):
|
|
"""测试获取所有必填参数的自定义 action"""
|
|
response = self.client.get('/api/v1/parameters/required/')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(len(response.data), 2)
|
|
keys = [item['key'] for item in response.data]
|
|
self.assertIn('color', keys)
|
|
self.assertIn('logo_image', keys)
|
|
|
|
def test_get_optional_parameters_action(self):
|
|
"""测试获取所有可选参数的自定义 action"""
|
|
response = self.client.get('/api/v1/parameters/optional/')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(len(response.data), 2)
|
|
keys = [item['key'] for item in response.data]
|
|
self.assertIn('size', keys)
|
|
self.assertIn('material', keys)
|
|
|
|
def test_get_parameter_states(self):
|
|
"""测试获取使用该参数的所有状态"""
|
|
response = self.client.get(f'/api/v1/parameters/{self.param1.id}/states/')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(response.data['parameter_id'], self.param1.id)
|
|
self.assertEqual(response.data['parameter_key'], 'color')
|
|
self.assertEqual(response.data['count'], 1)
|
|
self.assertEqual(len(response.data['states']), 1)
|
|
self.assertEqual(response.data['states'][0]['name'], '设计状态')
|
|
|
|
def test_get_parameter_states_multiple(self):
|
|
"""测试获取被多个状态使用的参数"""
|
|
# 让 param2 也被 state1 使用
|
|
self.state1.parameters.add(self.param2)
|
|
|
|
response = self.client.get(f'/api/v1/parameters/{self.param2.id}/states/')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(response.data['count'], 2) # 被两个状态使用
|
|
state_names = [state['name'] for state in response.data['states']]
|
|
self.assertIn('设计状态', state_names)
|
|
self.assertIn('生产状态', state_names)
|
|
|
|
def test_unauthorized_access(self):
|
|
"""测试未认证访问"""
|
|
self.client.force_authenticate(user=None)
|
|
response = self.client.get('/api/v1/parameters/')
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
def test_create_parameter_minimal(self):
|
|
"""测试创建最小参数(只有必需字段)"""
|
|
data = {
|
|
'key': 'simple_param'
|
|
}
|
|
response = self.client.post('/api/v1/parameters/', data)
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
|
self.assertEqual(response.data['key'], 'simple_param')
|
|
self.assertIsNone(response.data['value'])
|
|
self.assertEqual(response.data['description'], '')
|
|
self.assertFalse(response.data['is_required'])
|
|
self.assertFalse(response.data['is_image_path'])
|