Skip to content

Commit

Permalink
added pytests
Browse files Browse the repository at this point in the history
  • Loading branch information
nadineloepfe committed Jan 1, 2025
1 parent a2a76ce commit a686655
Show file tree
Hide file tree
Showing 15 changed files with 387 additions and 66 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@ src/hedera_sdk_python/hapi
.idea

# Pytest
.pytest_cache
.pytest_cache

uv.lock
8 changes: 0 additions & 8 deletions .idea/.gitignore

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/GitLink.xml

This file was deleted.

18 changes: 0 additions & 18 deletions .idea/hedera_sdk_python.iml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/misc.xml

This file was deleted.

8 changes: 0 additions & 8 deletions .idea/modules.xml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/vcs.xml

This file was deleted.

3 changes: 3 additions & 0 deletions src/hedera_sdk_python/consensus/topic_delete_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ def build_transaction_body(self):
Raises:
ValueError: If required fields are missing.
"""
if self.topic_id is None:
raise ValueError("Missing required fields: topic_id")

transaction_body = self.build_base_transaction_body()
transaction_body.consensusDeleteTopic.CopyFrom(consensus_delete_topic_pb2.ConsensusDeleteTopicTransactionBody(
topicID=self.topic_id.to_proto()
Expand Down
3 changes: 3 additions & 0 deletions src/hedera_sdk_python/consensus/topic_update_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ def build_transaction_body(self):
Raises:
ValueError: If required fields are missing.
"""
if self.topic_id is None:
raise ValueError("Missing required fields: topic_id")

