From d1a12fc8944b825d9effc9cc2932ab2db212708b Mon Sep 17 00:00:00 2001 From: LumenTeun Date: Wed, 17 Jun 2015 23:30:08 +0200 Subject: [PATCH 1/8] 'No repeats please' test fix. #941 --- seed/challenges/advanced-bonfires.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/advanced-bonfires.json b/seed/challenges/advanced-bonfires.json index e14504dba4..978ebe81ce 100644 --- a/seed/challenges/advanced-bonfires.json +++ b/seed/challenges/advanced-bonfires.json @@ -230,7 +230,7 @@ "permAlone('aab');" ], "tests": [ - "expect(permAlone('aab')).to.be.a.number;", + "expect(permAlone('aab')).to.be.a('number');", "expect(permAlone('aab')).to.equal(2);", "expect(permAlone('aaa')).to.equal(0);", "expect(permAlone('aabb')).to.equal(8);", From 842a2efe64785d44a4ffd403bed6a56e352149d3 Mon Sep 17 00:00:00 2001 From: LumenTeun Date: Thu, 18 Jun 2015 11:56:13 +0200 Subject: [PATCH 2/8] More test cases for 'Seek and Destroy' #942 --- seed/challenges/basic-bonfires.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index df4b6bc16c..5a553f92ed 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -656,7 +656,10 @@ ], "tests": [ "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'should remove correct values from an array');", - "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'should remove correct values from an array');" + "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'should remove correct values from an array');", + "assert.deepEqual(destroyer([3, 5, 1, 2, 2], 2, 3, 5), [1], 'should accept more than two additional arguments');", + "assert.deepEqual(destroyer([2, 3, 2, 3], 2, 3), [], 'should remove correct values from an array');", + "assert.deepEqual(destroyer(['tree', 'hamburger', 53], 'tree', 53), ['hamburger'], 'should handle NaN-elements');" ], "MDNlinks": [ "Arguments object", From 7735f19fcc03233aa082a38d1ea556d5dd480bb2 Mon Sep 17 00:00:00 2001 From: rcw271828 Date: Thu, 18 Jun 2015 20:36:33 -0400 Subject: [PATCH 3/8] Update field-guides.json Fixed a typo in languages section of field guides. --- seed/field-guides.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/field-guides.json b/seed/field-guides.json index 2de429b569..9d3e906d16 100644 --- a/seed/field-guides.json +++ b/seed/field-guides.json @@ -863,7 +863,7 @@ "description": [ "
", "

Translation is an all-or-nothing proposal.", - "

We won't be able to add new languages to Free Code Camp until all of our challenges are translated into that langauge.

", + "

We won't be able to add new languages to Free Code Camp until all of our challenges are translated into that language.

", "

In addition to translating these initially, we'll also need to maintain the translation as the challenges are gradually updated.

", "

If you're able to help us, you can join our Trello board by sending @quincylarson your email address in Slack.

