def test_duplicated_operation_ids(test_client):
    with test_client.websocket_connect("/", [GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        ws.send_json(ConnectionInitMessage().as_dict())

        response = ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query='subscription { echo(message: "Hi", delay: 5) }'
                ),
            ).as_dict()
        )

        ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query='subscription { echo(message: "Hi", delay: 5) }'
                ),
            ).as_dict()
        )

        data = ws.receive()
        assert data["type"] == "websocket.close"
        assert data["code"] == 4409
Example #2
0
async def test_duplicated_operation_ids(aiohttp_client):
    app = create_app()
    aiohttp_app_client = await aiohttp_client(app)

    async with aiohttp_app_client.ws_connect(
            "/graphql", protocols=[GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        await ws.send_json(ConnectionInitMessage().as_dict())

        response = await ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        await ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query='subscription { echo(message: "Hi", delay: 5) }'),
            ).as_dict())

        await ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query='subscription { echo(message: "Hi", delay: 5) }'),
            ).as_dict())

        data = await ws.receive(timeout=2)
        assert ws.closed
        assert ws.close_code == 4409
        assert data.extra == "Subscriber for sub1 already exists"
def test_subscription_cancellation(test_client):
    with test_client.websocket_connect("/", [GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        ws.send_json(ConnectionInitMessage().as_dict())

        response = ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query='subscription { echo(message: "Hi", delay: 99) }'
                ),
            ).as_dict()
        )

        ws.send_json(
            SubscribeMessage(
                id="sub2",
                payload=SubscribeMessagePayload(
                    query="subscription { debug { numActiveResultHandlers } }",
                ),
            ).as_dict()
        )

        response = ws.receive_json()
        assert (
            response
            == NextMessage(
                id="sub2", payload={"data": {"debug": {"numActiveResultHandlers": 2}}}
            ).as_dict()
        )

        response = ws.receive_json()
        assert response == CompleteMessage(id="sub2").as_dict()

        ws.send_json(CompleteMessage(id="sub1").as_dict())

        ws.send_json(
            SubscribeMessage(
                id="sub3",
                payload=SubscribeMessagePayload(
                    query="subscription { debug { numActiveResultHandlers } }",
                ),
            ).as_dict()
        )

        response = ws.receive_json()
        assert (
            response
            == NextMessage(
                id="sub3", payload={"data": {"debug": {"numActiveResultHandlers": 1}}}
            ).as_dict()
        )

        response = ws.receive_json()
        assert response == CompleteMessage(id="sub3").as_dict()

        ws.close()
Example #4
0
async def test_simple_subscription(aiohttp_client):
    app = create_app()
    aiohttp_app_client = await aiohttp_client(app)

    async with aiohttp_app_client.ws_connect(
            "/graphql", protocols=[GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        await ws.send_json(ConnectionInitMessage().as_dict())

        response = await ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        await ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query='subscription { echo(message: "Hi") }'),
            ).as_dict())

        response = await ws.receive_json()
        assert (response == NextMessage(id="sub1",
                                        payload={
                                            "data": {
                                                "echo": "Hi"
                                            }
                                        }).as_dict())

        await ws.send_json(CompleteMessage(id="sub1").as_dict())

        await ws.close()
        assert ws.closed
Example #5
0
async def test_subscription_field_errors(aiohttp_client):
    app = create_app()
    aiohttp_app_client = await aiohttp_client(app)

    async with aiohttp_app_client.ws_connect(
            "/graphql", protocols=[GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        await ws.send_json(ConnectionInitMessage().as_dict())

        response = await ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        await ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query="subscription { notASubscriptionField }", ),
            ).as_dict())

        response = await ws.receive_json()
        assert response["type"] == ErrorMessage.type
        assert response["id"] == "sub1"
        assert len(response["payload"]) == 1
        assert response["payload"][0]["path"] is None
        assert response["payload"][0]["locations"] == [{
            "line": 1,
            "column": 16
        }]
        assert (
            response["payload"][0]["message"] ==
            "The subscription field 'notASubscriptionField' is not defined.")

        await ws.close()
        assert ws.closed
Example #6
0
async def test_subscription_exceptions(aiohttp_client):
    app = create_app()
    aiohttp_app_client = await aiohttp_client(app)

    async with aiohttp_app_client.ws_connect(
            "/graphql", protocols=[GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        await ws.send_json(ConnectionInitMessage().as_dict())

        response = await ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        await ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query='subscription { exception(message: "TEST EXC") }', ),
            ).as_dict())

        response = await ws.receive_json()
        assert response["type"] == ErrorMessage.type
        assert response["id"] == "sub1"
        assert len(response["payload"]) == 1
        assert response["payload"][0]["path"] is None
        assert response["payload"][0]["locations"] is None
        assert response["payload"][0]["message"] == "TEST EXC"

        await ws.close()
        assert ws.closed
