diff --git a/packages/learn/src/templates/Challenges/rechallenge/transformers.js b/packages/learn/src/templates/Challenges/rechallenge/transformers.js index 6aad460cf0..76ae12c429 100644 --- a/packages/learn/src/templates/Challenges/rechallenge/transformers.js +++ b/packages/learn/src/templates/Challenges/rechallenge/transformers.js @@ -82,10 +82,12 @@ function tryTransform(wrap = identity) { return function transformWrappedPoly(source) { const result = attempt(wrap, source); if (isError(result)) { - const friendlyError = `${result}` - .match(/[\w\W]+?\n/)[0] - .replace(' unknown:', ''); - throw new Error(friendlyError); + console.error(result); + // note(Bouncey): Error thrown here to collapse the build pipeline + // At the minute, it will not bubble up + // We collapse the pipeline so the app doesn't fall over trying + // parse bad code (syntax/type errors etc...) + throw new Error(); } return result; }; @@ -110,12 +112,7 @@ export const sassTransformer = cond([ [stubTrue, identity] ]); -export const _transformers = [ - // addLoopProtectHtmlJsJsx, - replaceNBSP, - babelTransformer, - sassTransformer -]; +export const _transformers = [replaceNBSP, babelTransformer, sassTransformer]; export function applyTransformers(file, transformers = _transformers) { return transformers.reduce((obs, transformer) => { diff --git a/packages/learn/src/templates/Challenges/redux/completion-epic.js b/packages/learn/src/templates/Challenges/redux/completion-epic.js index c25c80c9f1..9f1992caf4 100644 --- a/packages/learn/src/templates/Challenges/redux/completion-epic.js +++ b/packages/learn/src/templates/Challenges/redux/completion-epic.js @@ -126,7 +126,7 @@ export default function completionEpic(action$, { getState }) { const { nextChallengePath, introPath, challengeType } = meta; const next = of(push(introPath ? introPath : nextChallengePath)); const closeChallengeModal = of(closeModal('completion')); - let submitter = () => of({type: 'no-user-signed-in'}); + let submitter = () => of({ type: 'no-user-signed-in' }); if ( !(challengeType in submitTypes) || !(submitTypes[challengeType] in submitters) @@ -140,7 +140,6 @@ export default function completionEpic(action$, { getState }) { submitter = submitters[submitTypes[challengeType]]; } - return submitter(type, state).pipe( concat(next), concat(closeChallengeModal), diff --git a/packages/learn/src/templates/Challenges/redux/execute-challenge-epic.js b/packages/learn/src/templates/Challenges/redux/execute-challenge-epic.js index f705613fa6..d85640e904 100644 --- a/packages/learn/src/templates/Challenges/redux/execute-challenge-epic.js +++ b/packages/learn/src/templates/Challenges/redux/execute-challenge-epic.js @@ -9,7 +9,12 @@ import { map, filter, pluck, - concat + concat, + tap, + catchError, + ignoreElements, + startWith, + delay } from 'rxjs/operators'; import { ofType, combineEpics } from 'redux-observable'; import { overEvery, isString } from 'lodash'; @@ -22,7 +27,8 @@ import { updateConsole, checkChallenge, updateTests, - disableJSOnError + disableJSOnError, + isJSEnabledSelector } from './'; import { buildFromFiles, buildBackendChallenge } from '../utils/build'; import { @@ -49,10 +55,11 @@ function updateMainEpic(actions, { getState }, { document }) { ), debounceTime(executeDebounceTimeout), switchMap(() => - buildFromFiles(getState(), true) - .map(frameMain) - .ignoreElements() - .catch(() => of({ type: 'NULL' })) + buildFromFiles(getState(), true).pipe( + map(frameMain), + ignoreElements(), + catchError(err => of(disableJSOnError(err))) + ) ) ); return merge(buildAndFrameMain, proxyLogger.map(updateConsole)); @@ -76,40 +83,41 @@ function executeChallengeEpic(action$, { getState }, { document }) { const postTests = of( updateConsole('// tests completed'), checkChallenge(checkChallengePayload) - ).delay(250); - // run the tests within the test iframe - return runTestsInTestFrame(document, tests) - .flatMap(tests => { + ).pipe(delay(250)); + return runTestsInTestFrame(document, tests).pipe( + switchMap(tests => { return from(tests).pipe( map(({ message }) => message), filter(overEvery(isString, Boolean)), map(updateConsole), concat(of(updateTests(tests))) ); - }) - .concat(postTests); + }), + concat(postTests) + ); }) ); const buildAndFrameChallenge = action$.pipe( ofType(types.executeChallenge), debounceTime(executeDebounceTimeout), - // if isCodeLocked do not run challenges - // .filter(() => !codeLockedSelector(getState())) + filter(() => isJSEnabledSelector(getState())), switchMap(() => { const state = getState(); const { challengeType } = challengeMetaSelector(state); if (challengeType === backend) { - return buildBackendChallenge(state) - .do(frameTests) - .ignoreElements() - .startWith(initConsole('// running test')) - .catch(err => disableJSOnError(err)); + return buildBackendChallenge(state).pipe( + tap(frameTests), + ignoreElements(), + startWith(initConsole('// running test')), + catchError(err => of(disableJSOnError(err))) + ); } - return buildFromFiles(state, false) - .do(frameTests) - .ignoreElements() - .startWith(initConsole('// running test')) - .catch(err => disableJSOnError(err)); + return buildFromFiles(state, false).pipe( + tap(frameTests), + ignoreElements(), + startWith(initConsole('// running test')), + catchError(err => of(disableJSOnError(err))) + ); }) ); return merge(buildAndFrameChallenge, challengeResults); diff --git a/packages/learn/src/templates/Challenges/redux/index.js b/packages/learn/src/templates/Challenges/redux/index.js index cb82dfb231..1de7ba068e 100644 --- a/packages/learn/src/templates/Challenges/redux/index.js +++ b/packages/learn/src/templates/Challenges/redux/index.js @@ -104,10 +104,13 @@ export const updateSuccessMessage = createAction(types.updateSuccessMessage); export const lockCode = createAction(types.lockCode); export const unlockCode = createAction(types.unlockCode); -export const disableJSOnError = createAction(types.disableJSOnError, err => { - console.error(err); - return {}; -}); +export const disableJSOnError = createAction( + types.disableJSOnError, + ({ payload }) => { + console.error(JSON.stringify(payload)); + return null; + } +); export const storedCodeFound = createAction(types.storedCodeFound); export const noStoredCodeFound = createAction(types.noStoredCodeFound); diff --git a/packages/learn/src/templates/Challenges/utils/build.js b/packages/learn/src/templates/Challenges/utils/build.js index 5184eb1bb6..87c4b5f903 100644 --- a/packages/learn/src/templates/Challenges/utils/build.js +++ b/packages/learn/src/templates/Challenges/utils/build.js @@ -8,7 +8,6 @@ import { challengeFilesSelector, isJSEnabledSelector, challengeMetaSelector, - disableJSOnError, backendFormValuesSelector } from '../redux'; import { @@ -55,8 +54,7 @@ export function buildFromFiles(state, shouldProxyConsole) { ::pipe(shouldProxyConsole ? proxyLoggerTransformer : identity) ::pipe(jsToHtml) ::pipe(cssToHtml) - ::concatHtml(finalRequires, template) - .catch(err => disableJSOnError(err)); + ::concatHtml(finalRequires, template); } export function buildBackendChallenge(state) {