mirror of
https://github.com/meshtastic/python.git
synced 2026-01-29 18:11:15 -05:00
222 lines
6.9 KiB
Python
222 lines
6.9 KiB
Python
"""Meshtastic unit tests for showNodes favorite column feature"""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
|
|
from ..mesh_interface import MeshInterface
|
|
|
|
|
|
@pytest.fixture
|
|
def _iface_with_favorite_nodes():
|
|
"""Fixture to setup nodes with favorite flags."""
|
|
nodesById = {
|
|
"!9388f81c": {
|
|
"num": 2475227164,
|
|
"user": {
|
|
"id": "!9388f81c",
|
|
"longName": "Favorite Node",
|
|
"shortName": "FAV1",
|
|
"macaddr": "RBeTiPgc",
|
|
"hwModel": "TBEAM",
|
|
},
|
|
"position": {},
|
|
"lastHeard": 1640204888,
|
|
"isFavorite": True,
|
|
},
|
|
"!12345678": {
|
|
"num": 305419896,
|
|
"user": {
|
|
"id": "!12345678",
|
|
"longName": "Regular Node",
|
|
"shortName": "REG1",
|
|
"macaddr": "ABCDEFGH",
|
|
"hwModel": "TLORA_V2",
|
|
},
|
|
"position": {},
|
|
"lastHeard": 1640204999,
|
|
"isFavorite": False,
|
|
},
|
|
"!abcdef00": {
|
|
"num": 2882400000,
|
|
"user": {
|
|
"id": "!abcdef00",
|
|
"longName": "Legacy Node",
|
|
"shortName": "LEG1",
|
|
"macaddr": "XYZABC00",
|
|
"hwModel": "HELTEC_V3",
|
|
},
|
|
"position": {},
|
|
"lastHeard": 1640205000,
|
|
# Note: No isFavorite field - testing backward compatibility
|
|
},
|
|
}
|
|
|
|
nodesByNum = {
|
|
2475227164: {
|
|
"num": 2475227164,
|
|
"user": {
|
|
"id": "!9388f81c",
|
|
"longName": "Favorite Node",
|
|
"shortName": "FAV1",
|
|
"macaddr": "RBeTiPgc",
|
|
"hwModel": "TBEAM",
|
|
},
|
|
"position": {"time": 1640206266},
|
|
"lastHeard": 1640206266,
|
|
"isFavorite": True,
|
|
},
|
|
305419896: {
|
|
"num": 305419896,
|
|
"user": {
|
|
"id": "!12345678",
|
|
"longName": "Regular Node",
|
|
"shortName": "REG1",
|
|
"macaddr": "ABCDEFGH",
|
|
"hwModel": "TLORA_V2",
|
|
},
|
|
"position": {"time": 1640206200},
|
|
"lastHeard": 1640206200,
|
|
"isFavorite": False,
|
|
},
|
|
2882400000: {
|
|
"num": 2882400000,
|
|
"user": {
|
|
"id": "!abcdef00",
|
|
"longName": "Legacy Node",
|
|
"shortName": "LEG1",
|
|
"macaddr": "XYZABC00",
|
|
"hwModel": "HELTEC_V3",
|
|
},
|
|
"position": {"time": 1640206100},
|
|
"lastHeard": 1640206100,
|
|
# Note: No isFavorite field - testing backward compatibility
|
|
},
|
|
}
|
|
|
|
iface = MeshInterface(noProto=True)
|
|
iface.nodes = nodesById
|
|
iface.nodesByNum = nodesByNum
|
|
myInfo = MagicMock()
|
|
iface.myInfo = myInfo
|
|
iface.myInfo.my_node_num = 2475227164
|
|
return iface
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_showNodes_favorite_column_header(capsys, _iface_with_favorite_nodes):
|
|
"""Test that 'Fav' column header appears in showNodes output"""
|
|
iface = _iface_with_favorite_nodes
|
|
iface.showNodes()
|
|
out, err = capsys.readouterr()
|
|
assert "Fav" in out
|
|
assert err == ""
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_showNodes_favorite_asterisk_display(capsys, _iface_with_favorite_nodes):
|
|
"""Test that favorite nodes show asterisk and non-favorites show empty"""
|
|
iface = _iface_with_favorite_nodes
|
|
iface.showNodes()
|
|
out, err = capsys.readouterr()
|
|
|
|
# Check that the output contains the "Fav" column
|
|
assert "Fav" in out
|
|
|
|
# Find lines containing our nodes
|
|
lines = out.split('\n')
|
|
favorite_line = None
|
|
regular_line = None
|
|
legacy_line = None
|
|
for line in lines:
|
|
if "Favorite Node" in line or "FAV1" in line:
|
|
favorite_line = line
|
|
if "Regular Node" in line or "REG1" in line:
|
|
regular_line = line
|
|
if "Legacy Node" in line or "LEG1" in line:
|
|
legacy_line = line
|
|
|
|
# Verify all nodes are present in the output
|
|
assert favorite_line is not None, "Favorite node should be in output"
|
|
assert regular_line is not None, "Regular node should be in output"
|
|
assert legacy_line is not None, "Legacy node should be in output"
|
|
|
|
# Verify the favorite node has an asterisk in its row
|
|
assert "*" in favorite_line, "Favorite node should have an asterisk"
|
|
|
|
# Verify the regular (non-favorite) node does NOT have an asterisk
|
|
assert regular_line.count("*") == 0, "Non-favorite node should not have an asterisk"
|
|
|
|
# Verify the legacy node (without isFavorite field) does NOT have an asterisk
|
|
assert legacy_line.count("*") == 0, "Legacy node without isFavorite field should not have an asterisk"
|
|
|
|
assert err == ""
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_showNodes_favorite_field_formatting():
|
|
"""Test the formatting logic for isFavorite field"""
|
|
# Test favorite node
|
|
raw_value = True
|
|
formatted_value = "*" if raw_value else ""
|
|
assert formatted_value == "*"
|
|
|
|
# Test non-favorite node
|
|
raw_value = False
|
|
formatted_value = "*" if raw_value else ""
|
|
assert formatted_value == ""
|
|
|
|
# Test None/missing value
|
|
raw_value = None
|
|
formatted_value = "*" if raw_value else ""
|
|
assert formatted_value == ""
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_showNodes_with_custom_fields_including_favorite(capsys, _iface_with_favorite_nodes):
|
|
"""Test that isFavorite can be specified in custom showFields"""
|
|
iface = _iface_with_favorite_nodes
|
|
custom_fields = ["user.longName", "isFavorite"]
|
|
iface.showNodes(showFields=custom_fields)
|
|
out, err = capsys.readouterr()
|
|
|
|
# Should still show the Fav column when explicitly requested
|
|
assert "Fav" in out
|
|
assert err == ""
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_showNodes_default_fields_includes_favorite(_iface_with_favorite_nodes):
|
|
"""Test that isFavorite is included in default fields"""
|
|
iface = _iface_with_favorite_nodes
|
|
|
|
# Call showNodes which uses default fields
|
|
result = iface.showNodes()
|
|
|
|
# The result should contain the formatted table as a string
|
|
assert "Fav" in result
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_showNodes_backward_compatibility_missing_field(capsys, _iface_with_favorite_nodes):
|
|
"""Test that nodes without isFavorite field are handled gracefully"""
|
|
iface = _iface_with_favorite_nodes
|
|
iface.showNodes()
|
|
out, err = capsys.readouterr()
|
|
|
|
# Find the legacy node line
|
|
lines = out.split('\n')
|
|
legacy_line = None
|
|
for line in lines:
|
|
if "Legacy Node" in line or "LEG1" in line:
|
|
legacy_line = line
|
|
break
|
|
|
|
# Verify the legacy node appears in output
|
|
assert legacy_line is not None, "Legacy node without isFavorite field should appear in output"
|
|
|
|
# Verify it doesn't have an asterisk (should be treated as non-favorite)
|
|
assert legacy_line.count("*") == 0, "Legacy node should not have asterisk (treated as non-favorite)"
|
|
|
|
assert err == ""
|