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

Commit 27da590

Browse files
authored
Merge branch 'master' into docs
2 parents f5087af + 81b8a9a commit 27da590

3 files changed

Lines changed: 65 additions & 74 deletions

File tree

runestone/activecode/js/activecode.js

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
*
33
* Created by bmiller on 3/19/15.
44
*/
5+
/* Define global variables for ESLint */
6+
/* global Sk */
7+
58
"use strict";
69

710
import RunestoneBase from "../../common/js/runestonebase.js";
@@ -1132,40 +1135,39 @@ Yet another is that there is an internal error. The internal error message is:
11321135
return Promise.resolve(prog);
11331136
}
11341137

1135-
async manage_scrubber(scrubber_dfd, history_dfd, saveCode) {
1138+
async manage_scrubber(saveCode) {
1139+
let scrubber_dfd = false;
11361140
if (this.historyScrubber === null && !this.autorun) {
11371141
scrubber_dfd = await this.addHistoryScrubber();
11381142
}
1139-
if (
1140-
this.historyScrubber &&
1141-
this.history[$(this.historyScrubber).slider("value")] !=
1142-
this.editor.getValue()
1143-
) {
1144-
saveCode = "True";
1145-
this.history.push(this.editor.getValue());
1146-
this.timestamps.push(new Date().toLocaleString());
1147-
$(this.historyScrubber).slider(
1148-
"option",
1149-
"max",
1150-
this.history.length - 1
1151-
);
1152-
$(this.historyScrubber).slider(
1153-
"option",
1154-
"value",
1155-
this.history.length - 1
1156-
);
1157-
this.slideit();
1158-
} else {
1159-
saveCode = "False";
1160-
}
1161-
if (this.historyScrubber == null) {
1162-
saveCode = "False";
1143+
if (scrubber_dfd && scrubber_dfd.ok) {
1144+
if (
1145+
this.historyScrubber &&
1146+
this.history[$(this.historyScrubber).slider("value")] !=
1147+
this.editor.getValue()
1148+
) {
1149+
saveCode = "True";
1150+
this.history.push(this.editor.getValue());
1151+
this.timestamps.push(new Date().toLocaleString());
1152+
$(this.historyScrubber).slider(
1153+
"option",
1154+
"max",
1155+
this.history.length - 1
1156+
);
1157+
$(this.historyScrubber).slider(
1158+
"option",
1159+
"value",
1160+
this.history.length - 1
1161+
);
1162+
this.slideit();
1163+
} else {
1164+
saveCode = "False";
1165+
}
1166+
if (this.historyScrubber == null) {
1167+
saveCode = "False";
1168+
}
11631169
}
1164-
history_dfd = Promise.resolve({
1165-
history_dfd: scrubber_dfd,
1166-
saveCode: saveCode,
1167-
});
1168-
return history_dfd;
1170+
return Promise.resolve(saveCode);
11691171
}
11701172

11711173
async checkCurrentAnswer() {
@@ -1238,7 +1240,6 @@ Yet another is that there is an internal error. The internal error message is:
12381240
this.isAnswered = true;
12391241
var prog = await this.buildProg(true);
12401242
this.saveCode = "True";
1241-
var scrubber_dfd, history_dfd;
12421243
$(this.output).text("");
12431244
$(this.eContainer).remove();
12441245
if (this.codelens) {
@@ -1277,14 +1278,7 @@ Yet another is that there is an internal error. The internal error message is:
12771278
duration: 700,
12781279
queue: false,
12791280
});
1280-
var __ret = await this.manage_scrubber(
1281-
scrubber_dfd,
1282-
history_dfd,
1283-
this.saveCode
1284-
);
1285-
history_dfd = __ret.history_dfd;
1286-
this.saveCode = __ret.saveCode;
1287-
promise_list.push(__ret);
1281+
this.saveCode = await this.manage_scrubber(this.saveCode);
12881282
}
12891283
this.run_promise = Sk.misceval.asyncToPromise(function () {
12901284
return Sk.importMainWithBody("<stdin>", false, prog, true);
@@ -1295,7 +1289,7 @@ Yet another is that there is an internal error. The internal error message is:
12951289
var self = this;
12961290
Promise.all(promise_list)
12971291
.then(
1298-
function (mod) {
1292+
function () {
12991293
$(this.runButton).removeAttr("disabled");
13001294
if (!noUI) {
13011295
if (this.slideit) {

runestone/activecode/test/test_activecode.py

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
from selenium.webdriver import ActionChains
22
from selenium.webdriver.support import expected_conditions as EC
3-
from selenium.webdriver.support.ui import WebDriverWait
43
from selenium.webdriver.common.by import By
5-
from selenium.common.exceptions import ElementClickInterceptedException
4+
from selenium.common.exceptions import (
5+
ElementClickInterceptedException,
6+
TimeoutException,
7+
)
68
import time
79
from runestone.unittest_base import module_fixture_maker, RunestoneTestCase
810

@@ -19,21 +21,19 @@ def test_hello(self):
1921
:return:
2022
"""
2123
self.driver.get(self.host + "/index.html")
22-
wait = WebDriverWait(self.driver, 10)
2324
try:
24-
wait.until(EC.presence_of_element_located((By.ID, "test1")))
25-
except:
25+
self.wait.until(EC.presence_of_element_located((By.ID, "test1")))
26+
except TimeoutException:
2627
text = self.driver.page_source
2728
print(text[:300])
2829
t1 = self.driver.find_element_by_id("test1")
2930
self.assertIsNotNone(t1)
3031
rb = t1.find_element_by_class_name("run-button")
3132
self.assertIsNotNone(rb)
3233
rb.click()
33-
time.sleep(0.5)
34-
wait = WebDriverWait(self.driver, 10)
35-
wait.until(
36-
EC.text_to_be_present_in_element((By.ID, "test1_stdout"), "Hello")
34+
self.wait.until(
35+
EC.text_to_be_present_in_element((By.ID, "test1_stdout"), "Hello World"),
36+
message="Did not find expected text",
3737
)
3838
output = t1.find_element_by_class_name("ac_output")
3939
self.assertEqual(output.text.strip(), "Hello World")
@@ -47,22 +47,22 @@ def test_hidden(self):
4747
:return:
4848
"""
4949
self.driver.get(self.host + "/index.html")
50-
wait = WebDriverWait(self.driver, 10)
5150
try:
52-
wait.until(EC.presence_of_element_located((By.ID, "testprefixcode")))
53-
except:
51+
self.wait.until(EC.presence_of_element_located((By.ID, "testprefixcode")))
52+
except TimeoutException:
5453
text = self.driver.page_source
5554
print(text[:300])
5655
t1 = self.driver.find_element_by_id("testprefixcode")
5756
self.assertIsNotNone(t1)
5857
rb = t1.find_element_by_class_name("run-button")
5958
self.assertIsNotNone(rb)
6059
rb.click()
61-
wait.until(
62-
EC.text_to_be_present_in_element((By.ID, "testprefixcode_stdout"), "My")
60+
self.wait.until(
61+
EC.text_to_be_present_in_element(
62+
(By.ID, "testprefixcode_stdout"), "My Code"
63+
)
6364
)
6465
output = t1.find_element_by_class_name("ac_output")
65-
self.assertIn("My Code", output.text.strip())
6666
self.assertIn("hidden code", output.text.strip())
6767
self.assertIn("i\nx", output.text.strip())
6868

@@ -98,9 +98,7 @@ def test_history(self):
9898
self.driver.execute_script(
9999
"""window.edList['test1'].editor.setValue("print('GoodBye')")"""
100100
)
101-
WebDriverWait(self.driver, 10).until(
102-
EC.element_to_be_clickable((By.CLASS_NAME, "run-button"))
103-
)
101+
self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, "run-button")))
104102
try:
105103
rb.click()
106104
except ElementClickInterceptedException:
@@ -147,7 +145,7 @@ def test_livecode_datafile(self):
147145
print("Ouput so far:", output.text)
148146
try:
149147
self.assertLess(count, 20)
150-
except:
148+
except Exception:
151149
print("WARNING - No response from JOBE server")
152150

153151
def test_activity_count(self):
@@ -179,10 +177,7 @@ def test_sql_activecode(self):
179177
rb = t2.find_element_by_class_name("run-button")
180178
self.assertIsNotNone(rb)
181179
rb.click()
182-
wait = WebDriverWait(self.driver, 10)
183-
wait.until(
184-
EC.text_to_be_present_in_element((By.ID, "sql1_stdout"), "You")
185-
)
180+
self.wait.until(EC.text_to_be_present_in_element((By.ID, "sql1_stdout"), "You"))
186181
res = self.driver.find_element_by_id("sql1_sql_out")
187182
self.assertIsNotNone(res)
188183
out = self.driver.find_element_by_id("sql1_stdout")
@@ -204,8 +199,7 @@ def test_readfiles(self):
204199
rb = t2.find_element_by_class_name("run-button")
205200
self.assertIsNotNone(rb)
206201
rb.click()
207-
wait = WebDriverWait(self.driver, 10)
208-
wait.until(
202+
self.wait.until(
209203
EC.text_to_be_present_in_element((By.ID, "ac9_13_1_stdout"), "Lind")
210204
)
211205
out = t2.find_element_by_id("ac9_13_1_stdout")
@@ -221,11 +215,11 @@ def test_altair(self):
221215
rb.click()
222216
out = t2.find_element_by_id("alt_kiva_bar1_stdout")
223217
self.assertIsNotNone(out)
224-
wait = WebDriverWait(self.driver, 10)
225-
wait.until(
226-
EC.text_to_be_present_in_element((By.ID, "alt_kiva_bar1_stdout"), "mark")
218+
self.wait.until(
219+
EC.text_to_be_present_in_element(
220+
(By.ID, "alt_kiva_bar1_stdout"), "mark = bar"
221+
)
227222
)
228-
self.assertIn("mark = bar", out.text)
229223
self.assertIn("{'field': 'customer', 'type': 'nominal'}", out.text)
230224
can = t2.find_element_by_tag_name("canvas")
231225
self.assertIsNotNone(can)
@@ -237,13 +231,11 @@ def test_image(self):
237231
rb = t2.find_element_by_class_name("run-button")
238232
self.assertIsNotNone(rb)
239233
rb.click()
240-
wait = WebDriverWait(self.driver, 10)
241-
wait.until(
234+
self.wait.until(
242235
EC.text_to_be_present_in_element((By.ID, "ac14_7_2_stdout"), "400")
243236
)
244237
out = t2.find_element_by_id("ac14_7_2_stdout")
245238
self.assertIsNotNone(out)
246-
self.assertTrue("400" in out.text)
247239
self.assertTrue("244" in out.text)
248240
self.assertTrue(("165 161 158" in out.text) or ("165 162 157" in out.text))
249241
can = t2.find_element_by_tag_name("canvas")

runestone/unittest_base.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
# -------------------
2525
from selenium import webdriver
2626
from selenium.webdriver.chrome.options import Options
27+
from selenium.webdriver.support.ui import WebDriverWait
2728
import pytest
2829
from pyvirtualdisplay import Display
2930

@@ -70,14 +71,15 @@ def setUpModule(self):
7071
# Change to this directory for running Runestone.
7172
self.old_cwd = os.getcwd()
7273
os.chdir(self.base_path)
73-
# use call so that npm run build completes before we move on to runestone build
74+
# use `run` so that `npm run build` completes before we move on to `runestone build`
7475
# otherwise the runestone build may fail due to lack of a runestone.js file!
75-
p = subprocess.call(
76+
p = subprocess.run(
7677
["npm.cmd" if IS_WINDOWS else "npm", "run", "build"],
7778
stdout=subprocess.PIPE,
7879
stderr=subprocess.PIPE,
7980
universal_newlines=True,
8081
)
82+
self.assertFalse(p.returncode)
8183
# Compile the docs. Save the stdout and stderr for examination.
8284
p = subprocess.Popen(
8385
["runestone", "build", "--all"],
@@ -230,6 +232,9 @@ def setUp(self):
230232
self.host = HOST_URL
231233
# Add an `implicit wait <https://selenium-python.readthedocs.io/waits.html#implicit-waits>`_.
232234
self.driver.implicitly_wait(5)
235+
# For cases where an implicit wait does not help. For example waiting for text to appear
236+
# after running an activecode. We create an explicit wait object.
237+
self.wait = WebDriverWait(self.driver, 5)
233238

234239
def tearDown(self):
235240
# Clear as much as possible, to present an almost-fresh instance of a browser for the next test. (Shutting down then starting up a browswer is very slow.)

0 commit comments

Comments
 (0)