test_cli_remove.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #!/usr/bin/env python3
  2. """
  3. Comprehensive tests for archivebox remove command.
  4. Verify remove deletes snapshots from DB and filesystem.
  5. """
  6. import os
  7. import subprocess
  8. import sqlite3
  9. from pathlib import Path
  10. from .fixtures import *
  11. def test_remove_deletes_snapshot_from_db(tmp_path, process, disable_extractors_dict):
  12. """Test that remove command deletes snapshot from database."""
  13. os.chdir(tmp_path)
  14. # Add a snapshot
  15. subprocess.run(
  16. ['archivebox', 'add', '--index-only', '--depth=0', 'https://example.com'],
  17. capture_output=True,
  18. env=disable_extractors_dict,
  19. )
  20. # Verify it exists
  21. conn = sqlite3.connect("index.sqlite3")
  22. c = conn.cursor()
  23. count_before = c.execute("SELECT COUNT(*) FROM core_snapshot").fetchone()[0]
  24. conn.close()
  25. assert count_before == 1
  26. # Remove it
  27. subprocess.run(
  28. ['archivebox', 'remove', 'https://example.com', '--yes'],
  29. capture_output=True,
  30. env=disable_extractors_dict,
  31. )
  32. # Verify it's gone
  33. conn = sqlite3.connect("index.sqlite3")
  34. c = conn.cursor()
  35. count_after = c.execute("SELECT COUNT(*) FROM core_snapshot").fetchone()[0]
  36. conn.close()
  37. assert count_after == 0
  38. def test_remove_deletes_archive_directory(tmp_path, process, disable_extractors_dict):
  39. """Test that remove deletes the archive directory when using --delete flag.
  40. Archive directories are named by timestamp, not by snapshot ID.
  41. """
  42. os.chdir(tmp_path)
  43. # Add a snapshot
  44. subprocess.run(
  45. ['archivebox', 'add', '--index-only', '--depth=0', 'https://example.com'],
  46. capture_output=True,
  47. env=disable_extractors_dict,
  48. )
  49. # Get snapshot timestamp
  50. conn = sqlite3.connect("index.sqlite3")
  51. c = conn.cursor()
  52. timestamp = c.execute("SELECT timestamp FROM core_snapshot").fetchone()[0]
  53. conn.close()
  54. archive_dir = tmp_path / "archive" / str(timestamp)
  55. assert archive_dir.exists()
  56. # Remove snapshot with --delete to remove both DB record and directory
  57. subprocess.run(
  58. ['archivebox', 'remove', 'https://example.com', '--yes', '--delete'],
  59. capture_output=True,
  60. env=disable_extractors_dict,
  61. )
  62. # Archive directory should be deleted
  63. assert not archive_dir.exists()
  64. def test_remove_yes_flag_skips_confirmation(tmp_path, process, disable_extractors_dict):
  65. """Test that --yes flag skips confirmation prompt."""
  66. os.chdir(tmp_path)
  67. subprocess.run(
  68. ['archivebox', 'add', '--index-only', '--depth=0', 'https://example.com'],
  69. capture_output=True,
  70. env=disable_extractors_dict,
  71. )
  72. # Remove with --yes should complete without interaction
  73. result = subprocess.run(
  74. ['archivebox', 'remove', 'https://example.com', '--yes'],
  75. capture_output=True,
  76. env=disable_extractors_dict,
  77. timeout=30,
  78. )
  79. assert result.returncode == 0
  80. def test_remove_multiple_snapshots(tmp_path, process, disable_extractors_dict):
  81. """Test removing multiple snapshots at once."""
  82. os.chdir(tmp_path)
  83. # Add multiple snapshots
  84. for url in ['https://example.com', 'https://example.org']:
  85. subprocess.run(
  86. ['archivebox', 'add', '--index-only', '--depth=0', url],
  87. capture_output=True,
  88. env=disable_extractors_dict,
  89. )
  90. # Verify both exist
  91. conn = sqlite3.connect("index.sqlite3")
  92. c = conn.cursor()
  93. count_before = c.execute("SELECT COUNT(*) FROM core_snapshot").fetchone()[0]
  94. conn.close()
  95. assert count_before == 2
  96. # Remove both
  97. subprocess.run(
  98. ['archivebox', 'remove', 'https://example.com', 'https://example.org', '--yes'],
  99. capture_output=True,
  100. env=disable_extractors_dict,
  101. )
  102. # Verify both are gone
  103. conn = sqlite3.connect("index.sqlite3")
  104. c = conn.cursor()
  105. count_after = c.execute("SELECT COUNT(*) FROM core_snapshot").fetchone()[0]
  106. conn.close()
  107. assert count_after == 0
  108. def test_remove_with_filter(tmp_path, process, disable_extractors_dict):
  109. """Test removing snapshots using filter."""
  110. os.chdir(tmp_path)
  111. # Add snapshots
  112. subprocess.run(
  113. ['archivebox', 'add', '--index-only', '--depth=0', 'https://example.com'],
  114. capture_output=True,
  115. env=disable_extractors_dict,
  116. )
  117. # Remove using filter
  118. result = subprocess.run(
  119. ['archivebox', 'remove', '--filter-type=search', '--filter=example.com', '--yes'],
  120. capture_output=True,
  121. env=disable_extractors_dict,
  122. timeout=30,
  123. )
  124. # Should complete (exit code depends on implementation)
  125. assert result.returncode in [0, 1, 2]
  126. def test_remove_nonexistent_url_fails_gracefully(tmp_path, process, disable_extractors_dict):
  127. """Test that removing non-existent URL fails gracefully."""
  128. os.chdir(tmp_path)
  129. result = subprocess.run(
  130. ['archivebox', 'remove', 'https://nonexistent-url-12345.com', '--yes'],
  131. capture_output=True,
  132. env=disable_extractors_dict,
  133. )
  134. # Should fail or show error
  135. assert result.returncode != 0 or 'not found' in result.stdout.lower() or 'no matches' in result.stdout.lower()
  136. def test_remove_after_flag(tmp_path, process, disable_extractors_dict):
  137. """Test remove --after flag removes snapshots after date."""
  138. os.chdir(tmp_path)
  139. subprocess.run(
  140. ['archivebox', 'add', '--index-only', '--depth=0', 'https://example.com'],
  141. capture_output=True,
  142. env=disable_extractors_dict,
  143. )
  144. # Try remove with --after flag (should work or show usage)
  145. result = subprocess.run(
  146. ['archivebox', 'remove', '--after=2020-01-01', '--yes'],
  147. capture_output=True,
  148. env=disable_extractors_dict,
  149. timeout=30,
  150. )
  151. # Should complete
  152. assert result.returncode in [0, 1, 2]