diff --git a/.github/workflows/mobile-curriculum-tests.yml b/.github/workflows/mobile-curriculum-tests.yml new file mode 100644 index 00000000000..d7a1b0d9822 --- /dev/null +++ b/.github/workflows/mobile-curriculum-tests.yml @@ -0,0 +1,72 @@ +name: Mobile Curriculum Tests +on: + push: + paths-ignore: + - 'docs/**' + branches-ignore: + - 'renovate/**' + pull_request: + paths-ignore: + - 'docs/**' + +jobs: + mobile-test: + name: Test curriculum for mobile app + runs-on: ubuntu-20.04 + + steps: + - name: Checkout Source Files + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3 + + - name: Checkout mobile + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3 + with: + repository: freeCodeCamp/mobile + path: mobile + + - name: Use Node.js 16.x + uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3 + with: + node-version: 16.x + cache: 'npm' + + - name: Setup Flutter 3.0.x + uses: subosito/flutter-action@9d48f4efd5460d7013af812069d08b23f37aed20 # tag=v2 + with: + flutter-version: '3.0.x' + channel: 'stable' + cache: true + cache-key: flutter-3.0.x + cache-path: ${{ runner.tool_cache }}/flutter + + - name: Set freeCodeCamp Environment Variables + run: cp sample.env .env + + - name: Install and Build + run: | + npm ci + npm run create:config + npm run build:curriculum + + - name: Generate mobile test files + run: | + cd mobile/mobile-app + echo "DEVELOPMENTMODE=true" > .env + echo "NEWSURL=https://www.freecodecamp.org/news/ghost/api/v3/content/" >> .env + flutter pub get + flutter test test/widget_test.dart + + - name: Cypress run + uses: cypress-io/github-action@v2 + with: + record: ${{ env.CYPRESS_RECORD_KEY != 0 }} + start: npx serve + wait-on: http://localhost:3000 + wait-on-timeout: 1200 + config: retries=1,screenshotOnRunFailure=false,video=false,baseUrl=http://localhost:3000/mobile/mobile-app/generated-tests/ + browser: chrome + headless: true + spec: cypress/integration/mobile-learn/test-challenges.js + env: + CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/divide-one-decimal-by-another-with-javascript.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/divide-one-decimal-by-another-with-javascript.md index 783ed7a0fbf..c3ee7fda9df 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/divide-one-decimal-by-another-with-javascript.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/divide-one-decimal-by-another-with-javascript.md @@ -37,12 +37,6 @@ assert(code.match(/quotient/g).length === 1); # --seed-- -## --after-user-code-- - -```js -(function(y){return 'quotient = '+y;})(quotient); -``` - ## --seed-contents-- ```js diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/escape-sequences-in-strings.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/escape-sequences-in-strings.md index df8bafee9d7..b41d20aed01 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/escape-sequences-in-strings.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/escape-sequences-in-strings.md @@ -78,14 +78,6 @@ assert(myStr === 'FirstLine\n\t\\SecondLine\nThirdLine'); # --seed-- -## --after-user-code-- - -```js -(function(){ -if (myStr !== undefined){ -console.log('myStr:\n' + myStr);}})(); -``` - ## --seed-contents-- ```js diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/initializing-variables-with-the-assignment-operator.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/initializing-variables-with-the-assignment-operator.md index 83b498c3b2d..1fd59cdfff7 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/initializing-variables-with-the-assignment-operator.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/initializing-variables-with-the-assignment-operator.md @@ -31,12 +31,6 @@ assert(/var\s+a\s*=\s*9(\s*;?\s*)$/.test(code)); # --seed-- -## --after-user-code-- - -```js -if(typeof a !== 'undefined') {(function(a){return "a = " + a;})(a);} else { (function() {return 'a is undefined';})(); } -``` - ## --seed-contents-- ```js diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/quoting-strings-with-single-quotes.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/quoting-strings-with-single-quotes.md index cce2d897b4d..dc6b0959b9f 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/quoting-strings-with-single-quotes.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/quoting-strings-with-single-quotes.md @@ -62,12 +62,6 @@ assert(code.match(/"/g).length === 4 && code.match(/'/g).length === 2); # --seed-- -## --after-user-code-- - -```js -(function() { return "myStr = " + myStr; })(); -``` - ## --seed-contents-- ```js diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/stand-in-line.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/stand-in-line.md index cd65b1cd1c2..acb85f3b8eb 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/stand-in-line.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/basic-javascript/stand-in-line.md @@ -98,7 +98,7 @@ function nextInLine(arr, item) { } // Setup -const testArr = [1, 2, 3, 4, 5]; +let testArr = [1, 2, 3, 4, 5]; // Display code console.log("Before: " + JSON.stringify(testArr)); @@ -109,7 +109,7 @@ console.log("After: " + JSON.stringify(testArr)); # --solutions-- ```js -const testArr = [1, 2, 3, 4, 5]; +let testArr = [1, 2, 3, 4, 5]; function nextInLine(arr, item) { arr.push(item); diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/write-concise-declarative-functions-with-es6.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/write-concise-declarative-functions-with-es6.md index 4c319f7bf16..78a62f5fb2d 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/write-concise-declarative-functions-with-es6.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/es6/write-concise-declarative-functions-with-es6.md @@ -53,7 +53,8 @@ assert( `bicycle.setGear(48)` should change the `gear` value to 48. ```js -assert(new bicycle.setGear(48).gear === 48); +bicycle.setGear(48); +assert(bicycle.gear === 48); ``` # --seed-- diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/make-a-person.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/make-a-person.md index b4b91f7cddc..ce2a043add9 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/make-a-person.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/make-a-person.md @@ -137,14 +137,6 @@ assert.strictEqual( # --seed-- -## --after-user-code-- - -```js -if(bob){ - bob = new Person("Bob Ross"); -} -``` - ## --seed-contents-- ```js diff --git a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/object-oriented-programming/add-methods-after-inheritance.md b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/object-oriented-programming/add-methods-after-inheritance.md index 33a5ab2895c..13db3f85a7c 100644 --- a/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/object-oriented-programming/add-methods-after-inheritance.md +++ b/curriculum/challenges/english/02-javascript-algorithms-and-data-structures/object-oriented-programming/add-methods-after-inheritance.md @@ -79,23 +79,55 @@ assert(beagle.constructor === Dog); `beagle.eat()` should log the string `nom nom nom` ```js -console.log = function (msg) { - throw msg; -}; -assert.throws(() => beagle.eat(), 'nom nom nom'); +capture(); +beagle.eat(); +uncapture(); +assert(logOutput == 'nom nom nom'); ``` `beagle.bark()` should log the string `Woof!` ```js -console.log = function (msg) { - throw msg; -}; -assert.throws(() => beagle.bark(), 'Woof!'); +capture(); +beagle.bark(); +uncapture(); +assert(logOutput == 'Woof!'); ``` # --seed-- +## --before-user-code-- + +```js +var logOutput = ""; +var originalConsole = console +function capture() { + var nativeLog = console.log; + console.log = function (message) { + logOutput = message; + if(nativeLog.apply) { + nativeLog.apply(originalConsole, arguments); + } else { + var nativeMsg = Array.prototype.slice.apply(arguments).join(' '); + nativeLog(nativeMsg); + } + }; +} + +function uncapture() { + console.log = originalConsole.log; +} + +capture(); +``` + +## --after-user-code-- + +```js +uncapture(); +(function() { return logOutput || "console.log never called"; })(); +``` + ## --seed-contents-- ```js diff --git a/cypress/integration/mobile-learn/test-challenges.js b/cypress/integration/mobile-learn/test-challenges.js new file mode 100644 index 00000000000..84386be01d3 --- /dev/null +++ b/cypress/integration/mobile-learn/test-challenges.js @@ -0,0 +1,28 @@ +import currData from '../../../config/curriculum.json'; +import { orderedSuperBlockInfo } from '../../../tools/scripts/build/build-external-curricula-data'; + +const publicSB = orderedSuperBlockInfo + .filter(sb => sb.public === true) + .map(sb => sb.dashedName); + +describe('Test challenges in mobile', () => { + for (let superBlock of publicSB) { + for (let currBlock of Object.values(currData[superBlock]['blocks'])) { + describe(`SuperBlock: ${superBlock} - Block: ${currBlock['meta']['name']}`, () => { + for (let currChallenge of currBlock['challenges']) { + it(`Challenge: ${currChallenge['title']}(${currChallenge['id']})`, () => { + cy.visit( + `/${superBlock}/${currChallenge['block']}/${currChallenge['id']}`, + { + onBeforeLoad(win) { + cy.spy(win.console, 'log').as('consoleLog'); + } + } + ); + cy.get('@consoleLog').should('be.calledWith', 'completed'); + }); + } + }); + } + } +});