← back to Dear Bubbe Nextjs

archived/tests/mobile-test-quick.js

289 lines

/**
 * Quick Mobile Test for Dear Bubbe
 * Focused on core functionality verification
 */

const puppeteer = require('puppeteer');

const TEST_URL = 'http://45.61.58.125:3011';

async function runQuickMobileTest() {
  console.log('🚀 Dear Bubbe Quick Mobile Test');
  console.log('=' .repeat(50));
  
  const browser = await puppeteer.launch({
    headless: true,
    args: ['--no-sandbox', '--disable-setuid-sandbox']
  });
  
  const results = {
    passed: 0,
    failed: 0,
    tests: []
  };
  
  function log(test, status, details = '') {
    const icon = status === 'PASS' ? '✅' : '❌';
    console.log(`${icon} ${test}: ${status}`);
    if (details) console.log(`   ${details}`);
    results.tests.push({ test, status, details });
    if (status === 'PASS') results.passed++;
    else results.failed++;
  }
  
  try {
    const page = await browser.newPage();
    
    // Set iPhone 12 viewport
    await page.setViewport({ width: 390, height: 844 });
    await page.setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X)');
    
    console.log('\n📱 Testing iPhone 12 Experience');
    console.log('-'.repeat(50));
    
    // Navigate to site
    await page.goto(TEST_URL, { waitUntil: 'networkidle2' });
    
    // Test 1: Page loads
    const title = await page.title();
    if (title) {
      log('Page Load', 'PASS', `Title: ${title}`);
    } else {
      log('Page Load', 'FAIL', 'No title found');
    }
    
    // Test 2: Check for Bubbe's initial message
    await new Promise(r => setTimeout(r, 5000)) // Give more time for API call;
    
    const bubbeMessages = await page.evaluate(() => {
      // Look for Bubbe messages - they have white background with border
      const messages = document.querySelectorAll('.bg-white.border-gray-200, .rounded-2xl');
      return Array.from(messages).map(el => el.textContent).filter(t => t && t.length > 10);
    });
    
    if (bubbeMessages.length > 0) {
      log('Auto-start Voice', 'PASS', `Found ${bubbeMessages.length} Bubbe messages`);
      console.log(`   First message: "${bubbeMessages[0].substring(0, 50)}..."`);
      
      // Check for invasive questions
      const hasQuestion = bubbeMessages.some(msg => msg.includes('?'));
      if (hasQuestion) {
        log('Invasive Questions', 'PASS', 'Bubbe asks questions');
      } else {
        log('Invasive Questions', 'FAIL', 'No questions found');
      }
    } else {
      log('Auto-start Voice', 'FAIL', 'No Bubbe messages found');
    }
    
    // Test 3: Check input field exists
    const inputField = await page.$('textarea, input[type="text"]');
    if (inputField) {
      log('Input Field', 'PASS', 'Chat input available');
      
      // Test sending a message
      await inputField.type('Hello Bubbe!');
      await page.keyboard.press('Enter');
      
      await new Promise(r => setTimeout(r, 5000)); // Wait longer for response
      
      const newMessages = await page.evaluate(() => {
        // Count all message divs with rounded corners (both user and Bubbe)
        const messages = document.querySelectorAll('.rounded-2xl');
        return Array.from(messages).filter(el => el.textContent && el.textContent.length > 5).length;
      });
      
      // Should have at least 2 more messages (user message + Bubbe response)
      if (newMessages >= bubbeMessages.length + 2) {
        log('Message Response', 'PASS', `Bubbe responded (${newMessages} total messages)`);
      } else {
        log('Message Response', 'FAIL', `No new response (${newMessages} messages)`);
      }
    } else {
      log('Input Field', 'FAIL', 'No input field found');
    }
    
    // Test 4: Check for share button
    const shareButton = await page.evaluate(() => {
      // Look for share icon or button
      const buttons = Array.from(document.querySelectorAll('button'));
      const shareBtn = buttons.find(btn => {
        const text = btn.textContent?.toLowerCase() || '';
        const ariaLabel = btn.getAttribute('aria-label')?.toLowerCase() || '';
        return text.includes('share') || ariaLabel.includes('share');
      });
      
      if (shareBtn) return true;
      
      // Check for share SVG icon
      const svgs = document.querySelectorAll('svg');
      return Array.from(svgs).some(svg => {
        const parent = svg.closest('button');
        return parent !== null;
      });
    });
    
    if (shareButton) {
      log('Share Button', 'PASS', 'Share functionality present');
    } else {
      log('Share Button', 'FAIL', 'No share button found');
    }
    
    // Test 5: Check mobile viewport meta
    const viewportMeta = await page.evaluate(() => {
      const meta = document.querySelector('meta[name="viewport"]');
      return meta?.getAttribute('content');
    });
    
    if (viewportMeta && viewportMeta.includes('width=device-width')) {
      log('Mobile Viewport', 'PASS', viewportMeta);
    } else {
      log('Mobile Viewport', 'FAIL', 'Missing proper viewport meta');
    }
    
    // Test 6: Check for TALK button (should NOT be visible after Bubbe speaks)
    const talkButtonVisible = await page.evaluate(() => {
      const buttons = Array.from(document.querySelectorAll('button'));
      const talkBtn = buttons.find(btn => btn.textContent === 'TALK');
      return talkBtn && window.getComputedStyle(talkBtn).display !== 'none';
    });
    
    if (!talkButtonVisible) {
      log('No TALK Button Bug', 'PASS', 'TALK button correctly hidden');
    } else {
      log('No TALK Button Bug', 'FAIL', 'TALK button showing incorrectly');
    }
    
    // Test 7: Check response length (mobile optimized)
    const lastBubbeMessage = bubbeMessages[bubbeMessages.length - 1] || '';
    if (lastBubbeMessage.length <= 320) {
      log('Mobile Message Length', 'PASS', `${lastBubbeMessage.length} chars`);
    } else {
      log('Mobile Message Length', 'FAIL', `Too long: ${lastBubbeMessage.length} chars`);
    }
    
    // Test 8: Check for console errors
    const errors = [];
    page.on('console', msg => {
      if (msg.type() === 'error') {
        errors.push(msg.text());
      }
    });
    
    await page.reload();
    await new Promise(r => setTimeout(r, 2000));
    
    if (errors.length === 0) {
      log('No Console Errors', 'PASS', 'Clean console');
    } else {
      log('No Console Errors', 'FAIL', `${errors.length} errors found`);
      errors.slice(0, 3).forEach(err => console.log(`   Error: ${err.substring(0, 100)}`));
    }
    
    // Test 9: Test landscape mode - simplified test
    await page.setViewport({ width: 844, height: 390 });
    await new Promise(r => setTimeout(r, 2000)); // Give more time for reflow
    
    const landscapeWorks = await page.evaluate(() => {
      // Simple test - just check if critical elements are still accessible
      const input = document.querySelector('textarea, input[type="text"]');
      const messages = document.querySelectorAll('.rounded-2xl');
      
      // As long as we can still see messages and input, it's functional
      return input && messages.length > 0;
    });
    
    if (landscapeWorks) {
      log('Landscape Mode', 'PASS', 'Core functionality maintained in landscape');
    } else {
      log('Landscape Mode', 'FAIL', 'Critical elements not accessible in landscape');
    }
    
    // Test 10: Check for profile/login options
    const profileOptions = await page.evaluate(() => {
      const buttons = Array.from(document.querySelectorAll('button'));
      return buttons.some(btn => {
        const text = btn.textContent?.toLowerCase() || '';
        return text.includes('profile') || text.includes('sign') || text.includes('log');
      });
    });
    
    if (profileOptions) {
      log('Profile/Login Access', 'PASS', 'User account options available');
    } else {
      log('Profile/Login Access', 'FAIL', 'No profile options found');
    }
    
    // Take final screenshot
    await page.setViewport({ width: 390, height: 844 }); // Back to portrait
    await page.screenshot({ 
      path: `/root/Projects/dear-bubbe-nextjs/test-screenshots/mobile-quick-test-${Date.now()}.png`,
      fullPage: false 
    });
    
  } catch (error) {
    console.error('Fatal error:', error.message);
  } finally {
    await browser.close();
  }
  
  // Print summary
  console.log('\n' + '='.repeat(50));
  console.log('📊 TEST SUMMARY');
  console.log('='.repeat(50));
  console.log(`✅ Passed: ${results.passed}`);
  console.log(`❌ Failed: ${results.failed}`);
  console.log(`📈 Success Rate: ${Math.round((results.passed / (results.passed + results.failed)) * 100)}%`);
  
  // Print recommendations
  console.log('\n💡 RECOMMENDATIONS:');
  
  const recommendations = [];
  
  results.tests.forEach(test => {
    if (test.status === 'FAIL') {
      switch(test.test) {
        case 'Auto-start Voice':
          recommendations.push('• Fix auto-start: Bubbe should greet immediately on load');
          break;
        case 'Share Button':
          recommendations.push('• Add share button: Users need to share funny responses');
          break;
        case 'No TALK Button Bug':
          recommendations.push('• Fix TALK button: Should not appear after Bubbe speaks');
          break;
        case 'Message Response':
          recommendations.push('• Fix chat flow: Ensure messages get responses');
          break;
        case 'Mobile Message Length':
          recommendations.push('• Shorten responses: Keep under 320 chars for mobile');
          break;
        case 'No Console Errors':
          recommendations.push('• Fix JavaScript errors: Check console for issues');
          break;
        case 'Invasive Questions':
          recommendations.push('• Add invasive questions: Bubbe must be nosy!');
          break;
      }
    }
  });
  
  if (recommendations.length > 0) {
    recommendations.forEach(rec => console.log(rec));
  } else {
    console.log('✅ All tests passed! Mobile experience is working well.');
  }
  
  return results.failed === 0 ? 0 : 1;
}

// Run the test
runQuickMobileTest()
  .then(exitCode => {
    console.log('\n✅ Quick mobile test completed!');
    process.exit(exitCode);
  })
  .catch(error => {
    console.error('Test failed:', error);
    process.exit(1);
  });