|
1 | 1 | import sys |
2 | 2 | import os |
3 | 3 | import unittest |
| 4 | +import tempfile |
| 5 | +import shutil |
4 | 6 |
|
5 | 7 | # Add src to path |
6 | 8 | sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'src'))) |
7 | 9 |
|
8 | | -from deadlink.utils import is_external_url, normalize_url |
| 10 | +from deadlink.utils import is_external_url, normalize_url, get_status_text |
| 11 | +from deadlink.models import LinkResult |
| 12 | +from deadlink.reporter import generate_report, get_report_filename |
| 13 | +from deadlink.database import DatabaseManager |
| 14 | +from deadlink.scanner import get_all_links |
9 | 15 | from deadlink.version import VERSION |
| 16 | +from unittest.mock import patch, MagicMock |
10 | 17 |
|
11 | 18 | class TestCore(unittest.TestCase): |
| 19 | + def setUp(self): |
| 20 | + self.test_dir = tempfile.mkdtemp() |
| 21 | + |
| 22 | + def tearDown(self): |
| 23 | + shutil.rmtree(self.test_dir) |
| 24 | + |
12 | 25 | def test_version_exists(self): |
13 | 26 | self.assertIsNotNone(VERSION) |
14 | 27 | print(f"Testing version: {VERSION}") |
15 | 28 |
|
16 | 29 | def test_url_normalization(self): |
17 | 30 | url = "https://example.com/path/" |
18 | 31 | normalized = normalize_url(url) |
| 32 | + # normalize_url should strip trailing slash for paths |
19 | 33 | self.assertEqual(normalized, "https://example.com/path") |
| 34 | + |
| 35 | + url_with_query = "https://example.com/path/?q=1#frag" |
| 36 | + normalized_q = normalize_url(url_with_query) |
| 37 | + self.assertEqual(normalized_q, "https://example.com/path?q=1") |
| 38 | + |
| 39 | + url_home = "https://example.com/" |
| 40 | + # home page should keep trailing slash |
| 41 | + self.assertEqual(normalize_url(url_home), "https://example.com/") |
20 | 42 |
|
21 | 43 | def test_external_link_check(self): |
22 | 44 | base = "https://example.com" |
23 | 45 | external = "https://google.com" |
24 | 46 | internal = "https://example.com/about" |
| 47 | + internal_www = "https://www.example.com/about" |
25 | 48 |
|
26 | 49 | self.assertTrue(is_external_url(external, base)) |
27 | 50 | self.assertFalse(is_external_url(internal, base)) |
| 51 | + self.assertFalse(is_external_url(internal_www, base)) |
| 52 | + |
| 53 | + def test_status_text_lookup(self): |
| 54 | + self.assertEqual(get_status_text(200), "200 OK") |
| 55 | + self.assertEqual(get_status_text(404), "404 Not Found") |
| 56 | + self.assertEqual(get_status_text(500), "500 Internal Server Error") |
| 57 | + self.assertIn("999", get_status_text(999)) |
| 58 | + |
| 59 | + def test_link_result_model(self): |
| 60 | + res = LinkResult( |
| 61 | + url="https://test.com", |
| 62 | + status_code=200, |
| 63 | + status_text="OK", |
| 64 | + response_time=0.5, |
| 65 | + found_on="https://base.com", |
| 66 | + is_dead=False, |
| 67 | + is_external=True, |
| 68 | + link_type="Image" |
| 69 | + ) |
| 70 | + self.assertEqual(res.url, "https://test.com") |
| 71 | + self.assertTrue(res.is_external) |
| 72 | + self.assertFalse(res.is_dead) |
| 73 | + self.assertEqual(res.link_type, "Image") |
| 74 | + |
| 75 | + def test_report_generation(self): |
| 76 | + results = [ |
| 77 | + LinkResult("https://a.com", 200, "OK", 0.1, "base", False, False), |
| 78 | + LinkResult("https://b.com", 404, "Not Found", 0.1, "base", True, False), |
| 79 | + LinkResult("https://external.com", 200, "OK", 0.1, "base", False, True) |
| 80 | + ] |
| 81 | + report = generate_report(results) |
| 82 | + self.assertIn("DEAD LINK CHECKER REPORT", report) |
| 83 | + self.assertIn("Total items checked: 3", report) |
| 84 | + self.assertIn("Working items: 2", report) |
| 85 | + self.assertIn("Dead items: 1", report) |
| 86 | + self.assertIn("Internal: 2", report) |
| 87 | + self.assertIn("External: 1", report) |
| 88 | + |
| 89 | + def test_report_filename_generation(self): |
| 90 | + url = "https://www.Example-Site.com/page" |
| 91 | + filename = get_report_filename(url, "csv", reports_dir=self.test_dir) |
| 92 | + self.assertIn("example-site_com", filename) |
| 93 | + self.assertTrue(filename.endswith(".csv")) |
| 94 | + |
| 95 | + filename_session = get_report_filename(url, "txt", reports_dir=self.test_dir, session_folder="session_1") |
| 96 | + self.assertIn("session_1", filename_session) |
| 97 | + self.assertTrue(os.path.exists(os.path.join(self.test_dir, "session_1"))) |
| 98 | + |
| 99 | + def test_database_manager(self): |
| 100 | + # Use in-memory database for testing |
| 101 | + db = DatabaseManager(":memory:") |
| 102 | + results = [ |
| 103 | + LinkResult("https://a.com", 200, "OK", 0.1, "base", False, False) |
| 104 | + ] |
| 105 | + session_id = db.save_session("https://test.com", "website", results, "folder_1") |
| 106 | + |
| 107 | + sessions = db.get_sessions() |
| 108 | + self.assertEqual(len(sessions), 1) |
| 109 | + self.assertEqual(sessions[0]['url'], "https://test.com") |
| 110 | + |
| 111 | + session_results = db.get_session_results(session_id) |
| 112 | + self.assertEqual(len(session_results), 1) |
| 113 | + self.assertEqual(session_results[0]['url'], "https://a.com") |
| 114 | + |
| 115 | + db.delete_session(session_id) |
| 116 | + self.assertEqual(len(db.get_sessions()), 0) |
| 117 | + |
| 118 | + @patch('requests.get') |
| 119 | + def test_link_scraper(self, mock_get): |
| 120 | + mock_response = MagicMock() |
| 121 | + mock_response.text = '<html><body><a href="/page1">Link</a><img src="img.png"></body></html>' |
| 122 | + mock_response.raise_for_status = MagicMock() |
| 123 | + mock_get.return_value = mock_response |
| 124 | + |
| 125 | + links, base = get_all_links("https://test.com") |
| 126 | + self.assertEqual(len(links), 2) |
| 127 | + urls = [l[0] for l in links] |
| 128 | + self.assertIn("https://test.com/page1", urls) |
| 129 | + self.assertIn("https://test.com/img.png", urls) |
28 | 130 |
|
29 | 131 | if __name__ == '__main__': |
30 | 132 | unittest.main() |
0 commit comments