def test_server_sent_ping(test_client):
    with test_client.websocket_connect("/", [GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        ws.send_json(ConnectionInitMessage().as_dict())

        response = ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(query="subscription { requestPing }"),
            ).as_dict()
        )

        response = ws.receive_json()
        assert response == PingMessage().as_dict()

        ws.send_json(PongMessage().as_dict())

        response = ws.receive_json()
        assert (
            response
            == NextMessage(id="sub1", payload={"data": {"requestPing": True}}).as_dict()
        )

        response = ws.receive_json()
        assert response == CompleteMessage(id="sub1").as_dict()

        ws.close()
async def test_connection_init_timeout_cancellation(test_client):
    app = create_app(connection_init_wait_timeout=timedelta(milliseconds=500))
    test_client = TestClient(app)

    with test_client.websocket_connect("/", [GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        ws.send_json(ConnectionInitMessage().as_dict())

        response = ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        await asyncio.sleep(1)

        ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query="subscription { debug { isConnectionInitTimeoutTaskDone } }"
                ),
            ).as_dict()
        )

        response = ws.receive_json()
        assert (
            response
            == NextMessage(
                id="sub1",
                payload={"data": {"debug": {"isConnectionInitTimeoutTaskDone": True}}},
            ).as_dict()
        )

        ws.close()
def test_subscription_exceptions(test_client):
    with test_client.websocket_connect("/", [GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        ws.send_json(ConnectionInitMessage().as_dict())

        response = ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query='subscription { exception(message: "TEST EXC") }',
                ),
            ).as_dict()
        )

        response = ws.receive_json()
        assert response["type"] == ErrorMessage.type
        assert response["id"] == "sub1"
        assert len(response["payload"]) == 1
        assert response["payload"][0]["path"] is None
        assert response["payload"][0]["locations"] is None
        assert response["payload"][0]["message"] == "TEST EXC"

        ws.close()
def test_subscription_field_errors(test_client):
    with test_client.websocket_connect("/", [GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        ws.send_json(ConnectionInitMessage().as_dict())

        response = ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query="subscription { notASubscriptionField }",
                ),
            ).as_dict()
        )

        response = ws.receive_json()
        assert response["type"] == ErrorMessage.type
        assert response["id"] == "sub1"
        assert len(response["payload"]) == 1
        assert response["payload"][0]["path"] is None
        assert response["payload"][0]["locations"] == [{"line": 1, "column": 16}]
        assert (
            response["payload"][0]["message"]
            == "The subscription field 'notASubscriptionField' is not defined."
        )

        ws.close()
def test_subscription_syntax_error(test_client):
    with test_client.websocket_connect("/", [GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        ws.send_json(ConnectionInitMessage().as_dict())

        response = ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(query="subscription { INVALID_SYNTAX "),
            ).as_dict()
        )

        response = ws.receive_json()
        assert response["type"] == ErrorMessage.type
        assert response["id"] == "sub1"
        assert len(response["payload"]) == 1
        assert response["payload"][0]["path"] is None
        assert response["payload"][0]["locations"] == [{"line": 1, "column": 31}]
        assert (
            response["payload"][0]["message"]
            == "Syntax Error: Expected Name, found <EOF>."
        )

        ws.close()
def test_simple_subscription(test_client):
    with test_client.websocket_connect("/", [GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        ws.send_json(ConnectionInitMessage().as_dict())

        response = ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query='subscription { echo(message: "Hi") }'
                ),
            ).as_dict()
        )

        response = ws.receive_json()
        assert (
            response
            == NextMessage(id="sub1", payload={"data": {"echo": "Hi"}}).as_dict()
        )

        ws.send_json(CompleteMessage(id="sub1").as_dict())

        ws.close()
Example #13
0
async def test_subscription_syntax_error(aiohttp_client):
    app = create_app()
    aiohttp_app_client = await aiohttp_client(app)

    async with aiohttp_app_client.ws_connect(
            "/graphql", protocols=[GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        await ws.send_json(ConnectionInitMessage().as_dict())

        response = await ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        await ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query="subscription { INVALID_SYNTAX "),
            ).as_dict())

        response = await ws.receive_json()
        assert response["type"] == ErrorMessage.type
        assert response["id"] == "sub1"
        assert len(response["payload"]) == 1
        assert response["payload"][0]["path"] is None
        assert response["payload"][0]["locations"] == [{
            "line": 1,
            "column": 31
        }]
        assert (response["payload"][0]["message"] ==
                "Syntax Error: Expected Name, found <EOF>.")

        await ws.close()
        assert ws.closed
