File: test_stubs.py

package info (click to toggle)
vcr.py 7.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,060 kB
  • sloc: python: 6,264; makefile: 188; sh: 1
file content (135 lines) | stat: -rw-r--r-- 5,006 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
import http.client as httplib
import json
import zlib

import vcr

from ..assertions import assert_is_json_bytes


def _headers_are_case_insensitive(host, port):
    conn = httplib.HTTPConnection(host, port)
    conn.request("GET", "/cookies/set?k1=v1")
    r1 = conn.getresponse()
    cookie_data1 = r1.getheader("set-cookie")
    conn = httplib.HTTPConnection(host, port)
    conn.request("GET", "/cookies/set?k1=v1")
    r2 = conn.getresponse()
    cookie_data2 = r2.getheader("Set-Cookie")
    return cookie_data1 == cookie_data2


def test_case_insensitivity(tmpdir, httpbin):
    testfile = str(tmpdir.join("case_insensitivity.yml"))
    # check if headers are case insensitive outside of vcrpy
    host, port = httpbin.host, httpbin.port
    outside = _headers_are_case_insensitive(host, port)
    with vcr.use_cassette(testfile):
        # check if headers are case insensitive inside of vcrpy
        inside = _headers_are_case_insensitive(host, port)
        # check if headers are case insensitive after vcrpy deserializes headers
        inside2 = _headers_are_case_insensitive(host, port)

    # behavior should be the same both inside and outside
    assert outside == inside == inside2


def _multiple_header_value(httpbin):
    conn = httplib.HTTPConnection(httpbin.host, httpbin.port)
    conn.request("GET", "/response-headers?foo=bar&foo=baz")
    r = conn.getresponse()
    return r.getheader("foo")


def test_multiple_headers(tmpdir, httpbin):
    testfile = str(tmpdir.join("multiple_headers.yaml"))
    outside = _multiple_header_value(httpbin)

    with vcr.use_cassette(testfile):
        inside = _multiple_header_value(httpbin)

    assert outside == inside


def test_original_decoded_response_is_not_modified(tmpdir, httpbin):
    testfile = str(tmpdir.join("decoded_response.yml"))
    host, port = httpbin.host, httpbin.port

    conn = httplib.HTTPConnection(host, port)
    conn.request("GET", "/gzip")
    outside = conn.getresponse()

    with vcr.use_cassette(testfile, decode_compressed_response=True):
        conn = httplib.HTTPConnection(host, port)
        conn.request("GET", "/gzip")
        inside = conn.getresponse()

        # Assert that we do not modify the original response while appending
        # to the cassette.
        assert "gzip" == inside.headers["content-encoding"]

        # They should effectively be the same response.
        inside_headers = (h for h in inside.headers.items() if h[0].lower() != "date")
        outside_headers = (h for h in outside.getheaders() if h[0].lower() != "date")
        assert set(inside_headers) == set(outside_headers)
        inside = zlib.decompress(inside.read(), 16 + zlib.MAX_WBITS)
        outside = zlib.decompress(outside.read(), 16 + zlib.MAX_WBITS)
        assert inside == outside

    # Even though the above are raw bytes, the JSON data should have been
    # decoded and saved to the cassette.
    with vcr.use_cassette(testfile):
        conn = httplib.HTTPConnection(host, port)
        conn.request("GET", "/gzip")
        inside = conn.getresponse()

        assert "content-encoding" not in inside.headers
        assert_is_json_bytes(inside.read())


def _make_before_record_response(fields, replacement="[REDACTED]"):
    def before_record_response(response):
        string_body = response["body"]["string"].decode("utf8")
        body = json.loads(string_body)

        for field in fields:
            if field in body:
                body[field] = replacement

        response["body"]["string"] = json.dumps(body).encode()
        return response

    return before_record_response


def test_original_response_is_not_modified_by_before_filter(tmpdir, httpbin):
    testfile = str(tmpdir.join("sensitive_data_scrubbed_response.yml"))
    host, port = httpbin.host, httpbin.port
    field_to_scrub = "url"
    replacement = "[YOU_CANT_HAVE_THE_MANGO]"

    conn = httplib.HTTPConnection(host, port)
    conn.request("GET", "/get")
    outside = conn.getresponse()

    callback = _make_before_record_response([field_to_scrub], replacement)
    with vcr.use_cassette(testfile, before_record_response=callback):
        conn = httplib.HTTPConnection(host, port)
        conn.request("GET", "/get")
        inside = conn.getresponse()

        # The scrubbed field should be the same, because no cassette existed.
        # Furthermore, the responses should be identical.
        inside_body = json.loads(inside.read())
        outside_body = json.loads(outside.read())
        assert not inside_body[field_to_scrub] == replacement
        assert inside_body[field_to_scrub] == outside_body[field_to_scrub]

    # Ensure that when a cassette exists, the scrubbed response is returned.
    with vcr.use_cassette(testfile, before_record_response=callback):
        conn = httplib.HTTPConnection(host, port)
        conn.request("GET", "/get")
        inside = conn.getresponse()

        inside_body = json.loads(inside.read())
        assert inside_body[field_to_scrub] == replacement