Nuestro conocimiento compartido. Nuestro tesoro compartido. Wikipedia.
ShareCode
Permalink: http://www.treeweb.es/u/974/ 01/02/2011

ShareCode

1 <!DOCTYPE html>2 <html lang="es">3 <head>4  <meta charset="UTF-8">5  <title>Plataforma de Testing Automatizado de APIs</title>6  <!-- Enlaces a Bootstrap CSS y Bootstrap Icons -->7  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">8  <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet">9  <!-- Estilos personalizados -->10  <style>11  body {12  background-color: var(--bs-body-bg);13  color: var(--bs-body-color);14  transition: background-color 0.3s, color 0.3s;15  }16  .card {17  margin-bottom: 20px;18  transition: transform 0.2s;19  }20  .card:hover {21  transform: translateY(-3px);22  }23  .navbar-brand img {24  height: 40px;25  }26  .theme-toggle {27  cursor: pointer;28  }29  .sidebar {30  position: fixed;31  top: 56px;32  bottom: 0;33  left: 0;34  padding: 20px;35  width: 250px;36  background-color: #f8f9fa;37  overflow-y: auto;38  }39  .content {40  margin-left: 270px;41  padding: 20px;42  }43  .nav-pills .nav-link.active {44  background-color: #0d6efd;45  }46  .accordion-button:not(.collapsed) {47  color: #0d6efd;48  background-color: #e7f1ff;49  }50  @media (max-width: 767px) {51  .sidebar {52  position: relative;53  width: 100%;54  margin-bottom: 20px;55  }56  .content {57  margin-left: 0;58  }59  }60  </style>61 </head>62 <body>63  <!-- Barra de navegación -->64  <nav class="navbar navbar-expand-lg navbar-dark bg-primary">65  <div class="container-fluid">66  <a class="navbar-brand" href="#">67  <!-- Logo -->68  <img src="https://via.placeholder.com/150x40?text=Logo" alt="Logo">69  </a>70  <span class="navbar-text text-white">71  Plataforma de Testing Automatizado de APIs72  </span>73  <button class="btn btn-secondary ms-auto theme-toggle" id="themeToggle">74  <i class="bi bi-moon-fill"></i>75  </button>76  </div>77  </nav>78 79  <!-- Barra lateral -->80  <div class="sidebar">81  <h5>Flujo de Prueba</h5>82  <ul class="nav nav-pills flex-column">83  <li class="nav-item">84  <a class="nav-link active" href="#variables" @click="selectTab('variables')">85  <i class="bi bi-sliders"></i> Variables86  </a>87  </li>88  <li class="nav-item">89  <a class="nav-link" href="#request" @click="selectTab('request')">90  <i class="bi bi-arrow-up-right-circle"></i> Request91  </a>92  </li>93  <li class="nav-item">94  <a class="nav-link" href="#assertions" @click="selectTab('assertions')">95  <i class="bi bi-check-circle"></i> Aserciones96  </a>97  </li>98  <li class="nav-item">99  <a class="nav-link" href="#sleep" @click="selectTab('sleep')">100  <i class="bi bi-hourglass-split"></i> Sleep101  </a>102  </li>103  <li class="nav-item">104  <a class="nav-link" href="#repeat" @click="selectTab('repeat')">105  <i class="bi bi-repeat"></i> Repeat106  </a>107  </li>108  <li class="nav-item">109  <a class="nav-link" href="#call" @click="selectTab('call')">110  <i class="bi bi-box-arrow-in-right"></i> Call111  </a>112  </li>113  </ul>114  </div>115 116  <!-- Contenido principal -->117  <div id="app" class="content">118  <!-- Pestañas principales -->119  <ul class="nav nav-tabs" id="mainTabs" role="tablist">120  <li class="nav-item" role="presentation" v-for="tab in tabs">121  <button class="nav-link" :class="{ active: activeTab === tab.id }" :id="tab.id + '-tab'" data-bs-toggle="tab" :data-bs-target="'#' + tab.id" type="button" role="tab" @click="selectTab(tab.id)">122  {{ tab.name }}123  </button>124  </li>125  </ul>126  <div class="tab-content mt-4">127  <!-- Variables -->128  <div class="tab-pane fade" :class="{ 'show active': activeTab === 'variables' }" id="variables" role="tabpanel">129  <div class="card">130  <div class="card-body">131  <!-- Variable principal -->132  <div class="row g-3">133  <div class="col-md-6">134  <label class="form-label">Nombre de la Variable</label>135  <input type="text" class="form-control" v-model="variables.name">136  </div>137  <div class="col-md-6">138  <label class="form-label">Valor</label>139  <input type="text" class="form-control" v-model="variables.value">140  </div>141  </div>142  <!-- Aserción de variable -->143  <div class="form-check form-switch mt-3">144  <input class="form-check-input" type="checkbox" id="assertVariable" v-model="variables.assert">145  <label class="form-check-label" for="assertVariable">146  Assert variable147  </label>148  </div>149  <div class="mt-2" v-if="variables.assert">150  <label class="form-label">Valores Esperados (separados por coma)</label>151  <input type="text" class="form-control" v-model="variables.assertValues">152  </div>153  </div>154  </div>155  </div>156  <!-- Request -->157  <div class="tab-pane fade" :class="{ 'show active': activeTab === 'request' }" id="request" role="tabpanel">158  <div class="card">159  <div class="card-body">160  <!-- Método y URL -->161  <div class="row g-3 align-items-end">162  <div class="col-md-3">163  <label class="form-label">Método HTTP</label>164  <select class="form-select" v-model="request.method">165  <option>GET</option>166  <option>POST</option>167  <option>PUT</option>168  <option>DELETE</option>169  </select>170  </div>171  <div class="col-md-9">172  <label class="form-label">URL</label>173  <input type="text" class="form-control" v-model="request.url" @input="validateURL">174  <div class="invalid-feedback" v-if="!validURL">175  Por favor, introduce una URL válida.176  </div>177  </div>178  </div>179  <!-- Headers y Body en Accordions -->180  <div class="accordion mt-4" id="requestAccordion">181  <!-- Headers -->182  <div class="accordion-item">183  <h2 class="accordion-header" id="headingHeaders">184  <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseHeaders" aria-expanded="false" aria-controls="collapseHeaders">185  Headers186  </button>187  </h2>188  <div id="collapseHeaders" class="accordion-collapse collapse" aria-labelledby="headingHeaders" data-bs-parent="#requestAccordion">189  <div class="accordion-body">190  <div v-for="(header, index) in request.headers" :key="index" class="row g-2 mb-2 align-items-center">191  <div class="col-md-5">192  <input type="text" class="form-control" v-model="header.key" placeholder="Header Key">193  </div>194  <div class="col-md-5">195  <input type="text" class="form-control" v-model="header.value" placeholder="Header Value">196  </div>197  <div class="col-md-2">198  <button class="btn btn-outline-danger w-100" @click="removeHeader(index)">199  <i class="bi bi-trash"></i>200  </button>201  </div>202  </div>203  <button class="btn btn-outline-primary add-button" @click="addHeader">204  <i class="bi bi-plus-lg"></i> Agregar Header205  </button>206  </div>207  </div>208  </div>209  <!-- Body -->210  <div class="accordion-item" v-if="request.method !== 'GET'">211  <h2 class="accordion-header" id="headingBody">212  <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseBody" aria-expanded="false" aria-controls="collapseBody">213  Body214  </button>215  </h2>216  <div id="collapseBody" class="accordion-collapse collapse" aria-labelledby="headingBody" data-bs-parent="#requestAccordion">217  <div class="accordion-body">218  <textarea class="form-control" rows="5" v-model="request.body" placeholder="Cuerpo de la solicitud"></textarea>219  </div>220  </div>221  </div>222  </div>223  </div>224  </div>225  </div>226  <!-- Aserciones -->227  <div class="tab-pane fade" :class="{ 'show active': activeTab === 'assertions' }" id="assertions" role="tabpanel">228  <div class="card">229  <div class="card-body">230  <!-- Aserción de respuesta -->231  <div class="form-check form-switch">232  <input class="form-check-input" type="checkbox" id="assertResponseBody" v-model="assertion.enabled">233  <label class="form-check-label" for="assertResponseBody">Activar Aserción de Respuesta</label>234  </div>235  <div class="mt-3" v-if="assertion.enabled">236  <label class="form-label">Condición</label>237  <input type="text" class="form-control" v-model="assertion.condition" placeholder="Ejemplo: response.body.data.status is success">238  </div>239  </div>240  </div>241  </div>242  <!-- Sleep -->243  <div class="tab-pane fade" :class="{ 'show active': activeTab === 'sleep' }" id="sleep" role="tabpanel">244  <div class="card">245  <div class="card-body">246  <label class="form-label">Tiempo de Espera</label>247  <input type="text" class="form-control" v-model="sleepTime" placeholder="Ejemplo: 10s">248  </div>249  </div>250  </div>251  <!-- Repeat -->252  <div class="tab-pane fade" :class="{ 'show active': activeTab === 'repeat' }" id="repeat" role="tabpanel">253  <div class="card">254  <div class="card-body">255  <label class="form-label">Número de Iteraciones</label>256  <input type="number" class="form-control" v-model.number="repeatCount" min="1">257  </div>258  </div>259  </div>260  <!-- Call -->261  <div class="tab-pane fade" :class="{ 'show active': activeTab === 'call' }" id="call" role="tabpanel">262  <div class="card">263  <div class="card-body">264  <h5>Parámetros para Create Payment</h5>265  <div v-for="(param, index) in callParams" :key="index" class="row g-3 align-items-center mb-2">266  <div class="col-md-4">267  <label class="form-label">{{ param.name }}</label>268  </div>269  <div class="col-md-8">270  <input type="text" class="form-control" v-model="param.value">271  </div>272  </div>273  </div>274  </div>275  </div>276  </div>277 278  <!-- Botón de Ejecución -->279  <div class="text-center my-4">280  <button class="btn btn-lg btn-primary" @click="executeTest" :disabled="!validURL">281  <i class="bi bi-play-fill"></i> Ejecutar Prueba282  </button>283  </div>284 285  <!-- Result -->286  <div class="card" v-if="result">287  <div class="card-header" :class="{'bg-success text-white': result.success, 'bg-danger text-white': !result.success}">288  <h5>Resultado</h5>289  </div>290  <div class="card-body">291  <p><strong>STATUS:</strong> {{ result.status }}</p>292  <p><strong>Mensaje:</strong> {{ result.message }}</p>293  </div>294  </div>295 296  </div>297 298  <!-- Enlaces a Vue.js y Bootstrap JS -->299  <script src="https://cdn.jsdelivr.net/npm/vue@3.3.4/dist/vue.global.prod.js"></script>300  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>301 302  <!-- Script Vue.js -->303  <script>304  const { createApp } = Vue;305 306  createApp({307  data() {308  return {309  activeTab: 'variables',310  tabs: [311  { id: 'variables', name: 'Variables' },312  { id: 'request', name: 'Request' },313  { id: 'assertions', name: 'Aserciones' },314  { id: 'sleep', name: 'Sleep' },315  { id: 'repeat', name: 'Repeat' },316  { id: 'call', name: 'Call' },317  ],318  variables: {319  name: 'user-id',320  value: 'uuid',321  assert: false,322  assertValues: ''323  },324  request: {325  method: 'GET',326  url: '',327  headers: [],328  body: ''329  },330  assertion: {331  enabled: false,332  condition: ''333  },334  sleepTime: '',335  repeatCount: 1,336  callParams: [337  { name: 'payment-id', value: '[uuid]' },338  { name: 'amount', value: '' },339  { name: 'IBAN', value: 'my-iban' }340  ],341  result: null,342  validURL: true,343  darkTheme: false344  }345  },346  methods: {347  selectTab(tabId) {348  this.activeTab = tabId;349  },350  addHeader() {351  this.request.headers.push({ key: '', value: '' });352  },353  removeHeader(index) {354  this.request.headers.splice(index, 1);355  },356  validateURL() {357  try {358  new URL(this.request.url);359  this.validURL = true;360  } catch (_) {361  this.validURL = false;362  }363  },364  executeTest() {365  // Simulación de ejecución de prueba366  this.result = {367  success: true,368  status: 'ACCEPTED',369  message: 'SUBMISSION ID posted: 521-2021-3215-33'370  };371  // Animación de scroll al resultado372  this.$nextTick(() => {373  const resultCard = document.querySelector('.card:last-child');374  resultCard.scrollIntoView({ behavior: 'smooth' });375  });376  }377  },378  mounted() {379  // Inicializar el tema según las preferencias del usuario380  const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;381  if (prefersDark) {382  this.toggleTheme();383  }384  }385  }).mount('#app');386 387  // Manejo del botón de cambio de tema fuera de Vue388  document.getElementById('themeToggle').addEventListener('click', () => {389  document.body.classList.toggle('bg-dark');390  document.body.classList.toggle('text-white');391  const icon = document.getElementById('themeToggle').querySelector('i');392  icon.classList.toggle('bi-moon-fill');393  icon.classList.toggle('bi-sun-fill');394  });395  </script>396 </body>397 </html>398 


Este ShareCode tiene versiones:
  1. Flujo Secuencial de API... (28/09/2024)
Enlace
El enlace para compartir es: