feat(package): Initial Curriculum separation (#17174)

* feat(package): Initial Curriculum separation

* feat(package): Add org scope to package

* chore(ooops): Remove development file

* feat(npm): Add .npmignore

* fix(paths): Fix curriculum paths

* feat(build): Add a build step

* chore(seed): Move package file back to seed

* fix(ignore): Fix .npmIgnore file

* chore(docs): Update README

* chore(seed): Rename coding interview blocks

* fix(seed): Challenge files now fit into learn

* chore(seed): Update seed files for use in learn

* chore(escapes): Unescape script tags of jQuery
This commit is contained in:
Stuart Taylor
2018-05-21 14:56:49 +01:00
committed by mrugesh mohapatra
parent 63482406ea
commit ee66d84ccb
69 changed files with 99780 additions and 73476 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
node_modules
dist
unpacked/
*.log
*.tgz

3
.npmignore Normal file
View File

@ -0,0 +1,3 @@
*
!dist/*.js
!dist/challenges/**/*.json

View File

@ -1,4 +1,73 @@
## freeCodeCamp Curriculum
This directory contains code and data to "seed" the Mongo database with challenges.
This package contains the "seed" files used in the freeCodeCamp Curriculum.
### Installation
```sh
npm i @freecodecamp/curriculum
# or
yarn add @freecodecamp/curriculum
```
### Usage
```js
import { getChallenges } from '@freecodecamp/curriculum';
getChallenges() // will provide an array of blocks i.e. basic CSS, functional programming
```
#### `block` Structure
```json
{
"name": "ES6",
"order": 2,
"time": "5 hours",
"helpRoom": "Help",
"challenges": [/*<challenge>*/],
"fileName": "02-javascript-algorithms-and-data-structures/es6.json",
"superBlock": "javascript-algorithms-and-data-structures",
"superOrder": 2
}
```
#### `challenge` Structure
```json
{
"id": "ObjectId()",
"title": "Declare a Read-Only Variable with the const Keyword",
"description": [
"A Description of the challenge and what is required to pass"
],
"tests": [
{
"text": "should return \"foo\"",
"testString": "a stringified function using Chai asserts"
}
],
"challengeType": 1,
"translations": {},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"Initial editor seed"
],
"head": [
"A place for test set up",
"Can be thought of as mocha's beforeEach()"
],
"tail": [
"A place for test tear down",
"Can be thought of as mocha's afterEach()"
]
}
}
},
```
See the main [CONTRIBUTING](../CONTRIBUTING.md) file for instructions and details.

View File

@ -1,102 +0,0 @@
/**
* MDN Links
*
* These links are for Bonfires. Each key/value pair is used to render a Bonfire with appropriate links.
* The text of the key is what the link text will be, e.g. <a href="https://developer ...">Global Array Object</a>
* General convention is to use the page title of the MDN reference page.
*
**/
var links = {
// ========= NON MDN REFS
"Currying": "https://leanpub.com/javascript-allonge/read#pabc",
"Smallest Common Multiple": "https://www.mathsisfun.com/least-common-multiple.html",
"Permutations": "https://www.mathsisfun.com/combinatorics/combinations-permutations.html",
"HTML Entities": "http://dev.w3.org/html5/html-author/charref",
"Symmetric Difference": "https://www.youtube.com/watch?v=PxffSUQRkG4",
"Roman Numerals": "http://www.mathsisfun.com/roman-numerals.html",
"Floating Point Guide": "http://floating-point-gui.de",
// ========= GLOBAL OBJECTS
"Global Array Object": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array",
"Global Object": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object",
"Global String Object": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String",
"Boolean Objects": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean",
"RegExp": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp",
"Global Function Object": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function",
"Arguments object": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments",
"Closures": "https://developer.mozilla.org/en-US/docs/" +
"Web/JavaScript/Closures",
// ========= GLOBAL OBJECT METHODS
"parseInt()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt",
// ========= PROPERTIES/MISC
"String.length": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length",
// ========== OBJECT METHODS
"Object.getOwnPropertyNames()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames",
"Object.keys()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys",
"Object.prototype.hasOwnProperty()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty",
// ======== STRING METHODS
"String.prototype.charAt()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charAt",
"String.prototype.charCodeAt()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt",
"String.prototype.concat()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/concat",
"String.prototype.indexOf()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf",
"String.fromCharCode()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCharCode",
"String.prototype.lastIndexOf()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/lastIndexOf",
"String.prototype.match()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match",
"String.prototype.replace()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace",
"String.prototype.slice()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice",
"String.prototype.split()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split",
"String.prototype.substring()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring",
"String.prototype.substr()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr",
"String.prototype.toLowerCase()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase",
"String.prototype.toString()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toString",
"String.prototype.toUpperCase()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase",
// ======== ARRAY METHODS
"Array.prototype.concat()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat",
"Array.prototype.every()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every",
"Array.prototype.filter()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter",
"Array.prototype.forEach()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach",
"Array.prototype.indexOf()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf",
"Array.isArray()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray",
"Array.prototype.join()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join",
"Array.prototype.lastIndexOf()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf",
"Array.prototype.map()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map",
"Array.prototype.pop()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop",
"Array.prototype.push()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push",
"Array.prototype.reduce()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce",
"Array.prototype.reverse()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse",
"Array.prototype.shift()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift",
"Array.prototype.slice()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice",
"Array.prototype.some()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some",
"Array.prototype.sort()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort",
"Array.prototype.splice()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice",
"Array.prototype.toString()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString",
// ======== STATEMENTS AND DECLARATIONS
"Switch Statement": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch",
// ======== MATH METHODS
"Math.max()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max",
"Math.min()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/min",
"Math.pow()": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/pow",
"Remainder": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Remainder",
// ======== GENERAL JAVASCRIPT REFERENCES
"Arithmetic Operators": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators",
"Comparison Operators": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators",
"Strict Inequality Operator": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Non-identity_strict_inequality_(!)",
"Details of the Object Model": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model",
"For Loops": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for",
"Truthy": "https://developer.mozilla.org/en-US/docs/Glossary/Truthy",
"Falsy": "https://developer.mozilla.org/en-US/docs/Glossary/Falsy"
};
module.exports = links;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,175 +1,9 @@
{
"name": "Applied Responsive Web Design Projects",
"name": "Responsive Web Design Projects",
"order": 7,
"time": "150 hours",
"helpRoom": "Help",
"challenges": [
{
"id": "587d78af367417b2b2512b02",
"title": "Get Set for our Responsive Web Design Projects",
"description": [
[
"",
"",
"Our front end development projects will give you a chance to apply the front end skills you've developed up to this point. We'll use a popular browser-based code editor called CodePen.",
""
],
[
"",
"",
"These projects are hard. It takes most campers several days to build each project. You will get frustrated. But don't quit. This gets easier with practice.",
""
],
[
"",
"",
"When you get stuck, just use the Read-Search-Ask methodology. Don't worry - you've got this.",
""
],
[
"",
"",
"You can build these project challenges on your local computer or on a web-based code editor like <a href='https://www.codepen.io'>CodePen.io</a>. As long as your projects are publicly accessible online, you can submit their web addresses so you can claim your verified Responsive Web Design certificate.",
"https://codepen.io/accounts/signup/user/free"
]
],
"challengeSeed": [],
"tests": [],
"type": "Waypoint",
"isRequired": false,
"challengeType": 7,
"translations": {
"es": {
"title": "Prepárate para los Proyectos de Desarrollo de Interfaces",
"description": [
[
"https://i.imgur.com/OAD6SJz.png",
"Una imagen del juego Simón, uno de nuestros proyectos de interfaz.",
"Nuestros proyectos de desarrollo de interfaces te darán oportunidad de aplicar las habilidades con interfaces que has desarrollado hasta este momento. Usaremos un editor de código basado en el navegador llamado CodePen.",
""
],
[
"https://i.imgur.com/WBetuBa.jpg",
"Un programador frustado golpeando la pantalla de su computador.",
"Nuestros desafíos sobre algoritmos son difíciles. Algunos pueden requerir muchas horas para resolverse. Podrás frustarte, pero no te rindas. Se vuelve fácil con práctica.",
""
],
[
"https://i.imgur.com/p2TpOQd.jpg",
"Un tierno perro que salta sobre un obstáculo, pica el ojo y te apunta con su pata.",
"Cuando te atasques, usa la metodología Leer-Buscar-Preguntar. No te preocupes - lo tienes resuelto.",
""
],
[
"https://i.imgur.com/G1saeDt.gif",
"Un gif que muestra cómo crear una cuenta en Codepen.",
"Para nuestros desafíos de interfaces, usaremos un editor de código basado en el navegador que es muy famoso llamado Codepen. Pulsa en el botón de abajo \"Open link in new tab\" para abrir la página de registro de CodePen. Rellena el formulario y pulsa \"Sign up\". <br><div class=\"small\">Nota: Si ya tienes una cuenta de CodePen, puedes omitir este paso pulsando \"Open link in new tab\", cierra la nueva pestaña que se abre, entonces pulsa \"go to my next step\". Eliminamos nuestro botón \"skip step\" porque mucha gente solamente pulsa el botón sin realizar estos importantes pasos.</div>",
"https://codepen.io/accounts/signup/user/free"
],
[
"https://i.imgur.com/U4y9RJ1.gif",
"Un gif que muestra que puedes escribir \"hello world\" en el editor, lo cual escribirá \"hello world\" en la ventana de vista previa. También puedes mover las ventanas para cambiar su tamaño, y cambiar su orientación.",
"En la ventana de HTML, crea un elemento h1 con el texto \"Hola mundo\". Puedes arrastrar los bordes de las ventanas para cambiar su tamaño. También puedes pulsar el botón de \"Change View\" para cambiar la orientación de las ventanas.",
""
],
[
"https://i.imgur.com/G9KFQDL.gif",
"Un gif que muestra el proceso de agregar Bootstrap a tu proyecto.",
"Pulsa el engrane en la esquina superior izquierda de la ventana de CSS, luego ve hacia abajo hasta donde dice \"Quick add\" y elige Bootstrap. Ahora dale a tu elemento h1 la clase \"text-primary\" para cambiar su color y verificar que Bootstrap está activado.",
""
]
]
},
"pt-br": {
"title": "Prepare-se para nossos Projetos de Desenvolvimento Front End",
"description": [
[
"https://i.imgur.com/OAD6SJz.png",
"A imagem de um jogo Simon, um de nossos projetos front end.",
"Nossos projetos de Desenvolvimento front end vão dar a você a chance de aplicar as habilidades front end que você desenvolveu até esse ponto. Nós vamos usar um editor popular chamado CodePen que funciona direto no navegador.",
""
],
[
"https://i.imgur.com/WBetuBa.jpg",
"Um programador atravessando a tela de seu laptop com um soco em frustração.",
"Esses projetos são difíceis. A maioria dos campistas leva alguns dias para contruir cada projeto. Você vai ficar frustrado. Mas não desista. Isso fica mais fácil com a prática.",
""
],
[
"https://i.imgur.com/p2TpOQd.jpg",
"Um cachorro fofo pulando sobre um obstáculo, piscando e apontando sua pata a você.",
"Quando ficar travado, use a metodologia Ler-Buscar-Perguntar. Não se preocupe - você consegue.",
""
],
[
"https://i.imgur.com/G1saeDt.gif",
"Um gif mostrando com criar uma conta CodePen.",
"Para nossos projetos front end, usaremos um popular editor de código baseado em navegador chamado CodePen. Clique no botão \"Open link in new tab\" abaixo para abrir a página de resgistro do CodePen. Preencha o formulário e clique em \"Sign up\". <br><div class=\"small\">Nota: Se você já tem uma conta CodePen, você pode pular esse passo clicando em \"Open link in new tab\", fechando a nova aba que abrir, e clicando em \"go to my next step\". Nós removemos nosso botão \"skip step\" pois muitas pessoas iam simplesmente clicar nele repetidamente sem passar por esses passos importantes.</div>",
"https://codepen.io/accounts/signup/user/free"
],
[
"https://i.imgur.com/U4y9RJ1.gif",
"Um gif mostrando que você pode digitar \"hello world\" e será mostrado \"hello world\" na janela de visualização. Você também pode arrastar janelas para redimensioná-las e mudar a orientação das mesmas.",
"Na caixa do HTML, crie um elemento <code>h1</code> com o texto \"Hello World\". Você pode arrastar as bordas para redimensioná-las. Você pode também clicar no botão \"Change View\" e mudar a orientação das janelas.",
""
],
[
"https://i.imgur.com/G9KFQDL.gif",
"Um gif mostrando como adicionar o Bootstrap à sua pen.",
"Clique na engrenagem no canto superior esquerdo da caixa do CSS, então role para baixo até \"Quick add\" e escolha Bootstrap. Agora adicione ao seu elemento <code>h1</code> a classe <code>text-primary</code> para mudar sua cor e provar que o Bootstrap agora está disponível.",
""
],
[
"https://i.imgur.com/m0pWik2.gif",
"Um gif mostrando o processo de desativar o update automático da janela de visualização",
"Ao usar CodePen e Ajax, é uma boa idea desativar o update automático da janela de visualização para que as chamadas para as APIs não sejam feitas a todo momento. Muitas chamadas para API pode levar à bloqueios temporários e podem requerer períodos de esperar para que possam ser usadas novamente. <br> <div class=\"small\"> Para desativar o update automático da janela de visualização clique no botão \"Settings\" no topo da página, então clique na aba \"Behavior\". No final da página, desmarque \"AUTO UPDATE PREVIEW\". Agora clique em \"Run\" no topo da página para atualizar a janela de visualização e clique \"Save\".</div>",
""
]
]
},
"ru": {
"title": "Приготовьтесь к разработке фронтенд проектов",
"description": [
[
"https://i.imgur.com/OAD6SJz.png",
"Игра Саймона - один из фронтенд проектов.",
"Наши фронтенд проекты дадут вам шанс применить полученные к этому моменту знания по фронтенд разработке. Мы будем использовать популярный браузерный редактор кода - CodePen.",
""
],
[
"https://i.imgur.com/WBetuBa.jpg",
"Программист от отчаяния кулаком пробивает экран своего ноутбука.",
"Это трудные проекты. Разработка каждого занимает у большинства кэмперов несколько дней. У вас может возникнуть чувство отчаяния. Несмотря на это не сдавайтесь. С практикой этот процесс станет проще.",
""
],
[
"https://i.imgur.com/p2TpOQd.jpg",
"Милый пес, прыгающий через препятствие, указывает на вас лапой и подмигивает.",
"Если что-то не получается, воспользуйтесь Read-Search-Ask. Не волнуйтесь - вы сможете это сделать.",
""
],
[
"https://i.imgur.com/G1saeDt.gif",
"Гифка показывающая как зарегистрироваться на CodePen.",
"Для заданий по фронтенд разработке, мы будем использовать популярный браузерный редактор кода под названием CodePen. Откройте страницу регистрации на сайте CodePen, нажав на расположенную чуть ниже кнопку \"Open link in new tab\". Заполните форму и нажмите \"Sign up\". <br><div class=\"small\">Замечание: Если у вас уже есть аккаунт CodePen, то этот шаг можно пропустить: нажмите на кнопку \"Open link in new tab\", закройте появившуюся вкладку и затем кликните \"go to my next step\". Мы убрали кнопку \"skip step\", ввиду того что большинство людей просто нажимали бы ее несколько раз подряд и пропускали бы эти важные инструкции.</div>",
"https://codepen.io/accounts/signup/user/free"
],
[
"https://i.imgur.com/U4y9RJ1.gif",
"Гифка показывающая набор в редакторе заголовка с текстом \"hello world\", который затем отображается в окошке предпросмотра. А также указывающая как изменить размер окон редактора или поменять их расположение.",
"В окошке HTML создайте элемент h1 с текстом \"Hello World\". Ухватив края окон можно изменить их размер. А нажав на кнопку \"Change View\" поменять их расположение.",
""
],
[
"https://i.imgur.com/G9KFQDL.gif",
"Гифка показывающая как в CodePen добавить к проекту Bootstrap.",
"Нажмите на звездочку в левом верхнем углу окошка CSS, найдите внизу поле \"Quick add\" и выберите в нем Bootstrap. Добавьте к элементу h1 класс \"text-primary\", чтобы изменить его цвет и удостовериться, что Bootstrap подключен.",
""
]
]
}
}
},
{
"id": "bd7158d8c442eddfaeb5bd18",
"title": "Build a Tribute Page",

View File

@ -4,73 +4,6 @@
"time": "1 hour",
"helpRoom": "Help",
"challenges": [
{
"id": "587d78b0367417b2b2512b07",
"title": "Introduction to the Responsive Web Design Challenges",
"description": [
[
"",
"",
"Today, there are many types of devices that can access the web. They range from large desktop computers to small mobile phones. These devices have different screen sizes, resolutions, and processing power.",
""
],
[
"",
"",
"Responsive Web Design is an approach to designing web content that responds to the constraints of different devices. The page structure and CSS rules should be flexible to accommodate these differences.",
""
],
[
"",
"",
"In general, design the page's CSS to your target audience. If you expect most of your traffic to be from mobile users, take a 'mobile-first' approach. Then add conditional rules for larger screen sizes. If your visitors are desktop users, then design for larger screens with conditional rules for smaller sizes.",
""
],
[
"",
"",
"CSS gives you the tools to write different style rules, then apply them depending on the device displaying the page. This section will cover the basic ways to use CSS for Responsive Web Design.",
""
]
],
"releasedOn": "Feb 17, 2017",
"challengeSeed": [],
"tests": [],
"type": "waypoint",
"challengeType": 7,
"isRequired": false,
"translations": {
"pt-br": {
"title": "Introdução aos Desafios de Web Design Responsivo",
"description": [
[
"",
"",
"Hoje em dia há muitos dispositivos que podem acessar a web. Eles vão de computadores grandes de mesa até os pequenos celulares. Estes dispositivos tem diferentes tamanhos de tela, resoluções e capacidade de processamento.",
""
],
[
"",
"",
"O Web Design Responsivo é uma abordagem para o design the conteúdo para a web que responde às limitações dos diferentes dispositivos. A estrutura das páginas e as regras CSS devem ser flexíveis para acomodar estas diferenças.",
""
],
[
"",
"",
"Em geral, foque o design do CSS de sua página em seu público alvo. Se você espera que a maior parte dos seus usuários utilizem seus celulares, use uma abordagem 'mobile-first.' E então adicione regras condicionais para as telas maiores. Se seus usuários utilizam computadores de mesa, foque o design em telas maiores e utilize regras condicionais para tamanhos menores.",
""
],
[
"",
"",
"CSS lhe dá as ferramentas para escrever regras de estilo diversas, e então aplicá-las dependendo do dispositivo que estiver acessando a página. Esta seção cobrirá as maneiras básicas de utilizar CSS para o Web Design Responsivo.",
""
]
]
}
}
},
{
"id": "587d78b0367417b2b2512b08",
"title": "Create a Media Query",
@ -85,21 +18,15 @@
"<hr>",
"Add a media query, so that the <code>p</code> tag has a <code>font-size</code> of 10px when the device's height is less than or equal to 800px."
],
"challengeSeed": [
"<style>",
" p {",
" font-size: 20px;",
" }",
" ",
" /* Add media query below */",
" ",
"</style>",
" ",
"<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus quis tempus massa. Aenean erat nisl, gravida vel vestibulum cursus, interdum sit amet lectus. Sed sit amet quam nibh. Suspendisse quis tincidunt nulla. In hac habitasse platea dictumst. Ut sit amet pretium nisl. Vivamus vel mi sem. Aenean sit amet consectetur sem. Suspendisse pretium, purus et gravida consequat, nunc ligula ultricies diam, at aliquet velit libero a dui.</p>"
],
"tests": [
"assert($('p').css('font-size') == '10px', 'message: Your <code>p</code> element should have the <code>font-size</code> of 10px when the device <code>height</code> is less than or equal to 800px.');",
"assert(code.match(/@media\\s?\\(max-height:\\s*?800px\\)/g), 'message: Declare a <code>@media</code> query for devices with a <code>height</code> less than or equal to 800px.');"
{
"text": "Your <code>p</code> element should have the <code>font-size</code> of 10px when the device <code>height</code> is less than or equal to 800px.",
"testString": "assert($('p').css('font-size') == '10px', 'Your <code>p</code> element should have the <code>font-size</code> of 10px when the device <code>height</code> is less than or equal to 800px.');"
},
{
"text": "Declare a <code>@media</code> query for devices with a <code>height</code> less than or equal to 800px.",
"testString": "assert(code.match(/@media\\s?\\(max-height:\\s*?800px\\)/g), 'Declare a <code>@media</code> query for devices with a <code>height</code> less than or equal to 800px.');"
}
],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
@ -119,6 +46,27 @@
"Adicione uma media query para que o tag <code>p</code> tenha um <code>font-size</code> de 10px quando a altura do dispositivo for menor ou igual a 800px."
]
}
},
"files": {
"indexhtml": {
"key": "indexhtml",
"ext": "html",
"name": "index",
"contents": [
"<style>",
" p {",
" font-size: 20px;",
" }",
" ",
" /* Add media query below */",
" ",
"</style>",
" ",
"<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus quis tempus massa. Aenean erat nisl, gravida vel vestibulum cursus, interdum sit amet lectus. Sed sit amet quam nibh. Suspendisse quis tincidunt nulla. In hac habitasse platea dictumst. Ut sit amet pretium nisl. Vivamus vel mi sem. Aenean sit amet consectetur sem. Suspendisse pretium, purus et gravida consequat, nunc ligula ultricies diam, at aliquet velit libero a dui.</p>"
],
"head": [],
"tail": []
}
}
},
{
@ -133,17 +81,19 @@
"<hr>",
"Add style rules for the <code>img</code> tag to make it responsive to the size of its container. It should display as a block-level element, it should fit the full width of its container without stretching, and it should keep its original aspect ratio."
],
"challengeSeed": [
"<style>",
" ",
"</style>",
"",
"<img src=\"https://s3.amazonaws.com/freecodecamp/FCCStickerPack.jpg\" alt=\"freeCodeCamp stickers set\">"
],
"tests": [
"assert(code.match(/max-width:\\s*?100%;/g), 'message: Your <code>img</code> tag should have a <code>max-width</code> set to 100%.');",
"assert($('img').css('display') == 'block', 'message: Your <code>img</code> tag should have a <code>display</code> set to block.');",
"assert(code.match(/height:\\s*?auto;/g), 'message: Your <code>img</code> tag should have a <code>height</code> set to auto.');"
{
"text": "Your <code>img</code> tag should have a <code>max-width</code> set to 100%.",
"testString": "assert(code.match(/max-width:\\s*?100%;/g), 'Your <code>img</code> tag should have a <code>max-width</code> set to 100%.');"
},
{
"text": "Your <code>img</code> tag should have a <code>display</code> set to block.",
"testString": "assert($('img').css('display') == 'block', 'Your <code>img</code> tag should have a <code>display</code> set to block.');"
},
{
"text": "Your <code>img</code> tag should have a <code>height</code> set to auto.",
"testString": "assert(code.match(/height:\\s*?auto;/g), 'Your <code>img</code> tag should have a <code>height</code> set to auto.');"
}
],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
@ -163,6 +113,22 @@
"Adicione regras de estilo para a tag <code>img</code> para torná-la responsiva com relação ao tamanho do seu container. Ela deve ser exibida como um elemento de nível block, e deve preencher toda a largura de seu container sem esticar, mantendo as proporções originais."
]
}
},
"files": {
"indexhtml": {
"key": "indexhtml",
"ext": "html",
"name": "index",
"contents": [
"<style>",
" ",
"</style>",
"",
"<img src=\"https://s3.amazonaws.com/freecodecamp/FCCStickerPack.jpg\" alt=\"freeCodeCamp stickers set\">"
],
"head": [],
"tail": []
}
}
},
{
@ -175,16 +141,15 @@
"<hr>",
"Set the <code>width</code> and <code>height</code> of the <code>img</code> tag to half of their original values. In this case, both the original <code>height</code> and the original <code>width</code> are 200px."
],
"challengeSeed": [
"<style>",
" ",
"</style>",
"",
"<img src=\"https://s3.amazonaws.com/freecodecamp/FCCStickers-CamperBot200x200.jpg\" alt=\"freeCodeCamp sticker that says 'Because CamperBot Cares'\">"
],
"tests": [
"assert($('img').css('width') == '100px', 'message: Your <code>img</code> tag should have a <code>width</code> of 100 pixels.');",
"assert($('img').css('height') == '100px', 'message: Your <code>img</code> tag should have a <code>height</code> of 100 pixels.');"
{
"text": "Your <code>img</code> tag should have a <code>width</code> of 100 pixels.",
"testString": "assert($('img').css('width') == '100px', 'Your <code>img</code> tag should have a <code>width</code> of 100 pixels.');"
},
{
"text": "Your <code>img</code> tag should have a <code>height</code> of 100 pixels.",
"testString": "assert($('img').css('height') == '100px', 'Your <code>img</code> tag should have a <code>height</code> of 100 pixels.');"
}
],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
@ -202,6 +167,22 @@
"Configure os valores de <code>width</code> e <code>height</code> da tag <code>img</code> como metade do seu tamanho original. Nesse caso, o valor original de <code>height</code> e o valor original de <code>width</code> são de 200px."
]
}
},
"files": {
"indexhtml": {
"key": "indexhtml",
"ext": "html",
"name": "index",
"contents": [
"<style>",
" ",
"</style>",
"",
"<img src=\"https://s3.amazonaws.com/freecodecamp/FCCStickers-CamperBot200x200.jpg\" alt=\"freeCodeCamp sticker that says 'Because CamperBot Cares'\">"
],
"head": [],
"tail": []
}
}
},
{
@ -214,17 +195,15 @@
"<hr>",
"Set the <code>width</code> of the <code>h2</code> tag to 80% of the viewport's width and the <code>width</code> of the paragraph as 75% of the viewport's smaller dimension."
],
"challengeSeed": [
"<style>",
" ",
"</style>",
"",
"<h2>Importantus Ipsum</h2>",
"<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus quis tempus massa. Aenean erat nisl, gravida vel vestibulum cursus, interdum sit amet lectus. Sed sit amet quam nibh. Suspendisse quis tincidunt nulla. In hac habitasse platea dictumst. Ut sit amet pretium nisl. Vivamus vel mi sem. Aenean sit amet consectetur sem. Suspendisse pretium, purus et gravida consequat, nunc ligula ultricies diam, at aliquet velit libero a dui.</p>"
],
"tests": [
"assert(code.match(/h2\\s*?{\\s*?width:\\s*?80vw;\\s*?}/g), 'message: Your <code>h2</code> tag should have a <code>width</code> of 80vw.');",
"assert(code.match(/p\\s*?{\\s*?width:\\s*?75vmin;\\s*?}/g), 'message: Your <code>p</code> tag should have a <code>width</code> of 75vmin.');"
{
"text": "Your <code>h2</code> tag should have a <code>width</code> of 80vw.",
"testString": "assert(code.match(/h2\\s*?{\\s*?width:\\s*?80vw;\\s*?}/g), 'Your <code>h2</code> tag should have a <code>width</code> of 80vw.');"
},
{
"text": "Your <code>p</code> tag should have a <code>width</code> of 75vmin.",
"testString": "assert(code.match(/p\\s*?{\\s*?width:\\s*?75vmin;\\s*?}/g), 'Your <code>p</code> tag should have a <code>width</code> of 75vmin.');"
}
],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
@ -242,6 +221,23 @@
"Ajuste o <code>width</code> da tag <code>h2</code> para 80% da largura da janela de exibição e a <code>width</code> do parágrafo para 75% da menor dimensão da janela de exibição."
]
}
},
"files": {
"indexhtml": {
"key": "indexhtml",
"ext": "html",
"name": "index",
"contents": [
"<style>",
" ",
"</style>",
"",
"<h2>Importantus Ipsum</h2>",
"<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus quis tempus massa. Aenean erat nisl, gravida vel vestibulum cursus, interdum sit amet lectus. Sed sit amet quam nibh. Suspendisse quis tincidunt nulla. In hac habitasse platea dictumst. Ut sit amet pretium nisl. Vivamus vel mi sem. Aenean sit amet consectetur sem. Suspendisse pretium, purus et gravida consequat, nunc ligula ultricies diam, at aliquet velit libero a dui.</p>"
],
"head": [],
"tail": []
}
}
}
]

View File

