You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/src/modules/4-advanced/linting.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,6 +3,7 @@ order: 2
3
3
---
4
4
5
5
# Code Formatting and Linting
6
+
6
7
Code linting is the process of conducting static analysis on code to detect potential runtime issues and enforce
7
8
stylistic conventions. Linting for the repository is provided by [ESLint](https://eslint.org).
8
9
@@ -11,31 +12,38 @@ stylistic conventions. Linting for the repository is provided by [ESLint](https:
11
12
> removed from the Modules repository.
12
13
13
14
## Running ESLint
15
+
14
16
ESLint can be run on its own on your bundle/tab code by using either of the following commands:
17
+
15
18
```sh
16
19
yarn lint
17
20
yarn buildtools lint .
18
21
```
19
22
20
23
If you wish to run ESLint during the build process, you can instead use:
24
+
21
25
```sh
22
26
yarn build --lint
23
27
yarn buildtools build <bundle|tab>. --lint
24
28
```
25
29
26
30
## Disabling ESLint Rules
31
+
27
32
If, for whatever reason you need to disable a specific ESLint rule for your bundle/tab, you can use the `// eslint-disable` directive. Please provide a short explanation on why
28
33
the rule needs to be disabled, following the example provided below:
34
+
29
35
```tsx
30
36
import { Button } from'@blueprintjs/core';
31
37
// eslint-disable @typescript-eslint/no-var-requires This import doesn't work if written using ESM
32
38
const TextBox =require('Textbox').default
33
39
```
34
40
35
41
## Ignoring Files
42
+
36
43
By default, ESLint has been configured to not lint files in specific directories or matching specific patterns. You can see the ignore patterns in `eslint.config.js` under the section labelled "Global Ignores". Please
37
44
note that if any of your code files matche these ignore patterns, they will not be properly linted by ESLint.
38
45
39
46
## Integration with Git Hooks
47
+
40
48
Linting is run during the pre-push hook and also on pull-requests. Your code must not have any lint errors in order to be pushed to the
41
49
branch and can have neither errors nor warnings to be merged.
Copy file name to clipboardExpand all lines: docs/src/modules/4-advanced/testing.md
+30-1Lines changed: 30 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ The testing library used by this repository is [`vitest`](https://vitest.dev).
8
8
> [!IMPORTANT]
9
9
> Other Source Academy repositories use `jest` as their testing package. Although `vitest` has been designed as a drop in replacement for `jest`,
10
10
> there are subtle differences between the two. For example, `vi.spyOn` doesn't replace the implementation within the module while `jest.spyOn` does (See [here](https://vitest.dev/guide/mocking.html#mocking-pitfalls)).
11
-
>
11
+
>
12
12
> Refer to [this page](https://vitest.dev/guide/migration.html#jest) for more differences between `jest` and `vitest`.
13
13
14
14
## Adding Tests
@@ -17,6 +17,7 @@ By default, any Typescript (`.ts`) files located within a `__tests__` folder are
17
17
detect any tests within that file, it will throw an error. This also includes any subdirectories under a `__tests__` folder.
18
18
19
19
Simply write your tests within a `__tests__` folder:
20
+
20
21
```ts
21
22
// curve/src/__tests__/index.ts
22
23
import { describe, expect, test } from'vitest'; // You will need to import these functions, unlike in Jest
@@ -33,6 +34,7 @@ describe('This is a describe block', () => {
33
34
> Javascript and Typescript declarations but will still conduct type checking for them.
34
35
35
36
Tests for tabs can also use the `.tsx` extension along with JSX syntax:
37
+
36
38
```tsx
37
39
// Curve/__tests__/index.tsx
38
40
import { expect, test } from'vitest';
@@ -52,16 +54,19 @@ For more instructions on how to write tests you can refer to the [Vitest website
52
54
53
55
While writing tests, you might find that you might want to focus on a single test or single group of tests. For this, `vitest` provides on its `test`, `it` and `describe` functions
54
56
a `.skip` and a `.only` property:
57
+
55
58
```ts
56
59
describe('Test1 and Test3 will run!', () => {
57
60
test('Test1', () => {});
58
61
test.skip('Test2', () => {});
59
62
test('Test3', () => {})
60
63
});
61
64
```
65
+
62
66
You don't have to comment out your tests; simply use `.skip` to indicate that a test block should not be executed.
63
67
64
68
If for some reason you want to skip your tests based on some condition, `vitest` provides the `skipIf` property:
69
+
65
70
```ts
66
71
describe('Test1 and Test3 will run!', () => {
67
72
test('Test1', () => {});
@@ -71,13 +76,15 @@ describe('Test1 and Test3 will run!', () => {
71
76
```
72
77
73
78
`.only` is kind of the reverse of `.skip`. Tests that you use `.only` with will be the **only** tests that run in that file:
79
+
74
80
```ts
75
81
describe('Only Test 2 will run!', () => {
76
82
test('Test1', () => {});
77
83
test.only('Test2', () => {});
78
84
test('Test3', () => {})
79
85
});
80
86
```
87
+
81
88
The main runner that runs unit tests on the CI/CD pipeline does not allow for `.only`. You can simulate this behaviour by running your tests with the
82
89
`--no-allow-only` flag. This behaviour is intended to prevent you from causing only part of your tests to run.
83
90
@@ -86,12 +93,14 @@ The main runner that runs unit tests on the CI/CD pipeline does not allow for `.
86
93
> to remove `.only` before pushing to the main repository.
87
94
88
95
Pushing with skipped tests however, is allowed. Do leave a comment explaining why the test is skipped:
96
+
89
97
```ts
90
98
// Test is skipped because there is an outstanding bug
91
99
test.skip('Test path resolution', () => {})
92
100
```
93
101
94
102
### Stubbing Tests
103
+
95
104
If you want to indicate that tests should be written for certain functionality in the future, you can use `.todo`:
> [vitest] Vite unexpectedly reloaded a test. This may cause tests to fail, lead to flaky behaviour or duplicated test runs.
145
160
> For a stable experience, please add mentioned dependencies to your config's `optimizeDeps.include` field manually.
146
161
> ```
162
+
>
147
163
> If this warning appears when you run your tests on the machine, you may find that your tests may still pass on the local machine, but
148
164
> fail on the CI pipeline.
149
165
>
150
166
> This is because you have a dependency that Vite can only detect at runtime and so has to run its internal transforms twice. This causes
151
167
> Vitest to fail, since the original import would have failed. To fix this, you should create your own `vitest.config.js` and add those
152
168
> dependencies to `optimizeDeps`:
169
+
>
153
170
> ```js
154
171
> export default defineProject({
155
172
> optimizeDeps: {
@@ -160,13 +177,15 @@ written in plain Javascript with a <nobr><code>// @ts-check</code></nobr> direct
160
177
> }
161
178
> })
162
179
> ```
180
+
>
163
181
> For more information, refer to the [Vite](https://vite.dev/config/dep-optimization-options.html#optimizedeps-include) documentation.
164
182
165
183
Should you need to use a unique configuration, simply create your own `vitest.config.js` at the root of your bundle/tab.
166
184
The configuration options in your `vitest.config.js` will be used **in addition** to the default options, so it is not necessary
167
185
to redefine every single option in your configuration file.
168
186
169
187
You should use the `defineProject` helper instead of the `defineConfig` helper:
188
+
170
189
```js [vitest.config.js]
171
190
// @ts-check
172
191
import { defineProject } from 'vitest/config';
@@ -183,13 +202,15 @@ There is no need to use `mergeConfig` to merge your configuration with the root
183
202
the merging is performed automatically.
184
203
185
204
## Browser Mode
205
+
186
206
Tabs have the ability to leverage `playwright` and `vitest`'s browser mode to ensure that the interactive features of the tab actually
187
207
behave like they should.
188
208
189
209
The default testing configuration for tabs has browser mode disabled. This is so that if your tab doesn't need the features that Playwright provides,
190
210
`vitest` won't need to spin up the Playwright instance.
191
211
192
212
### Setting up Browser Mode
213
+
193
214
Should you wish to enable browser mode, create a custom `vitest` configuration file for your tab with the `browswer.enabled` option set to `true`:
194
215
195
216
```js {9}
@@ -214,13 +235,15 @@ Now, the tests for your tab will be run in browser mode.
214
235
> add more instances if necessary.
215
236
216
237
### Writing Interactive Tests
238
+
217
239
Writing interactive tests is not very different from writing regular tests. Most of the time, the usual test and assertion functions will suffice.
218
240
219
241
> [!INFO]
220
242
> While writing your tests, you should use watch mode. This will allow `vitest` to open a browser and actually display what your tab looks like whilst
221
243
> being rendered during the test.
222
244
223
245
Use the `render`functionprovided`vitest-browser-react` to render your tab/component to a screen. The returned component can then be interacted with:
246
+
224
247
```tsx
225
248
import { render } from 'vitest-browser-react';
226
249
@@ -233,13 +256,15 @@ test('Testing my component', () => {
233
256
expect().somethingToHaveHappened();
234
257
});
235
258
```
259
+
236
260
`vitest` also provides [a different set](https://vitest.dev/guide/browser/assertion-api.html) of matchers that you can use specifically with browser elements.
237
261
238
262
> [!TIP]
239
263
>`vitest-browser-react` also provides a `cleanup`functionthat can be used after each test. You don't _technically_ need to use it, but
240
264
> you may find that if you have multiple tests in the same file that behaviour might be inconsistent.
241
265
>
242
266
> You can use it with `afterEach` from `vitest`:
267
+
>
243
268
> ```ts
244
269
> import { afterEach } from 'vitest';
245
270
> import { cleanup } from 'vitest-browser-react';
@@ -248,6 +273,7 @@ test('Testing my component', () => {
248
273
> ```
249
274
250
275
### `expect.poll` and `expect.element`
276
+
251
277
Sometimes, visual elements take a while to finish or an element might take a while to load. If you just directly used an assertion, the assertion
252
278
might fail because the element hasn't displayed yet:
The `mqtt` dependency however, is specified as such in `package.json`:
23
+
20
24
```json
21
25
{
22
26
"dependencies": {
@@ -25,6 +29,7 @@ The `mqtt` dependency however, is specified as such in `package.json`:
25
29
}
26
30
}
27
31
```
32
+
28
33
The helpful comment below the import explains the discrepancy. Without further configuration, we find that Typescript is unable to find the types for the `mqtt/dist/mqtt` package:
Copy file name to clipboardExpand all lines: docs/src/repotools/linting.md
+3Lines changed: 3 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,6 +4,7 @@ The ESLint config file for this repository is fairly complex. The different conf
4
4
You can refer to [this](https://eslint.org/docs/latest/use/configure/configuration-files) page for more information on how ESLint processes these configuration objects.
5
5
6
6
Generally, there are two types of linting rules:
7
+
7
8
1. Repository only code (used for development of modules)
8
9
2. Module code (Code that is actually intended to be used in Source)
9
10
@@ -14,6 +15,7 @@ ESLint does provide a configuration inspector which can be started using <nobr>`
14
15
and also other information like what rules are considered deprecated.
15
16
16
17
## Configuration Conventions
18
+
17
19
Our linting configurations often inherit from recommended configurations provided by plugins. However, not all of the rules that are configured by these configurations make sense
18
20
for the repository at large. This requires that we manually override some of the settings provided by these configurations.
19
21
@@ -36,6 +38,7 @@ are usually incomplete snippets of Typescript/Javascript, so a lot of the typica
36
38
-->
37
39
38
40
## Linting JSON Files
41
+
39
42
For the most part, there are only stylistic rules that need to be applied to JSON files. This is why this repository doesn't use the official `@eslint/json` package for linting JSON files.
40
43
Instead. the parser from `eslint-plugin-json` is used so that stylistic rules can be applied to the JSON files. This does mean that none of the rules from `@eslint/json` can be applied
This page is dedicated to explaining all the VSCode integrations available from this repository.
3
4
4
5
Since most developers here are assumed to be using Visual Studio Code, this repository automatically provides some extra tooling that integrates with VSCode, all found within the `.vscode` folder.
5
6
6
7
## JSON Schemas
8
+
7
9
By default, VSCode doesn't apply any kind of validation to JSON files that don't have explicit schemas. Using the `settings.json` file, we can apply JSON schemas to specific JSON files.
8
10
9
11
For this repository, this has been configured for `tsconfig.*.json` files to extend both the original `tsconfig` schema, but also to include the Typedoc schema. Bundle manifest files
10
12
should also automatically receive validation and IntelliSense autocompletion.
11
13
12
14
## ESLint Validation
15
+
13
16
By default, the VSCode ESLint extension doesn't also lint YAML files. This means that although ESLint will lint YAML files, the linting warnings and errors
14
17
for YAML files will not appear in VSCode. Thus, we need to provide a specific configuration to tell the extension to lint YAML files.
0 commit comments