fix: allow log in testString, restrict test errors

Console logs from testString get reported and test errors are sent to
the dev console (JS).

challenge building is only attempted if there is a build function to do
so.

Various functions have been renamed to better reflect what they do.
This commit is contained in:
Oliver Eyton-Williams
2019-11-19 12:46:48 +01:00
committed by mrugesh
parent 9194b7731b
commit febba792e7
4 changed files with 32 additions and 22 deletions

View File

@ -38,7 +38,7 @@ const __utils = (() => {
self.postMessage(data);
}
function logToBoth(err) {
function log(err) {
if (!(err instanceof chai.AssertionError)) {
// report to both the browser and the fcc consoles, discarding the
// stack trace via toString as it only useful to debug the site, not a
@ -47,14 +47,14 @@ const __utils = (() => {
}
}
const toggleLogging = on => {
self.console.log = on ? proxyLog : () => {};
const toggleProxyLogger = on => {
self.console.log = on ? proxyLog : oldLog;
};
return {
postResult,
logToBoth,
toggleLogging
log,
toggleProxyLogger
};
})();
@ -66,7 +66,8 @@ self.onmessage = async e => {
// Fake Deep Equal dependency
const DeepEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
__utils.toggleLogging(e.data.firstTest);
// User code errors should be reported, but only once:
__utils.toggleProxyLogger(e.data.firstTest);
/* eslint-enable no-unused-vars */
try {
let testResult;
@ -84,7 +85,7 @@ self.onmessage = async e => {
throw err;
}
// log build errors
__utils.logToBoth(err);
__utils.log(err);
// the tests may not require working code, so they are evaluated even if
// the user code does not get executed.
testResult = eval(e.data.testString);
@ -97,10 +98,11 @@ self.onmessage = async e => {
pass: true
});
} catch (err) {
// report errors that happened during testing, so the user learns of
// execution errors and not just build errors.
__utils.toggleLogging(true);
__utils.logToBoth(err);
// Errors from testing go to the browser console only.
__utils.toggleProxyLogger(false);
// Report execution errors in case user code has errors that are only
// uncovered during testing.
__utils.log(err);
// postResult flushes the logs and must be called after logging is finished.
__utils.postResult({
err: {

View File

@ -26,6 +26,7 @@ import {
import {
buildChallenge,
canBuildChallenge,
getTestRunner,
challengeHasPreview,
updatePreview,
@ -153,15 +154,17 @@ function* previewChallengeSaga() {
yield fork(takeEveryConsole, logProxy);
const challengeData = yield select(challengeDataSelector);
const buildData = yield buildChallengeData(challengeData);
// evaluate the user code in the preview frame or in the worker
if (challengeHasPreview(challengeData)) {
const document = yield getContext('document');
yield call(updatePreview, buildData, document, proxyLogger);
} else if (isJavaScriptChallenge(challengeData)) {
const runUserCode = getTestRunner(buildData, { proxyLogger });
// without a testString the testRunner just evaluates the user's code
yield call(runUserCode, null, 5000);
if (canBuildChallenge(challengeData)) {
const buildData = yield buildChallengeData(challengeData);
// evaluate the user code in the preview frame or in the worker
if (challengeHasPreview(challengeData)) {
const document = yield getContext('document');
yield call(updatePreview, buildData, document, proxyLogger);
} else if (isJavaScriptChallenge(challengeData)) {
const runUserCode = getTestRunner(buildData, { proxyLogger });
// without a testString the testRunner just evaluates the user's code
yield call(runUserCode, null, 5000);
}
}
} catch (err) {
console.log(err);

View File

@ -71,6 +71,11 @@ const buildFunctions = {
[challengeTypes.backEndProject]: buildBackendChallenge
};
export function canBuildChallenge(challengeData) {
const { challengeType } = challengeData;
return buildFunctions.hasOwnProperty(challengeType);
}
export async function buildChallenge(challengeData) {
const { challengeType } = challengeData;
let build = buildFunctions[challengeType];

View File

@ -104,8 +104,8 @@ const initTestFrame = frameReady => ctx => {
const initMainFrame = (frameReady, proxyLogger) => ctx => {
waitForFrame(ctx).then(() => {
// Overwriting the onerror added by createHeader to catch any errors thrown
// after the frame is ready. It has to be overwritten, as proxyUpdateConsole
// cannot be added as part of createHeader.
// after the frame is ready. It has to be overwritten, as proxyLogger cannot
// be added as part of createHeader.
ctx.window.onerror = function(msg) {
console.log(msg);
if (proxyLogger) {