File: test_recipes.py

package info (click to toggle)
python-falcon 4.0.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,172 kB
  • sloc: python: 33,608; javascript: 92; sh: 50; makefile: 50
file content (143 lines) | stat: -rw-r--r-- 4,282 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
import pytest

import falcon
import falcon.testing


class TestMultipartMixed:
    """Test parsing example from the now-obsolete RFC 1867:

    --AaB03x
    Content-Disposition: form-data; name="field1"

    Joe Blow
    --AaB03x
    Content-Disposition: form-data; name="docs"
    Content-Type: multipart/mixed; boundary=BbC04y

    --BbC04y
    Content-Disposition: attachment; filename="file1.txt"

    This is file1.

    --BbC04y
    Content-Disposition: attachment; filename="file2.txt"

    Hello, World!

    --BbC04y--

    --AaB03x--
    """

    @classmethod
    def prepare_form(cls):
        lines = [line.strip() for line in cls.__doc__.splitlines()[2:]]

        # NOTE(vytas): On CPython 3.13-rc1, the last newline was missing.
        if lines[-1]:
            lines.append('')

        return '\r\n'.join(lines).encode()

    def test_parse(self, util):
        recipe = util.load_module('examples/recipes/multipart_mixed_main.py')

        result = falcon.testing.simulate_post(
            recipe.app,
            '/forms',
            body=self.prepare_form(),
            content_type='multipart/form-data; boundary=AaB03x',
        )
        assert result.status_code == 200
        assert result.json == {
            'file1.txt': 'This is file1.\r\n',
            'file2.txt': 'Hello, World!\r\n',
        }


class TestOutputCSV:
    @pytest.mark.parametrize(
        'recipe,expected_head',
        [
            ('output_csv_text', '"fruit","quantity"\r\n"apples",13\r\n'),
            ('output_csv_stream', '"n","Fibonacci Fn"\r\n0,0\r\n1,1\r\n'),
        ],
        ids=['simple', 'stream'],
    )
    def test_csv_output(self, asgi, app_kind, util, recipe, expected_head):
        module = util.load_module(
            recipe, parent_dir='examples/recipes', suffix=app_kind
        )
        app = util.create_app(asgi)
        app.add_route('/report', module.Report())

        result = falcon.testing.simulate_get(app, '/report')
        assert result.status_code == 200
        assert result.text.startswith(expected_head)


class TestPrettyJSON:
    class QuoteResource:
        def on_get(self, req, resp):
            resp.media = {
                'author': 'Grace Hopper',
                'quote': (
                    "I've always been more interested in "
                    'the future than in the past.'
                ),
            }

    class NegotiationMiddleware:
        def process_request(self, req, resp):
            resp.content_type = req.accept

    def test_optional_indent(self, util):
        recipe = util.load_module('examples/recipes/pretty_json_main.py')

        app = falcon.App(middleware=[self.NegotiationMiddleware()])
        app.add_route('/quote', self.QuoteResource())
        app.resp_options.media_handlers.update(
            {falcon.MEDIA_JSON: recipe.CustomJSONHandler()}
        )

        result = falcon.testing.simulate_get(
            app, '/quote', headers={'Accept': 'application/json; indent=4'}
        )
        assert result.status_code == 200
        assert result.text == (
            '{\n'
            '    "author": "Grace Hopper",\n'
            '    "quote": "I\'ve always been more interested in the future '
            'than in the past."\n'
            '}'
        )


class TestRawURLPath:
    def path_extras(self, asgi, url):
        if asgi:
            return {'raw_path': url.encode()}
        return None

    def test_raw_path(self, asgi, app_kind, util):
        recipe = util.load_module(
            'raw_url_path', parent_dir='examples/recipes', suffix=app_kind
        )

        # TODO(vytas): Improve TestClient to automatically add ASGI raw_path
        #   (as it does for WSGI): GH #2262.

        url1 = '/cache/http%3A%2F%2Ffalconframework.org'
        result1 = falcon.testing.simulate_get(
            recipe.app, url1, extras=self.path_extras(asgi, url1)
        )
        assert result1.status_code == 200
        assert result1.json == {'url': 'http://falconframework.org'}

        url2 = '/cache/http%3A%2F%2Ffalconframework.org/status'
        result2 = falcon.testing.simulate_get(
            recipe.app, url2, extras=self.path_extras(asgi, url2)
        )
        assert result2.status_code == 200
        assert result2.json == {'cached': True}