1# #!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# <HTTPretty - HTTP client mock for Python>
5# Copyright (C) <2011-2021> Gabriel Falcão <gabriel@nacaolivre.org>
6#
7# Permission is hereby granted, free of charge, to any person
8# obtaining a copy of this software and associated documentation
9# files (the "Software"), to deal in the Software without
10# restriction, including without limitation the rights to use,
11# copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the
13# Software is furnished to do so, subject to the following
14# conditions:
15#
16# The above copyright notice and this permission notice shall be
17# included in all copies or substantial portions of the Software.
18#
19# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26# OTHER DEALINGS IN THE SOFTWARE.
27from __future__ import unicode_literals
28
29import re
30import httplib2
31from freezegun import freeze_time
32from sure import expect, within, miliseconds
33from httpretty import HTTPretty, httprettified
34from httpretty.core import decode_utf8
35
36
37@httprettified
38@within(two=miliseconds)
39def test_httpretty_should_mock_a_simple_get_with_httplib2_read(now):
40    "HTTPretty should mock a simple GET with httplib2.context.http"
41
42    HTTPretty.register_uri(HTTPretty.GET, "http://yipit.com/",
43                           body="Find the best daily deals")
44
45    _, got = httplib2.Http().request('http://yipit.com', 'GET')
46    expect(got).to.equal(b'Find the best daily deals')
47
48    expect(HTTPretty.last_request.method).to.equal('GET')
49    expect(HTTPretty.last_request.path).to.equal('/')
50
51
52@httprettified
53@within(two=miliseconds)
54def test_httpretty_provides_easy_access_to_querystrings(now):
55    "HTTPretty should provide an easy access to the querystring"
56
57    HTTPretty.register_uri(HTTPretty.GET, "http://yipit.com/",
58                           body="Find the best daily deals")
59
60    httplib2.Http().request('http://yipit.com?foo=bar&foo=baz&chuck=norris', 'GET')
61    expect(HTTPretty.last_request.querystring).to.equal({
62        'foo': ['bar', 'baz'],
63        'chuck': ['norris'],
64    })
65
66
67@httprettified
68@freeze_time("2013-10-04 04:20:00")
69def test_httpretty_should_mock_headers_httplib2():
70    "HTTPretty should mock basic headers with httplib2"
71
72    HTTPretty.register_uri(HTTPretty.GET, "http://github.com/",
73                           body="this is supposed to be the response",
74                           status=201)
75
76    headers, _ = httplib2.Http().request('http://github.com', 'GET')
77    expect(headers['status']).to.equal('201')
78    expect(dict(headers)).to.equal({
79        'content-type': 'text/plain; charset=utf-8',
80        'connection': 'close',
81        'content-length': '35',
82        'status': '201',
83        'server': 'Python/HTTPretty',
84        'date': 'Fri, 04 Oct 2013 04:20:00 GMT',
85    })
86
87
88@httprettified
89@freeze_time("2013-10-04 04:20:00")
90def test_httpretty_should_allow_adding_and_overwritting_httplib2():
91    "HTTPretty should allow adding and overwritting headers with httplib2"
92
93    HTTPretty.register_uri(HTTPretty.GET, "http://github.com/foo",
94                           body="this is supposed to be the response",
95                           adding_headers={
96                               'Server': 'Apache',
97                               'Content-Length': '27',
98                               'Content-Type': 'application/json',
99                           })
100
101    headers, _ = httplib2.Http().request('http://github.com/foo', 'GET')
102
103    expect(dict(headers)).to.equal({
104        'content-type': 'application/json',
105        'content-location': 'http://github.com/foo',
106        'connection': 'close',
107        'content-length': '27',
108        'status': '200',
109        'server': 'Apache',
110        'date': 'Fri, 04 Oct 2013 04:20:00 GMT',
111    })
112
113
114@httprettified
115@within(two=miliseconds)
116def test_httpretty_should_allow_forcing_headers_httplib2(now):
117    "HTTPretty should allow forcing headers with httplib2"
118
119    HTTPretty.register_uri(HTTPretty.GET, "http://github.com/foo",
120                           body="this is supposed to be the response",
121                           forcing_headers={
122                               'Content-Type': 'application/xml',
123                           })
124
125    headers, _ = httplib2.Http().request('http://github.com/foo', 'GET')
126
127    expect(dict(headers)).to.equal({
128        'content-location': 'http://github.com/foo',  # httplib2 FORCES
129                                                      # content-location
130                                                      # even if the
131                                                      # server does not
132                                                      # provide it
133        'content-type': 'application/xml',
134        'status': '200',  # httplib2 also ALWAYS put status on headers
135    })
136
137
138@httprettified
139@freeze_time("2013-10-04 04:20:00")
140def test_httpretty_should_allow_adding_and_overwritting_by_kwargs_u2():
141    "HTTPretty should allow adding and overwritting headers by keyword args " \
142        "with httplib2"
143
144    HTTPretty.register_uri(HTTPretty.GET, "http://github.com/foo",
145                           body="this is supposed to be the response",
146                           server='Apache',
147                           content_length='27',
148                           content_type='application/json')
149
150    headers, _ = httplib2.Http().request('http://github.com/foo', 'GET')
151
152    expect(dict(headers)).to.equal({
153        'content-type': 'application/json',
154        'content-location': 'http://github.com/foo',  # httplib2 FORCES
155                                                      # content-location
156                                                      # even if the
157                                                      # server does not
158                                                      # provide it
159        'connection': 'close',
160        'content-length': '27',
161        'status': '200',
162        'server': 'Apache',
163        'date': 'Fri, 04 Oct 2013 04:20:00 GMT',
164    })
165
166
167@httprettified
168@within(two=miliseconds)
169def test_rotating_responses_with_httplib2(now):
170    "HTTPretty should support rotating responses with httplib2"
171
172    HTTPretty.register_uri(
173        HTTPretty.GET, "https://api.yahoo.com/test",
174        responses=[
175            HTTPretty.Response(body="first response", status=201),
176            HTTPretty.Response(body='second and last response', status=202),
177        ])
178
179    headers1, body1 = httplib2.Http().request(
180        'https://api.yahoo.com/test', 'GET')
181
182    expect(headers1['status']).to.equal('201')
183    expect(body1).to.equal(b'first response')
184
185    headers2, body2 = httplib2.Http().request(
186        'https://api.yahoo.com/test', 'GET')
187
188    expect(headers2['status']).to.equal('202')
189    expect(body2).to.equal(b'second and last response')
190
191    headers3, body3 = httplib2.Http().request(
192        'https://api.yahoo.com/test', 'GET')
193
194    expect(headers3['status']).to.equal('202')
195    expect(body3).to.equal(b'second and last response')
196
197
198@httprettified
199@within(two=miliseconds)
200def test_can_inspect_last_request(now):
201    "HTTPretty.last_request is a mimetools.Message request from last match"
202
203    HTTPretty.register_uri(HTTPretty.POST, "http://api.github.com/",
204                           body='{"repositories": ["HTTPretty", "lettuce"]}')
205
206    headers, body = httplib2.Http().request(
207        'http://api.github.com', 'POST',
208        body='{"username": "gabrielfalcao"}',
209        headers={
210            'content-type': 'text/json',
211        },
212    )
213
214    expect(HTTPretty.last_request.method).to.equal('POST')
215    expect(HTTPretty.last_request.body).to.equal(
216        b'{"username": "gabrielfalcao"}',
217    )
218    expect(HTTPretty.last_request.headers['content-type']).to.equal(
219        'text/json',
220    )
221    expect(body).to.equal(b'{"repositories": ["HTTPretty", "lettuce"]}')
222
223
224@httprettified
225@within(two=miliseconds)
226def test_can_inspect_last_request_with_ssl(now):
227    "HTTPretty.last_request is recorded even when mocking 'https' (SSL)"
228
229    HTTPretty.register_uri(HTTPretty.POST, "https://secure.github.com/",
230                           body='{"repositories": ["HTTPretty", "lettuce"]}')
231
232    headers, body = httplib2.Http().request(
233        'https://secure.github.com', 'POST',
234        body='{"username": "gabrielfalcao"}',
235        headers={
236            'content-type': 'text/json',
237        },
238    )
239
240    expect(HTTPretty.last_request.method).to.equal('POST')
241    expect(HTTPretty.last_request.body).to.equal(
242        b'{"username": "gabrielfalcao"}',
243    )
244    expect(HTTPretty.last_request.headers['content-type']).to.equal(
245        'text/json',
246    )
247    expect(body).to.equal(b'{"repositories": ["HTTPretty", "lettuce"]}')
248
249
250@httprettified
251@within(two=miliseconds)
252def test_httpretty_ignores_querystrings_from_registered_uri(now):
253    "Registering URIs with query string cause them to be ignored"
254
255    HTTPretty.register_uri(HTTPretty.GET, "http://yipit.com/?id=123",
256                           body="Find the best daily deals")
257
258    _, got = httplib2.Http().request('http://yipit.com/?id=123', 'GET')
259
260    expect(got).to.equal(b'Find the best daily deals')
261    expect(HTTPretty.last_request.method).to.equal('GET')
262    expect(HTTPretty.last_request.path).to.equal('/?id=123')
263
264
265@httprettified
266@within(two=miliseconds)
267def test_callback_response(now):
268    ("HTTPretty should call a callback function to be set as the body with"
269     " httplib2")
270
271    def request_callback(request, uri, headers):
272        return [200, headers, "The {} response from {}".format(decode_utf8(request.method), uri)]
273
274    HTTPretty.register_uri(
275        HTTPretty.GET, "https://api.yahoo.com/test",
276        body=request_callback)
277
278    headers1, body1 = httplib2.Http().request(
279        'https://api.yahoo.com/test', 'GET')
280
281    expect(body1).to.equal(b"The GET response from https://api.yahoo.com/test")
282
283    HTTPretty.register_uri(
284        HTTPretty.POST, "https://api.yahoo.com/test_post",
285        body=request_callback)
286
287    headers2, body2 = httplib2.Http().request(
288        'https://api.yahoo.com/test_post', 'POST')
289
290    expect(body2).to.equal(b"The POST response from https://api.yahoo.com/test_post")
291
292
293@httprettified
294def test_httpretty_should_allow_registering_regexes():
295    "HTTPretty should allow registering regexes with httplib2"
296
297    HTTPretty.register_uri(
298        HTTPretty.GET,
299        'http://api.yipit.com/v1/deal;brand=gap',
300        body="Found brand",
301    )
302
303    response, body = httplib2.Http().request('http://api.yipit.com/v1/deal;brand=gap', 'GET')
304    expect(body).to.equal(b'Found brand')
305    expect(HTTPretty.last_request.method).to.equal('GET')
306    expect(HTTPretty.last_request.path).to.equal('/v1/deal;brand=gap')
307