Skip to content

Commit 11620bb

Browse files
committed
chore: update docs to latest node v18 practices
1 parent 29e9cb1 commit 11620bb

4 files changed

Lines changed: 138 additions & 98 deletions

File tree

docs/technologies/html-css.md

Lines changed: 112 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,24 @@ Since we have already written a pure evaluation script that runs and finally wri
8888
The full path of the script is made available at run-time with another environment variable called `TEST_FILE_NAME`. Therefore, all we have to do is write the following in the evaluation script area:
8989

9090
```sh
91-
node $TEST_FILE_NAME
91+
#!/bin/bash
92+
set -e 1
93+
94+
mkdir -p /home/damner/code/.labtests
95+
96+
cat > /home/damner/code/.labtests/package.json << EOF
97+
{
98+
"type": "module"
99+
}
100+
EOF
101+
102+
cd /home/damner/code/.labtests
103+
mv $TEST_FILE_NAME ./nodecheck.test.js
104+
105+
# import puppeteer doesn't work without it
106+
npm link puppeteer
107+
108+
node nodecheck.test.js 2>&1 | tee evaluationscript.log
92109
```
93110

94111
This will make sure we run the full Node.js script and write the results properly for the playground IDE to read. It would look like the following:
@@ -117,86 +134,109 @@ The moment you select the Node.js (Puppeteer), the following code should appear
117134

118135
```js
119136
// !! Boilerplate code starts
120-
const fs = require('fs')
121-
const puppeteer = require('puppeteer')
122-
123-
async function run() {
124-
// results is a boolean[] that maps challenge results shown to user
125-
const results = []
126-
127-
// launch the headless browser for testing
128-
const browser = await puppeteer.launch({
129-
executablePath: '/usr/bin/google-chrome',
130-
headless: true,
131-
args: [
132-
'--no-sandbox',
133-
'--disable-setuid-sandbox',
134-
'--disable-dev-shm-usage',
135-
'--disable-accelerated-2d-canvas',
136-
'--no-first-run',
137-
'--no-zygote',
138-
'--single-process',
139-
'--disable-gpu',
140-
],
141-
})
142-
page = await browser.newPage()
137+
import fs from 'node:fs'
138+
import puppeteer from 'puppeteer'
139+
140+
// testlog is a log of test results
141+
const testlog = []
142+
143+
// launch the headless browser for testing
144+
const browser = await puppeteer.launch({
145+
executablePath: '/usr/bin/google-chrome',
146+
headless: true,
147+
args: [
148+
'--no-sandbox',
149+
'--disable-setuid-sandbox',
150+
'--disable-dev-shm-usage',
151+
'--disable-accelerated-2d-canvas',
152+
'--no-first-run',
153+
'--no-zygote',
154+
'--single-process',
155+
'--disable-gpu',
156+
],
157+
})
158+
const page = await browser.newPage()
159+
160+
// wait for server to come online
161+
await page.goto('http://localhost:1337')
162+
163+
// add jQuery and chai for unit testing support if you want
164+
await Promise.all([
165+
page.addScriptTag({
166+
url: 'https://code.jquery.com/jquery-3.5.1.slim.min.js',
167+
}),
168+
page.addScriptTag({
169+
url: 'https://cdnjs.cloudflare.com/ajax/libs/chai/4.2.0/chai.min.js',
170+
}),
171+
])
172+
173+
// add chai-dom
174+
await page.addScriptTag({
175+
url: 'https://cdn.jsdelivr.net/npm/chai-dom@1.11.0/chai-dom.min.js',
176+
})
143177

144-
// wait for server to come online
145-
await page.goto('http://localhost:1337')
178+
// !! Boilerplate code ends
146179

147-
// add jQuery and chai for unit testing support if you want
148-
await Promise.all([
149-
page.addScriptTag({
150-
url: 'https://code.jquery.com/jquery-3.5.1.slim.min.js',
151-
}),
152-
page.addScriptTag({
153-
url: 'https://cdnjs.cloudflare.com/ajax/libs/chai/4.2.0/chai.min.js',
154-
}),
155-
])
180+
// Start your tests here in individual try-catch block
156181

157-
// !! Boilerplate code ends
182+
{
183+
const result = await page.evaluate(async () => {
184+
const { expect } = window.chai
185+
try {
186+
expect(
187+
document.body.innerHTML.toLowerCase().includes('hello world')
188+
).to.be.true
189+
return { status: 'pass' }
190+
} catch (error) {
191+
return {
192+
status: 'error',
193+
error: error.message || 'Challenge failed',
194+
}
195+
}
196+
})
158197

159-
// Start your tests here in individual try-catch block
198+
testlog.push(result)
199+
}
160200

161-
try {
162-
await page.evaluate(async () => {
163-
const assert = window.chai.assert
164-
assert(
165-
document.body.innerHTML.toLowerCase().includes('hello world')
166-
)
167-
})
168-
console.log('Test #1 passed!')
169-
results.push(true)
170-
} catch (error) {
171-
console.log('Test #1 failed! Did you do <this>?')
172-
results.push(false)
173-
}
174-
175-
try {
176-
await page.evaluate(async () => {
177-
const assert = window.chai.assert
178-
assert(
201+
{
202+
const result = await page.evaluate(async () => {
203+
const { expect } = window.chai
204+
try {
205+
expect(
179206
document.body.innerHTML
180207
.toLowerCase()
181208
.includes('hello world again')
182-
)
183-
})
184-
console.log('Test #1 passed!')
185-
results.push(true)
186-
} catch (error) {
187-
console.log('Test #1 failed! Did you do <this>?')
188-
results.push(false)
189-
}
190-
191-
// End your tests here
192-
fs.writeFileSync(process.env.UNIT_TEST_OUTPUT_FILE, JSON.stringify(results))
193-
await browser.close().catch((err) => {})
194-
195-
// Exit the process
196-
process.exit(0)
209+
).to.be.true
210+
return { status: 'pass' }
211+
} catch (error) {
212+
return {
213+
status: 'error',
214+
error: error.message || 'Challenge failed',
215+
}
216+
}
217+
})
218+
219+
testlog.push(result)
197220
}
198-
run()
199-
// !! Boilerplate code ends
221+
222+
// very important for the final length of \`testlog\` array to match the number of challenges, in this case - 2.
223+
224+
// write the test log
225+
fs.writeFileSync(
226+
'/home/damner/code/.labtests/testlog.json',
227+
JSON.stringify(testlog)
228+
)
229+
230+
// write the results array boolean. this will map to passed or failed challenges depending on the boolean value at the challenge index
231+
fs.writeFileSync(
232+
process.env.UNIT_TEST_OUTPUT_FILE,
233+
JSON.stringify(testlog.map((result) => result.status === 'pass'))
234+
)
235+
236+
await browser.close().catch((err) => {})
237+
238+
// Exit the process
239+
process.exit(0)
200240
```
201241

