"""
Binance Derivatives Trading USDS Futures WebSocket Market Streams

OpenAPI Specification for the Binance Derivatives Trading USDS Futures WebSocket Market Streams
The version of the OpenAPI document: 1.0.0
Generated by OpenAPI Generator (https://openapi-generator.tech)

Do not edit the class manually.
"""

import pytest

from unittest.mock import AsyncMock, MagicMock

from binance_common.configuration import ConfigurationWebSocketStreams
from binance_common.errors import RequiredError
from binance_common.utils import ws_streams_placeholder
from binance_common.websocket import WebSocketStreamBase, RequestStreamHandle
from binance_sdk_derivatives_trading_usds_futures.websocket_streams.streams import (
    WebsocketMarketStreamsApi,
)


@pytest.fixture
def mock_websocket_client():
    """Fixture to provide a reusable mocked WebSocketStreamBase instance."""
    config = ConfigurationWebSocketStreams(stream_url="wss://mock-url")
    websocket_stream_client = WebSocketStreamBase(config)
    websocket_stream_client.subscribe = AsyncMock()
    websocket_stream_client.unsubscribe = AsyncMock()
    return websocket_stream_client


class TestWebSocketStreams:
    @pytest.fixture(autouse=True)
    def setup(self, mock_websocket_client):
        self.websocket_client = mock_websocket_client
        self.ws_streams = WebsocketMarketStreamsApi(
            websocket_base=self.websocket_client
        )

    @pytest.mark.asyncio
    async def test_aggregate_trade_streams_subscription(self):
        """Test that aggregate_trade_streams() subscribes to the correct WebSocket stream."""

        params = {
            "symbol": "btcusdt",
        }

        expected_response = {
            "e": "aggTrade",
            "E": 123456789,
            "s": "BTCUSDT",
            "a": 5933014,
            "p": "0.001",
            "q": "100",
            "f": 100,
            "l": 105,
            "T": 123456785,
            "m": True,
        }
        stream_endpoint = ws_streams_placeholder(
            "/<symbol>@aggTrade".replace("/", "", 1),
            params,
        )

        def mock_on(event, callback, stream):
            if event == "message" and stream == stream_endpoint:
                callback(expected_response)

        self.websocket_client.on = MagicMock(side_effect=mock_on)

        mock_callback = MagicMock()

        stream = await self.ws_streams.aggregate_trade_streams(**params)
        assert isinstance(stream, RequestStreamHandle)
        assert callable(stream.on)
        assert callable(stream.unsubscribe)
        stream.on("message", mock_callback)
        mock_callback.assert_called_once_with(expected_response)

    @pytest.mark.asyncio
    async def test_aggregate_trade_streams_success(self):
        """Test aggregate_trade_streams() successfully with required parameters only."""

        params = {
            "symbol": "btcusdt",
        }

        expected_response = {
            "e": "aggTrade",
            "E": 123456789,
            "s": "BTCUSDT",
            "a": 5933014,
            "p": "0.001",
            "q": "100",
            "f": 100,
            "l": 105,
            "T": 123456785,
            "m": True,
        }
        self.ws_streams.aggregate_trade_streams = AsyncMock(
            return_value=expected_response
        )

        response = await self.ws_streams.aggregate_trade_streams(**params)
        assert response is not None
        assert response == expected_response

    @pytest.mark.asyncio
    async def test_aggregate_trade_streams_success_with_optional_params(self):
        """Test aggregate_trade_streams() successfully with optional parameters."""

        params = {"symbol": "btcusdt", "id": "e9d6b4349871b40611412680b3445fac"}

        expected_response = {
            "e": "aggTrade",
            "E": 123456789,
            "s": "BTCUSDT",
            "a": 5933014,
            "p": "0.001",
            "q": "100",
            "f": 100,
            "l": 105,
            "T": 123456785,
            "m": True,
        }

        self.ws_streams.aggregate_trade_streams = AsyncMock(
            return_value=expected_response
        )

        response = await self.ws_streams.aggregate_trade_streams(**params)
        assert response is not None
        assert response == expected_response

    @pytest.mark.asyncio
    async def test_aggregate_trade_streams_missing_required_param_symbol(self):
        """Test that aggregate_trade_streams() raises RequiredError when 'symbol' is missing."""
        params = {
            "symbol": "btcusdt",
        }
        params["symbol"] = None

        with pytest.raises(RequiredError, match="Missing required parameter 'symbol'"):
            await self.ws_streams.aggregate_trade_streams(**params)

    @pytest.mark.asyncio
    async def test_aggregate_trade_streams_server_error(self):
        """Test that aggregate_trade_streams() raises an error when the server returns an error."""

        params = {
            "symbol": "btcusdt",
        }

        mock_error = Exception("ResponseError")
        self.ws_streams.aggregate_trade_streams = MagicMock(side_effect=mock_error)

        with pytest.raises(Exception, match="ResponseError"):
            await self.ws_streams.aggregate_trade_streams(**params)

    @pytest.mark.asyncio
    async def test_all_book_tickers_stream_subscription(self):
        """Test that all_book_tickers_stream() subscribes to the correct WebSocket stream."""

        expected_response = {
            "e": "bookTicker",
            "u": 400900217,
            "E": 1568014460893,
            "T": 1568014460891,
            "s": "BNBUSDT",
            "b": "25.35190000",
            "B": "31.21000000",
            "a": "25.36520000",
            "A": "40.66000000",
        }
        stream_endpoint = ws_streams_placeholder(
            "/!bookTicker".replace("/", "", 1),
            {},
        )

        def mock_on(event, callback, stream):
            if event == "message" and stream == stream_endpoint:
                callback(expected_response)

        self.websocket_client.on = MagicMock(side_effect=mock_on)

        mock_callback = MagicMock()

        stream = await self.ws_streams.all_book_tickers_stream()
        assert isinstance(stream, RequestStreamHandle)
        assert callable(stream.on)
        assert callable(stream.unsubscribe)
        stream.on("message", mock_callback)
        mock_callback.assert_called_once_with(expected_response)

    @pytest.mark.asyncio
    async def test_all_book_tickers_stream_success(self):
        """Test all_book_tickers_stream() successfully with required parameters only."""

        expected_response = {
            "e": "bookTicker",
            "u": 400900217,
            "E": 1568014460893,
            "T": 1568014460891,
            "s": "BNBUSDT",
            "b": "25.35190000",
            "B": "31.21000000",
            "a": "25.36520000",
            "A": "40.66000000",
        }
        self.ws_streams.all_book_tickers_stream = AsyncMock(
            return_value=expected_response
        )

        response = await self.ws_streams.all_book_tickers_stream()
        assert response is not None
        assert response == expected_response

    @pytest.mark.asyncio
    async def test_all_book_tickers_stream_success_with_optional_params(self):
        """Test all_book_tickers_stream() successfully with optional parameters."""

        params = {"id": "e9d6b4349871b40611412680b3445fac"}

        expected_response = {
            "e": "bookTicker",
            "u": 400900217,
            "E": 1568014460893,
            "T": 1568014460891,
            "s": "BNBUSDT",
            "b": "25.35190000",
            "B": "31.21000000",
            "a": "25.36520000",
            "A": "40.66000000",
        }

        self.ws_streams.all_book_tickers_stream = AsyncMock(
            return_value=expected_response
        )

        response = await self.ws_streams.all_book_tickers_stream(**params)
        assert response is not None
        assert response == expected_response

    @pytest.mark.asyncio
    async def test_all_book_tickers_stream_server_error(self):
        """Test that all_book_tickers_stream() raises an error when the server returns an error."""

        mock_error = Exception("ResponseError")
        self.ws_streams.all_book_tickers_stream = MagicMock(side_effect=mock_error)

        with pytest.raises(Exception, match="ResponseError"):
            await self.ws_streams.all_book_tickers_stream()

    @pytest.mark.asyncio
    async def test_all_market_liquidation_order_streams_subscription(self):
        """Test that all_market_liquidation_order_streams() subscribes to the correct WebSocket stream."""

        expected_response = {
            "e": "forceOrder",
            "E": 1568014460893,
            "o": {
                "s": "BTCUSDT",
                "S": "SELL",
                "o": "LIMIT",
                "f": "IOC",
                "q": "0.014",
                "p": "9910",
                "ap": "9910",
                "X": "FILLED",
                "l": "0.014",
                "z": "0.014",
                "T": 1568014460893,
            },
        }
        stream_endpoint = ws_streams_placeholder(
            "/!forceOrder@arr".replace("/", "", 1),
            {},
        )

        def mock_on(event, callback, stream):
            if event == "message" and stream == stream_endpoint:
                callback(expected_response)

        self.websocket_client.on = MagicMock(side_effect=mock_on)

        mock_callback = MagicMock()

        stream = await self.ws_streams.all_market_liquidation_order_streams()
        assert isinstance(stream, RequestStreamHandle)
        assert callable(stream.on)
        assert callable(stream.unsubscribe)
        stream.on("message", mock_callback)
        mock_callback.assert_called_once_with(expected_response)

    @pytest.mark.asyncio
    async def test_all_market_liquidation_order_streams_success(self):
        """Test all_market_liquidation_order_streams() successfully with required parameters only."""

        expected_response = {
            "e": "forceOrder",
            "E": 1568014460893,
            "o": {
                "s": "BTCUSDT",
                "S": "SELL",
                "o": "LIMIT",
                "f": "IOC",
                "q": "0.014",
                "p": "9910",
                "ap": "9910",
                "X": "FILLED",
                "l": "0.014",
                "z": "0.014",
                "T": 1568014460893,
            },
        }
        self.ws_streams.all_market_liquidation_order_streams = AsyncMock(
            return_value=expected_response
        )

        response = await self.ws_streams.all_market_liquidation_order_streams()
        assert response is not None
        assert response == expected_response

    @pytest.mark.asyncio
    async def test_all_market_liquidation_order_streams_success_with_optional_params(
        self,
    ):
        """Test all_market_liquidation_order_streams() successfully with optional parameters."""

        params = {"id": "e9d6b4349871b40611412680b3445fac"}

        expected_response = {
            "e": "forceOrder",
            "E": 1568014460893,
            "o": {
                "s": "BTCUSDT",
                "S": "SELL",
                "o": "LIMIT",
                "f": "IOC",
                "q": "0.014",
                "p": "9910",
                "ap": "9910",
                "X": "FILLED",
                "l": "0.014",
                "z": "0.014",
                "T": 1568014460893,
            },
        }

        self.ws_streams.all_market_liquidation_order_streams = AsyncMock(
            return_value=expected_response
        )

        response = await self.ws_streams.all_market_liquidation_order_streams(**params)
        assert response is not None
        assert response == expected_response

    @pytest.mark.asyncio
    async def test_all_market_liquidation_order_streams_server_error(self):
        """Test that all_market_liquidation_order_streams() raises an error when the server returns an error."""

        mock_error = Exception("ResponseError")
        self.ws_streams.all_market_liquidation_order_streams = MagicMock(
            side_effect=mock_error
        )

        with pytest.raises(Exception, match="ResponseError"):
            await self.ws_streams.all_market_liquidation_order_streams()

    @pytest.mark.asyncio
    async def test_all_market_mini_tickers_stream_subscription(self):
        """Test that all_market_mini_tickers_stream() subscribes to the correct WebSocket stream."""

        expected_response = [
            {
                "e": "24hrMiniTicker",
                "E": 123456789,
                "s": "BTCUSDT",
                "c": "0.0025",
                "o": "0.0010",
                "h": "0.0025",
                "l": "0.0010",
                "v": "10000",
                "q": "18",
            }
        ]
        stream_endpoint = ws_streams_placeholder(
            "/!miniTicker@arr".replace("/", "", 1),
            {},
        )

        def mock_on(event, callback, stream):
            if event == "message" and stream == stream_endpoint:
                callback(expected_response)

        self.websocket_client.on = MagicMock(side_effect=mock_on)

        mock_callback = MagicMock()

        stream = await self.ws_streams.all_market_mini_tickers_stream()
        assert isinstance(stream, RequestStreamHandle)
        assert callable(stream.on)
        assert callable(stream.unsubscribe)
        stream.on("message", mock_callback)
        mock_callback.assert_called_once_with(expected_response)

    @pytest.mark.asyncio
    async def test_all_market_mini_tickers_stream_success(self):
        """Test all_market_mini_tickers_stream() successfully with required parameters only."""

        expected_response = [
            {
                "e": "24hrMiniTicker",
                "E": 123456789,
                "s": "BTCUSDT",
                "c": "0.0025",
                "o": "0.0010",
                "h": "0.0025",
                "l": "0.0010",
                "v": "10000",
                "q": "18",
            }
        ]
        self.ws_streams.all_market_mini_tickers_stream = AsyncMock(
            return_value=expected_response
        )

        response = await self.ws_streams.all_market_mini_tickers_stream()
        assert response is not None
        assert response == expected_response

    @pytest.mark.asyncio
    async def test_all_market_mini_tickers_stream_success_with_optional_params(self):
        """Test all_market_mini_tickers_stream() successfully with optional parameters."""

        params = {"id": "e9d6b4349871b40611412680b3445fac"}

        expected_response = [
            {
                "e": "24hrMiniTicker",
                "E": 123456789,
                "s": "BTCUSDT",
                "c": "0.0025",
                "o": "0.0010",
                "h": "0.0025",
                "l": "0.0010",
                "v": "10000",
                "q": "18",
            }
        ]

        self.ws_streams.all_market_mini_tickers_stream = AsyncMock(
            return_value=expected_response
        )

        response = await self.ws_streams.all_market_mini_tickers_stream(**params)
        assert response is not None
        assert response == expected_response

    @pytest.mark.asyncio
    async def test_all_market_mini_tickers_stream_server_error(self):
        """Test that all_market_mini_tickers_stream() raises an error when the server returns an error."""

        mock_error = Exception("ResponseError")
        self.ws_streams.all_market_mini_tickers_stream = MagicMock(
            side_effect=mock_error
        )

        with pytest.raises(Exception, match="ResponseError"):
            await self.ws_streams.all_market_mini_tickers_stream()

    @pytest.mark.asyncio
    async def test_all_market_tickers_streams_subscription(self):
        """Test that all_market_tickers_streams() subscribes to the correct WebSocket stream."""

        expected_response = [
            {
                "e": "24hrTicker",
                "E": 123456789,
                "s": "BTCUSDT",
                "p": "0.0015",
                "P": "250.00",
                "w": "0.0018",
                "c": "0.0025",
                "Q": "10",
                "o": "0.0010",
                "h": "0.0025",
                "l": "0.0010",
                "v": "10000",
                "q": "18",
                "O": 0,
                "C": 86400000,
                "F": 0,
                "L": 18150,
                "n": 18151,
            }
        ]
        stream_endpoint = ws_streams_placeholder(
            "/!ticker@arr".replace("/", "", 1),
            {},
        )

        def mock_on(event, callback, stream):
            if event == "message" and stream == stream_endpoint:
                callback(expected_response)

        self.websocket_client.on = MagicMock(side_effect=mock_on)

        mock_callback = MagicMock()

        stream = await self.ws_streams.all_market_tickers_streams()
        assert isinstance(stream, RequestStreamHandle)
        assert callable(stream.on)
        assert callable(stream.unsubscribe)
        stream.on("message", mock_callback)
        mock_callback.assert_called_once_with(expected_response)

    @pytest.mark.asyncio
    async def test_all_market_tickers_streams_success(self):
        """Test all_market_tickers_streams() successfully with required parameters only."""

        expected_response = [
            {
                "e": "24hrTicker",
                "E": 123456789,
                "s": "BTCUSDT",
                "p": "0.0015",
                "P": "250.00",
                "w": "0.0018",
                "c": "0.0025",
                "Q": "10",
                "o": "0.0010",
                "h": "0.0025",
                "l": "0.0010",
                "v": "10000",
                "q": "18",
                "O": 0,
                "C": 86400000,
                "F": 0,
                "L": 18150,
                "n": 18151,
            }
        ]
        self.ws_streams.all_market_tickers_streams = AsyncMock(
            return_value=expected_response
        )

        response = await self.ws_streams.all_market_tickers_streams()
        assert response is not None
        assert response == expected_response

    @pytest.mark.asyncio
    async def test_all_market_tickers_streams_success_with_optional_params(self):
        """Test all_market_tickers_streams() successfully with optional parameters."""

        params = {"id": "e9d6b4349871b40611412680b3445fac"}

        expected_response = [
            {
                "e": "24hrTicker",
                "E": 123456789,
                "s": "BTCUSDT",
                "p": "0.0015",
                "P": "250.00",
                "w": "0.0018",
                "c": "0.0025",
                "Q": "10",
                "o": "0.0010",
                "h": "0.0025",
                "l": "0.0010",
                "v": "10000",
                "q": "18",
                "O": 0,
                "C": 86400000,
                "F": 0,
                "L": 18150,
                "n": 18151,
            }
        ]

        self.ws_streams.all_market_tickers_streams = AsyncMock(
            return_value=expected_response
        )

        response = await self.ws_streams.all_market_tickers_streams(**params)
        assert response is not None
        assert response == expected_response

    @pytest.mark.asyncio
    async def test_all_market_tickers_streams_server_error(self):
        """Test that all_market_tickers_streams() raises an error when the server returns an error."""

        mock_error = Exception("ResponseError")
        self.ws_streams.all_market_tickers_streams = MagicMock(side_effect=mock_error)

        with pytest.raises(Exception, match="ResponseError"):
            await self.ws_streams.all_market_tickers_streams()

    @pytest.mark.asyncio
    async def test_composite_index_symbol_information_streams_subscription(self):
        """Test that composite_index_symbol_information_streams() subscribes to the correct WebSocket stream."""

        params = {
            "symbol": "btcusdt",
        }

        expected_response = {
            "e": "compositeIndex",
            "E": 1602310596000,
            "s": "DEFIUSDT",
            "p": "554.41604065",
            "C": "baseAsset",
            "c": [
                {
                    "b": "BAL",
                    "q": "USDT",
                    "w": "1.04884844",
                    "W": "0.01457800",
                    "i": "24.33521021",
                },
                {
                    "b": "BAND",
                    "q": "USDT",
                    "w": "3.53782729",
                    "W": "0.03935200",
                    "i": "7.26420084",
                },
            ],
        }
        stream_endpoint = ws_streams_placeholder(
            "/<symbol>@compositeIndex".replace("/", "", 1),
            params,
        )

        def mock_on(event, callback, stream):
            if event == "message" and stream == stream_endpoint:
                callback(expected_response)

        self.websocket_client.on = MagicMock(side_effect=mock_on)

        mock_callback = MagicMock()

        stream = await self.ws_streams.composite_index_symbol_information_streams(
            **params
        )
        assert isinstance(stream, RequestStreamHandle)
        assert callable(stream.on)
        assert callable(stream.unsubscribe)
        stream.on("message", mock_callback)
        mock_callback.assert_called_once_with(expected_response)

    @pytest.mark.asyncio
    async def test_composite_index_symbol_information_streams_success(self):
        """Test composite_index_symbol_information_streams() successfully with required parameters only."""

        params = {
            "symbol": "btcusdt",
        }

        expected_response = {
            "e": "compositeIndex",
            "E": 1602310596000,
            "s": "DEFIUSDT",
            "p": "554.41604065",
            "C": "baseAsset",
            "c": [
                {
                    "b": "BAL",
                    "q": "USDT",
                    "w": "1.04884844",
                    "W": "0.01457800",
                    "i": "24.33521021",
                },
                {
                    "b": "BAND",
                    "q": "USDT",
                    "w": "3.53782729",
                    "W": "0.03935200",
                    "i": "7.26420084",
                },
            ],
        }
        self.ws_streams.composite_index_symbol_information_streams = AsyncMock(
            return_value=expected_response
        )

        response = await self.ws_streams.composite_index_symbol_information_streams(
            **params
        )
        assert response is not None
        assert response == expected_response

    @pytest.mark.asyncio
    async def test_composite_index_symbol_information_streams_success_with_optional_params(
        self,
    ):
        """Test composite_index_symbol_information_streams() successfully with optional parameters."""

        params = {"symbol": "btcusdt", "id": "e9d6b4349871b40611412680b3445fac"}

        expected_response = {
            "e": "compositeIndex",
            "E": 1602310596000,
            "s": "DEFIUSDT",
            "p": "554.41604065",
            "C": "baseAsset",
            "c": [
                {
                    "b": "BAL",
                    "q": "USDT",
                    "w": "1.04884844",
                    "W": "0.01457800",
                    "i": "24.33521021",
                },
                {
                    "b": "BAND",
                    "q": "USDT",
                    "w": "3.53782729",
                    "W": "0.03935200",
                    "i": "7.26420084",
                },
            ],
        }

        self.ws_streams.composite_index_symbol_information_streams = AsyncMock(
            return_value=expected_response
        )

        response = await self.ws_streams.composite_index_symbol_information_streams(
            **params
        )
        assert response is not None
        assert response == expected_response

    @pytest.mark.asyncio
    async def test_composite_index_symbol_information_streams_missing_required_param_symbol(
        self,
    ):
        """Test that composite_index_symbol_information_streams() raises RequiredError when 'symbol' is missing."""
        params = {
            "symbol": "btcusdt",
        }
        params["symbol"] = None

        with pytest.raises(RequiredError, match="Missing required parameter 'symbol'"):
            await self.ws_streams.composite_index_symbol_information_streams(**params)

    @pytest.mark.asyncio
    async def test_composite_index_symbol_information_streams_server_error(self):
        """Test that composite_index_symbol_information_streams() raises an error when the server returns an error."""

        params = {
            "symbol": "btcusdt",
        }

        mock_error = Exception("ResponseError")
        self.ws_streams.composite_index_symbol_information_streams = MagicMock(
            side_effect=mock_error
        )

        with pytest.raises(Exception, match="ResponseError"):
            await self.ws_streams.composite_index_symbol_information_streams(**params)

    @pytest.mark.asyncio
    async def test_continuous_contract_kline_candlestick_streams_subscription(self):
        """Test that continuous_contract_kline_candlestick_streams() subscribes to the correct WebSocket stream."""

        params = {
            "pair": "btcusdt",
            "contract_type": "next_quarter",
            "interval": "1m",
        }

        expected_response = {
            "e": "continuous_kline",
            "E": 1607443058651,
            "ps": "BTCUSDT",
            "ct": "PERPETUAL",
            "k": {
                "t": 1607443020000,
                "T": 1607443079999,
                "i": "1m",
                "f": 116467658886,
                "L": 116468012423,
                "o": "18787.00",
                "c": "18804.04",
                "h": "18804.04",
                "l": "18786.54",
                "v": "197.664",
                "n": 543,
                "x": False,
                "q": "3715253.19494",
                "V": "184.769",
                "Q": "3472925.84746",
                "B": "0",
            },
        }
        stream_endpoint = ws_streams_placeholder(
            "/<pair>_<contractType>@continuousKline_<interval>".replace("/", "", 1),
            params,
        )

        def mock_on(event, callback, stream):
            if event == "message" and stream == stream_endpoint:
                callback(expected_response)

        self.websocket_client.on = MagicMock(side_effect=mock_on)

        mock_callback = MagicMock()

        stream = await self.ws_streams.continuous_contract_kline_candlestick_streams(
            **params
        )
        assert isinstance(stream, RequestStreamHandle)
        assert callable(stream.on)
        assert callable(stream.unsubscribe)
        stream.on("message", mock_callback)
        mock_callback.assert_called_once_with(expected_response)

    @pytest.mark.asyncio
    async def test_continuous_contract_kline_candlestick_streams_success(self):
        """Test continuous_contract_kline_candlestick_streams() successfully with required parameters only."""

        params = {
            "pair": "btcusdt",
            "contract_type": "next_quarter",
            "interval": "1m",
        }

        expected_response = {
            "e": "continuous_kline",
            "E": 1607443058651,
            "ps": "BTCUSDT",
            "ct": "PERPETUAL",
            "k": {
                "t": 1607443020000,
                "T": 1607443079999,
                "i": "1m",
                "f": 116467658886,
                "L": 116468012423,
                "o": "18787.00",
                "c": "18804.04",
                "h": "18804.04",
                "l": "18786.54",
                "v": "197.664",
                "n": 543,
                "x": False,
                "q": "3715253.19494",
                "V": "184.769",
                "Q": "3472925.84746",
                "B": "0",
            },
        }
        self.ws_streams.continuous_contract_kline_candlestick_streams = AsyncMock(
            return_value=expected_response
        )

        response = await self.ws_streams.continuous_contract_kline_candlestick_streams(
            **params
        )
        assert response is not None
        assert response == expected_response

    @pytest.mark.asyncio
    async def test_continuous_contract_kline_candlestick_streams_success_with_optional_params(
        self,
    ):
        """Test continuous_contract_kline_candlestick_streams() successfully with optional parameters."""

        params = {
            "pair": "btcusdt",
            "contract_type": "next_quarter",
            "interval": "1m",
            "id": "e9d6b4349871b40611412680b3445fac",
        }

        expected_response = {
            "e": "continuous_kline",
            "E": 1607443058651,
            "ps": "BTCUSDT",
            "ct": "PERPETUAL",
            "k": {
                "t": 1607443020000,
                "T": 1607443079999,
                "i": "1m",
                "f": 116467658886,
                "L": 116468012423,
                "o": "18787.00",
                "c": "18804.04",
                "h": "18804.04",
                "l": "18786.54",
                "v": "197.664",
                "n": 543,
                "x": False,
                "q": "3715253.19494",
                "V": "184.769",
                "Q": "3472925.84746",
                "B": "0",
            },
        }

        self.ws_streams.continuous_contract_kline_candlestick_streams = AsyncMock(
            return_value=expected_response
        )

        response = await self.ws_streams.continuous_contract_kline_candlestick_streams(
            **params
        )
        assert response is not None
        assert response == expected_response

    @pytest.mark.asyncio
    async def test_continuous_contract_kline_candlestick_streams_missing_required_param_pair(
        self,
    ):
        """Test that continuous_contract_kline_candlestick_streams() raises RequiredError when 'pair' is missing."""
        params = {
            "pair": "btcusdt",
            "contract_type": "next_quarter",
            "interval": "1m",
        }
        params["pair"] = None

        with pytest.raises(RequiredError, match="Missing required parameter 'pair'"):
            await self.ws_streams.continuous_contract_kline_candlestick_streams(
                **params
            )

    @pytest.mark.asyncio
    async def test_continuous_contract_kline_candlestick_streams_missing_required_param_contract_type(
        self,
    ):
        """Test that continuous_contract_kline_candlestick_streams() raises RequiredError when 'contract_type' is missing."""
        params = {
            "pair": "btcusdt",
            "contract_type": "next_quarter",
            "interval": "1m",
        }
        params["contract_type"] = None

        with pytest.raises(
            RequiredError, match="Missing required parameter 'contract_type'"
        ):
            await self.ws_streams.continuous_contract_kline_candlestick_streams(
                **params
            )

    @pytest.mark.asyncio
    async def test_continuous_contract_kline_candlestick_streams_missing_required_param_interval(
        self,
    ):
        """Test that continuous_contract_kline_candlestick_streams() raises RequiredError when 'interval' is missing."""
        params = {
            "pair": "btcusdt",
            "contract_type": "next_quarter",
            "interval": "1m",
        }
        params["interval"] = None

        with pytest.raises(
            RequiredError, match="Missing required parameter 'interval'"
        ):
            await self.ws_streams.continuous_contract_kline_candlestick_streams(
                **params
            )

    @pytest.mark.asyncio
    async def test_continuous_contract_kline_candlestick_streams_server_error(self):
        """Test that continuous_contract_kline_candlestick_streams() raises an error when the server returns an error."""

        params = {
            "pair": "btcusdt",
            "contract_type": "next_quarter",
            "interval": "1m",
        }

        mock_error = Exception("ResponseError")
