feat(scripts): add scripts to seed exams (#50836)

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
Tom
2023-07-14 10:35:09 -05:00
committed by GitHub
parent b2a366a6a9
commit 21ed268289
10 changed files with 702 additions and 46 deletions

View File

@@ -75,6 +75,7 @@
"preseed": "npm-run-all create:*",
"seed": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seed-demo-user",
"seed:certified-user": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seed-demo-user certified-user",
"seed:exams": "cd tools/scripts/seed-exams && cross-env node ./create-exams.js",
"serve:client": "cd ./client && pnpm run serve",
"serve:client-ci": "cd ./client && pnpm run serve-ci",
"start": "npm-run-all create:* -p develop:server serve:client",

121
pnpm-lock.yaml generated
View File

@@ -1254,6 +1254,30 @@ importers:
specifier: 5.7.0
version: 5.7.0
tools/scripts/seed-exams:
devDependencies:
dotenv:
specifier: 16.3.1
version: 16.3.1
joi:
specifier: 17.9.2
version: 17.9.2
joi-objectid:
specifier: 3.0.1
version: 3.0.1
js-yaml:
specifier: 4.1.0
version: 4.1.0
lodash:
specifier: 4.17.21
version: 4.17.21
mongodb:
specifier: 5.6.0
version: 5.6.0
nanoid:
specifier: 4.0.2
version: 4.0.2
tools/ui-components:
dependencies:
'@fortawesome/free-solid-svg-icons':
@@ -16109,6 +16133,7 @@ packages:
dependencies:
ms: 2.1.3
supports-color: 8.1.1
dev: true
/debug@4.3.1:
resolution: {integrity: sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==}
@@ -16423,7 +16448,7 @@ packages:
'@types/tmp': 0.0.33
application-config-path: 0.1.1
command-exists: 1.2.9
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
eol: 0.9.1
get-port: 3.2.0
glob: 7.2.3
@@ -16729,7 +16754,7 @@ packages:
hasBin: true
dependencies:
cross-spawn: 7.0.3
dotenv: 16.0.3
dotenv: 16.3.1
dotenv-expand: 10.0.0
minimist: 1.2.8
dev: true
@@ -16747,11 +16772,6 @@ packages:
engines: {node: '>=10'}
dev: false
/dotenv@16.0.3:
resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==}
engines: {node: '>=12'}
dev: true
/dotenv@16.3.1:
resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==}
engines: {node: '>=12'}
@@ -17326,7 +17346,7 @@ packages:
/eslint-import-resolver-node@0.3.7:
resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==}
dependencies:
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
is-core-module: 2.11.0
resolve: 1.22.2
transitivePeerDependencies:
@@ -17354,7 +17374,7 @@ packages:
optional: true
dependencies:
'@typescript-eslint/parser': 4.33.0(eslint@7.32.0)(typescript@4.9.5)
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
eslint: 7.32.0
eslint-import-resolver-node: 0.3.7
transitivePeerDependencies:
@@ -17382,7 +17402,7 @@ packages:
optional: true
dependencies:
'@typescript-eslint/parser': 5.61.0(eslint@8.44.0)(typescript@4.9.5)
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
eslint: 8.44.0
eslint-import-resolver-node: 0.3.7
transitivePeerDependencies:
@@ -17455,7 +17475,7 @@ packages:
array-includes: 3.1.6
array.prototype.flat: 1.3.1
array.prototype.flatmap: 1.3.1
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
doctrine: 2.1.0
eslint: 7.32.0
eslint-import-resolver-node: 0.3.7
@@ -17487,7 +17507,7 @@ packages:
array-includes: 3.1.6
array.prototype.flat: 1.3.1
array.prototype.flatmap: 1.3.1
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
doctrine: 2.1.0
eslint: 8.44.0
eslint-import-resolver-node: 0.3.7
@@ -18758,7 +18778,7 @@ packages:
debug:
optional: true
dependencies:
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
/follow-redirects@1.15.2(debug@4.3.4):
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
@@ -19124,7 +19144,7 @@ packages:
gatsby-telemetry: 2.15.0
hosted-git-info: 3.0.8
is-valid-path: 0.1.1
joi: 17.8.3
joi: 17.9.2
lodash: 4.17.21
meant: 1.0.3
node-fetch: 2.6.9
@@ -19587,7 +19607,7 @@ packages:
css-minimizer-webpack-plugin: 2.0.0(webpack@5.88.1)
css.escape: 1.5.1
date-fns: 2.30.0
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
deepmerge: 4.3.0
del: 5.1.0
detect-port: 1.5.1
@@ -19633,7 +19653,7 @@ packages:
invariant: 2.2.4
is-relative: 1.0.0
is-relative-url: 3.0.0
joi: 17.8.3
joi: 17.9.2
json-loader: 0.5.7
latest-version: 5.1.0
lodash: 4.17.21
@@ -20805,23 +20825,13 @@ packages:
dependencies:
'@types/express': 4.17.17
'@types/http-proxy': 1.17.10
http-proxy: 1.18.1
http-proxy: 1.18.1(debug@3.2.7)
is-glob: 4.0.3
is-plain-obj: 3.0.0
micromatch: 4.0.5
transitivePeerDependencies:
- debug
/http-proxy@1.18.1:
resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==}
engines: {node: '>=8.0.0'}
dependencies:
eventemitter3: 4.0.7
follow-redirects: 1.15.2(debug@4.3.4)
requires-port: 1.0.0
transitivePeerDependencies:
- debug
/http-proxy@1.18.1(debug@3.2.7):
resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==}
engines: {node: '>=8.0.0'}
@@ -22990,15 +23000,6 @@ packages:
resolution: {integrity: sha512-V/3hbTlGpvJ03Me6DJbdBI08hBTasFOmipsauOsxOSnsF1blxV537WTl1zPwbfcKle4AK0Ma4OPnzMH4LlvTpQ==}
dev: true
/joi@17.8.3:
resolution: {integrity: sha512-q5Fn6Tj/jR8PfrLrx4fpGH4v9qM6o+vDUfD4/3vxxyg34OmKcNqYZ1qn2mpLza96S8tL0p0rIw2gOZX+/cTg9w==}
dependencies:
'@hapi/hoek': 9.3.0
'@hapi/topo': 5.1.0
'@sideway/address': 4.1.4
'@sideway/formula': 3.0.1
'@sideway/pinpoint': 2.0.0
/joi@17.9.2:
resolution: {integrity: sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw==}
dependencies:
@@ -23789,7 +23790,7 @@ packages:
dependencies:
async: 0.9.2
commondir: 1.0.1
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
lodash: 4.17.21
semver: 5.7.1
strong-globalize: 4.1.3
@@ -23802,7 +23803,7 @@ packages:
resolution: {integrity: sha512-vDRR4gqkvGOEXh5yL383xGuGxUW9xtF+NCY6/lJu1VAgupKltZxEx3Vw+L3nsGvQrlkJTSmiK3jk72qxkoBtbw==}
engines: {node: '>=6'}
dependencies:
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
lodash: 4.17.21
loopback-swagger: 5.9.0
strong-globalize: 4.1.3
@@ -23817,7 +23818,7 @@ packages:
dependencies:
async: 2.6.4
bson: 1.1.6
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
loopback-connector: 4.11.1
mongodb: 3.6.9
strong-globalize: 4.1.3
@@ -23861,7 +23862,7 @@ packages:
dependencies:
async: 2.6.4
bluebird: 3.7.2
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
depd: 1.1.2
inflection: 1.13.4
lodash: 4.17.21
@@ -23885,7 +23886,7 @@ packages:
resolution: {integrity: sha512-p0qSzuuX7eATe5Bxy+RqCj3vSfSFfdCtqyf3yuC+DpchMvgal33XlhEi2UmywyK/Ym28oVnZxxWmfrwFMzSwLQ==}
engines: {node: '>=4.0.0'}
dependencies:
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
transitivePeerDependencies:
- supports-color
dev: false
@@ -23895,7 +23896,7 @@ packages:
engines: {node: '>=8.9'}
dependencies:
async: 2.6.4
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
strong-globalize: 4.1.3
transitivePeerDependencies:
- supports-color
@@ -23906,7 +23907,7 @@ packages:
engines: {node: '>=8'}
dependencies:
async: 2.6.4
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
ejs: 2.7.4
lodash: 4.17.21
strong-globalize: 4.1.3
@@ -25281,6 +25282,28 @@ packages:
- aws-crt
dev: false
/mongodb@5.6.0:
resolution: {integrity: sha512-z8qVs9NfobHJm6uzK56XBZF8XwM9H294iRnB7wNjF0SnY93si5HPziIJn+qqvUR5QOff/4L0gCD6SShdR/GtVQ==}
engines: {node: '>=14.20.1'}
peerDependencies:
'@aws-sdk/credential-providers': ^3.201.0
mongodb-client-encryption: '>=2.3.0 <3'
snappy: ^7.2.2
peerDependenciesMeta:
'@aws-sdk/credential-providers':
optional: true
mongodb-client-encryption:
optional: true
snappy:
optional: true
dependencies:
bson: 5.4.0
mongodb-connection-string-url: 2.6.0
socks: 2.7.1
optionalDependencies:
saslprep: 1.0.3
dev: true
/mongodb@5.7.0:
resolution: {integrity: sha512-zm82Bq33QbqtxDf58fLWBwTjARK3NSvKYjyz997KSy6hpat0prjeX/kxjbPVyZY60XYPDNETaHkHJI2UCzSLuw==}
engines: {node: '>=14.20.1'}
@@ -25453,6 +25476,12 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
/nanoid@4.0.2:
resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==}
engines: {node: ^14 || ^16 || >=18}
hasBin: true
dev: true
/nanomatch@1.2.13:
resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==}
engines: {node: '>=0.10.0'}
@@ -25501,7 +25530,7 @@ packages:
engines: {node: '>= 4.4.x'}
hasBin: true
dependencies:
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
iconv-lite: 0.4.24
sax: 1.2.4
transitivePeerDependencies:
@@ -33625,7 +33654,7 @@ packages:
/webpack-virtual-modules@0.2.2:
resolution: {integrity: sha512-kDUmfm3BZrei0y+1NTHJInejzxfhtU8eDj2M7OKb2IWrPFAeO1SOH2KuQ68MSZu9IGEHcxbkKKR1v18FrUSOmA==}
dependencies:
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
transitivePeerDependencies:
- supports-color
dev: true
@@ -33633,7 +33662,7 @@ packages:
/webpack-virtual-modules@0.3.2:
resolution: {integrity: sha512-RXQXioY6MhzM4CNQwmBwKXYgBs6ulaiQ8bkNQEl2J6Z+V+s7lgl/wGvaI/I0dLnYKB8cKsxQc17QOAVIphPLDw==}
dependencies:
debug: 3.2.7(supports-color@8.1.1)
debug: 3.2.7(supports-color@5.5.0)
transitivePeerDependencies:
- supports-color

