|
50 | 50 | from oauth2client.client import AUTHORIZED_USER
|
51 | 51 | from oauth2client.client import Credentials
|
52 | 52 | from oauth2client.client import DEFAULT_ENV_NAME
|
| 53 | +from oauth2client.client import DeviceFlowInfo |
53 | 54 | from oauth2client.client import Error
|
54 | 55 | from oauth2client.client import ApplicationDefaultCredentialsError
|
55 | 56 | from oauth2client.client import FlowExchangeError
|
|
80 | 81 | from oauth2client.client import flow_from_clientsecrets
|
81 | 82 | from oauth2client.client import save_to_well_known_file
|
82 | 83 | from oauth2client.clientsecrets import _loadfile
|
| 84 | +from oauth2client.clientsecrets import InvalidClientSecretsError |
83 | 85 | from oauth2client.service_account import ServiceAccountCredentials
|
84 | 86 | from oauth2client._helpers import _to_bytes
|
85 | 87 |
|
@@ -1695,6 +1697,60 @@ def test_override_flow_via_kwargs(self):
|
1695 | 1697 | self.assertEqual(OOB_CALLBACK_URN, q['redirect_uri'][0])
|
1696 | 1698 | self.assertEqual('online', q['access_type'][0])
|
1697 | 1699 |
|
| 1700 | + @mock.patch('oauth2client.client.logger') |
| 1701 | + def test_step1_get_authorize_url_redirect_override(self, logger): |
| 1702 | + flow = OAuth2WebServerFlow('client_id+1', scope='foo', |
| 1703 | + redirect_uri=OOB_CALLBACK_URN) |
| 1704 | + alt_redirect = 'foo:bar' |
| 1705 | + self.assertEqual(flow.redirect_uri, OOB_CALLBACK_URN) |
| 1706 | + result = flow.step1_get_authorize_url(redirect_uri=alt_redirect) |
| 1707 | + # Make sure the redirect value was updated. |
| 1708 | + self.assertEqual(flow.redirect_uri, alt_redirect) |
| 1709 | + query_params = { |
| 1710 | + 'client_id': flow.client_id, |
| 1711 | + 'redirect_uri': alt_redirect, |
| 1712 | + 'scope': flow.scope, |
| 1713 | + 'access_type': 'offline', |
| 1714 | + 'response_type': 'code', |
| 1715 | + } |
| 1716 | + expected = _update_query_params(flow.auth_uri, query_params) |
| 1717 | + assertUrisEqual(self, expected, result) |
| 1718 | + # Check stubs. |
| 1719 | + self.assertEqual(logger.warning.call_count, 1) |
| 1720 | + |
| 1721 | + def test_step1_get_authorize_url_without_redirect(self): |
| 1722 | + flow = OAuth2WebServerFlow('client_id+1', scope='foo', |
| 1723 | + redirect_uri=None) |
| 1724 | + with self.assertRaises(ValueError): |
| 1725 | + flow.step1_get_authorize_url(redirect_uri=None) |
| 1726 | + |
| 1727 | + def test_step1_get_authorize_url_without_login_hint(self): |
| 1728 | + login_hint = 'There are wascally wabbits nearby' |
| 1729 | + flow = OAuth2WebServerFlow('client_id+1', scope='foo', |
| 1730 | + redirect_uri=OOB_CALLBACK_URN, |
| 1731 | + login_hint=login_hint) |
| 1732 | + result = flow.step1_get_authorize_url() |
| 1733 | + query_params = { |
| 1734 | + 'client_id': flow.client_id, |
| 1735 | + 'login_hint': login_hint, |
| 1736 | + 'redirect_uri': OOB_CALLBACK_URN, |
| 1737 | + 'scope': flow.scope, |
| 1738 | + 'access_type': 'offline', |
| 1739 | + 'response_type': 'code', |
| 1740 | + } |
| 1741 | + expected = _update_query_params(flow.auth_uri, query_params) |
| 1742 | + assertUrisEqual(self, expected, result) |
| 1743 | + |
| 1744 | + def test_step2_exchange_no_input(self): |
| 1745 | + flow = OAuth2WebServerFlow('client_id+1', scope='foo') |
| 1746 | + with self.assertRaises(ValueError): |
| 1747 | + flow.step2_exchange() |
| 1748 | + |
| 1749 | + def test_step2_exchange_code_and_device_flow(self): |
| 1750 | + flow = OAuth2WebServerFlow('client_id+1', scope='foo') |
| 1751 | + with self.assertRaises(ValueError): |
| 1752 | + flow.step2_exchange(code='code', device_flow_info='dfi') |
| 1753 | + |
1698 | 1754 | def test_scope_is_required(self):
|
1699 | 1755 | self.assertRaises(TypeError, OAuth2WebServerFlow, 'client_id+1')
|
1700 | 1756 |
|
@@ -1910,6 +1966,43 @@ def test_flow_from_clientsecrets_cached(self):
|
1910 | 1966 | 'some_secrets', '', redirect_uri='oob', cache=cache_mock)
|
1911 | 1967 | self.assertEqual('foo_client_secret', flow.client_secret)
|
1912 | 1968 |
|
| 1969 | + @mock.patch('oauth2client.clientsecrets.loadfile', |
| 1970 | + side_effect=InvalidClientSecretsError) |
| 1971 | + def test_flow_from_clientsecrets_invalid(self, loadfile_mock): |
| 1972 | + filename = object() |
| 1973 | + cache = object() |
| 1974 | + with self.assertRaises(InvalidClientSecretsError): |
| 1975 | + flow_from_clientsecrets(filename, None, cache=cache, |
| 1976 | + message=None) |
| 1977 | + loadfile_mock.assert_called_once_with(filename, cache=cache) |
| 1978 | + |
| 1979 | + @mock.patch('oauth2client.clientsecrets.loadfile', |
| 1980 | + side_effect=InvalidClientSecretsError) |
| 1981 | + @mock.patch('sys.exit') |
| 1982 | + def test_flow_from_clientsecrets_invalid_w_msg(self, sys_exit, |
| 1983 | + loadfile_mock): |
| 1984 | + filename = object() |
| 1985 | + cache = object() |
| 1986 | + message = 'hi mom' |
| 1987 | + |
| 1988 | + flow_from_clientsecrets(filename, None, cache=cache, message=message) |
| 1989 | + sys_exit.assert_called_once_with(message) |
| 1990 | + loadfile_mock.assert_called_once_with(filename, cache=cache) |
| 1991 | + |
| 1992 | + @mock.patch('oauth2client.clientsecrets.loadfile') |
| 1993 | + def test_flow_from_clientsecrets_unknown_flow(self, loadfile_mock): |
| 1994 | + client_type = 'UNKNOWN' |
| 1995 | + loadfile_mock.return_value = client_type, None |
| 1996 | + filename = object() |
| 1997 | + cache = object() |
| 1998 | + |
| 1999 | + err_msg = 'This OAuth 2.0 flow is unsupported: %r' % (client_type,) |
| 2000 | + with self.assertRaisesRegexp(client.UnknownClientSecretsFlowError, |
| 2001 | + err_msg): |
| 2002 | + flow_from_clientsecrets(filename, None, cache=cache) |
| 2003 | + |
| 2004 | + loadfile_mock.assert_called_once_with(filename, cache=cache) |
| 2005 | + |
1913 | 2006 |
|
1914 | 2007 | class CredentialsFromCodeTests(unittest2.TestCase):
|
1915 | 2008 |
|
@@ -2061,5 +2154,60 @@ def test_without_crypto(self):
|
2061 | 2154 | client._require_crypto_or_die()
|
2062 | 2155 |
|
2063 | 2156 |
|
| 2157 | +class TestDeviceFlowInfo(unittest2.TestCase): |
| 2158 | + |
| 2159 | + DEVICE_CODE = 'e80ff179-fd65-416c-9dbf-56a23e5d23e4' |
| 2160 | + USER_CODE = '4bbd8b82-fc73-11e5-adf3-00c2c63e5792' |
| 2161 | + VER_URL = 'http://foo.bar' |
| 2162 | + |
| 2163 | + def test_FromResponse(self): |
| 2164 | + response = { |
| 2165 | + 'device_code': self.DEVICE_CODE, |
| 2166 | + 'user_code': self.USER_CODE, |
| 2167 | + 'verification_url': self.VER_URL, |
| 2168 | + } |
| 2169 | + result = DeviceFlowInfo.FromResponse(response) |
| 2170 | + expected_result = DeviceFlowInfo(self.DEVICE_CODE, self.USER_CODE, |
| 2171 | + None, self.VER_URL, None) |
| 2172 | + self.assertEqual(result, expected_result) |
| 2173 | + |
| 2174 | + def test_FromResponse_fallback_to_uri(self): |
| 2175 | + response = { |
| 2176 | + 'device_code': self.DEVICE_CODE, |
| 2177 | + 'user_code': self.USER_CODE, |
| 2178 | + 'verification_uri': self.VER_URL, |
| 2179 | + } |
| 2180 | + result = DeviceFlowInfo.FromResponse(response) |
| 2181 | + expected_result = DeviceFlowInfo(self.DEVICE_CODE, self.USER_CODE, |
| 2182 | + None, self.VER_URL, None) |
| 2183 | + self.assertEqual(result, expected_result) |
| 2184 | + |
| 2185 | + def test_FromResponse_missing_url(self): |
| 2186 | + response = { |
| 2187 | + 'device_code': self.DEVICE_CODE, |
| 2188 | + 'user_code': self.USER_CODE, |
| 2189 | + } |
| 2190 | + with self.assertRaises(client.OAuth2DeviceCodeError): |
| 2191 | + DeviceFlowInfo.FromResponse(response) |
| 2192 | + |
| 2193 | + @mock.patch('oauth2client.client._NOW') |
| 2194 | + def test_FromResponse_with_expires_in(self, dt_now): |
| 2195 | + expires_in = 23 |
| 2196 | + response = { |
| 2197 | + 'device_code': self.DEVICE_CODE, |
| 2198 | + 'user_code': self.USER_CODE, |
| 2199 | + 'verification_url': self.VER_URL, |
| 2200 | + 'expires_in': expires_in, |
| 2201 | + } |
| 2202 | + now = datetime.datetime(1999, 1, 1, 12, 30, 27) |
| 2203 | + expire = datetime.datetime(1999, 1, 1, 12, 30, 27 + expires_in) |
| 2204 | + dt_now.return_value = now |
| 2205 | + |
| 2206 | + result = DeviceFlowInfo.FromResponse(response) |
| 2207 | + expected_result = DeviceFlowInfo(self.DEVICE_CODE, self.USER_CODE, |
| 2208 | + None, self.VER_URL, expire) |
| 2209 | + self.assertEqual(result, expected_result) |
| 2210 | + |
| 2211 | + |
2064 | 2212 | if __name__ == '__main__': # pragma: NO COVER
|
2065 | 2213 | unittest2.main()
|
0 commit comments