@ -4,37 +4,6 @@
"time": "1 hour",
"helpRoom": "Help",
"challenges": [
{
"id": "587d7b83367417b2b2512b32",
"title": "Introduction to the Debugging Challenges",
"description": [
[
"",
"",
"Debugging is a valuable and (unfortunately) necessary tool for programmers. It follows the testing phase of checking if your code works as intended, and discovering it does not. Debugging is the process of finding exactly what isn't working and fixing it.",
""
],
[
"",
"",
"After spending time creating a brilliant block of code, it is tough realizing it may have errors. These issues generally come in three forms: 1) syntax errors that prevent a program from running, 2) runtime errors when code fails to execute or has unexpected behavior, and 3) semantic (or logical) errors when code doesn't do what it's meant to.<br><br>Modern code editors (and experience) can help identify syntax errors. Semantic and runtime errors are harder to find. They may cause your program to crash, make it run forever, or give incorrect output. Think of debugging as trying to understand why your code is behaving the way it is.<br><br>Example of a syntax error - often detected by the code editor:<br><br><blockquote>funtion willNotWork( {<br>&nbsp;&nbsp;console.log(\"Yuck\");<br>}<br>// \"function\" keyword is misspelled and there's a missing parenthesis</blockquote><br><br>Here's an example of a runtime error - often detected while the program executes:<br><br><blockquote>function loopy() {<br>&nbsp;&nbsp;while(true) {<br>&nbsp;&nbsp;&nbsp;&nbsp;console.log(\"Hello, world!\");<br>&nbsp;&nbsp;}<br>}<br>// Calling loopy starts an infinite loop, which may crash your browser</blockquote><br><br>Example of a semantic error - often detected after testing code output:<br><br><blockquote>function calcAreaOfRect(w, h) {<br>&nbsp;&nbsp;return w + h; // This should be w * h<br>}<br>let myRectArea = calcAreaOfRect(2, 3);<br>// Correct syntax and the program executes, but this gives the wrong answer</blockquote>",
""
],
[
"",
"",
"Debugging is frustrating, but it helps to develop (and follow) a step-by-step approach to review your code. This means checking the intermediate values and types of variables to see if they are what they should be. You can start with a simple process of elimination.<br><br>For example, if function A works and returns what it's supposed to, then function B may have the issue. Or start checking values in a block of code from the middle to try to cut the search space in half. A problem in one spot indicates a bug in the first half of the code. If not, it's likely in the second.<br><br>This section will cover a couple helpful tools to find bugs, and some of the common forms they take. Fortunately, debugging is a learnable skill that just requires a little patience and practice to master.",
""
]
],
"releasedOn": "Feb 17, 2017",
"challengeSeed": [],
"tests": [],
"type": "waypoint",
"challengeType": 7,
"isRequired": false,
"translations": {}
},
{
"id": "587d7b83367417b2b2512b33",
"title": "Use the JavaScript Console to Check the Value of a Variable",
@ -47,25 +16,37 @@
"<hr>",
"Use the <code>console.log()</code> method to print the value of the variable <code>a</code> where noted in the code."
],
"challengeSeed": [
"let a = 5;",
"let b = 1;",
"a++;",
"// Add your code below this line",
"",
"",
"let sumAB = a + b;",
"console.log(sumAB);"
],
"tests": [
"assert(code.match(/console\\.log\\(a\\)/g), 'message: Your code should use <code>console.log()</code> to check the value of the variable <code>a</code>.');"
{
"text": "Your code should use <code>console.log()</code> to check the value of the variable <code>a</code>.",
"testString": "assert(code.match(/console\\.log\\(a\\)/g), 'Your code should use <code>console.log()</code> to check the value of the variable <code>a</code>.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 1,
"translations": {}
"translations": {},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"let a = 5;",
"let b = 1;",
"a++;",
"// Add your code below this line",
"",
"",
"let sumAB = a + b;",
"console.log(sumAB);"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7b83367417b2b2512b37",
@ -81,31 +62,49 @@
"Use <code>console.log()</code> to print the variables in the code where indicated.",
""
],
"challengeSeed": [
"// Open your browser console",
"let outputTwo = \"This will print to the browser console 2 times\";",
"// Use console.log() to print the outputTwo variable",
"",
"",
"let outputOne = \"Try to get this to log only once to the browser console\";",
"// Use console.clear() in the next line to print the outputOne only once",
"",
"",
"// Use console.log() to print the outputOne variable",
"",
""
],
"tests": [
"assert(code.match(/console\\.log\\(outputTwo\\)/g), 'message: Use <code>console.log()</code> to print the <code>outputTwice</code> variable. In your Browser Console this should print out the value of the variable two times.');",
"assert(code.match(/console\\.log\\(outputOne\\)/g), 'message: Use <code>console.log()</code> to print the <code>outputOne</code> variable.');",
"assert(code.match(/(?<!\\/\\/ Use )console\\.clear\\(\\)/g), 'message: Use <code>console.clear()</code> to modify your output so that <code>outputOne</code> variable only outputs once.');"
{
"text": "Use <code>console.log()</code> to print the <code>outputTwice</code> variable. In your Browser Console this should print out the value of the variable two times.",
"testString": "assert(code.match(/console\\.log\\(outputTwo\\)/g), 'Use <code>console.log()</code> to print the <code>outputTwice</code> variable. In your Browser Console this should print out the value of the variable two times.');"
},
{
"text": "Use <code>console.log()</code> to print the <code>outputOne</code> variable.",
"testString": "assert(code.match(/console\\.log\\(outputOne\\)/g), 'Use <code>console.log()</code> to print the <code>outputOne</code> variable.');"
},
{
"text": "Use <code>console.clear()</code> to modify your output so that <code>outputOne</code> variable only outputs once.",
"testString": "assert(code.match(/(?<!\\/\\/ Use )console\\.clear\\(\\)/g), 'Use <code>console.clear()</code> to modify your output so that <code>outputOne</code> variable only outputs once.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 1,
"translations": {}
"translations": {},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"// Open your browser console",
"let outputTwo = \"This will print to the browser console 2 times\";",
"// Use console.log() to print the outputTwo variable",
"",
"",
"let outputOne = \"Try to get this to log only once to the browser console\";",
"// Use console.clear() in the next line to print the outputOne only once",
"",
"",
"// Use console.log() to print the outputOne variable",
"",
""
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7b84367417b2b2512b34",
@ -118,24 +117,42 @@
"<hr>",
"Add two <code>console.log()</code> statements to check the <code>typeof</code> each of the two variables <code>seven</code> and <code>three</code> in the code."
],
"challengeSeed": [
"let seven = 7;",
"let three = \"3\";",
"console.log(seven + three);",
"// Add your code below this line",
""
],
"tests": [
"assert(code.match(/console\\.log\\(typeof[\\( ].*\\)?\\)/g).length == 2, 'message: Your code should use <code>typeof</code> in two <code>console.log()</code> statements to check the type of the variables.');",
"assert(code.match(/typeof[\\( ]seven\\)?/g), 'message: Your code should use <code>typeof</code> to check the type of the variable <code>seven</code>.');",
"assert(code.match(/typeof[\\( ]three\\)?/g), 'message: Your code should use <code>typeof</code> to check the type of the variable <code>three</code>.');"
{
"text": "Your code should use <code>typeof</code> in two <code>console.log()</code> statements to check the type of the variables.",
"testString": "assert(code.match(/console\\.log\\(typeof[\\( ].*\\)?\\)/g).length == 2, 'Your code should use <code>typeof</code> in two <code>console.log()</code> statements to check the type of the variables.');"
},
{
"text": "Your code should use <code>typeof</code> to check the type of the variable <code>seven</code>.",
"testString": "assert(code.match(/typeof[\\( ]seven\\)?/g), 'Your code should use <code>typeof</code> to check the type of the variable <code>seven</code>.');"
},
{
"text": "Your code should use <code>typeof</code> to check the type of the variable <code>three</code>.",
"testString": "assert(code.match(/typeof[\\( ]three\\)?/g), 'Your code should use <code>typeof</code> to check the type of the variable <code>three</code>.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 1,
"translations": {}
"translations": {},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"let seven = 7;",
"let three = \"3\";",
"console.log(seven + three);",
"// Add your code below this line",
""
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7b84367417b2b2512b35",
@ -146,25 +163,49 @@
"<hr>",
"Fix the two spelling errors in the code so the <code>netWorkingCapital</code> calculation works."
],
"challengeSeed": [
"let receivables = 10;",
"let payables = 8;",
"let netWorkingCapital = recievables - payable;",
"console.log(`Net working capital is: ${netWorkingCapital}`);"
],
"tests": [
"assert(netWorkingCapital === 2, 'message: Check the spelling of the two variables used in the netWorkingCapital calculation, the console output should show that \"Net working capital is: 2\".');",
"assert(!code.match(/recievables/g), 'message: There should be no instances of mis-spelled variables in the code.');",
"assert(code.match(/receivables/g).length == 2, 'message: The <code>receivables</code> variable should be declared and used properly in the code.');",
"assert(!code.match(/payable;/g), 'message: There should be no instances of mis-spelled variables in the code.');",
"assert(code.match(/payables/g).length == 2, 'message: The <code>payables</code> variable should be declared and used properly in the code.');"
{
"text": "Check the spelling of the two variables used in the netWorkingCapital calculation, the console output should show that \"Net working capital is: 2\".",
"testString": "assert(netWorkingCapital === 2, 'Check the spelling of the two variables used in the netWorkingCapital calculation, the console output should show that \"Net working capital is: 2\".');"
},
{
"text": "There should be no instances of mis-spelled variables in the code.",
"testString": "assert(!code.match(/recievables/g), 'There should be no instances of mis-spelled variables in the code.');"
},
{
"text": "The <code>receivables</code> variable should be declared and used properly in the code.",
"testString": "assert(code.match(/receivables/g).length == 2, 'The <code>receivables</code> variable should be declared and used properly in the code.');"
},
{
"text": "There should be no instances of mis-spelled variables in the code.",
"testString": "assert(!code.match(/payable;/g), 'There should be no instances of mis-spelled variables in the code.');"
},
{
"text": "The <code>payables</code> variable should be declared and used properly in the code.",
"testString": "assert(code.match(/payables/g).length == 2, 'The <code>payables</code> variable should be declared and used properly in the code.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 1,
"translations": {}
"translations": {},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"let receivables = 10;",
"let payables = 8;",
"let netWorkingCapital = recievables - payable;",
"console.log(`Net working capital is: ${netWorkingCapital}`);"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7b84367417b2b2512b36",
@ -175,21 +216,36 @@
"<hr>",
"Fix the two pair errors in the code."
],
"challengeSeed": [
"let myArray = [1, 2, 3;",
"let arraySum = myArray.reduce((previous, current => previous + current);",
"console.log(`Sum of array values is: ${arraySum}`);"
],
"tests": [
"assert(code.match(/myArray\\s*?=\\s*?\\[\\s*?1\\s*?,\\s*?2\\s*?,\\s*?3\\s*?\\];/g), 'message: Your code should fix the missing piece of the array.');",
"assert(arraySum === 6, 'message: Your code should fix the missing piece of the <code>.reduce()</code> method. The console output should show that \"Sum of array values is: 6\".');"
{
"text": "Your code should fix the missing piece of the array.",
"testString": "assert(code.match(/myArray\\s*?=\\s*?\\[\\s*?1\\s*?,\\s*?2\\s*?,\\s*?3\\s*?\\];/g), 'Your code should fix the missing piece of the array.');"
},
{
"text": "Your code should fix the missing piece of the <code>.reduce()</code> method. The console output should show that \"Sum of array values is: 6\".",
"testString": "assert(arraySum === 6, 'Your code should fix the missing piece of the <code>.reduce()</code> method. The console output should show that \"Sum of array values is: 6\".');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 1,
"translations": {}
"translations": {},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"let myArray = [1, 2, 3;",
"let arraySum = myArray.reduce((previous, current => previous + current);",
"console.log(`Sum of array values is: ${arraySum}`);"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7b84367417b2b2512b37",
@ -204,20 +260,35 @@
"<hr>",
"Fix the string so it either uses different quotes for the <code>href</code> value, or escape the existing ones. Keep the double quote marks around the entire string."
],
"challengeSeed": [
"let innerHtml = \"<p>Click here to <a href=\"#Home\">return home</a></p>\";",
"console.log(innerHtml);"
],
"tests": [
"assert(code.match(/<a href=\\s*?('|\\\\\")#Home\\1\\s*?>/g), 'message: Your code should fix the quotes around the <code>href</code> value \"#Home\" by either changing or escaping them.');",
"assert(code.match(/\"<p>.*?<\\/p>\";/g), 'message: Your code should keep the double quotes around the entire string.');"
{
"text": "Your code should fix the quotes around the <code>href</code> value \"#Home\" by either changing or escaping them.",
"testString": "assert(code.match(/<a href=\\s*?('|\\\\\")#Home\\1\\s*?>/g), 'Your code should fix the quotes around the <code>href</code> value \"#Home\" by either changing or escaping them.');"
},
{
"text": "Your code should keep the double quotes around the entire string.",
"testString": "assert(code.match(/\"<p>.*?<\\/p>\";/g), 'Your code should keep the double quotes around the entire string.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 1,
"translations": {}
"translations": {},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"let innerHtml = \"<p>Click here to <a href=\"#Home\">return home</a></p>\";",
"console.log(innerHtml);"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7b85367417b2b2512b38",
@ -231,29 +302,44 @@
"<hr>",
"Fix the condition so the program runs the right branch, and the appropriate value is assigned to <code>result</code>."
],
"challengeSeed": [
"let x = 7;",
"let y = 9;",
"let result = \"to come\";",
"",
"if(x = y) {",
" result = \"Equal!\";",
"} else {",
" result = \"Not equal!\";",
"}",
"",
"console.log(result);"
],
"tests": [
"assert(result == \"Not equal!\", 'message: Your code should fix the condition so it checks for equality, instead of using assignment.');",
"assert(code.match(/x\\s*?===?\\s*?y/g), 'message: The condition can use either <code>==</code> or <code>===</code> to test for equality.');"
{
"text": "Your code should fix the condition so it checks for equality, instead of using assignment.",
"testString": "assert(result == \"Not equal!\", 'Your code should fix the condition so it checks for equality, instead of using assignment.');"
},
{
"text": "The condition can use either <code>==</code> or <code>===</code> to test for equality.",
"testString": "assert(code.match(/x\\s*?===?\\s*?y/g), 'The condition can use either <code>==</code> or <code>===</code> to test for equality.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 1,
"translations": {}
"translations": {},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"let x = 7;",
"let y = 9;",
"let result = \"to come\";",
"",
"if(x = y) {",
" result = \"Equal!\";",
"} else {",
" result = \"Not equal!\";",
"}",
"",
"console.log(result);"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7b85367417b2b2512b39",
@ -265,26 +351,41 @@
"<hr>",
"Fix the code so the variable <code>result</code> is set to the value returned from calling the function <code>getNine</code>."
],
"challengeSeed": [
"function getNine() {",
" let x = 6;",
" let y = 3;",
" return x + y;",
"}",
"",
"let result = getNine;",
"console.log(result);"
],
"tests": [
"assert(result == 9, 'message: Your code should fix the variable <code>result</code> so it is set to the number that the function <code>getNine</code> returns.');",
"assert(code.match(/getNine\\(\\)/g).length == 2, 'message: Your code should call the <code>getNine</code> function.');"
{
"text": "Your code should fix the variable <code>result</code> so it is set to the number that the function <code>getNine</code> returns.",
"testString": "assert(result == 9, 'Your code should fix the variable <code>result</code> so it is set to the number that the function <code>getNine</code> returns.');"
},
{
"text": "Your code should call the <code>getNine</code> function.",
"testString": "assert(code.match(/getNine\\(\\)/g).length == 2, 'Your code should call the <code>getNine</code> function.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 1,
"translations": {}
"translations": {},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function getNine() {",
" let x = 6;",
" let y = 3;",
" return x + y;",
"}",
"",
"let result = getNine;",
"console.log(result);"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7b85367417b2b2512b3a",
@ -294,26 +395,41 @@
"<hr>",
"The function <code>raiseToPower</code> raises a base to an exponent. Unfortunately, it's not called properly - fix the code so the value of <code>power</code> is the expected 8."
],
"challengeSeed": [
"function raiseToPower(b, e) {",
" return Math.pow(b, e);",
"}",
"",
"let base = 2;",
"let exp = 3;",
"let power = raiseToPower(exp, base);",
"console.log(power);"
],
"tests": [
"assert(power == 8, 'message: Your code should fix the variable <code>power</code> so it equals 2 raised to the 3rd power, not 3 raised to the 2nd power.');",
"assert(code.match(/raiseToPower\\(\\s*?base\\s*?,\\s*?exp\\s*?\\);/g), 'message: Your code should use the correct order of the arguments for the <code>raiseToPower</code> function call.');"
{
"text": "Your code should fix the variable <code>power</code> so it equals 2 raised to the 3rd power, not 3 raised to the 2nd power.",
"testString": "assert(power == 8, 'Your code should fix the variable <code>power</code> so it equals 2 raised to the 3rd power, not 3 raised to the 2nd power.');"
},
{
"text": "Your code should use the correct order of the arguments for the <code>raiseToPower</code> function call.",
"testString": "assert(code.match(/raiseToPower\\(\\s*?base\\s*?,\\s*?exp\\s*?\\);/g), 'Your code should use the correct order of the arguments for the <code>raiseToPower</code> function call.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 1,
"translations": {}
"translations": {},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function raiseToPower(b, e) {",
" return Math.pow(b, e);",
"}",
"",
"let base = 2;",
"let exp = 3;",
"let power = raiseToPower(exp, base);",
"console.log(power);"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7b86367417b2b2512b3b",
@ -325,31 +441,52 @@
"<hr>",
"Fix the two indexing errors in the following function so all the numbers 1 through 5 are printed to the console."
],
"challengeSeed": [
"function countToFive() {",
" let firstFive = \"12345\";",
" let len = firstFive.length;",
" // Fix the line below",
" for (let i = 1; i <= len; i++) {",
" // Do not alter code below this line",
" console.log(firstFive[i]);",
" }",
"}",
"",
"countToFive();"
],
"tests": [
"assert(code.match(/i\\s*?=\\s*?0\\s*?;/g).length == 1, 'message: Your code should set the initial condition of the loop so it starts at the first index.');",
"assert(!code.match(/i\\s?=\\s*?1\\s*?;/g), 'message: Your code should fix the initial condition of the loop so that the index starts at 0.');",
"assert(code.match(/i\\s*?<\\s*?len\\s*?;/g).length == 1, 'message: Your code should set the terminal condition of the loop so it stops at the last index.');",
"assert(!code.match(/i\\s*?<=\\s*?len;/g), 'message: Your code should fix the terminal condition of the loop so that it stops at 1 before the length.');"
{
"text": "Your code should set the initial condition of the loop so it starts at the first index.",
"testString": "assert(code.match(/i\\s*?=\\s*?0\\s*?;/g).length == 1, 'Your code should set the initial condition of the loop so it starts at the first index.');"
},
{
"text": "Your code should fix the initial condition of the loop so that the index starts at 0.",
"testString": "assert(!code.match(/i\\s?=\\s*?1\\s*?;/g), 'Your code should fix the initial condition of the loop so that the index starts at 0.');"
},
{
"text": "Your code should set the terminal condition of the loop so it stops at the last index.",
"testString": "assert(code.match(/i\\s*?<\\s*?len\\s*?;/g).length == 1, 'Your code should set the terminal condition of the loop so it stops at the last index.');"
},
{
"text": "Your code should fix the terminal condition of the loop so that it stops at 1 before the length.",
"testString": "assert(!code.match(/i\\s*?<=\\s*?len;/g), 'Your code should fix the terminal condition of the loop so that it stops at 1 before the length.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 1,
"translations": {}
"translations": {},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function countToFive() {",
" let firstFive = \"12345\";",
" let len = firstFive.length;",
" // Fix the line below",
" for (let i = 1; i <= len; i++) {",
" // Do not alter code below this line",
" console.log(firstFive[i]);",
" }",
"}",
"",
"countToFive();"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7b86367417b2b2512b3c",
@ -360,38 +497,56 @@
"<hr>",
"The following function is supposed to create a two-dimensional array with <code>m</code> rows and <code>n</code> columns of zeroes. Unfortunately, it's not producing the expected output because the <code>row</code> variable isn't being reinitialized (set back to an empty array) in the outer loop. Fix the code so it returns a correct 3x2 array of zeroes, which looks like <code>[[0, 0], [0, 0], [0, 0]]</code>."
],
"challengeSeed": [
"function zeroArray(m, n) {",
" // Creates a 2-D array with m rows and n columns of zeroes",
" let newArray = [];",
" let row = [];",
" for (let i = 0; i < m; i++) {",
" // Adds the m-th row into newArray",
" ",
" for (let j = 0; j < n; j++) {",
" // Pushes n zeroes into the current row to create the columns",
" row.push(0);",
" }",
" // Pushes the current row, which now has n zeroes in it, to the array",
" newArray.push(row);",
" }",
" return newArray;",
"}",
"",
"let matrix = zeroArray(3, 2);",
"console.log(matrix);"
],
"tests": [
"assert(JSON.stringify(matrix) == \"[[0,0],[0,0],[0,0]]\", 'message: Your code should set the <code>matrix</code> variable to an array holding 3 rows of 2 columns of zeroes each.');",
"assert(matrix.length == 3, 'message: The <code>matrix</code> variable should have 3 rows.');",
"assert(matrix[0].length == 2 && matrix[1].length === 2 && matrix[2].length === 2, 'message: The <code>matrix</code> variable should have 2 columns in each row.');"
{
"text": "Your code should set the <code>matrix</code> variable to an array holding 3 rows of 2 columns of zeroes each.",
"testString": "assert(JSON.stringify(matrix) == \"[[0,0],[0,0],[0,0]]\", 'Your code should set the <code>matrix</code> variable to an array holding 3 rows of 2 columns of zeroes each.');"
},
{
"text": "The <code>matrix</code> variable should have 3 rows.",
"testString": "assert(matrix.length == 3, 'The <code>matrix</code> variable should have 3 rows.');"
},
{
"text": "The <code>matrix</code> variable should have 2 columns in each row.",
"testString": "assert(matrix[0].length == 2 && matrix[1].length === 2 && matrix[2].length === 2, 'The <code>matrix</code> variable should have 2 columns in each row.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 1,
"translations": {}
"translations": {},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function zeroArray(m, n) {",
" // Creates a 2-D array with m rows and n columns of zeroes",
" let newArray = [];",
" let row = [];",
" for (let i = 0; i < m; i++) {",
" // Adds the m-th row into newArray",
" ",
" for (let j = 0; j < n; j++) {",
" // Pushes n zeroes into the current row to create the columns",
" row.push(0);",
" }",
" // Pushes the current row, which now has n zeroes in it, to the array",
" newArray.push(row);",
" }",
" return newArray;",
"}",
"",
"let matrix = zeroArray(3, 2);",
"console.log(matrix);"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7b86367417b2b2512b3d",
@ -404,23 +559,38 @@
"<hr>",
"The <code>myFunc()</code> function contains an infinite loop because the terminal condition <code>i != 4</code> will never evaluate to <code>false</code> (and break the looping) - <code>i</code> will increment by 2 each pass, and jump right over 4 since <code>i</code> is odd to start. Fix the comparison operator in the terminal condition so the loop only runs for <code>i</code> less than or equal to 4."
],
"challengeSeed": [
"function myFunc() {",
" for (let i = 1; i != 4; i += 2) {",
" console.log(\"Still going!\");",
" }",
"}"
],
"tests": [
"assert(code.match(/i\\s*?<=\\s*?4;/g).length == 1, 'message: Your code should change the comparison operator in the terminal condition (the middle part) of the <code>for</code> loop.');",
"assert(!code.match(/i\\s*?!=\\s*?4;/g), 'message: Your code should fix the comparison operator in the terminal condition of the loop.');"
{
"text": "Your code should change the comparison operator in the terminal condition (the middle part) of the <code>for</code> loop.",
"testString": "assert(code.match(/i\\s*?<=\\s*?4;/g).length == 1, 'Your code should change the comparison operator in the terminal condition (the middle part) of the <code>for</code> loop.');"
},
{
"text": "Your code should fix the comparison operator in the terminal condition of the loop.",
"testString": "assert(!code.match(/i\\s*?!=\\s*?4;/g), 'Your code should fix the comparison operator in the terminal condition of the loop.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 1,
"translations": {}
"translations": {},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function myFunc() {",
" for (let i = 1; i != 4; i += 2) {",
" console.log(\"Still going!\");",
" }",
"}"
],
"head": [],
"tail": []
}
}
}
]
}

View File

@ -15,30 +15,59 @@
"We'll also pass strings with special symbols, such as <code>\"2A3*3a2\"</code>, <code>\"2A3 3a2\"</code>, and <code>\"2_A3*3#A2\"</code>.",
"Remember to use <a href=\"http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514\" target=\"_blank\">Read-Search-Ask</a> if you get stuck. Write your own code."
],
"challengeSeed": [
"function palindrome(str) {",
" // Good luck!",
" return true;",
"}",
"",
"",
"",
"palindrome(\"eye\");"
],
"tests": [
"assert(typeof palindrome(\"eye\") === \"boolean\", 'message: <code>palindrome(\"eye\")</code> should return a boolean.');",
"assert(palindrome(\"eye\") === true, 'message: <code>palindrome(\"eye\")</code> should return true.');",
"assert(palindrome(\"_eye\") === true, 'message: <code>palindrome(\"_eye\")</code> should return true.');",
"assert(palindrome(\"race car\") === true, 'message: <code>palindrome(\"race car\")</code> should return true.');",
"assert(palindrome(\"not a palindrome\") === false, 'message: <code>palindrome(\"not a palindrome\")</code> should return false.');",
"assert(palindrome(\"A man, a plan, a canal. Panama\") === true, 'message: <code>palindrome(\"A man, a plan, a canal. Panama\")</code> should return true.');",
"assert(palindrome(\"never odd or even\") === true, 'message: <code>palindrome(\"never odd or even\")</code> should return true.');",
"assert(palindrome(\"nope\") === false, 'message: <code>palindrome(\"nope\")</code> should return false.');",
"assert(palindrome(\"almostomla\") === false, 'message: <code>palindrome(\"almostomla\")</code> should return false.');",
"assert(palindrome(\"My age is 0, 0 si ega ym.\") === true, 'message: <code>palindrome(\"My age is 0, 0 si ega ym.\")</code> should return true.');",
"assert(palindrome(\"1 eye for of 1 eye.\") === false, 'message: <code>palindrome(\"1 eye for of 1 eye.\")</code> should return false.');",
"assert(palindrome(\"0_0 (: /-\\ :) 0-0\") === true, 'message: <code>palindrome(\"0_0 (: /-\\ :) 0-0\")</code> should return true.');",
"assert(palindrome(\"five|\\_/|four\") === false, 'message: <code>palindrome(\"five|\\_/|four\")</code> should return false.');"
{
"text": "<code>palindrome(\"eye\")</code> should return a boolean.",
"testString": "assert(typeof palindrome(\"eye\") === \"boolean\", '<code>palindrome(\"eye\")</code> should return a boolean.');"
},
{
"text": "<code>palindrome(\"eye\")</code> should return true.",
"testString": "assert(palindrome(\"eye\") === true, '<code>palindrome(\"eye\")</code> should return true.');"
},
{
"text": "<code>palindrome(\"_eye\")</code> should return true.",
"testString": "assert(palindrome(\"_eye\") === true, '<code>palindrome(\"_eye\")</code> should return true.');"
},
{
"text": "<code>palindrome(\"race car\")</code> should return true.",
"testString": "assert(palindrome(\"race car\") === true, '<code>palindrome(\"race car\")</code> should return true.');"
},
{
"text": "<code>palindrome(\"not a palindrome\")</code> should return false.",
"testString": "assert(palindrome(\"not a palindrome\") === false, '<code>palindrome(\"not a palindrome\")</code> should return false.');"
},
{
"text": "<code>palindrome(\"A man, a plan, a canal. Panama\")</code> should return true.",
"testString": "assert(palindrome(\"A man, a plan, a canal. Panama\") === true, '<code>palindrome(\"A man, a plan, a canal. Panama\")</code> should return true.');"
},
{
"text": "<code>palindrome(\"never odd or even\")</code> should return true.",
"testString": "assert(palindrome(\"never odd or even\") === true, '<code>palindrome(\"never odd or even\")</code> should return true.');"
},
{
"text": "<code>palindrome(\"nope\")</code> should return false.",
"testString": "assert(palindrome(\"nope\") === false, '<code>palindrome(\"nope\")</code> should return false.');"
},
{
"text": "<code>palindrome(\"almostomla\")</code> should return false.",
"testString": "assert(palindrome(\"almostomla\") === false, '<code>palindrome(\"almostomla\")</code> should return false.');"
},
{
"text": "<code>palindrome(\"My age is 0, 0 si ega ym.\")</code> should return true.",
"testString": "assert(palindrome(\"My age is 0, 0 si ega ym.\") === true, '<code>palindrome(\"My age is 0, 0 si ega ym.\")</code> should return true.');"
},
{
"text": "<code>palindrome(\"1 eye for of 1 eye.\")</code> should return false.",
"testString": "assert(palindrome(\"1 eye for of 1 eye.\") === false, '<code>palindrome(\"1 eye for of 1 eye.\")</code> should return false.');"
},
{
"text": "<code>palindrome(\"0_0 (: /-\\ :) 0-0\")</code> should return true.",
"testString": "assert(palindrome(\"0_0 (: /-\\ :) 0-0\") === true, '<code>palindrome(\"0_0 (: /-\\ :) 0-0\")</code> should return true.');"
},
{
"text": "<code>palindrome(\"five|\\_/|four\")</code> should return false.",
"testString": "assert(palindrome(\"five|\\_/|four\") === false, '<code>palindrome(\"five|\\_/|four\")</code> should return false.');"
}
],
"type": "bonfire",
"isRequired": true,
@ -73,6 +102,25 @@
"Lembre-se de usar <a href=\"http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514\" target=\"_blank\">Ler-Pesquisar-Perguntar</a> se você ficar travado. Escreva seu próprio código."
]
}
},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function palindrome(str) {",
" // Good luck!",
" return true;",
"}",
"",
"",
"",
"palindrome(\"eye\");"
],
"head": [],
"tail": []
}
}
},
{
@ -83,43 +131,114 @@
"All <a href=\"http://www.mathsisfun.com/roman-numerals.html\" target=\"_blank\">roman numerals</a> answers should be provided in upper-case.",
"Remember to use <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
],
"challengeSeed": [
"function convertToRoman(num) {",
" return num;",
"}",
"",
"convertToRoman(36);"
],
"solutions": [
"function convertToRoman(num) {\n var ref = [['M', 1000], ['CM', 900], ['D', 500], ['CD', 400], ['C', 100], ['XC', 90], ['L', 50], ['XL', 40], ['X', 10], ['IX', 9], ['V', 5], ['IV', 4], ['I', 1]];\n var res = [];\n ref.forEach(function(p) {\n while (num >= p[1]) {\n res.push(p[0]);\n num -= p[1];\n }\n });\n return res.join('');\n}"
],
"tests": [
"assert.deepEqual(convertToRoman(2), \"II\", 'message: <code>convertToRoman(2)</code> should return \"II\".');",
"assert.deepEqual(convertToRoman(3), \"III\", 'message: <code>convertToRoman(3)</code> should return \"III\".');",
"assert.deepEqual(convertToRoman(4), \"IV\", 'message: <code>convertToRoman(4)</code> should return \"IV\".');",
"assert.deepEqual(convertToRoman(5), \"V\", 'message: <code>convertToRoman(5)</code> should return \"V\".');",
"assert.deepEqual(convertToRoman(9), \"IX\", 'message: <code>convertToRoman(9)</code> should return \"IX\".');",
"assert.deepEqual(convertToRoman(12), \"XII\", 'message: <code>convertToRoman(12)</code> should return \"XII\".');",
"assert.deepEqual(convertToRoman(16), \"XVI\", 'message: <code>convertToRoman(16)</code> should return \"XVI\".');",
"assert.deepEqual(convertToRoman(29), \"XXIX\", 'message: <code>convertToRoman(29)</code> should return \"XXIX\".');",
"assert.deepEqual(convertToRoman(44), \"XLIV\", 'message: <code>convertToRoman(44)</code> should return \"XLIV\".');",
"assert.deepEqual(convertToRoman(45), \"XLV\", 'message: <code>convertToRoman(45)</code> should return \"XLV\"');",
"assert.deepEqual(convertToRoman(68), \"LXVIII\", 'message: <code>convertToRoman(68)</code> should return \"LXVIII\"');",
"assert.deepEqual(convertToRoman(83), \"LXXXIII\", 'message: <code>convertToRoman(83)</code> should return \"LXXXIII\"');",
"assert.deepEqual(convertToRoman(97), \"XCVII\", 'message: <code>convertToRoman(97)</code> should return \"XCVII\"');",
"assert.deepEqual(convertToRoman(99), \"XCIX\", 'message: <code>convertToRoman(99)</code> should return \"XCIX\"');",
"assert.deepEqual(convertToRoman(400), \"CD\", 'message: <code>convertToRoman(400)</code> should return \"CD\"');",
"assert.deepEqual(convertToRoman(500), \"D\", 'message: <code>convertToRoman(500)</code> should return \"D\"');",
"assert.deepEqual(convertToRoman(501), \"DI\", 'message: <code>convertToRoman(501)</code> should return \"DI\"');",
"assert.deepEqual(convertToRoman(649), \"DCXLIX\", 'message: <code>convertToRoman(649)</code> should return \"DCXLIX\"');",
"assert.deepEqual(convertToRoman(798), \"DCCXCVIII\", 'message: <code>convertToRoman(798)</code> should return \"DCCXCVIII\"');",
"assert.deepEqual(convertToRoman(891), \"DCCCXCI\", 'message: <code>convertToRoman(891)</code> should return \"DCCCXCI\"');",
"assert.deepEqual(convertToRoman(1000), \"M\", 'message: <code>convertToRoman(1000)</code> should return \"M\"');",
"assert.deepEqual(convertToRoman(1004), \"MIV\", 'message: <code>convertToRoman(1004)</code> should return \"MIV\"');",
"assert.deepEqual(convertToRoman(1006), \"MVI\", 'message: <code>convertToRoman(1006)</code> should return \"MVI\"');",
"assert.deepEqual(convertToRoman(1023), \"MXXIII\", 'message: <code>convertToRoman(1023)</code> should return \"MXXIII\"');",
"assert.deepEqual(convertToRoman(2014), \"MMXIV\", 'message: <code>convertToRoman(2014)</code> should return \"MMXIV\"');",
"assert.deepEqual(convertToRoman(3999), \"MMMCMXCIX\", 'message: <code>convertToRoman(3999)</code> should return \"MMMCMXCIX\"');"
{
"text": "<code>convertToRoman(2)</code> should return \"II\".",
"testString": "assert.deepEqual(convertToRoman(2), \"II\", '<code>convertToRoman(2)</code> should return \"II\".');"
},
{
"text": "<code>convertToRoman(3)</code> should return \"III\".",
"testString": "assert.deepEqual(convertToRoman(3), \"III\", '<code>convertToRoman(3)</code> should return \"III\".');"
},
{
"text": "<code>convertToRoman(4)</code> should return \"IV\".",
"testString": "assert.deepEqual(convertToRoman(4), \"IV\", '<code>convertToRoman(4)</code> should return \"IV\".');"
},
{
"text": "<code>convertToRoman(5)</code> should return \"V\".",
"testString": "assert.deepEqual(convertToRoman(5), \"V\", '<code>convertToRoman(5)</code> should return \"V\".');"
},
{
"text": "<code>convertToRoman(9)</code> should return \"IX\".",
"testString": "assert.deepEqual(convertToRoman(9), \"IX\", '<code>convertToRoman(9)</code> should return \"IX\".');"
},
{
"text": "<code>convertToRoman(12)</code> should return \"XII\".",
"testString": "assert.deepEqual(convertToRoman(12), \"XII\", '<code>convertToRoman(12)</code> should return \"XII\".');"
},
{
"text": "<code>convertToRoman(16)</code> should return \"XVI\".",
"testString": "assert.deepEqual(convertToRoman(16), \"XVI\", '<code>convertToRoman(16)</code> should return \"XVI\".');"
},
{
"text": "<code>convertToRoman(29)</code> should return \"XXIX\".",
"testString": "assert.deepEqual(convertToRoman(29), \"XXIX\", '<code>convertToRoman(29)</code> should return \"XXIX\".');"
},
{
"text": "<code>convertToRoman(44)</code> should return \"XLIV\".",
"testString": "assert.deepEqual(convertToRoman(44), \"XLIV\", '<code>convertToRoman(44)</code> should return \"XLIV\".');"
},
{
"text": "<code>convertToRoman(45)</code> should return \"XLV\"",
"testString": "assert.deepEqual(convertToRoman(45), \"XLV\", '<code>convertToRoman(45)</code> should return \"XLV\"');"
},
{
"text": "<code>convertToRoman(68)</code> should return \"LXVIII\"",
"testString": "assert.deepEqual(convertToRoman(68), \"LXVIII\", '<code>convertToRoman(68)</code> should return \"LXVIII\"');"
},
{
"text": "<code>convertToRoman(83)</code> should return \"LXXXIII\"",
"testString": "assert.deepEqual(convertToRoman(83), \"LXXXIII\", '<code>convertToRoman(83)</code> should return \"LXXXIII\"');"
},
{
"text": "<code>convertToRoman(97)</code> should return \"XCVII\"",
"testString": "assert.deepEqual(convertToRoman(97), \"XCVII\", '<code>convertToRoman(97)</code> should return \"XCVII\"');"
},
{
"text": "<code>convertToRoman(99)</code> should return \"XCIX\"",
"testString": "assert.deepEqual(convertToRoman(99), \"XCIX\", '<code>convertToRoman(99)</code> should return \"XCIX\"');"
},
{
"text": "<code>convertToRoman(400)</code> should return \"CD\"",
"testString": "assert.deepEqual(convertToRoman(400), \"CD\", '<code>convertToRoman(400)</code> should return \"CD\"');"
},
{
"text": "<code>convertToRoman(500)</code> should return \"D\"",
"testString": "assert.deepEqual(convertToRoman(500), \"D\", '<code>convertToRoman(500)</code> should return \"D\"');"
},
{
"text": "<code>convertToRoman(501)</code> should return \"DI\"",
"testString": "assert.deepEqual(convertToRoman(501), \"DI\", '<code>convertToRoman(501)</code> should return \"DI\"');"
},
{
"text": "<code>convertToRoman(649)</code> should return \"DCXLIX\"",
"testString": "assert.deepEqual(convertToRoman(649), \"DCXLIX\", '<code>convertToRoman(649)</code> should return \"DCXLIX\"');"
},
{
"text": "<code>convertToRoman(798)</code> should return \"DCCXCVIII\"",
"testString": "assert.deepEqual(convertToRoman(798), \"DCCXCVIII\", '<code>convertToRoman(798)</code> should return \"DCCXCVIII\"');"
},
{
"text": "<code>convertToRoman(891)</code> should return \"DCCCXCI\"",
"testString": "assert.deepEqual(convertToRoman(891), \"DCCCXCI\", '<code>convertToRoman(891)</code> should return \"DCCCXCI\"');"
},
{
"text": "<code>convertToRoman(1000)</code> should return \"M\"",
"testString": "assert.deepEqual(convertToRoman(1000), \"M\", '<code>convertToRoman(1000)</code> should return \"M\"');"
},
{
"text": "<code>convertToRoman(1004)</code> should return \"MIV\"",
"testString": "assert.deepEqual(convertToRoman(1004), \"MIV\", '<code>convertToRoman(1004)</code> should return \"MIV\"');"
},
{
"text": "<code>convertToRoman(1006)</code> should return \"MVI\"",
"testString": "assert.deepEqual(convertToRoman(1006), \"MVI\", '<code>convertToRoman(1006)</code> should return \"MVI\"');"
},
{
"text": "<code>convertToRoman(1023)</code> should return \"MXXIII\"",
"testString": "assert.deepEqual(convertToRoman(1023), \"MXXIII\", '<code>convertToRoman(1023)</code> should return \"MXXIII\"');"
},
{
"text": "<code>convertToRoman(2014)</code> should return \"MMXIV\"",
"testString": "assert.deepEqual(convertToRoman(2014), \"MMXIV\", '<code>convertToRoman(2014)</code> should return \"MMXIV\"');"
},
{
"text": "<code>convertToRoman(3999)</code> should return \"MMMCMXCIX\"",
"testString": "assert.deepEqual(convertToRoman(3999), \"MMMCMXCIX\", '<code>convertToRoman(3999)</code> should return \"MMMCMXCIX\"');"
}
],
"type": "bonfire",
"MDNlinks": [
@ -147,6 +266,22 @@
"N'oublie pas d'utiliser <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
]
}
},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function convertToRoman(num) {",
" return num;",
"}",
"",
"convertToRoman(36);"
],
"head": [],
"tail": []
}
}
},
{
@ -159,24 +294,26 @@
"All letters will be uppercase. Do not transform any non-alphabetic character (i.e. spaces, punctuation), but do pass them on.",
"Remember to use <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
],
"challengeSeed": [
"function rot13(str) { // LBH QVQ VG!",
" ",
" return str;",
"}",
"",
"// Change the inputs below to test",
"rot13(\"SERR PBQR PNZC\");"
],
"tail": [],
"solutions": [
"var lookup = {\n 'A': 'N','B': 'O','C': 'P','D': 'Q',\n 'E': 'R','F': 'S','G': 'T','H': 'U',\n 'I': 'V','J': 'W','K': 'X','L': 'Y',\n 'M': 'Z','N': 'A','O': 'B','P': 'C',\n 'Q': 'D','R': 'E','S': 'F','T': 'G',\n 'U': 'H','V': 'I','W': 'J','X': 'K',\n 'Y': 'L','Z': 'M' \n};\n\nfunction rot13(encodedStr) {\n var codeArr = encodedStr.split(\"\"); // String to Array\n var decodedArr = []; // Your Result goes here\n // Only change code below this line\n \n decodedArr = codeArr.map(function(letter) {\n if(lookup.hasOwnProperty(letter)) {\n letter = lookup[letter];\n }\n return letter;\n });\n\n // Only change code above this line\n return decodedArr.join(\"\"); // Array to String\n}"
],
"tests": [
"assert(rot13(\"SERR PBQR PNZC\") === \"FREE CODE CAMP\", 'message: <code>rot13(\"SERR PBQR PNZC\")</code> should decode to <code>FREE CODE CAMP</code>');",
"assert(rot13(\"SERR CVMMN!\") === \"FREE PIZZA!\", 'message: <code>rot13(\"SERR CVMMN!\")</code> should decode to <code>FREE PIZZA!</code>');",
"assert(rot13(\"SERR YBIR?\") === \"FREE LOVE?\", 'message: <code>rot13(\"SERR YBIR?\")</code> should decode to <code>FREE LOVE?</code>');",
"assert(rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\") === \"THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.\", 'message: <code>rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\")</code> should decode to <code>THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.</code>');"
{
"text": "<code>rot13(\"SERR PBQR PNZC\")</code> should decode to <code>FREE CODE CAMP</code>",
"testString": "assert(rot13(\"SERR PBQR PNZC\") === \"FREE CODE CAMP\", '<code>rot13(\"SERR PBQR PNZC\")</code> should decode to <code>FREE CODE CAMP</code>');"
},
{
"text": "<code>rot13(\"SERR CVMMN!\")</code> should decode to <code>FREE PIZZA!</code>",
"testString": "assert(rot13(\"SERR CVMMN!\") === \"FREE PIZZA!\", '<code>rot13(\"SERR CVMMN!\")</code> should decode to <code>FREE PIZZA!</code>');"
},
{
"text": "<code>rot13(\"SERR YBIR?\")</code> should decode to <code>FREE LOVE?</code>",
"testString": "assert(rot13(\"SERR YBIR?\") === \"FREE LOVE?\", '<code>rot13(\"SERR YBIR?\")</code> should decode to <code>FREE LOVE?</code>');"
},
{
"text": "<code>rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\")</code> should decode to <code>THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.</code>",
"testString": "assert(rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\") === \"THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.\", '<code>rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\")</code> should decode to <code>THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.</code>');"
}
],
"type": "bonfire",
"MDNlinks": [
@ -207,6 +344,24 @@
"Lembre-se de usar <a href=\"http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514\" target=\"_blank\">Ler-Pesquisar-Perguntar</a> se você ficar travado. Escreva seu próprio código."
]
}
},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function rot13(str) { // LBH QVQ VG!",
" ",
" return str;",
"}",
"",
"// Change the inputs below to test",
"rot13(\"SERR PBQR PNZC\");"
],
"head": [],
"tail": []
}
}
},
{
@ -219,45 +374,118 @@
"For this challenge you will be presented with a string such as <code>800-692-7753</code> or <code>8oo-six427676;laskdjf</code>. Your job is to validate or reject the US phone number based on any combination of the formats provided above. The area code is required. If the country code is provided, you must confirm that the country code is <code>1</code>. Return <code>true</code> if the string is a valid US phone number; otherwise return <code>false</code>.",
"Remember to use <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
],
"challengeSeed": [
"function telephoneCheck(str) {",
" // Good luck!",
" return true;",
"}",
"",
"telephoneCheck(\"555-555-5555\");"
],
"solutions": [
"var re = /^([+]?1[\\s]?)?((?:[(](?:[2-9]1[02-9]|[2-9][02-8][0-9])[)][\\s]?)|(?:(?:[2-9]1[02-9]|[2-9][02-8][0-9])[\\s.-]?)){1}([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2}[\\s.-]?){1}([0-9]{4}){1}$/;\n\nfunction telephoneCheck(str) {\n return re.test(str);\n}\n\ntelephoneCheck(\"555-555-5555\");"
],
"tests": [
"assert(typeof telephoneCheck(\"555-555-5555\") === \"boolean\", 'message: <code>telephoneCheck(\"555-555-5555\")</code> should return a boolean.');",
"assert(telephoneCheck(\"1 555-555-5555\") === true, 'message: <code>telephoneCheck(\"1 555-555-5555\")</code> should return true.');",
"assert(telephoneCheck(\"1 (555) 555-5555\") === true, 'message: <code>telephoneCheck(\"1 (555) 555-5555\")</code> should return true.');",
"assert(telephoneCheck(\"5555555555\") === true, 'message: <code>telephoneCheck(\"5555555555\")</code> should return true.');",
"assert(telephoneCheck(\"555-555-5555\") === true, 'message: <code>telephoneCheck(\"555-555-5555\")</code> should return true.');",
"assert(telephoneCheck(\"(555)555-5555\") === true, 'message: <code>telephoneCheck(\"(555)555-5555\")</code> should return true.');",
"assert(telephoneCheck(\"1(555)555-5555\") === true, 'message: <code>telephoneCheck(\"1(555)555-5555\")</code> should return true.');",
"assert(telephoneCheck(\"555-5555\") === false, 'message: <code>telephoneCheck(\"555-5555\")</code> should return false.');",
"assert(telephoneCheck(\"5555555\") === false, 'message: <code>telephoneCheck(\"5555555\")</code> should return false.');",
"assert(telephoneCheck(\"1 555)555-5555\") === false, 'message: <code>telephoneCheck(\"1 555)555-5555\")</code> should return false.');",
"assert(telephoneCheck(\"1 555 555 5555\") === true, 'message: <code>telephoneCheck(\"1 555 555 5555\")</code> should return true.');",
"assert(telephoneCheck(\"1 456 789 4444\") === true, 'message: <code>telephoneCheck(\"1 456 789 4444\")</code> should return true.');",
"assert(telephoneCheck(\"123**&!!asdf#\") === false, 'message: <code>telephoneCheck(\"123**&!!asdf#\")</code> should return false.');",
"assert(telephoneCheck(\"55555555\") === false, 'message: <code>telephoneCheck(\"55555555\")</code> should return false.');",
"assert(telephoneCheck(\"(6054756961)\") === false, 'message: <code>telephoneCheck(\"(6054756961)\")</code> should return false');",
"assert(telephoneCheck(\"2 (757) 622-7382\") === false, 'message: <code>telephoneCheck(\"2 (757) 622-7382\")</code> should return false.');",
"assert(telephoneCheck(\"0 (757) 622-7382\") === false, 'message: <code>telephoneCheck(\"0 (757) 622-7382\")</code> should return false.');",
"assert(telephoneCheck(\"-1 (757) 622-7382\") === false, 'message: <code>telephoneCheck(\"-1 (757) 622-7382\")</code> should return false');",
"assert(telephoneCheck(\"2 757 622-7382\") === false, 'message: <code>telephoneCheck(\"2 757 622-7382\")</code> should return false.');",
"assert(telephoneCheck(\"10 (757) 622-7382\") === false, 'message: <code>telephoneCheck(\"10 (757) 622-7382\")</code> should return false.');",
"assert(telephoneCheck(\"27576227382\") === false, 'message: <code>telephoneCheck(\"27576227382\")</code> should return false.');",
"assert(telephoneCheck(\"(275)76227382\") === false, 'message: <code>telephoneCheck(\"(275)76227382\")</code> should return false.');",
"assert(telephoneCheck(\"2(757)6227382\") === false, 'message: <code>telephoneCheck(\"2(757)6227382\")</code> should return false.');",
"assert(telephoneCheck(\"2(757)622-7382\") === false, 'message: <code>telephoneCheck(\"2(757)622-7382\")</code> should return false.');",
"assert(telephoneCheck(\"555)-555-5555\") === false, 'message: <code>telephoneCheck(\"555)-555-5555\")</code> should return false.');",
"assert(telephoneCheck(\"(555-555-5555\") === false, 'message: <code>telephoneCheck(\"(555-555-5555\")</code> should return false.');",
"assert(telephoneCheck(\"(555)5(55?)-5555\") === false, 'message: <code>telephoneCheck(\"(555)5(55?)-5555\")</code> should return false.');"
{
"text": "<code>telephoneCheck(\"555-555-5555\")</code> should return a boolean.",
"testString": "assert(typeof telephoneCheck(\"555-555-5555\") === \"boolean\", '<code>telephoneCheck(\"555-555-5555\")</code> should return a boolean.');"
},
{
"text": "<code>telephoneCheck(\"1 555-555-5555\")</code> should return true.",
"testString": "assert(telephoneCheck(\"1 555-555-5555\") === true, '<code>telephoneCheck(\"1 555-555-5555\")</code> should return true.');"
},
{
"text": "<code>telephoneCheck(\"1 (555) 555-5555\")</code> should return true.",
"testString": "assert(telephoneCheck(\"1 (555) 555-5555\") === true, '<code>telephoneCheck(\"1 (555) 555-5555\")</code> should return true.');"
},
{
"text": "<code>telephoneCheck(\"5555555555\")</code> should return true.",
"testString": "assert(telephoneCheck(\"5555555555\") === true, '<code>telephoneCheck(\"5555555555\")</code> should return true.');"
},
{
"text": "<code>telephoneCheck(\"555-555-5555\")</code> should return true.",
"testString": "assert(telephoneCheck(\"555-555-5555\") === true, '<code>telephoneCheck(\"555-555-5555\")</code> should return true.');"
},
{
"text": "<code>telephoneCheck(\"(555)555-5555\")</code> should return true.",
"testString": "assert(telephoneCheck(\"(555)555-5555\") === true, '<code>telephoneCheck(\"(555)555-5555\")</code> should return true.');"
},
{
"text": "<code>telephoneCheck(\"1(555)555-5555\")</code> should return true.",
"testString": "assert(telephoneCheck(\"1(555)555-5555\") === true, '<code>telephoneCheck(\"1(555)555-5555\")</code> should return true.');"
},
{
"text": "<code>telephoneCheck(\"555-5555\")</code> should return false.",
"testString": "assert(telephoneCheck(\"555-5555\") === false, '<code>telephoneCheck(\"555-5555\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"5555555\")</code> should return false.",
"testString": "assert(telephoneCheck(\"5555555\") === false, '<code>telephoneCheck(\"5555555\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"1 555)555-5555\")</code> should return false.",
"testString": "assert(telephoneCheck(\"1 555)555-5555\") === false, '<code>telephoneCheck(\"1 555)555-5555\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"1 555 555 5555\")</code> should return true.",
"testString": "assert(telephoneCheck(\"1 555 555 5555\") === true, '<code>telephoneCheck(\"1 555 555 5555\")</code> should return true.');"
},
{
"text": "<code>telephoneCheck(\"1 456 789 4444\")</code> should return true.",
"testString": "assert(telephoneCheck(\"1 456 789 4444\") === true, '<code>telephoneCheck(\"1 456 789 4444\")</code> should return true.');"
},
{
"text": "<code>telephoneCheck(\"123**&!!asdf#\")</code> should return false.",
"testString": "assert(telephoneCheck(\"123**&!!asdf#\") === false, '<code>telephoneCheck(\"123**&!!asdf#\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"55555555\")</code> should return false.",
"testString": "assert(telephoneCheck(\"55555555\") === false, '<code>telephoneCheck(\"55555555\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"(6054756961)\")</code> should return false",
"testString": "assert(telephoneCheck(\"(6054756961)\") === false, '<code>telephoneCheck(\"(6054756961)\")</code> should return false');"
},
{
"text": "<code>telephoneCheck(\"2 (757) 622-7382\")</code> should return false.",
"testString": "assert(telephoneCheck(\"2 (757) 622-7382\") === false, '<code>telephoneCheck(\"2 (757) 622-7382\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"0 (757) 622-7382\")</code> should return false.",
"testString": "assert(telephoneCheck(\"0 (757) 622-7382\") === false, '<code>telephoneCheck(\"0 (757) 622-7382\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"-1 (757) 622-7382\")</code> should return false",
"testString": "assert(telephoneCheck(\"-1 (757) 622-7382\") === false, '<code>telephoneCheck(\"-1 (757) 622-7382\")</code> should return false');"
},
{
"text": "<code>telephoneCheck(\"2 757 622-7382\")</code> should return false.",
"testString": "assert(telephoneCheck(\"2 757 622-7382\") === false, '<code>telephoneCheck(\"2 757 622-7382\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"10 (757) 622-7382\")</code> should return false.",
"testString": "assert(telephoneCheck(\"10 (757) 622-7382\") === false, '<code>telephoneCheck(\"10 (757) 622-7382\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"27576227382\")</code> should return false.",
"testString": "assert(telephoneCheck(\"27576227382\") === false, '<code>telephoneCheck(\"27576227382\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"(275)76227382\")</code> should return false.",
"testString": "assert(telephoneCheck(\"(275)76227382\") === false, '<code>telephoneCheck(\"(275)76227382\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"2(757)6227382\")</code> should return false.",
"testString": "assert(telephoneCheck(\"2(757)6227382\") === false, '<code>telephoneCheck(\"2(757)6227382\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"2(757)622-7382\")</code> should return false.",
"testString": "assert(telephoneCheck(\"2(757)622-7382\") === false, '<code>telephoneCheck(\"2(757)622-7382\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"555)-555-5555\")</code> should return false.",
"testString": "assert(telephoneCheck(\"555)-555-5555\") === false, '<code>telephoneCheck(\"555)-555-5555\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"(555-555-5555\")</code> should return false.",
"testString": "assert(telephoneCheck(\"(555-555-5555\") === false, '<code>telephoneCheck(\"(555-555-5555\")</code> should return false.');"
},
{
"text": "<code>telephoneCheck(\"(555)5(55?)-5555\")</code> should return false.",
"testString": "assert(telephoneCheck(\"(555)5(55?)-5555\") === false, '<code>telephoneCheck(\"(555)5(55?)-5555\")</code> should return false.');"
}
],
"type": "bonfire",
"MDNlinks": [
@ -296,6 +524,23 @@
"Lembre-se de usar <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Ler-Procurar-Perguntar</a> se você ficar preso. Tente programar em par. Escreva seu próprio código."
]
}
},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function telephoneCheck(str) {",
" // Good luck!",
" return true;",
"}",
"",
"telephoneCheck(\"555-555-5555\");"
],
"head": [],
"tail": []
}
}
},
{
@ -311,36 +556,34 @@
"Remember to use <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code.",
"<table class='table table-striped'><tr><th>Currency Unit</th><th>Amount</th></tr><tr><td>Penny</td><td>$0.01 (PENNY)</td></tr><tr><td>Nickel</td><td>$0.05 (NICKEL)</td></tr><tr><td>Dime</td><td>$0.1 (DIME)</td></tr><tr><td>Quarter</td><td>$0.25 (QUARTER)</td></tr><tr><td>Dollar</td><td>$1 (DOLLAR)</td></tr><tr><td>Five Dollars</td><td>$5 (FIVE)</td></tr><tr><td>Ten Dollars</td><td>$10 (TEN)</td></tr><tr><td>Twenty Dollars</td><td>$20 (TWENTY)</td></tr><tr><td>One-hundred Dollars</td><td>$100 (ONE HUNDRED)</td></tr></table>"
],
"challengeSeed": [
"function checkCashRegister(price, cash, cid) {",
" var change;",
" // Here is your change, ma'am.",
" return change;",
"}",
"",
"// Example cash-in-drawer array:",
"// [[\"PENNY\", 1.01],",
"// [\"NICKEL\", 2.05],",
"// [\"DIME\", 3.1],",
"// [\"QUARTER\", 4.25],",
"// [\"ONE\", 90],",
"// [\"FIVE\", 55],",
"// [\"TEN\", 20],",
"// [\"TWENTY\", 60],",
"// [\"ONE HUNDRED\", 100]]",
"",
"checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]);"
],
"solutions": [
"var denom = [\n\t{ name: 'ONE HUNDRED', val: 100},\n\t{ name: 'TWENTY', val: 20},\n\t{ name: 'TEN', val: 10},\n\t{ name: 'FIVE', val: 5},\n\t{ name: 'ONE', val: 1},\n\t{ name: 'QUARTER', val: 0.25},\n\t{ name: 'DIME', val: 0.1},\n\t{ name: 'NICKEL', val: 0.05},\n\t{ name: 'PENNY', val: 0.01}\n];\n\nfunction checkCashRegister(price, cash, cid) {\n var output = {status: null, change: []};\n var change = cash - price;\n var register = cid.reduce(function(acc, curr) {\n acc.total += curr[1];\n acc[curr[0]] = curr[1];\n return acc;\n }, {total: 0});\n if(register.total === change) {\n output.status = 'CLOSED';\n output.change = cid;\n return output;\n }\n if(register.total < change) {\n output.status = 'INSUFFICIENT_FUNDS';\n return output;\n }\n var change_arr = denom.reduce(function(acc, curr) {\n var value = 0;\n while(register[curr.name] > 0 && change >= curr.val) {\n change -= curr.val;\n register[curr.name] -= curr.val;\n value += curr.val;\n change = Math.round(change * 100) / 100;\n }\n if(value > 0) {\n acc.push([ curr.name, value ]);\n }\n return acc;\n }, []);\n if(change_arr.length < 1 || change > 0) {\n output.status = 'INSUFFICIENT_FUNDS';\n return output;\n }\n output.status = 'OPEN';\n output.change = change_arr;\n return output;\n}"
],
"tests": [
"assert.deepEqual(Object.prototype.toString.call(checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])), '[object Object]', 'message: <code>checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])</code> should return an object.');",
"assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]), {status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}, 'message: <code>checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])</code> should return <code>{status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}</code>.');",
"assert.deepEqual(checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]), {status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}, 'message: <code>checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])</code> should return <code>{status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}</code>.');",
"assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"INSUFFICIENT_FUNDS\", change: []}, 'message: <code>checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])</code> should return <code>{status: \"INSUFFICIENT_FUNDS\", change: []}</code>.');",
"assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"INSUFFICIENT_FUNDS\", change: []}, 'message: <code>checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])</code> should return <code>{status: \"INSUFFICIENT_FUNDS\", change: []}</code>.');",
"assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}, 'message: <code>checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])</code> should return <code>{status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}</code>.');"
{
"text": "<code>checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])</code> should return an object.",
"testString": "assert.deepEqual(Object.prototype.toString.call(checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])), '[object Object]', '<code>checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])</code> should return an object.');"
},
{
"text": "<code>checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])</code> should return <code>{status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}</code>.",
"testString": "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]), {status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}, '<code>checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])</code> should return <code>{status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}</code>.');"
},
{
"text": "<code>checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])</code> should return <code>{status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}</code>.",
"testString": "assert.deepEqual(checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]), {status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}, '<code>checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])</code> should return <code>{status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}</code>.');"
},
{
"text": "<code>checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])</code> should return <code>{status: \"INSUFFICIENT_FUNDS\", change: []}</code>.",
"testString": "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"INSUFFICIENT_FUNDS\", change: []}, '<code>checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])</code> should return <code>{status: \"INSUFFICIENT_FUNDS\", change: []}</code>.');"
},
{
"text": "<code>checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])</code> should return <code>{status: \"INSUFFICIENT_FUNDS\", change: []}</code>.",
"testString": "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"INSUFFICIENT_FUNDS\", change: []}, '<code>checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])</code> should return <code>{status: \"INSUFFICIENT_FUNDS\", change: []}</code>.');"
},
{
"text": "<code>checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])</code> should return <code>{status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}</code>.",
"testString": "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}, '<code>checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])</code> should return <code>{status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}</code>.');"
}
],
"type": "bonfire",
"isRequired": true,
@ -381,6 +624,35 @@
"<table class='table table-striped'><tr><th>Currency Unit</th><th>Amount</th></tr><tr><td>Penny</td><td>$0.01 (PENNY)</td></tr><tr><td>Nickel</td><td>$0.05 (NICKEL)</td></tr><tr><td>Dime</td><td>$0.1 (DIME)</td></tr><tr><td>Quarter</td><td>$0.25 (QUARTER)</td></tr><tr><td>Dollar</td><td>$1 (DOLLAR)</td></tr><tr><td>Five Dollars</td><td>$5 (FIVE)</td></tr><tr><td>Ten Dollars</td><td>$10 (TEN)</td></tr><tr><td>Twenty Dollars</td><td>$20 (TWENTY)</td></tr><tr><td>One-hundred Dollars</td><td>$100 (ONE HUNDRED)</td></tr></table>"
]
}
},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function checkCashRegister(price, cash, cid) {",
" var change;",
" // Here is your change, ma'am.",
" return change;",
"}",
"",
"// Example cash-in-drawer array:",
"// [[\"PENNY\", 1.01],",
"// [\"NICKEL\", 2.05],",
"// [\"DIME\", 3.1],",
"// [\"QUARTER\", 4.25],",
"// [\"ONE\", 90],",
"// [\"FIVE\", 55],",
"// [\"TEN\", 20],",
"// [\"TWENTY\", 60],",
"// [\"ONE HUNDRED\", 100]]",
"",
"checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]);"
],
"head": [],
"tail": []
}
}
}
]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -45,13 +45,25 @@
" }",
"};"
],
"tail": "ReactDOM.render(<DisplayMessages />, document.getElementById('root'))"
"tail": [
"ReactDOM.render(<DisplayMessages />, document.getElementById('root'))"
],
"head": []
}
},
"tests": [
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); return mockedComponent.find('div').text() === '' })(), 'message: The <code>DisplayMessages</code> component should render an empty <code>div</code> element.');",
"getUserInput => assert((function() { const noWhiteSpace = getUserInput('index').replace(/\\s/g,''); return noWhiteSpace.includes('constructor(props)') && noWhiteSpace.includes('super(props'); })(), 'message: The <code>DisplayMessages</code> constructor should be called properly with <code>super</code>, passing in <code>props</code>.');",
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); const initialState = mockedComponent.state(); return typeof initialState === 'object' && initialState.input === '' && Array.isArray(initialState.messages) && initialState.messages.length === 0; })(), 'message: The <code>DisplayMessages</code> component should have an initial state equal to <code>{input: \"\", messages: []}</code>.');"
{
"text": "The <code>DisplayMessages</code> component should render an empty <code>div</code> element.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); return mockedComponent.find('div').text() === '' })(), 'The <code>DisplayMessages</code> component should render an empty <code>div</code> element.');"
},
{
"text": "The <code>DisplayMessages</code> constructor should be called properly with <code>super</code>, passing in <code>props</code>.",
"testString": "getUserInput => assert((function() { const noWhiteSpace = getUserInput('index').replace(/\\s/g,''); return noWhiteSpace.includes('constructor(props)') && noWhiteSpace.includes('super(props'); })(), 'The <code>DisplayMessages</code> constructor should be called properly with <code>super</code>, passing in <code>props</code>.');"
},
{
"text": "The <code>DisplayMessages</code> component should have an initial state equal to <code>{input: \"\", messages: []}</code>.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); const initialState = mockedComponent.state(); return typeof initialState === 'object' && initialState.input === '' && Array.isArray(initialState.messages) && initialState.messages.length === 0; })(), 'The <code>DisplayMessages</code> component should have an initial state equal to <code>{input: \"\", messages: []}</code>.');"
}
],
"solutions": [
"class DisplayMessages extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n input: '',\n messages: []\n }\n }\n render() {\n return <div/>\n }\n};"
@ -100,16 +112,37 @@
" }",
"};"
],
"tail": "ReactDOM.render(<DisplayMessages />, document.getElementById('root'))"
"tail": [
"ReactDOM.render(<DisplayMessages />, document.getElementById('root'))"
],
"head": []
}
},
"tests": [
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); const initialState = mockedComponent.state(); return ( typeof initialState === 'object' && initialState.input === '' && initialState.messages.length === 0); })(), 'message: The <code>DisplayMessages</code> component should initialize with a state equal to <code>{ input: \"\", messages: [] }</code>.');",
"async () => { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); const state = () => { mockedComponent.setState({messages: ['__TEST__MESSAGE']}); return waitForIt(() => mockedComponent )}; const updated = await state(); assert(updated.find('div').length === 1 && updated.find('h2').length === 1 && updated.find('button').length === 1 && updated.find('ul').length === 1, 'message: The <code>DisplayMessages</code> component should render a <code>div</code> containing an <code>h2</code> element, a <code>button</code> element, a <code>ul</code> element, and <code>li</code> elements as children.'); }; ",
"async () => { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); const causeChange = (c, v) => c.find('input').simulate('change', { target: { value: v }}); const testValue = '__TEST__EVENT__INPUT'; const changed = () => { causeChange(mockedComponent, testValue); return waitForIt(() => mockedComponent )}; const updated = await changed(); assert(updated.find('input').props().value === testValue, 'message: The <code>input</code> element should render the value of <code>input</code> in local state.'); }; ",
"async () => { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); const causeChange = (c, v) => c.find('input').simulate('change', { target: { value: v }}); const initialState = mockedComponent.state(); const testMessage = '__TEST__EVENT__MESSAGE__'; const changed = () => { causeChange(mockedComponent, testMessage); return waitForIt(() => mockedComponent )}; const afterInput = await changed(); assert(initialState.input === '' && afterInput.state().input === '__TEST__EVENT__MESSAGE__', 'message: Calling the method <code>handleChange</code> should update the <code>input</code> value in state to the current input.'); }; ",
"async () => { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); const causeChange = (c, v) => c.find('input').simulate('change', { target: { value: v }}); const initialState = mockedComponent.state(); const testMessage_1 = '__FIRST__MESSAGE__'; const firstChange = () => { causeChange(mockedComponent, testMessage_1); return waitForIt(() => mockedComponent )}; const firstResult = await firstChange(); const firstSubmit = () => { mockedComponent.find('button').simulate('click'); return waitForIt(() => mockedComponent )}; const afterSubmit_1 = await firstSubmit(); const submitState_1 = afterSubmit_1.state(); const testMessage_2 = '__SECOND__MESSAGE__'; const secondChange = () => { causeChange(mockedComponent, testMessage_2); return waitForIt(() => mockedComponent )}; const secondResult = await secondChange(); const secondSubmit = () => { mockedComponent.find('button').simulate('click'); return waitForIt(() => mockedComponent )}; const afterSubmit_2 = await secondSubmit(); const submitState_2 = afterSubmit_2.state(); assert(initialState.messages.length === 0 && submitState_1.messages.length === 1 && submitState_2.messages.length === 2 && submitState_2.messages[1] === testMessage_2, 'message: Clicking the <code>Add message</code> button should call the method <code>submitMessage</code> which should add the current <code>input</code> to the <code>messages</code> array in state.'); }; ",
"async () => { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); const causeChange = (c, v) => c.find('input').simulate('change', { target: { value: v }}); const initialState = mockedComponent.state(); const testMessage = '__FIRST__MESSAGE__'; const firstChange = () => { causeChange(mockedComponent, testMessage); return waitForIt(() => mockedComponent )}; const firstResult = await firstChange(); const firstState = firstResult.state(); const firstSubmit = () => { mockedComponent.find('button').simulate('click'); return waitForIt(() => mockedComponent )}; const afterSubmit = await firstSubmit(); const submitState = afterSubmit.state(); assert(firstState.input === testMessage && submitState.input === '', 'message: The <code>submitMessage</code> method should clear the current input.'); }; "
{
"text": "The <code>DisplayMessages</code> component should initialize with a state equal to <code>{ input: \"\", messages: [] }</code>.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); const initialState = mockedComponent.state(); return ( typeof initialState === 'object' && initialState.input === '' && initialState.messages.length === 0); })(), 'The <code>DisplayMessages</code> component should initialize with a state equal to <code>{ input: \"\", messages: [] }</code>.');"
},
{
"text": "The <code>DisplayMessages</code> component should render a <code>div</code> containing an <code>h2</code> element, a <code>button</code> element, a <code>ul</code> element, and <code>li</code> elements as children.",
"testString": "async () => { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); const state = () => { mockedComponent.setState({messages: ['__TEST__MESSAGE']}); return waitForIt(() => mockedComponent )}; const updated = await state(); assert(updated.find('div').length === 1 && updated.find('h2').length === 1 && updated.find('button').length === 1 && updated.find('ul').length === 1, 'The <code>DisplayMessages</code> component should render a <code>div</code> containing an <code>h2</code> element, a <code>button</code> element, a <code>ul</code> element, and <code>li</code> elements as children.'); }; "
},
{
"text": "The <code>input</code> element should render the value of <code>input</code> in local state.",
"testString": "async () => { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); const causeChange = (c, v) => c.find('input').simulate('change', { target: { value: v }}); const testValue = '__TEST__EVENT__INPUT'; const changed = () => { causeChange(mockedComponent, testValue); return waitForIt(() => mockedComponent )}; const updated = await changed(); assert(updated.find('input').props().value === testValue, 'The <code>input</code> element should render the value of <code>input</code> in local state.'); }; "
},
{
"text": "Calling the method <code>handleChange</code> should update the <code>input</code> value in state to the current input.",
"testString": "async () => { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); const causeChange = (c, v) => c.find('input').simulate('change', { target: { value: v }}); const initialState = mockedComponent.state(); const testMessage = '__TEST__EVENT__MESSAGE__'; const changed = () => { causeChange(mockedComponent, testMessage); return waitForIt(() => mockedComponent )}; const afterInput = await changed(); assert(initialState.input === '' && afterInput.state().input === '__TEST__EVENT__MESSAGE__', 'Calling the method <code>handleChange</code> should update the <code>input</code> value in state to the current input.'); }; "
},
{
"text": "Clicking the <code>Add message</code> button should call the method <code>submitMessage</code> which should add the current <code>input</code> to the <code>messages</code> array in state.",
"testString": "async () => { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); const causeChange = (c, v) => c.find('input').simulate('change', { target: { value: v }}); const initialState = mockedComponent.state(); const testMessage_1 = '__FIRST__MESSAGE__'; const firstChange = () => { causeChange(mockedComponent, testMessage_1); return waitForIt(() => mockedComponent )}; const firstResult = await firstChange(); const firstSubmit = () => { mockedComponent.find('button').simulate('click'); return waitForIt(() => mockedComponent )}; const afterSubmit_1 = await firstSubmit(); const submitState_1 = afterSubmit_1.state(); const testMessage_2 = '__SECOND__MESSAGE__'; const secondChange = () => { causeChange(mockedComponent, testMessage_2); return waitForIt(() => mockedComponent )}; const secondResult = await secondChange(); const secondSubmit = () => { mockedComponent.find('button').simulate('click'); return waitForIt(() => mockedComponent )}; const afterSubmit_2 = await secondSubmit(); const submitState_2 = afterSubmit_2.state(); assert(initialState.messages.length === 0 && submitState_1.messages.length === 1 && submitState_2.messages.length === 2 && submitState_2.messages[1] === testMessage_2, 'Clicking the <code>Add message</code> button should call the method <code>submitMessage</code> which should add the current <code>input</code> to the <code>messages</code> array in state.'); }; "
},
{
"text": "The <code>submitMessage</code> method should clear the current input.",
"testString": "async () => { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); const causeChange = (c, v) => c.find('input').simulate('change', { target: { value: v }}); const initialState = mockedComponent.state(); const testMessage = '__FIRST__MESSAGE__'; const firstChange = () => { causeChange(mockedComponent, testMessage); return waitForIt(() => mockedComponent )}; const firstResult = await firstChange(); const firstState = firstResult.state(); const firstSubmit = () => { mockedComponent.find('button').simulate('click'); return waitForIt(() => mockedComponent )}; const afterSubmit = await firstSubmit(); const submitState = afterSubmit.state(); assert(firstState.input === testMessage && submitState.input === '', 'The <code>submitMessage</code> method should clear the current input.'); }; "
}
],
"solutions": [
"class DisplayMessages extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n input: '',\n messages: []\n }\n this.handleChange = this.handleChange.bind(this); \n this.submitMessage = this.submitMessage.bind(this); \n }\n handleChange(event) {\n this.setState({\n input: event.target.value\n });\n }\n submitMessage() {\n const currentMessage = this.state.input;\n this.setState({\n input: '',\n messages: this.state.messages.concat(currentMessage)\n });\n }\n render() {\n return (\n <div>\n <h2>Type in a new Message:</h2>\n <input\n value={this.state.input}\n onChange={this.handleChange}/><br/>\n <button onClick={this.submitMessage}>Submit</button>\n <ul>\n {this.state.messages.map( (message, idx) => {\n return (\n <li key={idx}>{message}</li>\n )\n })\n }\n </ul>\n </div>\n );\n }\n};"
@ -137,16 +170,36 @@
"contents": [
"// define ADD, addMessage(), messageReducer(), and store here:",
""
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert(ADD === 'ADD', 'message: The const <code>ADD</code> should exist and hold a value equal to the string <code>ADD</code>');",
"assert((function() { const addAction = addMessage('__TEST__MESSAGE__'); return addAction.type === ADD && addAction.message === '__TEST__MESSAGE__'; })(), 'message: The action creator <code>addMessage</code> should return an object with <code>type</code> equal to <code>ADD</code> and message equal to the message that is passed in.');",
"assert(typeof messageReducer === 'function', 'message: <code>messageReducer</code> should be a function.');",
"assert((function() { const initialState = store.getState(); return typeof store === 'object' && initialState.length === 0; })(), 'message: The store should exist and have an initial state set to an empty array.');",
"assert((function() { const initialState = store.getState(); const isFrozen = DeepFreeze(initialState); store.dispatch(addMessage('__A__TEST__MESSAGE')); const addState = store.getState(); return (isFrozen && addState[0] === '__A__TEST__MESSAGE'); })(), 'message: Dispatching <code>addMessage</code> against the store should immutably add a new message to the array of messages held in state.');",
"assert((function() { const addState = store.getState(); store.dispatch({type: 'FAKE_ACTION'}); const testState = store.getState(); return (addState === testState); })(), 'message: The <code>messageReducer</code> should return the current state if called with any other actions.');"
{
"text": "The const <code>ADD</code> should exist and hold a value equal to the string <code>ADD</code>",
"testString": "assert(ADD === 'ADD', 'The const <code>ADD</code> should exist and hold a value equal to the string <code>ADD</code>');"
},
{
"text": "The action creator <code>addMessage</code> should return an object with <code>type</code> equal to <code>ADD</code> and message equal to the message that is passed in.",
"testString": "assert((function() { const addAction = addMessage('__TEST__MESSAGE__'); return addAction.type === ADD && addAction.message === '__TEST__MESSAGE__'; })(), 'The action creator <code>addMessage</code> should return an object with <code>type</code> equal to <code>ADD</code> and message equal to the message that is passed in.');"
},
{
"text": "<code>messageReducer</code> should be a function.",
"testString": "assert(typeof messageReducer === 'function', '<code>messageReducer</code> should be a function.');"
},
{
"text": "The store should exist and have an initial state set to an empty array.",
"testString": "assert((function() { const initialState = store.getState(); return typeof store === 'object' && initialState.length === 0; })(), 'The store should exist and have an initial state set to an empty array.');"
},
{
"text": "Dispatching <code>addMessage</code> against the store should immutably add a new message to the array of messages held in state.",
"testString": "assert((function() { const initialState = store.getState(); const isFrozen = DeepFreeze(initialState); store.dispatch(addMessage('__A__TEST__MESSAGE')); const addState = store.getState(); return (isFrozen && addState[0] === '__A__TEST__MESSAGE'); })(), 'Dispatching <code>addMessage</code> against the store should immutably add a new message to the array of messages held in state.');"
},
{
"text": "The <code>messageReducer</code> should return the current state if called with any other actions.",
"testString": "assert((function() { const addState = store.getState(); store.dispatch({type: 'FAKE_ACTION'}); const testState = store.getState(); return (addState === testState); })(), 'The <code>messageReducer</code> should return the current state if called with any other actions.');"
}
],
"solutions": [
"const ADD = 'ADD';\n\nconst addMessage = (message) => {\n return {\n type: ADD,\n message\n }\n};\n\nconst messageReducer = (state = [], action) => {\n switch (action.type) {\n case ADD:\n return [\n ...state,\n action.message\n ];\n default:\n return state;\n }\n};\n\nconst store = Redux.createStore(messageReducer);"
@ -253,14 +306,29 @@
" // change code above this line",
"};"
],
"tail": "ReactDOM.render(<AppWrapper />, document.getElementById('root'))"
"tail": [
"ReactDOM.render(<AppWrapper />, document.getElementById('root'))"
],
"head": []
}
},
"tests": [
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('AppWrapper').length === 1; })(), 'message: The <code>AppWrapper</code> should render.');",
"getUserInput => assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return getUserInput('index').replace(/\\s/g,'').includes('<Providerstore={store}>'); })(), 'message: The <code>Provider</code> wrapper component should have a prop of <code>store</code> passed to it, equal to the Redux store.');",
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('AppWrapper').find('DisplayMessages').length === 1; })(), 'message: <code>DisplayMessages</code> should render as a child of <code>AppWrapper</code>.');",
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('div').length === 1 && mockedComponent.find('h2').length === 1 && mockedComponent.find('button').length === 1 && mockedComponent.find('ul').length === 1; })(), 'message: The <code>DisplayMessages</code> component should render an h2, input, button, and <code>ul</code> element.');"
{
"text": "The <code>AppWrapper</code> should render.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('AppWrapper').length === 1; })(), 'The <code>AppWrapper</code> should render.');"
},
{
"text": "The <code>Provider</code> wrapper component should have a prop of <code>store</code> passed to it, equal to the Redux store.",
"testString": "getUserInput => assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return getUserInput('index').replace(/\\s/g,'').includes('<Providerstore={store}>'); })(), 'The <code>Provider</code> wrapper component should have a prop of <code>store</code> passed to it, equal to the Redux store.');"
},
{
"text": "<code>DisplayMessages</code> should render as a child of <code>AppWrapper</code>.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('AppWrapper').find('DisplayMessages').length === 1; })(), '<code>DisplayMessages</code> should render as a child of <code>AppWrapper</code>.');"
},
{
"text": "The <code>DisplayMessages</code> component should render an h2, input, button, and <code>ul</code> element.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('div').length === 1 && mockedComponent.find('h2').length === 1 && mockedComponent.find('button').length === 1 && mockedComponent.find('ul').length === 1; })(), 'The <code>DisplayMessages</code> component should render an h2, input, button, and <code>ul</code> element.');"
}
],
"solutions": [
"// Redux Code:\nconst ADD = 'ADD';\n\nconst addMessage = (message) => {\n return {\n type: ADD,\n message\n }\n};\n\nconst messageReducer = (state = [], action) => {\n switch (action.type) {\n case ADD:\n return [\n ...state,\n action.message\n ];\n default:\n return state;\n }\n};\n\nconst store = Redux.createStore(messageReducer);\n\n// React Code:\n\nclass DisplayMessages extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n input: '',\n messages: []\n }\n this.handleChange = this.handleChange.bind(this); \n this.submitMessage = this.submitMessage.bind(this); \n }\n handleChange(event) {\n this.setState({\n input: event.target.value\n });\n }\n submitMessage() {\n const currentMessage = this.state.input;\n this.setState({\n input: '',\n messages: this.state.messages.concat(currentMessage)\n });\n }\n render() {\n return (\n <div>\n <h2>Type in a new Message:</h2>\n <input\n value={this.state.input}\n onChange={this.handleChange}/><br/>\n <button onClick={this.submitMessage}>Submit</button>\n <ul>\n {this.state.messages.map( (message, idx) => {\n return (\n <li key={idx}>{message}</li>\n )\n })\n }\n </ul>\n </div>\n );\n }\n};\n\nconst Provider = ReactRedux.Provider;\n\nclass AppWrapper extends React.Component {\n // change code below this line\n render() {\n return (\n <Provider store = {store}>\n <DisplayMessages/>\n </Provider>\n );\n }\n // change code above this line\n};"
@ -291,14 +359,28 @@
"",
"// change code below this line",
""
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert(Array.isArray(state) && state.length === 0, 'message: The const <code>state</code> should be an empty array.');",
"assert(typeof mapStateToProps === 'function', 'message: <code>mapStateToProps</code> should be a function.');",
"assert(typeof mapStateToProps() === 'object', 'message: <code>mapStateToProps</code> should return an object.');",
"assert(mapStateToProps(['messages']).messages.pop() === 'messages', 'message: Passing an array as state to <code>mapStateToProps</code> should return this array assigned to a key of <code>messages</code>.');"
{
"text": "The const <code>state</code> should be an empty array.",
"testString": "assert(Array.isArray(state) && state.length === 0, 'The const <code>state</code> should be an empty array.');"
},
{
"text": "<code>mapStateToProps</code> should be a function.",
"testString": "assert(typeof mapStateToProps === 'function', '<code>mapStateToProps</code> should be a function.');"
},
{
"text": "<code>mapStateToProps</code> should return an object.",
"testString": "assert(typeof mapStateToProps() === 'object', '<code>mapStateToProps</code> should return an object.');"
},
{
"text": "Passing an array as state to <code>mapStateToProps</code> should return this array assigned to a key of <code>messages</code>.",
"testString": "assert(mapStateToProps(['messages']).messages.pop() === 'messages', 'Passing an array as state to <code>mapStateToProps</code> should return this array assigned to a key of <code>messages</code>.');"
}
],
"solutions": [
"const state = [];\n\n// change code below this line\n\nconst mapStateToProps = (state) => {\n return {\n messages: state\n }\n};"
@ -334,14 +416,28 @@
"",
"// change code below this line",
""
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert((function() { const addMessageTest = addMessage(); return ( addMessageTest.hasOwnProperty('type') && addMessageTest.hasOwnProperty('message')); })(), 'message: <code>addMessage</code> should return an object with keys <code>type</code> and <code>message</code>.');",
"assert(typeof mapDispatchToProps === 'function', 'message: <code>mapDispatchToProps</code> should be a function.');",
"assert(typeof mapDispatchToProps() === 'object', 'message: <code>mapDispatchToProps</code> should return an object.');",
"assert((function() { let testAction; const dispatch = (fn) => { testAction = fn; }; let dispatchFn = mapDispatchToProps(dispatch); dispatchFn.submitNewMessage('__TEST__MESSAGE__'); return (testAction.type === 'ADD' && testAction.message === '__TEST__MESSAGE__'); })(), 'message: Dispatching <code>addMessage</code> with <code>submitNewMessage</code> from <code>mapDispatchToProps</code> should return a message to the dispatch function.');"
{
"text": "<code>addMessage</code> should return an object with keys <code>type</code> and <code>message</code>.",
"testString": "assert((function() { const addMessageTest = addMessage(); return ( addMessageTest.hasOwnProperty('type') && addMessageTest.hasOwnProperty('message')); })(), '<code>addMessage</code> should return an object with keys <code>type</code> and <code>message</code>.');"
},
{
"text": "<code>mapDispatchToProps</code> should be a function.",
"testString": "assert(typeof mapDispatchToProps === 'function', '<code>mapDispatchToProps</code> should be a function.');"
},
{
"text": "<code>mapDispatchToProps</code> should return an object.",
"testString": "assert(typeof mapDispatchToProps() === 'object', '<code>mapDispatchToProps</code> should return an object.');"
},
{
"text": "Dispatching <code>addMessage</code> with <code>submitNewMessage</code> from <code>mapDispatchToProps</code> should return a message to the dispatch function.",
"testString": "assert((function() { let testAction; const dispatch = (fn) => { testAction = fn; }; let dispatchFn = mapDispatchToProps(dispatch); dispatchFn.submitNewMessage('__TEST__MESSAGE__'); return (testAction.type === 'ADD' && testAction.message === '__TEST__MESSAGE__'); })(), 'Dispatching <code>addMessage</code> with <code>submitNewMessage</code> from <code>mapDispatchToProps</code> should return a message to the dispatch function.');"
}
],
"solutions": [
"const addMessage = (message) => {\n return {\n type: 'ADD',\n message: message\n }\n};\n\n// change code below this line\n\nconst mapDispatchToProps = (dispatch) => {\n return {\n submitNewMessage: function(message) {\n dispatch(addMessage(message));\n }\n }\n};"
@ -418,13 +514,23 @@
" }",
"};",
"ReactDOM.render(<AppWrapper />, document.getElementById('root'))"
]
],
"head": []
}
},
"tests": [
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('Presentational').length === 1; })(), 'message: The <code>Presentational</code> component should render.');",
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const props = mockedComponent.find('Presentational').props(); return props.messages === '__INITIAL__STATE__'; })(), 'message: The <code>Presentational</code> component should receive a prop <code>messages</code> via <code>connect</code>.');",
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const props = mockedComponent.find('Presentational').props(); return typeof props.submitNewMessage === 'function'; })(), 'message: The <code>Presentational</code> component should receive a prop <code>submitNewMessage</code> via <code>connect</code>.');"
{
"text": "The <code>Presentational</code> component should render.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('Presentational').length === 1; })(), 'The <code>Presentational</code> component should render.');"
},
{
"text": "The <code>Presentational</code> component should receive a prop <code>messages</code> via <code>connect</code>.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const props = mockedComponent.find('Presentational').props(); return props.messages === '__INITIAL__STATE__'; })(), 'The <code>Presentational</code> component should receive a prop <code>messages</code> via <code>connect</code>.');"
},
{
"text": "The <code>Presentational</code> component should receive a prop <code>submitNewMessage</code> via <code>connect</code>.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const props = mockedComponent.find('Presentational').props(); return typeof props.submitNewMessage === 'function'; })(), 'The <code>Presentational</code> component should receive a prop <code>submitNewMessage</code> via <code>connect</code>.');"
}
],
"solutions": [
"const addMessage = (message) => {\n return {\n type: 'ADD',\n message: message\n }\n};\n\nconst mapStateToProps = (state) => {\n return {\n messages: state\n }\n};\n\nconst mapDispatchToProps = (dispatch) => {\n return {\n submitNewMessage: (message) => {\n dispatch(addMessage(message));\n }\n }\n};\n\nclass Presentational extends React.Component {\n constructor(props) {\n super(props);\n }\n render() {\n return <h3>This is a Presentational Component</h3>\n }\n};\n\nconst connect = ReactRedux.connect;\n// change code below this line\n\nconst ConnectedComponent = connect(mapStateToProps, mapDispatchToProps)(Presentational); \n"
@ -547,15 +653,33 @@
" }",
"};"
],
"tail": "ReactDOM.render(<AppWrapper />, document.getElementById('root'))"
"tail": [
"ReactDOM.render(<AppWrapper />, document.getElementById('root'))"
],
"head": []
}
},
"tests": [
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('AppWrapper').length === 1; })(), 'message: The <code>AppWrapper</code> should render to the page.');",
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('Presentational').length === 1; })(), 'message: The <code>Presentational</code> component should render an <code>h2</code>, <code>input</code>, <code>button</code>, and <code>ul</code> elements.');",
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const PresentationalComponent = mockedComponent.find('Presentational'); return ( PresentationalComponent.find('div').length === 1 && PresentationalComponent.find('h2').length === 1 && PresentationalComponent.find('button').length === 1 && PresentationalComponent.find('ul').length === 1 ); })(), 'message: The <code>Presentational</code> component should render an <code>h2</code>, <code>input</code>, <code>button</code>, and <code>ul</code> elements.');",
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const PresentationalComponent = mockedComponent.find('Presentational'); const props = PresentationalComponent.props(); return Array.isArray(props.messages); })(), 'message: The <code>Presentational</code> component should receive <code>messages</code> from the Redux store as a prop.');",
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const PresentationalComponent = mockedComponent.find('Presentational'); const props = PresentationalComponent.props(); return typeof props.submitNewMessage === 'function'; })(), 'message: The <code>Presentational</code> component should receive the <code>submitMessage</code> action creator as a prop.');"
{
"text": "The <code>AppWrapper</code> should render to the page.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('AppWrapper').length === 1; })(), 'The <code>AppWrapper</code> should render to the page.');"
},
{
"text": "The <code>Presentational</code> component should render an <code>h2</code>, <code>input</code>, <code>button</code>, and <code>ul</code> elements.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('Presentational').length === 1; })(), 'The <code>Presentational</code> component should render an <code>h2</code>, <code>input</code>, <code>button</code>, and <code>ul</code> elements.');"
},
{
"text": "The <code>Presentational</code> component should render an <code>h2</code>, <code>input</code>, <code>button</code>, and <code>ul</code> elements.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const PresentationalComponent = mockedComponent.find('Presentational'); return ( PresentationalComponent.find('div').length === 1 && PresentationalComponent.find('h2').length === 1 && PresentationalComponent.find('button').length === 1 && PresentationalComponent.find('ul').length === 1 ); })(), 'The <code>Presentational</code> component should render an <code>h2</code>, <code>input</code>, <code>button</code>, and <code>ul</code> elements.');"
},
{
"text": "The <code>Presentational</code> component should receive <code>messages</code> from the Redux store as a prop.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const PresentationalComponent = mockedComponent.find('Presentational'); const props = PresentationalComponent.props(); return Array.isArray(props.messages); })(), 'The <code>Presentational</code> component should receive <code>messages</code> from the Redux store as a prop.');"
},
{
"text": "The <code>Presentational</code> component should receive the <code>submitMessage</code> action creator as a prop.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const PresentationalComponent = mockedComponent.find('Presentational'); const props = PresentationalComponent.props(); return typeof props.submitNewMessage === 'function'; })(), 'The <code>Presentational</code> component should receive the <code>submitMessage</code> action creator as a prop.');"
}
],
"solutions": [
"// Redux:\nconst ADD = 'ADD';\n\nconst addMessage = (message) => {\n return {\n type: ADD,\n message: message\n }\n};\n\nconst messageReducer = (state = [], action) => {\n switch (action.type) {\n case ADD:\n return [\n ...state,\n action.message\n ];\n default:\n return state;\n }\n};\n\nconst store = Redux.createStore(messageReducer);\n\n// React:\nclass Presentational extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n input: '',\n messages: []\n }\n this.handleChange = this.handleChange.bind(this); \n this.submitMessage = this.submitMessage.bind(this); \n }\n handleChange(event) {\n this.setState({\n input: event.target.value\n });\n }\n submitMessage() {\n const currentMessage = this.state.input;\n this.setState({\n input: '',\n messages: this.state.messages.concat(currentMessage)\n });\n }\n render() {\n return (\n <div>\n <h2>Type in a new Message:</h2>\n <input\n value={this.state.input}\n onChange={this.handleChange}/><br/>\n <button onClick={this.submitMessage}>Submit</button>\n <ul>\n {this.state.messages.map( (message, idx) => {\n return (\n <li key={idx}>{message}</li>\n )\n })\n }\n </ul>\n </div>\n );\n }\n};\n\n// React-Redux:\nconst mapStateToProps = (state) => {\n return { messages: state }\n};\n\nconst mapDispatchToProps = (dispatch) => {\n return {\n submitNewMessage: (newMessage) => {\n dispatch(addMessage(newMessage))\n }\n }\n};\n\nconst Provider = ReactRedux.Provider;\nconst connect = ReactRedux.connect;\n\n// define the Container component here:\nconst Container = connect(mapStateToProps, mapDispatchToProps)(Presentational);\n\nclass AppWrapper extends React.Component {\n constructor(props) {\n super(props);\n }\n render() {\n // complete the return statement:\n return (\n <Provider store={store}>\n <Container/>\n </Provider>\n );\n }\n};"
@ -677,19 +801,49 @@
" }",
"};"
],
"tail": "ReactDOM.render(<AppWrapper />, document.getElementById('root'))"
"tail": [
"ReactDOM.render(<AppWrapper />, document.getElementById('root'))"
],
"head": []
}
},
"tests": [
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('AppWrapper').length === 1; })(), 'message: The <code>AppWrapper</code> should render to the page.');",
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('Presentational').length === 1; })(), 'message: The <code>Presentational</code> component should render an <code>h2</code>, <code>input</code>, <code>button</code>, and <code>ul</code> elements.');",
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const PresentationalComponent = mockedComponent.find('Presentational'); return ( PresentationalComponent.find('div').length === 1 && PresentationalComponent.find('h2').length === 1 && PresentationalComponent.find('button').length === 1 && PresentationalComponent.find('ul').length === 1 ); })(), 'message: The <code>Presentational</code> component should render an <code>h2</code>, <code>input</code>, <code>button</code>, and <code>ul</code> elements.');",
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const PresentationalComponent = mockedComponent.find('Presentational'); const props = PresentationalComponent.props(); return Array.isArray(props.messages); })(), 'message: The <code>Presentational</code> component should receive <code>messages</code> from the Redux store as a prop.');",
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const PresentationalComponent = mockedComponent.find('Presentational'); const props = PresentationalComponent.props(); return typeof props.submitNewMessage === 'function'; })(), 'message: The <code>Presentational</code> component should receive the <code>submitMessage</code> action creator as a prop.');",
"assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const PresentationalState = mockedComponent.find('Presentational').instance().state; return typeof PresentationalState.input === 'string' && Object.keys(PresentationalState).length === 1; })(), 'message: The state of the <code>Presentational</code> component should contain one property, <code>input</code>, which is initialized to an empty string.');",
"async () => { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const testValue = '__MOCK__INPUT__'; const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); const causeChange = (c, v) => c.find('input').simulate('change', { target: { value: v }}); let initialInput = mockedComponent.find('Presentational').find('input'); const changed = () => { causeChange(mockedComponent, testValue); return waitForIt(() => mockedComponent )}; const updated = await changed(); const updatedInput = updated.find('Presentational').find('input'); assert(initialInput.props().value === '' && updatedInput.props().value === '__MOCK__INPUT__', 'message: Typing in the <code>input</code> element should update the state of the <code>Presentational</code> component.'); }; ",
"async () => { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); let beforeProps = mockedComponent.find('Presentational').props(); const testValue = '__TEST__EVENT__INPUT__'; const causeChange = (c, v) => c.find('input').simulate('change', { target: { value: v }}); const changed = () => { causeChange(mockedComponent, testValue); return waitForIt(() => mockedComponent )}; const clickButton = () => { mockedComponent.find('button').simulate('click'); return waitForIt(() => mockedComponent )}; const afterChange = await changed(); const afterChangeInput = afterChange.find('input').props().value; const afterClick = await clickButton(); const afterProps = mockedComponent.find('Presentational').props(); assert(beforeProps.messages.length === 0 && afterChangeInput === testValue && afterProps.messages.pop() === testValue && afterClick.find('input').props().value === '', 'message: Dispatching the <code>submitMessage</code> on the <code>Presentational</code> component should update Redux store and clear the input in local state.'); }; ",
"async () => { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); let beforeProps = mockedComponent.find('Presentational').props(); const testValue = '__TEST__EVENT__INPUT__'; const causeChange = (c, v) => c.find('input').simulate('change', { target: { value: v }}); const changed = () => { causeChange(mockedComponent, testValue); return waitForIt(() => mockedComponent )}; const clickButton = () => { mockedComponent.find('button').simulate('click'); return waitForIt(() => mockedComponent )}; const afterChange = await changed(); const afterChangeInput = afterChange.find('input').props().value; const afterClick = await clickButton(); const afterProps = mockedComponent.find('Presentational').props(); assert(beforeProps.messages.length === 0 && afterChangeInput === testValue && afterProps.messages.pop() === testValue && afterClick.find('input').props().value === '' && afterClick.find('ul').childAt(0).text() === testValue, 'message: The <code>Presentational</code> component should render the <code>messages</code> from the Redux store.'); }; "
{
"text": "The <code>AppWrapper</code> should render to the page.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('AppWrapper').length === 1; })(), 'The <code>AppWrapper</code> should render to the page.');"
},
{
"text": "The <code>Presentational</code> component should render an <code>h2</code>, <code>input</code>, <code>button</code>, and <code>ul</code> elements.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('Presentational').length === 1; })(), 'The <code>Presentational</code> component should render an <code>h2</code>, <code>input</code>, <code>button</code>, and <code>ul</code> elements.');"
},
{
"text": "The <code>Presentational</code> component should render an <code>h2</code>, <code>input</code>, <code>button</code>, and <code>ul</code> elements.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const PresentationalComponent = mockedComponent.find('Presentational'); return ( PresentationalComponent.find('div').length === 1 && PresentationalComponent.find('h2').length === 1 && PresentationalComponent.find('button').length === 1 && PresentationalComponent.find('ul').length === 1 ); })(), 'The <code>Presentational</code> component should render an <code>h2</code>, <code>input</code>, <code>button</code>, and <code>ul</code> elements.');"
},
{
"text": "The <code>Presentational</code> component should receive <code>messages</code> from the Redux store as a prop.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const PresentationalComponent = mockedComponent.find('Presentational'); const props = PresentationalComponent.props(); return Array.isArray(props.messages); })(), 'The <code>Presentational</code> component should receive <code>messages</code> from the Redux store as a prop.');"
},
{
"text": "The <code>Presentational</code> component should receive the <code>submitMessage</code> action creator as a prop.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const PresentationalComponent = mockedComponent.find('Presentational'); const props = PresentationalComponent.props(); return typeof props.submitNewMessage === 'function'; })(), 'The <code>Presentational</code> component should receive the <code>submitMessage</code> action creator as a prop.');"
},
{
"text": "The state of the <code>Presentational</code> component should contain one property, <code>input</code>, which is initialized to an empty string.",
"testString": "assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const PresentationalState = mockedComponent.find('Presentational').instance().state; return typeof PresentationalState.input === 'string' && Object.keys(PresentationalState).length === 1; })(), 'The state of the <code>Presentational</code> component should contain one property, <code>input</code>, which is initialized to an empty string.');"
},
{
"text": "Typing in the <code>input</code> element should update the state of the <code>Presentational</code> component.",
"testString": "async () => { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const testValue = '__MOCK__INPUT__'; const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); const causeChange = (c, v) => c.find('input').simulate('change', { target: { value: v }}); let initialInput = mockedComponent.find('Presentational').find('input'); const changed = () => { causeChange(mockedComponent, testValue); return waitForIt(() => mockedComponent )}; const updated = await changed(); const updatedInput = updated.find('Presentational').find('input'); assert(initialInput.props().value === '' && updatedInput.props().value === '__MOCK__INPUT__', 'Typing in the <code>input</code> element should update the state of the <code>Presentational</code> component.'); }; "
},
{
"text": "Dispatching the <code>submitMessage</code> on the <code>Presentational</code> component should update Redux store and clear the input in local state.",
"testString": "async () => { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); let beforeProps = mockedComponent.find('Presentational').props(); const testValue = '__TEST__EVENT__INPUT__'; const causeChange = (c, v) => c.find('input').simulate('change', { target: { value: v }}); const changed = () => { causeChange(mockedComponent, testValue); return waitForIt(() => mockedComponent )}; const clickButton = () => { mockedComponent.find('button').simulate('click'); return waitForIt(() => mockedComponent )}; const afterChange = await changed(); const afterChangeInput = afterChange.find('input').props().value; const afterClick = await clickButton(); const afterProps = mockedComponent.find('Presentational').props(); assert(beforeProps.messages.length === 0 && afterChangeInput === testValue && afterProps.messages.pop() === testValue && afterClick.find('input').props().value === '', 'Dispatching the <code>submitMessage</code> on the <code>Presentational</code> component should update Redux store and clear the input in local state.'); }; "
},
{
"text": "The <code>Presentational</code> component should render the <code>messages</code> from the Redux store.",
"testString": "async () => { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 100)); let beforeProps = mockedComponent.find('Presentational').props(); const testValue = '__TEST__EVENT__INPUT__'; const causeChange = (c, v) => c.find('input').simulate('change', { target: { value: v }}); const changed = () => { causeChange(mockedComponent, testValue); return waitForIt(() => mockedComponent )}; const clickButton = () => { mockedComponent.find('button').simulate('click'); return waitForIt(() => mockedComponent )}; const afterChange = await changed(); const afterChangeInput = afterChange.find('input').props().value; const afterClick = await clickButton(); const afterProps = mockedComponent.find('Presentational').props(); assert(beforeProps.messages.length === 0 && afterChangeInput === testValue && afterProps.messages.pop() === testValue && afterClick.find('input').props().value === '' && afterClick.find('ul').childAt(0).text() === testValue, 'The <code>Presentational</code> component should render the <code>messages</code> from the Redux store.'); }; "
}
],
"solutions": [
"// Redux:\nconst ADD = 'ADD';\n\nconst addMessage = (message) => {\n return {\n type: ADD,\n message: message\n }\n};\n\nconst messageReducer = (state = [], action) => {\n switch (action.type) {\n case ADD:\n return [\n ...state,\n action.message\n ];\n default:\n return state;\n }\n};\n\nconst store = Redux.createStore(messageReducer);\n\n// React:\nconst Provider = ReactRedux.Provider;\nconst connect = ReactRedux.connect;\n\n// Change code below this line\nclass Presentational extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n input: ''\n }\n this.handleChange = this.handleChange.bind(this); \n this.submitMessage = this.submitMessage.bind(this); \n }\n handleChange(event) {\n this.setState({\n input: event.target.value\n });\n }\n submitMessage() {\n this.props.submitNewMessage(this.state.input);\n this.setState({\n input: ''\n });\n }\n render() {\n return (\n <div>\n <h2>Type in a new Message:</h2>\n <input\n value={this.state.input}\n onChange={this.handleChange}/><br/>\n <button onClick={this.submitMessage}>Submit</button>\n <ul>\n {this.props.messages.map( (message, idx) => {\n return (\n <li key={idx}>{message}</li>\n )\n })\n }\n </ul>\n </div>\n );\n }\n};\n// Change code above this line\n\nconst mapStateToProps = (state) => {\n return {messages: state}\n};\n\nconst mapDispatchToProps = (dispatch) => {\n return {\n submitNewMessage: (message) => {\n dispatch(addMessage(message))\n }\n }\n};\n\nconst Container = connect(mapStateToProps, mapDispatchToProps)(Presentational);\n\nclass AppWrapper extends React.Component {\n render() {\n return (\n <Provider store={store}>\n <Container/>\n </Provider>\n );\n }\n};"
@ -740,11 +894,16 @@
"",
"// change code below this line",
""
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert(editor.getValue().includes('console.log(\"Now I know React and Redux!\")') || editor.getValue().includes('console.log(\\'Now I know React and Redux!\\')'), 'message: The message <code>Now I know React and Redux!</code> should be logged to the console.');"
{
"text": "The message <code>Now I know React and Redux!</code> should be logged to the console.",
"testString": "assert(editor.getValue().includes('console.log(\"Now I know React and Redux!\")') || editor.getValue().includes('console.log(\\'Now I know React and Redux!\\')'), 'The message <code>Now I know React and Redux!</code> should be logged to the console.');"
}
],
"solutions": [
"console.log('Now I know React and Redux!');"

File diff suppressed because it is too large Load Diff

View File

@ -40,12 +40,20 @@
"// Define the store here:",
"",
""
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert(typeof store.getState === 'function', 'message: The redux store exists.');",
"assert(store.getState()=== 5, 'message: The redux store has a value of 5 for the state.');"
{
"text": "The redux store exists.",
"testString": "assert(typeof store.getState === 'function', 'The redux store exists.');"
},
{
"text": "The redux store has a value of 5 for the state.",
"testString": "assert(store.getState()=== 5, 'The redux store has a value of 5 for the state.');"
}
],
"solutions": [
"const reducer = (state = 5) => {\n return state;\n}\n\n// Redux methods are available from a Redux object\n// For example: Redux.createStore()\n// Define the store here:\n\nconst store = Redux.createStore(reducer);"
@ -76,12 +84,20 @@
"",
"// change code below this line",
""
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert(store.getState()===5, 'message: The redux store should have a value of 5 for the initial state.');",
"getUserInput => assert(currentState === 5 && getUserInput('index').includes('store.getState()'), 'message: A variable <code>currentState</code> should exist and should be assigned the current state of the Redux store.');"
{
"text": "The redux store should have a value of 5 for the initial state.",
"testString": "assert(store.getState()===5, 'The redux store should have a value of 5 for the initial state.');"
},
{
"text": "A variable <code>currentState</code> should exist and should be assigned the current state of the Redux store.",
"testString": "getUserInput => assert(currentState === 5 && getUserInput('index').includes('store.getState()'), 'A variable <code>currentState</code> should exist and should be assigned the current state of the Redux store.');"
}
],
"solutions": [
"const store = Redux.createStore(\n (state = 5) => state\n);\n\n// change code below this line\nconst currentState = store.getState();"
@ -109,12 +125,20 @@
"contents": [
"// Define an action here:",
""
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert((function() { return typeof action === 'object' })(), 'message: An action object should exist.');",
"assert((function() { return action.type === 'LOGIN' })(), 'message: The action should have a key property type with value <code>LOGIN</code>.');"
{
"text": "An action object should exist.",
"testString": "assert((function() { return typeof action === 'object' })(), 'An action object should exist.');"
},
{
"text": "The action should have a key property type with value <code>LOGIN</code>.",
"testString": "assert((function() { return action.type === 'LOGIN' })(), 'The action should have a key property type with value <code>LOGIN</code>.');"
}
],
"solutions": [
"const action = {\n type: 'LOGIN'\n}"
@ -144,13 +168,24 @@
"}",
"// Define an action creator here:",
""
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert(typeof actionCreator === 'function', 'message: The function <code>actionCreator</code> should exist.');",
"assert(typeof action === 'object', 'message: Running the <code>actionCreator</code> function should return the action object.');",
"assert(action.type === 'LOGIN', 'message: The returned action should have a key property type with value <code>LOGIN</code>.');"
{
"text": "The function <code>actionCreator</code> should exist.",
"testString": "assert(typeof actionCreator === 'function', 'The function <code>actionCreator</code> should exist.');"
},
{
"text": "Running the <code>actionCreator</code> function should return the action object.",
"testString": "assert(typeof action === 'object', 'Running the <code>actionCreator</code> function should return the action object.');"
},
{
"text": "The returned action should have a key property type with value <code>LOGIN</code>.",
"testString": "assert(action.type === 'LOGIN', 'The returned action should have a key property type with value <code>LOGIN</code>.');"
}
],
"solutions": [
"const action = {\n type: 'LOGIN'\n}\n// Define an action creator here:\nconst actionCreator = () => {\n return action;\n};"
@ -189,13 +224,24 @@
"",
"// Dispatch the action here:",
""
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert(loginAction().type === 'LOGIN', 'message: Calling the function <code>loginAction</code> should return an object with <code>type</code> property set to the string <code>LOGIN</code>.');",
"assert(store.getState().login === false, 'message: The store should be initialized with an object with property <code>login</code> set to <code>false</code>.');",
"getUserInput => assert((function() { let noWhiteSpace = getUserInput('index').replace(/\\s/g,''); return noWhiteSpace.includes('store.dispatch(loginAction())') || noWhiteSpace.includes('store.dispatch({type: \\'LOGIN\\'})') === true })(), 'message: The <code>store.dispatch()</code> method should be used to dispatch an action of type <code>LOGIN</code>.');"
{
"text": "Calling the function <code>loginAction</code> should return an object with <code>type</code> property set to the string <code>LOGIN</code>.",
"testString": "assert(loginAction().type === 'LOGIN', 'Calling the function <code>loginAction</code> should return an object with <code>type</code> property set to the string <code>LOGIN</code>.');"
},
{
"text": "The store should be initialized with an object with property <code>login</code> set to <code>false</code>.",
"testString": "assert(store.getState().login === false, 'The store should be initialized with an object with property <code>login</code> set to <code>false</code>.');"
},
{
"text": "The <code>store.dispatch()</code> method should be used to dispatch an action of type <code>LOGIN</code>.",
"testString": "getUserInput => assert((function() { let noWhiteSpace = getUserInput('index').replace(/\\s/g,''); return noWhiteSpace.includes('store.dispatch(loginAction())') || noWhiteSpace.includes('store.dispatch({type: \\'LOGIN\\'})') === true })(), 'The <code>store.dispatch()</code> method should be used to dispatch an action of type <code>LOGIN</code>.');"
}
],
"solutions": [
"const store = Redux.createStore(\n (state = {login: false}) => state\n);\n\nconst loginAction = () => {\n return {\n type: 'LOGIN'\n }\n};\n\n// Dispatch the action here:\nstore.dispatch(loginAction());"
@ -238,14 +284,28 @@
" type: 'LOGIN'",
" }",
"};"
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert(loginAction().type === 'LOGIN', 'message: Calling the function <code>loginAction</code> should return an object with type property set to the string <code>LOGIN</code>.');",
"assert(store.getState().login === false, 'message: The store should be initialized with an object with property <code>login</code> set to <code>false</code>.');",
"assert((function() { const initialState = store.getState(); store.dispatch(loginAction()); const afterState = store.getState(); return initialState.login === false && afterState.login === true })(), 'message: Dispatching <code>loginAction</code> should update the <code>login</code> property in the store state to <code>true</code>.');",
"assert((function() { store.dispatch({type: '__TEST__ACTION__'}); let afterTest = store.getState(); return typeof afterTest === 'object' && afterTest.hasOwnProperty('login') })(), 'message: If the action is not of type <code>LOGIN</code>, the store should return the current state.');"
{
"text": "Calling the function <code>loginAction</code> should return an object with type property set to the string <code>LOGIN</code>.",
"testString": "assert(loginAction().type === 'LOGIN', 'Calling the function <code>loginAction</code> should return an object with type property set to the string <code>LOGIN</code>.');"
},
{
"text": "The store should be initialized with an object with property <code>login</code> set to <code>false</code>.",
"testString": "assert(store.getState().login === false, 'The store should be initialized with an object with property <code>login</code> set to <code>false</code>.');"
},
{
"text": "Dispatching <code>loginAction</code> should update the <code>login</code> property in the store state to <code>true</code>.",
"testString": "assert((function() { const initialState = store.getState(); store.dispatch(loginAction()); const afterState = store.getState(); return initialState.login === false && afterState.login === true })(), 'Dispatching <code>loginAction</code> should update the <code>login</code> property in the store state to <code>true</code>.');"
},
{
"text": "If the action is not of type <code>LOGIN</code>, the store should return the current state.",
"testString": "assert((function() { store.dispatch({type: '__TEST__ACTION__'}); let afterTest = store.getState(); return typeof afterTest === 'object' && afterTest.hasOwnProperty('login') })(), 'If the action is not of type <code>LOGIN</code>, the store should return the current state.');"
}
],
"solutions": [
"const defaultState = {\n login: false\n};\n\nconst reducer = (state = defaultState, action) => {\n\n if (action.type === 'LOGIN') {\n return {login: true}\n }\n\n else {\n return state\n }\n\n};\n\nconst store = Redux.createStore(reducer);\n\nconst loginAction = () => {\n return {\n type: 'LOGIN'\n }\n};"
@ -294,16 +354,36 @@
" type: 'LOGOUT'",
" }",
"};"
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert(loginUser().type === 'LOGIN', 'message: Calling the function <code>loginUser</code> should return an object with type property set to the string <code>LOGIN</code>.');",
"assert(logoutUser().type === 'LOGOUT', 'message: Calling the function <code>logoutUser</code> should return an object with type property set to the string <code>LOGOUT</code>.');",
"assert(store.getState().authenticated === false, 'message: The store should be initialized with an object with an <code>authenticated</code> property set to <code>false</code>.');",
"assert((function() { const initialState = store.getState(); store.dispatch(loginUser()); const afterLogin = store.getState(); return initialState.authenticated === false && afterLogin.authenticated === true })(), 'message: Dispatching <code>loginUser</code> should update the <code>authenticated</code> property in the store state to <code>true</code>.');",
"assert((function() { store.dispatch(loginUser()); const loggedIn = store.getState(); store.dispatch(logoutUser()); const afterLogout = store.getState(); return loggedIn.authenticated === true && afterLogout.authenticated === false })(), 'message: Dispatching <code>logoutUser</code> should update the <code>authenticated</code> property in the store state to <code>false</code>.');",
"getUserInput => assert( getUserInput('index').toString().includes('switch') && getUserInput('index').toString().includes('case') && getUserInput('index').toString().includes('default'), 'message: The <code>authReducer</code> function should handle multiple action types with a <code>switch</code> statement.');"
{
"text": "Calling the function <code>loginUser</code> should return an object with type property set to the string <code>LOGIN</code>.",
"testString": "assert(loginUser().type === 'LOGIN', 'Calling the function <code>loginUser</code> should return an object with type property set to the string <code>LOGIN</code>.');"
},
{
"text": "Calling the function <code>logoutUser</code> should return an object with type property set to the string <code>LOGOUT</code>.",
"testString": "assert(logoutUser().type === 'LOGOUT', 'Calling the function <code>logoutUser</code> should return an object with type property set to the string <code>LOGOUT</code>.');"
},
{
"text": "The store should be initialized with an object with an <code>authenticated</code> property set to <code>false</code>.",
"testString": "assert(store.getState().authenticated === false, 'The store should be initialized with an object with an <code>authenticated</code> property set to <code>false</code>.');"
},
{
"text": "Dispatching <code>loginUser</code> should update the <code>authenticated</code> property in the store state to <code>true</code>.",
"testString": "assert((function() { const initialState = store.getState(); store.dispatch(loginUser()); const afterLogin = store.getState(); return initialState.authenticated === false && afterLogin.authenticated === true })(), 'Dispatching <code>loginUser</code> should update the <code>authenticated</code> property in the store state to <code>true</code>.');"
},
{
"text": "Dispatching <code>logoutUser</code> should update the <code>authenticated</code> property in the store state to <code>false</code>.",
"testString": "assert((function() { store.dispatch(loginUser()); const loggedIn = store.getState(); store.dispatch(logoutUser()); const afterLogout = store.getState(); return loggedIn.authenticated === true && afterLogout.authenticated === false })(), 'Dispatching <code>logoutUser</code> should update the <code>authenticated</code> property in the store state to <code>false</code>.');"
},
{
"text": "The <code>authReducer</code> function should handle multiple action types with a <code>switch</code> statement.",
"testString": "getUserInput => assert( getUserInput('index').toString().includes('switch') && getUserInput('index').toString().includes('case') && getUserInput('index').toString().includes('default'), 'The <code>authReducer</code> function should handle multiple action types with a <code>switch</code> statement.');"
}
],
"solutions": [
"const defaultState = {\n authenticated: false\n};\n\nconst authReducer = (state = defaultState, action) => {\n\n switch (action.type) {\n\n case 'LOGIN':\n return {\n authenticated: true\n }\n\n case 'LOGOUT':\n return {\n authenticated: false\n }\n\n default:\n return state;\n\n }\n\n};\n\nconst store = Redux.createStore(authReducer);\n\nconst loginUser = () => {\n return {\n type: 'LOGIN'\n }\n};\n\nconst logoutUser = () => {\n return {\n type: 'LOGOUT'\n }\n};"
@ -371,18 +451,44 @@
" type: 'LOGOUT'",
" }",
"};"
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert(loginUser().type === 'LOGIN', 'message: Calling the function <code>loginUser</code> should return an object with <code>type</code> property set to the string <code>LOGIN</code>.');",
"assert(logoutUser().type === 'LOGOUT', 'message: Calling the function <code>logoutUser</code> should return an object with <code>type</code> property set to the string <code>LOGOUT</code>.');",
"assert(store.getState().authenticated === false, 'message: The store should be initialized with an object with property <code>login</code> set to <code>false</code>.');",
"assert((function() { const initialState = store.getState(); store.dispatch(loginUser()); const afterLogin = store.getState(); return initialState.authenticated === false && afterLogin.authenticated === true })(), 'message: Dispatching <code>loginUser</code> should update the <code>login</code> property in the store state to <code>true</code>.');",
"assert((function() { store.dispatch(loginUser()); const loggedIn = store.getState(); store.dispatch(logoutUser()); const afterLogout = store.getState(); return loggedIn.authenticated === true && afterLogout.authenticated === false })(), 'message: Dispatching <code>logoutUser</code> should update the <code>login</code> property in the store state to <code>false</code>.');",
"getUserInput => assert((function() { return typeof authReducer === 'function' && getUserInput('index').toString().includes('switch') && getUserInput('index').toString().includes('case') && getUserInput('index').toString().includes('default') })(), 'message: The <code>authReducer</code> function should handle multiple action types with a switch statement.');",
"getUserInput => assert((function() { const noWhiteSpace = getUserInput('index').toString().replace(/\\s/g,''); return (noWhiteSpace.includes('constLOGIN=\\'LOGIN\\'') || noWhiteSpace.includes('constLOGIN=\"LOGIN\"')) && (noWhiteSpace.includes('constLOGOUT=\\'LOGOUT\\'') || noWhiteSpace.includes('constLOGOUT=\"LOGOUT\"')) })(), 'message: <code>LOGIN</code> and <code>LOGOUT</code> should be declared as <code>const</code> values and should be assigned strings of <code>LOGIN</code>and <code>LOGOUT</code>.');",
"getUserInput => assert((function() { const noWhiteSpace = getUserInput('index').toString().replace(/\\s/g,''); return noWhiteSpace.includes('caseLOGIN:') && noWhiteSpace.includes('caseLOGOUT:') && noWhiteSpace.includes('type:LOGIN') && noWhiteSpace.includes('type:LOGOUT') })(), 'message: The action creators and the reducer should reference the <code>LOGIN</code> and <code>LOGOUT</code> constants.');"
{
"text": "Calling the function <code>loginUser</code> should return an object with <code>type</code> property set to the string <code>LOGIN</code>.",
"testString": "assert(loginUser().type === 'LOGIN', 'Calling the function <code>loginUser</code> should return an object with <code>type</code> property set to the string <code>LOGIN</code>.');"
},
{
"text": "Calling the function <code>logoutUser</code> should return an object with <code>type</code> property set to the string <code>LOGOUT</code>.",
"testString": "assert(logoutUser().type === 'LOGOUT', 'Calling the function <code>logoutUser</code> should return an object with <code>type</code> property set to the string <code>LOGOUT</code>.');"
},
{
"text": "The store should be initialized with an object with property <code>login</code> set to <code>false</code>.",
"testString": "assert(store.getState().authenticated === false, 'The store should be initialized with an object with property <code>login</code> set to <code>false</code>.');"
},
{
"text": "Dispatching <code>loginUser</code> should update the <code>login</code> property in the store state to <code>true</code>.",
"testString": "assert((function() { const initialState = store.getState(); store.dispatch(loginUser()); const afterLogin = store.getState(); return initialState.authenticated === false && afterLogin.authenticated === true })(), 'Dispatching <code>loginUser</code> should update the <code>login</code> property in the store state to <code>true</code>.');"
},
{
"text": "Dispatching <code>logoutUser</code> should update the <code>login</code> property in the store state to <code>false</code>.",
"testString": "assert((function() { store.dispatch(loginUser()); const loggedIn = store.getState(); store.dispatch(logoutUser()); const afterLogout = store.getState(); return loggedIn.authenticated === true && afterLogout.authenticated === false })(), 'Dispatching <code>logoutUser</code> should update the <code>login</code> property in the store state to <code>false</code>.');"
},
{
"text": "The <code>authReducer</code> function should handle multiple action types with a switch statement.",
"testString": "getUserInput => assert((function() { return typeof authReducer === 'function' && getUserInput('index').toString().includes('switch') && getUserInput('index').toString().includes('case') && getUserInput('index').toString().includes('default') })(), 'The <code>authReducer</code> function should handle multiple action types with a switch statement.');"
},
{
"text": "<code>LOGIN</code> and <code>LOGOUT</code> should be declared as <code>const</code> values and should be assigned strings of <code>LOGIN</code>and <code>LOGOUT</code>.",
"testString": "getUserInput => assert((function() { const noWhiteSpace = getUserInput('index').toString().replace(/\\s/g,''); return (noWhiteSpace.includes('constLOGIN=\\'LOGIN\\'') || noWhiteSpace.includes('constLOGIN=\"LOGIN\"')) && (noWhiteSpace.includes('constLOGOUT=\\'LOGOUT\\'') || noWhiteSpace.includes('constLOGOUT=\"LOGOUT\"')) })(), '<code>LOGIN</code> and <code>LOGOUT</code> should be declared as <code>const</code> values and should be assigned strings of <code>LOGIN</code>and <code>LOGOUT</code>.');"
},
{
"text": "The action creators and the reducer should reference the <code>LOGIN</code> and <code>LOGOUT</code> constants.",
"testString": "getUserInput => assert((function() { const noWhiteSpace = getUserInput('index').toString().replace(/\\s/g,''); return noWhiteSpace.includes('caseLOGIN:') && noWhiteSpace.includes('caseLOGOUT:') && noWhiteSpace.includes('type:LOGIN') && noWhiteSpace.includes('type:LOGOUT') })(), 'The action creators and the reducer should reference the <code>LOGIN</code> and <code>LOGOUT</code> constants.');"
}
],
"solutions": [
"const LOGIN = 'LOGIN';\nconst LOGOUT = 'LOGOUT';\n\nconst defaultState = {\n authenticated: false\n};\n\nconst authReducer = (state = defaultState, action) => {\n\n switch (action.type) {\n\n case LOGIN:\n return {\n authenticated: true\n }\n\n case LOGOUT:\n return {\n authenticated: false\n }\n\n default:\n return state;\n\n }\n\n};\n\nconst store = Redux.createStore(authReducer);\n\nconst loginUser = () => {\n return {\n type: LOGIN\n }\n};\n\nconst logoutUser = () => {\n return {\n type: LOGOUT\n }\n};"
@ -436,13 +542,23 @@
"console.log(count);",
"store.dispatch({type: ADD});",
"console.log(count);"
]
],
"tail": []
}
},
"tests": [
"assert((function() { const initialState = store.getState(); store.dispatch({ type: 'ADD' }); const newState = store.getState(); return newState === (initialState + 1); })(), 'message: Dispatching the <code>ADD</code> action on the store should increment the state by <code>1</code>.');",
"getUserInput => assert(getUserInput('index').includes('store.subscribe('), 'message: There should be a listener function subscribed to the store using <code>store.subscribe</code>.');",
"assert(store.getState() === count, 'message: The callback to <code>store.subscribe</code> should also increment the global <code>count</code> variable as the store is updated.');"
{
"text": "Dispatching the <code>ADD</code> action on the store should increment the state by <code>1</code>.",
"testString": "assert((function() { const initialState = store.getState(); store.dispatch({ type: 'ADD' }); const newState = store.getState(); return newState === (initialState + 1); })(), 'Dispatching the <code>ADD</code> action on the store should increment the state by <code>1</code>.');"
},
{
"text": "There should be a listener function subscribed to the store using <code>store.subscribe</code>.",
"testString": "getUserInput => assert(getUserInput('index').includes('store.subscribe('), 'There should be a listener function subscribed to the store using <code>store.subscribe</code>.');"
},
{
"text": "The callback to <code>store.subscribe</code> should also increment the global <code>count</code> variable as the store is updated.",
"testString": "assert(store.getState() === count, 'The callback to <code>store.subscribe</code> should also increment the global <code>count</code> variable as the store is updated.');"
}
],
"solutions": [
"const ADD = 'ADD';\n\nconst reducer = (state = 0, action) => {\n switch(action.type) {\n case ADD:\n return state + 1;\n default:\n return state;\n }\n};\n\nconst store = Redux.createStore(reducer);\n let count = 0; \n// change code below this line\n\nstore.subscribe( () =>\n { \n count++; \n } \n);\n\n// change code above this line\n\nstore.dispatch({type: ADD});\nstore.dispatch({type: ADD});\nstore.dispatch({type: ADD});"
@ -507,14 +623,28 @@
"",
"const store = Redux.createStore(rootReducer);",
""
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert((function() { const initalState = store.getState().count; store.dispatch({type: INCREMENT}); store.dispatch({type: INCREMENT}); const firstState = store.getState().count; store.dispatch({type: DECREMENT}); const secondState = store.getState().count; return firstState === initalState + 2 && secondState === firstState - 1 })(), 'message: The <code>counterReducer</code> should increment and decrement the <code>state</code>.');",
"assert((function() { store.dispatch({type: LOGIN}); const loggedIn = store.getState().auth.authenticated; store.dispatch({type: LOGOUT}); const loggedOut = store.getState().auth.authenticated; return loggedIn === true && loggedOut === false })(), 'message: The <code>authReducer</code> should toggle the <code>state</code> of <code>authenticated</code> between <code>true</code> and <code>false</code>.');",
"assert((function() { const state = store.getState(); return typeof state.auth === 'object' && typeof state.auth.authenticated === 'boolean' && typeof state.count === 'number' })(), 'message: The store <code>state</code> should have two keys: <code>count</code>, which holds a number, and <code>auth</code>, which holds an object. The <code>auth</code> object should have a property of <code>authenticated</code>, which holds a boolean.');",
"getUserInput => assert((function() { const noWhiteSpace = getUserInput('index').replace(/\\s/g,''); return typeof rootReducer === 'function' && noWhiteSpace.includes('Redux.combineReducers') })(), 'message: The <code>rootReducer</code> should be a function that combines the <code>counterReducer</code> and the <code>authReducer</code>.');"
{
"text": "The <code>counterReducer</code> should increment and decrement the <code>state</code>.",
"testString": "assert((function() { const initalState = store.getState().count; store.dispatch({type: INCREMENT}); store.dispatch({type: INCREMENT}); const firstState = store.getState().count; store.dispatch({type: DECREMENT}); const secondState = store.getState().count; return firstState === initalState + 2 && secondState === firstState - 1 })(), 'The <code>counterReducer</code> should increment and decrement the <code>state</code>.');"
},
{
"text": "The <code>authReducer</code> should toggle the <code>state</code> of <code>authenticated</code> between <code>true</code> and <code>false</code>.",
"testString": "assert((function() { store.dispatch({type: LOGIN}); const loggedIn = store.getState().auth.authenticated; store.dispatch({type: LOGOUT}); const loggedOut = store.getState().auth.authenticated; return loggedIn === true && loggedOut === false })(), 'The <code>authReducer</code> should toggle the <code>state</code> of <code>authenticated</code> between <code>true</code> and <code>false</code>.');"
},
{
"text": "The store <code>state</code> should have two keys: <code>count</code>, which holds a number, and <code>auth</code>, which holds an object. The <code>auth</code> object should have a property of <code>authenticated</code>, which holds a boolean.",
"testString": "assert((function() { const state = store.getState(); return typeof state.auth === 'object' && typeof state.auth.authenticated === 'boolean' && typeof state.count === 'number' })(), 'The store <code>state</code> should have two keys: <code>count</code>, which holds a number, and <code>auth</code>, which holds an object. The <code>auth</code> object should have a property of <code>authenticated</code>, which holds a boolean.');"
},
{
"text": "The <code>rootReducer</code> should be a function that combines the <code>counterReducer</code> and the <code>authReducer</code>.",
"testString": "getUserInput => assert((function() { const noWhiteSpace = getUserInput('index').replace(/\\s/g,''); return typeof rootReducer === 'function' && noWhiteSpace.includes('Redux.combineReducers') })(), 'The <code>rootReducer</code> should be a function that combines the <code>counterReducer</code> and the <code>authReducer</code>.');"
}
],
"solutions": [
"const INCREMENT = 'INCREMENT';\nconst DECREMENT = 'DECREMENT';\n\nconst counterReducer = (state = 0, action) => {\n switch(action.type) {\n case INCREMENT:\n return state + 1;\n case DECREMENT:\n return state - 1;\n default:\n return state;\n }\n};\n\nconst LOGIN = 'LOGIN';\nconst LOGOUT = 'LOGOUT';\n\nconst authReducer = (state = {authenticated: false}, action) => {\n switch(action.type) {\n case LOGIN:\n return {\n authenticated: true\n }\n case LOGOUT:\n return {\n authenticated: false\n }\n default:\n return state;\n }\n};\n\nconst rootReducer = Redux.combineReducers({\n count: counterReducer,\n auth: authReducer\n});\n\nconst store = Redux.createStore(rootReducer);"
@ -564,12 +694,20 @@
"console.log(store.getState());",
"store.dispatch(addNoteText('Hello!'));",
"console.log(store.getState());"
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert((function() { const addNoteFn = addNoteText('__TEST__NOTE'); return addNoteFn.type === ADD_NOTE && addNoteFn.text === '__TEST__NOTE' })(), 'message: The action creator <code>addNoteText</code> should return an object with keys <code>type</code> and <code>text</code>.');",
"assert((function() { const initialState = store.getState(); store.dispatch(addNoteText('__TEST__NOTE')); const newState = store.getState(); return initialState !== newState && newState === '__TEST__NOTE' })(), 'message: Dispatching an action of type <code>ADD_NOTE</code> with the <code>addNoteText</code> action creator should update the <code>state</code> to the string passed to the action creator.');"
{
"text": "The action creator <code>addNoteText</code> should return an object with keys <code>type</code> and <code>text</code>.",
"testString": "assert((function() { const addNoteFn = addNoteText('__TEST__NOTE'); return addNoteFn.type === ADD_NOTE && addNoteFn.text === '__TEST__NOTE' })(), 'The action creator <code>addNoteText</code> should return an object with keys <code>type</code> and <code>text</code>.');"
},
{
"text": "Dispatching an action of type <code>ADD_NOTE</code> with the <code>addNoteText</code> action creator should update the <code>state</code> to the string passed to the action creator.",
"testString": "assert((function() { const initialState = store.getState(); store.dispatch(addNoteText('__TEST__NOTE')); const newState = store.getState(); return initialState !== newState && newState === '__TEST__NOTE' })(), 'Dispatching an action of type <code>ADD_NOTE</code> with the <code>addNoteText</code> action creator should update the <code>state</code> to the string passed to the action creator.');"
}
],
"solutions": [
"const ADD_NOTE = 'ADD_NOTE';\n\nconst notesReducer = (state = 'Initial State', action) => {\n switch(action.type) {\n // change code below this line\n case ADD_NOTE:\n return action.text;\n // change code above this line\n default:\n return state;\n }\n};\n\nconst addNoteText = (note) => {\n // change code below this line\n return {\n type: ADD_NOTE,\n text: note\n }\n // change code above this line\n};\n\nconst store = Redux.createStore(notesReducer);\n\nconsole.log(store.getState());\nstore.dispatch(addNoteText('Hello Redux!'));\nconsole.log(store.getState());"
@ -643,15 +781,32 @@
" asyncDataReducer,",
" Redux.applyMiddleware(ReduxThunk.default)",
");"
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert(requestingData().type === REQUESTING_DATA, 'message: The <code>requestingData</code> action creator should return an object of type equal to the value of <code>REQUESTING_DATA</code>.');",
"assert(receivedData('data').type === RECEIVED_DATA, 'message: The <code>receivedData</code> action creator should return an object of type equal to the value of <code>RECEIVED_DATA</code>.');",
"assert(typeof asyncDataReducer === 'function', 'message: <code>asyncDataReducer</code> should be a function.');",
"assert((function() { const initialState = store.getState(); store.dispatch(requestingData()); const reqState = store.getState(); return initialState.fetching === false && reqState.fetching === true })(), 'message: Dispatching the requestingData action creator should update the store <code>state</code> property of fetching to <code>true</code>.');",
"assert((function() { const noWhiteSpace = handleAsync.toString().replace(/\\s/g,''); return noWhiteSpace.includes('dispatch(requestingData())') === true && noWhiteSpace.includes('dispatch(receivedData(data))') === true })(), 'message: Dispatching <code>handleAsync</code> should dispatch the data request action and then dispatch the received data action after a delay.');"
{
"text": "The <code>requestingData</code> action creator should return an object of type equal to the value of <code>REQUESTING_DATA</code>.",
"testString": "assert(requestingData().type === REQUESTING_DATA, 'The <code>requestingData</code> action creator should return an object of type equal to the value of <code>REQUESTING_DATA</code>.');"
},
{
"text": "The <code>receivedData</code> action creator should return an object of type equal to the value of <code>RECEIVED_DATA</code>.",
"testString": "assert(receivedData('data').type === RECEIVED_DATA, 'The <code>receivedData</code> action creator should return an object of type equal to the value of <code>RECEIVED_DATA</code>.');"
},
{
"text": "<code>asyncDataReducer</code> should be a function.",
"testString": "assert(typeof asyncDataReducer === 'function', '<code>asyncDataReducer</code> should be a function.');"
},
{
"text": "Dispatching the requestingData action creator should update the store <code>state</code> property of fetching to <code>true</code>.",
"testString": "assert((function() { const initialState = store.getState(); store.dispatch(requestingData()); const reqState = store.getState(); return initialState.fetching === false && reqState.fetching === true })(), 'Dispatching the requestingData action creator should update the store <code>state</code> property of fetching to <code>true</code>.');"
},
{
"text": "Dispatching <code>handleAsync</code> should dispatch the data request action and then dispatch the received data action after a delay.",
"testString": "assert((function() { const noWhiteSpace = handleAsync.toString().replace(/\\s/g,''); return noWhiteSpace.includes('dispatch(requestingData())') === true && noWhiteSpace.includes('dispatch(receivedData(data))') === true })(), 'Dispatching <code>handleAsync</code> should dispatch the data request action and then dispatch the received data action after a delay.');"
}
],
"solutions": [
"const REQUESTING_DATA = 'REQUESTING_DATA'\nconst RECEIVED_DATA = 'RECEIVED_DATA'\n\nconst requestingData = () => { return {type: REQUESTING_DATA} }\nconst receivedData = (data) => { return {type: RECEIVED_DATA, users: data.users} }\n\nconst handleAsync = () => {\n return function(dispatch) {\n dispatch(requestingData());\n setTimeout(function() {\n let data = {\n users: ['Jeff', 'William', 'Alice']\n }\n dispatch(receivedData(data));\n }, 2500);\n }\n};\n\nconst defaultState = {\n fetching: false,\n users: []\n};\n\nconst asyncDataReducer = (state = defaultState, action) => {\n switch(action.type) {\n case REQUESTING_DATA:\n return {\n fetching: true,\n users: []\n }\n case RECEIVED_DATA:\n return {\n fetching: false,\n users: action.users\n }\n default:\n return state;\n }\n};\n\nconst store = Redux.createStore(\n asyncDataReducer,\n Redux.applyMiddleware(ReduxThunk.default)\n);"
@ -686,16 +841,36 @@
"const decAction = null; // define an action creator for decrementing",
"",
"const store = null; // define the Redux store here, passing in your reducers"
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert(incAction().type ===INCREMENT, 'message: The action creator <code>incAction</code> should return an action object with <code>type</code> equal to the value of <code>INCREMENT</code>');",
"assert(decAction().type === DECREMENT, 'message: The action creator <code>decAction</code> should return an action object with <code>type</code> equal to the value of <code>DECREMENT</code>');",
"assert(store.getState() === 0, 'message: The Redux store should initialize with a <code>state</code> of 0.');",
"assert((function() { const initialState = store.getState(); store.dispatch(incAction()); const incState = store.getState(); return initialState + 1 === incState })(), 'message: Dispatching <code>incAction</code> on the Redux store should increment the <code>state</code> by 1.');",
"assert((function() { const initialState = store.getState(); store.dispatch(decAction()); const decState = store.getState(); return initialState - 1 === decState })(), 'message: Dispatching <code>decAction</code> on the Redux store should decrement the <code>state</code> by 1.');",
"assert(typeof counterReducer === 'function', 'message: <code>counterReducer</code> should be a function');"
{
"text": "The action creator <code>incAction</code> should return an action object with <code>type</code> equal to the value of <code>INCREMENT</code>",
"testString": "assert(incAction().type ===INCREMENT, 'The action creator <code>incAction</code> should return an action object with <code>type</code> equal to the value of <code>INCREMENT</code>');"
},
{
"text": "The action creator <code>decAction</code> should return an action object with <code>type</code> equal to the value of <code>DECREMENT</code>",
"testString": "assert(decAction().type === DECREMENT, 'The action creator <code>decAction</code> should return an action object with <code>type</code> equal to the value of <code>DECREMENT</code>');"
},
{
"text": "The Redux store should initialize with a <code>state</code> of 0.",
"testString": "assert(store.getState() === 0, 'The Redux store should initialize with a <code>state</code> of 0.');"
},
{
"text": "Dispatching <code>incAction</code> on the Redux store should increment the <code>state</code> by 1.",
"testString": "assert((function() { const initialState = store.getState(); store.dispatch(incAction()); const incState = store.getState(); return initialState + 1 === incState })(), 'Dispatching <code>incAction</code> on the Redux store should increment the <code>state</code> by 1.');"
},
{
"text": "Dispatching <code>decAction</code> on the Redux store should decrement the <code>state</code> by 1.",
"testString": "assert((function() { const initialState = store.getState(); store.dispatch(decAction()); const decState = store.getState(); return initialState - 1 === decState })(), 'Dispatching <code>decAction</code> on the Redux store should decrement the <code>state</code> by 1.');"
},
{
"text": "<code>counterReducer</code> should be a function",
"testString": "assert(typeof counterReducer === 'function', '<code>counterReducer</code> should be a function');"
}
],
"solutions": [
"const INCREMENT = 'INCREMENT';\nconst DECREMENT = 'DECREMENT';\n\nconst counterReducer = (state = 0, action) => {\n switch(action.type) {\n case INCREMENT:\n return state + 1;\n case DECREMENT:\n return state - 1;\n default:\n return state;\n }\n};\n\nconst incAction = () => {\n return {\n type: INCREMENT\n }\n};\n\nconst decAction = () => {\n return {\n type: DECREMENT\n }\n};\n\nconst store = Redux.createStore(counterReducer);"
@ -751,13 +926,24 @@
"}",
"",
"const store = Redux.createStore(immutableReducer);"
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert((function() { const todos = [ 'Go to the store', 'Clean the house', 'Cook dinner', 'Learn to code' ]; const initialState = store.getState(); return Array.isArray(initialState) && initialState.join(',') === todos.join(','); })(), 'message: The Redux store should exist and initialize with a state equal to the <code>todos</code> array in the code editor.');",
"assert(typeof addToDo === 'function' && typeof immutableReducer === 'function', 'message: <code>addToDo</code> and <code>immutableReducer</code> both should be functions.');",
"assert((function() { const initialState = store.getState(); const isFrozen = DeepFreeze(initialState); store.dispatch(addToDo('__TEST__TO__DO__')); const finalState = store.getState(); const expectedState = [ 'Go to the store', 'Clean the house', 'Cook dinner', 'Learn to code', '__TEST__TO__DO__' ]; return( isFrozen && DeepEqual(finalState, expectedState)); })(), 'message: Dispatching an action of type <code>ADD_TO_DO</code> on the Redux store should add a <code>todo</code> item and should NOT mutate state.');"
{
"text": "The Redux store should exist and initialize with a state equal to the <code>todos</code> array in the code editor.",
"testString": "assert((function() { const todos = [ 'Go to the store', 'Clean the house', 'Cook dinner', 'Learn to code' ]; const initialState = store.getState(); return Array.isArray(initialState) && initialState.join(',') === todos.join(','); })(), 'The Redux store should exist and initialize with a state equal to the <code>todos</code> array in the code editor.');"
},
{
"text": "<code>addToDo</code> and <code>immutableReducer</code> both should be functions.",
"testString": "assert(typeof addToDo === 'function' && typeof immutableReducer === 'function', '<code>addToDo</code> and <code>immutableReducer</code> both should be functions.');"
},
{
"text": "Dispatching an action of type <code>ADD_TO_DO</code> on the Redux store should add a <code>todo</code> item and should NOT mutate state.",
"testString": "assert((function() { const initialState = store.getState(); const isFrozen = DeepFreeze(initialState); store.dispatch(addToDo('__TEST__TO__DO__')); const finalState = store.getState(); const expectedState = [ 'Go to the store', 'Clean the house', 'Cook dinner', 'Learn to code', '__TEST__TO__DO__' ]; return( isFrozen && DeepEqual(finalState, expectedState)); })(), 'Dispatching an action of type <code>ADD_TO_DO</code> on the Redux store should add a <code>todo</code> item and should NOT mutate state.');"
}
],
"solutions": [
"const ADD_TO_DO = 'ADD_TO_DO';\n\n// A list of strings representing tasks to do:\nconst todos = [\n 'Go to the store',\n 'Clean the house',\n 'Cook dinner',\n 'Learn to code',\n];\n\nconst immutableReducer = (state = todos, action) => {\n switch(action.type) {\n case ADD_TO_DO:\n return state.concat(action.todo);\n default:\n return state;\n }\n};\n\n// an example todo argument would be 'Learn React',\nconst addToDo = (todo) => {\n return {\n type: ADD_TO_DO,\n todo\n }\n}\n\nconst store = Redux.createStore(immutableReducer);"
@ -802,14 +988,28 @@
"}",
"",
"const store = Redux.createStore(immutableReducer);"
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert((function() { const initialState = store.getState(); return ( Array.isArray(initialState) === true && initialState[0] === 'Do not mutate state!'); })(), 'message: The Redux store should exist and initialize with a state equal to <code>[Do not mutate state!]</code>.');",
"assert(typeof addToDo === 'function' && typeof immutableReducer === 'function', 'message: <code>addToDo</code> and <code>immutableReducer</code> both should be functions.');",
"assert((function() { const initialState = store.getState(); const isFrozen = DeepFreeze(initialState); store.dispatch(addToDo('__TEST__TO__DO__')); const finalState = store.getState(); const expectedState = [ 'Do not mutate state!', '__TEST__TO__DO__' ]; return( isFrozen && DeepEqual(finalState, expectedState)); })(), 'message: Dispatching an action of type <code>ADD_TO_DO</code> on the Redux store should add a <code>todo</code> item and should NOT mutate state.');",
"getUserInput => assert(getUserInput('index').includes('...state'), 'message: The spread operator should be used to return new state.');"
{
"text": "The Redux store should exist and initialize with a state equal to <code>[Do not mutate state!]</code>.",
"testString": "assert((function() { const initialState = store.getState(); return ( Array.isArray(initialState) === true && initialState[0] === 'Do not mutate state!'); })(), 'The Redux store should exist and initialize with a state equal to <code>[Do not mutate state!]</code>.');"
},
{
"text": "<code>addToDo</code> and <code>immutableReducer</code> both should be functions.",
"testString": "assert(typeof addToDo === 'function' && typeof immutableReducer === 'function', '<code>addToDo</code> and <code>immutableReducer</code> both should be functions.');"
},
{
"text": "Dispatching an action of type <code>ADD_TO_DO</code> on the Redux store should add a <code>todo</code> item and should NOT mutate state.",
"testString": "assert((function() { const initialState = store.getState(); const isFrozen = DeepFreeze(initialState); store.dispatch(addToDo('__TEST__TO__DO__')); const finalState = store.getState(); const expectedState = [ 'Do not mutate state!', '__TEST__TO__DO__' ]; return( isFrozen && DeepEqual(finalState, expectedState)); })(), 'Dispatching an action of type <code>ADD_TO_DO</code> on the Redux store should add a <code>todo</code> item and should NOT mutate state.');"
},
{
"text": "The spread operator should be used to return new state.",
"testString": "getUserInput => assert(getUserInput('index').includes('...state'), 'The spread operator should be used to return new state.');"
}
],
"solutions": [
"const immutableReducer = (state = ['Do not mutate state!'], action) => {\n switch(action.type) {\n case 'ADD_TO_DO':\n return [\n ...state,\n action.todo\n ];\n default:\n return state;\n }\n};\n\nconst addToDo = (todo) => {\n return {\n type: 'ADD_TO_DO',\n todo\n }\n}\n\nconst store = Redux.createStore(immutableReducer);"
@ -852,13 +1052,24 @@
"}",
"",
"const store = Redux.createStore(immutableReducer);"
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert((function() { const initialState = store.getState(); return (Array.isArray(initialState) === true && DeepEqual(initialState, [0, 1, 2, 3, 4, 5])); })(), 'message: The Redux store should exist and initialize with a state equal to <code>[0,1,2,3,4,5]</code>');",
"assert(typeof removeItem === 'function' && typeof immutableReducer === 'function', 'message: <code>removeItem</code> and <code>immutableReducer</code> both should be functions.');",
"assert((function() { const initialState = store.getState(); const isFrozen = DeepFreeze(initialState); store.dispatch(removeItem(3)); const state_1 = store.getState(); store.dispatch(removeItem(2)); const state_2 = store.getState(); store.dispatch(removeItem(0)); store.dispatch(removeItem(0)); store.dispatch(removeItem(0)); const state_3 = store.getState(); return isFrozen && DeepEqual(state_1, [0, 1, 2, 4, 5]) && DeepEqual(state_2, [0, 1, 4, 5]) && DeepEqual(state_3, [5]); })(), 'message: Dispatching the <code>removeItem</code> action creator should remove items from the state and should NOT mutate state.');"
{
"text": "The Redux store should exist and initialize with a state equal to <code>[0,1,2,3,4,5]</code>",
"testString": "assert((function() { const initialState = store.getState(); return (Array.isArray(initialState) === true && DeepEqual(initialState, [0, 1, 2, 3, 4, 5])); })(), 'The Redux store should exist and initialize with a state equal to <code>[0,1,2,3,4,5]</code>');"
},
{
"text": "<code>removeItem</code> and <code>immutableReducer</code> both should be functions.",
"testString": "assert(typeof removeItem === 'function' && typeof immutableReducer === 'function', '<code>removeItem</code> and <code>immutableReducer</code> both should be functions.');"
},
{
"text": "Dispatching the <code>removeItem</code> action creator should remove items from the state and should NOT mutate state.",
"testString": "assert((function() { const initialState = store.getState(); const isFrozen = DeepFreeze(initialState); store.dispatch(removeItem(3)); const state_1 = store.getState(); store.dispatch(removeItem(2)); const state_2 = store.getState(); store.dispatch(removeItem(0)); store.dispatch(removeItem(0)); store.dispatch(removeItem(0)); const state_3 = store.getState(); return isFrozen && DeepEqual(state_1, [0, 1, 2, 4, 5]) && DeepEqual(state_2, [0, 1, 4, 5]) && DeepEqual(state_3, [5]); })(), 'Dispatching the <code>removeItem</code> action creator should remove items from the state and should NOT mutate state.');"
}
],
"solutions": [
"const immutableReducer = (state = [0,1,2,3,4,5], action) => {\n switch(action.type) {\n case 'REMOVE_ITEM':\n return [\n ...state.slice(0, action.index),\n ...state.slice(action.index + 1)\n ];\n default:\n return state;\n }\n};\n\nconst removeItem = (index) => {\n return {\n type: 'REMOVE_ITEM',\n index\n }\n}\n\nconst store = Redux.createStore(immutableReducer);"
@ -909,14 +1120,28 @@
"};",
"",
"const store = Redux.createStore(immutableReducer);"
]
],
"head": [],
"tail": []
}
},
"tests": [
"assert((function() { const expectedState = { user: 'CamperBot', status: 'offline', friends: '732,982', community: 'freeCodeCamp' }; const initialState = store.getState(); return DeepEqual(expectedState, initialState); })(), 'message: The Redux store should exist and initialize with a state that is equivalent to the <code>defaultState</code> object declared on line 1.');",
"assert(typeof wakeUp === 'function' && typeof immutableReducer === 'function', 'message: <code>wakeUp</code> and <code>immutableReducer</code> both should be functions.');",
"assert((function() { const initialState = store.getState(); const isFrozen = DeepFreeze(initialState); store.dispatch({type: 'ONLINE'}); const finalState = store.getState(); const expectedState = { user: 'CamperBot', status: 'online', friends: '732,982', community: 'freeCodeCamp' }; return isFrozen && DeepEqual(finalState, expectedState); })(), 'message: Dispatching an action of type <code>ONLINE</code> should update the property <code>status</code> in state to <code>online</code> and should NOT mutate state.');",
"getUserInput => assert(getUserInput('index').includes('Object.assign'), 'message: <code>Object.assign</code> should be used to return new state.');"
{
"text": "The Redux store should exist and initialize with a state that is equivalent to the <code>defaultState</code> object declared on line 1.",
"testString": "assert((function() { const expectedState = { user: 'CamperBot', status: 'offline', friends: '732,982', community: 'freeCodeCamp' }; const initialState = store.getState(); return DeepEqual(expectedState, initialState); })(), 'The Redux store should exist and initialize with a state that is equivalent to the <code>defaultState</code> object declared on line 1.');"
},
{
"text": "<code>wakeUp</code> and <code>immutableReducer</code> both should be functions.",
"testString": "assert(typeof wakeUp === 'function' && typeof immutableReducer === 'function', '<code>wakeUp</code> and <code>immutableReducer</code> both should be functions.');"
},
{
"text": "Dispatching an action of type <code>ONLINE</code> should update the property <code>status</code> in state to <code>online</code> and should NOT mutate state.",
"testString": "assert((function() { const initialState = store.getState(); const isFrozen = DeepFreeze(initialState); store.dispatch({type: 'ONLINE'}); const finalState = store.getState(); const expectedState = { user: 'CamperBot', status: 'online', friends: '732,982', community: 'freeCodeCamp' }; return isFrozen && DeepEqual(finalState, expectedState); })(), 'Dispatching an action of type <code>ONLINE</code> should update the property <code>status</code> in state to <code>online</code> and should NOT mutate state.');"
},
{
"text": "<code>Object.assign</code> should be used to return new state.",
"testString": "getUserInput => assert(getUserInput('index').includes('Object.assign'), '<code>Object.assign</code> should be used to return new state.');"
}
],
"solutions": [
"const defaultState = {\n user: 'CamperBot',\n status: 'offline',\n friends: '732,982',\n community: 'freeCodeCamp'\n};\n\nconst immutableReducer = (state = defaultState, action) => {\n switch(action.type) {\n case 'ONLINE':\n return Object.assign({}, state, {\n status: 'online'\n });\n default:\n return state;\n }\n};\n\nconst wakeUp = () => {\n return {\n type: 'ONLINE'\n }\n};\n\nconst store = Redux.createStore(immutableReducer);"

View File

@ -4,25 +4,6 @@
"time": "5 hours",
"helpRoom": "Help",
"challenges": [
{
"id": "587d7dbd367417b2b2512bb3",
"title": "Introduction to the Sass Challenges",
"description": [
[
"",
"",
"Sass, or \"Syntactically Awesome StyleSheets\", is a language extension of CSS. It adds features that aren't available using basic CSS syntax. Sass makes it easier for developers to simplify and maintain the style sheets for their projects.<br><br>Sass can extend the CSS language because it is a preprocessor. It takes code written using Sass syntax, and converts it into basic CSS. This allows you to create variables, nest CSS rules into others, and import other Sass files, among other things. The result is more compact, easier to read code.<br><br>There are two syntaxes available for Sass. The first, known as SCSS (Sassy CSS) and used throughout these challenges, is an extension of the syntax of CSS. This means that every valid CSS stylesheet is a valid SCSS file with the same meaning. Files using this syntax have the .scss extension.<br><br>The second and older syntax, known as the indented syntax (or sometimes just \"Sass\"), uses indentation rather than brackets to indicate nesting of selectors, and newlines rather than semicolons to separate properties. Files using this syntax have the .sass extension.<br><br>This section introduces the basic features of Sass.",
""
]
],
"releasedOn": "Feb 17, 2017",
"challengeSeed": [],
"tests": [],
"type": "waypoint",
"challengeType": 7,
"isRequired": false,
"translations": {}
},
{
"id": "587d7dbd367417b2b2512bb4",
"title": "Store Data with Sass Variables",
@ -41,44 +22,65 @@
"<hr>",
"Create a variable <code>$text-color</code> and set it to red. Then change the value of the <code>color</code> property for the <code>.blog-post</code> and <code>h2</code> to the <code>$text-color</code> variable."
],
"challengeSeed": [
"<style type='text/sass'>",
" ",
" ",
" .header{",
" text-align: center;",
" }",
" .blog-post, h2 {",
" color: red;",
" }",
"</style>",
"",
"<h1 class=\"header\">Learn Sass</h1>",
"<div class=\"blog-post\">",
" <h2>Some random title</h2>",
" <p>This is a paragraph with some random text in it</p>",
"</div>",
"<div class=\"blog-post\">",
" <h2>Header #2</h2>",
" <p>Here is some more random text.</p>",
"</div>",
"<div class=\"blog-post\">",
" <h2>Here is another header</h2>",
" <p>Even more random text within a paragraph</p>",
"</div>"
],
"tests": [
"assert(code.match(/\\$text-color:\\s*?red;/g), 'message: Your code should have a Sass variable declared for <code>$text-color</code> with a value of red.');",
"assert(code.match(/color:\\s*?\\$text-color;/g), 'message: Your code should use the <code>$text-color</code> variable to change the <code>color</code> for the <code>.blog-post</code> and <code>h2</code> items.');",
"assert($('.blog-post').css('color') == 'rgb(255, 0, 0)', 'message: Your <code>.blog-post</code> element should have a </code>color</code> of red.');",
"assert($('h2').css('color') == 'rgb(255, 0, 0)', 'message: Your <code>h2</code> elements should have a </code>color</code> of red.');"
{
"text": "Your code should have a Sass variable declared for <code>$text-color</code> with a value of red.",
"testString": "assert(code.match(/\\$text-color:\\s*?red;/g), 'Your code should have a Sass variable declared for <code>$text-color</code> with a value of red.');"
},
{
"text": "Your code should use the <code>$text-color</code> variable to change the <code>color</code> for the <code>.blog-post</code> and <code>h2</code> items.",
"testString": "assert(code.match(/color:\\s*?\\$text-color;/g), 'Your code should use the <code>$text-color</code> variable to change the <code>color</code> for the <code>.blog-post</code> and <code>h2</code> items.');"
},
{
"text": "Your <code>.blog-post</code> element should have a </code>color</code> of red.",
"testString": "assert($('.blog-post').css('color') == 'rgb(255, 0, 0)', 'Your <code>.blog-post</code> element should have a </code>color</code> of red.');"
},
{
"text": "Your <code>h2</code> elements should have a </code>color</code> of red.",
"testString": "assert($('h2').css('color') == 'rgb(255, 0, 0)', 'Your <code>h2</code> elements should have a </code>color</code> of red.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 0,
"translations": {}
"translations": {},
"files": {
"indexhtml": {
"key": "indexhtml",
"ext": "html",
"name": "index",
"contents": [
"<style type='text/sass'>",
" ",
" ",
" .header{",
" text-align: center;",
" }",
" .blog-post, h2 {",
" color: red;",
" }",
"</style>",
"",
"<h1 class=\"header\">Learn Sass</h1>",
"<div class=\"blog-post\">",
" <h2>Some random title</h2>",
" <p>This is a paragraph with some random text in it</p>",
"</div>",
"<div class=\"blog-post\">",
" <h2>Header #2</h2>",
" <p>Here is some more random text.</p>",
"</div>",
"<div class=\"blog-post\">",
" <h2>Here is another header</h2>",
" <p>Even more random text within a paragraph</p>",
"</div>"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7dbd367417b2b2512bb5",
@ -98,34 +100,46 @@
"<hr>",
"Use the <code>nesting</code> technique shown above to re-organize the CSS rules for both children of <code>.blog-post</code> element. For testing purposes, the <code>h1</code> should come before the <code>p</code> element."
],
"challengeSeed": [
"<style type='text/sass'>",
" .blog-post {",
" ",
" }",
" h1 {",
" text-align: center;",
" color: blue;",
" }",
" p {",
" font-size: 20px;",
" }",
"</style>",
"",
"<div class=\"blog-post\">",
" <h1>Blog Title</h1>",
" <p>This is a paragraph</p>",
"</div>"
],
"tests": [
"assert(code.match(/\\.blog-post\\s*?{\\s*?h1\\s*?{\\s*?text-align:\\s*?center;\\s*?color:\\s*?blue;\\s*?}\\s*?p\\s*?{\\s*?font-size:\\s*?20px;\\s*?}\\s*?}/gi), 'message: Your code should re-organize the CSS rules so the <code>h1</code> and <code>p</code> are nested in the <code>.blog-post</code> parent element.');"
{
"text": "Your code should re-organize the CSS rules so the <code>h1</code> and <code>p</code> are nested in the <code>.blog-post</code> parent element.",
"testString": "assert(code.match(/\\.blog-post\\s*?{\\s*?h1\\s*?{\\s*?text-align:\\s*?center;\\s*?color:\\s*?blue;\\s*?}\\s*?p\\s*?{\\s*?font-size:\\s*?20px;\\s*?}\\s*?}/gi), 'Your code should re-organize the CSS rules so the <code>h1</code> and <code>p</code> are nested in the <code>.blog-post</code> parent element.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 0,
"translations": {}
"translations": {},
"files": {
"indexhtml": {
"key": "indexhtml",
"ext": "html",
"name": "index",
"contents": [
"<style type='text/sass'>",
" .blog-post {",
" ",
" }",
" h1 {",
" text-align: center;",
" color: blue;",
" }",
" p {",
" font-size: 20px;",
" }",
"</style>",
"",
"<div class=\"blog-post\">",
" <h1>Blog Title</h1>",
" <p>This is a paragraph</p>",
"</div>"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7dbd367417b2b2512bb6",
@ -149,36 +163,63 @@
"<hr>",
"Write a <code>mixin</code> for <code>border-radius</code> and give it a <code>$radius</code> parameter. It should use all the vendor prefixes from the example. Then use the <code>border-radius</code> <code>mixin</code> to give the <code>#awesome</code> element a border radius of 15px."
],
"challengeSeed": [
"<style type='text/sass'>",
" ",
" ",
" ",
" #awesome {",
" width: 150px;",
" height: 150px;",
" background-color: green;",
" ",
" }",
"</style>",
"",
"<div id=\"awesome\"></div>",
" "
],
"tests": [
"assert(code.match(/@mixin\\s+?border-radius\\(\\s*?\\$radius\\s*?\\)\\s*?{/gi), 'message: Your code should declare a <code>mixin</code> named <code>border-radius</code> which has a parameter named <code>$radius</code>.');",
"assert(code.match(/-webkit-border-radius:\\s*?\\$radius;/gi), 'message: Your code should include the <code>-webkit-border-radius</code> vender prefix that uses the <code>$radius</code> parameter.');",
"assert(code.match(/-moz-border-radius:\\s*?\\$radius;/gi), 'message: Your code should include the <code>-moz-border-radius</code> vender prefix that uses the <code>$radius</code> parameter.');",
"assert(code.match(/-ms-border-radius:\\s*?\\$radius;/gi), 'message: Your code should include the <code>-ms-border-radius</code> vender prefix that uses the <code>$radius</code> parameter.');",
"assert(code.match(/border-radius:\\s*?\\$radius;/gi).length == 4, 'message: Your code should include the general <code>border-radius</code> rule that uses the <code>$radius</code> parameter.');",
"assert(code.match(/@include\\s+?border-radius\\(\\s*?15px\\s*?\\);/gi), 'message: Your code should call the <code>border-radius mixin</code> using the <code>@include</code> keyword, setting it to 15px.');"
{
"text": "Your code should declare a <code>mixin</code> named <code>border-radius</code> which has a parameter named <code>$radius</code>.",
"testString": "assert(code.match(/@mixin\\s+?border-radius\\(\\s*?\\$radius\\s*?\\)\\s*?{/gi), 'Your code should declare a <code>mixin</code> named <code>border-radius</code> which has a parameter named <code>$radius</code>.');"
},
{
"text": "Your code should include the <code>-webkit-border-radius</code> vender prefix that uses the <code>$radius</code> parameter.",
"testString": "assert(code.match(/-webkit-border-radius:\\s*?\\$radius;/gi), 'Your code should include the <code>-webkit-border-radius</code> vender prefix that uses the <code>$radius</code> parameter.');"
},
{
"text": "Your code should include the <code>-moz-border-radius</code> vender prefix that uses the <code>$radius</code> parameter.",
"testString": "assert(code.match(/-moz-border-radius:\\s*?\\$radius;/gi), 'Your code should include the <code>-moz-border-radius</code> vender prefix that uses the <code>$radius</code> parameter.');"
},
{
"text": "Your code should include the <code>-ms-border-radius</code> vender prefix that uses the <code>$radius</code> parameter.",
"testString": "assert(code.match(/-ms-border-radius:\\s*?\\$radius;/gi), 'Your code should include the <code>-ms-border-radius</code> vender prefix that uses the <code>$radius</code> parameter.');"
},
{
"text": "Your code should include the general <code>border-radius</code> rule that uses the <code>$radius</code> parameter.",
"testString": "assert(code.match(/border-radius:\\s*?\\$radius;/gi).length == 4, 'Your code should include the general <code>border-radius</code> rule that uses the <code>$radius</code> parameter.');"
},
{
"text": "Your code should call the <code>border-radius mixin</code> using the <code>@include</code> keyword, setting it to 15px.",
"testString": "assert(code.match(/@include\\s+?border-radius\\(\\s*?15px\\s*?\\);/gi), 'Your code should call the <code>border-radius mixin</code> using the <code>@include</code> keyword, setting it to 15px.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 0,
"translations": {}
"translations": {},
"files": {
"indexhtml": {
"key": "indexhtml",
"ext": "html",
"name": "index",
"contents": [
"<style type='text/sass'>",
" ",
" ",
" ",
" #awesome {",
" width: 150px;",
" height: 150px;",
" background-color: green;",
" ",
" }",
"</style>",
"",
"<div id=\"awesome\"></div>",
" "
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7dbe367417b2b2512bb8",
@ -198,34 +239,58 @@
"Create a <code>mixin</code> called <code>border-stroke</code> that takes a parameter <code>$val</code>. The <code>mixin</code> should check for the following conditions using <code>@if</code>, <code>@else if</code>, and <code>@else</code>:",
"<blockquote>light - 1px solid black<br>medium - 3px solid black<br>heavy - 6px solid black<br>none - no border</blockquote>"
],
"challengeSeed": [
"<style type='text/sass'>",
" ",
" ",
" ",
" #box {",
" width: 150px;",
" height: 150px;",
" background-color: red;",
" @include border-stroke(medium);",
" } ",
"</style>",
"",
"<div id=\"box\"></div>"
],
"tests": [
"assert(code.match(/@mixin\\s+?border-stroke\\s*?\\(\\s*?\\$val\\s*?\\)\\s*?{/gi), 'message: Your code should declare a <code>mixin</code> named <code>border-stroke</code> which has a parameter named <code>$val</code>.');",
"assert(code.match(/@if\\s+?\\$val\\s*?===?\\s*?light\\s*?{\\s*?border\\s*?:\\s*?1px\\s+?solid\\s+?black\\s*?;\\s*?}/gi), 'message: Your <code>mixin</code> should have an <code>@if</code> statement to check if <code>$val</code> is light, and to set the <code>border</code> to 1px solid black.');",
"assert(code.match(/@else\\s+?if\\s+?\\$val\\s*?===?\\s*?medium\\s*?{\\s*?border\\s*?:\\s*?3px\\s+?solid\\s+?black\\s*?;\\s*?}/gi), 'message: Your <code>mixin</code> should have an <code>@else if</code> statement to check if <code>$val</code> is medium, and to set the <code>border</code> to 3px solid black.');",
"assert(code.match(/@else\\s+?if\\s+?\\$val\\s*?===?\\s*?heavy\\s*?{\\s*?border\\s*?:\\s*?6px\\s+?solid\\s+?black\\s*?;\\s*?}/gi), 'message: Your <code>mixin</code> should have an <code>@else if</code> statement to check if <code>$val</code> is heavy, and to set the <code>border</code> to 6px solid black.');",
"assert(code.match(/@else\\s*?{\\s*?border\\s*?:\\s*?none\\s*?;\\s*?}/gi), 'message: Your <code>mixin</code> should have an <code>@else</code> statement to set the <code>border</code> to none.');"
{
"text": "Your code should declare a <code>mixin</code> named <code>border-stroke</code> which has a parameter named <code>$val</code>.",
"testString": "assert(code.match(/@mixin\\s+?border-stroke\\s*?\\(\\s*?\\$val\\s*?\\)\\s*?{/gi), 'Your code should declare a <code>mixin</code> named <code>border-stroke</code> which has a parameter named <code>$val</code>.');"
},
{
"text": "Your <code>mixin</code> should have an <code>@if</code> statement to check if <code>$val</code> is light, and to set the <code>border</code> to 1px solid black.",
"testString": "assert(code.match(/@if\\s+?\\$val\\s*?===?\\s*?light\\s*?{\\s*?border\\s*?:\\s*?1px\\s+?solid\\s+?black\\s*?;\\s*?}/gi), 'Your <code>mixin</code> should have an <code>@if</code> statement to check if <code>$val</code> is light, and to set the <code>border</code> to 1px solid black.');"
},
{
"text": "Your <code>mixin</code> should have an <code>@else if</code> statement to check if <code>$val</code> is medium, and to set the <code>border</code> to 3px solid black.",
"testString": "assert(code.match(/@else\\s+?if\\s+?\\$val\\s*?===?\\s*?medium\\s*?{\\s*?border\\s*?:\\s*?3px\\s+?solid\\s+?black\\s*?;\\s*?}/gi), 'Your <code>mixin</code> should have an <code>@else if</code> statement to check if <code>$val</code> is medium, and to set the <code>border</code> to 3px solid black.');"
},
{
"text": "Your <code>mixin</code> should have an <code>@else if</code> statement to check if <code>$val</code> is heavy, and to set the <code>border</code> to 6px solid black.",
"testString": "assert(code.match(/@else\\s+?if\\s+?\\$val\\s*?===?\\s*?heavy\\s*?{\\s*?border\\s*?:\\s*?6px\\s+?solid\\s+?black\\s*?;\\s*?}/gi), 'Your <code>mixin</code> should have an <code>@else if</code> statement to check if <code>$val</code> is heavy, and to set the <code>border</code> to 6px solid black.');"
},
{
"text": "Your <code>mixin</code> should have an <code>@else</code> statement to set the <code>border</code> to none.",
"testString": "assert(code.match(/@else\\s*?{\\s*?border\\s*?:\\s*?none\\s*?;\\s*?}/gi), 'Your <code>mixin</code> should have an <code>@else</code> statement to set the <code>border</code> to none.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 0,
"translations": {}
"translations": {},
"files": {
"indexhtml": {
"key": "indexhtml",
"ext": "html",
"name": "index",
"contents": [
"<style type='text/sass'>",
" ",
" ",
" ",
" #box {",
" width: 150px;",
" height: 150px;",
" background-color: red;",
" @include border-stroke(medium);",
" } ",
"</style>",
"",
"<div id=\"box\"></div>"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7dbe367417b2b2512bb9",
@ -248,33 +313,60 @@
"Write a <code>@for</code> directive that takes a variable <code>$j</code> that goes from 1 <b>to</b> 6.",
"It should create 5 classes called <code>.text-1</code> to <code>.text-5</code> where each has a <code>font-size</code> set to 10px multiplied by the index."
],
"challengeSeed": [
"<style type='text/sass'>",
" ",
" ",
" ",
"</style>",
"",
"<p class=\"text-1\">Hello</p>",
"<p class=\"text-2\">Hello</p>",
"<p class=\"text-3\">Hello</p>",
"<p class=\"text-4\">Hello</p>",
"<p class=\"text-5\">Hello</p>"
],
"tests": [
"assert(code.match(/@for /g), 'message: Your code should use the <code>@for</code> directive.');",
"assert($('.text-1').css('font-size') == '10px', 'message: Your <code>.text-1</code> class should have a <code>font-size</code> of 10px.');",
"assert($('.text-2').css('font-size') == '20px', 'message: Your <code>.text-2</code> class should have a <code>font-size</code> of 20px.');",
"assert($('.text-3').css('font-size') == '30px', 'message: Your <code>.text-3</code> class should have a <code>font-size</code> of 30px.');",
"assert($('.text-4').css('font-size') == '40px', 'message: Your <code>.text-4</code> class should have a <code>font-size</code> of 40px.');",
"assert($('.text-5').css('font-size') == '50px', 'message: Your <code>.text-5</code> class should have a <code>font-size</code> of 50px.');"
{
"text": "Your code should use the <code>@for</code> directive.",
"testString": "assert(code.match(/@for /g), 'Your code should use the <code>@for</code> directive.');"
},
{
"text": "Your <code>.text-1</code> class should have a <code>font-size</code> of 10px.",
"testString": "assert($('.text-1').css('font-size') == '10px', 'Your <code>.text-1</code> class should have a <code>font-size</code> of 10px.');"
},
{
"text": "Your <code>.text-2</code> class should have a <code>font-size</code> of 20px.",
"testString": "assert($('.text-2').css('font-size') == '20px', 'Your <code>.text-2</code> class should have a <code>font-size</code> of 20px.');"
},
{
"text": "Your <code>.text-3</code> class should have a <code>font-size</code> of 30px.",
"testString": "assert($('.text-3').css('font-size') == '30px', 'Your <code>.text-3</code> class should have a <code>font-size</code> of 30px.');"
},
{
"text": "Your <code>.text-4</code> class should have a <code>font-size</code> of 40px.",
"testString": "assert($('.text-4').css('font-size') == '40px', 'Your <code>.text-4</code> class should have a <code>font-size</code> of 40px.');"
},
{
"text": "Your <code>.text-5</code> class should have a <code>font-size</code> of 50px.",
"testString": "assert($('.text-5').css('font-size') == '50px', 'Your <code>.text-5</code> class should have a <code>font-size</code> of 50px.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 0,
"translations": {}
"translations": {},
"files": {
"indexhtml": {
"key": "indexhtml",
"ext": "html",
"name": "index",
"contents": [
"<style type='text/sass'>",
" ",
" ",
" ",
"</style>",
"",
"<p class=\"text-1\">Hello</p>",
"<p class=\"text-2\">Hello</p>",
"<p class=\"text-3\">Hello</p>",
"<p class=\"text-4\">Hello</p>",
"<p class=\"text-5\">Hello</p>"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7dbf367417b2b2512bba",
@ -298,33 +390,54 @@
"Write an <code>@each</code> directive that goes through a list: <code>blue, black, red</code> and assigns each variable to a <code>.color-bg</code> class, where the \"color\" part changes for each item.",
"Each class should set the <code>background-color</code> the respective color."
],
"challengeSeed": [
"<style type='text/sass'>",
" ",
" ",
" ",
" div {",
" height: 200px;",
" width: 200px;",
" }",
"</style>",
"",
"<div class=\"blue-bg\"></div>",
"<div class=\"black-bg\"></div>",
"<div class=\"red-bg\"></div>"
],
"tests": [
"assert(code.match(/@each /g), 'message: Your code should use the <code>@each</code> directive.');",
"assert($('.blue-bg').css('background-color') == 'rgb(0, 0, 255)', 'message: Your <code>.blue-bg</code> class should have a <code>background-color</code> of blue.');",
"assert($('.black-bg').css('background-color') == 'rgb(0, 0, 0)', 'message: Your <code>.black-bg</code> class should have a <code>background-color</code> of black.');",
"assert($('.red-bg').css('background-color') == 'rgb(255, 0, 0)', 'message: Your <code>.red-bg</code> class should have a <code>background-color</code> of red.');"
{
"text": "Your code should use the <code>@each</code> directive.",
"testString": "assert(code.match(/@each /g), 'Your code should use the <code>@each</code> directive.');"
},
{
"text": "Your <code>.blue-bg</code> class should have a <code>background-color</code> of blue.",
"testString": "assert($('.blue-bg').css('background-color') == 'rgb(0, 0, 255)', 'Your <code>.blue-bg</code> class should have a <code>background-color</code> of blue.');"
},
{
"text": "Your <code>.black-bg</code> class should have a <code>background-color</code> of black.",
"testString": "assert($('.black-bg').css('background-color') == 'rgb(0, 0, 0)', 'Your <code>.black-bg</code> class should have a <code>background-color</code> of black.');"
},
{
"text": "Your <code>.red-bg</code> class should have a <code>background-color</code> of red.",
"testString": "assert($('.red-bg').css('background-color') == 'rgb(255, 0, 0)', 'Your <code>.red-bg</code> class should have a <code>background-color</code> of red.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 0,
"translations": {}
"translations": {},
"files": {
"indexhtml": {
"key": "indexhtml",
"ext": "html",
"name": "index",
"contents": [
"<style type='text/sass'>",
" ",
" ",
" ",
" div {",
" height: 200px;",
" width: 200px;",
" }",
"</style>",
"",
"<div class=\"blue-bg\"></div>",
"<div class=\"black-bg\"></div>",
"<div class=\"red-bg\"></div>"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7dbf367417b2b2512bbb",
@ -345,45 +458,93 @@
"Use <code>@while</code> to create a series of classes with different <code>font-sizes</code>.",
"There should be 10 different classes from <code>text-1</code> to <code>text-10</code>. Then set <code>font-size</code> to 5px multiplied by the current index number. Make sure to avoid an infinite loop!"
],
"challengeSeed": [
"<style type='text/sass'>",
" ",
" ",
" ",
"</style>",
"",
"<p class=\"text-1\">Hello</p>",
"<p class=\"text-2\">Hello</p>",
"<p class=\"text-3\">Hello</p>",
"<p class=\"text-4\">Hello</p>",
"<p class=\"text-5\">Hello</p>",
"<p class=\"text-6\">Hello</p>",
"<p class=\"text-7\">Hello</p>",
"<p class=\"text-8\">Hello</p>",
"<p class=\"text-9\">Hello</p>",
"<p class=\"text-10\">Hello</p>"
],
"tests": [
"assert(code.match(/@while /g), 'message: Your code should use the <code>@while</code> directive.');",
"assert(code.match(/\\$.*:\\s*?1;/gi), 'message: Your code should set an index variable to 1 to start.');",
"assert(code.match(/\\$(.*):\\s*?\\$\\1\\s*?\\+\\s*?1;/gi), 'message: Your code should increment the counter variable.');",
"assert($('.text-1').css('font-size') == '5px', 'message: Your <code>.text-1</code> class should have a <code>font-size</code> of 5px.');",
"assert($('.text-2').css('font-size') == '10px', 'message: Your <code>.text-2</code> class should have a <code>font-size</code> of 10px.');",
"assert($('.text-3').css('font-size') == '15px', 'message: Your <code>.text-3</code> class should have a <code>font-size</code> of 15px.');",
"assert($('.text-4').css('font-size') == '20px', 'message: Your <code>.text-4</code> class should have a <code>font-size</code> of 20px.');",
"assert($('.text-5').css('font-size') == '25px', 'message: Your <code>.text-5</code> class should have a <code>font-size</code> of 25px.');",
"assert($('.text-6').css('font-size') == '30px', 'message: Your <code>.text-6</code> class should have a <code>font-size</code> of 30px.');",
"assert($('.text-7').css('font-size') == '35px', 'message: Your <code>.text-7</code> class should have a <code>font-size</code> of 35px.');",
"assert($('.text-8').css('font-size') == '40px', 'message: Your <code>.text-8</code> class should have a <code>font-size</code> of 40px.');",
"assert($('.text-9').css('font-size') == '45px', 'message: Your <code>.text-9</code> class should have a <code>font-size</code> of 45px.');",
"assert($('.text-10').css('font-size') == '50px', 'message: Your <code>.text-10</code> class should have a <code>font-size</code> of 50px.');"
{
"text": "Your code should use the <code>@while</code> directive.",
"testString": "assert(code.match(/@while /g), 'Your code should use the <code>@while</code> directive.');"
},
{
"text": "Your code should set an index variable to 1 to start.",
"testString": "assert(code.match(/\\$.*:\\s*?1;/gi), 'Your code should set an index variable to 1 to start.');"
},
{
"text": "Your code should increment the counter variable.",
"testString": "assert(code.match(/\\$(.*):\\s*?\\$\\1\\s*?\\+\\s*?1;/gi), 'Your code should increment the counter variable.');"
},
{
"text": "Your <code>.text-1</code> class should have a <code>font-size</code> of 5px.",
"testString": "assert($('.text-1').css('font-size') == '5px', 'Your <code>.text-1</code> class should have a <code>font-size</code> of 5px.');"
},
{
"text": "Your <code>.text-2</code> class should have a <code>font-size</code> of 10px.",
"testString": "assert($('.text-2').css('font-size') == '10px', 'Your <code>.text-2</code> class should have a <code>font-size</code> of 10px.');"
},
{
"text": "Your <code>.text-3</code> class should have a <code>font-size</code> of 15px.",
"testString": "assert($('.text-3').css('font-size') == '15px', 'Your <code>.text-3</code> class should have a <code>font-size</code> of 15px.');"
},
{
"text": "Your <code>.text-4</code> class should have a <code>font-size</code> of 20px.",
"testString": "assert($('.text-4').css('font-size') == '20px', 'Your <code>.text-4</code> class should have a <code>font-size</code> of 20px.');"
},
{
"text": "Your <code>.text-5</code> class should have a <code>font-size</code> of 25px.",
"testString": "assert($('.text-5').css('font-size') == '25px', 'Your <code>.text-5</code> class should have a <code>font-size</code> of 25px.');"
},
{
"text": "Your <code>.text-6</code> class should have a <code>font-size</code> of 30px.",
"testString": "assert($('.text-6').css('font-size') == '30px', 'Your <code>.text-6</code> class should have a <code>font-size</code> of 30px.');"
},
{
"text": "Your <code>.text-7</code> class should have a <code>font-size</code> of 35px.",
"testString": "assert($('.text-7').css('font-size') == '35px', 'Your <code>.text-7</code> class should have a <code>font-size</code> of 35px.');"
},
{
"text": "Your <code>.text-8</code> class should have a <code>font-size</code> of 40px.",
"testString": "assert($('.text-8').css('font-size') == '40px', 'Your <code>.text-8</code> class should have a <code>font-size</code> of 40px.');"
},
{
"text": "Your <code>.text-9</code> class should have a <code>font-size</code> of 45px.",
"testString": "assert($('.text-9').css('font-size') == '45px', 'Your <code>.text-9</code> class should have a <code>font-size</code> of 45px.');"
},
{
"text": "Your <code>.text-10</code> class should have a <code>font-size</code> of 50px.",
"testString": "assert($('.text-10').css('font-size') == '50px', 'Your <code>.text-10</code> class should have a <code>font-size</code> of 50px.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 0,
"translations": {}
"translations": {},
"files": {
"indexhtml": {
"key": "indexhtml",
"ext": "html",
"name": "index",
"contents": [
"<style type='text/sass'>",
" ",
" ",
" ",
"</style>",
"",
"<p class=\"text-1\">Hello</p>",
"<p class=\"text-2\">Hello</p>",
"<p class=\"text-3\">Hello</p>",
"<p class=\"text-4\">Hello</p>",
"<p class=\"text-5\">Hello</p>",
"<p class=\"text-6\">Hello</p>",
"<p class=\"text-7\">Hello</p>",
"<p class=\"text-8\">Hello</p>",
"<p class=\"text-9\">Hello</p>",
"<p class=\"text-10\">Hello</p>"
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7dbf367417b2b2512bbc",
@ -403,22 +564,34 @@
"<hr>",
"Write an <code>@import</code> statement to import a <code>partial</code> named <code>_variables.scss</code> into the main.scss file."
],
"challengeSeed": [
"// The main.scss file",
"",
"",
"",
""
],
"tests": [
"assert(code.match(/@import\\s+?('|\")variables\\1/gi), 'message: Your code should use the <code>@import</code> directive, and should not include the underscore in the file name.');"
{
"text": "Your code should use the <code>@import</code> directive, and should not include the underscore in the file name.",
"testString": "assert(code.match(/@import\\s+?('|\")variables\\1/gi), 'Your code should use the <code>@import</code> directive, and should not include the underscore in the file name.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 0,
"translations": {}
"translations": {},
"files": {
"indexhtml": {
"key": "indexhtml",
"ext": "html",
"name": "index",
"contents": [
"// The main.scss file",
"",
"",
"",
""
],
"head": [],
"tail": []
}
}
},
{
"id": "587d7fa5367417b2b2512bbd",
@ -441,40 +614,55 @@
"<hr>",
"Make a class <code>.info-important</code> that extends <code>.info</code> and also has a <code>background-color</code> set to magenta."
],
"challengeSeed": [
"<style type='text/sass'>",
" h3{",
" text-align: center;",
" }",
" .info{",
" width: 200px;",
" border: 1px solid black;",
" margin: 0 auto;",
" }",
" ",
" ",
" ",
" ",
"</style>",
"<h3>Posts</h3>",
"<div class=\"info-important\">",
" <p>This is an important post. It should extend the class \".info\" and have its own CSS styles.</p>",
"</div>",
"",
"<div class=\"info\">",
" <p>This is a simple post. It has basic styling and can be extended for other uses.</p>",
"</div>"
],
"tests": [
"assert(code.match(/\\.info-important\\s*?{[\\s\\S]*background-color\\s*?:\\s*?magenta\\s*?;[\\s\\S]*}/gi), 'message: Your <code>info-important</code> class should have a <code>background-color</code> set to <code>magenta</code>.');",
"assert(code.match(/\\.info-important\\s*?{[\\s\\S]*@extend\\s*?.info\\s*?;[\\s\\S]*/gi), 'message: Your <code>info-important</code> class should use <code>@extend</code> to inherit the styling from the <code>info</code> class.');"
{
"text": "Your <code>info-important</code> class should have a <code>background-color</code> set to <code>magenta</code>.",
"testString": "assert(code.match(/\\.info-important\\s*?{[\\s\\S]*background-color\\s*?:\\s*?magenta\\s*?;[\\s\\S]*}/gi), 'Your <code>info-important</code> class should have a <code>background-color</code> set to <code>magenta</code>.');"
},
{
"text": "Your <code>info-important</code> class should use <code>@extend</code> to inherit the styling from the <code>info</code> class.",
"testString": "assert(code.match(/\\.info-important\\s*?{[\\s\\S]*@extend\\s*?.info\\s*?;[\\s\\S]*/gi), 'Your <code>info-important</code> class should use <code>@extend</code> to inherit the styling from the <code>info</code> class.');"
}
],
"solutions": [],
"hints": [],
"type": "waypoint",
"releasedOn": "Feb 17, 2017",
"challengeType": 0,
"translations": {}
"translations": {},
"files": {
"indexhtml": {
"key": "indexhtml",
"ext": "html",
"name": "index",
"contents": [
"<style type='text/sass'>",
" h3{",
" text-align: center;",
" }",
" .info{",
" width: 200px;",
" border: 1px solid black;",
" margin: 0 auto;",
" }",
" ",
" ",
" ",
" ",
"</style>",
"<h3>Posts</h3>",
"<div class=\"info-important\">",
" <p>This is an important post. It should extend the class \".info\" and have its own CSS styles.</p>",
"</div>",
"",
"<div class=\"info\">",
" <p>This is a simple post. It has basic styling and can be extended for other uses.</p>",
"</div>"
],
"head": [],
"tail": []
}
}
}
]
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
{
"name": "API and Microservice Projects",
"name": "APIs and Microservices Projects",
"order": 4,
"time": "150 hours",
"helpRoom": "HelpBackend",

View File

@ -4,31 +4,6 @@
"time": "5 hours",
"helpRoom": "Help",
"challenges": [
{
"id": "587d7fb0367417b2b2512bec",
"title": "Introduction to the Basic Node and Express Challenges",
"description": [
[
"",
"",
"Node.js is a JavaScript tool that allows developers to write backend (server-side) programs in JavaScript. Node.js comes with a handful of built-in modules&mdash;small, independent programs&mdash;that help facilitate this purpose. Some of the core modules include:<br><br><ul><li>HTTP: a module that acts as a server</li><li>File System: a module that reads and modifies files</li><li>Path: a module for working with directory and file paths</li><li>Assertion Testing: a module that checks code against prescribed constraints</li></ul><br>Express, while not included with Node.js, is another module often used with it. Express runs between the server created by Node.js and the frontend pages of a web application. Express also handles an application's routing. Routing directs users to the correct page based on their interaction with the application.<br><br>While there are alternatives to using Express, its simplicity makes it a good place to begin when learning the interaction between a backend powered by Node.js and the frontend.",
""
],
[
"",
"",
"Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public Glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.<br>Start this project on Glitch using <a href='https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-express/'>this link</a> or clone <a href='https://github.com/freeCodeCamp/boilerplate-express/'>this repository</a> on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!",
""
]
],
"releasedOn": "Feb 17, 2017",
"challengeSeed": [],
"tests": [],
"type": "waypoint",
"challengeType": 7,
"isRequired": false,
"translations": {}
},
{
"id": "587d7fb0367417b2b2512bed",
"title": "Meet the Node console",

View File

@ -4,31 +4,6 @@
"time": "5 hours",
"helpRoom": "Help",
"challenges": [
{
"id": "587d7fb3367417b2b2512bfa",
"title": "Introduction to the Managing Packages with npm Challenges",
"description": [
[
"",
"",
"The Node Package Manager (npm) is a command-line tool used by developers to share and control modules (or packages) of JavaScript code written for use with Node.js.<br><br>When starting a new project, npm generates a <code>package.json</code> file. This file lists the package dependencies for your project. Since npm packages are regularly updated, the <code>package.json</code> file allows you to set specific version numbers for each dependency. This ensures that updates to a package don't break your project.<br><br>npm saves packages in a folder named <code>node_modules</code>. These packages can be installed in two ways:<br><br><ol><li>globally in a root <code>node_modules</code> folder, accessible by all projects.</li><li>locally within a project's own <code>node_modules</code> folder, accessible only to that project.</li></ol><br>Most developers prefer to install packages local to each project to create a separation between the dependencies of different projects.",
""
],
[
"",
"",
"Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public Glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.<br>Start this project on Glitch using <a href='https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-npm'>this link</a> or clone <a href='https://github.com/freeCodeCamp/boilerplate-npm/'>this repository</a> on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!",
""
]
],
"releasedOn": "Feb 17, 2017",
"challengeSeed": [],
"tests": [],
"type": "waypoint",
"challengeType": 7,
"isRequired": false,
"translations": {}
},
{
"id": "587d7fb3367417b2b2512bfb",
"title": "How to Use package.json, the Core of Any Node.js Project or npm Package",

View File

@ -4,72 +4,6 @@
"time": "5 hours",
"helpRoom": "Help",
"challenges": [
{
"id": "587d7fb5367417b2b2512c05",
"title": "Introduction to the MongoDB and Mongoose Challenges",
"description": [
[
"",
"",
"MongoDB is a database that stores data records (documents) for use by an application. Mongo is a non-relational, \"NoSQL\" database. This means Mongo stores all data associated within one record, instead of storing it across many preset tables as in a SQL database. Some benefits of this storage model are:<br><br><ul><li>Scalability: by default, non-relational databases are split (or \"sharded\") across many systems instead of only one. This makes it easier to improve performance at a lower cost.</li><li>Flexibility: new datasets and properties can be added to a document without the need to make a new table for that data.</li><li>Replication: copies of the database run in parallel so if one goes down, one of the copies becomes the new primary data source.</li></ul><br>While there are many non-relational databases, Mongo's use of JSON as its document storage structure makes it a logical choice when learning backend JavaScript. Accessing documents and their properties is like accessing objects in JavaScript.<br><br>Mongoose.js is an npm module for Node.js that allows you to write objects for Mongo as you would in JavaScript. This can make is easier to construct documents for storage in Mongo.",
""
],
[
"",
"",
"Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.<br>Start this project on Glitch using <a href='https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-mongomongoose/'>this link</a> or clone <a href='https://github.com/freeCodeCamp/boilerplate-mongomongoose/'>this repository</a> on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!",
""
]
],
"releasedOn": "Feb 17, 2017",
"challengeSeed": [],
"tests": [],
"type": "waypoint",
"challengeType": 7,
"isRequired": false,
"translations": {}
},
{
"id": "587d7fb5367437b2b2512c05",
"title": "Create an online database using mLab",
"description": [
[
"",
"",
"For the following challenges, we are going to start using MongoDB to store our data. To simplify the configuration, we are going to use mLab.<br><br>mLab is a MongoDB Database-as-a-Service platform, which basically means that they configure and host the database for you, making it so the only responsibility you have is to populate your database with what matters: data!<br>In the following steps, we are going to show you how to: <ul><li>Create an mLab account.</li><li>Create a free online database.</li><li>Create a new admin user on the database, so you can access it.</li><li>Get the mLab URI, which you will use in your application to connect to your database.</li></ul>Let's start by going to mLab by clicking the button below.",
"https://mlab.com/"
],
[
"",
"",
"Once you open the mLab page, you should sign up for a new account.<ul><li>Click the <a href='https://mlab.com/signup/'>Sign Up</a> button in the top right corner to open the registration page.</li><li>Fill the registration form with your information and send it.</li><li>You should be logged into your new, unverified account.</li><li>In the top of the screen, a message should appear asking to send you an e-mail for account verification. Send and confirm it.</li><li>After you confirm your account, click <bold>Create new</bold> in the <i>MongoDB Deployments</i> section.</li></ul>",
""
],
[
"",
"",
"Now we are going to create the actual database you are going to be using.<ul><li>Choose a <i>Cloud Provider</i> from the available list.</li><li>Select the <i>Sandbox</i> plan type, which is the only one with no cost, and press <bold>Continue</bold>.</li><li>Select a region for your Sandbox, from the available list, and press <bold>Continue</bold>.</li><li>Input a name for your database. This name will be used in the URI for your database. After that, press <bold>Continue</bold>.</li></ul>A summary of all your choices should appear, allowing you to change any information provided in the previous steps. Press <bold>Submit Order</bold> to confirm the information.",
""
],
[
"",
"",
"After you confirmed your configuration, a new sandbox should have been created in the <i>MongoDB Deployments</i> section. We are now going to create an administrator, so you can use the database in your application.<ul><li>Click the newly-created database.</li><li>Click the <i>Users</i> section.</li><li>Click the <bold>Add database user</bold> button.</li><li>Input an username and password for your administrator. Do not mark it as read-only or you will not be able to add any information to the database with this user.</li></ul>",
""
],
[
"",
"",
"Almost done! We have created our new database and created an user to access it, so we just need to find a way to use it in our applications.<ul><li>In your database page, you should see some instructions about connecting using the standard MongoDB URI.</li><li>The line should look like this <code>mongodb://dbuser:dbpassword@ds0$PORT$.mlab.com:$PORT$/$DATABASE-NAME$</code>.</li><li>Copy this URI and substitute dbuser and dbpassword with the information for the user you previously created in the database.</li><li>That's it! This is the URI you will add to your application to connect to your database. Keep this URI safe somewhere, so you can use it later!</li>Feel free to create separate databases for different applications, if they don't have an use for the same data. You just need to create the sandbox, user and obtain the new URI.</ul>",
""
]
],
"challengeSeed": [],
"tests": [],
"type": "waypoint",
"challengeType": 7,
"translations": {}
},
{
"id": "587d7fb6367417b2b2512c06",
"title": "Install and Set Up Mongoose",

View File

@ -4,25 +4,6 @@
"time": "5 hours",
"helpRoom": "Help",
"challenges": [
{
"id": "5895f6fff9fc0f352b528e62",
"title": "Advanced Node/Express Introduction",
"description": [
[
"",
"",
"<em>Authentication</em> is the process or action of verifying the identity of a user or process. Up to this point you have not been able to create an app utilizing this key concept.<br>The most common and easiest to use authentication middleware for Node.js is <a href='http://passportjs.org/'>Passport</a>. It is easy to learn, light-weight, and extremely flexible allowing for many <em>strategies</em>, which we will talk about in later challenges. In addition to authentication we will also look at template engines which allow for use of <em>Pug</em> and web sockets which allow for real time communication between all your clients and your server. Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.<br>Start this project on Glitch using <a href='https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-advancednode/'>this link</a> or clone <a href='https://github.com/freeCodeCamp/boilerplate-advancednode/'>this repository</a> on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!",
""
]
],
"releasedOn": "Feb 17, 2017",
"challengeSeed": [],
"tests": [],
"type": "waypoint",
"challengeType": 7,
"isRequired": false,
"translations": {}
},
{
"id": "5895f700f9fc0f352b528e63",
"title": "Set up a Template Engine",
@ -407,25 +388,6 @@
"challengeType": 2,
"translations": {}
},
{
"id": "589a69f5f9fc0f352b528e6f",
"title": "Social Authentication with OAuth",
"description": [
[
"",
"",
"OAuth 2.0 is the industry-standard authorization and is used across the internet for social login such as letting you login to freeCodeCamp with your Github account.<br>Implementing social login with passport using OAuth is extremely easy to do because of the <a href='http://passportjs.org/'>300+ modules</a> already on npm for adding new strategies to your app. In addition to the ease of installation, it is also easier to use because you do not have to deal with a separate <em>registration</em> or any user input.<br>Start this project on Glitch using <a href='https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-socialauth/'>this link</a> or clone <a href='https://github.com/freeCodeCamp/boilerplate-socialauth/'>this repository</a> on GitHub! If you use Glitch, remember to save the link to your project somewhere safe. Be sure to enter your database in the .env file- it can be the same one from last project since you'll be using a new collection!",
""
]
],
"releasedOn": "Feb 17, 2017",
"challengeSeed": [],
"tests": [],
"type": "waypoint",
"challengeType": 7,
"isRequired": false,
"translations": {}
},
{
"id": "589a69f5f9fc0f352b528e70",
"title": "Implementation of Social Authentication",
@ -507,36 +469,6 @@
"challengeType": 2,
"translations": {}
},
{
"id": "589fc820f9fc0f352b528e73",
"title": "Socket.IO Introduction",
"description": [
[
"",
"",
"<dfn>Socket.IO</dfn> enables real-time, reliable, speedy communication between your server and clients from all devices and browsers. It listens for connects on your server that come from the client which connects with a single javascript statement. The whole library is based on emitting, broadcasting, and receiving events that contain an event name and some data which can include things like strings, objects, arrays, and even blobs like files or video. This is used for all sorts of purposes including instant messaging online, real-time analytics, streaming, and document collaboration.<br>Start this project on Glitch using <a href='https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-socketio/'>this link</a> or clone <a href='https://github.com/freeCodeCamp/boilerplate-socketio/'>this repository</a> on GitHub! If you use Glitch, remember to save the link to your project somewhere safe.",
""
],
[
"",
"",
"To set up this project to get started now in the .env file:<ol><li>Create a random session secret</li><li>Fill in the database (it may be the same as the last few projects since this will use a new collection)</li><li>Obtain another set of Github OAuth credentials with the callback once again pointed at '/auth/github/callback' and add it in</li></ol>",
""
],
[
"",
"",
"A few changes have been made to this starter.<br>Instead of <code>app.listen</code>, you now have <pre>const http = require('http').Server(app);\n\nhttp.listen(process.env.PORT || 3000);</pre> This is required because for the initial handshake between the server and client, http is used. Setting up our server like this allows us to have both processes use a single port.<br>Also, we have declared <code>const sessionStore = new session.MemoryStore();</code> and used <code>sessionStore</code> as the store in our express session. In our previous apps we have not done this because by default it is done automattically. It is not this way so we can reference/use the <code>sessionStore</code> in other parts of our code now. In addition, we've given our session a key to reference it easier.",
""
]
],
"releasedOn": "Feb 17, 2017",
"challengeSeed": [],
"tests": [],
"type": "waypoint",
"challengeType": 7,
"isRequired": false
},
{
"id": "589fc830f9fc0f352b528e74",
"title": "Set up the Environment",
@ -718,24 +650,6 @@
"hints": [],
"challengeType": 2,
"translations": {}
},
{
"id": "58a0b2caf9fc0f352b528e7a",
"title": "Continuing Your Live Chat",
"description": [
[
"",
"",
"From this point, you could choose to implement a plethora of features with just the knowledge you have learned up to this point! Some ideas you could choose to continue this project on with include, but aren't limited to the following:<ul><li>Displaying the users profile picture next to the messages</li><li>Displaying a time stamp on messages</li><li>Saving the most recent messages so when a new user connects they can see the most recent messages sent before they connected</li><li>Add a sidebar showing active users</li><li>Create a {user} is typing feature</li><li>Turn the client into a React component you can add to any of your previous projects</li></ul>",
""
]
],
"releasedOn": "Feb 17, 2017",
"challengeSeed": [],
"tests": [],
"type": "waypoint",
"challengeType": 7,
"isRequired": false
}
]
}

View File

@ -4,25 +4,6 @@
"time": "5 hours",
"helpRoom": "HelpBackend",
"challenges": [
{
"id": "58af07504bbe015e85a91dbd",
"title": "Introduction to Information Security with HelmetJS Challenges",
"description": [
[
"",
"",
"HelmetJS is a type of middleware for Express-based applications that automatically sets HTTP headers to prevent sensitive information from unintentially being passed between the server and client. While HelmetJS does not account for all situations, it does include support for common ones like Content Security Policy, XSS Filtering, and HTTP Strict Transport Security, among others. HelmetJS can be installed on an Express project from npm, after which each layer of protection can be configured to best fit the project.<br><br>Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.<br>Start this project on Glitch using <a href='https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-infosec/'>this link</a> or clone <a href='https://github.com/freeCodeCamp/boilerplate-infosec/'>this repository</a> on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!",
""
]
],
"releasedOn": "Feb 17, 2017",
"challengeSeed": [],
"tests": [],
"type": "waypoint",
"challengeType": 7,
"isRequired": false,
"translations": {}
},
{
"id": "587d8247367417b2b2512c36",
"title": "Install and Require Helmet",
@ -278,24 +259,6 @@
"releasedOn": "Feb 17, 2017",
"translations": {}
},
{
"id": "58a25bcef9fc0f352b528e7b",
"title": "Protect Your Data with BCrypt",
"description": [
[
"",
"",
"The safest way to protect a password is to never even store it- even encrypted. The solution to this security problem is hashing. Unlike encryptions, hashes cannot be transformed back into the original data. So how do you use a hash? A hash is used to verify data like a password again at a later point in time without actually knowing what it is in the future by hashing the entered password in the same manner as the original and comparing the results; if they match then you can be sure it is the same data. A widely used library for this is <em>BCrypt</em>. With how easy BCrypt is to implement into your web applications, you should never have any excuse to store a plain text password in your databases.<br>Start this project on Glitch using <a href='https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-bcrypt/'>this link</a> or clone <a href='https://github.com/freeCodeCamp/boilerplate-bcrypt/'>this repository</a> on GitHub! If you use Glitch, remember to save the link to your project somewhere safe.",
""
]
],
"releasedOn": "",
"challengeSeed": [],
"tests": [],
"type": "Waypoint",
"challengeType": 7,
"isRequired": false
},
{
"id": "58a25bcef9fc0f352b528e7c",
"title": "Understand BCrypt Hashes",

View File

@ -4,25 +4,6 @@
"time": "5 hours",
"helpRoom": "Help",
"challenges": [
{
"id": "58af0b4b4bbe015e85a91dbe",
"title": "Quality Assurance Introduction",
"description": [
[
"",
"",
"As your programs become more complex, you need to test them often to make sure any new code you add doesn't break the program's original functionality. Chai is a JavaScript testing library that helps you check that your program still behaves the way you expect it to after you make changes. Using Chai, you can write tests that describe your program's requirements and see if your program meets them.<br><br>Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.<br>Start this project on Glitch using <a href='https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-mochachai/'>this link</a> or clone <a href='https://github.com/freeCodeCamp/boilerplate-mochachai/'>this repository</a> on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!",
""
]
],
"releasedOn": "Feb 17, 2017",
"challengeSeed": [],
"tests": [],
"type": "waypoint",
"challengeType": 7,
"isRequired": false,
"translations": {}
},
{
"id": "587d824a367417b2b2512c46",
"title": "Learn How JavaScript Assertions Work",

View File

@ -1,5 +1,5 @@
{
"name": "Coding Interview Algorithm Questions",
"name": "Algorithms",
"order": 1,
"time": "",
"helpRoom": "HelpJavaScript",
@ -12,31 +12,66 @@
"Given two sets (for example set <code>A = {1, 2, 3}</code> and set <code>B = {2, 3, 4}</code>), the mathematical term \"symmetric difference\" of two sets is the set of elements which are in either of the two sets, but not in both (<code>A &xutri; B = C = {1, 4}</code>). For every additional symmetric difference you take (say on a set <code>D = {2, 3}</code>), you should get the set with elements which are in either of the two the sets but not both (<code>C &xutri; D = {1, 4} &xutri; {2, 3} = {1, 2, 3, 4}</code>). The resulting array must contain only unique values (<em>no duplicates</em>).",
"Remember to use <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
],
"challengeSeed": [
"function sym(args) {",
" return args;",
"}",
"",
"sym([1, 2, 3], [5, 2, 1, 4]);"
],
"solutions": [
"function sym() {\n var arrays = [].slice.call(arguments);\n return arrays.reduce(function (symDiff, arr) {\n return symDiff.concat(arr).filter(function (val, idx, theArr) {\n return theArr.indexOf(val) === idx \n && (symDiff.indexOf(val) === -1 || arr.indexOf(val) === -1);\n });\n });\n}\nsym([1, 2, 3], [5, 2, 1, 4]);\n"
],
"tests": [
"assert.sameMembers(sym([1, 2, 3], [5, 2, 1, 4]), [3, 4, 5], 'message: <code>sym([1, 2, 3], [5, 2, 1, 4])</code> should return <code>[3, 4, 5]</code>.');",
"assert.equal(sym([1, 2, 3], [5, 2, 1, 4]).length, 3, 'message: <code>sym([1, 2, 3], [5, 2, 1, 4])</code> should contain only three elements.');",
"assert.sameMembers(sym([1, 2, 3, 3], [5, 2, 1, 4]), [3, 4, 5], 'message: <code>sym([1, 2, 3, 3], [5, 2, 1, 4])</code> should return <code>[3, 4, 5]</code>.');",
"assert.equal(sym([1, 2, 3, 3], [5, 2, 1, 4]).length, 3, 'message: <code>sym([1, 2, 3, 3], [5, 2, 1, 4])</code> should contain only three elements.');",
"assert.sameMembers(sym([1, 2, 3], [5, 2, 1, 4, 5]), [3, 4, 5], 'message: <code>sym([1, 2, 3], [5, 2, 1, 4, 5])</code> should return <code>[3, 4, 5]</code>.');",
"assert.equal(sym([1, 2, 3], [5, 2, 1, 4, 5]).length, 3, 'message: <code>sym([1, 2, 3], [5, 2, 1, 4, 5])</code> should contain only three elements.');",
"assert.sameMembers(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5], 'message: <code>sym([1, 2, 5], [2, 3, 5], [3, 4, 5])</code> should return <code>[1, 4, 5]</code>');",
"assert.equal(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]).length, 3, 'message: <code>sym([1, 2, 5], [2, 3, 5], [3, 4, 5])</code> should contain only three elements.');",
"assert.sameMembers(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]), [1, 4, 5], 'message: <code>sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5])</code> should return <code>[1, 4, 5]</code>.');",
"assert.equal(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]).length, 3, 'message: <code>sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5])</code> should contain only three elements.');",
"assert.sameMembers(sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3]), [2, 3, 4, 6, 7], 'message: <code>sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3])</code> should return <code>[2, 3, 4, 6, 7]</code>.');",
"assert.equal(sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3]).length, 5, 'message: <code>sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3])</code> should contain only five elements.');",
"assert.sameMembers(sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1]), [1, 2, 4, 5, 6, 7, 8, 9], 'message: <code>sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1])</code> should return <code>[1, 2, 4, 5, 6, 7, 8, 9]</code>.');",
"assert.equal(sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1]).length, 8, 'message: <code>sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1])</code> should contain only eight elements.');"
{
"text": "<code>sym([1, 2, 3], [5, 2, 1, 4])</code> should return <code>[3, 4, 5]</code>.",
"testString": "assert.sameMembers(sym([1, 2, 3], [5, 2, 1, 4]), [3, 4, 5], '<code>sym([1, 2, 3], [5, 2, 1, 4])</code> should return <code>[3, 4, 5]</code>.');"
},
{
"text": "<code>sym([1, 2, 3], [5, 2, 1, 4])</code> should contain only three elements.",
"testString": "assert.equal(sym([1, 2, 3], [5, 2, 1, 4]).length, 3, '<code>sym([1, 2, 3], [5, 2, 1, 4])</code> should contain only three elements.');"
},
{
"text": "<code>sym([1, 2, 3, 3], [5, 2, 1, 4])</code> should return <code>[3, 4, 5]</code>.",
"testString": "assert.sameMembers(sym([1, 2, 3, 3], [5, 2, 1, 4]), [3, 4, 5], '<code>sym([1, 2, 3, 3], [5, 2, 1, 4])</code> should return <code>[3, 4, 5]</code>.');"
},
{
"text": "<code>sym([1, 2, 3, 3], [5, 2, 1, 4])</code> should contain only three elements.",
"testString": "assert.equal(sym([1, 2, 3, 3], [5, 2, 1, 4]).length, 3, '<code>sym([1, 2, 3, 3], [5, 2, 1, 4])</code> should contain only three elements.');"
},
{
"text": "<code>sym([1, 2, 3], [5, 2, 1, 4, 5])</code> should return <code>[3, 4, 5]</code>.",
"testString": "assert.sameMembers(sym([1, 2, 3], [5, 2, 1, 4, 5]), [3, 4, 5], '<code>sym([1, 2, 3], [5, 2, 1, 4, 5])</code> should return <code>[3, 4, 5]</code>.');"
},
{
"text": "<code>sym([1, 2, 3], [5, 2, 1, 4, 5])</code> should contain only three elements.",
"testString": "assert.equal(sym([1, 2, 3], [5, 2, 1, 4, 5]).length, 3, '<code>sym([1, 2, 3], [5, 2, 1, 4, 5])</code> should contain only three elements.');"
},
{
"text": "<code>sym([1, 2, 5], [2, 3, 5], [3, 4, 5])</code> should return <code>[1, 4, 5]</code>",
"testString": "assert.sameMembers(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5], '<code>sym([1, 2, 5], [2, 3, 5], [3, 4, 5])</code> should return <code>[1, 4, 5]</code>');"
},
{
"text": "<code>sym([1, 2, 5], [2, 3, 5], [3, 4, 5])</code> should contain only three elements.",
"testString": "assert.equal(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]).length, 3, '<code>sym([1, 2, 5], [2, 3, 5], [3, 4, 5])</code> should contain only three elements.');"
},
{
"text": "<code>sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5])</code> should return <code>[1, 4, 5]</code>.",
"testString": "assert.sameMembers(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]), [1, 4, 5], '<code>sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5])</code> should return <code>[1, 4, 5]</code>.');"
},
{
"text": "<code>sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5])</code> should contain only three elements.",
"testString": "assert.equal(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]).length, 3, '<code>sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5])</code> should contain only three elements.');"
},
{
"text": "<code>sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3])</code> should return <code>[2, 3, 4, 6, 7]</code>.",
"testString": "assert.sameMembers(sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3]), [2, 3, 4, 6, 7], '<code>sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3])</code> should return <code>[2, 3, 4, 6, 7]</code>.');"
},
{
"text": "<code>sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3])</code> should contain only five elements.",
"testString": "assert.equal(sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3]).length, 5, '<code>sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3])</code> should contain only five elements.');"
},
{
"text": "<code>sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1])</code> should return <code>[1, 2, 4, 5, 6, 7, 8, 9]</code>.",
"testString": "assert.sameMembers(sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1]), [1, 2, 4, 5, 6, 7, 8, 9], '<code>sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1])</code> should return <code>[1, 2, 4, 5, 6, 7, 8, 9]</code>.');"
},
{
"text": "<code>sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1])</code> should contain only eight elements.",
"testString": "assert.equal(sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1]).length, 8, '<code>sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1])</code> should contain only eight elements.');"
}
],
"type": "bonfire",
"MDNlinks": [
@ -69,6 +104,22 @@
"Lembre-se de usar <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Ler-Procurar-Perguntar</a> se você ficar preso. Tente programar em par. Escreva seu próprio código."
]
}
},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function sym(args) {",
" return args;",
"}",
"",
"sym([1, 2, 3], [5, 2, 1, 4]);"
],
"head": [],
"tail": []
}
}
},
{
@ -78,39 +129,34 @@
"Compare and update the inventory stored in a 2D array against a second 2D array of a fresh delivery. Update the current existing inventory item quantities (in <code>arr1</code>). If an item cannot be found, add the new item and quantity into the inventory array. The returned inventory array should be in alphabetical order by item.",
"Remember to use <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
],
"challengeSeed": [
"function updateInventory(arr1, arr2) {",
" // All inventory must be accounted for or you're fired!",
" return arr1;",
"}",
"",
"// Example inventory lists",
"var curInv = [",
" [21, \"Bowling Ball\"],",
" [2, \"Dirty Sock\"],",
" [1, \"Hair Pin\"],",
" [5, \"Microphone\"]",
"];",
"",
"var newInv = [",
" [2, \"Hair Pin\"],",
" [3, \"Half-Eaten Apple\"],",
" [67, \"Bowling Ball\"],",
" [7, \"Toothpaste\"]",
"];",
"",
"updateInventory(curInv, newInv);"
],
"solutions": [
"function updateInventory(arr1, arr2) {\n arr2.forEach(function(item) {\n createOrUpdate(arr1, item);\n });\n // All inventory must be accounted for or you're fired!\n return arr1;\n}\n\nfunction createOrUpdate(arr1, item) {\n var index = -1;\n while (++index < arr1.length) {\n if (arr1[index][1] === item[1]) {\n arr1[index][0] += item[0];\n return;\n }\n if (arr1[index][1] > item[1]) {\n break;\n }\n }\n arr1.splice(index, 0, item);\n}\n\n// Example inventory lists\nvar curInv = [\n [21, 'Bowling Ball'],\n [2, 'Dirty Sock'],\n [1, 'Hair Pin'],\n [5, 'Microphone']\n];\n\nvar newInv = [\n [2, 'Hair Pin'],\n [3, 'Half-Eaten Apple'],\n [67, 'Bowling Ball'],\n [7, 'Toothpaste']\n];\n\nupdateInventory(curInv, newInv);\n"
],
"tests": [
"assert.isArray(updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]), 'message: The function <code>updateInventory</code> should return an array.');",
"assert.equal(updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]).length, 6, 'message: <code>updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]])</code> should return an array with a length of 6.');",
"assert.deepEqual(updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]), [[88, \"Bowling Ball\"], [2, \"Dirty Sock\"], [3, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [5, \"Microphone\"], [7, \"Toothpaste\"]], 'message: <code>updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]])</code> should return <code>[[88, \"Bowling Ball\"], [2, \"Dirty Sock\"], [3, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [5, \"Microphone\"], [7, \"Toothpaste\"]]</code>.');",
"assert.deepEqual(updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], []), [[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], 'message: <code>updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [])</code> should return <code>[[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]]</code>.');",
"assert.deepEqual(updateInventory([], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]), [[67, \"Bowling Ball\"], [2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [7, \"Toothpaste\"]], 'message: <code>updateInventory([], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]])</code> should return <code>[[67, \"Bowling Ball\"], [2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [7, \"Toothpaste\"]]</code>.');",
"assert.deepEqual(updateInventory([[0, \"Bowling Ball\"], [0, \"Dirty Sock\"], [0, \"Hair Pin\"], [0, \"Microphone\"]], [[1, \"Hair Pin\"], [1, \"Half-Eaten Apple\"], [1, \"Bowling Ball\"], [1, \"Toothpaste\"]]), [[1, \"Bowling Ball\"], [0, \"Dirty Sock\"], [1, \"Hair Pin\"], [1, \"Half-Eaten Apple\"], [0, \"Microphone\"], [1, \"Toothpaste\"]], 'message: <code>updateInventory([[0, \"Bowling Ball\"], [0, \"Dirty Sock\"], [0, \"Hair Pin\"], [0, \"Microphone\"]], [[1, \"Hair Pin\"], [1, \"Half-Eaten Apple\"], [1, \"Bowling Ball\"], [1, \"Toothpaste\"]])</code> should return <code>[[1, \"Bowling Ball\"], [0, \"Dirty Sock\"], [1, \"Hair Pin\"], [1, \"Half-Eaten Apple\"], [0, \"Microphone\"], [1, \"Toothpaste\"]]</code>.');"
{
"text": "The function <code>updateInventory</code> should return an array.",
"testString": "assert.isArray(updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]), 'The function <code>updateInventory</code> should return an array.');"
},
{
"text": "<code>updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]])</code> should return an array with a length of 6.",
"testString": "assert.equal(updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]).length, 6, '<code>updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]])</code> should return an array with a length of 6.');"
},
{
"text": "<code>updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]])</code> should return <code>[[88, \"Bowling Ball\"], [2, \"Dirty Sock\"], [3, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [5, \"Microphone\"], [7, \"Toothpaste\"]]</code>.",
"testString": "assert.deepEqual(updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]), [[88, \"Bowling Ball\"], [2, \"Dirty Sock\"], [3, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [5, \"Microphone\"], [7, \"Toothpaste\"]], '<code>updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]])</code> should return <code>[[88, \"Bowling Ball\"], [2, \"Dirty Sock\"], [3, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [5, \"Microphone\"], [7, \"Toothpaste\"]]</code>.');"
},
{
"text": "<code>updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [])</code> should return <code>[[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]]</code>.",
"testString": "assert.deepEqual(updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], []), [[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], '<code>updateInventory([[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]], [])</code> should return <code>[[21, \"Bowling Ball\"], [2, \"Dirty Sock\"], [1, \"Hair Pin\"], [5, \"Microphone\"]]</code>.');"
},
{
"text": "<code>updateInventory([], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]])</code> should return <code>[[67, \"Bowling Ball\"], [2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [7, \"Toothpaste\"]]</code>.",
"testString": "assert.deepEqual(updateInventory([], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]]), [[67, \"Bowling Ball\"], [2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [7, \"Toothpaste\"]], '<code>updateInventory([], [[2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [67, \"Bowling Ball\"], [7, \"Toothpaste\"]])</code> should return <code>[[67, \"Bowling Ball\"], [2, \"Hair Pin\"], [3, \"Half-Eaten Apple\"], [7, \"Toothpaste\"]]</code>.');"
},
{
"text": "<code>updateInventory([[0, \"Bowling Ball\"], [0, \"Dirty Sock\"], [0, \"Hair Pin\"], [0, \"Microphone\"]], [[1, \"Hair Pin\"], [1, \"Half-Eaten Apple\"], [1, \"Bowling Ball\"], [1, \"Toothpaste\"]])</code> should return <code>[[1, \"Bowling Ball\"], [0, \"Dirty Sock\"], [1, \"Hair Pin\"], [1, \"Half-Eaten Apple\"], [0, \"Microphone\"], [1, \"Toothpaste\"]]</code>.",
"testString": "assert.deepEqual(updateInventory([[0, \"Bowling Ball\"], [0, \"Dirty Sock\"], [0, \"Hair Pin\"], [0, \"Microphone\"]], [[1, \"Hair Pin\"], [1, \"Half-Eaten Apple\"], [1, \"Bowling Ball\"], [1, \"Toothpaste\"]]), [[1, \"Bowling Ball\"], [0, \"Dirty Sock\"], [1, \"Hair Pin\"], [1, \"Half-Eaten Apple\"], [0, \"Microphone\"], [1, \"Toothpaste\"]], '<code>updateInventory([[0, \"Bowling Ball\"], [0, \"Dirty Sock\"], [0, \"Hair Pin\"], [0, \"Microphone\"]], [[1, \"Hair Pin\"], [1, \"Half-Eaten Apple\"], [1, \"Bowling Ball\"], [1, \"Toothpaste\"]])</code> should return <code>[[1, \"Bowling Ball\"], [0, \"Dirty Sock\"], [1, \"Hair Pin\"], [1, \"Half-Eaten Apple\"], [0, \"Microphone\"], [1, \"Toothpaste\"]]</code>.');"
}
],
"type": "bonfire",
"MDNlinks": [
@ -139,6 +185,38 @@
"Lembre-se de usar <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Ler-Procurar-Perguntar</a> se você ficar preso. Tente programar em par. Escreva seu próprio código."
]
}
},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function updateInventory(arr1, arr2) {",
" // All inventory must be accounted for or you're fired!",
" return arr1;",
"}",
"",
"// Example inventory lists",
"var curInv = [",
" [21, \"Bowling Ball\"],",
" [2, \"Dirty Sock\"],",
" [1, \"Hair Pin\"],",
" [5, \"Microphone\"]",
"];",
"",
"var newInv = [",
" [2, \"Hair Pin\"],",
" [3, \"Half-Eaten Apple\"],",
" [67, \"Bowling Ball\"],",
" [7, \"Toothpaste\"]",
"];",
"",
"updateInventory(curInv, newInv);"
],
"head": [],
"tail": []
}
}
},
{
@ -149,27 +227,50 @@
"For example, <code>aab</code> should return 2 because it has 6 total permutations (<code>aab</code>, <code>aab</code>, <code>aba</code>, <code>aba</code>, <code>baa</code>, <code>baa</code>), but only 2 of them (<code>aba</code> and <code>aba</code>) don't have the same letter (in this case <code>a</code>) repeating.",
"Remember to use <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
],
"challengeSeed": [
"function permAlone(str) {",
" return str;",
"}",
"",
"permAlone('aab');"
],
"solutions": [
"function permAlone(str) {\n return permutor(str).filter(function(perm) {\n return !perm.match(/(.)\\1/g);\n }).length;\n}\n\nfunction permutor(str) {\n // http://staff.roguecc.edu/JMiller/JavaScript/permute.html\n //permArr: Global array which holds the list of permutations\n //usedChars: Global utility array which holds a list of \"currently-in-use\" characters\n var permArr = [], usedChars = [];\n function permute(input) {\n //convert input into a char array (one element for each character)\n var i, ch, chars = input.split(\"\");\n for (i = 0; i < chars.length; i++) {\n //get and remove character at index \"i\" from char array\n ch = chars.splice(i, 1);\n //add removed character to the end of used characters\n usedChars.push(ch);\n //when there are no more characters left in char array to add, add used chars to list of permutations\n if (chars.length === 0) permArr[permArr.length] = usedChars.join(\"\");\n //send characters (minus the removed one from above) from char array to be permuted\n permute(chars.join(\"\"));\n //add removed character back into char array in original position\n chars.splice(i, 0, ch);\n //remove the last character used off the end of used characters array\n usedChars.pop();\n }\n }\n permute(str);\n return permArr;\n}\n\npermAlone('aab');\n"
],
"tests": [
"assert.isNumber(permAlone('aab'), 'message: <code>permAlone(\"aab\")</code> should return a number.');",
"assert.strictEqual(permAlone('aab'), 2, 'message: <code>permAlone(\"aab\")</code> should return 2.');",
"assert.strictEqual(permAlone('aaa'), 0, 'message: <code>permAlone(\"aaa\")</code> should return 0.');",
"assert.strictEqual(permAlone('aabb'), 8, 'message: <code>permAlone(\"aabb\")</code> should return 8.');",
"assert.strictEqual(permAlone('abcdefa'), 3600, 'message: <code>permAlone(\"abcdefa\")</code> should return 3600.');",
"assert.strictEqual(permAlone('abfdefa'), 2640, 'message: <code>permAlone(\"abfdefa\")</code> should return 2640.');",
"assert.strictEqual(permAlone('zzzzzzzz'), 0, 'message: <code>permAlone(\"zzzzzzzz\")</code> should return 0.');",
"assert.strictEqual(permAlone('a'), 1, 'message: <code>permAlone(\"a\")</code> should return 1.');",
"assert.strictEqual(permAlone('aaab'), 0, 'message: <code>permAlone(\"aaab\")</code> should return 0.');",
"assert.strictEqual(permAlone('aaabb'), 12, 'message: <code>permAlone(\"aaabb\")</code> should return 12.');"
{
"text": "<code>permAlone(\"aab\")</code> should return a number.",
"testString": "assert.isNumber(permAlone('aab'), '<code>permAlone(\"aab\")</code> should return a number.');"
},
{
"text": "<code>permAlone(\"aab\")</code> should return 2.",
"testString": "assert.strictEqual(permAlone('aab'), 2, '<code>permAlone(\"aab\")</code> should return 2.');"
},
{
"text": "<code>permAlone(\"aaa\")</code> should return 0.",
"testString": "assert.strictEqual(permAlone('aaa'), 0, '<code>permAlone(\"aaa\")</code> should return 0.');"
},
{
"text": "<code>permAlone(\"aabb\")</code> should return 8.",
"testString": "assert.strictEqual(permAlone('aabb'), 8, '<code>permAlone(\"aabb\")</code> should return 8.');"
},
{
"text": "<code>permAlone(\"abcdefa\")</code> should return 3600.",
"testString": "assert.strictEqual(permAlone('abcdefa'), 3600, '<code>permAlone(\"abcdefa\")</code> should return 3600.');"
},
{
"text": "<code>permAlone(\"abfdefa\")</code> should return 2640.",
"testString": "assert.strictEqual(permAlone('abfdefa'), 2640, '<code>permAlone(\"abfdefa\")</code> should return 2640.');"
},
{
"text": "<code>permAlone(\"zzzzzzzz\")</code> should return 0.",
"testString": "assert.strictEqual(permAlone('zzzzzzzz'), 0, '<code>permAlone(\"zzzzzzzz\")</code> should return 0.');"
},
{
"text": "<code>permAlone(\"a\")</code> should return 1.",
"testString": "assert.strictEqual(permAlone('a'), 1, '<code>permAlone(\"a\")</code> should return 1.');"
},
{
"text": "<code>permAlone(\"aaab\")</code> should return 0.",
"testString": "assert.strictEqual(permAlone('aaab'), 0, '<code>permAlone(\"aaab\")</code> should return 0.');"
},
{
"text": "<code>permAlone(\"aaabb\")</code> should return 12.",
"testString": "assert.strictEqual(permAlone('aaabb'), 12, '<code>permAlone(\"aaabb\")</code> should return 12.');"
}
],
"type": "bonfire",
"MDNlinks": [
@ -202,6 +303,22 @@
"Lembre-se de usar <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Ler-Procurar-Perguntar</a> se você ficar preso. Tente programar em par. Escreva seu próprio código."
]
}
},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function permAlone(str) {",
" return str;",
"}",
"",
"permAlone('aab');"
],
"head": [],
"tail": []
}
}
},
{
@ -216,22 +333,30 @@
"7 + 13 = 20 &#8594; Indices 0 + 3 = 3<br>9 + 11 = 20 &#8594; Indices 1 + 2 = 3<br>3 + 3 = 6 &#8594 Return <code>6</code>",
"Remember to use <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
],
"challengeSeed": [
"function pairwise(arr, arg) {",
" return arg;",
"}",
"",
"pairwise([1,4,2,3,0,5], 7);"
],
"solutions": [
"function pairwise(arr, arg) {\n var sum = 0;\n arr.forEach(function(e, i, a) {\n if (e != null) { \n var diff = arg-e;\n a[i] = null;\n var dix = a.indexOf(diff);\n if (dix !== -1) {\n sum += dix;\n sum += i;\n a[dix] = null;\n } \n }\n });\n return sum;\n}\n\npairwise([1,4,2,3,0,5], 7);\n"
],
"tests": [
"assert.deepEqual(pairwise([1, 4, 2, 3, 0, 5], 7), 11, 'message: <code>pairwise([1, 4, 2, 3, 0, 5], 7)</code> should return 11.');",
"assert.deepEqual(pairwise([1, 3, 2, 4], 4), 1, 'message: <code>pairwise([1, 3, 2, 4], 4)</code> should return 1.');",
"assert.deepEqual(pairwise([1, 1, 1], 2), 1, 'message: <code>pairwise([1, 1, 1], 2)</code> should return 1.');",
"assert.deepEqual(pairwise([0, 0, 0, 0, 1, 1], 1), 10, 'message: <code>pairwise([0, 0, 0, 0, 1, 1], 1)</code> should return 10.');",
"assert.deepEqual(pairwise([], 100), 0, 'message: <code>pairwise([], 100)</code> should return 0.');"
{
"text": "<code>pairwise([1, 4, 2, 3, 0, 5], 7)</code> should return 11.",
"testString": "assert.deepEqual(pairwise([1, 4, 2, 3, 0, 5], 7), 11, '<code>pairwise([1, 4, 2, 3, 0, 5], 7)</code> should return 11.');"
},
{
"text": "<code>pairwise([1, 3, 2, 4], 4)</code> should return 1.",
"testString": "assert.deepEqual(pairwise([1, 3, 2, 4], 4), 1, '<code>pairwise([1, 3, 2, 4], 4)</code> should return 1.');"
},
{
"text": "<code>pairwise([1, 1, 1], 2)</code> should return 1.",
"testString": "assert.deepEqual(pairwise([1, 1, 1], 2), 1, '<code>pairwise([1, 1, 1], 2)</code> should return 1.');"
},
{
"text": "<code>pairwise([0, 0, 0, 0, 1, 1], 1)</code> should return 10.",
"testString": "assert.deepEqual(pairwise([0, 0, 0, 0, 1, 1], 1), 10, '<code>pairwise([0, 0, 0, 0, 1, 1], 1)</code> should return 10.');"
},
{
"text": "<code>pairwise([], 100)</code> should return 0.",
"testString": "assert.deepEqual(pairwise([], 100), 0, '<code>pairwise([], 100)</code> should return 0.');"
}
],
"type": "bonfire",
"MDNlinks": [
@ -272,6 +397,22 @@
"Lembre-se de usar <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Ler-Procurar-Perguntar</a> se você ficar preso. Tente programar em par. Escreva seu próprio código."
]
}
},
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function pairwise(arr, arg) {",
" return arg;",
"}",
"",
"pairwise([1,4,2,3,0,5], 7);"
],
"head": [],
"tail": []
}
}
},
{
@ -284,34 +425,54 @@
"<strong>Instructions:</strong> Write a function <code>bubbleSort</code> which takes an array of integers as input and returns an array of these integers in sorted order from least to greatest.",
"<strong>Note:</strong><br>We are calling this function from behind the scenes; the test array we are using is commented out in the editor. Try logging <code>array</code> to see your sorting algorithm in action!"
],
"challengeSeed": [
"function bubbleSort(array) {",
" // change code below this line",
"",
" // change code above this line",
" return array;",
"}",
"",
"// test array:",
"// [1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]"
],
"tail": [
"function isSorted(arr) {",
" var check = (i) => (i == arr.length - 1) ? true : (arr[i] > arr[i + 1]) ? false : check(i + 1);",
" return check(0);",
"};"
],
"tests": [
"assert(typeof bubbleSort == 'function', 'message: <code>bubbleSort</code> is a function.');",
"assert(isSorted(bubbleSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])), 'message: <code>bubbleSort</code> returns a sorted array (least to greatest).');",
"assert.sameMembers(bubbleSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92]), [1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92], 'message: <code>bubbleSort</code> returns an array that is unchanged except for order.');",
"assert.strictEqual(code.search(/\\.sort\\(/), -1, 'message: <code>bubbleSort</code> should not use the built-in <code>.sort()</code> method.');"
{
"text": "<code>bubbleSort</code> is a function.",
"testString": "assert(typeof bubbleSort == 'function', '<code>bubbleSort</code> is a function.');"
},
{
"text": "<code>bubbleSort</code> returns a sorted array (least to greatest).",
"testString": "assert(isSorted(bubbleSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])), '<code>bubbleSort</code> returns a sorted array (least to greatest).');"
},
{
"text": "<code>bubbleSort</code> returns an array that is unchanged except for order.",
"testString": "assert.sameMembers(bubbleSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92]), [1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92], '<code>bubbleSort</code> returns an array that is unchanged except for order.');"
},
{
"text": "<code>bubbleSort</code> should not use the built-in <code>.sort()</code> method.",
"testString": "assert.strictEqual(code.search(/\\.sort\\(/), -1, '<code>bubbleSort</code> should not use the built-in <code>.sort()</code> method.');"
}
],
"type": "waypoint",
"solutions": [],
"challengeType": 1,
"translations": {},
"releasedOn": "February 17, 2017"
"releasedOn": "February 17, 2017",
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function bubbleSort(array) {",
" // change code below this line",
"",
" // change code above this line",
" return array;",
"}",
"",
"// test array:",
"// [1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]"
],
"head": [],
"tail": [
"function isSorted(arr) {",
" var check = (i) => (i == arr.length - 1) ? true : (arr[i] > arr[i + 1]) ? false : check(i + 1);",
" return check(0);",
"};"
]
}
}
},
{
"id": "587d8259367417b2b2512c85",
@ -321,34 +482,54 @@
"<strong>Instructions</strong>: Write a function <code>selectionSort</code> which takes an array of integers as input and returns an array of these integers in sorted order from least to greatest.",
"<strong>Note:</strong><br>We are calling this function from behind the scenes; the test array we are using is commented out in the editor. Try logging <code>array</code> to see your sorting algorithm in action!"
],
"challengeSeed": [
"function selectionSort(array) {",
" // change code below this line",
"",
" // change code above this line",
" return array;",
"}",
"",
"// test array:",
"// [1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]"
],
"tail": [
"function isSorted(arr) {",
" var check = (i) => (i == arr.length - 1) ? true : (arr[i] > arr[i + 1]) ? false : check(i + 1);",
" return check(0);",
"};"
],
"tests": [
"assert(typeof selectionSort == 'function', 'message: <code>selectionSort</code> is a function.');",
"assert(isSorted(selectionSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])), 'message: <code>selectionSort</code> returns a sorted array (least to greatest).');",
"assert.sameMembers(selectionSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92]), [1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92], 'message: <code>selectionSort</code> returns an array that is unchanged except for order.');",
"assert.strictEqual(code.search(/\\.sort\\(/), -1, 'message: <code>selectionSort</code> should not use the built-in <code>.sort()</code> method.');"
{
"text": "<code>selectionSort</code> is a function.",
"testString": "assert(typeof selectionSort == 'function', '<code>selectionSort</code> is a function.');"
},
{
"text": "<code>selectionSort</code> returns a sorted array (least to greatest).",
"testString": "assert(isSorted(selectionSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])), '<code>selectionSort</code> returns a sorted array (least to greatest).');"
},
{
"text": "<code>selectionSort</code> returns an array that is unchanged except for order.",
"testString": "assert.sameMembers(selectionSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92]), [1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92], '<code>selectionSort</code> returns an array that is unchanged except for order.');"
},
{
"text": "<code>selectionSort</code> should not use the built-in <code>.sort()</code> method.",
"testString": "assert.strictEqual(code.search(/\\.sort\\(/), -1, '<code>selectionSort</code> should not use the built-in <code>.sort()</code> method.');"
}
],
"type": "waypoint",
"solutions": [],
"challengeType": 1,
"translations": {},
"releasedOn": "February 17, 2017"
"releasedOn": "February 17, 2017",
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function selectionSort(array) {",
" // change code below this line",
"",
" // change code above this line",
" return array;",
"}",
"",
"// test array:",
"// [1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]"
],
"head": [],
"tail": [
"function isSorted(arr) {",
" var check = (i) => (i == arr.length - 1) ? true : (arr[i] > arr[i + 1]) ? false : check(i + 1);",
" return check(0);",
"};"
]
}
}
},
{
"id": "587d8259367417b2b2512c86",
@ -358,34 +539,54 @@
"<strong>Instructions:</strong> Write a function <code>insertionSort</code> which takes an array of integers as input and returns an array of these integers in sorted order from least to greatest.",
"<strong>Note:</strong><br>We are calling this function from behind the scenes; the test array we are using is commented out in the editor. Try logging <code>array</code> to see your sorting algorithm in action!"
],
"challengeSeed": [
"function insertionSort(array) {",
" // change code below this line",
"",
" // change code above this line",
" return array;",
"}",
"",
"// test array:",
"// [1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]"
],
"tail": [
"function isSorted(arr) {",
" var check = (i) => (i == arr.length - 1) ? true : (arr[i] > arr[i + 1]) ? false : check(i + 1);",
" return check(0);",
"};"
],
"tests": [
"assert(typeof insertionSort == 'function', 'message: <code>insertionSort</code> is a function.');",
"assert(isSorted(insertionSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])), 'message: <code>insertionSort</code> returns a sorted array (least to greatest).');",
"assert.sameMembers(insertionSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92]), [1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92], 'message: <code>insertionSort</code> returns an array that is unchanged except for order.');",
"assert.strictEqual(code.search(/\\.sort\\(/), -1, 'message: <code>insertionSort</code> should not use the built-in <code>.sort()</code> method.');"
{
"text": "<code>insertionSort</code> is a function.",
"testString": "assert(typeof insertionSort == 'function', '<code>insertionSort</code> is a function.');"
},
{
"text": "<code>insertionSort</code> returns a sorted array (least to greatest).",
"testString": "assert(isSorted(insertionSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])), '<code>insertionSort</code> returns a sorted array (least to greatest).');"
},
{
"text": "<code>insertionSort</code> returns an array that is unchanged except for order.",
"testString": "assert.sameMembers(insertionSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92]), [1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92], '<code>insertionSort</code> returns an array that is unchanged except for order.');"
},
{
"text": "<code>insertionSort</code> should not use the built-in <code>.sort()</code> method.",
"testString": "assert.strictEqual(code.search(/\\.sort\\(/), -1, '<code>insertionSort</code> should not use the built-in <code>.sort()</code> method.');"
}
],
"type": "waypoint",
"solutions": [],
"challengeType": 1,
"translations": {},
"releasedOn": "February 17, 2017"
"releasedOn": "February 17, 2017",
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function insertionSort(array) {",
" // change code below this line",
"",
" // change code above this line",
" return array;",
"}",
"",
"// test array:",
"// [1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]"
],
"head": [],
"tail": [
"function isSorted(arr) {",
" var check = (i) => (i == arr.length - 1) ? true : (arr[i] > arr[i + 1]) ? false : check(i + 1);",
" return check(0);",
"};"
]
}
}
},
{
"id": "587d825a367417b2b2512c89",
@ -396,34 +597,54 @@
"<strong>Instructions:</strong> Write a function <code>quickSort</code> which takes an array of integers as input and returns an array of these integers in sorted order from least to greatest. While the choice of the pivot value is important, any pivot will do for our purposes here. For simplicity, the first or last element could be used.",
"<strong>Note:</strong><br>We are calling this function from behind the scenes; the test array we are using is commented out in the editor. Try logging <code>array</code> to see your sorting algorithm in action!"
],
"challengeSeed": [
"function quickSort(array) {",
" // change code below this line",
"",
" // change code above this line",
" return array;",
"}",
"",
"// test array:",
"// [1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]"
],
"tests": [
"assert(typeof quickSort == 'function', 'message: <code>quickSort</code> is a function.');",
"assert(isSorted(quickSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])), 'message: <code>quickSort</code> returns a sorted array (least to greatest).');",
"assert.sameMembers(quickSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92]), [1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92], 'message: <code>quickSort</code> returns an array that is unchanged except for order.');",
"assert.strictEqual(code.search(/\\.sort\\(/), -1, 'message: <code>quickSort</code> should not use the built-in <code>.sort()</code> method.');"
],
"tail": [
"function isSorted(arr) {",
" var check = (i) => (i == arr.length - 1) ? true : (arr[i] > arr[i + 1]) ? false : check(i + 1);",
" return check(0);",
"};"
{
"text": "<code>quickSort</code> is a function.",
"testString": "assert(typeof quickSort == 'function', '<code>quickSort</code> is a function.');"
},
{
"text": "<code>quickSort</code> returns a sorted array (least to greatest).",
"testString": "assert(isSorted(quickSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])), '<code>quickSort</code> returns a sorted array (least to greatest).');"
},
{
"text": "<code>quickSort</code> returns an array that is unchanged except for order.",
"testString": "assert.sameMembers(quickSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92]), [1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92], '<code>quickSort</code> returns an array that is unchanged except for order.');"
},
{
"text": "<code>quickSort</code> should not use the built-in <code>.sort()</code> method.",
"testString": "assert.strictEqual(code.search(/\\.sort\\(/), -1, '<code>quickSort</code> should not use the built-in <code>.sort()</code> method.');"
}
],
"type": "waypoint",
"solutions": [],
"challengeType": 1,
"translations": {},
"releasedOn": "February 17, 2017"
"releasedOn": "February 17, 2017",
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function quickSort(array) {",
" // change code below this line",
"",
" // change code above this line",
" return array;",
"}",
"",
"// test array:",
"// [1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]"
],
"head": [],
"tail": [
"function isSorted(arr) {",
" var check = (i) => (i == arr.length - 1) ? true : (arr[i] > arr[i + 1]) ? false : check(i + 1);",
" return check(0);",
"};"
]
}
}
},
{
"id": "587d825c367417b2b2512c8f",
@ -437,34 +658,54 @@
"<strong>Instructions:</strong> Write a function <code>mergeSort</code> which takes an array of integers as input and returns an array of these integers in sorted order from least to greatest. A good way to implement this is to write one function, for instance <code>merge</code>, which is responsible for merging two sorted arrays, and another function, for instance <code>mergeSort</code>, which is responsible for the recursion that produces single-item arrays to feed into merge. Good luck!",
"<strong>Note:</strong><br>We are calling this function from behind the scenes; the test array we are using is commented out in the editor. Try logging <code>array</code> to see your sorting algorithm in action!"
],
"challengeSeed": [
"function mergeSort(array) {",
" // change code below this line",
"",
" // change code above this line",
" return array;",
"}",
"",
"// test array:",
"// [1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]"
],
"tests": [
"assert(typeof mergeSort == 'function', 'message: <code>mergeSort</code> is a function.');",
"assert(isSorted(mergeSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])), 'message: <code>mergeSort</code> returns a sorted array (least to greatest).');",
"assert.sameMembers(mergeSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92]), [1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92], 'message: <code>mergeSort</code> returns an array that is unchanged except for order.');",
"assert.strictEqual(code.search(/\\.sort\\(/), -1, 'message: <code>mergeSort</code> should not use the built-in <code>.sort()</code> method.');"
],
"tail": [
"function isSorted(arr) {",
" var check = (i) => (i == arr.length - 1) ? true : (arr[i] > arr[i + 1]) ? false : check(i + 1);",
" return check(0);",
"};"
{
"text": "<code>mergeSort</code> is a function.",
"testString": "assert(typeof mergeSort == 'function', '<code>mergeSort</code> is a function.');"
},
{
"text": "<code>mergeSort</code> returns a sorted array (least to greatest).",
"testString": "assert(isSorted(mergeSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])), '<code>mergeSort</code> returns a sorted array (least to greatest).');"
},
{
"text": "<code>mergeSort</code> returns an array that is unchanged except for order.",
"testString": "assert.sameMembers(mergeSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92]), [1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92], '<code>mergeSort</code> returns an array that is unchanged except for order.');"
},
{
"text": "<code>mergeSort</code> should not use the built-in <code>.sort()</code> method.",
"testString": "assert.strictEqual(code.search(/\\.sort\\(/), -1, '<code>mergeSort</code> should not use the built-in <code>.sort()</code> method.');"
}
],
"type": "waypoint",
"solutions": [],
"challengeType": 1,
"translations": {},
"releasedOn": "February 17, 2017"
"releasedOn": "February 17, 2017",
"files": {
"indexjs": {
"key": "indexjs",
"ext": "js",
"name": "index",
"contents": [
"function mergeSort(array) {",
" // change code below this line",
"",
" // change code above this line",
" return array;",
"}",
"",
"// test array:",
"// [1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]"
],
"head": [],
"tail": [
"function isSorted(arr) {",
" var check = (i) => (i == arr.length - 1) ? true : (arr[i] > arr[i + 1]) ? false : check(i + 1);",
" return check(0);",
"};"
]
}
}
}
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
{
"name": "Coding Interview Take-home Projects",
"name": "Take Home Projects",
"order": 4,
"time": "",
"helpRoom": "HelpFrontEnd",
@ -12,7 +12,7 @@
"<strong>Rule #1:</strong> Don't look at the example project's code. Figure it out for yourself.",
"<strong>Rule #2:</strong> Fulfill the below <a href='https://en.wikipedia.org/wiki/User_story' target='_blank'>user stories</a>. Use whichever libraries or APIs you need. Give it your own personal style.",
"<strong>User Story:</strong> I can see the weather in my current location.",
"<strong>User Story:</strong> I can see a different icon or background image that matches the current weather. The weather could be rain, shower rain, light rain, moderate rain, snow, few clouds, scattered clouds, broken clouds, clouds, drizzling, clear sky, thunderstorm, mist, fog, or smoke. (The icon or image could be the same for shower rain, light rain, etc.)",
"<strong>User Story:</strong> I can see a different icon or background image (e.g. snowy mountain, hot desert) depending on the weather.",
"<strong>User Story:</strong> I can push a button to toggle between Fahrenheit and Celsius.",
"<strong>Note:</strong> Many internet browsers now require an HTTP Secure (<code>https://</code>) connection to obtain a user's locale via HTML5 Geolocation. For this reason, we recommend using HTML5 Geolocation to get user location and then use the freeCodeCamp Weather API <a href='https://fcc-weather-api.glitch.me' target='_blank'>https://fcc-weather-api.glitch.me</a> which uses an HTTP Secure connection for the weather. Also, be sure to connect to <a href='https://codepen.io' target='_blank'>CodePen.io</a> via <code>https://</code>.",
"Remember to use <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Read-Search-Ask</a> if you get stuck.",
@ -31,7 +31,7 @@
"<span class='text-info'>Objetivo:</span> Crea una aplicación con <a href='https://codepen.io' target='_blank'>CodePen.io</a> cuya funcionalidad sea similar a la de esta: <a href='https://codepen.io/freeCodeCamp/full/bELRjV' target='_blank'>https://codepen.io/freeCodeCamp/full/bELRjV</a>.",
"Satisface las siguientes <a href='https://en.wikipedia.org/wiki/User_story' target='_blank'>historias de usuario</a>. Usa cualquier librería o APIs que necesites.",
"<span class='text-info'>Historia de usuario:</span> Pedo obtener información acerca del clima en mi localización actual.",
"<span class='text-info'>Historia de usuario:</span> Puedo ver un ícono o imagen de fondo diferente que coincide con el clima actual. El clima podría ser rain, shower rain, light rain, moderate rain, snow, few clouds, scattered clouds, broken clouds, clouds, drizzling, clear sky, thunderstorm, mist, fog, o smoke. (El ícono o la imagen podría ser el mismo para lluvia de lluvia, lluvia ligera, etc.)",
"<span class='text-info'>Historia de usuario:</span> Puedo ver un icono diferente o una imagen de fondo diferente (e.g. montaña con nieve, desierto caliente) dependiendo del clima.",
"<span class='text-info'>Historia de usuario:</span> Puedo pulsar un botón para cambiar la unidad de temperatura de grados Fahrenheit a Celsius y viceversa.",
"Recomendamos utilizar <a href='https://openweathermap.org/current#geo' target='_blank'>Open Weather API</a>. Al utilizarlo tendrás que crear una llave API gratuita. Normalmente debes evitar exponer llaves de API en CodePen, pero por el momento no hemos encontrado un API de clima que no requiera llave.",
"Recuerda utilizar <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado.",
@ -49,7 +49,7 @@
"Реализуйте следующие <a href='https://en.wikipedia.org/wiki/User_story' target='_blank'>пользовательские истории</a>, сделайте также бонусные по желанию:",
"<span class='text-info'>Пользовательская история:</span> В качестве пользователя, я могу узнать погоду с учетом моего текущего местоположения.",
"<span class='text-info'>Бонусная пользовательская история:</span> В качестве пользователя, я могу в зависимости от погоды видеть различные температурные значки.",
"<span class='text-info'>Бонусная пользовательская история:</span> Я вижу другой значок или фоновое изображение, которое соответствует текущей погоде. Погода может быть rain, shower rain, light rain, moderate rain, snow, few clouds, scattered clouds, broken clouds, clouds, drizzling, clear sky, thunderstorm, mist, fog, smoke. (Значок или изображение могут быть одинаковыми для дождя дождя, легкого дождя и т. Д.)",
"<span class='text-info'>Бонусная пользовательская история:</span> В качестве пользователя, я могу в зависимости от погоды видеть различные фоновые изображения (снежные горы, знойная пустыня).",
"<span class='text-info'>Бонусная пользовательская история:</span> В качестве пользователя, я могу нажать на кнопку чтобы переключится между градусами по Цельсию или по Фаренгейту.",
"Если что-то не получается, воспользуйтесь <a href='http://forum.freecodecamp.org/t/how-to-get-help-when-you-are-stuck/19514' target='_blank'>Read-Search-Ask</a>.",
"Когда выполните задание кликните кнопку \"I've completed this challenge\" и добавьте ссылку на ваш CodePen. Если вы программировали с кем-то в паре, также добавьте имя вашего напарника.",
@ -869,5 +869,8 @@
"challengeType": 3,
"isRequired": false
}
]
],
"fileName": "08-coding-interview-questions-and-take-home-assignments/take-home-interview-projects.json",
"superBlock": "coding-interview-questions-and-take-home-assignments",
"superOrder": 8
}

File diff suppressed because one or more lines are too long

View File

@ -24,7 +24,7 @@
"title": "URL Shortener Microservice"
},
{
"id": "5a8b073d06fa14fcfde687aa",
"id": "bd7158d8c443edefaeb5bdee",
"title": "Exercise Tracker"
},
{

View File

@ -34,4 +34,4 @@
]
}
]
}
}

