Skip to content

Commit

Permalink
Merge branch 'master' into python-den-levels-page
Browse files Browse the repository at this point in the history
  • Loading branch information
evemartin authored Aug 12, 2024
2 parents 075fa04 + d6ca990 commit de431c6
Show file tree
Hide file tree
Showing 24 changed files with 583 additions and 332 deletions.
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,46 @@

<!--next-version-placeholder-->

## v6.0.2 (2024-08-08)

### Fix

* Flying cow bug ([#1699](https://github.com/ocadotechnology/rapid-router/issues/1699)) ([`2a6c005`](https://github.com/ocadotechnology/rapid-router/commit/2a6c0056cccdf5deee10798721761bae44ff7e3e))

## v6.0.1 (2024-08-07)

### Fix

* Deliver at non-destination does not show popup ([#1694](https://github.com/ocadotechnology/rapid-router/issues/1694)) ([`9e1f4b0`](https://github.com/ocadotechnology/rapid-router/commit/9e1f4b05749186469fd49e64d2620b10ad10e4d2))

## v6.0.0 (2024-08-01)

### Fix

* Remove Kurono references ([#1690](https://github.com/ocadotechnology/rapid-router/issues/1690)) ([`9cab34e`](https://github.com/ocadotechnology/rapid-router/commit/9cab34ea513e34d8be86a3618b19e8a68a8ab297))

### Breaking

* Remove Kurono references ([#1690](https://github.com/ocadotechnology/rapid-router/issues/1690)) ([`9cab34e`](https://github.com/ocadotechnology/rapid-router/commit/9cab34ea513e34d8be86a3618b19e8a68a8ab297))

## v5.28.0 (2024-07-31)

### Feature

* Add Python commands for crossing animals ([#1689](https://github.com/ocadotechnology/rapid-router/issues/1689)) ([`c6aed98`](https://github.com/ocadotechnology/rapid-router/commit/c6aed9843c72c8b176bedcb128cd4600017be6de))

## v5.27.1 (2024-07-31)

### Fix

* Reinstate buttons to overwrite popup ([#1688](https://github.com/ocadotechnology/rapid-router/issues/1688)) ([`9866068`](https://github.com/ocadotechnology/rapid-router/commit/986606850f478d33f01f1c407092423d8726f8f3))

## v5.27.0 (2024-07-30)

### Feature

* Remove superflous python commands in rapid router. ([#1680](https://github.com/ocadotechnology/rapid-router/issues/1680)) ([`d5e051d`](https://github.com/ocadotechnology/rapid-router/commit/d5e051d05f2f39f24aaf98e37e7e7bb45e2becc3))

## v5.26.1 (2024-07-17)

### Fix
Expand Down
242 changes: 38 additions & 204 deletions Pipfile.lock

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion example_project/rapid_router_test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@
"game",
"pipeline",
"portal",
"aimmo",
"common",
"django.contrib.admin",
"django.contrib.admindocs",
Expand Down
1 change: 0 additions & 1 deletion example_project/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
"game",
"pipeline",
"portal",
"aimmo",
"common",
"django.contrib.admin",
"django.contrib.admindocs",
Expand Down
2 changes: 0 additions & 2 deletions example_project/urls.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from aimmo import urls as aimmo_urls
from django.conf.urls import include, url
from django.contrib import admin
from django.urls import path
Expand All @@ -13,6 +12,5 @@
url(r"^", include(portal_urls)),
path("administration/", admin.site.urls),
url(r"^rapidrouter/", include(game_urls)),
url(r"^aimmo/", include(aimmo_urls)),
url(r"^pythonden/", include(python_den_urls))
]
2 changes: 1 addition & 1 deletion game/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "5.26.1"
__version__ = "6.0.2"
25 changes: 20 additions & 5 deletions game/end_to_end_tests/base_game_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ def go_to_homepage(self):
return HomePage(self.selenium)

def go_to_level(self, level_name):
path = reverse("play_default_level", kwargs={"levelName": str(level_name)})
path = reverse(
"play_default_level", kwargs={"levelName": str(level_name)}
)
self._go_to_path(path)

return GamePage(self.selenium)
Expand Down Expand Up @@ -117,15 +119,21 @@ def try_again_if_not_full_score_test(self, level, workspace_file):

workspace_id = self.use_workspace(workspace_file, user_profile)

return self.go_to_level(level).load_solution(workspace_id).run_retry_program()
return (
self.go_to_level(level)
.load_solution(workspace_id)
.run_retry_program()
)

def run_crashing_test(self, level, workspace_file):
user_profile = self.login_once()

workspace_id = self.use_workspace(workspace_file, user_profile)

return (
self.go_to_level(level).load_solution(workspace_id).run_crashing_program()
self.go_to_level(level)
.load_solution(workspace_id)
.run_crashing_program()
)

def run_python_commands_test(self, level):
Expand All @@ -146,6 +154,9 @@ def run_console_print_test(self, level):
def run_invalid_import_test(self, level):
return self.go_to_level(level).run_invalid_import_program()

def run_animal_sound_horn_test(self, level):
return self.go_to_custom_level(level).run_animal_sound_horn_program()

def running_out_of_instructions_test(self, level, workspace_file):
user_profile = self.login_once()

Expand Down Expand Up @@ -217,7 +228,9 @@ def login_once(self):
login_page = self.go_to_homepage().go_to_teacher_login_page()
login_page.login(email, password)
email = email
BaseGameTest.user_profile = UserProfile.objects.get(user__email=email)
BaseGameTest.user_profile = UserProfile.objects.get(
user__email=email
)

BaseGameTest.already_logged_on = True

Expand All @@ -234,7 +247,9 @@ def tearDownClass(cls):
BaseGameTest.already_logged_on = False

def solution_file_path(self, filename):
return os.path.join(BaseGameTest.BLOCKLY_SOLUTIONS_DIR, filename + ".xml")
return os.path.join(
BaseGameTest.BLOCKLY_SOLUTIONS_DIR, filename + ".xml"
)

def read_solution(self, filename):
path = self.solution_file_path(filename)
Expand Down
72 changes: 58 additions & 14 deletions game/end_to_end_tests/game_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ class GamePage(BasePage):
def __init__(self, browser):
super(GamePage, self).__init__(browser)

self.browser.execute_script("ocargo.animation.FAST_ANIMATION_DURATION = 1;")
self.browser.execute_script(
"ocargo.animation.FAST_ANIMATION_DURATION = 1;"
)

assert self.on_correct_page("game_page")

Expand All @@ -30,13 +32,19 @@ def _dismiss_initial_dialog(self):
return self

def dismiss_dialog(self, button_id):
self.wait_for_element_to_be_clickable((By.ID, button_id), wait_seconds=15)
self.wait_for_element_to_be_clickable(
(By.ID, button_id), wait_seconds=15
)
self.browser.find_element(By.ID, button_id).click()
self.wait_for_element_to_be_invisible((By.ID, button_id), wait_seconds=15)
self.wait_for_element_to_be_invisible(
(By.ID, button_id), wait_seconds=15
)

def save_solution(self, workspace_name):
self.browser.find_element(By.ID, "save_tab").click()
self.browser.find_element(By.ID, "workspaceNameInput").send_keys(workspace_name)
self.browser.find_element(By.ID, "workspaceNameInput").send_keys(
workspace_name
)
self.browser.find_element(By.ID, "saveWorkspace").click()
return self

Expand Down Expand Up @@ -70,7 +78,9 @@ def step(self):

def solution_button(self):
self.browser.find_element(By.ID, "solution_tab").click()
solution_loaded = self.browser.execute_script("return ocargo.solutionLoaded;")
solution_loaded = self.browser.execute_script(
"return ocargo.solutionLoaded;"
)
timeout = time.time() + 30

while not solution_loaded:
Expand All @@ -90,12 +100,20 @@ def clear_console_button(self):
return self

def assert_level_number(self, level_number):
path = reverse("play_default_level", kwargs={"levelName": str(level_number)})
assert_that(self.browser.current_url.replace("#myModal", ""), ends_with(path))
path = reverse(
"play_default_level", kwargs={"levelName": str(level_number)}
)
assert_that(
self.browser.current_url.replace("#myModal", ""), ends_with(path)
)

def assert_episode_number(self, episode_number):
path = reverse("start_episode", kwargs={"episodeId": str(episode_number)})
assert_that(self.browser.current_url.replace("#myModal", ""), ends_with(path))
path = reverse(
"start_episode", kwargs={"episodeId": str(episode_number)}
)
assert_that(
self.browser.current_url.replace("#myModal", ""), ends_with(path)
)

def assert_is_green_light(self, traffic_light_index):
self._assert_light_is_on(traffic_light_index, "green")
Expand All @@ -104,8 +122,8 @@ def assert_is_red_light(self, traffic_light_index):
self._assert_light_is_on(traffic_light_index, "red")

def _assert_light_is_on(self, traffic_light_index, colour):
image = self.browser.find_element(By.ID,
"trafficLight_%s_%s" % (traffic_light_index, colour)
image = self.browser.find_element(
By.ID, "trafficLight_%s_%s" % (traffic_light_index, colour)
)

assert_that(image.get_attribute("opacity"), equal_to("1"))
Expand All @@ -114,7 +132,9 @@ def run_program(self, wait_for_element_id="modal-content"):
self.browser.find_element(By.ID, "fast_tab").click()

try:
self.wait_for_element_to_be_clickable((By.ID, wait_for_element_id), 45)
self.wait_for_element_to_be_clickable(
(By.ID, wait_for_element_id), 45
)
except TimeoutException as e:
millis = int(round(time.time() * 1000))
screenshot_filename = "/tmp/game_tests_%s-%s.png" % (
Expand All @@ -130,7 +150,9 @@ def run_program(self, wait_for_element_id="modal-content"):
def run_retry_program(self):
self.run_program("try_again_button")
modal_content = self.browser.find_element(By.ID, "modal-content").text
assert_that(modal_content, contains_string("Try creating a simpler program."))
assert_that(
modal_content, contains_string("Try creating a simpler program.")
)
self.browser.find_element(By.ID, "try_again_button").click()
time.sleep(1)
return self
Expand Down Expand Up @@ -184,6 +206,20 @@ def run_invalid_import_program(self):
"from van import Va", "You can only import 'Van' from 'van'"
)

def run_animal_sound_horn_program(self):
return self._run_working_program(
"""
while not my_van.at_destination():
if my_van.is_animal_crossing():
my_van.sound_horn()
if my_van.is_road_forward():
my_van.move_forwards()
elif my_van.is_road_left():
my_van.turn_left()
else:
my_van.turn_right()""",
)

def check_python_commands(self):
self.python_commands_button()
time.sleep(1)
Expand Down Expand Up @@ -241,6 +277,12 @@ def _run_failing_python_program_popup(self, code, text):
assert_that(error_message, contains_string(text))
return self

def _run_working_program(self, code):
self._write_code(code)
self.browser.find_element(By.ID, "fast_tab").click()
time.sleep(1)
return self

def _write_code(self, code):
self.browser.execute_script(
"ocargo.pythonControl.appendCode(arguments[0])", code
Expand All @@ -249,7 +291,9 @@ def _write_code(self, code):

def _run_procedure_error_program(self, text):
self.run_program("close_button")
error_message = self.browser.find_element(By.ID, "myModal-mainText").text
error_message = self.browser.find_element(
By.ID, "myModal-mainText"
).text
assert_that(error_message, contains_string(text))

def _assert_score(self, element_id, score):
Expand Down
3 changes: 1 addition & 2 deletions game/end_to_end_tests/test_cow_crashes.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from game.character import get_character
from game.end_to_end_tests.base_game_test import BaseGameTest
from game.models import Level, Block, LevelBlock

from game.theme import get_theme
from game.character import get_character


class TestCowCrashes(BaseGameTest):
Expand Down
35 changes: 35 additions & 0 deletions game/end_to_end_tests/test_python_levels.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

from game.character import get_character
from game.end_to_end_tests.base_game_test import BaseGameTest
from game.models import Level
from game.theme import get_theme

DELAY_TIME = 10

Expand Down Expand Up @@ -33,3 +36,35 @@ def test_run_code(self):
assert WebDriverWait(self.selenium, DELAY_TIME).until(
EC.presence_of_all_elements_located((By.ID, "myModal-lead"))
)

def test_animal_sound_horn(self):
grass = get_theme(name="grass")

van = get_character("Van")

animal_level = Level(
name="Animal commands",
anonymous=False,
blocklyEnabled=False,
character=van,
cows='[{"minCows":1,"maxCows":1,"potentialCoordinates":[{"x":3,"y":4}],"type":"WHITE"}]',
default=False,
destinations="[[4,4]]",
direct_drive=False,
fuel_gauge=False,
max_fuel=50,
model_solution="",
origin='{"coordinate":[2,4],"direction":"E"}',
path='[{"coordinate":[2,4],"connectedNodes":[1]},{"coordinate":[3,4],"connectedNodes":[0,2]},{"coordinate":[4,4],"connectedNodes":[1]}]',
pythonEnabled=True,
theme=grass,
threads=1,
traffic_lights="[]",
disable_algorithm_score=True,
)

user_profile = self.login_once()
animal_level.owner = user_profile
animal_level.save()

self.run_animal_sound_horn_test(animal_level).assert_success()
Loading

0 comments on commit de431c6

Please sign in to comment.