test_consolelog.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. """
  2. Tests for the consolelog plugin.
  3. Tests the real consolelog hook with an actual URL to verify
  4. console output capture.
  5. """
  6. import json
  7. import shutil
  8. import subprocess
  9. import sys
  10. import tempfile
  11. import time
  12. from pathlib import Path
  13. from django.test import TestCase
  14. # Import chrome test helpers
  15. sys.path.insert(0, str(Path(__file__).parent.parent.parent / 'chrome' / 'tests'))
  16. from chrome_test_helpers import (
  17. chrome_session,
  18. CHROME_NAVIGATE_HOOK,
  19. get_plugin_dir,
  20. get_hook_script,
  21. )
  22. # Get the path to the consolelog hook
  23. PLUGIN_DIR = get_plugin_dir(__file__)
  24. CONSOLELOG_HOOK = get_hook_script(PLUGIN_DIR, 'on_Snapshot__*_consolelog.*')
  25. class TestConsolelogPlugin(TestCase):
  26. """Test the consolelog plugin."""
  27. def test_consolelog_hook_exists(self):
  28. """Consolelog hook script should exist."""
  29. self.assertIsNotNone(CONSOLELOG_HOOK, "Consolelog hook not found in plugin directory")
  30. self.assertTrue(CONSOLELOG_HOOK.exists(), f"Hook not found: {CONSOLELOG_HOOK}")
  31. class TestConsolelogWithChrome(TestCase):
  32. """Integration tests for consolelog plugin with Chrome."""
  33. def setUp(self):
  34. """Set up test environment."""
  35. self.temp_dir = Path(tempfile.mkdtemp())
  36. def tearDown(self):
  37. """Clean up."""
  38. shutil.rmtree(self.temp_dir, ignore_errors=True)
  39. def test_consolelog_captures_output(self):
  40. """Consolelog hook should capture console output from page."""
  41. test_url = 'data:text/html,<script>console.log("archivebox-console-test")</script>'
  42. snapshot_id = 'test-consolelog-snapshot'
  43. with chrome_session(
  44. self.temp_dir,
  45. crawl_id='test-consolelog-crawl',
  46. snapshot_id=snapshot_id,
  47. test_url=test_url,
  48. navigate=False,
  49. timeout=30,
  50. ) as (chrome_process, chrome_pid, snapshot_chrome_dir, env):
  51. console_dir = snapshot_chrome_dir.parent / 'consolelog'
  52. console_dir.mkdir(exist_ok=True)
  53. # Run consolelog hook with the active Chrome session (background hook)
  54. result = subprocess.Popen(
  55. ['node', str(CONSOLELOG_HOOK), f'--url={test_url}', f'--snapshot-id={snapshot_id}'],
  56. cwd=str(console_dir),
  57. stdout=subprocess.PIPE,
  58. stderr=subprocess.PIPE,
  59. text=True,
  60. env=env
  61. )
  62. nav_result = subprocess.run(
  63. ['node', str(CHROME_NAVIGATE_HOOK), f'--url={test_url}', f'--snapshot-id={snapshot_id}'],
  64. cwd=str(snapshot_chrome_dir),
  65. capture_output=True,
  66. text=True,
  67. timeout=120,
  68. env=env
  69. )
  70. self.assertEqual(nav_result.returncode, 0, f"Navigation failed: {nav_result.stderr}")
  71. # Check for output file
  72. console_output = console_dir / 'console.jsonl'
  73. # Allow it to run briefly, then terminate (background hook)
  74. for _ in range(10):
  75. if console_output.exists() and console_output.stat().st_size > 0:
  76. break
  77. time.sleep(1)
  78. if result.poll() is None:
  79. result.terminate()
  80. try:
  81. stdout, stderr = result.communicate(timeout=5)
  82. except subprocess.TimeoutExpired:
  83. result.kill()
  84. stdout, stderr = result.communicate()
  85. else:
  86. stdout, stderr = result.communicate()
  87. # At minimum, verify no crash
  88. self.assertNotIn('Traceback', stderr)
  89. # If output file exists, verify it's valid JSONL and has output
  90. if console_output.exists():
  91. with open(console_output) as f:
  92. content = f.read().strip()
  93. self.assertTrue(content, "Console output should not be empty")
  94. for line in content.split('\n'):
  95. if line.strip():
  96. try:
  97. record = json.loads(line)
  98. # Verify structure
  99. self.assertIn('timestamp', record)
  100. self.assertIn('type', record)
  101. except json.JSONDecodeError:
  102. pass # Some lines may be incomplete
  103. if __name__ == '__main__':
  104. pytest.main([__file__, '-v'])