View File

@ -34,4 +34,4 @@
]
}
]
}
}

View File

@ -54,4 +54,4 @@
]
}
]
}
}

View File

@ -54,4 +54,4 @@
]
}
]
}
}

View File

@ -28,7 +28,7 @@
"title": "Build a Technical Documentation Page"
},
{
"id": "bd7158d8c242eddfaeb5bd13",
"id": "587d78b0367417b2b2512b06",
"title": "Build a Personal Portfolio Webpage"
}
]

View File

@ -1,53 +0,0 @@
/* eslint-disable no-process-exit */
/**
* Data creation script for academic data pushes. Run this script with
* node seed/get-challenge-completion.js >> ~/output.json
* For large data sets supply the flag --max_old_space_size=2000000 to node.
* Run from the root FCC directory. Beware, this will generate a very large file
* if you have a large user collection such as the production mongo db.
*/
require('dotenv').load();
var secrets = require('../config/secrets'),
mongodb = require('mongodb'),
MongoClient = mongodb.MongoClient;
MongoClient.connect(secrets.db, function(err, database) {
if (err) {
throw err;
}
var firstTime = true;
var stream = database.collection('user')
.find({'completedChallenges': { $ne: null },
'isLocked': { $ne: true } },
{'completedChallenges': true})
.stream();
console.log('[');
stream.on('data', function(results) {
if (!results.completedChallenges) {
// dud
} else {
var dataOut = [];
results.completedChallenges.forEach(function(challenge) {
dataOut.push({
name: challenge.name,
completedDate: challenge.completedDate,
solution: challenge.solution
});
});
if (dataOut.length) {
if (!firstTime) {
console.log(',' + JSON.stringify(dataOut));
} else {
firstTime = false;
console.log(JSON.stringify(dataOut));
}
}
}
}).on('end', function() {
console.log(']');
process.exit(0);
});
});

