codeforlife-portal 5.32.2__py2.py3-none-any.whl → 8.9.9__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.
- cfl_common/common/__init__.py +1 -0
- cfl_common/common/app_settings.py +66 -0
- cfl_common/common/apps.py +6 -0
- cfl_common/common/context_processors.py +9 -0
- cfl_common/common/csp_config.py +85 -0
- cfl_common/common/helpers/__init__.py +0 -0
- cfl_common/common/helpers/data_migration_loader.py +42 -0
- cfl_common/common/helpers/emails.py +393 -0
- cfl_common/common/helpers/generators.py +52 -0
- cfl_common/common/helpers/organisation.py +10 -0
- cfl_common/common/mail.py +201 -0
- cfl_common/common/migrations/0001_initial.py +240 -0
- cfl_common/common/migrations/0002_emailverification.py +55 -0
- cfl_common/common/migrations/0003_aimmocharacter.py +31 -0
- cfl_common/common/migrations/0004_add_aimmocharacters.py +17 -0
- cfl_common/common/migrations/0005_add_worksheets.py +8 -0
- cfl_common/common/migrations/0006_update_aimmo_character_image_path.py +17 -0
- cfl_common/common/migrations/0007_add_pdf_names_to_first_two_worksheets.py +8 -0
- cfl_common/common/migrations/0008_unlock_worksheet_3.py +11 -0
- cfl_common/common/migrations/0009_add_blocked_time_to_teacher_and_student.py +24 -0
- cfl_common/common/migrations/0010_remove_teacher_title.py +18 -0
- cfl_common/common/migrations/0011_student_login_id.py +18 -0
- cfl_common/common/migrations/0012_usersession.py +39 -0
- cfl_common/common/migrations/0013_class_school.py +42 -0
- cfl_common/common/migrations/0014_login_type.py +29 -0
- cfl_common/common/migrations/0015_dailyactivity.py +31 -0
- cfl_common/common/migrations/0016_joinreleasestudent.py +42 -0
- cfl_common/common/migrations/0017_copy_email_to_username.py +18 -0
- cfl_common/common/migrations/0018_update_aimmo_character_image_path.py +15 -0
- cfl_common/common/migrations/0019_aimmocharacter_alt.py +16 -0
- cfl_common/common/migrations/0020_class_is_active_and_null_access_code.py +23 -0
- cfl_common/common/migrations/0021_school_is_active.py +28 -0
- cfl_common/common/migrations/0022_school_cleanup.py +29 -0
- cfl_common/common/migrations/0023_userprofile_aimmo_badges.py +22 -0
- cfl_common/common/migrations/0024_teacher_invited_by.py +25 -0
- cfl_common/common/migrations/0025_schoolteacherinvitation.py +47 -0
- cfl_common/common/migrations/0026_teacher_remove_join_request.py +22 -0
- cfl_common/common/migrations/0027_class_created_by.py +25 -0
- cfl_common/common/migrations/0028_coding_club_downloads.py +23 -0
- cfl_common/common/migrations/0029_dynamicelement.py +22 -0
- cfl_common/common/migrations/0030_add_maintenance_banner.py +25 -0
- cfl_common/common/migrations/0031_improve_admin_panel.py +56 -0
- cfl_common/common/migrations/0032_dailyactivity_level_control_submits.py +18 -0
- cfl_common/common/migrations/0033_password_reset_tracking_fields.py +23 -0
- cfl_common/common/migrations/0034_dailyactivity_daily_school_student_lockout_reset.py +18 -0
- cfl_common/common/migrations/0035_rename_lockout_fields.py +27 -0
- cfl_common/common/migrations/0036_rename_awaiting_email_verification_userprofile_is_verified.py +17 -0
- cfl_common/common/migrations/0037_migrate_email_verification.py +21 -0
- cfl_common/common/migrations/0038_delete_emailverification.py +16 -0
- cfl_common/common/migrations/0039_copy_email_to_username.py +18 -0
- cfl_common/common/migrations/0040_school_county.py +18 -0
- cfl_common/common/migrations/0041_populate_gb_counties.py +27 -0
- cfl_common/common/migrations/0042_totalactivity.py +25 -0
- cfl_common/common/migrations/0043_add_total_activity.py +30 -0
- cfl_common/common/migrations/0044_update_activity_models.py +33 -0
- cfl_common/common/migrations/0045_otp.py +23 -0
- cfl_common/common/migrations/0046_alter_school_country.py +19 -0
- cfl_common/common/migrations/0047_delete_school_postcode.py +16 -0
- cfl_common/common/migrations/0048_unique_school_names.py +42 -0
- cfl_common/common/migrations/0049_anonymise_orphan_users.py +29 -0
- cfl_common/common/migrations/0050_anonymise_orphan_schools.py +30 -0
- cfl_common/common/migrations/0051_verify_returning_users.py +26 -0
- cfl_common/common/migrations/0052_add_cse_fields.py +68 -0
- cfl_common/common/migrations/0053_clean_class_data.py +24 -0
- cfl_common/common/migrations/0054_delete_aimmo_models.py +20 -0
- cfl_common/common/migrations/0055_alter_schoolteacherinvitation_token.py +18 -0
- cfl_common/common/migrations/0056_set_non_school_teachers_as_non_admins.py +25 -0
- cfl_common/common/migrations/0057_teacher_teacher__is_admin.py +19 -0
- cfl_common/common/migrations/0058_userprofile_google_refresh_token_and_more.py +24 -0
- cfl_common/common/migrations/__init__.py +0 -0
- cfl_common/common/models.py +557 -0
- cfl_common/common/permissions.py +84 -0
- cfl_common/common/tests/__init__.py +0 -0
- cfl_common/common/tests/test_migration_anonymise_orphan_schools.py +30 -0
- cfl_common/common/tests/test_migration_anonymise_orphan_users.py +30 -0
- cfl_common/common/tests/test_migration_blocked_time.py +15 -0
- cfl_common/common/tests/test_migration_remove_teacher_title.py +13 -0
- cfl_common/common/tests/test_migration_unique_school_names.py +33 -0
- cfl_common/common/tests/test_migration_verify_returning_users.py +59 -0
- cfl_common/common/tests/test_models.py +87 -0
- cfl_common/common/tests/utils/__init__.py +0 -0
- cfl_common/common/tests/utils/classes.py +38 -0
- cfl_common/common/tests/utils/email.py +67 -0
- cfl_common/common/tests/utils/organisation.py +41 -0
- cfl_common/common/tests/utils/student.py +123 -0
- cfl_common/common/tests/utils/teacher.py +73 -0
- cfl_common/common/tests/utils/user.py +27 -0
- cfl_common/common/utils.py +56 -0
- cfl_common/setup.py +61 -0
- codeforlife_portal-8.9.9.dist-info/METADATA +226 -0
- {codeforlife_portal-5.32.2.dist-info → codeforlife_portal-8.9.9.dist-info}/RECORD +341 -238
- {codeforlife_portal-5.32.2.dist-info → codeforlife_portal-8.9.9.dist-info}/WHEEL +1 -1
- codeforlife_portal-8.9.9.dist-info/licenses/LICENSE.md +3 -0
- {codeforlife_portal-5.32.2.dist-info → codeforlife_portal-8.9.9.dist-info}/top_level.txt +1 -0
- deploy/middleware/maintenance.py +25 -0
- deploy/middleware/screentime_warning.py +29 -0
- deploy/middleware/security.py +5 -6
- deploy/middleware/session_timeout.py +31 -0
- deploy/middleware/tmp_basic_auth.py +41 -0
- example_project/portal_test_settings.py +239 -0
- example_project/settings.py +156 -17
- example_project/urls.py +5 -6
- portal/__init__.py +1 -1
- portal/admin.py +142 -29
- portal/app_settings.py +10 -7
- portal/forms/dotmailer.py +6 -4
- portal/forms/invite_teacher.py +19 -10
- portal/forms/organisation.py +137 -68
- portal/forms/play.py +53 -98
- portal/forms/registration.py +70 -164
- portal/forms/teach.py +147 -121
- portal/handlers.py +1 -2
- portal/helpers/decorators.py +30 -10
- portal/helpers/password.py +86 -47
- portal/helpers/ratelimit.py +32 -15
- portal/helpers/regexes.py +5 -0
- portal/helpers/request_handlers.py +10 -0
- portal/migrations/0044_auto_20150430_0959.py +6 -2
- portal/mixins/__init__.py +1 -0
- portal/mixins/cron_mixin.py +12 -0
- portal/permissions/__init__.py +1 -0
- portal/permissions/is_cron_request_from_google.py +14 -0
- portal/static/portal/img/10_years_anniversary.png +0 -0
- portal/static/portal/img/RR_logo_grass_background.png +0 -0
- portal/static/portal/img/coding_club_hero.jpg +0 -0
- portal/static/portal/img/coding_club_python_pack.png +0 -0
- portal/static/portal/img/facebook.png +0 -0
- portal/static/portal/img/gitbook.png +0 -0
- portal/static/portal/img/howe_dell_1.png +0 -0
- portal/static/portal/img/howe_dell_2.png +0 -0
- portal/static/portal/img/howe_dell_3.png +0 -0
- portal/static/portal/img/logo_cfl.png +0 -0
- portal/static/portal/img/logo_cfl_powered.svg +35 -0
- portal/static/portal/img/logo_cfl_reminder_cards.jpg +0 -0
- portal/static/portal/img/logo_ocado_group.png +0 -0
- portal/static/portal/img/logo_python_den.svg +21 -0
- portal/static/portal/img/long_europe_map.png +0 -0
- portal/static/portal/img/python_den.png +0 -0
- portal/static/portal/img/python_den_banner.svg +26 -0
- portal/static/portal/img/rapid_router_landing_hero.png +0 -0
- portal/static/portal/img/rr_advanced.png +0 -0
- portal/static/portal/img/ten_year_map_pin.svg +1 -0
- portal/static/portal/img/thumbnail_educate_rapid_router.png +0 -0
- portal/static/portal/img/thumbnail_educate_resources.png +0 -0
- portal/static/portal/img/thumbnail_play_rapid_router.png +0 -0
- portal/static/portal/img/thumbnail_python_den.png +0 -0
- portal/static/portal/img/twitter.png +0 -0
- portal/static/portal/js/carouselCards.js +25 -0
- portal/static/portal/js/common.js +96 -1
- portal/static/portal/js/independentLogin.js +16 -0
- portal/static/portal/js/independentRegistration.js +86 -0
- portal/static/portal/js/levelControl.js +77 -0
- portal/static/portal/js/lib/jquery.min.js +2 -0
- portal/static/portal/js/organisation_manage.js +142 -14
- portal/static/portal/js/passwordStrength.js +154 -64
- portal/static/portal/js/resetPassword.js +23 -0
- portal/static/portal/js/riveted.min.js +238 -239
- portal/static/portal/js/school.js +13 -0
- portal/static/portal/js/studentLogin.js +16 -0
- portal/static/portal/js/teacherEditStudent.js +23 -0
- portal/static/portal/js/teacherLogin.js +16 -0
- portal/static/portal/js/tenYearMap.js +14 -0
- portal/static/portal/sass/colorbox.scss +0 -1
- portal/static/portal/sass/modules/_colours.scss +1 -0
- portal/static/portal/sass/modules/_levels.scss +1 -1
- portal/static/portal/sass/modules/_mixins.scss +21 -0
- portal/static/portal/sass/partials/_banners.scss +4 -177
- portal/static/portal/sass/partials/_buttons.scss +12 -15
- portal/static/portal/sass/partials/_carousel.scss +129 -0
- portal/static/portal/sass/partials/_footer.scss +21 -22
- portal/static/portal/sass/partials/_forms.scss +60 -5
- portal/static/portal/sass/partials/_grids.scss +34 -61
- portal/static/portal/sass/partials/_header.scss +28 -20
- portal/static/portal/sass/partials/_images.scss +292 -39
- portal/static/portal/sass/partials/_popup.scss +18 -15
- portal/static/portal/sass/partials/_tables.scss +12 -20
- portal/static/portal/sass/partials/_text.scss +6 -10
- portal/static/portal/sass/styles.scss +0 -1
- portal/static/portal/video/code for life .pdf +0 -0
- portal/strings/about.py +5 -0
- portal/strings/coding_club.py +9 -0
- portal/strings/play.py +6 -5
- portal/strings/teach.py +1 -1
- portal/strings/teacher_resources.py +2 -8
- portal/strings/ten_year_map.py +13 -0
- portal/templates/403.html +2 -2
- portal/templates/404.html +1 -1
- portal/templates/500.html +2 -2
- portal/templates/{captcha → django_recaptcha}/includes/js_v2_invisible.html +3 -3
- portal/templates/{captcha → django_recaptcha}/widget_v2_invisible.html +2 -2
- portal/templates/email.html +4 -2
- portal/templates/maintenance.html +34 -0
- portal/templates/portal/about.html +94 -62
- portal/templates/portal/base.html +176 -152
- portal/templates/portal/coding_club.html +100 -0
- portal/templates/portal/contribute.html +56 -52
- portal/templates/portal/email_invitation_sent.html +1 -1
- portal/templates/portal/email_style_template.html +374 -0
- portal/templates/portal/email_verification_failed.html +1 -1
- portal/templates/portal/email_verification_needed.html +9 -9
- portal/templates/portal/form_shapes.html +20 -8
- portal/templates/portal/getinvolved.html +6 -6
- portal/templates/portal/home.html +35 -10
- portal/templates/portal/home_learning.html +19 -19
- portal/templates/portal/locked_out.html +0 -1
- portal/templates/portal/locked_out_school_student.html +16 -0
- portal/templates/portal/login/independent_student.html +31 -15
- portal/templates/portal/login/student.html +10 -7
- portal/templates/portal/login/student_class_code.html +7 -4
- portal/templates/portal/login/teacher.html +34 -17
- portal/templates/portal/partials/banner.html +18 -4
- portal/templates/portal/partials/benefits.html +1 -1
- portal/templates/portal/partials/card_list.html +34 -24
- portal/templates/portal/partials/character_list.html +5 -5
- portal/templates/portal/partials/cookie_list.html +161 -0
- portal/templates/portal/partials/delete_popup.html +18 -0
- portal/templates/portal/partials/footer.html +57 -26
- portal/templates/portal/partials/header.html +118 -117
- portal/templates/portal/partials/hero_card.html +4 -3
- portal/templates/portal/partials/info_popup.html +3 -3
- portal/templates/portal/partials/invite_admin_teacher.html +23 -0
- portal/templates/portal/partials/popup.html +7 -2
- portal/templates/portal/partials/register_newsletter_tickbox.html +2 -5
- portal/templates/portal/partials/screentime_popup.html +14 -0
- portal/templates/portal/partials/service_unavailable_popup.html +17 -0
- portal/templates/portal/partials/session_popup.html +19 -0
- portal/templates/portal/play/student_dashboard.html +42 -29
- portal/templates/portal/play/student_edit_account.html +64 -9
- portal/templates/portal/play.html +61 -41
- portal/templates/portal/privacy_notice.html +697 -0
- portal/templates/portal/register.html +122 -92
- portal/templates/portal/reset_password.html +20 -40
- portal/templates/portal/reset_password_confirm.html +9 -4
- portal/templates/portal/reset_password_email_sent.html +15 -13
- portal/templates/portal/teach/base_registering.html +1 -1
- portal/templates/portal/teach/class.html +4 -6
- portal/templates/portal/teach/dashboard.html +212 -117
- portal/templates/portal/teach/invited.html +90 -0
- portal/templates/portal/teach/onboarding_classes.html +5 -3
- portal/templates/portal/teach/onboarding_print.html +1 -1
- portal/templates/portal/teach/onboarding_school.html +26 -139
- portal/templates/portal/teach/onboarding_students.html +1 -1
- portal/templates/portal/teach/teacher_dismiss_students.html +73 -55
- portal/templates/portal/teach/teacher_edit_class.html +168 -11
- portal/templates/portal/teach/teacher_edit_student.html +12 -5
- portal/templates/portal/teach/teacher_move_all_classes.html +25 -38
- portal/templates/portal/teach/teacher_move_students_to_class.html +1 -1
- portal/templates/portal/teach.html +61 -42
- portal/templates/portal/ten_year_map.html +147 -0
- portal/templates/portal/terms.html +191 -42
- portal/templates/two_factor/core/login.html +71 -59
- portal/templates/two_factor/core/setup.html +58 -49
- portal/templates/two_factor/profile/disable.html +1 -1
- portal/templates/two_factor/profile/profile.html +35 -17
- portal/templatetags/app_tags.py +59 -84
- portal/templatetags/card_list_tags.py +0 -4
- portal/tests/base_test.py +14 -3
- portal/tests/conftest.py +0 -15
- portal/tests/migrations/test_migration_make_portaladmin_teacher.py +2 -6
- portal/tests/migrations/test_migration_preview_users.py +3 -9
- portal/tests/migrations/test_migration_remove_guardian.py +1 -3
- portal/tests/migrations/test_migration_use_common_models.py +2 -6
- portal/tests/migrations/test_migration_verify_portaladmin.py +1 -3
- portal/tests/pageObjects/portal/admin/admin_base_page.py +0 -21
- portal/tests/pageObjects/portal/base_page.py +16 -26
- portal/tests/pageObjects/portal/email_verification_needed_page.py +3 -2
- portal/tests/pageObjects/portal/game_page.py +12 -19
- portal/tests/pageObjects/portal/home_page.py +13 -15
- portal/tests/pageObjects/portal/independent_login_page.py +13 -17
- portal/tests/pageObjects/portal/password_reset_form_page.py +20 -4
- portal/tests/pageObjects/portal/password_reset_page.py +25 -0
- portal/tests/pageObjects/portal/play/account_page.py +18 -27
- portal/tests/pageObjects/portal/play/dashboard_page.py +4 -4
- portal/tests/pageObjects/portal/play/join_school_or_club_page.py +8 -10
- portal/tests/pageObjects/portal/play/play_base_page.py +5 -3
- portal/tests/pageObjects/portal/signup_page.py +28 -59
- portal/tests/pageObjects/portal/student_login_class_code.py +6 -9
- portal/tests/pageObjects/portal/student_login_page.py +6 -8
- portal/tests/pageObjects/portal/teach/add_independent_student_to_class_page.py +3 -3
- portal/tests/pageObjects/portal/teach/added_independent_student_to_class_page.py +3 -1
- portal/tests/pageObjects/portal/teach/class_page.py +36 -13
- portal/tests/pageObjects/portal/teach/dashboard_page.py +43 -84
- portal/tests/pageObjects/portal/teach/dismiss_students_page.py +7 -5
- portal/tests/pageObjects/portal/teach/edit_student_page.py +10 -8
- portal/tests/pageObjects/portal/teach/move_class_page.py +5 -10
- portal/tests/pageObjects/portal/teach/move_classes_page.py +4 -2
- portal/tests/pageObjects/portal/teach/move_students_disambiguate_page.py +4 -2
- portal/tests/pageObjects/portal/teach/move_students_page.py +6 -13
- portal/tests/pageObjects/portal/teach/onboarding_classes_page.py +5 -3
- portal/tests/pageObjects/portal/teach/onboarding_organisation_page.py +11 -49
- portal/tests/pageObjects/portal/teach/onboarding_student_list_page.py +7 -12
- portal/tests/pageObjects/portal/teach/onboarding_students_page.py +4 -27
- portal/tests/pageObjects/portal/teach/teach_base_page.py +6 -4
- portal/tests/pageObjects/portal/teacher_login_page.py +10 -16
- portal/tests/selenium_test_case.py +3 -43
- portal/tests/snapshots/snap_test_partials.py +11 -165
- portal/tests/test_2FA.py +15 -33
- portal/tests/test_admin.py +15 -97
- portal/tests/test_api.py +212 -73
- portal/tests/test_captcha_forms.py +2 -2
- portal/tests/test_class.py +374 -24
- portal/tests/test_emails.py +83 -20
- portal/tests/{test_newsletter_footer.py → test_global_forms.py} +5 -5
- portal/tests/test_helper_methods.py +30 -0
- portal/tests/test_independent_student.py +255 -144
- portal/tests/test_invite_teacher.py +318 -10
- portal/tests/test_middleware.py +138 -15
- portal/tests/test_organisation.py +78 -262
- portal/tests/test_partials.py +0 -88
- portal/tests/test_ratelimit.py +218 -36
- portal/tests/test_school_student.py +35 -40
- portal/tests/test_security.py +12 -31
- portal/tests/test_teacher.py +425 -325
- portal/tests/test_teacher_student.py +103 -91
- portal/tests/test_views.py +900 -76
- portal/tests/utils/classes.py +2 -2
- portal/tests/utils/messages.py +13 -28
- portal/urls.py +237 -164
- portal/views/admin.py +0 -332
- portal/views/api.py +82 -68
- portal/views/cron/__init__.py +1 -0
- portal/views/cron/user.py +322 -0
- portal/views/dotmailer.py +9 -1
- portal/views/email.py +33 -77
- portal/views/google_analytics.py +28 -0
- portal/views/home.py +126 -97
- portal/views/legal.py +13 -0
- portal/views/login/independent_student.py +5 -5
- portal/views/login/student.py +51 -14
- portal/views/login/teacher.py +2 -6
- portal/views/organisation.py +20 -189
- portal/views/registration.py +97 -17
- portal/views/student/edit_account_details.py +99 -72
- portal/views/student/play.py +81 -62
- portal/views/teacher/dashboard.py +421 -149
- portal/views/teacher/teach.py +226 -177
- portal/views/two_factor/__init__.py +0 -0
- portal/views/two_factor/core.py +28 -0
- portal/views/two_factor/form.py +7 -0
- portal/views/two_factor/profile.py +11 -0
- codeforlife_portal-5.32.2.dist-info/LICENSE.md +0 -577
- codeforlife_portal-5.32.2.dist-info/METADATA +0 -38
- deploy/permissions.py +0 -2
- example_project/manage.py +0 -10
- portal/autoconfig.py +0 -140
- portal/csp_config.py +0 -60
- portal/forms/add_game.py +0 -33
- portal/helpers/location.py +0 -121
- portal/static/portal/img/kurono_hero.jpg +0 -0
- portal/static/portal/img/kurono_landing_hero.png +0 -0
- portal/static/portal/img/kurono_logo.svg +0 -1
- portal/static/portal/img/kurono_logo_grey_background.svg +0 -1
- portal/static/portal/img/kurono_logo_mark.svg +0 -1
- portal/static/portal/img/kurono_resources_hero.jpg +0 -0
- portal/static/portal/img/kurono_story.png +0 -0
- portal/static/portal/img/ocado-swirl.svg +0 -22
- portal/static/portal/img/thumbnail_educate_kurono.png +0 -0
- portal/static/portal/img/thumbnail_educate_resources_and_progress_tracking.png +0 -0
- portal/static/portal/img/thumbnail_kurono_resources.png +0 -0
- portal/static/portal/img/thumbnail_play_kurono.png +0 -0
- portal/static/portal/img/x_close_video.png +0 -0
- portal/static/portal/js/aimmoGame.js +0 -106
- portal/static/portal/js/deleteWorkspaces.js +0 -14
- portal/static/portal/js/fuzzySchoolLookup.js +0 -46
- portal/static/portal/js/lib/jquery-3.5.1.min.js +0 -2
- portal/static/portal/js/lib/jquery-ui-1.12.1.min.js +0 -13
- portal/static/portal/sass/partials/_videos.scss +0 -10
- portal/static/portal/video/aimmo_play_now_background_video.mp4 +0 -0
- portal/strings/student_aimmo_dashboard.py +0 -6
- portal/templates/portal/admin/aggregated_data.html +0 -35
- portal/templates/portal/admin/map.html +0 -70
- portal/templates/portal/mouseflow.html +0 -9
- portal/templates/portal/partials/aimmo_games_table.html +0 -83
- portal/templates/portal/partials/register_over_required_age_tickbox.html +0 -9
- portal/templates/portal/play/independent_student_dashboard.html +0 -64
- portal/templates/portal/play/student_aimmo_dashboard.html +0 -63
- portal/templates/portal/privacy_policy.html +0 -483
- portal/templates/portal/reset_password_email.html +0 -9
- portal/templates/portal/teach/invite.html +0 -25
- portal/templates/portal/teach/teacher_aimmo_dashboard.html +0 -95
- portal/templates/portal/teach/teacher_resources.html +0 -68
- portal/templatetags/character_list_tags.py +0 -16
- portal/tests/pageObjects/portal/kurono_teacher_dashboard_page.py +0 -49
- portal/tests/pageObjects/portal/student_password_reset_form_page.py +0 -23
- portal/tests/pageObjects/portal/teach/onboarding_revoke_request_page.py +0 -20
- portal/tests/pageObjects/portal/teacher_password_reset_form_page.py +0 -23
- portal/tests/test_aimmo_dashboards.py +0 -172
- portal/tests/test_location.py +0 -217
- portal/tests/utils/aimmo_games.py +0 -30
- portal/views/aimmo/dashboard.py +0 -119
- portal/views/privacy_policy.py +0 -9
- portal/views/teacher/teacher_resources.py +0 -42
- {portal/views/aimmo → cfl_common}/__init__.py +0 -0
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
{% extends 'portal/base.html' %}
|
|
2
|
-
{% load staticfiles %}
|
|
3
|
-
{% load app_tags %}
|
|
4
|
-
{% load banner_tags %}
|
|
5
|
-
|
|
6
|
-
{% block subNav %}
|
|
7
|
-
{% banner banner_name="BANNER" %}
|
|
8
|
-
<div class="sticky-subnav sub-nav sub-nav--teacher">
|
|
9
|
-
<div class="container">
|
|
10
|
-
<div class="row">
|
|
11
|
-
<div class="col-sm-12 sub-nav">
|
|
12
|
-
<span class="iconify sub-nav--icon" data-icon="mdi:information-outline"></span>
|
|
13
|
-
<p class="flex-grow-1">
|
|
14
|
-
<strong>We have moved our resources to Gitbook.</strong>
|
|
15
|
-
</p>
|
|
16
|
-
</div>
|
|
17
|
-
</div>
|
|
18
|
-
</div>
|
|
19
|
-
|
|
20
|
-
</div>
|
|
21
|
-
{% endblock subNav %}
|
|
22
|
-
|
|
23
|
-
{% block content %}
|
|
24
|
-
<div id="resources_page"></div>
|
|
25
|
-
|
|
26
|
-
<div class="background container">
|
|
27
|
-
<div class="row">
|
|
28
|
-
<div class="col-sm-12 text-center">
|
|
29
|
-
<h4>You can find our resources on our new Gitbook space</h4>
|
|
30
|
-
</div>
|
|
31
|
-
</div>
|
|
32
|
-
|
|
33
|
-
<div class="row d-flex">
|
|
34
|
-
<div class="col-sm-6 d-flex flex-column">
|
|
35
|
-
<div class="flex-grow-1">
|
|
36
|
-
<p>Our resources have been moved to Gitbook to give you better experience. Please visit our dedicated
|
|
37
|
-
{% if rapid_router_resources %}
|
|
38
|
-
<a href="https://code-for-life.gitbook.io/teaching-resources/" target="_blank">Code for Life Space</a>
|
|
39
|
-
{% else %}
|
|
40
|
-
<a href="https://code-for-life.gitbook.io/teaching-resources/v/kurono-teaching-resources/"
|
|
41
|
-
target="_blank">Code for Life Space</a>
|
|
42
|
-
{% endif %}
|
|
43
|
-
to find everything you need from lesson plans to solutions.
|
|
44
|
-
</p>
|
|
45
|
-
<p>This space is only available to teachers.</p>
|
|
46
|
-
</div>
|
|
47
|
-
<div>
|
|
48
|
-
{% if rapid_router_resources %}
|
|
49
|
-
<a href="https://code-for-life.gitbook.io/teaching-resources/"
|
|
50
|
-
class="button button--primary button--icon" target="_blank">
|
|
51
|
-
Open Rapid Router resources<span class="iconify" data-icon="mdi:open-in-new"></span>
|
|
52
|
-
</a>
|
|
53
|
-
{% else %}
|
|
54
|
-
<a href="https://code-for-life.gitbook.io/teaching-resources/v/kurono-teaching-resources/"
|
|
55
|
-
class="button button--primary button--icon" target="_blank">
|
|
56
|
-
Open Kurono resources<span class="iconify" data-icon="mdi:open-in-new"></span>
|
|
57
|
-
</a>
|
|
58
|
-
{% endif %}
|
|
59
|
-
</div>
|
|
60
|
-
</div>
|
|
61
|
-
|
|
62
|
-
<div class="col-sm-6">
|
|
63
|
-
<img src="{% static 'portal/img/gitbook_space.png' %}">
|
|
64
|
-
</div>
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
67
|
-
|
|
68
|
-
{% endblock content %}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
from django import template
|
|
2
|
-
from common.models import AimmoCharacter
|
|
3
|
-
|
|
4
|
-
register = template.Library()
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@register.inclusion_tag("portal/partials/character_list.html")
|
|
8
|
-
def character_list():
|
|
9
|
-
"""
|
|
10
|
-
Registers the inclusion tag for the character card list partial.
|
|
11
|
-
The template currently expects a list of elements which each contain the following:
|
|
12
|
-
- name: the heading of the card
|
|
13
|
-
- image_path: the path to the card's image
|
|
14
|
-
- description: the text paragraph of the card
|
|
15
|
-
"""
|
|
16
|
-
return {"characters": AimmoCharacter.objects.sorted()}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
from __future__ import absolute_import
|
|
2
|
-
|
|
3
|
-
from .base_page import BasePage
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class KuronoTeacherDashboardPage(BasePage):
|
|
7
|
-
def __init__(self, browser):
|
|
8
|
-
super(KuronoTeacherDashboardPage, self).__init__(browser)
|
|
9
|
-
|
|
10
|
-
assert self.on_correct_page("kurono_teacher_dashboard_page")
|
|
11
|
-
|
|
12
|
-
def create_game(self, class_id):
|
|
13
|
-
self._click_add_game_dropdown()
|
|
14
|
-
|
|
15
|
-
self.browser.find_element_by_id(f"class_{class_id}").click()
|
|
16
|
-
|
|
17
|
-
return self
|
|
18
|
-
|
|
19
|
-
def change_game_worksheet(self, worksheet_id):
|
|
20
|
-
self._click_change_worksheet_dropdown()
|
|
21
|
-
|
|
22
|
-
self.browser.find_element_by_id(f"worksheet_{worksheet_id}").click()
|
|
23
|
-
|
|
24
|
-
self.confirm_dialog()
|
|
25
|
-
|
|
26
|
-
return self
|
|
27
|
-
|
|
28
|
-
def delete_games(self, game_ids):
|
|
29
|
-
# Tick checkboxes
|
|
30
|
-
for game_id in game_ids:
|
|
31
|
-
self.browser.find_element_by_xpath(
|
|
32
|
-
f"//input[@name='game_ids' and @value='{game_id}']"
|
|
33
|
-
).click()
|
|
34
|
-
|
|
35
|
-
# Click delete
|
|
36
|
-
self.browser.find_element_by_id("deleteGamesButton").click()
|
|
37
|
-
|
|
38
|
-
self.confirm_dialog()
|
|
39
|
-
|
|
40
|
-
return self
|
|
41
|
-
|
|
42
|
-
def _click_change_worksheet_confirm_button(self):
|
|
43
|
-
self.browser.find_element_by_id("confirm_button").click()
|
|
44
|
-
|
|
45
|
-
def _click_add_game_dropdown(self):
|
|
46
|
-
self.browser.find_element_by_id("add_class_dropdown").click()
|
|
47
|
-
|
|
48
|
-
def _click_change_worksheet_dropdown(self):
|
|
49
|
-
self.browser.find_element_by_id("worksheets_dropdown").click()
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
from __future__ import absolute_import
|
|
2
|
-
|
|
3
|
-
from .base_page import BasePage
|
|
4
|
-
from .home_page import HomePage
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class StudentPasswordResetFormPage(BasePage):
|
|
8
|
-
def __init__(self, browser):
|
|
9
|
-
super(StudentPasswordResetFormPage, self).__init__(browser)
|
|
10
|
-
|
|
11
|
-
assert self.on_correct_page("reset_password_student_page")
|
|
12
|
-
|
|
13
|
-
def cancel(self):
|
|
14
|
-
self.browser.find_element_by_id("cancel_button").click()
|
|
15
|
-
|
|
16
|
-
return HomePage(self.browser)
|
|
17
|
-
|
|
18
|
-
def reset_username_submit(self, username):
|
|
19
|
-
self.browser.find_element_by_id("id_username").send_keys(username)
|
|
20
|
-
|
|
21
|
-
self.browser.find_element_by_id("reset_button").click()
|
|
22
|
-
|
|
23
|
-
return self
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
from __future__ import absolute_import
|
|
2
|
-
|
|
3
|
-
from .teach_base_page import TeachBasePage
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class OnboardingRevokeRequestPage(TeachBasePage):
|
|
7
|
-
def __init__(self, browser):
|
|
8
|
-
super(OnboardingRevokeRequestPage, self).__init__(browser)
|
|
9
|
-
|
|
10
|
-
assert self.on_correct_page("onboarding_revoke_request_page")
|
|
11
|
-
|
|
12
|
-
def check_organisation_name(self, name, postcode):
|
|
13
|
-
text = "You have a pending request to join %s, %s" % (name, postcode)
|
|
14
|
-
return text in self.browser.find_element_by_tag_name("body").text
|
|
15
|
-
|
|
16
|
-
def revoke_join(self):
|
|
17
|
-
self.browser.find_element_by_name("revoke_join_request").click()
|
|
18
|
-
import portal.tests.pageObjects.portal.teach.onboarding_organisation_page as onboarding_organisation_page
|
|
19
|
-
|
|
20
|
-
return onboarding_organisation_page.OnboardingOrganisationPage(self.browser)
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
from __future__ import absolute_import
|
|
2
|
-
|
|
3
|
-
from .base_page import BasePage
|
|
4
|
-
from .home_page import HomePage
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class TeacherPasswordResetFormPage(BasePage):
|
|
8
|
-
def __init__(self, browser):
|
|
9
|
-
super(TeacherPasswordResetFormPage, self).__init__(browser)
|
|
10
|
-
|
|
11
|
-
assert self.on_correct_page("reset_password_teacher_page")
|
|
12
|
-
|
|
13
|
-
def cancel(self):
|
|
14
|
-
self.browser.find_element_by_id("cancel_button").click()
|
|
15
|
-
return HomePage(self.browser)
|
|
16
|
-
|
|
17
|
-
def reset_email_submit(self, email):
|
|
18
|
-
self.browser.find_element_by_id("id_email").send_keys(email)
|
|
19
|
-
|
|
20
|
-
self.wait_for_element_by_id("reset_button")
|
|
21
|
-
|
|
22
|
-
self.browser.find_element_by_id("reset_button").click()
|
|
23
|
-
return self
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from aimmo.models import Game
|
|
3
|
-
from aimmo.worksheets import WORKSHEETS
|
|
4
|
-
from common.models import Class
|
|
5
|
-
from common.tests.utils.classes import create_class_directly
|
|
6
|
-
from common.tests.utils.organisation import (
|
|
7
|
-
create_organisation_directly,
|
|
8
|
-
)
|
|
9
|
-
from common.tests.utils.student import create_school_student_directly
|
|
10
|
-
from common.tests.utils.teacher import signup_teacher_directly
|
|
11
|
-
from django.test.client import Client
|
|
12
|
-
from django.urls.base import reverse
|
|
13
|
-
|
|
14
|
-
from .base_test import BaseTest
|
|
15
|
-
from .conftest import IndependentStudent, SchoolStudent
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@pytest.mark.django_db
|
|
19
|
-
def test_student_cannot_access_teacher_dashboard(
|
|
20
|
-
student1: SchoolStudent, class1: Class
|
|
21
|
-
):
|
|
22
|
-
"""
|
|
23
|
-
Given you are logged in as a student,
|
|
24
|
-
When you try to access the teacher dashboard,
|
|
25
|
-
Then you cannot access it and are instead redirected.
|
|
26
|
-
"""
|
|
27
|
-
c = Client()
|
|
28
|
-
url = reverse("student_login", kwargs={"access_code": class1.access_code})
|
|
29
|
-
data = {
|
|
30
|
-
"username": student1.username,
|
|
31
|
-
"password": student1.password,
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
c.post(url, data)
|
|
35
|
-
|
|
36
|
-
student_dashboard_url = reverse("student_aimmo_dashboard")
|
|
37
|
-
|
|
38
|
-
response_s = c.get(student_dashboard_url)
|
|
39
|
-
|
|
40
|
-
assert response_s.status_code == 200
|
|
41
|
-
|
|
42
|
-
teacher_dashboard_url = reverse("teacher_aimmo_dashboard")
|
|
43
|
-
|
|
44
|
-
response = c.get(teacher_dashboard_url)
|
|
45
|
-
|
|
46
|
-
assert response.status_code == 302
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
@pytest.mark.django_db
|
|
50
|
-
def test_indep_student_cannot_access_dashboard(
|
|
51
|
-
independent_student1: IndependentStudent,
|
|
52
|
-
):
|
|
53
|
-
"""
|
|
54
|
-
Given you are logged in as an independent student,
|
|
55
|
-
When you try to access the student dashboard,
|
|
56
|
-
Then you can access it but the context only has the banner.
|
|
57
|
-
"""
|
|
58
|
-
c = Client()
|
|
59
|
-
url = reverse("independent_student_login")
|
|
60
|
-
data = {
|
|
61
|
-
"username": independent_student1.username,
|
|
62
|
-
"password": independent_student1.password,
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
c.post(url, data)
|
|
66
|
-
|
|
67
|
-
student_dashboard_url = reverse("student_aimmo_dashboard")
|
|
68
|
-
|
|
69
|
-
response = c.get(student_dashboard_url)
|
|
70
|
-
|
|
71
|
-
assert response.status_code == 200
|
|
72
|
-
assert "BANNER" in response.context
|
|
73
|
-
assert "HERO_CARD" not in response.context
|
|
74
|
-
assert "CARD_LIST" not in response.context
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
@pytest.mark.django_db
|
|
78
|
-
def test_student_aimmo_dashboard_loads(
|
|
79
|
-
student1: SchoolStudent, class1: Class, aimmo_game1: Game
|
|
80
|
-
):
|
|
81
|
-
"""
|
|
82
|
-
Given an aimmo game is linked to a class,
|
|
83
|
-
When a student of that class goes on the Student Kurono Dashboard page,
|
|
84
|
-
Then the page loads and the context contains the hero card and card list
|
|
85
|
-
associated to the aimmo game.
|
|
86
|
-
|
|
87
|
-
Then, given that the class no longer has a game linked to it,
|
|
88
|
-
When the student goes on the same page,
|
|
89
|
-
Then the page still loads but the context no longer contains the hero card
|
|
90
|
-
or the card list elements.
|
|
91
|
-
"""
|
|
92
|
-
c = Client()
|
|
93
|
-
student_login_url = reverse(
|
|
94
|
-
"student_login", kwargs={"access_code": class1.access_code}
|
|
95
|
-
)
|
|
96
|
-
data = {
|
|
97
|
-
"username": student1.username,
|
|
98
|
-
"password": student1.password,
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
c.post(student_login_url, data)
|
|
102
|
-
|
|
103
|
-
student_dashboard_url = reverse("student_aimmo_dashboard")
|
|
104
|
-
response = c.get(student_dashboard_url)
|
|
105
|
-
|
|
106
|
-
assert response.status_code == 200
|
|
107
|
-
assert "HERO_CARD" in response.context
|
|
108
|
-
assert "CARD_LIST" in response.context
|
|
109
|
-
|
|
110
|
-
aimmo_game1.delete()
|
|
111
|
-
|
|
112
|
-
url = reverse("student_aimmo_dashboard")
|
|
113
|
-
response = c.get(url)
|
|
114
|
-
|
|
115
|
-
assert response.status_code == 200
|
|
116
|
-
assert "HERO_CARD" not in response.context
|
|
117
|
-
assert "CARD_LIST" not in response.context
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
# Selenium tests
|
|
121
|
-
class TestAimmoDashboardFrontend(BaseTest):
|
|
122
|
-
def test_worksheet_dropdown_changes_worksheet(self):
|
|
123
|
-
teacher_email, teacher_password = signup_teacher_directly()
|
|
124
|
-
create_organisation_directly(teacher_email)
|
|
125
|
-
klass, class_name, access_code = create_class_directly(teacher_email)
|
|
126
|
-
student_name, student_password, _ = create_school_student_directly(access_code)
|
|
127
|
-
|
|
128
|
-
worksheet1 = WORKSHEETS.get(1)
|
|
129
|
-
worksheet2 = WORKSHEETS.get(2)
|
|
130
|
-
|
|
131
|
-
self.selenium.get(self.live_server_url)
|
|
132
|
-
page = (
|
|
133
|
-
self.go_to_homepage()
|
|
134
|
-
.go_to_teacher_login_page()
|
|
135
|
-
.login(teacher_email, teacher_password)
|
|
136
|
-
)
|
|
137
|
-
page = page.go_to_kurono_teacher_dashboard_page().create_game(klass.id)
|
|
138
|
-
|
|
139
|
-
game = Game.objects.get(game_class=klass)
|
|
140
|
-
|
|
141
|
-
assert game.worksheet == worksheet1
|
|
142
|
-
|
|
143
|
-
page.change_game_worksheet(worksheet2.id)
|
|
144
|
-
|
|
145
|
-
game = Game.objects.get(game_class=klass)
|
|
146
|
-
|
|
147
|
-
assert game.worksheet == worksheet2
|
|
148
|
-
|
|
149
|
-
def test_delete_games(self):
|
|
150
|
-
teacher_email, teacher_password = signup_teacher_directly()
|
|
151
|
-
create_organisation_directly(teacher_email)
|
|
152
|
-
|
|
153
|
-
klass1, _, _ = create_class_directly(teacher_email)
|
|
154
|
-
game1 = Game(game_class=klass1)
|
|
155
|
-
game1.save()
|
|
156
|
-
|
|
157
|
-
klass2, _, _ = create_class_directly(teacher_email)
|
|
158
|
-
game2 = Game(game_class=klass2)
|
|
159
|
-
game2.save()
|
|
160
|
-
|
|
161
|
-
assert Game.objects.count() == 2
|
|
162
|
-
|
|
163
|
-
self.selenium.get(self.live_server_url)
|
|
164
|
-
page = (
|
|
165
|
-
self.go_to_homepage()
|
|
166
|
-
.go_to_teacher_login_page()
|
|
167
|
-
.login(teacher_email, teacher_password)
|
|
168
|
-
)
|
|
169
|
-
page.go_to_kurono_teacher_dashboard_page().delete_games([game1.id, game2.id])
|
|
170
|
-
|
|
171
|
-
assert Game.objects.filter(is_archived=False).count() == 0
|
|
172
|
-
assert Game.objects.filter(is_archived=True).count() == 2
|
portal/tests/test_location.py
DELETED
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import os
|
|
3
|
-
import unittest
|
|
4
|
-
|
|
5
|
-
import requests
|
|
6
|
-
import responses
|
|
7
|
-
|
|
8
|
-
from portal.helpers.location import lookup_coord, lookup_country
|
|
9
|
-
|
|
10
|
-
DATA_DIR = os.path.join(os.path.dirname(__file__), "data")
|
|
11
|
-
|
|
12
|
-
# Returns a string read from the given file that can be deserialised into json objects
|
|
13
|
-
def read_json_from_file(filename):
|
|
14
|
-
data = ""
|
|
15
|
-
|
|
16
|
-
if filename:
|
|
17
|
-
f = open(filename, "r")
|
|
18
|
-
data = f.read()
|
|
19
|
-
f.close()
|
|
20
|
-
|
|
21
|
-
return data
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# Returns path to the file that contains the json response
|
|
25
|
-
def datafile(filename):
|
|
26
|
-
return os.path.join(DATA_DIR, filename)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
MAPS_API_GEOCODE_JSON = "https://maps.googleapis.com/maps/api/geocode/json?"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class TestLocation(unittest.TestCase):
|
|
33
|
-
def assert_default_coord(self, town, lat, lng):
|
|
34
|
-
# default values returned when error occurs in lookup_coord()
|
|
35
|
-
self.assertEqual((town, lat, lng), (0, 0, 0))
|
|
36
|
-
|
|
37
|
-
def assert_default_country_and_coord(self, country, town, lat, lng):
|
|
38
|
-
# default values returned when error occurs in lookup_country()
|
|
39
|
-
self.assertEqual((country, town, lat, lng), ("GB", 0, 55.378051, -3.435973))
|
|
40
|
-
|
|
41
|
-
@responses.activate
|
|
42
|
-
def test_lookup_coord_call_api_once(self):
|
|
43
|
-
responses.add(
|
|
44
|
-
responses.GET,
|
|
45
|
-
MAPS_API_GEOCODE_JSON + "address=SW72AZ&components=country:GB",
|
|
46
|
-
body=read_json_from_file(datafile("sw72az_gb.json")),
|
|
47
|
-
match_querystring=True,
|
|
48
|
-
content_type="application/json",
|
|
49
|
-
)
|
|
50
|
-
result = lookup_coord("SW72AZ", "GB")
|
|
51
|
-
self.assertEqual(len(responses.calls), 1, "API was called more than once")
|
|
52
|
-
|
|
53
|
-
@responses.activate
|
|
54
|
-
def test_lookup_coord_json_unchanged(self):
|
|
55
|
-
responses.add(
|
|
56
|
-
responses.GET,
|
|
57
|
-
MAPS_API_GEOCODE_JSON + "address=SW72AZ&components=country:GB",
|
|
58
|
-
body=read_json_from_file(datafile("sw72az_gb.json")),
|
|
59
|
-
match_querystring=True,
|
|
60
|
-
content_type="application/json",
|
|
61
|
-
)
|
|
62
|
-
result = lookup_coord("SW72AZ", "GB")
|
|
63
|
-
self.assertEqual(
|
|
64
|
-
responses.calls[0].response.json(),
|
|
65
|
-
json.loads(read_json_from_file(datafile("sw72az_gb.json"))),
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
@responses.activate
|
|
69
|
-
def test_lookup_coord_valid_postcode_country_gb1(self):
|
|
70
|
-
responses.add(
|
|
71
|
-
responses.GET,
|
|
72
|
-
MAPS_API_GEOCODE_JSON + "address=SW72AZ&components=country:GB",
|
|
73
|
-
body=read_json_from_file(datafile("sw72az_gb.json")),
|
|
74
|
-
match_querystring=True,
|
|
75
|
-
content_type="application/json",
|
|
76
|
-
)
|
|
77
|
-
result = lookup_coord("SW72AZ", "GB")
|
|
78
|
-
self.assertEqual(result, (None, "GB", "London", 51.5005046, -0.1782187))
|
|
79
|
-
|
|
80
|
-
@responses.activate
|
|
81
|
-
def test_lookup_coord_valid_postcode_country_gb2(self):
|
|
82
|
-
responses.add(
|
|
83
|
-
responses.GET,
|
|
84
|
-
MAPS_API_GEOCODE_JSON + "address=AL10 9NE&components=country:GB",
|
|
85
|
-
body=read_json_from_file(datafile("al109ne_gb.json")),
|
|
86
|
-
match_querystring=True,
|
|
87
|
-
content_type="application/json",
|
|
88
|
-
)
|
|
89
|
-
result = lookup_coord("AL10 9NE", "GB")
|
|
90
|
-
self.assertEqual(result, (None, "GB", "Hatfield", 51.7623259, -0.2438929))
|
|
91
|
-
|
|
92
|
-
# Default to coordinates of country
|
|
93
|
-
@responses.activate
|
|
94
|
-
def test_lookup_coord_invalid_postcode_country_gb(self):
|
|
95
|
-
responses.add(
|
|
96
|
-
responses.GET,
|
|
97
|
-
MAPS_API_GEOCODE_JSON + "address=10000&components=country:GB",
|
|
98
|
-
body=read_json_from_file(datafile("10000_gb.json")),
|
|
99
|
-
match_querystring=True,
|
|
100
|
-
content_type="application/json",
|
|
101
|
-
)
|
|
102
|
-
result = lookup_coord("10000", "GB")
|
|
103
|
-
self.assertEqual(result, (None, "GB", 0, 55.378051, -3.435973))
|
|
104
|
-
|
|
105
|
-
@responses.activate
|
|
106
|
-
def test_lookup_coord_invalid_postcode_country_kr(self):
|
|
107
|
-
responses.add(
|
|
108
|
-
responses.GET,
|
|
109
|
-
MAPS_API_GEOCODE_JSON + "address=AL109NE&components=country:KR",
|
|
110
|
-
body=read_json_from_file(datafile("al109ne_kr.json")),
|
|
111
|
-
match_querystring=True,
|
|
112
|
-
content_type="application/json",
|
|
113
|
-
)
|
|
114
|
-
result = lookup_coord("AL109NE", "KR")
|
|
115
|
-
self.assertEqual(result, (None, "KR", 0, 35.907757, 127.766922))
|
|
116
|
-
|
|
117
|
-
@responses.activate
|
|
118
|
-
def test_lookup_coord_connection_error(self):
|
|
119
|
-
error, country, town, lat, lng = lookup_coord("AL109NE", "GB")
|
|
120
|
-
assert "Connection error" in error
|
|
121
|
-
self.assert_default_coord(town, lat, lng)
|
|
122
|
-
|
|
123
|
-
@responses.activate
|
|
124
|
-
def test_lookup_coord_cannot_decode_json(self):
|
|
125
|
-
responses.add(
|
|
126
|
-
responses.GET,
|
|
127
|
-
MAPS_API_GEOCODE_JSON + "address=AL109NE&components=country:GB",
|
|
128
|
-
body="",
|
|
129
|
-
match_querystring=True,
|
|
130
|
-
content_type="application/json",
|
|
131
|
-
)
|
|
132
|
-
error, country, town, lat, lng = lookup_coord("AL109NE", "GB")
|
|
133
|
-
assert "Value error" in error
|
|
134
|
-
self.assert_default_coord(town, lat, lng)
|
|
135
|
-
|
|
136
|
-
@responses.activate
|
|
137
|
-
def test_lookup_coord_request_error_404(self):
|
|
138
|
-
responses.add(
|
|
139
|
-
responses.GET,
|
|
140
|
-
MAPS_API_GEOCODE_JSON + "address=AL109NE&components=country:GB",
|
|
141
|
-
body=read_json_from_file(datafile("al109ne_gb.json")),
|
|
142
|
-
status=requests.codes.not_found,
|
|
143
|
-
match_querystring=True,
|
|
144
|
-
content_type="application/json",
|
|
145
|
-
)
|
|
146
|
-
error, country, town, lat, lng = lookup_coord("AL109NE", "GB")
|
|
147
|
-
assert "Request error" in error
|
|
148
|
-
self.assert_default_coord(town, lat, lng)
|
|
149
|
-
|
|
150
|
-
@responses.activate
|
|
151
|
-
def test_lookup_coord_zero_results(self):
|
|
152
|
-
responses.add(
|
|
153
|
-
responses.GET,
|
|
154
|
-
MAPS_API_GEOCODE_JSON + "address=AL109NE&components=country:AB",
|
|
155
|
-
body=read_json_from_file(datafile("al109ne_ab.json")),
|
|
156
|
-
match_querystring=True,
|
|
157
|
-
content_type="application/json",
|
|
158
|
-
)
|
|
159
|
-
error, country, town, lat, lng = lookup_coord("AL109NE", "AB")
|
|
160
|
-
assert "API error" in error
|
|
161
|
-
self.assert_default_coord(town, lat, lng)
|
|
162
|
-
|
|
163
|
-
@responses.activate
|
|
164
|
-
def test_lookup_country_valid_postcode1(self):
|
|
165
|
-
responses.add(
|
|
166
|
-
responses.GET,
|
|
167
|
-
MAPS_API_GEOCODE_JSON + "components=postal_code:SW72AZ",
|
|
168
|
-
body=read_json_from_file(datafile("sw72az.json")),
|
|
169
|
-
match_querystring=True,
|
|
170
|
-
content_type="application/json",
|
|
171
|
-
)
|
|
172
|
-
result = lookup_country("SW72AZ")
|
|
173
|
-
self.assertEqual(result, (None, "GB", "London", 51.5005046, -0.1782187))
|
|
174
|
-
|
|
175
|
-
@responses.activate
|
|
176
|
-
def test_lookup_country_valid_postcode1(self):
|
|
177
|
-
responses.add(
|
|
178
|
-
responses.GET,
|
|
179
|
-
MAPS_API_GEOCODE_JSON + "components=postal_code:AL10 9NE",
|
|
180
|
-
body=read_json_from_file(datafile("al109ne.json")),
|
|
181
|
-
match_querystring=True,
|
|
182
|
-
content_type="application/json",
|
|
183
|
-
)
|
|
184
|
-
result = lookup_country("AL10 9NE")
|
|
185
|
-
self.assertEqual(result, (None, "GB", "Hatfield", 51.7623259, -0.2438929))
|
|
186
|
-
|
|
187
|
-
@responses.activate
|
|
188
|
-
def test_lookup_country_invalid_postcode_zero_results(self):
|
|
189
|
-
responses.add(
|
|
190
|
-
responses.GET,
|
|
191
|
-
MAPS_API_GEOCODE_JSON + "components=postal_code:xxxxx",
|
|
192
|
-
body=read_json_from_file(datafile("xxxxx.json")),
|
|
193
|
-
match_querystring=True,
|
|
194
|
-
content_type="application/json",
|
|
195
|
-
)
|
|
196
|
-
error, country, town, lat, lng = lookup_country("xxxxx")
|
|
197
|
-
assert "API error" in error
|
|
198
|
-
self.assert_default_country_and_coord(country, town, lat, lng)
|
|
199
|
-
|
|
200
|
-
@responses.activate
|
|
201
|
-
def test_lookup_country_connection_error(self):
|
|
202
|
-
error, country, town, lat, lng = lookup_country("xxxxx")
|
|
203
|
-
assert "Connection error" in error
|
|
204
|
-
|
|
205
|
-
@responses.activate
|
|
206
|
-
def test_lookup_country_request_error_404(self):
|
|
207
|
-
responses.add(
|
|
208
|
-
responses.GET,
|
|
209
|
-
MAPS_API_GEOCODE_JSON + "components=postal_code:AL109NE",
|
|
210
|
-
body=read_json_from_file(datafile("al109ne.json")),
|
|
211
|
-
status=requests.codes.not_found,
|
|
212
|
-
match_querystring=True,
|
|
213
|
-
content_type="application/json",
|
|
214
|
-
)
|
|
215
|
-
error, country, town, lat, lng = lookup_country("AL109NE")
|
|
216
|
-
assert "Request error" in error
|
|
217
|
-
self.assert_default_country_and_coord(country, town, lat, lng)
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
from aimmo.models import Game
|
|
2
|
-
from common.models import Class
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def generate_name():
|
|
6
|
-
name = "Game %d" % generate_name.next_id
|
|
7
|
-
|
|
8
|
-
generate_name.next_id += 1
|
|
9
|
-
|
|
10
|
-
return name
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
generate_name.next_id = 1
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def create_aimmo_game_directly(klass: Class, worksheet_id: int) -> Game:
|
|
17
|
-
"""Generate an aimmo game with the details given.
|
|
18
|
-
|
|
19
|
-
Args:
|
|
20
|
-
klass (Class): The instance of the class.
|
|
21
|
-
worksheet_id (int): The id of the worksheet.
|
|
22
|
-
|
|
23
|
-
Returns:
|
|
24
|
-
game: Game: The game model instance.
|
|
25
|
-
"""
|
|
26
|
-
name = generate_name()
|
|
27
|
-
|
|
28
|
-
game = Game.objects.create(name=name, game_class=klass, worksheet_id=worksheet_id)
|
|
29
|
-
|
|
30
|
-
return game
|