1 |
*** Settings *** |
2 |
Documentation Test les pièces. |
3 |
|
4 |
# On inclut les mots-clefs |
5 |
Resource resources/resources.robot |
6 |
# On ouvre/ferme le navigateur au début/à la fin du Test Suite. |
7 |
Suite Setup For Suite Setup |
8 |
Suite Teardown For Suite Teardown |
9 |
|
10 |
*** Test Cases *** |
11 |
Constitution d'un jeu de données |
12 |
|
13 |
[Documentation] L'objet de ce 'Test Case' est de constituer un jeu de de |
14 |
... données cohérent pour les scénarios fonctionnels qui suivent. |
15 |
|
16 |
# |
17 |
Depuis la page d'accueil guichet guichet |
18 |
# Liste des arguments pour la demande |
19 |
&{args_demande} = Create Dictionary |
20 |
... dossier_autorisation_type_detaille=Permis de construire pour une maison individuelle et / ou ses annexes |
21 |
... demande_type=Dépôt Initial |
22 |
# Liste des arguments pour le pétitionnaire |
23 |
&{args_petitionnaire} = Create Dictionary |
24 |
... particulier_civilite=Madame |
25 |
... particulier_nom=Rivière |
26 |
... particulier_prenom=Coralie |
27 |
# |
28 |
${di} = Ajouter la nouvelle demande depuis le tableau de bord ${args_demande} ${args_petitionnaire} |
29 |
|
30 |
# Liste des arguments pour la demande |
31 |
&{args_demande_at} = Create Dictionary |
32 |
... dossier_autorisation_type_detaille=Demande d'autorisation de construire, d'aménager ou de modifier un ERP |
33 |
... demande_type=Dépôt Initial |
34 |
# Liste des arguments pour le pétitionnaire |
35 |
&{args_petitionnaire_at} = Create Dictionary |
36 |
... particulier_civilite=Madame |
37 |
... particulier_nom=Duplanty |
38 |
... particulier_prenom=Dominic |
39 |
# |
40 |
${di_at} = Ajouter la nouvelle demande depuis le tableau de bord ${args_demande_at} ${args_petitionnaire_at} |
41 |
|
42 |
# |
43 |
Depuis la page d'accueil instr instr |
44 |
# |
45 |
Ajouter une consultation depuis un dossier ${di} 59.13 - Régie des Tranports de Marseille - DTP/CIP |
46 |
|
47 |
# Les dossiers sont accessibles dans la suite du test |
48 |
Set Suite Variable ${di} |
49 |
Set Suite Variable ${di_at} |
50 |
|
51 |
|
52 |
Ajout d'une pièce |
53 |
|
54 |
[Documentation] Ajoute une pièce. Vérifie l'unicité des pièces et ajoute une pièce |
55 |
... sur une dossier AT pour vérifier l'envoi ERP. |
56 |
|
57 |
# Données de la pièce |
58 |
&{document_numerise_values} = Create Dictionary |
59 |
... uid_upload=testImportManuel.pdf |
60 |
... date_creation=15/09/2015 |
61 |
... document_numerise_type=autres pièces composant le dossier (A0) |
62 |
# |
63 |
Depuis la page d'accueil instr instr |
64 |
# |
65 |
Ajouter une pièce depuis le dossier d'instruction ${di} ${document_numerise_values} |
66 |
# On ajoute la même pièce pour vérifier le message d'erreur, car une pièce |
67 |
# doit être unique |
68 |
Ajouter une pièce depuis le dossier d'instruction ${di} ${document_numerise_values} Les valeurs saisies dans les champs dossier, Nom du fichier existent déjà, veuillez saisir de nouvelles valeurs. |
69 |
# On ajoute une pièce sur un AT pour vérifier la transmission ERP |
70 |
# Ajouter une pièce depuis le dossier d'instruction ${di_at} ${document_numerise_values} Le message a été transmis au référentiel ERP. |
71 |
|
72 |
|
73 |
Modification d'une pièce |
74 |
|
75 |
[Documentation] Modifie une pièce et vérifie que son nom est régénéré. |
76 |
|
77 |
# Données de la pièce |
78 |
&{document_numerise_values} = Create Dictionary |
79 |
... uid_upload=testImportManuel2.pdf |
80 |
... date_creation=20/09/2015 |
81 |
# |
82 |
Depuis la page d'accueil divi divi |
83 |
# |
84 |
Modifier une pièce depuis le dossier d'instruction ${di} autres pièces composant le dossier (A0) ${document_numerise_values} |
85 |
# |
86 |
Depuis la page d'accueil instr instr |
87 |
# |
88 |
Depuis le contexte du dossier d'instruction de mes encours ${di} |
89 |
On clique sur l'onglet document_numerise Pièce(s) |
90 |
# On clique pour visualiser le document, le nom doit avoir été modifié par |
91 |
# rapport à la date |
92 |
Wait Until Keyword Succeeds ${TIMEOUT} ${RETRY_INTERVAL} Click Element css=tr.col3 td.firstcol a.lienTable span.reqmo-16 |
93 |
Open PDF file |
94 |
# On vérifie la localisation du terrain |
95 |
Wait Until Keyword Succeeds 5 sec 0.2 sec Page Should Contain TEST IMPORT MANUEL 2 |
96 |
# On ferme le PDF |
97 |
Close PDF |
98 |
|
99 |
|
100 |
Vérification de l'affichage sur le dossier d'autorisation |
101 |
|
102 |
[Documentation] Vérifie l'affichage sur les dossiers d'autorisation. |
103 |
|
104 |
# On récupère le numéro du dossier d'autorisation depuis le numéro du DI |
105 |
${dossier_autorisation} = Get Substring ${di} 0 -2 |
106 |
# |
107 |
Depuis la page d'accueil guichet guichet |
108 |
# |
109 |
Depuis l'onglet des pièces du dossier d'autorisation ${dossier_autorisation} |
110 |
# On vérifie que le numéro du dossier d'instruction est affiché |
111 |
Page Should Contain ${di} |
112 |
# On vérifie que le nom du fichier est affiché |
113 |
Page Should Contain 20150920AUTPDG.pdf |
114 |
# On clique pour visualiser le document |
115 |
Wait Until Keyword Succeeds ${TIMEOUT} ${RETRY_INTERVAL} Click Element css=tr.col4 td.col-1 a.lienTable span.reqmo-16 |
116 |
Open PDF file |
117 |
# On vérifie la localisation du terrain |
118 |
Wait Until Keyword Succeeds 5 sec 0.2 sec Page Should Contain TEST IMPORT MANUEL 2 |
119 |
# On ferme le PDF |
120 |
Close PDF |
121 |
|
122 |
|
123 |
Vérification de l'affichage sur la demande d'avis |
124 |
|
125 |
[Documentation] Vérifie l'affichage sur les demandes d'avis. |
126 |
|
127 |
# |
128 |
Depuis la page d'accueil avec widget de redirection consu consu |
129 |
# |
130 |
Depuis l'onglet des pièces de la demande d'avis en cours du dossier d'instruction ${di} |
131 |
# On vérifie que le nom du fichier est affiché |
132 |
Page Should Contain 20150920AUTPDG.pdf |
133 |
# On clique pour visualiser le document |
134 |
Wait Until Keyword Succeeds ${TIMEOUT} ${RETRY_INTERVAL} Click Element css=tr.col3 td.firstcol a.lienTable span.reqmo-16 |
135 |
Open PDF file |
136 |
# On vérifie la localisation du terrain |
137 |
Wait Until Keyword Succeeds 5 sec 0.2 sec Page Should Contain TEST IMPORT MANUEL 2 |
138 |
# On ferme le PDF |
139 |
Close PDF |
140 |
# |
141 |
Se déconnecter avec widget de redirection |
142 |
|
143 |
|
144 |
Suppression d'une pièce |
145 |
|
146 |
[Documentation] Supprime une pièce. |
147 |
|
148 |
# |
149 |
Depuis la page d'accueil chef chef |
150 |
# |
151 |
Supprimer une pièce depuis le dossier d'instruction ${di} autres pièces composant le dossier (A0) |
152 |
|
153 |
|
154 |
TNR Ajout de pièces au DI en tant qu'instructeur |
155 |
|
156 |
[Documentation] L'utilisation d'un getval faisait qu'un dossier au hasard était |
157 |
... récupéré lors de l'ajout de pièces, quand ce dossier était clôturé l'ajout de |
158 |
... pièces produisait une erreur de droits insuffisants pour les instructeurs. |
159 |
|
160 |
# On crée une nouvelle demande pour le TNR |
161 |
Depuis la page d'accueil guichet guichet |
162 |
&{args_petitionnaire} = Create Dictionary |
163 |
... particulier_nom=Riel |
164 |
... particulier_prenom=Sébastien |
165 |
|
166 |
&{args_demande} = Create Dictionary |
167 |
... dossier_autorisation_type_detaille=Permis de construire pour une maison individuelle et / ou ses annexes |
168 |
... demande_type=Dépôt Initial |
169 |
${di_libelle} = Ajouter la nouvelle demande depuis le tableau de bord ${args_demande} ${args_petitionnaire} |
170 |
|
171 |
# Le bug provenait du fait que l'on instanciait à tort le premier document |
172 |
# numérisé créé en base de données. Celui-ci est lié au AZ 013055 12 00001P0. |
173 |
# Ainsi on testait toujours ce DI pour savoir s'il était clôturé et donc si |
174 |
# on avait le droit ou non d'ajouter une pièce. |
175 |
Depuis la page d'accueil instrpoly instrpoly |
176 |
Ajouter une instruction au DI AZ 013055 12 00001P0 ARRÊTÉ DE REFUS |
177 |
Click On Back Button In Subform |
178 |
# En cloturant le AZ 013055 12 00001P0 on reproduit le use case. |
179 |
Click On Link ARRÊTÉ DE REFUS |
180 |
Click On SubForm Portlet Action instruction finaliser |
181 |
Click On SubForm Portlet Action instruction definaliser |
182 |
Click On SubForm Portlet Action instruction modifier |
183 |
${today} = Date du jour FR |
184 |
Input Datepicker date_retour_rar ${today} |
185 |
Click On Submit Button In Subform |
186 |
|
187 |
# On teste l'ajout de pièces sur le DI de test en tant qu'instructeur |
188 |
# Cela doit fonctionner bien que le AZ 013055 12 00001P0 soit clôturé |
189 |
&{document_numerise_values} = Create Dictionary |
190 |
... uid_upload=testImportManuel.pdf |
191 |
... date_creation=15/09/2015 |
192 |
... document_numerise_type=autres pièces composant le dossier (A0) |
193 |
Ajouter une pièce depuis le dossier d'instruction ${di_libelle} ${document_numerise_values} |
194 |
|
195 |
# On supprime les événements d'instruction créés spécifiquement pour le TNR |
196 |
Depuis la page d'accueil admin admin |
197 |
Supprimer l'instruction AZ 013055 12 00001P0 Arrêté de Refus signé |
198 |
Supprimer l'instruction AZ 013055 12 00001P0 ARRÊTÉ DE REFUS |
199 |
|
200 |
|
201 |
TNR Vérification des métadonnées des fichiers |
202 |
|
203 |
[Documentation] Vérifie les métadonnées des fichiers créé par |
204 |
... l'application. |
205 |
|
206 |
# On crée une nouvelle demande pour le TNR |
207 |
Depuis la page d'accueil guichet guichet |
208 |
&{args_petitionnaire} = Create Dictionary |
209 |
... particulier_civilite=Monsieur |
210 |
... particulier_nom=Dufresne |
211 |
... particulier_prenom=Thierry |
212 |
# |
213 |
&{args_demande} = Create Dictionary |
214 |
... dossier_autorisation_type_detaille=Permis de construire pour une maison individuelle et / ou ses annexes |
215 |
... demande_type=Dépôt Initial |
216 |
# |
217 |
${di_metadata} = Ajouter la nouvelle demande depuis le tableau de bord ${args_demande} ${args_petitionnaire} |
218 |
${libelle_di_metadata} = Sans espace ${di_metadata} |
219 |
|
220 |
# On ajoute une pièce sur le dossier d'instruction initial |
221 |
Depuis la page d'accueil admin admin |
222 |
# Données de la pièce |
223 |
&{document_numerise_values} = Create Dictionary |
224 |
... uid_upload=testImportManuel.pdf |
225 |
... document_numerise_type=arrêté |
226 |
# |
227 |
Ajouter une pièce depuis le dossier d'instruction ${di_metadata} ${document_numerise_values} |
228 |
# On récupére l'UID de la pièce pour définir les chemins |
229 |
Depuis le contexte de la pièce par le dossier d'instruction ${di_metadata} arrêté |
230 |
Click On Subform Portlet Action document_numerise modifier |
231 |
${uid} = Get Value uid |
232 |
${path_1} = Get Substring ${uid} 0 2 |
233 |
${path_2} = Get Substring ${uid} 0 4 |
234 |
# On vérifie les métadonnées depuis le fichier ".info" dans le filesystem |
235 |
${file_info} = Get File ..${/}var${/}filestorage${/}${path_1}${/}${path_2}${/}${uid}.info |
236 |
Should Contain ${file_info} dossier=${libelle_di_metadata} |
237 |
Should Contain ${file_info} dossier_version=0 |
238 |
Should Contain ${file_info} typeInstruction=P |
239 |
|
240 |
# On accepte le dossier d'instruction initial |
241 |
Ajouter une instruction au DI ${di_metadata} accepter un dossier sans réserve |
242 |
|
243 |
# On ajoute un modificatif sur le dossier d'instruction |
244 |
Depuis la page d'accueil guichet guichet |
245 |
# |
246 |
&{args_demande} = Create Dictionary |
247 |
... demande_type=Demande de modification |
248 |
# |
249 |
${di_metadata_1} = Ajouter la demande sur existant depuis le tableau de bord ${di_metadata} ${args_demande} |
250 |
# On récupère le numéro du dossier sans espace |
251 |
${libelle_di_metadata_1} = Sans espace ${di_metadata_1} |
252 |
# On ajoute une pièce sur le dossier d'instruction de modification 1 |
253 |
Depuis la page d'accueil admin admin |
254 |
# Données de la pièce |
255 |
&{document_numerise_values} = Create Dictionary |
256 |
... uid_upload=testImportManuel.pdf |
257 |
... document_numerise_type=arrêté |
258 |
# |
259 |
Ajouter une pièce depuis le dossier d'instruction ${di_metadata_1} ${document_numerise_values} |
260 |
# On récupére l'UID de la pièce pour définir les chemins |
261 |
Depuis le contexte de la pièce par le dossier d'instruction ${di_metadata_1} arrêté |
262 |
Click On Subform Portlet Action document_numerise modifier |
263 |
${uid} = Get Value uid |
264 |
${path_1} = Get Substring ${uid} 0 2 |
265 |
${path_2} = Get Substring ${uid} 0 4 |
266 |
# On vérifie les métadonnées depuis le fichier ".info" dans le filesystem |
267 |
${file_info} = Get File ..${/}var${/}filestorage${/}${path_1}${/}${path_2}${/}${uid}.info |
268 |
Should Contain ${file_info} dossier=${libelle_di_metadata_1} |
269 |
Should Contain ${file_info} dossier_version=01 |
270 |
Should Contain ${file_info} typeInstruction=M |
271 |
|
272 |
# On accepte le dossier d'instruction de modification 1 |
273 |
Ajouter une instruction au DI ${di_metadata_1} accepter un dossier sans réserve |
274 |
|
275 |
# On ajoute un modificatif sur le dossier d'instruction |
276 |
Depuis la page d'accueil guichet guichet |
277 |
# |
278 |
&{args_demande} = Create Dictionary |
279 |
... demande_type=Demande de modification |
280 |
# |
281 |
${di_metadata_2} = Ajouter la demande sur existant depuis le tableau de bord ${di_metadata_1} ${args_demande} |
282 |
# On récupère le numéro du dossier sans espace |
283 |
${libelle_di_metadata_2} = Sans espace ${di_metadata_2} |
284 |
# On ajoute une pièce sur le dossier d'instruction de modification 2 |
285 |
Depuis la page d'accueil admin admin |
286 |
# Données de la pièce |
287 |
&{document_numerise_values} = Create Dictionary |
288 |
... uid_upload=testImportManuel.pdf |
289 |
... document_numerise_type=arrêté |
290 |
# |
291 |
Ajouter une pièce depuis le dossier d'instruction ${di_metadata_2} ${document_numerise_values} |
292 |
# On récupére l'UID de la pièce pour définir les chemins |
293 |
Depuis le contexte de la pièce par le dossier d'instruction ${di_metadata_2} arrêté |
294 |
Click On Subform Portlet Action document_numerise modifier |
295 |
${uid} = Get Value uid |
296 |
${path_1} = Get Substring ${uid} 0 2 |
297 |
${path_2} = Get Substring ${uid} 0 4 |
298 |
# On vérifie les métadonnées depuis le fichier ".info" dans le filesystem |
299 |
${file_info} = Get File ..${/}var${/}filestorage${/}${path_1}${/}${path_2}${/}${uid}.info |
300 |
Should Contain ${file_info} dossier=${libelle_di_metadata_2} |
301 |
Should Contain ${file_info} dossier_version=02 |
302 |
Should Contain ${file_info} typeInstruction=M |
303 |
|
304 |
# On ajoute une pièce sur le dossier d'instruction de modification 1 |
305 |
Depuis la page d'accueil admin admin |
306 |
# Données de la pièce |
307 |
&{document_numerise_values} = Create Dictionary |
308 |
... uid_upload=testImportManuel.pdf |
309 |
... document_numerise_type=arrêté de conformité |
310 |
# |
311 |
Ajouter une pièce depuis le dossier d'instruction ${di_metadata_1} ${document_numerise_values} |
312 |
# On récupére l'UID de la pièce pour définir les chemins |
313 |
Depuis le contexte de la pièce par le dossier d'instruction ${di_metadata_1} arrêté de conformité |
314 |
Click On Subform Portlet Action document_numerise modifier |
315 |
${uid} = Get Value uid |
316 |
${path_1} = Get Substring ${uid} 0 2 |
317 |
${path_2} = Get Substring ${uid} 0 4 |
318 |
# On vérifie les métadonnées depuis le fichier ".info" dans le filesystem |
319 |
${file_info} = Get File ..${/}var${/}filestorage${/}${path_1}${/}${path_2}${/}${uid}.info |
320 |
Should Contain ${file_info} dossier=${libelle_di_metadata_1} |
321 |
Should Contain ${file_info} dossier_version=01 |
322 |
Should Contain ${file_info} typeInstruction=M |
323 |
|
324 |
|
325 |
Téléchargement de l'intégralité des pièces |
326 |
|
327 |
[Documentation] Contrôle que l'action "télécharger toutes les pièces" dans l'onglet |
328 |
... Pièce(s) d'un dossier d'instruction, dans l'onglet Pièce(s) du DA et les demandes |
329 |
... d'avis produit bien une archive téléchargeable contenant toutes les pièces. |
330 |
|
331 |
Depuis la page d'accueil guichet guichet |
332 |
&{args_petitionnaire} = Create Dictionary |
333 |
... particulier_nom=Compagnon |
334 |
... particulier_prenom=Émilie |
335 |
|
336 |
&{args_demande} = Create Dictionary |
337 |
... dossier_autorisation_type_detaille=Permis de construire pour une maison individuelle et / ou ses annexes |
338 |
... demande_type=Dépôt Initial |
339 |
${di_libelle} = Ajouter la nouvelle demande depuis le tableau de bord ${args_demande} ${args_petitionnaire} |
340 |
|
341 |
Depuis la page d'accueil admin admin |
342 |
|
343 |
&{document_numerise_values} = Create Dictionary |
344 |
... uid_upload=testImportManuel.pdf |
345 |
... date_creation=31/03/2016 |
346 |
... document_numerise_type=autres pièces composant le dossier (A0) |
347 |
Ajouter une pièce depuis le dossier d'instruction ${di_libelle} ${document_numerise_values} |
348 |
|
349 |
&{document_numerise_values} = Create Dictionary |
350 |
... uid_upload=testImportManuel2.pdf |
351 |
... date_creation=30/03/2016 |
352 |
... document_numerise_type=autres pièces composant le dossier (A0) |
353 |
Ajouter une pièce depuis le dossier d'instruction ${di_libelle} ${document_numerise_values} |
354 |
|
355 |
# Pièce de type "arrêté retour prefecture" qui sera disponible depuis le DA |
356 |
&{document_numerise_values} = Create Dictionary |
357 |
... uid_upload=testImportManuel.pdf |
358 |
... date_creation=31/03/2016 |
359 |
... document_numerise_type=arrêté retour préfecture |
360 |
Ajouter une pièce depuis le dossier d'instruction ${di_libelle} ${document_numerise_values} |
361 |
|
362 |
Depuis la page d'accueil instr instr |
363 |
# Ajout d'une consultation au dossier pour que consu puisse accéder aux pièces |
364 |
Ajouter une consultation depuis un dossier ${di_libelle} 59.01 - Direction de l'Eau et de l'Assainissement |
365 |
|
366 |
Depuis l'onglet des pièces du dossier d'instruction ${di_libelle} |
367 |
${path_archive} ${archive_name} = Télécharger toutes les pièces |
368 |
|
369 |
# Composition du nom correct de l'archive zip |
370 |
${di_libelle_spaceless} = Sans espace ${di_libelle} |
371 |
${date_jour} = Date du jour EN |
372 |
${date_jour_sans_tirets} = STR_REPLACE - ${EMPTY} ${date_jour} |
373 |
${correct_archive_name_di} = Set Variable ${di_libelle_spaceless}_${date_jour_sans_tirets}.zip |
374 |
|
375 |
# Vérification du nom de l'archive, qui doit commencer par le n° de DI |
376 |
Should Be Equal ${correct_archive_name_di} ${archive_name} |
377 |
# L'archive doit contenir les 3 pièces du DI |
378 |
Archive Should Contain File ${path_archive} 20160331AUTPDG.pdf |
379 |
Archive Should Contain File ${path_archive} 20160330AUTPDG.pdf |
380 |
Archive Should Contain File ${path_archive} 20160331ART.pdf |
381 |
|
382 |
# Récupération de l'archive dans le contexte du DA du DI utilisé précédemment |
383 |
${da_libelle} = Get Substring ${di_libelle} 0 -2 |
384 |
${da_libelle_spaceless} = Sans espace ${da_libelle} |
385 |
${correct_archive_name_da} = Set Variable ${da_libelle_spaceless}_${date_jour_sans_tirets}.zip |
386 |
|
387 |
Depuis l'onglet des pièces du dossier d'autorisation ${da_libelle} |
388 |
${path_archive} ${archive_name} = Télécharger toutes les pièces |
389 |
|
390 |
# Le nom de l'archive doit commencer par le numéro de DA (sans le P0 du DI) |
391 |
Should Be Equal ${correct_archive_name_da} ${archive_name} |
392 |
Archive Should Contain File ${path_archive} 20160331AUTPDG.pdf |
393 |
Archive Should Contain File ${path_archive} 20160330AUTPDG.pdf |
394 |
Archive Should Contain File ${path_archive} 20160331ART.pdf |
395 |
|
396 |
# Récupération de l'archive depuis la demande d'avis en cours |
397 |
Depuis la page d'accueil avec widget de redirection consu consu |
398 |
Depuis la demande d'avis en cours du dossier ${di_libelle} |
399 |
On clique sur l'onglet document_numerise Pièce(s) |
400 |
|
401 |
${path_archive} ${archive_name} = Télécharger toutes les pièces |
402 |
|
403 |
Should Be Equal ${correct_archive_name_di} ${archive_name} |
404 |
Archive Should Contain File ${path_archive} 20160331AUTPDG.pdf |
405 |
Archive Should Contain File ${path_archive} 20160330AUTPDG.pdf |
406 |
Archive Should Contain File ${path_archive} 20160331ART.pdf |
407 |
|
408 |
# On rend l'avis sur la consultation pour qu'elle devienne "passée" |
409 |
On clique sur l'onglet main Demandes D'avis En Cours |
410 |
&{args_avis_consultation} = Create Dictionary |
411 |
... avis_consultation=Favorable |
412 |
... motivation=Pas de réserves |
413 |
... fichier_upload=testImportManuel.pdf |
414 |
|
415 |
Rendre l'avis sur la consultation du dossier ${di_libelle} ${args_avis_consultation} |
416 |
Depuis la demande d'avis passée du dossier ${di_libelle} |
417 |
On clique sur l'onglet document_numerise Pièce(s) |
418 |
|
419 |
${path_archive} ${archive_name} = Télécharger toutes les pièces |
420 |
|
421 |
Should Be Equal ${correct_archive_name_di} ${archive_name} |
422 |
Archive Should Contain File ${path_archive} 20160331AUTPDG.pdf |
423 |
Archive Should Contain File ${path_archive} 20160330AUTPDG.pdf |
424 |
Archive Should Contain File ${path_archive} 20160331ART.pdf |