"""
Binance Staking REST API

OpenAPI Specification for the Binance Staking REST API
The version of the OpenAPI document: 1.0.0
Generated by OpenAPI Generator (https://openapi-generator.tech)

Do not edit the class manually.
"""

import json
import pytest
import requests

from unittest.mock import MagicMock, patch
from urllib.parse import parse_qs

from binance_common.configuration import ConfigurationRestAPI
from binance_common.errors import RequiredError
from binance_common.utils import normalize_query_values, is_one_of_model, snake_to_camel

from binance_sdk_staking.rest_api.api import OnChainYieldsApi
from binance_sdk_staking.rest_api.models import (
    GetOnChainYieldsLockedPersonalLeftQuotaResponse,
)
from binance_sdk_staking.rest_api.models import (
    GetOnChainYieldsLockedProductListResponse,
)
from binance_sdk_staking.rest_api.models import (
    GetOnChainYieldsLockedProductPositionResponse,
)
from binance_sdk_staking.rest_api.models import (
    GetOnChainYieldsLockedRedemptionRecordResponse,
)
from binance_sdk_staking.rest_api.models import (
    GetOnChainYieldsLockedRewardsHistoryResponse,
)
from binance_sdk_staking.rest_api.models import (
    GetOnChainYieldsLockedSubscriptionPreviewResponse,
)
from binance_sdk_staking.rest_api.models import (
    GetOnChainYieldsLockedSubscriptionRecordResponse,
)
from binance_sdk_staking.rest_api.models import OnChainYieldsAccountResponse
from binance_sdk_staking.rest_api.models import RedeemOnChainYieldsLockedProductResponse
from binance_sdk_staking.rest_api.models import (
    SetOnChainYieldsLockedAutoSubscribeResponse,
)
from binance_sdk_staking.rest_api.models import (
    SetOnChainYieldsLockedProductRedeemOptionResponse,
)
from binance_sdk_staking.rest_api.models import (
    SubscribeOnChainYieldsLockedProductResponse,
)


