dan085 avatar

blacksugar-testing-system

Sistema maestro consolidado de pruebas para BlackSugar21. Gestión completa de datos de prueba incluy

by dan085|Open Source

BlackSugar21 Testing System - Comprehensive Skill

Table of Contents


Overview

Sistema unificado e interactivo de gestión de datos de prueba para BlackSugar21. Consolida todas las operaciones de testing en un único script maestro con menú categorizado, soporte multi-usuario, y limpieza granular.

⚡ QUICK REFERENCE

Inicio Rápido

cd /Users/daniel/IdeaProjects/Public-BlackSugar21/scripts
node test-system-unified.js

Opciones del Menú

OpciónAcciónUsuarios
1Listar matchesAmbos
2Crear 1-10 matchesAmbos
3Enviar mensajeReordena matches
4Generar 3-10 escenarioCon conversaciones
5Crear 5-30 discoveryPara HomeView
6Verificar orden matchesValidar sequence
7Verificar sistemaEstadísticas
8Limpieza selectivaMatches/Discovery
9Limpieza completaTODO
10Cambiar usuarioDaniel/Rosita

Test Users

  • Daniel: sU8xLiwQWNXmbYdR63p1uO6TSm72 (hombre → ver mujeres)
  • Rosita: DsDSK5xqEZZXAIKxtIKyBGntw8f2 (mujer → ver hombres)

Workflows Típicos

# Setup inicial
node test-system-unified.js
# Option 7 (verify) → Option 2 (create 5) → Option 5 (create 20)

# Test reordering
# Option 3 (send msg) → Watch in app → Option 6 (verify)

# Multi-user testing
# Option 10 (change user) → repeat setup

Patrones Clave

  • Email patterns: test_match_*@bstest.com, discovery_*@bstest-discovery.com
  • Firestore flags: isTest: true, isTestUser: true, isDiscoveryProfile: true
  • Timestamps: Staggered automáticamente para orden natural
  • Photos: 5 photos per profile from randomuser.me

🧪 CI Matrix (activo desde 2026-04-18)

Ver .github/workflows/ci.yml + .github/workflows/e2e-smoke.yml.

Offline gate (cada push + PR)

