How to Work on Lab Challenges
Labs are a type of challenge that presents an empty or almost empty editor to the camper, and a list of user stories to satisfy.
Lab descriptions should have this format:
[introduction]
**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.
**User Stories:**
[numbered list with all the details needed to pass the lab]
Note/Hint: (this is optional)These challenges are used to allow for practice and reinforce concepts and practice problem solving.
It can be that in the user stories there is written something that is not tested (for various reasons, including test limitations), but everything tested must be written in the user stories.
The demo projects (the code under the solution header in the markdown file) can be more involved, it should be a good example of what could be created going above and beyond the user stories. For the beginning labs, the demo projects are usually simpler, to avoid overwhelming the campers.
Labs that have a visual output (i.e. HTML-based) can have a demo project, in which case the frontmatter includes demoType: onClick. It is not mandatory, if the project design does not require it, it can be omitted.
Create the Lab
Section titled “Create the Lab”You can create the lab with pnpm run create-new-project. This opens up a command line UI that guides you through the process. Once that has finished, there should be a new challenge in the English curriculum that you can use for the first step of the project. For example, if you created a project called test-project in the Responsive Web Design certification, it would be in curriculum/challenges/english/blocks/test-project.
The script will ask the following questions:
- Which certification does this belong to? — Select the certification (e.g., Responsive Web Design). This determines which superblock the lab is added to.
- What is the dashed name (in kebab-case) for this project? — The block name in kebab-case (e.g.,
lab-building-a-card). Must be unique across all blocks. - Enter a title for this project: — The display title shown to campers. Defaults to the dashed name if left blank.
- Choose a help category — Select the most relevant category (e.g., HTML-CSS for HTML-based labs, JavaScript for JS labs).
- Choose a block label — Select
lab. (This question only appears for chapter-based certifications.) - Choose a block layout — Select
link. (This question only appears for chapter-based certifications.) - What chapter should this project go in? — Select the chapter within the certification. (Chapter-based certifications only.)
- What module should this project go in? — Select the module within the chosen chapter. (Chapter-based certifications only.)
- At which position does this appear in the module? — The position number within the module (e.g., 1 for first project). (Chapter-based certifications only.)
For non-chapter-based certifications, instead of questions 5–9, you will be asked:
- Which position does this appear in the certificate? — The position number in the certificate’s project list.
Lab File Template
Section titled “Lab File Template”Each lab is a single Markdown file. The challengeType and seed language depend on the type of lab:
challengeType | Lab type | Seed language(s) | Solution language(s) |
|---|---|---|---|
25 | HTML/CSS(/JS/JSX) | html + css, or + js, or + jsx | same combination |
26 | JavaScript | js | js |
27 | Python | py | py |
13 | Bash/SQL/etc. | no seed — runs via a CodeRoad url field | none |
saveSubmissionToDB: true is only present in cert-project labs.
Here is the template for a JavaScript lab:
---id: <ObjectId>title: Build / Implement / Design / Debug [Name]challengeType: XdashedName: lab-namedemoType: onClick---
# --description--
**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.
**User Stories:**
1. ...
# --hints--
Description of what the test checks.
```js// test code```
# --seed--
## --seed-contents--
```lang
```
# --solutions--
```lang// solution code```Hooks are optional code blocks that run at specific points during test execution. They can be used to set up shared state, install fake timers, or clean up after tests.
Hooks are supported for lab types 25, 26, and 27.
Four hooks are available:
| Hook | When it runs |
|---|---|
--before-all-- | Once, before any test runs |
--before-each-- | Before each individual test |
--after-each-- | After each individual test (in a finally block, so it always runs even if the test fails) |
--after-all-- | Once, after all tests have finished |
Execution order:
For challenges that have an HTML file, --before-all-- is injected as a <script> tag into the sandboxed iframe before the user’s HTML is parsed, so it runs before user code. It has full access to DOM APIs and global test helpers like __FakeTimers and $ (jQuery). The user’s code then renders into the page, and each test runs against the live DOM:
1. --before-all--
2. user code (evaluated once)
3. (for each test): --before-each-- → test → --after-each--
4.--after-all--For challenges that do not have an HTML file, --before-all-- runs once before any test. However, because user code is re-evaluated as part of each individual test (concatenated with --before-each-- and the test in a single eval), variables declared in --before-all-- will not be in scope during tests. To share state across tests, assign to the global object directly (e.g. globalThis.x = 1 instead of let x = 1):
1. --before-all--
2. (for each test): --before-each-- → user code → test → --after-each--
3. --after-all--Syntax:
Hooks use the same # --hook-name-- heading syntax as other sections. Each hook must contain exactly one code block. Hooks are placed after --description-- and before --hints--:
# --description--
...
# --before-all--
```js// Runs once before any test. Set up shared state here.let clock = __FakeTimers.install();```
# --before-each--
```js// Runs before each test.```
# --after-each--
```js// Runs after each test, even if it fails.```
# --after-all--
```js// Runs once after all tests. Clean up here.clock.uninstall();```
# --hints--
...Proposing a Pull Request (PR)
Section titled “Proposing a Pull Request (PR)”After you’ve committed your changes, check here for how to open a Pull Request.