diff --git a/tests/test_oauth.py b/tests/test_oauth.py new file mode 100644 index 0000000..996f510 --- /dev/null +++ b/tests/test_oauth.py @@ -0,0 +1,118 @@ +from spotipy.oauth2 import SpotifyOAuth +import json +import io +import unittest + +try: + import unittest.mock as mock +except ImportError: + import mock + +patch = mock.patch +DEFAULT = mock.DEFAULT + + +def _make_fake_token(expires_at, expires_in, scope): + return dict( + expires_at=expires_at, + expires_in=expires_in, + scope=scope, + token_type="Bearer", + refresh_token="REFRESH", + access_token="ACCESS") + + +def _fake_file(): + return mock.Mock(spec_set=io.FileIO) + + +def _token_file(token): + fi = _fake_file() + fi.read.return_value = token + return fi + + +def _make_oauth(*args, **kwargs): + return SpotifyOAuth("CLID", "CLISEC", "REDIR", "STATE", *args, **kwargs) + + +class OAuthCacheTest(unittest.TestCase): + + @patch.multiple(SpotifyOAuth, + _is_token_expired=DEFAULT, _refresh_access_token=DEFAULT) + @patch('spotipy.oauth2.open', create=True) + def test_gets_from_cache_path(self, opener, + _is_token_expired, _refresh_access_token): + scope = "playlist-modify-private" + path = ".cache-username" + tok = _make_fake_token(1, 1, scope) + + opener.return_value = _token_file(json.dumps(tok, ensure_ascii=False)) + _is_token_expired.return_value = False + + spot = _make_oauth(scope, path) + cached_tok = spot.get_cached_token() + + opener.assert_called_with(path) + self.assertIsNotNone(cached_tok) + self.assertEqual(_refresh_access_token.call_count, 0) + + @patch.multiple(SpotifyOAuth, + _is_token_expired=DEFAULT, _refresh_access_token=DEFAULT) + @patch('spotipy.oauth2.open', create=True) + def test_expired_token_refreshes(self, opener, + _is_token_expired, _refresh_access_token): + scope = "playlist-modify-private" + path = ".cache-username" + expired_tok = _make_fake_token(0, None, scope) + fresh_tok = _make_fake_token(1, 1, scope) + + token_file = _token_file(json.dumps(expired_tok, ensure_ascii=False)) + opener.return_value = token_file + _refresh_access_token.return_value = fresh_tok + + spot = _make_oauth(scope, path) + spot.get_cached_token() + + _is_token_expired.assert_called_with(expired_tok) + _refresh_access_token.assert_called_with(expired_tok['refresh_token']) + opener.assert_any_call(path) + + @patch.multiple(SpotifyOAuth, + _is_token_expired=DEFAULT, _refresh_access_token=DEFAULT) + @patch('spotipy.oauth2.open', create=True) + def test_badly_scoped_token_bails(self, opener, + _is_token_expired, _refresh_access_token): + token_scope = "playlist-modify-public" + requested_scope = "playlist-modify-private" + path = ".cache-username" + tok = _make_fake_token(1, 1, token_scope) + + opener.return_value = _token_file(json.dumps(tok, ensure_ascii=False)) + _is_token_expired.return_value = False + + spot = _make_oauth(requested_scope, path) + cached_tok = spot.get_cached_token() + + opener.assert_called_with(path) + self.assertIsNone(cached_tok) + self.assertEqual(_refresh_access_token.call_count, 0) + + @patch('spotipy.oauth2.open', create=True) + def test_saves_to_cache_path(self, opener): + scope = "playlist-modify-private" + path = ".cache-username" + tok = _make_fake_token(1, 1, scope) + + fi = _fake_file() + opener.return_value = fi + + spot = SpotifyOAuth("CLID", "CLISEC", "REDIR", "STATE", scope, path) + spot._save_token_info(tok) + + opener.assert_called_with(path, 'w') + self.assertTrue(fi.write.called) + + +if __name__ == '__main__': + unittest.main() diff --git a/tox.ini b/tox.ini index ffce4a8..705b07e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,7 @@ [tox] envlist = py27,py34 [testenv] -deps=requests +deps= + requests + py27: mock commands=python -m unittest discover tests