Coverage for tests / unit / ai / test_availability.py: 100%

37 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-04-03 18:53 +0000

1"""Tests for AI availability checks.""" 

2 

3from __future__ import annotations 

4 

5import builtins 

6from unittest.mock import patch 

7 

8import click 

9import pytest 

10from assertpy import assert_that 

11 

12from lintro.ai.availability import ( 

13 is_ai_available, 

14 is_provider_available, 

15 require_ai, 

16 reset_availability_cache, 

17) 

18 

19_real_import = builtins.__import__ 

20 

21 

22def test_availability_available_when_anthropic_installed(): 

23 """Verify AI is available when the anthropic module is installed.""" 

24 with patch.dict("sys.modules", {"anthropic": object()}): 

25 reset_availability_cache() 

26 result = is_ai_available() 

27 assert_that(result).is_true() 

28 

29 

30def test_availability_caching(): 

31 """Subsequent calls use the cached result without re-importing.""" 

32 import_calls: list[str] = [] 

33 

34 def _tracking_import(name, *args, **kwargs): 

35 if name in ("anthropic", "openai"): 

36 import_calls.append(name) 

37 return _real_import(name, *args, **kwargs) 

38 

39 reset_availability_cache() 

40 with ( 

41 patch.dict("sys.modules", {"anthropic": object()}), 

42 patch("builtins.__import__", side_effect=_tracking_import), 

43 ): 

44 result1 = is_ai_available() 

45 

46 import_calls.clear() 

47 

48 # Second call should return cached True without any import attempt. 

49 with patch("builtins.__import__", side_effect=_tracking_import): 

50 result2 = is_ai_available() 

51 

52 assert_that(result1).is_true() 

53 assert_that(result2).is_true() 

54 assert_that(import_calls).is_empty() 

55 

56 

57def test_availability_unknown_provider(): 

58 """Verify that an unknown provider is reported as unavailable.""" 

59 result = is_provider_available("unknown") 

60 assert_that(result).is_false() 

61 

62 

63def test_availability_require_raises_when_unavailable(): 

64 """Verify require_ai raises UsageError when AI is not available.""" 

65 with ( 

66 patch( 

67 "lintro.ai.availability.is_ai_available", 

68 return_value=False, 

69 ), 

70 pytest.raises(click.UsageError, match="lintro\\[ai\\]"), 

71 ): 

72 require_ai() 

73 

74 

75def test_availability_require_passes_when_available(): 

76 """Verify require_ai succeeds without error when AI is available.""" 

77 with patch( 

78 "lintro.ai.availability.is_ai_available", 

79 return_value=True, 

80 ): 

81 require_ai()