| 
									
										
										
										
											2015-11-01 17:20:03 -08:00
										 |  |  | /* eslint-disable no-eval, no-process-exit */ | 
					
						
							|  |  |  | import _ from 'lodash'; | 
					
						
							|  |  |  | import { Observable } from 'rx'; | 
					
						
							|  |  |  | import tape from 'tape'; | 
					
						
							|  |  |  | import getChallenges from './getChallenges'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function createIsAssert(t, isThing) { | 
					
						
							|  |  |  |   const { assert } = t; | 
					
						
							|  |  |  |   return function() { | 
					
						
							|  |  |  |     const args = [...arguments]; | 
					
						
							|  |  |  |     args[0] = isThing(args[0]); | 
					
						
							|  |  |  |     assert.apply(t, args); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function fillAssert(t) { | 
					
						
							|  |  |  |   const assert = t.assert; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   assert.isArray = createIsAssert(t, _.isArray); | 
					
						
							|  |  |  |   assert.isBoolean = createIsAssert(t, _.isBoolean); | 
					
						
							|  |  |  |   assert.isString = createIsAssert(t, _.isString); | 
					
						
							|  |  |  |   assert.isNumber = createIsAssert(t, _.isNumber); | 
					
						
							|  |  |  |   assert.isUndefined = createIsAssert(t, _.isUndefined); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   assert.deepEqual = t.deepEqual; | 
					
						
							|  |  |  |   assert.equal = t.equal; | 
					
						
							|  |  |  |   assert.strictEqual = t.equal; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   assert.sameMembers = function sameMembers() { | 
					
						
							|  |  |  |     const [ first, second, ...args] = arguments; | 
					
						
							|  |  |  |     assert.apply( | 
					
						
							|  |  |  |       t, | 
					
						
							|  |  |  |       [ | 
					
						
							|  |  |  |         _.difference(first, second).length === 0 && | 
					
						
							|  |  |  |         _.difference(second, first).length === 0 | 
					
						
							|  |  |  |       ].concat(args) | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   assert.includeMembers = function includeMembers() { | 
					
						
							|  |  |  |     const [ first, second, ...args] = arguments; | 
					
						
							|  |  |  |     assert.apply(t, [_.difference(second, first).length === 0].concat(args)); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   assert.match = function match() { | 
					
						
							|  |  |  |     const [value, regex, ...args] = arguments; | 
					
						
							|  |  |  |     assert.apply(t, [regex.test(value)].concat(args)); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return assert; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-28 22:54:02 -08:00
										 |  |  | function createTest({ | 
					
						
							|  |  |  |   title, | 
					
						
							|  |  |  |   tests = [], | 
					
						
							|  |  |  |   solutions = [], | 
					
						
							| 
									
										
										
										
											2015-12-28 23:14:42 -08:00
										 |  |  |   head = [], | 
					
						
							|  |  |  |   tail = [] | 
					
						
							| 
									
										
										
										
											2015-12-28 22:54:02 -08:00
										 |  |  | }) { | 
					
						
							|  |  |  |   solutions = solutions.filter(solution => !!solution); | 
					
						
							|  |  |  |   tests = tests.filter(test => !!test); | 
					
						
							| 
									
										
										
										
											2015-12-28 23:14:42 -08:00
										 |  |  |   head = head.join('\n'); | 
					
						
							|  |  |  |   tail = tail.join('\n'); | 
					
						
							| 
									
										
										
										
											2015-11-01 17:20:03 -08:00
										 |  |  |   const plan = tests.length; | 
					
						
							| 
									
										
										
										
											2015-12-28 22:54:02 -08:00
										 |  |  |   if (!plan) { | 
					
						
							|  |  |  |     return Observable.just({ | 
					
						
							|  |  |  |       title, | 
					
						
							|  |  |  |       type: 'missing' | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-01 17:20:03 -08:00
										 |  |  |   return Observable.fromCallback(tape)(title) | 
					
						
							|  |  |  |     .doOnNext(t => solutions.length ? t.plan(plan) : t.end()) | 
					
						
							|  |  |  |     .flatMap(t => { | 
					
						
							|  |  |  |       if (solutions.length <= 0) { | 
					
						
							|  |  |  |         t.comment('No solutions for ' + title); | 
					
						
							|  |  |  |         return Observable.just({ | 
					
						
							|  |  |  |           title, | 
					
						
							|  |  |  |           type: 'missing' | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-28 22:54:02 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-01 17:20:03 -08:00
										 |  |  |       return Observable.just(t) | 
					
						
							|  |  |  |         .map(fillAssert) | 
					
						
							|  |  |  |         /* eslint-disable no-unused-vars */ | 
					
						
							| 
									
										
										
										
											2015-12-29 10:23:57 -08:00
										 |  |  |         // assert and code used within the eval
 | 
					
						
							| 
									
										
										
										
											2015-11-01 17:20:03 -08:00
										 |  |  |         .doOnNext(assert => { | 
					
						
							|  |  |  |           solutions.forEach(solution => { | 
					
						
							|  |  |  |             tests.forEach(test => { | 
					
						
							| 
									
										
										
										
											2015-12-28 23:14:42 -08:00
										 |  |  |               const code = solution; | 
					
						
							| 
									
										
										
										
											2015-12-28 22:54:02 -08:00
										 |  |  |               const editor = { getValue() { return code; } }; | 
					
						
							|  |  |  |               /* eslint-enable no-unused-vars */ | 
					
						
							| 
									
										
										
										
											2015-11-01 21:18:00 -08:00
										 |  |  |               try { | 
					
						
							| 
									
										
										
										
											2015-12-28 23:14:42 -08:00
										 |  |  |                 (() => { | 
					
						
							| 
									
										
										
										
											2015-12-29 10:23:57 -08:00
										 |  |  |                   return eval( | 
					
						
							|  |  |  |                     head + '\n;;' + | 
					
						
							|  |  |  |                     solution + '\n;;' + | 
					
						
							|  |  |  |                     tail + '\n;;' + | 
					
						
							|  |  |  |                     test); | 
					
						
							| 
									
										
										
										
											2015-12-28 23:14:42 -08:00
										 |  |  |                 })(); | 
					
						
							| 
									
										
										
										
											2015-11-01 21:18:00 -08:00
										 |  |  |               } catch (e) { | 
					
						
							|  |  |  |                 t.fail(e); | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2015-11-01 17:20:03 -08:00
										 |  |  |             }); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         .map(() => ({ title })); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Observable.from(getChallenges()) | 
					
						
							|  |  |  |   .flatMap(challengeSpec => { | 
					
						
							|  |  |  |     return Observable.from(challengeSpec.challenges); | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  |   .flatMap(challenge => { | 
					
						
							|  |  |  |     return createTest(challenge); | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  |   .map(({ title, type }) => { | 
					
						
							|  |  |  |     if (type === 'missing') { | 
					
						
							|  |  |  |       return title; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  |   .filter(title => !!title) | 
					
						
							|  |  |  |   .toArray() | 
					
						
							|  |  |  |   .subscribe( | 
					
						
							|  |  |  |     (noSolutions) => { | 
					
						
							|  |  |  |       console.log( | 
					
						
							|  |  |  |         '# These challenges have no solutions\n- [ ] ' + | 
					
						
							|  |  |  |           noSolutions.join('\n- [ ] ') | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     err => { throw err; }, | 
					
						
							|  |  |  |     () => process.exit(0) | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | 
 |