This repo contains the source code for the Awesome Learning platform. These sub-folders are picked up by the CodeSandbox.io GitHub wizard and turned in to on-the-fly CodeSandbox instances.
The CodeSandbox wizard works by pulling the source code from the specified link and bootstrapping a new CodeSandbox instance with it. Check out the docs here
In the Awesome Learning platform repo, we link to the CodeSandbox git endpoint. When a user clicks the link within the session, CodeSandbox stands up an on the fly instance for them.
The CodeSandbox endpoint works by pre-pending your username and repo link with https://codesandbox.io/s/github/
. If your lesson is nested within the awesome learning exercises repo, it would look something like this.
endpoint link: `https://codesandbox.io/s/github/`
lesson deeplink: `/wayfair/awesome-learning-exercises/tree/master/data-types/types-and-equality`
combined link in the repo: `https://codesandbox.io/s/github/wayfair/awesome-learning-exercises/tree/master/data-types/types-and-equality`
Clicking on the above combined link will open the CodeSandbox with the bootstrapped code from that part of the exercises repo.
You don't have to npm install anything. This isn't meant to be used as a standalone entity.
Because this repo is meant only to be a source for CodeSandboxes, it must follow a few guidelines though -
When adding a new lesson, it should:
- Include a
package.json
at the top level of each lesson folder.- The CodeSandbox git wizard requires an accessible
package.json
when open a nested link, which all lesson links will be.
- The CodeSandbox git wizard requires an accessible
- Include all required dependencies for your particular repo in each lesson
package.json
- Include suggested solutions to all exercises
We follow the rough structure of
├── course-name
│ ├── lesson-name-1
│ ├── lesson-name-2
│ ├── etc....
This manifests as something like this:
├── array-methods
│ ├── advanced-reduce
│ ├── filter-and-map
│ ├── forEach
│ ├── reduce
│ └── sort
├── async-patterns
│ ├── advanced-promises
│ └── intro-to-promises
├── data-types
│ ├── objects
│ └── types-and-equality
├── functions-and-scope
│ ├── closures
│ ├── context-and-arrows
│ └── scope
├── testing
| ├── components-and-enzyme
| └── intro-to-unit-testing
├── readme.md
└── package.json
Within each lesson directory should be all the files required to build a working CodeSandbox instance.
NOTE: For the CodeSandbox GitHub wizard to work, you will need a package.json file at the top level of your lesson folder.
Example "types and equality" lesson under the "data-types" course directory
├── data-types
│ └── types-and-equality
│ ├── package.json
│ └── src
│ ├── exercises
│ │ └── __tests__
│ │ ├── 1-types.test.js
│ │ ├── 2-equality.test.js
│ │ └── 3-practical-types-and-equality.test.js
│ └── solutions
│ ├── 1-solution.js
│ ├── 2-solution.js
│ └── 3-solution.js
If you are relying on jest tests, test files must be contained within a __tests__
folder nested underneath a src
directory or CodeSandbox will not transpile the files correctly, and global Jest variables will not be in scope. This is a known issue for CodeSandbox and will hopefully be resolved soon.
{
"name": "awesome-learning-[course-name]-[lesson-name]",
"description": "Awesome Learning: [Course Name]: [Lesson Name] Exercises",
"dependencies": {
"jest": "24.1.0"
},
"devDependencies": {
"@types/jest": "23.3.13",
"jest": "23.6.0"
}
}
We use template strings and emojis to denote comments and directions within our lesson files
Lesson Introduction
------------------------------------------------
⬇️ = Indicates the beginning of the lesson description block
⬆️ = Indicates the end of the lesson description block
Example:
`
⬇️
Welcome to <Session Name - Blah Blah>
This will do things and other things
⬆️
`
------------------------------------------------
Exercise Description
------------------------------------------------
📚 = Brackets an exercise title
Example:
`📚 Exercise 1 - Let's write a promise 📚`
------------------------
🛠️ = Denotes the exercise task
Example:
`🛠️ Fill in the getUserBasket function below.
🛠️ This function should take a user id and resolve with
🛠️ an array of their basket items if they have any,
`
------------------------
💡 = Denotes a tip, trick, or hint
Example:
`💡 fetchBasket returns an object in this shape:
{
customerId: string,
name: string,
items: array
}
`
------------------------
🚨 = Denotes a warning, callout, something that may trip people up
Example:
`🚨 This will require you to call getUserBasket`
------------------------------------------------
Example Exercise:
------------------------------------------------
`
📚 Exercise 5 - Implement getBasketItems 📚
Now that we can fetch a basketId given a userId,
we need a way to fetch baskets.
Luckily we have a promise-based function called fetchBasket
which takes in a basketId, hits an endpoint, and returns a basket
object if one matches the basketId provided.
🛠️ Fill in the getBasketItems function below
🛠️ It should take in a basketId string,
🛠️ call the fetchBasket endpoint with basketId.
🛠️ If items exists on the response object, resolve with the items array.
🛠️ If items doesn't exist on the response object, resolve with an empty array
💡 fetchBasket returns an object in this shape:
{
customerId: string,
name: string,
items: array
}
`;
------------------------------------------------
Example File
------------------------------------------------
`
⬇️
Welcome to Async Js- Intro to promises!
This will build your knowledge of async JS -
particularly promises. You will use to two mock APIs
to mimic working with something like a fetch or AJAX call.
If you are curious about those fake APIs, feel free to
check them out in the ../api folder.
⬆️
`;
`
📚 Exercise 1 - Let's write a promise 📚
🛠️ Inside the exerciseOne block, return a new promise.
🛠️ This promise should resolve with the string
🛠️ 'promise complete!' after a delay of 100ms.
`;
const exerciseOne = () => {
// Your code here
};
test('the promise resolves with a string of "promise complete!"', () => {
return expect(exerciseOne()).resolves.toBe("promise complete!");
});
`
📚 Exercise 2 - Rejected! 📚
🛠️ Return a new promise from the exerciseTwo block.
🛠️ This promise should reject with the string
🛠️ 'promise rejected!' after a delay of 100ms.
`;
const exerciseTwo = () => {
// Your code here
};
test('the promise rejects with a string of "promise rejected!"', () => {
expect.assertions(1);
return expect(exerciseTwo()).rejects.toMatch("promise rejected!");
});