rapid-router 5.18.0__py2.py3-none-any.whl → 7.6.8__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.
- example_project/rapid_router_test_settings.py +19 -7
- example_project/settings.py +21 -8
- example_project/urls.py +5 -6
- game/__init__.py +1 -1
- game/admin.py +7 -2
- game/character.py +8 -0
- game/decor.py +40 -0
- game/end_to_end_tests/base_game_test.py +34 -27
- game/end_to_end_tests/editor_page.py +15 -0
- game/end_to_end_tests/game_page.py +88 -20
- game/end_to_end_tests/selenium_test_case.py +1 -20
- game/end_to_end_tests/test_cow_crashes.py +3 -5
- game/end_to_end_tests/test_level_editor.py +273 -10
- game/end_to_end_tests/test_level_selection.py +25 -3
- game/end_to_end_tests/test_play_through.py +222 -127
- game/end_to_end_tests/test_python_levels.py +41 -7
- game/end_to_end_tests/test_saving_workspace.py +2 -1
- game/forms.py +7 -1
- game/level_management.py +26 -11
- game/messages.py +899 -337
- game/migrations/0001_squashed_0025_levels_ordering_pt1.py +19 -1
- game/migrations/0026_levels_pt2.py +13 -2
- game/migrations/0032_cannot_turn_left_level.py +13 -2
- game/migrations/0033_recursion_level.py +13 -2
- game/migrations/0034_joes_level.py +13 -2
- game/migrations/0035_disable_route_score_level_70.py +0 -2
- game/migrations/0036_level_score_73.py +0 -2
- game/migrations/0037_level_score_79.py +0 -2
- game/migrations/0038_level_score_40.py +0 -1
- game/migrations/0042_level_score_73.py +0 -2
- game/migrations/0048_add_cow_field_and_blocks.py +0 -2
- game/migrations/0049_level_score_34.py +0 -2
- game/migrations/0050_level_score_40.py +0 -2
- game/migrations/0051_level_score_49.py +0 -1
- game/migrations/0086_loop_levels.py +13 -2
- game/migrations/0092_disable_algo_score_in_custom_levels.py +28 -0
- game/migrations/0093_alter_level_character_name.py +18 -0
- game/migrations/0094_add_hint_lesson_subtitle_to_levels.py +28 -0
- game/migrations/0095_level_commands.py +18 -0
- game/migrations/0096_alter_level_commands.py +18 -0
- game/migrations/0097_add_python_den_levels.py +1515 -0
- game/migrations/0098_add_episode_link_fields.py +44 -0
- game/migrations/0099_python_episodes_links.py +103 -0
- game/migrations/0100_reorder_python_levels.py +179 -0
- game/migrations/0101_rename_episodes.py +45 -0
- game/migrations/0102_reoder_episodes_13_14.py +136 -0
- game/migrations/0103_level_1015_solution.py +26 -0
- game/migrations/0104_remove_level_direct_drive.py +17 -0
- game/migrations/0105_delete_invalid_attempts.py +18 -0
- game/migrations/0106_fields_to_snake_case.py +48 -0
- game/migrations/0107_rename_worksheet_link_episode_student_worksheet_link.py +18 -0
- game/migrations/0108_episode_indy_worksheet_link.py +18 -0
- game/migrations/0109_create_episodes_23_and_24.py +99 -0
- game/migrations/0110_remove_episode_indy_worksheet_link_and_more.py +100 -0
- game/migrations/0111_create_worksheets.py +149 -0
- game/migrations/0112_worksheet_locked_classes.py +21 -0
- game/migrations/0113_level_needs_approval.py +18 -0
- game/migrations/0114_default_and_non_student_levels_no_approval.py +31 -0
- game/migrations/0115_level_level__default_does_not_need_approval.py +22 -0
- game/migrations/0116_update_worksheet_video_links.py +68 -0
- game/migrations/0117_update_solutions_to_if_else.py +61 -0
- game/models.py +127 -17
- game/permissions.py +51 -19
- game/python_den_urls.py +26 -0
- game/random_road.py +9 -9
- game/serializers.py +12 -17
- game/static/django_reverse_js/js/reverse.js +171 -0
- game/static/game/css/LilitaOne-Regular.ttf +0 -0
- game/static/game/css/backgrounds.css +8 -12
- game/static/game/css/dataTables.custom.css +3 -2
- game/static/game/css/editor.css +47 -0
- game/static/game/css/game.css +37 -43
- game/static/game/css/game_screen.css +16 -0
- game/static/game/css/level_editor.css +5 -0
- game/static/game/css/level_selection.css +17 -2
- game/static/game/image/Python_Den_hero_student.png +0 -0
- game/static/game/image/Python_levels_page.svg +1954 -0
- game/static/game/image/characters/front_view/Electric_van.svg +448 -0
- game/static/game/image/characters/top_view/Electric_van.svg +448 -0
- game/static/game/image/decor/city/solar_panel.svg +1200 -0
- game/static/game/image/decor/farm/solar_panel.svg +86 -0
- game/static/game/image/decor/grass/solar_panel.svg +86 -0
- game/static/game/image/decor/snow/solar_panel.svg +173 -0
- game/static/game/image/electric_van.svg +448 -0
- game/static/game/image/icons/description.svg +1 -0
- game/static/game/image/icons/hint.svg +1 -0
- game/static/game/image/icons/python.svg +1 -1
- game/static/game/image/pigeon.svg +684 -0
- game/static/game/image/python_den_header.svg +19 -0
- game/static/game/js/animation.js +65 -24
- game/static/game/js/blockly/msg/js/bg.js +52 -1
- game/static/game/js/blockly/msg/js/ca.js +52 -1
- game/static/game/js/blockly/msg/js/en-gb.js +2 -0
- game/static/game/js/blockly/msg/js/en.js +2 -0
- game/static/game/js/blockly/msg/js/es.js +52 -1
- game/static/game/js/blockly/msg/js/fr.js +2 -0
- game/static/game/js/blockly/msg/js/hi.js +2 -0
- game/static/game/js/blockly/msg/js/it.js +52 -1
- game/static/game/js/blockly/msg/js/pl.js +52 -1
- game/static/game/js/blockly/msg/js/pt-br.js +52 -1
- game/static/game/js/blockly/msg/js/ru.js +52 -1
- game/static/game/js/blockly/msg/js/ur.js +52 -1
- game/static/game/js/blocklyCustomBlocks.js +93 -52
- game/static/game/js/button.js +12 -0
- game/static/game/js/cow.js +11 -7
- game/static/game/js/drawing.js +68 -29
- game/static/game/js/editor.js +23 -0
- game/static/game/js/game.js +74 -110
- game/static/game/js/level_editor.js +646 -274
- game/static/game/js/level_moderation.js +33 -2
- game/static/game/js/level_selection.js +1 -1
- game/static/game/js/loadLanguages.js +2 -2
- game/static/game/js/model.js +32 -2
- game/static/game/js/pythonControl.js +14 -1
- game/static/game/js/scoreboard.js +0 -37
- game/static/game/js/scoreboardSharedLevels.js +48 -0
- game/static/game/js/skulpt/skulpt-stdlib.js +1 -1
- game/static/game/js/sound.js +52 -5
- game/static/game/raphael_image/characters/top_view/Electric_van.svg +448 -0
- game/static/game/raphael_image/decor/city/solar_panel.svg +1200 -0
- game/static/game/raphael_image/decor/farm/solar_panel.svg +86 -0
- game/static/game/raphael_image/decor/grass/solar_panel.svg +86 -0
- game/static/game/raphael_image/decor/snow/solar_panel.svg +173 -0
- game/static/game/raphael_image/pigeon.svg +685 -0
- game/static/game/sass/game.scss +2 -2
- game/static/game/sound/clown_horn.mp3 +0 -0
- game/static/game/sound/clown_horn.ogg +0 -0
- game/static/game/sound/electric_van_starting.mp3 +0 -0
- game/static/game/sound/electric_van_starting.ogg +0 -0
- game/static/game/sound/pigeon.mp3 +0 -0
- game/static/game/sound/pigeon.ogg +0 -0
- game/static/game/sound/sleigh_bells.mp3 +0 -0
- game/static/game/sound/sleigh_bells.ogg +0 -0
- game/static/game/sound/sleigh_crash.mp3 +0 -0
- game/static/game/sound/sleigh_crash.ogg +0 -0
- game/templates/game/base.html +34 -14
- game/templates/game/basenonav.html +11 -5
- game/templates/game/game.html +142 -38
- game/templates/game/level_editor.html +340 -236
- game/templates/game/level_moderation.html +19 -6
- game/templates/game/level_selection.html +18 -110
- game/templates/game/python_den_level_selection.html +291 -0
- game/templates/game/python_den_worksheet.html +101 -0
- game/templates/game/scoreboard.html +83 -64
- game/tests/test_level_editor.py +94 -26
- game/tests/test_level_selection.py +149 -46
- game/tests/test_python_den_worksheet.py +85 -0
- game/tests/test_scoreboard.py +34 -7
- game/tests/utils/level.py +32 -26
- game/theme.py +5 -5
- game/urls.py +199 -61
- game/views/language_code_conversions.py +86 -86
- game/views/level.py +155 -63
- game/views/level_editor.py +88 -55
- game/views/level_moderation.py +23 -0
- game/views/level_selection.py +116 -47
- game/views/level_solutions.py +491 -106
- game/views/scoreboard.py +76 -51
- game/views/worksheet.py +25 -0
- rapid_router-7.6.8.dist-info/METADATA +174 -0
- {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info}/RECORD +164 -104
- {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info}/WHEEL +1 -1
- example_project/manage.py +0 -10
- game/static/game/image/actions/go.svg +0 -18
- game/static/game/js/js-reverse.js +0 -14
- game/static/game/js/pqselect.min.js +0 -9
- game/static/game/js/widget-scroller.js +0 -906
- rapid_router-5.18.0.dist-info/METADATA +0 -17
- {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info/licenses}/LICENSE.md +0 -0
- {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info}/top_level.txt +0 -0
|
@@ -1,11 +1,37 @@
|
|
|
1
1
|
from selenium.webdriver.common.action_chains import ActionChains
|
|
2
2
|
from selenium.webdriver.common.by import By
|
|
3
|
+
from selenium.webdriver.support import expected_conditions as EC
|
|
4
|
+
from selenium.webdriver.support.ui import Select, WebDriverWait
|
|
3
5
|
|
|
4
6
|
from game.end_to_end_tests.base_game_test import BaseGameTest
|
|
5
7
|
from game.views.level_editor import available_blocks
|
|
6
8
|
|
|
9
|
+
DELAY_TIME = 10
|
|
10
|
+
|
|
7
11
|
|
|
8
12
|
class TestLevelEditor(BaseGameTest):
|
|
13
|
+
def set_up_basic_map(self):
|
|
14
|
+
self.test_level_editor_displays()
|
|
15
|
+
|
|
16
|
+
add_road_button = self.selenium.find_element(By.ID, "add_road")
|
|
17
|
+
add_road_button.click()
|
|
18
|
+
|
|
19
|
+
road_start = self.selenium.find_element(
|
|
20
|
+
By.CSS_SELECTOR, "rect[x='130'][y='530']"
|
|
21
|
+
)
|
|
22
|
+
road_end = self.selenium.find_element(By.CSS_SELECTOR, "rect[x='330'][y='530']")
|
|
23
|
+
ActionChains(self.selenium).drag_and_drop(road_start, road_end).perform()
|
|
24
|
+
|
|
25
|
+
mark_start_button = self.selenium.find_element(By.ID, "start")
|
|
26
|
+
mark_start_button.click()
|
|
27
|
+
ActionChains(self.selenium).move_to_element(road_start).click().perform()
|
|
28
|
+
|
|
29
|
+
add_house_button = self.selenium.find_element(By.ID, "add_house")
|
|
30
|
+
add_house_button.click()
|
|
31
|
+
ActionChains(self.selenium).move_to_element(road_end).click().perform()
|
|
32
|
+
|
|
33
|
+
return [road_start, road_end]
|
|
34
|
+
|
|
9
35
|
def test_level_editor_displays(self):
|
|
10
36
|
page = self.go_to_level_editor()
|
|
11
37
|
|
|
@@ -22,25 +48,262 @@ class TestLevelEditor(BaseGameTest):
|
|
|
22
48
|
assert page.element_exists_by_id(f"{block_type}_image")
|
|
23
49
|
|
|
24
50
|
def test_multiple_houses(self):
|
|
25
|
-
|
|
26
|
-
add_road_button.click()
|
|
51
|
+
[road_start, road_end] = self.set_up_basic_map()
|
|
27
52
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
53
|
+
road_middle = self.selenium.find_element(
|
|
54
|
+
By.CSS_SELECTOR, "rect[x='230'][y='530']"
|
|
55
|
+
)
|
|
31
56
|
|
|
32
57
|
add_house_button = self.selenium.find_element(By.ID, "add_house")
|
|
33
58
|
add_house_button.click()
|
|
34
|
-
ActionChains(self.selenium).move_to_element(
|
|
35
|
-
ActionChains(self.selenium).move_to_element(road_end).click().perform()
|
|
59
|
+
ActionChains(self.selenium).move_to_element(road_middle).click().perform()
|
|
36
60
|
|
|
37
|
-
added_houses = self.selenium.find_elements(
|
|
61
|
+
added_houses = self.selenium.find_elements(
|
|
62
|
+
By.CSS_SELECTOR, "rect[fill='#0000ff']"
|
|
63
|
+
)
|
|
38
64
|
assert len(added_houses) == 2
|
|
39
65
|
|
|
40
66
|
delete_house_button = self.selenium.find_element(By.ID, "delete_house")
|
|
41
67
|
delete_house_button.click()
|
|
42
|
-
ActionChains(self.selenium).move_to_element(
|
|
68
|
+
ActionChains(self.selenium).move_to_element(road_middle).click().perform()
|
|
43
69
|
ActionChains(self.selenium).move_to_element(road_start).perform()
|
|
44
70
|
|
|
45
|
-
houses_after_delete = self.selenium.find_elements(
|
|
71
|
+
houses_after_delete = self.selenium.find_elements(
|
|
72
|
+
By.CSS_SELECTOR, "rect[fill='#0000ff']"
|
|
73
|
+
)
|
|
46
74
|
assert len(houses_after_delete) == 1
|
|
75
|
+
|
|
76
|
+
def test_cow_on_origin(self):
|
|
77
|
+
page = self.go_to_level_editor()
|
|
78
|
+
[road_start, road_end] = self.set_up_basic_map()
|
|
79
|
+
|
|
80
|
+
origin_space = self.selenium.find_elements(
|
|
81
|
+
By.CSS_SELECTOR, "rect[fill='#ff0000']"
|
|
82
|
+
)
|
|
83
|
+
assert len(origin_space) == 1
|
|
84
|
+
|
|
85
|
+
page.go_to_scenery_tab()
|
|
86
|
+
|
|
87
|
+
draggable_cow = self.selenium.find_element(By.ID, "cow")
|
|
88
|
+
ActionChains(self.selenium).click_and_hold(draggable_cow).move_to_element(
|
|
89
|
+
road_start
|
|
90
|
+
).perform()
|
|
91
|
+
start_space_warning = self.selenium.find_elements(
|
|
92
|
+
By.CSS_SELECTOR,
|
|
93
|
+
"rect[fill='#e35f4d'][fill-opacity='0.7'][x='130'][y='530']",
|
|
94
|
+
)
|
|
95
|
+
assert len(start_space_warning) == 1
|
|
96
|
+
|
|
97
|
+
def test_cow_on_house(self):
|
|
98
|
+
page = self.go_to_level_editor()
|
|
99
|
+
[road_start, road_end] = self.set_up_basic_map()
|
|
100
|
+
|
|
101
|
+
house_space = self.selenium.find_elements(
|
|
102
|
+
By.CSS_SELECTOR, "rect[fill='#0000ff']"
|
|
103
|
+
)
|
|
104
|
+
assert len(house_space) == 1
|
|
105
|
+
assert road_end == house_space[0]
|
|
106
|
+
|
|
107
|
+
page.go_to_scenery_tab()
|
|
108
|
+
|
|
109
|
+
draggable_cow = self.selenium.find_elements(By.ID, "cow")
|
|
110
|
+
assert len(draggable_cow) == 1
|
|
111
|
+
ActionChains(self.selenium).click_and_hold(draggable_cow[0]).move_to_element(
|
|
112
|
+
road_end
|
|
113
|
+
).perform()
|
|
114
|
+
allowed_space = self.selenium.find_elements(
|
|
115
|
+
By.CSS_SELECTOR, "rect[fill='#87e34d']"
|
|
116
|
+
)
|
|
117
|
+
assert len(allowed_space) == 0
|
|
118
|
+
|
|
119
|
+
def test_draggable_decor(self):
|
|
120
|
+
page = self.go_to_level_editor()
|
|
121
|
+
page.go_to_scenery_tab()
|
|
122
|
+
|
|
123
|
+
source_tree = self.selenium.find_element(By.ID, "tree2")
|
|
124
|
+
end_space = self.selenium.find_element(
|
|
125
|
+
By.CSS_SELECTOR, "rect[x='130'][y='530']"
|
|
126
|
+
)
|
|
127
|
+
ActionChains(self.selenium).drag_and_drop(source_tree, end_space).perform()
|
|
128
|
+
|
|
129
|
+
decor_tree = self.selenium.find_elements(By.CSS_SELECTOR, "image[x='0'][y='0']")
|
|
130
|
+
cloned_source_tree = self.selenium.find_elements(By.ID, "tree2")
|
|
131
|
+
assert len(decor_tree) == 1
|
|
132
|
+
assert len(cloned_source_tree) == 1
|
|
133
|
+
|
|
134
|
+
def test_draggable_cow(self):
|
|
135
|
+
page = self.go_to_level_editor()
|
|
136
|
+
page.go_to_scenery_tab()
|
|
137
|
+
|
|
138
|
+
source_cow = self.selenium.find_element(By.ID, "cow")
|
|
139
|
+
end_space = self.selenium.find_element(
|
|
140
|
+
By.CSS_SELECTOR, "rect[x='130'][y='530']"
|
|
141
|
+
)
|
|
142
|
+
ActionChains(self.selenium).drag_and_drop(source_cow, end_space).perform()
|
|
143
|
+
|
|
144
|
+
scenery_cow = self.selenium.find_elements(
|
|
145
|
+
By.CSS_SELECTOR, "image[x='0'][y='0']"
|
|
146
|
+
)
|
|
147
|
+
cloned_source_cow = self.selenium.find_elements(By.ID, "cow")
|
|
148
|
+
assert len(scenery_cow) == 1
|
|
149
|
+
assert len(cloned_source_cow) == 1
|
|
150
|
+
|
|
151
|
+
def test_draggable_traffic_light(self):
|
|
152
|
+
page = self.go_to_level_editor()
|
|
153
|
+
page.go_to_scenery_tab()
|
|
154
|
+
|
|
155
|
+
source_light = self.selenium.find_element(By.ID, "trafficLightRed")
|
|
156
|
+
end_space = self.selenium.find_element(
|
|
157
|
+
By.CSS_SELECTOR, "rect[x='130'][y='530']"
|
|
158
|
+
)
|
|
159
|
+
ActionChains(self.selenium).drag_and_drop(source_light, end_space).perform()
|
|
160
|
+
|
|
161
|
+
scenery_light = self.selenium.find_elements(
|
|
162
|
+
By.CSS_SELECTOR, "image[x='0'][y='0']"
|
|
163
|
+
)
|
|
164
|
+
cloned_source_light = self.selenium.find_elements(By.ID, "trafficLightRed")
|
|
165
|
+
assert len(scenery_light) == 1
|
|
166
|
+
assert len(cloned_source_light) == 1
|
|
167
|
+
|
|
168
|
+
def test_custom_description_and_hint(self):
|
|
169
|
+
# login
|
|
170
|
+
self.login_once()
|
|
171
|
+
|
|
172
|
+
# go to level editor and set up basic map
|
|
173
|
+
page = self.go_to_level_editor()
|
|
174
|
+
[road_start, road_end] = self.set_up_basic_map()
|
|
175
|
+
|
|
176
|
+
# fill in custom description and hint fields
|
|
177
|
+
page.go_to_description_tab()
|
|
178
|
+
self.selenium.find_element(By.ID, "subtitle").send_keys("test subtitle")
|
|
179
|
+
self.selenium.find_element(By.ID, "description").send_keys("test description")
|
|
180
|
+
|
|
181
|
+
page.go_to_hint_tab()
|
|
182
|
+
self.selenium.find_element(By.ID, "hint").send_keys("test hint")
|
|
183
|
+
|
|
184
|
+
# save level and choose to play it
|
|
185
|
+
page.go_to_save_tab()
|
|
186
|
+
self.selenium.find_element(By.ID, "levelNameInput").send_keys("test level")
|
|
187
|
+
self.selenium.find_element(By.ID, "saveLevel").click()
|
|
188
|
+
assert WebDriverWait(self.selenium, DELAY_TIME).until(
|
|
189
|
+
EC.presence_of_element_located((By.ID, "play_button"))
|
|
190
|
+
)
|
|
191
|
+
self.selenium.find_element(By.ID, "play_button").click()
|
|
192
|
+
|
|
193
|
+
# check to see if custom subtitle and lesson appear on the initial popup
|
|
194
|
+
assert WebDriverWait(self.selenium, DELAY_TIME).until(
|
|
195
|
+
EC.presence_of_element_located((By.ID, "myModal-lead"))
|
|
196
|
+
)
|
|
197
|
+
modal_text = self.selenium.find_element(By.ID, "myModal-lead").get_attribute(
|
|
198
|
+
"innerHTML"
|
|
199
|
+
)
|
|
200
|
+
assert "test subtitle" in modal_text
|
|
201
|
+
assert "test description" in modal_text
|
|
202
|
+
self.selenium.find_element(By.ID, "close-modal").click()
|
|
203
|
+
|
|
204
|
+
# wait for modal to disappear
|
|
205
|
+
assert WebDriverWait(self.selenium, DELAY_TIME).until(
|
|
206
|
+
EC.none_of(
|
|
207
|
+
EC.visibility_of_all_elements_located((By.ID, "myModal-mainText"))
|
|
208
|
+
)
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# check to see if the custom hint appears on failure modal
|
|
212
|
+
fast_tab = self.selenium.find_element(By.ID, "fast_tab")
|
|
213
|
+
fast_tab.click()
|
|
214
|
+
assert WebDriverWait(self.selenium, DELAY_TIME).until(
|
|
215
|
+
EC.visibility_of_element_located((By.ID, "hintPopupBtn"))
|
|
216
|
+
)
|
|
217
|
+
hint_button = self.selenium.find_element(By.ID, "hintPopupBtn")
|
|
218
|
+
hint_button.click()
|
|
219
|
+
|
|
220
|
+
hint_modal_text = self.selenium.find_element(By.ID, "hintText").get_attribute(
|
|
221
|
+
"innerHTML"
|
|
222
|
+
)
|
|
223
|
+
hint_modal_style = self.selenium.find_element(By.ID, "hintText").get_attribute(
|
|
224
|
+
"style"
|
|
225
|
+
)
|
|
226
|
+
assert "display: none" in hint_button.get_attribute("style")
|
|
227
|
+
assert "display: block" in hint_modal_style
|
|
228
|
+
assert "test hint" in hint_modal_text
|
|
229
|
+
|
|
230
|
+
self.selenium.find_element(By.ID, "try_again_button").click()
|
|
231
|
+
|
|
232
|
+
# check to see if the custom hint appears on the hint popup
|
|
233
|
+
self.selenium.find_element(By.ID, "help_tab").click()
|
|
234
|
+
assert WebDriverWait(self.selenium, DELAY_TIME).until(
|
|
235
|
+
EC.visibility_of_element_located((By.ID, "myModal-mainText"))
|
|
236
|
+
)
|
|
237
|
+
hint_modal_text_two = self.selenium.find_element(
|
|
238
|
+
By.ID, "myModal-mainText"
|
|
239
|
+
).get_attribute("innerHTML")
|
|
240
|
+
assert "test hint" in hint_modal_text_two
|
|
241
|
+
|
|
242
|
+
def test_solar_panels(self):
|
|
243
|
+
"""test that the solar panels appear as a scenery option when clicking on the scenery tab
|
|
244
|
+
"""
|
|
245
|
+
page = self.go_to_level_editor()
|
|
246
|
+
page.go_to_scenery_tab()
|
|
247
|
+
|
|
248
|
+
solar_panel = self.selenium.find_element(
|
|
249
|
+
By.ID, "solar_panel"
|
|
250
|
+
)
|
|
251
|
+
assert solar_panel.is_displayed()
|
|
252
|
+
|
|
253
|
+
def test_electric_fuel_gauge(self):
|
|
254
|
+
self.login_once()
|
|
255
|
+
|
|
256
|
+
page = self.go_to_level_editor()
|
|
257
|
+
|
|
258
|
+
[road_start, road_end] = self.set_up_basic_map()
|
|
259
|
+
page.go_to_character_tab()
|
|
260
|
+
|
|
261
|
+
# the electric van has dropdown value 7 - select the electric van as character
|
|
262
|
+
Select(self.selenium.find_element(By.ID, "character_select")).select_by_value(
|
|
263
|
+
"7"
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
# save level and choose to play it
|
|
267
|
+
page.go_to_save_tab()
|
|
268
|
+
self.selenium.find_element(By.ID, "levelNameInput").send_keys(
|
|
269
|
+
"test electric van level"
|
|
270
|
+
)
|
|
271
|
+
self.selenium.find_element(By.ID, "saveLevel").click()
|
|
272
|
+
assert WebDriverWait(self.selenium, DELAY_TIME).until(
|
|
273
|
+
EC.visibility_of_element_located((By.ID, "myModal-lead"))
|
|
274
|
+
)
|
|
275
|
+
self.selenium.find_element(By.ID, "play_button").click()
|
|
276
|
+
|
|
277
|
+
# check to see if electric fuel gauge appears
|
|
278
|
+
assert WebDriverWait(self.selenium, DELAY_TIME).until(
|
|
279
|
+
EC.presence_of_element_located((By.ID, "electricFuelGauge"))
|
|
280
|
+
)
|
|
281
|
+
electric_fuel_gauge = self.selenium.find_element(By.ID, "electricFuelGauge")
|
|
282
|
+
assert "visibility: visible" in electric_fuel_gauge.get_attribute("style")
|
|
283
|
+
|
|
284
|
+
def test_pigeon(self):
|
|
285
|
+
"""Test that cows on the map automatically become pigeons when the theme is changed to "city" """
|
|
286
|
+
page = self.go_to_level_editor()
|
|
287
|
+
page.go_to_scenery_tab()
|
|
288
|
+
|
|
289
|
+
source_cow = self.selenium.find_element(By.ID, "cow")
|
|
290
|
+
end_space = self.selenium.find_element(
|
|
291
|
+
By.CSS_SELECTOR, "rect[x='130'][y='530']"
|
|
292
|
+
)
|
|
293
|
+
ActionChains(self.selenium).drag_and_drop(source_cow, end_space).perform()
|
|
294
|
+
|
|
295
|
+
scenery_cow = self.selenium.find_elements(
|
|
296
|
+
By.CSS_SELECTOR, "image[x='0'][y='0']"
|
|
297
|
+
)
|
|
298
|
+
cow_link = scenery_cow[0].get_attribute("href")
|
|
299
|
+
assert cow_link == "/static/game/raphael_image/Clarice.svg"
|
|
300
|
+
|
|
301
|
+
Select(self.selenium.find_element(By.ID, "theme_select")).select_by_value(
|
|
302
|
+
"city"
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
scenery_pigeon = self.selenium.find_elements(
|
|
306
|
+
By.CSS_SELECTOR, "image[x='0'][y='0']"
|
|
307
|
+
)
|
|
308
|
+
pigeon_link = scenery_pigeon[0].get_attribute("href")
|
|
309
|
+
assert pigeon_link == "/static/game/raphael_image/pigeon.svg"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import pytest
|
|
1
2
|
from common.tests.utils.classes import create_class_directly
|
|
2
3
|
from common.tests.utils.organisation import create_organisation_directly
|
|
3
4
|
from common.tests.utils.student import create_school_student_directly
|
|
@@ -34,7 +35,9 @@ class TestLevelSelection(BaseGameTest):
|
|
|
34
35
|
page = self.go_to_reverse("levels")
|
|
35
36
|
|
|
36
37
|
# The coin images for the levels
|
|
37
|
-
level_coin_images = page.browser.find_elements(
|
|
38
|
+
level_coin_images = page.browser.find_elements(
|
|
39
|
+
By.CSS_SELECTOR, ("#collapse-4 div img")
|
|
40
|
+
)
|
|
38
41
|
# There are 4 levels in this episode, each with gold coin
|
|
39
42
|
assert_that(len(level_coin_images), equal_to(4))
|
|
40
43
|
|
|
@@ -45,13 +48,32 @@ class TestLevelSelection(BaseGameTest):
|
|
|
45
48
|
)
|
|
46
49
|
|
|
47
50
|
# So the episode has a gold coin too
|
|
48
|
-
episode_coin_image = page.browser.find_element(
|
|
51
|
+
episode_coin_image = page.browser.find_element(
|
|
52
|
+
By.CSS_SELECTOR, "#episode-4 > p > img"
|
|
53
|
+
)
|
|
49
54
|
assert_that(
|
|
50
55
|
episode_coin_image.get_attribute("src"),
|
|
51
56
|
ends_with("/static/game/image/coins/coin_gold.svg"),
|
|
52
57
|
)
|
|
53
58
|
|
|
54
59
|
try:
|
|
55
|
-
image_for_uncomplete_episode = page.browser.find_element(
|
|
60
|
+
image_for_uncomplete_episode = page.browser.find_element(
|
|
61
|
+
By.CSS_SELECTOR, "#episode-3 > p > img"
|
|
62
|
+
)
|
|
56
63
|
except NoSuchElementException as this_should_happen:
|
|
57
64
|
pass
|
|
65
|
+
|
|
66
|
+
@pytest.mark.skip(reason="levelless episode no longer opens up after clicking next level, need to investigate")
|
|
67
|
+
def test_redirect_to_levelless_episode(self):
|
|
68
|
+
levels_page = self.go_to_reverse("python_levels")
|
|
69
|
+
expected_url = levels_page.browser.current_url
|
|
70
|
+
|
|
71
|
+
page = self.go_to_level_without_dismissing_dialog(26, True)
|
|
72
|
+
self.selenium.find_element(By.ID, "next_button").click()
|
|
73
|
+
|
|
74
|
+
current_url = page.browser.current_url
|
|
75
|
+
assert current_url == expected_url
|
|
76
|
+
|
|
77
|
+
episode_20_header = self.selenium.find_element(By.ID, "collapse-20")
|
|
78
|
+
episode_20_expanded = episode_20_header.get_attribute("class")
|
|
79
|
+
assert episode_20_expanded == "collapse"
|