Vue接口平台学习十——接口用例页面2

news2025/4/22 7:44:58

效果图及简单说明

在这里插入图片描述
左边选择用例,右侧就显示该用例的详细信息。
使用el-collapse折叠组件,将请求到的用例详情数据展示到页面中。
所有数据内容,绑定到caseData中

// 页面绑定的用例编辑数据
const caseData = reactive({
  title: "",
  interface: {
    method: "get",
    url: ""
  },
  headers: '',
  request: {
    json: '{}',
    data: '{}',
    params: '{}'
  },
  file: [],
  setup_script: '',
  teardown_script: ''
})

页面内容实现

1. 请求API信息

<el-collapse-item name="1">
    <template #title>
       <img src="@/assets/icons/icon-api-a.png" width="20">
       <b>API信息</b>
     </template>
     <el-input v-model="caseData.interface.url" readonly>
       <template #prepend>
         <el-select v-model="caseData.interface.method" placeholder="选择请求方法" style="width: 115px">
           <el-option label="GET" value="get"/>
           <el-option label="POST" value="post"/>
           <el-option label="PUT" value="put"/>
           <el-option label="PATCH" value="patch"/>
           <el-option label="DELETE" value="delete"/>
         </el-select>
       </template>
     </el-input>
 </el-collapse-item>

一个下拉选择(请求方法) + 一个只读的input框
在这里插入图片描述

2.用例title

<el-collapse-item name="2">
      <template #title>
        <img src="@/assets/icons/case.png" width="20">
        <b>用例名称</b>
      </template>
      <el-input v-model="caseData.title">
        <template #prepend>
          <span>用例名称</span>
        </template>
      </el-input>
 </el-collapse-item>

一个带前缀的input输入框
在这里插入图片描述

3. 前置脚本

前置脚本是一个python代码编辑器

<div class="code">
    <Editor v-model="caseData.setup_script" lang="python" height='300px' class="scriptEdit"></Editor>
</div>

但是,可以准备一些预制脚本,方便使用。
可以创建编辑一些脚本保存在数据库,然后读取。这里没有选择那么复杂的内容,直接写死在了前端页面点击添加。

<div class='script_code'>
  <div class="code">
    <Editor v-model="caseData.setup_script" lang="python" height='300px' class="scriptEdit"></Editor>
  </div>
  <div class='mod'>
    <div class="add_code">
      <el-button @click='addSetupScript("func")' plain size="small">调用全局工具函数</el-button>
    </div>
    <div class="add_code">
      <el-button @click='addSetupScript("global")' plain size="small">设置全局变量</el-button>
    </div>
    <div class="add_code">
      <el-button @click='addSetupScript("env")' plain size="small">设置局部变量</el-button>
    </div>
    <div class="add_code">
      <el-button @click='addSetupScript("sql")' plain size="small">执行sql查询</el-button>
    </div>
  </div>
</div>
// 生成前置脚本
function addSetupScript(item) {
  if (item === "func") {
    caseData.setup_script += '# 调用全局工具函数random_mobile随机生成一个手机号码\nmobile = global_func.random_mobile()\n'
  } else if (item === "global") {
    caseData.setup_script += '# 设置局部变量\ntest.save_global_variable("变量名","变量值")\n'
  } else if (item === "env") {
    caseData.setup_script += '# 设置局部变量\ntest.save_env_variable("变量名","变量值")\n'
  } else if (item === "sql") {
    caseData.setup_script +=
        '# ----执行sql语句(需要在环境中配置数据库连接信息)----\n # db.连接名.execute_all(sql语句) \nsql = "SELECT count(*) as count FROM futureloan.member"\nres = db.hwyun.execute_all(sql)\n'
  }
}

在这里插入图片描述

4. 请求头

同样代码编辑器

<el-collapse-item name="4">
  <template #title>
    <img src="@/assets/icons/keyhole.png" width="20">
    <b>请求头</b>
  </template>
  <Editor lang="json" v-model="caseData.headers"></Editor>
</el-collapse-item>

在这里插入图片描述

5.查询参数

<el-collapse-item name="5">
  <template #title>
    <img src="@/assets/icons/API_api.png" width="20">
    <b>查询参数</b>
  </template>
  <Editor lang="json" v-model="caseData.request.params"></Editor>

</el-collapse-item>

在这里插入图片描述

6. 请求体(Get请求不可点击)

get请求禁用了,然后如果是文件类型数据,复用之前的FormData组件

