APITest.vue 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151
  1. <template>
  2. <ElTabs class="tabs" v-model="activeTab">
  3. <ElTabPane label="接口测试" name="apitest">
  4. <ElTable :data="apitests" width="100%">
  5. <ElTableColumn
  6. prop="testId"
  7. label="ID"
  8. align="center"
  9. width="60">
  10. </ElTableColumn>
  11. <ElTableColumn
  12. prop="testName"
  13. label="测试名称"
  14. align="center"
  15. width="170">
  16. </ElTableColumn>
  17. <ElTableColumn
  18. prop="username"
  19. label="创建者"
  20. align="center"
  21. width="170">
  22. </ElTableColumn>
  23. <ElTableColumn
  24. prop="createTime"
  25. label="创建时间"
  26. align="center"
  27. width="160">
  28. </ElTableColumn>
  29. <ElTableColumn
  30. label="详情"
  31. align="center">
  32. <template #default="scope">
  33. <ElButton
  34. @click="handleClick('latest', scope.row.testId)"
  35. type="text"
  36. size="small">最近执行详情</ElButton>
  37. <ElButton @click="handleClick('detail', scope.row.testId)" type="text" size="small">测试任务详情</ElButton>
  38. </template>
  39. </ElTableColumn>
  40. <ElTableColumn
  41. align="center">
  42. <template #header>
  43. <span>操作</span>
  44. <ElButton @click="handleClick('create')" type="text" class="add-button">新建</ElButton>
  45. </template>
  46. <template #default="scope">
  47. <ElButton @click="handleClick('trigger', scope.row.testId)" type="text" size="small">触发</ElButton>
  48. <ElButton @click="handleClick('delete', scope.row.testId)" type="text" size="small">删除</ElButton>
  49. </template>
  50. </ElTableColumn>
  51. </ElTable>
  52. <!-- 测试任务详情 -->
  53. <ElDrawer
  54. v-model="detailDrawer"
  55. :size="800">
  56. <template #title>
  57. <el-row class="entry-row">
  58. <el-col :span="2">
  59. <div class="node-type">测试</div>
  60. </el-col>
  61. <el-col :span="2">
  62. <template class="entry-row">
  63. <span>#{{detailAPIInfo.testId}}</span>
  64. </template>
  65. </el-col>
  66. <el-col :span="4">
  67. <template class="entry-row">
  68. <span>{{detailAPIInfo.testName}}</span>
  69. </template>
  70. </el-col>
  71. </el-row>
  72. </template>
  73. <template #default>
  74. <el-row type="flex" justify="center">
  75. <el-col :span="20">
  76. <el-tabs
  77. v-model="detailTab">
  78. <el-tab-pane label="基本信息" name="basic_info">
  79. <el-row class="entry-row" style="margin-top: 15px">
  80. <el-col :span="4">
  81. <h4>url: </h4>
  82. </el-col>
  83. <el-col :span="18">
  84. <div>{{detailAPIInfo.url}}</div>
  85. </el-col>
  86. </el-row>
  87. <el-row class="entry-row" style="margin-top: 15px">
  88. <el-col :span="4">
  89. <h4>params: </h4>
  90. </el-col>
  91. <el-col :span="18">
  92. <div>
  93. <vue-json-editor
  94. :height="'400px'"
  95. v-model="detailAPIInfo.params"
  96. :show-btns="false"
  97. :mode="'code'"
  98. :modes="['code']"
  99. lang="zh"></vue-json-editor>
  100. </div>
  101. </el-col>
  102. </el-row>
  103. <el-row class="entry-row" style="margin-top: 15px">
  104. <el-col :span="4">
  105. <h4>method: </h4>
  106. </el-col>
  107. <el-col :span="18">
  108. <div>{{detailAPIInfo.method}}</div>
  109. </el-col>
  110. </el-row>
  111. <el-row class="entry-row" style="margin-top: 15px">
  112. <el-col :span="4">
  113. <h4>qps: </h4>
  114. </el-col>
  115. <el-col :span="18">
  116. <div>{{detailAPIInfo.qps}}</div>
  117. </el-col>
  118. </el-row>
  119. </el-tab-pane>
  120. <el-tab-pane label="执行历史" name="execute_history">
  121. <h5>注:Max、Min、Average的单位均为ms</h5>
  122. <el-table :data="testResults" width="100%">
  123. <el-table-column
  124. prop="id"
  125. label="ID"
  126. align="center"
  127. width="60">
  128. </el-table-column>
  129. <el-table-column
  130. prop="executeTime"
  131. label="执行时间"
  132. align="center">
  133. </el-table-column>
  134. <el-table-column
  135. prop="success"
  136. label="成功"
  137. align="center">
  138. </el-table-column>
  139. <el-table-column
  140. prop="failure"
  141. label="失败"
  142. align="center">
  143. <template #default="scope">
  144. {{scope.row.failure}}
  145. <span v-if="scope.row.success === 0">
  146. <i class="el-icon-warning" title="url/参数有误或者服务器出错!"></i>
  147. </span>
  148. </template>
  149. </el-table-column>
  150. <el-table-column
  151. prop="maxTime"
  152. label="Max"
  153. align="center">
  154. </el-table-column>
  155. <el-table-column
  156. prop="minTime"
  157. label="Min"
  158. align="center">
  159. </el-table-column>
  160. <el-table-column
  161. prop="averageTime"
  162. label="Average"
  163. align="center">
  164. </el-table-column>
  165. </el-table>
  166. </el-tab-pane>
  167. <el-tab-pane label="自动化测试结果" name="autoTest_result">
  168. <h5>注:Max、Min、Average的单位均为ms</h5>
  169. <ElTable :data="autoTestResult" width="100%">
  170. <ElTableColumn
  171. prop="id"
  172. label="ID"
  173. align="center"
  174. width="60">
  175. </ElTableColumn>
  176. <!-- <ElTableColumn-->
  177. <!-- prop="testId"-->
  178. <!-- label="所属测试ID"-->
  179. <!-- align="center"-->
  180. <!-- width="100">-->
  181. <!-- </ElTableColumn>-->
  182. <ElTableColumn
  183. prop="executeTime"
  184. label="执行时间"
  185. align="center"
  186. width="100">
  187. </ElTableColumn>
  188. <!-- <ElTableColumn-->
  189. <!-- prop="timeList"-->
  190. <!-- label="执行时间列表"-->
  191. <!-- align="center">-->
  192. <!-- </ElTableColumn>-->
  193. <ElTableColumn
  194. prop="success"
  195. label="成功"
  196. align="center"
  197. width="100">
  198. </ElTableColumn>
  199. <ElTableColumn
  200. prop="failure"
  201. label="失败"
  202. align="center"
  203. width="100">
  204. </ElTableColumn>
  205. <ElTableColumn
  206. prop="maxTime"
  207. label="Max"
  208. align="center"
  209. width="100">
  210. </ElTableColumn>
  211. <ElTableColumn
  212. prop="minTime"
  213. label="Min"
  214. align="center"
  215. width="100">
  216. </ElTableColumn>
  217. <ElTableColumn
  218. prop="averageTime"
  219. label="Average"
  220. align="center"
  221. width="100">
  222. </ElTableColumn>
  223. <ElTableColumn
  224. prop="pipelineRecordId"
  225. label="流水线ID"
  226. align="center"
  227. width="100">
  228. </ElTableColumn>
  229. </ElTable>
  230. </el-tab-pane>
  231. </el-tabs>
  232. </el-col>
  233. </el-row>
  234. </template>
  235. </ElDrawer>
  236. <!-- 新建测试任务 -->
  237. <el-dialog
  238. v-model="showAPITestCreateModel"
  239. width="600px"
  240. :before-close="(done) => {$refs['createAPITestForm'].resetFields();done();}"
  241. >
  242. <template #title>创建测试任务</template>
  243. <el-form
  244. :model="createAPITestForm"
  245. :rules="rules"
  246. ref="createAPITestForm"
  247. label-position="right"
  248. label-width="100px"
  249. label-suffix=":"
  250. class="create-APITest-form">
  251. <el-form-item label="测试名称" prop="testName" required>
  252. <el-input v-model="createAPITestForm.testName" placeholder="请输入接口测试的名称"></el-input>
  253. </el-form-item>
  254. <el-form-item label="待测URL" prop="url" required>
  255. <el-input v-model="createAPITestForm.url" placeholder="请输入待测试的URL"></el-input>
  256. </el-form-item>
  257. <el-form-item label="参数" prop="params">
  258. <div>
  259. <vue-json-editor
  260. :height="'400px'"
  261. v-model="createAPITestForm.params"
  262. :show-btns="false"
  263. mode="code"
  264. :modes="['code']"
  265. lang="zh"
  266. @json-change="onJsonChange"
  267. @json-save="onJsonSave"
  268. @has-error="onError"
  269. ></vue-json-editor>
  270. <span v-if="!jsonValid" style="color: #F56C6C; font-size: 12px">JSON is invalid.</span>
  271. </div>
  272. </el-form-item>
  273. <el-form-item label="方法" prop="method" required>
  274. <ElSelect v-model="createAPITestForm.method" placeholder="请选择待测URL的方法">
  275. <ElOption
  276. v-for="(method, index) in methodList"
  277. :key="index" :label="method"
  278. :value="method">
  279. </ElOption>
  280. </ElSelect>
  281. </el-form-item>
  282. <el-form-item label="并发数" prop="qps" required="">
  283. <el-input v-model="createAPITestForm.qps" placeholder="请输入并发数(10的倍数)"></el-input>
  284. </el-form-item>
  285. </el-form>
  286. <template #footer>
  287. <span class="dialog-footer">
  288. <el-button type="primary" @click="handleAPITestCreateConfirm">确 定</el-button>
  289. </span>
  290. </template>
  291. </el-dialog>
  292. <ElDrawer
  293. v-model="latestDrawer"
  294. :size="750">
  295. <template #title>
  296. <el-row class="entry-row">
  297. <el-col :span="3">
  298. <div class="node-type">测试结果</div>
  299. </el-col>
  300. <el-col :span="2">
  301. <template class="entry-row">
  302. <span>#{{latestResultInfo.id}}</span>
  303. </template>
  304. </el-col>
  305. </el-row>
  306. </template>
  307. <template #default>
  308. <el-row type="flex" justify="center">
  309. <el-col :span="22">
  310. <el-row class="entry-row" style="margin-top: 15px">
  311. <el-col :span="5">
  312. <h4>执行时间:</h4>
  313. </el-col>
  314. <el-col :span="18">
  315. <div>{{latestResultInfo.executeTime}}</div>
  316. </el-col>
  317. </el-row>
  318. <el-row class="entry-row" style="margin-top: 15px">
  319. <el-col :span="5">
  320. <h4>成功:</h4>
  321. </el-col>
  322. <el-col :span="18">
  323. <div>{{latestResultInfo.success}}</div>
  324. </el-col>
  325. </el-row>
  326. <el-row class="entry-row" style="margin-top: 15px">
  327. <el-col :span="5">
  328. <h4>失败:</h4>
  329. </el-col>
  330. <el-col :span="18">
  331. <div>
  332. {{latestResultInfo.failure}}
  333. <span v-if="latestResultInfo.success === 0" style="color: red">(url/参数输入有误或者服务器出错!)</span>
  334. </div>
  335. </el-col>
  336. </el-row>
  337. <el-row class="entry-row" style="margin-top: 15px">
  338. <el-col :span="5">
  339. <h4>maxTime:</h4>
  340. </el-col>
  341. <el-col :span="18">
  342. <div>{{latestResultInfo.maxTime}} ms</div>
  343. </el-col>
  344. </el-row>
  345. <el-row class="entry-row" style="margin-top: 15px">
  346. <el-col :span="5">
  347. <h4>minTime:</h4>
  348. </el-col>
  349. <el-col :span="18">
  350. <div>{{latestResultInfo.minTime}} ms</div>
  351. </el-col>
  352. </el-row>
  353. <el-row class="entry-row" style="margin-top: 15px">
  354. <el-col :span="5">
  355. <h4>averageTime:</h4>
  356. </el-col>
  357. <el-col :span="18">
  358. <div>{{latestResultInfo.averageTime}} ms</div>
  359. </el-col>
  360. </el-row>
  361. </el-col>
  362. </el-row>
  363. <el-row>
  364. <el-col :span="12">
  365. <div id="chart1" style="height: 500px; width: 350px"></div>
  366. </el-col>
  367. <el-col :span="12">
  368. <div id="chart2" style="height: 500px; width: 350px"></div>
  369. </el-col>
  370. </el-row>
  371. </template>
  372. </ElDrawer>
  373. </ElTabPane>
  374. <ElTabPane label="黑盒测试" name="testCases">
  375. <ElTable :data="testcases" width="100%">
  376. <ElTableColumn
  377. prop="id"
  378. label="ID"
  379. align="center"
  380. width="60">
  381. </ElTableColumn>
  382. <ElTableColumn
  383. prop="title"
  384. label="标题"
  385. align="center">
  386. </ElTableColumn>
  387. <ElTableColumn
  388. prop="taskId"
  389. label="关联的任务ID"
  390. align="center"
  391. width="150">
  392. </ElTableColumn>
  393. <ElTableColumn
  394. prop="pass"
  395. label="执行状态"
  396. align="center"
  397. width="100"
  398. :filters="[{ text: '进行中', value: false }, { text: '已完成', value: true }]"
  399. :filter-method="(value, row) => {
  400. return row.pass === value;
  401. }"
  402. filter-placement="bottom-end">
  403. <template #default="scope">
  404. <template v-if="scope.row.pass === false">
  405. <ElTag>进行中<i class="el-icon-loading"></i></ElTag>
  406. </template>
  407. <template v-else-if="scope.row.pass === true">
  408. <ElTag type="success">已完成</ElTag>
  409. </template>
  410. <template v-else>
  411. <ElTag type="warning">未知状态</ElTag>
  412. </template>
  413. </template>
  414. </ElTableColumn>
  415. <ElTableColumn
  416. label="详情"
  417. align="center"
  418. width="120">
  419. <template #default="scope">
  420. <ElButton
  421. @click="handleTestCasesClick('steps', scope.row.id)"
  422. type="text"
  423. size="small">测试用例步骤列表</ElButton>
  424. </template>
  425. </ElTableColumn>
  426. <ElTableColumn
  427. align="center">
  428. <template #header>
  429. <span>操作</span>
  430. <ElButton
  431. @click="handleTestCasesClick('latest', 0)"
  432. type="text"
  433. class="add-button">部署的历史记录</ElButton>
  434. <ElButton @click="handleTestCasesClick('create')" type="text" class="add-button">新建</ElButton>
  435. </template>
  436. <template #default="scope">
  437. <ElButton v-if="scope.row.pass === false" @click="handleTestCasesClick('finish', scope.row.id)" type="text" size="small">
  438. 完成测试
  439. </ElButton>
  440. <ElButton v-else @click="handleTestCasesClick('finish', scope.row.id)" type="text" size="small" disabled>完成测试</ElButton>
  441. <ElButton v-if="scope.row.pass === true" @click="handleTestCasesClick('reopen', scope.row.id)" type="text" size="small">
  442. 重新开放测试
  443. </ElButton>
  444. <ElButton v-else @click="handleTestCasesClick('reopen', scope.row.id)" type="text" size="small" disabled>重新开放测试</ElButton>
  445. <ElButton @click="handleTestCasesClick('edit', scope.row.id)" type="text" size="small">编辑</ElButton>
  446. <ElButton @click="handleTestCasesClick('delete', scope.row.id)" type="text" size="small">删除</ElButton>
  447. </template>
  448. </ElTableColumn>
  449. </ElTable>
  450. <!-- 部署的历史记录 -->
  451. <ElDrawer
  452. v-model="deployHistoryDrawer"
  453. :size="650">
  454. <template #title>
  455. <el-row class="entry-row">
  456. <el-col :span="3">
  457. <div class="node-type">项目</div>
  458. </el-col>
  459. <el-col :span="2">
  460. <template class="entry-row">
  461. <span>#{{currentProjectId}}</span>
  462. </template>
  463. </el-col>
  464. </el-row>
  465. </template>
  466. <template #default>
  467. <el-row type="flex" justify="center">
  468. <el-col :span="20">
  469. <el-table :data="deployHistoryInfo" width="100%">
  470. <el-table-column
  471. prop="id"
  472. label="ID"
  473. align="center"
  474. width="60">
  475. </el-table-column>
  476. <el-table-column
  477. prop="timestamp"
  478. label="部署时间"
  479. align="center"
  480. width="150">
  481. </el-table-column>
  482. <el-table-column
  483. prop="operationType"
  484. label="操作类型"
  485. align="center">
  486. </el-table-column>
  487. <el-table-column
  488. prop="pipelineRecordId"
  489. label="流水线ID"
  490. align="center"
  491. width="80">
  492. </el-table-column>
  493. </el-table>
  494. </el-col>
  495. </el-row>
  496. </template>
  497. </ElDrawer>
  498. <!-- 新建测试用例 -->
  499. <el-dialog
  500. v-model="showTestCaseCreateModel"
  501. width="600px"
  502. :before-close="(done) => {$refs['createTestCaseForm'].resetFields();done();}"
  503. destroy-on-close>
  504. <template #title>创建测试用例</template>
  505. <el-form
  506. :model="createTestCaseForm"
  507. ref="createTestCaseForm"
  508. label-position="right"
  509. label-width="70px"
  510. label-suffix=":"
  511. class="create-APITest-form">
  512. <el-form-item label="title" prop="title">
  513. <el-input
  514. v-model="createTestCaseForm.title"
  515. type="textarea"
  516. :rows="5"
  517. placeholder="请输入测试用例的标题"></el-input>
  518. </el-form-item>
  519. <el-form-item label="taskId" prop="taskId">
  520. <el-select v-model="createTestCaseForm.taskId">
  521. <el-option
  522. v-for="item in taskIdList"
  523. :key="item"
  524. :value="item"></el-option>
  525. </el-select>
  526. </el-form-item>
  527. </el-form>
  528. <template #footer>
  529. <span class="dialog-footer">
  530. <el-button type="primary" @click="handleTestCaseCreateConfirm">确 定</el-button>
  531. </span>
  532. </template>
  533. </el-dialog>
  534. <!-- 测试用例步骤详情 -->
  535. <ElDrawer
  536. v-model="stepsDrawer"
  537. :size="800">
  538. <template #title>
  539. <el-row class="entry-row">
  540. <el-col :span="3">
  541. <div class="node-type">测试用例</div>
  542. </el-col>
  543. <el-col :span="2">
  544. <template class="entry-row">
  545. <span>#{{detailTestCaseInfo.id}}</span>
  546. </template>
  547. </el-col>
  548. <el-col :span="6">
  549. <div>
  550. <ElButton @click="handleSteps('create', detailTestCaseInfo.id, 0)" type="text" class="add-button">新建测试用例步骤</ElButton>
  551. </div>
  552. </el-col>
  553. </el-row>
  554. </template>
  555. <template #default>
  556. <el-row type="flex" justify="center">
  557. <el-col :span="20">
  558. <el-row class="entry-row" style="margin-top: 15px; margin-bottom: 30px">
  559. <el-col :span="2">
  560. <h4>标题: </h4>
  561. </el-col>
  562. <el-col :span="18">
  563. <div>{{detailTestCaseInfo.title}}</div>
  564. </el-col>
  565. </el-row>
  566. <el-tabs v-model="stepsTab">
  567. <el-tab-pane label="测试用例步骤" name="steps">
  568. <el-table :data="detailStepsInfo" width="100%">
  569. <el-table-column
  570. prop="id"
  571. label="ID"
  572. align="center"
  573. width="60">
  574. </el-table-column>
  575. <el-table-column
  576. prop="description"
  577. label="描述"
  578. align="center">
  579. </el-table-column>
  580. <el-table-column
  581. prop="expectation"
  582. label="预期输出"
  583. align="center">
  584. </el-table-column>
  585. <el-table-column
  586. prop="state"
  587. label="状态"
  588. align="center">
  589. </el-table-column>
  590. <el-table-column
  591. align="center">
  592. <template #header>
  593. <span>操作</span>
  594. </template>
  595. <template #default="scope">
  596. <ElButton @click="handleSteps('update', scope.row.testCaseId, scope.row.id)" type="text" size="small">更新</ElButton>
  597. <ElButton
  598. @click="handleSteps('updateState', scope.row.testCaseId, scope.row.id)" type="text" size="small">修改状态</ElButton>
  599. <ElButton @click="handleSteps('delete', scope.row.testCaseId, scope.row.id)" type="text" size="small">删除</ElButton>
  600. </template>
  601. </el-table-column>
  602. </el-table>
  603. </el-tab-pane>
  604. </el-tabs>
  605. </el-col>
  606. </el-row>
  607. </template>
  608. </ElDrawer>
  609. <!-- 修改测试用例步骤 -->
  610. <el-dialog
  611. v-model="showUpdateStepModel"
  612. width="600px"
  613. :before-close="(done) => {$refs['updateStepForm'].resetFields();done();}"
  614. destroy-on-close>
  615. <template #title>修改测试用例步骤</template>
  616. <el-form
  617. :model="updateStepForm"
  618. ref="updateStepForm"
  619. label-position="right"
  620. label-width="100px"
  621. label-suffix=":">
  622. <el-form-item label="id" prop="id">
  623. <el-input
  624. v-model="updateStepForm.id"
  625. disabled>
  626. </el-input>
  627. </el-form-item>
  628. <el-form-item label="description" prop="description">
  629. <el-input
  630. v-model="updateStepForm.description"
  631. type="textarea"
  632. :rows="4">
  633. </el-input>
  634. </el-form-item>
  635. <el-form-item label="expectation" prop="expectation">
  636. <el-input
  637. v-model="updateStepForm.expectation"
  638. type="textarea"
  639. :rows="4">
  640. </el-input>
  641. </el-form-item>
  642. </el-form>
  643. <template #footer>
  644. <span class="dialog-footer">
  645. <el-button type="primary" @click="handleStepUpdateConfirm">确 定</el-button>
  646. </span>
  647. </template>
  648. </el-dialog>
  649. <!-- 修改测试用例步骤state -->
  650. <el-dialog
  651. v-model="showUpdateStepStateModel"
  652. width="600px"
  653. :before-close="(done) => {$refs['updateStepForm'].resetFields();done();}"
  654. destroy-on-close>
  655. <template #title>修改测试用例步骤状态</template>
  656. <el-form
  657. :model="updateStepForm"
  658. ref="updateStepForm"
  659. label-position="right"
  660. label-width="100px"
  661. label-suffix=":">
  662. <el-form-item label="id" prop="id">
  663. <el-input
  664. v-model="updateStepForm.id"
  665. disabled>
  666. </el-input>
  667. </el-form-item>
  668. <el-form-item label="state" prop="state">
  669. <ElSelect
  670. v-model="updateStepForm.state">
  671. <ElOption
  672. v-for="(state, index) in stateList"
  673. :key="index"
  674. :label="state"
  675. :value="state">
  676. </ElOption>
  677. </ElSelect>
  678. </el-form-item>
  679. </el-form>
  680. <template #footer>
  681. <span class="dialog-footer">
  682. <el-button type="primary" @click="handleStepUpdateStateConfirm">确 定</el-button>
  683. </span>
  684. </template>
  685. </el-dialog>
  686. <!-- 修改测试用例title -->
  687. <el-dialog
  688. v-model="showEditTestCaseModel"
  689. width="600px"
  690. :before-close="(done) => {$refs['detailTestCaseInfo'].resetFields();done();}"
  691. destroy-on-close>
  692. <template #title>编辑测试用例标题</template>
  693. <el-form
  694. :model="detailTestCaseInfo"
  695. ref="detailTestCaseInfo"
  696. label-position="right"
  697. label-width="100px"
  698. label-suffix=":">
  699. <el-form-item label="id" prop="id">
  700. <el-input
  701. v-model="detailTestCaseInfo.id"
  702. disabled>
  703. </el-input>
  704. </el-form-item>
  705. <el-form-item label="title" prop="title">
  706. <el-input
  707. v-model="detailTestCaseInfo.title"
  708. type="textarea"
  709. :rows="4">
  710. </el-input>
  711. </el-form-item>
  712. </el-form>
  713. <template #footer>
  714. <span class="dialog-footer">
  715. <el-button type="primary" @click="handleTestCaseEditConfirm">确 定</el-button>
  716. </span>
  717. </template>
  718. </el-dialog>
  719. </ElTabPane>
  720. </ElTabs>
  721. </template>
  722. <script>
  723. import vueJsonEditor from 'vue-json-editor';
  724. import { APITestAPI, FuncTestAPI, AutoTestAPI } from '@/api';
  725. import { ElMessage } from 'element-plus';
  726. import * as echarts from 'echarts';
  727. export default {
  728. components: {
  729. vueJsonEditor,
  730. },
  731. data() {
  732. return {
  733. currentProjectId: -1,
  734. activeTab: 'apitest',
  735. apitests: [],
  736. detailDrawer: false,
  737. detailAPIInfo: [],
  738. detailTab: 'basic_info',
  739. testResults: [],
  740. showAPITestCreateModel: false,
  741. createAPITestForm: {
  742. testName: '',
  743. url: '',
  744. params: {},
  745. method: '',
  746. qps: '',
  747. createTime: '',
  748. username: '',
  749. },
  750. methodList: ['GET', 'POST'],
  751. jsonValid: true,
  752. latestDrawer: false,
  753. latestResultInfo: {},
  754. qps: 0,
  755. timer: null,
  756. testcases: [],
  757. showTestCaseCreateModel: false,
  758. createTestCaseForm: {
  759. projectId: -1,
  760. title: '',
  761. taskId: '',
  762. },
  763. stepsDrawer: false,
  764. detailTestCaseInfo: [],
  765. stepsTab: 'steps',
  766. detailStepsInfo: {},
  767. showUpdateStepModel: false,
  768. updateStepForm: {},
  769. showEditTestCaseModel: false,
  770. stateList: ['待测试', '已测试', '出现bug'],
  771. showUpdateStepStateModel: false,
  772. deployHistoryInfo: {},
  773. deployHistoryDrawer: false,
  774. autoTestResult: [],
  775. taskIdList: [],
  776. };
  777. },
  778. async mounted() {
  779. this.currentProjectId = this.$store.state.workspace.currentProjectId;
  780. this.apitests = await APITestAPI.getAPITestInfosByProjectId(this.$store.state.workspace.currentProjectId);
  781. this.testcases = await FuncTestAPI.getTestCases(this.$store.state.workspace.currentProjectId);
  782. this.taskIdList = await FuncTestAPI.getTreeIdList(this.$store.state.workspace.currentProjectId);
  783. // this.autoTestResult = await AutoTestAPI.getAutoTestResultByProjectId(this.$store.state.workspace.currentProjectId);
  784. },
  785. methods: {
  786. async handleClick(action, id) {
  787. switch (action) {
  788. case 'create': {
  789. this.showAPITestCreateModel = true;
  790. break;
  791. }
  792. case 'latest': {
  793. this.latestResultInfo = await APITestAPI.getLatestResultByTestId(id);
  794. if (this.latestResultInfo === null) {
  795. ElMessage.error('还未执行!');
  796. } else {
  797. this.apitests.forEach((item) => {
  798. if (item.testId === id) {
  799. this.qps = item.qps;
  800. }
  801. });
  802. this.latestDrawer = true;
  803. const that = this;
  804. this.timer = setTimeout(() => {
  805. this.$nextTick(() => {
  806. that.initChart1();
  807. that.initChart2();
  808. });
  809. }, 1500);
  810. }
  811. break;
  812. }
  813. case 'detail': {
  814. this.apitests.forEach((item) => {
  815. if (item.testId === id) {
  816. this.detailAPIInfo = item;
  817. }
  818. });
  819. this.testResults = await APITestAPI.getAPITestResultByTestId(id);
  820. this.autoTestResult = await AutoTestAPI.getAutoTestResultByProjectId(this.$store.state.workspace.currentProjectId, id);
  821. console.log(this.autoTestResult);
  822. this.detailDrawer = true;
  823. break;
  824. }
  825. case 'trigger': {
  826. await APITestAPI.executeAPITestByTestId(id);
  827. this.timer = setTimeout(() => {
  828. this.$nextTick(() => {
  829. ElMessage.success('执行成功!');
  830. });
  831. }, 3000);
  832. break;
  833. }
  834. case 'delete': {
  835. await APITestAPI.deleteAPITestByTestId(id);
  836. ElMessage.success('删除成功!');
  837. this.apitests = await APITestAPI.getAPITestInfosByProjectId(this.$store.state.workspace.currentProjectId);
  838. break;
  839. }
  840. default: {
  841. console.warn('Unknown type of action.');
  842. }
  843. }
  844. },
  845. onJsonChange(value) {
  846. this.onJsonSave(value);
  847. },
  848. onJsonSave(value) {
  849. this.createAPITestForm.params = value;
  850. this.jsonValid = true;
  851. },
  852. onError(value) {
  853. this.jsonValid = false;
  854. },
  855. async handleAPITestCreateConfirm() {
  856. this.$refs.createAPITestForm.validate(async (valid) => {
  857. if (valid) {
  858. this.createAPITestForm.createTime = this.getCurrentTime();
  859. await APITestAPI.createAPITest({
  860. projectId: this.$store.state.workspace.currentProjectId,
  861. createTime: this.createAPITestForm.createTime,
  862. username: this.$store.state.user.username,
  863. testName: this.createAPITestForm.testName,
  864. url: this.createAPITestForm.url,
  865. params: this.createAPITestForm.params,
  866. method: this.createAPITestForm.method,
  867. qps: this.createAPITestForm.qps,
  868. });
  869. this.apitests = await APITestAPI.getAPITestInfosByProjectId(this.$store.state.workspace.currentProjectId);
  870. this.$refs.createAPITestForm.resetFields();
  871. this.showAPITestCreateModel = false;
  872. ElMessage.success('创建成功!');
  873. }
  874. });
  875. },
  876. getCurrentTime() {
  877. const yy = new Date().getFullYear();
  878. const mm = new Date().getMonth() + 1;
  879. const dd = new Date().getDate();
  880. const hh = new Date().getHours();
  881. const mf = new Date().getMinutes() < 10 ? `0${new Date().getMinutes()}` : new Date().getMinutes();
  882. const ss = new Date().getSeconds() < 10 ? `0${new Date().getSeconds()}` : new Date().getSeconds();
  883. return `${yy}-${mm}-${dd} ${hh}:${mf}:${ss}`;
  884. },
  885. async initChart1() {
  886. const chart1 = echarts.init(document.getElementById('chart1'));
  887. const options1 = {
  888. title: {
  889. text: `并发数: ${this.qps}`,
  890. x: 'center',
  891. y: 'center',
  892. textStyle: {
  893. fontSize: 16,
  894. },
  895. },
  896. tooltip: {
  897. trigger: 'item',
  898. },
  899. series: [
  900. {
  901. type: 'pie',
  902. radius: ['40%', '50%'],
  903. clockwise: true,
  904. avoidLabelOverlap: true,
  905. hoverOffset: 15,
  906. data: [
  907. { value: this.latestResultInfo.success, name: '成功', itemStyle: { color: '#CCFF99' } },
  908. { value: this.latestResultInfo.failure, name: '失败', itemStyle: { color: '#FF6600' } },
  909. ],
  910. },
  911. ],
  912. };
  913. chart1.setOption(options1);
  914. },
  915. async initChart2() {
  916. const chart2 = echarts.init(document.getElementById('chart2'));
  917. const option2 = {
  918. title: {
  919. text: '访问时间曲线图',
  920. bottom: '5%',
  921. left: 'center',
  922. },
  923. tooltip: {
  924. trigger: 'trigger',
  925. axisPointer: {
  926. type: 'cross',
  927. label: {
  928. backgroundColor: '#6a7985',
  929. },
  930. },
  931. },
  932. xAxis: [
  933. {
  934. type: 'category',
  935. boundaryGap: false,
  936. },
  937. ],
  938. yAxis: [
  939. {
  940. name: '执行时间/单位ms',
  941. type: 'value',
  942. min: 'dataMin',
  943. max: 'dataMax',
  944. },
  945. ],
  946. series: [
  947. {
  948. name: '访问时间',
  949. data: this.latestResultInfo.timeList,
  950. type: 'line',
  951. smooth: true,
  952. showSymbol: true,
  953. symbolSize: 3,
  954. symbol: 'circle',
  955. itemStyle: { color: '#8D67FF' },
  956. markPoint: {
  957. data: [
  958. { type: 'max', name: '最大值' },
  959. { type: 'min', name: '最小值' },
  960. ],
  961. },
  962. markLine: {
  963. data: [
  964. { type: 'average', name: '平均值' },
  965. ],
  966. },
  967. },
  968. ],
  969. };
  970. chart2.setOption(option2);
  971. },
  972. async handleTestCasesClick(action, id) {
  973. switch (action) {
  974. case 'create': {
  975. this.showTestCaseCreateModel = true;
  976. break;
  977. }
  978. case 'latest': {
  979. this.deployHistoryInfo = await FuncTestAPI.getLatestRecord(this.$store.state.workspace.currentProjectId);
  980. this.deployHistoryDrawer = true;
  981. break;
  982. }
  983. case 'finish': {
  984. await FuncTestAPI.finishTestCase(id);
  985. this.testcases = await FuncTestAPI.getTestCases(this.$store.state.workspace.currentProjectId);
  986. break;
  987. }
  988. case 'reopen': {
  989. await FuncTestAPI.reopenTestCase(id);
  990. this.testcases = await FuncTestAPI.getTestCases(this.$store.state.workspace.currentProjectId);
  991. break;
  992. }
  993. case 'edit': {
  994. this.testcases.forEach((item) => {
  995. if (item.id === id) {
  996. this.detailTestCaseInfo = item;
  997. }
  998. });
  999. this.showEditTestCaseModel = true;
  1000. break;
  1001. }
  1002. case 'delete': {
  1003. await FuncTestAPI.deleteTestCase(id);
  1004. ElMessage.success('删除成功!');
  1005. this.testcases = await FuncTestAPI.getTestCases(this.$store.state.workspace.currentProjectId);
  1006. break;
  1007. }
  1008. case 'steps': {
  1009. this.testcases.forEach((item) => {
  1010. if (item.id === id) {
  1011. this.detailTestCaseInfo = item;
  1012. }
  1013. });
  1014. this.detailStepsInfo = await FuncTestAPI.getTestCaseSteps(id);
  1015. this.stepsDrawer = true;
  1016. break;
  1017. }
  1018. default: {
  1019. console.warn('Unknown type of action.');
  1020. }
  1021. }
  1022. },
  1023. async handleTestCaseCreateConfirm() {
  1024. this.$refs.createTestCaseForm.validate(async (valid) => {
  1025. if (valid) {
  1026. this.createTestCaseForm.projectId = this.$store.state.workspace.currentProjectId;
  1027. await FuncTestAPI.createTestCase(
  1028. this.createTestCaseForm.projectId, this.createTestCaseForm.title, this.createTestCaseForm.taskId,
  1029. );
  1030. this.testcases = await FuncTestAPI.getTestCases(this.$store.state.workspace.currentProjectId);
  1031. this.$refs.createTestCaseForm.resetFields();
  1032. this.showTestCaseCreateModel = false;
  1033. ElMessage.success('创建成功!');
  1034. }
  1035. });
  1036. },
  1037. async handleSteps(action, caseId, stepId) {
  1038. switch (action) {
  1039. case 'create': {
  1040. await FuncTestAPI.createTestCaseStep(caseId);
  1041. ElMessage.success('创建成功!');
  1042. this.detailStepsInfo = await FuncTestAPI.getTestCaseSteps(caseId);
  1043. break;
  1044. }
  1045. case 'delete': {
  1046. await FuncTestAPI.deleteTestCaseStep(stepId);
  1047. ElMessage.success('删除成功!');
  1048. this.detailStepsInfo = await FuncTestAPI.getTestCaseSteps(caseId);
  1049. break;
  1050. }
  1051. case 'update': {
  1052. this.showUpdateStepModel = true;
  1053. this.detailStepsInfo.forEach((item) => {
  1054. if (item.id === stepId) {
  1055. this.updateStepForm = item;
  1056. }
  1057. });
  1058. break;
  1059. }
  1060. case 'updateState': {
  1061. this.showUpdateStepStateModel = true;
  1062. this.detailStepsInfo.forEach((item) => {
  1063. if (item.id === stepId) {
  1064. this.updateStepForm = item;
  1065. }
  1066. });
  1067. break;
  1068. }
  1069. default: {
  1070. console.warn('Unknown type of action.');
  1071. }
  1072. }
  1073. },
  1074. async handleStepUpdateConfirm() {
  1075. this.$refs.updateStepForm.validate(async (valid) => {
  1076. if (valid) {
  1077. await FuncTestAPI.updateTestCaseStep(this.updateStepForm.id, this.updateStepForm.description, this.updateStepForm.expectation);
  1078. this.detailStepsInfo = await FuncTestAPI.getTestCaseSteps(this.updateStepForm.testCaseId);
  1079. this.$refs.updateStepForm.resetFields();
  1080. this.showUpdateStepModel = false;
  1081. ElMessage.success('修改成功!');
  1082. }
  1083. });
  1084. },
  1085. async handleStepUpdateStateConfirm() {
  1086. this.$refs.updateStepForm.validate(async (valid) => {
  1087. if (valid) {
  1088. let state;
  1089. if (this.updateStepForm.state === '待测试') {
  1090. state = 'WAITING';
  1091. } else if (this.updateStepForm.state === '已测试') {
  1092. state = 'PASS';
  1093. } else if (this.updateStepForm.state === '出现bug') {
  1094. state = 'BUG';
  1095. }
  1096. await FuncTestAPI.updateTestCaseStepState(this.updateStepForm.id, state);
  1097. this.detailStepsInfo = await FuncTestAPI.getTestCaseSteps(this.updateStepForm.testCaseId);
  1098. this.$refs.updateStepForm.resetFields();
  1099. this.showUpdateStepStateModel = false;
  1100. ElMessage.success('修改成功!');
  1101. }
  1102. });
  1103. },
  1104. async handleTestCaseEditConfirm() {
  1105. this.$refs.detailTestCaseInfo.validate(async (valid) => {
  1106. if (valid) {
  1107. await FuncTestAPI.updateTestCase(this.detailTestCaseInfo.id, this.detailTestCaseInfo.title);
  1108. this.testcases = await FuncTestAPI.getTestCases(this.$store.state.workspace.currentProjectId);
  1109. this.$refs.detailTestCaseInfo.resetFields();
  1110. this.showEditTestCaseModel = false;
  1111. ElMessage.success('修改成功!');
  1112. }
  1113. });
  1114. },
  1115. },
  1116. };
  1117. </script>
  1118. <style lang="scss" scoped>
  1119. .tabs {
  1120. width: 80%;
  1121. margin: auto auto;
  1122. }
  1123. .add-button {
  1124. margin-left: 14px;
  1125. }
  1126. .entry-row {
  1127. width: 100%;
  1128. margin: 3px 20px;
  1129. display: flex;
  1130. flex-direction: row;
  1131. align-items: center;
  1132. justify-content: flex-start;
  1133. h3, h4{
  1134. color: #172b4d;
  1135. }
  1136. }
  1137. .node-type{
  1138. color: #FFFFFF;
  1139. border-radius: 3px;
  1140. font-size: 14px;
  1141. background-color: #42b983;
  1142. text-align: center;
  1143. }
  1144. .create-APITest-form {
  1145. width: 80%;
  1146. margin: 0 auto;
  1147. }
  1148. </style>