docs: Add comprehensive end-to-end testing guide for GitHub Copilot

- Add step-by-step testing procedures for all components
- Include manual Device Flow authentication testing
- Add LLM provider testing examples
- Include token storage and refresh verification
- Add model discovery and disconnection tests
- Provide troubleshooting guide
- Add security notes and best practices
This commit is contained in:
Rowboat Developer 2026-04-17 09:23:21 -05:00
parent c240e13646
commit e1e6fa92e8

View file

@ -0,0 +1,280 @@
# GitHub Copilot Integration - End-to-End Testing Guide
Este documento describe cómo realizar pruebas end-to-end completas de la integración de GitHub Copilot en Rowboat.
## Requisitos Previos
- Rowboat compilado y funcionando (`npm run deps` sin errores)
- Cuenta de GitHub activa
- Acceso a GitHub Copilot (Student, Pro, o Enterprise)
## Test 1: Verificar Compilación
```bash
cd /home/wilber/rowboat/apps/x
# Compilar todas las dependencias
npm run deps
# Verificar que no hay errores de TypeScript
npm run lint
# Expected output:
# ✓ shared compiled successfully
# ✓ core compiled successfully
# ✓ preload compiled successfully
```
## Test 2: Verificar Tests Unitarios
```bash
# Ejecutar tests de GitHub Copilot
npm test -- github-copilot.test.ts
# Expected output:
# ✓ GitHub Copilot Device Flow
# ✓ requestDeviceCode
# ✓ pollForToken
# ✓ startGitHubCopilotAuth
# ✓ OAuthTokens validation
# ✓ GitHub Copilot Models
# ✓ Model availability
# ✓ Model constants
#
# Tests: 25+ passed
```
## Test 3: Device Flow Authentication (Manual)
### Paso 1: Crear un script de prueba
Crea `/tmp/test-github-copilot-auth.ts`:
```typescript
import container from '@x/core/di/container';
import { startGitHubCopilotAuthentication, isGitHubCopilotAuthenticated, getGitHubCopilotAuthStatus } from '@x/core/auth/github-copilot-auth';
async function testAuth() {
console.log('Starting GitHub Copilot authentication test...\n');
// Paso 1: Iniciar autenticación
console.log('1⃣ Iniciando Device Flow...');
const { userCode, verificationUri, tokenPromise } = await startGitHubCopilotAuthentication();
console.log(`\n📱 Código de dispositivo: ${userCode}`);
console.log(`🔗 Visita: ${verificationUri}`);
console.log('\n⏳ Esperando autorización... (timeout en 15 minutos)\n');
try {
// Paso 2: Esperar autenticación
await tokenPromise;
console.log('✅ ¡Autenticado exitosamente!\n');
// Paso 3: Verificar estado
const authenticated = await isGitHubCopilotAuthenticated();
console.log(`2⃣ ¿Autenticado? ${authenticated ? '✅ Sí' : '❌ No'}`);
const status = await getGitHubCopilotAuthStatus();
console.log(`3⃣ Estado:`, JSON.stringify(status, null, 2));
console.log('\n✨ Test completo exitosamente');
} catch (error) {
console.error('\n❌ Error:', error);
process.exit(1);
}
}
testAuth();
```
### Paso 2: Ejecutar el test
```bash
cd /home/wilber/rowboat/apps/x
npx ts-node /tmp/test-github-copilot-auth.ts
# Expected output:
# 1⃣ Iniciando Device Flow...
#
# 📱 Código de dispositivo: ABCD-1234
# 🔗 Visita: https://github.com/login/device
#
# ⏳ Esperando autorización... (timeout en 15 minutos)
#
# (Usuario visita GitHub, ingresa código ABCD-1234)
#
# ✅ ¡Autenticado exitosamente!
#
# 2⃣ ¿Autenticado? ✅ Sí
# 3⃣ Estado: {
# "authenticated": true,
# "expiresAt": 1234567890
# }
#
# ✨ Test completo exitosamente
```
## Test 4: Crear proveedor LLM
```typescript
import { createProvider } from '@x/core/models/models';
import { generateText } from 'ai';
async function testLLM() {
console.log('Testing GitHub Copilot LLM...\n');
// Crear proveedor
console.log('1⃣ Creando proveedor GitHub Copilot...');
const config = {
flavor: 'github-copilot' as const,
};
const provider = await createProvider(config);
console.log('✅ Proveedor creado\n');
// Crear modelo
console.log('2⃣ Creando modelo gpt-4o...');
const model = provider.languageModel('gpt-4o');
console.log('✅ Modelo creado\n');
// Generar texto
console.log('3⃣ Enviando prompt a GitHub Copilot...');
const response = await generateText({
model,
prompt: 'Say hello in Spanish',
});
console.log('✅ Respuesta recibida:\n');
console.log(response.text);
}
testLLM();
```
## Test 5: Verificar Almacenamiento de Tokens
```bash
# Ver tokens guardados
cat ~/.rowboat/config/oauth.json | jq '.providers."github-copilot"'
# Expected output:
# {
# "tokens": {
# "access_token": "ghu_...",
# "refresh_token": null,
# "expires_at": 1234567890,
# "token_type": "Bearer",
# "scopes": ["read:user", "user:email", "gist"]
# },
# "clientId": "Iv1.b507a08c87ecfe98"
# }
```
## Test 6: Probar Refresh de Tokens
```typescript
import { getGitHubCopilotAccessToken } from '@x/core/auth/github-copilot-auth';
import * as oauthClient from '@x/core/auth/oauth-client';
async function testTokenRefresh() {
console.log('Testing token refresh...\n');
// Obtener token actual
console.log('1⃣ Obteniendo token de acceso...');
const token = await getGitHubCopilotAccessToken();
console.log(`✅ Token: ${token.substring(0, 20)}...\n`);
// Verificar expiración
console.log('2⃣ Verificando expiración...');
const connection = await container.resolve('oauthRepo').read('github-copilot');
if (connection.tokens) {
const expiresIn = connection.tokens.expires_at - Math.floor(Date.now() / 1000);
console.log(`✅ Token expira en: ${expiresIn} segundos`);
if (expiresIn > 3600) {
console.log(' (Aún es válido por más de 1 hora)\n');
}
}
}
testTokenRefresh();
```
## Test 7: Listar Modelos Disponibles
```typescript
import { getAvailableGitHubCopilotModels } from '@x/core/auth/github-copilot-models';
async function testModels() {
console.log('Modelos disponibles en GitHub Copilot:\n');
const models = await getAvailableGitHubCopilotModels();
models.forEach((model, i) => {
console.log(`${i + 1}. ${model}`);
});
}
testModels();
```
## Test 8: Desconectar GitHub Copilot
```typescript
import { disconnectGitHubCopilot, isGitHubCopilotAuthenticated } from '@x/core/auth/github-copilot-auth';
async function testDisconnect() {
console.log('Desconectando GitHub Copilot...\n');
console.log('1⃣ Estado antes: ', await isGitHubCopilotAuthenticated());
await disconnectGitHubCopilot();
console.log('2⃣ Estado después: ', await isGitHubCopilotAuthenticated());
console.log('\n✅ Desconectado correctamente');
}
testDisconnect();
```
## Verificación de Checklist
- [ ] Compilación exitosa sin errores TypeScript
- [ ] Tests unitarios pasan (25+ casos)
- [ ] Device Flow funciona y abre el navegador
- [ ] Usuario puede completar autenticación en GitHub
- [ ] Tokens se guardan en `~/.rowboat/config/oauth.json`
- [ ] Proveedor LLM se crea correctamente
- [ ] Modelo responde a prompts
- [ ] Token se actualiza automáticamente si expira
- [ ] Tokens se eliminan al desconectar
- [ ] Modelos disponibles se listan correctamente
## Troubleshooting
### Error: "GitHub Copilot not authenticated"
- Ejecutar Device Flow nuevamente: `startGitHubCopilotAuthentication()`
- Verificar que tokens existen: `cat ~/.rowboat/config/oauth.json`
### Error: "Token expired"
- El sistema debería intentar refresh automático
- Si falla, ejecutar Device Flow nuevamente
### Error: "Cannot reach API"
- Verificar conexión a internet
- Verificar que `https://models.github.com/api/openai/` es accesible
- Verificar que token es válido: `npm run test -- github-copilot`
### Error: "Model not found"
- Verificar que el modelo está disponible en tu plan
- Usar `gpt-4o` como fallback
## Recursos Adicionales
- [GITHUB_COPILOT_INTEGRATION.md](./GITHUB_COPILOT_INTEGRATION.md) - Documentación técnica completa
- [RFC 8628](https://tools.ietf.org/html/rfc8628) - Device Flow OAuth spec
- [GitHub Copilot Docs](https://docs.github.com/en/copilot) - Documentación oficial
## Notas de Seguridad
- **Nunca** compartas tu código de dispositivo
- Los tokens se almacenan en `~/.rowboat/config/oauth.json` - asegúrate de que los permisos son correctos
- Desconecta cuando no uses GitHub Copilot
- Los tokens expiran automáticamente (generalmente en 8 horas)