Skip to content

Commit 6bc1fb9

Browse files
docs: e2e guide (#492)
* docs: e2e guide Signed-off-by: David Dal Busco <david.dalbusco@outlook.com> * πŸ“„ Update LLMs.txt snapshot for PR review --------- Signed-off-by: David Dal Busco <david.dalbusco@outlook.com> Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
1 parent b44b56c commit 6bc1fb9

4 files changed

Lines changed: 273 additions & 0 deletions

File tree

β€Ž.llms-snapshots/llms-full.txtβ€Ž

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5001,6 +5001,90 @@ You can either automate your deployment with GitHub Actions (recommended) or dep
50015001

50025002
[GitHub Actions](/docs/guides/github-actions.md)[Manual](/docs/guides/manual-deployment.md)
50035003

5004+
# End-to-End Testing
5005+
5006+
End to end (E2E) testing helps you verify that your application behaves as expected when deployed. It covers real workflows β€” from serverless functions to client calls β€” and helps catch issues that unit tests might miss.
5007+
5008+
This page outlines how to approach E2E testing with Juno. It includes recommendations and patterns.
5009+
5010+
---
5011+
5012+
## Frameworks
5013+
5014+
We suggest [Playwright](https://playwright.dev/), but [Cypress](https://www.cypress.io/) or other frameworks will work.
5015+
5016+
Choose whatever fits your project best.
5017+
5018+
That being said, integrating authentication is easier in Playwright given that a plugin is available (see next chapter).
5019+
5020+
---
5021+
5022+
## Authentication
5023+
5024+
If your application require authentication, we recommend using the Playwright plugin for Internet Identity maintained by the DFINITY foundation:
5025+
5026+
πŸ‘‰ [github.com/dfinity/internet-identity-playwright](https://github.com/dfinity/internet-identity-playwright)
5027+
5028+
It handles the full login flow programmatically, allowing your tests to sign in without user interaction.
5029+
5030+
### Example usage
5031+
5032+
After installing the plugin, you can write a test like this:
5033+
5034+
```
5035+
import { testWithII } from "@dfinity/internet-identity-playwright";testWithII("should sign-in with a new user", async ({ page, iiPage }) => { await page.goto("/"); await iiPage.signInWithNewIdentity();});
5036+
```
5037+
5038+
---
5039+
5040+
## Continuous Integration
5041+
5042+
To run end-to-end tests in CI, we recommend using the `junobuild/satellite` image.
5043+
5044+
This image runs a headless Satellite (spun with a predictable ID `jx5yt-yyaaa-aaaal-abzbq-cai`) with all core services enabled. It's a bit faster to start and does not require using the Console UI.
5045+
5046+
---
5047+
5048+
### Configuration
5049+
5050+
In your `juno.config.ts`, make sure to set the `development` ID to match the one used by the image, and set the emulator to run the `junobuild/satellite` image.
5051+
5052+
If you're using a different image like Skylab, you can make this configuration dynamic based on the mode received by `defineConfig`.
5053+
5054+
You can also replace `development` with `test` or any other mode. Adapt as you wish.
5055+
5056+
```
5057+
import { defineConfig } from "@junobuild/config";export default defineConfig({ satellite: { ids: { development: "jx5yt-yyaaa-aaaal-abzbq-cai", production: "<PROD_SATELLITE_ID>" }, source: "out", collections: { datastore: [ { collection: "notes", read: "managed", write: "managed", memory: "stable" } ], storage: [ { collection: "images", read: "managed", write: "managed", memory: "stable" } ] } }, emulator: { runner: { type: "docker" }, satellite: {} }});
5058+
```
5059+
5060+
The configuration above also defines the collections used by the application under test.
5061+
5062+
In the next chapter, we'll apply this config before running the tests.
5063+
5064+
---
5065+
5066+
### GitHub Actions
5067+
5068+
To run the tests in your CI, you can either use the [GitHub Actions](/docs/guides/github-actions.md) or install the CLI manually. In the example below, we install the CLI because we chain multiple commands.
5069+
5070+
```
5071+
name: E2E Testson: pull_request: workflow_dispatch:jobs: e2e: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Node uses: actions/setup-node@v4 with: node-version: 22 registry-url: "https://registry.npmjs.org" - name: Install dependencies run: npm ci - name: Install Juno CLI run: npm i -g @junobuild/cli - name: Run emulator run: | set -e juno dev start --headless & juno dev wait juno login --emulator --mode development --headless juno config --mode development --headless - name: Run tests run: npm run e2e:ci - name: Upload Playwright report on failure uses: actions/upload-artifact@v4 if: ${{ failure() }} with: name: playwright-report path: playwright-report/ retention-days: 3 - name: Upload Playwright results on failure uses: actions/upload-artifact@v4 if: ${{ failure() }} with: name: test-results path: test-results/ retention-days: 3 may-merge: needs: ["e2e"] runs-on: ubuntu-latest steps: - name: Cleared for merging run: echo OK
5072+
```
5073+
5074+
So, how it works:
5075+
5076+
* We start by checking out the code, installing Node.js, and running `npm ci` to install your project dependencies.
5077+
* As mentioned, instead of the Juno GitHub Actions, we install the Juno CLI globally so we can use it in the next steps.
5078+
* We then run the emulator using `juno dev start --headless`, which launches the `junobuild/satellite` Docker image (defined in the `juno.config`) in the background, and follow up with:
5079+
* `juno dev wait` to ensure the emulator is ready before continuing.
5080+
* `juno login` sets up authentication against the emulator in headless mode. This way the CLI can operate the Satellite β€” required for the next step.
5081+
* `juno config` applies the configuration and sets the collections required by the project.
5082+
* Once everything is ready, we run the end-to-end tests via `npm run e2e:ci`. Replace with the command that runs your tests in headless mode.
5083+
* If the tests fail, Playwright reports and raw test results are uploaded as artifacts to help debugging.
5084+
* Finally, if everything passes, the `may-merge` job marks the PR as cleared.
5085+
5086+
That's it. Minimal setup, no need for the Console UI, and everything runs headlessly in CI.
5087+
50045088
# Manual Deployment
50055089

50065090
We recommend using [GitHub Actions](/docs/guides/github-actions.md) for automated and efficient deployments. However, this guide walks you through manually deploying your app using the Juno CLI, covering the setup, build, and deployment process to your Juno Satellite.

β€Ž.llms-snapshots/llms.txtβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ Juno is your self-contained serverless platform for building full-stack web apps
8484
- [AI](https://juno.build/docs/guides/ai.md): Learn how to use Juno's llms.txt files to provide AI tools with better context for building serverless functions, deploying satellites, and integrating the SDK.
8585
- [Angular](https://juno.build/docs/guides/angular.md): Use Juno with Angular
8686
- [Astro](https://juno.build/docs/guides/astro.md): Learn how to integrate Juno with Astro for seamless development. Follow our quickstart guide and hosting instructions.
87+
- [End-to-End Testing](https://juno.build/docs/guides/e2e.md): Learn how to write and run end-to-end (E2E) tests for your Juno project using tools like Playwright and GitHub Actions. Includes emulator setup, authentication handling, and CI integration.
8788
- [Manual](https://juno.build/docs/guides/manual-deployment.md): Learn how to deploy an application to a Juno Satellite from your device using the CLI.
8889
- [Next.js](https://juno.build/docs/guides/nextjs.md): Learn how to integrate Juno with Next.js. Follow our quickstart guide and examples to get started.
8990
- [NodeJS](https://juno.build/docs/guides/nodejs.md): SDK usage in a NodeJS context

β€Ždocs/guides/e2e.mdβ€Ž

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
---
2+
id: e2e
3+
title: End-to-End Testing
4+
description: Learn how to write and run end-to-end (E2E) tests for your Juno project using tools like Playwright and GitHub Actions. Includes emulator setup, authentication handling, and CI integration.
5+
---
6+
7+
# End-to-End Testing
8+
9+
End to end (E2E) testing helps you verify that your application behaves as expected when deployed. It covers real workflows β€” from serverless functions to client calls β€” and helps catch issues that unit tests might miss.
10+
11+
This page outlines how to approach E2E testing with Juno. It includes recommendations and patterns.
12+
13+
---
14+
15+
## Frameworks
16+
17+
We suggest [Playwright](https://playwright.dev/), but [Cypress](https://www.cypress.io/) or other frameworks will work.
18+
19+
Choose whatever fits your project best.
20+
21+
That being said, integrating authentication is easier in Playwright given that a plugin is available (see next chapter).
22+
23+
---
24+
25+
## Authentication
26+
27+
If your application require authentication, we recommend using the Playwright plugin for Internet Identity maintained by the DFINITY foundation:
28+
29+
πŸ‘‰ [github.com/dfinity/internet-identity-playwright](https://github.com/dfinity/internet-identity-playwright)
30+
31+
It handles the full login flow programmatically, allowing your tests to sign in without user interaction.
32+
33+
### Example usage
34+
35+
After installing the plugin, you can write a test like this:
36+
37+
```typescript
38+
import { testWithII } from "@dfinity/internet-identity-playwright";
39+
40+
testWithII("should sign-in with a new user", async ({ page, iiPage }) => {
41+
await page.goto("/");
42+
43+
await iiPage.signInWithNewIdentity();
44+
});
45+
```
46+
47+
---
48+
49+
## Continuous Integration
50+
51+
To run end-to-end tests in CI, we recommend using the `junobuild/satellite` image.
52+
53+
This image runs a headless Satellite (spun with a predictable ID `jx5yt-yyaaa-aaaal-abzbq-cai`) with all core services enabled. It's a bit faster to start and does not require using the Console UI.
54+
55+
---
56+
57+
### Configuration
58+
59+
In your `juno.config.ts`, make sure to set the `development` ID to match the one used by the image, and set the emulator to run the `junobuild/satellite` image.
60+
61+
If you're using a different image like Skylab, you can make this configuration dynamic based on the mode received by `defineConfig`.
62+
63+
You can also replace `development` with `test` or any other mode. Adapt as you wish.
64+
65+
```typescript
66+
import { defineConfig } from "@junobuild/config";
67+
68+
export default defineConfig({
69+
satellite: {
70+
ids: {
71+
development: "jx5yt-yyaaa-aaaal-abzbq-cai",
72+
production: "<PROD_SATELLITE_ID>"
73+
},
74+
source: "out",
75+
collections: {
76+
datastore: [
77+
{
78+
collection: "notes",
79+
read: "managed",
80+
write: "managed",
81+
memory: "stable"
82+
}
83+
],
84+
storage: [
85+
{
86+
collection: "images",
87+
read: "managed",
88+
write: "managed",
89+
memory: "stable"
90+
}
91+
]
92+
}
93+
},
94+
emulator: {
95+
runner: {
96+
type: "docker"
97+
},
98+
satellite: {}
99+
}
100+
});
101+
```
102+
103+
The configuration above also defines the collections used by the application under test.
104+
105+
In the next chapter, we'll apply this config before running the tests.
106+
107+
---
108+
109+
### GitHub Actions
110+
111+
To run the tests in your CI, you can either use the [GitHub Actions](./github-actions/index.mdx) or install the CLI manually. In the example below, we install the CLI because we chain multiple commands.
112+
113+
```yaml
114+
name: E2E Tests
115+
116+
on:
117+
pull_request:
118+
workflow_dispatch:
119+
120+
jobs:
121+
e2e:
122+
runs-on: ubuntu-latest
123+
124+
steps:
125+
- name: Checkout
126+
uses: actions/checkout@v4
127+
128+
- name: Set up Node
129+
uses: actions/setup-node@v4
130+
with:
131+
node-version: 22
132+
registry-url: "https://registry.npmjs.org"
133+
134+
- name: Install dependencies
135+
run: npm ci
136+
137+
- name: Install Juno CLI
138+
run: npm i -g @junobuild/cli
139+
140+
- name: Run emulator
141+
run: |
142+
set -e
143+
juno dev start --headless &
144+
juno dev wait
145+
juno login --emulator --mode development --headless
146+
juno config --mode development --headless
147+
148+
- name: Run tests
149+
run: npm run e2e:ci
150+
151+
- name: Upload Playwright report on failure
152+
uses: actions/upload-artifact@v4
153+
if: ${{ failure() }}
154+
with:
155+
name: playwright-report
156+
path: playwright-report/
157+
retention-days: 3
158+
159+
- name: Upload Playwright results on failure
160+
uses: actions/upload-artifact@v4
161+
if: ${{ failure() }}
162+
with:
163+
name: test-results
164+
path: test-results/
165+
retention-days: 3
166+
167+
may-merge:
168+
needs: ["e2e"]
169+
runs-on: ubuntu-latest
170+
steps:
171+
- name: Cleared for merging
172+
run: echo OK
173+
```
174+
175+
So, how it works:
176+
177+
- We start by checking out the code, installing Node.js, and running `npm ci` to install your project dependencies.
178+
- As mentioned, instead of the Juno GitHub Actions, we install the Juno CLI globally so we can use it in the next steps.
179+
- We then run the emulator using `juno dev start --headless`, which launches the `junobuild/satellite` Docker image (defined in the `juno.config`) in the background, and follow up with:
180+
- `juno dev wait` to ensure the emulator is ready before continuing.
181+
- `juno login` sets up authentication against the emulator in headless mode. This way the CLI can operate the Satellite β€” required for the next step.
182+
- `juno config` applies the configuration and sets the collections required by the project.
183+
- Once everything is ready, we run the end-to-end tests via `npm run e2e:ci`. Replace with the command that runs your tests in headless mode.
184+
- If the tests fail, Playwright reports and raw test results are uploaded as artifacts to help debugging.
185+
- Finally, if everything passes, the `may-merge` job marks the PR as cleared.
186+
187+
That's it. Minimal setup, no need for the Console UI, and everything runs headlessly in CI.

β€Žsidebars.tsβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ const sidebars: SidebarsConfig = {
7272
]
7373
},
7474
"guides/local-development",
75+
"guides/e2e",
7576
"guides/ai"
7677
]
7778
},

0 commit comments

Comments
Β (0)