tests/test_exporter.py (4873B)
1 """Tests for ap_scanner.exporter."""
2
3 import csv
4 import json
5 from pathlib import Path
6
7 from ap_scanner.exporter import generate_filename, save_csv, save_json
8
9
10 def test_generate_filename_format():
11 name = generate_filename()
12 assert name.startswith("ap_scan_")
13 assert name.endswith(".csv")
14
15
16 def test_save_csv_creates_file(sample_ap, tmp_path):
17 filepath = tmp_path / "test_output.csv"
18 aps = {sample_ap.bssid: sample_ap}
19 result = save_csv(aps, str(filepath))
20 assert Path(result).exists()
21
22
23 def test_save_csv_field_count(sample_ap, tmp_path):
24 filepath = tmp_path / "test_fields.csv"
25 aps = {sample_ap.bssid: sample_ap}
26 save_csv(aps, str(filepath))
27
28 with open(filepath, "r", encoding="utf-8") as f:
29 reader = csv.reader(f, delimiter=";")
30 header = next(reader)
31 assert len(header) == 20
32 row = next(reader)
33 assert len(row) == 20
34
35
36 def test_save_csv_semicolon_delimiter(sample_ap, tmp_path):
37 filepath = tmp_path / "test_delim.csv"
38 aps = {sample_ap.bssid: sample_ap}
39 save_csv(aps, str(filepath))
40
41 content = filepath.read_text(encoding="utf-8")
42 # Header should contain semicolons (semicolon-delimited)
43 assert ";" in content.splitlines()[0]
44
45
46 def test_save_csv_auto_filename(sample_ap, tmp_path, monkeypatch):
47 monkeypatch.chdir(tmp_path)
48 aps = {sample_ap.bssid: sample_ap}
49 result = save_csv(aps)
50 assert result.startswith("ap_scan_")
51 assert Path(result).exists()
52
53
54 # --- JSON export ---
55
56 def test_generate_filename_json():
57 name = generate_filename("json")
58 assert name.startswith("ap_scan_")
59 assert name.endswith(".json")
60
61
62 def test_save_json_creates_file(sample_ap, tmp_path):
63 filepath = tmp_path / "test_output.json"
64 aps = {sample_ap.bssid: sample_ap}
65 result = save_json(aps, str(filepath))
66 assert Path(result).exists()
67
68
69 def test_save_json_valid_structure(sample_ap, tmp_path):
70 filepath = tmp_path / "test_struct.json"
71 aps = {sample_ap.bssid: sample_ap}
72 save_json(aps, str(filepath))
73
74 with open(filepath, "r", encoding="utf-8") as f:
75 data = json.load(f)
76
77 assert "scan_time" in data
78 assert "access_points" in data
79 assert len(data["access_points"]) == 1
80 ap = data["access_points"][0]
81 assert ap["bssid"] == sample_ap.bssid
82 assert ap["ssid"] == sample_ap.display_ssid
83 assert ap["channel"] == sample_ap.channel
84
85
86 def test_save_json_auto_filename(sample_ap, tmp_path, monkeypatch):
87 monkeypatch.chdir(tmp_path)
88 aps = {sample_ap.bssid: sample_ap}
89 result = save_json(aps)
90 assert result.startswith("ap_scan_")
91 assert result.endswith(".json")
92 assert Path(result).exists()
93
94
95 # --- Active scan export ---
96
97 def test_save_json_with_active_scan(open_ap, tmp_path):
98 from ap_scanner.models import ActiveScanClient, ActiveScanResult
99
100 open_ap.active_scan_result = ActiveScanResult(
101 bssid=open_ap.bssid, ssid=open_ap.display_ssid,
102 connected=True, assigned_ip="192.168.1.100",
103 gateway_ip="192.168.1.1", gateway_mac="AA:BB:CC:DD:EE:01",
104 dns_servers=["8.8.8.8"], gateway_open_ports=[80, 443],
105 clients=[ActiveScanClient(ip="192.168.1.50", mac="AA:AA:AA:AA:AA:AA")],
106 duration_secs=12.3,
107 )
108 filepath = tmp_path / "active.json"
109 aps = {open_ap.bssid: open_ap}
110 save_json(aps, str(filepath))
111
112 with open(filepath, "r", encoding="utf-8") as f:
113 data = json.load(f)
114
115 ap_data = data["access_points"][0]
116 assert "active_scan" in ap_data
117 scan = ap_data["active_scan"]
118 assert scan["connected"] is True
119 assert scan["assigned_ip"] == "192.168.1.100"
120 assert scan["gateway_ip"] == "192.168.1.1"
121 assert scan["gateway_open_ports"] == [80, 443]
122 assert len(scan["clients"]) == 1
123 assert scan["clients"][0]["ip"] == "192.168.1.50"
124
125
126 def test_save_csv_active_scan_columns(open_ap, tmp_path):
127 from ap_scanner.models import ActiveScanResult
128
129 open_ap.active_scan_result = ActiveScanResult(
130 bssid=open_ap.bssid, ssid=open_ap.display_ssid,
131 connected=True, assigned_ip="10.0.0.5",
132 gateway_ip="10.0.0.1", gateway_open_ports=[22, 80],
133 )
134 filepath = tmp_path / "active.csv"
135 aps = {open_ap.bssid: open_ap}
136 save_csv(aps, str(filepath))
137
138 with open(filepath, "r", encoding="utf-8") as f:
139 reader = csv.DictReader(f, delimiter=";")
140 row = next(reader)
141
142 assert row["Active Scan IP"] == "10.0.0.5"
143 assert row["Active Scan Gateway"] == "10.0.0.1"
144 assert row["Active Scan Ports"] == "22,80"
145
146
147 def test_save_json_no_active_scan(sample_ap, tmp_path):
148 filepath = tmp_path / "no_active.json"
149 aps = {sample_ap.bssid: sample_ap}
150 save_json(aps, str(filepath))
151
152 with open(filepath, "r", encoding="utf-8") as f:
153 data = json.load(f)
154
155 ap_data = data["access_points"][0]
156 assert "active_scan" not in ap_data