29
gulpfile.js Normal file
View File

@ -0,0 +1,29 @@
const gulp = require('gulp');
const util = require('gulp-util');
const jsonMinify = require('gulp-json-minify');
const babel = require('gulp-babel');
const rename = require('gulp-rename');
gulp.task('json:minify', function() {
return gulp.src('./challenges/**/*.json')
.pipe(jsonMinify())
.pipe(gulp.dest('dist/challenges/'))
.on('error', util.log);
});
gulp.task('babel-getChallenges', () =>
gulp.src('./getChallenges.js')
.pipe(babel({
presets: ['env']
}))
.pipe(gulp.dest('dist'))
);
gulp.task('babel', ['babel-getChallenges'], () =>
gulp.src('./package-entry.js')
.pipe(rename('./index.js'))
.pipe(babel({
presets: ['env']
}))
.pipe(gulp.dest('dist/'))
);

View File

@ -5,11 +5,13 @@ const adler32 = require('adler32');
const Rx = require('rx');
const _ = require('lodash');
const createDebugger = require('debug');
const utils = require('../server/utils');
const getChallenges = require('./getChallenges');
const { validateChallenge } = require(
'./schema/challengeSchema'
);
const app = require('../server/server');
const createDebugger = require('debug');
const { validateChallenge } = require('./schema/challengeSchema');
const log = createDebugger('fcc:seed');
// force logger to always output

