修改文件结构,统一文档格式
This commit is contained in:
248
backend/tools/testing/test-api-binding.js
Normal file
248
backend/tools/testing/test-api-binding.js
Normal file
@@ -0,0 +1,248 @@
|
||||
const { Farm } = require('./models');
|
||||
const { sequelize } = require('./config/database');
|
||||
const farmController = require('./controllers/farmController');
|
||||
|
||||
// 模拟Express请求和响应对象
|
||||
function createMockReq(body, params = {}) {
|
||||
return {
|
||||
body,
|
||||
params
|
||||
};
|
||||
}
|
||||
|
||||
function createMockRes() {
|
||||
const res = {
|
||||
statusCode: 200,
|
||||
data: null,
|
||||
status: function(code) {
|
||||
this.statusCode = code;
|
||||
return this;
|
||||
},
|
||||
json: function(data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
// 测试API绑定的完整流程
|
||||
async function testApiBinding() {
|
||||
console.log('=== API数据绑定测试 ===\n');
|
||||
|
||||
let testFarmId = null;
|
||||
|
||||
try {
|
||||
// 1. 测试创建养殖场API
|
||||
console.log('1. 测试创建养殖场API...');
|
||||
const createReq = createMockReq({
|
||||
name: 'API测试农场',
|
||||
owner: 'API测试负责人',
|
||||
phone: '13800138001',
|
||||
address: 'API测试地址',
|
||||
longitude: 106.2309,
|
||||
latitude: 38.4872,
|
||||
status: 'active'
|
||||
});
|
||||
|
||||
const createRes = createMockRes();
|
||||
await farmController.createFarm(createReq, createRes);
|
||||
|
||||
console.log('✓ 创建API响应:', {
|
||||
status: createRes.statusCode,
|
||||
success: createRes.data?.success,
|
||||
farm_id: createRes.data?.data?.id,
|
||||
location: createRes.data?.data?.location
|
||||
});
|
||||
|
||||
if (!createRes.data?.success) {
|
||||
throw new Error('创建养殖场失败: ' + createRes.data?.message);
|
||||
}
|
||||
|
||||
testFarmId = createRes.data.data.id;
|
||||
|
||||
// 2. 测试获取养殖场API
|
||||
console.log('\n2. 测试获取养殖场API...');
|
||||
const getReq = createMockReq({}, { id: testFarmId });
|
||||
const getRes = createMockRes();
|
||||
await farmController.getFarmById(getReq, getRes);
|
||||
|
||||
console.log('✓ 获取API响应:', {
|
||||
status: getRes.statusCode,
|
||||
success: getRes.data?.success,
|
||||
location: getRes.data?.data?.location,
|
||||
location_type: typeof getRes.data?.data?.location
|
||||
});
|
||||
|
||||
const farmData = getRes.data?.data;
|
||||
if (!farmData) {
|
||||
throw new Error('获取养殖场数据失败');
|
||||
}
|
||||
|
||||
// 3. 模拟前端editFarm函数的数据解析
|
||||
console.log('\n3. 模拟前端editFarm数据解析...');
|
||||
const record = farmData;
|
||||
|
||||
// 前端解析逻辑
|
||||
const longitude = record.location?.lng || undefined;
|
||||
const latitude = record.location?.lat || undefined;
|
||||
|
||||
console.log('✓ 前端解析结果:', {
|
||||
original_location: record.location,
|
||||
parsed_longitude: longitude,
|
||||
parsed_latitude: latitude,
|
||||
longitude_type: typeof longitude,
|
||||
latitude_type: typeof latitude
|
||||
});
|
||||
|
||||
// 4. 模拟前端formData绑定
|
||||
console.log('\n4. 模拟前端formData绑定...');
|
||||
const formData = {
|
||||
id: record.id,
|
||||
name: record.name,
|
||||
owner: record.contact || '',
|
||||
phone: record.phone,
|
||||
address: record.address,
|
||||
longitude: longitude,
|
||||
latitude: latitude,
|
||||
status: record.status
|
||||
};
|
||||
|
||||
console.log('✓ formData绑定结果:', {
|
||||
longitude: formData.longitude,
|
||||
latitude: formData.latitude,
|
||||
longitude_type: typeof formData.longitude,
|
||||
latitude_type: typeof formData.latitude
|
||||
});
|
||||
|
||||
// 5. 模拟用户修改经纬度
|
||||
console.log('\n5. 模拟用户修改经纬度...');
|
||||
const modifiedFormData = {
|
||||
...formData,
|
||||
longitude: 106.2400,
|
||||
latitude: 38.4900
|
||||
};
|
||||
|
||||
console.log('✓ 修改后的formData:', {
|
||||
longitude: modifiedFormData.longitude,
|
||||
latitude: modifiedFormData.latitude,
|
||||
longitude_type: typeof modifiedFormData.longitude,
|
||||
latitude_type: typeof modifiedFormData.latitude
|
||||
});
|
||||
|
||||
// 6. 测试更新养殖场API
|
||||
console.log('\n6. 测试更新养殖场API...');
|
||||
const updateReq = createMockReq({
|
||||
name: modifiedFormData.name,
|
||||
owner: modifiedFormData.owner,
|
||||
phone: modifiedFormData.phone,
|
||||
address: modifiedFormData.address,
|
||||
longitude: modifiedFormData.longitude,
|
||||
latitude: modifiedFormData.latitude,
|
||||
status: modifiedFormData.status
|
||||
}, { id: testFarmId });
|
||||
|
||||
const updateRes = createMockRes();
|
||||
await farmController.updateFarm(updateReq, updateRes);
|
||||
|
||||
console.log('✓ 更新API响应:', {
|
||||
status: updateRes.statusCode,
|
||||
success: updateRes.data?.success,
|
||||
location: updateRes.data?.data?.location
|
||||
});
|
||||
|
||||
// 7. 验证更新结果
|
||||
console.log('\n7. 验证更新结果...');
|
||||
const verifyReq = createMockReq({}, { id: testFarmId });
|
||||
const verifyRes = createMockRes();
|
||||
await farmController.getFarmById(verifyReq, verifyRes);
|
||||
|
||||
const updatedFarm = verifyRes.data?.data;
|
||||
console.log('✓ 更新后的数据:', {
|
||||
location: updatedFarm?.location,
|
||||
location_lng: updatedFarm?.location?.lng,
|
||||
location_lat: updatedFarm?.location?.lat,
|
||||
expected_lng: 106.2400,
|
||||
expected_lat: 38.4900,
|
||||
lng_match: updatedFarm?.location?.lng === 106.2400,
|
||||
lat_match: updatedFarm?.location?.lat === 38.4900
|
||||
});
|
||||
|
||||
// 8. 测试边界情况 - 清空经纬度
|
||||
console.log('\n8. 测试边界情况 - 清空经纬度...');
|
||||
const clearReq = createMockReq({
|
||||
name: modifiedFormData.name,
|
||||
owner: modifiedFormData.owner,
|
||||
phone: modifiedFormData.phone,
|
||||
address: modifiedFormData.address,
|
||||
longitude: undefined,
|
||||
latitude: undefined,
|
||||
status: modifiedFormData.status
|
||||
}, { id: testFarmId });
|
||||
|
||||
const clearRes = createMockRes();
|
||||
await farmController.updateFarm(clearReq, clearRes);
|
||||
|
||||
console.log('✓ 清空经纬度API响应:', {
|
||||
status: clearRes.statusCode,
|
||||
success: clearRes.data?.success,
|
||||
location: clearRes.data?.data?.location
|
||||
});
|
||||
|
||||
// 9. 验证清空结果
|
||||
console.log('\n9. 验证清空结果...');
|
||||
const verifyClearReq = createMockReq({}, { id: testFarmId });
|
||||
const verifyClearRes = createMockRes();
|
||||
await farmController.getFarmById(verifyClearReq, verifyClearRes);
|
||||
|
||||
const clearedFarm = verifyClearRes.data?.data;
|
||||
console.log('✓ 清空后的数据:', {
|
||||
location: clearedFarm?.location,
|
||||
location_lng: clearedFarm?.location?.lng,
|
||||
location_lat: clearedFarm?.location?.lat,
|
||||
has_lng: 'lng' in (clearedFarm?.location || {}),
|
||||
has_lat: 'lat' in (clearedFarm?.location || {})
|
||||
});
|
||||
|
||||
console.log('\n=== API数据绑定测试完成 ===');
|
||||
console.log('\n📋 测试总结:');
|
||||
console.log('1. ✅ 创建API正确处理经纬度数据');
|
||||
console.log('2. ✅ 获取API正确返回location对象');
|
||||
console.log('3. ✅ 前端数据解析逻辑正确');
|
||||
console.log('4. ✅ formData绑定逻辑正确');
|
||||
console.log('5. ✅ 用户修改数据处理正确');
|
||||
console.log('6. ✅ 更新API正确处理经纬度数据');
|
||||
console.log('7. ✅ 数据更新验证正确');
|
||||
console.log('8. ✅ 边界情况处理正确');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 测试过程中出现错误:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// 清理测试数据
|
||||
if (testFarmId) {
|
||||
console.log('\n10. 清理测试数据...');
|
||||
try {
|
||||
await Farm.destroy({ where: { id: testFarmId } });
|
||||
console.log('✓ 测试数据已清理');
|
||||
} catch (error) {
|
||||
console.error('清理测试数据失败:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
if (require.main === module) {
|
||||
testApiBinding()
|
||||
.then(() => {
|
||||
console.log('\n🎉 所有API绑定测试通过!');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('\n💥 API绑定测试失败:', error.message);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { testApiBinding };
|
||||
211
backend/tools/testing/test-clear-coordinates.js
Normal file
211
backend/tools/testing/test-clear-coordinates.js
Normal file
@@ -0,0 +1,211 @@
|
||||
const { Farm } = require('./models');
|
||||
const { sequelize } = require('./config/database');
|
||||
const farmController = require('./controllers/farmController');
|
||||
|
||||
// 模拟Express请求和响应对象
|
||||
function createMockReq(body, params = {}) {
|
||||
return {
|
||||
body,
|
||||
params
|
||||
};
|
||||
}
|
||||
|
||||
function createMockRes() {
|
||||
const res = {
|
||||
statusCode: 200,
|
||||
data: null,
|
||||
status: function(code) {
|
||||
this.statusCode = code;
|
||||
return this;
|
||||
},
|
||||
json: function(data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
// 测试清空经纬度的不同场景
|
||||
async function testClearCoordinates() {
|
||||
console.log('=== 清空经纬度测试 ===\n');
|
||||
|
||||
let testFarmId = null;
|
||||
|
||||
try {
|
||||
// 1. 创建带有经纬度的测试记录
|
||||
console.log('1. 创建带有经纬度的测试记录...');
|
||||
const createReq = createMockReq({
|
||||
name: '清空测试农场',
|
||||
owner: '测试负责人',
|
||||
phone: '13800138002',
|
||||
address: '测试地址',
|
||||
longitude: 106.2309,
|
||||
latitude: 38.4872,
|
||||
status: 'active'
|
||||
});
|
||||
|
||||
const createRes = createMockRes();
|
||||
await farmController.createFarm(createReq, createRes);
|
||||
|
||||
testFarmId = createRes.data.data.id;
|
||||
console.log('✓ 创建成功,location:', createRes.data.data.location);
|
||||
|
||||
// 2. 测试传入null值清空
|
||||
console.log('\n2. 测试传入null值清空...');
|
||||
const clearNullReq = createMockReq({
|
||||
name: '清空测试农场',
|
||||
owner: '测试负责人',
|
||||
phone: '13800138002',
|
||||
address: '测试地址',
|
||||
longitude: null,
|
||||
latitude: null,
|
||||
status: 'active'
|
||||
}, { id: testFarmId });
|
||||
|
||||
const clearNullRes = createMockRes();
|
||||
await farmController.updateFarm(clearNullReq, clearNullRes);
|
||||
|
||||
console.log('✓ null值清空结果:', {
|
||||
location: clearNullRes.data.data.location,
|
||||
has_lng: 'lng' in (clearNullRes.data.data.location || {}),
|
||||
has_lat: 'lat' in (clearNullRes.data.data.location || {})
|
||||
});
|
||||
|
||||
// 3. 重新设置经纬度
|
||||
console.log('\n3. 重新设置经纬度...');
|
||||
const resetReq = createMockReq({
|
||||
name: '清空测试农场',
|
||||
owner: '测试负责人',
|
||||
phone: '13800138002',
|
||||
address: '测试地址',
|
||||
longitude: 106.2400,
|
||||
latitude: 38.4900,
|
||||
status: 'active'
|
||||
}, { id: testFarmId });
|
||||
|
||||
const resetRes = createMockRes();
|
||||
await farmController.updateFarm(resetReq, resetRes);
|
||||
|
||||
console.log('✓ 重新设置结果:', resetRes.data.data.location);
|
||||
|
||||
// 4. 测试传入空字符串清空
|
||||
console.log('\n4. 测试传入空字符串清空...');
|
||||
const clearEmptyReq = createMockReq({
|
||||
name: '清空测试农场',
|
||||
owner: '测试负责人',
|
||||
phone: '13800138002',
|
||||
address: '测试地址',
|
||||
longitude: '',
|
||||
latitude: '',
|
||||
status: 'active'
|
||||
}, { id: testFarmId });
|
||||
|
||||
const clearEmptyRes = createMockRes();
|
||||
await farmController.updateFarm(clearEmptyReq, clearEmptyRes);
|
||||
|
||||
console.log('✓ 空字符串清空结果:', {
|
||||
location: clearEmptyRes.data.data.location,
|
||||
has_lng: 'lng' in (clearEmptyRes.data.data.location || {}),
|
||||
has_lat: 'lat' in (clearEmptyRes.data.data.location || {})
|
||||
});
|
||||
|
||||
// 5. 重新设置经纬度
|
||||
console.log('\n5. 再次重新设置经纬度...');
|
||||
const reset2Req = createMockReq({
|
||||
name: '清空测试农场',
|
||||
owner: '测试负责人',
|
||||
phone: '13800138002',
|
||||
address: '测试地址',
|
||||
longitude: 106.2500,
|
||||
latitude: 38.5000,
|
||||
status: 'active'
|
||||
}, { id: testFarmId });
|
||||
|
||||
const reset2Res = createMockRes();
|
||||
await farmController.updateFarm(reset2Req, reset2Res);
|
||||
|
||||
console.log('✓ 再次设置结果:', reset2Res.data.data.location);
|
||||
|
||||
// 6. 测试不传入经纬度字段(undefined)
|
||||
console.log('\n6. 测试不传入经纬度字段(undefined)...');
|
||||
const noCoordReq = createMockReq({
|
||||
name: '清空测试农场-修改',
|
||||
owner: '测试负责人-修改',
|
||||
phone: '13800138003',
|
||||
address: '测试地址-修改',
|
||||
status: 'active'
|
||||
// 注意:这里没有longitude和latitude字段
|
||||
}, { id: testFarmId });
|
||||
|
||||
const noCoordRes = createMockRes();
|
||||
await farmController.updateFarm(noCoordReq, noCoordRes);
|
||||
|
||||
console.log('✓ 不传入经纬度字段结果:', {
|
||||
location: noCoordRes.data.data.location,
|
||||
has_lng: 'lng' in (noCoordRes.data.data.location || {}),
|
||||
has_lat: 'lat' in (noCoordRes.data.data.location || {}),
|
||||
name: noCoordRes.data.data.name
|
||||
});
|
||||
|
||||
// 7. 测试只清空其中一个坐标
|
||||
console.log('\n7. 测试只清空经度,保留纬度...');
|
||||
const clearLngReq = createMockReq({
|
||||
name: '清空测试农场-修改',
|
||||
owner: '测试负责人-修改',
|
||||
phone: '13800138003',
|
||||
address: '测试地址-修改',
|
||||
longitude: null,
|
||||
latitude: 38.5100,
|
||||
status: 'active'
|
||||
}, { id: testFarmId });
|
||||
|
||||
const clearLngRes = createMockRes();
|
||||
await farmController.updateFarm(clearLngReq, clearLngRes);
|
||||
|
||||
console.log('✓ 只清空经度结果:', {
|
||||
location: clearLngRes.data.data.location,
|
||||
has_lng: 'lng' in (clearLngRes.data.data.location || {}),
|
||||
has_lat: 'lat' in (clearLngRes.data.data.location || {}),
|
||||
lng_value: clearLngRes.data.data.location?.lng,
|
||||
lat_value: clearLngRes.data.data.location?.lat
|
||||
});
|
||||
|
||||
console.log('\n=== 清空经纬度测试完成 ===');
|
||||
console.log('\n📋 测试总结:');
|
||||
console.log('1. ✅ null值可以正确清空经纬度');
|
||||
console.log('2. ✅ 空字符串可以正确清空经纬度');
|
||||
console.log('3. ✅ 不传入字段时保持原有值');
|
||||
console.log('4. ✅ 可以单独清空其中一个坐标');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 测试过程中出现错误:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// 清理测试数据
|
||||
if (testFarmId) {
|
||||
console.log('\n8. 清理测试数据...');
|
||||
try {
|
||||
await Farm.destroy({ where: { id: testFarmId } });
|
||||
console.log('✓ 测试数据已清理');
|
||||
} catch (error) {
|
||||
console.error('清理测试数据失败:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
if (require.main === module) {
|
||||
testClearCoordinates()
|
||||
.then(() => {
|
||||
console.log('\n🎉 所有清空经纬度测试通过!');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('\n💥 清空经纬度测试失败:', error.message);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { testClearCoordinates };
|
||||
191
backend/tools/testing/test-coordinate-edit-flow.js
Normal file
191
backend/tools/testing/test-coordinate-edit-flow.js
Normal file
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* 测试经纬度编辑功能的完整流程
|
||||
* 验证数据显示和更新的准确性
|
||||
* @file test-coordinate-edit-flow.js
|
||||
*/
|
||||
|
||||
const { Farm } = require('./models');
|
||||
const { sequelize } = require('./config/database-simple');
|
||||
|
||||
async function testCoordinateEditFlow() {
|
||||
try {
|
||||
console.log('开始测试经纬度编辑功能...');
|
||||
await sequelize.authenticate();
|
||||
|
||||
// 1. 创建测试记录
|
||||
console.log('\n=== 步骤1: 创建测试记录 ===');
|
||||
const testFarm = await Farm.create({
|
||||
name: '经纬度编辑测试农场',
|
||||
type: 'farm',
|
||||
location: {
|
||||
lng: 106.2309,
|
||||
lat: 38.4872
|
||||
},
|
||||
address: '宁夏回族自治区银川市',
|
||||
contact: '测试用户',
|
||||
phone: '13800138000',
|
||||
status: 'active'
|
||||
});
|
||||
|
||||
console.log(`✅ 创建成功 - ID: ${testFarm.id}`);
|
||||
console.log(` 初始经度: ${testFarm.location.lng}`);
|
||||
console.log(` 初始纬度: ${testFarm.location.lat}`);
|
||||
|
||||
// 2. 模拟前端获取数据进行编辑
|
||||
console.log('\n=== 步骤2: 模拟前端获取编辑数据 ===');
|
||||
const farmForEdit = await Farm.findByPk(testFarm.id);
|
||||
|
||||
// 模拟前端editFarm函数的数据解析
|
||||
const editFormData = {
|
||||
id: farmForEdit.id,
|
||||
name: farmForEdit.name,
|
||||
address: farmForEdit.address,
|
||||
contact: farmForEdit.contact,
|
||||
phone: farmForEdit.phone,
|
||||
status: farmForEdit.status,
|
||||
longitude: farmForEdit.location?.lng,
|
||||
latitude: farmForEdit.location?.lat
|
||||
};
|
||||
|
||||
console.log('前端编辑表单数据:');
|
||||
console.log(` 经度输入框值: ${editFormData.longitude} (类型: ${typeof editFormData.longitude})`);
|
||||
console.log(` 纬度输入框值: ${editFormData.latitude} (类型: ${typeof editFormData.latitude})`);
|
||||
|
||||
// 验证数据正确性
|
||||
const isDataCorrect = (
|
||||
editFormData.longitude === testFarm.location.lng &&
|
||||
editFormData.latitude === testFarm.location.lat
|
||||
);
|
||||
|
||||
console.log(`数据显示正确性: ${isDataCorrect ? '✅ 正确' : '❌ 错误'}`);
|
||||
|
||||
// 3. 模拟用户修改经纬度值
|
||||
console.log('\n=== 步骤3: 模拟用户修改经纬度值 ===');
|
||||
const modifiedData = {
|
||||
...editFormData,
|
||||
longitude: 106.5507, // 修改经度
|
||||
latitude: 38.7123 // 修改纬度
|
||||
};
|
||||
|
||||
console.log('用户修改后的值:');
|
||||
console.log(` 新经度: ${modifiedData.longitude}`);
|
||||
console.log(` 新纬度: ${modifiedData.latitude}`);
|
||||
|
||||
// 4. 模拟后端更新操作
|
||||
console.log('\n=== 步骤4: 模拟后端更新操作 ===');
|
||||
|
||||
// 构建新的location对象(模拟updateFarm函数逻辑)
|
||||
const newLocation = {};
|
||||
if (modifiedData.longitude !== undefined && modifiedData.longitude !== null) {
|
||||
newLocation.lng = parseFloat(modifiedData.longitude);
|
||||
}
|
||||
if (modifiedData.latitude !== undefined && modifiedData.latitude !== null) {
|
||||
newLocation.lat = parseFloat(modifiedData.latitude);
|
||||
}
|
||||
|
||||
console.log('构建的location对象:', JSON.stringify(newLocation));
|
||||
|
||||
// 执行更新
|
||||
await farmForEdit.update({ location: newLocation });
|
||||
console.log('✅ 数据库更新完成');
|
||||
|
||||
// 5. 验证更新结果
|
||||
console.log('\n=== 步骤5: 验证更新结果 ===');
|
||||
const updatedFarm = await Farm.findByPk(testFarm.id);
|
||||
|
||||
console.log('更新后的数据库记录:');
|
||||
console.log(` 经度: ${updatedFarm.location.lng} (类型: ${typeof updatedFarm.location.lng})`);
|
||||
console.log(` 纬度: ${updatedFarm.location.lat} (类型: ${typeof updatedFarm.location.lat})`);
|
||||
|
||||
// 验证更新准确性
|
||||
const isUpdateCorrect = (
|
||||
updatedFarm.location.lng === modifiedData.longitude &&
|
||||
updatedFarm.location.lat === modifiedData.latitude
|
||||
);
|
||||
|
||||
console.log(`更新准确性: ${isUpdateCorrect ? '✅ 正确' : '❌ 错误'}`);
|
||||
|
||||
// 6. 模拟再次编辑(验证修改后的值能正确显示)
|
||||
console.log('\n=== 步骤6: 验证修改后的值能正确显示 ===');
|
||||
const farmForSecondEdit = await Farm.findByPk(testFarm.id);
|
||||
|
||||
const secondEditFormData = {
|
||||
id: farmForSecondEdit.id,
|
||||
name: farmForSecondEdit.name,
|
||||
longitude: farmForSecondEdit.location?.lng,
|
||||
latitude: farmForSecondEdit.location?.lat
|
||||
};
|
||||
|
||||
console.log('第二次编辑时的表单数据:');
|
||||
console.log(` 经度输入框值: ${secondEditFormData.longitude}`);
|
||||
console.log(` 纬度输入框值: ${secondEditFormData.latitude}`);
|
||||
|
||||
// 验证显示的是最新修改的值
|
||||
const isSecondDisplayCorrect = (
|
||||
secondEditFormData.longitude === modifiedData.longitude &&
|
||||
secondEditFormData.latitude === modifiedData.latitude
|
||||
);
|
||||
|
||||
console.log(`修改后值显示正确性: ${isSecondDisplayCorrect ? '✅ 正确' : '❌ 错误'}`);
|
||||
|
||||
// 7. 测试边界情况
|
||||
console.log('\n=== 步骤7: 测试边界情况 ===');
|
||||
|
||||
// 测试清空经纬度
|
||||
console.log('测试清空经纬度...');
|
||||
await farmForSecondEdit.update({
|
||||
location: {}
|
||||
});
|
||||
|
||||
const farmWithEmptyLocation = await Farm.findByPk(testFarm.id);
|
||||
const emptyEditFormData = {
|
||||
longitude: farmWithEmptyLocation.location?.lng,
|
||||
latitude: farmWithEmptyLocation.location?.lat
|
||||
};
|
||||
|
||||
console.log('清空后的表单数据:');
|
||||
console.log(` 经度: ${emptyEditFormData.longitude} (${typeof emptyEditFormData.longitude})`);
|
||||
console.log(` 纬度: ${emptyEditFormData.latitude} (${typeof emptyEditFormData.latitude})`);
|
||||
|
||||
// 8. 生成测试报告
|
||||
console.log('\n=== 测试报告 ===');
|
||||
const allTestsPassed = isDataCorrect && isUpdateCorrect && isSecondDisplayCorrect;
|
||||
|
||||
console.log(`总体结果: ${allTestsPassed ? '✅ 所有测试通过' : '❌ 存在问题'}`);
|
||||
console.log('详细结果:');
|
||||
console.log(` - 初始数据显示: ${isDataCorrect ? '✅' : '❌'}`);
|
||||
console.log(` - 数据更新准确性: ${isUpdateCorrect ? '✅' : '❌'}`);
|
||||
console.log(` - 修改后值显示: ${isSecondDisplayCorrect ? '✅' : '❌'}`);
|
||||
|
||||
// 9. 清理测试数据
|
||||
console.log('\n=== 清理测试数据 ===');
|
||||
await testFarm.destroy();
|
||||
console.log('✅ 测试数据已清理');
|
||||
|
||||
return {
|
||||
success: allTestsPassed,
|
||||
results: {
|
||||
initialDisplay: isDataCorrect,
|
||||
updateAccuracy: isUpdateCorrect,
|
||||
modifiedDisplay: isSecondDisplayCorrect
|
||||
}
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('测试失败:', error.message);
|
||||
if (error.sql) {
|
||||
console.error('SQL:', error.sql);
|
||||
}
|
||||
return { success: false, error: error.message };
|
||||
} finally {
|
||||
await sequelize.close();
|
||||
console.log('\n数据库连接已关闭');
|
||||
}
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
if (require.main === module) {
|
||||
testCoordinateEditFlow();
|
||||
}
|
||||
|
||||
module.exports = { testCoordinateEditFlow };
|
||||
229
backend/tools/testing/test-coordinate-input-flow.js
Normal file
229
backend/tools/testing/test-coordinate-input-flow.js
Normal file
@@ -0,0 +1,229 @@
|
||||
const { Farm } = require('./models');
|
||||
const { sequelize } = require('./config/database');
|
||||
const farmController = require('./controllers/farmController');
|
||||
|
||||
// 模拟Express请求和响应对象
|
||||
function createMockReq(body, params = {}) {
|
||||
return {
|
||||
body,
|
||||
params
|
||||
};
|
||||
}
|
||||
|
||||
function createMockRes() {
|
||||
const res = {
|
||||
statusCode: 200,
|
||||
data: null,
|
||||
status: function(code) {
|
||||
this.statusCode = code;
|
||||
return this;
|
||||
},
|
||||
json: function(data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
// 模拟前端输入处理逻辑
|
||||
function simulateFrontendInputProcessing(userInput) {
|
||||
console.log(`\n🔍 模拟用户输入: "${userInput}"`);
|
||||
|
||||
// 模拟 a-input-number 的 parser 函数
|
||||
const parser = (value) => {
|
||||
if (!value) return value;
|
||||
// 移除非数字字符,保留小数点和负号
|
||||
const cleaned = value.toString().replace(/[^\d.-]/g, '');
|
||||
// 确保只有一个小数点和负号在开头
|
||||
const parts = cleaned.split('.');
|
||||
if (parts.length > 2) {
|
||||
return parts[0] + '.' + parts.slice(1).join('');
|
||||
}
|
||||
return cleaned;
|
||||
};
|
||||
|
||||
const parsedValue = parser(userInput);
|
||||
console.log(` 📝 Parser处理后: "${parsedValue}"`);
|
||||
|
||||
// 模拟 v-model 的数值转换
|
||||
let finalValue;
|
||||
if (parsedValue === '' || parsedValue === undefined || parsedValue === null) {
|
||||
finalValue = undefined;
|
||||
} else {
|
||||
const numValue = parseFloat(parsedValue);
|
||||
finalValue = isNaN(numValue) ? undefined : numValue;
|
||||
}
|
||||
|
||||
console.log(` 🔢 最终绑定值: ${finalValue} (类型: ${typeof finalValue})`);
|
||||
|
||||
return finalValue;
|
||||
}
|
||||
|
||||
// 测试各种用户输入场景
|
||||
async function testCoordinateInputFlow() {
|
||||
console.log('=== 经纬度输入流程测试 ===\n');
|
||||
|
||||
let testFarmId = null;
|
||||
|
||||
try {
|
||||
// 1. 创建测试记录
|
||||
console.log('1. 创建测试养殖场...');
|
||||
const createReq = createMockReq({
|
||||
name: '输入测试农场',
|
||||
owner: '测试负责人',
|
||||
phone: '13800138003',
|
||||
address: '测试地址',
|
||||
longitude: 106.2309,
|
||||
latitude: 38.4872,
|
||||
status: 'active'
|
||||
});
|
||||
|
||||
const createRes = createMockRes();
|
||||
await farmController.createFarm(createReq, createRes);
|
||||
|
||||
testFarmId = createRes.data.data.id;
|
||||
console.log('✓ 创建成功,初始location:', createRes.data.data.location);
|
||||
|
||||
// 2. 测试各种用户输入场景
|
||||
const testCases = [
|
||||
{
|
||||
name: '正常小数输入',
|
||||
longitude: '106.2400',
|
||||
latitude: '38.4900'
|
||||
},
|
||||
{
|
||||
name: '整数输入',
|
||||
longitude: '106',
|
||||
latitude: '38'
|
||||
},
|
||||
{
|
||||
name: '高精度小数输入',
|
||||
longitude: '106.234567',
|
||||
latitude: '38.487654'
|
||||
},
|
||||
{
|
||||
name: '负数输入',
|
||||
longitude: '-106.2400',
|
||||
latitude: '-38.4900'
|
||||
},
|
||||
{
|
||||
name: '包含非法字符的输入',
|
||||
longitude: '106.24abc',
|
||||
latitude: '38.49xyz'
|
||||
},
|
||||
{
|
||||
name: '多个小数点的输入',
|
||||
longitude: '106.24.56',
|
||||
latitude: '38.49.78'
|
||||
},
|
||||
{
|
||||
name: '空字符串输入',
|
||||
longitude: '',
|
||||
latitude: ''
|
||||
},
|
||||
{
|
||||
name: '只输入小数点',
|
||||
longitude: '.',
|
||||
latitude: '.'
|
||||
},
|
||||
{
|
||||
name: '边界值输入',
|
||||
longitude: '180.0',
|
||||
latitude: '90.0'
|
||||
},
|
||||
{
|
||||
name: '超出范围的输入',
|
||||
longitude: '200.0',
|
||||
latitude: '100.0'
|
||||
}
|
||||
];
|
||||
|
||||
for (let i = 0; i < testCases.length; i++) {
|
||||
const testCase = testCases[i];
|
||||
console.log(`\n${i + 2}. 测试场景: ${testCase.name}`);
|
||||
|
||||
// 模拟前端输入处理
|
||||
const processedLongitude = simulateFrontendInputProcessing(testCase.longitude);
|
||||
const processedLatitude = simulateFrontendInputProcessing(testCase.latitude);
|
||||
|
||||
// 构建提交数据
|
||||
const submitData = {
|
||||
name: '输入测试农场',
|
||||
owner: '测试负责人',
|
||||
phone: '13800138003',
|
||||
address: '测试地址',
|
||||
longitude: processedLongitude,
|
||||
latitude: processedLatitude,
|
||||
status: 'active'
|
||||
};
|
||||
|
||||
console.log(` 📤 提交数据:`, {
|
||||
longitude: submitData.longitude,
|
||||
latitude: submitData.latitude
|
||||
});
|
||||
|
||||
// 调用后端API
|
||||
const updateReq = createMockReq(submitData, { id: testFarmId });
|
||||
const updateRes = createMockRes();
|
||||
|
||||
try {
|
||||
await farmController.updateFarm(updateReq, updateRes);
|
||||
|
||||
console.log(` ✅ 更新成功:`, {
|
||||
location: updateRes.data.data.location,
|
||||
has_lng: 'lng' in (updateRes.data.data.location || {}),
|
||||
has_lat: 'lat' in (updateRes.data.data.location || {})
|
||||
});
|
||||
|
||||
// 验证数据范围
|
||||
const location = updateRes.data.data.location || {};
|
||||
if (location.lng !== undefined) {
|
||||
if (location.lng < -180 || location.lng > 180) {
|
||||
console.log(` ⚠️ 警告: 经度超出有效范围 (-180~180): ${location.lng}`);
|
||||
}
|
||||
}
|
||||
if (location.lat !== undefined) {
|
||||
if (location.lat < -90 || location.lat > 90) {
|
||||
console.log(` ⚠️ 警告: 纬度超出有效范围 (-90~90): ${location.lat}`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log(` ❌ 更新失败:`, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\n=== 输入流程测试完成 ===');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 测试过程中出现错误:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// 清理测试数据
|
||||
if (testFarmId) {
|
||||
console.log('\n🧹 清理测试数据...');
|
||||
try {
|
||||
await Farm.destroy({ where: { id: testFarmId } });
|
||||
console.log('✓ 测试数据已清理');
|
||||
} catch (error) {
|
||||
console.error('清理测试数据失败:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
if (require.main === module) {
|
||||
testCoordinateInputFlow()
|
||||
.then(() => {
|
||||
console.log('\n🎉 所有输入流程测试完成!');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('\n💥 输入流程测试失败:', error.message);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { testCoordinateInputFlow };
|
||||
142
backend/tools/testing/test-data-sync.js
Normal file
142
backend/tools/testing/test-data-sync.js
Normal file
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* 测试前端和后端数据同步
|
||||
* 验证经纬度数据的完整流程
|
||||
* @file test-data-sync.js
|
||||
*/
|
||||
|
||||
const { Farm } = require('./models');
|
||||
const { sequelize } = require('./config/database-simple');
|
||||
|
||||
async function testDataSync() {
|
||||
try {
|
||||
console.log('连接数据库...');
|
||||
await sequelize.authenticate();
|
||||
|
||||
console.log('\n=== 测试数据同步 ===');
|
||||
|
||||
// 1. 创建测试记录
|
||||
console.log('\n1. 创建测试记录...');
|
||||
const testFarm = await Farm.create({
|
||||
name: '数据同步测试农场',
|
||||
type: 'farm',
|
||||
location: {
|
||||
lng: 106.28,
|
||||
lat: 38.47
|
||||
},
|
||||
address: '宁夏回族自治区银川市测试区',
|
||||
contact: '测试管理员',
|
||||
phone: '13800138000',
|
||||
status: 'active'
|
||||
});
|
||||
|
||||
console.log(`✅ 创建成功 - ID: ${testFarm.id}`);
|
||||
console.log(` 经度: ${testFarm.location.lng}`);
|
||||
console.log(` 纬度: ${testFarm.location.lat}`);
|
||||
|
||||
// 2. 查询记录验证
|
||||
console.log('\n2. 查询记录验证...');
|
||||
const retrievedFarm = await Farm.findByPk(testFarm.id);
|
||||
console.log(`查询结果:`);
|
||||
console.log(` ID: ${retrievedFarm.id}`);
|
||||
console.log(` 名称: ${retrievedFarm.name}`);
|
||||
console.log(` Location类型: ${typeof retrievedFarm.location}`);
|
||||
console.log(` Location值: ${JSON.stringify(retrievedFarm.location)}`);
|
||||
console.log(` 经度: ${retrievedFarm.location.lng} (类型: ${typeof retrievedFarm.location.lng})`);
|
||||
console.log(` 纬度: ${retrievedFarm.location.lat} (类型: ${typeof retrievedFarm.location.lat})`);
|
||||
|
||||
// 3. 模拟API响应格式
|
||||
console.log('\n3. 模拟API响应格式...');
|
||||
const apiResponse = {
|
||||
success: true,
|
||||
data: {
|
||||
id: retrievedFarm.id,
|
||||
name: retrievedFarm.name,
|
||||
location: retrievedFarm.location,
|
||||
address: retrievedFarm.address,
|
||||
contact: retrievedFarm.contact,
|
||||
phone: retrievedFarm.phone,
|
||||
status: retrievedFarm.status
|
||||
}
|
||||
};
|
||||
|
||||
console.log('API响应格式:');
|
||||
console.log(JSON.stringify(apiResponse, null, 2));
|
||||
|
||||
// 4. 模拟前端数据解析
|
||||
console.log('\n4. 模拟前端数据解析...');
|
||||
const frontendData = apiResponse.data;
|
||||
const formData = {
|
||||
id: frontendData.id,
|
||||
name: frontendData.name,
|
||||
address: frontendData.address,
|
||||
contact: frontendData.contact,
|
||||
phone: frontendData.phone,
|
||||
status: frontendData.status,
|
||||
longitude: frontendData.location?.lng,
|
||||
latitude: frontendData.location?.lat
|
||||
};
|
||||
|
||||
console.log('前端表单数据:');
|
||||
console.log(` 经度: ${formData.longitude} (类型: ${typeof formData.longitude})`);
|
||||
console.log(` 纬度: ${formData.latitude} (类型: ${typeof formData.latitude})`);
|
||||
|
||||
// 5. 模拟更新操作
|
||||
console.log('\n5. 模拟更新操作...');
|
||||
const updateData = {
|
||||
longitude: 106.30,
|
||||
latitude: 38.50
|
||||
};
|
||||
|
||||
// 构建新的location对象
|
||||
const newLocation = {
|
||||
lng: parseFloat(updateData.longitude),
|
||||
lat: parseFloat(updateData.latitude)
|
||||
};
|
||||
|
||||
await retrievedFarm.update({ location: newLocation });
|
||||
|
||||
// 验证更新结果
|
||||
const updatedFarm = await Farm.findByPk(testFarm.id);
|
||||
console.log('更新后的数据:');
|
||||
console.log(` 经度: ${updatedFarm.location.lng}`);
|
||||
console.log(` 纬度: ${updatedFarm.location.lat}`);
|
||||
|
||||
// 6. 验证数据一致性
|
||||
console.log('\n6. 验证数据一致性...');
|
||||
const isConsistent = (
|
||||
updatedFarm.location.lng === updateData.longitude &&
|
||||
updatedFarm.location.lat === updateData.latitude
|
||||
);
|
||||
|
||||
console.log(`数据一致性检查: ${isConsistent ? '✅ 通过' : '❌ 失败'}`);
|
||||
console.log(` 期望经度: ${updateData.longitude}`);
|
||||
console.log(` 实际经度: ${updatedFarm.location.lng}`);
|
||||
console.log(` 期望纬度: ${updateData.latitude}`);
|
||||
console.log(` 实际纬度: ${updatedFarm.location.lat}`);
|
||||
|
||||
// 7. 清理测试数据
|
||||
console.log('\n7. 清理测试数据...');
|
||||
await testFarm.destroy();
|
||||
console.log('✅ 测试数据已清理');
|
||||
|
||||
console.log('\n=== 测试完成 ===');
|
||||
console.log(`结果: ${isConsistent ? '数据同步正常' : '数据同步异常'}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('测试失败:', error.message);
|
||||
if (error.sql) {
|
||||
console.error('SQL:', error.sql);
|
||||
}
|
||||
} finally {
|
||||
await sequelize.close();
|
||||
console.log('\n数据库连接已关闭');
|
||||
}
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
if (require.main === module) {
|
||||
console.log('开始测试数据同步...');
|
||||
testDataSync();
|
||||
}
|
||||
|
||||
module.exports = { testDataSync };
|
||||
63
backend/tools/testing/test-db-connection.js
Normal file
63
backend/tools/testing/test-db-connection.js
Normal file
@@ -0,0 +1,63 @@
|
||||
const mysql = require('mysql2/promise');
|
||||
require('dotenv').config();
|
||||
|
||||
async function testConnection() {
|
||||
const config = {
|
||||
host: process.env.DB_HOST || '129.211.213.226',
|
||||
port: process.env.DB_PORT || 3306,
|
||||
user: process.env.DB_USER || 'root',
|
||||
password: process.env.DB_PASSWORD || 'Aiotagro@741',
|
||||
database: process.env.DB_NAME || 'nxTest',
|
||||
connectTimeout: 10000,
|
||||
acquireTimeout: 10000,
|
||||
timeout: 10000
|
||||
};
|
||||
|
||||
console.log('尝试连接数据库...');
|
||||
console.log('配置:', {
|
||||
host: config.host,
|
||||
port: config.port,
|
||||
user: config.user,
|
||||
database: config.database
|
||||
});
|
||||
|
||||
try {
|
||||
const connection = await mysql.createConnection(config);
|
||||
console.log('✅ 数据库连接成功!');
|
||||
|
||||
// 测试查询
|
||||
const [rows] = await connection.execute('SELECT 1 as test');
|
||||
console.log('✅ 查询测试成功:', rows);
|
||||
|
||||
// 获取数据库信息
|
||||
const [dbInfo] = await connection.execute('SELECT DATABASE() as current_db, VERSION() as version');
|
||||
console.log('✅ 数据库信息:', dbInfo);
|
||||
|
||||
await connection.end();
|
||||
console.log('✅ 连接已关闭');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 数据库连接失败:');
|
||||
console.error('错误代码:', error.code);
|
||||
console.error('错误消息:', error.message);
|
||||
console.error('完整错误:', error);
|
||||
|
||||
// 提供一些常见错误的解决方案
|
||||
if (error.code === 'ECONNREFUSED') {
|
||||
console.log('\n💡 可能的解决方案:');
|
||||
console.log('1. 检查MySQL服务是否正在运行');
|
||||
console.log('2. 检查端口3306是否开放');
|
||||
console.log('3. 检查防火墙设置');
|
||||
} else if (error.code === 'ER_ACCESS_DENIED_ERROR') {
|
||||
console.log('\n💡 可能的解决方案:');
|
||||
console.log('1. 检查用户名和密码是否正确');
|
||||
console.log('2. 检查用户是否有远程访问权限');
|
||||
} else if (error.code === 'ER_BAD_DB_ERROR') {
|
||||
console.log('\n💡 可能的解决方案:');
|
||||
console.log('1. 检查数据库名称是否正确');
|
||||
console.log('2. 检查数据库是否存在');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testConnection();
|
||||
115
backend/tools/testing/test-devices-api.js
Normal file
115
backend/tools/testing/test-devices-api.js
Normal file
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* 测试设备API和数据导入功能
|
||||
*/
|
||||
|
||||
const { Device, Farm } = require('./models');
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
|
||||
async function testDevicesData() {
|
||||
try {
|
||||
console.log('=== 测试设备数据导入功能 ===\n');
|
||||
|
||||
// 1. 检查数据库中的设备数据
|
||||
console.log('1. 检查数据库中的设备数据:');
|
||||
const devices = await Device.findAll({
|
||||
include: [{
|
||||
model: Farm,
|
||||
as: 'farm',
|
||||
attributes: ['id', 'name', 'location']
|
||||
}],
|
||||
limit: 10
|
||||
});
|
||||
|
||||
console.log(` - 数据库中共有 ${await Device.count()} 个设备`);
|
||||
console.log(' - 前10个设备信息:');
|
||||
devices.forEach((device, index) => {
|
||||
console.log(` ${index + 1}. ID: ${device.id}, 名称: ${device.name}, 类型: ${device.type}, 状态: ${device.status}`);
|
||||
if (device.farm) {
|
||||
console.log(` 所属农场: ${device.farm.name}`);
|
||||
}
|
||||
});
|
||||
|
||||
// 2. 测试设备API响应格式
|
||||
console.log('\n2. 测试设备API响应格式:');
|
||||
const deviceController = require('./controllers/deviceController');
|
||||
|
||||
// 模拟API请求
|
||||
const mockReq = {
|
||||
query: { page: 1, limit: 5 }
|
||||
};
|
||||
|
||||
const mockRes = {
|
||||
json: (data) => {
|
||||
console.log(' - API响应格式正确');
|
||||
console.log(` - 返回设备数量: ${data.data ? data.data.length : 0}`);
|
||||
if (data.data && data.data.length > 0) {
|
||||
console.log(' - 第一个设备数据结构:');
|
||||
const firstDevice = data.data[0];
|
||||
console.log(` * ID: ${firstDevice.id}`);
|
||||
console.log(` * 名称: ${firstDevice.name}`);
|
||||
console.log(` * 类型: ${firstDevice.type}`);
|
||||
console.log(` * 状态: ${firstDevice.status}`);
|
||||
console.log(` * 农场: ${firstDevice.farm ? firstDevice.farm.name : '未关联'}`);
|
||||
console.log(` * 安装日期: ${firstDevice.installation_date}`);
|
||||
console.log(` * 最后维护: ${firstDevice.last_maintenance}`);
|
||||
}
|
||||
return data;
|
||||
},
|
||||
status: (code) => ({
|
||||
json: (data) => {
|
||||
console.log(` - API返回状态码: ${code}`);
|
||||
if (code !== 200) {
|
||||
console.log(` - 错误信息: ${data.message}`);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
await deviceController.getAllDevices(mockReq, mockRes);
|
||||
|
||||
// 3. 检查数据完整性
|
||||
console.log('\n3. 检查数据完整性:');
|
||||
const deviceTypes = await Device.findAll({
|
||||
attributes: ['type'],
|
||||
group: ['type']
|
||||
});
|
||||
|
||||
console.log(' - 设备类型统计:');
|
||||
for (const deviceType of deviceTypes) {
|
||||
const count = await Device.count({ where: { type: deviceType.type } });
|
||||
console.log(` * ${deviceType.type}: ${count} 个`);
|
||||
}
|
||||
|
||||
const statusStats = await Device.findAll({
|
||||
attributes: ['status'],
|
||||
group: ['status']
|
||||
});
|
||||
|
||||
console.log(' - 设备状态统计:');
|
||||
for (const status of statusStats) {
|
||||
const count = await Device.count({ where: { status: status.status } });
|
||||
console.log(` * ${status.status}: ${count} 个`);
|
||||
}
|
||||
|
||||
console.log('\n=== 设备数据导入功能测试完成 ===');
|
||||
console.log('✅ 数据库中的设备数据已成功准备好,可以在前端设备管理模块中正常显示');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 测试过程中出现错误:', error.message);
|
||||
console.error(error.stack);
|
||||
}
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
if (require.main === module) {
|
||||
testDevicesData().then(() => {
|
||||
process.exit(0);
|
||||
}).catch((error) => {
|
||||
console.error('测试失败:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { testDevicesData };
|
||||
193
backend/tools/testing/test-frontend-binding.js
Normal file
193
backend/tools/testing/test-frontend-binding.js
Normal file
@@ -0,0 +1,193 @@
|
||||
const { Farm } = require('./models');
|
||||
const { sequelize } = require('./config/database');
|
||||
|
||||
// 测试前端数据绑定的完整流程
|
||||
async function testFrontendBinding() {
|
||||
console.log('=== 前端数据绑定测试 ===\n');
|
||||
|
||||
try {
|
||||
// 1. 创建测试记录
|
||||
console.log('1. 创建测试记录...');
|
||||
const testFarm = await Farm.create({
|
||||
name: '绑定测试农场',
|
||||
type: '养殖场',
|
||||
contact: '测试负责人',
|
||||
phone: '13800138000',
|
||||
address: '测试地址',
|
||||
longitude: 106.2309,
|
||||
latitude: 38.4872,
|
||||
status: 'active'
|
||||
});
|
||||
|
||||
console.log('✓ 测试记录创建成功:', {
|
||||
id: testFarm.id,
|
||||
name: testFarm.name,
|
||||
location: testFarm.location
|
||||
});
|
||||
|
||||
// 2. 模拟API查询返回的数据格式
|
||||
console.log('\n2. 模拟API查询返回数据...');
|
||||
const apiResponse = await Farm.findByPk(testFarm.id, {
|
||||
attributes: ['id', 'name', 'type', 'contact', 'phone', 'address', 'location', 'status', 'created_at']
|
||||
});
|
||||
|
||||
console.log('✓ API返回数据格式:', {
|
||||
id: apiResponse.id,
|
||||
name: apiResponse.name,
|
||||
location: apiResponse.location,
|
||||
location_type: typeof apiResponse.location,
|
||||
location_structure: apiResponse.location ? Object.keys(apiResponse.location) : 'null'
|
||||
});
|
||||
|
||||
// 3. 模拟前端editFarm函数的数据解析
|
||||
console.log('\n3. 模拟前端editFarm数据解析...');
|
||||
const record = apiResponse.toJSON();
|
||||
|
||||
// 前端解析逻辑
|
||||
const longitude = record.location?.lng || undefined;
|
||||
const latitude = record.location?.lat || undefined;
|
||||
|
||||
console.log('✓ 前端解析结果:', {
|
||||
original_location: record.location,
|
||||
parsed_longitude: longitude,
|
||||
parsed_latitude: latitude,
|
||||
longitude_type: typeof longitude,
|
||||
latitude_type: typeof latitude
|
||||
});
|
||||
|
||||
// 4. 模拟前端formData绑定
|
||||
console.log('\n4. 模拟前端formData绑定...');
|
||||
const formData = {
|
||||
id: record.id,
|
||||
name: record.name,
|
||||
owner: record.contact || '',
|
||||
phone: record.phone,
|
||||
address: record.address,
|
||||
longitude: longitude,
|
||||
latitude: latitude,
|
||||
status: record.status
|
||||
};
|
||||
|
||||
console.log('✓ formData绑定结果:', {
|
||||
longitude: formData.longitude,
|
||||
latitude: formData.latitude,
|
||||
longitude_type: typeof formData.longitude,
|
||||
latitude_type: typeof formData.latitude
|
||||
});
|
||||
|
||||
// 5. 测试数据类型转换
|
||||
console.log('\n5. 测试数据类型转换...');
|
||||
|
||||
// 模拟用户输入修改
|
||||
const userInputLongitude = '106.2400';
|
||||
const userInputLatitude = '38.4900';
|
||||
|
||||
// 模拟前端输入框的数据处理
|
||||
const processedLongitude = parseFloat(userInputLongitude);
|
||||
const processedLatitude = parseFloat(userInputLatitude);
|
||||
|
||||
console.log('✓ 用户输入处理:', {
|
||||
input_longitude: userInputLongitude,
|
||||
input_latitude: userInputLatitude,
|
||||
processed_longitude: processedLongitude,
|
||||
processed_latitude: processedLatitude,
|
||||
processed_longitude_type: typeof processedLongitude,
|
||||
processed_latitude_type: typeof processedLatitude
|
||||
});
|
||||
|
||||
// 6. 模拟提交数据
|
||||
console.log('\n6. 模拟提交更新...');
|
||||
const submitData = {
|
||||
...formData,
|
||||
longitude: processedLongitude,
|
||||
latitude: processedLatitude
|
||||
};
|
||||
|
||||
// 更新记录
|
||||
await testFarm.update(submitData);
|
||||
|
||||
// 验证更新结果
|
||||
const updatedFarm = await Farm.findByPk(testFarm.id);
|
||||
console.log('✓ 更新后的数据:', {
|
||||
location: updatedFarm.location,
|
||||
location_lng: updatedFarm.location?.lng,
|
||||
location_lat: updatedFarm.location?.lat
|
||||
});
|
||||
|
||||
// 7. 测试边界情况
|
||||
console.log('\n7. 测试边界情况...');
|
||||
|
||||
// 测试undefined值
|
||||
const testUndefined = {
|
||||
longitude: undefined,
|
||||
latitude: undefined
|
||||
};
|
||||
|
||||
console.log('✓ undefined值测试:', {
|
||||
longitude_undefined: testUndefined.longitude,
|
||||
latitude_undefined: testUndefined.latitude,
|
||||
longitude_type: typeof testUndefined.longitude,
|
||||
latitude_type: typeof testUndefined.latitude
|
||||
});
|
||||
|
||||
// 测试null值
|
||||
const testNull = {
|
||||
longitude: null,
|
||||
latitude: null
|
||||
};
|
||||
|
||||
console.log('✓ null值测试:', {
|
||||
longitude_null: testNull.longitude,
|
||||
latitude_null: testNull.latitude,
|
||||
longitude_type: typeof testNull.longitude,
|
||||
latitude_type: typeof testNull.latitude
|
||||
});
|
||||
|
||||
// 测试空字符串
|
||||
const testEmpty = {
|
||||
longitude: '',
|
||||
latitude: ''
|
||||
};
|
||||
|
||||
console.log('✓ 空字符串测试:', {
|
||||
longitude_empty: testEmpty.longitude,
|
||||
latitude_empty: testEmpty.latitude,
|
||||
longitude_type: typeof testEmpty.longitude,
|
||||
latitude_type: typeof testEmpty.latitude
|
||||
});
|
||||
|
||||
// 8. 清理测试数据
|
||||
console.log('\n8. 清理测试数据...');
|
||||
await testFarm.destroy();
|
||||
console.log('✓ 测试数据已清理');
|
||||
|
||||
console.log('\n=== 前端数据绑定测试完成 ===');
|
||||
console.log('\n📋 测试总结:');
|
||||
console.log('1. ✅ 数据库存储格式正确 (JSON对象)');
|
||||
console.log('2. ✅ API返回数据格式正确');
|
||||
console.log('3. ✅ 前端数据解析逻辑正确');
|
||||
console.log('4. ✅ formData绑定逻辑正确');
|
||||
console.log('5. ✅ 数据类型转换正确');
|
||||
console.log('6. ✅ 更新操作正确');
|
||||
console.log('7. ✅ 边界情况处理正确');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 测试过程中出现错误:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
if (require.main === module) {
|
||||
testFrontendBinding()
|
||||
.then(() => {
|
||||
console.log('\n🎉 所有测试通过!');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('\n💥 测试失败:', error.message);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { testFrontendBinding };
|
||||
216
backend/tools/testing/test-location-data.js
Normal file
216
backend/tools/testing/test-location-data.js
Normal file
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
* 测试经纬度数据传递和存储
|
||||
* @file test-location-data.js
|
||||
* @description 验证经纬度输入值是否正确传递到数据库操作层
|
||||
*/
|
||||
|
||||
const { Farm } = require('./models');
|
||||
const { sequelize } = require('./config/database-simple');
|
||||
|
||||
// 测试数据
|
||||
const testData = {
|
||||
name: '测试养殖场_经纬度验证',
|
||||
owner: '测试负责人',
|
||||
phone: '13800138000',
|
||||
address: '测试地址',
|
||||
longitude: 106.123456,
|
||||
latitude: 38.654321,
|
||||
status: 'active'
|
||||
};
|
||||
|
||||
async function testLocationDataFlow() {
|
||||
try {
|
||||
console.log('开始测试经纬度数据传递流程...');
|
||||
|
||||
// 1. 测试创建养殖场时的经纬度处理
|
||||
console.log('\n1. 测试创建养殖场时的经纬度处理');
|
||||
console.log('输入数据:', {
|
||||
longitude: testData.longitude,
|
||||
latitude: testData.latitude
|
||||
});
|
||||
|
||||
// 模拟后端控制器的处理逻辑
|
||||
const { longitude, latitude } = testData;
|
||||
const location = {};
|
||||
if (longitude !== undefined && longitude !== null) {
|
||||
location.lng = parseFloat(longitude);
|
||||
}
|
||||
if (latitude !== undefined && latitude !== null) {
|
||||
location.lat = parseFloat(latitude);
|
||||
}
|
||||
|
||||
console.log('处理后的location对象:', location);
|
||||
|
||||
// 创建养殖场记录
|
||||
const farm = await Farm.create({
|
||||
name: testData.name,
|
||||
type: 'farm',
|
||||
location,
|
||||
address: testData.address,
|
||||
contact: testData.owner,
|
||||
phone: testData.phone,
|
||||
status: testData.status
|
||||
});
|
||||
|
||||
console.log('创建成功,数据库中的记录:');
|
||||
console.log('- ID:', farm.id);
|
||||
console.log('- Name:', farm.name);
|
||||
console.log('- Location:', JSON.stringify(farm.location));
|
||||
console.log('- Location.lng:', farm.location.lng);
|
||||
console.log('- Location.lat:', farm.location.lat);
|
||||
|
||||
// 2. 测试更新养殖场时的经纬度处理
|
||||
console.log('\n2. 测试更新养殖场时的经纬度处理');
|
||||
const newLongitude = 107.987654;
|
||||
const newLatitude = 39.123456;
|
||||
|
||||
console.log('新的输入数据:', {
|
||||
longitude: newLongitude,
|
||||
latitude: newLatitude
|
||||
});
|
||||
|
||||
// 模拟更新逻辑
|
||||
const updateLocation = farm.location || {};
|
||||
if (newLongitude !== undefined && newLongitude !== null) {
|
||||
updateLocation.lng = parseFloat(newLongitude);
|
||||
}
|
||||
if (newLatitude !== undefined && newLatitude !== null) {
|
||||
updateLocation.lat = parseFloat(newLatitude);
|
||||
}
|
||||
|
||||
console.log('处理后的location对象:', updateLocation);
|
||||
|
||||
await farm.update({
|
||||
location: updateLocation
|
||||
});
|
||||
|
||||
// 重新查询验证
|
||||
const updatedFarm = await Farm.findByPk(farm.id);
|
||||
console.log('更新后数据库中的记录:');
|
||||
console.log('- Location:', JSON.stringify(updatedFarm.location));
|
||||
console.log('- Location.lng:', updatedFarm.location.lng);
|
||||
console.log('- Location.lat:', updatedFarm.location.lat);
|
||||
|
||||
// 3. 测试数据类型验证
|
||||
console.log('\n3. 测试数据类型验证');
|
||||
console.log('原始输入类型:', typeof testData.longitude, typeof testData.latitude);
|
||||
console.log('parseFloat后类型:', typeof parseFloat(testData.longitude), typeof parseFloat(testData.latitude));
|
||||
console.log('数据库存储值类型:', typeof updatedFarm.location.lng, typeof updatedFarm.location.lat);
|
||||
|
||||
// 4. 测试边界值
|
||||
console.log('\n4. 测试边界值处理');
|
||||
const boundaryTests = [
|
||||
{ lng: -180, lat: -90, desc: '最小边界值' },
|
||||
{ lng: 180, lat: 90, desc: '最大边界值' },
|
||||
{ lng: 0, lat: 0, desc: '零值' },
|
||||
{ lng: 106.123456789, lat: 38.987654321, desc: '高精度值' }
|
||||
];
|
||||
|
||||
for (const test of boundaryTests) {
|
||||
const testLocation = {
|
||||
lng: parseFloat(test.lng),
|
||||
lat: parseFloat(test.lat)
|
||||
};
|
||||
|
||||
await farm.update({ location: testLocation });
|
||||
const verifyFarm = await Farm.findByPk(farm.id);
|
||||
|
||||
console.log(`${test.desc}:`);
|
||||
console.log(` 输入: lng=${test.lng}, lat=${test.lat}`);
|
||||
console.log(` 存储: lng=${verifyFarm.location.lng}, lat=${verifyFarm.location.lat}`);
|
||||
console.log(` 精度保持: ${test.lng === verifyFarm.location.lng && test.lat === verifyFarm.location.lat}`);
|
||||
}
|
||||
|
||||
// 5. 清理测试数据
|
||||
console.log('\n5. 清理测试数据');
|
||||
await farm.destroy();
|
||||
console.log('测试数据已清理');
|
||||
|
||||
console.log('\n✅ 经纬度数据传递流程测试完成');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 测试过程中发生错误:', error);
|
||||
console.error('错误详情:', error.message);
|
||||
if (error.sql) {
|
||||
console.error('SQL语句:', error.sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 测试空值处理
|
||||
async function testNullValues() {
|
||||
try {
|
||||
console.log('\n=== 测试空值处理 ===');
|
||||
|
||||
const testCases = [
|
||||
{ longitude: undefined, latitude: undefined, desc: 'undefined值' },
|
||||
{ longitude: null, latitude: null, desc: 'null值' },
|
||||
{ longitude: '', latitude: '', desc: '空字符串' },
|
||||
{ longitude: 106.123, latitude: undefined, desc: '仅经度有值' },
|
||||
{ longitude: undefined, latitude: 38.456, desc: '仅纬度有值' }
|
||||
];
|
||||
|
||||
for (let i = 0; i < testCases.length; i++) {
|
||||
const testCase = testCases[i];
|
||||
console.log(`\n测试案例 ${i + 1}: ${testCase.desc}`);
|
||||
console.log('输入:', { longitude: testCase.longitude, latitude: testCase.latitude });
|
||||
|
||||
// 模拟控制器处理逻辑
|
||||
const location = {};
|
||||
if (testCase.longitude !== undefined && testCase.longitude !== null && testCase.longitude !== '') {
|
||||
location.lng = parseFloat(testCase.longitude);
|
||||
}
|
||||
if (testCase.latitude !== undefined && testCase.latitude !== null && testCase.latitude !== '') {
|
||||
location.lat = parseFloat(testCase.latitude);
|
||||
}
|
||||
|
||||
console.log('处理后location:', location);
|
||||
|
||||
try {
|
||||
const farm = await Farm.create({
|
||||
name: `测试空值_${i + 1}`,
|
||||
type: 'farm',
|
||||
location,
|
||||
address: '测试地址',
|
||||
contact: '测试联系人',
|
||||
status: 'active'
|
||||
});
|
||||
|
||||
console.log('创建成功,存储的location:', JSON.stringify(farm.location));
|
||||
|
||||
// 清理
|
||||
await farm.destroy();
|
||||
} catch (error) {
|
||||
console.log('创建失败:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('空值测试失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 主函数
|
||||
async function main() {
|
||||
try {
|
||||
// 确保数据库连接
|
||||
await sequelize.authenticate();
|
||||
console.log('数据库连接成功');
|
||||
|
||||
await testLocationDataFlow();
|
||||
await testNullValues();
|
||||
|
||||
} catch (error) {
|
||||
console.error('测试失败:', error);
|
||||
} finally {
|
||||
await sequelize.close();
|
||||
console.log('\n数据库连接已关闭');
|
||||
}
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
if (require.main === module) {
|
||||
main();
|
||||
}
|
||||
|
||||
module.exports = { testLocationDataFlow, testNullValues };
|
||||
13
backend/tools/testing/test-simple-db.js
Normal file
13
backend/tools/testing/test-simple-db.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const { testConnection } = require('./config/database-simple');
|
||||
|
||||
async function test() {
|
||||
console.log('测试数据库连接...');
|
||||
const result = await testConnection();
|
||||
if (result) {
|
||||
console.log('✅ 数据库连接测试成功');
|
||||
} else {
|
||||
console.log('❌ 数据库连接测试失败');
|
||||
}
|
||||
}
|
||||
|
||||
test();
|
||||
251
backend/tools/testing/test-update-location.js
Normal file
251
backend/tools/testing/test-update-location.js
Normal file
@@ -0,0 +1,251 @@
|
||||
/**
|
||||
* 测试经纬度更新功能
|
||||
* @file test-update-location.js
|
||||
* @description 专门测试更新操作中经纬度数据的正确处理
|
||||
*/
|
||||
|
||||
const { Farm } = require('./models');
|
||||
const { sequelize } = require('./config/database-simple');
|
||||
|
||||
async function testLocationUpdate() {
|
||||
try {
|
||||
console.log('开始测试经纬度更新功能...');
|
||||
|
||||
// 1. 创建初始记录
|
||||
console.log('\n1. 创建初始记录');
|
||||
const initialData = {
|
||||
name: '更新测试养殖场',
|
||||
type: 'farm',
|
||||
location: { lng: 106.123456, lat: 38.654321 },
|
||||
address: '初始地址',
|
||||
contact: '初始联系人',
|
||||
phone: '13800138000',
|
||||
status: 'active'
|
||||
};
|
||||
|
||||
const farm = await Farm.create(initialData);
|
||||
console.log('初始记录创建成功:');
|
||||
console.log('- ID:', farm.id);
|
||||
console.log('- Location:', JSON.stringify(farm.location));
|
||||
|
||||
// 2. 测试更新经纬度
|
||||
console.log('\n2. 测试更新经纬度');
|
||||
const newLongitude = 107.987654;
|
||||
const newLatitude = 39.123456;
|
||||
|
||||
console.log('新的经纬度值:', { longitude: newLongitude, latitude: newLatitude });
|
||||
|
||||
// 模拟控制器的更新逻辑
|
||||
const location = { ...(farm.location || {}) };
|
||||
if (newLongitude !== undefined && newLongitude !== null) {
|
||||
location.lng = parseFloat(newLongitude);
|
||||
}
|
||||
if (newLatitude !== undefined && newLatitude !== null) {
|
||||
location.lat = parseFloat(newLatitude);
|
||||
}
|
||||
|
||||
console.log('处理后的location对象:', location);
|
||||
|
||||
// 执行更新
|
||||
await farm.update({
|
||||
location
|
||||
});
|
||||
|
||||
// 重新查询验证
|
||||
const updatedFarm = await Farm.findByPk(farm.id);
|
||||
console.log('\n更新后的记录:');
|
||||
console.log('- Location:', JSON.stringify(updatedFarm.location));
|
||||
console.log('- Location.lng:', updatedFarm.location.lng);
|
||||
console.log('- Location.lat:', updatedFarm.location.lat);
|
||||
|
||||
// 验证更新是否成功
|
||||
const updateSuccess = (
|
||||
updatedFarm.location.lng === newLongitude &&
|
||||
updatedFarm.location.lat === newLatitude
|
||||
);
|
||||
|
||||
console.log('\n更新验证结果:');
|
||||
console.log('- 期望经度:', newLongitude);
|
||||
console.log('- 实际经度:', updatedFarm.location.lng);
|
||||
console.log('- 期望纬度:', newLatitude);
|
||||
console.log('- 实际纬度:', updatedFarm.location.lat);
|
||||
console.log('- 更新成功:', updateSuccess ? '✅' : '❌');
|
||||
|
||||
// 3. 测试部分更新(只更新经度)
|
||||
console.log('\n3. 测试部分更新(只更新经度)');
|
||||
const partialLongitude = 108.555555;
|
||||
|
||||
const partialLocation = { ...(updatedFarm.location || {}) };
|
||||
if (partialLongitude !== undefined && partialLongitude !== null) {
|
||||
partialLocation.lng = parseFloat(partialLongitude);
|
||||
}
|
||||
// 注意:这里不更新纬度
|
||||
|
||||
await farm.update({ location: partialLocation });
|
||||
|
||||
const partialUpdatedFarm = await Farm.findByPk(farm.id);
|
||||
console.log('部分更新后的记录:');
|
||||
console.log('- Location:', JSON.stringify(partialUpdatedFarm.location));
|
||||
console.log('- 经度是否更新:', partialUpdatedFarm.location.lng === partialLongitude ? '✅' : '❌');
|
||||
console.log('- 纬度是否保持:', partialUpdatedFarm.location.lat === newLatitude ? '✅' : '❌');
|
||||
|
||||
// 4. 测试清空经纬度
|
||||
console.log('\n4. 测试清空经纬度');
|
||||
const emptyLocation = {};
|
||||
|
||||
await farm.update({ location: emptyLocation });
|
||||
|
||||
const emptyUpdatedFarm = await Farm.findByPk(farm.id);
|
||||
console.log('清空后的记录:');
|
||||
console.log('- Location:', JSON.stringify(emptyUpdatedFarm.location));
|
||||
console.log('- 是否为空对象:', Object.keys(emptyUpdatedFarm.location).length === 0 ? '✅' : '❌');
|
||||
|
||||
// 5. 清理测试数据
|
||||
console.log('\n5. 清理测试数据');
|
||||
await farm.destroy();
|
||||
console.log('测试数据已清理');
|
||||
|
||||
console.log('\n✅ 经纬度更新功能测试完成');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 测试过程中发生错误:', error);
|
||||
console.error('错误详情:', error.message);
|
||||
if (error.sql) {
|
||||
console.error('SQL语句:', error.sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 测试通过API接口的完整流程
|
||||
async function testAPIFlow() {
|
||||
try {
|
||||
console.log('\n=== 测试API接口流程 ===');
|
||||
|
||||
// 模拟前端发送的请求数据
|
||||
const createRequest = {
|
||||
body: {
|
||||
name: 'API测试养殖场',
|
||||
owner: 'API测试负责人',
|
||||
phone: '13900139000',
|
||||
address: 'API测试地址',
|
||||
longitude: 106.789123,
|
||||
latitude: 38.456789,
|
||||
status: 'active'
|
||||
}
|
||||
};
|
||||
|
||||
console.log('\n1. 模拟创建请求');
|
||||
console.log('请求数据:', {
|
||||
longitude: createRequest.body.longitude,
|
||||
latitude: createRequest.body.latitude
|
||||
});
|
||||
|
||||
// 模拟createFarm控制器逻辑
|
||||
const { name, owner, longitude, latitude, address, phone, status } = createRequest.body;
|
||||
|
||||
const location = {};
|
||||
if (longitude !== undefined && longitude !== null) {
|
||||
location.lng = parseFloat(longitude);
|
||||
}
|
||||
if (latitude !== undefined && latitude !== null) {
|
||||
location.lat = parseFloat(latitude);
|
||||
}
|
||||
|
||||
const farm = await Farm.create({
|
||||
name,
|
||||
type: 'farm',
|
||||
location,
|
||||
address,
|
||||
contact: owner,
|
||||
phone,
|
||||
status: status || 'active'
|
||||
});
|
||||
|
||||
console.log('创建结果:', {
|
||||
id: farm.id,
|
||||
location: farm.location
|
||||
});
|
||||
|
||||
// 模拟更新请求
|
||||
const updateRequest = {
|
||||
params: { id: farm.id },
|
||||
body: {
|
||||
name: farm.name,
|
||||
owner: farm.contact,
|
||||
phone: farm.phone,
|
||||
address: farm.address,
|
||||
longitude: 107.111222,
|
||||
latitude: 39.333444,
|
||||
status: farm.status
|
||||
}
|
||||
};
|
||||
|
||||
console.log('\n2. 模拟更新请求');
|
||||
console.log('更新数据:', {
|
||||
longitude: updateRequest.body.longitude,
|
||||
latitude: updateRequest.body.latitude
|
||||
});
|
||||
|
||||
// 模拟updateFarm控制器逻辑
|
||||
const updateData = updateRequest.body;
|
||||
const updateLocation = { ...(farm.location || {}) };
|
||||
if (updateData.longitude !== undefined && updateData.longitude !== null) {
|
||||
updateLocation.lng = parseFloat(updateData.longitude);
|
||||
}
|
||||
if (updateData.latitude !== undefined && updateData.latitude !== null) {
|
||||
updateLocation.lat = parseFloat(updateData.latitude);
|
||||
}
|
||||
|
||||
await farm.update({
|
||||
name: updateData.name,
|
||||
location: updateLocation,
|
||||
address: updateData.address,
|
||||
contact: updateData.owner,
|
||||
phone: updateData.phone,
|
||||
status: updateData.status
|
||||
});
|
||||
|
||||
// 验证更新结果
|
||||
const finalFarm = await Farm.findByPk(farm.id);
|
||||
console.log('更新结果:', {
|
||||
location: finalFarm.location
|
||||
});
|
||||
|
||||
const apiUpdateSuccess = (
|
||||
finalFarm.location.lng === updateData.longitude &&
|
||||
finalFarm.location.lat === updateData.latitude
|
||||
);
|
||||
|
||||
console.log('API流程验证:', apiUpdateSuccess ? '✅ 成功' : '❌ 失败');
|
||||
|
||||
// 清理
|
||||
await farm.destroy();
|
||||
|
||||
} catch (error) {
|
||||
console.error('API流程测试失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 主函数
|
||||
async function main() {
|
||||
try {
|
||||
await sequelize.authenticate();
|
||||
console.log('数据库连接成功');
|
||||
|
||||
await testLocationUpdate();
|
||||
await testAPIFlow();
|
||||
|
||||
} catch (error) {
|
||||
console.error('测试失败:', error);
|
||||
} finally {
|
||||
await sequelize.close();
|
||||
console.log('\n数据库连接已关闭');
|
||||
}
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
if (require.main === module) {
|
||||
main();
|
||||
}
|
||||
|
||||
module.exports = { testLocationUpdate, testAPIFlow };
|
||||
118
backend/tools/testing/test-users-api.js
Normal file
118
backend/tools/testing/test-users-api.js
Normal file
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* 测试用户管理API
|
||||
*/
|
||||
const axios = require('axios');
|
||||
|
||||
const API_BASE_URL = 'http://localhost:5350/api';
|
||||
|
||||
// 测试用户登录并获取token
|
||||
async function testLogin() {
|
||||
try {
|
||||
console.log('测试用户登录...');
|
||||
const response = await axios.post(`${API_BASE_URL}/auth/login`, {
|
||||
username: 'admin',
|
||||
password: '123456'
|
||||
});
|
||||
|
||||
if (response.data.success) {
|
||||
console.log('✓ 登录成功');
|
||||
console.log('Token:', response.data.token);
|
||||
return response.data.token;
|
||||
} else {
|
||||
console.log('✗ 登录失败:', response.data.message);
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('✗ 登录请求失败:', error.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 测试获取用户列表
|
||||
async function testGetUsers(token) {
|
||||
try {
|
||||
console.log('\n测试获取用户列表...');
|
||||
const response = await axios.get(`${API_BASE_URL}/users`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
});
|
||||
|
||||
if (response.data.success) {
|
||||
console.log('✓ 获取用户列表成功');
|
||||
console.log('用户数量:', response.data.data.length);
|
||||
response.data.data.forEach(user => {
|
||||
console.log(`- ${user.username} (${user.email}) - 角色: ${user.role}`);
|
||||
});
|
||||
return true;
|
||||
} else {
|
||||
console.log('✗ 获取用户列表失败:', response.data.message);
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('✗ 获取用户列表请求失败:', error.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 测试创建用户
|
||||
async function testCreateUser(token) {
|
||||
try {
|
||||
console.log('\n测试创建用户...');
|
||||
const newUser = {
|
||||
username: 'testuser_' + Date.now(),
|
||||
email: `test_${Date.now()}@example.com`,
|
||||
password: '123456',
|
||||
role: 'user'
|
||||
};
|
||||
|
||||
const response = await axios.post(`${API_BASE_URL}/users`, newUser, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (response.data.success) {
|
||||
console.log('✓ 创建用户成功');
|
||||
console.log('新用户ID:', response.data.data.id);
|
||||
return response.data.data.id;
|
||||
} else {
|
||||
console.log('✗ 创建用户失败:', response.data.message);
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('✗ 创建用户请求失败:', error.response?.data?.message || error.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 主测试函数
|
||||
async function runTests() {
|
||||
console.log('开始测试用户管理API...');
|
||||
console.log('=' .repeat(50));
|
||||
|
||||
// 1. 测试登录
|
||||
const token = await testLogin();
|
||||
if (!token) {
|
||||
console.log('\n测试终止:无法获取认证token');
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 测试获取用户列表
|
||||
await testGetUsers(token);
|
||||
|
||||
// 3. 测试创建用户
|
||||
const newUserId = await testCreateUser(token);
|
||||
|
||||
// 4. 再次获取用户列表,验证新用户是否创建成功
|
||||
if (newUserId) {
|
||||
console.log('\n验证新用户是否创建成功...');
|
||||
await testGetUsers(token);
|
||||
}
|
||||
|
||||
console.log('\n测试完成!');
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
runTests().catch(console.error);
|
||||
31
backend/tools/testing/test_bcrypt.js
Normal file
31
backend/tools/testing/test_bcrypt.js
Normal file
@@ -0,0 +1,31 @@
|
||||
const bcrypt = require('bcrypt');
|
||||
|
||||
async function testBcrypt() {
|
||||
try {
|
||||
const password = '123456';
|
||||
const storedHash = '$2b$10$yTdFpkw5MPU5OprOE7xWJ.arvesmRxKm2MpjwdbzNpEUIR2lq4C9S';
|
||||
|
||||
console.log('测试密码:', password);
|
||||
console.log('存储的哈希:', storedHash);
|
||||
|
||||
// 直接使用 bcrypt.compare
|
||||
const result1 = await bcrypt.compare(password, storedHash);
|
||||
console.log('bcrypt.compare 结果:', result1);
|
||||
|
||||
// 生成新的哈希并测试
|
||||
const newHash = await bcrypt.hash(password, 10);
|
||||
console.log('新生成的哈希:', newHash);
|
||||
|
||||
const result2 = await bcrypt.compare(password, newHash);
|
||||
console.log('新哈希验证结果:', result2);
|
||||
|
||||
// 测试同步方法
|
||||
const result3 = bcrypt.compareSync(password, storedHash);
|
||||
console.log('bcrypt.compareSync 结果:', result3);
|
||||
|
||||
} catch (error) {
|
||||
console.error('测试失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
testBcrypt();
|
||||
Reference in New Issue
Block a user