Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit 01a7bb9

Browse files
committed
Fix: Make the run button unclickable until Activecode finishes running the code.
Make the test code wait until the Activecode run is finished before proceeding to check results.
1 parent 7008fd7 commit 01a7bb9

2 files changed

Lines changed: 12 additions & 24 deletions

File tree

runestone/activecode/js/activecode.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ export class ActiveCode extends RunestoneBase {
125125
1000
126126
);
127127
if (this.autorun) {
128-
$(document).ready(this.runProg.bind(this));
128+
// Simulate pressing the run button, since this will also prevent the user from clicking it until the initial run is complete, and also help the user understand why they're waiting.
129+
$(document).ready(this.runButtonHandler.bind(this));
129130
}
130131
this.indicate_component_ready();
131132
}
@@ -233,7 +234,9 @@ export class ActiveCode extends RunestoneBase {
233234
}
234235
}
235236

236-
async runButtonHander() {
237+
async runButtonHandler() {
238+
// Disable the run button until the run is finished.
239+
this.runButton.disabled = true;
237240
try {
238241
await this.runProg();
239242
} catch (e) {
@@ -243,6 +246,8 @@ export class ActiveCode extends RunestoneBase {
243246
this.logCurrentAnswer();
244247
}
245248
this.renderFeedback();
249+
// The run is finished; re-enable the button.
250+
this.runButton.disabled = false;
246251
}
247252

248253
createControls() {
@@ -257,7 +262,7 @@ export class ActiveCode extends RunestoneBase {
257262
ctrlDiv.appendChild(butt);
258263
this.runButton = butt;
259264
console.log("adding click function for run");
260-
this.runButton.onclick = this.runButtonHander.bind(this);
265+
this.runButton.onclick = this.runButtonHandler.bind(this);
261266
$(butt).attr("type", "button");
262267

263268
if (this.enabledownload || eBookConfig.downloadsEnabled) {

runestone/activecode/test/test_activecode.py

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import time
2-
31
import pytest
42
from selenium.webdriver import ActionChains
53
from selenium.webdriver.support import expected_conditions as EC
@@ -16,6 +14,9 @@ def click_run(selenium_utils, ac_selenium_element):
1614
selenium_utils.driver.execute_script("window.scrollTo(0, 0);")
1715
rb = ac_selenium_element.find_element_by_class_name("run-button")
1816
rb.click()
17+
# After clicking run, the browser may need some time to load and execute the code. Wait until the run button becomes clickable, indicating the code has finished running.
18+
div_id = ac_selenium_element.get_attribute("id")
19+
selenium_utils.wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, f"#{div_id} .run-button")))
1920

2021

2122
def test_hello(selenium_utils_get):
@@ -68,15 +69,13 @@ def test_history(selenium_utils_get):
6869
div_id = "test_activecode_2"
6970
t1 = find_ac(selenium_utils_get, div_id)
7071
click_run(selenium_utils_get, t1)
71-
time.sleep(2)
7272

7373
ta = t1.find_element_by_class_name("cm-s-default")
7474
assert ta
7575
selenium_utils_get.driver.execute_script(
7676
f"""window.edList['{div_id}'].editor.setValue("print('Goodbye')")"""
7777
)
7878
click_run(selenium_utils_get, t1)
79-
time.sleep(2)
8079
output = t1.find_element_by_class_name("ac_output")
8180
assert output.text.strip() == "Goodbye"
8281
move = ActionChains(selenium_utils_get.driver)
@@ -85,7 +84,6 @@ def test_history(selenium_utils_get):
8584
slider = t1.find_element_by_class_name("ui-slider-handle")
8685
move.click_and_hold(slider).move_by_offset(-width, 0).release().perform()
8786
click_run(selenium_utils_get, t1)
88-
time.sleep(2)
8987
output = t1.find_element_by_class_name("ac_output")
9088
assert output.text.strip() == "Hello World"
9189

@@ -98,18 +96,7 @@ def test_livecode_datafile(selenium_utils_get):
9896
t2 = find_ac(selenium_utils_get, "test_activecode_3")
9997
click_run(selenium_utils_get, t2)
10098
output = t2.find_element_by_class_name("ac_output")
101-
102-
count = 0
103-
# Give it some time run
104-
print(output.text)
105-
while output.text.strip() != "Width: 25.0" and count < 20:
106-
count += 1
107-
time.sleep(0.5)
108-
print("Ouput so far:", output.text)
109-
try:
110-
assert count < 20
111-
except Exception:
112-
print("WARNING - No response from JOBE server")
99+
assert output.text.strip() == "Width: 25.0"
113100

114101

115102
@pytest.fixture
@@ -123,8 +110,6 @@ def test_activity_count(selenium_utils_progress):
123110
click_run(selenium_utils_progress, t2)
124111
pb = selenium_utils_progress.driver.find_element_by_id("subchapterprogress")
125112
assert pb
126-
# Wait for the JS to run. Increase this delay if the next assertion fails.
127-
time.sleep(3)
128113
total = selenium_utils_progress.driver.find_element_by_id("scprogresstotal").text.strip()
129114
assert 2 == int(total)
130115
possible = selenium_utils_progress.driver.find_element_by_id("scprogressposs").text.strip()
@@ -140,7 +125,6 @@ def test_sql_activecode(selenium_utils_get):
140125
div_id = "test_activecode_6"
141126
t2 = find_ac(selenium_utils_get, div_id)
142127
click_run(selenium_utils_get, t2)
143-
time.sleep(2)
144128
selenium_utils_get.wait.until(EC.text_to_be_present_in_element((By.ID, f"{div_id}_stdout"), "You"))
145129
res = selenium_utils_get.driver.find_element_by_id(f"{div_id}_sql_out")
146130
assert res
@@ -150,7 +134,6 @@ def test_sql_activecode(selenium_utils_get):
150134
div_id = "test_activecode_7"
151135
t2 = find_ac(selenium_utils_get, div_id)
152136
click_run(selenium_utils_get, t2)
153-
time.sleep(2)
154137
out = selenium_utils_get.driver.find_element_by_id(f"{div_id}_stdout")
155138
assert "" == out.text.strip()
156139

0 commit comments

Comments
 (0)