View File

@@ -12,4 +12,5 @@ packages:
- 'tools/crowdin'
- 'tools/scripts/build'
- 'tools/scripts/seed'
- 'tools/scripts/seed-exams'
- 'tools/ui-components'

View File

@@ -0,0 +1,33 @@
## WARNING: Never change any of the ID's or delete anything. Mark things as deprecated instead.
### How to create a new exam:
1. Add the exam file in the `exams` folder
2. Add the exam meta data:
- `_id`: This should match the `id` in the exam challenge markdown file,
- `title`: This should match the `title` in the exam challenge markdown file,
- `numberOfQuestionsInExam`: This is how many questions will be given to campers who take the exam. It must be less than or equal to the length of the `questions` array.
- `passingPercent`: Percent of questions needed to get correct to pass the exam
- `prerequisites`: Array of challenges that are required to complete before being able to take the exam. Each should have an `id` and `title` that match what's in their challenge markdown file
- `questions`: Array of exam questions
3. Add the exam questions to the `questions` array:
- `question`: The exam question
- `wrongAnswers`: Array of answers. There should be at least 4, but 6-7 would be ideal.
- `correctAnswers`: Array of answers. There should be at least 1, but 2 or more would be ideal when possible.
4. `wrongAnswers` and `correctAnwers` arrays:
- `answer`: This is one of the multiple choice options
5. Add the ID's:
- Change the `examPath` variable in the `add-nano-ids.js` file to the name of the new exam file
- Run it with `node add-nano-ids.js`. It will add an `id` to each `question`, and each `answer`.
Add a `deprecated: true` property to any of the `questions`, `wrongAnswers`, or `correctAnwers`. Any that include this will be omitted when generating an exam.
The exam files in this folder are not used in production. Never push real exam questions to GitHub or anywhere public. These exams are for local development and testing. To seed the real exams to staging/production databases, replace the example exams here with the real exams, connect to the desired database, and run the `create-exams.js` script.