202242
Let us understand what is happening here exactly:

docs/technologies/node.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,15 @@ set -e 1
106106
# Install vitest and testing util
107107
cd /home/damner/code
108108
yarn add vite@3 vitest@0.22.1 --dev
109-
mkdir -p /home/damner/code/__labtests
109+
mkdir -p /home/damner/code/.labtests
110110

111111
# Move test file
112-
mv $TEST_FILE_NAME /home/damner/code/__labtests/nodecheck.test.js
112+
mv $TEST_FILE_NAME /home/damner/code/.labtests/nodecheck.test.js
113113

114114
# setup file
115115

116116
# vitest config file
117-
cat > /home/damner/code/__labtests/config.js << EOF
117+
cat > /home/damner/code/.labtests/config.js << EOF
118118
import { defineConfig } from 'vite'
119119
export default defineConfig({
120120
plugins: [],
@@ -125,25 +125,25 @@ export default defineConfig({
125125
EOF
126126

127127
# process.js file
128-
cat > /home/damner/code/__labtests/process.js << EOF
128+
cat > /home/damner/code/.labtests/process.js << EOF
129129
const fs = require('fs')
130130
const payload = require('./payload.json')
131131
const answers = payload.testResults[0].assertionResults.map(test => test.status === 'passed')
132132
fs.writeFileSync(process.env.UNIT_TEST_OUTPUT_FILE, JSON.stringify(answers))
133133
EOF
134134

135135
# run test
136-
yarn vitest run --config=/home/damner/code/__labtests/config.js --threads=false --reporter=json --outputFile=/home/damner/code/__labtests/payload.json || true
136+
yarn vitest run --config=/home/damner/code/.labtests/config.js --threads=false --reporter=json --outputFile=/home/damner/code/.labtests/payload.json || true
137137

138138

139139
# Write results to UNIT_TEST_OUTPUT_FILE to communicate to frontend
140-
node /home/damner/code/__labtests/process.js
140+
node /home/damner/code/.labtests/process.js
141141
```
142142

143143
Let's understand what the above evaluation script is doing:
144144

145145
- We navigate to users' default code directory and install `vitest` and `vite`. We do this because we'll use `vitest` as the test runner.
146-
- We then move the cloned test file (more on this in the next step) inside `__labtests` folder. This folder is hidden from the user in the GUI while test is running.
146+
- We then move the cloned test file (more on this in the next step) inside `.labtests` folder. This folder is hidden from the user in the GUI while test is running.
147147
- We create a custom configuration for vite which would be read by vitest for testing.
148148
- We then create a `process.js` file that would read the results written by vitest and process them to write them on a file inside `$UNIT_TEST_OUTPUT_FILE` environment variable. This is important because this file is read by the playground to evaluate whether the challenges passed or failed.
149149
- Whatever your mapping of final JSON boolean array written in `process.env.UNIT_TEST_OUTPUT_FILE` is, it is matched exactly to the results on the playground. For example, if the array written is `[true, false, true, true]`, the following would be the output on playground:

docs/technologies/python-pytest.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,13 @@ Therefore, your testing script would look like as follows:
126126
#!/bin/bash
127127
set -e 1
128128

129-
mkdir -p /home/damner/code/__labtests
129+
mkdir -p /home/damner/code/.labtests
130130

131-
mv $TEST_FILE_NAME /home/damner/code/__labtests/pytest.py
132-
echo "" > /home/damner/code/__labtests/__init__.py
131+
mv $TEST_FILE_NAME /home/damner/code/.labtests/pytest.py
132+
echo "" > /home/damner/code/.labtests/__init__.py
133133

134134
# run test
135-
cd /home/damner/code/__labtests
135+
cd /home/damner/code/.labtests
136136
pytest --json-report pytest.py || true
137137

138138
# process results file
@@ -145,16 +145,16 @@ EOF
145145

146146

147147
# Write results to UNIT_TEST_OUTPUT_FILE to communicate to frontend
148-
node /home/damner/code/__labtests/processPythonResults.js
148+
node /home/damner/code/.labtests/processPythonResults.js
149149
```
150150

151151
You might need to have a little understanding of bash scripting. Let us understand how the evaluation bash script is working:
152152

153153
- With `set -e 1` we effectively say that the script should stop on any errors
154154
- You can install additional packages here if you want. They would only be installed the first time user runs the test. On subsequent runs, it can reuse the installed packages (since they are not removed at the end of testing)
155-
- Then we create a `__labtests` folder inside of the `/home/damner/code` user code directory. Note that `__labtests` is a special folder that can be used to place your test code. This folder will not be visible in the file explorer user sees, and the files placed in this folder are not "backed up to cloud" for user.
156-
- We move the test file you wrote earlier (in last step) to `/home/damner/code/__labtests/pytest.py`.
157-
- We then create another setup file `/home/damner/code/__labtests/processPythonResults.js`. This is because we need to parse the results outputted by the Python testing utility to reflect it on the playgrounds. You may as well create this file in python (reading the JSON report and outputting a boolean array in a file stored in env `$UNIT_TEST_OUTPUT_FILE`)
155+
- Then we create a `.labtests` folder inside of the `/home/damner/code` user code directory. Note that `.labtests` is a special folder that can be used to place your test code. This folder will not be visible in the file explorer user sees, and the files placed in this folder are not "backed up to cloud" for user.
156+
- We move the test file you wrote earlier (in last step) to `/home/damner/code/.labtests/pytest.py`.
157+
- We then create another setup file `/home/damner/code/.labtests/processPythonResults.js`. This is because we need to parse the results outputted by the Python testing utility to reflect it on the playgrounds. You may as well create this file in python (reading the JSON report and outputting a boolean array in a file stored in env `$UNIT_TEST_OUTPUT_FILE`)
158158
- This is important because on the playground page, the way challenges work, is that they get green or red based on a JSON boolean array written inside the file in environment variable: `$UNIT_TEST_OUTPUT_FILE`
159159
- For example, once the test run succeeds, and if you write `[true,false,true,true]` inside `$UNIT_TEST_OUTPUT_FILE`, it would reflect as PASS, FAIL, PASS for 3 challenges available inside codedamn playground UI (as shown below)
160160

docs/technologies/react.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -154,18 +154,18 @@ set -e 1
154154
# Install vitest and testing util
155155
cd /home/damner/code
156156
yarn add vitest@0.22.1 jsdom@20.0.0 @testing-library/jest-dom@5.16.4 @testing-library/react@13.3.0 --dev
157-
mkdir -p /home/damner/code/__labtests
157+
mkdir -p /home/damner/code/.labtests
158158

159159
# Move test file
160-
mv $TEST_FILE_NAME /home/damner/code/__labtests/reactcheck.test.jsx
160+
mv $TEST_FILE_NAME /home/damner/code/.labtests/reactcheck.test.jsx
161161

162162
# setup file
163-
cat > /home/damner/code/__labtests/setup.js << EOF
163+
cat > /home/damner/code/.labtests/setup.js << EOF
164164
import '@testing-library/jest-dom'
165165
EOF
166166

167167
# vitest config file
168-
cat > /home/damner/code/__labtests/config.js << EOF
168+
cat > /home/damner/code/.labtests/config.js << EOF
169169
import { defineConfig } from 'vite'
170170
import react from '@vitejs/plugin-react'
171171
@@ -175,13 +175,13 @@ export default defineConfig({
175175
test: {
176176
globals: true,
177177
environment: 'jsdom',
178-
setupFiles: '/home/damner/code/__labtests/setup.js',
178+
setupFiles: '/home/damner/code/.labtests/setup.js',
179179
}
180180
})
181181
EOF
182182

183183
# process.js file
184-
cat > /home/damner/code/__labtests/process.js << EOF
184+
cat > /home/damner/code/.labtests/process.js << EOF
185185
const fs = require('fs')
186186
const payload = require('./payload.json')
187187
const answers = payload.testResults[0].assertionResults.map(test => test.status === 'passed')
@@ -190,20 +190,20 @@ fs.writeFileSync(process.env.UNIT_TEST_OUTPUT_FILE, JSON.stringify(answers))
190190
EOF
191191

192192
# run test
193-
yarn vitest run --config=/home/damner/code/__labtests/config.js --threads=false --reporter=json --outputFile=/home/damner/code/__labtests/payload.json || true
193+
yarn vitest run --config=/home/damner/code/.labtests/config.js --threads=false --reporter=json --outputFile=/home/damner/code/.labtests/payload.json || true
194194

195195
# Write results to UNIT_TEST_OUTPUT_FILE to communicate to frontend
196-
node /home/damner/code/__labtests/process.js
196+
node /home/damner/code/.labtests/process.js
197197
```
198198

199199
You might need to have a little understanding of bash scripting. Let us understand how the evaluation bash script is working:
200200

201201
- With `set -e 1` we effectively say that the script should stop on any errors
202202
- We then navigate to user default directory `/home/damner/code` and then install the required NPM packages. Note that this assumes we already have `vite` installed. If you're using a different react setup (like `create-react-app`), you might have to install `vite` as well.
203203
- You can install additional packages here if you want. They would only be installed the first time user runs the test. On subsequent runs, it can reuse the installed packages (since they are not removed at the end of testing)
204-
- Then we create a `__labtests` folder inside of the `/home/damner/code` user code directory. Note that `__labtests` is a special folder that can be used to place your test code. This folder will not be visible in the file explorer user sees, and the files placed in this folder are not "backed up to cloud" for user.
205-
- We move the test file you wrote earlier (in last step) to `/home/damner/code/__labtests/reactcheck.test.jsx`. Note that it is important to give it an extension of `.test.jsx` for vitest to pick it as a JSX test file.
206-
- We then create another setup file `/home/damner/code/__labtests/setup.js` with just `jsdom` as the import. This is because vitest can then use JSDOM to parse the DOM without browser. More information about this [setup file can be found in vitest docs here](https://vitest.dev/config/#setupfiles).
204+
- Then we create a `.labtests` folder inside of the `/home/damner/code` user code directory. Note that `.labtests` is a special folder that can be used to place your test code. This folder will not be visible in the file explorer user sees, and the files placed in this folder are not "backed up to cloud" for user.
205+
- We move the test file you wrote earlier (in last step) to `/home/damner/code/.labtests/reactcheck.test.jsx`. Note that it is important to give it an extension of `.test.jsx` for vitest to pick it as a JSX test file.
206+
- We then create another setup file `/home/damner/code/.labtests/setup.js` with just `jsdom` as the import. This is because vitest can then use JSDOM to parse the DOM without browser. More information about this [setup file can be found in vitest docs here](https://vitest.dev/config/#setupfiles).
207207
- We then also create a custom vite config file as `config.js`. This is because we don't want to override your (or users') custom `vite.config.js` file if present. This file only loads `jsdom` and marks the `globals: true` hence importing `describe`, `test`, etc. automatically available without importing. More information about the configuration can be found here in [vitest docs](https://vitest.dev/config/#globals).
208208
- We then create a `process.js` file that can be used to process our results into a single file of boolean values. This is important because on the playground page, the way challenges work, is that they get green or red based on a JSON boolean array written inside the file in environment variable: `$UNIT_TEST_OUTPUT_FILE`
209209
- For example, once the test run succeeds, and if you write `[true,false,true,true]` inside `$UNIT_TEST_OUTPUT_FILE`, it would reflect as PASS, FAIL, PASS for 3 challenges available inside codedamn playground UI (as shown below)

0 commit comments

Comments
 (0)