123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- import json
- import os
- import sys
- import unittest
- from click.testing import CliRunner
- from mock import patch, DEFAULT
- from requests.models import Response
- from .base import TempAppDirTestCase
- from http_prompt import xdg
- from http_prompt.context import Context
- from http_prompt.cli import cli, execute, ExecutionListener
- def run_and_exit(cli_args=None, prompt_commands=None):
- """Run http-prompt executable, execute some prompt commands, and exit."""
- if cli_args is None:
- cli_args = []
- # Make sure last command is 'exit'
- if prompt_commands is None:
- prompt_commands = ['exit']
- else:
- prompt_commands += ['exit']
- # Fool cli() so that it believes we're running from CLI instead of pytest.
- # We will restore it at the end of the function.
- orig_argv = sys.argv
- sys.argv = ['http-prompt'] + cli_args
- try:
- with patch.multiple('http_prompt.cli',
- prompt=DEFAULT, execute=DEFAULT) as mocks:
- mocks['execute'].side_effect = execute
- # prompt() is mocked to return the command in 'prompt_commands' in
- # sequence, i.e., prompt() returns prompt_commands[i-1] when it is
- # called for the ith time
- mocks['prompt'].side_effect = prompt_commands
- result = CliRunner().invoke(cli, cli_args)
- context = mocks['execute'].call_args[0][1]
- return result, context
- finally:
- sys.argv = orig_argv
- class TestCli(TempAppDirTestCase):
- def test_without_args(self):
- result, context = run_and_exit(['http://localhost'])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://localhost')
- self.assertEqual(context.options, {})
- self.assertEqual(context.body_params, {})
- self.assertEqual(context.headers, {})
- self.assertEqual(context.querystring_params, {})
- def test_incomplete_url1(self):
- result, context = run_and_exit(['://example.com'])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://example.com')
- self.assertEqual(context.options, {})
- self.assertEqual(context.body_params, {})
- self.assertEqual(context.headers, {})
- self.assertEqual(context.querystring_params, {})
- def test_incomplete_url2(self):
- result, context = run_and_exit(['//example.com'])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://example.com')
- self.assertEqual(context.options, {})
- self.assertEqual(context.body_params, {})
- self.assertEqual(context.headers, {})
- self.assertEqual(context.querystring_params, {})
- def test_incomplete_url3(self):
- result, context = run_and_exit(['example.com'])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://example.com')
- self.assertEqual(context.options, {})
- self.assertEqual(context.body_params, {})
- self.assertEqual(context.headers, {})
- self.assertEqual(context.querystring_params, {})
- def test_httpie_oprions(self):
- url = 'http://example.com'
- custom_args = '--auth value: name=foo'
- result, context = run_and_exit([url] + custom_args.split())
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://example.com')
- self.assertEqual(context.options, {'--auth': 'value:'})
- self.assertEqual(context.body_params, {'name': 'foo'})
- self.assertEqual(context.headers, {})
- self.assertEqual(context.querystring_params, {})
- def test_persistent_context(self):
- result, context = run_and_exit(['//example.com', 'name=bob', 'id==10'])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://example.com')
- self.assertEqual(context.options, {})
- self.assertEqual(context.body_params, {'name': 'bob'})
- self.assertEqual(context.headers, {})
- self.assertEqual(context.querystring_params, {'id': ['10']})
- result, context = run_and_exit()
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://example.com')
- self.assertEqual(context.options, {})
- self.assertEqual(context.body_params, {'name': 'bob'})
- self.assertEqual(context.headers, {})
- self.assertEqual(context.querystring_params, {'id': ['10']})
- def test_cli_args_bypasses_persistent_context(self):
- result, context = run_and_exit(['//example.com', 'name=bob', 'id==10'])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://example.com')
- self.assertEqual(context.options, {})
- self.assertEqual(context.body_params, {'name': 'bob'})
- self.assertEqual(context.headers, {})
- self.assertEqual(context.querystring_params, {'id': ['10']})
- result, context = run_and_exit(['//example.com', 'sex=M'])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://example.com')
- self.assertEqual(context.options, {})
- self.assertEqual(context.body_params, {'sex': 'M'})
- self.assertEqual(context.headers, {})
- def test_config_file(self):
- # Config file is not there at the beginning
- config_path = os.path.join(xdg.get_config_dir(), 'config.py')
- self.assertFalse(os.path.exists(config_path))
- # After user runs it for the first time, a default config file should
- # be created
- result, context = run_and_exit(['//example.com'])
- self.assertEqual(result.exit_code, 0)
- self.assertTrue(os.path.exists(config_path))
- def test_cli_arguments_with_spaces(self):
- result, context = run_and_exit(['example.com', "name=John Doe",
- "Authorization:Bearer API KEY"])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://example.com')
- self.assertEqual(context.options, {})
- self.assertEqual(context.querystring_params, {})
- self.assertEqual(context.body_params, {'name': 'John Doe'})
- self.assertEqual(context.headers, {'Authorization': 'Bearer API KEY'})
- def test_spec_from_local(self):
- spec_filepath = self.make_tempfile(json.dumps({
- 'paths': {
- '/users': {},
- '/orgs': {}
- }
- }))
- result, context = run_and_exit(['example.com', "--spec",
- spec_filepath])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://example.com')
- self.assertEqual(set([n.name for n in context.root.children]),
- set(['users', 'orgs']))
- def test_spec_basePath(self):
- spec_filepath = self.make_tempfile(json.dumps({
- 'basePath': '/api/v1',
- 'paths': {
- '/users': {},
- '/orgs': {}
- }
- }))
- result, context = run_and_exit(['example.com', "--spec",
- spec_filepath])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://example.com')
- lv1_names = set([node.name for node in context.root.ls()])
- lv2_names = set([node.name for node in context.root.ls('api')])
- lv3_names = set([node.name for node in context.root.ls('api', 'v1')])
- self.assertEqual(lv1_names, set(['api']))
- self.assertEqual(lv2_names, set(['v1']))
- self.assertEqual(lv3_names, set(['users', 'orgs']))
- def test_spec_from_http(self):
- spec_url = 'https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json'
- result, context = run_and_exit(['https://api.github.com', '--spec',
- spec_url])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'https://api.github.com')
- top_level_paths = set([n.name for n in context.root.children])
- self.assertIn('repos', top_level_paths)
- self.assertIn('users', top_level_paths)
- def test_spec_from_http_only(self):
- spec_url = (
- 'https://api.apis.guru/v2/specs/medium.com/1.0.0/swagger.json')
- result, context = run_and_exit(['--spec', spec_url])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'https://api.medium.com/v1')
- lv1_names = set([node.name for node in context.root.ls()])
- lv2_names = set([node.name for node in context.root.ls('v1')])
- self.assertEqual(lv1_names, set(['v1']))
- self.assertEqual(lv2_names, set(['me', 'publications', 'users']))
- def test_spec_with_trailing_slash(self):
- spec_filepath = self.make_tempfile(json.dumps({
- 'basePath': '/api',
- 'paths': {
- '/': {},
- '/users/': {}
- }
- }))
- result, context = run_and_exit(['example.com', "--spec",
- spec_filepath])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://example.com')
- lv1_names = set([node.name for node in context.root.ls()])
- lv2_names = set([node.name for node in context.root.ls('api')])
- self.assertEqual(lv1_names, set(['api']))
- self.assertEqual(lv2_names, set(['/', 'users/']))
- def test_env_only(self):
- env_filepath = self.make_tempfile(
- "cd http://example.com\nname=bob\nid==10")
- result, context = run_and_exit(["--env", env_filepath])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://example.com')
- self.assertEqual(context.options, {})
- self.assertEqual(context.body_params, {'name': 'bob'})
- self.assertEqual(context.headers, {})
- self.assertEqual(context.querystring_params, {'id': ['10']})
- def test_env_with_url(self):
- env_filepath = self.make_tempfile(
- "cd http://example.com\nname=bob\nid==10")
- result, context = run_and_exit(["--env", env_filepath,
- 'other_example.com'])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://other_example.com')
- self.assertEqual(context.options, {})
- self.assertEqual(context.body_params, {'name': 'bob'})
- self.assertEqual(context.headers, {})
- self.assertEqual(context.querystring_params, {'id': ['10']})
- def test_env_with_options(self):
- env_filepath = self.make_tempfile(
- "cd http://example.com\nname=bob\nid==10")
- result, context = run_and_exit(["--env", env_filepath,
- 'other_example.com', 'name=alice'])
- self.assertEqual(result.exit_code, 0)
- self.assertEqual(context.url, 'http://other_example.com')
- self.assertEqual(context.options, {})
- self.assertEqual(context.body_params, {'name': 'alice'})
- self.assertEqual(context.headers, {})
- self.assertEqual(context.querystring_params, {'id': ['10']})
- @patch('http_prompt.cli.prompt')
- @patch('http_prompt.cli.execute')
- def test_press_ctrl_d(self, execute_mock, prompt_mock):
- prompt_mock.side_effect = EOFError
- execute_mock.side_effect = execute
- result = CliRunner().invoke(cli, [])
- self.assertEqual(result.exit_code, 0)
- class TestExecutionListenerSetCookies(unittest.TestCase):
- def setUp(self):
- self.listener = ExecutionListener({})
- self.response = Response()
- self.response.cookies.update({
- 'username': 'john',
- 'sessionid': 'abcd'
- })
- self.context = Context('http://localhost')
- self.context.headers['Cookie'] = 'name="John Doe"; sessionid=xyz'
- def test_auto(self):
- self.listener.cfg['set_cookies'] = 'auto'
- self.listener.response_returned(self.context, self.response)
- self.assertEqual(self.context.headers['Cookie'],
- 'name="John Doe"; sessionid=abcd; username=john')
- @patch('http_prompt.cli.click.confirm')
- def test_ask_and_yes(self, confirm_mock):
- confirm_mock.return_value = True
- self.listener.cfg['set_cookies'] = 'ask'
- self.listener.response_returned(self.context, self.response)
- self.assertEqual(self.context.headers['Cookie'],
- 'name="John Doe"; sessionid=abcd; username=john')
- @patch('http_prompt.cli.click.confirm')
- def test_ask_and_no(self, confirm_mock):
- confirm_mock.return_value = False
- self.listener.cfg['set_cookies'] = 'ask'
- self.listener.response_returned(self.context, self.response)
- self.assertEqual(self.context.headers['Cookie'],
- 'name="John Doe"; sessionid=xyz')
- def test_off(self):
- self.listener.cfg['set_cookies'] = 'off'
- self.listener.response_returned(self.context, self.response)
- self.assertEqual(self.context.headers['Cookie'],
- 'name="John Doe"; sessionid=xyz')
|