View File

@@ -0,0 +1,54 @@
/*
* Script that will add `id` fields to the `questions`, `wrong_answers`, and
* `correct_answers` of an exam file where the `id` doesn't exist.
*/
import { readFileSync, writeFileSync } from 'fs';
import { customAlphabet } from 'nanoid';
import yaml from 'js-yaml';
const newId = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz', 10);
// Change this to the path of the file you want to add id's to
const examPath = './exams/example-certification-exam.yml';
const examFile = readFileSync(examPath, { encoding: 'utf-8' });
const examJson = yaml.load(examFile);
// The strangeness of how the id's are added below is to keep the id at the top
// of each object when rewriting the YAML at the end
const newQuestions = [];
examJson.questions?.forEach(question => {
let newQuestion;
if (!question.id) {
newQuestion = { id: newId(), ...question };
} else {
newQuestion = { ...question };
}
let newWrongAnswers = [];
question.wrongAnswers?.forEach(answer => {
if (!answer.id) {
newWrongAnswers.push({ id: newId(), ...answer });
} else {
newWrongAnswers.push(answer);
}
});
let newCorrectAnswers = [];
question.correctAnswers?.forEach(answer => {
if (!answer.id) {
newCorrectAnswers.push({ id: newId(), ...answer });
} else {
newCorrectAnswers.push(answer);
}
});
newQuestion.wrongAnswers = newWrongAnswers;
newQuestion.correctAnswers = newCorrectAnswers;
newQuestions.push(newQuestion);
});
examJson.questions = newQuestions;
const yamlStr = yaml.dump(examJson);
writeFileSync(examPath, yamlStr, 'utf8');