transaction_body = self.build_base_transaction_body()
transaction_body.consensusUpdateTopic.CopyFrom(consensus_update_topic_pb2.ConsensusUpdateTopicTransactionBody(
topicID=self.topic_id.to_proto(),
Expand Down
13 changes: 11 additions & 2 deletions src/hedera_sdk_python/query/transaction_get_receipt_query.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from hedera_sdk_python.query.query import Query
from hedera_sdk_python.hapi import transaction_get_receipt_pb2, query_pb2
from hedera_sdk_python.hapi import transaction_get_receipt_pb2, query_pb2, query_header_pb2
from hedera_sdk_python.response_code import ResponseCode
from hedera_sdk_python.transaction.transaction_id import TransactionId
from hedera_sdk_python.transaction.transaction_receipt import TransactionReceipt
Expand Down Expand Up @@ -31,6 +31,13 @@ def set_transaction_id(self, transaction_id: TransactionId):
self.transaction_id = transaction_id
return self

def _is_payment_required(self):
"""
Override the default in the base Query class:
This particular query does NOT require a payment.
"""
return False

def _make_request(self):
"""
Constructs the protobuf request for the transaction receipt query.
Expand All @@ -46,7 +53,9 @@ def _make_request(self):
if not self.transaction_id:
raise ValueError("Transaction ID must be set before making the request.")

query_header = self._make_request_header()
query_header = query_header_pb2.QueryHeader()
query_header.responseType = query_header_pb2.ResponseType.ANSWER_ONLY

transaction_get_receipt = transaction_get_receipt_pb2.TransactionGetReceiptQuery()
transaction_get_receipt.header.CopyFrom(query_header)
transaction_get_receipt.transactionID.CopyFrom(self.transaction_id.to_proto())
Expand Down
23 changes: 12 additions & 11 deletions src/hedera_sdk_python/transaction/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,23 +185,24 @@ def build_base_transaction_body(self):
ValueError: If required IDs are not set.
"""
if self.transaction_id is None:
if self.operator_account_id is None:
raise ValueError("Operator account ID is not set.")
self.transaction_id = TransactionId.generate(self.operator_account_id)
if self.operator_account_id is None:
raise ValueError("Operator account ID is not set.")
self.transaction_id = TransactionId.generate(self.operator_account_id)

transaction_id_proto = self.transaction_id.to_proto()

if self.node_account_id is None:
raise ValueError("Node account ID is not set.")

transaction_body = transaction_body_pb2.TransactionBody(
transactionID=transaction_id_proto,
nodeAccountID=self.node_account_id.to_proto(),
transactionFee=self.transaction_fee or self._default_transaction_fee,
transactionValidDuration=duration_pb2.Duration(seconds=self.transaction_valid_duration),
generateRecord=self.generate_record,
memo=self.memo
)
transaction_body = transaction_body_pb2.TransactionBody()
transaction_body.transactionID.CopyFrom(transaction_id_proto)
transaction_body.nodeAccountID.CopyFrom(self.node_account_id.to_proto())

transaction_body.transactionFee = self.transaction_fee or self._default_transaction_fee

transaction_body.transactionValidDuration.seconds = self.transaction_valid_duration
transaction_body.generateRecord = self.generate_record
transaction_body.memo = self.memo

return transaction_body

Expand Down
106 changes: 106 additions & 0 deletions tests/test_topic_create_transaction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import pytest
from unittest.mock import MagicMock
from hedera_sdk_python.consensus.topic_create_transaction import TopicCreateTransaction
from hedera_sdk_python.account.account_id import AccountId
from hedera_sdk_python.crypto.private_key import PrivateKey
from hedera_sdk_python.client.client import Client
from hedera_sdk_python.response_code import ResponseCode
from hedera_sdk_python.hapi import (
transaction_receipt_pb2
)
from hedera_sdk_python.transaction.transaction_receipt import TransactionReceipt
from hedera_sdk_python.transaction.transaction_id import TransactionId
from hedera_sdk_python.hapi import timestamp_pb2 as hapi_timestamp_pb2

@pytest.mark.usefixtures("mock_account_ids")
def test_build_topic_create_transaction_body(mock_account_ids):
"""
Test building a TopicCreateTransaction body with valid memo, admin key.
"""
_, _, node_account_id, _, _ = mock_account_ids

tx = TopicCreateTransaction(memo="Hello Topic", admin_key=PrivateKey.generate().public_key())

tx.operator_account_id = AccountId(0, 0, 2)
tx.node_account_id = node_account_id

transaction_body = tx.build_transaction_body()

assert transaction_body.consensusCreateTopic.memo == "Hello Topic"
assert transaction_body.consensusCreateTopic.adminKey.ed25519

def test_missing_operator_in_topic_create(mock_account_ids):
"""
Test that building the body fails if no operator ID is set.
"""
_, _, node_account_id, _, _ = mock_account_ids

tx = TopicCreateTransaction(memo="No Operator")
tx.node_account_id = node_account_id

with pytest.raises(ValueError, match="Operator account ID is not set."):
tx.build_transaction_body()

def test_missing_node_in_topic_create(mock_account_ids):
"""
Test that building the body fails if no node account ID is set.
"""
tx = TopicCreateTransaction(memo="No Node")
tx.operator_account_id = AccountId(0, 0, 2)

with pytest.raises(ValueError, match="Node account ID is not set."):
tx.build_transaction_body()

def test_sign_topic_create_transaction(mock_account_ids):
"""
Test signing the TopicCreateTransaction with a private key.
"""
_, _, node_account_id, _, _ = mock_account_ids
tx = TopicCreateTransaction(memo="Signing test")
tx.operator_account_id = AccountId(0, 0, 2)
tx.node_account_id = node_account_id

private_key = PrivateKey.generate()

body_bytes = tx.build_transaction_body().SerializeToString()
tx.transaction_body_bytes = body_bytes

tx.sign(private_key)
assert len(tx.signature_map.sigPair) == 1

def test_execute_topic_create_transaction(mock_account_ids):
"""
Test executing the TopicCreateTransaction with a mock Client.
"""
_, _, node_account_id, _, _ = mock_account_ids

tx = TopicCreateTransaction(memo="Execute test")
tx.operator_account_id = AccountId(0, 0, 2)

client = MagicMock(spec=Client)
client.operator_private_key = PrivateKey.generate()
client.operator_account_id = AccountId(0, 0, 2)
client.node_account_id = node_account_id

real_tx_id = TransactionId(
account_id=AccountId(0, 0, 2),
valid_start=hapi_timestamp_pb2.Timestamp(seconds=11111, nanos=222)
)
client.generate_transaction_id.return_value = real_tx_id

client.topic_stub = MagicMock()

mock_response = MagicMock()
mock_response.nodeTransactionPrecheckCode = ResponseCode.OK
client.topic_stub.createTopic.return_value = mock_response

proto_receipt = transaction_receipt_pb2.TransactionReceipt(status=ResponseCode.OK)
real_receipt = TransactionReceipt.from_proto(proto_receipt)
client.get_transaction_receipt.return_value = real_receipt

receipt = tx.execute(client)

client.topic_stub.createTopic.assert_called_once()
assert receipt is not None
assert receipt.status == ResponseCode.OK
print("Test passed: TopicCreateTransaction executed successfully.")
94 changes: 94 additions & 0 deletions tests/test_topic_delete_transaction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import pytest
from unittest.mock import MagicMock
from hedera_sdk_python.consensus.topic_delete_transaction import TopicDeleteTransaction
from hedera_sdk_python.consensus.topic_id import TopicId
from hedera_sdk_python.account.account_id import AccountId
from hedera_sdk_python.crypto.private_key import PrivateKey
from hedera_sdk_python.client.client import Client
from hedera_sdk_python.response_code import ResponseCode
from hedera_sdk_python.hapi import transaction_receipt_pb2
from hedera_sdk_python.transaction.transaction_receipt import TransactionReceipt
from hedera_sdk_python.transaction.transaction_id import TransactionId
from hedera_sdk_python.hapi import timestamp_pb2 as hapi_timestamp_pb2

@pytest.mark.usefixtures("mock_account_ids")
def test_build_topic_delete_transaction_body(mock_account_ids):
"""
Test building a TopicDeleteTransaction body with a valid topic ID.
"""
_, _, node_account_id, _, _ = mock_account_ids
topic_id = TopicId(0,0,1234)
tx = TopicDeleteTransaction(topic_id=topic_id)

tx.operator_account_id = AccountId(0, 0, 2)
tx.node_account_id = node_account_id

transaction_body = tx.build_transaction_body()
assert transaction_body.consensusDeleteTopic.topicID.topicNum == 1234

def test_missing_topic_id_in_delete(mock_account_ids):
"""
Test that building fails if no topic ID is provided.
"""
_, _, node_account_id, _, _ = mock_account_ids
tx = TopicDeleteTransaction(topic_id=None)
tx.operator_account_id = AccountId(0, 0, 2)
tx.node_account_id = node_account_id

with pytest.raises(ValueError, match="Missing required fields"):
tx.build_transaction_body()

def test_sign_topic_delete_transaction(mock_account_ids):
"""
Test signing the TopicDeleteTransaction with a private key.
"""
_, _, node_account_id, _, _ = mock_account_ids
tx = TopicDeleteTransaction(topic_id=TopicId(0,0,9876))
tx.operator_account_id = AccountId(0, 0, 2)
tx.node_account_id = node_account_id

private_key = PrivateKey.generate()

body_bytes = tx.build_transaction_body().SerializeToString()
tx.transaction_body_bytes = body_bytes

tx.sign(private_key)
assert len(tx.signature_map.sigPair) == 1

def test_execute_topic_delete_transaction(mock_account_ids):
"""
Test executing the TopicDeleteTransaction with a mock Client.
"""
_, _, node_account_id, _, _ = mock_account_ids
topic_id = TopicId(0,0,9876)
tx = TopicDeleteTransaction(topic_id=topic_id)
tx.operator_account_id = AccountId(0, 0, 2)

client = MagicMock(spec=Client)
client.operator_private_key = PrivateKey.generate()
client.operator_account_id = AccountId(0, 0, 2)
client.node_account_id = node_account_id

real_tx_id = TransactionId(
account_id=AccountId(0, 0, 2),
valid_start=hapi_timestamp_pb2.Timestamp(seconds=20000, nanos=3333)
)
client.generate_transaction_id.return_value = real_tx_id

client.topic_stub = MagicMock()
mock_response = MagicMock()
mock_response.nodeTransactionPrecheckCode = ResponseCode.OK
client.topic_stub.deleteTopic.return_value = mock_response

proto_receipt = transaction_receipt_pb2.TransactionReceipt(status=ResponseCode.OK)
real_receipt = TransactionReceipt.from_proto(proto_receipt)
client.get_transaction_receipt.return_value = real_receipt

# Act
receipt = tx.execute(client)

# Assert
client.topic_stub.deleteTopic.assert_called_once()
assert receipt is not None
assert receipt.status == ResponseCode.OK
print("Test passed: TopicDeleteTransaction executed successfully.")
Loading

0 comments on commit a686655

Please sign in to comment.