<el-collapse-item name="6" :disabled="caseData.interface.method=='get'">
  <template #title>
    <img src="@/assets/icons/body.png" width="20">
    <b>请求体</b>
  </template>
  <el-radio-group v-model="bodyType">
    <el-radio-button label="json">Json</el-radio-button>
    <el-radio-button label="data">X-www-form-urlencoded</el-radio-button>
    <el-radio-button label="form-data">Form-data</el-radio-button>
  </el-radio-group>
  <!-- json参数 -->
  <div v-if='bodyType==="json"'>
    <Editor lang="json" v-model="caseData.request.json"></Editor>
  </div>
  <div v-else-if='bodyType==="data"'>
    <Editor lang="json" v-model="caseData.request.data"></Editor>
  </div>
  <div v-else>
    <FromData v-model="file"></FromData>
  </div>
</el-collapse-item>

在这里插入图片描述

7.后置脚本(同前置脚本)

<el-collapse-item name="7">
  <template #title>
    <img src="@/assets/icons/instruction.png" width="20">
    <b>后置断言脚本</b>
  </template>
  <div class='script_code'>
    <div class="code">
      <Editor v-model="caseData.teardown_script" lang="python" height='300px' ></Editor>
    </div>
    <div class='mod'>
      <el-scrollbar height="300px">
        <div class="add_code">
          <el-button @click="addTearDownCodeMod('getBody')" plain size="small">获取响应体</el-button>
        </div>
        <div class="add_code">
          <el-button @click="addTearDownCodeMod('http')" plain size="small">HTTP状态码断言</el-button>
        </div>    
        <div class="add_code">
          <el-button @click="addTearDownCodeMod('contain')" plain size="small">断言包含</el-button>
         <!-- 省略 ....	-->
        </div>
      </el-scrollbar>
    </div>
  </div>
</el-collapse-item>

在这里插入图片描述

8.悬浮操作按钮

与测试环境页面一样,使用 Affix 固钉 组件

https://element-plus.org/zh-CN/component/affix.html#affix-%E5%9B%BA%E9%92%89

<el-affix :offset="40" position="bottom">
  <div class="btns">
    <el-button @click='runCase' type="primary" plain size="small" icon='Promotion'>运行</el-button>
    <el-button @click='copyCase' type="primary" plain size="small" icon='DocumentCopy'>复制</el-button>
    <el-button @click='saveCase' type="primary" plain size="small" icon='FolderChecked'>保存</el-button>
    <el-button @click='clickDelete' type="danger" plain size="small" icon='Delete'>删除</el-button>
  </div>
</el-affix>

页面功能实现

1. 点击获取接口用例详情

在之前一节,左侧显示了用例列表。并且点击某个用例,实现了点击方法@click='selectCase(_case.id)',也就是function selectCase(id) { activeCase.value = id }将activeCase 赋值了。
而在右侧,显示用例详情页,把activeCase值传给了CaseEditor这个组件

<div class="card right_box">
   <CaseEditor :case_id='activeCase'></CaseEditor>
</div>

然后在CaseEditor组件定义props接收传递的值,然后监听这个值变化,就请求获取用例详情。

const props = defineProps({
  case_id: ""
})

// 侦听case_id的变化
watch(() => props.case_id, (val) => {
  if (val !== '') {
    getCaseInfo(val)
  }
})

if (props.case_id != undefined) {
  getCaseInfo(props.case_id)
}


// 调用获取详情的接口
async function getCaseInfo(id) {
  // console.log("获取详情:"+id)
  const response = await http.pro.getCaseInfoAPi(id)
  if (response.status === 200) {
    // 保存用例对象
    caseObj = response.data
    // 把用例数据绑定到编辑页面
    caseData.title = caseObj.title
    caseData.interface = caseObj.interface
    caseData.setup_script = caseObj.setup_script
    caseData.file = caseObj.file
    caseData.teardown_script = caseObj.teardown_script
    caseData.headers = JSON.stringify(caseObj.headers, 0, 4)
    caseData.request.json = JSON.stringify(caseObj.request.json || {}, 0, 4)
    caseData.request.data = JSON.stringify(caseObj.request.data || {}, 0, 4)
    caseData.request.params = JSON.stringify(caseObj.request.params || {}, 0, 4)
    file.value = caseObj.file

  }
  // get请求默认不展示请求体,其他默认自动展开
  if (caseData.interface.method == 'get') {
    activeNames.value = ['1', '2']
  } else {
    activeNames.value = ['1', '2', '6']
  }

  // console.log(activeNames)
  // 根据请求体信息,默认选中对应的拦
  if (caseData.request.json != '{}') {
    bodyType.value = 'json'
  } else if (caseData.request.data != '{}') {
    bodyType.value = 'data'
  } else if (caseData.file.length != 0) {
    bodyType.value = 'form-data'
  }
}

