feat: mobile curriculum testing (#47586)

* feat: first draft of action and cypress spec

* feat: test all generated challenges

* fix: better identification of block

* action: update cypress config

* action: upload to dashboard

* action: testing js cert challenges

* fix: unnecessary after user code for Make a Person

* feat: capture console log output for assert test

* fix: remove after seed code

* fix: change const to let

* fix: test

* action: disable js certification

* action: stop checking out branch in action

* action: check out right mobile repo

Co-authored-by: sembauke <semboot699@gmail.com>
pull/48052/head
Niraj Nandish 2022-10-15 05:27:34 +05:30 committed by GitHub
parent 035b475500
commit 441f11db38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 144 additions and 45 deletions

View File

@ -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 }}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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--

View File

@ -137,14 +137,6 @@ assert.strictEqual(
# --seed--
## --after-user-code--
```js
if(bob){
bob = new Person("Bob Ross");
}
```
## --seed-contents--
```js

View File

@ -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

View File

@ -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');
});
}
});
}
}
});