", "
" From 8ade99b5d738470f7e8d4d38b014ba94c413796c Mon Sep 17 00:00:00 2001 From: Brett Guillory Date: Sat, 13 Jun 2015 20:54:43 -0500 Subject: [PATCH 4/8] Fixed a word --- seed/challenges/basic-bonfires.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index df4b6bc16c..8ecebec116 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -853,7 +853,7 @@ "difficulty": "2.03", "description": [ "Perform a search and replace on the sentence using the arguments provided and return the new sentence.", - "First argument is the sentence the perform the search and replace on.", + "First argument is the sentence to perform the search and replace on.", "Second argument is the word that you will be replacing (before).", "Third argument is what you will be replacing the second argument with (after).", "NOTE: Preserve the case of the original word when you are replacing it. For example if you mean to replace the word 'Book' with the word 'dog', it should be replaced as 'Dog'", From d6db51355e15e3ba426ceac18cbd754207a99e40 Mon Sep 17 00:00:00 2001 From: Brett Guillory Date: Sat, 13 Jun 2015 23:28:33 -0500 Subject: [PATCH 5/8] Added missing MDN Link This bonfire "Missing letters"seems to be missing an important MDN link to "String.fromCharCode()", which is needed to get the missing character to return for the test. Since the missing character is obviously not in the string supplied, you cannot get the character code for it from the string. --- seed/challenges/basic-bonfires.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index 8ecebec116..08c797f58c 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -990,7 +990,8 @@ "expect(fearNotLetter('yz')).to.be.undefined;" ], "MDNlinks": [ - "String.charCodeAt()" + "String.charCodeAt()", + "String.fromCharCode()" ], "challengeType": 5, "nameCn": "", From 934250387379b454a9258dfd680fa136997de3f6 Mon Sep 17 00:00:00 2001 From: Stephen Wanhella Date: Thu, 18 Jun 2015 02:18:18 -0700 Subject: [PATCH 6/8] Added new test with different max number to Bonfire: Truncate a String Issue 959 --- seed/challenges/basic-bonfires.json | 1 + 1 file changed, 1 insertion(+) diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index 08c797f58c..412ed80ad1 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -422,6 +422,7 @@ ], "tests": [ "expect(truncate('A-tisket a-tasket A green and yellow basket', 11)).to.eqls('A-tisket...');", + "expect(truncate('Peter Piper picked a peck of pickled peppers', 14)).to.eqls('Peter Piper...');", "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length) === 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is = length');", "assert.strictEqual(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2), 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is < length');" ], From 50a0ad3595588244c172226caff3d5f5c85a437d Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Sat, 20 Jun 2015 00:36:28 -0700 Subject: [PATCH 7/8] fix use gt not $gt closes #1022 --- server/boot/nonprofits.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/boot/nonprofits.js b/server/boot/nonprofits.js index 988ded5f84..1d16e76b74 100644 --- a/server/boot/nonprofits.js +++ b/server/boot/nonprofits.js @@ -9,7 +9,7 @@ module.exports = function(app) { function nonprofitsDirectory(req, res, next) { Nonprofit.find( - { where: { estimatedHours: { $gt: 0 } } }, + { where: { estimatedHours: { gt: 0 } } }, function(err, nonprofits) { if (err) { return next(err); } From 43ae70465bf347817c736e0e024be53c4ac337ec Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Sat, 20 Jun 2015 11:43:12 -0700 Subject: [PATCH 8/8] refactor returnIndividualBonfires --- server/boot/challenge.js | 219 ++++++++++++++----------------------- server/utils/middleware.js | 10 ++ 2 files changed, 90 insertions(+), 139 deletions(-) diff --git a/server/boot/challenge.js b/server/boot/challenge.js index bddf9118c4..4b3d23e0e0 100644 --- a/server/boot/challenge.js +++ b/server/boot/challenge.js @@ -32,7 +32,9 @@ var R = require('ramda'), utils = require('../utils'), - userMigration = require('../utils/middleware').userMigration; + saveUser = require('../utils/rx').saveUser, + userMigration = require('../utils/middleware').userMigration, + ifNoUserRedirectTo = require('../utils/middleware').ifNoUserRedirectTo; var challengeMapWithNames = utils.getChallengeMapWithNames(); var challengeMapWithIds = utils.getChallengeMapWithIds(); @@ -51,23 +53,30 @@ module.exports = function(app) { // the follow routes are covered by userMigration router.use(userMigration); - router.get('/challenges/next-challenge', returnNextChallenge); - router.get('/challenges/:challengeName', returnIndividualChallenge); - router.get('/challenges/', returnCurrentChallenge); router.get('/map', challengeMap); + router.get( + '/challenges/next-challenge', + ifNoUserRedirectTo('../challenges/learn-how-free-code-camp-works'), + returnNextChallenge + ); + + router.get('/challenges/:challengeName', returnIndividualChallenge); + + router.get( + '/challenges/', + ifNoUserRedirectTo('../challenges/learn-how-free-code-camp-works'), + returnCurrentChallenge + ); app.use(router); function returnNextChallenge(req, res, next) { - if (!req.user) { - return res.redirect('../challenges/learn-how-free-code-camp-works'); - } var completed = req.user.completedChallenges.map(function (elem) { return elem.id; }); req.user.uncompletedChallenges = utils.allChallengeIds() - .filter(function (elem) { + .filter(function(elem) { if (completed.indexOf(elem) === -1) { return elem; } @@ -100,18 +109,17 @@ module.exports = function(app) { nextChallengeName = R.head(challengeMapWithDashedNames[0].challenges); } - req.user.save(function(err) { - if (err) { - return next(err); - } - return res.redirect('../challenges/' + nextChallengeName); - }); + saveUser(req.user) + .subscribe( + function() {}, + next, + function() { + res.redirect('../challenges/' + nextChallengeName); + } + ); } function returnCurrentChallenge(req, res, next) { - if (!req.user) { - return res.redirect('../challenges/learn-how-free-code-camp-works'); - } var completed = req.user.completedChallenges.map(function (elem) { return elem.id; }); @@ -133,12 +141,14 @@ module.exports = function(app) { var nameString = req.user.currentChallenge.dashedName; - req.user.save(function(err) { - if (err) { - return next(err); - } - return res.redirect('../challenges/' + nameString); - }); + saveUser(req.user) + .subscribe( + function() {}, + next, + function() { + res.redirect('../challenges/' + nameString); + } + ); } function returnIndividualChallenge(req, res, next) { @@ -152,8 +162,10 @@ module.exports = function(app) { // Handle not found if (!challenge) { req.flash('errors', { - msg: '404: We couldn\'t find a challenge with that name. ' + - 'Please double check the name.' + msg: + '404: We couldn\'t find a challenge with the name `' + + dashedName + + '` Please double check the name.' }); return res.redirect('/challenges'); } @@ -167,8 +179,9 @@ module.exports = function(app) { map(function (key) { return challengeMapWithIds[key] .filter(function (elem) { - return String(elem) === String(challenge.id); - }).map(function () { + return String(elem) === challenge.id; + }) + .map(function () { return key; }); }) @@ -176,120 +189,48 @@ module.exports = function(app) { }; } - var challengeType = { - 0: function() { - res.render('coursewares/showHTML', { - title: challenge.name, - dashedName: dashedName, - name: challenge.name, - brief: challenge.description[0], - details: challenge.description.slice(1), - tests: challenge.tests, - challengeSeed: challenge.challengeSeed, - verb: utils.randomVerb(), - phrase: utils.randomPhrase(), - compliment: utils.randomCompliment(), - challengeId: challenge.id, - environment: utils.whichEnvironment(), - challengeType: challenge.challengeType - }); - }, - - 1: function() { - res.render('coursewares/showJS', { - title: challenge.name, - dashedName: dashedName, - name: challenge.name, - brief: challenge.description[0], - details: challenge.description.slice(1), - tests: challenge.tests, - challengeSeed: challenge.challengeSeed, - verb: utils.randomVerb(), - phrase: utils.randomPhrase(), - compliment: utils.randomCompliment(), - challengeId: challenge.id, - challengeType: challenge.challengeType - }); - }, - - 2: function() { - res.render('coursewares/showVideo', { - title: challenge.name, - dashedName: dashedName, - name: challenge.name, - details: challenge.description, - tests: challenge.tests, - video: challenge.challengeSeed[0], - verb: utils.randomVerb(), - phrase: utils.randomPhrase(), - compliment: utils.randomCompliment(), - challengeId: challenge.id, - challengeType: challenge.challengeType - }); - }, - - 3: function() { - res.render('coursewares/showZiplineOrBasejump', { - title: challenge.name, - dashedName: dashedName, - name: challenge.name, - details: challenge.description, - video: challenge.challengeSeed[0], - verb: utils.randomVerb(), - phrase: utils.randomPhrase(), - compliment: utils.randomCompliment(), - challengeId: challenge.id, - challengeType: challenge.challengeType - }); - }, - - 4: function() { - res.render('coursewares/showZiplineOrBasejump', { - title: challenge.name, - dashedName: dashedName, - name: challenge.name, - details: challenge.description, - video: challenge.challengeSeed[0], - verb: utils.randomVerb(), - phrase: utils.randomPhrase(), - compliment: utils.randomCompliment(), - challengeId: challenge.id, - challengeType: challenge.challengeType - }); - }, - - 5: function() { - res.render('coursewares/showBonfire', { - completedWith: null, - title: challenge.name, - dashedName: dashedName, - name: challenge.name, - difficulty: Math.floor(+challenge.difficulty), - brief: challenge.description.shift(), - details: challenge.description, - tests: challenge.tests, - challengeSeed: challenge.challengeSeed, - verb: utils.randomVerb(), - phrase: utils.randomPhrase(), - compliment: utils.randomCompliment(), - bonfires: challenge, - challengeId: challenge.id, - MDNkeys: challenge.MDNlinks, - MDNlinks: getMDNLinks(challenge.MDNlinks), - challengeType: challenge.challengeType - }); - } + var commonLocals = { + title: challenge.name, + dashedName: dashedName, + name: challenge.name, + details: challenge.description.slice(1), + tests: challenge.tests, + challengeSeed: challenge.challengeSeed, + verb: utils.randomVerb(), + phrase: utils.randomPhrase(), + compliment: utils.randomCompliment(), + challengeId: challenge.id, + challengeType: challenge.challengeType, + // video challenges + video: challenge.challengeSeed[0], + // bonfires specific + difficulty: Math.floor(+challenge.difficulty), + brief: challenge.description.shift(), + bonfires: challenge, + MDNkeys: challenge.MDNlinks, + MDNlinks: getMDNLinks(challenge.MDNlinks), + // htmls specific + environment: utils.whichEnvironment() }; - if (req.user) { - req.user.save(function (err) { - if (err) { - return next(err); + + var challengeView = { + 0: 'coursewares/showHTML', + 1: 'coursewares/showJS', + 2: 'coursewares/showVideo', + 3: 'coursewares/showZiplineOrBasejump', + 4: 'coursewares/showZiplineOrBasejump', + 5: 'coursewares/showBonfire' + }; + + saveUser(req.user) + .subscribe( + function() {}, + next, + function() { + var view = challengeView[challenge.challengeType]; + res.render(view, commonLocals); } - return challengeType[challenge.challengeType](); - }); - } else { - return challengeType[challenge.challengeType](); - } + ); }); } diff --git a/server/utils/middleware.js b/server/utils/middleware.js index 5d2d12741c..5af207e513 100644 --- a/server/utils/middleware.js +++ b/server/utils/middleware.js @@ -33,3 +33,13 @@ exports.userMigration = function userMigration(req, res, next) { ); return next(); }; + +exports.ifNoUserRedirectTo = function ifNoUserRedirectTo(url) { + return function(req, res, next) { + if (req.user) { + return next(); + } + return res.redirect(url); + }; +}; +