Coverage for tests/tests_cli/test_client.py: 79%

67 statements  

« prev     ^ index     » next       coverage.py v7.11.3, created at 2026-01-05 21:44 +0100

1#!/usr/bin/env python3 

2"""Unittests for the ramses_cli client.py class.""" 

3 

4import io 

5from collections.abc import Generator 

6from unittest.mock import AsyncMock, MagicMock 

7 

8import pytest 

9from click.testing import CliRunner 

10 

11from ramses_cli.client import cli 

12from ramses_rf.database import MessageIndex 

13from ramses_rf.gateway import Gateway 

14 

15STDIN = io.StringIO("053 I --- 01:123456 --:------ 01:123456 3150 002 FC00\r\n") 

16CMD = "RQ 01:123456 1F09 00" 

17 

18 

19@pytest.fixture 

20def mock_gateway() -> Generator[MagicMock, None, None]: 

21 """Create a mock Gateway instance for testing.""" 

22 gateway = MagicMock(spec=Gateway) 

23 gateway.send_cmd = AsyncMock() 

24 gateway.dispatcher = MagicMock() 

25 gateway.dispatcher.send = MagicMock() 

26 

27 # Add required attributes 

28 gateway.config = MagicMock() 

29 gateway.config.disable_discovery = False 

30 gateway.config.enable_eavesdrop = False 

31 gateway._loop = MagicMock() 

32 gateway._loop.call_soon = MagicMock() 

33 gateway._loop.call_later = MagicMock() 

34 gateway._loop.time = MagicMock(return_value=0.0) 

35 gateway._include = {} 

36 # Add msg_db attribute accessed by the message store, activates the SQLite MessageIndex 

37 gateway.msg_db = MessageIndex(maintain=False) 

38 

39 yield gateway 

40 

41 

42def test_parse_no_input() -> None: 

43 runner = CliRunner() 

44 result = runner.invoke(cli, ["parse"]) 

45 assert result.exit_code == 2 # missing input file 

46 assert result.output.startswith("Usage: cli parse [OPTIONS] INPUT_FILE") 

47 

48 

49def test_parse(monkeypatch: pytest.MonkeyPatch) -> None: 

50 monkeypatch.setattr("sys.stdin", STDIN) 

51 runner = CliRunner() 

52 result = runner.invoke(cli, ["parse", "-"]) 

53 assert result.exit_code == 0 # OK input file supplied 

54 assert result.output == "" 

55 

56 

57def test_monitor_no_port() -> None: 

58 runner = CliRunner() 

59 result = runner.invoke(cli, ["monitor"]) 

60 assert result.exit_code == 2 # missing port name 

61 assert result.output.startswith("Usage: cli monitor [OPTIONS] SERIAL_PORT") 

62 

63 

64def test_monitor(monkeypatch: pytest.MonkeyPatch) -> None: 

65 runner = CliRunner() 

66 result = runner.invoke(cli, ["monitor", "nullmodem"]) 

67 assert result.exit_code == 0 # OK port name supplied 

68 assert result.output == " - discovery is enabled\n" 

69 

70 

71def test_execute_no_arg() -> None: 

72 runner = CliRunner() 

73 result = runner.invoke(cli, ["execute"]) 

74 assert result.exit_code == 2 # missing command, port 

75 assert result.output.startswith("Usage: cli execute [OPTIONS] SERIAL_PORT") 

76 

77 

78def test_execute(monkeypatch: pytest.MonkeyPatch) -> None: 

79 runner = CliRunner() 

80 result = runner.invoke(cli, ["execute", CMD]) 

81 assert result.exit_code == 0 # OK command supplied 

82 assert result.output == " - discovery is force-disabled\n" 

83 

84 

85def test_listen_no_arg() -> None: 

86 runner = CliRunner() 

87 result = runner.invoke(cli, ["listen"]) 

88 assert result.exit_code == 2 # missing port 

89 assert result.output.startswith("Usage: cli listen [OPTIONS] SERIAL_PORT") 

90 

91 

92def test_listen(monkeypatch: pytest.MonkeyPatch) -> None: 

93 runner = CliRunner() 

94 result = runner.invoke(cli, ["listen", "nullmodem"]) 

95 assert result.exit_code == 0 # OK port supplied 

96 assert result.output == " - sending is force-disabled\n" 

97 

98 

99# def test_convert() -> None: 

100# assert False 

101# 

102# 

103# def test_cli(): 

104# assert False 

105# 

106# 

107# def test_file_command(): 

108# assert False 

109# 

110# 

111# def test_file_cli(): 

112# assert False 

113# 

114# 

115# def test_port_command(): 

116# assert False 

117# 

118# 

119# def test_port_cli(): 

120# assert False 

121# 

122# 

123# def test_parse_cli(): 

124# assert False 

125# 

126# 

127# def test_print_results(): 

128# assert False 

129# 

130# 

131# def test__save_state(): 

132# assert False 

133# 

134# 

135# def test__print_engine_state(): 

136# assert False 

137# 

138# 

139# def test_print_summary(): 

140# assert False