Skip to content

Commit 684498b

Browse files
committed
more good stuff in 19, get a fiddly listing with emails in escaped correctly
1 parent 31ed75d commit 684498b

File tree

3 files changed

+59
-47
lines changed

3 files changed

+59
-47
lines changed

chapter_19_mocking.asciidoc

Lines changed: 57 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ So we can insert the token into our email like this:
917917

918918

919919
[role="sourcecode"]
920-
.src/accounts/views.py (ch17l023)
920+
.src/accounts/views.py (ch19l023)
921921
====
922922
[source,python]
923923
----
@@ -947,43 +947,45 @@ def send_login_email(request):
947947
framework, and that gets overcomplicated pretty quickly. You can find
948948
lots more discussion on this if you're curious by doing a bit of googling.
949949

950-
Two more pieces in the puzzle. We need an authentication backend, whose
951-
job it will be to examine tokens for validity and then return the corresponding
952-
users; then we need to get our login view to actually log users in,
953-
if they can authenticate.((("", startref="Mpythong19")))((("", startref="Pmock19")))
950+
Two more pieces in the puzzle.
951+
We need an authentication backend,
952+
whose job it will be to examine tokens for validity
953+
and then return the corresponding users;
954+
then we need to get our login view to actually log users in,
955+
if they can authenticate.
956+
((("", startref="Mpythong19")))((("", startref="Pmock19")))
954957

955958

956959

957960

958-
De-spiking Our Custom Authentication Backend
959-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
961+
=== De-spiking Our Custom Authentication Backend
960962

961-
((("mocks", "de-spiking custom authentication", id="Mdespike19")))((("spiking and de-spiking", "de-spiking", id="SDdesp19")))Our
962-
custom authentication backend is next. Here's how it looked in the spike:
963+
((("mocks", "de-spiking custom authentication", id="Mdespike19")))
964+
((("spiking and de-spiking", "de-spiking", id="SDdesp19")))
965+
Our custom authentication backend is next.
966+
Here's how it looked in the spike:
963967

964968

965969
[[spike-reminder]]
966970
[role="skipme small-code"]
967971
[source,python]
968972
----
969-
class PasswordlessAuthenticationBackend(object):
970-
971-
def authenticate(self, uid):
972-
print('uid', uid, file=sys.stderr)
973+
class PasswordlessAuthenticationBackend(BaseBackend):
974+
def authenticate(self, request, uid):
975+
print("uid", uid, file=sys.stderr)
973976
if not Token.objects.filter(uid=uid).exists():
974-
print('no token found', file=sys.stderr)
977+
print("no token found", file=sys.stderr)
975978
return None
976979
token = Token.objects.get(uid=uid)
977-
print('got token', file=sys.stderr)
980+
print("got token", file=sys.stderr)
978981
try:
979982
user = ListUser.objects.get(email=token.email)
980-
print('got user', file=sys.stderr)
983+
print("got user", file=sys.stderr)
981984
return user
982985
except ListUser.DoesNotExist:
983-
print('new user', file=sys.stderr)
986+
print("new user", file=sys.stderr)
984987
return ListUser.objects.create(email=token.email)
985988
986-
987989
def get_user(self, email):
988990
return ListUser.objects.get(email=email)
989991
----
@@ -1006,54 +1008,56 @@ How about something like this?
10061008

10071009

10081010
[role="sourcecode"]
1009-
.src/accounts/tests/test_authentication.py
1011+
.src/accounts/tests/test_authentication.py (ch19l024)
10101012
====
10111013
[source,python]
10121014
----
1013-
from django.test import TestCase
10141015
from django.contrib.auth import get_user_model
1016+
from django.http import HttpRequest
1017+
from django.test import TestCase
1018+
10151019
from accounts.authentication import PasswordlessAuthenticationBackend
10161020
from accounts.models import Token
1021+
10171022
User = get_user_model()
10181023
10191024
10201025
class AuthenticateTest(TestCase):
1021-
10221026
def test_returns_None_if_no_such_token(self):
10231027
result = PasswordlessAuthenticationBackend().authenticate(
1024-
'no-such-token'
1028+
HttpRequest(), "no-such-token"
10251029
)
10261030
self.assertIsNone(result)
10271031
1028-
10291032
def test_returns_new_user_with_correct_email_if_token_exists(self):
1030-
1033+
10311034
token = Token.objects.create(email=email)
1032-
user = PasswordlessAuthenticationBackend().authenticate(token.uid)
1035+
user = PasswordlessAuthenticationBackend().authenticate(
1036+
HttpRequest(), token.uid
1037+
)
10331038
new_user = User.objects.get(email=email)
10341039
self.assertEqual(user, new_user)
10351040
1036-
10371041
def test_returns_existing_user_with_correct_email_if_token_exists(self):
1038-
1042+
10391043
existing_user = User.objects.create(email=email)
10401044
token = Token.objects.create(email=email)
1041-
user = PasswordlessAuthenticationBackend().authenticate(token.uid)
1045+
user = PasswordlessAuthenticationBackend().authenticate(
1046+
HttpRequest(), token.uid
1047+
)
10421048
self.assertEqual(user, existing_user)
1043-
10441049
----
10451050
====
10461051

