From 161582f6c9bb32e00eb56f8cb92c2821671f1049 Mon Sep 17 00:00:00 2001 From: Nathan Leniz Date: Wed, 4 Feb 2015 19:59:51 -0500 Subject: [PATCH] courseware testing implemented --- controllers/courseware.js | 1 - public/js/lib/chai/chai-jquery.js | 231 ++++++++++++++++++ .../lib/coursewares/coursewaresFramework.js | 80 +++--- seed_data/coursewares.json | 16 +- views/coursewares/show.jade | 77 +++--- 5 files changed, 318 insertions(+), 87 deletions(-) create mode 100644 public/js/lib/chai/chai-jquery.js diff --git a/controllers/courseware.js b/controllers/courseware.js index deb6230c86..912a12c412 100644 --- a/controllers/courseware.js +++ b/controllers/courseware.js @@ -66,7 +66,6 @@ exports.returnIndividualCourseware = function(req, res, next) { details: courseware.description.slice(1), tests: courseware.tests, challengeSeed: courseware.challengeSeed, - challengeEntryPoint: courseware.challengeEntryPoint, cc: !!req.user, points: req.user ? req.user.points : undefined, verb: resources.randomVerb(), diff --git a/public/js/lib/chai/chai-jquery.js b/public/js/lib/chai/chai-jquery.js new file mode 100644 index 0000000000..52d8a72282 --- /dev/null +++ b/public/js/lib/chai/chai-jquery.js @@ -0,0 +1,231 @@ +(function (chaiJquery) { + // Module systems magic dance. + if (typeof require === "function" && typeof exports === "object" && typeof module === "object") { + // NodeJS + module.exports = chaiJquery; + } else if (typeof define === "function" && define.amd) { + // AMD + define(['jquery'], function ($) { + return function (chai, utils) { + return chaiJquery(chai, utils, $); + }; + }); + } else { + // Other environment (usually " + -"" + -"" + -"" + -"" + -""; + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + +var coursewareTests = ""; var delay; // Initialize CodeMirror editor with a nice html5 canvas demo. @@ -38,32 +54,33 @@ editor.on("change", function () { clearTimeout(delay); delay = setTimeout(updatePreview, 300); }); + +/** + * Window postMessage receiving funtionality + */ +var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; +var eventer = window[eventMethod]; +var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message"; + +// Listen to message from child window +eventer(messageEvent,function(e) { + if (e.data === 'CompleteAwesomeSauce') { + showCompletion(); + } +},false); + function updatePreview() { var previewFrame = document.getElementById('preview'); var preview = previewFrame.contentDocument || previewFrame.contentWindow.document; preview.open(); - preview.write(libraryIncludes + editor.getValue()); + preview.write(libraryIncludes + editor.getValue() + coursewareTests); preview.close(); + var passing = true; + } setTimeout(updatePreview, 300); -// Default value for editor if one isn't provided in (i.e. a challenge) -var nonChallengeValue = '/*Welcome to Bonfire, Free Code Camp\'s future CoderByte replacement.\n' + - 'Please feel free to use Bonfire as an in-browser playground and linting tool.\n' + - 'Note that you can also write tests using Chai.js by using the keywords assert and expect */\n\n' + - 'function test() {\n' + - ' assert(2 !== 3, "2 is not equal to 3");\n' + - ' return [1,2,3].map(function(elem) {\n' + - ' return elem * elem;\n' + - ' });\n' + - '}\n' + - 'expect(test()).to.be.a("array");\n\n' + - 'assert.deepEqual(test(), [1,4,9]);\n\n' + - 'var foo = test();\n' + - 'foo.should.be.a("array");\n\n' + - 'test();\n'; - var codeOutput = CodeMirror.fromTextArea(document.getElementById("codeOutput"), { lineNumbers: false, mode: "text", @@ -86,17 +103,9 @@ var editorValue; var challengeSeed = challengeSeed || null; var tests = tests || []; -var challengeEntryPoint = challengeEntryPoint || null; -if (challengeSeed !== null) { - editorValue = challengeSeed + '\n\n' + challengeEntryPoint; -} else { - editorValue = nonChallengeValue; -} - - -myCodeMirror.setValue(editorValue); +myCodeMirror.setValue(challengeSeed); function doLinting () { editor.operation(function () { @@ -131,10 +140,7 @@ function bonfireExecute() { var userJavaScript = myCodeMirror.getValue(); userJavaScript = removeComments(userJavaScript); userJavaScript = scrapeTests(userJavaScript); - // simple fix in case the user forgets to invoke their function - if (challengeEntryPoint) { - userJavaScript = challengeEntryPoint + ' ' + userJavaScript; - } + submit(userJavaScript, function(cls, message) { if (cls) { codeOutput.setValue(message.error); @@ -251,4 +257,6 @@ var runTests = function(err, data) { function showCompletion() { $('#complete-bonfire-dialog').modal('show'); -} \ No newline at end of file +} + +document.domain = 'localhost'; \ No newline at end of file diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index a773aa40fd..69a3c1a4f8 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -1,19 +1,17 @@ [ { "_id" : "bd7123c8c441eddfaeb5bdef", - "name": "Meet Bonfire", + "name": "Intro", "difficulty": "0", "description": [ - "Click the button below for further instructions.", - "Your goal is to fix the failing test.", - "First, run all the tests by clickin \"Run code\" or by pressing Control + Enter", - "The failing test is in red. Fix the code so that all tests pass. Then you can move on to the next Bonfire." + "Welcome to the FCC courseware! You can click on the button below for more information", + "Courseware comes loaded with Bootstrap, Jquery, and Angular. You can include more libraries by finding a cdn and including them in your html", + "We hope you have fun learning!", + "To advance to the next exercise, change the h1 tag's text to say hello world" ], "tests": [ - "expect(meetBonfire(\"test\")).to.be.a(\"boolean\");", - "expect(meetBonfire(\"test\")).to.be.true;" + "expect($('h1')).to.have.text('hello world');" ], - "challengeSeed": "function meetBonfire(argument) {\n // Good luck!\n console.log(\"you can read this function's argument in the developer tools\", argument);\n\nreturn false;\n}\n\n", - "challengeEntryPoint": "meetBonfire(\"You can do this!\");" + "challengeSeed": "

hello you

" } ] \ No newline at end of file diff --git a/views/coursewares/show.jade b/views/coursewares/show.jade index 7f9868f508..789d9b6316 100644 --- a/views/coursewares/show.jade +++ b/views/coursewares/show.jade @@ -7,6 +7,7 @@ block content script(src='/js/lib/codemirror/addon/lint/javascript-lint.js') script(src='//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js') script(src='/js/lib/chai/chai.js') + script(src='/js/lib/chai/chai-jquery.js') link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css') link(rel='stylesheet', href='/js/lib/codemirror/addon/lint/lint.css') link(rel='stylesheet', href='/js/lib/codemirror/theme/monokai.css') @@ -63,46 +64,40 @@ block content .hidden-xs.hidden-sm img.iphone-position(src="https://s3.amazonaws.com/freecodecamp/iphone6-frame.png") iframe.iphone#preview - // - .visible-xs-block.visible-sm-block.text-center - iframe.no-phone#preview - // - //.modal-dialog.animated.zoomIn.fast-animation - // .modal-content - // .modal-header.challenge-list-header= compliment - // a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × - // .modal-body(ng-controller="pairedWithController") - // .text-center - // .animated.zoomInDown.delay-half - // span.landing-icon.ion-checkmark-circled.text-primary - // - if (cc) - // form.form-horizontal(novalidate='novalidate', name='completedWithForm') - // .form-group.text-center - // .col-xs-10.col-xs-offset-1.col-sm-8.col-sm-offset-2.col-md-8.col-md-offset-2.animated.fadeIn - // // extra field to distract password tools like lastpass from injecting css into our username field - // input.form-control(ng-show="false") - // input.form-control#completed-with(name="existingUser", placeholder="If you paired, enter your pair's username here", existing-username='', ng-model="existingUser", autofocus) - // .col-xs-10.col-xs-offset-1.col-sm-8.col-sm-offset-2.col-md-8.col-md-offset-2(ng-show="completedWithForm.$error.exists && !completedWithForm.existingUser.$pristine && existingUser.length > 0") - // alert(type='danger') - // span.ion-close-circled - // | Username not found - // a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block.next-bonfire-button(name='_csrf', value=_csrf, aria-hidden='true', ng-disabled='completedWithForm.$invalid && existingUser.length > 0') Take me to my next challenge - // - if (points && points > 2) - // a.animated.fadeIn.btn.btn-lg.btn-block.btn-twitter(href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20%40FreeCodeCamp%20Bonfire:%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/bonfires/#{dashedName}&hashtags=LearnToCode, JavaScript" target="_blank") - // i.fa.fa-twitter   - // = phrase - // - else - // a.animated.fadeIn.btn.btn-lg.signup-btn.btn-block(href='/login') Sign in so you can save your progress - // #all-bonfires-dialog.modal(tabindex='-1') - //.modal-dialog.animated.fadeInUp.fast-animation - // .modal-content - // .modal-header.challenge-list-header Bonfires - // a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × - // .modal-body - // include ../partials/bonfires - // - //script(src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js") - //script(src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js") - //style(src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css") + + + #complete-bonfire-dialog.modal(tabindex='-1') + .modal-dialog.animated.zoomIn.fast-animation + .modal-content + .modal-header.challenge-list-header= compliment + a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × + .modal-body(ng-controller="pairedWithController") + + .text-center + .animated.zoomInDown.delay-half + span.completion-icon.ion-checkmark-circled.text-primary + - if (cc) + form.form-horizontal(novalidate='novalidate', name='completedWithForm') + .form-group.text-center + .col-xs-10.col-xs-offset-1.col-sm-8.col-sm-offset-2.col-md-8.col-md-offset-2.animated.fadeIn + // extra field to distract password tools like lastpass from injecting css into our username field + input.form-control(ng-show="false") + input.form-control#completed-with(name="existingUser", placeholder="If you paired, enter your pair's username here", existing-username='', ng-model="existingUser", autofocus) + .col-xs-10.col-xs-offset-1.col-sm-8.col-sm-offset-2.col-md-8.col-md-offset-2(ng-cloak, ng-show="completedWithForm.$error.exists && !completedWithForm.existingUser.$pristine && existingUser.length > 0") + alert(type='danger') + span.ion-close-circled + | Username not found + + a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block.next-bonfire-button(name='_csrf', value=_csrf, aria-hidden='true', ng-disabled='completedWithForm.$invalid && existingUser.length > 0') Take me to my next challenge + + + - if (points && points > 2) + a.animated.fadeIn.btn.btn-lg.btn-block.btn-twitter(href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20%40FreeCodeCamp%20Bonfire:%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/bonfires/#{dashedName}&hashtags=LearnToCode, JavaScript" target="_blank") + i.fa.fa-twitter   + = phrase + - else + a.animated.fadeIn.btn.btn-lg.signup-btn.btn-block(href='/login') Sign in so you can save your progress + + \ No newline at end of file