2.保存用例

编辑好数据后,都是双向绑定的,直接组成参数调用api就行了。

// 保存用例
async function saveCase() {

  if (caseData.headers == '') {
    caseData.headers = '{}'
  } else if (caseData.request.params == '') {
    caseData.request.params = '{}'
  } else if (caseData.request.json == '') {
    caseData.request.json = '{}'
  } else if (caseData.request.data == '') {
    caseData.request.data = '{}'
  }

  // 准备参数
  const params = {
    title: caseData.title,
    headers: JSON.parse(caseData.headers),
    request: {
      params: JSON.parse(caseData.request.params),
    },
    setup_script: caseData.setup_script,
    teardown_script: caseData.teardown_script,
  }
  if (caseData.interface.method != 'get') {
    // console.log('!get')
    if (bodyType.value === 'json') {
      params.request.json = JSON.parse(caseData.request.json)
    } else if (bodyType.value === 'data') {
      params.request.data = JSON.parse(caseData.request.data)
    } else {
      params.file = file.value
    }
  }

  // 调用修改用例的接口
  const response = await api.updateCaseApi(props.case_id, params)
  if (response.status === 200) {
    ElNotification({
      title: '保存成功',
      type: 'success',
    })
    // 刷新页面数据
    pstore.getInterFaceList()
  }
}

3. 删除用例

和之前的删除方法没有什么区别,有个二次确认弹窗。然后删除过后,把页面数据清空。

// 删除测试用例的方法
function clickDelete() {
  ElMessageBox.confirm(
      '删除操作不可恢复,请确认是否要删除该测试用例?',
      '提示', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning',
      }
  ).then(async () => {
    // 调用后端接口进行删除
    const response = await http.pro.deleteCaseApi(props.case_id)
    if (response.status === 204) {
      ElNotification({
        title: '删除成功',
        type: 'success',
      })
      // 刷新页面数据
      pstore.getInterFaceList()
      resetData()
    }
  }).catch(() => {
    ElNotification({
      type: 'info',
      title: '已取消删除操作',
    })
  })
}

function resetData() {
  // 清空页面编辑的数据
  caseData.title = ''
  caseData.interface = {
    method: "get",
    url: ""
  }
  caseData.setup_script = ''
  caseData.file = []
  caseData.teardown_script = ''
  caseData.headers = ''
  caseData.request.json = "{}"
  caseData.request.data = "{}"
  caseData.request.params = "{}"
  caseObj = {}
}

4. 复制用例

与新增测试环境一样,在名字后面+copy,其他内容都保持不变

// 复制用例
async function copyCase() {
  const response = await http.pro.createCaseApi({
    title: caseObj.title + '-COPY',
    interface: caseObj.interface.id
  })
  if (response.status === 201) {
    ElNotification({
      title: '复制成功',
      type: 'success',
    })
    // 刷新页面数据
    pstore.getInterFaceList()
  }
}

5. 运行用例

运行结果用抽屉组件展示,展示内容就是之前调试运行时的Result组件

  <!-- 测试用例运行的结果 -->
  <el-drawer v-model="isShowDrawer" size="50%">
    <template #header>
      <b>运行结果</b>
    </template>
    <template #default>
      <Result :result='responseData'></Result>
    </template>
  </el-drawer>
// 保存用例运行的结果
let responseData = ref({})
// 是否显示结果的窗口
let isShowDrawer = ref(false)

async function runCase() {
  // 准备参数
  const params = {
    env: pstore.env,
    cases: {
      title: caseData.title,
      interface: caseData.interface,
      headers: JSON.parse(caseData.headers),
      request: {
        params: JSON.parse(caseData.request.params),
      },
      setup_script: caseData.setup_script,
      teardown_script: caseData.teardown_script,
    }
  }
  // console.log(params.cases.interface.method)
  if (params.cases.interface.method != 'get') {
    if (bodyType.value === 'json') {
      params.cases.request.json = JSON.parse(caseData.request.json)
    } else if (bodyType.value === 'data') {
      params.cases.request.data = JSON.parse(caseData.request.data)
    } else {
      params.cases.file = caseData.file
    }
  }
  // console.log(params.cases.request)
  // 调用运行用例的接口
  const response = await http.run.runInterFaceCaseApi(params)
  if (response.status === 200) {
    // console.log('运行成功')
    responseData.value = response.data
    // 展示执行结果
    isShowDrawer.value = true
  }
}