View File

@@ -0,0 +1,76 @@
import { readFileSync } from 'fs';
import path, { join } from 'path';
import { fileURLToPath } from 'url';
import dotenv from 'dotenv';
import yaml from 'js-yaml';
import { MongoClient, ObjectId } from 'mongodb';
import { validateExamSchema } from './exam-schema.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
dotenv.config({ path: path.resolve(__dirname, '../../../.env') });
const { MONGOHQ_URL } = process.env;
// Only these will be added to or updated in the database
const examFilenames = [
'foundational-c-sharp-with-microsoft-certification-exam.yml',
'example-certification-exam.yml'
];
const client = new MongoClient(MONGOHQ_URL, { useUnifiedTopology: true });
const db = client.db('freecodecamp');
const exams = db.collection('Exam');
function handleError(err, client) {
if (err) {
console.error('Oh noes!! Error seeding exams.');
console.error(err);
try {
client.close();
} catch (e) {
// no-op
} finally {
/* eslint-disable-next-line no-process-exit */
process.exit(1);
}
}
}
const seed = async () => {
for (const filename of examFilenames) {
try {
const examPath = join('./exams', filename);
const examFile = readFileSync(examPath, { encoding: 'utf-8' });
const examJson = yaml.load(examFile);
const validExam = validateExamSchema(examJson);
if (validExam.error) {
throw new Error(
`Invalid exam schema for '${filename}': ${validExam.error.message}`
);
}
examJson._id = new ObjectId(examJson._id);
// Update existing database object, or create new if it doesn't exist
await exams.updateOne(
{ _id: examJson._id },
{ $set: examJson },
{ upsert: true }
);
console.log(`'${examJson.title}' added to exams database.`);
} catch (err) {
handleError(err, client);
}
}
console.log('Finished seeding exams.');
};
seed()
.then(() => client.close())
.catch(err => handleError(err, client));

View File

