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

Commit 41dc164

Browse files
authored
Merge branch 'master' into docs
2 parents 27da590 + 8094684 commit 41dc164

8 files changed

Lines changed: 130 additions & 98 deletions

File tree

runestone/activecode/js/activecode.js

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,14 @@ export class ActiveCode extends RunestoneBase {
241241
$(butt).addClass("btn btn-success run-button");
242242
ctrlDiv.appendChild(butt);
243243
this.runButton = butt;
244+
console.log("adding click function for run");
244245
$(butt).click(
245246
async function () {
246-
await this.runProg();
247+
try {
248+
await this.runProg();
249+
} catch (e) {
250+
console.log(`there was an error ${e} running the code`);
251+
}
247252
if (this.logResults) {
248253
this.logCurrentAnswer();
249254
}
@@ -1136,42 +1141,46 @@ Yet another is that there is an internal error. The internal error message is:
11361141
}
11371142

11381143
async manage_scrubber(saveCode) {
1139-
let scrubber_dfd = false;
11401144
if (this.historyScrubber === null && !this.autorun) {
1141-
scrubber_dfd = await this.addHistoryScrubber();
1142-
}
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";
1145+
let response = await this.addHistoryScrubber();
1146+
if (!response.ok) {
1147+
console.log("Failed to load history -- this should not fail.");
11681148
}
11691149
}
1150+
if (
1151+
this.historyScrubber &&
1152+
this.history[$(this.historyScrubber).slider("value")] !=
1153+
this.editor.getValue()
1154+
) {
1155+
saveCode = "True";
1156+
this.history.push(this.editor.getValue());
1157+
this.timestamps.push(new Date().toLocaleString());
1158+
$(this.historyScrubber).slider(
1159+
"option",
1160+
"max",
1161+
this.history.length - 1
1162+
);
1163+
$(this.historyScrubber).slider(
1164+
"option",
1165+
"value",
1166+
this.history.length - 1
1167+
);
1168+
this.slideit();
1169+
} else {
1170+
saveCode = "False";
1171+
}
1172+
if (this.historyScrubber == null) {
1173+
saveCode = "False";
1174+
}
11701175
return Promise.resolve(saveCode);
11711176
}
11721177

11731178
async checkCurrentAnswer() {
1174-
this.run_promise = this.runProg();
1179+
try {
1180+
await this.runProg();
1181+
} catch (e) {
1182+
console.log(`error running code ${e}`);
1183+
}
11751184
}
11761185

11771186
logCurrentAnswer() {
@@ -1229,6 +1238,7 @@ Yet another is that there is an internal error. The internal error message is:
12291238
*
12301239
*/
12311240
async runProg(noUI, logResults) {
1241+
console.log("starting runProg");
12321242
if (typeof logResults === "undefined") {
12331243
this.logResults = true;
12341244
} else {
@@ -1241,7 +1251,10 @@ Yet another is that there is an internal error. The internal error message is:
12411251
var prog = await this.buildProg(true);
12421252
this.saveCode = "True";
12431253
$(this.output).text("");
1244-
$(this.eContainer).remove();
1254+
while ($(`#${this.divid}_errinfo`).length > 0) {
1255+
$(`#${this.divid}_errinfo`).remove();
1256+
}
1257+
//$(this.eContainer).remove();
12451258
if (this.codelens) {
12461259
this.codelens.style.display = "none";
12471260
}

runestone/activecode/js/timed_activecode.js

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,21 +71,10 @@ var TimedActiveCodeMixin = {
7171
},
7272

7373
reinitializeListeners: function (taken) {
74-
// re-attach the run button listener
75-
$(this.runButton).click(this.runProg.bind(this));
7674
$(this.codeDiv).show();
7775
this.runButton.disabled = false;
7876
$(this.codeDiv).removeClass("ac-disabled");
7977
this.editor.refresh();
80-
$(this.histButton).click(this.addHistoryScrubber.bind(this));
81-
if (this.historyScrubber !== null) {
82-
$(this.historyScrubber).slider({
83-
max: this.history.length - 1,
84-
value: this.history.length - 1,
85-
slide: this.slideit.bind(this),
86-
change: this.slideit.bind(this),
87-
});
88-
}
8978
if (taken) {
9079
$(`#${this.divid}_unit_results`).show();
9180
}

runestone/common/js/runestonebase.js

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ export default class RunestoneBase {
6060
});
6161
}
6262

63-
// .. _logBookEvent:
64-
//
65-
// logBookEvent
66-
// ------------
63+
// .. _logBookEvent:
64+
//
65+
// logBookEvent
66+
// ------------
6767
// This function sends the provided ``eventInfo`` to the `hsblog endpoint` of the server. Awaiting this function returns either ``undefined`` (if Runestone services are not available) or the data returned by the server as a JavaScript object (already JSON-decoded).
6868
async logBookEvent(eventInfo) {
6969
if (this.graderactive) {
@@ -99,10 +99,10 @@ export default class RunestoneBase {
9999
return post_return;
100100
}
101101

102-
// .. _logRunEvent:
103-
//
104-
// logRunEvent
105-
// -----------
102+
// .. _logRunEvent:
103+
//
104+
// logRunEvent
105+
// -----------
106106
// This function sends the provided ``eventInfo`` to the `runlog endpoint`. When awaited, this function returns the data (decoded from JSON) the server sent back.
107107
async logRunEvent(eventInfo) {
108108
let post_promise = "done";
@@ -121,8 +121,8 @@ export default class RunestoneBase {
121121
headers: this.jsonHeaders,
122122
body: JSON.stringify(eventInfo),
123123
});
124-
post_promise = await fetch(request);
125-
if (!post_promise.ok) {
124+
let response = await fetch(request);
125+
if (!response.ok) {
126126
throw new Error("Failed to log the run");
127127
}
128128
post_promise = await response.json();
@@ -139,6 +139,10 @@ export default class RunestoneBase {
139139
/* Checking/loading from storage */
140140
async checkServer(eventInfo) {
141141
// Check if the server has stored answer
142+
let self = this;
143+
this.checkServerComplete = new Promise(function (resolve, reject) {
144+
self.csresolver = resolve;
145+
});
142146
if (this.useRunestoneServices || this.graderactive) {
143147
let data = {};
144148
data.div_id = this.divid;
@@ -165,6 +169,7 @@ export default class RunestoneBase {
165169
let response = await fetch(request);
166170
data = await response.json();
167171
this.repopulateFromStorage(data);
172+
this.csresolver("server");
168173
} catch (err) {
169174
try {
170175
this.checkLocalStorage();
@@ -177,6 +182,7 @@ export default class RunestoneBase {
177182
}
178183
} else {
179184
this.checkLocalStorage(); // just go right to local storage
185+
this.csresolver("local");
180186
}
181187
}
182188

runestone/mchoice/test/test_assess.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
1-
"""
2-
Test Multiple Choice question directive
3-
"""
1+
# ****************************************************
2+
# |docname| - Test Multiple Choice question directive
3+
# ****************************************************
44

55
__author__ = "yasinovskyy"
66

77
from unittest import TestCase
8-
from selenium.webdriver.support import expected_conditions as EC
98
from selenium.webdriver.common.by import By
10-
from runestone.unittest_base import module_fixture_maker, RunestoneTestCase
9+
from selenium.webdriver.support import expected_conditions as EC
10+
from runestone.unittest_base import (
11+
module_fixture_maker,
12+
RunestoneTestCase,
13+
element_has_css_class,
14+
)
1115

1216
mf, setUpModule, tearDownModule = module_fixture_maker(__file__, True)
1317

18+
1419
# Look for errors producted by invalid questions.
1520
class MultipleChoiceQuestion_Error_Tests(TestCase):
1621
def test_1(self):
@@ -132,10 +137,9 @@ def test_mc1(self):
132137
t1 = self.driver.find_element_by_id("question2")
133138
btn_check = t1.find_element_by_tag_name("button")
134139
btn_check.click()
135-
fb = t1.find_element_by_id("question2_feedback")
136-
self.assertIsNotNone(fb)
137-
cnamestr = fb.get_attribute("class")
138-
self.assertIn("alert-danger", cnamestr)
140+
self.wait.until(
141+
element_has_css_class((By.ID, "question2_feedback"), "alert-danger")
142+
)
139143

140144
def test_mc2(self):
141145
"""Multiple Choice: Correct answer selected"""
@@ -149,6 +153,10 @@ def test_mc2(self):
149153

150154
fb = t1.find_element_by_id("question2_feedback")
151155
self.assertIsNotNone(fb)
156+
self.wait.until(
157+
EC.text_to_be_present_in_element((By.ID, "question2_feedback"), "Red"),
158+
message="Did not find expected text",
159+
)
152160
cnamestr = fb.get_attribute("class")
153161
self.assertIn("alert-info", cnamestr)
154162

runestone/parsons/js/parsons.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ export default class Parsons extends RunestoneBase {
278278
this.parsonsControlDiv.appendChild(this.messageDiv);
279279
$(this.messageDiv).hide();
280280
$(this.origElem).replaceWith(this.containerDiv);
281+
$(this.containerDiv).closest(".sqcontainer").css("max-width", "none");
281282
}
282283
// Initialize lines and solution properties
283284
initializeLines(text) {
@@ -296,13 +297,13 @@ export default class Parsons extends RunestoneBase {
296297
// Remove the options from the code
297298
// only options are #paired or #distractor
298299
var options = {};
299-
textBlock = textBlock.replace(/#(paired|distractor)/, function (
300-
mystring,
301-
arg1
302-
) {
303-
options[arg1] = true;
304-
return "";
305-
});
300+
textBlock = textBlock.replace(
301+
/#(paired|distractor)/,
302+
function (mystring, arg1) {
303+
options[arg1] = true;
304+
return "";
305+
}
306+
);
306307
// Create lines
307308
var lines = [];
308309
var split = textBlock.split("\n");
@@ -2058,8 +2059,9 @@ export default class Parsons extends RunestoneBase {
20582059
$(this.messageDiv).hide();
20592060
}
20602061
// Disable the interface
2061-
disableInteraction() {
2062+
async disableInteraction() {
20622063
// Disable blocks
2064+
await this.checkServerComplete;
20632065
if (this.blocks !== undefined) {
20642066
for (var i = 0; i < this.blocks.length; i++) {
20652067
var block = this.blocks[i];

runestone/selectquestion/selectone.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747

4848

4949
TEMPLATE = """
50-
<div class="runestone alert alert-warning">
50+
<div class="runestone alert alert-warning sqcontainer">
5151
<div data-component="selectquestion" id={component_id} {selector} {points} {proficiency} {min_difficulty} {max_difficulty} {autogradable} {not_seen_ever} {primary} {AB}>
5252
<p>Loading ...</p>
5353
</div>

runestone/timed/js/timed.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,10 @@ export default class Timed extends RunestoneBase {
815815
currentQuestion.checkCurrentAnswer();
816816
currentQuestion.logCurrentAnswer();
817817
currentQuestion.renderFeedback();
818+
currentQuestion.disableInteraction();
818819

819820
for (var i = 0; i < this.renderedQuestionArray.length; i++) {
820-
var currentQuestion = this.renderedQuestionArray[i];
821+
let currentQuestion = this.renderedQuestionArray[i];
821822
// set the state to forreview so we know that feedback may be appropriate
822823
currentQuestion.state = "forreview";
823824
}

0 commit comments

Comments
 (0)