Example #14
0
    async def handle_message(self, message: dict):
        try:
            message_type = message.pop("type")

            if message_type == ConnectionInitMessage.type:
                await self.handle_connection_init(
                    ConnectionInitMessage(**message))

            elif message_type == PingMessage.type:
                await self.handle_ping(PingMessage(**message))

            elif message_type == PongMessage.type:
                await self.handle_pong(PongMessage(**message))

            elif message_type == SubscribeMessage.type:
                payload = SubscribeMessagePayload(**message.pop("payload"))
                await self.handle_subscribe(
                    SubscribeMessage(payload=payload, **message))

            elif message_type == CompleteMessage.type:
                await self.handle_complete(CompleteMessage(**message))

            else:
                error_message = f"Unknown message type: {message_type}"
                await self.handle_invalid_message(error_message)

        except (KeyError, TypeError):
            error_message = "Failed to parse message"
            await self.handle_invalid_message(error_message)
Example #15
0
def test_unauthorized_subscriptions(test_client):
    with test_client.websocket_connect("/graphql",
                                       [GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query='subscription { echo(message: "Hi") }'),
            ).as_dict())

        data = ws.receive()
        assert data["type"] == "websocket.close"
        assert data["code"] == 4401
Example #16
0
async def test_unauthorized_subscriptions(aiohttp_client):
    app = create_app()
    aiohttp_app_client = await aiohttp_client(app)

    async with aiohttp_app_client.ws_connect(
            "/graphql", protocols=[GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        await ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query='subscription { echo(message: "Hi") }'),
            ).as_dict())

        data = await ws.receive(timeout=2)
        assert ws.closed
        assert ws.close_code == 4401
        assert data.extra == "Unauthorized"
Example #17
0
async def test_connection_init_timeout_cancellation(aiohttp_client):
    app = create_app(connection_init_wait_timeout=timedelta(milliseconds=50))
    aiohttp_app_client = await aiohttp_client(app)

    async with aiohttp_app_client.ws_connect(
            "/graphql", protocols=[GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        await ws.send_json(ConnectionInitMessage().as_dict())

        response = await ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        await asyncio.sleep(0.1)

        await ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query=
                    "subscription { debug { isConnectionInitTimeoutTaskDone } }"
                ),
            ).as_dict())

        response = await ws.receive_json()
        assert (response == NextMessage(
            id="sub1",
            payload={
                "data": {
                    "debug": {
                        "isConnectionInitTimeoutTaskDone": True
                    }
                }
            },
        ).as_dict())

        await ws.close()
        assert ws.closed
Example #18
0
async def test_server_sent_ping(aiohttp_client):
    app = create_app()
    aiohttp_app_client = await aiohttp_client(app)

    async with aiohttp_app_client.ws_connect(
            "/graphql", protocols=[GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        await ws.send_json(ConnectionInitMessage().as_dict())

        response = await ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        await ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query="subscription { requestPing }"),
            ).as_dict())

        response = await ws.receive_json()
        assert response == PingMessage().as_dict()

        await ws.send_json(PongMessage().as_dict())

        response = await ws.receive_json()
        assert (response == NextMessage(id="sub1",
                                        payload={
                                            "data": {
                                                "requestPing": True
                                            }
                                        }).as_dict())

        response = await ws.receive_json()
        assert response == CompleteMessage(id="sub1").as_dict()

        await ws.close()
        assert ws.closed
Example #19
0
async def test_subscription_cancellation(aiohttp_client):
    app = create_app()
    aiohttp_app_client = await aiohttp_client(app)

    async with aiohttp_app_client.ws_connect(
            "/graphql", protocols=[GRAPHQL_TRANSPORT_WS_PROTOCOL]) as ws:
        await ws.send_json(ConnectionInitMessage().as_dict())

        response = await ws.receive_json()
        assert response == ConnectionAckMessage().as_dict()

        await ws.send_json(
            SubscribeMessage(
                id="sub1",
                payload=SubscribeMessagePayload(
                    query='subscription { echo(message: "Hi", delay: 99) }'),
            ).as_dict())

        await ws.send_json(
            SubscribeMessage(
                id="sub2",
                payload=SubscribeMessagePayload(
                    query="subscription { debug { numActiveResultHandlers } }",
                ),
            ).as_dict())

        response = await ws.receive_json()
        assert (response == NextMessage(id="sub2",
                                        payload={
                                            "data": {
                                                "debug": {
                                                    "numActiveResultHandlers":
                                                    2
                                                }
                                            }
                                        }).as_dict())

        response = await ws.receive_json()
        assert response == CompleteMessage(id="sub2").as_dict()

        await ws.send_json(CompleteMessage(id="sub1").as_dict())

        await ws.send_json(
            SubscribeMessage(
                id="sub3",
                payload=SubscribeMessagePayload(
                    query="subscription { debug { numActiveResultHandlers } }",
                ),
            ).as_dict())

        response = await ws.receive_json()
        assert (response == NextMessage(id="sub3",
                                        payload={
                                            "data": {
                                                "debug": {
                                                    "numActiveResultHandlers":
                                                    1
                                                }
                                            }
                                        }).as_dict())

        response = await ws.receive_json()
        assert response == CompleteMessage(id="sub3").as_dict()

        await ws.close()
        assert ws.closed