1 <!DOCTYPE html>2 <html lang="en">3 <head>4 <meta charset="UTF-8">5 <meta name="viewport" content="width=device-width, initial-scale=1.0">6 <title>Flowtest Execution</title>7 <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">8 </head>9 <body class="bg-gray-100">10 <div class="container mx-auto p-4">11 <h1 class="text-2xl font-bold mb-4">Flowtest Execution</h1>12 <div id="execution-log" class="space-y-4">13 <!-- Logs of requests execution will be appended here -->14 </div>15 <button id="start-execution" class="bg-green-500 text-white px-4 py-2 rounded mt-4">Start Execution</button>16 </div>17 18 <script>19 document.getElementById('start-execution').addEventListener('click', startExecution);20 21 async function startExecution() {22 const logContainer = document.getElementById('execution-log');23 logContainer.innerHTML = ''; // Clear previous logs24 25 const steps = [26 {27 type: 'request',28 method: 'GET',29 url: '{{ base_url }}/users/{{ user_id }}?format=json',30 headers: {31 'Application-ID': '{{ app_id }}'32 },33 body: null,34 asserts: [35 { path: 'response.body.counter', operator: 'is_not', value: 0 }36 ]37 },38 // Add more steps here...39 ];40 41 const variables = {42 base_url: 'https://api.example.com',43 user_id: '12345',44 app_id: 'abcd1234'45 };46 47 for (const step of steps) {48 let logEntry = document.createElement('div');49 logEntry.classList.add('log-entry');50 logEntry.innerHTML = `<p><strong>${step.method}</strong> ${replaceVariables(step.url, variables)}</p>`;51 logContainer.appendChild(logEntry);52 53 try {54 const response = await executeStep(step, variables);55 logEntry.classList.add('success');56 logEntry.innerHTML += `<p>Response: ${JSON.stringify(response)}</p>`;57 58 if (step.asserts) {59 for (const assert of step.asserts) {60 const result = evaluateAssert(response, assert);61 if (!result.passed) {62 throw new Error(`Assert failed: ${result.message}`);63 }64 }65 }66 } catch (error) {67 logEntry.classList.add('error');68 logEntry.innerHTML += `<p>Error: ${error.message}</p>`;69 break; // Stop execution on error70 }71 }72 }73 74 async function executeStep(step, variables) {75 const url = replaceVariables(step.url, variables);76 const headers = Object.keys(step.headers).reduce((acc, key) => {77 acc[key] = replaceVariables(step.headers[key], variables);78 return acc;79 }, {});80 const body = step.body ? JSON.stringify(replaceVariables(JSON.stringify(step.body), variables)) : null;81 82 const options = {83 method: step.method,84 headers: headers,85 body: body86 };87 88 const response = await fetch(url, options);89 90 if (!response.ok) {91 throw new Error(`HTTP error! status: ${response.status}`);92 }93 94 const data = await response.json();95 // Update variables based on response if necessary96 return { status: response.status, headers: response.headers, body: data };97 }98 99 function replaceVariables(template, variables) {100 return template.replace(/{{s*([^}]+)s*}}/g, (match, p1) => variables[p1.trim()] || match);101 }102 103 function evaluateAssert(response, assert) {104 const value = getValueFromPath(response, assert.path);105 let passed = false;106 let message = '';107 108 switch (assert.operator) {109 case 'is_not':110 passed = value !== assert.value;111 message = `${assert.path} should not be ${assert.value}, but was ${value}`;112 break;113 // Add more operators as needed114 default:115 message = `Unknown operator ${assert.operator}`;116 }117 118 return { passed, message };119 }120 121 function getValueFromPath(obj, path) {122 return path.split('.').reduce((acc, part) => acc && acc[part], obj);123 }124 125 </script>126 </body>127 </html>128
Enlace
El enlace para compartir es: