You've already forked httpie-cli
							
							
				mirror of
				https://github.com/httpie/cli.git
				synced 2025-10-30 23:47:52 +02:00 
			
		
		
		
	Refactored tests into smaller modules.
This commit is contained in:
		| @@ -1379,8 +1379,6 @@ Changelog | ||||
| .. _Tox: http://tox.testrun.org | ||||
| .. _Github API: http://developer.github.com/v3/issues/comments/#create-a-comment | ||||
| .. _supported Python environments: https://github.com/jkbr/httpie/blob/master/tox.ini | ||||
| .. _Ubuntu: http://packages.ubuntu.com/httpie | ||||
| .. _Debian: http://packages.debian.org/httpie | ||||
| .. _the repository: https://github.com/jkbr/httpie | ||||
| .. _these fine people: https://github.com/jkbr/httpie/contributors | ||||
| .. _Jakub Roztocil: http://subtleapps.com | ||||
|   | ||||
| @@ -17,3 +17,10 @@ try: | ||||
| except ImportError: | ||||
|     #noinspection PyUnresolvedReferences,PyCompatibility | ||||
|     from urlparse import urlsplit | ||||
|  | ||||
| try: | ||||
|     #noinspection PyCompatibility | ||||
|     from urllib.request import urlopen | ||||
| except ImportError: | ||||
|     #noinspection PyCompatibility | ||||
|     from urllib2 import urlopen | ||||
|   | ||||
| @@ -155,7 +155,6 @@ class Download(object): | ||||
|  | ||||
|         :param output_file: The file to store response body in. If not | ||||
|                             provided, it will be guessed from the response. | ||||
|         :type output_file: file | ||||
|  | ||||
|         :param progress_file: Where to report download progress. | ||||
|         :type progress_file: file | ||||
|   | ||||
							
								
								
									
										210
									
								
								tests/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								tests/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | ||||
| import os | ||||
| import sys | ||||
| import time | ||||
| import json | ||||
| import shutil | ||||
| import tempfile | ||||
| import unittest | ||||
| try: | ||||
|     from unittest import skipIf, skip | ||||
| except ImportError: | ||||
|     skip = lambda msg: lambda self: None | ||||
|  | ||||
|     # noinspection PyUnusedLocal | ||||
|     def skipIf(cond, reason): | ||||
|         def decorator(test_method): | ||||
|             if cond: | ||||
|                 return lambda self: None | ||||
|             return test_method | ||||
|         return decorator | ||||
|  | ||||
| from requests.structures import CaseInsensitiveDict | ||||
|  | ||||
| TESTS_ROOT = os.path.abspath(os.path.dirname(__file__)) | ||||
| # HACK: Prepend ../ to PYTHONPATH so that we can import httpie form there. | ||||
| sys.path.insert(0, os.path.realpath(os.path.join(TESTS_ROOT, '..'))) | ||||
| from httpie import ExitStatus | ||||
| from httpie.models import Environment | ||||
| from httpie.core import main | ||||
| from httpie.compat import is_py26, bytes, str | ||||
|  | ||||
|  | ||||
| def patharg(path): | ||||
|     """Back slashes need to be escaped in ITEM args, even in Windows paths.""" | ||||
|     return path.replace('\\', '\\\\\\') | ||||
|  | ||||
|  | ||||
| HTTPBIN_URL = os.environ.get('HTTPBIN_URL', | ||||
|                              'http://httpbin.org').rstrip('/') | ||||
|  | ||||
|  | ||||
| CRLF = '\r\n' | ||||
| OK = 'HTTP/1.1 200' | ||||
| 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' | ||||
|     '\x1b[39m\x1b[38;5;245m \x1b[39m\x1b[38;5;136mOK' | ||||
| ) | ||||
| COLOR = '\x1b[' | ||||
|  | ||||
| ### Test files | ||||
| FILE_PATH = os.path.join(TESTS_ROOT, 'fixtures', 'file.txt') | ||||
| FILE2_PATH = os.path.join(TESTS_ROOT, 'fixtures', 'file2.txt') | ||||
| BIN_FILE_PATH = os.path.join(TESTS_ROOT, 'fixtures', 'file.bin') | ||||
| JSON_FILE_PATH = os.path.join(TESTS_ROOT, 'fixtures', 'test.json') | ||||
|  | ||||
| FILE_PATH_ARG = patharg(FILE_PATH) | ||||
| FILE2_PATH_ARG = patharg(FILE2_PATH) | ||||
| BIN_FILE_PATH_ARG = patharg(BIN_FILE_PATH) | ||||
| JSON_FILE_PATH_ARG = patharg(JSON_FILE_PATH) | ||||
|  | ||||
| with open(FILE_PATH) as f: | ||||
|     # Strip because we don't want new lines in the data so that we can | ||||
|     # easily count occurrences also when embedded in JSON (where the new | ||||
|     # line would be escaped). | ||||
|     FILE_CONTENT = f.read().strip() | ||||
| with open(BIN_FILE_PATH, 'rb') as f: | ||||
|     BIN_FILE_CONTENT = f.read() | ||||
| with open(JSON_FILE_PATH, 'rb') as f: | ||||
|     JSON_FILE_CONTENT = f.read() | ||||
|  | ||||
|  | ||||
| def httpbin(path): | ||||
|     url = HTTPBIN_URL + path | ||||
|     return url | ||||
|  | ||||
|  | ||||
| def mk_config_dir(): | ||||
|     return tempfile.mkdtemp(prefix='httpie_test_config_dir_') | ||||
|  | ||||
|  | ||||
| class Response(object): | ||||
|  | ||||
|     # noinspection PyDefaultArgument | ||||
|     def __init__(self, url, headers={}, status_code=200): | ||||
|         self.url = url | ||||
|         self.headers = CaseInsensitiveDict(headers) | ||||
|         self.status_code = status_code | ||||
|  | ||||
|  | ||||
| class TestEnvironment(Environment): | ||||
|     colors = 0 | ||||
|     stdin_isatty = True, | ||||
|     stdout_isatty = True | ||||
|     is_windows = False | ||||
|     _shutil = shutil  # we need it in __del__ (would get gc'd) | ||||
|  | ||||
|     def __init__(self, **kwargs): | ||||
|  | ||||
|         if 'stdout' not in kwargs: | ||||
|             kwargs['stdout'] = tempfile.TemporaryFile('w+b') | ||||
|  | ||||
|         if 'stderr' not in kwargs: | ||||
|             kwargs['stderr'] = tempfile.TemporaryFile('w+t') | ||||
|  | ||||
|         self.delete_config_dir = False | ||||
|         if 'config_dir' not in kwargs: | ||||
|             kwargs['config_dir'] = mk_config_dir() | ||||
|             self.delete_config_dir = True | ||||
|  | ||||
|         super(TestEnvironment, self).__init__(**kwargs) | ||||
|  | ||||
|     def __del__(self): | ||||
|         if self.delete_config_dir: | ||||
|             self._shutil.rmtree(self.config_dir) | ||||
|  | ||||
|  | ||||
| class BytesResponse(bytes): | ||||
|     stderr = json = exit_status = None | ||||
|  | ||||
|  | ||||
| class StrResponse(str): | ||||
|     stderr = json = exit_status = None | ||||
|  | ||||
|  | ||||
| def http(*args, **kwargs): | ||||
|     """ | ||||
|     Invoke `httpie.core.main()` with `args` and `kwargs`, | ||||
|     and return a unicode response. | ||||
|  | ||||
|     Return a `StrResponse`, or `BytesResponse` if unable to decode the output. | ||||
|     The response has the following attributes: | ||||
|  | ||||
|         `stderr`: text written to stderr | ||||
|         `exit_status`: the exit status | ||||
|         `json`: decoded JSON (if possible) or `None` | ||||
|  | ||||
|     Exceptions are propagated except for SystemExit. | ||||
|  | ||||
|     """ | ||||
|     env = kwargs.get('env') | ||||
|     if not env: | ||||
|         env = kwargs['env'] = TestEnvironment() | ||||
|  | ||||
|     stdout = env.stdout | ||||
|     stderr = env.stderr | ||||
|     try: | ||||
|  | ||||
|         try: | ||||
|             exit_status = main(args=['--traceback'] + list(args), **kwargs) | ||||
|             if '--download' in args: | ||||
|                 # Let the progress reporter thread finish. | ||||
|                 time.sleep(.5) | ||||
|         except Exception: | ||||
|             sys.stderr.write(stderr.read()) | ||||
|             raise | ||||
|         except SystemExit: | ||||
|             exit_status = ExitStatus.ERROR | ||||
|  | ||||
|         stdout.seek(0) | ||||
|         stderr.seek(0) | ||||
|  | ||||
|         output = stdout.read() | ||||
|         try: | ||||
|             r = StrResponse(output.decode('utf8')) | ||||
|         except UnicodeDecodeError: | ||||
|             r = BytesResponse(output) | ||||
|         else: | ||||
|             if COLOR not in r: | ||||
|                 # De-serialize JSON body if possible. | ||||
|                 if r.strip().startswith('{'): | ||||
|                     #noinspection PyTypeChecker | ||||
|                     r.json = json.loads(r) | ||||
|                 elif r.count('Content-Type:') == 1 and 'application/json' in r: | ||||
|                     try: | ||||
|                         j = r.strip()[r.strip().rindex('\r\n\r\n'):] | ||||
|                     except ValueError: | ||||
|                         pass | ||||
|                     else: | ||||
|                         try: | ||||
|                             r.json = json.loads(j) | ||||
|                         except ValueError: | ||||
|                             pass | ||||
|  | ||||
|         r.stderr = stderr.read() | ||||
|         r.exit_status = exit_status | ||||
|  | ||||
|         return r | ||||
|  | ||||
|     finally: | ||||
|         stdout.close() | ||||
|         stderr.close() | ||||
|  | ||||
|  | ||||
| class BaseTestCase(unittest.TestCase): | ||||
|  | ||||
|     maxDiff = 100000 | ||||
|  | ||||
|     if is_py26: | ||||
|         def assertIn(self, member, container, msg=None): | ||||
|             self.assertTrue(member in container, msg) | ||||
|  | ||||
|         def assertNotIn(self, member, container, msg=None): | ||||
|             self.assertTrue(member not in container, msg) | ||||
|  | ||||
|         def assertDictEqual(self, d1, d2, msg=None): | ||||
|             self.assertEqual(set(d1.keys()), set(d2.keys()), msg) | ||||
|             self.assertEqual(sorted(d1.values()), sorted(d2.values()), msg) | ||||
|  | ||||
|     def assertIsNone(self, obj, msg=None): | ||||
|         self.assertEqual(obj, None, msg=msg) | ||||
							
								
								
									
										71
									
								
								tests/test_auth.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								tests/test_auth.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| """HTTP authentication-related tests.""" | ||||
| import requests | ||||
|  | ||||
| from tests import BaseTestCase, http, httpbin, OK, skipIf | ||||
| import httpie.input | ||||
|  | ||||
|  | ||||
| class AuthTest(BaseTestCase): | ||||
|  | ||||
|     def test_basic_auth(self): | ||||
|         r = http( | ||||
|             '--auth=user:password', | ||||
|             'GET', | ||||
|             httpbin('/basic-auth/user/password') | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"authenticated": true', r) | ||||
|         self.assertIn('"user": "user"', r) | ||||
|  | ||||
|     @skipIf(requests.__version__ == '0.13.6', | ||||
|             'Redirects with prefetch=False are broken in Requests 0.13.6') | ||||
|     def test_digest_auth(self): | ||||
|         r = http( | ||||
|             '--auth-type=digest', | ||||
|             '--auth=user:password', | ||||
|             'GET', | ||||
|             httpbin('/digest-auth/auth/user/password') | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn(r'"authenticated": true', r) | ||||
|         self.assertIn(r'"user": "user"', r) | ||||
|  | ||||
|     def test_password_prompt(self): | ||||
|  | ||||
|         httpie.input.AuthCredentials._getpass = lambda self, prompt: 'password' | ||||
|  | ||||
|         r = http( | ||||
|             '--auth', | ||||
|             'user', | ||||
|             'GET', | ||||
|             httpbin('/basic-auth/user/password') | ||||
|         ) | ||||
|  | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"authenticated": true', r) | ||||
|         self.assertIn('"user": "user"', r) | ||||
|  | ||||
|     def test_credentials_in_url(self): | ||||
|         url = httpbin('/basic-auth/user/password') | ||||
|         url = 'http://user:password@' + url.split('http://', 1)[1] | ||||
|         r = http( | ||||
|             'GET', | ||||
|             url | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"authenticated": true', r) | ||||
|         self.assertIn('"user": "user"', r) | ||||
|  | ||||
|     def test_credentials_in_url_auth_flag_has_priority(self): | ||||
|         """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') | ||||
|         url = 'http://user:wrong_password@' + url.split('http://', 1)[1] | ||||
|         r = http( | ||||
|             '--auth=user:password', | ||||
|             'GET', | ||||
|             url | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"authenticated": true', r) | ||||
|         self.assertIn('"user": "user"', r) | ||||
							
								
								
									
										93
									
								
								tests/test_binary.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								tests/test_binary.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | ||||
| """Tests for dealing with binary request and response data.""" | ||||
| from httpie.compat import urlopen | ||||
| from httpie.output import BINARY_SUPPRESSED_NOTICE | ||||
| from tests import ( | ||||
|     BaseTestCase, TestEnvironment, http, httpbin, | ||||
|     BIN_FILE_PATH, BIN_FILE_CONTENT, BIN_FILE_PATH_ARG, | ||||
|  | ||||
| ) | ||||
|  | ||||
|  | ||||
| class BinaryRequestDataTest(BaseTestCase): | ||||
|  | ||||
|     def test_binary_stdin(self): | ||||
|         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, | ||||
|             ) | ||||
|             self.assertEqual(r, BIN_FILE_CONTENT) | ||||
|  | ||||
|     def test_binary_file_path(self): | ||||
|         env = TestEnvironment( | ||||
|             stdin_isatty=True, | ||||
|             stdout_isatty=False | ||||
|         ) | ||||
|         r = http( | ||||
|             '--print=B', | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             '@' + BIN_FILE_PATH_ARG, | ||||
|             env=env, | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual(r, BIN_FILE_CONTENT) | ||||
|  | ||||
|     def test_binary_file_form(self): | ||||
|         env = TestEnvironment( | ||||
|             stdin_isatty=True, | ||||
|             stdout_isatty=False | ||||
|         ) | ||||
|         r = http( | ||||
|             '--print=B', | ||||
|             '--form', | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             'test@' + BIN_FILE_PATH_ARG, | ||||
|             env=env, | ||||
|         ) | ||||
|         self.assertIn(bytes(BIN_FILE_CONTENT), bytes(r)) | ||||
|  | ||||
|  | ||||
| class BinaryResponseDataTest(BaseTestCase): | ||||
|  | ||||
|     url = 'http://www.google.com/favicon.ico' | ||||
|  | ||||
|     @property | ||||
|     def bindata(self): | ||||
|         if not hasattr(self, '_bindata'): | ||||
|             self._bindata = urlopen(self.url).read() | ||||
|         return self._bindata | ||||
|  | ||||
|     def test_binary_suppresses_when_terminal(self): | ||||
|         r = http( | ||||
|             'GET', | ||||
|             self.url | ||||
|         ) | ||||
|         self.assertIn(BINARY_SUPPRESSED_NOTICE.decode(), r) | ||||
|  | ||||
|     def test_binary_suppresses_when_not_terminal_but_pretty(self): | ||||
|         r = http( | ||||
|             '--pretty=all', | ||||
|             'GET', | ||||
|             self.url, | ||||
|             env=TestEnvironment(stdin_isatty=True, | ||||
|                             stdout_isatty=False) | ||||
|         ) | ||||
|         self.assertIn(BINARY_SUPPRESSED_NOTICE.decode(), r) | ||||
|  | ||||
|     def test_binary_included_and_correct_when_suitable(self): | ||||
|         r = http( | ||||
|             'GET', | ||||
|             self.url, | ||||
|             env=TestEnvironment(stdin_isatty=True, | ||||
|                             stdout_isatty=False) | ||||
|         ) | ||||
|         self.assertEqual(r, self.bindata) | ||||
							
								
								
									
										347
									
								
								tests/test_cli.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										347
									
								
								tests/test_cli.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,347 @@ | ||||
| """CLI argument parsing related tests.""" | ||||
| import json | ||||
|  | ||||
| # noinspection PyCompatibility | ||||
| import argparse | ||||
|  | ||||
| from tests import ( | ||||
|     BaseTestCase, TestEnvironment, http, httpbin, | ||||
|     FILE_PATH_ARG, JSON_FILE_PATH_ARG, | ||||
|     JSON_FILE_CONTENT, FILE_CONTENT, OK, FILE_PATH | ||||
| ) | ||||
| from httpie import input | ||||
| from httpie import ExitStatus | ||||
| from httpie.cli import parser | ||||
|  | ||||
|  | ||||
| class ItemParsingTest(BaseTestCase): | ||||
|  | ||||
|     def setUp(self): | ||||
|         self.key_value_type = input.KeyValueArgType( | ||||
|             *input.SEP_GROUP_ALL_ITEMS | ||||
|         ) | ||||
|  | ||||
|     def test_invalid_items(self): | ||||
|         items = ['no-separator'] | ||||
|         for item in items: | ||||
|             self.assertRaises(argparse.ArgumentTypeError, | ||||
|                               lambda: self.key_value_type(item)) | ||||
|  | ||||
|     def test_escape(self): | ||||
|         headers, data, files, params = input.parse_items([ | ||||
|             # headers | ||||
|             self.key_value_type('foo\\:bar:baz'), | ||||
|             self.key_value_type('jack\\@jill:hill'), | ||||
|             # data | ||||
|             self.key_value_type('baz\\=bar=foo'), | ||||
|             # files | ||||
|             self.key_value_type('bar\\@baz@%s' % FILE_PATH_ARG) | ||||
|         ]) | ||||
|         # `requests.structures.CaseInsensitiveDict` => `dict` | ||||
|         headers = dict(headers._store.values()) | ||||
|         self.assertDictEqual(headers, { | ||||
|             'foo:bar': 'baz', | ||||
|             'jack@jill': 'hill', | ||||
|         }) | ||||
|         self.assertDictEqual(data, { | ||||
|             'baz=bar': 'foo', | ||||
|         }) | ||||
|         self.assertIn('bar@baz', files) | ||||
|  | ||||
|     def test_escape_longsep(self): | ||||
|         headers, data, files, params = input.parse_items([ | ||||
|             self.key_value_type('bob\\:==foo'), | ||||
|         ]) | ||||
|         self.assertDictEqual(params, { | ||||
|             'bob:': 'foo', | ||||
|         }) | ||||
|  | ||||
|     def test_valid_items(self): | ||||
|         headers, data, files, params = input.parse_items([ | ||||
|             self.key_value_type('string=value'), | ||||
|             self.key_value_type('header:value'), | ||||
|             self.key_value_type('list:=["a", 1, {}, false]'), | ||||
|             self.key_value_type('obj:={"a": "b"}'), | ||||
|             self.key_value_type('eh:'), | ||||
|             self.key_value_type('ed='), | ||||
|             self.key_value_type('bool:=true'), | ||||
|             self.key_value_type('file@' + FILE_PATH_ARG), | ||||
|             self.key_value_type('query==value'), | ||||
|             self.key_value_type('string-embed=@' + FILE_PATH_ARG), | ||||
|             self.key_value_type('raw-json-embed:=@' + JSON_FILE_PATH_ARG), | ||||
|         ]) | ||||
|  | ||||
|         # Parsed headers | ||||
|         # `requests.structures.CaseInsensitiveDict` => `dict` | ||||
|         headers = dict(headers._store.values()) | ||||
|         self.assertDictEqual(headers, { | ||||
|             'header': 'value', | ||||
|             'eh': '' | ||||
|         }) | ||||
|  | ||||
|         # Parsed data | ||||
|         raw_json_embed = data.pop('raw-json-embed') | ||||
|         self.assertDictEqual(raw_json_embed, json.loads( | ||||
|             JSON_FILE_CONTENT.decode('utf8'))) | ||||
|         data['string-embed'] = data['string-embed'].strip() | ||||
|         self.assertDictEqual(dict(data), { | ||||
|             "ed": "", | ||||
|             "string": "value", | ||||
|             "bool": True, | ||||
|             "list": ["a", 1, {}, False], | ||||
|             "obj": {"a": "b"}, | ||||
|             "string-embed": FILE_CONTENT, | ||||
|         }) | ||||
|  | ||||
|         # Parsed query string parameters | ||||
|         self.assertDictEqual(params, { | ||||
|             'query': 'value', | ||||
|         }) | ||||
|  | ||||
|         # Parsed file fields | ||||
|         self.assertIn('file', files) | ||||
|         self.assertEqual(files['file'][1].read().strip().decode('utf8'), | ||||
|                          FILE_CONTENT) | ||||
|  | ||||
|  | ||||
| class QuerystringTest(BaseTestCase): | ||||
|  | ||||
|     def test_query_string_params_in_url(self): | ||||
|         r = http( | ||||
|             '--print=Hhb', | ||||
|             'GET', | ||||
|             httpbin('/get?a=1&b=2') | ||||
|         ) | ||||
|  | ||||
|         path = '/get?a=1&b=2' | ||||
|         url = httpbin(path) | ||||
|  | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('GET %s HTTP/1.1' % path, r) | ||||
|         self.assertIn('"url": "%s"' % url, 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) | ||||
|  | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('GET %s HTTP/1.1' % path, r) | ||||
|         self.assertIn('"url": "%s"' % url, 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) | ||||
|  | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('GET %s HTTP/1.1' % path, r) | ||||
|         self.assertIn('"url": "%s"' % url, r) | ||||
|  | ||||
|  | ||||
| class CLIParserTestCase(BaseTestCase): | ||||
|  | ||||
|     def test_expand_localhost_shorthand(self): | ||||
|         args = parser.parse_args(args=[':'], env=TestEnvironment()) | ||||
|  | ||||
|         self.assertEqual(args.url, 'http://localhost') | ||||
|  | ||||
|     def test_expand_localhost_shorthand_with_slash(self): | ||||
|         args = parser.parse_args(args=[':/'], env=TestEnvironment()) | ||||
|  | ||||
|         self.assertEqual(args.url, 'http://localhost/') | ||||
|  | ||||
|     def test_expand_localhost_shorthand_with_port(self): | ||||
|         args = parser.parse_args(args=[':3000'], env=TestEnvironment()) | ||||
|  | ||||
|         self.assertEqual(args.url, 'http://localhost:3000') | ||||
|  | ||||
|     def test_expand_localhost_shorthand_with_path(self): | ||||
|         args = parser.parse_args(args=[':/path'], env=TestEnvironment()) | ||||
|  | ||||
|         self.assertEqual(args.url, 'http://localhost/path') | ||||
|  | ||||
|     def test_expand_localhost_shorthand_with_port_and_slash(self): | ||||
|         args = parser.parse_args(args=[':3000/'], env=TestEnvironment()) | ||||
|  | ||||
|         self.assertEqual(args.url, 'http://localhost:3000/') | ||||
|  | ||||
|     def test_expand_localhost_shorthand_with_port_and_path(self): | ||||
|         args = parser.parse_args(args=[':3000/path'], env=TestEnvironment()) | ||||
|  | ||||
|         self.assertEqual(args.url, 'http://localhost:3000/path') | ||||
|  | ||||
|     def test_dont_expand_shorthand_ipv6_as_shorthand(self): | ||||
|         args = parser.parse_args(args=['::1'], env=TestEnvironment()) | ||||
|  | ||||
|         self.assertEqual(args.url, 'http://::1') | ||||
|  | ||||
|     def test_dont_expand_longer_ipv6_as_shorthand(self): | ||||
|         args = parser.parse_args( | ||||
|             args=['::ffff:c000:0280'], | ||||
|             env=TestEnvironment() | ||||
|         ) | ||||
|         self.assertEqual(args.url, 'http://::ffff:c000:0280') | ||||
|  | ||||
|     def test_dont_expand_full_ipv6_as_shorthand(self): | ||||
|         args = parser.parse_args( | ||||
|             args=['0000:0000:0000:0000:0000:0000:0000:0001'], | ||||
|             env=TestEnvironment() | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual( | ||||
|             args.url, | ||||
|             'http://0000:0000:0000:0000:0000:0000:0000:0001' | ||||
|         ) | ||||
|  | ||||
|  | ||||
| class ArgumentParserTestCase(BaseTestCase): | ||||
|  | ||||
|     def setUp(self): | ||||
|         self.parser = input.Parser() | ||||
|  | ||||
|     def test_guess_when_method_set_and_valid(self): | ||||
|         self.parser.args = argparse.Namespace() | ||||
|         self.parser.args.method = 'GET' | ||||
|         self.parser.args.url = 'http://example.com/' | ||||
|         self.parser.args.items = [] | ||||
|         self.parser.args.ignore_stdin = False | ||||
|  | ||||
|         self.parser.env = TestEnvironment() | ||||
|  | ||||
|         self.parser._guess_method() | ||||
|  | ||||
|         self.assertEqual(self.parser.args.method, 'GET') | ||||
|         self.assertEqual(self.parser.args.url, 'http://example.com/') | ||||
|         self.assertEqual(self.parser.args.items, []) | ||||
|  | ||||
|     def test_guess_when_method_not_set(self): | ||||
|  | ||||
|         self.parser.args = argparse.Namespace() | ||||
|         self.parser.args.method = None | ||||
|         self.parser.args.url = 'http://example.com/' | ||||
|         self.parser.args.items = [] | ||||
|         self.parser.args.ignore_stdin = False | ||||
|         self.parser.env = TestEnvironment() | ||||
|  | ||||
|         self.parser._guess_method() | ||||
|  | ||||
|         self.assertEqual(self.parser.args.method, 'GET') | ||||
|         self.assertEqual(self.parser.args.url, 'http://example.com/') | ||||
|         self.assertEqual(self.parser.args.items, []) | ||||
|  | ||||
|     def test_guess_when_method_set_but_invalid_and_data_field(self): | ||||
|         self.parser.args = argparse.Namespace() | ||||
|         self.parser.args.method = 'http://example.com/' | ||||
|         self.parser.args.url = 'data=field' | ||||
|         self.parser.args.items = [] | ||||
|         self.parser.args.ignore_stdin = False | ||||
|         self.parser.env = TestEnvironment() | ||||
|         self.parser._guess_method() | ||||
|  | ||||
|         self.assertEqual(self.parser.args.method, 'POST') | ||||
|         self.assertEqual(self.parser.args.url, 'http://example.com/') | ||||
|         self.assertEqual( | ||||
|             self.parser.args.items, | ||||
|             [input.KeyValue( | ||||
|                 key='data', value='field', sep='=', orig='data=field')]) | ||||
|  | ||||
|     def test_guess_when_method_set_but_invalid_and_header_field(self): | ||||
|         self.parser.args = argparse.Namespace() | ||||
|         self.parser.args.method = 'http://example.com/' | ||||
|         self.parser.args.url = 'test:header' | ||||
|         self.parser.args.items = [] | ||||
|         self.parser.args.ignore_stdin = False | ||||
|  | ||||
|         self.parser.env = TestEnvironment() | ||||
|  | ||||
|         self.parser._guess_method() | ||||
|  | ||||
|         self.assertEqual(self.parser.args.method, 'GET') | ||||
|         self.assertEqual(self.parser.args.url, 'http://example.com/') | ||||
|         self.assertEqual( | ||||
|             self.parser.args.items, | ||||
|             [input.KeyValue( | ||||
|                 key='test', value='header', sep=':', orig='test:header')]) | ||||
|  | ||||
|     def test_guess_when_method_set_but_invalid_and_item_exists(self): | ||||
|         self.parser.args = argparse.Namespace() | ||||
|         self.parser.args.method = 'http://example.com/' | ||||
|         self.parser.args.url = 'new_item=a' | ||||
|         self.parser.args.items = [ | ||||
|             input.KeyValue( | ||||
|                 key='old_item', value='b', sep='=', orig='old_item=b') | ||||
|         ] | ||||
|         self.parser.args.ignore_stdin = False | ||||
|  | ||||
|         self.parser.env = TestEnvironment() | ||||
|  | ||||
|         self.parser._guess_method() | ||||
|  | ||||
|         self.assertEqual(self.parser.args.items, [ | ||||
|             input.KeyValue( | ||||
|                 key='new_item', value='a', sep='=', orig='new_item=a'), | ||||
|             input.KeyValue( | ||||
|                 key='old_item', value='b', sep='=', orig='old_item=b'), | ||||
|         ]) | ||||
|  | ||||
|  | ||||
| class TestNoOptions(BaseTestCase): | ||||
|  | ||||
|     def test_valid_no_options(self): | ||||
|         r = http( | ||||
|             '--verbose', | ||||
|             '--no-verbose', | ||||
|             'GET', | ||||
|             httpbin('/get') | ||||
|         ) | ||||
|         self.assertNotIn('GET /get HTTP/1.1', r) | ||||
|  | ||||
|     def test_invalid_no_options(self): | ||||
|         r = http( | ||||
|             '--no-war', | ||||
|             'GET', | ||||
|             httpbin('/get') | ||||
|         ) | ||||
|         self.assertEqual(r.exit_status, 1) | ||||
|         self.assertIn('unrecognized arguments: --no-war', r.stderr) | ||||
|         self.assertNotIn('GET /get HTTP/1.1', r) | ||||
|  | ||||
|  | ||||
| class IgnoreStdinTest(BaseTestCase): | ||||
|  | ||||
|     def test_ignore_stdin(self): | ||||
|         with open(FILE_PATH) as f: | ||||
|             r = http( | ||||
|                 '--ignore-stdin', | ||||
|                 '--verbose', | ||||
|                 httpbin('/get'), | ||||
|                 env=TestEnvironment(stdin=f, stdin_isatty=False) | ||||
|             ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('GET /get HTTP', r)  # Don't default to POST. | ||||
|         self.assertNotIn(FILE_CONTENT, r)  # Don't send stdin data. | ||||
|  | ||||
|     def test_ignore_stdin_cannot_prompt_password(self): | ||||
|         r = http( | ||||
|             '--ignore-stdin', | ||||
|             '--auth=username-without-password', | ||||
|             httpbin('/get'), | ||||
|         ) | ||||
|         self.assertEqual(r.exit_status, ExitStatus.ERROR) | ||||
|         self.assertIn('because --ignore-stdin', r.stderr) | ||||
							
								
								
									
										175
									
								
								tests/test_defaults.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								tests/test_defaults.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | ||||
| """ | ||||
| Tests for the provided defaults regarding HTTP method, and --json vs. --form. | ||||
|  | ||||
| """ | ||||
| from tests import ( | ||||
|     BaseTestCase, TestEnvironment, | ||||
|     http, httpbin, | ||||
|     OK, FILE_PATH, | ||||
| ) | ||||
|  | ||||
|  | ||||
| class ImplicitHTTPMethodTest(BaseTestCase): | ||||
|  | ||||
|     def test_implicit_GET(self): | ||||
|         r = http(httpbin('/get')) | ||||
|         self.assertIn(OK, r) | ||||
|  | ||||
|     def test_implicit_GET_with_headers(self): | ||||
|         r = http( | ||||
|             httpbin('/headers'), | ||||
|             'Foo:bar' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"Foo": "bar"', r) | ||||
|  | ||||
|     def test_implicit_POST_json(self): | ||||
|         r = http( | ||||
|             httpbin('/post'), | ||||
|             'hello=world' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn(r'\"hello\": \"world\"', r) | ||||
|  | ||||
|     def test_implicit_POST_form(self): | ||||
|         r = http( | ||||
|             '--form', | ||||
|             httpbin('/post'), | ||||
|             'foo=bar' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"foo": "bar"', r) | ||||
|  | ||||
|     def test_implicit_POST_stdin(self): | ||||
|         with open(FILE_PATH) as f: | ||||
|             env = TestEnvironment( | ||||
|                 stdin_isatty=False, | ||||
|                 stdin=f, | ||||
|             ) | ||||
|             r = http( | ||||
|                 '--form', | ||||
|                 httpbin('/post'), | ||||
|                 env=env | ||||
|             ) | ||||
|         self.assertIn(OK, r) | ||||
|  | ||||
|  | ||||
| class AutoContentTypeAndAcceptHeadersTest(BaseTestCase): | ||||
|     """ | ||||
|     Test that Accept and Content-Type correctly defaults to JSON, | ||||
|     but can still be overridden. The same with Content-Type when --form | ||||
|     -f is used. | ||||
|  | ||||
|     """ | ||||
|     def test_GET_no_data_no_auto_headers(self): | ||||
|         # https://github.com/jkbr/httpie/issues/62 | ||||
|         r = http( | ||||
|             'GET', | ||||
|             httpbin('/headers') | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"Accept": "*/*"', r) | ||||
|         self.assertNotIn('"Content-Type": "application/json', r) | ||||
|  | ||||
|     def test_POST_no_data_no_auto_headers(self): | ||||
|         # JSON headers shouldn't be automatically set for POST with no data. | ||||
|         r = http( | ||||
|             'POST', | ||||
|             httpbin('/post') | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"Accept": "*/*"', r) | ||||
|         self.assertNotIn('"Content-Type": "application/json', r) | ||||
|  | ||||
|     def test_POST_with_data_auto_JSON_headers(self): | ||||
|         r = http( | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             'a=b' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"Accept": "application/json"', r) | ||||
|         self.assertIn('"Content-Type": "application/json; charset=utf-8', r) | ||||
|  | ||||
|     def test_GET_with_data_auto_JSON_headers(self): | ||||
|         # JSON headers should automatically be set also for GET with data. | ||||
|         r = http( | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             'a=b' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"Accept": "application/json"', r) | ||||
|         self.assertIn('"Content-Type": "application/json; charset=utf-8', r) | ||||
|  | ||||
|     def test_POST_explicit_JSON_auto_JSON_accept(self): | ||||
|         r = http( | ||||
|             '--json', | ||||
|             'POST', | ||||
|             httpbin('/post') | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertEqual(r.json['headers']['Accept'], 'application/json') | ||||
|         # Make sure Content-Type gets set even with no data. | ||||
|         # https://github.com/jkbr/httpie/issues/137 | ||||
|         self.assertIn('application/json', r.json['headers']['Content-Type']) | ||||
|  | ||||
|     def test_GET_explicit_JSON_explicit_headers(self): | ||||
|         r = http( | ||||
|             '--json', | ||||
|             'GET', | ||||
|             httpbin('/headers'), | ||||
|             'Accept:application/xml', | ||||
|             'Content-Type:application/xml' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"Accept": "application/xml"', r) | ||||
|         self.assertIn('"Content-Type": "application/xml"', r) | ||||
|  | ||||
|     def test_POST_form_auto_Content_Type(self): | ||||
|         r = http( | ||||
|             '--form', | ||||
|             'POST', | ||||
|             httpbin('/post') | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn( | ||||
|             '"Content-Type":' | ||||
|             ' "application/x-www-form-urlencoded; charset=utf-8"', | ||||
|             r | ||||
|         ) | ||||
|  | ||||
|     def test_POST_form_Content_Type_override(self): | ||||
|         r = http( | ||||
|             '--form', | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             'Content-Type:application/xml' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"Content-Type": "application/xml"', r) | ||||
|  | ||||
|     def test_print_only_body_when_stdout_redirected_by_default(self): | ||||
|  | ||||
|         r = http( | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             env=TestEnvironment( | ||||
|                 stdin_isatty=True, | ||||
|                 stdout_isatty=False | ||||
|             ) | ||||
|         ) | ||||
|         self.assertNotIn('HTTP/', r) | ||||
|  | ||||
|     def test_print_overridable_when_stdout_redirected(self): | ||||
|  | ||||
|         r = http( | ||||
|             '--print=h', | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             env=TestEnvironment( | ||||
|                 stdin_isatty=True, | ||||
|                 stdout_isatty=False | ||||
|             ) | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
							
								
								
									
										33
									
								
								tests/test_docs.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								tests/test_docs.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| import os | ||||
| import subprocess | ||||
|  | ||||
| from tests import TESTS_ROOT, BaseTestCase, skipIf | ||||
|  | ||||
|  | ||||
| def has_docutils(): | ||||
|     try: | ||||
|         #noinspection PyUnresolvedReferences | ||||
|         import docutils | ||||
|         return True | ||||
|     except ImportError: | ||||
|         return False | ||||
|  | ||||
|  | ||||
| def get_readme_errors(): | ||||
|     p = subprocess.Popen([ | ||||
|         'rst2pseudoxml.py', | ||||
|         '--report=1', | ||||
|         '--exit-status=1', | ||||
|         os.path.join(TESTS_ROOT, '..', 'README.rst') | ||||
|     ], stderr=subprocess.PIPE, stdout=subprocess.PIPE) | ||||
|     err = p.communicate()[1] | ||||
|     if p.returncode: | ||||
|         return err | ||||
|  | ||||
|  | ||||
| class READMETest(BaseTestCase): | ||||
|  | ||||
|     @skipIf(not has_docutils(), 'docutils not installed') | ||||
|     def test_README_reStructuredText_valid(self): | ||||
|         errors = get_readme_errors() | ||||
|         self.assertFalse(errors, msg=errors) | ||||
							
								
								
									
										158
									
								
								tests/test_downloads.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								tests/test_downloads.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,158 @@ | ||||
| import os | ||||
| import time | ||||
|  | ||||
| from httpie.compat import urlopen | ||||
| from httpie.downloads import ( | ||||
|     parse_content_range, | ||||
|     filename_from_content_disposition, | ||||
|     filename_from_url, | ||||
|     get_unique_filename, | ||||
|     ContentRangeError, | ||||
|     Download, | ||||
| ) | ||||
| from tests import ( | ||||
|     BaseTestCase, httpbin, http, TestEnvironment, Response | ||||
| ) | ||||
|  | ||||
|  | ||||
| class DownloadUtilsTest(BaseTestCase): | ||||
|  | ||||
|     def test_Content_Range_parsing(self): | ||||
|  | ||||
|         parse = parse_content_range | ||||
|  | ||||
|         self.assertEqual(parse('bytes 100-199/200', 100), 200) | ||||
|         self.assertEqual(parse('bytes 100-199/*', 100), 200) | ||||
|  | ||||
|         # missing | ||||
|         self.assertRaises(ContentRangeError, parse, None, 100) | ||||
|  | ||||
|         # syntax error | ||||
|         self.assertRaises(ContentRangeError, parse, 'beers 100-199/*', 100) | ||||
|  | ||||
|         # unexpected range | ||||
|         self.assertRaises(ContentRangeError, parse, 'bytes 100-199/*', 99) | ||||
|  | ||||
|         # invalid instance-length | ||||
|         self.assertRaises(ContentRangeError, parse, 'bytes 100-199/199', 100) | ||||
|  | ||||
|         # invalid byte-range-resp-spec | ||||
|         self.assertRaises(ContentRangeError, parse, 'bytes 100-99/199', 100) | ||||
|  | ||||
|         # invalid byte-range-resp-spec | ||||
|         self.assertRaises(ContentRangeError, parse, 'bytes 100-100/*', 100) | ||||
|  | ||||
|     def test_Content_Disposition_parsing(self): | ||||
|         parse = filename_from_content_disposition | ||||
|         self.assertEqual( | ||||
|             parse('attachment; filename=hello-WORLD_123.txt'), | ||||
|             'hello-WORLD_123.txt' | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             parse('attachment; filename=".hello-WORLD_123.txt"'), | ||||
|             'hello-WORLD_123.txt' | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             parse('attachment; filename="white space.txt"'), | ||||
|             'white space.txt' | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             parse(r'attachment; filename="\"quotes\".txt"'), | ||||
|             '"quotes".txt' | ||||
|         ) | ||||
|         self.assertEqual(parse('attachment; filename=/etc/hosts'), 'hosts') | ||||
|         self.assertIsNone(parse('attachment; filename=')) | ||||
|  | ||||
|     def test_filename_from_url(self): | ||||
|         self.assertEqual(filename_from_url( | ||||
|             url='http://example.org/foo', | ||||
|             content_type='text/plain' | ||||
|         ), 'foo.txt') | ||||
|         self.assertEqual(filename_from_url( | ||||
|             url='http://example.org/foo', | ||||
|             content_type='text/html; charset=utf8' | ||||
|         ), 'foo.html') | ||||
|         self.assertEqual(filename_from_url( | ||||
|             url='http://example.org/foo', | ||||
|             content_type=None | ||||
|         ), 'foo') | ||||
|         self.assertEqual(filename_from_url( | ||||
|             url='http://example.org/foo', | ||||
|             content_type='x-foo/bar' | ||||
|         ), 'foo') | ||||
|  | ||||
|     def test_unique_filename(self): | ||||
|  | ||||
|         def make_exists(unique_on_attempt=0): | ||||
|             # noinspection PyUnresolvedReferences,PyUnusedLocal | ||||
|             def exists(filename): | ||||
|                 if exists.attempt == unique_on_attempt: | ||||
|                     return False | ||||
|                 exists.attempt += 1 | ||||
|                 return True | ||||
|             exists.attempt = 0 | ||||
|             return exists | ||||
|  | ||||
|         self.assertEqual( | ||||
|             get_unique_filename('foo.bar', exists=make_exists()), | ||||
|             'foo.bar' | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             get_unique_filename('foo.bar', exists=make_exists(1)), | ||||
|             'foo.bar-1' | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             get_unique_filename('foo.bar', exists=make_exists(10)), | ||||
|             'foo.bar-10' | ||||
|         ) | ||||
|  | ||||
|  | ||||
| class DownloadsTest(BaseTestCase): | ||||
|     # TODO: more tests | ||||
|  | ||||
|     def test_actual_download(self): | ||||
|         url = httpbin('/robots.txt') | ||||
|         body = urlopen(url).read().decode() | ||||
|         r = http( | ||||
|             '--download', | ||||
|             url, | ||||
|             env=TestEnvironment( | ||||
|                 stdin_isatty=True, | ||||
|                 stdout_isatty=False | ||||
|             ) | ||||
|         ) | ||||
|         self.assertIn('Downloading', r.stderr) | ||||
|         self.assertIn('[K', r.stderr) | ||||
|         self.assertIn('Done', r.stderr) | ||||
|         self.assertEqual(body, r) | ||||
|  | ||||
|     def test_download_with_Content_Length(self): | ||||
|         download = Download(output_file=open(os.devnull, 'w')) | ||||
|         download.start(Response( | ||||
|             url=httpbin('/'), | ||||
|              headers={'Content-Length': 10} | ||||
|         )) | ||||
|         time.sleep(1.1) | ||||
|         download.chunk_downloaded(b'12345') | ||||
|         time.sleep(1.1) | ||||
|         download.chunk_downloaded(b'12345') | ||||
|         download.finish() | ||||
|         self.assertFalse(download.interrupted) | ||||
|  | ||||
|     def test_download_no_Content_Length(self): | ||||
|         download = Download(output_file=open(os.devnull, 'w')) | ||||
|         download.start(Response(url=httpbin('/'))) | ||||
|         time.sleep(1.1) | ||||
|         download.chunk_downloaded(b'12345') | ||||
|         download.finish() | ||||
|         self.assertFalse(download.interrupted) | ||||
|  | ||||
|     def test_download_interrupted(self): | ||||
|         download = Download(output_file=open(os.devnull, 'w')) | ||||
|         download.start(Response( | ||||
|             url=httpbin('/'), | ||||
|             headers={'Content-Length': 5} | ||||
|         )) | ||||
|         download.chunk_downloaded(b'1234') | ||||
|         download.finish() | ||||
|         self.assertTrue(download.interrupted) | ||||
							
								
								
									
										82
									
								
								tests/test_exit_status.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								tests/test_exit_status.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| import requests | ||||
|  | ||||
| from httpie import ExitStatus | ||||
| from tests import ( | ||||
|     BaseTestCase, TestEnvironment, | ||||
|     http, httpbin, OK, skip, skipIf | ||||
| ) | ||||
|  | ||||
|  | ||||
| class ExitStatusTest(BaseTestCase): | ||||
|  | ||||
|     def test_ok_response_exits_0(self): | ||||
|         r = http( | ||||
|             'GET', | ||||
|             httpbin('/status/200') | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertEqual(r.exit_status, ExitStatus.OK) | ||||
|  | ||||
|     def test_error_response_exits_0_without_check_status(self): | ||||
|         r = http( | ||||
|             'GET', | ||||
|             httpbin('/status/500') | ||||
|         ) | ||||
|         self.assertIn('HTTP/1.1 500', r) | ||||
|         self.assertEqual(r.exit_status, ExitStatus.OK) | ||||
|         self.assertTrue(not r.stderr) | ||||
|  | ||||
|     @skip('timeout broken in requests' | ||||
|           ' (https://github.com/jkbr/httpie/issues/185)') | ||||
|     def test_timeout_exit_status(self): | ||||
|         r = http( | ||||
|             '--timeout=0.5', | ||||
|             'GET', | ||||
|             httpbin('/delay/1') | ||||
|         ) | ||||
|         self.assertEqual(r.exit_status, ExitStatus.ERROR_TIMEOUT) | ||||
|  | ||||
|     def test_3xx_check_status_exits_3_and_stderr_when_stdout_redirected(self): | ||||
|         r = http( | ||||
|             '--check-status', | ||||
|             '--headers',  # non-terminal, force headers | ||||
|             'GET', | ||||
|             httpbin('/status/301'), | ||||
|             env=TestEnvironment(stdout_isatty=False,) | ||||
|         ) | ||||
|         self.assertIn('HTTP/1.1 301', r) | ||||
|         self.assertEqual(r.exit_status, ExitStatus.ERROR_HTTP_3XX) | ||||
|         self.assertIn('301 moved permanently', r.stderr.lower()) | ||||
|  | ||||
|     @skipIf(requests.__version__ == '0.13.6', | ||||
|             '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') | ||||
|         ) | ||||
|         # The redirect will be followed so 200 is expected. | ||||
|         self.assertIn('HTTP/1.1 200 OK', r) | ||||
|         self.assertEqual(r.exit_status, ExitStatus.OK) | ||||
|  | ||||
|     def test_4xx_check_status_exits_4(self): | ||||
|         r = http( | ||||
|             '--check-status', | ||||
|             'GET', | ||||
|             httpbin('/status/401') | ||||
|         ) | ||||
|         self.assertIn('HTTP/1.1 401', r) | ||||
|         self.assertEqual(r.exit_status, ExitStatus.ERROR_HTTP_4XX) | ||||
|         # Also stderr should be empty since stdout isn't redirected. | ||||
|         self.assertTrue(not r.stderr) | ||||
|  | ||||
|     def test_5xx_check_status_exits_5(self): | ||||
|         r = http( | ||||
|             '--check-status', | ||||
|             'GET', | ||||
|             httpbin('/status/500') | ||||
|         ) | ||||
|         self.assertIn('HTTP/1.1 500', r) | ||||
|         self.assertEqual(r.exit_status, ExitStatus.ERROR_HTTP_5XX) | ||||
							
								
								
									
										91
									
								
								tests/test_httpie.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								tests/test_httpie.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| """High-level tests.""" | ||||
| from tests import ( | ||||
|     BaseTestCase, TestEnvironment, | ||||
|     http, httpbin, OK, | ||||
|     FILE_PATH, FILE_CONTENT | ||||
| ) | ||||
|  | ||||
|  | ||||
| class HTTPieTest(BaseTestCase): | ||||
|  | ||||
|     def test_GET(self): | ||||
|         r = http( | ||||
|             'GET', | ||||
|             httpbin('/get') | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|  | ||||
|     def test_DELETE(self): | ||||
|         r = http( | ||||
|             'DELETE', | ||||
|             httpbin('/delete') | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|  | ||||
|     def test_PUT(self): | ||||
|         r = http( | ||||
|             'PUT', | ||||
|             httpbin('/put'), | ||||
|             'foo=bar' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn(r'\"foo\": \"bar\"', r) | ||||
|  | ||||
|     def test_POST_JSON_data(self): | ||||
|         r = http( | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             'foo=bar' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn(r'\"foo\": \"bar\"', r) | ||||
|  | ||||
|     def test_POST_form(self): | ||||
|         r = http( | ||||
|             '--form', | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             'foo=bar' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"foo": "bar"', r) | ||||
|  | ||||
|     def test_POST_form_multiple_values(self): | ||||
|         r = http( | ||||
|             '--form', | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             'foo=bar', | ||||
|             'foo=baz', | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertDictEqual(r.json['form'], { | ||||
|             'foo': ['bar', 'baz'] | ||||
|         }) | ||||
|  | ||||
|     def test_POST_stdin(self): | ||||
|  | ||||
|         with open(FILE_PATH) as f: | ||||
|             env = TestEnvironment( | ||||
|                 stdin=f, | ||||
|                 stdin_isatty=False, | ||||
|             ) | ||||
|  | ||||
|             r = http( | ||||
|                 '--form', | ||||
|                 'POST', | ||||
|                 httpbin('/post'), | ||||
|                 env=env | ||||
|             ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn(FILE_CONTENT, r) | ||||
|  | ||||
|     def test_headers(self): | ||||
|         r = http( | ||||
|             'GET', | ||||
|             httpbin('/headers'), | ||||
|             'Foo:bar' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"User-Agent": "HTTPie', r) | ||||
|         self.assertIn('"Foo": "bar"', r) | ||||
							
								
								
									
										184
									
								
								tests/test_output.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								tests/test_output.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,184 @@ | ||||
| from tests import ( | ||||
|     BaseTestCase, TestEnvironment, | ||||
|     http, httpbin, | ||||
|     OK, COLOR, CRLF | ||||
| ) | ||||
|  | ||||
|  | ||||
| class VerboseFlagTest(BaseTestCase): | ||||
|  | ||||
|     def test_verbose(self): | ||||
|         r = http( | ||||
|             '--verbose', | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             'test-header:__test__' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         #noinspection PyUnresolvedReferences | ||||
|         self.assertEqual(r.count('__test__'), 2) | ||||
|  | ||||
|     def test_verbose_form(self): | ||||
|         # https://github.com/jkbr/httpie/issues/53 | ||||
|         r = http( | ||||
|             '--verbose', | ||||
|             '--form', | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             'foo=bar', | ||||
|             'baz=bar' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('foo=bar&baz=bar', r) | ||||
|  | ||||
|     def test_verbose_json(self): | ||||
|         r = http( | ||||
|             '--verbose', | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             'foo=bar', | ||||
|             'baz=bar' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('"baz": "bar"', r)  # request | ||||
|         self.assertIn(r'\"baz\": \"bar\"', r)  # response | ||||
|  | ||||
|  | ||||
| class PrettyOptionsTest(BaseTestCase): | ||||
|     """Test the --pretty flag handling.""" | ||||
|  | ||||
|     def test_pretty_enabled_by_default(self): | ||||
|         r = http( | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             env=TestEnvironment(colors=256), | ||||
|         ) | ||||
|         self.assertIn(COLOR, r) | ||||
|  | ||||
|     def test_pretty_enabled_by_default_unless_stdout_redirected(self): | ||||
|         r = http( | ||||
|             'GET', | ||||
|             httpbin('/get') | ||||
|         ) | ||||
|         self.assertNotIn(COLOR, r) | ||||
|  | ||||
|     def test_force_pretty(self): | ||||
|         r = http( | ||||
|             '--pretty=all', | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             env=TestEnvironment(stdout_isatty=False, colors=256), | ||||
|         ) | ||||
|         self.assertIn(COLOR, r) | ||||
|  | ||||
|     def test_force_ugly(self): | ||||
|         r = http( | ||||
|             '--pretty=none', | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|         ) | ||||
|         self.assertNotIn(COLOR, r) | ||||
|  | ||||
|     def test_subtype_based_pygments_lexer_match(self): | ||||
|         """Test that media subtype is used if type/subtype doesn't | ||||
|         match any lexer. | ||||
|  | ||||
|         """ | ||||
|         r = http( | ||||
|             '--print=B', | ||||
|             '--pretty=all', | ||||
|             httpbin('/post'), | ||||
|             'Content-Type:text/foo+json', | ||||
|             'a=b', | ||||
|             env=TestEnvironment(colors=256) | ||||
|         ) | ||||
|         self.assertIn(COLOR, r) | ||||
|  | ||||
|     def test_colors_option(self): | ||||
|         r = http( | ||||
|             '--print=B', | ||||
|             '--pretty=colors', | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             'a=b', | ||||
|             env=TestEnvironment(colors=256), | ||||
|         ) | ||||
|         #noinspection PyUnresolvedReferences | ||||
|         # Tests that the JSON data isn't formatted. | ||||
|         self.assertEqual(r.strip().count('\n'), 0) | ||||
|         self.assertIn(COLOR, r) | ||||
|  | ||||
|     def test_format_option(self): | ||||
|         r = http( | ||||
|             '--print=B', | ||||
|             '--pretty=format', | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             'a=b', | ||||
|             env=TestEnvironment(colors=256), | ||||
|         ) | ||||
|         #noinspection PyUnresolvedReferences | ||||
|         # Tests that the JSON data is formatted. | ||||
|         self.assertEqual(r.strip().count('\n'), 2) | ||||
|         self.assertNotIn(COLOR, r) | ||||
|  | ||||
|  | ||||
| class LineEndingsTest(BaseTestCase): | ||||
|     """Test that CRLF is properly used in headers and | ||||
|     as the headers/body separator.""" | ||||
|  | ||||
|     def _validate_crlf(self, msg): | ||||
|         lines = iter(msg.splitlines(True)) | ||||
|         for header in lines: | ||||
|             if header == CRLF: | ||||
|                 break | ||||
|             self.assertTrue(header.endswith(CRLF), repr(header)) | ||||
|         else: | ||||
|             self.fail('CRLF between headers and body not found in %r' % msg) | ||||
|         body = ''.join(lines) | ||||
|         self.assertNotIn(CRLF, body) | ||||
|         return body | ||||
|  | ||||
|     def test_CRLF_headers_only(self): | ||||
|         r = http( | ||||
|             '--headers', | ||||
|             'GET', | ||||
|             httpbin('/get') | ||||
|         ) | ||||
|         body = self._validate_crlf(r) | ||||
|         self.assertFalse(body, 'Garbage after headers: %r' % r) | ||||
|  | ||||
|     def test_CRLF_ugly_response(self): | ||||
|         r = http( | ||||
|             '--pretty=none', | ||||
|             'GET', | ||||
|             httpbin('/get') | ||||
|         ) | ||||
|         self._validate_crlf(r) | ||||
|  | ||||
|     def test_CRLF_formatted_response(self): | ||||
|         r = http( | ||||
|             '--pretty=format', | ||||
|             'GET', | ||||
|             httpbin('/get') | ||||
|         ) | ||||
|         self.assertEqual(r.exit_status, 0) | ||||
|         self._validate_crlf(r) | ||||
|  | ||||
|     def test_CRLF_ugly_request(self): | ||||
|         r = http( | ||||
|             '--pretty=none', | ||||
|             '--print=HB', | ||||
|             'GET', | ||||
|             httpbin('/get') | ||||
|         ) | ||||
|         self._validate_crlf(r) | ||||
|  | ||||
|     def test_CRLF_formatted_request(self): | ||||
|         r = http( | ||||
|             '--pretty=format', | ||||
|             '--print=HB', | ||||
|             'GET', | ||||
|             httpbin('/get') | ||||
|         ) | ||||
|         self._validate_crlf(r) | ||||
							
								
								
									
										165
									
								
								tests/test_sessions.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								tests/test_sessions.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | ||||
| import os | ||||
| import shutil | ||||
|  | ||||
| from tests import ( | ||||
|     BaseTestCase, TestEnvironment, | ||||
|     mk_config_dir, http, httpbin, | ||||
|     OK, | ||||
| ) | ||||
|  | ||||
|  | ||||
| class SessionsTest(BaseTestCase): | ||||
|  | ||||
|     @property | ||||
|     def env(self): | ||||
|         return TestEnvironment(config_dir=self.config_dir) | ||||
|  | ||||
|     def setUp(self): | ||||
|         # Start a full-blown session with a custom request header, | ||||
|         # authorization, and response cookies. | ||||
|         self.config_dir = mk_config_dir() | ||||
|         r = http( | ||||
|             '--follow', | ||||
|             '--session=test', | ||||
|             '--auth=username:password', | ||||
|             'GET', | ||||
|             httpbin('/cookies/set?hello=world'), | ||||
|             'Hello:World', | ||||
|             env=self.env | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|  | ||||
|     def tearDown(self): | ||||
|         shutil.rmtree(self.config_dir) | ||||
|  | ||||
|     def test_session_create(self): | ||||
|         # Verify that the session has been created. | ||||
|         r = http( | ||||
|             '--session=test', | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             env=self.env | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|  | ||||
|         self.assertEqual(r.json['headers']['Hello'], 'World') | ||||
|         self.assertEqual(r.json['headers']['Cookie'], 'hello=world') | ||||
|         self.assertIn('Basic ', r.json['headers']['Authorization']) | ||||
|  | ||||
|     def test_session_ignored_header_prefixes(self): | ||||
|         r = http( | ||||
|             '--session=test', | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             'Content-Type: text/plain', | ||||
|             'If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT', | ||||
|             env=self.env | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|  | ||||
|         r2 = http( | ||||
|             '--session=test', | ||||
|             'GET', | ||||
|             httpbin('/get') | ||||
|         ) | ||||
|         self.assertIn(OK, r2) | ||||
|         self.assertNotIn('Content-Type', r2.json['headers']) | ||||
|         self.assertNotIn('If-Unmodified-Since', r2.json['headers']) | ||||
|  | ||||
|     def test_session_update(self): | ||||
|         # Get a response to a request from the original session. | ||||
|         r1 = http( | ||||
|             '--session=test', | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             env=self.env | ||||
|         ) | ||||
|         self.assertIn(OK, r1) | ||||
|  | ||||
|         # Make a request modifying the session data. | ||||
|         r2 = http( | ||||
|             '--follow', | ||||
|             '--session=test', | ||||
|             '--auth=username:password2', | ||||
|             'GET', | ||||
|             httpbin('/cookies/set?hello=world2'), | ||||
|             'Hello:World2', | ||||
|             env=self.env | ||||
|         ) | ||||
|         self.assertIn(OK, r2) | ||||
|  | ||||
|         # Get a response to a request from the updated session. | ||||
|         r3 = http( | ||||
|             '--session=test', | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             env=self.env | ||||
|         ) | ||||
|         self.assertIn(OK, r3) | ||||
|  | ||||
|         self.assertEqual(r3.json['headers']['Hello'], 'World2') | ||||
|         self.assertEqual(r3.json['headers']['Cookie'], 'hello=world2') | ||||
|         self.assertNotEqual(r1.json['headers']['Authorization'], | ||||
|                             r3.json['headers']['Authorization']) | ||||
|  | ||||
|     def test_session_read_only(self): | ||||
|         # Get a response from the original session. | ||||
|         r1 = http( | ||||
|             '--session=test', | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             env=self.env | ||||
|         ) | ||||
|         self.assertIn(OK, r1) | ||||
|  | ||||
|         # Make a request modifying the session data but | ||||
|         # with --session-read-only. | ||||
|         r2 = http( | ||||
|             '--follow', | ||||
|             '--session-read-only=test', | ||||
|             '--auth=username:password2', | ||||
|             'GET', | ||||
|             httpbin('/cookies/set?hello=world2'), | ||||
|             'Hello:World2', | ||||
|             env=self.env | ||||
|         ) | ||||
|         self.assertIn(OK, r2) | ||||
|  | ||||
|         # Get a response from the updated session. | ||||
|         r3 = http( | ||||
|             '--session=test', | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             env=self.env | ||||
|         ) | ||||
|         self.assertIn(OK, r3) | ||||
|  | ||||
|         # Origin can differ on Travis. | ||||
|         del r1.json['origin'], r3.json['origin'] | ||||
|         # Different for each request. | ||||
|         del r1.json['headers']['X-Request-Id'], \ | ||||
|             r3.json['headers']['X-Request-Id'] | ||||
|         # Should be the same as before r2. | ||||
|         self.assertDictEqual(r1.json, r3.json) | ||||
|  | ||||
|     def test_session_by_path(self): | ||||
|         session_path = os.path.join(self.config_dir, 'session-by-path.json') | ||||
|  | ||||
|         r1 = http( | ||||
|             '--session=' + session_path, | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             'Foo:Bar', | ||||
|             env=self.env | ||||
|         ) | ||||
|         self.assertIn(OK, r1) | ||||
|  | ||||
|         r2 = http( | ||||
|             '--session=' + session_path, | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             env=self.env | ||||
|         ) | ||||
|         self.assertIn(OK, r2) | ||||
|  | ||||
|         self.assertEqual(r2.json['headers']['Foo'], 'Bar') | ||||
							
								
								
									
										71
									
								
								tests/test_stream.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								tests/test_stream.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| from httpie.compat import is_windows | ||||
| from httpie.output import BINARY_SUPPRESSED_NOTICE | ||||
| from tests import ( | ||||
|     http, httpbin, skipIf, | ||||
|     BaseTestCase, TestEnvironment, | ||||
|     BIN_FILE_CONTENT, BIN_FILE_PATH | ||||
| ) | ||||
|  | ||||
|  | ||||
| class StreamTest(BaseTestCase): | ||||
|     # GET because httpbin 500s with binary POST body. | ||||
|  | ||||
|     @skipIf(is_windows, 'Pretty redirect not supported under Windows') | ||||
|     def test_pretty_redirected_stream(self): | ||||
|         """Test that --stream works with prettified redirected output.""" | ||||
|         with open(BIN_FILE_PATH, 'rb') as f: | ||||
|             r = http( | ||||
|                 '--verbose', | ||||
|                 '--pretty=all', | ||||
|                 '--stream', | ||||
|                 'GET', | ||||
|                 httpbin('/get'), | ||||
|                 env=TestEnvironment( | ||||
|                     colors=256, | ||||
|                     stdin=f, | ||||
|                     stdin_isatty=False, | ||||
|                     stdout_isatty=False, | ||||
|                 ) | ||||
|             ) | ||||
|         self.assertIn(BINARY_SUPPRESSED_NOTICE.decode(), r) | ||||
|         # We get 'Bad Request' but it's okay. | ||||
|         #self.assertIn(OK_COLOR, r) | ||||
|  | ||||
|     def test_encoded_stream(self): | ||||
|         """Test that --stream works with non-prettified | ||||
|         redirected terminal output.""" | ||||
|         with open(BIN_FILE_PATH, 'rb') as f: | ||||
|             r = http( | ||||
|                 '--pretty=none', | ||||
|                 '--stream', | ||||
|                 '--verbose', | ||||
|                 'GET', | ||||
|                 httpbin('/get'), | ||||
|                 env=TestEnvironment( | ||||
|                     stdin=f, | ||||
|                     stdin_isatty=False | ||||
|                 ), | ||||
|             ) | ||||
|         self.assertIn(BINARY_SUPPRESSED_NOTICE.decode(), r) | ||||
|         # We get 'Bad Request' but it's okay. | ||||
|         #self.assertIn(OK, r) | ||||
|  | ||||
|     def test_redirected_stream(self): | ||||
|         """Test that --stream works with non-prettified | ||||
|         redirected terminal output.""" | ||||
|         with open(BIN_FILE_PATH, 'rb') as f: | ||||
|             r = http( | ||||
|                 '--pretty=none', | ||||
|                 '--stream', | ||||
|                 '--verbose', | ||||
|                 'GET', | ||||
|                 httpbin('/get'), | ||||
|                 env=TestEnvironment( | ||||
|                     stdout_isatty=False, | ||||
|                     stdin=f, | ||||
|                     stdin_isatty=False | ||||
|                 ) | ||||
|             ) | ||||
|         # We get 'Bad Request' but it's okay. | ||||
|         #self.assertIn(OK.encode(), r) | ||||
|         self.assertIn(BIN_FILE_CONTENT, r) | ||||
							
								
								
									
										84
									
								
								tests/test_uploads.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								tests/test_uploads.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| import os | ||||
|  | ||||
| from httpie.input import ParseError | ||||
| from tests import ( | ||||
|     BaseTestCase, TestEnvironment, http, httpbin, | ||||
|     FILE_PATH_ARG, FILE_PATH, OK, FILE_CONTENT, | ||||
| ) | ||||
|  | ||||
|  | ||||
| class MultipartFormDataFileUploadTest(BaseTestCase): | ||||
|  | ||||
|     def test_non_existent_file_raises_parse_error(self): | ||||
|         self.assertRaises(ParseError, http, | ||||
|             '--form', | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             'foo@/__does_not_exist__', | ||||
|         ) | ||||
|  | ||||
|     def test_upload_ok(self): | ||||
|         r = http( | ||||
|             '--form', | ||||
|             '--verbose', | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             'test-file@%s' % FILE_PATH_ARG, | ||||
|             'foo=bar' | ||||
|         ) | ||||
|  | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn('Content-Disposition: form-data; name="foo"', r) | ||||
|         self.assertIn('Content-Disposition: form-data; name="test-file";' | ||||
|                       ' filename="%s"' % os.path.basename(FILE_PATH), r) | ||||
|         #noinspection PyUnresolvedReferences | ||||
|         self.assertEqual(r.count(FILE_CONTENT), 2) | ||||
|         self.assertIn('"foo": "bar"', r) | ||||
|  | ||||
|  | ||||
| class RequestBodyFromFilePathTest(BaseTestCase): | ||||
|     """ | ||||
|     `http URL @file' | ||||
|  | ||||
|     """ | ||||
|     def test_request_body_from_file_by_path(self): | ||||
|         r = http( | ||||
|             '--verbose', | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             '@' + FILE_PATH_ARG | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn(FILE_CONTENT, r) | ||||
|         self.assertIn('"Content-Type": "text/plain"', 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' | ||||
|         ) | ||||
|         self.assertIn(OK, r) | ||||
|         self.assertIn(FILE_CONTENT, r) | ||||
|         self.assertIn('"Content-Type": "x-foo/bar"', r) | ||||
|  | ||||
|     def test_request_body_from_file_by_path_no_field_name_allowed(self): | ||||
|         env = TestEnvironment(stdin_isatty=True) | ||||
|         r = http( | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             'field-name@' + FILE_PATH_ARG, | ||||
|             env=env | ||||
|         ) | ||||
|         self.assertIn('perhaps you meant --form?', r.stderr) | ||||
|  | ||||
|     def test_request_body_from_file_by_path_no_data_items_allowed(self): | ||||
|         r = http( | ||||
|             'POST', | ||||
|             httpbin('/post'), | ||||
|             '@' + FILE_PATH_ARG, | ||||
|             'foo=bar', | ||||
|             env=TestEnvironment(stdin_isatty=False) | ||||
|         ) | ||||
|         self.assertIn('cannot be mixed', r.stderr) | ||||
							
								
								
									
										32
									
								
								tests/test_windows.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								tests/test_windows.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| import os | ||||
| import tempfile | ||||
|  | ||||
| from tests import ( | ||||
|     BaseTestCase, TestEnvironment, | ||||
|     http, httpbin, Environment, skip | ||||
| ) | ||||
|  | ||||
|  | ||||
| class WindowsOnlyTests(BaseTestCase): | ||||
|  | ||||
|     @skip('FIXME: kills the runner') | ||||
|     #@skipIf(not is_windows, 'windows-only') | ||||
|     def test_windows_colorized_output(self): | ||||
|         # Spits out the colorized output. | ||||
|         http(httpbin('/get'), env=Environment()) | ||||
|  | ||||
|  | ||||
| class FakeWindowsTest(BaseTestCase): | ||||
|  | ||||
|     def test_output_file_pretty_not_allowed_on_windows(self): | ||||
|  | ||||
|         r = http( | ||||
|             '--output', | ||||
|             os.path.join(tempfile.gettempdir(), '__httpie_test_output__'), | ||||
|             '--pretty=all', | ||||
|             'GET', | ||||
|             httpbin('/get'), | ||||
|             env=TestEnvironment(is_windows=True) | ||||
|         ) | ||||
|         self.assertIn( | ||||
|             'Only terminal output can be colorized on Windows', r.stderr) | ||||
							
								
								
									
										1759
									
								
								tests/tests.py
									
									
									
									
									
								
							
							
						
						
									
										1759
									
								
								tests/tests.py
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user