fix(接口测试): 接口列表批量复制指定版本的case时文件也会一同处理

接口列表批量复制指定版本的case时文件也会一同处理
This commit is contained in:
song-tianyang 2023-01-05 15:28:33 +08:00 committed by 建国
parent 245ab47458
commit 2971c6284e
8 changed files with 86 additions and 13 deletions

View File

@ -1,7 +1,6 @@
package io.metersphere.utils;
package io.metersphere.commons.utils;
import io.metersphere.api.dto.definition.BatchDataCopyRequest;
import io.metersphere.commons.utils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import java.util.ArrayList;

View File

@ -50,7 +50,6 @@ import io.metersphere.service.ext.ExtApiScheduleService;
import io.metersphere.service.ext.ExtFileAssociationService;
import io.metersphere.service.plan.TestPlanApiCaseService;
import io.metersphere.service.scenario.ApiScenarioService;
import io.metersphere.utils.BatchProcessingUtil;
import io.metersphere.xpack.api.service.ApiCaseBatchSyncService;
import io.metersphere.xpack.api.service.ApiDefinitionSyncService;
import io.metersphere.xpack.quota.service.QuotaService;
@ -2287,7 +2286,7 @@ public class ApiDefinitionService {
saveMockExpectList.forEach(mockExpectConfigBatchMapper::insert);
}
if (CollectionUtils.isNotEmpty(updateMockExpectList)) {
updateMockExpectList.forEach(mockExpectConfigBatchMapper::updateByPrimaryKey);
updateMockExpectList.forEach(mockExpectConfigBatchMapper::updateByPrimaryKeyWithBLOBs);
}
}
}
@ -2312,9 +2311,11 @@ public class ApiDefinitionService {
List<ApiTestCaseWithBLOBs> saveCaseList = new ArrayList<>();
List<ApiTestCaseWithBLOBs> updateCaseList = new ArrayList<>();
Map<String, Integer> lastCaseNumMap = new LinkedHashMap<>();
//用例文件关联关系数据 <要复制的用例ID 生成的用例ID>
Map<String, String> forceOverrideFileMap = new HashMap<>();
sourceApiCaseList.forEach(item -> {
String oldApiId = item.getApiDefinitionId();
String refId = sourceApiIdRefIdMap.get(oldApiId);
String sourceApiId = item.getApiDefinitionId();
String refId = sourceApiIdRefIdMap.get(sourceApiId);
if (StringUtils.isNotBlank(refId)) {
ApiDefinition api = refIdMap.get(refId);
if (api != null) {
@ -2349,15 +2350,22 @@ public class ApiDefinitionService {
newCase.setUpdateTime(timeStamp);
updateCaseList.add(newCase);
}
forceOverrideFileMap.put(item.getId(), newCase.getId());
//本地文件覆盖
FileUtils.forceOverrideBodyFiles(item.getId(), newCase.getId());
}
}
});
FileAssociationMapper batchFileAssociationMapper = batchSqlSession.getMapper(FileAssociationMapper.class);
extFileAssociationService.forceOverrideFileAssociation(forceOverrideFileMap, batchFileAssociationMapper);
ApiTestCaseMapper apiTestCaseBatchMapper = batchSqlSession.getMapper(ApiTestCaseMapper.class);
if (CollectionUtils.isNotEmpty(saveCaseList)) {
saveCaseList.forEach(apiTestCaseBatchMapper::insert);
}
if (CollectionUtils.isNotEmpty(updateCaseList)) {
updateCaseList.forEach(apiTestCaseBatchMapper::updateByPrimaryKey);
updateCaseList.forEach(apiTestCaseBatchMapper::updateByPrimaryKeyWithBLOBs);
}
}
}

View File