在这里插入图片描述
到此页面功能实现完成。

小优化,增加loading

刚才运行时,受网络问题,一直没结果。所以,就增加一个loading效果
同样使用了element的loading组件

https://element-plus.org/zh-CN/component/loading.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8A%A0%E8%BD%BD%E4%B8%AD%E7%BB%84%E4%BB%B6%E5%86%85%E5%AE%B9

给页面绑定loading相关数据

<el-collapse v-model="activeNames" v-loading="scrennLoading" element-loading-text="运行中..."  element-loading-background="rgba(122, 122, 122, 0.8)">

然后运行时,显示loading,运行结束再隐藏loading

const scrennLoading = ref(false)

async function runCase() {
  // 显示loading
  scrennLoading.value = true
  。。。
  // 隐藏loading
  scrennLoading.value = false
}

在这里插入图片描述

总结

复用之前的组件以减少开发量。所以一个经常会用到的组件,最好单独抽出来。以便后续使用。
然后用了cursor,没次数了。又尝试了一下Trae,也是挺不错的。遇到问题向Ai求助真是泰裤辣!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2339943.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

目标检测中的损失函数(二) | BIoU RIoU α-IoU

BIoU来自发表在2018年CVPR上的文章&#xff1a;《Improving Object Localization With Fitness NMS and Bounded IoU Loss》 论文针对现有目标检测方法只关注“足够好”的定位&#xff0c;而非“最优”的框&#xff0c;提出了一种考虑定位质量的NMS策略和BIoU loss。 这里不赘…

Linux 入门十一:Linux 网络编程

一、概述 1. 网络编程基础 网络编程是通过网络应用编程接口&#xff08;API&#xff09;编写程序&#xff0c;实现不同主机上进程间的信息交互。它解决的核心问题是&#xff1a;如何让不同主机上的程序进行通信。 2. 网络模型&#xff1a;从 OSI 到 TCP/IP OSI 七层模型&…

沐渥氮气柜控制板温湿度氧含量氮气流量四显智控系统

氮气柜控制板通常用于实时监控和调节柜内环境参数&#xff0c;确保存储物品如电子元件、精密仪器、化学品等&#xff0c;处于低氧、干燥的稳定状态。以下是沐渥氮气柜控制板核心参数的详细介绍及控制逻辑&#xff1a; 一、控制板核心参数显示模块 1&#xff09;‌温度显示‌&am…

[c语言日寄]免费文档生成器——Doxygen在c语言程序中的使用

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋&#xff1a;这是一个专注于C语言刷题的专栏&#xff0c;精选题目&#xff0c;搭配详细题解、拓展算法。从基础语法到复杂算法&#xff0c;题目涉及的知识点全面覆盖&#xff0c;助力你系统提升。无论你是初学者&#xff0c;还是…

QtCreator的设计器、预览功能能看到程序图标,编译运行后图标消失

重新更换虚拟机&#xff08;Vmware Kylin&#xff09;&#xff0c;重新编译和配置了很多第三方库后&#xff0c;将代码跑到新的这个虚拟机环境中&#xff0c;但是出现程序图标不可见&#xff0c;占位也消失&#xff0c;后来继续检查ui文件&#xff0c;ui文件图标也异常&#x…

面试常用基础算法

目录 快速排序归并排序堆排序 n n n皇后问题最大和子数组爬楼梯中心扩展法求最长回文子序列分割回文串动态规划求最长回文子序列最长回文子串单调栈双指针算法修改 分割回文串滑动窗口栈 快速排序 #include <iostream> #include <algorithm>using namespace std;…

悬空引用和之道、之禅-《分析模式》漫谈57

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 “Analysis Patterns”的第5章“对象引用”原文&#xff1a; Unless you can catch all such references, there is the risk of a dangling reference, which often has painful con…

【初阶数据结构】树——二叉树(上)

