11import pytest
22from unittest .mock import MagicMock
3+ import warnings
34
45from hiero_sdk_python .tokens .nft_id import NftId
56from hiero_sdk_python .tokens .token_info import TokenInfo
6- from hiero_sdk_python .transaction .transaction_receipt import TransactionReceipt
77from hiero_sdk_python .tokens .token_id import TokenId
8+ from hiero_sdk_python .tokens .token_type import TokenType
9+ from hiero_sdk_python .tokens .token_freeze_status import TokenFreezeStatus
10+ from hiero_sdk_python .tokens .token_kyc_status import TokenKycStatus
11+ from hiero_sdk_python .tokens .token_pause_status import TokenPauseStatus
12+ from hiero_sdk_python .tokens .supply_type import SupplyType
13+ from hiero_sdk_python .tokens .token_id import TokenId
14+ from hiero_sdk_python .hapi .services .basic_types_pb2 import TokenID , AccountID , Key
15+ from hiero_sdk_python .transaction .transaction_receipt import TransactionReceipt
16+
817
918def test_nftid_deprecated_alias_access ():
1019 token = TokenId .from_string ("0.0.123" )
@@ -70,4 +79,103 @@ def test_transactionreceipt_deprecated_alias_access():
7079 with pytest .warns (FutureWarning ) as record_file :
7180 fileid = tr .fileId
7281 assert fileid is None
73- assert "fileId" in str (record_file [0 ].message )
82+ assert "fileId" in str (record_file [0 ].message )
83+
84+ class DummyProto :
85+ """Stand‑in for proto_TokenInfo; uses real TokenID/AccountID so ._from_proto accepts them."""
86+
87+ def __init__ (self ):
88+ # scalar fields
89+ self .name = "Foo"
90+ self .symbol = "F"
91+ self .decimals = 2
92+ self .totalSupply = 1_000
93+ self .deleted = False
94+ self .memo = "test"
95+ self .tokenType = TokenType .FUNGIBLE_COMMON .value
96+ self .maxSupply = 10_000
97+ self .ledger_id = b"\x00 "
98+ self .metadata = b"\x01 "
99+
100+ # real protobuf messages for tokenId and treasury
101+ self .tokenId = TokenID (shardNum = 0 , realmNum = 0 , tokenNum = 42 )
102+ self .treasury = AccountID (shardNum = 0 , realmNum = 0 , accountNum = 99 )
103+
104+ # empty key protos
105+ self .adminKey = Key ()
106+ self .kycKey = Key ()
107+ self .freezeKey = Key ()
108+ self .wipeKey = Key ()
109+ self .supplyKey = Key ()
110+ self .metadata_key = Key ()
111+ self .fee_schedule_key = Key ()
112+ self .pause_key = Key ()
113+
114+ # statuses
115+ self .defaultFreezeStatus = TokenFreezeStatus .FREEZE_NOT_APPLICABLE .value
116+ self .defaultKycStatus = TokenKycStatus .KYC_NOT_APPLICABLE .value
117+ self .pause_status = TokenPauseStatus .PAUSE_NOT_APPLICABLE .value
118+ self .supplyType = SupplyType .FINITE .value
119+
120+ # skip these branches
121+ self .autoRenewAccount = None
122+ self .autoRenewPeriod = None
123+ self .expiry = None
124+
125+
126+ def test_camelcase_init_and_snake_field_assignment ():
127+ with warnings .catch_warnings (record = True ) as w :
128+ warnings .simplefilter ("always" , FutureWarning )
129+ ti = TokenInfo (tokenId = "TID123" , totalSupply = 500 , isDeleted = True )
130+ assert any ("tokenId" in str (wi .message ) for wi in w )
131+ assert any ("totalSupply" in str (wi .message ) for wi in w )
132+ assert ti .token_id == "TID123"
133+ assert ti .total_supply == 500
134+ assert ti .is_deleted is True
135+
136+ def test_legacy_attribute_get_and_set_warns ():
137+ ti = TokenInfo ()
138+ with warnings .catch_warnings (record = True ) as w :
139+ warnings .simplefilter ("always" , FutureWarning )
140+ ti .adminKey = "AKey"
141+ assert any ("adminKey=" in str (wi .message ) for wi in w )
142+ assert ti .admin_key == "AKey"
143+
144+ ti .default_freeze_status = TokenFreezeStatus .FREEZE_NOT_APPLICABLE
145+ with warnings .catch_warnings (record = True ) as w :
146+ warnings .simplefilter ("always" , FutureWarning )
147+ val = ti .defaultFreezeStatus
148+ assert any ("defaultFreezeStatus" in str (wi .message ) for wi in w )
149+ assert isinstance (val , TokenFreezeStatus )
150+
151+ def test_setter_aliases_work_and_mutate_correct_field ():
152+ ti = TokenInfo ()
153+ ti .set_freezeKey (TokenFreezeStatus .FREEZE_NOT_APPLICABLE )
154+ assert ti .freeze_key == TokenFreezeStatus .FREEZE_NOT_APPLICABLE
155+ ti .set_defaultKycStatus (TokenKycStatus .KYC_NOT_APPLICABLE )
156+ assert ti .default_kyc_status == TokenKycStatus .KYC_NOT_APPLICABLE
157+ ti .set_pauseStatus (TokenPauseStatus .PAUSE_NOT_APPLICABLE )
158+ assert ti .pause_status == TokenPauseStatus .PAUSE_NOT_APPLICABLE
159+ ti .set_supplyType (SupplyType .INFINITE )
160+ assert ti .supply_type == SupplyType .INFINITE
161+
162+ def test_from_proto_and_to_string_contains_expected ():
163+ proto = DummyProto ()
164+ ti = TokenInfo ._from_proto (proto )
165+ # core fields
166+ assert ti .name == "Foo"
167+ assert ti .symbol == "F"
168+ # repr uses snake_case
169+ s = str (ti )
170+ assert "token_id=" in s
171+ assert "name='Foo'" in s
172+ assert "total_supply=1000" in s
173+
174+ @pytest .mark .parametrize ("field,value" , [
175+ ("decimals" , 8 ),
176+ ("memo" , "hello" ),
177+ ])
178+ def test_snake_case_assignment_and_retrieval (field , value ):
179+ ti = TokenInfo ()
180+ setattr (ti , field , value )
181+ assert getattr (ti , field ) == value
0 commit comments