Trigger: push a main o pull_request que toque functions/**. Runtime: <15s. Secrets: ninguno.

Corre npm test desde functions/, que ejecuta 4 suites puramente static-analysis (sin admin SDK, sin Gemini API — usan fs.readFileSync + regex sobre lib/*.js):

ArchivoAssertsCubre
test-comprehensive-300.js333regex, sanitization, guards, clamping, i18n, safety
test-post-deploy-350.js394code patterns, RAG/Coach/Moderation/Places config
test-discovery-v2-parity.js111orientation, userType, reviewer bypass, gender_mismatch, super-like
test-situation-sim.js2710-lang directives, edge cases (XSS/SQL/RTL)
TOTAL865block merge on any failure

E2E smoke (nightly + manual)

Trigger: workflow_dispatch (manual) + schedule: cron '0 7 * * *' (07:00 UTC nightly). Runtime: <5 min. Secrets: FIREBASE_SERVICE_ACCOUNT_BLACK_SUGAR_21, GEMINI_API_KEY, REVIEWER_UID (opcional).

Corre functions/test-e2e-smoke.js que hace 6 live checks:

  1. Firestore reachable (reviewer doc)
  2. Geohash range query (mirrors discovery-feed.js:130 — NO composite index, filter in-memory)
  3. Reviewer isTest profiles reachable
  4. Remote Config reachable (skip gracefully si SA sin permission)
  5. coachKnowledge RAG non-empty
  6. multiUniverseCache docs carry cacheSchemaVersion (>= 3)

Local:

cd functions
GOOGLE_APPLICATION_CREDENTIALS=/path/to/sa.json \
GOOGLE_CLOUD_PROJECT=black-sugar21 \
npm run e2e:smoke

npm scripts disponibles

npm test              # offline suite (865 asserts, gate CI)
npm run test:multiverse  # local only (lazy admin SDK init via places-helpers)
npm run e2e:smoke     # live suite (needs credentials)

Reglas para extender

  • Nuevo test estático → agregar al comando encadenado en npm test. Debe terminar con process.exit(failed > 0 ? 1 : 0).
  • Nuevo test live → agregar a test-e2e-smoke.js como nueva async function test<Name>() en lugar de nuevo archivo. Degrade graciosamente con console.warn + passed++ para fallos esperables (permission, index missing).
  • NO agregar tests live al npm test — rompería CI en runners sin secrets.

System Context

Testing System Details

  • Name: test-system-unified.js
  • Type: Node.js Interactive CLI Tool
  • Location: /scripts/test-system-unified.js
  • Purpose: Gestión completa de datos de prueba
  • Users Supported: Daniel (sU8xLiwQWNXmbYdR63p1uO6TSm72), Rosita (DsDSK5xqEZZXAIKxtIKyBGntw8f2)
  • Backend: Firebase Admin SDK
  • Replaced Scripts: 19+ legacy scripts consolidados

Technology Stack

  • Runtime: Node.js v18+
  • SDK: Firebase Admin SDK
  • Database: Firestore
  • Auth: Firebase Authentication
  • Storage: Firebase Storage
  • Interface: readline (interactive CLI)

Key Capabilities

  1. Match Management - Crear, listar, enviar mensajes, verificar orden
  2. Discovery Profiles - Generar perfiles para swipe/HomeView con fotos
  3. Verification - Diagnóstico completo del sistema
  4. Selective Cleanup - Limpieza granular por tipo de datos
  5. Multi-User Support - Alternar entre usuarios de prueba
  6. Real-time Testing - Probar reordenamiento de matches en tiempo real

Project Structure

scripts/
├── 📄 Documentation
│   ├── README.md                        # Guía principal
│   ├── TEST_SYSTEM_UNIFIED_README.md    # Docs completas
│   ├── SYSTEM_MAP.md                    # Mapa visual y flujos
│   ├── QUICKSTART.md                    # Inicio rápido
│   ├── SCENARIO_GENERATOR_GUIDE.md      # Escenarios avanzados
│   └── HOME_VIEW_TEST_PLAN.md           # Plan testing HomeView
│
├── 🎯 Main Script (CORE)
│   └── test-system-unified.js           # ⭐ Sistema maestro
│
├── 🔧 Auxiliary Scripts
│   ├── generate-avatar-urls.js          # Generar URLs avatares
│   ├── get-user-email.js                # Lookup email por UID
│   ├── optimize-matches-and-images.js   # Optimizaciones
│   ├── update-avatars-only.js           # Actualizar avatares
│   ├── upload-test-avatars.js           # Subir avatares
│   └── upload-test-avatars-to-storage.js # Subir a Storage
│
└── ⚙️ Configuration
    ├── serviceAccountKey.json           # Firebase credentials (gitignored)
    ├── serviceAccountKey.example.json   # Template
    └── test-avatars-urls.json           # Avatar URLs cache

Core System Architecture

test-system-unified.js - Main Script

User Selection System

const TEST_USERS = {
  daniel: {
    email: 'dverdugo85@gmail.com',
    uid: 'sU8xLiwQWNXmbYdR63p1uO6TSm72',
    name: 'Daniel'
  },
  rosita: {
    email: 'rosita@example.com',
    uid: 'DsDSK5xqEZZXAIKxtIKyBGntw8f2',
    name: 'Rosita'
  }
};

let CURRENT_USER = null; // Set by selectTestUser()

Menu Structure

🧪 SISTEMA UNIFICADO DE PRUEBAS
════════════════════════════════════════════

📋 GESTIÓN DE MATCHES
1. Listar matches actuales
2. Crear matches de prueba (1-10)
3. Enviar mensaje a un match
4. Generar escenario completo (3-10)

🎯 PERFILES DE DISCOVERY
5. Crear perfiles para HomeView/Swipe (5-30)

🔍 VERIFICACIÓN Y DIAGNÓSTICO
6. Verificar orden de matches
7. Verificar sistema completo

🧹 LIMPIEZA
8. Limpieza selectiva (por tipo)
9. Limpieza completa (todo)

⚙️ CONFIGURACIÓN
10. Cambiar usuario de prueba
11. Salir

Data Types and Structures

Match Users

interface MatchUser {
  // Firebase Auth
  email: string;  // "test_match_*@bstest.com" | "test_scenario_*@bstest.com"
  password: string; // "Test1234!"
  uid: string;
  
  // Firestore Profile (profiles collection)
  profile: {
    name: string;
    gender: 'male' | 'female';
    userType: 'ELITE' | 'ELITE' | 'PRIME'; // UI: 💎 Elite / 💎 Elite / 🌟 Prime
    age: number;
    city: string;
    createdAt: Timestamp;
    isTest: true;  // Flag for identification
  };
  
  // Match (matches collection)
  match: {
    userId1: string;  // CURRENT_USER.uid
    userId2: string;  // created user uid
    timestamp: Timestamp;  // Staggered timestamps
    lastMessage: string;
    lastMessageSeq: number;
    lastMessageTimestamp: Timestamp;
    createdAt: Timestamp;
    isTest: true;
  };
  
  // Initial Message (messages collection)
  message: {
    matchId: string;
    senderId: string;
    text: string;
    timestamp: Timestamp;
    createdAt: Timestamp;
  };
}

Discovery Profiles

interface DiscoveryProfile {
  // Firebase Auth
  email: string;  // "discovery_*@bstest-discovery.com"
  password: string; // "Test1234!"
  uid: string;
  
  // Firestore Profile (profiles collection)
  profile: {
    name: string;  // "FirstName LastName"
    gender: 'male' | 'female';
    userType: 'ELITE' | 'ELITE' | 'PRIME'; // UI: 💎 Elite / 💎 Elite / 🌟 Prime
    age: number;  // 22-40
    city: string;  // Santiago, Valparaíso, Concepción, Viña del Mar
    bio: string;  // From predefined list
    pictureUrls: string[];  // 5 photos from randomuser.me
    createdAt: Timestamp;
    isDiscoveryProfile: true;  // Flag for identification
    isTest: true;
  };
}

Test Data Identification Patterns

Email Patterns:

  • Match users: test_match_*@bstest.com, test_scenario_*@bstest.com
  • Discovery profiles: discovery_*@bstest-discovery.com

Firestore Flags:

  • isTest: true - General test data marker
  • isTestUser: true - Legacy match users
  • isDiscoveryProfile: true - Discovery profiles marker

Core Functions Reference

1. User Selection

async function selectTestUser()
  • Shows interactive menu to select Daniel or Rosita
  • Verifies user exists in Firebase Auth
  • Updates CURRENT_USER global variable
  • Called at startup and via option 10

2. Match Management Functions

listDanielMatches()

async function listDanielMatches(): Promise<DocumentSnapshot[]>
  • Queries matches where userId1 == CURRENT_USER.uid
  • Queries matches where userId2 == CURRENT_USER.uid
  • Combines and sorts by timestamp DESC → lastMessageSeq DESC
  • Fetches other user profiles
  • Returns sorted array of match documents

createTestMatches()

async function createTestMatches()
  • Prompts for count (1-10)
  • Creates users in Firebase Auth
  • Creates profiles in Firestore
  • Creates matches with staggered timestamps
  • Creates initial messages
  • Uses batch operations for efficiency

sendMessageToMatch()

async function sendMessageToMatch(matches: DocumentSnapshot[])
  • Shows numbered list of matches
  • Prompts for match selection and message
  • Countdown timer (5 seconds) for app observation
  • Updates match document (timestamp, lastMessage, lastMessageSeq)
  • Creates message document
  • Verifies new order and displays results

generateTestScenario()

async function generateTestScenario()
  • Prompts for count (3-10)
  • Creates multiple users with profiles
  • Creates matches with staggered timestamps
  • Sends multiple messages per match (up to 3)
  • Creates realistic conversation scenarios
  • Displays expected order

3. Discovery Profile Functions

createDiscoveryProfiles()

async function createDiscoveryProfiles()
  • Prompts for count (5-30)
  • Alternates gender for variety
  • Determines appropriate userType based on CURRENT_USER
  • Generates 5 photos per profile (randomuser.me)
  • Creates complete profiles with bio, age, city
  • Sets isDiscoveryProfile and isTest flags

4. Verification Functions

verifyMatchOrder()

async function verifyMatchOrder()
  • Fetches all matches for CURRENT_USER
  • Sorts by timestamp DESC → lastMessageSeq DESC
  • Displays detailed list with timestamps and sequences
  • Validates ordering logic

verifySystem()

async function verifySystem()
  • Counts matches for current user
  • Counts discovery profiles
  • Counts profiles with photos
  • Counts test users in Auth
  • Counts active conversations
  • Displays comprehensive statistics
  • Provides suggestions based on state

5. Cleanup Functions

cleanupTestData()

async function cleanupTestData()
  • Lists all test users (@bstest.com, @bstest-discovery.com)
  • Requires confirmation
  • Deletes matches (both userId1 and userId2)
  • Deletes messages in matches
  • Deletes profiles from Firestore
  • Deletes users from Auth
  • Displays detailed summary

selectiveCleanup()

async function selectiveCleanup()
  • Submenu with 4 options
  • cleanupMatchesOnly() - Keeps discovery profiles
  • cleanupDiscoveryOnly() - Keeps matches
  • cleanupKeepScenario() - Reserved for future implementation
  • cleanupTestData() - Complete cleanup

Query Optimization Patterns

Avoiding Composite Indexes

// ❌ BAD: Requires composite index
const matches = await db.collection('matches')
  .where('userId1', '==', userId)
  .orderBy('timestamp', 'desc')
  .get();

// ✅ GOOD: Single field queries, sort in memory
const matches1 = await db.collection('matches')
  .where('userId1', '==', userId)
  .get();
  
const matches2 = await db.collection('matches')
  .where('userId2', '==', userId)
  .get();

const allMatches = [...matches1.docs, ...matches2.docs];
allMatches.sort((a, b) => {
  const tsA = a.data().timestamp?.toMillis() || 0;
  const tsB = b.data().timestamp?.toMillis() || 0;
  if (tsB !== tsA) return tsB - tsA;
  return (b.data().lastMessageSeq || 0) - (a.data().lastMessageSeq || 0);
});

Timestamp Staggering

// Crear timestamps escalonados para orden natural
for (let i = 0; i < count; i++) {
  const minutesAgo = (count - i) * 60 * 1000;
  const timestamp = new Date(Date.now() - minutesAgo);
  
  await db.collection('matches').doc(matchId).set({
    // ... other fields
    timestamp: admin.firestore.Timestamp.fromDate(timestamp),
  });
}

Common Testing Workflows

Workflow 1: Initial Setup

# Start script
node test-system-unified.js

# Select user (1: Daniel, 2: Rosita)
# Option 7: Verify system → See current state
# Option 5: Create 20-30 discovery profiles
# Option 4: Generate 5-10 matches with conversations
# Option 7: Verify system → Confirm all OK
# Open app and test

Workflow 2: Test Match Reordering

# Option 1: List matches → See current order
# Option 3: Send message → Watch match move to #1
# Option 6: Verify order → Confirm correct ordering
# Option 1: List matches → Verify new position

Workflow 3: Multi-User Testing

# User: Daniel
# Option 2: Create 5 matches
# Option 5: Create 15 discovery profiles
# Option 10: Change to Rosita
# Option 2: Create 5 matches
# Option 5: Create 15 discovery profiles
# Test both apps simultaneously

Workflow 4: Selective Cleanup

# Option 8: Selective cleanup
#   ├─ Option 1: Only matches (keep discovery)
#   ├─ Option 2: Only discovery (keep matches)
#   ├─ Option 3: Keep last scenario
#   └─ Option 4: Complete cleanup

Color Console System

const colors = {
  reset: '\x1b[0m',
  bright: '\x1b[1m',
  red: '\x1b[31m',     // Errors
  green: '\x1b[32m',   // Success
  yellow: '\x1b[33m',  // Warnings
  blue: '\x1b[34m',    // Reserved
  magenta: '\x1b[35m', // Special
  cyan: '\x1b[36m',    // Info/Headers
};

function log(message, color = 'reset') {
  console.log(`${colors[color]}${message}${colors.reset}`);
}

Usage Conventions:

  • 🔵 Cyan → Títulos, información general
  • 🟢 Green → Operaciones exitosas, confirmaciones
  • 🟡 Yellow → Advertencias, esperas, procesos
  • 🔴 Red → Errores críticos
  • ⚪ Bright → Encabezados importantes, separadores

Test Data Naming Conventions

Names Arrays

const testNames = {
  women: ['Sofia', 'Isabella', 'Valentina', 'Camila', 'Martina', 
          'Lucia', 'Emma', 'Paula', 'Julia', 'Amanda'],
  men: ['Carlos', 'Miguel', 'Alejandro', 'Diego', 'Sebastian', 
        'Mateo', 'Lucas', 'Santiago', 'Nicolas', 'Andres']
};

const lastNames = ['Martinez', 'Lopez', 'Garcia', 'Rodriguez', 
                   'Fernandez', 'Sanchez', 'Ramirez', 'Torres'];

const bios = [
  'Amante del buen vino y viajes exóticos 🍷✈️',
  'Emprendedor exitoso buscando conexión genuina 💼',
  'Aventurera, disfruto de la vida al máximo 🌟',
  // ... more bios
];

Photo URL Generation

// 5 photos per profile, rotating indexes 1-99
function getProfilePhotos(isMale, profileIndex) {
  const photos = [];
  const baseIndex = (profileIndex * 3) % 99;
  
  for (let i = 0; i < 5; i++) {
    const photoIndex = (baseIndex + i) % 99 + 1;
    const gender = isMale ? 'men' : 'women';
    photos.push(`https://randomuser.me/api/portraits/${gender}/${photoIndex}.jpg`);
  }
  
  return photos;
}

Error Handling Patterns

Authentication Errors

try {
  const userRecord = await auth.createUser({
    email: email,
    password: password,
    displayName: name
  });
} catch (error) {
  if (error.code === 'auth/email-already-exists') {
    log(`⚠️ Email ya existe, saltando...`, 'yellow');
    continue;
  }
  log(`❌ Error creando usuario: ${error.message}`, 'red');
}

Firestore Errors

try {
  await db.collection('matches').doc(matchId).set(data);
} catch (error) {
  if (error.code === 'permission-denied') {
    log(`❌ Permisos insuficientes en Firestore`, 'red');
  } else if (error.code === 'unavailable') {
    log(`⚠️ Firestore temporalmente no disponible, reintentando...`, 'yellow');
    await new Promise(resolve => setTimeout(resolve, 2000));
    // Retry logic
  }
}

User Input Validation

const numMatches = await question('¿Cuántos matches? (1-10): ');
const count = parseInt(numMatches);

if (isNaN(count) || count < 1 || count > 10) {
  log('❌ Número inválido. Debe ser entre 1 y 10', 'red');
  return;
}

Performance Optimization Tips

1. Batch Operations

// ✅ GOOD: Use batch for multiple writes
const batch = db.batch();

for (let i = 0; i < count; i++) {
  const profileRef = db.collection('profiles').doc(userId);
  batch.set(profileRef, profileData);
  
  const matchRef = db.collection('matches').doc(matchId);
  batch.set(matchRef, matchData);
}

await batch.commit(); // Single network call

2. Parallel Auth Queries

// ✅ GOOD: Query both directions in parallel
const [matches1, matches2] = await Promise.all([
  db.collection('matches').where('userId1', '==', userId).get(),
  db.collection('matches').where('userId2', '==', userId).get()
]);

3. Limit Data Fetching

// Only fetch what's needed
const profileDoc = await db.collection('profiles')
  .doc(userId)
  .get();

if (profileDoc.exists) {
  const { name } = profileDoc.data(); // Destructure only needed fields
}

Troubleshooting Guide

Common Issues and Solutions

Issue: "Service account key not found"

# Solution:
ls -la scripts/serviceAccountKey.json
# If missing, download from Firebase Console
# Project Settings > Service Accounts > Generate New Private Key

Issue: "No matches for verification"

// Solution: Create matches first
// Option 2: Create matches (1-10)
// or
// Option 4: Generate complete scenario (3-10)

Issue: "Match order not updating"

// Verify timestamp and sequence are updating:
await matchRef.update({
  lastMessage: message,
  lastMessageSeq: newSeq,  // Increment sequence
  timestamp: admin.firestore.FieldValue.serverTimestamp(), // Update timestamp
  lastMessageTimestamp: admin.firestore.FieldValue.serverTimestamp()
});

Issue: "Discovery profiles not appearing in app"

// Check userType logic:
if (CURRENT_USER.name === 'Daniel') {
  // Daniel es hombre, mostrar mujeres (🌟 Prime / 💎 Elite)
  userType = isMale ? 'ELITE' : (i % 3 === 0 ? 'ELITE' : 'PRIME');
} else {
  // Rosita es mujer, mostrar hombres (💎 Elite)
  userType = isMale ? 'ELITE' : 'PRIME';
}

Issue: "Script hangs or is very slow"

# Check for existing test data:
# Option 7: Verify system → See counts
# If too many test users, cleanup first:
# Option 9: Complete cleanup

Testing Best Practices

Before Creating Data

  1. ✅ Verify current state (Option 7)
  2. ✅ Check for existing test data
  3. ✅ Confirm selected user is correct
  4. ✅ Plan quantity (recommended: 5-10 matches, 20-30 discovery)

During Testing

  1. ✅ Use option 1 frequently to see current state
  2. ✅ Test reordering with option 3 + app observation
  3. ✅ Verify order with option 6 after changes
  4. ✅ Check both app platforms (iOS/Android/Web)

After Testing

  1. ✅ Use selective cleanup (option 8) if continuing tests
  2. ✅ Use complete cleanup (option 9) when finished
  3. ✅ Verify cleanup succeeded (option 7)
  4. ✅ Document any issues found

Integration with App Testing

Testing Match Reordering (Core Feature)

# 1. Create initial matches
Option 4: Generate scenario (5 matches)

# 2. Open app, observe initial order
# iOS: MatchesView
# Android: MatchesScreen
# Web: Matches component

# 3. Send message from script
Option 3: Send message to match #5

# 4. Observe in app (should move to #1 instantly)
# iOS: Verify list updates via Combine subscription
# Android: Verify list updates via Flow collection
# Web: Verify list updates via RxJS subscription

# 5. Verify programmatically
Option 6: Verify order

Testing Discovery/HomeView

# 1. Create discovery profiles
Option 5: Create 25 profiles

# 2. Open app HomeView
# iOS: HomeView with CardStackView
# Android: HomeScreen with CardStackView
# Web: Home component with swipe cards

# 3. Verify profiles appear with photos
# Each profile should have 5 photos
# Swipe functionality should work
# Like/dislike actions should create matches

# 4. Check match creation
Option 1: List matches (should increase after likes)

Testing Multi-User Scenarios

# 1. Setup Daniel
Select user 1 (Daniel)
Option 4: Generate 5 matches
Option 5: Create 15 discovery

# 2. Setup Rosita  
Option 10: Change user
Select user 2 (Rosita)
Option 4: Generate 5 matches
Option 5: Create 15 discovery

# 3. Test cross-user interactions
# Open Daniel app on device 1
# Open Rosita app on device 2
# Create match between them via discovery
# Send messages back and forth
# Verify reordering on both sides

Firebase Admin SDK Best Practices

Service Account Security

// ✅ GOOD: Use environment variable in production
const serviceAccount = process.env.FIREBASE_SERVICE_ACCOUNT 
  ? JSON.parse(process.env.FIREBASE_SERVICE_ACCOUNT)
  : require('./serviceAccountKey.json');

// ❌ BAD: Hardcode or commit credentials
// const serviceAccount = { ... };

Connection Reuse

// ✅ GOOD: Single initialization
if (!admin.apps.length) {
  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount)
  });
}

// ❌ BAD: Multiple initializations
// admin.initializeApp(...) multiple times

Proper Cleanup

// Always cleanup resources when exiting
process.on('SIGINT', async () => {
  log('\n👋 Cerrando conexiones...', 'yellow');
  await admin.app().delete();
  process.exit(0);
});

Advanced Usage Patterns

Programmatic Script Execution

// Import as module for automated testing
const { createTestMatches, verifySystem } = require('./test-system-unified.js');

async function runAutomatedTest() {
  // Set user programmatically
  CURRENT_USER = TEST_USERS.daniel;
  
  // Create data
  await createTestMatches();
  
  // Verify
  await verifySystem();
  
  // Cleanup
  await cleanupTestData();
}

Custom Data Generation

// Extend for specific test scenarios
async function createSpecificScenario() {
  // Create users with specific characteristics
  const youngUsers = createUsersWithAge(22, 25);
  const oldUsers = createUsersWithAge(35, 40);
  
  // Mix userTypes
  const babies = createUsersWithType('PRIME');
  const daddies = createUsersWithType('ELITE');
  
  // Create matches with specific patterns
  await createMatchesBetween(youngUsers, oldUsers);
}

Migration Notes (Legacy Scripts)

Replaced Scripts Mapping

Legacy ScriptNew System Location
check-daniel-matches.jsOption 1: listDanielMatches()
populate-test-matches.jsOption 2: createTestMatches()
test-match-ordering.jsOptions 3,6: sendMessageToMatch(), verifyMatchOrder()
populate-discovery-profiles.jsOption 5: createDiscoveryProfiles()
verify-test-data.jsOption 7: verifySystem()
debug-matches-users.jsOption 7: verifySystem() (integrated)
cleanup-test-matches.jsOptions 8,9: selectiveCleanup(), cleanupTestData()

Benefits of Unified System

  • 95% reduction in script files (19 → 1)
  • User selection without restarting
  • Selective cleanup preserves needed data
  • Integrated verification with statistics
  • Menu navigation more intuitive
  • Consistent patterns across all operations

Related Documentation

  • README.md - Main guide and quick start
  • TEST_SYSTEM_UNIFIED_README.md - Complete system documentation
  • SYSTEM_MAP.md - Visual architecture and workflows
  • QUICKSTART.md - Fast setup guide
  • SCENARIO_GENERATOR_GUIDE.md - Advanced scenario patterns
  • HOME_VIEW_TEST_PLAN.md - HomeView specific testing

Maintenance and Updates

Adding New Features

  1. Add function after existing functions (before menu)
  2. Update menu with new option
  3. Add case in switch statement
  4. Update documentation (README + SKILL)
  5. Test thoroughly before committing

Adding New Test Users

// In TEST_USERS object:
const TEST_USERS = {
  daniel: { ... },
  rosita: { ... },
  newUser: {
    email: 'newuser@example.com',
    uid: 'newUserUidHere',
    name: 'NewUser'
  }
};

Extending Data Types

// Add new profile fields:
await db.collection('profiles').doc(userId).set({
  // ... existing fields
  newField: value,
  anotherField: data
});

Quick Command Reference

# Start system
node test-system-unified.js

# Common workflows
1 → List matches
2 → Create 5-10 matches
3 → Send message + test reorder
4 → Generate complete scenario
5 → Create 20-30 discovery profiles
6 → Verify match order
7 → System statistics
8 → Selective cleanup
9 → Complete cleanup
10 → Change user
11 → Exit

Support and Troubleshooting

Debug Mode

// Add at top of script for verbose logging
const DEBUG = true;

if (DEBUG) {
  console.log('DEBUG:', variableName, value);
}

Firestore Rules Testing

# Test from terminal
firebase emulators:start --only firestore
# Use emulator for testing without affecting production

Performance Profiling

const startTime = Date.now();
await someOperation();
const duration = Date.now() - startTime;
log(`⏱️ Operation took ${duration}ms`, 'cyan');

Version: 2.0
Last Updated: 12 de enero de 2026
Author: GitHub Copilot
Status: Production Ready ✅