diff --git a/client/src/client/frame-runner.js b/client/src/client/frame-runner.js index 84a94dce7d..e2bf59931f 100644 --- a/client/src/client/frame-runner.js +++ b/client/src/client/frame-runner.js @@ -1,5 +1,6 @@ import '@babel/polyfill'; import jQuery from 'jquery'; +import curriculumHelpers from '../utils/curriculum-helpers'; window.$ = jQuery; @@ -48,6 +49,7 @@ async function initTestFrame(e = { code: {} }) { // eslint-disable-next-line no-inline-comments const { default: chai } = await import(/* webpackChunkName: "chai" */ 'chai'); const assert = chai.assert; + const __helpers = curriculumHelpers; /* eslint-enable no-unused-vars */ let Enzyme; diff --git a/client/src/client/workers/test-evaluator.js b/client/src/client/workers/test-evaluator.js index 4f146101ac..cec40e4eba 100644 --- a/client/src/client/workers/test-evaluator.js +++ b/client/src/client/workers/test-evaluator.js @@ -2,6 +2,7 @@ import chai from 'chai'; import '@babel/polyfill'; import __toString from 'lodash/toString'; import { format as __format } from '../../utils/format'; +import curriculumHelpers from '../../utils/curriculum-helpers'; const __utils = (() => { const MAX_LOGS_SIZE = 64 * 1024; @@ -59,6 +60,7 @@ self.onmessage = async e => { const editableContents = (e.data?.code?.editableContents || '').slice(); const assert = chai.assert; + const __helpers = curriculumHelpers; // Fake Deep Equal dependency const DeepEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b); diff --git a/client/src/utils/__fixtures/curriculum-helpers-css.js b/client/src/utils/__fixtures/curriculum-helpers-css.js new file mode 100644 index 0000000000..e34371664f --- /dev/null +++ b/client/src/utils/__fixtures/curriculum-helpers-css.js @@ -0,0 +1,45 @@ +const cssFullExample = ` +a { + color: green; + display: flex; +} +.aClass { + font-size: 32px; + /* the property below should not appear in final css string + width: 400px; + height: 200px; + */ + flex: 1; + flex-direction: row; +} +/* Set the background color to blue for screens that are 300px or less */ +@media screen and (max-width: 300px) { + body { + background-color: blue; + } +}`; + +const cssCodeWithCommentsRemoved = ` +a { + color: green; + display: flex; +} +.aClass { + font-size: 32px; + + flex: 1; + flex-direction: row; +} + +@media screen and (max-width: 300px) { + body { + background-color: blue; + } +}`; + +const testValues = { + cssFullExample, + cssCodeWithCommentsRemoved +}; + +export default testValues; diff --git a/client/src/utils/__fixtures/curriculum-helpers-html.js b/client/src/utils/__fixtures/curriculum-helpers-html.js new file mode 100644 index 0000000000..0e8580fc8a --- /dev/null +++ b/client/src/utils/__fixtures/curriculum-helpers-html.js @@ -0,0 +1,30 @@ +const htmlFullExample = ` + + +not a comment + +not a commment not a comment +not a comment + +not a comment +`; + +const htmlCodeWithCommentsRemoved = ` + + +not a comment + +not a commment not a comment +not a comment + +not a comment +`; + +const testValues = { + htmlFullExample, + htmlCodeWithCommentsRemoved +}; + +export default testValues; diff --git a/client/src/utils/__fixtures/curriculum-helpers-javascript.js b/client/src/utils/__fixtures/curriculum-helpers-javascript.js new file mode 100644 index 0000000000..399f5d8461 --- /dev/null +++ b/client/src/utils/__fixtures/curriculum-helpers-javascript.js @@ -0,0 +1,44 @@ +const jsCodeWithSingleAndMultLineComments = ` +function nonMutatingPush(original, newItem) { + /* This is a + multi-line comment + that should be removed. */ + return original.push(newItem); +} +var first = [1, 2, 3]; +// This is a single line comment +var second = [4, 5]; +nonMutatingPush(first, second);`; + +const jsCodeWithSingleAndMultLineCommentsRemoved = ` +function nonMutatingPush(original, newItem) { + + + + return original.push(newItem); +} +var first = [1, 2, 3]; + +var second = [4, 5]; +nonMutatingPush(first, second);`; + +const jsCodeWithUrl = ` +function nonMutatingPush(original, newItem) { + var url = 'https://freecodecamp.org'; // this comment should vanish + return original.push(newItem); +}`; + +const jsCodeWithUrlUnchanged = ` +function nonMutatingPush(original, newItem) { + var url = 'https://freecodecamp.org'; + return original.push(newItem); +}`; + +const testValues = { + jsCodeWithSingleAndMultLineComments, + jsCodeWithSingleAndMultLineCommentsRemoved, + jsCodeWithUrl, + jsCodeWithUrlUnchanged +}; + +export default testValues; diff --git a/client/src/utils/__fixtures/curriculum-helpers-remove-white-space.js b/client/src/utils/__fixtures/curriculum-helpers-remove-white-space.js new file mode 100644 index 0000000000..841279da24 --- /dev/null +++ b/client/src/utils/__fixtures/curriculum-helpers-remove-white-space.js @@ -0,0 +1,16 @@ +const stringWithWhiteSpaceChars = ` +This string sentence has various white spaces characters: +\t* This line starts with a tab character. +\t* This line has several preceding white space characters.`; + +/* eslint-disable max-len */ +const stringWithWhiteSpaceCharsRemoved = + 'Thisstringsentencehasvariouswhitespacescharacters:*Thislinestartswithatabcharacter.*Thislinehasseveralprecedingwhitespacecharacters.'; +/* esline-enable max-len */ + +const testValues = { + stringWithWhiteSpaceChars, + stringWithWhiteSpaceCharsRemoved +}; + +export default testValues; diff --git a/client/src/utils/curriculum-helpers.js b/client/src/utils/curriculum-helpers.js new file mode 100644 index 0000000000..fc9699dd0a --- /dev/null +++ b/client/src/utils/curriculum-helpers.js @@ -0,0 +1,35 @@ +import { parse } from '@babel/parser'; +import generate from '@babel/generator'; + +const removeHtmlComments = str => str.replace(//g, ''); + +const removeCssComments = str => str.replace(/\/\*[\s\S]+?\*\//g, ''); + +const removeJSComments = codeStr => { + // Note: removes trailing new lines and tailing spaces at end of lines + const options = { + comments: false, + retainLines: true, + compact: false, + concise: false, + minified: false + }; + try { + const ast = parse(codeStr); + const { code } = generate(ast, options, codeStr); + return code; + } catch (err) { + return codeStr; + } +}; + +const removeWhiteSpace = (str = '') => { + return str.replace(/\s/g, ''); +}; + +export default { + removeHtmlComments, + removeCssComments, + removeJSComments, + removeWhiteSpace +}; diff --git a/client/src/utils/curriculum-helpers.test.js b/client/src/utils/curriculum-helpers.test.js new file mode 100644 index 0000000000..b8c5388f2c --- /dev/null +++ b/client/src/utils/curriculum-helpers.test.js @@ -0,0 +1,87 @@ +/* global describe it expect */ + +import __testHelpers from './curriculum-helpers'; +import jsTestValues from './__fixtures/curriculum-helpers-javascript'; +import cssTestValues from './__fixtures/curriculum-helpers-css'; +import htmlTestValues from './__fixtures/curriculum-helpers-html'; +/* eslint-disable max-len */ +import whiteSpaceTestValues from './__fixtures/curriculum-helpers-remove-white-space'; +/* eslint-enable max-len */ + +const { + stringWithWhiteSpaceChars, + stringWithWhiteSpaceCharsRemoved +} = whiteSpaceTestValues; + +const { cssFullExample, cssCodeWithCommentsRemoved } = cssTestValues; + +const { htmlFullExample, htmlCodeWithCommentsRemoved } = htmlTestValues; + +const { + jsCodeWithSingleAndMultLineComments, + jsCodeWithSingleAndMultLineCommentsRemoved, + jsCodeWithUrl, + jsCodeWithUrlUnchanged +} = jsTestValues; + +describe('removeWhiteSpace', () => { + const { removeWhiteSpace } = __testHelpers; + it('returns a string', () => { + expect(typeof removeWhiteSpace('This should return a string')).toBe( + 'string' + ); + }); + + it('returns a string with no white space characters', () => { + expect(removeWhiteSpace(stringWithWhiteSpaceChars)).toBe( + stringWithWhiteSpaceCharsRemoved + ); + }); +}); + +describe('removeJSComments', () => { + const { removeJSComments } = __testHelpers; + it('returns a string', () => { + expect(typeof removeJSComments('const should = "return a string"')).toBe( + 'string' + ); + }); + + it('returns a string with no single or multi-line comments', () => { + expect(removeJSComments(jsCodeWithSingleAndMultLineComments)).toBe( + jsCodeWithSingleAndMultLineCommentsRemoved + ); + }); + + it('does not remove a url found in JS code', () => { + expect(removeJSComments(jsCodeWithUrl)).toBe(jsCodeWithUrlUnchanged); + }); +}); + +describe('removeCssComments', () => { + const { removeCssComments } = __testHelpers; + it('returns a string', () => { + expect(typeof removeCssComments('.aClass: { color: red; }')).toBe('string'); + }); + + it('returns a CSS string with no single or multi-line comments', () => { + expect(removeCssComments(cssFullExample)).toBe(cssCodeWithCommentsRemoved); + }); +}); + +describe('removeHtmlComments', () => { + const { removeHtmlComments } = __testHelpers; + it('returns a string', () => { + expect( + typeof removeHtmlComments( + '

hello world

h2 element

' + ) + ).toBe('string'); + }); + + it('returns an HTML string with no single or multi-line comments', () => { + expect(removeHtmlComments(htmlFullExample)).toBe( + htmlCodeWithCommentsRemoved + ); + }); +}); diff --git a/curriculum/challenges/english/01-responsive-web-design/applied-visual-design/change-animation-timing-with-keywords.english.md b/curriculum/challenges/english/01-responsive-web-design/applied-visual-design/change-animation-timing-with-keywords.english.md index 2f1ea2b9f5..c3519fff5c 100644 --- a/curriculum/challenges/english/01-responsive-web-design/applied-visual-design/change-animation-timing-with-keywords.english.md +++ b/curriculum/challenges/english/01-responsive-web-design/applied-visual-design/change-animation-timing-with-keywords.english.md @@ -23,9 +23,9 @@ For the elements with id of ball1 and ball2, add an animation-timing-function property for the element with the id ball1 should be linear. - testString: const ball1Animation = $('#ball1').css('animation-timing-function').replace(/\s/g, '');assert(ball1Animation == 'linear' || ball1Animation == 'cubic-bezier(0,0,1,1)'); + testString: const ball1Animation = __helpers.removeWhiteSpace($('#ball1').css('animation-timing-function'));assert(ball1Animation == 'linear' || ball1Animation == 'cubic-bezier(0,0,1,1)'); - text: The value of the animation-timing-function property for the element with the id ball2 should be ease-out. - testString: const ball2Animation = $('#ball2').css('animation-timing-function').replace(/\s/g, ''); assert(ball2Animation == 'ease-out' || ball2Animation == 'cubic-bezier(0,0,0.58,1)'); + testString: const ball2Animation = __helpers.removeWhiteSpace($('#ball2').css('animation-timing-function')); assert(ball2Animation == 'ease-out' || ball2Animation == 'cubic-bezier(0,0,0.58,1)'); ``` diff --git a/curriculum/challenges/english/01-responsive-web-design/applied-visual-design/learn-how-bezier-curves-work.english.md b/curriculum/challenges/english/01-responsive-web-design/applied-visual-design/learn-how-bezier-curves-work.english.md index 15e8da813f..102eb9cd9a 100644 --- a/curriculum/challenges/english/01-responsive-web-design/applied-visual-design/learn-how-bezier-curves-work.english.md +++ b/curriculum/challenges/english/01-responsive-web-design/applied-visual-design/learn-how-bezier-curves-work.english.md @@ -28,7 +28,7 @@ tests: - text: The value of the animation-timing-function property for the element with the id ball1 should be the linear-equivalent cubic-bezier function. testString: assert($('#ball1').css('animation-timing-function') == 'cubic-bezier(0.25, 0.25, 0.75, 0.75)'); - text: The value of the animation-timing-function property for the element with the id ball2 should not change. - testString: const ball2Animation = $('#ball2').css('animation-timing-function').replace(/\s/g, ''); assert(ball2Animation == 'ease-out' || ball2Animation == 'cubic-bezier(0,0,0.58,1)'); + testString: const ball2Animation = __helpers.removeWhiteSpace($('#ball2').css('animation-timing-function')); assert(ball2Animation == 'ease-out' || ball2Animation == 'cubic-bezier(0,0,0.58,1)'); ``` diff --git a/curriculum/challenges/english/01-responsive-web-design/applied-visual-design/use-a-bezier-curve-to-move-a-graphic.english.md b/curriculum/challenges/english/01-responsive-web-design/applied-visual-design/use-a-bezier-curve-to-move-a-graphic.english.md index 9f4460f38f..ff0d021daf 100644 --- a/curriculum/challenges/english/01-responsive-web-design/applied-visual-design/use-a-bezier-curve-to-move-a-graphic.english.md +++ b/curriculum/challenges/english/01-responsive-web-design/applied-visual-design/use-a-bezier-curve-to-move-a-graphic.english.md @@ -29,7 +29,7 @@ tests: - text: The element with the id red should no longer have the animation-timing-function property of linear. testString: assert($('#red').css('animation-timing-function') !== 'linear'); - text: The value of the animation-timing-function property for the element with the id blue should not change. - testString: const blueBallAnimation = $('#blue').css('animation-timing-function').replace(/\s/g, ''); assert(blueBallAnimation == 'ease-out' || blueBallAnimation == 'cubic-bezier(0,0,0.58,1)'); + testString: const blueBallAnimation = __helpers.removeWhiteSpace($('#blue').css('animation-timing-function')); assert(blueBallAnimation == 'ease-out' || blueBallAnimation == 'cubic-bezier(0,0,0.58,1)'); ``` diff --git a/curriculum/challenges/english/01-responsive-web-design/basic-css/use-clockwise-notation-to-specify-the-margin-of-an-element.english.md b/curriculum/challenges/english/01-responsive-web-design/basic-css/use-clockwise-notation-to-specify-the-margin-of-an-element.english.md index 565ec4e833..3ffe096944 100644 --- a/curriculum/challenges/english/01-responsive-web-design/basic-css/use-clockwise-notation-to-specify-the-margin-of-an-element.english.md +++ b/curriculum/challenges/english/01-responsive-web-design/basic-css/use-clockwise-notation-to-specify-the-margin-of-an-element.english.md @@ -33,7 +33,7 @@ tests: - text: Your blue-box class should give the left of elements 40px of margin. testString: assert($(".blue-box").css("margin-left") === "40px"); - text: You should use the clockwise notation to set the margin of blue-box class. - testString: const removeCssComments = str => str.replace(/\/\*[\s\S]+?\*\//g, '');assert(/\.blue-box\s*{[\s\S]*margin[\s]*:\s*\d+px\s+\d+px\s+\d+px\s+\d+px(;\s*[^}]+\s*}|;?\s*})/.test(removeCssComments($('style').text()))); + testString: assert(/\.blue-box\s*{[\s\S]*margin[\s]*:\s*\d+px\s+\d+px\s+\d+px\s+\d+px(;\s*[^}]+\s*}|;?\s*})/.test(__helpers.removeCssComments($('style').text()))); ``` diff --git a/curriculum/challenges/english/01-responsive-web-design/basic-css/use-clockwise-notation-to-specify-the-padding-of-an-element.english.md b/curriculum/challenges/english/01-responsive-web-design/basic-css/use-clockwise-notation-to-specify-the-padding-of-an-element.english.md index 4a653fbc19..80ad2f5acf 100644 --- a/curriculum/challenges/english/01-responsive-web-design/basic-css/use-clockwise-notation-to-specify-the-padding-of-an-element.english.md +++ b/curriculum/challenges/english/01-responsive-web-design/basic-css/use-clockwise-notation-to-specify-the-padding-of-an-element.english.md @@ -32,7 +32,7 @@ tests: - text: Your blue-box class should give the left of elements 40px of padding. testString: assert($(".blue-box").css("padding-left") === "40px"); - text: You should use the clockwise notation to set the padding of blue-box class. - testString: const removeCssComments = str => str.replace(/\/\*[\s\S]+?\*\//g, '');assert(/\.blue-box\s*{[\s\S]*padding[\s]*:\s*\d+px\s+\d+px\s+\d+px\s+\d+px(;\s*[^}]+\s*}|;?\s*})/.test(removeCssComments($('style').text()))); + testString: assert(/\.blue-box\s*{[\s\S]*padding[\s]*:\s*\d+px\s+\d+px\s+\d+px\s+\d+px(;\s*[^}]+\s*}|;?\s*})/.test(__helpers.removeCssComments($('style').text()))); ``` diff --git a/curriculum/challenges/english/01-responsive-web-design/basic-html-and-html5/add-images-to-your-website.english.md b/curriculum/challenges/english/01-responsive-web-design/basic-html-and-html5/add-images-to-your-website.english.md index 4f82075ac9..b0c03dcd3c 100644 --- a/curriculum/challenges/english/01-responsive-web-design/basic-html-and-html5/add-images-to-your-website.english.md +++ b/curriculum/challenges/english/01-responsive-web-design/basic-html-and-html5/add-images-to-your-website.english.md @@ -38,7 +38,7 @@ tests: - text: Your image should have a src attribute that points to the kitten image. testString: assert(/^https:\/\/bit\.ly\/fcc-relaxing-cat$/i.test($("img").attr("src"))); - text: Your image element's alt attribute should not be empty. - testString: assert($("img").attr("alt") && $("img").attr("alt").length && /)\S+\1\S*\/?>/.test(code.replace(/\s/g,''))); + testString: assert($("img").attr("alt") && $("img").attr("alt").length && /)\S+\1\S*\/?>/.test(__helpers.removeWhiteSpace(code))); ``` diff --git a/curriculum/challenges/english/01-responsive-web-design/basic-html-and-html5/create-an-ordered-list.english.md b/curriculum/challenges/english/01-responsive-web-design/basic-html-and-html5/create-an-ordered-list.english.md index 73ca989225..12c7bcaf6b 100644 --- a/curriculum/challenges/english/01-responsive-web-design/basic-html-and-html5/create-an-ordered-list.english.md +++ b/curriculum/challenges/english/01-responsive-web-design/basic-html-and-html5/create-an-ordered-list.english.md @@ -52,9 +52,9 @@ tests: - text: Your li element should have a closing tag. testString: assert(code.match(/<\/li>/g) && code.match(/
  • /g) && code.match(/<\/li>/g).length === code.match(/
  • /g).length); - text: The li elements in your unordered list should not be empty. - testString: $('ul li').each((i, val) => assert(val.textContent.replace(/\s/g, ''))); + testString: $('ul li').each((i, val) => assert(__helpers.removeWhiteSpace(val.textContent))); - text: The li elements in your ordered list should not be empty. - testString: $('ol li').each((i, val) => assert(!!val.textContent.replace(/\s/g, ''))); + testString: $('ol li').each((i, val) => assert(!!__helpers.removeWhiteSpace(val.textContent))); ``` diff --git a/curriculum/challenges/english/01-responsive-web-design/css-grid/divide-the-grid-into-an-area-template.english.md b/curriculum/challenges/english/01-responsive-web-design/css-grid/divide-the-grid-into-an-area-template.english.md index 1a91452b87..f8a7127713 100644 --- a/curriculum/challenges/english/01-responsive-web-design/css-grid/divide-the-grid-into-an-area-template.english.md +++ b/curriculum/challenges/english/01-responsive-web-design/css-grid/divide-the-grid-into-an-area-template.english.md @@ -33,7 +33,7 @@ Place the area template so that the cell labeled advert becomes an ```yml tests: - text: container class should have a grid-template-areas property similar to the preview but has . instead of the advert area. - testString: const removeCssComments = str => str.replace(/\/\*[\s\S]+?\*\//g, ''); assert(removeCssComments(code).match(/.container\s*?{[\s\S]*grid-template-areas\s*?:\s*?"\s*?header\s*?header\s*?header\s*?"\s*?"\s*?.\s*?content\s*?content\s*?"\s*?"\s*?footer\s*?footer\s*?footer\s*?"\s*?;[\s\S]*}/gi)); + testString: assert(__helpers.removeCssComments(code).match(/.container\s*?{[\s\S]*grid-template-areas\s*?:\s*?"\s*?header\s*?header\s*?header\s*?"\s*?"\s*?.\s*?content\s*?content\s*?"\s*?"\s*?footer\s*?footer\s*?footer\s*?"\s*?;[\s\S]*}/gi)); ``` diff --git a/curriculum/challenges/english/01-responsive-web-design/css-grid/place-items-in-grid-areas-using-the-grid-area-property.english.md b/curriculum/challenges/english/01-responsive-web-design/css-grid/place-items-in-grid-areas-using-the-grid-area-property.english.md index d1b2b63334..60be806fca 100644 --- a/curriculum/challenges/english/01-responsive-web-design/css-grid/place-items-in-grid-areas-using-the-grid-area-property.english.md +++ b/curriculum/challenges/english/01-responsive-web-design/css-grid/place-items-in-grid-areas-using-the-grid-area-property.english.md @@ -30,7 +30,7 @@ Place an element with the item5 class in the footer ar ```yml tests: - text: item5 class should have a grid-area property that has the value of footer. - testString: const removeCssComments = str => str.replace(/\/\*[\s\S]+?\*\//g, '');assert(removeCssComments(code).match(/.item5\s*?{[\s\S]*grid-area\s*?:\s*?footer\s*?;[\s\S]*}/gi)); + testString: assert(__helpers.removeCssComments(code).match(/.item5\s*?{[\s\S]*grid-area\s*?:\s*?footer\s*?;[\s\S]*}/gi)); ``` diff --git a/curriculum/challenges/english/01-responsive-web-design/css-grid/use-grid-column-to-control-spacing.english.md b/curriculum/challenges/english/01-responsive-web-design/css-grid/use-grid-column-to-control-spacing.english.md index 203a4852be..865ec3d707 100644 --- a/curriculum/challenges/english/01-responsive-web-design/css-grid/use-grid-column-to-control-spacing.english.md +++ b/curriculum/challenges/english/01-responsive-web-design/css-grid/use-grid-column-to-control-spacing.english.md @@ -33,7 +33,7 @@ Make the item with the class item5 consume the last two columns of ```yml tests: - text: item5 class should have a grid-column property. - testString: assert($('style').text().replace(/\s/g, '').match(/\.item5{.*grid-column:.*}/g)); + testString: assert(__helpers.removeWhiteSpace($('style').text()).match(/\.item5{.*grid-column:.*}/g)); - text: item5 class should have a grid-column property which results in it consuming the last two columns of the grid. testString: " const colStart = getComputedStyle($('.item5')[0]).gridColumnStart; diff --git a/curriculum/challenges/english/01-responsive-web-design/css-grid/use-grid-row-to-control-spacing.english.md b/curriculum/challenges/english/01-responsive-web-design/css-grid/use-grid-row-to-control-spacing.english.md index d497eed571..b32308830e 100644 --- a/curriculum/challenges/english/01-responsive-web-design/css-grid/use-grid-row-to-control-spacing.english.md +++ b/curriculum/challenges/english/01-responsive-web-design/css-grid/use-grid-row-to-control-spacing.english.md @@ -22,7 +22,7 @@ Make the element with the item5 class consume the last two rows. ```yml tests: - text: item5 class should have a grid-row property. - testString: assert($('style').text().replace(/\s/g, '').match(/\.item5{.*grid-row:.*}/g)); + testString: assert(__helpers.removeWhiteSpace($('style').text()).match(/\.item5{.*grid-row:.*}/g)); - text: item5 class should have a grid-row property which results in it consuming the last two rows of the grid. testString: " const rowStart = getComputedStyle($('.item5')[0]).gridRowStart; diff --git a/curriculum/challenges/english/01-responsive-web-design/css-grid/use-media-queries-to-create-responsive-layouts.english.md b/curriculum/challenges/english/01-responsive-web-design/css-grid/use-media-queries-to-create-responsive-layouts.english.md index 5fdc5102cb..1f682b7179 100644 --- a/curriculum/challenges/english/01-responsive-web-design/css-grid/use-media-queries-to-create-responsive-layouts.english.md +++ b/curriculum/challenges/english/01-responsive-web-design/css-grid/use-media-queries-to-create-responsive-layouts.english.md @@ -23,7 +23,7 @@ When the viewport width is 400px or more, make the header area occu ```yml tests: - text: When the viewport is 400px or more, container class should have a grid-template-areas property in which the header and footer areas occupy the top and bottom rows respectively and advert and content occupy the left and right columns of the middle row. - testString: const removeCssComments = str => str.replace(/\/\*[\s\S]+?\*\//g, ''); assert(removeCssComments(code).match(/@media\s*?\(\s*?min-width\s*?:\s*?400px\s*?\)[\s\S]*.container\s*?{[\s\S]*grid-template-areas\s*?:\s*?"\s*?header\s*?header\s*?"\s*?"\s*?advert\s*?content\s*?"\s*?"\s*?footer\s*?footer\s*?"\s*?;[\s\S]*}/gi)); + testString: assert(__helpers.removeCssComments(code).match(/@media\s*?\(\s*?min-width\s*?:\s*?400px\s*?\)[\s\S]*.container\s*?{[\s\S]*grid-template-areas\s*?:\s*?"\s*?header\s*?header\s*?"\s*?"\s*?advert\s*?content\s*?"\s*?"\s*?footer\s*?footer\s*?"\s*?;[\s\S]*}/gi)); ``` diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-data-structures/copy-an-array-with-the-spread-operator.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-data-structures/copy-an-array-with-the-spread-operator.english.md index c4351d1318..ff6bb4149e 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-data-structures/copy-an-array-with-the-spread-operator.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-data-structures/copy-an-array-with-the-spread-operator.english.md @@ -38,7 +38,7 @@ tests: - text: copyMachine(["it works"], 3) should return [["it works"], ["it works"], ["it works"]] testString: assert.deepEqual(copyMachine(['it works'], 3), [['it works'], ['it works'], ['it works']]); - text: The copyMachine function should utilize the spread operator with array arr - testString: assert(removeJSComments(code).match(/\.\.\.arr/)); + testString: assert(__helpers.removeJSComments(code).match(/\.\.\.arr/)); ``` @@ -66,15 +66,6 @@ console.log(copyMachine([true, false, true], 2)); -### After Test -
    - -```js -const removeJSComments = str => str.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, ''); -``` - -
    - ## Solution diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-data-structures/remove-items-using-splice.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-data-structures/remove-items-using-splice.english.md index 5b52d00928..7339397b71 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-data-structures/remove-items-using-splice.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-data-structures/remove-items-using-splice.english.md @@ -42,13 +42,13 @@ We've initialized an array `arr`. Use `splice()` to remove elements from `arr`, ```yml tests: - text: You should not change the original line of const arr = [2, 4, 5, 1, 7, 5, 2, 1];. - testString: assert(code.replace(/\s/g, '').match(/constarr=\[2,4,5,1,7,5,2,1\];?/)); + testString: assert(__helpers.removeWhiteSpace(code).match(/constarr=\[2,4,5,1,7,5,2,1\];?/)); - text: arr should only contain elements that sum to 10. testString: assert.strictEqual(arr.reduce((a, b) => a + b), 10); - text: Your code should utilize the splice() method on arr. - testString: assert(code.replace(/\s/g, '').match(/arr\.splice\(/)); + testString: assert(__helpers.removeWhiteSpace(code).match(/arr\.splice\(/)); - text: The splice should only remove elements from arr and not add any additional elements to arr. - testString: assert(!code.replace(/\s/g, '').match(/arr\.splice\(\d+,\d+,\d+.*\)/g)); + testString: assert(!__helpers.removeWhiteSpace(code).match(/arr\.splice\(\d+,\d+,\d+.*\)/g)); ``` diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/access-multi-dimensional-arrays-with-indexes.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/access-multi-dimensional-arrays-with-indexes.english.md index be1b328d76..cbd2f8d3b9 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/access-multi-dimensional-arrays-with-indexes.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/access-multi-dimensional-arrays-with-indexes.english.md @@ -39,7 +39,7 @@ tests: - text: myData should be equal to 8. testString: assert(myData === 8); - text: You should be using bracket notation to read the correct value from myArray. - testString: assert(/myData=myArray\[2\]\[1\]/.test(code.replace(/\s/g, ''))); + testString: assert(/myData=myArray\[2\]\[1\]/.test(__helpers.removeWhiteSpace(code))); ``` diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/iterate-through-an-array-with-a-for-loop.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/iterate-through-an-array-with-a-for-loop.english.md index 179f5f6add..acd6d4e5b0 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/iterate-through-an-array-with-a-for-loop.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/iterate-through-an-array-with-a-for-loop.english.md @@ -37,7 +37,7 @@ tests: - text: You should use a for loop to iterate through myArr. testString: assert(/for\s*\(/g.test(code) && /myArr\s*\[/g.test(code)); - text: You should not attempt to directly assign the value 20 to total. - testString: assert(!code.replace(/\s/g, '').match(/total[=+-]0*[1-9]+/gm)); + testString: assert(!__helpers.removeWhiteSpace(code).match(/total[=+-]0*[1-9]+/gm)); ``` diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/local-scope-and-functions.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/local-scope-and-functions.english.md index 0f223c304e..9c858a5c4b 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/local-scope-and-functions.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/local-scope-and-functions.english.md @@ -43,7 +43,7 @@ tests: } assert.throws(declared, ReferenceError); - text: You should add a local myVar variable. - testString: assert(/functionmyLocalScope\(\)\{.+(var|let|const)myVar[\s\S]*}/.test(code.replace(/\s/g, ''))); + testString: assert(/functionmyLocalScope\(\)\{.+(var|let|const)myVar[\s\S]*}/.test(__helpers.removeWhiteSpace(code))); ``` diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/replace-loops-using-recursion.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/replace-loops-using-recursion.english.md index 0cf58778f4..ac1953f4a1 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/replace-loops-using-recursion.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/replace-loops-using-recursion.english.md @@ -57,9 +57,9 @@ tests: - text: sum([2, 3, 4, 5], 3) should equal 9. testString: assert.equal(sum([2, 3, 4, 5], 3), 9); - text: Your code should not rely on any kind of loops (for or while or higher order functions such as forEach, map, filter, or reduce.). - testString: assert(!removeJSComments(code).match(/for|while|forEach|map|filter|reduce/g)); + testString: assert(!__helpers.removeJSComments(code).match(/for|while|forEach|map|filter|reduce/g)); - text: You should use recursion to solve this problem. - testString: assert(removeJSComments(sum.toString()).match(/sum\(.*\)/g).length > 1); + testString: assert(__helpers.removeJSComments(sum.toString()).match(/sum\(.*\)/g).length > 1); ``` @@ -80,16 +80,6 @@ function sum(arr, n) { -### After Test -
    - -```js -const removeJSComments = str => str.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, ''); - -``` - -
    - ## Solution diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/subtract-one-number-from-another-with-javascript.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/subtract-one-number-from-another-with-javascript.english.md index 1eef292503..ee430d8bc5 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/subtract-one-number-from-another-with-javascript.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/subtract-one-number-from-another-with-javascript.english.md @@ -33,7 +33,7 @@ tests: - text: The variable difference should be equal to 12. testString: assert(difference === 12); - text: You should only subtract one number from 45. - testString: assert(/difference=45-33;?/.test(code.replace(/\s/g, ''))); + testString: assert(/difference=45-33;?/.test(__helpers.removeWhiteSpace(code))); ``` diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-undefined-value-returned-from-a-function.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-undefined-value-returned-from-a-function.english.md index da06cb5d05..430712ec91 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-undefined-value-returned-from-a-function.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-undefined-value-returned-from-a-function.english.md @@ -39,7 +39,7 @@ tests: - text: Returned value from addFive should be undefined. testString: assert(addFive() === undefined); - text: Inside the addFive function, you should add 5 to the sum variable. - testString: assert(addFive.toString().replace(/\s/g, '').match(/sum=sum\+5|sum\+=5/)); + testString: assert(__helpers.removeWhiteSpace(addFive.toString()).match(/sum=sum\+5|sum\+=5/)); ``` diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-countdown.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-countdown.english.md index 067beecc4f..f043708d27 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-countdown.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-countdown.english.md @@ -52,9 +52,9 @@ tests: - text: countdown(5) should return [5, 4, 3, 2, 1] testString: assert.deepStrictEqual(countdown(5), [5, 4, 3, 2, 1]); - text: Your code should not rely on any kind of loops (for, while or higher order functions such as forEach, map, filter, and reduce). - testString: assert(!removeJSComments(code).match(/for|while|forEach|map|filter|reduce/g)); + testString: assert(!__helpers.removeJSComments(code).match(/for|while|forEach|map|filter|reduce/g)); - text: You should use recursion to solve this problem. - testString: assert(removeJSComments(countdown.toString()).match(/countdown\s*\(.+\)/)); + testString: assert(__helpers.removeJSComments(countdown.toString()).match(/countdown\s*\(.+\)/)); ``` @@ -76,15 +76,6 @@ function countdown(n){ -### After Test -
    - -```js -const removeJSComments = str => str.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, ''); -``` - -
    - ## Solution diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-range-of-numbers.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-range-of-numbers.english.md index 17f3c56e0e..74f6b7fc9c 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-range-of-numbers.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-range-of-numbers.english.md @@ -25,9 +25,9 @@ tests: - text: Your function should return an array. testString: assert(Array.isArray(rangeOfNumbers(5, 10))); - text: Your code should not use any loop syntax (for or while or higher order functions such as forEach, map, filter, or reduce). - testString: assert(!removeJSComments(code).match(/for|while|forEach|map|filter|reduce/g)); + testString: assert(!__helpers.removeJSComments(code).match(/for|while|forEach|map|filter|reduce/g)); - text: rangeOfNumbers should use recursion (call itself) to solve this challenge. - testString: assert(removeJSComments(rangeOfNumbers.toString()).match(/rangeOfNumbers\s*\(.+\)/)); + testString: assert(__helpers.removeJSComments(rangeOfNumbers.toString()).match(/rangeOfNumbers\s*\(.+\)/)); - text: rangeOfNumbers(1, 5) should return [1, 2, 3, 4, 5]. testString: assert.deepStrictEqual(rangeOfNumbers(1, 5), [1, 2, 3, 4, 5]); - text: rangeOfNumbers(6, 9) should return [6, 7, 8, 9]. @@ -51,15 +51,6 @@ function rangeOfNumbers(startNum, endNum) { -### After Test -
    - -```js -const removeJSComments = str => str.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, ''); -``` - -
    - ## Solution diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/debugging/understanding-the-differences-between-the-freecodecamp-and-browser-console.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/debugging/understanding-the-differences-between-the-freecodecamp-and-browser-console.english.md index e300aa870a..6e9dc56b6d 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/debugging/understanding-the-differences-between-the-freecodecamp-and-browser-console.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/debugging/understanding-the-differences-between-the-freecodecamp-and-browser-console.english.md @@ -28,9 +28,9 @@ First, use console.log to log the output variable. The ```yml tests: - text: You should use console.clear() to clear the browser console. - testString: const removeJSComments = code.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, ''); const noSpaces = removeJSComments.replace(/\s/g, ''); assert(noSpaces.match(/console.clear\(\)/)); + testString: assert(__helpers.removeWhiteSpace(__helpers.removeJSComments(code)).match(/console.clear\(\)/)); - text: You should use console.log() to print the output variable. - testString: const noSpaces = code.replace(/\s/g, ''); assert(noSpaces.match(/console\.log\(output\)/)); + testString: assert(__helpers.removeWhiteSpace(code).match(/console\.log\(output\)/)); ``` @@ -53,8 +53,6 @@ let output = "Get this to log once in the freeCodeCamp console and twice in the - - ## Solution diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/complete-a-promise-with-resolve-and-reject.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/complete-a-promise-with-resolve-and-reject.english.md index 718d69f00f..b67a808b1e 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/complete-a-promise-with-resolve-and-reject.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/complete-a-promise-with-resolve-and-reject.english.md @@ -33,9 +33,10 @@ Make the promise handle success and failure. If responseFromServer ```yml tests: - text: resolve should be called with the expected string when the if condition is true. - testString: assert(removeJSComments(code).match(/if\s*\(\s*responseFromServer\s*\)\s*{\s*resolve\s*\(\s*('|"|`)We got the data\1\s*\)(\s*|\s*;\s*)}/g)); + testString: assert(__helpers.removeJSComments(code).match(/if\s*\(\s*responseFromServer\s*\)\s*{\s*resolve\s*\(\s*('|"|`)We got the data\1\s*\)(\s*|\s*;\s*)}/g)); - text: reject should be called with the expected string when the if condition is false. - testString: assert(removeJSComments(code).match(/}\s*else\s*{\s*reject\s*\(\s*('|"|`)Data not received\1\s*\)(\s*|\s*;\s*)}/g)); + testString: assert(__helpers.removeJSComments(code).match(/}\s*else\s*{\s*reject\s*\(\s*('|"|`)Data not received\1\s*\)(\s*|\s*;\s*)}/g)); + ``` @@ -59,14 +60,6 @@ const makeServerRequest = new Promise((resolve, reject) => { -### After Test -
    - -```js -const removeJSComments = str => str.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, ''); -``` - -
    ## Solution diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/handle-a-fulfilled-promise-with-then.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/handle-a-fulfilled-promise-with-then.english.md index eaa1e75631..3f2cb45d01 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/handle-a-fulfilled-promise-with-then.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/handle-a-fulfilled-promise-with-then.english.md @@ -29,11 +29,11 @@ Add the then method to your promise. Use result as the ```yml tests: - text: You should call the then method on the promise. - testString: assert(codeWithoutSpaces.match(/(makeServerRequest|\))\.then\(/g)); + testString: assert(__helpers.removeWhiteSpace(code).match(/(makeServerRequest|\))\.then\(/g)); - text: Your then method should have a callback function with result as its parameter. testString: assert(resultIsParameter); - text: You should log result to the console. - testString: assert(resultIsParameter && codeWithoutSpaces.match(/\.then\(.*?result.*?console.log\(result\).*?\)/)); + testString: assert(resultIsParameter && __helpers.removeWhiteSpace(code).match(/\.then\(.*?result.*?console.log\(result\).*?\)/)); ``` @@ -61,8 +61,7 @@ const makeServerRequest = new Promise((resolve, reject) => {
    ```js -const codeWithoutSpaces = code.replace(/\s/g, ''); -const resultIsParameter = /\.then\((function\(result\){|result|\(result\)=>)/.test(codeWithoutSpaces); +const resultIsParameter = /\.then\((function\(result\){|result|\(result\)=>)/.test(__helpers.removeWhiteSpace(code)); ```
    diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/handle-a-rejected-promise-with-catch.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/handle-a-rejected-promise-with-catch.english.md index 36dbb68202..78fbcc61be 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/handle-a-rejected-promise-with-catch.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/handle-a-rejected-promise-with-catch.english.md @@ -31,11 +31,11 @@ Add the catch method to your promise. Use error as the ```yml tests: - text: You should call the catch method on the promise. - testString: assert(codeWithoutSpaces.match(/(makeServerRequest|\))\.catch\(/g)); + testString: assert(__helpers.removeWhiteSpace(code).match(/(makeServerRequest|\))\.catch\(/g)); - text: Your catch method should have a callback function with error as its parameter. testString: assert(errorIsParameter); - text: You should log error to the console. - testString: assert(errorIsParameter && codeWithoutSpaces.match(/\.catch\(.*?error.*?console.log\(error\).*?\)/)); + testString: assert(errorIsParameter && __helpers.removeWhiteSpace(code).match(/\.catch\(.*?error.*?console.log\(error\).*?\)/)); ``` @@ -67,8 +67,7 @@ makeServerRequest.then(result => {
    ```js -const codeWithoutSpaces = code.replace(/\s/g, ''); -const errorIsParameter = /\.catch\((function\(error\){|error|\(error\)=>)/.test(codeWithoutSpaces); +const errorIsParameter = /\.catch\((function\(error\){|error|\(error\)=>)/.test(__helpers.removeWhiteSpace(code)); ```
    diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-extract-values-from-objects.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-extract-values-from-objects.english.md index 3307bdce0e..33a74c160f 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-extract-values-from-objects.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-extract-values-from-objects.english.md @@ -41,11 +41,11 @@ Replace the two assignments with an equivalent destructuring assignment. It shou ```yml tests: - text: You should remove the ES5 assignment syntax. - testString: assert(!removeJSComments(code).match(/today\s*=\s*HIGH_TEMPERATURES\.(today|tomorrow)/g)) + testString: assert(!__helpers.removeJSComments(code).match(/today\s*=\s*HIGH_TEMPERATURES\.(today|tomorrow)/g)) - text: You should use destructuring to create the today variable. - testString: assert(removeJSComments(code).match(/(var|let|const)\s*{\s*(today[^}]*|[^,]*,\s*today)\s*}\s*=\s*HIGH_TEMPERATURES(;|\s+|\/\/)/g)); + testString: assert(__helpers.removeJSComments(code).match(/(var|let|const)\s*{\s*(today[^}]*|[^,]*,\s*today)\s*}\s*=\s*HIGH_TEMPERATURES(;|\s+|\/\/)/g)); - text: You should use destructuring to create the tomorrow variable. - testString: assert(removeJSComments(code).match(/(var|let|const)\s*{\s*(tomorrow[^}]*|[^,]*,\s*tomorrow)\s*}\s*=\s*HIGH_TEMPERATURES(;|\s+|\/\/)/g)); + testString: assert(__helpers.removeJSComments(code).match(/(var|let|const)\s*{\s*(tomorrow[^}]*|[^,]*,\s*tomorrow)\s*}\s*=\s*HIGH_TEMPERATURES(;|\s+|\/\/)/g)); - text: today should be equal to 77 and tomorrow should be equal to 80. testString: assert(today === 77 && tomorrow === 80); @@ -74,15 +74,6 @@ const tomorrow = HIGH_TEMPERATURES.tomorrow; -### After Test -
    - -```js -const removeJSComments = str => str.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, ''); -``` - -
    - ## Solution diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-pass-an-object-as-a-functions-parameters.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-pass-an-object-as-a-functions-parameters.english.md index 48641765f6..85f300c3c5 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-pass-an-object-as-a-functions-parameters.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-pass-an-object-as-a-functions-parameters.english.md @@ -43,7 +43,7 @@ tests: - text: half(stats) should be 28.015 testString: assert(half(stats) === 28.015); - text: Destructuring should be used. - testString: assert(code.replace(/\s/g, '').match(/half=\({\w+,\w+}\)/)); + testString: assert(__helpers.removeWhiteSpace(code).match(/half=\({\w+,\w+}\)/)); - text: Destructured parameter should be used. testString: assert(!code.match(/stats\.max|stats\.min/)); diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-with-the-rest-parameter-to-reassign-array-elements.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-with-the-rest-parameter-to-reassign-array-elements.english.md index 68e6b3335a..6d891165e6 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-with-the-rest-parameter-to-reassign-array-elements.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-with-the-rest-parameter-to-reassign-array-elements.english.md @@ -37,7 +37,7 @@ tests: - text: Array.slice() should not be used. testString: getUserInput => assert(!getUserInput('index').match(/slice/g)); - text: Destructuring on list should be used. - testString: assert(code.replace(/\s/g, '').match(/\[(([_$a-z]\w*)?,){1,}\.\.\.arr\]=list/i)); + testString: assert(__helpers.removeWhiteSpace(code).match(/\[(([_$a-z]\w*)?,){1,}\.\.\.arr\]=list/i)); ``` diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-the-rest-parameter-with-function-parameters.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-the-rest-parameter-with-function-parameters.english.md index 5d003a699a..1dc09b8e9c 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-the-rest-parameter-with-function-parameters.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/use-the-rest-parameter-with-function-parameters.english.md @@ -40,7 +40,7 @@ tests: - text: The result of sum() should be 0 testString: assert(sum() === 0); - text: The sum function should use the ... rest parameter on the args parameter. - testString: assert(code.replace(/\s/g,'').match(/sum=\(\.\.\.args\)=>/)); + testString: assert(__helpers.removeWhiteSpace(code).match(/sum=\(\.\.\.args\)=>/)); ``` diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/write-concise-declarative-functions-with-es6.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/write-concise-declarative-functions-with-es6.english.md index ea73909047..d7bda4a98d 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/write-concise-declarative-functions-with-es6.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/write-concise-declarative-functions-with-es6.english.md @@ -42,7 +42,7 @@ Refactor the function setGear inside the object bicycle assert(!removeJSComments(code).match(/function/)); + testString: getUserInput => assert(!__helpers.removeJSComments(code).match(/function/)); - text: setGear should be a declarative function. testString: assert(typeof bicycle.setGear === 'function' && code.match(/setGear\s*\(.+\)\s*\{/)); - text: bicycle.setGear(48) should change the gear value to 48. @@ -72,15 +72,6 @@ console.log(bicycle.gear); -### After Test -
    - -```js -const removeJSComments = str => str.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, ''); -``` - -
    - ## Solution diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/functional-programming/use-higher-order-functions-map-filter-or-reduce-to-solve-a-complex-problem.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/functional-programming/use-higher-order-functions-map-filter-or-reduce-to-solve-a-complex-problem.english.md index 991bf02b19..ba90a88630 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/functional-programming/use-higher-order-functions-map-filter-or-reduce-to-solve-a-complex-problem.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/functional-programming/use-higher-order-functions-map-filter-or-reduce-to-solve-a-complex-problem.english.md @@ -24,9 +24,9 @@ tests: - text: squareList should be a function. testString: assert.typeOf(squareList, 'function'), 'squareList should be a function'; - text: for or while loops or forEach should not be used. - testString: assert(!removeJSComments(code).match(/for|while|forEach/g)); + testString: assert(!__helpers.removeJSComments(code).match(/for|while|forEach/g)); - text: map, filter, or reduce should be used. - testString: assert(removeJSComments(code).match(/\.(map|filter|reduce)\s*\(/g)); + testString: assert(__helpers.removeJSComments(code).match(/\.(map|filter|reduce)\s*\(/g)); - text: The function should return an array. testString: assert(Array.isArray(squareList([4, 5.6, -9.8, 3.14, 42, 6, 8.34, -2]))); - text: squareList([4, 5.6, -9.8, 3.14, 42, 6, 8.34, -2]) should return [16, 1764, 36]. @@ -55,14 +55,6 @@ console.log(squaredIntegers); -
    - -```js -const removeJSComments = str => str.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, ''); -``` - -
    - ## Solution diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/functional-programming/use-the-map-method-to-extract-data-from-an-array.english.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/functional-programming/use-the-map-method-to-extract-data-from-an-array.english.md index 95748fc074..2d51d7fe0c 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/functional-programming/use-the-map-method-to-extract-data-from-an-array.english.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/functional-programming/use-the-map-method-to-extract-data-from-an-array.english.md @@ -41,7 +41,7 @@ tests: - text: The watchList variable should not change. testString: assert(watchList[0].Title === "Inception" && watchList[4].Director == "James Cameron"); - text: Your code should not use a for loop. - testString: assert(!removeJSComments(code).match(/for\s*?\([\s\S]*?\)/)); + testString: assert(!__helpers.removeJSComments(code).match(/for\s*?\([\s\S]*?\)/)); - text: Your code should use the map method. testString: assert(code.match(/\.map/g)); - text: ratings should equal [{"title":"Inception","rating":"8.8"},{"title":"Interstellar","rating":"8.6"},{"title":"The Dark Knight","rating":"9.0"},{"title":"Batman Begins","rating":"8.3"},{"title":"Avatar","rating":"7.9"}]. @@ -185,15 +185,6 @@ console.log(JSON.stringify(ratings)); -### After Test -
    - -```js -const removeJSComments = str => str.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, ''); -``` - -
    - ## Solution diff --git a/curriculum/challenges/english/03-front-end-libraries/react-and-redux/getting-started-with-react-redux.english.md b/curriculum/challenges/english/03-front-end-libraries/react-and-redux/getting-started-with-react-redux.english.md index fc08fd64ad..89f24306b1 100644 --- a/curriculum/challenges/english/03-front-end-libraries/react-and-redux/getting-started-with-react-redux.english.md +++ b/curriculum/challenges/english/03-front-end-libraries/react-and-redux/getting-started-with-react-redux.english.md @@ -26,7 +26,7 @@ tests: - text: The DisplayMessages component should render an empty div element. testString: assert((function() { const mockedComponent = Enzyme.mount(React.createElement(DisplayMessages)); return mockedComponent.find('div').text() === '' })()); - text: The DisplayMessages constructor should be called properly with super, passing in props. - testString: getUserInput => assert((function() { const noWhiteSpace = getUserInput('index').replace(/\s/g,''); return noWhiteSpace.includes('constructor(props)') && noWhiteSpace.includes('super(props'); })()); + testString: getUserInput => assert((function() { const noWhiteSpace = __helpers.removeWhiteSpace(getUserInput('index')); return noWhiteSpace.includes('constructor(props)') && noWhiteSpace.includes('super(props'); })()); - text: 'The DisplayMessages component should have an initial state equal to {input: "", messages: []}.' 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; })());" diff --git a/curriculum/challenges/english/03-front-end-libraries/react-and-redux/use-provider-to-connect-redux-to-react.english.md b/curriculum/challenges/english/03-front-end-libraries/react-and-redux/use-provider-to-connect-redux-to-react.english.md index 4a4590ff21..0ce519d4a1 100644 --- a/curriculum/challenges/english/03-front-end-libraries/react-and-redux/use-provider-to-connect-redux-to-react.english.md +++ b/curriculum/challenges/english/03-front-end-libraries/react-and-redux/use-provider-to-connect-redux-to-react.english.md @@ -33,7 +33,7 @@ tests: - text: The AppWrapper should render. testString: assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('AppWrapper').length === 1; })()); - text: The Provider wrapper component should have a prop of store 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(''); })()); + testString: getUserInput => assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return __helpers.removeWhiteSpace(getUserInput('index')).includes(''); })()); - text: DisplayMessages should render as a child of AppWrapper. testString: assert((function() { const mockedComponent = Enzyme.mount(React.createElement(AppWrapper)); return mockedComponent.find('AppWrapper').find('DisplayMessages').length === 1; })()); - text: The DisplayMessages component should render an h2, input, button, and ul element. diff --git a/curriculum/challenges/english/03-front-end-libraries/react/pass-props-to-a-stateless-functional-component.english.md b/curriculum/challenges/english/03-front-end-libraries/react/pass-props-to-a-stateless-functional-component.english.md index 230e78c457..9d3537e7e8 100644 --- a/curriculum/challenges/english/03-front-end-libraries/react/pass-props-to-a-stateless-functional-component.english.md +++ b/curriculum/challenges/english/03-front-end-libraries/react/pass-props-to-a-stateless-functional-component.english.md @@ -44,7 +44,7 @@ tests: - text: The date prop of the CurrentDate should contain a string of text. testString: assert((function() { const mockedComponent = Enzyme.mount(React.createElement(Calendar)); const prop = mockedComponent.children().childAt(1).props().date; return( typeof prop === 'string' && prop.length > 0 ); })()); - text: The date prop should be generated by calling Date() - testString: assert(//.test(code.replace(/\s/g, ''))) + testString: assert(//.test(__helpers.removeWhiteSpace(code))) - text: The CurrentDate component should render the value from the date prop in the p tag. testString: let date = "dummy date"; assert((function() { const mockedComponent = Enzyme.mount(React.createElement(CurrentDate, {date})); return mockedComponent.find('p').html().includes(date); })()); diff --git a/curriculum/challenges/english/03-front-end-libraries/react/review-using-props-with-stateless-functional-components.english.md b/curriculum/challenges/english/03-front-end-libraries/react/review-using-props-with-stateless-functional-components.english.md index b92f45d6af..b9eded62bf 100644 --- a/curriculum/challenges/english/03-front-end-libraries/react/review-using-props-with-stateless-functional-components.english.md +++ b/curriculum/challenges/english/03-front-end-libraries/react/review-using-props-with-stateless-functional-components.english.md @@ -28,9 +28,9 @@ tests: - text: The Camper component should render. testString: assert((function() { const mockedComponent = Enzyme.mount(React.createElement(CampSite)); return mockedComponent.find('Camper').length === 1; })()); - text: The Camper component should include default props which assign the string CamperBot to the key name. - testString: assert(/Camper.defaultProps={name:(['"`])CamperBot\1,?}/.test(code.replace(/\s/g, ''))); + testString: assert(/Camper.defaultProps={name:(['"`])CamperBot\1,?}/.test(__helpers.removeWhiteSpace(code))); - text: The Camper component should include prop types which require the name prop to be of type string. - testString: assert(/Camper.propTypes={name:PropTypes.string.isRequired,?}/.test(code.replace(/\s/g, ''))); + testString: assert(/Camper.propTypes={name:PropTypes.string.isRequired,?}/.test(__helpers.removeWhiteSpace(code))); - text: The Camper component should contain a p element with only the text from the name prop. testString: assert((function() { const mockedComponent = Enzyme.mount(React.createElement(CampSite)); return mockedComponent.find('p').text() === mockedComponent.find('Camper').props().name; })()); diff --git a/curriculum/challenges/english/03-front-end-libraries/react/use-proptypes-to-define-the-props-you-expect.english.md b/curriculum/challenges/english/03-front-end-libraries/react/use-proptypes-to-define-the-props-you-expect.english.md index be1486971f..8d5f038fb1 100644 --- a/curriculum/challenges/english/03-front-end-libraries/react/use-proptypes-to-define-the-props-you-expect.english.md +++ b/curriculum/challenges/english/03-front-end-libraries/react/use-proptypes-to-define-the-props-you-expect.english.md @@ -33,7 +33,7 @@ tests: - text: The Items component should render. testString: assert((function() { const mockedComponent = Enzyme.mount(React.createElement(ShoppingCart)); return mockedComponent.find('Items').length === 1; })()); - text: The Items component should include a propTypes check that requires quantity to be a number. - testString: getUserInput => assert((function() { const noWhiteSpace = getUserInput('index').replace(/ /g, ''); return noWhiteSpace.includes('quantity:PropTypes.number.isRequired') && noWhiteSpace.includes('Items.propTypes='); })()); + testString: getUserInput => assert((function() { const noWhiteSpace = __helpers.removeWhiteSpace(getUserInput('index')); return noWhiteSpace.includes('quantity:PropTypes.number.isRequired') && noWhiteSpace.includes('Items.propTypes='); })()); ``` diff --git a/curriculum/challenges/english/03-front-end-libraries/react/use-state-to-toggle-an-element.english.md b/curriculum/challenges/english/03-front-end-libraries/react/use-state-to-toggle-an-element.english.md index 9eb51983d5..468ffb4586 100644 --- a/curriculum/challenges/english/03-front-end-libraries/react/use-state-to-toggle-an-element.english.md +++ b/curriculum/challenges/english/03-front-end-libraries/react/use-state-to-toggle-an-element.english.md @@ -77,7 +77,7 @@ tests: assert(!firstValue && secondValue && !thirdValue); })();" - text: An anonymous function should be passed to setState. - testString: const paramRegex = '[a-zA-Z$_]\\w*(,[a-zA-Z$_]\\w*)?'; const noSpaces = code.replace(/\s/g, ''); assert(new RegExp('this\\.setState\\((function\\(' + paramRegex + '\\){|([a-zA-Z$_]\\w*|\\(' + paramRegex + '\\))=>)').test(noSpaces)); + testString: const paramRegex = '[a-zA-Z$_]\\w*(,[a-zA-Z$_]\\w*)?'; assert(new RegExp('this\\.setState\\((function\\(' + paramRegex + '\\){|([a-zA-Z$_]\\w*|\\(' + paramRegex + '\\))=>)').test(__helpers.removeWhiteSpace(code))); - text: this should not be used inside setState testString: assert(!/this\.setState\([^}]*this/.test(code)); ``` diff --git a/curriculum/challenges/english/03-front-end-libraries/react/write-a-react-component-from-scratch.english.md b/curriculum/challenges/english/03-front-end-libraries/react/write-a-react-component-from-scratch.english.md index 4b77cdf6a9..c40c423d7a 100644 --- a/curriculum/challenges/english/03-front-end-libraries/react/write-a-react-component-from-scratch.english.md +++ b/curriculum/challenges/english/03-front-end-libraries/react/write-a-react-component-from-scratch.english.md @@ -23,7 +23,7 @@ Render this component to the DOM using ReactDOM.render(). There is ```yml tests: - text: There should be a React component called MyComponent. - testString: getUserInput => assert(getUserInput('index').replace(/\s/g, '').includes('classMyComponentextendsReact.Component{')); + testString: getUserInput => assert(__helpers.removeWhiteSpace(getUserInput('index')).includes('classMyComponentextendsReact.Component{')); - text: MyComponent should contain an h1 tag with text My First React Component! Case and punctuation matter. testString: assert((function() { const mockedComponent = Enzyme.mount(React.createElement(MyComponent)); return mockedComponent.find('h1').text() === 'My First React Component!'; })()); - text: MyComponent should render to the DOM. diff --git a/curriculum/challenges/english/03-front-end-libraries/redux/combine-multiple-reducers.english.md b/curriculum/challenges/english/03-front-end-libraries/redux/combine-multiple-reducers.english.md index 3a57e2c57c..724fc7425b 100644 --- a/curriculum/challenges/english/03-front-end-libraries/redux/combine-multiple-reducers.english.md +++ b/curriculum/challenges/english/03-front-end-libraries/redux/combine-multiple-reducers.english.md @@ -39,7 +39,7 @@ tests: - text: 'The store state should have two keys: count, which holds a number, and auth, which holds an object. The auth object should have a property of authenticated, 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' })());" - text: The rootReducer should be a function that combines the counterReducer and the authReducer. - testString: getUserInput => assert((function() { const noWhiteSpace = getUserInput('index').replace(/\s/g,''); return typeof rootReducer === 'function' && noWhiteSpace.includes('Redux.combineReducers') })()); + testString: getUserInput => assert((function() { const noWhiteSpace = __helpers.removeWhiteSpace(getUserInput('index')); return typeof rootReducer === 'function' && noWhiteSpace.includes('Redux.combineReducers') })()); ``` diff --git a/curriculum/challenges/english/03-front-end-libraries/redux/use-const-for-action-types.english.md b/curriculum/challenges/english/03-front-end-libraries/redux/use-const-for-action-types.english.md index cdd2afee83..a75df764b9 100644 --- a/curriculum/challenges/english/03-front-end-libraries/redux/use-const-for-action-types.english.md +++ b/curriculum/challenges/english/03-front-end-libraries/redux/use-const-for-action-types.english.md @@ -35,9 +35,9 @@ tests: - text: The authReducer 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') })()); - text: LOGIN and LOGOUT should be declared as const values and should be assigned strings of LOGINand LOGOUT. - testString: const noWhiteSpace = code.replace(/\s/g, ''); assert(/constLOGIN=(['"`])LOGIN\1/.test(noWhiteSpace) && /constLOGOUT=(['"`])LOGOUT\1/.test(noWhiteSpace)); + testString: const noWhiteSpace = __helpers.removeWhiteSpace(code); assert(/constLOGIN=(['"`])LOGIN\1/.test(noWhiteSpace) && /constLOGOUT=(['"`])LOGOUT\1/.test(noWhiteSpace)); - text: The action creators and the reducer should reference the LOGIN and LOGOUT 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') })()); + testString: getUserInput => assert((function() { const noWhiteSpace = __helpers.removeWhiteSpace(getUserInput('index').toString()); return noWhiteSpace.includes('caseLOGIN:') && noWhiteSpace.includes('caseLOGOUT:') && noWhiteSpace.includes('type:LOGIN') && noWhiteSpace.includes('type:LOGOUT') })()); ``` diff --git a/curriculum/challenges/english/03-front-end-libraries/redux/use-middleware-to-handle-asynchronous-actions.english.md b/curriculum/challenges/english/03-front-end-libraries/redux/use-middleware-to-handle-asynchronous-actions.english.md index 578e585214..6ee818aace 100644 --- a/curriculum/challenges/english/03-front-end-libraries/redux/use-middleware-to-handle-asynchronous-actions.english.md +++ b/curriculum/challenges/english/03-front-end-libraries/redux/use-middleware-to-handle-asynchronous-actions.english.md @@ -33,7 +33,7 @@ tests: - text: Dispatching the requestingData action creator should update the store state property of fetching to true. testString: assert((function() { const initialState = store.getState(); store.dispatch(requestingData()); const reqState = store.getState(); return initialState.fetching === false && reqState.fetching === true })()); - text: Dispatching handleAsync 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 })()); + testString: assert((function() { const noWhiteSpace = __helpers.removeWhiteSpace(handleAsync.toString()); return noWhiteSpace.includes('dispatch(requestingData())') === true && noWhiteSpace.includes('dispatch(receivedData(data))') === true })()); ``` diff --git a/curriculum/challenges/english/10-coding-interview-prep/project-euler/problem-43-sub-string-divisibility.english.md b/curriculum/challenges/english/10-coding-interview-prep/project-euler/problem-43-sub-string-divisibility.english.md index 522356ce70..bed55bd073 100644 --- a/curriculum/challenges/english/10-coding-interview-prep/project-euler/problem-43-sub-string-divisibility.english.md +++ b/curriculum/challenges/english/10-coding-interview-prep/project-euler/problem-43-sub-string-divisibility.english.md @@ -41,7 +41,7 @@ tests: - text: substringDivisibility() should return [ 1430952867, 1460357289, 1406357289, 4130952867, 4160357289, 4106357289 ]. testString: assert.sameMembers(substringDivisibility(), [ 1430952867, 1460357289, 1406357289, 4130952867, 4160357289, 4106357289 ]); - text: You should not copy and return the array. - testString: assert(!removeJSComments(code).match(/(1430952867)|(1460357289)|(1406357289)|(4130952867)|(4160357289)|(4106357289)/)) + testString: assert(!__helpers.removeJSComments(code).match(/(1430952867)|(1460357289)|(1406357289)|(4130952867)|(4160357289)|(4106357289)/)) ``` @@ -63,15 +63,6 @@ substringDivisibility(); -### After Test -
    - -```js -const removeJSComments = str => str.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, ''); -``` - -
    - ## Solution diff --git a/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/iban.english.md b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/iban.english.md index 54f3277343..587716512a 100644 --- a/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/iban.english.md +++ b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/iban.english.md @@ -77,7 +77,7 @@ function isValid(iban) { MC:27, MR:27, SM:27, AL:28, AZ:28, CY:28, DO:28, GT:28, HU:28, LB:28, PL:28, BR:29, PS:29, KW:30, MU:30, MT:31 } - iban = iban.replace(/\s/g, '') + iban = __helpers.removeWhiteSpace(iban) if (!iban.match(/^[\dA-Z]+$/)) return false var len = iban.length if (len != ibanLen[iban.substr(0,2)]) return false diff --git a/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/state-name-puzzle.english.md b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/state-name-puzzle.english.md index 925b87b182..1808983bb2 100644 --- a/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/state-name-puzzle.english.md +++ b/curriculum/challenges/english/10-coding-interview-prep/rosetta-code/state-name-puzzle.english.md @@ -66,7 +66,7 @@ function solve(input) { function solve(input) { var orig = {}; input.forEach(function(e) { - orig[e.replace(/\s/g, '').toLowerCase()] = e; + orig[__helpers.removeWhiteSpace(e).toLowerCase()] = e; }); input = Object.keys(orig);