← back to Dear Bubbe Nextjs

archived/tests/test-voice-auto.js

185 lines

#!/usr/bin/env node

/**
 * Voice Auto-Start Test Script
 * Tests that Bubbe starts talking immediately on page load
 */

const puppeteer = require('puppeteer');

async function testVoiceAutoStart() {
  console.log('🧪 Testing Voice Auto-Start Feature...\n');
  
  const browser = await puppeteer.launch({
    headless: true,
    args: [
      '--no-sandbox',
      '--disable-setuid-sandbox',
      '--use-fake-ui-for-media-stream', // Auto-grant mic permission
      '--use-fake-device-for-media-stream' // Use fake mic
    ]
  });
  
  try {
    const page = await browser.newPage();
    
    // Enable console logging
    page.on('console', msg => {
      if (msg.type() === 'log') {
        console.log(`  [Browser]: ${msg.text()}`);
      }
    });
    
    // Track important events
    let events = {
      pageLoaded: false,
      voiceManagerInitialized: false,
      greetingSent: false,
      voiceRequested: false,
      audioPlayed: false
    };
    
    // Inject event tracking
    await page.evaluateOnNewDocument(() => {
      // Track fetch requests
      const originalFetch = window.fetch;
      window.fetch = async (...args) => {
        const url = args[0];
        console.log(`[Fetch]: ${url}`);
        
        if (url.includes('/api/chat')) {
          window.__greetingSent = true;
        }
        if (url.includes('/api/bubbe-voice')) {
          window.__voiceRequested = true;
        }
        
        return originalFetch(...args);
      };
      
      // Track audio playback
      const originalPlay = HTMLAudioElement.prototype.play;
      HTMLAudioElement.prototype.play = function() {
        console.log('[Audio]: Play attempted');
        window.__audioPlayed = true;
        return originalPlay.call(this);
      };
    });
    
    console.log('📱 Loading page...');
    await page.goto('http://localhost:3011', { 
      waitUntil: 'networkidle2',
      timeout: 30000 
    });
    events.pageLoaded = true;
    console.log('✅ Page loaded\n');
    
    // Wait a bit for initialization
    await new Promise(resolve => setTimeout(resolve, 3000));
    
    // Check if components initialized
    events.voiceManagerInitialized = await page.evaluate(() => {
      return document.querySelector('.voice-manager') !== null;
    });
    
    events.greetingSent = await page.evaluate(() => {
      return window.__greetingSent === true;
    });
    
    events.voiceRequested = await page.evaluate(() => {
      return window.__voiceRequested === true;
    });
    
    events.audioPlayed = await page.evaluate(() => {
      return window.__audioPlayed === true;
    });
    
    // Check for messages in the UI
    const hasMessages = await page.evaluate(() => {
      const messages = document.querySelectorAll('[class*="mb-4"]');
      return messages.length > 0;
    });
    
    // Get voice status from UI
    const voiceStatus = await page.evaluate(() => {
      const statusEl = document.querySelector('[class*="text-center"][class*="text-white"]');
      return statusEl ? statusEl.textContent : null;
    });
    
    // Print results
    console.log('\n📊 Test Results:');
    console.log('─────────────────────────────────');
    console.log(`✅ Page Loaded: ${events.pageLoaded ? '✓' : '✗'}`);
    console.log(`${events.voiceManagerInitialized ? '✅' : '❌'} Voice Manager Initialized: ${events.voiceManagerInitialized ? '✓' : '✗'}`);
    console.log(`${events.greetingSent ? '✅' : '❌'} Initial Greeting Sent: ${events.greetingSent ? '✓' : '✗'}`);
    console.log(`${events.voiceRequested ? '✅' : '⚠️'} Voice Generation Requested: ${events.voiceRequested ? '✓' : '✗ (may be blocked on headless)'}`);
    console.log(`${events.audioPlayed ? '✅' : '⚠️'} Audio Playback Attempted: ${events.audioPlayed ? '✓' : '✗ (normal in headless)'}`);
    console.log(`${hasMessages ? '✅' : '❌'} Messages Displayed: ${hasMessages ? '✓' : '✗'}`);
    console.log(`📢 Voice Status: ${voiceStatus || 'Unknown'}`);
    console.log('─────────────────────────────────');
    
    // Overall result
    const criticalPassed = events.pageLoaded && 
                          events.voiceManagerInitialized && 
                          events.greetingSent && 
                          hasMessages;
    
    if (criticalPassed) {
      console.log('\n✅ SUCCESS: Voice auto-start is working correctly!');
      console.log('   Bubbe starts talking immediately on page load.');
      if (!events.audioPlayed) {
        console.log('   Note: Audio playback blocked in headless mode (normal).');
      }
    } else {
      console.log('\n❌ FAILURE: Voice auto-start has issues:');
      if (!events.voiceManagerInitialized) {
        console.log('   - Voice Manager did not initialize');
      }
      if (!events.greetingSent) {
        console.log('   - Initial greeting was not sent');
      }
      if (!hasMessages) {
        console.log('   - No messages displayed in UI');
      }
    }
    
    // Test mobile simulation
    console.log('\n📱 Testing Mobile Experience...');
    await page.setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1');
    await page.setViewport({ width: 375, height: 667 });
    await page.reload({ waitUntil: 'networkidle2' });
    await new Promise(resolve => setTimeout(resolve, 2000));
    
    const mobileHasOverlay = await page.evaluate(() => {
      return document.querySelector('[class*="fixed"][class*="inset-0"]') !== null;
    });
    
    console.log(`${mobileHasOverlay ? '✅' : '⚠️'} Mobile Overlay: ${mobileHasOverlay ? 'Present (tap-to-start)' : 'Not shown (autoplay may work)'}`);
    
    return criticalPassed;
    
  } catch (error) {
    console.error('\n❌ Test failed with error:', error.message);
    return false;
  } finally {
    await browser.close();
  }
}

// Run the test
testVoiceAutoStart()
  .then(passed => {
    console.log('\n' + '='.repeat(50));
    if (passed) {
      console.log('🎉 All critical tests passed!');
      console.log('Voice chat auto-starts successfully on page load.');
    } else {
      console.log('⚠️ Some tests failed. Check the output above.');
    }
    console.log('='.repeat(50));
    process.exit(passed ? 0 : 1);
  })
  .catch(error => {
    console.error('Fatal error:', error);
    process.exit(1);
  });