import { FreeDatas2HTML, SearchEngine } from "../src/FreeDatas2HTML"; const errors=require("../src/errors.js"); const fixtures=require("./fixtures.js"); describe("Test du moteur de recherche.", () => { let converter: FreeDatas2HTML; let mySearch: SearchEngine; let searchElement : HTMLInputElement; beforeEach( async () => { document.body.insertAdjacentHTML("afterbegin", fixtures.datasViewEltHTML); converter=new FreeDatas2HTML("CSV"); converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" }); converter.datasViewElt={ id:"datas" }; await converter.run(); mySearch=new SearchEngine(converter, { id:"mySearch" }); }); afterEach( () => { document.body.removeChild(document.getElementById("fixture")); }); describe("Test des données de configuration.", () => { it("Doit avoir créé une instance de SearchEngine", () => { expect(mySearch).toBeInstanceOf(SearchEngine); }); it("Doit générer une erreur, si initialisé sans avoir au préalable chargé des données.", async () => { converter=new FreeDatas2HTML("CSV"); expect(() => { return new SearchEngine(converter, { id:"mySearch" }); }).toThrowError(errors.filterNeedDatas); converter.parser.datas2Parse="Z (numéro atomique),Élément,Symbole,Famille,Abondance des éléments dans la croûte terrestre (μg/k)"; await converter.run(); expect(() => { return new SearchEngine(converter, { id:"mySearch" }); }).toThrowError(errors.filterNeedDatas); }); it("Si une chaîne vide est transmise pour le texte du bouton, elle doit être ignorée.", () => { mySearch.btnTxt=""; expect(mySearch.btnTxt).toEqual("Search"); mySearch.btnTxt=" "; expect(mySearch.btnTxt).toEqual("Search"); }); it("Si une chaîne de + de 30 caractères est transmise pour le texte du bouton, elle doit être ignorée.", () => { mySearch.btnTxt="Si une chaîne de + de 30 caractères est transmise pour le texte du bouton, elle doit être ignorée."; expect(mySearch.btnTxt).toEqual("Search"); }); it("Toute chaîne de caractères valide doit être acceptée comme texte pour le bouton.", () => { mySearch.btnTxt="a"; expect(mySearch.btnTxt).toEqual("a"); mySearch.btnTxt=" aaa "; expect(mySearch.btnTxt).toEqual(" aaa "); }); it("Doit générer une erreur, si au moins un des numéros des champs sur lesquels effectuer les recherches n'existe pas dans les données.", () => { expect(() => { return new SearchEngine(converter, { id:"mySearch" }, [-1,0,2]); }).toThrowError(errors.searchFieldNotFound); expect(() => { return new SearchEngine(converter, { id:"mySearch" }, [0,1,10]); }).toThrowError(errors.searchFieldNotFound); expect(() => { return new SearchEngine(converter, { id:"mySearch" }, [0,1.1,10]); }).toThrowError(errors.searchFieldNotFound); }); it("Si tous numéros des champs sur lesquels effectuer les recherches existent dans les données, ils doivent être acceptés.", () => { expect(() => { return new SearchEngine(converter, { id:"mySearch" }, [0,2,3]); }).not.toThrowError(); mySearch=new SearchEngine(converter, { id:"mySearch" }, [0,2,3]); expect(mySearch.fields2Search).toEqual(["Z (numéro atomique)","Symbole","Famille"]); }); it("Un tableau vide pour les champs sur lesquels effectuer les recherche doit être accepté.", () => { expect(() => { return new SearchEngine(converter, { id:"mySearch" }, []); }).not.toThrowError(); expect(mySearch.fields2Search).toEqual(["Z (numéro atomique)","Élément","Symbole","Famille","Abondance des éléments dans la croûte terrestre (μg/k)"]); }); }); describe("Création du champ de recherche.", () => { it("Doit générer un élement et un bouton dans l'élément HTML indiqué avec les propriétés de base.", () => { mySearch.filter2HTML(); expect(document.getElementById("mySearch").innerHTML).toEqual(`
 
`); }); it("Doit prendre en compte l'éventuel label fourni pour le champ de recherche.", () => { mySearch.label="Qui cherche trouve ?"; mySearch.filter2HTML(); expect(document.getElementById("mySearch").innerHTML).toEqual(`
 
`); }); it("Doit prendre en compte l'éventuel texte personnalisé du bouton de recherche.", () => { mySearch.btnTxt="Qui cherche trouve ?"; mySearch.filter2HTML(); expect(document.getElementById("mySearch").innerHTML).toEqual(`
 
`); }); it("Doit indiquer l'éventuel nombre de caractères requis pour lancer la recherche.", () => { mySearch.nbCharsForSearch=2; mySearch.filter2HTML(); expect(document.getElementById("mySearch").innerHTML).toEqual(`
 
`); }); it("Doit indiquer l'éventuel nombre de caractères requis pour lancer la recherche en utilisant un texte personnalisé.", () => { mySearch.nbCharsForSearch=3; mySearch.placeholder="Saisir NB caractères pour lancer votre recherche."; mySearch.filter2HTML(); expect(document.getElementById("mySearch").innerHTML).toEqual(`
 
`); }); it("Doit accepter un texte d'indication libre, même quand il n'y a pas de nombre de caractères requis.", () => { mySearch.placeholder="Bonne chance !"; mySearch.filter2HTML(); expect(document.getElementById("mySearch").innerHTML).toEqual(`
 
`); }); it("Doit prendre en compte l'ensemble des attributs renseignés.", () => { mySearch.label="Qui cherche trouve ?"; mySearch.btnTxt="Qui cherche trouve ?"; mySearch.nbCharsForSearch=3; mySearch.placeholder="Saisir NB caractères pour lancer votre recherche."; mySearch.filter2HTML(); expect(document.getElementById("mySearch").innerHTML).toEqual(`
 
`); }); }); describe("Lancement de la recherche.", () => { let searchInput: HTMLInputElement, searchBtn: HTMLInputElement; beforeEach( async () => { mySearch.filter2HTML(); searchInput=document.getElementById("freeDatas2HTMLSearchTxt") as HTMLInputElement; searchBtn=document.getElementById("freeDatas2HTMLSearchBtn") as HTMLInputElement; }); it("Le clic sur le bouton SUBMIT doit appeler la fonction actualisant l'affichage.", () => { spyOn(converter, "refreshView"); searchBtn.click(); expect(converter.refreshView).toHaveBeenCalledTimes(1); searchInput.value="z"; searchBtn.click(); expect(converter.refreshView).toHaveBeenCalledTimes(2); }); it("Le clic sur le bouton SUBMIT doit appeler la fonction actualisant l'affichage, pour peu que le nombre de caractères défini soit saisi.", () => { spyOn(converter, "refreshView"); mySearch.nbCharsForSearch=3; searchInput.value="z"; searchBtn.click(); expect(converter.refreshView).not.toHaveBeenCalled(); searchInput.value="zz"; searchBtn.click(); expect(converter.refreshView).not.toHaveBeenCalled(); searchInput.value="zzz"; searchBtn.click(); expect(converter.refreshView).toHaveBeenCalledTimes(1); // Il est toujours possible d'annuler la recherche : searchInput.value=""; searchBtn.click(); expect(converter.refreshView).toHaveBeenCalledTimes(2); }); it("Si demandé, l'actualisation est lancée à chaque saisie, y compris si le champ est vide.", () => { spyOn(converter, "refreshView"); mySearch.automaticSearch=true; searchInput.value="z"; searchInput.dispatchEvent(new Event("input")); expect(converter.refreshView).toHaveBeenCalledTimes(1); searchInput.value="zz"; searchInput.dispatchEvent(new Event("input")); expect(converter.refreshView).toHaveBeenCalledTimes(2); searchInput.value=""; searchInput.dispatchEvent(new Event("input")); expect(converter.refreshView).toHaveBeenCalledTimes(3); }); it("Si demandé, l'actualisation est lancée à chaque saisie, mais avec un minimum de caractères défini.", () => { spyOn(converter, "refreshView"); mySearch.nbCharsForSearch=3; mySearch.automaticSearch=true; searchInput.value="z"; searchInput.dispatchEvent(new Event("input")); expect(converter.refreshView).not.toHaveBeenCalled(); searchInput.value="zz"; searchInput.dispatchEvent(new Event("input")); expect(converter.refreshView).not.toHaveBeenCalled(); searchInput.value="zzz"; searchInput.dispatchEvent(new Event("input")); expect(converter.refreshView).toHaveBeenCalledTimes(1); searchInput.value="zz"; searchInput.dispatchEvent(new Event("input")); expect(converter.refreshView).toHaveBeenCalledTimes(1); // Il est toujours possible d'annuler la recherche : searchInput.value=""; searchInput.dispatchEvent(new Event("input")); expect(converter.refreshView).toHaveBeenCalledTimes(2); }); it("Doit toujours retourner true si le champ de recherche est vide.", () => { mySearch.automaticSearch=true; // Le champ est vide par défaut : searchInput.dispatchEvent(new Event("input")); expect(mySearch.dataIsOk({ "nom" : "oui" })).toBeTrue(); // Même comportement après un retour : searchInput.value="z"; searchInput.dispatchEvent(new Event("input")); searchInput.value=""; searchInput.dispatchEvent(new Event("input")); expect(mySearch.dataIsOk({ "nom" : "oui" })).toBeTrue(); }); describe("Filtre des données", () => { beforeEach( async () => { mySearch.automaticSearch=true; }); it("Doit retourner false, si la donnée testée ne possède aucun des champs sur lesquels est lancée la recherche.", () => { searchInput.value="lithium"; searchInput.dispatchEvent(new Event("input")); expect(mySearch.dataIsOk({ "nom" : "lithium" })).toBeFalse(); }); it("Doit retourner false, si une donnée testée ne correspond pas à la valeur cherchée.", async () => { searchInput.value="Halogène"; searchInput.dispatchEvent(new Event("input")); expect(mySearch.dataIsOk({ "Famille": "Halogene" })).toBeFalse();// sensible aux accents }); it("Doit retourner true, si la valeur recherchée est retrouvée dans la donnée recherchée, sans prendre en compte la casse.", () => { // Expression exacte : searchInput.value="Halogène"; searchInput.dispatchEvent(new Event("input")); expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue(); // Expression partielle : searchInput.value="gène"; searchInput.dispatchEvent(new Event("input")); expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue(); // Insensible à casse : searchInput.value="halo"; searchInput.dispatchEvent(new Event("input")); expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue(); }); }); }); });