Skip to content

Commit 716713b

Browse files
authored
feat: add examples for jest and jest+typescript (#115)
Adds jest examples
1 parent 3d71fa6 commit 716713b

File tree

18 files changed

+589
-12
lines changed

18 files changed

+589
-12
lines changed

Diff for: .github/workflows/ci.yml

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ jobs:
2424
- helia-cjs
2525
- helia-electron
2626
- helia-esbuild
27+
- helia-jest
28+
- helia-jest-typescript
2729
- helia-nestjs
2830
- helia-nextjs
2931
- helia-parcel
@@ -85,6 +87,8 @@ jobs:
8587
- helia-cjs
8688
- helia-electron
8789
- helia-esbuild
90+
- helia-jest
91+
- helia-jest-typescript
8892
- helia-nestjs
8993
- helia-parcel
9094
- helia-nextjs

Diff for: README.md

+16-10
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
- [Basics](#basics)
2828
- [Frameworks](#frameworks)
2929
- [Bundlers](#bundlers)
30+
- [Testing](#testing)
3031
- [Other tooling](#other-tooling)
3132
- [Prerequisites](#prerequisites)
3233
- [IPFS Tutorials at ProtoSchool](#ipfs-tutorials-at-protoschool)
@@ -57,21 +58,26 @@ Feel free to jump directly into the examples, however going through the followin
5758

5859
- [Helia-101](/examples/helia-101/): Spawn a Helia node, add a file and cat the file
5960
- [Helia CommonJS](/examples/helia-cjs/): Just like Helia-101, but with [CommonJS](https://en.wikipedia.org/wiki/CommonJS) instead of [ESM](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)
60-
- [Helia via CDNs](/examples/helia-script-tag/): A simple proof-of-concept to distributing and using helia using `<script>` tags
61-
- [Creating a CAR file with Helia](/examples/helia-create-car/): An example showing how to create a car file with helia. CAR files are useful for making filecion deals.
61+
- [Helia via CDNs](/examples/helia-script-tag/): A simple proof-of-concept to distributing and using Helia using `<script>` tags
62+
- [Creating a CAR file with Helia](/examples/helia-create-car/): An example showing how to create a car file with Helia. CAR files are useful for making filecion deals.
6263

6364
#### Frameworks
6465

65-
- [Helia with Electron](/examples/helia-electron/): Create an Electron app with helia
66-
- [Helia with Next.js](/examples/helia-nextjs/): Create a Next.js app with helia
67-
- [Helia with NestJS](/examples/helia-nestjs/): Create a NestJS app with helia
68-
- [Helia with Vue](/examples/helia-vue/): Create a vue app with helia
69-
- [Helia with Vite](/examples/helia-vite/): Create a react+vite app with helia
66+
- [Helia with Electron](/examples/helia-electron/): Create an Electron app with Helia
67+
- [Helia with Next.js](/examples/helia-nextjs/): Create a Next.js app with Helia
68+
- [Helia with NestJS](/examples/helia-nestjs/): Create a NestJS app with Helia
69+
- [Helia with Vue](/examples/helia-vue/): Create a vue app with Helia
70+
- [Helia with Vite](/examples/helia-vite/): Create a react+vite app with Helia
7071

7172
#### Bundlers
7273

73-
- [Helia with esbuild](/examples/helia-esbuild/): Bundle helia with esbuild
74-
- [Helia with Webpack](/examples/helia-webpack/): Bundle helia with webpack
74+
- [Helia with esbuild](/examples/helia-esbuild/): Bundle Helia with esbuild
75+
- [Helia with Webpack](/examples/helia-webpack/): Bundle Helia with webpack
76+
77+
#### Testing
78+
79+
- [Helia with Jest](/examples/helia-jest/): Test Helia with Jest
80+
- [Helia with Jest and TypeScript](/examples/helia-jest-typescript/): Test Helia with Jest and TypeScript
7581

7682
#### Other tooling
7783

@@ -145,7 +151,7 @@ Search `.github/workflows/test.yml` for the `test-examples` section and add a bl
145151
deps: helia@$PWD/packages/helia/dist
146152
```
147153
148-
The value of the `deps` key will vary depending on which modules from helia your example uses. Above we override the `helia` module, but your example may different deps.
154+
The value of the `deps` key will vary depending on which modules from Helia your example uses. Above we override the `helia` module, but your example may different deps.
149155

150156
Please see the existing setup in `.github/workflows/test.yml` for how to ensure you are overriding the correct modules.
151157

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# ⚠️ IMPORTANT ⚠️
2+
3+
# Please do not create a Pull Request for this repository
4+
5+
The contents of this repository are automatically synced from the parent [Helia Examples Project](https://github.com/ipfs-examples/helia-examples) so any changes made to the standalone repository will be lost after the next sync.
6+
7+
Please open a PR against [IPFS Examples](https://github.com/ipfs-examples/helia-examples) instead.
8+
9+
## Contributing
10+
11+
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.
12+
13+
1. Fork the [Helia Examples Project](https://github.com/ipfs-examples/helia-examples)
14+
2. Create your Feature Branch (`git checkout -b feature/amazing-example`)
15+
3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`)
16+
4. Push to the Branch (`git push origin feature/amazing-example`)
17+
5. Open a Pull Request
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: pull
2+
3+
on:
4+
workflow_dispatch
5+
6+
jobs:
7+
sync:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v2
11+
- name: Pull from another repository
12+
uses: ipfs-examples/actions-pull-directory-from-repo@main
13+
with:
14+
source-repo: ipfs-examples/helia-examples
15+
source-folder-path: examples/${{ github.event.repository.name }}
16+
source-branch: main
17+
target-branch: main
18+
git-username: github-actions
19+
git-email: github-actions@github.com

Diff for: examples/helia-jest-typescript/README.md

+230
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
<p align="center">
2+
<a href="https://github.com/ipfs/helia" title="Helia">
3+
<img src="https://raw.githubusercontent.com/ipfs/helia/main/assets/helia.png" alt="Helia logo" width="300" />
4+
</a>
5+
</p>
6+
7+
<h3 align="center"><b>Test Helia with Jest and TypeScript</b></h3>
8+
9+
<p align="center">
10+
<img src="https://raw.githubusercontent.com/jlord/forkngo/gh-pages/badges/cobalt.png" width="200">
11+
<br>
12+
<a href="https://ipfs.github.io/helia/modules/helia.html">Explore the docs</a>
13+
·
14+
<a href="https://github.com/ipfs-examples/helia-examples/issues">Report Bug</a>
15+
·
16+
<a href="https://github.com/ipfs-examples/helia-examples/issues">Request Feature/Example</a>
17+
</p>
18+
19+
## About
20+
21+
[Jest](https://jestjs.io/) is a JavaScript testing framework that transpiles code on the fly to enable a fast-feedback testing cycle for the developer.
22+
23+
It is typically used to test browser code, whereby it injects an artificial DOM implementation into the global scope to enable running the actual tests on [Node.js](https://nodejs.org) to take advantage of faster startup times at the cost of not always having 100% feature/behavior parity with the actual target platform.
24+
25+
In some circumstances this is helpful but it can also result in hard to debug errors, particularly around resolving modules and loading them.
26+
27+
Some developers also use Jest to test pure Node.js code which the benefit of familiarity but also has the same issues around transpilation.
28+
29+
Adding [TypeScript](https://www.typescriptlang.org/) into the mix adds another layer of misdirection so the error messages are more cryptic than just running plain JS.
30+
31+
```
32+
Cannot find module 'helia' from '../src/index.ts'
33+
34+
Require stack:
35+
/path/to/project/src/index.ts
36+
index.spec.ts
37+
38+
> 1 | import { createHelia } from 'helia'
39+
2 | import type { Helia } from '@helia/interface'
40+
```
41+
42+
In this example we are going to cover the config necessary to use Jest with TypeScript that compiles to ESM modules.
43+
44+
### 1. TypeScript and ESM
45+
46+
Please see the [helia-typescript](https://github.com/ipfs-examples/helia-typescript) example to ensure your application is building your TypeScript source to ESM correctly.
47+
48+
At the very minimum you should check the compiled output of your application to ensure no calls to `require` are present and instead all modules are loaded via `import`.
49+
50+
### 2. `ts-jest` Transform
51+
52+
[ts-jest](https://www.npmjs.com/package/ts-jest) is a Jest transformer for your `.ts` source files that are under test.
53+
54+
By default it will transpile code to [CommonJS](https://en.wikipedia.org/wiki/CommonJS) which is undesirable if your codebase is designed to be consumed as ESM.
55+
56+
To get it to transform code to ESM, the [useESM](https://kulshekhar.github.io/ts-jest/docs/next/getting-started/options/useESM/) option must be set:
57+
58+
**jest.config.json**
59+
60+
```json
61+
{
62+
"transform": {
63+
"^.+\\.(t|j)s$": ["ts-jest", {
64+
"useESM": true
65+
}]
66+
}
67+
}
68+
```
69+
70+
### 3. `ts-jest` Presets
71+
72+
By default `ts-jest` will not be able to load ES Modules:
73+
74+
```
75+
FAIL test/index.spec.ts
76+
● Test suite failed to run
77+
78+
Cannot find module 'helia' from '../src/index.ts'
79+
80+
Require stack:
81+
/Users/alex/Documents/Workspaces/ipfs-examples/helia-examples/examples/helia-jest-typescript/src/index.ts
82+
index.spec.ts
83+
84+
> 1 | import { createHelia } from 'helia'
85+
| ^
86+
2 | import type { Helia } from '@helia/interface'
87+
```
88+
89+
To fix this it is necessary to tell Jest to use the `ts-jest` `default-esm` preset:
90+
91+
**jest.config.json**
92+
93+
```json
94+
{
95+
"preset": "ts-jest/presets/default-esm"
96+
}
97+
```
98+
99+
### 4. Importing other files from the same project
100+
101+
When authoring ESM, [file extensions are mandatory](https://nodejs.org/api/esm.html#esm_mandatory_file_extensions), however `ts-jest` will not resolve (for example) `./index.ts` when importing `./index.js`:
102+
103+
```
104+
Cannot find module '../src/index.js' from 'index.spec.ts'
105+
106+
at Resolver._throwModNotFoundError (../../../node_modules/jest-resolve/build/resolver.js:427:11)
107+
```
108+
109+
The solution is to use a module name mapper to remove the file extension from relative imports and then Jest can fall back to it's version of the Node.js [require.resolve algorithm](https://nodejs.org/api/modules.html#all-together) which will locate `index.ts` from an `index.js` import:
110+
111+
**jest.config.json**
112+
113+
```json
114+
{
115+
"moduleNameMapper": {
116+
"^(\\.{1,2}/.*)\\.[jt]s$": "$1"
117+
}
118+
}
119+
```
120+
121+
## Putting it all together
122+
123+
Your `jest.config.json` should look something like this:
124+
125+
```json
126+
{
127+
"moduleFileExtensions": [
128+
"js",
129+
"json",
130+
"ts"
131+
],
132+
"rootDir": "test",
133+
"testRegex": ".*\\.spec\\.ts$",
134+
"transform": {
135+
"^.+\\.(t|j)s$": ["ts-jest", {
136+
"useESM": true
137+
}]
138+
},
139+
"preset": "ts-jest/presets/default-esm",
140+
"moduleNameMapper": {
141+
"^(\\.{1,2}/.*)\\.[jt]s$": "$1"
142+
}
143+
}
144+
```
145+
146+
We can now run the tests:
147+
148+
```console
149+
% NODE_OPTIONS=--experimental-vm-modules jest
150+
151+
PASS test/index.spec.ts (6.055 s)
152+
Helia
153+
libp2p
154+
✓ should have a peer id (519 ms)
155+
156+
Test Suites: 1 passed, 1 total
157+
Tests: 1 passed, 1 total
158+
Snapshots: 0 total
159+
Time: 6.134 s
160+
Ran all test suites.
161+
```
162+
163+
That's it! You just successfully ran a suite that can test your Helia application.
164+
165+
## About The Project
166+
167+
- Read the [docs](https://ipfs.github.io/helia/modules/helia.html)
168+
- Look into other [examples](https://github.com/ipfs-examples/helia-examples) to learn how to spawn a Helia node in Node.js and in the Browser
169+
- Visit https://dweb-primer.ipfs.io to learn about IPFS and the concepts that underpin it
170+
- Head over to https://proto.school to take interactive tutorials that cover core IPFS APIs
171+
- Check out https://docs.ipfs.io for tips, how-tos and more
172+
- See https://blog.ipfs.io for news and more
173+
- Need help? Please ask 'How do I?' questions on https://discuss.ipfs.io
174+
175+
## Getting Started
176+
177+
### Prerequisites
178+
179+
Make sure you have installed all of the following prerequisites on your development machine:
180+
181+
- Git - [Download & Install Git](https://git-scm.com/downloads). OSX and Linux machines typically have this already installed.
182+
- Node.js - [Download & Install Node.js](https://nodejs.org/en/download/) and the npm package manager.
183+
184+
### Installation and Running example
185+
186+
```console
187+
> npm install
188+
> npm test
189+
```
190+
191+
## Documentation
192+
193+
- [IPFS Primer](https://dweb-primer.ipfs.io/)
194+
- [IPFS Docs](https://docs.ipfs.io/)
195+
- [Tutorials](https://proto.school)
196+
- [More examples](https://github.com/ipfs-examples/helia-examples)
197+
- [API - Helia](https://ipfs.github.io/helia/modules/helia.html)
198+
- [API - @helia/unixfs](https://ipfs.github.io/helia-unixfs/modules/helia.html)
199+
200+
## Contributing
201+
202+
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.
203+
204+
1. Fork the IPFS Project
205+
2. Create your Feature Branch (`git checkout -b feature/amazing-feature`)
206+
3. Commit your Changes (`git commit -a -m 'feat: add some amazing feature'`)
207+
4. Push to the Branch (`git push origin feature/amazing-feature`)
208+
5. Open a Pull Request
209+
210+
## Want to hack on IPFS?
211+
212+
[![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)
213+
214+
The IPFS implementation in JavaScript needs your help! There are a few things you can do right now to help out:
215+
216+
Read the [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md) and [JavaScript Contributing Guidelines](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md).
217+
218+
- **Check out existing issues** The [issue list](https://github.com/ipfs/helia/issues) has many that are marked as ['help wanted'](https://github.com/ipfs/helia/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22help+wanted%22) or ['difficulty:easy'](https://github.com/ipfs/helia/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Adifficulty%3Aeasy) which make great starting points for development, many of which can be tackled with no prior IPFS knowledge
219+
- **Look at the [Helia Roadmap](https://github.com/ipfs/helia/blob/main/ROADMAP.md)** This are the high priority items being worked on right now
220+
- **Perform code reviews** More eyes will help
221+
a. speed the project along
222+
b. ensure quality, and
223+
c. reduce possible future bugs
224+
- **Add tests**. There can never be enough tests
225+
226+
[cid]: https://docs.ipfs.tech/concepts/content-addressing "Content Identifier"
227+
[Uint8Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
228+
[libp2p]: https://libp2p.io
229+
[IndexedDB]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
230+
[S3]: https://aws.amazon.com/s3/

Diff for: examples/helia-jest-typescript/jest.config.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"moduleFileExtensions": [
3+
"js",
4+
"json",
5+
"ts"
6+
],
7+
"rootDir": "test",
8+
"testRegex": ".*\\.spec\\.ts$",
9+
"transform": {
10+
"^.+\\.(t|j)s$": ["ts-jest", {
11+
"useESM": true
12+
}]
13+
},
14+
"preset": "ts-jest/presets/default-esm",
15+
"moduleNameMapper": {
16+
"^(\\.{1,2}/.*)\\.[jt]s$": "$1"
17+
}
18+
}

Diff for: examples/helia-jest-typescript/package.json

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "helia-jest-typescript",
3+
"version": "1.0.0",
4+
"private": true,
5+
"type": "module",
6+
"description": "Test Helia with Jest and TypeScript",
7+
"scripts": {
8+
"test": "NODE_OPTIONS=--experimental-vm-modules jest"
9+
},
10+
"dependencies": {
11+
"helia": "^1.3.12"
12+
},
13+
"devDependencies": {
14+
"@types/jest": "^29.5.2",
15+
"jest": "^29.6.2",
16+
"ts-jest": "^29.1.1",
17+
"typescript": "^5.1.6"
18+
}
19+
}

Diff for: examples/helia-jest-typescript/src/index.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { createHelia } from 'helia'
2+
import type { Helia } from '@helia/interface'
3+
4+
export async function createHeliaNode (): Promise<Helia> {
5+
const node = await createHelia()
6+
7+
return node
8+
}

0 commit comments

Comments
 (0)