class TestOnChainYieldsApi:
    @pytest.fixture(autouse=True)
    def setup_client(self):
        """Setup a client instance with mocked session before each test method."""
        self.mock_session = MagicMock(spec=requests.Session)
        config = ConfigurationRestAPI(
            api_key="test-api-key",
            api_secret="test-api-secret",
        )
        self.client = OnChainYieldsApi(configuration=config, session=self.mock_session)

    def set_mock_response(self, data: dict = {}, status_code=200, headers=None):
        """Helper method to setup mock response for the client's session request."""
        if headers is None:
            headers = {}

        mock_response = MagicMock()
        mock_response.status_code = status_code
        mock_response.json.return_value = data
        mock_response.text = json.dumps(data)
        mock_response.headers = headers

        self.mock_session.request.return_value = mock_response

    @patch("binance_common.utils.get_signature")
    def test_get_on_chain_yields_locked_personal_left_quota_success(
        self, mock_get_signature
    ):
        """Test get_on_chain_yields_locked_personal_left_quota() successfully with required parameters only."""

        params = {
            "project_id": "1",
        }

        expected_response = {"leftPersonalQuota": "1000"}
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.get_on_chain_yields_locked_personal_left_quota(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs
        parsed_params = parse_qs(request_kwargs["params"])
        camel_case_params = {snake_to_camel(k): v for k, v in params.items()}
        normalized = normalize_query_values(parsed_params, camel_case_params)

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert (
            "/sapi/v1/onchain-yields/locked/personalLeftQuota" in request_kwargs["url"]
        )
        assert request_kwargs["method"] == "GET"
        assert normalized["projectId"] == "1"

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(GetOnChainYieldsLockedPersonalLeftQuotaResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(GetOnChainYieldsLockedPersonalLeftQuotaResponse, "from_dict")
        ):
            expected = GetOnChainYieldsLockedPersonalLeftQuotaResponse.from_dict(
                expected_response
            )
        else:
            expected = (
                GetOnChainYieldsLockedPersonalLeftQuotaResponse.model_validate_json(
                    json.dumps(expected_response)
                )
            )

        assert response.data() == expected

    @patch("binance_common.utils.get_signature")
    def test_get_on_chain_yields_locked_personal_left_quota_success_with_optional_params(
        self, mock_get_signature
    ):
        """Test get_on_chain_yields_locked_personal_left_quota() successfully with optional parameters."""

        params = {"project_id": "1", "recv_window": 5000}

        expected_response = {"leftPersonalQuota": "1000"}
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.get_on_chain_yields_locked_personal_left_quota(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert (
            "/sapi/v1/onchain-yields/locked/personalLeftQuota" in request_kwargs["url"]
        )
        assert request_kwargs["method"] == "GET"

        self.mock_session.request.assert_called_once()
        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(GetOnChainYieldsLockedPersonalLeftQuotaResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(GetOnChainYieldsLockedPersonalLeftQuotaResponse, "from_dict")
        ):
            expected = GetOnChainYieldsLockedPersonalLeftQuotaResponse.from_dict(
                expected_response
            )
        else:
            expected = (
                GetOnChainYieldsLockedPersonalLeftQuotaResponse.model_validate_json(
                    json.dumps(expected_response)
                )
            )

        assert response.data() == expected

    def test_get_on_chain_yields_locked_personal_left_quota_missing_required_param_project_id(
        self,
    ):
        """Test that get_on_chain_yields_locked_personal_left_quota() raises RequiredError when 'project_id' is missing."""
        params = {
            "project_id": "1",
        }
        params["project_id"] = None

        with pytest.raises(
            RequiredError, match="Missing required parameter 'project_id'"
        ):
            self.client.get_on_chain_yields_locked_personal_left_quota(**params)

    def test_get_on_chain_yields_locked_personal_left_quota_server_error(self):
        """Test that get_on_chain_yields_locked_personal_left_quota() raises an error when the server returns an error."""

        params = {
            "project_id": "1",
        }

        mock_error = Exception("ResponseError")
        self.client.get_on_chain_yields_locked_personal_left_quota = MagicMock(
            side_effect=mock_error
        )

        with pytest.raises(Exception, match="ResponseError"):
            self.client.get_on_chain_yields_locked_personal_left_quota(**params)

    @patch("binance_common.utils.get_signature")
    def test_get_on_chain_yields_locked_product_list_success(self, mock_get_signature):
        """Test get_on_chain_yields_locked_product_list() successfully with required parameters only."""

        expected_response = {
            "rows": [
                {
                    "projectId": "Solv-60d",
                    "detail": {
                        "asset": "BTC",
                        "rewardAsset": "SOLV",
                        "duration": 60,
                        "renewable": True,
                        "isSoldOut": True,
                        "apr": "0.039",
                        "status": "PREHEATING",
                        "subscriptionStartTime": 1646182276000,
                        "canRedeemToFlex": True,
                    },
                    "quota": {"totalPersonalQuota": "2", "minimum": "0.001"},
                }
            ],
            "total": 1,
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.get_on_chain_yields_locked_product_list()

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/onchain-yields/locked/list" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(GetOnChainYieldsLockedProductListResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(GetOnChainYieldsLockedProductListResponse, "from_dict")
        ):
            expected = GetOnChainYieldsLockedProductListResponse.from_dict(
                expected_response
            )
        else:
            expected = GetOnChainYieldsLockedProductListResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    @patch("binance_common.utils.get_signature")
    def test_get_on_chain_yields_locked_product_list_success_with_optional_params(
        self, mock_get_signature
    ):
        """Test get_on_chain_yields_locked_product_list() successfully with optional parameters."""

        params = {"asset": "BETH", "current": 1, "size": 10, "recv_window": 5000}

        expected_response = {
            "rows": [
                {
                    "projectId": "Solv-60d",
                    "detail": {
                        "asset": "BTC",
                        "rewardAsset": "SOLV",
                        "duration": 60,
                        "renewable": True,
                        "isSoldOut": True,
                        "apr": "0.039",
                        "status": "PREHEATING",
                        "subscriptionStartTime": 1646182276000,
                        "canRedeemToFlex": True,
                    },
                    "quota": {"totalPersonalQuota": "2", "minimum": "0.001"},
                }
            ],
            "total": 1,
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.get_on_chain_yields_locked_product_list(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/onchain-yields/locked/list" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        self.mock_session.request.assert_called_once()
        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(GetOnChainYieldsLockedProductListResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(GetOnChainYieldsLockedProductListResponse, "from_dict")
        ):
            expected = GetOnChainYieldsLockedProductListResponse.from_dict(
                expected_response
            )
        else:
            expected = GetOnChainYieldsLockedProductListResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    def test_get_on_chain_yields_locked_product_list_server_error(self):
        """Test that get_on_chain_yields_locked_product_list() raises an error when the server returns an error."""

        mock_error = Exception("ResponseError")
        self.client.get_on_chain_yields_locked_product_list = MagicMock(
            side_effect=mock_error
        )

        with pytest.raises(Exception, match="ResponseError"):
            self.client.get_on_chain_yields_locked_product_list()

    @patch("binance_common.utils.get_signature")
    def test_get_on_chain_yields_locked_product_position_success(
        self, mock_get_signature
    ):
        """Test get_on_chain_yields_locked_product_position() successfully with required parameters only."""

        expected_response = {
            "rows": [
                {
                    "positionId": "123123",
                    "projectId": "Solv-60d",
                    "asset": "BTC",
                    "amount": "122.09202928",
                    "purchaseTime": "1646182276000",
                    "duration": "60",
                    "accrualDays": "4",
                    "rewardAsset": "SOLV",
                    "APY": "0.039",
                    "rewardAmt": "5.17181528",
                    "nextPay": "1.29295383",
                    "nextPayDate": "1646697600000",
                    "payPeriod": "1",
                    "rewardsPayDate": "1646697600000",
                    "rewardsEndDate": "1651449600000",
                    "deliverDate": "1651536000000",
                    "nextSubscriptionDate": "1651536000000",
                    "redeemingAmt": "232.2323",
                    "redeemTo": "FLEXIBLE",
                    "canRedeemEarly": True,
                    "autoSubscribe": True,
                    "type": "AUTO",
                    "status": "HOLDING",
                }
            ],
            "total": 1,
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.get_on_chain_yields_locked_product_position()

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/onchain-yields/locked/position" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(GetOnChainYieldsLockedProductPositionResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(GetOnChainYieldsLockedProductPositionResponse, "from_dict")
        ):
            expected = GetOnChainYieldsLockedProductPositionResponse.from_dict(
                expected_response
            )
        else:
            expected = (
                GetOnChainYieldsLockedProductPositionResponse.model_validate_json(
                    json.dumps(expected_response)
                )
            )

        assert response.data() == expected

    @patch("binance_common.utils.get_signature")
    def test_get_on_chain_yields_locked_product_position_success_with_optional_params(
        self, mock_get_signature
    ):
        """Test get_on_chain_yields_locked_product_position() successfully with optional parameters."""

        params = {
            "asset": "BETH",
            "position_id": 1,
            "project_id": "1",
            "current": 1,
            "size": 10,
            "recv_window": 5000,
        }

        expected_response = {
            "rows": [
                {
                    "positionId": "123123",
                    "projectId": "Solv-60d",
                    "asset": "BTC",
                    "amount": "122.09202928",
                    "purchaseTime": "1646182276000",
                    "duration": "60",
                    "accrualDays": "4",
                    "rewardAsset": "SOLV",
                    "APY": "0.039",
                    "rewardAmt": "5.17181528",
                    "nextPay": "1.29295383",
                    "nextPayDate": "1646697600000",
                    "payPeriod": "1",
                    "rewardsPayDate": "1646697600000",
                    "rewardsEndDate": "1651449600000",
                    "deliverDate": "1651536000000",
                    "nextSubscriptionDate": "1651536000000",
                    "redeemingAmt": "232.2323",
                    "redeemTo": "FLEXIBLE",
                    "canRedeemEarly": True,
                    "autoSubscribe": True,
                    "type": "AUTO",
                    "status": "HOLDING",
                }
            ],
            "total": 1,
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.get_on_chain_yields_locked_product_position(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert "/sapi/v1/onchain-yields/locked/position" in request_kwargs["url"]
        assert request_kwargs["method"] == "GET"

        self.mock_session.request.assert_called_once()
        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(GetOnChainYieldsLockedProductPositionResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(GetOnChainYieldsLockedProductPositionResponse, "from_dict")
        ):
            expected = GetOnChainYieldsLockedProductPositionResponse.from_dict(
                expected_response
            )
        else:
            expected = (
                GetOnChainYieldsLockedProductPositionResponse.model_validate_json(
                    json.dumps(expected_response)
                )
            )

        assert response.data() == expected

    def test_get_on_chain_yields_locked_product_position_server_error(self):
        """Test that get_on_chain_yields_locked_product_position() raises an error when the server returns an error."""

        mock_error = Exception("ResponseError")
        self.client.get_on_chain_yields_locked_product_position = MagicMock(
            side_effect=mock_error
        )

        with pytest.raises(Exception, match="ResponseError"):
            self.client.get_on_chain_yields_locked_product_position()

    @patch("binance_common.utils.get_signature")
    def test_get_on_chain_yields_locked_redemption_record_success(
        self, mock_get_signature
    ):
        """Test get_on_chain_yields_locked_redemption_record() successfully with required parameters only."""

        expected_response = {
            "rows": [
                {
                    "positionId": "123123",
                    "redeemId": 40607,
                    "time": 1575018510000,
                    "asset": "BTC",
                    "lockPeriod": "30",
                    "amount": "21312.23223",
                    "originalAmount": "21312.23223",
                    "type": "NORMAL",
                    "deliverDate": "1575018510000",
                    "lossAmount": "0.00001232",
                    "isComplete": True,
                    "rewardAsset": "SOLV",
                    "rewardAmt": "5.17181528",
                    "status": "PAID",
                }
            ],
            "total": 1,
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.get_on_chain_yields_locked_redemption_record()

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert (
            "/sapi/v1/onchain-yields/locked/history/redemptionRecord"
            in request_kwargs["url"]
        )
        assert request_kwargs["method"] == "GET"

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(GetOnChainYieldsLockedRedemptionRecordResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(GetOnChainYieldsLockedRedemptionRecordResponse, "from_dict")
        ):
            expected = GetOnChainYieldsLockedRedemptionRecordResponse.from_dict(
                expected_response
            )
        else:
            expected = (
                GetOnChainYieldsLockedRedemptionRecordResponse.model_validate_json(
                    json.dumps(expected_response)
                )
            )

        assert response.data() == expected

    @patch("binance_common.utils.get_signature")
    def test_get_on_chain_yields_locked_redemption_record_success_with_optional_params(
        self, mock_get_signature
    ):
        """Test get_on_chain_yields_locked_redemption_record() successfully with optional parameters."""

        params = {
            "position_id": 1,
            "redeem_id": "1",
            "asset": "BETH",
            "start_time": 1623319461670,
            "end_time": 1641782889000,
            "current": 1,
            "size": 10,
            "recv_window": 5000,
        }

        expected_response = {
            "rows": [
                {
                    "positionId": "123123",
                    "redeemId": 40607,
                    "time": 1575018510000,
                    "asset": "BTC",
                    "lockPeriod": "30",
                    "amount": "21312.23223",
                    "originalAmount": "21312.23223",
                    "type": "NORMAL",
                    "deliverDate": "1575018510000",
                    "lossAmount": "0.00001232",
                    "isComplete": True,
                    "rewardAsset": "SOLV",
                    "rewardAmt": "5.17181528",
                    "status": "PAID",
                }
            ],
            "total": 1,
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.get_on_chain_yields_locked_redemption_record(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert (
            "/sapi/v1/onchain-yields/locked/history/redemptionRecord"
            in request_kwargs["url"]
        )
        assert request_kwargs["method"] == "GET"

        self.mock_session.request.assert_called_once()
        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(GetOnChainYieldsLockedRedemptionRecordResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(GetOnChainYieldsLockedRedemptionRecordResponse, "from_dict")
        ):
            expected = GetOnChainYieldsLockedRedemptionRecordResponse.from_dict(
                expected_response
            )
        else:
            expected = (
                GetOnChainYieldsLockedRedemptionRecordResponse.model_validate_json(
                    json.dumps(expected_response)
                )
            )

        assert response.data() == expected

    def test_get_on_chain_yields_locked_redemption_record_server_error(self):
        """Test that get_on_chain_yields_locked_redemption_record() raises an error when the server returns an error."""

        mock_error = Exception("ResponseError")
        self.client.get_on_chain_yields_locked_redemption_record = MagicMock(
            side_effect=mock_error
        )

        with pytest.raises(Exception, match="ResponseError"):
            self.client.get_on_chain_yields_locked_redemption_record()

    @patch("binance_common.utils.get_signature")
    def test_get_on_chain_yields_locked_rewards_history_success(
        self, mock_get_signature
    ):
        """Test get_on_chain_yields_locked_rewards_history() successfully with required parameters only."""

        expected_response = {
            "rows": [
                {
                    "positionId": "123123",
                    "time": 1575018510000,
                    "asset": "BNB",
                    "lockPeriod": "30",
                    "amount": "21312.23223",
                }
            ],
            "total": 1,
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.get_on_chain_yields_locked_rewards_history()

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert (
            "/sapi/v1/onchain-yields/locked/history/rewardsRecord"
            in request_kwargs["url"]
        )
        assert request_kwargs["method"] == "GET"

        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(GetOnChainYieldsLockedRewardsHistoryResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(GetOnChainYieldsLockedRewardsHistoryResponse, "from_dict")
        ):
            expected = GetOnChainYieldsLockedRewardsHistoryResponse.from_dict(
                expected_response
            )
        else:
            expected = GetOnChainYieldsLockedRewardsHistoryResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    @patch("binance_common.utils.get_signature")
    def test_get_on_chain_yields_locked_rewards_history_success_with_optional_params(
        self, mock_get_signature
    ):
        """Test get_on_chain_yields_locked_rewards_history() successfully with optional parameters."""

        params = {
            "position_id": "1",
            "asset": "BETH",
            "start_time": 1623319461670,
            "end_time": 1641782889000,
            "current": 1,
            "size": 10,
            "recv_window": 5000,
        }

        expected_response = {
            "rows": [
                {
                    "positionId": "123123",
                    "time": 1575018510000,
                    "asset": "BNB",
                    "lockPeriod": "30",
                    "amount": "21312.23223",
                }
            ],
            "total": 1,
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.get_on_chain_yields_locked_rewards_history(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs

        assert "url" in request_kwargs
        assert "signature" in parse_qs(request_kwargs["params"])
        assert (
            "/sapi/v1/onchain-yields/locked/history/rewardsRecord"
            in request_kwargs["url"]
        )
        assert request_kwargs["method"] == "GET"

        self.mock_session.request.assert_called_once()
        assert response is not None
        is_list = isinstance(expected_response, list)
        is_flat_list = (
            is_list and not isinstance(expected_response[0], list) if is_list else False
        )
        is_oneof = is_one_of_model(GetOnChainYieldsLockedRewardsHistoryResponse)

        if is_list and not is_flat_list:
            expected = expected_response
        elif (
            is_oneof
            or is_list
            or hasattr(GetOnChainYieldsLockedRewardsHistoryResponse, "from_dict")
        ):
            expected = GetOnChainYieldsLockedRewardsHistoryResponse.from_dict(
                expected_response
            )
        else:
            expected = GetOnChainYieldsLockedRewardsHistoryResponse.model_validate_json(
                json.dumps(expected_response)
            )

        assert response.data() == expected

    def test_get_on_chain_yields_locked_rewards_history_server_error(self):
        """Test that get_on_chain_yields_locked_rewards_history() raises an error when the server returns an error."""

        mock_error = Exception("ResponseError")
        self.client.get_on_chain_yields_locked_rewards_history = MagicMock(
            side_effect=mock_error
        )

        with pytest.raises(Exception, match="ResponseError"):
            self.client.get_on_chain_yields_locked_rewards_history()

    @patch("binance_common.utils.get_signature")
    def test_get_on_chain_yields_locked_subscription_preview_success(
        self, mock_get_signature
    ):
        """Test get_on_chain_yields_locked_subscription_preview() successfully with required parameters only."""

        params = {
            "project_id": "1",
            "amount": 1.0,
        }

        expected_response = {
            "rewardAsset": "SOLV",
            "totalRewardAmt": "5.17181528",
            "nextPay": "1.29295383",
            "nextPayDate": "1646697600000",
            "rewardsPayDate": "1646697600000",
            "valueDate": "1646697600000",
            "rewardsEndDate": "1651449600000",
            "deliverDate": "1651536000000",
            "nextSubscriptionDate": "1651536000000",
        }
        mock_get_signature.return_value = "mocked_signature"
        self.set_mock_response(expected_response)

        response = self.client.get_on_chain_yields_locked_subscription_preview(**params)

        actual_call_args = self.mock_session.request.call_args
        request_kwargs = actual_call_args.kwargs
        parsed_params = parse_qs(request_kwargs["params"])
        camel_case_params = {snake_to_camel(k): v for k, v in params.items()}
        normalized = normalize_query_values(parsed_params, camel_case_params)

        self.mock_session.request.assert_called_once()
        mock_get_signature.assert_called_once()