View File

@ -1,137 +0,0 @@
var fs = require('fs');
var path = require('path');
var sortKeys = require('sort-keys');
// var Rx = require('rx');
// var langTagRegex = /^[a-z]{2,3}(?:-[A-Z]{2,3}(?:-[a-zA-Z]{4})?)?$/;
var translationRegex = /(description|title)([a-zA-Z]{2,4})/i;
var oldNameRegex = /name([a-zA-Z]{2,4})/i;
function hasOldTranslation(key) {
return translationRegex.test(key) || oldNameRegex.test(key);
}
function normalizeLangTag(tag) {
return tag.slice(0, 2).toLowerCase() + (
tag.length > 2 ? '-' + tag.slice(2).toUpperCase() : ''
);
}
function sortTranslationsKeys(translations) {
Object.keys(translations)
.forEach(function(key) {
if (Object.keys(translations[key]).length > 2) {
console.log('keys', Object.keys(translations[key]));
throw new Error('Unknown keys');
}
});
var _translations = Object.keys(translations)
.reduce(function(_translations, key) {
_translations[key] = sortKeys(translations[key], {
compare: function(a, b) {
return b > a;
}
});
_translations[key] = Object.keys(_translations[key])
.reduce(function(translation, _key) {
translation[_key.toLowerCase()] = _translations[key][_key];
return translation;
}, {});
return _translations;
}, {});
return sortKeys(_translations);
}
function createNewTranslations(challenge) {
return Object.keys(challenge)
.filter(hasOldTranslation)
.reduce(function(translations, oldKey) {
var matches, tag, newTranslation;
if (translationRegex.test(oldKey)) {
matches = oldKey.match(translationRegex);
tag = normalizeLangTag(matches[2]);
newTranslation = {};
newTranslation[matches[1]] = challenge[oldKey];
translations[tag] = translations[tag] ?
({...translations[tag], ...newTranslation}) :
({...newTranslation});
return translations;
}
matches = oldKey.match(oldNameRegex);
tag = normalizeLangTag(matches[1]);
newTranslation = { title: challenge[oldKey] };
translations[tag] = translations[tag] ?
({...translations[tag], ...newTranslation}) :
({...newTranslation});
return translations;
}, {});
}
function normalizeChallenge(challenge) {
var keys = Object.keys(challenge);
challenge.translations = challenge.translations || {};
var hasOldTranslations = keys.some(hasOldTranslation);
if (hasOldTranslations) {
challenge.translations = ({
...challenge.translations,
...createNewTranslations(challenge)
});
}
challenge.translations = sortTranslationsKeys(challenge.translations);
// remove old translations from the top level
return Object.keys(challenge)
.filter(function(key) { return !hasOldTranslation(key); })
.reduce(function(newChallenge, key) {
newChallenge[key] = challenge[key];
return newChallenge;
}, {});
}
function normalizeBlock(block) {
block.challenges = block.challenges.map(normalizeChallenge);
return block;
}
function getFilesForDir(dir) {
return fs.readdirSync(path.join(__dirname, '/' + dir))
.map(function(file) {
if (fs.statSync(path.join(__dirname, dir + '/' + file)).isFile()) {
return { path: dir + '/' + file };
}
return getFilesForDir(dir + '/' + file);
})
.reduce(function(files, file) {
if (!Array.isArray(file)) {
files.push(file);
return files;
}
return files.concat(file);
}, []);
}
function normalize(dir) {
return getFilesForDir(dir)
.map(function(data) {
return {
path: data.path,
block: require(path.join(__dirname, data.path))
};
})
.map(function(data) {
return {
path: data.path,
block: normalizeBlock(data.block)
};
})
.forEach(function(data) {
var file = JSON.stringify(data.block, null, 2);
if (/[^\n]$/.test(file)) {
file = file + '\n';
}
fs.writeFileSync(
path.join(__dirname, '/', data.path),
file
);
});
}
normalize('challenges');