@@ -0,0 +1,86 @@
import Joi from 'joi';
import JoiObjectId from 'joi-objectid';
Joi.objectId = JoiObjectId(Joi);
const nanoIdRE = new RegExp('[a-z0-9]{10}');
const PrerequisitesJoi = Joi.object().keys({
id: Joi.objectId().required(),
title: Joi.string()
});
const AnswerJoi = Joi.object().keys({
id: Joi.string().regex(nanoIdRE).required(),
deprecated: Joi.bool(),
answer: Joi.string().required()
});
const QuestionJoi = Joi.object().keys({
id: Joi.string().regex(nanoIdRE).required(),
question: Joi.string().required(),
deprecated: Joi.bool(),
wrongAnswers: Joi.array()
.items(AnswerJoi)
.required()
.custom((value, helpers) => {
const nonDeprecatedCount = value.reduce(
(count, answer) => (answer.deprecated ? count : count + 1),
0
);
const minimumAnswers = 4;
if (nonDeprecatedCount < minimumAnswers) {
return helpers.message(
`'wrongAnswers' must have at least ${minimumAnswers} non-deprecated answers.`
);
}
return value;
}),
correctAnswers: Joi.array()
.items(AnswerJoi)
.required()
.custom((value, helpers) => {
const nonDeprecatedCount = value.reduce(
(count, answer) => (answer.deprecated ? count : count + 1),
0
);
const minimumAnswers = 1;
if (nonDeprecatedCount < minimumAnswers) {
return helpers.message(
`'correctAnswers' must have at least ${minimumAnswers} non-deprecated answer.`
);
}
return value;
})
});
const schema = Joi.object().keys({
// TODO: make sure _id and title match what's in the challenge markdown file
_id: Joi.objectId().required(),
title: Joi.string().required(),
numberOfQuestionsInExam: Joi.number()
.min(1)
.max(
Joi.ref('questions', {
adjust: questions => {
const nonDeprecatedCount = questions.reduce(
(count, question) => (question.deprecated ? count : count + 1),
0
);
return nonDeprecatedCount;
}
})
)
.required(),
passingPercent: Joi.number().min(0).max(100).required(),
prerequisites: Joi.array().items(PrerequisitesJoi),
questions: Joi.array().items(QuestionJoi).min(1).required()
});
export const validateExamSchema = exam => {
return schema.validate(exam);
};

View File

@@ -0,0 +1,166 @@
_id: 645147516c245de4d11eb7ba
title: Example Certification Exam
numberOfQuestionsInExam: 5
passingPercent: 70
questions:
- id: vjxyn2ngzs
question: Which of the following is NOT a JavaScript data type?
wrongAnswers:
- id: h1x269fts9
answer: Integer
- id: 3x3j6ts2sb
answer: Boolean
- id: 9g4ix2tr1z
answer: Symbol
- id: n1rfllrvvy
answer: String
- id: 33oq8q3aio
answer: Bigint
- id: 7w1gaddxup
answer: Undefined
- id: ywgqr2wp6i
answer: Object
correctAnswers:
- id: ydmnlkjviv
answer: Array
- id: sy2trjs7p8
answer: Float
- id: lpmv63p5sv
question: What does the `NaN` keyword represent in JavaScript?
wrongAnswers:
- id: 3cxs9as4bt
answer: Not a Node
- id: axn8omt3zf
answer: Null and None
- id: 7ssyazt4zu
answer: No Assignment Named
- id: do4cm37x7y
answer: Negative Assertion Needed
- id: r2hbfnrodz
answer: Never Allow Null
correctAnswers:
- id: ah5kkj38s1
answer: Not a Number
- id: g2hudvmgoj
question: >-
Which method is used to remove the last element from an array in
JavaScript?
wrongAnswers:
- id: jrxd1hjv63
answer: '`shift()`'
- id: udc3kecrqn
answer: '`unshift()`'
- id: a12aysp2et
answer: '`slice()`'
- id: xljr0lkb0n
answer: '`splice()`'
- id: qe4z3kxgyz
answer: '`concat()`'
correctAnswers:
- id: gwddf01p89
answer: '`pop()`'
- id: 7tfdjebrnq
question: >-
What is the correct way to create a new instance of an object in
JavaScript?
wrongAnswers:
- id: 5bygwpaz4d
answer: '`Object.create(MyObject);`'
- id: h5s3304gbl
answer: '`MyObject.create();`'
- id: mdsjsjpi9t
answer: '`Object.new(MyObject);`'
- id: 3o8otd8j9h
answer: '`MyObject.new();`'
- id: h4ozml27zn
answer: '`MyObject.instance();`'
deprecated: true
correctAnswers:
- id: qbfhqmnedn
answer: '`new MyObject();`'
- id: hx0gxr5yjc
question: What is the purpose of the `querySelectorAll` method in JavaScript?
deprecated: true
wrongAnswers:
- id: 71iry42cy1
answer: To select all elements with a specific ID
- id: jjyk5e9e1l
answer: To select all elements of a specific tag name
- id: k5tpc2o2q8
answer: To select all child elements of a specific parent
- id: s3cm1tq4wt
answer: To select all elements with a specific attribute
- id: l1gtuheh87
answer: To select elements based on their position in the DOM
correctAnswers:
- id: e6xz6zdpxr
answer: To select all elements with a specific class name
- id: eigcj3e0mg
question: Which operator is used to compare two values for equality in JavaScript?
wrongAnswers:
- id: ltgdcoyonb
answer: '`!=`'
- id: f3szfel7x6
answer: '`<`'
- id: b0meyxhvtu
answer: '`>`'
- id: 31dd0pte4i
answer: '`<=`'
- id: 9u8bi7wqa2
answer: '`>=`'
correctAnswers:
- id: fmo9sof6v2
answer: '`==`'
deprecated: true
- id: tl6eo06r4x
answer: '`===`'
- id: l5f2beg2ih
question: >-
Which of the following statements is used to terminate a loop in
JavaScript?
wrongAnswers:
- id: kqi1fg8vtm
answer: stop
- id: a2clf7fmyx
answer: exit
- id: v58wx865e7
answer: return
- id: 5mgeaetnf0
answer: halt
- id: 2u73kyry6o
answer: skip
correctAnswers:
- id: 7j046bkjmf
answer: break
- id: atuq2zwg4h
question: What is the correct syntax to define a function in JavaScript?
wrongAnswers:
- id: dusl68wx2o
answer: '`function myFunction {}`'
- id: dlwjt59a5s
answer: '`def myFunction():`'
- id: 98p8ai27ko
answer: '`function = myFunction {}`'
- id: 7ciq8sood9
answer: '`function myFunction():`'
correctAnswers:
- id: wc3h7uc4zn
answer: '`function myFunction() {}`'
- id: 3ne0ju7yzq
question: >-
Which of the following methods is used to add a new element to the end of
an array in JavaScript?
wrongAnswers:
- id: fytb9yvbug
answer: shift()
- id: wnc31qc1ie
answer: unshift()
- id: 22mi7j64h5
answer: pop()
- id: da96ukvtol
answer: splice()
- id: gc6elnmtzw
answer: concat()
correctAnswers:
- id: pymbxhyn12
answer: push()

