*** Settings *** Documentation Test de l'API JSON ... ... Ce test vérifie le bon fonctionnement de l'API JSON exposant les données ... de l'application OpenResultat. Il crée un profil api_json avec les ... permissions minimales, un utilisateur associé, puis teste chaque endpoint ... JSON avec cet utilisateur. ... ... Les tests vérifient : ... - L'accès aux endpoints json_list (action 997) pour chaque entité ... - L'accès aux endpoints json_data (action 998) pour chaque entité ... - Le format et le contenu des réponses JSON ... - Les données spécifiques de l'élection (candidats, unités, participations, résultats) ... - Que l'utilisateur api_json avec le profil dédié peut accéder aux endpoints Resource resources/resources.robot Suite Setup For Suite Setup Suite Teardown For Suite Teardown *** Variables *** # Préfixe unique pour identifier les données de ce test ${API_TEST_PREFIX} API_JSON_TEST_ # URLs des endpoints JSON ${JSON_LIST_ACTION} 997 ${JSON_DATA_ACTION} 998 # Credentials de l'utilisateur API JSON avec permissions minimales ${API_JSON_USER} api_json ${API_JSON_PASSWORD} api_json # Liste des permissions nécessaires pour l'API JSON @{API_JSON_PERMISSIONS} ... password ... menu_application ... election_tab ... election_consulter ... candidat_tab ... candidat_consulter ... tranche_tab ... tranche_consulter ... type_election_tab ... type_election_consulter ... type_unite_tab ... type_unite_consulter ... unite_tab ... unite_consulter ... canton_tab ... canton_consulter ... circonscription_tab ... circonscription_consulter ... commune_tab ... commune_consulter ... departement_tab ... departement_consulter ... parti_politique_tab ... parti_politique_consulter *** Test Cases *** Constitution du jeu de Données [Documentation] L'objet de ce 'Test Case' est de constituer un jeu de ... données cohérent pour les scénarios fonctionnels qui suivent. ... Crée les données de test nécessaires pour valider ... le bon fonctionnement de l'API JSON. Chaque donnée est préfixée ... avec API_JSON_TEST_ pour être facilement identifiable. ... Crée le profil api_json avec les permissions minimales ... nécessaires pour accéder aux endpoints JSON, puis crée l'utilisateur ... api_json associé à ce profil. [Tags] api_json setup profil Depuis la page d'accueil admin admin ## Création du profil et de l'utilisateur api_json # Création du profil api_json Depuis le listing om_profil Click On Add Button Input Text libelle ${API_JSON_USER} Input Text hierarchie 0 Click On Submit Button La page ne doit pas contenir d'erreur # Récupération de l'ID du profil créé ${id_profil} = Get Text css=span#om_profil Set Suite Variable ${ID_PROFIL_API} ${id_profil} # Ajout des permissions au profil :FOR ${permission} IN @{API_JSON_PERMISSIONS} \ Ajouter permission au profil ${id_profil} ${permission} # Création de l'utilisateur api_json Depuis le listing om_utilisateur Click On Add Button Input Text nom ${API_JSON_USER} Input Text email ${API_JSON_USER}@test.test Input Text login ${API_JSON_USER} Input Text pwd ${API_JSON_PASSWORD} Select From List By Label om_profil ${API_JSON_USER} Click On Submit Button La page ne doit pas contenir d'erreur ## Création du jeu de données pour les tests API JSON # Création d'un type d'unité pour le test &{type_unite} = BuiltIn.Create Dictionary ... libelle=${API_TEST_PREFIX}type_unite ... hierarchie=99 ... bureau_vote=false ${id_type_unite} = Ajouter type_unite ${type_unite} Set Suite Variable ${ID_TYPE_UNITE_API} ${id_type_unite} # Création d'un type d'élection pour le test &{type_election} = BuiltIn.Create Dictionary ... libelle=${API_TEST_PREFIX}type_election ... code=APITE ... prefecture=99 ${id_type_election} = Ajouter type_election ${type_election} Set Suite Variable ${ID_TYPE_ELECTION_API} ${id_type_election} # Création d'un canton pour le test &{canton} = BuiltIn.Create Dictionary ... libelle=${API_TEST_PREFIX}canton ... code=APIC ... prefecture=99 ${id_canton} = Ajouter canton ${canton} Set Suite Variable ${ID_CANTON_API} ${id_canton} # Création d'une circonscription pour le test &{circonscription} = BuiltIn.Create Dictionary ... libelle=${API_TEST_PREFIX}circonscription ... code=APICI ... prefecture=99 ${id_circonscription} = Ajouter circonscription ${circonscription} Set Suite Variable ${ID_CIRCONSCRIPTION_API} ${id_circonscription} # Création d'une commune pour le test &{commune} = BuiltIn.Create Dictionary ... libelle=${API_TEST_PREFIX}commune ... code=APICO ... prefecture=99 ${id_commune} = Ajouter commune ${commune} Set Suite Variable ${ID_COMMUNE_API} ${id_commune} # Création d'un département pour le test &{departement} = BuiltIn.Create Dictionary ... libelle=${API_TEST_PREFIX}departement ... code=APID ... prefecture=99 ${id_departement} = Ajouter departement ${departement} Set Suite Variable ${ID_DEPARTEMENT_API} ${id_departement} # Création d'une tranche horaire pour le test (format HH:MM) &{tranche} = BuiltIn.Create Dictionary ... libelle=23:59 ... ordre=9999 ${id_tranche} = Ajouter tranche ${tranche} Set Suite Variable ${ID_TRANCHE_API} ${id_tranche} # Création d'un parti politique pour le test ${couleur_parti} = Set Variable \#ff5733 &{parti_politique} = BuiltIn.Create Dictionary ... libelle=${API_TEST_PREFIX}parti_politique ... couleur=${couleur_parti} ${id_parti_politique} = Ajouter parti_politique ${parti_politique} Set Suite Variable ${ID_PARTI_POLITIQUE_API} ${id_parti_politique} Set Suite Variable ${COULEUR_PARTI_API} ${couleur_parti} # Création d'un candidat pour le test &{candidat} = BuiltIn.Create Dictionary ... libelle=${API_TEST_PREFIX}candidat ${id_candidat} = Ajouter candidat ${candidat} Set Suite Variable ${ID_CANDIDAT_API} ${id_candidat} # Création d'une unité pour le test &{unite} = BuiltIn.Create Dictionary ... libelle=${API_TEST_PREFIX}unite ... type_unite=${API_TEST_PREFIX}type_unite ... ordre=999 ... perimetre=true ${id_unite} = Ajouter unite ${unite} Set Suite Variable ${ID_UNITE_API} ${id_unite} # Création d'une élection pour le test &{election} = BuiltIn.Create Dictionary ... libelle=${API_TEST_PREFIX}election ... code=apijson ... type_election=${API_TEST_PREFIX}type_election ... date=01/01/2030 ... perimetre=${API_TEST_PREFIX}unite ... heure_ouverture=08:00:00 ... heure_fermeture=20:00:00 ${id_election} = Ajouter election ${election} Set Suite Variable ${ID_ELECTION_API} ${id_election} # Ajout du candidat à l'élection avec une couleur spécifique ${couleur_candidat} = Set Variable \#3498db &{election_candidat} = BuiltIn.Create Dictionary ... candidat=${API_TEST_PREFIX}candidat ... ordre=1 ... couleur=${couleur_candidat} ${id_election_candidat} = Ajouter election_candidat ${election_candidat} ${id_election} Set Suite Variable ${ID_ELECTION_CANDIDAT_API} ${id_election_candidat} Set Suite Variable ${COULEUR_CANDIDAT_API} ${couleur_candidat} # ============================================================================= # TESTS API JSON AVEC UTILISATEUR api_json (permissions minimales) # ============================================================================= Endpoint JSON - Liste des types d'unités [Documentation] Vérifie l'endpoint json_list pour type_unite avec l'utilisateur ... api_json qui possède uniquement les permissions de consultation. [Tags] api_json type_unite Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON list type_unite La réponse JSON list doit contenir l'enregistrement ${response} libelle ${API_TEST_PREFIX}type_unite Endpoint JSON - Données d'un type d'unité [Documentation] Vérifie l'endpoint json_data pour type_unite. [Tags] api_json type_unite Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON data type_unite ${ID_TYPE_UNITE_API} Dictionary Should Contain Key ${response} libelle ${libelle} = Get From Dictionary ${response} libelle Should Be Equal ${libelle} ${API_TEST_PREFIX}type_unite Endpoint JSON - Liste des types d'élections [Documentation] Vérifie l'endpoint json_list pour type_election. [Tags] api_json type_election Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON list type_election La réponse JSON list doit contenir l'enregistrement ${response} libelle ${API_TEST_PREFIX}type_election Endpoint JSON - Données d'un type d'élection [Documentation] Vérifie l'endpoint json_data pour type_election. [Tags] api_json type_election Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON data type_election ${ID_TYPE_ELECTION_API} Dictionary Should Contain Key ${response} libelle ${libelle} = Get From Dictionary ${response} libelle Should Be Equal ${libelle} ${API_TEST_PREFIX}type_election Endpoint JSON - Liste des cantons [Documentation] Vérifie l'endpoint json_list pour canton. [Tags] api_json canton Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON list canton La réponse JSON list doit contenir l'enregistrement ${response} libelle ${API_TEST_PREFIX}canton Endpoint JSON - Données d'un canton [Documentation] Vérifie l'endpoint json_data pour canton. [Tags] api_json canton Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON data canton ${ID_CANTON_API} Dictionary Should Contain Key ${response} libelle ${libelle} = Get From Dictionary ${response} libelle Should Be Equal ${libelle} ${API_TEST_PREFIX}canton ${code} = Get From Dictionary ${response} code Should Be Equal ${code} APIC Endpoint JSON - Liste des circonscriptions [Documentation] Vérifie l'endpoint json_list pour circonscription. [Tags] api_json circonscription Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON list circonscription La réponse JSON list doit contenir l'enregistrement ${response} libelle ${API_TEST_PREFIX}circonscription Endpoint JSON - Données d'une circonscription [Documentation] Vérifie l'endpoint json_data pour circonscription. [Tags] api_json circonscription Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON data circonscription ${ID_CIRCONSCRIPTION_API} Dictionary Should Contain Key ${response} libelle ${libelle} = Get From Dictionary ${response} libelle Should Be Equal ${libelle} ${API_TEST_PREFIX}circonscription ${code} = Get From Dictionary ${response} code Should Be Equal ${code} APICI Endpoint JSON - Liste des communes [Documentation] Vérifie l'endpoint json_list pour commune. [Tags] api_json commune Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON list commune La réponse JSON list doit contenir l'enregistrement ${response} libelle ${API_TEST_PREFIX}commune Endpoint JSON - Données d'une commune [Documentation] Vérifie l'endpoint json_data pour commune. [Tags] api_json commune Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON data commune ${ID_COMMUNE_API} Dictionary Should Contain Key ${response} libelle ${libelle} = Get From Dictionary ${response} libelle Should Be Equal ${libelle} ${API_TEST_PREFIX}commune ${code} = Get From Dictionary ${response} code Should Be Equal ${code} APICO Endpoint JSON - Liste des départements [Documentation] Vérifie l'endpoint json_list pour departement. [Tags] api_json departement Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON list departement La réponse JSON list doit contenir l'enregistrement ${response} libelle ${API_TEST_PREFIX}departement Endpoint JSON - Données d'un département [Documentation] Vérifie l'endpoint json_data pour departement. [Tags] api_json departement Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON data departement ${ID_DEPARTEMENT_API} Dictionary Should Contain Key ${response} libelle ${libelle} = Get From Dictionary ${response} libelle Should Be Equal ${libelle} ${API_TEST_PREFIX}departement ${code} = Get From Dictionary ${response} code Should Be Equal ${code} APID Endpoint JSON - Liste des tranches [Documentation] Vérifie l'endpoint json_list pour tranche. [Tags] api_json tranche Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON list tranche # Le libellé de la tranche est stocké avec les secondes (23:59:00) La réponse JSON list doit contenir l'enregistrement partiel ${response} libelle 23:59 Endpoint JSON - Données d'une tranche [Documentation] Vérifie l'endpoint json_data pour tranche. [Tags] api_json tranche Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON data tranche ${ID_TRANCHE_API} Dictionary Should Contain Key ${response} libelle ${libelle} = Get From Dictionary ${response} libelle # Le libellé de la tranche est stocké avec les secondes (23:59:00) Should Contain ${libelle} 23:59 Endpoint JSON - Liste des candidats [Documentation] Vérifie l'endpoint json_list pour candidat. [Tags] api_json candidat Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON list candidat La réponse JSON list doit contenir l'enregistrement ${response} libelle ${API_TEST_PREFIX}candidat Endpoint JSON - Données d'un candidat [Documentation] Vérifie l'endpoint json_data pour candidat. [Tags] api_json candidat Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON data candidat ${ID_CANDIDAT_API} Dictionary Should Contain Key ${response} libelle ${libelle} = Get From Dictionary ${response} libelle Should Be Equal ${libelle} ${API_TEST_PREFIX}candidat Endpoint JSON - Liste des partis politiques [Documentation] Vérifie l'endpoint json_list pour parti_politique. [Tags] api_json parti_politique Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON list parti_politique La réponse JSON list doit contenir l'enregistrement ${response} libelle ${API_TEST_PREFIX}parti_politique # Vérifie que la couleur est présente dans les éléments de la liste La réponse JSON list doit contenir l'enregistrement avec couleur ${response} ${API_TEST_PREFIX}parti_politique ${COULEUR_PARTI_API} Endpoint JSON - Données d'un parti politique [Documentation] Vérifie l'endpoint json_data pour parti_politique. ... Vérifie également la présence du champ couleur dans la réponse. [Tags] api_json parti_politique Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON data parti_politique ${ID_PARTI_POLITIQUE_API} Dictionary Should Contain Key ${response} libelle ${libelle} = Get From Dictionary ${response} libelle Should Be Equal ${libelle} ${API_TEST_PREFIX}parti_politique # Vérification de la présence et de la valeur du champ couleur Dictionary Should Contain Key ${response} couleur ${couleur} = Get From Dictionary ${response} couleur Should Be Equal ${couleur} ${COULEUR_PARTI_API} Endpoint JSON - Liste des unités [Documentation] Vérifie l'endpoint json_list pour unite. [Tags] api_json unite Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON list unite La réponse JSON list doit contenir l'enregistrement ${response} libelle ${API_TEST_PREFIX}unite Endpoint JSON - Données d'une unité [Documentation] Vérifie l'endpoint json_data pour unite. [Tags] api_json unite Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON data unite ${ID_UNITE_API} Dictionary Should Contain Key ${response} libelle ${libelle} = Get From Dictionary ${response} libelle Should Be Equal ${libelle} ${API_TEST_PREFIX}unite Endpoint JSON - Liste des élections [Documentation] Vérifie l'endpoint json_list pour election. [Tags] api_json election Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON list election La réponse JSON list doit contenir l'enregistrement ${response} libelle ${API_TEST_PREFIX}election Endpoint JSON - Données d'une élection [Documentation] Vérifie l'endpoint json_data pour election. ... Vérifie également la présence des sous-tableaux candidats, unites, ... participations et resultats propres à l'API élection. ... Vérifie que la couleur du candidat est bien présente dans le tableau candidats. [Tags] api_json election Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON data election ${ID_ELECTION_API} # Vérification des données de base Dictionary Should Contain Key ${response} libelle ${libelle} = Get From Dictionary ${response} libelle Should Be Equal ${libelle} ${API_TEST_PREFIX}election ${code} = Get From Dictionary ${response} code Should Be Equal ${code} apijson # Vérification de la présence des sous-tableaux spécifiques à l'élection Dictionary Should Contain Key ${response} candidats Dictionary Should Contain Key ${response} unites Dictionary Should Contain Key ${response} participations Dictionary Should Contain Key ${response} resultats # Vérification que la couleur du candidat est présente dans le tableau candidats ${candidats} = Get From Dictionary ${response} candidats Le tableau candidats doit contenir la couleur ${candidats} ${ID_ELECTION_CANDIDAT_API} ${COULEUR_CANDIDAT_API} # ============================================================================= # TESTS DE VALIDATION DU FORMAT DES RÉPONSES # ============================================================================= Vérification format réponse json_list [Documentation] Vérifie que la réponse json_list est bien un tableau JSON ... avec les champs attendus pour chaque enregistrement. [Tags] api_json format Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON list candidat # Vérifie que c'est bien une liste ${length} = Get Length ${response} Should Be True ${length} > 0 # Vérifie la structure du premier élément ${first_item} = Get From List ${response} 0 Dictionary Should Contain Key ${first_item} candidat Dictionary Should Contain Key ${first_item} libelle Vérification format réponse json_data [Documentation] Vérifie que la réponse json_data est bien un objet JSON ... avec les champs attendus. [Tags] api_json format Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON data candidat ${ID_CANDIDAT_API} # Vérifie que c'est bien un dictionnaire avec les champs attendus Dictionary Should Contain Key ${response} candidat Dictionary Should Contain Key ${response} libelle # Vérifie que les valeurs ne contiennent pas de balises HTML (nettoyage strip_tags) ${libelle} = Get From Dictionary ${response} libelle Should Not Contain ${libelle} < Vérification données élection complète [Documentation] Vérifie en détail la structure des données retournées pour ... une élection, notamment la présence des sous-tableaux. [Tags] api_json election format Depuis la page d'accueil ${API_JSON_USER} ${API_JSON_PASSWORD} ${response} = Appeler endpoint JSON data election ${ID_ELECTION_API} # Vérification que les sous-tableaux sont présents # Note: candidats peut être une liste vide [] s'il n'y a pas de candidats liés Dictionary Should Contain Key ${response} candidats Dictionary Should Contain Key ${response} unites Dictionary Should Contain Key ${response} participations Dictionary Should Contain Key ${response} resultats *** Keywords *** Ajouter permission au profil [Documentation] Ajoute une permission (droit) au profil spécifié. [Arguments] ${id_profil} ${permission} # Accès au contexte du profil Go To ${PROJECT_URL}${OM_ROUTE_FORM}&obj=om_profil&action=3&idx=${id_profil} La page ne doit pas contenir d'erreur # Clic sur l'onglet des droits On clique sur l'onglet om_droit Droit # Ajout du droit Wait Until Element Is Visible css=a#action-soustab-om_droit-corner-ajouter Click Element css=a#action-soustab-om_droit-corner-ajouter Wait Until Element Is Visible css=div#sousform-om_droit input#libelle Input Text css=div#sousform-om_droit input#libelle ${permission} Click On Submit Button In Subform Appeler endpoint JSON list [Documentation] Appelle l'endpoint json_list (action 997) pour l'objet spécifié ... et retourne la réponse JSON parsée. [Arguments] ${obj} # Navigation vers l'endpoint JSON Go To ${PROJECT_URL}${OM_ROUTE_FORM}&obj=${obj}&action=${JSON_LIST_ACTION} La page ne doit pas contenir d'erreur # Récupération du contenu JSON depuis le conteneur ${json_text} = Get Text css=#form-container ${json_response} = Evaluate json.loads('''${json_text}''') json [Return] ${json_response} Appeler endpoint JSON data [Documentation] Appelle l'endpoint json_data (action 998) pour l'objet et l'ID spécifiés ... et retourne la réponse JSON parsée. [Arguments] ${obj} ${idx} # Navigation vers l'endpoint JSON Go To ${PROJECT_URL}${OM_ROUTE_FORM}&obj=${obj}&action=${JSON_DATA_ACTION}&idx=${idx} La page ne doit pas contenir d'erreur # Récupération du contenu JSON depuis le conteneur ${json_text} = Get Text css=#form-container ${json_response} = Evaluate json.loads('''${json_text}''') json [Return] ${json_response} La réponse JSON list doit contenir l'enregistrement [Documentation] Vérifie que la liste JSON contient au moins un enregistrement ... dont le champ spécifié a la valeur attendue (égalité stricte). [Arguments] ${json_list} ${field} ${expected_value} ${found} = Set Variable ${False} :FOR ${item} IN @{json_list} \ ${value} = Get From Dictionary ${item} ${field} \ ${match} = Run Keyword And Return Status Should Be Equal ${value} ${expected_value} \ ${found} = Set Variable If ${match} ${True} ${found} \ Exit For Loop If ${found} Should Be True ${found} ... L'enregistrement avec ${field}=${expected_value} n'a pas été trouvé dans la liste JSON La réponse JSON list doit contenir l'enregistrement partiel [Documentation] Vérifie que la liste JSON contient au moins un enregistrement ... dont le champ spécifié contient la valeur attendue (correspondance partielle). [Arguments] ${json_list} ${field} ${expected_value} ${found} = Set Variable ${False} :FOR ${item} IN @{json_list} \ ${value} = Get From Dictionary ${item} ${field} \ ${match} = Run Keyword And Return Status Should Contain ${value} ${expected_value} \ ${found} = Set Variable If ${match} ${True} ${found} \ Exit For Loop If ${found} Should Be True ${found} ... L'enregistrement contenant ${field}~=${expected_value} n'a pas été trouvé dans la liste JSON La réponse JSON list doit contenir l'enregistrement avec couleur [Documentation] Vérifie que la liste JSON contient au moins un enregistrement ... de parti_politique avec le libellé et la couleur attendus. [Arguments] ${json_list} ${expected_libelle} ${expected_couleur} ${found} = Set Variable ${False} :FOR ${item} IN @{json_list} \ ${libelle} = Get From Dictionary ${item} libelle \ ${libelle_match} = Run Keyword And Return Status Should Be Equal ${libelle} ${expected_libelle} \ ${has_couleur} = Run Keyword And Return Status Dictionary Should Contain Key ${item} couleur \ Continue For Loop If not ${libelle_match} \ Should Be True ${has_couleur} Le champ couleur est absent pour le parti ${expected_libelle} \ ${couleur} = Get From Dictionary ${item} couleur \ Should Be Equal ${couleur} ${expected_couleur} \ ${found} = Set Variable ${True} \ Exit For Loop If ${found} Should Be True ${found} ... L'enregistrement parti_politique avec libelle=${expected_libelle} et couleur=${expected_couleur} n'a pas été trouvé dans la liste JSON Le tableau candidats doit contenir la couleur [Documentation] Vérifie que le tableau candidats de l'élection contient ... un candidat avec l'identifiant et la couleur attendus. [Arguments] ${candidats_dict} ${expected_id} ${expected_couleur} # Le tableau candidats est un dictionnaire indexé par election_candidat Dictionary Should Contain Key ${candidats_dict} ${expected_id} ... Le candidat ${expected_id} n'a pas été trouvé dans le tableau candidats ${candidat} = Get From Dictionary ${candidats_dict} ${expected_id} Dictionary Should Contain Key ${candidat} couleur ... Le champ couleur est absent pour le candidat ${expected_id} ${couleur} = Get From Dictionary ${candidat} couleur Should Be Equal ${couleur} ${expected_couleur} ... La couleur du candidat ${expected_id} ne correspond pas : ${couleur} != ${expected_couleur}