10471052

1048-
In 'authenticate.py' we'll just have a little placeholder:
1053+
In _authenticate.py_ we'll just have a little placeholder:
10491054

10501055
[role="sourcecode"]
10511056
.src/accounts/authentication.py (ch19l025)
10521057
====
10531058
[source,python]
10541059
----
10551060
class PasswordlessAuthenticationBackend:
1056-
10571061
def authenticate(self, request, uid):
10581062
pass
10591063
----
@@ -1062,31 +1066,35 @@ class PasswordlessAuthenticationBackend:
10621066

10631067
How do we get on?
10641068

1065-
[subs="specialcharacters,macros"]
1069+
[subs="macros"]
10661070
----
10671071
$ pass:quotes[*python src/manage.py test accounts*]
10681072
10691073
.FE.........
10701074
======================================================================
1071-
ERROR: test_returns_new_user_with_correct_email_if_token_exists
1072-
(accounts.tests.test_authentication.AuthenticateTest)
1075+
ERROR: test_returns_new_user_with_correct_email_if_token_exists (accounts.tests
1076+
.test_authentication.AuthenticateTest.test_returns_new_user_with_correct_email_
1077+
if_token_exists)
10731078
---------------------------------------------------------------------
10741079
Traceback (most recent call last):
1075-
File "...goat-book/accounts/tests/test_authentication.py", line 21, in
1080+
File "...goat-book/src/accounts/tests/test_authentication.py", line 24, in
10761081
test_returns_new_user_with_correct_email_if_token_exists
10771082
new_user = User.objects.get(email=email)
1083+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
10781084
[...]
1079-
accounts.models.DoesNotExist: User matching query does not exist.
1085+
accounts.models.User.DoesNotExist: User matching query does not exist.
1086+
10801087
10811088
======================================================================
1082-
FAIL: test_returns_existing_user_with_correct_email_if_token_exists
1083-
(accounts.tests.test_authentication.AuthenticateTest)
1089+
FAIL: test_returns_existing_user_with_correct_email_if_token_exists (accounts.t
1090+
ests.test_authentication.AuthenticateTest.test_returns_existing_user_with_corre
1091+
ct_email_if_token_exists)
10841092
---------------------------------------------------------------------
10851093
Traceback (most recent call last):
1086-
File "...goat-book/accounts/tests/test_authentication.py", line 30, in
1094+
File "...goat-book/src/accounts/tests/test_authentication.py", line 34, in
10871095
test_returns_existing_user_with_correct_email_if_token_exists
10881096
self.assertEqual(user, existing_user)
1089-
AssertionError: None != <User: User object>
1097+
AssertionError: None != pass:specialcharacters[<User: User object ([email protected])>]
10901098
10911099
---------------------------------------------------------------------
10921100
Ran 12 tests in 0.038s
@@ -1104,6 +1112,7 @@ Here's a first cut:
11041112
----
11051113
from accounts.models import Token, User
11061114
1115+
11071116
class PasswordlessAuthenticationBackend:
11081117
def authenticate(self, request, uid):
11091118
token = Token.objects.get(uid=uid)
@@ -1118,15 +1127,17 @@ That gets one test passing but breaks another one:
11181127
[subs="specialcharacters,macros"]
11191128
----
11201129
$ pass:quotes[*python src/manage.py test accounts*]
1121-
ERROR: test_returns_None_if_no_such_token
1122-
(accounts.tests.test_authentication.AuthenticateTest)
11231130
1124-
accounts.models.DoesNotExist: Token matching query does not exist.
1131+
ERROR: test_returns_None_if_no_such_token (accounts.tests.test_authentication.A
1132+
uthenticateTest.test_returns_None_if_no_such_token)
1133+
[...]
1134+
accounts.models.Token.DoesNotExist: Token matching query does not exist.
11251135
1126-
ERROR: test_returns_new_user_with_correct_email_if_token_exists
1127-
(accounts.tests.test_authentication.AuthenticateTest)
1136+
ERROR: test_returns_new_user_with_correct_email_if_token_exists (accounts.tests
1137+
.test_authentication.AuthenticateTest.test_returns_new_user_with_correct_email_
1138+
if_token_exists)
11281139
[...]
1129-
accounts.models.DoesNotExist: User matching query does not exist.
1140+
accounts.models.User.DoesNotExist: User matching query does not exist.
11301141
----
11311142

11321143
Let's fix each of those in turn:

tests/test_chapter_19_mocking.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def test_listings_and_commands_and_output(self):
2323

2424
self.prep_database()
2525
# self.sourcetree.run_command("rm src/accounts/tests.py")
26+
self.sourcetree.run_command("mkdir -p src/static")
2627

2728
# hack fast-forward
2829
if os.environ.get("SKIP"):

0 commit comments

Comments
 (0)