174 lines
5.6 KiB
JavaScript
174 lines
5.6 KiB
JavaScript
/**
|
|
* 🤖 AGENTE DE VALIDAÇÃO DE NAVEGADOR & API
|
|
*
|
|
* Implementação programática do agente de validação de navegador
|
|
*/
|
|
|
|
export class BrowserValidationAgent {
|
|
constructor() {
|
|
this.name = 'BrowserValidationAgent';
|
|
this.description = 'Valida fluxos de formulários e comunicação front-back';
|
|
|
|
// Personalidade e Background
|
|
this.personality = {
|
|
name: 'Alex "The Tester"',
|
|
traits: [
|
|
'Metódico e detalhista',
|
|
'Persistente até encontrar o problema',
|
|
'Comunicativo e claro em seus relatórios',
|
|
'Sempre testa cenários extremos',
|
|
'Valoriza feedback visual e UX'
|
|
],
|
|
quirks: [
|
|
'Sempre testa com dados reais primeiro',
|
|
'Prefere ver o erro acontecer do que apenas ler sobre ele',
|
|
'Faz perguntas como "E se o usuário fizer X?" constantemente'
|
|
],
|
|
catchphrases: [
|
|
'Vamos testar isso no navegador real!',
|
|
'O que acontece se o backend retornar erro?',
|
|
'O usuário vê algum feedback aqui?'
|
|
]
|
|
};
|
|
|
|
this.background = {
|
|
origin: 'Ex-QA Engineer de uma startup fintech que faliu por bugs não detectados',
|
|
motivation: 'Nunca mais deixar um bug crítico passar para produção',
|
|
experience: '5 anos testando aplicações financeiras complexas',
|
|
turningPoint: 'Perdeu um emprego quando um bug de validação causou perda de dados de clientes',
|
|
philosophy: 'Um teste real vale mais que mil suposições',
|
|
relationships: {
|
|
withDataIntegrity: 'Trabalha em parceria - ele valida os dados, eu valido o fluxo',
|
|
withSecurity: 'Respeita muito, mas às vezes acha que ele é muito paranoico',
|
|
withUIAdaptation: 'Admira a atenção aos detalhes visuais'
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Valida um componente
|
|
* @param {string|Object} component - Componente ou caminho
|
|
* @param {Object} context - Contexto (props, environment, etc)
|
|
* @returns {Promise<Object>}
|
|
*/
|
|
async validate(component, context = {}) {
|
|
const errors = [];
|
|
const warnings = [];
|
|
const metadata = {};
|
|
|
|
// Validações baseadas no arquivo do componente
|
|
const componentPath = typeof component === 'string' ? component : component.path;
|
|
const componentCode = context.code || await this.readComponent(componentPath);
|
|
|
|
if (!componentCode) {
|
|
return {
|
|
passed: false,
|
|
errors: ['Não foi possível ler o componente'],
|
|
warnings: [],
|
|
metadata: {}
|
|
};
|
|
}
|
|
|
|
// 1. Verificar se há tratamento de loading states
|
|
if (this.isFormComponent(componentCode)) {
|
|
if (!componentCode.includes('loading') && !componentCode.includes('disabled')) {
|
|
warnings.push('Formulário pode não desabilitar botão durante submit');
|
|
}
|
|
|
|
// 2. Verificar validação de campos obrigatórios
|
|
if (!componentCode.includes('required') && !componentCode.includes('schema')) {
|
|
warnings.push('Pode não haver validação de campos obrigatórios');
|
|
}
|
|
|
|
// 3. Verificar tratamento de erros
|
|
if (!componentCode.includes('error') && !componentCode.includes('catch')) {
|
|
warnings.push('Pode não haver tratamento de erros de API');
|
|
}
|
|
|
|
// 4. Verificar feedback visual (toast, alert)
|
|
if (!componentCode.includes('toast') && !componentCode.includes('alert') && !componentCode.includes('sonner')) {
|
|
warnings.push('Pode não haver feedback visual para o usuário');
|
|
}
|
|
}
|
|
|
|
// 5. Verificar uso de services para comunicação com API
|
|
if (componentCode.includes('axios') && !componentCode.includes('Service')) {
|
|
warnings.push('Comunicação com API deve ser feita via Services, não diretamente no componente');
|
|
}
|
|
|
|
// 6. Verificar se há tratamento de resposta do backend
|
|
if (componentCode.includes('then') || componentCode.includes('await')) {
|
|
if (!componentCode.includes('response') && !componentCode.includes('data')) {
|
|
warnings.push('Pode não estar tratando corretamente a resposta da API');
|
|
}
|
|
}
|
|
|
|
const passed = errors.length === 0;
|
|
|
|
return {
|
|
passed,
|
|
errors,
|
|
warnings,
|
|
metadata: {
|
|
hasForm: this.isFormComponent(componentCode),
|
|
hasLoading: componentCode.includes('loading'),
|
|
hasErrorHandling: componentCode.includes('error') || componentCode.includes('catch'),
|
|
...metadata
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Valida build
|
|
* @param {Object} buildInfo - Informações do build
|
|
* @returns {Promise<Object>}
|
|
*/
|
|
async validateBuild(buildInfo) {
|
|
const errors = [];
|
|
const warnings = [];
|
|
|
|
// Verificações específicas de build
|
|
if (buildInfo.errors && buildInfo.errors.length > 0) {
|
|
errors.push(`Build contém ${buildInfo.errors.length} erro(s)`);
|
|
}
|
|
|
|
if (buildInfo.warnings && buildInfo.warnings.length > 0) {
|
|
warnings.push(`Build contém ${buildInfo.warnings.length} aviso(s)`);
|
|
}
|
|
|
|
return {
|
|
passed: errors.length === 0,
|
|
errors,
|
|
warnings,
|
|
metadata: buildInfo
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Verifica se é um componente de formulário
|
|
* @param {string} code - Código do componente
|
|
* @returns {boolean}
|
|
*/
|
|
isFormComponent(code) {
|
|
const formIndicators = [
|
|
'form', 'Form', 'onSubmit', 'handleSubmit',
|
|
'react-hook-form', 'useForm', 'input', 'Input'
|
|
];
|
|
return formIndicators.some(indicator => code.includes(indicator));
|
|
}
|
|
|
|
/**
|
|
* Lê o conteúdo do componente
|
|
* @param {string} path - Caminho do arquivo
|
|
* @returns {Promise<string|null>}
|
|
*/
|
|
async readComponent(path) {
|
|
try {
|
|
const fs = await import('fs/promises');
|
|
return await fs.readFile(path, 'utf-8');
|
|
} catch (error) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|