@yoann-86/react_test_lab 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,25 @@
1
+ name: install-node
2
+ description: Install dependencies for build and test jobs
3
+ runs:
4
+ using: "composite"
5
+ steps:
6
+ - name: 🔧 Use Node.js 24.x
7
+ uses: actions/setup-node@v5
8
+ with:
9
+ node-version: 24.x
10
+
11
+ - name: 🔐 Enable Corepack
12
+ run: corepack enable
13
+ shell: bash
14
+
15
+ - name: 💾 Cache node_modules
16
+ id: cache-node-modules
17
+ uses: actions/cache@v4
18
+ with:
19
+ path: node_modules
20
+ key: ${{ runner.os }}-node-modules-${{ hashFiles('**/pnpm-lock.yaml') }}
21
+
22
+ - name: 📥 Install dependencies
23
+ if: steps.cache-node-modules.outputs.cache-hit != 'true'
24
+ run: pnpm install --frozen-lockfile
25
+ shell: bash
@@ -0,0 +1,114 @@
1
+ name: Build, Test and Deploy React Application
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ build:
11
+ name: 🏗️ Build on Node.js 24.x
12
+ runs-on: ubuntu-latest
13
+ env:
14
+ REACT_APP_API_URL: ${{ secrets.REACT_APP_API_URL }}
15
+
16
+ steps:
17
+ - name: 👯‍♂️ Clone repository
18
+ uses: actions/checkout@v4
19
+ - name: Install Node.js 24.x and pnpm
20
+ uses: ./.github/actions/install-node
21
+ - name: 📑 Generate JSDoc documentation
22
+ run: pnpm jsdoc
23
+ - name: 🧰 Build
24
+ id: build
25
+ run: pnpm run build --if-present
26
+ - name: 🗒️ Build report
27
+ if: always()
28
+ run: |
29
+ echo "Node.js version: $(node -v)"
30
+ if [[ ${{ steps.build.outcome }} == "success" ]]; then
31
+ echo "✅ Build succeeded"
32
+ else
33
+ echo "❌ Build failed"
34
+ fi
35
+ - name: 🔧 Setup pages
36
+ id: pages
37
+ uses: actions/configure-pages@v3
38
+ - name: 📤 Upload artifact for deployment
39
+ uses: actions/upload-pages-artifact@v3
40
+ with:
41
+ path: build
42
+
43
+ test:
44
+ name: 🧪 Test on Node.js 24.x
45
+ runs-on: ubuntu-latest
46
+
47
+ steps:
48
+ - name: 👯‍♂️ Clone repository
49
+ uses: actions/checkout@v4
50
+ - name: Install Node.js 24.x and pnpm
51
+ uses: ./.github/actions/install-node
52
+ - name: 🧪 Integration Tests
53
+ id: int-test
54
+ run: pnpm test
55
+ - name: 🗒️ Test report
56
+ if: always()
57
+ run: |
58
+ echo "Node.js version: $(node -v)"
59
+ if [[ ${{ steps.int-test.outcome }} == "success" ]]; then
60
+ echo "✅ Integration Tests passed"
61
+ else
62
+ echo "❌ Integration Tests failed"
63
+ fi
64
+ - name: Upload coverage reports to Codecov
65
+ uses: codecov/codecov-action@v5
66
+ env:
67
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
68
+ e2e:
69
+ name: 🎭 End-to-End Tests
70
+ runs-on: ubuntu-latest
71
+ env:
72
+ REACT_APP_API_URL: ${{ secrets.REACT_APP_API_URL }}
73
+
74
+ steps:
75
+ - name: 👯‍♂️ Clone repository
76
+ uses: actions/checkout@v4
77
+ - name: Install Node.js 24.x and pnpm
78
+ uses: ./.github/actions/install-node
79
+
80
+ - name: 🔨 Build for E2E
81
+ run: PUBLIC_URL=/ pnpm run build
82
+ - name: 📦 Install Cypress binary manually
83
+ run: pnpm exec cypress install
84
+ - name: 🎭 Run e2e tests with Cypress
85
+ id: e2e-test
86
+ uses: cypress-io/github-action@v6
87
+ with:
88
+ install: false
89
+ start: npx serve -s build -l 3000
90
+ wait-on: "http://localhost:3000"
91
+ - name: 🗒️ E2E Test report
92
+ if: always()
93
+ run: |
94
+ echo "Node.js version: $(node -v)"
95
+ if [[ ${{ steps.e2e-test.outcome }} == "success" ]]; then
96
+ echo "✅ End-to-End Tests passed"
97
+ else
98
+ echo "❌ End-to-End Tests failed"
99
+ fi
100
+
101
+ deploy:
102
+ name: 🚀 Deploy to GitHub Pages
103
+ environment:
104
+ name: github-pages
105
+ url: ${{ steps.deployment.outputs.page_url }}
106
+ runs-on: ubuntu-latest
107
+ permissions:
108
+ pages: write
109
+ id-token: write
110
+ needs: [build, test, e2e]
111
+ steps:
112
+ - name: 🚀 Deploy to GitHub Pages
113
+ id: deployment
114
+ uses: actions/deploy-pages@v4
package/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # React Test Lab
2
+
3
+ Une application React de démonstration avec tests unitaires, documentation JSDoc et CI/CD automatisée via GitHub Actions.
4
+
5
+ ## Pré-requis
6
+
7
+ - **Node.js** 22.x ou supérieur
8
+ - **pnpm** (gestionnaire de paquets)
9
+
10
+ Pour installer pnpm :
11
+
12
+ ```bash
13
+ npm install -g pnpm
14
+ ```
15
+
16
+ ## Installation
17
+
18
+ Cloner le projet et installer les dépendances :
19
+
20
+ ```bash
21
+ git clone git@github.com:YoannAuroyYnov/react-test-lab.git
22
+ cd react_test_lab
23
+ pnpm install
24
+ ```
25
+
26
+ ## Exécuter l'application
27
+
28
+ ### Mode développement
29
+
30
+ ```bash
31
+ pnpm start
32
+ ```
33
+
34
+ L'application s'ouvrira automatiquement dans votre navigateur à l'adresse [http://localhost:3000](http://localhost:3000).
35
+
36
+ ### Build de production
37
+
38
+ ```bash
39
+ pnpm build
40
+ ```
41
+
42
+ Les fichiers optimisés seront générés dans le dossier `build/`.
43
+
44
+ ## Exécuter les tests
45
+
46
+ ### Tests unitaires et d'intégration (Jest + Testing Library)
47
+
48
+ ```bash
49
+ pnpm test
50
+ ```
51
+
52
+ Le rapport de couverture sera disponible dans le dossier `coverage/`.
53
+
54
+ ### Tests end-to-end (Cypress)
55
+
56
+ Dans un premier terminal, démarrez l'application :
57
+
58
+ ```bash
59
+ pnpm start
60
+ ```
61
+
62
+ Dans un second terminal, lancez Cypress en mode headless :
63
+
64
+ ```bash
65
+ npx cypress run
66
+ ```
67
+
68
+ Vous pouvez aussi utiliser l'interface graphique :
69
+
70
+ ```bash
71
+ pnpm cypress
72
+ ```
73
+
74
+ #### Mocks utilisés dans les tests
75
+
76
+ - **Jest / Testing Library** : `axios` est mocké dans les tests (par ex. `App.test.js`) pour contrôler les réponses de l'API `/users` et déclencher les chemins heureux ou d'erreur sans requêtes réseau réelles.
77
+ - **Cypress** : les appels HTTP sont interceptés avec `cy.intercept` (ex. `cypress/e2e/navigation.cy.js`) pour stubber `GET /users` et `POST /users`, simuler un premier chargement vide ou prérempli, et forcer un retour `201` lors de la création d'utilisateur. Cela rend les parcours E2E déterministes et rapides.
78
+
79
+ ## Documentation
80
+
81
+ Pour générer la documentation JSDoc :
82
+
83
+ ```bash
84
+ pnpm jsdoc
85
+ ```
86
+
87
+ La documentation sera générée dans `public/docs/` et accessible à `http://localhost:300/docs` après le build.
88
+
89
+ ## Déploiement
90
+
91
+ Le projet est automatiquement déployé sur GitHub Pages via GitHub Actions lors d'un push sur la branche `main`.
92
+
93
+ URL de déploiement : https://yoannauroyynov.github.io/react-test-lab/
94
+
95
+ ## Configuration CI/CD - Note sur l'optimisation
96
+
97
+ **⚠️ Important :** La configuration CI/CD actuelle (parallélisation des jobs, caching pnpm, etc.) est explorée à titre **éducatif**. Sur un projet de cette taille, ces optimisations ne sont **pas pertinentes** en pratique.
98
+
99
+ **Raison :** Les temps incompressibles de démarrage des conteneurs Docker (cold start, allocation de ressources) sont bien supérieurs aux gains potentiels du caching (~30-60 secondes économisées vs ~10-30 secondes de démarrage). En d'autres termes, le surcoût du lancement des pods dépasse largement les bénéfices de l'optimisation.
100
+
101
+ Cette exploration reste utile pour :
102
+
103
+ - Comprendre les bonnes pratiques GitHub Actions
104
+ - Mettre en place une architecture scalable pour des projets plus volumineux
105
+ - Démontrer une approche professionnelle de la CI/CD
package/TEST_PLAN.md ADDED
@@ -0,0 +1,94 @@
1
+ # Documentation des Tests
2
+
3
+ ## 📊 Vue d'ensemble
4
+
5
+ Ce projet implémente une suite complète de **119 tests** couvrant la validation de formulaire en deux niveaux :
6
+
7
+ - **Tests unitaires** : Logique métier du module `validator.js`
8
+ - **Tests d'intégration** : Interface React et interactions utilisateur
9
+
10
+ ## 🎯 Couverture de Code
11
+
12
+ ```
13
+ ----------------|---------|----------|---------|---------|-------------------
14
+ File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
15
+ ----------------|---------|----------|---------|---------|-------------------
16
+ All files | 100 | 93.75 | 100 | 100 |
17
+ src | 100 | 100 | 100 | 100 |
18
+ App.js | 100 | 100 | 100 | 100 |
19
+ src/components | 100 | 93.75 | 100 | 100 |
20
+ UserForm.jsx | 100 | 93.75 | 100 | 100 | 106
21
+ ----------------|---------|----------|---------|---------|-------------------
22
+
23
+ Test Suites: 3 passed, 3 total
24
+ Tests: 119 passed, 119 total
25
+ ```
26
+
27
+ **✅ 100% de couverture** (Statements, Functions, Lines)
28
+
29
+ ## 🧪 Tests Unitaires (validator.js) - 116 tests
30
+
31
+ ### Fonctions testées
32
+
33
+ | Fonction | Tests | Couvre |
34
+ | --------------------- | ----- | --------------------------------------------------- |
35
+ | `validateAge()` | 9 | Majeur/mineur, dates futures, erreurs de paramètres |
36
+ | `validateZipCode()` | ~20 | Codes FR métropole/Corse/DOM-TOM, formats invalides |
37
+ | `validateIndentity()` | ~18 | Noms/prénoms, accents, injection SQL/XSS |
38
+ | `validateName()` | ~13 | Caractères spéciaux, chiffres, champs vides |
39
+ | `validateEmail()` | ~25 | Format RFC 5322, injections, domaines invalides |
40
+
41
+ ### 🛡️ Sécurité - 30+ tests anti-injection
42
+
43
+ **Vecteurs testés** :
44
+
45
+ - SQL Injection : `'; DROP TABLE users;--`, `' OR '1'='1`
46
+ - XSS : `<script>alert('XSS')</script>`, `<img src=x onerror=...>`
47
+ - Path Traversal : `../../../etc/passwd`, `Anne\\root`
48
+ - Command Injection : `John; rm -rf /`
49
+
50
+ **Protection** : Rejet des caractères `<>:;/\@[]{}` dans noms/emails
51
+
52
+ ## 🖥️ Tests d'Intégration (React) - 3 tests
53
+
54
+ ### 1. Happy Path
55
+
56
+ Remplit le formulaire correctement, vérifie :
57
+
58
+ - ✅ Bouton disabled → enabled
59
+ - ✅ Sauvegarde dans localStorage
60
+ - ✅ Vidage des champs après soumission
61
+
62
+ ### 2. Utilisateur Chaotique
63
+
64
+ Simule erreurs et corrections :
65
+
66
+ - ✅ Saisies invalides (chiffres, caractères spéciaux, injection SQL)
67
+ - ✅ Messages d'erreur affichés
68
+ - ✅ Corrections successives
69
+ - ✅ Validation finale
70
+
71
+ ### 3. Counter (Sanity Check)
72
+
73
+ Test basique de fonctionnement
74
+
75
+ ## 📝 Règles de Validation
76
+
77
+ | Champ | Règles |
78
+ | ------------------ | ---------------------------------------------------------------------- |
79
+ | **Prénom/Nom** | Obligatoire, pas de chiffres ni caractères spéciaux, accents autorisés |
80
+ | **Email** | Format valide (RFC 5322), présence de @ et domaine |
81
+ | **Date naissance** | Majeur (18+ ans), pas de date future |
82
+ | **Code postal** | 5 chiffres, codes français valides uniquement (01-95, 20xxx, 971-976) |
83
+
84
+ ## 🚀 Commandes
85
+
86
+ ```bash
87
+ # Tous les tests avec couverture
88
+ pnpm test
89
+
90
+ # Rapport HTML
91
+ open coverage/lcov-report/index.html
92
+ ```
93
+
94
+ ---
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ presets: [
3
+ "@babel/preset-env",
4
+ ["@babel/preset-react", { runtime: "automatic" }],
5
+ ],
6
+ };
@@ -0,0 +1,182 @@
1
+ describe("Home page spec", () => {
2
+ const person = {
3
+ firstname: "Yoann",
4
+ lastname: "Auroy",
5
+ email: "yoann.auroy@ynov.com",
6
+ birth: "1986-12-31",
7
+ city: "Paris",
8
+ zipCode: "75001",
9
+ };
10
+
11
+ context("when users are already registered", () => {
12
+ const users = [
13
+ { firstname: "Alice", lastname: "Smith", name: "Alice Smith" },
14
+ { firstname: "Bob", lastname: "Johnson", name: "Bob Johnson" },
15
+ ];
16
+
17
+ beforeEach(() => {
18
+ cy.intercept("GET", "/users", users);
19
+ cy.visit("/react-test-lab");
20
+ });
21
+
22
+ it("should count the number of registered users", () => {
23
+ cy.get("h2").should("have.text", "Il y a 2 utilisateurs enregistrés");
24
+ });
25
+
26
+ it("should display the list of registered users", () => {
27
+ cy.get("[data-testid=users-list]")
28
+ .children()
29
+ .should("have.length", 2)
30
+ .first()
31
+ .should("contain.text", "1 - Alice Smith");
32
+ });
33
+
34
+ it("should add a new user to the list after registration", () => {
35
+ cy.get("[data-testid=navigation-button]").click();
36
+
37
+ cy.get("[data-testid=firstname-input]")
38
+ .type(person.firstname)
39
+ .should("have.value", person.firstname);
40
+
41
+ cy.get("[data-testid=lastname-input]")
42
+ .type(person.lastname)
43
+ .should("have.value", person.lastname);
44
+
45
+ cy.get("[data-testid=email-input]")
46
+ .type(person.email)
47
+ .should("have.value", person.email);
48
+
49
+ cy.get("[data-testid=birth-input]")
50
+ .type(person.birth)
51
+ .should("have.value", person.birth);
52
+
53
+ cy.get("[data-testid=city-input]")
54
+ .type(person.city)
55
+ .should("have.value", person.city);
56
+
57
+ cy.get("[data-testid=zip-input]")
58
+ .type(person.zipCode)
59
+ .should("have.value", person.zipCode);
60
+
61
+ cy.get("[data-testid=submit-button]").click();
62
+
63
+ cy.get("[data-testid=users-list]")
64
+ .children()
65
+ .should("have.length", 3)
66
+ .last()
67
+ .should("contain.text", "3 - Yoann Auroy");
68
+ });
69
+
70
+ it("should display only the 5 most recent users", () => {
71
+ const moreUsers = [
72
+ { firstname: "Charlie", lastname: "Brown", name: "Charlie Brown" },
73
+ { firstname: "David", lastname: "Wilson", name: "David Wilson" },
74
+ { firstname: "Eve", lastname: "Davis", name: "Eve Davis" },
75
+ { firstname: "Frank", lastname: "Miller", name: "Frank Miller" },
76
+ ];
77
+ cy.intercept("GET", "/users", [...users, ...moreUsers]);
78
+ cy.visit("/react-test-lab");
79
+
80
+ cy.get("[data-testid=users-list]").children().should("have.length", 5);
81
+
82
+ cy.get("[data-testid=users-list]")
83
+ .children()
84
+ .first()
85
+ .should("contain.text", "1 - Bob Johnson");
86
+
87
+ cy.get("[data-testid=users-list]")
88
+ .children()
89
+ .last()
90
+ .should("contain.text", "5 - Frank Miller");
91
+ });
92
+ });
93
+
94
+ context("when no users are registered", () => {
95
+ beforeEach(() => {
96
+ cy.visit("/react-test-lab/register");
97
+ });
98
+
99
+ it("should display a message when no users are registered", () => {
100
+ cy.visit("/react-test-lab");
101
+ cy.get("h2").should("have.text", "Il n'y a aucun utilisateur enregistré");
102
+ });
103
+
104
+ it("should register a new user", () => {
105
+ cy.get("[data-testid=firstname-input]")
106
+ .type(person.firstname)
107
+ .should("have.value", person.firstname);
108
+
109
+ cy.get("[data-testid=lastname-input]")
110
+ .type(person.lastname)
111
+ .should("have.value", person.lastname);
112
+
113
+ cy.get("[data-testid=email-input]")
114
+ .type(person.email)
115
+ .should("have.value", person.email);
116
+
117
+ cy.get("[data-testid=birth-input]")
118
+ .type(person.birth)
119
+ .should("have.value", person.birth);
120
+
121
+ cy.get("[data-testid=city-input]")
122
+ .type(person.city)
123
+ .should("have.value", person.city);
124
+
125
+ cy.get("[data-testid=zip-input]")
126
+ .type(person.zipCode)
127
+ .should("have.value", person.zipCode);
128
+
129
+ cy.get("[data-testid=submit-button]").click();
130
+ });
131
+ });
132
+
133
+ context("when form inputs are invalid", () => {
134
+ beforeEach(() => {
135
+ cy.visit("/react-test-lab/register");
136
+ });
137
+
138
+ it("should validate form inputs and disable submit button on errors", () => {
139
+ cy.get("[data-testid=firstname-input]")
140
+ .type("Yo4nn")
141
+ .should("have.value", "Yo4nn");
142
+ cy.get("[data-testid=firstname-error-text]").should(
143
+ "have.text",
144
+ "Les chiffres sont interdits",
145
+ );
146
+
147
+ cy.get("[data-testid=lastname-input]")
148
+ .type("; SELECT * FROM users;")
149
+ .should("have.value", "; SELECT * FROM users;");
150
+ cy.get("[data-testid=lastname-error-text]").should(
151
+ "have.text",
152
+ "Les caractères spéciaux sont interdits",
153
+ );
154
+
155
+ cy.get("[data-testid=email-input]")
156
+ .type("yoann.invalid_email.com")
157
+ .should("have.value", "yoann.invalid_email.com");
158
+ cy.get("[data-testid=email-error-text]").should(
159
+ "have.text",
160
+ "Le format de l'email est invalide",
161
+ );
162
+
163
+ cy.get("[data-testid=birth-input]")
164
+ .type("2020-01-01")
165
+ .should("have.value", "2020-01-01");
166
+ cy.get("[data-testid=birth-error-text]").should(
167
+ "have.text",
168
+ "Vous devez être majeur pour vous inscrire",
169
+ );
170
+
171
+ cy.get("[data-testid=zip-input]")
172
+ .type("7500")
173
+ .should("have.value", "7500");
174
+ cy.get("[data-testid=zip-error-text]").should(
175
+ "have.text",
176
+ "Le code postal doit comporter 5 chiffres",
177
+ );
178
+
179
+ cy.get("[data-testid=submit-button]").should("be.disabled");
180
+ });
181
+ });
182
+ });
@@ -0,0 +1,101 @@
1
+ describe("Navigation spec", () => {
2
+ const person = {
3
+ name: "Yoann Auroy",
4
+ firstname: "Yoann",
5
+ lastname: "Auroy",
6
+ email: "yoann.auroy@ynov.com",
7
+ birth: "1986-12-31",
8
+ city: "Paris",
9
+ zipCode: "75001",
10
+ };
11
+
12
+ context("when no user is registered", () => {
13
+ beforeEach(() => {
14
+ cy.intercept("GET", "/users", []);
15
+ cy.intercept("POST", "/users", {
16
+ statusCode: 201,
17
+ body: { ...person, id: 1 },
18
+ });
19
+ });
20
+
21
+ it("should navigate on the nominal flow", () => {
22
+ cy.visit("/react-test-lab");
23
+ cy.get("h2").should("have.text", "Il n'y a aucun utilisateur enregistré");
24
+ cy.get("[data-testid=users-list]").children().should("have.length", 0);
25
+
26
+ cy.get("[data-testid=navigation-button]").click();
27
+ cy.url().should("include", "/register");
28
+
29
+ cy.get("[data-testid=firstname-input]")
30
+ .type(person.firstname)
31
+ .should("have.value", person.firstname);
32
+
33
+ cy.get("[data-testid=lastname-input]")
34
+ .type(person.lastname)
35
+ .should("have.value", person.lastname);
36
+
37
+ cy.get("[data-testid=email-input]")
38
+ .type(person.email)
39
+ .should("have.value", person.email);
40
+
41
+ cy.get("[data-testid=birth-input]")
42
+ .type(person.birth)
43
+ .should("have.value", person.birth);
44
+
45
+ cy.get("[data-testid=city-input]")
46
+ .type(person.city)
47
+ .should("have.value", person.city);
48
+
49
+ cy.get("[data-testid=zip-input]")
50
+ .type(person.zipCode)
51
+ .should("have.value", person.zipCode);
52
+
53
+ cy.get("[data-testid=submit-button]").click();
54
+
55
+ cy.url().should("include", "/react-test-lab");
56
+
57
+ cy.get("h2").should("have.text", "Il y a 1 utilisateur enregistré");
58
+
59
+ cy.get("[data-testid=users-list]")
60
+ .children()
61
+ .should("have.length", 1)
62
+ .first()
63
+ .should("contain.text", "1 - Yoann Auroy");
64
+ });
65
+ });
66
+
67
+ context("when a user is already registered", () => {
68
+ beforeEach(() => {
69
+ cy.intercept("GET", "/users", [person]);
70
+ });
71
+
72
+ it("should not navigate on error flow", () => {
73
+ cy.visit("/react-test-lab");
74
+ cy.get("h2").should("have.text", "Il y a 1 utilisateur enregistré");
75
+
76
+ cy.get("[data-testid=navigation-button]").click();
77
+ cy.url().should("include", "/register");
78
+
79
+ cy.get("[data-testid=firstname-input]")
80
+ .type("; DROP TABLE users;")
81
+ .should("have.value", "; DROP TABLE users;");
82
+ cy.get("[data-testid=firstname-error-text]").should(
83
+ "have.text",
84
+ "Les caractères spéciaux sont interdits",
85
+ );
86
+
87
+ cy.get("[data-testid=submit-button]").should("be.disabled");
88
+
89
+ cy.get("[data-testid=back-button]").click();
90
+ cy.url().should("include", "/react-test-lab");
91
+
92
+ cy.get("h2").should("have.text", "Il y a 1 utilisateur enregistré");
93
+
94
+ cy.get("[data-testid=users-list]")
95
+ .children()
96
+ .should("have.length", 1)
97
+ .first()
98
+ .should("contain.text", "1 - Yoann Auroy");
99
+ });
100
+ });
101
+ });
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "Using fixtures to represent data",
3
+ "email": "hello@cypress.io",
4
+ "body": "Fixtures are a great way to mock data for responses to routes"
5
+ }
@@ -0,0 +1,25 @@
1
+ // ***********************************************
2
+ // This example commands.js shows you how to
3
+ // create various custom commands and overwrite
4
+ // existing commands.
5
+ //
6
+ // For more comprehensive examples of custom
7
+ // commands please read more here:
8
+ // https://on.cypress.io/custom-commands
9
+ // ***********************************************
10
+ //
11
+ //
12
+ // -- This is a parent command --
13
+ // Cypress.Commands.add('login', (email, password) => { ... })
14
+ //
15
+ //
16
+ // -- This is a child command --
17
+ // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
18
+ //
19
+ //
20
+ // -- This is a dual command --
21
+ // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
22
+ //
23
+ //
24
+ // -- This will overwrite an existing command --
25
+ // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
@@ -0,0 +1,17 @@
1
+ // ***********************************************************
2
+ // This example support/e2e.js is processed and
3
+ // loaded automatically before your test files.
4
+ //
5
+ // This is a great place to put global configuration and
6
+ // behavior that modifies Cypress.
7
+ //
8
+ // You can change the location of this file or turn off
9
+ // automatically serving support files with the
10
+ // 'supportFile' configuration option.
11
+ //
12
+ // You can read more here:
13
+ // https://on.cypress.io/configuration
14
+ // ***********************************************************
15
+
16
+ // Import commands.js using ES2015 syntax:
17
+ import './commands'
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from "cypress";
2
+
3
+ module.exports = defineConfig({
4
+ allowCypressEnv: false,
5
+
6
+ e2e: {
7
+ baseUrl: "http://localhost:3000",
8
+ setupNodeEvents(on, config) {
9
+ // implement node event listeners here
10
+ },
11
+ },
12
+ });