|
8 | 8 | # - Network harvester |
9 | 9 | # - System harvester |
10 | 10 | # - External harvester |
| 11 | +# - Weather harvester |
| 12 | +# - Radioactive harvester |
11 | 13 | # - Base harvester interface |
12 | 14 | # |
13 | 15 | # ============================================================================= |
|
21 | 23 | from trueentropy.harvesters.network import NetworkHarvester |
22 | 24 | from trueentropy.harvesters.system import SystemHarvester |
23 | 25 | from trueentropy.harvesters.external import ExternalHarvester |
| 26 | +from trueentropy.harvesters.weather import WeatherHarvester |
| 27 | +from trueentropy.harvesters.radioactive import RadioactiveHarvester |
24 | 28 |
|
25 | 29 |
|
26 | 30 | class TestHarvestResult: |
@@ -274,8 +278,91 @@ def test_repr(self) -> None: |
274 | 278 | SystemHarvester(), |
275 | 279 | NetworkHarvester(), |
276 | 280 | ExternalHarvester(), |
| 281 | + WeatherHarvester(), |
| 282 | + RadioactiveHarvester(), |
277 | 283 | ] |
278 | 284 |
|
279 | 285 | for h in harvesters: |
280 | 286 | repr_str = repr(h) |
281 | 287 | assert h.name in repr_str |
| 288 | + |
| 289 | + |
| 290 | +class TestWeatherHarvester: |
| 291 | + """Test WeatherHarvester.""" |
| 292 | + |
| 293 | + def test_name(self) -> None: |
| 294 | + """Harvester should have correct name.""" |
| 295 | + harvester = WeatherHarvester() |
| 296 | + assert harvester.name == "weather" |
| 297 | + |
| 298 | + def test_collect_returns_result(self) -> None: |
| 299 | + """collect() should return HarvestResult.""" |
| 300 | + harvester = WeatherHarvester() |
| 301 | + result = harvester.collect() |
| 302 | + |
| 303 | + assert isinstance(result, HarvestResult) |
| 304 | + |
| 305 | + def test_timeout_configuration(self) -> None: |
| 306 | + """Harvester should respect timeout config.""" |
| 307 | + harvester = WeatherHarvester(timeout=3.0) |
| 308 | + assert harvester.timeout == 3.0 |
| 309 | + |
| 310 | + def test_api_key_masking(self) -> None: |
| 311 | + """API key should be masked when accessed.""" |
| 312 | + harvester = WeatherHarvester(api_key="my_secret_api_key_12345") |
| 313 | + masked = harvester.api_key |
| 314 | + |
| 315 | + # Should be partially masked |
| 316 | + assert masked is not None |
| 317 | + assert "..." in masked |
| 318 | + assert "my_secret_api_key_12345" != masked |
| 319 | + |
| 320 | + def test_no_api_key_returns_none(self) -> None: |
| 321 | + """api_key property should return None when not set.""" |
| 322 | + harvester = WeatherHarvester() |
| 323 | + assert harvester.api_key is None |
| 324 | + |
| 325 | + |
| 326 | +class TestRadioactiveHarvester: |
| 327 | + """Test RadioactiveHarvester.""" |
| 328 | + |
| 329 | + def test_name(self) -> None: |
| 330 | + """Harvester should have correct name.""" |
| 331 | + harvester = RadioactiveHarvester() |
| 332 | + assert harvester.name == "radioactive" |
| 333 | + |
| 334 | + def test_collect_returns_result(self) -> None: |
| 335 | + """collect() should return HarvestResult.""" |
| 336 | + harvester = RadioactiveHarvester() |
| 337 | + result = harvester.collect() |
| 338 | + |
| 339 | + assert isinstance(result, HarvestResult) |
| 340 | + |
| 341 | + def test_timeout_configuration(self) -> None: |
| 342 | + """Harvester should respect timeout config.""" |
| 343 | + harvester = RadioactiveHarvester(timeout=15.0) |
| 344 | + assert harvester.timeout == 15.0 |
| 345 | + |
| 346 | + def test_num_integers_configuration(self) -> None: |
| 347 | + """Harvester should respect num_integers config.""" |
| 348 | + harvester = RadioactiveHarvester(num_integers=20) |
| 349 | + assert harvester.num_integers == 20 |
| 350 | + |
| 351 | + def test_num_integers_validation(self) -> None: |
| 352 | + """num_integers should have valid range.""" |
| 353 | + harvester = RadioactiveHarvester() |
| 354 | + |
| 355 | + with pytest.raises(ValueError): |
| 356 | + harvester.num_integers = 0 |
| 357 | + |
| 358 | + with pytest.raises(ValueError): |
| 359 | + harvester.num_integers = 1001 |
| 360 | + |
| 361 | + def test_api_key_masking(self) -> None: |
| 362 | + """API key should be masked when accessed.""" |
| 363 | + harvester = RadioactiveHarvester(api_key="12345678-abcd-efgh-ijkl") |
| 364 | + masked = harvester.api_key |
| 365 | + |
| 366 | + assert masked is not None |
| 367 | + assert "..." in masked |
| 368 | + |
0 commit comments