View File

@@ -0,0 +1,179 @@
_id: 647e22d18acb466c97ccbef8
title: Foundational C# with Microsoft Certification Exam
numberOfQuestionsInExam: 5
passingPercent: 75
prerequisites:
- id: 647f85d407d29547b3bee1bb
title: Trophy - Write Your First Code Using C#
- id: 647f87dc07d29547b3bee1bf
title: Trophy - Create and Run Simple C# Console Applications
- id: 647f882207d29547b3bee1c0
title: Trophy - Add Logic to C# Console Applications
- id: 647f867a07d29547b3bee1bc
title: Trophy - Work with Variable Data in C# Console Applications
- id: 647f877f07d29547b3bee1be
title: Trophy - Create Methods in C# Console Applications
- id: 647f86ff07d29547b3bee1bd
title: Trophy - Debug C# Console Applications
questions:
- id: vjxyn2ngzs
question: Which of the following is NOT a JavaScript data type?
wrongAnswers:
- id: 5y7xv9ppc1
answer: Integer
- id: 3x3j6ts2sb
answer: Boolean
- id: 9g4ix2tr1z
answer: Symbol
- id: n1rfllrvvy
answer: String
- id: 33oq8q3aio
answer: Bigint
- id: 7w1gaddxup
answer: Undefined
- id: ywgqr2wp6i
answer: Object
correctAnswers:
- id: ydmnlkjviv
answer: Array
- id: sy2trjs7p8
answer: Float
- id: lpmv63p5sv
question: What does the `NaN` keyword represent in JavaScript?
wrongAnswers:
- id: 3cxs9as4bt
answer: Not a Node
- id: axn8omt3zf
answer: Null and None
- id: 7ssyazt4zu
answer: No Assignment Named
- id: do4cm37x7y
answer: Negative Assertion Needed
- id: r2hbfnrodz
answer: Never Allow Null
correctAnswers:
- id: ah5kkj38s1
answer: Not a Number
- id: g2hudvmgoj
question: >-
Which method is used to remove the last element from an array in
JavaScript?
wrongAnswers:
- id: jrxd1hjv63
answer: '`shift()`'
- id: udc3kecrqn
answer: '`unshift()`'
- id: a12aysp2et
answer: '`slice()`'
- id: xljr0lkb0n
answer: '`splice()`'
- id: qe4z3kxgyz
answer: '`concat()`'
correctAnswers:
- id: gwddf01p89
answer: '`pop()`'
- id: 7tfdjebrnq
question: >-
What is the correct way to create a new instance of an object in
JavaScript?
wrongAnswers:
- id: 5bygwpaz4d
answer: '`Object.create(MyObject);`'
- id: h5s3304gbl
answer: '`MyObject.create();`'
- id: mdsjsjpi9t
answer: '`Object.new(MyObject);`'
- id: 3o8otd8j9h
answer: '`MyObject.new();`'
- id: h4ozml27zn
answer: '`MyObject.instance();`'
deprecated: true
correctAnswers:
- id: qbfhqmnedn
answer: '`new MyObject();`'
- id: hx0gxr5yjc
question: What is the purpose of the `querySelectorAll` method in JavaScript?
deprecated: true
wrongAnswers:
- id: 71iry42cy1
answer: To select all elements with a specific ID
- id: jjyk5e9e1l
answer: To select all elements of a specific tag name
- id: k5tpc2o2q8
answer: To select all child elements of a specific parent
- id: s3cm1tq4wt
answer: To select all elements with a specific attribute
- id: l1gtuheh87
answer: To select elements based on their position in the DOM
correctAnswers:
- id: e6xz6zdpxr
answer: To select all elements with a specific class name
- id: eigcj3e0mg
question: Which operator is used to compare two values for equality in JavaScript?
wrongAnswers:
- id: ltgdcoyonb
answer: '`!=`'
- id: f3szfel7x6
answer: '`<`'
- id: b0meyxhvtu
answer: '`>`'
- id: 31dd0pte4i
answer: '`<=`'
- id: 9u8bi7wqa2
answer: '`>=`'
correctAnswers:
- id: fmo9sof6v2
answer: '`==`'
deprecated: true
- id: tl6eo06r4x
answer: '`===`'
- id: l5f2beg2ih
question: >-
Which of the following statements is used to terminate a loop in
JavaScript?
wrongAnswers:
- id: kqi1fg8vtm
answer: stop
- id: a2clf7fmyx
answer: exit
- id: v58wx865e7
answer: return
- id: 5mgeaetnf0
answer: halt
- id: 2u73kyry6o
answer: skip
correctAnswers:
- id: 7j046bkjmf
answer: break
- id: atuq2zwg4h
question: What is the correct syntax to define a function in JavaScript?
wrongAnswers:
- id: dusl68wx2o
answer: '`function myFunction {}`'
- id: dlwjt59a5s
answer: '`def myFunction():`'
- id: 98p8ai27ko
answer: '`function = myFunction {}`'
- id: 7ciq8sood9
answer: '`function myFunction():`'
correctAnswers:
- id: wc3h7uc4zn
answer: '`function myFunction() {}`'
- id: 3ne0ju7yzq
question: >-
Which of the following methods is used to add a new element to the end of
an array in JavaScript?
wrongAnswers:
- id: fytb9yvbug
answer: shift()
- id: wnc31qc1ie
answer: unshift()
- id: 22mi7j64h5
answer: pop()
- id: da96ukvtol
answer: splice()
- id: gc6elnmtzw
answer: concat()
correctAnswers:
- id: pymbxhyn12
answer: push()

View File

@@ -0,0 +1,31 @@
{
"name": "@freecodecamp/seed-exams",
"version": "0.0.1",
"description": "Seed certification exams questions to database",
"license": "BSD-3-Clause",
"private": true,
"engines": {
"node": ">=16",
"pnpm": "8"
},
"repository": {
"type": "git",
"url": "git+https://github.com/freeCodeCamp/freeCodeCamp.git"
},
"bugs": {
"url": "https://github.com/freeCodeCamp/freeCodeCamp/issues"
},
"homepage": "https://github.com/freeCodeCamp/freeCodeCamp#readme",
"author": "freeCodeCamp <team@freecodecamp.org>",
"main": "none",
"devDependencies": {
"dotenv": "16.3.1",
"joi": "17.9.2",
"joi-objectid": "3.0.1",
"js-yaml": "4.1.0",
"lodash": "4.17.21",
"mongodb": "5.6.0",
"nanoid": "4.0.2"
},
"type": "module"
}