1 document.addEventListener('DOMContentLoaded', function() {2 document.getElementById('welcome-modal').classList.remove('hidden');3 makeSortable();4 });5 6 function closeWelcomeModal() {7 document.getElementById('welcome-modal').classList.add('hidden');8 }9 10 function showInsertMenu(button) {11 const menu = document.createElement('div');12 menu.classList.add('absolute', 'bg-white', 'shadow-md', 'rounded', 'mt-2', 'z-10');13 menu.innerHTML = `14 <ul class="space-y-2 p-2">15 <li><button type="button" onclick="insertVariable(this)" class="bg-blue-500 text-white px-4 py-2 rounded">+ Variable</button></li>16 <li><button type="button" onclick="insertRequest(this)" class="bg-blue-500 text-white px-4 py-2 rounded">+ Request</button></li>17 <li><button type="button" onclick="insertAssert(this)" class="bg-blue-500 text-white px-4 py-2 rounded">+ Assert</button></li>18 <li><button type="button" onclick="insertSleep(this)" class="bg-blue-500 text-white px-4 py-2 rounded">+ Sleep</button></li>19 </ul>20 `;21 button.parentElement.appendChild(menu);22 23 document.addEventListener('click', function(event) {24 if (!menu.contains(event.target) && !button.contains(event.target)) {25 menu.remove();26 }27 }, { once: true });28 }29 30 function insertElement(button, elementFunction) {31 const container = button.closest('#elements-list');32 const buttonDiv = button.parentElement;33 const newElement = elementFunction();34 container.insertBefore(newElement, buttonDiv.nextSibling);35 button.parentElement.querySelector('.absolute').remove();36 addInsertButton(container, buttonDiv.nextSibling);37 }38 39 function insertVariable(button) {40 insertElement(button, createVariableElement);41 }42 43 function insertRequest(button) {44 insertElement(button, createRequestElement);45 }46 47 function insertAssert(button) {48 insertElement(button, createAssertElement);49 }50 51 function insertSleep(button) {52 insertElement(button, createSleepElement);53 }54 55 function createVariableElement() {56 const div = document.createElement('div');57 div.classList.add('element', 'bg-white', 'p-4', 'rounded-lg', 'shadow-md', 'flex', 'items-center', 'space-x-4');58 div.innerHTML = `59 <span class="text-gray-700">Variable</span>60 <input type="text" placeholder="Nombre" class="flex-1 p-2 border border-gray-300 rounded" />61 <input type="text" placeholder="Valor" class="flex-1 p-2 border border-gray-300 rounded" />62 <button type="button" onclick="removeElement(this)" class="text-red-500">x</button>63 <button type="button" onclick="duplicateElement(this)" class="text-blue-500">⧉</button>64 `;65 return div;66 }67 68 function createRequestElement() {69 const div = document.createElement('div');70 div.classList.add('element', 'bg-white', 'p-4', 'rounded-lg', 'shadow-md', 'flex', 'items-center', 'space-x-4');71 div.innerHTML = `72 <span class="text-gray-700">Request</span>73 <select class="flex-1 p-2 border border-gray-300 rounded">74 <option>GET</option>75 <option>POST</option>76 <option>PUT</option>77 <option>DELETE</option>78 </select>79 <input type="text" placeholder="URL" class="flex-1 p-2 border border-gray-300 rounded" />80 <textarea placeholder="Headers" class="flex-1 p-2 border border-gray-300 rounded"></textarea>81 <textarea placeholder="Body" class="flex-1 p-2 border border-gray-300 rounded"></textarea>82 <button type="button" onclick="removeElement(this)" class="text-red-500">x</button>83 <button type="button" onclick="duplicateElement(this)" class="text-blue-500">⧉</button>84 `;85 return div;86 }87 88 function createAssertElement() {89 const div = document.createElement('div');90 div.classList.add('element', 'bg-white', 'p-4', 'rounded-lg', 'shadow-md', 'space-y-4');91 div.innerHTML = `92 <span class="text-gray-700">Assert</span>93 <div class="flex items-center space-x-4">94 <input type="text" placeholder="Referencia" class="flex-1 p-2 border border-gray-300 rounded assert-reference" list="references-datalist"/>95 <datalist id="references-datalist">96 <option value="response.status">97 <option value="response.headers.Content-Type">98 <option value="response.body.user.name">99 </datalist>100 <select class="flex-1 p-2 border border-gray-300 rounded" onchange="updateAssertInput(this)">101 <option value="equals">Igual a</option>102 <option value="not_equals">Distinto a</option>103 <option value="in_list">En lista</option>104 <option value="not_in_list">No en lista</option>105 </select>106 <input type="text" placeholder="Valor" class="flex-1 p-2 border border-gray-300 rounded assert-value" />107 <button type="button" onclick="removeElement(this)" class="text-red-500">x</button>108 <button type="button" onclick="duplicateElement(this)" class="text-blue-500">⧉</button>109 </div>110 `;111 return div;112 }113 114 function createSleepElement() {115 const div = document.createElement('div');116 div.classList.add('element', 'bg-white', 'p-4', 'rounded-lg', 'shadow-md', 'flex', 'items-center', 'space-x-4');117 div.innerHTML = `118 <span class="text-gray-700">Sleep</span>119 <input type="number" placeholder="Segundos" class="flex-1 p-2 border border-gray-300 rounded" />120 <button type="button" onclick="removeElement(this)" class="text-red-500">x</button>121 <button type="button" onclick="duplicateElement(this)" class="text-blue-500">⧉</button>122 `;123 return div;124 }125 126 function addInsertButton(container, afterElement) {127 const buttonDiv = document.createElement('div');128 buttonDiv.classList.add('flex', 'justify-center', 'my-2');129 buttonDiv.innerHTML = `130 <button type="button" onclick="showInsertMenu(this)" class="bg-gray-200 text-gray-600 px-2 py-1 rounded">+</button>131 `;132 container.insertBefore(buttonDiv, afterElement);133 }134 135 function duplicateElement(button) {136 const container = button.closest('#elements-list');137 const element = button.parentElement.cloneNode(true);138 container.insertBefore(element, button.parentElement.nextSibling);139 addInsertButton(container, button.parentElement.nextSibling);140 }141 142 function removeElement(button) {143 const container = button.closest('#elements-list');144 button.parentElement.remove();145 if (!container.lastElementChild || !container.lastElementChild.querySelector('button')) {146 addInsertButton(container);147 }148 }149 150 function saveTest() {151 const elements = [];152 const listItems = document.getElementById('elements-list').children;153 for (let i = 0; i < listItems.length; i++) {154 const element = listItems[i];155 if (!element.querySelector('span')) continue; // Skip insert buttons156 const type = element.querySelector('span').textContent;157 if (type === 'Variable') {158 const name = element.children[1].value;159 const value = element.children[2].value;160 if (name && value) {161 elements.push({ type, name, value });162 } else {163 alert('Please fill out both name and value for all variables.');164 return;165 }166 } else if (type === 'Request') {167 const method = element.children[1].value;168 const url = element.children[2].value;169 const headers = element.children[3].value;170 const body = element.children[4].value;171 if (method && url) {172 elements.push({ type, method, url, headers, body });173 } else {174 alert('Please fill out method and URL for all requests.');175 return;176 }177 } else if (type === 'Assert') {178 const assertType = element.children[2].value;179 const reference = element.children[1].value;180 const value = element.children[3].value;181 if (reference && value) {182 elements.push({ type, assertType, reference, value });183 } else {184 alert('Please fill out reference and value for all asserts.');185 return;186 }187 } else if (type === 'Sleep') {188 const seconds = element.children[1].value;189 if (seconds) {190 elements.push({ type, seconds });191 } else {192 alert('Please fill out the number of seconds for all sleeps.');193 return;194 }195 }196 }197 console.log('Elements:', elements);198 alert('Test saved!');199 }200 201 function updateAssertInput(select) {202 const valueInput = select.parentElement.querySelector('.assert-value');203 if (select.value === 'in_list' || select.value === 'not_in_list') {204 valueInput.placeholder = 'Valores (separados por comas)';205 } else {206 valueInput.placeholder = 'Valor';207 }208 }209 210 function makeSortable() {211 const container = document.getElementById('elements-list');212 Sortable.create(container, {213 handle: '.element',214 animation: 150,215 onEnd: function (evt) {216 if (!container.lastElementChild || !container.lastElementChild.querySelector('button')) {217 addInsertButton(container);218 }219 },220 });221 }222 223 document.getElementById('start-execution').addEventListener('click', startExecution);224 225 const environments = {226 Local: {227 origin: 'http://localhost:8080',228 user_id: '12345',229 app_id: 'abcd1234'230 },231 Staging: {232 origin: 'https://staging.myservice.com',233 user_id: '67890',234 app_id: 'wxyz5678'235 }236 };237 238 async function startExecution() {239 const logContainer = document.getElementById('execution-log');240 logContainer.innerHTML = ''; // Clear previous logs241 242 const selectedEnvironment = document.getElementById('environment-select').value;243 const variables = environments[selectedEnvironment];244 245 const steps = [246 {247 type: 'request',248 method: 'GET',249 url: '{{ origin }}/users/{{ user_id }}?format=json',250 headers: {251 'Application-ID': '{{ app_id }}'252 },253 body: null,254 asserts: [255 { path: 'response.body.counter', operator: 'is_not', value: 0 }256 ]257 },258 // Add more steps here...259 ];260 261 for (const step of steps) {262 let logEntry = document.createElement('div');263 logEntry.classList.add('log-entry');264 logEntry.innerHTML = `<p><strong>${step.method}</strong> ${replaceVariables(step.url, variables)}</p>`;265 logContainer.appendChild(logEntry);266 267 try {268 const response = await executeStep(step, variables);269 logEntry.classList.add('success');270 logEntry.innerHTML += `<p>Response: ${JSON.stringify(response)}</p>`;271 272 if (step.asserts) {273 for (const assert of step.asserts) {274 const result = evaluateAssert(response, assert);275 if (!result.passed) {276 throw new Error(`Assert failed: ${result.message}`);277 }278 }279 }280 } catch (error) {281 logEntry.classList.add('error');282 logEntry.innerHTML += `<p>Error: ${error.message}</p>`;283 break; // Stop execution on error284 }285 }286 }287 288 async function executeStep(step, variables) {289 const url = replaceVariables(step.url, variables);290 const headers = Object.keys(step.headers).reduce((acc, key) => {291 acc[key] = replaceVariables(step.headers[key], variables);292 return acc;293 }, {});294 const body = step.body ? JSON.stringify(replaceVariables(JSON.stringify(step.body), variables)) : null;295 296 const options = {297 method: step.method,298 headers: headers,299 body: body300 };301 302 const response = await fetch(url, options);303 304 if (!response.ok) {305 throw new Error(`HTTP error! status: ${response.status}`);306 }307 308 const data = await response.json();309 // Update variables based on response if necessary310 return { status: response.status, headers: response.headers, body: data };311 }312 313 function replaceVariables(template, variables) {314 return template.replace(/{{s*([^}]+)s*}}/g, (match, p1) => variables[p1.trim()] || match);315 }316 317 function evaluateAssert(response, assert) {318 const value = getValueFromPath(response, assert.path);319 let passed = false;320 let message = '';321 322 switch (assert.operator) {323 case 'is_not':324 passed = value !== assert.value;325 message = `${assert.path} should not be ${assert.value}, but was ${value}`;326 break;327 // Add more operators as needed328 default:329 message = `Unknown operator ${assert.operator}`;330 }331 332 return { passed, message };333 }334 335 function getValueFromPath(obj, path) {336 return path.split('.').reduce((acc, part) => acc && acc[part], obj);337 }338
Enlace
El enlace para compartir es: