codeforlife-portal 6.41.5__tar.gz → 6.41.7__tar.gz

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.

Files changed (567) hide show
  1. {codeforlife-portal-6.41.5/codeforlife_portal.egg-info → codeforlife-portal-6.41.7}/PKG-INFO +1 -1
  2. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7/codeforlife_portal.egg-info}/PKG-INFO +1 -1
  3. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/codeforlife_portal.egg-info/requires.txt +1 -1
  4. codeforlife-portal-6.41.7/portal/__init__.py +1 -0
  5. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/mouseflow.html +1 -1
  6. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/privacy_notice.html +5 -0
  7. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_independent_student.py +30 -17
  8. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_ratelimit.py +15 -12
  9. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_teacher.py +35 -21
  10. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_teacher_student.py +13 -3
  11. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_views.py +55 -194
  12. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/cron/user.py +12 -49
  13. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/pyproject.toml +6 -0
  14. codeforlife-portal-6.41.5/portal/__init__.py +0 -1
  15. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/LICENSE.md +0 -0
  16. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/MANIFEST.in +0 -0
  17. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/README.md +0 -0
  18. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/codeforlife_portal.egg-info/SOURCES.txt +0 -0
  19. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/codeforlife_portal.egg-info/dependency_links.txt +0 -0
  20. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/codeforlife_portal.egg-info/not-zip-safe +0 -0
  21. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/codeforlife_portal.egg-info/top_level.txt +0 -0
  22. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/__init__.py +0 -0
  23. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/captcha.py +0 -0
  24. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/middleware/__init__.py +0 -0
  25. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/middleware/admin_access.py +0 -0
  26. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/middleware/basicauth.py +0 -0
  27. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/middleware/exceptionlogging.py +0 -0
  28. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/middleware/screentime_warning.py +0 -0
  29. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/middleware/security.py +0 -0
  30. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/middleware/session_timeout.py +0 -0
  31. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/static/apple-touch-icon-120x120.png +0 -0
  32. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/static/apple-touch-icon-152x152.png +0 -0
  33. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/static/apple-touch-icon-180x180.png +0 -0
  34. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/static/apple-touch-icon-76x76.png +0 -0
  35. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/static/apple-touch-icon.png +0 -0
  36. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/static/robots.txt +0 -0
  37. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/templates/deploy/csrf_failure.html +0 -0
  38. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/deploy/views.py +0 -0
  39. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/admin.py +0 -0
  40. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/app_settings.py +0 -0
  41. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/backends.py +0 -0
  42. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/beta.py +0 -0
  43. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/context_processors.py +0 -0
  44. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/forms/__init__.py +0 -0
  45. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/forms/add_game.py +0 -0
  46. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/forms/admin.py +0 -0
  47. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/forms/dotmailer.py +0 -0
  48. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/forms/error_messages.py +0 -0
  49. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/forms/invite_teacher.py +0 -0
  50. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/forms/organisation.py +0 -0
  51. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/forms/play.py +0 -0
  52. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/forms/registration.py +0 -0
  53. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/forms/teach.py +0 -0
  54. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/handlers.py +0 -0
  55. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/helpers/__init__.py +0 -0
  56. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/helpers/captcha.py +0 -0
  57. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/helpers/decorators.py +0 -0
  58. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/helpers/password.py +0 -0
  59. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/helpers/ratelimit.py +0 -0
  60. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/helpers/regexes.py +0 -0
  61. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/helpers/request_handlers.py +0 -0
  62. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0001_squashed_0041_new_news.py +0 -0
  63. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0042_school_country.py +0 -0
  64. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0043_auto_20150430_0952.py +0 -0
  65. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0044_auto_20150430_0959.py +0 -0
  66. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0045_auto_20150430_1446.py +0 -0
  67. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0046_auto_20150723_1101.py +0 -0
  68. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0047_remove_userprofile_avatar.py +0 -0
  69. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0048_plural_management_frontnews.py +0 -0
  70. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0049_refactor_emailverifications.py +0 -0
  71. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0050_refactor_emailverifications_2.py +0 -0
  72. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0051_add_missing_ev_records.py +0 -0
  73. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0052_refactor_emailverifications_3.py +0 -0
  74. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0053_refactor_teacher_student_1.py +0 -0
  75. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0054_pending_join_request_can_be_blank.py +0 -0
  76. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0055_add_preview_user.py +0 -0
  77. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0056_remove_preview_user.py +0 -0
  78. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0057_delete_frontpagenews.py +0 -0
  79. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0058_move_to_common_models.py +0 -0
  80. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0059_move_email_verifications_to_common.py +0 -0
  81. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0060_delete_guardian.py +0 -0
  82. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0061_make_portaladmin_teacher.py +0 -0
  83. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/0062_verify_portaladmin.py +0 -0
  84. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/migrations/__init__.py +0 -0
  85. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/mixins/__init__.py +0 -0
  86. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/mixins/cron_mixin.py +0 -0
  87. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/models.py +0 -0
  88. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/permissions/__init__.py +0 -0
  89. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/permissions/is_cron_request_from_google.py +0 -0
  90. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/pipeline_compilers/__init__.py +0 -0
  91. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/pipeline_compilers/libsass_compiler.py +0 -0
  92. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.eot +0 -0
  93. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.svg +0 -0
  94. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.ttf +0 -0
  95. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.woff +0 -0
  96. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/fonts/bootstrap/glyphicons-halflings-regular.woff2 +0 -0
  97. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/10_years_anniversary.png +0 -0
  98. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/10x_logo.png +0 -0
  99. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/RR_logo_grass_background.png +0 -0
  100. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/RR_logo_green.svg +0 -0
  101. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/RR_logo_simple.png +0 -0
  102. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/about_us_cfl.jpg +0 -0
  103. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/about_us_hero.jpg +0 -0
  104. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/about_us_ocado.jpg +0 -0
  105. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/barefoot_logo.png +0 -0
  106. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/bcs_logo.png +0 -0
  107. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/clubs.png +0 -0
  108. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/coding_club_hero.jpg +0 -0
  109. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/coding_club_python_pack.png +0 -0
  110. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/colorboxImages/border.png +0 -0
  111. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/colorboxImages/controls.png +0 -0
  112. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/colorboxImages/loading.gif +0 -0
  113. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/colorboxImages/loading_background.png +0 -0
  114. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/colorboxImages/overlay.png +0 -0
  115. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/confirmation_tick.png +0 -0
  116. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/cross.png +0 -0
  117. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/dee.png +0 -0
  118. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/facebook.png +0 -0
  119. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/favicon.ico +0 -0
  120. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/get_involved_hero.png +0 -0
  121. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/gitbook.png +0 -0
  122. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/gitbook_space.png +0 -0
  123. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/github.png +0 -0
  124. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/github_hero.png +0 -0
  125. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/gla_logo.png +0 -0
  126. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/hamburger.png +0 -0
  127. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/help_and_support_hero.jpg +0 -0
  128. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/home_educate.png +0 -0
  129. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/home_educate_hero.jpg +0 -0
  130. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/home_learning_hero.jpg +0 -0
  131. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/home_play.png +0 -0
  132. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/home_play_hero.jpg +0 -0
  133. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/hope_logo.png +0 -0
  134. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/icl_logo.png +0 -0
  135. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/icon_controller.png +0 -0
  136. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/icon_free.png +0 -0
  137. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/icon_globe.png +0 -0
  138. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/icon_piechart.png +0 -0
  139. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/icon_step_by_step.png +0 -0
  140. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/icon_tracking.png +0 -0
  141. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/icon_uk_flag.png +0 -0
  142. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/kirsty.png +0 -0
  143. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/kurono_hero.jpg +0 -0
  144. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/kurono_landing_hero.png +0 -0
  145. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/kurono_logo.svg +0 -0
  146. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/kurono_logo_grey_background.svg +0 -0
  147. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/kurono_logo_mark.svg +0 -0
  148. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/kurono_resources_hero.jpg +0 -0
  149. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/kurono_story.png +0 -0
  150. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/logo_cfl.png +0 -0
  151. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/logo_cfl_reminder_cards.jpg +0 -0
  152. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/logo_cfl_white_landscape.png +0 -0
  153. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/logo_ocado.png +0 -0
  154. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/logo_ocado_group.png +0 -0
  155. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/logo_ocado_group.svg +0 -0
  156. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/logo_ocado_group_white.svg +0 -0
  157. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/mc_saatchi_logo.png +0 -0
  158. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/nigel.png +0 -0
  159. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/ocado-swirl.svg +0 -0
  160. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/oval_blue.svg +0 -0
  161. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/oval_pink.svg +0 -0
  162. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/oval_yellow.svg +0 -0
  163. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/paper_plane.png +0 -0
  164. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/phil.png +0 -0
  165. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/polygon_blue.svg +0 -0
  166. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/polygon_pink.svg +0 -0
  167. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/polygon_yellow.svg +0 -0
  168. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/pressure_cooker_logo.png +0 -0
  169. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/rapid_router.png +0 -0
  170. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/rapid_router_landing_hero.png +0 -0
  171. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/rapidrouter.png +0 -0
  172. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/resources_hero.jpg +0 -0
  173. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/resources_montage.jpg +0 -0
  174. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/reuben.png +0 -0
  175. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/rob.png +0 -0
  176. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/rr_advanced.png +0 -0
  177. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/rr_beginner.png +0 -0
  178. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/rr_intermediate.png +0 -0
  179. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/sadface.png +0 -0
  180. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/sharon_harrison.jpg +0 -0
  181. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/sian.png +0 -0
  182. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/teaching_resources_hero.jpg +0 -0
  183. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/thumbnail_educate_kurono.png +0 -0
  184. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/thumbnail_educate_rapid_router.png +0 -0
  185. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/thumbnail_educate_resources.png +0 -0
  186. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/thumbnail_intro_c4l.jpg +0 -0
  187. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/thumbnail_kurono_resources.png +0 -0
  188. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/thumbnail_play_kurono.png +0 -0
  189. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/thumbnail_play_rapid_router.png +0 -0
  190. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/twitter.png +0 -0
  191. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/universities.png +0 -0
  192. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/wes.png +0 -0
  193. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/img/x_close_video.png +0 -0
  194. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/aimmoGame.js +0 -0
  195. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/bootstrap.min.js +0 -0
  196. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/carouselCards.js +0 -0
  197. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/common.js +0 -0
  198. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/independentLogin.js +0 -0
  199. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/independentRegistration.js +0 -0
  200. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/join_create_game_toggle.js +0 -0
  201. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/jquery.placeholder.js +0 -0
  202. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/levelControl.js +0 -0
  203. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/lib/jquery-video-lightning.js +0 -0
  204. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/lib/jquery.colorbox.js +0 -0
  205. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/lib/jquery.easy-ticker.js +0 -0
  206. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/lib/jquery.min.js +0 -0
  207. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/lib/modernizr-build.js +0 -0
  208. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/lib/papaparse.min.js +0 -0
  209. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/organisation_manage.js +0 -0
  210. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/passwordStrength.js +0 -0
  211. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/play.js +0 -0
  212. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/resetPassword.js +0 -0
  213. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/riveted.min.js +0 -0
  214. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/school.js +0 -0
  215. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/sticky_subnav.js +0 -0
  216. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/studentLogin.js +0 -0
  217. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/teach_browser.js +0 -0
  218. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/teach_class.js +0 -0
  219. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/teacherEditStudent.js +0 -0
  220. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/js/teacherLogin.js +0 -0
  221. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_alerts.scss +0 -0
  222. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_badges.scss +0 -0
  223. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_breadcrumbs.scss +0 -0
  224. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_button-groups.scss +0 -0
  225. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_buttons.scss +0 -0
  226. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_carousel.scss +0 -0
  227. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_close.scss +0 -0
  228. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_code.scss +0 -0
  229. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_component-animations.scss +0 -0
  230. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_dropdowns.scss +0 -0
  231. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_forms.scss +0 -0
  232. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_glyphicons.scss +0 -0
  233. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_grid.scss +0 -0
  234. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_input-groups.scss +0 -0
  235. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_jumbotron.scss +0 -0
  236. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_labels.scss +0 -0
  237. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_list-group.scss +0 -0
  238. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_media.scss +0 -0
  239. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_mixins.scss +0 -0
  240. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_modals.scss +0 -0
  241. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_navbar.scss +0 -0
  242. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_navs.scss +0 -0
  243. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_normalize.scss +0 -0
  244. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_pager.scss +0 -0
  245. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_pagination.scss +0 -0
  246. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_panels.scss +0 -0
  247. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_popovers.scss +0 -0
  248. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_print.scss +0 -0
  249. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_progress-bars.scss +0 -0
  250. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_responsive-embed.scss +0 -0
  251. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_responsive-utilities.scss +0 -0
  252. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_scaffolding.scss +0 -0
  253. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_tables.scss +0 -0
  254. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_theme.scss +0 -0
  255. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_thumbnails.scss +0 -0
  256. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_tooltip.scss +0 -0
  257. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_type.scss +0 -0
  258. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_utilities.scss +0 -0
  259. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_variables.scss +0 -0
  260. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/_wells.scss +0 -0
  261. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_alerts.scss +0 -0
  262. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_background-variant.scss +0 -0
  263. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_border-radius.scss +0 -0
  264. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_breakpoints.scss +0 -0
  265. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_buttons.scss +0 -0
  266. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_center-block.scss +0 -0
  267. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_clearfix.scss +0 -0
  268. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_forms.scss +0 -0
  269. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_gradients.scss +0 -0
  270. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_grid-framework.scss +0 -0
  271. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_grid.scss +0 -0
  272. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_hide-text.scss +0 -0
  273. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_image.scss +0 -0
  274. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_labels.scss +0 -0
  275. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_list-group.scss +0 -0
  276. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_nav-divider.scss +0 -0
  277. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_nav-vertical-align.scss +0 -0
  278. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_opacity.scss +0 -0
  279. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_pagination.scss +0 -0
  280. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_panels.scss +0 -0
  281. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_progress-bar.scss +0 -0
  282. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_reset-filter.scss +0 -0
  283. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_reset-text.scss +0 -0
  284. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_resize.scss +0 -0
  285. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_responsive-visibility.scss +0 -0
  286. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_size.scss +0 -0
  287. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_tab-focus.scss +0 -0
  288. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_table-row.scss +0 -0
  289. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_text-emphasis.scss +0 -0
  290. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_text-overflow.scss +0 -0
  291. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_text-truncate.scss +0 -0
  292. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap/mixins/_vendor-prefixes.scss +0 -0
  293. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap.scss +0 -0
  294. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_mixins/_all.scss +0 -0
  295. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_mixins/_border-radius.scss +0 -0
  296. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_mixins/_box-shadow.scss +0 -0
  297. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_mixins/_hover.scss +0 -0
  298. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_mixins/_nav-divider.scss +0 -0
  299. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_partials/_dropdown.scss +0 -0
  300. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_partials/_glyphicons.scss +0 -0
  301. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_partials/_grid.scss +0 -0
  302. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_partials/_variables.scss +0 -0
  303. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_utilities/_align.scss +0 -0
  304. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_utilities/_background.scss +0 -0
  305. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_utilities/_borders.scss +0 -0
  306. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_utilities/_clearfix.scss +0 -0
  307. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_utilities/_cursor.scss +0 -0
  308. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_utilities/_display.scss +0 -0
  309. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_utilities/_flex.scss +0 -0
  310. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_utilities/_float.scss +0 -0
  311. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_utilities/_position.scss +0 -0
  312. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_utilities/_screenreaders.scss +0 -0
  313. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_utilities/_sizing.scss +0 -0
  314. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_utilities/_spacing.scss +0 -0
  315. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_utilities/_text.scss +0 -0
  316. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/bootstrap_utilities/_visibility.scss +0 -0
  317. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/colorbox.scss +0 -0
  318. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/modules/_all.scss +0 -0
  319. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/modules/_animation.scss +0 -0
  320. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/modules/_breakpoints.scss +0 -0
  321. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/modules/_card_constants.scss +0 -0
  322. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/modules/_colours.scss +0 -0
  323. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/modules/_homepage_constants.scss +0 -0
  324. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/modules/_levels.scss +0 -0
  325. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/modules/_mixins.scss +0 -0
  326. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/modules/_spacing.scss +0 -0
  327. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_banners.scss +0 -0
  328. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_base.scss +0 -0
  329. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_buttons.scss +0 -0
  330. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_carousel.scss +0 -0
  331. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_footer.scss +0 -0
  332. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_forms.scss +0 -0
  333. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_grids.scss +0 -0
  334. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_header.scss +0 -0
  335. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_images.scss +0 -0
  336. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_popup.scss +0 -0
  337. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_progress-bars.scss +0 -0
  338. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_subnavs.scss +0 -0
  339. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_tables.scss +0 -0
  340. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_text.scss +0 -0
  341. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_ui-dialog.scss +0 -0
  342. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_utils.scss +0 -0
  343. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/partials/_videos.scss +0 -0
  344. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/sass/styles.scss +0 -0
  345. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/video/aimmo_play_now_background_video.mp4 +0 -0
  346. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/static/portal/video/code for life .pdf +0 -0
  347. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/strings/__init__.py +0 -0
  348. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/strings/about.py +0 -0
  349. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/strings/coding_club.py +0 -0
  350. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/strings/help_and_support.py +0 -0
  351. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/strings/home_learning.py +0 -0
  352. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/strings/materials.py +0 -0
  353. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/strings/play.py +0 -0
  354. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/strings/student_aimmo_dashboard.py +0 -0
  355. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/strings/teach.py +0 -0
  356. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/strings/teacher_resources.py +0 -0
  357. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/403.html +0 -0
  358. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/404.html +0 -0
  359. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/500.html +0 -0
  360. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/captcha/includes/js_v2_invisible.html +0 -0
  361. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/captcha/widget_v2_invisible.html +0 -0
  362. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/email.html +0 -0
  363. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/email.txt +0 -0
  364. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/about.html +0 -0
  365. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/base.html +0 -0
  366. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/base_no_userprofile.html +0 -0
  367. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/coding_club.html +0 -0
  368. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/contribute.html +0 -0
  369. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/dotmailer_consent_form.html +0 -0
  370. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/email_invitation_sent.html +0 -0
  371. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/email_style_template.html +0 -0
  372. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/email_verification_failed.html +0 -0
  373. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/email_verification_needed.html +0 -0
  374. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/form_shapes.html +0 -0
  375. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/getinvolved.html +0 -0
  376. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/home.html +0 -0
  377. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/home_learning.html +0 -0
  378. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/locked_out.html +0 -0
  379. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/locked_out_school_student.html +0 -0
  380. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/login/independent_student.html +0 -0
  381. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/login/student.html +0 -0
  382. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/login/student_class_code.html +0 -0
  383. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/login/teacher.html +0 -0
  384. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/aimmo_games_table.html +0 -0
  385. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/banner.html +0 -0
  386. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/benefits.html +0 -0
  387. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/card_list.html +0 -0
  388. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/character_list.html +0 -0
  389. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/delete_popup.html +0 -0
  390. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/footer.html +0 -0
  391. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/header.html +0 -0
  392. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/headline.html +0 -0
  393. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/hero_card.html +0 -0
  394. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/info_popup.html +0 -0
  395. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/invite_admin_teacher.html +0 -0
  396. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/popup.html +0 -0
  397. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/register_newsletter_tickbox.html +0 -0
  398. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/screentime_popup.html +0 -0
  399. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/service_unavailable_popup.html +0 -0
  400. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/session_popup.html +0 -0
  401. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/teacher_non_dashboard_subnav.html +0 -0
  402. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/partials/teacher_non_dashboard_subnav_account.html +0 -0
  403. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/play/independent_student_dashboard.html +0 -0
  404. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/play/student_aimmo_dashboard.html +0 -0
  405. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/play/student_dashboard.html +0 -0
  406. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/play/student_edit_account.html +0 -0
  407. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/play/student_join_organisation.html +0 -0
  408. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/play.html +0 -0
  409. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/register.html +0 -0
  410. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/reset_password.html +0 -0
  411. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/reset_password_confirm.html +0 -0
  412. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/reset_password_done.html +0 -0
  413. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/reset_password_email_sent.html +0 -0
  414. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/tag_manager/tag_manager_body.html +0 -0
  415. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/tag_manager/tag_manager_head.html +0 -0
  416. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/base_registering.html +0 -0
  417. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/class.html +0 -0
  418. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/dashboard.html +0 -0
  419. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/invited.html +0 -0
  420. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/onboarding_classes.html +0 -0
  421. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/onboarding_print.html +0 -0
  422. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/onboarding_school.html +0 -0
  423. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/onboarding_students.html +0 -0
  424. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/teacher_add_external_student.html +0 -0
  425. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/teacher_added_external_student.html +0 -0
  426. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/teacher_aimmo_dashboard.html +0 -0
  427. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/teacher_dismiss_students.html +0 -0
  428. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/teacher_edit_class.html +0 -0
  429. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/teacher_edit_student.html +0 -0
  430. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/teacher_move_all_classes.html +0 -0
  431. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/teacher_move_students.html +0 -0
  432. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach/teacher_move_students_to_class.html +0 -0
  433. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/teach.html +0 -0
  434. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/portal/terms.html +0 -0
  435. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/two_factor/_base.html +0 -0
  436. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/two_factor/_wizard_actions.html +0 -0
  437. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/two_factor/_wizard_actions_enable_2fa.html +0 -0
  438. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/two_factor/_wizard_actions_submit.html +0 -0
  439. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/two_factor/_wizard_forms.html +0 -0
  440. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/two_factor/_wizard_forms_token.html +0 -0
  441. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/two_factor/backup_token.html +0 -0
  442. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/two_factor/core/backup_tokens.html +0 -0
  443. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/two_factor/core/login.html +0 -0
  444. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/two_factor/core/setup.html +0 -0
  445. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/two_factor/core/setup_complete.html +0 -0
  446. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/two_factor/profile/disable.html +0 -0
  447. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/two_factor/profile/profile.html +0 -0
  448. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templates/two_factor/setup_wizard_token.html +0 -0
  449. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templatetags/__init__.py +0 -0
  450. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templatetags/app_tags.py +0 -0
  451. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templatetags/banner_tags.py +0 -0
  452. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templatetags/benefits_tags.py +0 -0
  453. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templatetags/card_list_tags.py +0 -0
  454. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templatetags/character_list_tags.py +0 -0
  455. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templatetags/future.py +0 -0
  456. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templatetags/headline_tags.py +0 -0
  457. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templatetags/hero_card_tags.py +0 -0
  458. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/templatetags/table_tags.py +0 -0
  459. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/__init__.py +0 -0
  460. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/base_test.py +0 -0
  461. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/conftest.py +0 -0
  462. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/migrations/__init__.py +0 -0
  463. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/migrations/test_migration_make_portaladmin_teacher.py +0 -0
  464. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/migrations/test_migration_preview_user_remove.py +0 -0
  465. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/migrations/test_migration_preview_users.py +0 -0
  466. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/migrations/test_migration_remove_front_page_news.py +0 -0
  467. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/migrations/test_migration_remove_guardian.py +0 -0
  468. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/migrations/test_migration_use_common_models.py +0 -0
  469. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/migrations/test_migration_verify_portaladmin.py +0 -0
  470. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/__init__.py +0 -0
  471. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/__init__.py +0 -0
  472. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/admin/__init__.py +0 -0
  473. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/admin/admin_base_page.py +0 -0
  474. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/admin/admin_data_page.py +0 -0
  475. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/admin/admin_map_page.py +0 -0
  476. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/base_page.py +0 -0
  477. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/email_verification_needed_page.py +0 -0
  478. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/forbidden_page.py +0 -0
  479. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/game_page.py +0 -0
  480. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/home_page.py +0 -0
  481. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/independent_login_page.py +0 -0
  482. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/kurono_teacher_dashboard_page.py +0 -0
  483. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/password_reset_form_page.py +0 -0
  484. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/password_reset_page.py +0 -0
  485. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/play/__init__.py +0 -0
  486. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/play/account_page.py +0 -0
  487. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/play/dashboard_page.py +0 -0
  488. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/play/join_school_or_club_page.py +0 -0
  489. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/play/play_base_page.py +0 -0
  490. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/play_page.py +0 -0
  491. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/resources_page.py +0 -0
  492. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/signup_page.py +0 -0
  493. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/student_login_class_code.py +0 -0
  494. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/student_login_page.py +0 -0
  495. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/__init__.py +0 -0
  496. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/add_independent_student_to_class_page.py +0 -0
  497. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/added_independent_student_to_class_page.py +0 -0
  498. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/class_page.py +0 -0
  499. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/dashboard_page.py +0 -0
  500. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/dismiss_students_page.py +0 -0
  501. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/edit_student_page.py +0 -0
  502. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/move_class_page.py +0 -0
  503. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/move_classes_page.py +0 -0
  504. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/move_students_disambiguate_page.py +0 -0
  505. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/move_students_page.py +0 -0
  506. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/onboarding_classes_page.py +0 -0
  507. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/onboarding_organisation_page.py +0 -0
  508. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/onboarding_student_list_page.py +0 -0
  509. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/onboarding_students_page.py +0 -0
  510. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teach/teach_base_page.py +0 -0
  511. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/pageObjects/portal/teacher_login_page.py +0 -0
  512. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/selenium_test_case.py +0 -0
  513. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/snapshots/__init__.py +0 -0
  514. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/snapshots/snap_test_partials.py +0 -0
  515. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_2FA.py +0 -0
  516. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_admin.py +0 -0
  517. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_aimmo_dashboards.py +0 -0
  518. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_api.py +0 -0
  519. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_captcha_forms.py +0 -0
  520. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_class.py +0 -0
  521. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_daily_activities.py +0 -0
  522. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_emails.py +0 -0
  523. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_helper_methods.py +0 -0
  524. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_invite_teacher.py +0 -0
  525. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_middleware.py +0 -0
  526. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_newsletter_footer.py +0 -0
  527. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_organisation.py +0 -0
  528. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_partials.py +0 -0
  529. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_school_student.py +0 -0
  530. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/test_security.py +0 -0
  531. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/utils/__init__.py +0 -0
  532. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/utils/aimmo_games.py +0 -0
  533. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/utils/classes.py +0 -0
  534. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/tests/utils/messages.py +0 -0
  535. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/urls.py +0 -0
  536. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/__init__.py +0 -0
  537. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/about.py +0 -0
  538. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/admin.py +0 -0
  539. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/aimmo/__init__.py +0 -0
  540. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/aimmo/dashboard.py +0 -0
  541. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/api.py +0 -0
  542. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/cron/__init__.py +0 -0
  543. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/dotmailer.py +0 -0
  544. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/email.py +0 -0
  545. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/home.py +0 -0
  546. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/legal.py +0 -0
  547. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/login/__init__.py +0 -0
  548. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/login/independent_student.py +0 -0
  549. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/login/student.py +0 -0
  550. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/login/teacher.py +0 -0
  551. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/organisation.py +0 -0
  552. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/play_landing_page.py +0 -0
  553. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/registration.py +0 -0
  554. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/student/__init__.py +0 -0
  555. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/student/edit_account_details.py +0 -0
  556. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/student/play.py +0 -0
  557. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/teach.py +0 -0
  558. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/teacher/__init__.py +0 -0
  559. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/teacher/dashboard.py +0 -0
  560. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/teacher/teach.py +0 -0
  561. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/two_factor/__init__.py +0 -0
  562. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/two_factor/core.py +0 -0
  563. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/two_factor/form.py +0 -0
  564. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/views/two_factor/profile.py +0 -0
  565. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/portal/wsgi.py +0 -0
  566. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/setup.cfg +0 -0
  567. {codeforlife-portal-6.41.5 → codeforlife-portal-6.41.7}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codeforlife-portal
3
- Version: 6.41.5
3
+ Version: 6.41.7
4
4
  Classifier: Programming Language :: Python
5
5
  Classifier: Programming Language :: Python :: 3.8
6
6
  Classifier: Framework :: Django
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codeforlife-portal
3
- Version: 6.41.5
3
+ Version: 6.41.7
4
4
  Classifier: Programming Language :: Python
5
5
  Classifier: Programming Language :: Python :: 3.8
6
6
  Classifier: Framework :: Django
@@ -18,7 +18,7 @@ sqlparse==0.4.4
18
18
  libsass==0.22.0
19
19
  phonenumbers==8.12.12
20
20
  more-itertools==8.7.0
21
- cfl-common==6.41.5
21
+ cfl-common==6.41.7
22
22
  django-ratelimit==3.0.1
23
23
  django-preventconcurrentlogins==0.8.2
24
24
  django-csp==3.7
@@ -0,0 +1 @@
1
+ __version__ = "6.41.7"
@@ -1,4 +1,4 @@
1
- <script type="text/plain" class="optanon-category-CL002">
1
+ <script type="text/plain" class="optanon-category-C0002">
2
2
  var _mfq = _mfq || [];
3
3
  (function() {
4
4
  var mf = document.createElement("script");
@@ -666,6 +666,11 @@
666
666
  also information about the device you use (like the device type (desktop/tablet/phone), location
667
667
  (city/country) and language). Mouseflow does not collect any information on pages where it is not installed
668
668
  and does not track or collect information outside your web browser.</p>
669
+ <p><strong>YouTube</strong>. While embedded YouTube videos on our website do not use cookies, your browser's
670
+ Local Storage may be used by the video platform provider to enhance your viewing experience and collect
671
+ analytics data. This data enables the platform to track your interaction with the video content and may
672
+ gather information about your device and browsing behavior. The use of Local Storage by embedded video
673
+ providers is subject to their respective policies.</p>
669
674
 
670
675
  <h6>Managing and disabling cookies</h6>
671
676
 
@@ -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 create_organisation_directly, join_teacher_to_organisation
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
- def test_signup_under_13_sends_parent_email(self):
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
- assert len(mail.outbox) == 1
160
- assert mail.outbox[0].subject == "Code for Life account request"
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
- def test_login_not_verified(self):
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
- verify_email(page)
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
- def test_change_email(self):
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
- subject = str(mail.outbox[0].subject)
358
- assert subject == "Email address update"
359
- mail.outbox = []
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
- subject = str(mail.outbox[0].subject)
376
- assert subject == "Email address update"
377
- mail.outbox = []
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
- subject = str(mail.outbox[0].subject)
406
- assert subject == "Email address update"
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, mail.outbox[1])
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
 
@@ -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.models import Teacher, Student, DailyActivity
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 signup_teacher_directly, generate_details
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
- assert len(mail.outbox) == 1
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) == 2
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) == 2
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
- assert len(mail.outbox) == 1
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) == 2
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) == 2
491
+ assert len(mail.outbox) == 1
@@ -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 create_organisation_directly, join_teacher_to_organisation
14
- from common.tests.utils.student import create_independent_student_directly, create_school_student_directly
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
- def test_signup_email_verification(self):
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
- assert len(mail.outbox) == 1
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 email
397
- message = str(mail.outbox[0].body)
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
- def test_login_not_verified(self):
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
- verify_email(page)
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
- def test_change_email(self):
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
- subject = str(mail.outbox[0].subject)
557
- assert subject == "Email address update"
558
- mail.outbox = []
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
- subject = str(mail.outbox[0].subject)
570
- assert subject == "Email address update"
571
- mail.outbox = []
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
- subject = str(mail.outbox[0].subject)
590
- assert subject == "Email address update"
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, mail.outbox[1])
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 create_organisation_directly, join_teacher_to_organisation
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
- def test_dismiss(self):
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
- def test_multiple_dismiss(self):
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()