File: test_trytond.py

package info (click to toggle)
sentry-python 2.18.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,004 kB
  • sloc: python: 55,908; makefile: 114; sh: 111; xml: 2
file content (146 lines) | stat: -rw-r--r-- 3,943 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import json
import unittest.mock

import pytest

import trytond
from trytond.exceptions import TrytonException as TrytondBaseException
from trytond.exceptions import UserError as TrytondUserError
from trytond.exceptions import UserWarning as TrytondUserWarning
from trytond.exceptions import LoginException
from trytond.wsgi import app as trytond_app

from werkzeug.test import Client

from sentry_sdk.integrations.trytond import TrytondWSGIIntegration
from tests.conftest import unpack_werkzeug_response


@pytest.fixture(scope="function")
def app(sentry_init):
    yield trytond_app


@pytest.fixture
def get_client(app):
    def inner():
        return Client(app)

    return inner


@pytest.mark.parametrize(
    "exception", [Exception("foo"), type("FooException", (Exception,), {})("bar")]
)
def test_exceptions_captured(
    sentry_init, app, capture_exceptions, get_client, exception
):
    sentry_init(integrations=[TrytondWSGIIntegration()])
    exceptions = capture_exceptions()

    unittest.mock.sentinel.exception = exception

    @app.route("/exception")
    def _(request):
        raise unittest.mock.sentinel.exception

    client = get_client()
    _ = client.get("/exception")

    (e,) = exceptions
    assert e is exception


@pytest.mark.parametrize(
    "exception",
    [
        TrytondUserError("title"),
        TrytondUserWarning("title", "details"),
        LoginException("title", "details"),
    ],
)
def test_trytonderrors_not_captured(
    sentry_init, app, capture_exceptions, get_client, exception
):
    sentry_init(integrations=[TrytondWSGIIntegration()])
    exceptions = capture_exceptions()

    unittest.mock.sentinel.exception = exception

    @app.route("/usererror")
    def _(request):
        raise unittest.mock.sentinel.exception

    client = get_client()
    _ = client.get("/usererror")

    assert not exceptions


@pytest.mark.skipif(
    trytond.__version__.split(".") < ["5", "4"], reason="At least Trytond-5.4 required"
)
def test_rpc_error_page(sentry_init, app, get_client):
    """Test that, after initializing the Trytond-SentrySDK integration
    a custom error handler can be registered to the Trytond WSGI app so as to
    inform the event identifiers to the Tryton RPC client"""

    sentry_init(integrations=[TrytondWSGIIntegration()])

    @app.route("/rpcerror", methods=["POST"])
    def _(request):
        raise Exception("foo")

    @app.error_handler
    def _(app, request, e):
        if isinstance(e, TrytondBaseException):
            return
        else:
            data = TrytondUserError("Sentry error.", str(e))
            return app.make_response(request, data)

    client = get_client()

    # This would look like a natural Tryton RPC call
    _data = dict(
        id=42,  # request sequence
        method="class.method",  # rpc call
        params=[
            [1234],  # ids
            ["bar", "baz"],  # values
            dict(  # context
                client="12345678-9abc-def0-1234-56789abc",
                groups=[1],
                language="ca",
                language_direction="ltr",
            ),
        ],
    )
    response = client.post(
        "/rpcerror", content_type="application/json", data=json.dumps(_data)
    )

    (content, status, headers) = unpack_werkzeug_response(response)
    data = json.loads(content)
    assert status == "200 OK"
    assert headers.get("Content-Type") == "application/json"
    assert data == dict(id=42, error=["UserError", ["Sentry error.", "foo", None]])


def test_span_origin(sentry_init, app, capture_events, get_client):
    sentry_init(
        integrations=[TrytondWSGIIntegration()],
        traces_sample_rate=1.0,
    )
    events = capture_events()

    @app.route("/something")
    def _(request):
        return "ok"

    client = get_client()
    client.get("/something")

    (event,) = events

    assert event["contexts"]["trace"]["origin"] == "auto.http.trytond_wsgi"