1
package-entry.js Normal file
View File

@ -0,0 +1 @@
export { default as getChallenges } from './getChallenges';

5791
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

54
package.json Normal file
View File

@ -0,0 +1,54 @@
{
"name": "@freecodecamp/curriculum",
"version": "1.0.0",
"description": "freeCodeCamp's curriculum seed files",
"main": "dist/index.js",
"scripts": {
"build": "npm run build:js && npm run build:json",
"build:json": "gulp json:minify",
"build:js": "gulp babel",
"prepack": "npm run build",
"unpack": "babel-node ./unpack.js",
"repack": "babel-node ./repack.js",
"test": "babel-node ./test-challenges.js | tap-spec"
},
"repository": {
"type": "git",
"url": "git+https://github.com/freecodecamp/freecodecamp.git"
},
"keywords": [
"freecodecamp",
"curriculum",
"challenges",
"javascript",
"interview",
"json"
],
"author": "freeCodeCamp <team@freecodecamp.org>",
"license": "(BSD-3-Clause AND CC-BY-SA-4.0)",
"bugs": {
"url": "https://github.com/freecodecamp/freecodecamp/issues"
},
"homepage": "https://github.com/freecodecamp/freecodecamp#readme",
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-preset-env": "^1.7.0",
"babel-standalone": "^6.26.0",
"browserify": "^16.2.2",
"fs-extra": "^6.0.1",
"gulp": "^3.9.1",
"gulp-babel": "^7.0.1",
"gulp-json-minify": "^1.2.2",
"gulp-rename": "^1.2.3",
"gulp-util": "^3.0.8",
"joi": "^13.3.0",
"joi-objectid": "^2.0.0",
"jquery": "^3.3.1",
"lodash": "^4.17.10",
"tap-spec": "^4.1.1",
"tape": "^4.9.0",
"validator": "^10.2.0"
},
"dependencies": {}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -11,24 +11,7 @@ const schema = Joi.object().keys({
checksum: Joi.number(),
dashedName: Joi.string(),
description: Joi.array().items(
// classic/modern challenges
Joi.string().allow(''),
// step challenges
Joi.array().items(
Joi.string().allow('')
).length(4),
// quiz challenges
Joi.object().keys({
subtitle: Joi.string(),
question: Joi.string(),
choices: Joi.array(),
answer: Joi.number(),
explanation: Joi.string()
})
Joi.string().allow('')
).required(),
fileName: Joi.string(),
files: Joi.object().pattern(
@ -39,7 +22,7 @@ const schema = Joi.object().keys({
name: Joi.string(),
head: Joi.string().allow(''),
tail: Joi.string().allow(''),
contents: Joi.string()
contents: Joi.string().allow('')
})
),
guideUrl: Joi.string().uri({ scheme: 'https' }),
@ -73,14 +56,9 @@ const schema = Joi.object().keys({
Joi.string().allow('')
),
tests: Joi.array().items(
Joi.string().min(2),
Joi.object().keys({
text: Joi.string().required(),
testString: Joi.string().allow('').required()
}),
Joi.object().keys({
id: Joi.objectId().required(),
title: Joi.string().required()
})
),
template: Joi.string(),

View File

@ -4,18 +4,28 @@ import {Observable} from 'rx';
import tape from 'tape';
import getChallenges from './getChallenges';
import { modern } from '../common/app/utils/challengeTypes';
import MongoIds from './mongoIds';
import ChallengeTitles from './challengeTitles';
import addAssertsToTapTest from './addAssertsToTapTest';
// modern challengeType
const modern = 6;
let mongoIds = new MongoIds();
let challengeTitles = new ChallengeTitles();
function evaluateTest(solution, assert,
react, redux, reactRedux,
head, tail,
test, tapTest) {
function evaluateTest(
solution,
assert,
react,
redux,
reactRedux,
head,
tail,
test,
tapTest
) {
let code = solution;
@ -94,14 +104,22 @@ function evaluateTest(solution, assert,
try {
(() => {
return eval(
head + '\n;;' +
solution + '\n;;' +
tail + '\n;;' +
test
head + '\n' +
solution + '\n' +
tail + '\n' +
test.testString
);
})();
} catch (e) {
console.log(
head + '\n' +
solution + '\n' +
tail + '\n' +
test.testString
);
console.log(e);
tapTest.fail(e);
process.exit(1);
}
}
@ -110,8 +128,7 @@ function createTest({
id = '',
tests = [],
solutions = [],
head = [],
tail = [],
files = [],
react = false,
redux = false,
reactRedux = false
@ -128,12 +145,18 @@ function createTest({
console.log(`Replacing Async Tests for Challenge ${title}`);
tests = tests.map(challengeTestSource =>
isAsync(challengeTestSource) ?
"assert(true, 'message: great');" :
challengeTestSource);
}
head = head.join('\n');
tail = tail.join('\n');
"assert(true, 'message: great');" :
challengeTestSource);
}
const { head, tail } = Object.keys(files)
.map(key => files[key])
.reduce(
(result, file) => ({
head: result.head + ';' + file.head.join('\n'),
tail: result.tail + ';' + file.tail.join('\n')
}),
{ head: '', tail: '' }
);
const plan = tests.length;
if (!plan) {
return Observable.just({
@ -161,8 +184,17 @@ function createTest({
.doOnNext(assert => {
solutions.forEach(solution => {
tests.forEach(test => {
evaluateTest(solution, assert, react, redux, reactRedux,
head, tail, test, tapTest);
evaluateTest(
solution,
assert,
react,
redux,
reactRedux,
head,
tail,
test,
tapTest
);
});
});
})

View File

@ -2,7 +2,7 @@
import fs from 'fs-extra';
import path from 'path';
import _ from 'lodash';
import { dasherize } from '../common/utils';
import { dasherize } from './utils';
const jsonLinePrefix = '//--JSON:';
const paragraphBreak = '<!--break-->';
@ -199,8 +199,8 @@ class UnpackedChallenge {
text.push('</head>');
text.push('<body>');
text.push(`<h1>${this.challenge.title}</h1>`);
text.push(`<p>This is the <b>unpacked</b> version of
<code>${this.superBlockName}/${this.challengeBlockName}</code>
text.push(`<p>This is the <b>unpacked</b> version of
<code>${this.superBlockName}/${this.challengeBlockName}</code>
(challenge id <code>${this.challenge.id}</code>).</p>`);
text.push('<p>Open the JavaScript console to see test results.</p>');
@ -279,7 +279,7 @@ class UnpackedChallenge {
text.push('/*--tests--*/');
text.push(this.expandedTests(this.challenge.tests).join('\n'));
text.push('/*--end--*/');
text.push('});')
text.push('});');
text.push('</script>');
text.push('');

7
utils.js Normal file
View File

@ -0,0 +1,7 @@
export function dasherize(name) {
return ('' + name)
.toLowerCase()
.replace(/\s/g, '-')
.replace(/[^a-z0-9\-\.]/gi, '')
.replace(/\:/g, '');
}