文章目录 目录 前言 一、树 1.树的概念与结构 2.树相关术语 3.树的表示 二、二叉树 1.概念与结构 2.特殊的二叉树 3.二叉树存储结构 总结 前言 本篇带大家学习一种非线性数据结构——树&#xff0c;简单认识树和二叉数以及了解二叉树的存储结构。 一、树 1.树的概念与结构 树…

ECharts散点图-散点图14,附视频讲解与代码下载

引言&#xff1a; ECharts散点图是一种常见的数据可视化图表类型&#xff0c;它通过在二维坐标系或其它坐标系中绘制散乱的点来展示数据之间的关系。本文将详细介绍如何使用ECharts库实现一个散点图&#xff0c;包括图表效果预览、视频讲解及代码下载&#xff0c;让你轻松掌握…

GAIA-2:用于自动驾驶的可控多视图生成世界模型

25年3月来自英国创业公司 Wayze 的论文“GAIA-2: A Controllable Multi-View Generative World Model for Autonomous Driving”。&#xff08;注&#xff1a;23年9月其发布GAIA-1&#xff09; 生成模型为模拟复杂环境提供一种可扩展且灵活的范例&#xff0c;但目前的方法不足…

浅谈AI致幻

文章目录 当前形势下存在的AI幻觉&#xff08;AI致幻&#xff09;什么是AI幻觉AI幻觉的类型为什么AI会产生幻觉AI幻觉的危害与影响当前应对AI幻觉的技术与方法行业与学术界的最新进展未来挑战与展望结论 当前形势下存在的AI幻觉&#xff08;AI致幻&#xff09; 什么是AI幻觉 …

车载软件架构 --- 二级boot设计说明需求规范

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…

Java高效合并Excel报表实战:GcExcel让数据处理更简单

前言&#xff1a;为什么需要自动化合并Excel&#xff1f; 在日常办公场景中&#xff0c;Excel报表合并是数据分析的基础操作。根据2023年企业办公效率报告显示&#xff1a; 财务人员平均每周花费6.2小时在Excel合并操作上人工合并的错误率高达15%90%的中大型企业已采用自动化…

第十四届蓝桥杯 2023 C/C++组 平方差

目录 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路&#xff1a; 核心思路&#xff1a; 第一种思路&#xff1a; 第二种思路&#xff1a; 坑点&#xff1a; 代码&#xff1a; 数学找规律 O(n) 50分代码详解&#xff1a; O(1)满分代码详解&#x…

I/O复用函数的使用——select

I/O复用函数的使用——select 目录 一、概念 二、select接口 2.1 基础概念 2.2 使用 select 函数的标准输入读取代码 2.3 基于 select 模型的多客户端 TCP 服务器实现 一、概念 i/o复用使得程序能同时监听多个文件描述符&#xff0c;可以提高程序性能。 之前为了让服务器能…

图像预处理-图像轮廓特征查找

其实就是外接轮廓&#xff0c;有了轮廓点就可以找到最上、最下、最左、最右的四个坐标&#xff08;因为有xmin,xmax,ymin,ymax&#xff09;。就可以绘制出矩形。 一.外接矩形 cv.boundingRect(轮廓点) - 返回x,y,w,h&#xff0c;传入一个轮廓的轮廓点&#xff0c;若有多个轮廓需…

全同态加密医疗数据分析集python实现

目录 摘要一、前言二、全同态加密与医疗数据分析概述2.1 全同态加密(FHE)简介2.2 医疗数据分析需求三、数据生成与预处理四、系统架构与流程4.1 系统架构图五、核心数学公式六、异步任务调度与(可选)GPU 加速七、PyQt6 GUI 设计八、完整代码实现九、自查测试与总结十、展望…

list的学习

list的介绍 list文档的介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一…

HarmonyOS:Navigation实现导航之页面设置和路由操作

导读 设置标题栏模式设置菜单栏设置工具栏路由操作页面跳转页面返回页面替换页面删除移动页面参数获取路由拦截 子页面页面显示类型页面生命周期页面监听和查询 页面转场关闭转场自定义转场共享元素转场 跨包动态路由系统路由表自定义路由表 示例代码 Navigation组件适用于模块…

管道位移自动化监测方案

一、背景 管道系统在区域性地质沉降作用下易形成非均匀应力场集中现象&#xff0c;诱发管体屈曲变形及环焊缝界面剥离等连续损伤累积效应&#xff0c;进而导致管道力学性能退化与临界承载能力衰减。传统人工巡检受限于空间覆盖度不足及数据采集周期长&#xff08;≥72h&#xf…