fix(client): use proxy logger in test worker
This commit is contained in:
@ -3,12 +3,11 @@ import '@babel/polyfill';
|
|||||||
|
|
||||||
const oldLog = self.console.log.bind(self.console);
|
const oldLog = self.console.log.bind(self.console);
|
||||||
self.console.log = function proxyConsole(...args) {
|
self.console.log = function proxyConsole(...args) {
|
||||||
self.__logs = [...self.__logs, ...args];
|
self.postMessage({ type: 'LOG', data: String(args) });
|
||||||
return oldLog(...args);
|
return oldLog(...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
onmessage = async e => {
|
onmessage = async e => {
|
||||||
self.__logs = [];
|
|
||||||
const { script: __test, code } = e.data;
|
const { script: __test, code } = e.data;
|
||||||
/* eslint-disable no-unused-vars */
|
/* eslint-disable no-unused-vars */
|
||||||
const assert = chai.assert;
|
const assert = chai.assert;
|
||||||
@ -21,14 +20,13 @@ onmessage = async e => {
|
|||||||
if (typeof testResult === 'function') {
|
if (typeof testResult === 'function') {
|
||||||
await testResult(() => code);
|
await testResult(() => code);
|
||||||
}
|
}
|
||||||
self.postMessage({ pass: true, logs: self.__logs.map(String) });
|
self.postMessage({ pass: true });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
err: {
|
err: {
|
||||||
message: err.message,
|
message: err.message,
|
||||||
stack: err.stack
|
stack: err.stack
|
||||||
},
|
}
|
||||||
logs: self.__logs.map(String)
|
|
||||||
});
|
});
|
||||||
if (!(err instanceof chai.AssertionError)) {
|
if (!(err instanceof chai.AssertionError)) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
@ -67,15 +67,29 @@ function* ExecuteChallengeSaga() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function* logToConsole(channel) {
|
||||||
|
yield takeEvery(channel, function*(args) {
|
||||||
|
yield put(updateLogs(args));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function* ExecuteJSChallengeSaga() {
|
function* ExecuteJSChallengeSaga() {
|
||||||
const files = yield select(challengeFilesSelector);
|
const files = yield select(challengeFilesSelector);
|
||||||
const { code, solution } = yield call(buildJSFromFiles, files);
|
const { code, solution } = yield call(buildJSFromFiles, files);
|
||||||
|
|
||||||
|
const consoleProxy = yield channel();
|
||||||
|
yield fork(logToConsole, consoleProxy);
|
||||||
|
const log = args => consoleProxy.put(args);
|
||||||
|
testWorker.on('LOG', log);
|
||||||
|
|
||||||
const testResults = yield call(executeTests, {
|
const testResults = yield call(executeTests, {
|
||||||
testRunner: testWorker,
|
testRunner: testWorker,
|
||||||
code,
|
code,
|
||||||
solution
|
solution
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWorker.remove('LOG', log);
|
||||||
|
consoleProxy.close();
|
||||||
return testResults;
|
return testResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,12 +100,6 @@ function createTestFrame(state, ctx, proxyLogger) {
|
|||||||
}).then(() => console.log('Frame ready'));
|
}).then(() => console.log('Frame ready'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function* logToConsole(channel) {
|
|
||||||
yield takeEvery(channel, function*(args) {
|
|
||||||
yield put(updateLogs(args));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function* ExecuteDOMChallengeSaga() {
|
function* ExecuteDOMChallengeSaga() {
|
||||||
const state = yield select();
|
const state = yield select();
|
||||||
const ctx = yield call(buildFromFiles, state);
|
const ctx = yield call(buildFromFiles, state);
|
||||||
@ -166,14 +174,11 @@ function* executeTests({ testRunner, code = '', solution = '' }) {
|
|||||||
for (const { text, testString } of tests) {
|
for (const { text, testString } of tests) {
|
||||||
const newTest = { text, testString };
|
const newTest = { text, testString };
|
||||||
try {
|
try {
|
||||||
const { pass, err, logs = [] } = yield call(
|
const { pass, err } = yield call(
|
||||||
testRunner.execute,
|
testRunner.execute,
|
||||||
{ script: solution + '\n' + testString, code },
|
{ script: solution + '\n' + testString, code },
|
||||||
testTimeout
|
testTimeout
|
||||||
);
|
);
|
||||||
for (const log of logs) {
|
|
||||||
yield put(updateLogs(log));
|
|
||||||
}
|
|
||||||
if (pass) {
|
if (pass) {
|
||||||
newTest.pass = true;
|
newTest.pass = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2,6 +2,7 @@ export default class WorkerExecutor {
|
|||||||
constructor(workerName) {
|
constructor(workerName) {
|
||||||
this.workerName = workerName;
|
this.workerName = workerName;
|
||||||
this.worker = null;
|
this.worker = null;
|
||||||
|
this.observers = {};
|
||||||
|
|
||||||
this.execute = this.execute.bind(this);
|
this.execute = this.execute.bind(this);
|
||||||
this.killWorker = this.killWorker.bind(this);
|
this.killWorker = this.killWorker.bind(this);
|
||||||
@ -36,6 +37,13 @@ export default class WorkerExecutor {
|
|||||||
|
|
||||||
// Handle result
|
// Handle result
|
||||||
worker.onmessage = e => {
|
worker.onmessage = e => {
|
||||||
|
if (e.data && e.data.type) {
|
||||||
|
const observers = this.observers[e.data.type] || [];
|
||||||
|
for (const observer of observers) {
|
||||||
|
observer(e.data.data);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
resolve(e.data);
|
resolve(e.data);
|
||||||
};
|
};
|
||||||
@ -46,4 +54,18 @@ export default class WorkerExecutor {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
on(type, callback) {
|
||||||
|
const observers = this.observers[type] || [];
|
||||||
|
observers.push(callback);
|
||||||
|
this.observers[type] = observers;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(type, callback) {
|
||||||
|
const observers = this.observers[type] || [];
|
||||||
|
const index = observers.indexOf(callback);
|
||||||
|
if (index !== -1) {
|
||||||
|
observers.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user