@ -5,10 +5,15 @@ import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.base.domain.FileAssociation;
import io.metersphere.base.domain.FileAssociationExample;
import io.metersphere.base.mapper.FileAssociationMapper;
import io.metersphere.commons.enums.FileAssociationTypeEnums;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.metadata.service.FileAssociationService;
import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.request.BodyFile;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
import org.springframework.stereotype.Service;
@ -16,6 +21,8 @@ import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
@Service
@ -76,4 +83,38 @@ public class ExtFileAssociationService extends FileAssociationService {
}
return files;
}
/**
* 强制覆盖文件关系
*
* @param overrideIdMap <来源ID - 强制覆盖的ID>
* @param batchProcessingMapper 批量处理Mapper 在该方法调用地方进行事务提交
*/
public void forceOverrideFileAssociation(Map<String, String> overrideIdMap, FileAssociationMapper batchProcessingMapper) {
if (MapUtils.isEmpty(overrideIdMap) || batchProcessingMapper == null) {
return;
}
//删除原来的数据
FileAssociationExample example = new FileAssociationExample();
example.createCriteria().andSourceIdIn(new ArrayList<>(overrideIdMap.values()));
batchProcessingMapper.deleteByExample(example);
example.clear();
example.createCriteria().andSourceIdIn(new ArrayList<>(overrideIdMap.keySet()));
List<FileAssociation> fileAssociationList = batchProcessingMapper.selectByExample(example);
List<FileAssociation> saveList = new ArrayList<>();
fileAssociationList.forEach(item -> {
String overrideId = overrideIdMap.get(item.getSourceId());
if (StringUtils.isNotBlank(overrideId)) {
FileAssociation overrideFileAssociation = new FileAssociation();
BeanUtils.copyBean(overrideFileAssociation, item);
overrideFileAssociation.setId(UUID.randomUUID().toString());
overrideFileAssociation.setSourceId(overrideId);
saveList.add(overrideFileAssociation);
}
});
saveList.forEach(batchProcessingMapper::insert);
}
}

View File

@ -12,17 +12,26 @@
<el-select v-model="versionId" size="small" :placeholder="$t('project.version.please_input_version')">
<el-option v-for="v in versionData" :key="v.id" :label="v.name" :value="v.id" />
</el-select>
<el-popover
placement="top-start"
width="200"
trigger="hover"
:content="$t('api_definition.copy_data_from_other_version_tips')">
<i class="el-icon-warning" slot="reference" style="color: #f56c6c; margin: 0 0 0 5px" />
</el-popover>
</el-row>
<el-row style="margin-top: 10px">
<el-checkbox v-model="selectCase" v-permission="['PROJECT_API_DEFINITION:READ+CREATE_CASE']">{{ $t('commons.api_case') }}</el-checkbox>
<el-checkbox v-model="selectCase" v-permission="['PROJECT_API_DEFINITION:READ+CREATE_CASE']">{{
$t('commons.api_case')
}}</el-checkbox>
<el-checkbox v-model="selectMock">{{ $t('commons.mock') }}</el-checkbox>
</el-row>
</div>
</el-row>
<template v-slot:footer>
<el-button type="primary" :loading="saving" size="small" @click="save" @keydown.enter.native.prevent>{{
$t('commons.save')
}}</el-button>
<el-button type="primary" :loading="saving" size="small" @click="save" @keydown.enter.native.prevent>{{
$t('commons.save')
}}</el-button>
</template>
</ms-edit-dialog>
</template>
@ -37,7 +46,7 @@ export default {
return {
loading: false,
visible: false,
saving:false,
saving: false,
versionId: '',
versionData: [],
selectCase: true,
@ -82,7 +91,7 @@ export default {
this.$error(this.$t('project.version.please_input_version'));
} else {
this.saving = true;
this.$emit('handleSave', this.versionId,this.selectCase,this.selectMock);
this.$emit('handleSave', this.versionId, this.selectCase, this.selectMock);
}
},
},

View File

@ -19,6 +19,8 @@ const message = {
default_value: 'Default value',
},
copy_data_from_other_version: 'Copy data from other version',
copy_data_from_other_version_tips:
'Use cases with the same name and mock expectations will be forcibly overwritten!',
body: {
json_format_error: 'JSON format error',
},

View File

@ -18,6 +18,7 @@ const message = {
default_value: '默认值',
},
copy_data_from_other_version: '复制版本数据',
copy_data_from_other_version_tips: '名称相同的用例和Mock期望会进行强制覆盖!',
body: {
json_format_error: 'JSON格式错误',
},

View File

@ -18,6 +18,7 @@ const message = {
default_value: '默認值',
},
copy_data_from_other_version: '複製版本數據',
copy_data_from_other_version_tips: '名稱相同的用例和Mock期望會進行強制覆蓋!',
body: {
json_format_error: 'JSON格式錯誤',
},

View File

@ -171,6 +171,18 @@ public class FileUtils {
}
}
/**
* 强制覆盖文件
*
* @param sourceId 源ID
* @param targetId 目标ID
*/
public static void forceOverrideBodyFiles(String sourceId, String targetId) {
//删除源文件
deleteBodyFiles(targetId);
copyBodyFiles(sourceId, targetId);
}
/**
* 复制文件夹(使用缓冲字节流)
*