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  .step {17  display: flex;18  align-items: center;19  padding: 8px 12px;20  border: 1px solid #dee2e6;21  border-radius: 5px;22  margin-bottom: 8px;23  }24  .step-type {25  font-weight: bold;26  color: #0d6efd;27  margin-right: 10px;28  min-width: 60px;29  }30  .step-content {31  flex: 1;32  display: flex;33  align-items: center;34  }35  .step-content input,36  .step-content select,37  .step-content textarea {38  margin-right: 8px;39  }40  .step-controls {41  display: flex;42  align-items: center;43  }44  .step-controls button {45  background: none;46  border: none;47  margin-left: 5px;48  color: #6c757d;49  }50  .step-controls button:hover {51  color: #000;52  }53  .add-step {54  text-align: center;55  margin: 20px 0;56  }57  .theme-toggle {58  cursor: pointer;59  }60  .execute-btn {61  background: none;62  border: none;63  color: #198754;64  font-size: 1.2em;65  }66  .execute-btn:hover {67  color: #145c32;68  }69  </style>70 </head>71 <body>72  <!-- Barra de navegación -->73  <nav class="navbar navbar-expand-lg navbar-dark bg-primary">74  <div class="container-fluid">75  <a class="navbar-brand" href="#">76  <!-- Logo -->77  <img src="https://via.placeholder.com/150x40?text=Logo" alt="Logo">78  </a>79  <span class="navbar-text text-white">80  Plataforma de Testing Automatizado de APIs81  </span>82  <button class="btn btn-secondary ms-auto theme-toggle" id="themeToggle">83  <i class="bi bi-moon-fill"></i>84  </button>85  </div>86  </nav>87 88  <!-- Contenido principal -->89  <div id="app" class="container my-4">90  <!-- Lista de pasos -->91  <div v-for="(step, index) in steps" :key="index" class="step">92  <span class="step-type" v-if="step.type === 'variable'">VAR</span>93  <span class="step-type" v-else-if="step.type === 'request'">{{ step.data.method }}</span>94  <span class="step-type" v-else-if="step.type === 'assertion'">ASSERT</span>95 96  <div class="step-content">97  <!-- Contenido según el tipo de paso -->98  <component :is="getStepComponent(step.type)" v-model="step.data"></component>99  </div>100  <div class="step-controls">101  <button @click="moveUp(index)" :disabled="index === 0"><i class="bi bi-arrow-up"></i></button>102  <button @click="moveDown(index)" :disabled="index === steps.length - 1"><i class="bi bi-arrow-down"></i></button>103  <button v-if="step.type === 'request'" @click="executeRequestStep(index)" class="execute-btn"><i class="bi bi-play-circle"></i></button>104  <button @click="removeStep(index)"><i class="bi bi-trash"></i></button>105  </div>106  </div>107 108  <!-- Botones para añadir nuevos pasos -->109  <div class="add-step">110  <button class="btn btn-outline-primary me-2" @click="addStep('variable')">111  <i class="bi bi-sliders"></i> Variable112  </button>113  <button class="btn btn-outline-primary me-2" @click="addStep('request')">114  <i class="bi bi-arrow-up-right-circle"></i> Solicitud HTTP115  </button>116  <button class="btn btn-outline-primary me-2" @click="addStep('assertion')">117  <i class="bi bi-check-circle"></i> Aserción118  </button>119  <!-- Agrega más botones si es necesario -->120  </div>121 122  <!-- Botón de Ejecución -->123  <div class="text-center my-4">124  <button class="btn btn-lg btn-success" @click="executeTest" :disabled="!isExecutable">125  <i class="bi bi-play-fill"></i> Ejecutar Prueba Completa126  </button>127  </div>128 129  <!-- Resultados -->130  <div class="alert" :class="{'alert-success': result?.success, 'alert-danger': !result?.success}" v-if="result">131  <strong>Resultado:</strong> {{ result.message }}132  </div>133  </div>134 135  <!-- Enlaces a Vue.js y Bootstrap JS -->136  <script src="https://cdn.jsdelivr.net/npm/vue@3.3.4/dist/vue.global.prod.js"></script>137  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>138 139  <!-- Componentes para los pasos -->140  <script>141  const VariableStep = {142  template: `143  <div class="d-flex align-items-center">144  <input type="text" class="form-control me-2" v-model="data.name" placeholder="Nombre" style="max-width: 150px;">145  <span>=</span>146  <input type="text" class="form-control ms-2" v-model="data.value" placeholder="Valor" style="max-width: 150px;">147  </div>148  `,149  props: ['modelValue'],150  computed: {151  data: {152  get() { return this.modelValue; },153  set(value) { this.$emit('update:modelValue', value); }154  }155  }156  };157 158  const RequestStep = {159  template: `160  <div class="d-flex align-items-center flex-wrap">161  <select class="form-select me-2" v-model="data.method" style="max-width: 100px;">162  <option>GET</option>163  <option>POST</option>164  <option>PUT</option>165  <option>DELETE</option>166  </select>167  <input type="text" class="form-control me-2" v-model="data.url" placeholder="URL" style="flex: 1;">168  <!-- Botón para mostrar detalles -->169  <button class="btn btn-sm btn-outline-secondary me-2" @click="toggleDetails">170  <i class="bi" :class="showDetails ? 'bi-chevron-up' : 'bi-chevron-down'"></i>171  </button>172  <!-- Detalles opcionales -->173  <div v-if="showDetails" class="w-100 mt-2">174  <!-- Headers -->175  <button class="btn btn-sm btn-outline-secondary me-2" @click="toggleHeaders">176  <i class="bi" :class="showHeaders ? 'bi-dash' : 'bi-plus'"></i> Headers177  </button>178  <!-- Body -->179  <button class="btn btn-sm btn-outline-secondary" @click="toggleBody" v-if="data.method !== 'GET'">180  <i class="bi" :class="showBody ? 'bi-dash' : 'bi-plus'"></i> Body181  </button>182  <!-- Headers -->183  <div v-if="showHeaders" class="mt-2">184  <div v-for="(header, index) in data.headers" :key="index" class="d-flex align-items-center mb-2">185  <input type="text" class="form-control me-2" v-model="header.key" placeholder="Header Key" style="max-width: 150px;">186  <input type="text" class="form-control me-2" v-model="header.value" placeholder="Header Value" style="max-width: 150px;">187  <button class="btn btn-sm btn-outline-danger" @click="removeHeader(index)">188  <i class="bi bi-trash"></i>189  </button>190  </div>191  <button class="btn btn-outline-primary btn-sm" @click="addHeader">192  <i class="bi bi-plus-lg"></i> Agregar Header193  </button>194  </div>195  <!-- Body -->196  <div v-if="showBody" class="mt-2">197  <label class="form-label">Body</label>198  <textarea class="form-control" rows="3" v-model="data.body" placeholder="Cuerpo de la solicitud"></textarea>199  </div>200  </div>201  </div>202  `,203  props: ['modelValue'],204  data() {205  return {206  showDetails: false,207  showHeaders: false,208  showBody: false,209  }210  },211  computed: {212  data: {213  get() { return this.modelValue; },214  set(value) { this.$emit('update:modelValue', value); }215  }216  },217  methods: {218  toggleDetails() {219  this.showDetails = !this.showDetails;220  },221  toggleHeaders() {222  this.showHeaders = !this.showHeaders;223  },224  toggleBody() {225  this.showBody = !this.showBody;226  },227  addHeader() {228  this.data.headers.push({ key: '', value: '' });229  },230  removeHeader(index) {231  this.data.headers.splice(index, 1);232  }233  }234  };235 236  const AssertionStep = {237  template: `238  <div class="d-flex align-items-center">239  <input type="text" class="form-control" v-model="data.condition" placeholder="Condición">240  </div>241  `,242  props: ['modelValue'],243  computed: {244  data: {245  get() { return this.modelValue; },246  set(value) { this.$emit('update:modelValue', value); }247  }248  }249  };250 251  // Instancia de Vue252  const { createApp } = Vue;253 254  createApp({255  components: {256  'variable-step': VariableStep,257  'request-step': RequestStep,258  'assertion-step': AssertionStep,259  // Agrega más componentes si es necesario260  },261  data() {262  return {263  steps: [],264  result: null,265  darkTheme: false,266  }267  },268  computed: {269  isExecutable() {270  // Verifica si hay al menos un paso para ejecutar271  return this.steps.length > 0;272  }273  },274  methods: {275  getStepComponent(type) {276  switch (type) {277  case 'variable':278  return 'variable-step';279  case 'request':280  return 'request-step';281  case 'assertion':282  return 'assertion-step';283  // Otros casos...284  }285  },286  moveUp(index) {287  if (index > 0) {288  [this.steps[index - 1], this.steps[index]] = [this.steps[index], this.steps[index - 1]];289  }290  },291  moveDown(index) {292  if (index < this.steps.length - 1) {293  [this.steps[index], this.steps[index + 1]] = [this.steps[index + 1], this.steps[index]];294  }295  },296  removeStep(index) {297  this.steps.splice(index, 1);298  },299  addStep(type) {300  let newStep = {301  type: type,302  data: {}303  };304  switch (type) {305  case 'variable':306  newStep.data = { name: '', value: '' };307  break;308  case 'request':309  newStep.data = { method: 'GET', url: '', headers: [], body: '' };310  break;311  case 'assertion':312  newStep.data = { condition: '' };313  break;314  // Otros casos...315  }316  this.steps.push(newStep);317  },318  executeTest() {319  // Simulación de ejecución de prueba completa320  this.result = {321  success: true,322  message: 'Prueba completa ejecutada exitosamente.'323  };324  // Animación de scroll al resultado325  this.$nextTick(() => {326  window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });327  });328  },329  executeRequestStep(index) {330  // Simulación de ejecución individual del paso Request331  alert(`Ejecutando solicitud: ${this.steps[index].data.method} ${this.steps[index].data.url}`);332  // Aquí podrías implementar la lógica para ejecutar solo este paso y mostrar resultados333  }334  },335  mounted() {336  // Inicializar el tema según las preferencias del usuario337  const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;338  if (prefersDark) {339  this.toggleTheme();340  }341  }342  }).mount('#app');343 344  // Manejo del botón de cambio de tema fuera de Vue345  document.getElementById('themeToggle').addEventListener('click', () => {346  document.body.classList.toggle('bg-dark');347  document.body.classList.toggle('text-white');348  const icon = document.getElementById('themeToggle').querySelector('i');349  icon.classList.toggle('bi-moon-fill');350  icon.classList.toggle('bi-sun-fill');351  });352  </script>353 </body>354 </html>355 


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