test-tp1-ynov-react-kleas17 1.0.1 → 1.0.3
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.
- package/package.json +3 -3
- package/dist/App.test.js +0 -298
- package/dist/__snapshots__/App.test.js.snap +0 -38
- package/dist/api.test.js +0 -128
- package/dist/setupTests.js +0 -5
- package/dist/validator.test.js +0 -152
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "test-tp1-ynov-react-kleas17",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "React application package prepared for automated npm publishing.",
|
|
6
|
-
"main": "dist/
|
|
6
|
+
"main": "dist/library.js",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist"
|
|
9
9
|
],
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"scripts": {
|
|
26
26
|
"start": "react-scripts start",
|
|
27
27
|
"build": "react-scripts build",
|
|
28
|
-
"build-npm": "node -e \"process.env.NODE_ENV='production'; const fs=require('fs'); fs.rmSync('dist',{ recursive:true, force:true }); fs.mkdirSync('dist',{ recursive:true });\" && node ./node_modules/@babel/cli/bin/babel.js src --out-dir dist --copy-files
|
|
28
|
+
"build-npm": "node -e \"process.env.NODE_ENV='production'; const fs=require('fs'); fs.rmSync('dist',{ recursive:true, force:true }); fs.mkdirSync('dist',{ recursive:true });\" && node ./node_modules/@babel/cli/bin/babel.js src --out-dir dist --copy-files && node -e \"const fs=require('fs'); ['dist/App.test.js','dist/api.test.js','dist/validator.test.js','dist/setupTests.js','dist/__snapshots__','dist/App.test.js.snap'].forEach((p)=>fs.rmSync(p,{recursive:true,force:true}));\"",
|
|
29
29
|
"build-npm:unix": "NODE_ENV=production && rm -rf dist && mkdir dist && npx babel src --out-dir dist --copy-files",
|
|
30
30
|
"build-npm:win": "SET NODE_ENV=production && rm -rf dist && mkdir dist && npx babel src --out-dir dist --copy-files",
|
|
31
31
|
"prepublishOnly": "npm run build-npm",
|
package/dist/App.test.js
DELETED
|
@@ -1,298 +0,0 @@
|
|
|
1
|
-
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
2
|
-
import userEvent from '@testing-library/user-event';
|
|
3
|
-
import App from './App';
|
|
4
|
-
import * as apiModule from './api';
|
|
5
|
-
import * as validatorModule from './validator';
|
|
6
|
-
|
|
7
|
-
jest.mock('./api');
|
|
8
|
-
|
|
9
|
-
const champs = {
|
|
10
|
-
nom: /^Nom$/i,
|
|
11
|
-
prenom: /^Prénom$/i,
|
|
12
|
-
email: /email/i,
|
|
13
|
-
dateNaissance: /date de naissance/i,
|
|
14
|
-
cp: /code postal/i,
|
|
15
|
-
ville: /ville/i,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const userValide = {
|
|
19
|
-
nom: 'Martin',
|
|
20
|
-
prenom: 'Julie',
|
|
21
|
-
email: 'julie.martin@example.com',
|
|
22
|
-
dateNaissance: '1990-01-01',
|
|
23
|
-
cp: '69001',
|
|
24
|
-
ville: 'Lyon',
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
beforeEach(() => {
|
|
28
|
-
jest.restoreAllMocks();
|
|
29
|
-
jest.clearAllMocks();
|
|
30
|
-
window.history.pushState({}, '', '/');
|
|
31
|
-
apiModule.getRegistrations.mockResolvedValue([]);
|
|
32
|
-
apiModule.createRegistration.mockResolvedValue({ id: 1 });
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
async function renderApp() {
|
|
36
|
-
render(<App />);
|
|
37
|
-
await waitFor(() => expect(apiModule.getRegistrations).toHaveBeenCalled());
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async function allerAuFormulaire() {
|
|
41
|
-
await userEvent.click(screen.getByRole('link', { name: /ajouter un utilisateur/i }));
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async function remplirFormulaireValide() {
|
|
45
|
-
await userEvent.type(screen.getByLabelText(champs.nom), userValide.nom);
|
|
46
|
-
await userEvent.type(screen.getByLabelText(champs.prenom), userValide.prenom);
|
|
47
|
-
await userEvent.type(screen.getByLabelText(champs.email), userValide.email);
|
|
48
|
-
await userEvent.type(screen.getByLabelText(champs.dateNaissance), userValide.dateNaissance);
|
|
49
|
-
await userEvent.type(screen.getByLabelText(champs.cp), userValide.cp);
|
|
50
|
-
await userEvent.type(screen.getByLabelText(champs.ville), userValide.ville);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
describe('Navigation SPA et formulaire - integration', () => {
|
|
54
|
-
test('accueil initial: compteur a 0 et liste vide', async () => {
|
|
55
|
-
await renderApp();
|
|
56
|
-
|
|
57
|
-
expect(screen.getByText('0 utilisateur(s) inscrit(s)')).toBeInTheDocument();
|
|
58
|
-
expect(screen.getByText('Aucun utilisateur inscrit pour le moment.')).toBeInTheDocument();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
test('hydrate la liste depuis l API', async () => {
|
|
62
|
-
apiModule.getRegistrations.mockResolvedValueOnce([userValide]);
|
|
63
|
-
|
|
64
|
-
await renderApp();
|
|
65
|
-
|
|
66
|
-
expect(await screen.findByText('1 utilisateur(s) inscrit(s)')).toBeInTheDocument();
|
|
67
|
-
expect(screen.getByText('Martin Julie')).toBeInTheDocument();
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test('erreur API au chargement: fallback liste vide', async () => {
|
|
71
|
-
apiModule.getRegistrations.mockRejectedValueOnce(new Error('Network Error'));
|
|
72
|
-
|
|
73
|
-
await renderApp();
|
|
74
|
-
|
|
75
|
-
expect(screen.getByText('0 utilisateur(s) inscrit(s)')).toBeInTheDocument();
|
|
76
|
-
expect(screen.getByText('Aucun utilisateur inscrit pour le moment.')).toBeInTheDocument();
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test('navigation accueil vers formulaire puis retour accueil', async () => {
|
|
80
|
-
await renderApp();
|
|
81
|
-
|
|
82
|
-
await allerAuFormulaire();
|
|
83
|
-
expect(window.location.pathname).toBe('/register');
|
|
84
|
-
expect(screen.getByText('Formulaire utilisateur')).toBeInTheDocument();
|
|
85
|
-
|
|
86
|
-
await userEvent.click(screen.getByRole('link', { name: /retour à l'accueil/i }));
|
|
87
|
-
expect(window.location.pathname).toBe('/');
|
|
88
|
-
expect(screen.getByText("Bienvenue sur l'application d'inscription")).toBeInTheDocument();
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test('prenom avec chiffres: erreur et blocage submit', async () => {
|
|
92
|
-
await renderApp();
|
|
93
|
-
await allerAuFormulaire();
|
|
94
|
-
|
|
95
|
-
await userEvent.type(screen.getByLabelText(champs.prenom), 'Julie9');
|
|
96
|
-
|
|
97
|
-
expect(screen.getByText(/Caractères invalides dans le nom/i)).toBeInTheDocument();
|
|
98
|
-
expect(screen.getByRole('button', { name: /soumettre/i })).toBeDisabled();
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
test('ville avec symbole: erreur et blocage submit', async () => {
|
|
102
|
-
await renderApp();
|
|
103
|
-
await allerAuFormulaire();
|
|
104
|
-
|
|
105
|
-
await userEvent.type(screen.getByLabelText(champs.ville), 'Paris!');
|
|
106
|
-
|
|
107
|
-
expect(screen.getByText(/Caractères invalides dans le nom/i)).toBeInTheDocument();
|
|
108
|
-
expect(screen.getByRole('button', { name: /soumettre/i })).toBeDisabled();
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
test('email farfelu (accent/parenthese): erreur visible', async () => {
|
|
112
|
-
await renderApp();
|
|
113
|
-
await allerAuFormulaire();
|
|
114
|
-
|
|
115
|
-
await userEvent.type(screen.getByLabelText(champs.email), 'kleas3.marc@gma)l.com');
|
|
116
|
-
|
|
117
|
-
expect(screen.getByText("Format d'email invalide")).toBeInTheDocument();
|
|
118
|
-
expect(screen.getByRole('button', { name: /soumettre/i })).toBeDisabled();
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
test('date farfelue (0008): erreur visible', async () => {
|
|
122
|
-
await renderApp();
|
|
123
|
-
await allerAuFormulaire();
|
|
124
|
-
|
|
125
|
-
await userEvent.type(screen.getByLabelText(champs.nom), 'Martin');
|
|
126
|
-
await userEvent.type(screen.getByLabelText(champs.prenom), 'Julie');
|
|
127
|
-
await userEvent.type(screen.getByLabelText(champs.email), 'julie.martin2@example.com');
|
|
128
|
-
await userEvent.type(screen.getByLabelText(champs.cp), '69001');
|
|
129
|
-
await userEvent.type(screen.getByLabelText(champs.ville), 'Lyon');
|
|
130
|
-
await userEvent.type(screen.getByLabelText(champs.dateNaissance), '0008-08-08');
|
|
131
|
-
|
|
132
|
-
expect(screen.getByText('Date de naissance invalide')).toBeInTheDocument();
|
|
133
|
-
expect(screen.getByRole('button', { name: /soumettre/i })).toBeDisabled();
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
test('email deja utilise: erreur visible et soumission bloquee', async () => {
|
|
137
|
-
apiModule.getRegistrations.mockResolvedValueOnce([{ ...userValide }]);
|
|
138
|
-
await renderApp();
|
|
139
|
-
await screen.findByText('1 utilisateur(s) inscrit(s)');
|
|
140
|
-
await allerAuFormulaire();
|
|
141
|
-
|
|
142
|
-
await userEvent.type(screen.getByLabelText(champs.nom), 'Durand');
|
|
143
|
-
await userEvent.type(screen.getByLabelText(champs.prenom), 'Luc');
|
|
144
|
-
await userEvent.type(screen.getByLabelText(champs.email), userValide.email);
|
|
145
|
-
await userEvent.type(screen.getByLabelText(champs.dateNaissance), '1992-02-02');
|
|
146
|
-
await userEvent.type(screen.getByLabelText(champs.cp), '75001');
|
|
147
|
-
await userEvent.type(screen.getByLabelText(champs.ville), 'Paris');
|
|
148
|
-
|
|
149
|
-
expect(screen.getByText(/Cet email est .*utilis/i)).toBeInTheDocument();
|
|
150
|
-
expect(screen.getByRole('button', { name: /soumettre/i })).toBeDisabled();
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
test('soumission valide: redirection accueil, compteur et liste mis a jour', async () => {
|
|
154
|
-
await renderApp();
|
|
155
|
-
|
|
156
|
-
await allerAuFormulaire();
|
|
157
|
-
await remplirFormulaireValide();
|
|
158
|
-
await userEvent.click(screen.getByRole('button', { name: /soumettre/i }));
|
|
159
|
-
|
|
160
|
-
await waitFor(() => expect(window.location.pathname).toBe('/'));
|
|
161
|
-
expect(await screen.findByText('1 utilisateur(s) inscrit(s)')).toBeInTheDocument();
|
|
162
|
-
expect(screen.getByText('Martin Julie')).toBeInTheDocument();
|
|
163
|
-
expect(screen.getByRole('status')).toHaveTextContent('Inscription enregistrée');
|
|
164
|
-
|
|
165
|
-
expect(apiModule.createRegistration).toHaveBeenCalledWith(userValide);
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
test('soumission invalide ne declenche pas appel API', async () => {
|
|
169
|
-
await renderApp();
|
|
170
|
-
await allerAuFormulaire();
|
|
171
|
-
|
|
172
|
-
fireEvent.submit(screen.getByRole('button', { name: /soumettre/i }).closest('form'));
|
|
173
|
-
expect(apiModule.createRegistration).not.toHaveBeenCalled();
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
test('echec API a la soumission: reste sur formulaire et affiche erreur', async () => {
|
|
177
|
-
apiModule.createRegistration.mockRejectedValueOnce(new Error('Network Error'));
|
|
178
|
-
await renderApp();
|
|
179
|
-
|
|
180
|
-
await allerAuFormulaire();
|
|
181
|
-
await remplirFormulaireValide();
|
|
182
|
-
await userEvent.click(screen.getByRole('button', { name: /soumettre/i }));
|
|
183
|
-
|
|
184
|
-
await waitFor(() => expect(window.location.pathname).toBe('/register'));
|
|
185
|
-
expect(await screen.findByRole('status')).toHaveTextContent("Erreur lors de l'inscription");
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
test('erreur metier backend 400: affiche le message du serveur', async () => {
|
|
189
|
-
apiModule.createRegistration.mockRejectedValueOnce({
|
|
190
|
-
response: {
|
|
191
|
-
status: 400,
|
|
192
|
-
data: { message: 'Cet email est déjà utilisé (back)' },
|
|
193
|
-
},
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
await renderApp();
|
|
197
|
-
await allerAuFormulaire();
|
|
198
|
-
await remplirFormulaireValide();
|
|
199
|
-
await userEvent.click(screen.getByRole('button', { name: /soumettre/i }));
|
|
200
|
-
|
|
201
|
-
await waitFor(() => expect(window.location.pathname).toBe('/register'));
|
|
202
|
-
expect(await screen.findByRole('status')).toHaveTextContent('Cet email est déjà utilisé (back)');
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
test('erreur metier backend 409: affiche le message du serveur', async () => {
|
|
206
|
-
apiModule.createRegistration.mockRejectedValueOnce({
|
|
207
|
-
response: {
|
|
208
|
-
status: 409,
|
|
209
|
-
data: { message: 'Conflit: email déjà existant (409)' },
|
|
210
|
-
},
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
await renderApp();
|
|
214
|
-
await allerAuFormulaire();
|
|
215
|
-
await remplirFormulaireValide();
|
|
216
|
-
await userEvent.click(screen.getByRole('button', { name: /soumettre/i }));
|
|
217
|
-
|
|
218
|
-
await waitFor(() => expect(window.location.pathname).toBe('/register'));
|
|
219
|
-
expect(await screen.findByRole('status')).toHaveTextContent(
|
|
220
|
-
'Conflit: email déjà existant (409)'
|
|
221
|
-
);
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
test('erreur serveur 500: affiche une alerte utilisateur resilient', async () => {
|
|
225
|
-
apiModule.createRegistration.mockRejectedValueOnce({
|
|
226
|
-
response: {
|
|
227
|
-
status: 500,
|
|
228
|
-
},
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
await renderApp();
|
|
232
|
-
await allerAuFormulaire();
|
|
233
|
-
await remplirFormulaireValide();
|
|
234
|
-
await userEvent.click(screen.getByRole('button', { name: /soumettre/i }));
|
|
235
|
-
|
|
236
|
-
await waitFor(() => expect(window.location.pathname).toBe('/register'));
|
|
237
|
-
expect(await screen.findByRole('status')).toHaveTextContent(
|
|
238
|
-
'Serveur indisponible, veuillez réessayer plus tard.'
|
|
239
|
-
);
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
test('erreur technique de validation: fallback affiche', async () => {
|
|
243
|
-
const identitySpy = jest.spyOn(validatorModule, 'validateIdentity').mockImplementation(() => {
|
|
244
|
-
throw new Error('unexpected');
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
await renderApp();
|
|
248
|
-
await allerAuFormulaire();
|
|
249
|
-
|
|
250
|
-
const nomInput = screen.getByLabelText(champs.nom);
|
|
251
|
-
fireEvent.change(nomInput, { target: { value: 'Martin' } });
|
|
252
|
-
fireEvent.blur(nomInput);
|
|
253
|
-
|
|
254
|
-
expect(screen.getByText('Erreur de validation')).toBeInTheDocument();
|
|
255
|
-
identitySpy.mockRestore();
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
test('snapshot de la page accueil', async () => {
|
|
259
|
-
const { asFragment } = render(<App />);
|
|
260
|
-
await waitFor(() => expect(apiModule.getRegistrations).toHaveBeenCalled());
|
|
261
|
-
expect(asFragment()).toMatchSnapshot();
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
test('ne met pas a jour le state apres unmount pendant le chargement initial', async () => {
|
|
265
|
-
let resolveRequest;
|
|
266
|
-
const pendingRequest = new Promise((resolve) => {
|
|
267
|
-
resolveRequest = resolve;
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
apiModule.getRegistrations.mockReturnValueOnce(pendingRequest);
|
|
271
|
-
const { unmount } = render(<App />);
|
|
272
|
-
|
|
273
|
-
expect(apiModule.getRegistrations).toHaveBeenCalledTimes(1);
|
|
274
|
-
unmount();
|
|
275
|
-
|
|
276
|
-
resolveRequest([userValide]);
|
|
277
|
-
await waitFor(() => expect(apiModule.getRegistrations).toHaveBeenCalledTimes(1));
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
test('garde un etat sain si le chargement initial echoue apres attente', async () => {
|
|
281
|
-
let rejectRequest;
|
|
282
|
-
const pendingRequest = new Promise((_, reject) => {
|
|
283
|
-
rejectRequest = reject;
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
apiModule.getRegistrations.mockReturnValueOnce(pendingRequest);
|
|
287
|
-
render(<App />);
|
|
288
|
-
|
|
289
|
-
expect(apiModule.getRegistrations).toHaveBeenCalledTimes(1);
|
|
290
|
-
rejectRequest(new Error('Network Error'));
|
|
291
|
-
|
|
292
|
-
await waitFor(() => {
|
|
293
|
-
expect(screen.getByText('0 utilisateur(s) inscrit(s)')).toBeInTheDocument();
|
|
294
|
-
expect(screen.getByText('Aucun utilisateur inscrit pour le moment.')).toBeInTheDocument();
|
|
295
|
-
});
|
|
296
|
-
});
|
|
297
|
-
});
|
|
298
|
-
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`Navigation SPA et formulaire - integration snapshot de la page accueil 1`] = `
|
|
4
|
-
<DocumentFragment>
|
|
5
|
-
<div
|
|
6
|
-
class="App"
|
|
7
|
-
>
|
|
8
|
-
<main
|
|
9
|
-
class="form-container"
|
|
10
|
-
>
|
|
11
|
-
<section
|
|
12
|
-
data-cy="home-page"
|
|
13
|
-
>
|
|
14
|
-
<h1>
|
|
15
|
-
Bienvenue sur l'application d'inscription
|
|
16
|
-
</h1>
|
|
17
|
-
<p
|
|
18
|
-
data-cy="registered-count"
|
|
19
|
-
>
|
|
20
|
-
0 utilisateur(s) inscrit(s)
|
|
21
|
-
</p>
|
|
22
|
-
<p
|
|
23
|
-
data-cy="empty-list"
|
|
24
|
-
>
|
|
25
|
-
Aucun utilisateur inscrit pour le moment.
|
|
26
|
-
</p>
|
|
27
|
-
<a
|
|
28
|
-
class="action-button primary-action link-button"
|
|
29
|
-
data-cy="go-to-register"
|
|
30
|
-
href="/register"
|
|
31
|
-
>
|
|
32
|
-
Ajouter un utilisateur
|
|
33
|
-
</a>
|
|
34
|
-
</section>
|
|
35
|
-
</main>
|
|
36
|
-
</div>
|
|
37
|
-
</DocumentFragment>
|
|
38
|
-
`;
|
package/dist/api.test.js
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
|
-
import { countUsers, createRegistration, getRegistrations } from './api';
|
|
3
|
-
|
|
4
|
-
jest.mock('axios');
|
|
5
|
-
|
|
6
|
-
describe('api integration with axios mock', () => {
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
process.env.REACT_APP_SERVER_PORT = '3000';
|
|
9
|
-
delete process.env.REACT_APP_API_TOKEN;
|
|
10
|
-
jest.clearAllMocks();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test('getRegistrations: succes avec payload utilisateurs', async () => {
|
|
14
|
-
axios.get.mockImplementationOnce(() =>
|
|
15
|
-
Promise.resolve({
|
|
16
|
-
data: {
|
|
17
|
-
utilisateurs: [
|
|
18
|
-
{
|
|
19
|
-
nom: 'Martin',
|
|
20
|
-
prenom: 'Julie',
|
|
21
|
-
email: 'julie.martin@example.com',
|
|
22
|
-
dateNaissance: '1990-01-01',
|
|
23
|
-
cp: '69001',
|
|
24
|
-
ville: 'Lyon',
|
|
25
|
-
},
|
|
26
|
-
],
|
|
27
|
-
},
|
|
28
|
-
})
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
const users = await getRegistrations();
|
|
32
|
-
|
|
33
|
-
expect(axios.get).toHaveBeenCalledWith('http://localhost:3000/users', {});
|
|
34
|
-
expect(users).toEqual([
|
|
35
|
-
{
|
|
36
|
-
nom: 'Martin',
|
|
37
|
-
prenom: 'Julie',
|
|
38
|
-
email: 'julie.martin@example.com',
|
|
39
|
-
dateNaissance: '1990-01-01',
|
|
40
|
-
cp: '69001',
|
|
41
|
-
ville: 'Lyon',
|
|
42
|
-
},
|
|
43
|
-
]);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('getRegistrations: erreur reseau', async () => {
|
|
47
|
-
axios.get.mockImplementationOnce(() => Promise.reject(new Error('Network Error')));
|
|
48
|
-
|
|
49
|
-
await expect(getRegistrations()).rejects.toThrow('Network Error');
|
|
50
|
-
expect(axios.get).toHaveBeenCalledWith('http://localhost:3000/users', {});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test('getRegistrations: payload invalide retourne tableau vide', async () => {
|
|
54
|
-
axios.get.mockImplementationOnce(() =>
|
|
55
|
-
Promise.resolve({
|
|
56
|
-
data: { unexpected: true },
|
|
57
|
-
})
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
const users = await getRegistrations();
|
|
61
|
-
|
|
62
|
-
expect(users).toEqual([]);
|
|
63
|
-
expect(axios.get).toHaveBeenCalledWith('http://localhost:3000/users', {});
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test('countUsers: succes avec tableau', async () => {
|
|
67
|
-
axios.get.mockImplementationOnce(() =>
|
|
68
|
-
Promise.resolve({
|
|
69
|
-
data: [
|
|
70
|
-
{ id: 1, email: 'a@example.com' },
|
|
71
|
-
{ id: 2, email: 'b@example.com' },
|
|
72
|
-
],
|
|
73
|
-
})
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
const result = await countUsers();
|
|
77
|
-
|
|
78
|
-
expect(result).toEqual(2);
|
|
79
|
-
expect(axios.get).toHaveBeenCalledWith('http://localhost:3000/users', {});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
test('countUsers: erreur reseau', async () => {
|
|
83
|
-
axios.get.mockImplementationOnce(() => Promise.reject(new Error('Network Error')));
|
|
84
|
-
|
|
85
|
-
await expect(countUsers()).rejects.toThrow('Network Error');
|
|
86
|
-
expect(axios.get).toHaveBeenCalledTimes(1);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
test('createRegistration: succes', async () => {
|
|
90
|
-
const payload = {
|
|
91
|
-
nom: 'Durand',
|
|
92
|
-
prenom: 'Luc',
|
|
93
|
-
email: 'luc.durand@example.com',
|
|
94
|
-
dateNaissance: '1989-03-03',
|
|
95
|
-
cp: '75001',
|
|
96
|
-
ville: 'Paris',
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
axios.post.mockImplementationOnce(() =>
|
|
100
|
-
Promise.resolve({
|
|
101
|
-
data: { id: 101, ...payload },
|
|
102
|
-
})
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
const created = await createRegistration(payload);
|
|
106
|
-
|
|
107
|
-
expect(axios.post).toHaveBeenCalledWith('http://localhost:3000/users', payload, {});
|
|
108
|
-
expect(created).toEqual({ id: 101, ...payload });
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
test('createRegistration: erreur reseau', async () => {
|
|
112
|
-
axios.post.mockImplementationOnce(() => Promise.reject(new Error('Network Error')));
|
|
113
|
-
|
|
114
|
-
await expect(createRegistration({ email: 'ko@example.com' })).rejects.toThrow('Network Error');
|
|
115
|
-
expect(axios.post).toHaveBeenCalledTimes(1);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test('ajoute le header Authorization si REACT_APP_API_TOKEN est defini', async () => {
|
|
119
|
-
process.env.REACT_APP_API_TOKEN = 'test-token';
|
|
120
|
-
axios.get.mockResolvedValueOnce({ data: [] });
|
|
121
|
-
|
|
122
|
-
await getRegistrations();
|
|
123
|
-
|
|
124
|
-
expect(axios.get).toHaveBeenCalledWith('http://localhost:3000/users', {
|
|
125
|
-
headers: { Authorization: 'Bearer test-token' },
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
});
|
package/dist/setupTests.js
DELETED
package/dist/validator.test.js
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ValidationError,
|
|
3
|
-
validateAge,
|
|
4
|
-
validateEmail,
|
|
5
|
-
validateIdentity,
|
|
6
|
-
validatePostalCode,
|
|
7
|
-
validateUniqueEmail,
|
|
8
|
-
} from './validator';
|
|
9
|
-
|
|
10
|
-
describe('ValidationError', () => {
|
|
11
|
-
test('expose le code et le message', () => {
|
|
12
|
-
const error = new ValidationError('TEST_CODE', 'Message test');
|
|
13
|
-
expect(error.code).toBe('TEST_CODE');
|
|
14
|
-
expect(error.message).toBe('Message test');
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
describe('validateAge', () => {
|
|
19
|
-
test('retourne un age numerique pour un adulte', () => {
|
|
20
|
-
const age = validateAge(new Date('1990-01-01'));
|
|
21
|
-
expect(typeof age).toBe('number');
|
|
22
|
-
expect(age).toBeGreaterThanOrEqual(18);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test('rejette un type invalide', () => {
|
|
26
|
-
expect(() => validateAge('1990-01-01')).toThrow('Date de naissance invalide');
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test('rejette une date invalide', () => {
|
|
30
|
-
expect(() => validateAge(new Date('invalid-date'))).toThrow('Date de naissance invalide');
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test('rejette un utilisateur mineur', () => {
|
|
34
|
-
expect(() => validateAge(new Date('2015-06-01'))).toThrow(
|
|
35
|
-
"L'utilisateur doit avoir au moins 18 ans"
|
|
36
|
-
);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test('rejette une date dans le futur', () => {
|
|
40
|
-
expect(() => validateAge(new Date('2999-01-01'))).toThrow('Date de naissance invalide');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('rejette une date trop ancienne (age farfelu)', () => {
|
|
44
|
-
expect(() => validateAge(new Date('0008-08-08'))).toThrow('Date de naissance invalide');
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
describe('validatePostalCode', () => {
|
|
49
|
-
test('accepte un code postal francais valide', () => {
|
|
50
|
-
expect(() => validatePostalCode('75015')).not.toThrow();
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test('rejette un type non string', () => {
|
|
54
|
-
expect(() => validatePostalCode(75015)).toThrow(
|
|
55
|
-
'Le code postal doit être une chaîne de caractères'
|
|
56
|
-
);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test('rejette un code avec lettres', () => {
|
|
60
|
-
expect(() => validatePostalCode('75A15')).toThrow('Code postal français invalide');
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test('rejette un code trop court', () => {
|
|
64
|
-
expect(() => validatePostalCode('1234')).toThrow('Code postal français invalide');
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
test('rejette un code trop long', () => {
|
|
68
|
-
expect(() => validatePostalCode('123456')).toThrow('Code postal français invalide');
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
describe('validateIdentity', () => {
|
|
73
|
-
test('accepte nom simple', () => {
|
|
74
|
-
expect(() => validateIdentity('Jean Dupont')).not.toThrow();
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test('accepte accents et tirets', () => {
|
|
78
|
-
expect(() => validateIdentity('Élodie-Anne')).not.toThrow();
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
test('rejette type non string', () => {
|
|
82
|
-
expect(() => validateIdentity(null)).toThrow(
|
|
83
|
-
'Le nom ou le prénom doit être une chaîne de caractères'
|
|
84
|
-
);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
test('rejette contenu HTML', () => {
|
|
88
|
-
expect(() => validateIdentity('<b>Jean</b>')).toThrow('Contenu HTML détecté');
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test('rejette chiffres et symboles', () => {
|
|
92
|
-
expect(() => validateIdentity('Jean123')).toThrow('Caractères invalides dans le nom');
|
|
93
|
-
expect(() => validateIdentity('Jean!')).toThrow('Caractères invalides dans le nom');
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test('rejette chaine vide', () => {
|
|
97
|
-
expect(() => validateIdentity('')).toThrow('Caractères invalides dans le nom');
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
describe('validateEmail', () => {
|
|
102
|
-
test('accepte email valide', () => {
|
|
103
|
-
expect(() => validateEmail('jean.dupont@example.com')).not.toThrow();
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
test('rejette type non string', () => {
|
|
107
|
-
expect(() => validateEmail(undefined)).toThrow("L'email doit être une chaîne de caractères");
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
test('rejette format invalide', () => {
|
|
111
|
-
expect(() => validateEmail('jean.dupont')).toThrow("Format d'email invalide");
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
test('rejette email avec espace', () => {
|
|
115
|
-
expect(() => validateEmail('jean dupont@example.com')).toThrow("Format d'email invalide");
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test('rejette email avec caracteres farfelus (accent, parenthese)', () => {
|
|
119
|
-
expect(() => validateEmail('kleas3.marc@gmaa)l.com')).toThrow("Format d'email invalide");
|
|
120
|
-
expect(() => validateEmail('kleas3.marc@gmaàl.com')).toThrow("Format d'email invalide");
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
test('rejette email avec double point', () => {
|
|
124
|
-
expect(() => validateEmail('jean..dupont@example.com')).toThrow("Format d'email invalide");
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
describe('validateUniqueEmail', () => {
|
|
129
|
-
test('accepte un email non present', () => {
|
|
130
|
-
expect(() =>
|
|
131
|
-
validateUniqueEmail('new@example.com', [{ email: 'jean.dupont@example.com' }])
|
|
132
|
-
).not.toThrow();
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
test('rejette un email deja present', () => {
|
|
136
|
-
expect(() =>
|
|
137
|
-
validateUniqueEmail('jean.dupont@example.com', [{ email: 'jean.dupont@example.com' }])
|
|
138
|
-
).toThrow('Cet email est déjà utilisé');
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
test('compare sans tenir compte de la casse', () => {
|
|
142
|
-
expect(() =>
|
|
143
|
-
validateUniqueEmail('JEAN.DUPONT@example.com', [{ email: 'jean.dupont@example.com' }])
|
|
144
|
-
).toThrow('Cet email est déjà utilisé');
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
test('ignore les entrees invalides dans la liste', () => {
|
|
148
|
-
expect(() =>
|
|
149
|
-
validateUniqueEmail('new@example.com', [null, { email: 42 }, { notEmail: true }])
|
|
150
|
-
).not.toThrow();
|
|
151
|
-
});
|
|
152
|
-
});
|