Migrate to uv, add tests, and fix location-independent paths

This commit is contained in:
seangreaves
2026-02-21 11:35:29 +00:00
parent acbb957c14
commit 60eed23cb5
27 changed files with 3593 additions and 208 deletions

View File

@@ -1,61 +1,142 @@
import sugartrail
import pytest
import json
from pathlib import Path
import sugartrail
# test 1: network initialised without auth and without arguments:
# Use an absolute path so tests pass regardless of working directory.
# quickstart_a.json is a pre-generated file committed to the repo.
NETWORK_FILE = str(Path(__file__).parent.parent / 'assets/networks/quickstart_a.json')
def test_init_without_arguments(capsys):
NETWORK_FILE = str(Path(__file__).parent.parent / 'assets/networks/quickstart_a.json')
# ---------------------------------------------------------------------------
# Initialisation without arguments
# ---------------------------------------------------------------------------
def test_init_without_arguments(no_auth, capsys):
sugartrail.base.Network()
captured = capsys.readouterr()
assert captured.out == 'No input provided. Please provide either officer_id, company_id, address or file as input.\n'
# test 2: network initialised without auth and with arguments prints auth requirement:
def test_init_officer_without_auth(capsys):
sugartrail.base.Network(officer_id = '_')
# ---------------------------------------------------------------------------
# Initialisation without auth prints requirement message
# ---------------------------------------------------------------------------
def test_init_officer_without_auth(no_auth, capsys):
sugartrail.base.Network(officer_id='_')
captured = capsys.readouterr()
assert captured.out == 'Authentication required\n'
def test_init_company_without_auth(capsys):
sugartrail.base.Network(company_id = '_')
def test_init_company_without_auth(no_auth, capsys):
sugartrail.base.Network(company_id='_')
captured = capsys.readouterr()
assert captured.out == 'Authentication required\n'
def test_init_address_without_auth(capsys):
sugartrail.base.Network(address = '_')
def test_init_address_without_auth(no_auth, capsys):
sugartrail.base.Network(address='_')
captured = capsys.readouterr()
assert captured.out == 'Authentication required\n'
# test 3: network initialised without auth and with arguments remains stateless:
def test_empty_officer_without_auth(capsys):
network = sugartrail.base.Network(officer_id = '_')
assert network._officer_id == None
# ---------------------------------------------------------------------------
# State is unchanged when auth fails
# ---------------------------------------------------------------------------
def test_empty_company_without_auth(capsys):
network = sugartrail.base.Network(company_id = '_')
assert network._company_id == None
def test_empty_officer_without_auth(no_auth, capsys):
network = sugartrail.base.Network(officer_id='_')
assert network._officer_id is None
def test_empty_address_without_auth(capsys):
network = sugartrail.base.Network(address = '_')
assert network._address == None
def test_empty_company_without_auth(no_auth, capsys):
network = sugartrail.base.Network(company_id='_')
assert network._company_id is None
# test 4: network initialised with 'file' arg without auth loads network:
def test_empty_address_without_auth(no_auth, capsys):
network = sugartrail.base.Network(address='_')
assert network._address is None
# ---------------------------------------------------------------------------
# Loading a network from file (no auth required)
# ---------------------------------------------------------------------------
def test_file_init_without_auth():
network = sugartrail.base.Network(file ='./assets/networks/domain_corp_network.json')
with open('./assets/networks/domain_corp_network.json') as f:
network = sugartrail.base.Network(file=NETWORK_FILE)
with open(NETWORK_FILE) as f:
network_json = json.load(f)
for key in network.__dict__.keys():
if key not in sugartrail.base.Network._unserialisable_attributes:
assert network.__dict__[key] == network_json[key]
# test 5: network loads network from file without auth:
def test_file_load_without_auth():
def test_file_load_without_auth(capsys):
network = sugartrail.base.Network()
network.load('./assets/networks/domain_corp_network.json')
with open('./assets/networks/domain_corp_network.json') as f:
capsys.readouterr() # discard "No input provided" message
network.load(NETWORK_FILE)
with open(NETWORK_FILE) as f:
network_json = json.load(f)
for key in network.__dict__.keys():
if key not in sugartrail.base.Network._unserialisable_attributes:
assert network.__dict__[key] == network_json[key]
# ---------------------------------------------------------------------------
# find_path — pure graph traversal, no API calls needed
# ---------------------------------------------------------------------------
@pytest.fixture
def two_node_network(no_auth, capsys):
"""Network with a seed company connected to one officer."""
network = sugartrail.base.Network()
capsys.readouterr()
network.graph = {
'CO001': {
'title': 'Test Corp',
'depth': 0,
'node_type': 'Company',
'arcs': [],
},
'OFF001': {
'title': 'John Smith',
'depth': 1,
'node_type': 'Person',
'arcs': [{'arc_type': 'Officer', 'start_node': 'CO001'}],
},
}
network.n = 1
return network
def test_find_path_from_seed_returns_single_node(two_node_network):
path = two_node_network.find_path('CO001')
assert len(path) == 1
assert path[0]['id'] == 'CO001'
assert path[0]['node_type'] == 'Company'
def test_find_path_to_connected_node_includes_both(two_node_network):
path = two_node_network.find_path('OFF001')
ids = [item['id'] for item in path]
assert 'CO001' in ids
assert 'OFF001' in ids
def test_find_path_is_ordered_from_seed(two_node_network):
path = two_node_network.find_path('OFF001')
# Path should start at depth 0 (the seed)
assert path[0]['depth'] == 0
# ---------------------------------------------------------------------------
# Graph property views
# ---------------------------------------------------------------------------
def test_company_ids_property(two_node_network):
companies = two_node_network.company_ids
assert len(companies) == 1
assert companies[0]['company_id'] == 'CO001'
def test_officer_ids_property(two_node_network):
officers = two_node_network.officer_ids
assert len(officers) == 1
assert officers[0]['officer_id'] == 'OFF001'