Wikipedia para siempre
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  .block {17  border: 1px solid #dee2e6;18  border-radius: 5px;19  margin-bottom: 15px;20  overflow: hidden;21  }22  .block-header {23  background-color: #f8f9fa;24  padding: 10px 15px;25  display: flex;26  align-items: center;27  justify-content: space-between;28  }29  .block-body {30  padding: 15px;31  }32  .block-controls button {33  background: none;34  border: none;35  margin-left: 5px;36  color: #6c757d;37  }38  .block-controls button:hover {39  color: #000;40  }41  .add-block {42  text-align: center;43  margin: 20px 0;44  }45  .theme-toggle {46  cursor: pointer;47  }48  </style>49 </head>50 <body>51  <!-- Barra de navegación -->52  <nav class="navbar navbar-expand-lg navbar-dark bg-primary">53  <div class="container-fluid">54  <a class="navbar-brand" href="#">55  <!-- Logo -->56  <img src="https://via.placeholder.com/150x40?text=Logo" alt="Logo">57  </a>58  <span class="navbar-text text-white">59  Plataforma de Testing Automatizado de APIs60  </span>61  <button class="btn btn-secondary ms-auto theme-toggle" id="themeToggle">62  <i class="bi bi-moon-fill"></i>63  </button>64  </div>65  </nav>66 67  <!-- Contenido principal -->68  <div id="app" class="container my-4">69  <!-- Lista de bloques -->70  <div v-for="(block, index) in blocks" :key="index" class="block">71  <div class="block-header">72  <div>73  <i :class="getBlockIcon(block.type)"></i>74  <strong>{{ getBlockTitle(block) }}</strong>75  </div>76  <div class="block-controls">77  <button @click="moveUp(index)" :disabled="index === 0"><i class="bi bi-arrow-up"></i></button>78  <button @click="moveDown(index)" :disabled="index === blocks.length - 1"><i class="bi bi-arrow-down"></i></button>79  <button @click="toggleBlock(index)"><i :class="block.expanded ? 'bi bi-chevron-up' : 'bi bi-chevron-down'"></i></button>80  <button @click="removeBlock(index)"><i class="bi bi-trash"></i></button>81  </div>82  </div>83  <div class="block-body" v-if="block.expanded">84  <!-- Contenido dinámico según el tipo de bloque -->85  <component :is="getBlockComponent(block.type)" v-model="block.data"></component>86  </div>87  </div>88 89  <!-- Botón para agregar nuevos bloques -->90  <div class="add-block">91  <button class="btn btn-outline-primary" @click="showAddBlockModal">92  <i class="bi bi-plus-circle"></i> Añadir Paso93  </button>94  </div>95 96  <!-- Modal para seleccionar el tipo de bloque a agregar -->97  <div class="modal fade" id="addBlockModal" tabindex="-1" aria-labelledby="addBlockModalLabel" aria-hidden="true">98  <div class="modal-dialog">99  <div class="modal-content">100  <div class="modal-header">101  <h5 class="modal-title" id="addBlockModalLabel">Añadir Nuevo Paso</h5>102  <button type="button" class="btn-close" @click="hideAddBlockModal"></button>103  </div>104  <div class="modal-body">105  <p>Selecciona el tipo de paso que deseas agregar:</p>106  <div class="list-group">107  <button class="list-group-item list-group-item-action" @click="addBlock('variable')">108  <i class="bi bi-sliders"></i> Variable109  </button>110  <button class="list-group-item list-group-item-action" @click="addBlock('request')">111  <i class="bi bi-arrow-up-right-circle"></i> Solicitud HTTP112  </button>113  <button class="list-group-item list-group-item-action" @click="addBlock('assertion')">114  <i class="bi bi-check-circle"></i> Aserción115  </button>116  <!-- Agrega más opciones si es necesario -->117  </div>118  </div>119  </div>120  </div>121  </div>122 123  <!-- Botón de Ejecución -->124  <div class="text-center my-4">125  <button class="btn btn-lg btn-success" @click="executeTest" :disabled="!isExecutable">126  <i class="bi bi-play-fill"></i> Ejecutar Prueba127  </button>128  </div>129 130  <!-- Resultados -->131  <div class="block" v-if="result">132  <div class="block-header" :class="{'bg-success text-white': result.success, 'bg-danger text-white': !result.success}">133  <strong>Resultado</strong>134  </div>135  <div class="block-body">136  <p><strong>STATUS:</strong> {{ result.status }}</p>137  <p><strong>Mensaje:</strong> {{ result.message }}</p>138  </div>139  </div>140  </div>141 142  <!-- Enlaces a Vue.js y Bootstrap JS -->143  <script src="https://cdn.jsdelivr.net/npm/vue@3.3.4/dist/vue.global.prod.js"></script>144  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>145 146  <!-- Componentes para los bloques -->147  <script>148  const VariableBlock = {149  template: `150  <div>151  <div class="row g-3">152  <div class="col-md-6">153  <label class="form-label">Nombre de la Variable</label>154  <input type="text" class="form-control" v-model="data.name">155  </div>156  <div class="col-md-6">157  <label class="form-label">Valor</label>158  <input type="text" class="form-control" v-model="data.value">159  </div>160  </div>161  </div>162  `,163  props: ['modelValue'],164  computed: {165  data: {166  get() { return this.modelValue; },167  set(value) { this.$emit('update:modelValue', value); }168  }169  }170  };171 172  const RequestBlock = {173  template: `174  <div>175  <!-- Método y URL -->176  <div class="row g-3 align-items-end">177  <div class="col-md-3">178  <label class="form-label">Método HTTP</label>179  <select class="form-select" v-model="data.method">180  <option>GET</option>181  <option>POST</option>182  <option>PUT</option>183  <option>DELETE</option>184  </select>185  </div>186  <div class="col-md-9">187  <label class="form-label">URL</label>188  <input type="text" class="form-control" v-model="data.url">189  </div>190  </div>191  <!-- Headers y Body -->192  <div class="mt-3">193  <button class="btn btn-sm btn-outline-secondary" @click="toggleHeaders">194  <i class="bi" :class="showHeaders ? 'bi-dash' : 'bi-plus'"></i> Headers195  </button>196  <button class="btn btn-sm btn-outline-secondary ms-2" @click="toggleBody" v-if="data.method !== 'GET'">197  <i class="bi" :class="showBody ? 'bi-dash' : 'bi-plus'"></i> Body198  </button>199  </div>200  <!-- Headers -->201  <div v-if="showHeaders" class="mt-3">202  <div v-for="(header, index) in data.headers" :key="index" class="row g-2 mb-2 align-items-center">203  <div class="col-md-5">204  <input type="text" class="form-control" v-model="header.key" placeholder="Header Key">205  </div>206  <div class="col-md-5">207  <input type="text" class="form-control" v-model="header.value" placeholder="Header Value">208  </div>209  <div class="col-md-2">210  <button class="btn btn-outline-danger w-100" @click="removeHeader(index)">211  <i class="bi bi-trash"></i>212  </button>213  </div>214  </div>215  <button class="btn btn-outline-primary add-button" @click="addHeader">216  <i class="bi bi-plus-lg"></i> Agregar Header217  </button>218  </div>219  <!-- Body -->220  <div v-if="showBody" class="mt-3">221  <label class="form-label">Body</label>222  <textarea class="form-control" rows="5" v-model="data.body" placeholder="Cuerpo de la solicitud"></textarea>223  </div>224  </div>225  `,226  props: ['modelValue'],227  data() {228  return {229  showHeaders: false,230  showBody: false,231  }232  },233  computed: {234  data: {235  get() { return this.modelValue; },236  set(value) { this.$emit('update:modelValue', value); }237  }238  },239  methods: {240  toggleHeaders() {241  this.showHeaders = !this.showHeaders;242  },243  toggleBody() {244  this.showBody = !this.showBody;245  },246  addHeader() {247  this.data.headers.push({ key: '', value: '' });248  },249  removeHeader(index) {250  this.data.headers.splice(index, 1);251  }252  }253  };254 255  const AssertionBlock = {256  template: `257  <div>258  <label class="form-label">Condición de Aserción</label>259  <input type="text" class="form-control" v-model="data.condition" placeholder="Ejemplo: response.status == 200">260  </div>261  `,262  props: ['modelValue'],263  computed: {264  data: {265  get() { return this.modelValue; },266  set(value) { this.$emit('update:modelValue', value); }267  }268  }269  };270 271  // Instancia de Vue272  const { createApp } = Vue;273 274  createApp({275  components: {276  'variable-block': VariableBlock,277  'request-block': RequestBlock,278  'assertion-block': AssertionBlock,279  // Agrega más componentes según sea necesario280  },281  data() {282  return {283  blocks: [],284  result: null,285  darkTheme: false,286  }287  },288  computed: {289  isExecutable() {290  // Verifica si hay al menos un bloque para ejecutar291  return this.blocks.length > 0;292  }293  },294  methods: {295  getBlockTitle(block) {296  switch (block.type) {297  case 'variable':298  return `Set Variable: ${block.data.name} = ${block.data.value}`;299  case 'request':300  return `${block.data.method} ${block.data.url}`;301  case 'assertion':302  return `Aserción: ${block.data.condition}`;303  // Otros casos...304  }305  },306  getBlockIcon(type) {307  switch (type) {308  case 'variable':309  return 'bi bi-sliders';310  case 'request':311  return 'bi bi-arrow-up-right-circle';312  case 'assertion':313  return 'bi bi-check-circle';314  // Otros casos...315  }316  },317  getBlockComponent(type) {318  switch (type) {319  case 'variable':320  return 'variable-block';321  case 'request':322  return 'request-block';323  case 'assertion':324  return 'assertion-block';325  // Otros casos...326  }327  },328  toggleBlock(index) {329  this.blocks[index].expanded = !this.blocks[index].expanded;330  },331  moveUp(index) {332  if (index > 0) {333  [this.blocks[index - 1], this.blocks[index]] = [this.blocks[index], this.blocks[index - 1]];334  }335  },336  moveDown(index) {337  if (index < this.blocks.length - 1) {338  [this.blocks[index], this.blocks[index + 1]] = [this.blocks[index + 1], this.blocks[index]];339  }340  },341  removeBlock(index) {342  this.blocks.splice(index, 1);343  },344  showAddBlockModal() {345  const modal = new bootstrap.Modal(document.getElementById('addBlockModal'));346  modal.show();347  },348  hideAddBlockModal() {349  const modal = bootstrap.Modal.getInstance(document.getElementById('addBlockModal'));350  modal.hide();351  },352  addBlock(type) {353  let newBlock = {354  type: type,355  expanded: true,356  data: {}357  };358  switch (type) {359  case 'variable':360  newBlock.data = { name: '', value: '' };361  break;362  case 'request':363  newBlock.data = { method: 'GET', url: '', headers: [], body: '' };364  break;365  case 'assertion':366  newBlock.data = { condition: '' };367  break;368  // Otros casos...369  }370  this.blocks.push(newBlock);371  this.hideAddBlockModal();372  },373  executeTest() {374  // Simulación de ejecución de prueba375  this.result = {376  success: true,377  status: 'COMPLETED',378  message: 'Prueba ejecutada exitosamente.'379  };380  // Animación de scroll al resultado381  this.$nextTick(() => {382  const resultBlock = document.querySelector('.block:last-child');383  resultBlock.scrollIntoView({ behavior: 'smooth' });384  });385  }386  },387  mounted() {388  // Inicializar el tema según las preferencias del usuario389  const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;390  if (prefersDark) {391  this.toggleTheme();392  }393  }394  }).mount('#app');395 396  // Manejo del botón de cambio de tema fuera de Vue397  document.getElementById('themeToggle').addEventListener('click', () => {398  document.body.classList.toggle('bg-dark');399  document.body.classList.toggle('text-white');400  const icon = document.getElementById('themeToggle').querySelector('i');401  icon.classList.toggle('bi-moon-fill');402  icon.classList.toggle('bi-sun-fill');403  });404  </script>405 </body>406 </html>407 


Este ShareCode tiene versiones:
  1. Plataforma de Testing Automa... (28/09/2024)
Enlace
El enlace para compartir es: