Skip to content

Commit ed578f1

Browse files
authored
Merge pull request #530 from requests/autotest
Add Tests for Examples in docs
2 parents 39fe529 + 6cdf982 commit ed578f1

File tree

8 files changed

+163
-6
lines changed

8 files changed

+163
-6
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ dist/
2121
t.py
2222

2323
t2.py
24+
tests/examples/tmp_*py

HISTORY.rst

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
History
22
-------
33

4-
v1.4.0 (TBD)
4+
v1.4.0 (27 Feb 2024)
55
++++++++++++++++++++++++
6+
7+
Full set of changes are in [github](https://github.com/requests/requests-oauthlib/milestone/4?closed=1).
8+
9+
Additions & changes:
10+
611
- ``OAuth2Session`` now correctly uses the ``self.verify`` value if ``verify``
712
is not overridden in ``fetch_token`` and ``refresh_token``. Fixes `#404
813
<https://github.com/requests/requests-oauthlib/issues/404>`_.
914
- ``OAuth2Session`` constructor now uses its ``client.scope`` when a ``client``
1015
is provided and ``scope`` is not overridden. Fixes `#408
1116
<https://github.com/requests/requests-oauthlib/issues/408>`_
17+
- Add ``refresh_token_request`` and ``access_token_request`` compliance hooks
18+
- Add PKCE support and Auth0 example
1219
- Add support for Python 3.8-3.12
1320
- Remove support of Python 2.x, <3.7
1421
- Migrated to Github Action
15-
- Add PKCE support
22+
- Updated dependencies
23+
- Cleanup some docs and examples
1624

1725
v1.3.1 (21 January 2022)
1826
++++++++++++++++++++++++

docs/examples/native_spa_pkce_auth0.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11

2-
client_id = 'your_client_id'
2+
client_id = 'OAUTH_CLIENT_ID'
33

4-
authorization_base_url = "https://dev-foobar.eu.auth0.com/authorize"
5-
token_url = "https://dev-foobar.eu.auth0.com/oauth/token"
4+
authorization_base_url = "https://OAUTH_IDP_DOMAIN/authorize"
5+
token_url = "https://OAUTH_IDP_DOMAIN/oauth/token"
66
scope = ["openid"]
77

88
from requests_oauthlib import OAuth2Session

requests_oauthlib/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from .oauth2_auth import OAuth2
77
from .oauth2_session import OAuth2Session, TokenUpdated
88

9-
__version__ = "1.4.0-dev"
9+
__version__ = "1.4.0"
1010

1111
import requests
1212

requirements-test.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
coveralls==3.3.1
33
mock==4.0.3
44
requests-mock==1.11.0
5+
selenium==4.18.1

tests/examples/base.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import os.path
2+
import os
3+
import subprocess
4+
import shlex
5+
import shutil
6+
from selenium import webdriver
7+
from selenium.webdriver.common.by import By
8+
from selenium.webdriver.common.keys import Keys
9+
from selenium.webdriver.support import expected_conditions as EC
10+
from selenium.webdriver.support.wait import WebDriverWait
11+
12+
13+
cwd = os.path.dirname(os.path.realpath(__file__))
14+
15+
16+
class Sample():
17+
def setUp(self):
18+
super().setUp()
19+
self.proc = None
20+
self.outputs = []
21+
22+
def tearDown(self):
23+
super().tearDown()
24+
if self.proc is not None:
25+
self.proc.stdin.close()
26+
self.proc.stdout.close()
27+
self.proc.kill()
28+
29+
def replaceVariables(self, filein ,fileout, vars):
30+
with open(filein, "rt") as fin:
31+
with open(fileout, "wt") as fout:
32+
for line in fin:
33+
for k, v in vars.items():
34+
line = line.replace(k, v)
35+
fout.write(line)
36+
37+
def run_sample(self, filepath, variables):
38+
inpath = os.path.join(cwd, "..", "..", "docs", "examples", filepath)
39+
outpath = os.path.join(cwd, "tmp_{}".format(filepath))
40+
self.replaceVariables(inpath, outpath, variables)
41+
42+
self.proc = subprocess.Popen(
43+
[shutil.which("python"),
44+
outpath],
45+
text=True, bufsize=1,
46+
stdin=subprocess.PIPE,
47+
stdout=subprocess.PIPE
48+
)
49+
50+
def write(self, string):
51+
self.proc.stdin.write(string)
52+
self.proc.stdin.flush()
53+
54+
def wait_for_pattern(self, pattern):
55+
try:
56+
while True:
57+
line = self.proc.stdout.readline()
58+
self.outputs.append(line)
59+
if pattern in line:
60+
return line
61+
except subprocess.TimeoutExpired:
62+
self.assertTrue(False, "timeout when looking for output")
63+
64+
def wait_for_end(self):
65+
try:
66+
outs, err = self.proc.communicate(timeout=10)
67+
self.outputs += filter(lambda x: x != '', outs.split('\n'))
68+
except subprocess.TimeoutExpired:
69+
self.assertTrue(False, "timeout when looking for output")
70+
return self.outputs[-1]
71+
72+
73+
74+
class Browser():
75+
def setUp(self):
76+
super().setUp()
77+
options = webdriver.ChromeOptions()
78+
options.add_argument("--headless=new")
79+
self.driver = webdriver.Chrome(options=options)
80+
self.user_username = os.environ.get("AUTH0_USERNAME")
81+
self.user_password = os.environ.get("AUTH0_PASSWORD")
82+
83+
if not self.user_username or not self.user_password:
84+
self.skipTest("auth0 is not configured properly")
85+
86+
def tearDown(self):
87+
super().tearDown()
88+
self.driver.quit()
89+
90+
def authorize_auth0(self, authorize_url, expected_redirect_uri):
91+
self.driver.get(authorize_url)
92+
username = self.driver.find_element(By.ID, "username")
93+
password = self.driver.find_element(By.ID, "password")
94+
95+
wait = WebDriverWait(self.driver, timeout=2)
96+
wait.until(lambda d : username.is_displayed())
97+
wait.until(lambda d : password.is_displayed())
98+
99+
username.clear()
100+
username.send_keys(self.user_username)
101+
password.send_keys(self.user_password)
102+
username.send_keys(Keys.RETURN)
103+
104+
wait.until(EC.url_contains(expected_redirect_uri))
105+
return self.driver.current_url
106+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import os
2+
import unittest
3+
4+
from . import base
5+
6+
class TestNativeAuth0Test(base.Sample, base.Browser, unittest.TestCase):
7+
def setUp(self):
8+
super().setUp()
9+
self.client_id = os.environ.get("AUTH0_PKCE_CLIENT_ID")
10+
self.idp_domain = os.environ.get("AUTH0_DOMAIN")
11+
12+
if not self.client_id or not self.idp_domain:
13+
self.skipTest("native auth0 is not configured properly")
14+
15+
def test_login(self):
16+
# redirect_uri is http://
17+
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = "1"
18+
19+
self.run_sample(
20+
"native_spa_pkce_auth0.py", {
21+
"OAUTH_CLIENT_ID": self.client_id,
22+
"OAUTH_IDP_DOMAIN": self.idp_domain,
23+
}
24+
)
25+
authorize_url = self.wait_for_pattern("https://")
26+
redirect_uri = self.authorize_auth0(authorize_url, "http://")
27+
self.write(redirect_uri)
28+
last_line = self.wait_for_end()
29+
30+
import ast
31+
response = ast.literal_eval(last_line)
32+
self.assertIn("access_token", response)
33+
self.assertIn("id_token", response)
34+
self.assertIn("scope", response)
35+
self.assertIn("openid", response["scope"])
36+
self.assertIn("expires_in", response)
37+
self.assertIn("expires_at", response)
38+
self.assertIn("token_type", response)
39+
self.assertEqual("Bearer", response["token_type"])

tox.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ description=run test on {basepython}
66
deps=
77
-r{toxinidir}/requirements-test.txt
88
commands=coverage run --source=requests_oauthlib -m unittest discover
9+
pass_env=OAUTH_*
10+
AUTH0_*
911

1012
# tox -e docs to mimic readthedocs build.
1113
# should be similar to .readthedocs.yaml pipeline

0 commit comments

Comments
 (0)