329 lines
18 KiB
TypeScript
329 lines
18 KiB
TypeScript
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 mySearch=new SearchEngine(converter, { id:"mySearch" }, [0,2,3]); }).not.toThrowError();
|
|
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 mySearch=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 <input> et un bouton <submit> dans l'élément HTML indiqué avec les propriétés de base.", () =>
|
|
{
|
|
mySearch.filter2HTML();
|
|
expect(document.getElementById("mySearch").innerHTML).toEqual(`<form id="freeDatas2HTMLSearch"><input type="search" id="freeDatas2HTMLSearchTxt" name="freeDatas2HTMLSearchTxt"> <input type="submit" id="freeDatas2HTMLSearchBtn" value="Search"></form>`);
|
|
});
|
|
|
|
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(`<form id="freeDatas2HTMLSearch"><label for="freeDatas2HTMLSearchTxt">Qui cherche trouve ?</label><input type="search" id="freeDatas2HTMLSearchTxt" name="freeDatas2HTMLSearchTxt"> <input type="submit" id="freeDatas2HTMLSearchBtn" value="Search"></form>`);
|
|
});
|
|
|
|
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(`<form id="freeDatas2HTMLSearch"><input type="search" id="freeDatas2HTMLSearchTxt" name="freeDatas2HTMLSearchTxt"> <input type="submit" id="freeDatas2HTMLSearchBtn" value="Qui cherche trouve ?"></form>`);
|
|
});
|
|
|
|
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(`<form id="freeDatas2HTMLSearch"><input type="search" id="freeDatas2HTMLSearchTxt" name="freeDatas2HTMLSearchTxt" placeholder="Please enter at least 2 characters."> <input type="submit" id="freeDatas2HTMLSearchBtn" value="Search"></form>`);
|
|
});
|
|
|
|
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(`<form id="freeDatas2HTMLSearch"><input type="search" id="freeDatas2HTMLSearchTxt" name="freeDatas2HTMLSearchTxt" placeholder="Saisir 3 caractères pour lancer votre recherche."> <input type="submit" id="freeDatas2HTMLSearchBtn" value="Search"></form>`);
|
|
});
|
|
|
|
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(`<form id="freeDatas2HTMLSearch"><input type="search" id="freeDatas2HTMLSearchTxt" name="freeDatas2HTMLSearchTxt" placeholder="Bonne chance !"> <input type="submit" id="freeDatas2HTMLSearchBtn" value="Search"></form>`);
|
|
});
|
|
|
|
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(`<form id="freeDatas2HTMLSearch"><label for="freeDatas2HTMLSearchTxt">Qui cherche trouve ?</label><input type="search" id="freeDatas2HTMLSearchTxt" name="freeDatas2HTMLSearchTxt" placeholder="Saisir 3 caractères pour lancer votre recherche."> <input type="submit" id="freeDatas2HTMLSearchBtn" value="Qui cherche trouve ?"></form>`);
|
|
});
|
|
});
|
|
|
|
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("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);
|
|
// Les espaces entourant la valeur saisie doivent être ignorés dans le décompte des caractères :
|
|
searchInput.value=" zz";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(converter.refreshView).toHaveBeenCalledTimes(2);
|
|
searchInput.value="zz ";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(converter.refreshView).toHaveBeenCalledTimes(2);
|
|
searchInput.value=" zz ";
|
|
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();
|
|
// Y compris si il y a seulement des espaces :
|
|
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="Hallogène";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeFalse();
|
|
});
|
|
|
|
it("Doit retourner true, si la valeur recherchée est trouvée dans la donnée recherchée, sans prendre en compte la casse, ni les espaces entourant la saisie.", () =>
|
|
{
|
|
// 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();
|
|
// Espace entourant la saisie ignorés :
|
|
searchInput.value=" halo ";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue();
|
|
// Par défaut, la recherche doit être tolérante à la casse, à la présence ou non d'accent et ignorer les caractères n'étant ni des lettres, ni des chiffres
|
|
searchInput.value="Halogene";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue();
|
|
searchInput.value="halogène";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue();
|
|
searchInput.value="#Halogène";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeTrue();
|
|
});
|
|
|
|
it("Si demandé doit traiter les données avant de les comparer de manière à prendre en compte les accents, majuscules ou caractères spéciaux.", () =>
|
|
{
|
|
// Sensible à casse :
|
|
mySearch.searchMode.caseOff=false;
|
|
searchInput.value="halogène";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeFalse();
|
|
searchInput.value="Halogène";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(mySearch.dataIsOk({ "Famille": "halogène" })).toBeFalse();
|
|
// Sensible aux accents :
|
|
mySearch.searchMode.accentOff=false;
|
|
searchInput.value="Halogene";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeFalse();
|
|
searchInput.value="Halogène";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(mySearch.dataIsOk({ "Famille": "Halogene" })).toBeFalse();
|
|
// Prise en compte des caractères spéciaux :
|
|
mySearch.searchMode.specialCharsOff=false;
|
|
searchInput.value="Halogène^";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeFalse();
|
|
searchInput.value="Halogène";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(mySearch.dataIsOk({ "Famille": "Ha+logène" })).toBeFalse();
|
|
// Ignore les caractères spéciaux, sauf ceux en liste blanche :
|
|
mySearch.searchMode.specialCharsOff=true;
|
|
mySearch.searchMode.specialCharsWhiteList="^+";
|
|
expect(mySearch.dataIsOk({ "Famille": "Ha+logène" })).toBeFalse();
|
|
searchInput.value="Halogène^";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(mySearch.dataIsOk({ "Famille": "Halogène" })).toBeFalse();
|
|
});
|
|
|
|
it("Si demandé doit cherché l'expression en entier et non chacun des mots séparément.", async () =>
|
|
{
|
|
// Cas normal, ok si tous les mots sont trouvés séparément :
|
|
searchInput.value="gaz noble";
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(mySearch.dataIsOk({ "Famille": "le gaz est noble" })).toBeTrue();
|
|
expect(mySearch.dataIsOk({ "Famille": "noble est le gaz" })).toBeTrue();
|
|
expect(mySearch.dataIsOk({ "Famille": "gaz", "Symbole":"noble" })).toBeTrue();
|
|
|
|
// Il faut trouvé au moins une fois l'expression entière dans un des champs :
|
|
mySearch.searchMode.separatedWords=false;
|
|
searchInput.dispatchEvent(new Event("input"));
|
|
expect(mySearch.dataIsOk({ "Famille": "gaz noble" })).toBeTrue();
|
|
expect(mySearch.dataIsOk({ "Famille": "gaz noble", "Symbole":"He" })).toBeTrue();
|
|
expect(mySearch.dataIsOk({ "Famille": "le gaz est noble" })).toBeFalse();
|
|
expect(mySearch.dataIsOk({ "Famille": "gaz", "Symbole":"noble" })).toBeFalse();
|
|
});
|
|
|
|
});
|
|
});
|
|
|
|
}); |