codeforlife-portal 6.41.5__py2.py3-none-any.whl → 6.41.6__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of codeforlife-portal might be problematic. Click here for more details.
- cfl_common/common/app_settings.py +3 -0
- cfl_common/common/email_messages.py +0 -58
- cfl_common/common/helpers/data_migration_loader.py +3 -4
- cfl_common/common/helpers/emails.py +27 -45
- cfl_common/common/helpers/generators.py +1 -1
- cfl_common/common/mail.py +116 -0
- cfl_common/common/migrations/0002_emailverification.py +1 -3
- cfl_common/common/migrations/0005_add_worksheets.py +1 -5
- cfl_common/common/migrations/0007_add_pdf_names_to_first_two_worksheets.py +1 -5
- cfl_common/common/migrations/0008_unlock_worksheet_3.py +1 -5
- cfl_common/common/migrations/0017_copy_email_to_username.py +2 -8
- cfl_common/common/migrations/0021_school_is_active.py +7 -7
- cfl_common/common/migrations/0022_school_cleanup.py +9 -9
- cfl_common/common/migrations/0023_userprofile_aimmo_badges.py +4 -4
- cfl_common/common/migrations/0025_schoolteacherinvitation.py +29 -13
- cfl_common/common/migrations/0026_teacher_remove_join_request.py +5 -5
- cfl_common/common/migrations/0027_class_created_by.py +10 -4
- cfl_common/common/migrations/0028_coding_club_downloads.py +5 -5
- cfl_common/common/migrations/0029_dynamicelement.py +6 -6
- cfl_common/common/migrations/0030_add_maintenance_banner.py +1 -3
- cfl_common/common/migrations/0031_improve_admin_panel.py +32 -14
- cfl_common/common/migrations/0032_dailyactivity_level_control_submits.py +3 -3
- cfl_common/common/migrations/0033_password_reset_tracking_fields.py +5 -5
- cfl_common/common/migrations/0034_dailyactivity_daily_school_student_lockout_reset.py +3 -3
- cfl_common/common/migrations/0035_rename_lockout_fields.py +10 -10
- cfl_common/common/migrations/0037_migrate_email_verification.py +2 -2
- cfl_common/common/migrations/0038_delete_emailverification.py +2 -2
- cfl_common/common/migrations/0039_copy_email_to_username.py +1 -6
- cfl_common/common/migrations/0040_school_county.py +3 -3
- cfl_common/common/migrations/0042_totalactivity.py +7 -7
- cfl_common/common/migrations/0044_update_activity_models.py +9 -9
- cfl_common/common/migrations/0045_otp.py +5 -5
- cfl_common/common/migrations/0046_alter_school_country.py +3 -3
- cfl_common/common/tests/utils/email.py +14 -34
- cfl_common/common/tests/utils/student.py +8 -8
- cfl_common/common/tests/utils/teacher.py +8 -8
- {codeforlife_portal-6.41.5.dist-info → codeforlife_portal-6.41.6.dist-info}/METADATA +2 -2
- {codeforlife_portal-6.41.5.dist-info → codeforlife_portal-6.41.6.dist-info}/RECORD +49 -48
- example_project/portal_test_settings.py +5 -1
- portal/__init__.py +1 -1
- portal/tests/test_independent_student.py +30 -17
- portal/tests/test_ratelimit.py +15 -12
- portal/tests/test_teacher.py +35 -21
- portal/tests/test_teacher_student.py +13 -3
- portal/tests/test_views.py +55 -194
- portal/views/cron/user.py +12 -49
- {codeforlife_portal-6.41.5.dist-info → codeforlife_portal-6.41.6.dist-info}/LICENSE.md +0 -0
- {codeforlife_portal-6.41.5.dist-info → codeforlife_portal-6.41.6.dist-info}/WHEEL +0 -0
- {codeforlife_portal-6.41.5.dist-info → codeforlife_portal-6.41.6.dist-info}/top_level.txt +0 -0
|
@@ -1,27 +1,28 @@
|
|
|
1
1
|
cfl_common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
cfl_common/setup.py,sha256=5Rk-FXyWToTujXqGRYqeA0A5nJ4NC5woXxyb6NLLbpo,818
|
|
3
3
|
cfl_common/common/__init__.py,sha256=XlncBOpKp_gekbKH7Y_i6yu1qy5tJc3Y8sn8cDy-Vgk,48
|
|
4
|
-
cfl_common/common/app_settings.py,sha256=
|
|
4
|
+
cfl_common/common/app_settings.py,sha256=x2ROLY5Xl5LgqjxyTiChZvQorZYUXpFzEkaLsjh8UHo,2586
|
|
5
5
|
cfl_common/common/apps.py,sha256=49UXZ3bSkFKvIEOL4zM7y1sAhccQJyRtsoOg5XVd_8Y,129
|
|
6
6
|
cfl_common/common/context_processors.py,sha256=X0iuX5qu9kMWa7q8osE9CJ2LgM7pPOYQFGdjm8X3rk0,236
|
|
7
7
|
cfl_common/common/csp_config.py,sha256=sZT6s9zMT5FFIqNODsURT0ifxbDgXpDlki8UxaBq2iE,2940
|
|
8
|
-
cfl_common/common/email_messages.py,sha256=
|
|
8
|
+
cfl_common/common/email_messages.py,sha256=res-Uh_0KihJdvXKZg9EbvQ4ohQwS2rlR2wNHcazLoo,5009
|
|
9
|
+
cfl_common/common/mail.py,sha256=EsqghHcRbrvCHI-eVcd88PrVVvsz1ZMbUzHrWne3nyE,4192
|
|
9
10
|
cfl_common/common/models.py,sha256=vnvy8U-sHopyaxgJK9wTxelbKsCnYMjuEu3HIuAEkrs,14974
|
|
10
11
|
cfl_common/common/permissions.py,sha256=gC6RQGZI2QDBbglx-xr_V4Hl2C2nf1V2_uPmEuoEcJo,2416
|
|
11
12
|
cfl_common/common/utils.py,sha256=Nn2Npao9Uqad5Js_IdHwF-ow6wrPNpBLW4AO1LxoEBc,1727
|
|
12
13
|
cfl_common/common/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
cfl_common/common/helpers/data_migration_loader.py,sha256=
|
|
14
|
-
cfl_common/common/helpers/emails.py,sha256=
|
|
15
|
-
cfl_common/common/helpers/generators.py,sha256=
|
|
14
|
+
cfl_common/common/helpers/data_migration_loader.py,sha256=_BhS5lPmhcuVUbryBmJytlWdHyT02KYyxPkHar32mOE,1748
|
|
15
|
+
cfl_common/common/helpers/emails.py,sha256=u2X2brjHIlUDNIgQ6-Ld23Y4zyouJGTFH-G7HNQDBYs,11041
|
|
16
|
+
cfl_common/common/helpers/generators.py,sha256=kTL5e91I8wgmjJ-mu4jr9vIacjccUZ5pZSAz5cUNhdM,1505
|
|
16
17
|
cfl_common/common/helpers/organisation.py,sha256=e-JKumKoXrkMTzZPv0H4ViWL8vtCt7oXJjn_zZ1ec00,427
|
|
17
18
|
cfl_common/common/migrations/0001_initial.py,sha256=Y2kt2xmdCbrmDXCgqmhXeacicNg26Zj7L7SANSsgAAI,9664
|
|
18
|
-
cfl_common/common/migrations/0002_emailverification.py,sha256=
|
|
19
|
+
cfl_common/common/migrations/0002_emailverification.py,sha256=csWNasKNB5HQfrg5Owa6ovwx9f-v3ved-1B6QSu2_3s,2094
|
|
19
20
|
cfl_common/common/migrations/0003_aimmocharacter.py,sha256=ZS_-sJCVUnFdhDjyH75P5bryg5QKHPDfe-SXXK7k9KM,922
|
|
20
21
|
cfl_common/common/migrations/0004_add_aimmocharacters.py,sha256=543WKEphsvdKo8Z7f8wPgZHGxRPWMdo288O5_7edawo,430
|
|
21
|
-
cfl_common/common/migrations/0005_add_worksheets.py,sha256=
|
|
22
|
+
cfl_common/common/migrations/0005_add_worksheets.py,sha256=lIfjiNEOGiGEsrJJCN-BVaOcyidlT3s9uhwpCfyHFV0,376
|
|
22
23
|
cfl_common/common/migrations/0006_update_aimmo_character_image_path.py,sha256=De1d02dAYE2KT8uW1qPi0NmWp45_zXVNH7kjWg3f2ko,431
|
|
23
|
-
cfl_common/common/migrations/0007_add_pdf_names_to_first_two_worksheets.py,sha256=
|
|
24
|
-
cfl_common/common/migrations/0008_unlock_worksheet_3.py,sha256=
|
|
24
|
+
cfl_common/common/migrations/0007_add_pdf_names_to_first_two_worksheets.py,sha256=dQBI3VzqS8CpnpmQfXx_sNVDynhQL-KxwJNl38cgJi4,395
|
|
25
|
+
cfl_common/common/migrations/0008_unlock_worksheet_3.py,sha256=WzTdGbSjYNlyxNLVRMPWOhNBkR5e-lRewu0xBy5d69c,345
|
|
25
26
|
cfl_common/common/migrations/0009_add_blocked_time_to_teacher_and_student.py,sha256=hdff316HkAVCB0EW61qbR2lxwkxSTsD7OBK66PLBUUQ,599
|
|
26
27
|
cfl_common/common/migrations/0010_remove_teacher_title.py,sha256=dMX-wgD-nzRx2AmrvuLMtb1X7TIv1gZ9icacFgI1LNc,396
|
|
27
28
|
cfl_common/common/migrations/0011_student_login_id.py,sha256=0sMdbzshOu_hT3s7uC0ILKd4PA1waw14y83Re736788,400
|
|
@@ -30,36 +31,36 @@ cfl_common/common/migrations/0013_class_school.py,sha256=n5slnrrOFnrBsjAmkdcRxIU
|
|
|
30
31
|
cfl_common/common/migrations/0014_login_type.py,sha256=_liGPnErUKWj2hfErZjkw--2BM8pZCYIvdg96uJts08,817
|
|
31
32
|
cfl_common/common/migrations/0015_dailyactivity.py,sha256=jbzA7hwcEd7mg-w0he-OMpVGSUrjYuWW_QFXY2RWzjk,901
|
|
32
33
|
cfl_common/common/migrations/0016_joinreleasestudent.py,sha256=bu7s-artUHMRPxP0Rnbw10cQy47c2_GYOD8fzzHgXQ8,1208
|
|
33
|
-
cfl_common/common/migrations/0017_copy_email_to_username.py,sha256=
|
|
34
|
+
cfl_common/common/migrations/0017_copy_email_to_username.py,sha256=oon4z_fHDxABJ-J3T3IeucAJPl2lYCu75zcZk0a1xfs,587
|
|
34
35
|
cfl_common/common/migrations/0018_update_aimmo_character_image_path.py,sha256=WKrxcjGjQ2pE4lcubkU37nsThmHbeVni9tCNSQWm8Sk,387
|
|
35
36
|
cfl_common/common/migrations/0019_aimmocharacter_alt.py,sha256=vhcO1-1TFNYJ2ILLj-tHq_z7jlhd9URwColHqTh11m8,418
|
|
36
37
|
cfl_common/common/migrations/0020_class_is_active_and_null_access_code.py,sha256=g0frY5T5AuVwCPIhj9UEtyB0lyMktl285eBJtLpN-zk,555
|
|
37
|
-
cfl_common/common/migrations/0021_school_is_active.py,sha256=
|
|
38
|
-
cfl_common/common/migrations/0022_school_cleanup.py,sha256=
|
|
39
|
-
cfl_common/common/migrations/0023_userprofile_aimmo_badges.py,sha256=
|
|
38
|
+
cfl_common/common/migrations/0021_school_is_active.py,sha256=S1HjZIalqLSbqrTu7AF0xvqZEbzcvLCCa1rMa7Pnc-w,736
|
|
39
|
+
cfl_common/common/migrations/0022_school_cleanup.py,sha256=r3YYnC6gJtBy5Ewa8_cjDxvK-W3oEm1IKopn-UXVyXg,661
|
|
40
|
+
cfl_common/common/migrations/0023_userprofile_aimmo_badges.py,sha256=NsOOw2XB03k4U5-2wDzuvN7P69IHLNKcjsPLMxmJbPM,515
|
|
40
41
|
cfl_common/common/migrations/0024_teacher_invited_by.py,sha256=UxsKaGB16y7NjH6mrqZceNLi3tERgLb7gxS14ozsTjw,632
|
|
41
|
-
cfl_common/common/migrations/0025_schoolteacherinvitation.py,sha256=
|
|
42
|
-
cfl_common/common/migrations/0026_teacher_remove_join_request.py,sha256=
|
|
43
|
-
cfl_common/common/migrations/0027_class_created_by.py,sha256=
|
|
44
|
-
cfl_common/common/migrations/0028_coding_club_downloads.py,sha256=
|
|
45
|
-
cfl_common/common/migrations/0029_dynamicelement.py,sha256=
|
|
46
|
-
cfl_common/common/migrations/0030_add_maintenance_banner.py,sha256=
|
|
47
|
-
cfl_common/common/migrations/0031_improve_admin_panel.py,sha256=
|
|
48
|
-
cfl_common/common/migrations/0032_dailyactivity_level_control_submits.py,sha256=
|
|
49
|
-
cfl_common/common/migrations/0033_password_reset_tracking_fields.py,sha256=
|
|
50
|
-
cfl_common/common/migrations/0034_dailyactivity_daily_school_student_lockout_reset.py,sha256=
|
|
51
|
-
cfl_common/common/migrations/0035_rename_lockout_fields.py,sha256=
|
|
42
|
+
cfl_common/common/migrations/0025_schoolteacherinvitation.py,sha256=Ba2gpIfeCkPGDnB6JqbM1DXlixkLqsbE3voKVK9Gvok,1819
|
|
43
|
+
cfl_common/common/migrations/0026_teacher_remove_join_request.py,sha256=U7hfnmNwQ0c6yzkiXhMrm2AdgrQszTjBal4U-v0H_VE,528
|
|
44
|
+
cfl_common/common/migrations/0027_class_created_by.py,sha256=H9T78SxvnrM0mjh5l_msa060MsJoWZ_bV-VizBElNpc,632
|
|
45
|
+
cfl_common/common/migrations/0028_coding_club_downloads.py,sha256=RLp7-M95MhwHCZfvo2qHfA_KZXa4pqXBni1Kaf26kOw,606
|
|
46
|
+
cfl_common/common/migrations/0029_dynamicelement.py,sha256=T48j7Uwik_H0bg8eFpSxB-PgxEfmPlPgrr19UFETrj4,684
|
|
47
|
+
cfl_common/common/migrations/0030_add_maintenance_banner.py,sha256=gZAVSbUPfZBTXHlJ_vjO4XwlAgIm6JcR59xZWawS4Ns,851
|
|
48
|
+
cfl_common/common/migrations/0031_improve_admin_panel.py,sha256=UAOBZUS5jR071ciQjO-CoEN6y4BJqMSD1YvYwJBd3FI,1665
|
|
49
|
+
cfl_common/common/migrations/0032_dailyactivity_level_control_submits.py,sha256=E6KiHkUXs1ka0SknETP_HXRTr1cKELPBIj5WgVdZNS8,417
|
|
50
|
+
cfl_common/common/migrations/0033_password_reset_tracking_fields.py,sha256=s2kqLCJBeAIeYJjdlRdXHlmNwZb7Czq7omJp51VKc8M,619
|
|
51
|
+
cfl_common/common/migrations/0034_dailyactivity_daily_school_student_lockout_reset.py,sha256=j3OKxJZTK4NQKVx2JkcK4o9Ie6C9yqbQHfZRsn4NIZg,438
|
|
52
|
+
cfl_common/common/migrations/0035_rename_lockout_fields.py,sha256=1UbvNJ1Qf2SNqGRRJCjXhxHi_rnJuToUW8DEF-tH0ZM,808
|
|
52
53
|
cfl_common/common/migrations/0036_rename_awaiting_email_verification_userprofile_is_verified.py,sha256=wmfENAwFqegcBJYk0wcFdgvY-m2BlGAFQjt-wNO6kBM,396
|
|
53
|
-
cfl_common/common/migrations/0037_migrate_email_verification.py,sha256=
|
|
54
|
-
cfl_common/common/migrations/0038_delete_emailverification.py,sha256=
|
|
55
|
-
cfl_common/common/migrations/0039_copy_email_to_username.py,sha256=
|
|
56
|
-
cfl_common/common/migrations/0040_school_county.py,sha256=
|
|
54
|
+
cfl_common/common/migrations/0037_migrate_email_verification.py,sha256=zC8rZ3xFhkbHqr3oUyTO2XHleqbx8o9wA2S_24_Y6kY,1018
|
|
55
|
+
cfl_common/common/migrations/0038_delete_emailverification.py,sha256=JTjGGrcJQY7sagMWLTn8jWP4Ldm99LwWo8Sn7QgfIgw,314
|
|
56
|
+
cfl_common/common/migrations/0039_copy_email_to_username.py,sha256=h2NwkcMJ1pBCVKtEj9spM72hG4zm0JnWKXkQI7i9p48,552
|
|
57
|
+
cfl_common/common/migrations/0040_school_county.py,sha256=LuPMnxLXOVZDlIeFtKr5wNrxBvVVrcjbnXyCjWgq4QQ,411
|
|
57
58
|
cfl_common/common/migrations/0041_populate_gb_counties.py,sha256=74pFXOqUcPh8fCyhlOGQNUd0yzfDCUDR-Y2aO6UyP_Y,898
|
|
58
|
-
cfl_common/common/migrations/0042_totalactivity.py,sha256=
|
|
59
|
+
cfl_common/common/migrations/0042_totalactivity.py,sha256=U8nY0lcnreU4ugWpt8xi8lSDDRDg3cnV7liYVU_MxNw,810
|
|
59
60
|
cfl_common/common/migrations/0043_add_total_activity.py,sha256=9dCx3-uCrmG5XS9snhTeFEOpaqFWZvjIvkgukYldZ4I,1065
|
|
60
|
-
cfl_common/common/migrations/0044_update_activity_models.py,sha256=
|
|
61
|
-
cfl_common/common/migrations/0045_otp.py,sha256=
|
|
62
|
-
cfl_common/common/migrations/0046_alter_school_country.py,sha256=
|
|
61
|
+
cfl_common/common/migrations/0044_update_activity_models.py,sha256=9ZwggtsiMB8LzKQEoyeDSIaADbz_wFk55bt-C9wSooY,997
|
|
62
|
+
cfl_common/common/migrations/0045_otp.py,sha256=_GmCOFOINqFMBqPBvdBaR1nwAI_FkzIlMTq_kfaN1IQ,599
|
|
63
|
+
cfl_common/common/migrations/0046_alter_school_country.py,sha256=dg_lexw7ALB-jlOm_EBQauk9mI4VbqUGv0qQsHo0b5s,437
|
|
63
64
|
cfl_common/common/migrations/0047_delete_school_postcode.py,sha256=GPV0hLfXmbPpx4-G5OaaLy6aalKvSnZLH0aGggYx9u0,331
|
|
64
65
|
cfl_common/common/migrations/0048_unique_school_names.py,sha256=pu5xiuesvFNGngD-hl0OQ6Gi2r6pEY9fPCayKyb9n04,1433
|
|
65
66
|
cfl_common/common/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -71,10 +72,10 @@ cfl_common/common/tests/test_migration_remove_teacher_title.py,sha256=wwm6tayb75
|
|
|
71
72
|
cfl_common/common/tests/test_models.py,sha256=xMdzonW5CADMjas_zfg8V1YPQpUetleyn6TE95hbO9k,3723
|
|
72
73
|
cfl_common/common/tests/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
73
74
|
cfl_common/common/tests/utils/classes.py,sha256=ZA2pp9Pyx3rwi0VFwtuUA2Pys9xQJ-L_zE0u2tpwEH4,1094
|
|
74
|
-
cfl_common/common/tests/utils/email.py,sha256=
|
|
75
|
+
cfl_common/common/tests/utils/email.py,sha256=lNLl1SoQUnRAI0Z7nuaUS8HQwt9YHVc-YB9rqdYzyrw,2190
|
|
75
76
|
cfl_common/common/tests/utils/organisation.py,sha256=vNgKFtU3VPcWRnZfh82yCS90PLAK1XTYJNIxGwfgUI4,966
|
|
76
|
-
cfl_common/common/tests/utils/student.py,sha256=
|
|
77
|
-
cfl_common/common/tests/utils/teacher.py,sha256=
|
|
77
|
+
cfl_common/common/tests/utils/student.py,sha256=XlgWT0TdbIY6w9uB4SqOoXmhxxCRnucEcPY9Q5Xva0U,4415
|
|
78
|
+
cfl_common/common/tests/utils/teacher.py,sha256=kY9LuP1mTEj_andYxF9k54xEHiJ36a6dokHxA9cB9f0,2500
|
|
78
79
|
cfl_common/common/tests/utils/user.py,sha256=NvLzZLVP4jy5Hn1iztOYF_BTQ9WsbSmuWMEzGzhAsRU,919
|
|
79
80
|
deploy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
80
81
|
deploy/captcha.py,sha256=MbOBuGnbT_SOIltSjP1XMOLrfo1DldCilaVAEim0vM4,23
|
|
@@ -95,11 +96,11 @@ deploy/static/robots.txt,sha256=5cS4RITuQhbpNzvpk4AyDCXdlIBfmfCoBYRvCHY2VT8,24
|
|
|
95
96
|
deploy/templates/deploy/csrf_failure.html,sha256=-pBRPn4Y7nUdYHGpTHCokT9Boi-isuwuivF8V2K1SgM,412
|
|
96
97
|
example_project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
97
98
|
example_project/manage.py,sha256=EUgybZlZ7xk2Zf2KCwBbK_z7gf7Ifqs0_bl4Kijhdgo,242
|
|
98
|
-
example_project/portal_test_settings.py,sha256=
|
|
99
|
+
example_project/portal_test_settings.py,sha256=fkbeU36YhWvNbR_hm28Rq4pV6ln-dGHK1VdML_1CToY,7227
|
|
99
100
|
example_project/settings.py,sha256=GLelTfsnhAuf_rqjXUoIWoLtzKvr-9l8UQDQ23rxPQc,5580
|
|
100
101
|
example_project/urls.py,sha256=OVeRQ-TCpzHISBRuzqD0yd3ewF7H5U3c-f2p2alfUD0,430
|
|
101
102
|
example_project/wsgi.py,sha256=U1W6WzZxZaIdYZ5tks7w9fqp5WS5qvn2iThsVcskrWw,829
|
|
102
|
-
portal/__init__.py,sha256=
|
|
103
|
+
portal/__init__.py,sha256=999dLIVurJM2yzNmRoSaZj8TtiA2BNl-SI7UXD1Wf3E,23
|
|
103
104
|
portal/admin.py,sha256=k5Hsiln43DlVPoufnrx5AXWu_RijX8xi_n7wwBuuCJo,5132
|
|
104
105
|
portal/app_settings.py,sha256=DhWLQOwM0zVOXE3O5TNKbMM9K6agfLuCsHOdr1J7xEI,651
|
|
105
106
|
portal/backends.py,sha256=2Dss6_WoQwPuDzJUF1yEaTQTNG4eUrD12ujJQ5cp5Tc,812
|
|
@@ -537,18 +538,18 @@ portal/tests/test_class.py,sha256=V6Fkc6PqdisefKD3xs9PbfE2pKp-9e0gwQVkPUiu6bk,14
|
|
|
537
538
|
portal/tests/test_daily_activities.py,sha256=-siDCMGBD1ijjccHVk7eEmrk4bgTsvbh0B6hDoj2fo0,1803
|
|
538
539
|
portal/tests/test_emails.py,sha256=-rI3FlJO7n9qfZ8Vz_Fe3DmjOngr4r23PCpjIoRxNY0,9133
|
|
539
540
|
portal/tests/test_helper_methods.py,sha256=-SQCDZm2XUtyXGEp0CHIb_SSC9CPD-XOSnpnY8QclHk,890
|
|
540
|
-
portal/tests/test_independent_student.py,sha256=
|
|
541
|
+
portal/tests/test_independent_student.py,sha256=Kl2dyZh6-4TdlwWpsi2w1q54SoC_P2YWEvjJXrd6LdY,25857
|
|
541
542
|
portal/tests/test_invite_teacher.py,sha256=oeOaoJV1IqJSYPlaPFjnhVXdB2mq8otCTLp_lfjuCfk,12224
|
|
542
543
|
portal/tests/test_middleware.py,sha256=b6jfNmiRZ2snqLKsyJUG-RivoX5fmrqLlQkG9MeVnqM,8034
|
|
543
544
|
portal/tests/test_newsletter_footer.py,sha256=MdVUX53mEoDTa4Krq-jg9LFNo-QyghqvTvhHeNXBGnE,838
|
|
544
545
|
portal/tests/test_organisation.py,sha256=fOtck-0MkPM2F0V4RFH-QUeWEk6yUIXDv_GI5cl8sdg,7649
|
|
545
546
|
portal/tests/test_partials.py,sha256=ydh1nef6BqvMfah2BSBS9QDiKY0xopY74k_W1YVobAE,3687
|
|
546
|
-
portal/tests/test_ratelimit.py,sha256
|
|
547
|
+
portal/tests/test_ratelimit.py,sha256=-nlQHOT0Mk_9IKnKYa_t82Y6EL6oZD8uVZ5rof4C1O0,19144
|
|
547
548
|
portal/tests/test_school_student.py,sha256=bFZwY4twaFHQLp0cltMq8cLNDZGgCHTZBCZHK0JcV8s,8604
|
|
548
549
|
portal/tests/test_security.py,sha256=FGrlRfnzi-Xx2_bn4fTZlYORKm7w_GhGkD3havvplwc,3239
|
|
549
|
-
portal/tests/test_teacher.py,sha256=
|
|
550
|
-
portal/tests/test_teacher_student.py,sha256=
|
|
551
|
-
portal/tests/test_views.py,sha256=
|
|
550
|
+
portal/tests/test_teacher.py,sha256=mft_xw97AkNi5OGprafpMMdGM1L1J_sMedBBg_Unb9k,36139
|
|
551
|
+
portal/tests/test_teacher_student.py,sha256=NWITbUw1kijqu3c8eRHLHJKaYQMOsOMvl7PAVx5QghI,21567
|
|
552
|
+
portal/tests/test_views.py,sha256=6y4ICpo5KPTWQed3J1Hg74ZGBKI2y3-HNHAowOsge80,38769
|
|
552
553
|
portal/tests/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
553
554
|
portal/tests/migrations/test_migration_make_portaladmin_teacher.py,sha256=ekMRb6cU97oT0k9gCKW7IUB7oPuGmv4uWJCqInQN7x8,2589
|
|
554
555
|
portal/tests/migrations/test_migration_preview_user_remove.py,sha256=K6D-FZT9YFEA8oMxHz9VTglVV6MZOTRYVlvwWwXc2vU,555
|
|
@@ -620,7 +621,7 @@ portal/views/teach.py,sha256=nzlyTcgq9ImAjnqrF3esqi212qBLH5Ww1LKE2gSjoRY,210
|
|
|
620
621
|
portal/views/aimmo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
621
622
|
portal/views/aimmo/dashboard.py,sha256=YMOzonNE87OEP5lThY4BrF0rNyvIYpDInh_sM-n38AM,4046
|
|
622
623
|
portal/views/cron/__init__.py,sha256=5rxXyhJmLOExRdrYZ1VJttTsyRIPRybzdftbUDwFByI,20
|
|
623
|
-
portal/views/cron/user.py,sha256=
|
|
624
|
+
portal/views/cron/user.py,sha256=N4slzEXqzp557LLPlwA6sD3HVzDu74NBf128uvtwKnM,6044
|
|
624
625
|
portal/views/login/__init__.py,sha256=xSCtyFPSI87BRUybBgqa86ekFEolX5gUDbBSfBUMTyI,399
|
|
625
626
|
portal/views/login/independent_student.py,sha256=3dFULhwMAlX4VDrJl-Znril6a9M5xKBSHO1eWvujfS0,2662
|
|
626
627
|
portal/views/login/student.py,sha256=4bQLLhB-KHvvjim07rYWXaLCZzHjUVofl0wrRkb1s0w,5224
|
|
@@ -635,8 +636,8 @@ portal/views/two_factor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
|
|
|
635
636
|
portal/views/two_factor/core.py,sha256=O_wcBeFqdPYSGNGv-pT_vbs5-Dj1Z-Jfkd6f9-E5yZI,760
|
|
636
637
|
portal/views/two_factor/form.py,sha256=lnHNKI-BMlpncTuW3zUzjPaJJNuEra2I_nOam0eOKFY,257
|
|
637
638
|
portal/views/two_factor/profile.py,sha256=tkl_ludo8arMtd5LKNmohM66vpC_YQiP-0nspTSJiJ4,383
|
|
638
|
-
codeforlife_portal-6.41.
|
|
639
|
-
codeforlife_portal-6.41.
|
|
640
|
-
codeforlife_portal-6.41.
|
|
641
|
-
codeforlife_portal-6.41.
|
|
642
|
-
codeforlife_portal-6.41.
|
|
639
|
+
codeforlife_portal-6.41.6.dist-info/LICENSE.md,sha256=9AbRlCDqD2D1tPibimysFv3zg3AIc49-eyv9aEsyq9w,115
|
|
640
|
+
codeforlife_portal-6.41.6.dist-info/METADATA,sha256=57Xioq1NyqGfmTvTgctiYOeTCqOfxc-u6jvMuGdoqR4,1169
|
|
641
|
+
codeforlife_portal-6.41.6.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
|
|
642
|
+
codeforlife_portal-6.41.6.dist-info/top_level.txt,sha256=8e5pdsuIoTqEAMqpelHBjGjLbffcBtgOoggmd2q7nMw,41
|
|
643
|
+
codeforlife_portal-6.41.6.dist-info/RECORD,,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Django settings for example_project project."""
|
|
2
|
+
|
|
2
3
|
import os
|
|
4
|
+
|
|
3
5
|
from selenium import webdriver
|
|
4
6
|
|
|
5
7
|
DEBUG = True
|
|
@@ -33,6 +35,8 @@ if os.environ.get("SELENIUM_HEADLESS", None):
|
|
|
33
35
|
ROOT_URLCONF = "example_project.urls"
|
|
34
36
|
SECRET_KEY = "bad_test_secret"
|
|
35
37
|
|
|
38
|
+
DOTDIGITAL_AUTH = "dummy_dotdigital_auth"
|
|
39
|
+
|
|
36
40
|
DOTMAILER_CREATE_CONTACT_URL = "https://test-create-contact/"
|
|
37
41
|
DOTMAILER_DELETE_USER_BY_ID_URL = "https://test-delete-contact/"
|
|
38
42
|
DOTMAILER_MAIN_ADDRESS_BOOK_URL = "https://test-main-address-book/"
|
|
@@ -169,7 +173,7 @@ TEMPLATES = [
|
|
|
169
173
|
"common.context_processors.cookie_management_enabled",
|
|
170
174
|
"portal.context_processors.process_newsletter_form",
|
|
171
175
|
]
|
|
172
|
-
}
|
|
176
|
+
},
|
|
173
177
|
}
|
|
174
178
|
]
|
|
175
179
|
|
portal/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "6.41.
|
|
1
|
+
__version__ = "6.41.6"
|
|
@@ -2,11 +2,16 @@ from __future__ import absolute_import
|
|
|
2
2
|
|
|
3
3
|
import datetime
|
|
4
4
|
import time
|
|
5
|
+
from unittest.mock import ANY, Mock, patch
|
|
5
6
|
|
|
7
|
+
from common.mail import campaign_ids
|
|
6
8
|
from common.models import JoinReleaseStudent
|
|
7
9
|
from common.tests.utils import email as email_utils
|
|
8
10
|
from common.tests.utils.classes import create_class_directly
|
|
9
|
-
from common.tests.utils.organisation import
|
|
11
|
+
from common.tests.utils.organisation import (
|
|
12
|
+
create_organisation_directly,
|
|
13
|
+
join_teacher_to_organisation,
|
|
14
|
+
)
|
|
10
15
|
from common.tests.utils.student import (
|
|
11
16
|
create_independent_student,
|
|
12
17
|
create_independent_student_directly,
|
|
@@ -137,7 +142,8 @@ class TestIndependentStudent(TestCase):
|
|
|
137
142
|
# Assert response isn't a redirect (submit failure)
|
|
138
143
|
assert response.status_code == 200
|
|
139
144
|
|
|
140
|
-
|
|
145
|
+
@patch("common.helpers.emails.send_dotdigital_email")
|
|
146
|
+
def test_signup_under_13_sends_parent_email(self, mock_send_dotdigital_email: Mock):
|
|
141
147
|
c = Client()
|
|
142
148
|
|
|
143
149
|
response = c.post(
|
|
@@ -156,8 +162,9 @@ class TestIndependentStudent(TestCase):
|
|
|
156
162
|
)
|
|
157
163
|
|
|
158
164
|
assert response.status_code == 302
|
|
159
|
-
|
|
160
|
-
|
|
165
|
+
mock_send_dotdigital_email.assert_called_once_with(
|
|
166
|
+
campaign_ids["verify_new_user_via_parent"], ANY, personalization_values=ANY
|
|
167
|
+
)
|
|
161
168
|
|
|
162
169
|
|
|
163
170
|
# Class for Selenium tests. We plan to replace these and turn them into Cypress tests
|
|
@@ -256,16 +263,20 @@ class TestIndependentStudentFrontend(BaseTest):
|
|
|
256
263
|
page = page.independent_student_login(username, password)
|
|
257
264
|
assert self.is_dashboard(page)
|
|
258
265
|
|
|
259
|
-
|
|
266
|
+
@patch("common.helpers.emails.send_dotdigital_email")
|
|
267
|
+
def test_login_not_verified(self, mock_send_dotdigital_email):
|
|
260
268
|
username, password, _ = create_independent_student_directly(preverified=False)
|
|
261
269
|
self.selenium.get(self.live_server_url)
|
|
262
270
|
page = HomePage(self.selenium)
|
|
263
271
|
page = page.go_to_independent_student_login_page()
|
|
264
272
|
page = page.independent_student_login_failure(username, password)
|
|
265
273
|
|
|
274
|
+
errors = page.has_login_failed("independent_student_login_form", INVALID_LOGIN_MESSAGE)
|
|
266
275
|
assert page.has_login_failed("independent_student_login_form", INVALID_LOGIN_MESSAGE)
|
|
267
276
|
|
|
268
|
-
|
|
277
|
+
verification_url = mock_send_dotdigital_email.call_args.kwargs["personalization_values"]["VERIFICATION_LINK"]
|
|
278
|
+
|
|
279
|
+
verify_email(page, verification_url)
|
|
269
280
|
|
|
270
281
|
assert is_email_verified_message_showing(self.selenium)
|
|
271
282
|
|
|
@@ -340,7 +351,8 @@ class TestIndependentStudentFrontend(BaseTest):
|
|
|
340
351
|
"student_account_form", "Names may only contain letters, numbers, dashes, underscores, and spaces."
|
|
341
352
|
)
|
|
342
353
|
|
|
343
|
-
|
|
354
|
+
@patch("common.helpers.emails.send_dotdigital_email")
|
|
355
|
+
def test_change_email(self, mock_send_dotdigital_email):
|
|
344
356
|
homepage = self.go_to_homepage()
|
|
345
357
|
|
|
346
358
|
_, _, _, student_email, password = create_independent_student(homepage)
|
|
@@ -354,9 +366,9 @@ class TestIndependentStudentFrontend(BaseTest):
|
|
|
354
366
|
assert is_student_details_updated_message_showing(self.selenium)
|
|
355
367
|
assert is_email_updated_message_showing(self.selenium)
|
|
356
368
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
369
|
+
mock_send_dotdigital_email.assert_called_with(
|
|
370
|
+
campaign_ids["email_change_notification"], ANY, personalization_values=ANY
|
|
371
|
+
)
|
|
360
372
|
|
|
361
373
|
# Try changing email to an existing teacher's email
|
|
362
374
|
teacher_email, _ = signup_teacher_directly()
|
|
@@ -372,9 +384,9 @@ class TestIndependentStudentFrontend(BaseTest):
|
|
|
372
384
|
assert is_student_details_updated_message_showing(self.selenium)
|
|
373
385
|
assert is_email_updated_message_showing(self.selenium)
|
|
374
386
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
387
|
+
mock_send_dotdigital_email.assert_called_with(
|
|
388
|
+
campaign_ids["email_change_notification"], ANY, personalization_values=ANY
|
|
389
|
+
)
|
|
378
390
|
|
|
379
391
|
page = (
|
|
380
392
|
self.go_to_homepage()
|
|
@@ -402,11 +414,12 @@ class TestIndependentStudentFrontend(BaseTest):
|
|
|
402
414
|
|
|
403
415
|
page = page.logout()
|
|
404
416
|
|
|
405
|
-
|
|
406
|
-
|
|
417
|
+
mock_send_dotdigital_email.assert_called_with(
|
|
418
|
+
campaign_ids["email_change_verification"], ANY, personalization_values=ANY
|
|
419
|
+
)
|
|
420
|
+
verification_url = mock_send_dotdigital_email.call_args.kwargs["personalization_values"]["VERIFICATION_LINK"]
|
|
407
421
|
|
|
408
|
-
page = email_utils.follow_change_email_link_to_independent_dashboard(page,
|
|
409
|
-
mail.outbox = []
|
|
422
|
+
page = email_utils.follow_change_email_link_to_independent_dashboard(page, verification_url)
|
|
410
423
|
|
|
411
424
|
page = page.independent_student_login(new_email, password)
|
|
412
425
|
|
portal/tests/test_ratelimit.py
CHANGED
|
@@ -2,10 +2,12 @@ from __future__ import absolute_import
|
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
4
|
from datetime import datetime, timedelta
|
|
5
|
+
from unittest.mock import ANY, Mock, patch
|
|
5
6
|
|
|
6
7
|
import pytest
|
|
7
8
|
import pytz
|
|
8
|
-
from common.
|
|
9
|
+
from common.mail import campaign_ids
|
|
10
|
+
from common.models import DailyActivity, Student, Teacher
|
|
9
11
|
from common.tests.utils.classes import create_class_directly
|
|
10
12
|
from common.tests.utils.organisation import create_organisation_directly
|
|
11
13
|
from common.tests.utils.student import (
|
|
@@ -13,11 +15,10 @@ from common.tests.utils.student import (
|
|
|
13
15
|
create_school_student_directly,
|
|
14
16
|
generate_independent_student_details,
|
|
15
17
|
)
|
|
16
|
-
from common.tests.utils.teacher import
|
|
18
|
+
from common.tests.utils.teacher import generate_details, signup_teacher_directly
|
|
17
19
|
from django.core import mail
|
|
18
20
|
from django.test import Client, TestCase
|
|
19
|
-
from django.urls import reverse
|
|
20
|
-
from django.urls import reverse_lazy
|
|
21
|
+
from django.urls import reverse, reverse_lazy
|
|
21
22
|
|
|
22
23
|
from portal.helpers.ratelimit import get_ratelimit_count_for_user
|
|
23
24
|
from portal.views.login import has_user_lockout_expired
|
|
@@ -432,8 +433,9 @@ class TestRatelimit(TestCase):
|
|
|
432
433
|
assert current_daily_activity.school_student_lockout_resets == 2
|
|
433
434
|
|
|
434
435
|
|
|
436
|
+
@patch("common.helpers.emails.send_dotdigital_email")
|
|
435
437
|
@pytest.mark.django_db
|
|
436
|
-
def test_teacher_already_registered_email(client):
|
|
438
|
+
def test_teacher_already_registered_email(mock_send_dotdigital_email: Mock, client):
|
|
437
439
|
first_name, last_name, email, password = generate_details()
|
|
438
440
|
register_url = reverse("register")
|
|
439
441
|
data = {
|
|
@@ -448,19 +450,20 @@ def test_teacher_already_registered_email(client):
|
|
|
448
450
|
|
|
449
451
|
# Register the teacher first time, there should be a registration email
|
|
450
452
|
client.post(register_url, data)
|
|
451
|
-
|
|
453
|
+
mock_send_dotdigital_email.assert_called_once_with(campaign_ids["verify_new_user"], ANY, personalization_values=ANY)
|
|
452
454
|
|
|
453
455
|
# Register with the same email again, there should also be an already registered email
|
|
454
456
|
client.post(register_url, data)
|
|
455
|
-
assert len(mail.outbox) ==
|
|
457
|
+
assert len(mail.outbox) == 1
|
|
456
458
|
|
|
457
459
|
# Register with the same email one more time, there shouldn't be any new emails
|
|
458
460
|
client.post(register_url, data)
|
|
459
|
-
assert len(mail.outbox) ==
|
|
461
|
+
assert len(mail.outbox) == 1
|
|
460
462
|
|
|
461
463
|
|
|
464
|
+
@patch("common.helpers.emails.send_dotdigital_email")
|
|
462
465
|
@pytest.mark.django_db
|
|
463
|
-
def test_independent_student_already_registered_email(client):
|
|
466
|
+
def test_independent_student_already_registered_email(mock_send_dotdigital_email: Mock, client):
|
|
464
467
|
name, username, email_address, password = generate_independent_student_details()
|
|
465
468
|
register_url = reverse("register")
|
|
466
469
|
data = {
|
|
@@ -477,12 +480,12 @@ def test_independent_student_already_registered_email(client):
|
|
|
477
480
|
|
|
478
481
|
# Register the independent student first time, there should be a registration email
|
|
479
482
|
client.post(register_url, data)
|
|
480
|
-
|
|
483
|
+
mock_send_dotdigital_email.assert_called_once_with(campaign_ids["verify_new_user"], ANY, personalization_values=ANY)
|
|
481
484
|
|
|
482
485
|
# Register with the same email again, there should also be an already registered email
|
|
483
486
|
client.post(register_url, data)
|
|
484
|
-
assert len(mail.outbox) ==
|
|
487
|
+
assert len(mail.outbox) == 1
|
|
485
488
|
|
|
486
489
|
# Reset mock and register with the same email one more time, there shouldn't be any new emails
|
|
487
490
|
client.post(register_url, data)
|
|
488
|
-
assert len(mail.outbox) ==
|
|
491
|
+
assert len(mail.outbox) == 1
|
portal/tests/test_teacher.py
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
from __future__ import absolute_import
|
|
2
2
|
|
|
3
|
-
import re
|
|
4
3
|
import time
|
|
5
4
|
from datetime import timedelta
|
|
5
|
+
from unittest.mock import ANY, Mock, patch
|
|
6
6
|
from uuid import uuid4
|
|
7
7
|
|
|
8
8
|
import jwt
|
|
9
9
|
from aimmo.models import Game
|
|
10
|
+
from common.mail import campaign_ids
|
|
10
11
|
from common.models import Class, Student, Teacher
|
|
11
12
|
from common.tests.utils import email as email_utils
|
|
12
13
|
from common.tests.utils.classes import create_class_directly
|
|
13
|
-
from common.tests.utils.organisation import
|
|
14
|
-
|
|
14
|
+
from common.tests.utils.organisation import (
|
|
15
|
+
create_organisation_directly,
|
|
16
|
+
join_teacher_to_organisation,
|
|
17
|
+
)
|
|
18
|
+
from common.tests.utils.student import (
|
|
19
|
+
create_independent_student_directly,
|
|
20
|
+
create_school_student_directly,
|
|
21
|
+
)
|
|
15
22
|
from common.tests.utils.teacher import (
|
|
16
23
|
signup_duplicate_teacher_fail,
|
|
17
24
|
signup_teacher,
|
|
@@ -357,7 +364,8 @@ class TestTeacher(TestCase):
|
|
|
357
364
|
# Assert response isn't a redirect (submit failure)
|
|
358
365
|
assert response.status_code == 200
|
|
359
366
|
|
|
360
|
-
|
|
367
|
+
@patch("common.helpers.emails.send_dotdigital_email")
|
|
368
|
+
def test_signup_email_verification(self, mock_send_dotdigital_email: Mock):
|
|
361
369
|
c = Client()
|
|
362
370
|
|
|
363
371
|
response = c.post(
|
|
@@ -374,7 +382,9 @@ class TestTeacher(TestCase):
|
|
|
374
382
|
)
|
|
375
383
|
|
|
376
384
|
assert response.status_code == 302
|
|
377
|
-
|
|
385
|
+
mock_send_dotdigital_email.assert_called_once_with(
|
|
386
|
+
campaign_ids["verify_new_user"], ANY, personalization_values=ANY
|
|
387
|
+
)
|
|
378
388
|
|
|
379
389
|
# Try verification URL with a fake token
|
|
380
390
|
fake_token = jwt.encode(
|
|
@@ -393,9 +403,8 @@ class TestTeacher(TestCase):
|
|
|
393
403
|
# Assert response isn't a redirect (get failure)
|
|
394
404
|
assert bad_verification_response.status_code == 200
|
|
395
405
|
|
|
396
|
-
# Get verification link from
|
|
397
|
-
|
|
398
|
-
verification_url = re.search("http.+/", message).group(0)
|
|
406
|
+
# Get verification link from function call
|
|
407
|
+
verification_url = mock_send_dotdigital_email.call_args.kwargs["personalization_values"]["VERIFICATION_LINK"]
|
|
399
408
|
|
|
400
409
|
# Verify the email properly
|
|
401
410
|
verification_response = c.get(verification_url)
|
|
@@ -472,7 +481,8 @@ class TestTeacherFrontend(BaseTest):
|
|
|
472
481
|
page = page.login(email, password)
|
|
473
482
|
assert self.is_dashboard_page(page)
|
|
474
483
|
|
|
475
|
-
|
|
484
|
+
@patch("common.helpers.emails.send_dotdigital_email")
|
|
485
|
+
def test_login_not_verified(self, mock_send_dotdigital_email):
|
|
476
486
|
email, password = signup_teacher_directly(preverified=False)
|
|
477
487
|
create_organisation_directly(email)
|
|
478
488
|
_, _, access_code = create_class_directly(email)
|
|
@@ -484,7 +494,9 @@ class TestTeacherFrontend(BaseTest):
|
|
|
484
494
|
|
|
485
495
|
assert page.has_login_failed("form-login-teacher", INVALID_LOGIN_MESSAGE)
|
|
486
496
|
|
|
487
|
-
|
|
497
|
+
verification_url = mock_send_dotdigital_email.call_args.kwargs["personalization_values"]["VERIFICATION_LINK"]
|
|
498
|
+
|
|
499
|
+
verify_email(page, verification_url)
|
|
488
500
|
|
|
489
501
|
assert is_email_verified_message_showing(self.selenium)
|
|
490
502
|
|
|
@@ -537,7 +549,8 @@ class TestTeacherFrontend(BaseTest):
|
|
|
537
549
|
|
|
538
550
|
assert page.check_account_details({"first_name": "Florian", "last_name": "Aucomte"})
|
|
539
551
|
|
|
540
|
-
|
|
552
|
+
@patch("common.helpers.emails.send_dotdigital_email")
|
|
553
|
+
def test_change_email(self, mock_send_dotdigital_email):
|
|
541
554
|
email, password = signup_teacher_directly()
|
|
542
555
|
create_organisation_directly(email)
|
|
543
556
|
_, _, access_code = create_class_directly(email)
|
|
@@ -553,9 +566,9 @@ class TestTeacherFrontend(BaseTest):
|
|
|
553
566
|
assert self.is_email_verification_page(page)
|
|
554
567
|
assert is_email_updated_message_showing(self.selenium)
|
|
555
568
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
569
|
+
mock_send_dotdigital_email.assert_called_with(
|
|
570
|
+
campaign_ids["email_change_notification"], ANY, personalization_values=ANY
|
|
571
|
+
)
|
|
559
572
|
|
|
560
573
|
# Try changing email to an existing indy student's email, should fail
|
|
561
574
|
indy_email, _, _ = create_independent_student_directly()
|
|
@@ -566,9 +579,9 @@ class TestTeacherFrontend(BaseTest):
|
|
|
566
579
|
assert self.is_email_verification_page(page)
|
|
567
580
|
assert is_email_updated_message_showing(self.selenium)
|
|
568
581
|
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
582
|
+
mock_send_dotdigital_email.assert_called_with(
|
|
583
|
+
campaign_ids["email_change_notification"], ANY, personalization_values=ANY
|
|
584
|
+
)
|
|
572
585
|
|
|
573
586
|
page = self.go_to_homepage()
|
|
574
587
|
page = page.go_to_teacher_login_page().login(email, password).open_account_tab()
|
|
@@ -586,11 +599,12 @@ class TestTeacherFrontend(BaseTest):
|
|
|
586
599
|
|
|
587
600
|
page = page.logout()
|
|
588
601
|
|
|
589
|
-
|
|
590
|
-
|
|
602
|
+
mock_send_dotdigital_email.assert_called_with(
|
|
603
|
+
campaign_ids["email_change_verification"], ANY, personalization_values=ANY
|
|
604
|
+
)
|
|
605
|
+
verification_url = mock_send_dotdigital_email.call_args.kwargs["personalization_values"]["VERIFICATION_LINK"]
|
|
591
606
|
|
|
592
|
-
page = email_utils.follow_change_email_link_to_dashboard(page,
|
|
593
|
-
mail.outbox = []
|
|
607
|
+
page = email_utils.follow_change_email_link_to_dashboard(page, verification_url)
|
|
594
608
|
|
|
595
609
|
page = page.login(new_email, password).open_account_tab()
|
|
596
610
|
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
from __future__ import absolute_import
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
from unittest.mock import Mock, patch
|
|
4
5
|
|
|
5
6
|
import pytest
|
|
6
7
|
from common.models import JoinReleaseStudent
|
|
7
8
|
from common.tests.utils.classes import create_class_directly
|
|
8
|
-
from common.tests.utils.organisation import
|
|
9
|
+
from common.tests.utils.organisation import (
|
|
10
|
+
create_organisation_directly,
|
|
11
|
+
join_teacher_to_organisation,
|
|
12
|
+
)
|
|
9
13
|
from common.tests.utils.student import (
|
|
10
14
|
create_many_school_students,
|
|
11
15
|
create_school_student,
|
|
@@ -528,7 +532,8 @@ class TestTeacherStudentFrontend(BaseTest):
|
|
|
528
532
|
page = page.logout().go_to_teacher_login_page().login(email_2, password_2).open_classes_tab().go_to_class_page()
|
|
529
533
|
assert page.student_exists(student_name_1)
|
|
530
534
|
|
|
531
|
-
|
|
535
|
+
@patch("common.helpers.emails.send_dotdigital_email")
|
|
536
|
+
def test_dismiss(self, mock_send_dotdigital_email: Mock):
|
|
532
537
|
email, password = signup_teacher_directly()
|
|
533
538
|
create_organisation_directly(email)
|
|
534
539
|
_, _, access_code = create_class_directly(email)
|
|
@@ -557,7 +562,10 @@ class TestTeacherStudentFrontend(BaseTest):
|
|
|
557
562
|
assert len(logs) == 1
|
|
558
563
|
assert logs[0].action_type == JoinReleaseStudent.RELEASE
|
|
559
564
|
|
|
560
|
-
|
|
565
|
+
mock_send_dotdigital_email.assert_called()
|
|
566
|
+
|
|
567
|
+
@patch("common.helpers.emails.send_dotdigital_email")
|
|
568
|
+
def test_multiple_dismiss(self, mock_send_dotdigital_email: Mock):
|
|
561
569
|
email, password = signup_teacher_directly()
|
|
562
570
|
create_organisation_directly(email)
|
|
563
571
|
_, _, access_code = create_class_directly(email)
|
|
@@ -597,3 +605,5 @@ class TestTeacherStudentFrontend(BaseTest):
|
|
|
597
605
|
|
|
598
606
|
# student should still exist
|
|
599
607
|
assert page.student_exists(student_name_2)
|
|
608
|
+
|
|
609
|
+
mock_send_dotdigital_email.assert_called()
|