From 5a3e7a5d44ddd3d9fbbe080cc7a3c82abeb811b1 Mon Sep 17 00:00:00 2001 From: Stuart Taylor Date: Wed, 11 Apr 2018 15:10:48 +0100 Subject: [PATCH] Make babel transformed challenges more robust --- .../Challenges/redux/code-lock-epic.js | 9 ++++++++ .../redux/execute-challenge-epic.js | 22 +++++++++++-------- .../src/templates/Challenges/redux/index.js | 15 ++++++++++++- 3 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 packages/learn/src/templates/Challenges/redux/code-lock-epic.js diff --git a/packages/learn/src/templates/Challenges/redux/code-lock-epic.js b/packages/learn/src/templates/Challenges/redux/code-lock-epic.js new file mode 100644 index 0000000000..e47a70ac84 --- /dev/null +++ b/packages/learn/src/templates/Challenges/redux/code-lock-epic.js @@ -0,0 +1,9 @@ +import { map } from 'rxjs/operators/map'; +import { ofType } from 'redux-observable'; +import { types, unlockCode } from './'; + +function codeLockEpic(action$) { + return action$.pipe(ofType(types.executeChallenge), map(unlockCode)); +} + +export default codeLockEpic; 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 6b07fe288e..3e7ab24c53 100644 --- a/packages/learn/src/templates/Challenges/redux/execute-challenge-epic.js +++ b/packages/learn/src/templates/Challenges/redux/execute-challenge-epic.js @@ -1,4 +1,8 @@ -import { Observable, Subject } from 'rxjs'; +import { Subject } from 'rxjs'; +import { merge } from 'rxjs/observable/merge'; +import { of } from 'rxjs/observable/of'; +import { from } from 'rxjs/observable/from'; + import { debounceTime, switchMap, @@ -28,7 +32,7 @@ import { const executeDebounceTimeout = 750; function updateMainEpic(actions, { getState }, { document }) { - return Observable.of(document).pipe( + return of(document).pipe( filter(Boolean), switchMap(() => { const proxyLogger = new Subject(); @@ -40,10 +44,10 @@ function updateMainEpic(actions, { getState }, { document }) { buildFromFiles(getState(), true) .map(frameMain) .ignoreElements() - .catch(err => console.error(err)) + .catch(() => of({ type: 'NULL'})) ) ); - return Observable.merge( + return merge( buildAndFrameMain, proxyLogger.map(updateConsole) ); @@ -52,7 +56,7 @@ function updateMainEpic(actions, { getState }, { document }) { } function executeChallengeEpic(action$, { getState }, { document }) { - return Observable.of(document).pipe( + return of(document).pipe( filter(Boolean), switchMap(() => { const frameReady = new Subject(); @@ -64,18 +68,18 @@ function executeChallengeEpic(action$, { getState }, { document }) { tests: challengeTestsSelector(getState()) })), switchMap(({ checkChallengePayload, tests }) => { - const postTests = Observable.of( + const postTests = of( updateConsole('// tests completed'), checkChallenge(checkChallengePayload) ).delay(250); // run the tests within the test iframe return runTestsInTestFrame(document, tests) .flatMap(tests => { - return Observable.from(tests).pipe( + return from(tests).pipe( map(({ message }) => message), filter(_.overEvery(_.isString, Boolean)), map(updateConsole), - concat(Observable.of(updateTests(tests))) + concat(of(updateTests(tests))) ); }) .concat(postTests); @@ -103,7 +107,7 @@ function executeChallengeEpic(action$, { getState }, { document }) { .catch(err => console.log(err)); }) ); - return Observable.merge(buildAndFrameChallenge, challengeResults); + 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 10eebec36d..eb39ae917c 100644 --- a/packages/learn/src/templates/Challenges/redux/index.js +++ b/packages/learn/src/templates/Challenges/redux/index.js @@ -5,6 +5,7 @@ import { createPoly } from '../utils/polyvinyl'; import challengeModalEpic from './challenge-modal-epic'; import completionEpic from './completion-epic'; import executeChallengeEpic from './execute-challenge-epic'; +import codeLockEpic from './code-lock-epic'; const ns = 'challenge'; @@ -24,7 +25,12 @@ const initialState = { successMessage: 'Happy Coding!' }; -export const epics = [challengeModalEpic, completionEpic, executeChallengeEpic]; +export const epics = [ + challengeModalEpic, + codeLockEpic, + completionEpic, + executeChallengeEpic +]; export const types = createTypes( [ @@ -37,6 +43,8 @@ export const types = createTypes( 'updateJSEnabled', 'updateSuccessMessage', 'updateTests', + + 'unlockCode', 'disableJSOnError', 'closeModal', @@ -74,6 +82,7 @@ export const updateConsole = createAction(types.updateConsole); export const updateJSEnabled = createAction(types.updateJSEnabled); export const updateSuccessMessage = createAction(types.updateSuccessMessage); +export const unlockCode = createAction(types.unlockCode); export const disableJSOnError = createAction(types.disableJSOnError, err => { console.error(err); return {}; @@ -131,6 +140,10 @@ export const reducer = handleActions( } } }), + [types.unlockCode]: state => ({ + ...state, + isJSEnabled: true + }), [types.disableJSOnError]: state => ({ ...state, isJSEnabled: false