diff --git a/httpie/models.py b/httpie/models.py index af6163fd..d7c5414f 100644 --- a/httpie/models.py +++ b/httpie/models.py @@ -105,8 +105,13 @@ class HTTPRequest(HTTPMessage): if 'Host' not in self._orig.headers: headers['Host'] = url.netloc.split('@')[-1] - headers = ['%s: %s' % (name, value) - for name, value in headers.items()] + headers = [ + '%s: %s' % ( + name, + value if isinstance(value, str) else value.decode('utf8') + ) + for name, value in headers.items() + ] headers.insert(0, request_line) headers = '\r\n'.join(headers).strip() diff --git a/requirements-dev.txt b/requirements-dev.txt index bd00cc55..1b0b06ae 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,4 +2,5 @@ tox pytest pytest-xdist pytest-cov +pytest-httpbin docutils diff --git a/setup.py b/setup.py index 7a23a277..a4cc2719 100644 --- a/setup.py +++ b/setup.py @@ -26,6 +26,7 @@ class PyTest(TestCommand): tests_require = [ 'pytest', + 'pytest-httpbin', ] diff --git a/tests/test_auth.py b/tests/test_auth.py index 1977a064..53962615 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -2,42 +2,45 @@ import requests import pytest -from utils import http, httpbin, HTTP_OK +from utils import http, add_auth, HTTP_OK import httpie.input class TestAuth: - def test_basic_auth(self): + def test_basic_auth(self, httpbin): r = http('--auth=user:password', - 'GET', httpbin('/basic-auth/user/password')) + 'GET', httpbin.url + '/basic-auth/user/password') assert HTTP_OK in r assert r.json == {'authenticated': True, 'user': 'user'} @pytest.mark.skipif( requests.__version__ == '0.13.6', reason='Redirects with prefetch=False are broken in Requests 0.13.6') - def test_digest_auth(self): + def test_digest_auth(self, httpbin): r = http('--auth-type=digest', '--auth=user:password', - 'GET', httpbin('/digest-auth/auth/user/password')) + 'GET', httpbin.url + '/digest-auth/auth/user/password') assert HTTP_OK in r assert r.json == {'authenticated': True, 'user': 'user'} - def test_password_prompt(self): + def test_password_prompt(self, httpbin): httpie.input.AuthCredentials._getpass = lambda self, prompt: 'password' - r = http('--auth', 'user', 'GET', httpbin('/basic-auth/user/password')) + r = http('--auth', 'user', + 'GET', httpbin.url + '/basic-auth/user/password') assert HTTP_OK in r assert r.json == {'authenticated': True, 'user': 'user'} - def test_credentials_in_url(self): - url = httpbin('/basic-auth/user/password', auth='user:password') + def test_credentials_in_url(self, httpbin): + url = add_auth(httpbin.url + '/basic-auth/user/password', + auth='user:password') r = http('GET', url) assert HTTP_OK in r assert r.json == {'authenticated': True, 'user': 'user'} - def test_credentials_in_url_auth_flag_has_priority(self): + def test_credentials_in_url_auth_flag_has_priority(self, httpbin): """When credentials are passed in URL and via -a at the same time, then the ones from -a are used.""" - url = httpbin('/basic-auth/user/password', auth='user:wrong') + url = add_auth(httpbin.url + '/basic-auth/user/password', + auth='user:wrong') r = http('--auth=user:password', 'GET', url) assert HTTP_OK in r assert r.json == {'authenticated': True, 'user': 'user'} diff --git a/tests/test_binary.py b/tests/test_binary.py index 7a1bd062..7c112045 100644 --- a/tests/test_binary.py +++ b/tests/test_binary.py @@ -1,30 +1,30 @@ """Tests for dealing with binary request and response data.""" from httpie.compat import urlopen from httpie.output.streams import BINARY_SUPPRESSED_NOTICE -from utils import TestEnvironment, http, httpbin +from utils import TestEnvironment, http from fixtures import BIN_FILE_PATH, BIN_FILE_CONTENT, BIN_FILE_PATH_ARG class TestBinaryRequestData: - def test_binary_stdin(self): + def test_binary_stdin(self, httpbin): with open(BIN_FILE_PATH, 'rb') as stdin: env = TestEnvironment( stdin=stdin, stdin_isatty=False, stdout_isatty=False ) - r = http('--print=B', 'POST', httpbin('/post'), env=env) + r = http('--print=B', 'POST', httpbin.url + '/post', env=env) assert r == BIN_FILE_CONTENT - def test_binary_file_path(self): + def test_binary_file_path(self, httpbin): env = TestEnvironment(stdin_isatty=True, stdout_isatty=False) - r = http('--print=B', 'POST', httpbin('/post'), + r = http('--print=B', 'POST', httpbin.url + '/post', '@' + BIN_FILE_PATH_ARG, env=env, ) assert r == BIN_FILE_CONTENT - def test_binary_file_form(self): + def test_binary_file_form(self, httpbin): env = TestEnvironment(stdin_isatty=True, stdout_isatty=False) - r = http('--print=B', '--form', 'POST', httpbin('/post'), + r = http('--print=B', '--form', 'POST', httpbin.url + '/post', 'test@' + BIN_FILE_PATH_ARG, env=env) assert bytes(BIN_FILE_CONTENT) in bytes(r) diff --git a/tests/test_cli.py b/tests/test_cli.py index c19fcb29..103d9543 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -9,7 +9,7 @@ from httpie import input from httpie.input import KeyValue, KeyValueArgType from httpie import ExitStatus from httpie.cli import parser -from utils import TestEnvironment, http, httpbin, HTTP_OK +from utils import TestEnvironment, http, HTTP_OK from fixtures import ( FILE_PATH_ARG, JSON_FILE_PATH_ARG, JSON_FILE_CONTENT, FILE_CONTENT, FILE_PATH @@ -93,27 +93,28 @@ class TestItemParsing: class TestQuerystring: - def test_query_string_params_in_url(self): - r = http('--print=Hhb', 'GET', httpbin('/get?a=1&b=2')) + def test_query_string_params_in_url(self, httpbin): + r = http('--print=Hhb', 'GET', httpbin.url + '/get?a=1&b=2') path = '/get?a=1&b=2' - url = httpbin(path) + url = httpbin.url + path assert HTTP_OK in r assert 'GET %s HTTP/1.1' % path in r assert '"url": "%s"' % url in r - def test_query_string_params_items(self): - r = http('--print=Hhb', 'GET', httpbin('/get'), 'a==1', 'b==2') - path = '/get?a=1&b=2' - url = httpbin(path) + def test_query_string_params_items(self, httpbin): + r = http('--print=Hhb', 'GET', httpbin.url + '/get', 'a==1') + path = '/get?a=1' + url = httpbin.url + path assert HTTP_OK in r assert 'GET %s HTTP/1.1' % path in r assert '"url": "%s"' % url in r - def test_query_string_params_in_url_and_items_with_duplicates(self): - r = http('--print=Hhb', 'GET', httpbin('/get?a=1&a=1'), - 'a==1', 'a==1', 'b==2') - path = '/get?a=1&a=1&a=1&a=1&b=2' - url = httpbin(path) + def test_query_string_params_in_url_and_items_with_duplicates(self, + httpbin): + r = http('--print=Hhb', 'GET', + httpbin.url + '/get?a=1&a=1', 'a==1', 'a==1') + path = '/get?a=1&a=1&a=1&a=1' + url = httpbin.url + path assert HTTP_OK in r assert 'GET %s HTTP/1.1' % path in r assert '"url": "%s"' % url in r @@ -257,12 +258,13 @@ class TestArgumentParser: class TestNoOptions: - def test_valid_no_options(self): - r = http('--verbose', '--no-verbose', 'GET', httpbin('/get')) + + def test_valid_no_options(self, httpbin): + r = http('--verbose', '--no-verbose', 'GET', httpbin.url + '/get') assert 'GET /get HTTP/1.1' not in r - def test_invalid_no_options(self): - r = http('--no-war', 'GET', httpbin('/get'), + def test_invalid_no_options(self, httpbin): + r = http('--no-war', 'GET', httpbin.url + '/get', error_exit_ok=True) assert r.exit_status == 1 assert 'unrecognized arguments: --no-war' in r.stderr @@ -270,16 +272,18 @@ class TestNoOptions: class TestIgnoreStdin: - def test_ignore_stdin(self): + + def test_ignore_stdin(self, httpbin): with open(FILE_PATH) as f: env = TestEnvironment(stdin=f, stdin_isatty=False) - r = http('--ignore-stdin', '--verbose', httpbin('/get'), env=env) + r = http('--ignore-stdin', '--verbose', httpbin.url + '/get', + env=env) assert HTTP_OK in r assert 'GET /get HTTP' in r, "Don't default to POST." assert FILE_CONTENT not in r, "Don't send stdin data." - def test_ignore_stdin_cannot_prompt_password(self): - r = http('--ignore-stdin', '--auth=no-password', httpbin('/get'), + def test_ignore_stdin_cannot_prompt_password(self, httpbin): + r = http('--ignore-stdin', '--auth=no-password', httpbin.url + '/get', error_exit_ok=True) assert r.exit_status == ExitStatus.ERROR assert 'because --ignore-stdin' in r.stderr diff --git a/tests/test_defaults.py b/tests/test_defaults.py index dffbaf6e..652a272b 100644 --- a/tests/test_defaults.py +++ b/tests/test_defaults.py @@ -2,34 +2,34 @@ Tests for the provided defaults regarding HTTP method, and --json vs. --form. """ -from utils import TestEnvironment, http, httpbin, HTTP_OK +from utils import TestEnvironment, http, HTTP_OK, no_content_type from fixtures import FILE_PATH class TestImplicitHTTPMethod: - def test_implicit_GET(self): - r = http(httpbin('/get')) + def test_implicit_GET(self, httpbin): + r = http(httpbin.url + '/get') assert HTTP_OK in r - def test_implicit_GET_with_headers(self): - r = http(httpbin('/headers'), 'Foo:bar') + def test_implicit_GET_with_headers(self, httpbin): + r = http(httpbin.url + '/headers', 'Foo:bar') assert HTTP_OK in r assert r.json['headers']['Foo'] == 'bar' - def test_implicit_POST_json(self): - r = http(httpbin('/post'), 'hello=world') + def test_implicit_POST_json(self, httpbin): + r = http(httpbin.url + '/post', 'hello=world') assert HTTP_OK in r assert r.json['json'] == {'hello': 'world'} - def test_implicit_POST_form(self): - r = http('--form', httpbin('/post'), 'foo=bar') + def test_implicit_POST_form(self, httpbin): + r = http('--form', httpbin.url + '/post', 'foo=bar') assert HTTP_OK in r assert r.json['form'] == {'foo': 'bar'} - def test_implicit_POST_stdin(self): + def test_implicit_POST_stdin(self, httpbin): with open(FILE_PATH) as f: env = TestEnvironment(stdin_isatty=False, stdin=f) - r = http('--form', httpbin('/post'), env=env) + r = http('--form', httpbin.url + '/post', env=env) assert HTTP_OK in r @@ -41,66 +41,66 @@ class TestAutoContentTypeAndAcceptHeaders: """ - def test_GET_no_data_no_auto_headers(self): + def test_GET_no_data_no_auto_headers(self, httpbin): # https://github.com/jakubroztocil/httpie/issues/62 - r = http('GET', httpbin('/headers')) + r = http('GET', httpbin.url + '/headers') assert HTTP_OK in r assert r.json['headers']['Accept'] == '*/*' - assert 'Content-Type' not in r.json['headers'] + assert no_content_type(r.json['headers']) - def test_POST_no_data_no_auto_headers(self): + def test_POST_no_data_no_auto_headers(self, httpbin): # JSON headers shouldn't be automatically set for POST with no data. - r = http('POST', httpbin('/post')) + r = http('POST', httpbin.url + '/post') assert HTTP_OK in r assert '"Accept": "*/*"' in r assert '"Content-Type": "application/json' not in r - def test_POST_with_data_auto_JSON_headers(self): - r = http('POST', httpbin('/post'), 'a=b') + def test_POST_with_data_auto_JSON_headers(self, httpbin): + r = http('POST', httpbin.url + '/post', 'a=b') assert HTTP_OK in r assert '"Accept": "application/json"' in r assert '"Content-Type": "application/json; charset=utf-8' in r - def test_GET_with_data_auto_JSON_headers(self): + def test_GET_with_data_auto_JSON_headers(self, httpbin): # JSON headers should automatically be set also for GET with data. - r = http('POST', httpbin('/post'), 'a=b') + r = http('POST', httpbin.url + '/post', 'a=b') assert HTTP_OK in r assert '"Accept": "application/json"' in r, r assert '"Content-Type": "application/json; charset=utf-8' in r - def test_POST_explicit_JSON_auto_JSON_accept(self): - r = http('--json', 'POST', httpbin('/post')) + def test_POST_explicit_JSON_auto_JSON_accept(self, httpbin): + r = http('--json', 'POST', httpbin.url + '/post') assert HTTP_OK in r assert r.json['headers']['Accept'] == 'application/json' # Make sure Content-Type gets set even with no data. # https://github.com/jakubroztocil/httpie/issues/137 assert 'application/json' in r.json['headers']['Content-Type'] - def test_GET_explicit_JSON_explicit_headers(self): - r = http('--json', 'GET', httpbin('/headers'), + def test_GET_explicit_JSON_explicit_headers(self, httpbin): + r = http('--json', 'GET', httpbin.url + '/headers', 'Accept:application/xml', 'Content-Type:application/xml') assert HTTP_OK in r assert '"Accept": "application/xml"' in r assert '"Content-Type": "application/xml"' in r - def test_POST_form_auto_Content_Type(self): - r = http('--form', 'POST', httpbin('/post')) + def test_POST_form_auto_Content_Type(self, httpbin): + r = http('--form', 'POST', httpbin.url + '/post') assert HTTP_OK in r assert '"Content-Type": "application/x-www-form-urlencoded' in r - def test_POST_form_Content_Type_override(self): - r = http('--form', 'POST', httpbin('/post'), + def test_POST_form_Content_Type_override(self, httpbin): + r = http('--form', 'POST', httpbin.url + '/post', 'Content-Type:application/xml') assert HTTP_OK in r assert '"Content-Type": "application/xml"' in r - def test_print_only_body_when_stdout_redirected_by_default(self): + def test_print_only_body_when_stdout_redirected_by_default(self, httpbin): env = TestEnvironment(stdin_isatty=True, stdout_isatty=False) - r = http('GET', httpbin('/get'), env=env) + r = http('GET', httpbin.url + '/get', env=env) assert 'HTTP/' not in r - def test_print_overridable_when_stdout_redirected(self): + def test_print_overridable_when_stdout_redirected(self, httpbin): env = TestEnvironment(stdin_isatty=True, stdout_isatty=False) - r = http('--print=h', 'GET', httpbin('/get'), env=env) + r = http('--print=h', 'GET', httpbin.url + '/get', env=env) assert HTTP_OK in r diff --git a/tests/test_downloads.py b/tests/test_downloads.py index ce722606..3a8c8f24 100644 --- a/tests/test_downloads.py +++ b/tests/test_downloads.py @@ -9,7 +9,7 @@ from httpie.downloads import ( parse_content_range, filename_from_content_disposition, filename_from_url, get_unique_filename, ContentRangeError, Download, ) -from utils import httpbin, http, TestEnvironment +from utils import http, TestEnvironment class Response(object): @@ -94,8 +94,8 @@ class TestDownloadUtils: class TestDownloads: # TODO: more tests - def test_actual_download(self): - url = httpbin('/robots.txt') + def test_actual_download(self, httpbin): + url = httpbin.url + '/robots.txt' body = urlopen(url).read().decode() env = TestEnvironment(stdin_isatty=True, stdout_isatty=False) r = http('--download', url, env=env) @@ -104,11 +104,11 @@ class TestDownloads: assert 'Done' in r.stderr assert body == r - def test_download_with_Content_Length(self): + def test_download_with_Content_Length(self, httpbin): devnull = open(os.devnull, 'w') download = Download(output_file=devnull, progress_file=devnull) download.start(Response( - url=httpbin('/'), + url=httpbin.url + '/', headers={'Content-Length': 10} )) time.sleep(1.1) @@ -118,20 +118,20 @@ class TestDownloads: download.finish() assert not download.interrupted - def test_download_no_Content_Length(self): + def test_download_no_Content_Length(self, httpbin): devnull = open(os.devnull, 'w') download = Download(output_file=devnull, progress_file=devnull) - download.start(Response(url=httpbin('/'))) + download.start(Response(url=httpbin.url + '/')) time.sleep(1.1) download.chunk_downloaded(b'12345') download.finish() assert not download.interrupted - def test_download_interrupted(self): + def test_download_interrupted(self, httpbin): devnull = open(os.devnull, 'w') download = Download(output_file=devnull, progress_file=devnull) download.start(Response( - url=httpbin('/'), + url=httpbin.url + '/', headers={'Content-Length': 5} )) download.chunk_downloaded(b'1234') diff --git a/tests/test_exit_status.py b/tests/test_exit_status.py index 8e946317..7ac643f9 100644 --- a/tests/test_exit_status.py +++ b/tests/test_exit_status.py @@ -2,18 +2,18 @@ import requests import pytest from httpie import ExitStatus -from utils import TestEnvironment, http, httpbin, HTTP_OK +from utils import TestEnvironment, http, HTTP_OK class TestExitStatus: - def test_ok_response_exits_0(self): - r = http('GET', httpbin('/status/200')) + def test_ok_response_exits_0(self, httpbin): + r = http('GET', httpbin.url + '/status/200') assert HTTP_OK in r assert r.exit_status == ExitStatus.OK - def test_error_response_exits_0_without_check_status(self): - r = http('GET', httpbin('/status/500')) - assert 'HTTP/1.1 500' in r + def test_error_response_exits_0_without_check_status(self, httpbin): + r = http('GET', httpbin.url + '/status/500') + assert '500 INTERNAL SERVER ERRO' in r assert r.exit_status == ExitStatus.OK assert not r.stderr @@ -21,40 +21,43 @@ class TestExitStatus: tuple(map(int, requests.__version__.split('.'))) < (2, 3, 0), reason='timeout broken in requests prior v2.3.0 (#185)' ) - def test_timeout_exit_status(self): + def test_timeout_exit_status(self, httpbin): - r = http('--timeout=0.5', 'GET', httpbin('/delay/1'), + r = http('--timeout=0.5', 'GET', httpbin.url + '/delay/1', error_exit_ok=True) assert r.exit_status == ExitStatus.ERROR_TIMEOUT - def test_3xx_check_status_exits_3_and_stderr_when_stdout_redirected(self): + def test_3xx_check_status_exits_3_and_stderr_when_stdout_redirected( + self, httpbin): env = TestEnvironment(stdout_isatty=False) - r = http('--check-status', '--headers', 'GET', httpbin('/status/301'), + r = http('--check-status', '--headers', + 'GET', httpbin.url + '/status/301', env=env, error_exit_ok=True) - assert 'HTTP/1.1 301' in r + assert '301 MOVED PERMANENTLY' in r assert r.exit_status == ExitStatus.ERROR_HTTP_3XX assert '301 moved permanently' in r.stderr.lower() @pytest.mark.skipif( requests.__version__ == '0.13.6', reason='Redirects with prefetch=False are broken in Requests 0.13.6') - def test_3xx_check_status_redirects_allowed_exits_0(self): - r = http('--check-status', '--follow', 'GET', httpbin('/status/301'), + def test_3xx_check_status_redirects_allowed_exits_0(self, httpbin): + r = http('--check-status', '--follow', + 'GET', httpbin.url + '/status/301', error_exit_ok=True) # The redirect will be followed so 200 is expected. - assert 'HTTP/1.1 200 OK' in r + assert HTTP_OK in r assert r.exit_status == ExitStatus.OK - def test_4xx_check_status_exits_4(self): - r = http('--check-status', 'GET', httpbin('/status/401'), + def test_4xx_check_status_exits_4(self, httpbin): + r = http('--check-status', 'GET', httpbin.url + '/status/401', error_exit_ok=True) - assert 'HTTP/1.1 401' in r + assert '401 UNAUTHORIZED' in r assert r.exit_status == ExitStatus.ERROR_HTTP_4XX # Also stderr should be empty since stdout isn't redirected. assert not r.stderr - def test_5xx_check_status_exits_5(self): - r = http('--check-status', 'GET', httpbin('/status/500'), + def test_5xx_check_status_exits_5(self, httpbin): + r = http('--check-status', 'GET', httpbin.url + '/status/500', error_exit_ok=True) - assert 'HTTP/1.1 500' in r + assert '500 INTERNAL SERVER ERROR' in r assert r.exit_status == ExitStatus.ERROR_HTTP_5XX diff --git a/tests/test_httpie.py b/tests/test_httpie.py index 74be3a59..2ee647ea 100644 --- a/tests/test_httpie.py +++ b/tests/test_httpie.py @@ -1,5 +1,5 @@ """High-level tests.""" -from utils import TestEnvironment, http, httpbin, HTTP_OK +from utils import TestEnvironment, http, HTTP_OK from fixtures import FILE_PATH, FILE_CONTENT import httpie @@ -23,43 +23,43 @@ class TestHTTPie: # FIXME: py3 has version in stdout, py2 in stderr assert httpie.__version__ == r.stderr.strip() + r.strip() - def test_GET(self): - r = http('GET', httpbin('/get')) + def test_GET(self, httpbin): + r = http('GET', httpbin.url + '/get') assert HTTP_OK in r - def test_DELETE(self): - r = http('DELETE', httpbin('/delete')) + def test_DELETE(self, httpbin): + r = http('DELETE', httpbin.url + '/delete') assert HTTP_OK in r - def test_PUT(self): - r = http('PUT', httpbin('/put'), 'foo=bar') + def test_PUT(self, httpbin): + r = http('PUT', httpbin.url + '/put', 'foo=bar') assert HTTP_OK in r - assert r'\"foo\": \"bar\"' in r + assert r.json['json']['foo'] == 'bar' - def test_POST_JSON_data(self): - r = http('POST', httpbin('/post'), 'foo=bar') + def test_POST_JSON_data(self, httpbin): + r = http('POST', httpbin.url + '/post', 'foo=bar') assert HTTP_OK in r - assert r'\"foo\": \"bar\"' in r + assert r.json['json']['foo'] == 'bar' - def test_POST_form(self): - r = http('--form', 'POST', httpbin('/post'), 'foo=bar') + def test_POST_form(self, httpbin): + r = http('--form', 'POST', httpbin.url + '/post', 'foo=bar') assert HTTP_OK in r assert '"foo": "bar"' in r - def test_POST_form_multiple_values(self): - r = http('--form', 'POST', httpbin('/post'), 'foo=bar', 'foo=baz') + def test_POST_form_multiple_values(self, httpbin): + r = http('--form', 'POST', httpbin.url + '/post', 'foo=bar', 'foo=baz') assert HTTP_OK in r assert r.json['form'] == {'foo': ['bar', 'baz']} - def test_POST_stdin(self): + def test_POST_stdin(self, httpbin): with open(FILE_PATH) as f: env = TestEnvironment(stdin=f, stdin_isatty=False) - r = http('--form', 'POST', httpbin('/post'), env=env) + r = http('--form', 'POST', httpbin.url + '/post', env=env) assert HTTP_OK in r assert FILE_CONTENT in r - def test_headers(self): - r = http('GET', httpbin('/headers'), 'Foo:bar') + def test_headers(self, httpbin): + r = http('GET', httpbin.url + '/headers', 'Foo:bar') assert HTTP_OK in r assert '"User-Agent": "HTTPie' in r, r assert '"Foo": "bar"' in r diff --git a/tests/test_output.py b/tests/test_output.py index a5ac1048..ad2dec04 100644 --- a/tests/test_output.py +++ b/tests/test_output.py @@ -2,27 +2,28 @@ import pytest from httpie import ExitStatus from httpie.output.formatters.colors import get_lexer -from utils import TestEnvironment, http, httpbin, HTTP_OK, COLOR, CRLF +from utils import TestEnvironment, http, HTTP_OK, COLOR, CRLF class TestVerboseFlag: - def test_verbose(self): - r = http('--verbose', 'GET', httpbin('/get'), 'test-header:__test__') + def test_verbose(self, httpbin): + r = http('--verbose', + 'GET', httpbin.url + '/get', 'test-header:__test__') assert HTTP_OK in r assert r.count('__test__') == 2 - def test_verbose_form(self): + def test_verbose_form(self, httpbin): # https://github.com/jakubroztocil/httpie/issues/53 - r = http('--verbose', '--form', 'POST', httpbin('/post'), + r = http('--verbose', '--form', 'POST', httpbin.url + '/post', 'A=B', 'C=D') assert HTTP_OK in r assert 'A=B&C=D' in r - def test_verbose_json(self): - r = http('--verbose', 'POST', httpbin('/post'), 'foo=bar', 'baz=bar') + def test_verbose_json(self, httpbin): + r = http('--verbose', + 'POST', httpbin.url + '/post', 'foo=bar', 'baz=bar') assert HTTP_OK in r - assert '"baz": "bar"' in r # request - assert r'\"baz\": \"bar\"' in r # response + assert '"baz": "bar"' in r class TestColors: @@ -47,45 +48,47 @@ class TestColors: class TestPrettyOptions: """Test the --pretty flag handling.""" - def test_pretty_enabled_by_default(self): + def test_pretty_enabled_by_default(self, httpbin): env = TestEnvironment(colors=256) - r = http('GET', httpbin('/get'), env=env) + r = http('GET', httpbin.url + '/get', env=env) assert COLOR in r - def test_pretty_enabled_by_default_unless_stdout_redirected(self): - r = http('GET', httpbin('/get')) + def test_pretty_enabled_by_default_unless_stdout_redirected(self, httpbin): + r = http('GET', httpbin.url + '/get') assert COLOR not in r - def test_force_pretty(self): + def test_force_pretty(self, httpbin): env = TestEnvironment(stdout_isatty=False, colors=256) - r = http('--pretty=all', 'GET', httpbin('/get'), env=env, ) + r = http('--pretty=all', 'GET', httpbin.url + '/get', env=env, ) assert COLOR in r - def test_force_ugly(self): - r = http('--pretty=none', 'GET', httpbin('/get')) + def test_force_ugly(self, httpbin): + r = http('--pretty=none', 'GET', httpbin.url + '/get') assert COLOR not in r - def test_subtype_based_pygments_lexer_match(self): + def test_subtype_based_pygments_lexer_match(self, httpbin): """Test that media subtype is used if type/subtype doesn't match any lexer. """ env = TestEnvironment(colors=256) - r = http('--print=B', '--pretty=all', httpbin('/post'), + r = http('--print=B', '--pretty=all', httpbin.url + '/post', 'Content-Type:text/foo+json', 'a=b', env=env) assert COLOR in r - def test_colors_option(self): + def test_colors_option(self, httpbin): env = TestEnvironment(colors=256) - r = http('--print=B', '--pretty=colors', 'GET', httpbin('/get'), 'a=b', + r = http('--print=B', '--pretty=colors', + 'GET', httpbin.url + '/get', 'a=b', env=env) # Tests that the JSON data isn't formatted. assert not r.strip().count('\n') assert COLOR in r - def test_format_option(self): + def test_format_option(self, httpbin): env = TestEnvironment(colors=256) - r = http('--print=B', '--pretty=format', 'GET', httpbin('/get'), 'a=b', + r = http('--print=B', '--pretty=format', + 'GET', httpbin.url + '/get', 'a=b', env=env) # Tests that the JSON data is formatted. assert r.strip().count('\n') == 2 @@ -110,24 +113,24 @@ class TestLineEndings: assert CRLF not in body return body - def test_CRLF_headers_only(self): - r = http('--headers', 'GET', httpbin('/get')) + def test_CRLF_headers_only(self, httpbin): + r = http('--headers', 'GET', httpbin.url + '/get') body = self._validate_crlf(r) assert not body, 'Garbage after headers: %r' % r - def test_CRLF_ugly_response(self): - r = http('--pretty=none', 'GET', httpbin('/get')) + def test_CRLF_ugly_response(self, httpbin): + r = http('--pretty=none', 'GET', httpbin.url + '/get') self._validate_crlf(r) - def test_CRLF_formatted_response(self): - r = http('--pretty=format', 'GET', httpbin('/get')) + def test_CRLF_formatted_response(self, httpbin): + r = http('--pretty=format', 'GET', httpbin.url + '/get') assert r.exit_status == ExitStatus.OK self._validate_crlf(r) - def test_CRLF_ugly_request(self): - r = http('--pretty=none', '--print=HB', 'GET', httpbin('/get')) + def test_CRLF_ugly_request(self, httpbin): + r = http('--pretty=none', '--print=HB', 'GET', httpbin.url + '/get') self._validate_crlf(r) - def test_CRLF_formatted_request(self): - r = http('--pretty=format', '--print=HB', 'GET', httpbin('/get')) + def test_CRLF_formatted_request(self, httpbin): + r = http('--pretty=format', '--print=HB', 'GET', httpbin.url + '/get') self._validate_crlf(r) diff --git a/tests/test_regressions.py b/tests/test_regressions.py index 8c21d1d3..b80fba38 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -4,14 +4,14 @@ import socket from utils import http, HTTP_OK -def test_Host_header_overwrite(): +def test_Host_header_overwrite(httpbin): """ https://github.com/jakubroztocil/httpie/issues/235 """ host = 'httpbin.org' - url = 'http://{httpbin_ip}/get'.format( - httpbin_ip=socket.gethostbyname(host)) - r = http('--print=hH', url, 'host:{}'.format(host)) + url = httpbin.url + '/get' + r = http('--print=hH', url, 'host:{0}'.format(host)) assert HTTP_OK in r assert r.lower().count('host:') == 1 + assert 'host: {0}'.format(host) in r diff --git a/tests/test_sessions.py b/tests/test_sessions.py index c26e66ed..6d598584 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -3,12 +3,14 @@ import os import shutil from httpie.plugins.builtin import HTTPBasicAuth -from utils import TestEnvironment, mk_config_dir, http, httpbin, HTTP_OK +from utils import TestEnvironment, mk_config_dir, http, HTTP_OK, \ + no_content_type from fixtures import UNICODE class SessionTestBase(object): - def setup_method(self, method): + + def start_session(self, httpbin): """Create and reuse a unique config dir for each test.""" self.config_dir = mk_config_dir() @@ -33,67 +35,70 @@ class TestSessionFlow(SessionTestBase): """ - def setup_method(self, method): + def start_session(self, httpbin): """ Start a full-blown session with a custom request header, authorization, and response cookies. """ - super(TestSessionFlow, self).setup_method(method) + super(TestSessionFlow, self).start_session(httpbin) r1 = http('--follow', '--session=test', '--auth=username:password', - 'GET', httpbin('/cookies/set?hello=world'), 'Hello:World', + 'GET', httpbin.url + '/cookies/set?hello=world', + 'Hello:World', env=self.env()) assert HTTP_OK in r1 - def test_session_created_and_reused(self): + def test_session_created_and_reused(self, httpbin): + self.start_session(httpbin) # Verify that the session created in setup_method() has been used. - r2 = http('--session=test', 'GET', httpbin('/get'), env=self.env()) + r2 = http('--session=test', + 'GET', httpbin.url + '/get', env=self.env()) assert HTTP_OK in r2 assert r2.json['headers']['Hello'] == 'World' assert r2.json['headers']['Cookie'] == 'hello=world' assert 'Basic ' in r2.json['headers']['Authorization'] - def test_session_update(self): + def test_session_update(self, httpbin): + self.start_session(httpbin) # Get a response to a request from the original session. - r2 = http('--session=test', 'GET', httpbin('/get'), env=self.env()) + r2 = http('--session=test', 'GET', httpbin.url + '/get', env=self.env()) assert HTTP_OK in r2 # Make a request modifying the session data. r3 = http('--follow', '--session=test', '--auth=username:password2', - 'GET', httpbin('/cookies/set?hello=world2'), 'Hello:World2', + 'GET', httpbin.url + '/cookies/set?hello=world2', 'Hello:World2', env=self.env()) assert HTTP_OK in r3 # Get a response to a request from the updated session. - r4 = http('--session=test', 'GET', httpbin('/get'), env=self.env()) + r4 = http('--session=test', 'GET', httpbin.url + '/get', env=self.env()) assert HTTP_OK in r4 assert r4.json['headers']['Hello'] == 'World2' assert r4.json['headers']['Cookie'] == 'hello=world2' assert (r2.json['headers']['Authorization'] != r4.json['headers']['Authorization']) - def test_session_read_only(self): + def test_session_read_only(self, httpbin): + self.start_session(httpbin) # Get a response from the original session. - r2 = http('--session=test', 'GET', httpbin('/get'), env=self.env()) + r2 = http('--session=test', 'GET', httpbin.url + '/get', env=self.env()) assert HTTP_OK in r2 # Make a request modifying the session data but # with --session-read-only. r3 = http('--follow', '--session-read-only=test', '--auth=username:password2', 'GET', - httpbin('/cookies/set?hello=world2'), 'Hello:World2', + httpbin.url + '/cookies/set?hello=world2', 'Hello:World2', env=self.env()) assert HTTP_OK in r3 # Get a response from the updated session. - r4 = http('--session=test', 'GET', httpbin('/get'), env=self.env()) + r4 = http('--session=test', 'GET', httpbin.url + '/get', env=self.env()) assert HTTP_OK in r4 # Origin can differ on Travis. del r2.json['origin'], r4.json['origin'] # Different for each request. - del r2.json['headers']['X-Request-Id'] - del r4.json['headers']['X-Request-Id'] # Should be the same as before r3. assert r2.json == r4.json @@ -102,51 +107,58 @@ class TestSessionFlow(SessionTestBase): class TestSession(SessionTestBase): """Stand-alone session tests.""" - def test_session_ignored_header_prefixes(self): - r1 = http('--session=test', 'GET', httpbin('/get'), + def test_session_ignored_header_prefixes(self, httpbin): + self.start_session(httpbin) + r1 = http('--session=test', 'GET', httpbin.url + '/get', 'Content-Type: text/plain', 'If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT', env=self.env()) assert HTTP_OK in r1 - r2 = http('--session=test', 'GET', httpbin('/get'), env=self.env()) + r2 = http('--session=test', 'GET', httpbin.url + '/get', env=self.env()) assert HTTP_OK in r2 - assert 'Content-Type' not in r2.json['headers'] + assert no_content_type(r2.json['headers']) assert 'If-Unmodified-Since' not in r2.json['headers'] - def test_session_by_path(self): + def test_session_by_path(self, httpbin): + self.start_session(httpbin) session_path = os.path.join(self.config_dir, 'session-by-path.json') - r1 = http('--session=' + session_path, 'GET', httpbin('/get'), + r1 = http('--session=' + session_path, 'GET', httpbin.url + '/get', 'Foo:Bar', env=self.env()) assert HTTP_OK in r1 - r2 = http('--session=' + session_path, 'GET', httpbin('/get'), + r2 = http('--session=' + session_path, 'GET', httpbin.url + '/get', env=self.env()) assert HTTP_OK in r2 assert r2.json['headers']['Foo'] == 'Bar' - def test_session_unicode(self): - r1 = http('--session=test', '--auth', u'test:' + UNICODE, - 'GET', httpbin('/get'), - u'Test:%s' % UNICODE, + def test_session_unicode(self, httpbin): + self.start_session(httpbin) + + r1 = http('--session=test', u'--auth=test:' + UNICODE, + 'GET', httpbin.url + '/get', u'Test:%s' % UNICODE, env=self.env()) assert HTTP_OK in r1 r2 = http('--session=test', '--verbose', 'GET', - httpbin('/get'), env=self.env()) + httpbin.url + '/get', env=self.env()) assert HTTP_OK in r2 + + # FIXME: Authorization *sometimes* is not present on Python3 assert (r2.json['headers']['Authorization'] == HTTPBasicAuth.make_header(u'test', UNICODE)) # httpbin doesn't interpret utf8 headers assert UNICODE in r2 - def test_session_default_header_value_overwritten(self): + def test_session_default_header_value_overwritten(self, httpbin): + self.start_session(httpbin) # https://github.com/jakubroztocil/httpie/issues/180 - r1 = http('--session=test', httpbin('/headers'), 'User-Agent:custom', + r1 = http('--session=test', + httpbin.url + '/headers', 'User-Agent:custom', env=self.env()) assert HTTP_OK in r1 assert r1.json['headers']['User-Agent'] == 'custom' - r2 = http('--session=test', httpbin('/headers'), env=self.env()) + r2 = http('--session=test', httpbin.url + '/headers', env=self.env()) assert HTTP_OK in r2 assert r2.json['headers']['User-Agent'] == 'custom' diff --git a/tests/test_stream.py b/tests/test_stream.py index d21e98ef..9e967519 100644 --- a/tests/test_stream.py +++ b/tests/test_stream.py @@ -2,7 +2,7 @@ import pytest from httpie.compat import is_windows from httpie.output.streams import BINARY_SUPPRESSED_NOTICE -from utils import http, httpbin, TestEnvironment +from utils import http, TestEnvironment from fixtures import BIN_FILE_CONTENT, BIN_FILE_PATH @@ -11,26 +11,26 @@ class TestStream: @pytest.mark.skipif(is_windows, reason='Pretty redirect not supported under Windows') - def test_pretty_redirected_stream(self): + def test_pretty_redirected_stream(self, httpbin): """Test that --stream works with prettified redirected output.""" with open(BIN_FILE_PATH, 'rb') as f: env = TestEnvironment(colors=256, stdin=f, stdin_isatty=False, stdout_isatty=False) r = http('--verbose', '--pretty=all', '--stream', 'GET', - httpbin('/get'), env=env) + httpbin.url + '/get', env=env) assert BINARY_SUPPRESSED_NOTICE.decode() in r - def test_encoded_stream(self): + def test_encoded_stream(self, httpbin): """Test that --stream works with non-prettified redirected terminal output.""" with open(BIN_FILE_PATH, 'rb') as f: env = TestEnvironment(stdin=f, stdin_isatty=False) r = http('--pretty=none', '--stream', '--verbose', 'GET', - httpbin('/get'), env=env) + httpbin.url + '/get', env=env) assert BINARY_SUPPRESSED_NOTICE.decode() in r - def test_redirected_stream(self): + def test_redirected_stream(self, httpbin): """Test that --stream works with non-prettified redirected terminal output.""" with open(BIN_FILE_PATH, 'rb') as f: @@ -38,5 +38,5 @@ class TestStream: stdin_isatty=False, stdin=f) r = http('--pretty=none', '--stream', '--verbose', 'GET', - httpbin('/get'), env=env) + httpbin.url + '/get', env=env) assert BIN_FILE_CONTENT in r diff --git a/tests/test_unicode.py b/tests/test_unicode.py index 0932c9d4..abcd9ebd 100644 --- a/tests/test_unicode.py +++ b/tests/test_unicode.py @@ -3,85 +3,85 @@ Various unicode handling related tests. """ -from utils import http, httpbin, HTTP_OK +from utils import http, HTTP_OK from fixtures import UNICODE class TestUnicode: - def test_unicode_headers(self): + def test_unicode_headers(self, httpbin): # httpbin doesn't interpret utf8 headers - r = http(httpbin('/headers'), u'Test:%s' % UNICODE) + r = http(httpbin.url + '/headers', u'Test:%s' % UNICODE) assert HTTP_OK in r - def test_unicode_headers_verbose(self): + def test_unicode_headers_verbose(self, httpbin): # httpbin doesn't interpret utf8 headers - r = http('--verbose', httpbin('/headers'), u'Test:%s' % UNICODE) + r = http('--verbose', httpbin.url + '/headers', u'Test:%s' % UNICODE) assert HTTP_OK in r assert UNICODE in r - def test_unicode_form_item(self): - r = http('--form', 'POST', httpbin('/post'), u'test=%s' % UNICODE) + def test_unicode_form_item(self, httpbin): + r = http('--form', 'POST', httpbin.url + '/post', u'test=%s' % UNICODE) assert HTTP_OK in r assert r.json['form'] == {'test': UNICODE} - def test_unicode_form_item_verbose(self): + def test_unicode_form_item_verbose(self, httpbin): r = http('--verbose', '--form', - 'POST', httpbin('/post'), u'test=%s' % UNICODE) + 'POST', httpbin.url + '/post', u'test=%s' % UNICODE) assert HTTP_OK in r assert UNICODE in r - def test_unicode_json_item(self): - r = http('--json', 'POST', httpbin('/post'), u'test=%s' % UNICODE) + def test_unicode_json_item(self, httpbin): + r = http('--json', 'POST', httpbin.url + '/post', u'test=%s' % UNICODE) assert HTTP_OK in r assert r.json['json'] == {'test': UNICODE} - def test_unicode_json_item_verbose(self): + def test_unicode_json_item_verbose(self, httpbin): r = http('--verbose', '--json', - 'POST', httpbin('/post'), u'test=%s' % UNICODE) + 'POST', httpbin.url + '/post', u'test=%s' % UNICODE) assert HTTP_OK in r assert UNICODE in r - def test_unicode_raw_json_item(self): - r = http('--json', 'POST', httpbin('/post'), + def test_unicode_raw_json_item(self, httpbin): + r = http('--json', 'POST', httpbin.url + '/post', u'test:={ "%s" : [ "%s" ] }' % (UNICODE, UNICODE)) assert HTTP_OK in r assert r.json['json'] == {'test': {UNICODE: [UNICODE]}} - def test_unicode_raw_json_item_verbose(self): - r = http('--json', 'POST', httpbin('/post'), + def test_unicode_raw_json_item_verbose(self, httpbin): + r = http('--json', 'POST', httpbin.url + '/post', u'test:={ "%s" : [ "%s" ] }' % (UNICODE, UNICODE)) assert HTTP_OK in r assert r.json['json'] == {'test': {UNICODE: [UNICODE]}} - def test_unicode_url_query_arg_item(self): - r = http(httpbin('/get'), u'test==%s' % UNICODE) + def test_unicode_url_query_arg_item(self, httpbin): + r = http(httpbin.url + '/get', u'test==%s' % UNICODE) assert HTTP_OK in r assert r.json['args'] == {'test': UNICODE}, r - def test_unicode_url_query_arg_item_verbose(self): - r = http('--verbose', httpbin('/get'), u'test==%s' % UNICODE) + def test_unicode_url_query_arg_item_verbose(self, httpbin): + r = http('--verbose', httpbin.url + '/get', u'test==%s' % UNICODE) assert HTTP_OK in r assert UNICODE in r - def test_unicode_url(self): - r = http(httpbin(u'/get?test=' + UNICODE)) + def test_unicode_url(self, httpbin): + r = http(httpbin.url + u'/get?test=' + UNICODE) assert HTTP_OK in r assert r.json['args'] == {'test': UNICODE} # def test_unicode_url_verbose(self): - # r = http(httpbin('--verbose', u'/get?test=' + UNICODE)) + # r = http(httpbin.url + '--verbose', u'/get?test=' + UNICODE) # assert HTTP_OK in r - def test_unicode_basic_auth(self): + def test_unicode_basic_auth(self, httpbin): # it doesn't really authenticate us because httpbin # doesn't interpret the utf8-encoded auth http('--verbose', '--auth', u'test:%s' % UNICODE, - httpbin(u'/basic-auth/test/' + UNICODE)) + httpbin.url + u'/basic-auth/test/' + UNICODE) - def test_unicode_digest_auth(self): + def test_unicode_digest_auth(self, httpbin): # it doesn't really authenticate us because httpbin # doesn't interpret the utf8-encoded auth http('--auth-type=digest', '--auth', u'test:%s' % UNICODE, - httpbin(u'/digest-auth/auth/test/' + UNICODE)) + httpbin.url + u'/digest-auth/auth/test/' + UNICODE) diff --git a/tests/test_uploads.py b/tests/test_uploads.py index 073b98c9..f725c62d 100644 --- a/tests/test_uploads.py +++ b/tests/test_uploads.py @@ -3,23 +3,25 @@ import os import pytest from httpie.input import ParseError -from utils import TestEnvironment, http, httpbin, HTTP_OK +from utils import TestEnvironment, http, HTTP_OK from fixtures import FILE_PATH_ARG, FILE_PATH, FILE_CONTENT class TestMultipartFormDataFileUpload: - def test_non_existent_file_raises_parse_error(self): - with pytest.raises(ParseError): - http('--form', 'POST', httpbin('/post'), 'foo@/__does_not_exist__') - def test_upload_ok(self): - r = http('--form', '--verbose', 'POST', httpbin('/post'), + def test_non_existent_file_raises_parse_error(self, httpbin): + with pytest.raises(ParseError): + http('--form', + 'POST', httpbin.url + '/post', 'foo@/__does_not_exist__') + + def test_upload_ok(self, httpbin): + r = http('--form', '--verbose', 'POST', httpbin.url + '/post', 'test-file@%s' % FILE_PATH_ARG, 'foo=bar') assert HTTP_OK in r assert 'Content-Disposition: form-data; name="foo"' in r assert 'Content-Disposition: form-data; name="test-file";' \ ' filename="%s"' % os.path.basename(FILE_PATH) in r - assert r.count(FILE_CONTENT) == 2 + assert FILE_CONTENT in r assert '"foo": "bar"' in r @@ -29,27 +31,32 @@ class TestRequestBodyFromFilePath: """ - def test_request_body_from_file_by_path(self): - r = http('--verbose', 'POST', httpbin('/post'), '@' + FILE_PATH_ARG) + def test_request_body_from_file_by_path(self, httpbin): + r = http('--verbose', + 'POST', httpbin.url + '/post', '@' + FILE_PATH_ARG) assert HTTP_OK in r assert FILE_CONTENT in r, r assert '"Content-Type": "text/plain"' in r - def test_request_body_from_file_by_path_with_explicit_content_type(self): - r = http('POST', httpbin('/post'), '@' + FILE_PATH_ARG, - 'Content-Type:x-foo/bar') + def test_request_body_from_file_by_path_with_explicit_content_type( + self, httpbin): + r = http('--verbose', + 'POST', httpbin.url + '/post', '@' + FILE_PATH_ARG, + 'Content-Type:text/plain; charset=utf8') assert HTTP_OK in r assert FILE_CONTENT in r - assert '"Content-Type": "x-foo/bar"' in r + assert 'Content-Type: text/plain; charset=utf8' in r - def test_request_body_from_file_by_path_no_field_name_allowed(self): + def test_request_body_from_file_by_path_no_field_name_allowed( + self, httpbin): env = TestEnvironment(stdin_isatty=True) - r = http('POST', httpbin('/post'), 'field-name@' + FILE_PATH_ARG, + r = http('POST', httpbin.url + '/post', 'field-name@' + FILE_PATH_ARG, env=env, error_exit_ok=True) assert 'perhaps you meant --form?' in r.stderr - def test_request_body_from_file_by_path_no_data_items_allowed(self): + def test_request_body_from_file_by_path_no_data_items_allowed( + self, httpbin): env = TestEnvironment(stdin_isatty=False) - r = http('POST', httpbin('/post'), '@' + FILE_PATH_ARG, 'foo=bar', + r = http('POST', httpbin.url + '/post', '@' + FILE_PATH_ARG, 'foo=bar', env=env, error_exit_ok=True) assert 'cannot be mixed' in r.stderr diff --git a/tests/test_windows.py b/tests/test_windows.py index ad15fe52..91669f5c 100644 --- a/tests/test_windows.py +++ b/tests/test_windows.py @@ -4,7 +4,7 @@ import tempfile import pytest from httpie.context import Environment -from utils import TestEnvironment, http, httpbin +from utils import TestEnvironment, http from httpie.compat import is_windows @@ -13,17 +13,17 @@ class TestWindowsOnly: @pytest.mark.skipif(True, reason='this test for some reason kills the process') - def test_windows_colorized_output(self): + def test_windows_colorized_output(self, httpbin): # Spits out the colorized output. - http(httpbin('/get'), env=Environment()) + http(httpbin.url + '/get', env=Environment()) class TestFakeWindows: - def test_output_file_pretty_not_allowed_on_windows(self): + def test_output_file_pretty_not_allowed_on_windows(self, httpbin): env = TestEnvironment(is_windows=True) output_file = os.path.join( tempfile.gettempdir(), '__httpie_test_output__') r = http('--output', output_file, - '--pretty=all', 'GET', httpbin('/get'), + '--pretty=all', 'GET', httpbin.url + '/get', env=env, error_exit_ok=True) assert 'Only terminal output can be colorized on Windows' in r.stderr diff --git a/tests/utils.py b/tests/utils.py index 1a9e5eb6..aad27395 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -20,7 +20,7 @@ TESTS_ROOT = os.path.abspath(os.path.dirname(__file__)) CRLF = '\r\n' COLOR = '\x1b[' -HTTP_OK = 'HTTP/1.1 200' +HTTP_OK = '200 OK' HTTP_OK_COLOR = ( 'HTTP\x1b[39m\x1b[38;5;245m/\x1b[39m\x1b' '[38;5;37m1.1\x1b[39m\x1b[38;5;245m \x1b[39m\x1b[38;5;37m200' @@ -28,22 +28,19 @@ HTTP_OK_COLOR = ( ) -def httpbin(path, auth=None, - base=os.environ.get('HTTPBIN_URL', 'http://httpbin.org')): - """ - Return a fully-qualified httpbin URL for `path`. +def no_content_type(headers): + return ( + 'Content-Type' not in headers + # We need to do also this because of this issue: + # + # TODO: remove this function once the issue is if fixed + or headers['Content-Type'] == 'text/plain' + ) - >>> httpbin('/get') - 'http://httpbin.org/get' - >>> httpbin('/get', auth='user:password') - 'http://user:password@httpbin.org/get' - - """ - if auth: - proto, rest = base.split('://', 1) - base = proto + '://' + auth + '@' + rest - return base.rstrip('/') + path +def add_auth(url, auth): + proto, rest = url.split('://', 1) + return proto + '://' + auth + '@' + rest class TestEnvironment(Environment): @@ -104,7 +101,7 @@ def http(*args, **kwargs): $ http --auth=user:password GET httpbin.org/basic-auth/user/password - >>> r = http('-a', 'user:pw', httpbin('/basic-auth/user/pw')) + >>> r = http('-a', 'user:pw', 'httpbin.org/basic-auth/user/pw') >>> type(r) == StrCLIResponse True >>> r.exit_status diff --git a/tox.ini b/tox.ini index 3e37c178..d140537a 100644 --- a/tox.ini +++ b/tox.ini @@ -13,6 +13,7 @@ envlist = py26, py27, py34, pypy deps = pytest pytest-xdist + pytest-httpbin commands = py.test -n 8 --doctest-modules --basetemp={envtmpdir} {posargs:./tests ./httpie}