estructura_automation
Version:
Paquete de estructura de automation
109 lines (91 loc) • 3.89 kB
text/typescript
import fs from 'fs';
import path from 'path';
/**
* Calcula la distancia de Levenshtein entre dos strings
*/
const levenshteinDistance = (str1: string, str2: string): number => {
const matrix = Array(str2.length + 1).fill(null).map(() => Array(str1.length + 1).fill(null));
for (let i = 0; i <= str1.length; i++) {
matrix[0][i] = i;
}
for (let j = 0; j <= str2.length; j++) {
matrix[j][0] = j;
}
for (let j = 1; j <= str2.length; j++) {
for (let i = 1; i <= str1.length; i++) {
const indicator = str1[i - 1] === str2[j - 1] ? 0 : 1;
matrix[j][i] = Math.min(
matrix[j][i - 1] + 1, // deletion
matrix[j - 1][i] + 1, // insertion
matrix[j - 1][i - 1] + indicator // substitution
);
}
}
return matrix[str2.length][str1.length];
};
/**
* Calcula el porcentaje de similitud entre dos strings
*/
const calculateSimilarity = (str1: string, str2: string): number => {
const maxLength = Math.max(str1.length, str2.length);
if (maxLength === 0) return 100;
const distance = levenshteinDistance(str1.toLowerCase(), str2.toLowerCase());
return ((maxLength - distance) / maxLength) * 100;
};
/**
* Obtiene el ID de un test basado en su nombre desde la metadata generada.
* @param testName - Nombre exacto del test/scenario.
* @returns ID del test si lo encuentra.
* @throws Error si no encuentra el test.
*/
export const getTestIdByName = (testName: string): string => {
const metadataPath = path.resolve(process.cwd(), 'report/tests-metadata.json');
if (!fs.existsSync(metadataPath)) {
throw new Error('El archivo report/tests-metadata.json no existe. Ejecuta primero el generador de metadata.');
}
const content = fs.readFileSync(metadataPath, 'utf-8');
const metadata = JSON.parse(content);
// Buscar test que coincida exactamente con el nombre
const normalizedTestName = testName.toLowerCase().trim();
const matchingTest = metadata.tests.find((test: { name: string; id: string }) =>
test.name.toLowerCase().trim() === normalizedTestName
);
if (!matchingTest) {
// Calcular similitudes para sugerencias más inteligentes
const suggestions = metadata.tests
.map((test: { name: string; id: string }) => ({
...test,
similarity: calculateSimilarity(testName, test.name)
}))
.filter((test: { similarity: number }) => test.similarity > 50) // Solo mostrar similitudes > 50%
.sort((a: { similarity: number }, b: { similarity: number }) => b.similarity - a.similarity)
.slice(0, 5); // Top 5 sugerencias
let errorMsg = `❌🤦 Test not found 404:\n No se encontró: "${testName}"`;
if (suggestions.length > 0) {
errorMsg += `\n\n💡 ¿Quisiste decir alguna de estas opciones?:`;
suggestions.forEach((test: { name: string; similarity: number }) => {
const index = suggestions.indexOf(test);
errorMsg += `\n ${index + 1}. "${test.name}"`;
});
errorMsg += `\n\n🔍 Las sugerencias están ordenadas de mayor a menor por exactitud. \n\n`;
} else {
// Si no hay sugerencias por similitud, buscar por palabras clave
const keywords = testName.toLowerCase().split(' ').filter(word => word.length > 2);
const keywordMatches = metadata.tests.filter((test: { name: string }) => {
const testNameLower = test.name.toLowerCase();
return keywords.some(keyword => testNameLower.includes(keyword));
}).slice(0, 3);
if (keywordMatches.length > 0) {
errorMsg += `\n\n🔍 Tests que contienen palabras clave similares:`;
keywordMatches.forEach((test: { name: string }) => {
errorMsg += `\n 📋 "${test.name}"`;
});
}
}
// Mostrar solo el mensaje personalizado y detener pruebas sin stack trace
// eslint-disable-next-line no-console
console.error(errorMsg);
process.exit(1);
}
return `${testName}: ${matchingTest.id}`;
};