Revue classe principale + script de tests, suite anomalies durant intégration, principalement concernant les champs à afficher et le compteur.

This commit is contained in:
Fabrice PENHOËT 2021-11-04 19:15:04 +01:00
parent 5bb05bfe44
commit bc7a64a65f
2 changed files with 221 additions and 163 deletions

View File

@ -19,13 +19,13 @@ export class FreeDatas2HTML
public stopIfParseErrors: boolean=false; public stopIfParseErrors: boolean=false;
// Les options (classement, pagination, filtres...) : // Les options (classement, pagination, filtres...) :
private _datasCounterElt: DOMElement|undefined=undefined;
private _datasSortingFunctions: SortingFunctions[]=[]; private _datasSortingFunctions: SortingFunctions[]=[];
private _fields2Rend: number[]=[];
public datasFilters: Filters[]=[]; public datasFilters: Filters[]=[];
public datasSortingFields: SortingFields[]=[]; public datasSortingFields: SortingFields[]=[];
public datasSortedField: SortingFields|undefined; public datasSortedField: SortingFields|undefined;
public pagination: Paginations|undefined; public pagination: Paginations|undefined;
private _fields2Rend: number[]=[];
public datasCounterElt: DOMElement|undefined=undefined;
// Les résultats : // Les résultats :
private _fields: ParseResults["fields"]=[]; private _fields: ParseResults["fields"]=[];
@ -33,7 +33,8 @@ export class FreeDatas2HTML
private _datas2Rend: {[index: string]:string}[]=[]; private _datas2Rend: {[index: string]:string}[]=[];
private _nbDatasValid: number=0; private _nbDatasValid: number=0;
// Le parseur, comme le render sont initialisés, mais peuvent être modifiés par des instances d'autres classes respectant leur interface. // Le parseur, comme le render sont initialisés.
// Mais ils peuvent être modifiés ensuite par des instances de classes respectant leurs interfaces.
constructor(datasFormat:"CSV"|"HTML"|"JSON", datas2Parse="", datasRemoteSource?:RemoteSources) constructor(datasFormat:"CSV"|"HTML"|"JSON", datas2Parse="", datasRemoteSource?:RemoteSources)
{ {
this.datasRender=new Render(); this.datasRender=new Render();
@ -50,13 +51,13 @@ export class FreeDatas2HTML
break; break;
} }
if(datas2Parse.trim() !== "") if(datas2Parse.trim() !== "")
this.parser.datas2Parse=datas2Parse.trim(); this.parser.datas2Parse=datas2Parse;
else if(datasRemoteSource !== undefined) else if(datasRemoteSource !== undefined)
this.parser.setRemoteSource(datasRemoteSource); this.parser.setRemoteSource(datasRemoteSource);
} }
// Vérifie s'il y a bien un élément dans le DOM pour l'id fourni. // Vérifie s'il y a bien un élément dans le DOM pour l'id fourni.
// Fonction statique également utilisée par les autres classes. // Méthode statique également utilisée par les autres classes.
public static checkInDOMById(checkedElt: DOMElement) : DOMElement public static checkInDOMById(checkedElt: DOMElement) : DOMElement
{ {
let searchEltInDOM=document.getElementById(checkedElt.id); let searchEltInDOM=document.getElementById(checkedElt.id);
@ -74,11 +75,6 @@ export class FreeDatas2HTML
this._datasViewElt=FreeDatas2HTML.checkInDOMById(elt); this._datasViewElt=FreeDatas2HTML.checkInDOMById(elt);
} }
set datasCounterElt(counterDisplayElement: DOMElement)
{
this._datasCounterElt=FreeDatas2HTML.checkInDOMById(counterDisplayElement);
}
get datas(): ParseResults["datas"] get datas(): ParseResults["datas"]
{ {
return this._datas; return this._datas;
@ -104,8 +100,42 @@ export class FreeDatas2HTML
return this._datas2Rend; return this._datas2Rend;
} }
// Retourne l'éventuelle fonction spécifique de classement associée à un champ
public getSortingFunctionForField(datasFieldNb: number): SortingFunctions|undefined
{
for(let checkedFunction of this._datasSortingFunctions)
{
if(checkedFunction.datasFieldNb === datasFieldNb)
return checkedFunction;
}
return undefined;
}
// Lance le parsage des données
// + lance un premier affichage si l'élément du DOM devant recevoir les données est connu
public async run(): Promise<any>
{
await this.parser.parse();
if(this.parser.parseResults === undefined) // le parseur devrait lui-même générer une erreur blocante avant.
throw new Error(errors.parserFail);
else
{
if(this.stopIfParseErrors && this.parser.parseResults.errors !== undefined)
throw new Error(errors.parserMeetErrors);
else
{
this._fields=this.parser.parseResults.fields;
this._datas=this.parser.parseResults.datas;
if(this._datasViewElt !== undefined)
this.refreshView();
return true;
}
}
}
// Toutes les méthodes suivantes nécessitent que les données aient d'abord été parsées.
// Vérifie qu'un champ existe bien dans les données parsées. // Vérifie qu'un champ existe bien dans les données parsées.
// Utilisée par les autres classes.
public checkFieldExist(nb: number) : boolean public checkFieldExist(nb: number) : boolean
{ {
if(this.parser.parseResults === undefined || this.parser.parseResults.fields[nb] === undefined) if(this.parser.parseResults === undefined || this.parser.parseResults.fields[nb] === undefined)
@ -114,20 +144,6 @@ export class FreeDatas2HTML
return true; return true;
} }
// Vérifie que les numéros de champs pour lesquels il y a des fonctions de classement spécifiques sont cohérents.
// ! Ne peut donc être utilisé qu'après avoir parsé les données.
set datasSortingFunctions(SortingFunctions: SortingFunctions[])
{
this._datasSortingFunctions=[];
for(let checkedFunction of SortingFunctions)
{
if(! this.checkFieldExist(checkedFunction.datasFieldNb))
throw new Error(errors.converterFieldNotFound);
else
this._datasSortingFunctions.push(checkedFunction);
}
}
// Vérifie que tous les numéros de champs à afficher sont valides // Vérifie que tous les numéros de champs à afficher sont valides
// Un tableau vide signifie que tous les champs parsés seront affichés. // Un tableau vide signifie que tous les champs parsés seront affichés.
set fields2Rend(fields: number[]) set fields2Rend(fields: number[])
@ -136,7 +152,7 @@ export class FreeDatas2HTML
this._fields2Rend=fields; this._fields2Rend=fields;
else else
{ {
this._fields2Rend=[]; this._fields2Rend=[]; // réinitialisation nécessaire en cas de + sieurs appels au setter
for(let field of fields) for(let field of fields)
{ {
if(! this.checkFieldExist(field)) if(! this.checkFieldExist(field))
@ -147,6 +163,31 @@ export class FreeDatas2HTML
} }
} }
// Vérifie qu'un champ faire partie de ceux à afficher.
public checkField2Rend(nb: number) : boolean
{
if(this._fields2Rend.length === 0)
return this.checkFieldExist(nb);
else
{
if(this._fields2Rend.indexOf(nb) === -1)
return false;
else
return true;
}
}
// Retourne le rang d'un champ parmis ceux à afficher
public getFieldDisplayRank(nb: number) : number
{
if(this.checkField2Rend(nb) === false)
return -1;
if(this._fields2Rend.length === 0)
return nb;
else
return this._fields2Rend.indexOf(nb);
}
// Retourne le nom des champs à afficher // Retourne le nom des champs à afficher
public realFields2Rend() : string[] public realFields2Rend() : string[]
{ {
@ -164,56 +205,16 @@ export class FreeDatas2HTML
} }
} }
// Vérifie qu'un champ faire partie de ceux à afficher. // Vérifie que les numéros de champs pour lesquels il y a des fonctions de classement spécifiques sont cohérents.
public checkField2Rend(nb: number) : boolean set datasSortingFunctions(SortingFunctions: SortingFunctions[])
{ {
if(this.realFields2Rend()[nb] === undefined) this._datasSortingFunctions=[];
return false; for(let checkedFunction of SortingFunctions)
{
if(! this.checkFieldExist(checkedFunction.datasFieldNb))
throw new Error(errors.converterFieldNotFound);
else else
return true; this._datasSortingFunctions.push(checkedFunction);
}
// Retourne l'éventuelle fonction spécifique de classement associée à un champ
public getSortingFunctionForField(datasFieldNb: number): SortingFunctions|undefined
{
for(let checkedFunction of this._datasSortingFunctions)
{
if(checkedFunction.datasFieldNb === datasFieldNb)
return checkedFunction;
}
return undefined;
}
// Lancer le parsage des données et lance éventuellement un 1er affichage.
public async run(): Promise<any>
{
await this.parser.parse();
if(this.parser.parseResults === undefined) // mais le parseur devrait lui-même générer une erreur avant
throw new Error(errors.parserFail);
else
{
if(this.stopIfParseErrors && this.parser.parseResults.errors !== undefined)
throw new Error(errors.parserMeetErrors);
else
{
this._fields=this.parser.parseResults.fields;
this._datas=this.parser.parseResults.datas;
if(this._datasViewElt !== undefined)
this.refreshView();
return true;
}
}
}
public datasCounter2HTML() : void
{
if(this._datasCounterElt !== undefined)
{
// Dans certains cas, il est nécessaire de rechercher de nouveau l'élément pour que l'affichage fonctionne correctement.
// Du coup, revoir intérêt de faire la même chose dans le setter ?
const searchEltInDOM=document.getElementById(this._datasCounterElt.id);
if(searchEltInDOM !== null)
searchEltInDOM.textContent=""+this._nbDatasValid;
} }
} }
@ -225,8 +226,6 @@ export class FreeDatas2HTML
throw new Error(errors.converterRefreshFail); throw new Error(errors.converterRefreshFail);
else else
{ {
//console.log(this._fields2Rend);
if(this._fields2Rend.length === 0) if(this._fields2Rend.length === 0)
this.datasRender.fields=this._fields; this.datasRender.fields=this._fields;
else else
@ -236,10 +235,11 @@ export class FreeDatas2HTML
this.datasRender.datas=this._datas2Rend; this.datasRender.datas=this._datas2Rend;
this._datasViewElt.eltDOM!.innerHTML=this.datasRender.rend2HTML(); // "!", car l'existence de "eltDOM" est testée par le setter. this._datasViewElt.eltDOM!.innerHTML=this.datasRender.rend2HTML(); // "!", car l'existence de "eltDOM" est testée par le setter.
// Actualisation de l'éventuel compteur, après l'opération précédente, car le compteur peut être dans le template passé au Render // Actualisation du compteur, nécessairement après l'opération précédente,
// car l'élément HTML du compteur peut être dans le template du Render.
this.datasCounter2HTML(); this.datasCounter2HTML();
// Réactivation des éventuels champs de classement qui ont pu être écrasés : // (ré)activation des éventuels champs de classement :
for(let field of this.datasSortingFields) for(let field of this.datasSortingFields)
field.field2HTML(); field.field2HTML();
@ -249,6 +249,18 @@ export class FreeDatas2HTML
} }
} }
public datasCounter2HTML() : void
{
if(this.datasCounterElt !== undefined)
{
// La recherche de l'existence de l'élément du compteur du DOM ne se fait pas au niveau d'un setter.
// Car son emplacement peut être situé dans le template d'affichage des données et donc pas encore affiché.
// La recherche doit être faite à chaque fois pour cette même raison (bug du DOM).
this.datasCounterElt=FreeDatas2HTML.checkInDOMById(this.datasCounterElt);
this.datasCounterElt.eltDOM!.textContent=""+this._nbDatasValid; // "!", car on vient de tester l'existence de l'élément.
}
}
// Fonction sélectionnant les données à afficher en prenant en compte les éventuels filtres, la pagination, etc. // Fonction sélectionnant les données à afficher en prenant en compte les éventuels filtres, la pagination, etc.
public datas2HTML() : {[index: string]:string}[] public datas2HTML() : {[index: string]:string}[]
{ {
@ -297,18 +309,17 @@ export class FreeDatas2HTML
this._nbDatasValid=nbTotal; this._nbDatasValid=nbTotal;
// Tous les champs doivent-ils être affichés ? // Tous les champs doivent-ils être affichés ?
// Ne pas enlever les champs cachés plus tôt, car ils peuvent servir à filtrer les données // Ne pas les enlever les champs + tôt, car ils peuvent servir à filtrer les données
if(this._fields2Rend.length !== 0) if(this._fields2Rend.length !== 0)
{ {
let newDatas2Display=[]; const realFields=this.realFields2Rend(), newDatas2Display=[];
for(let row in datas2Display) for(let row in datas2Display)
{ {
let i=0, newData: {[index: string]: string} = {}; let newData: {[index: string]: string}={};
for(let field in datas2Display[row]) for(let field in datas2Display[row])
{ {
if(this._fields2Rend.indexOf(i) !== -1) if(realFields.indexOf(field) !== -1)
newData[field]=datas2Display[row][field]; newData[field]=datas2Display[row][field];
i++;
} }
newDatas2Display.push(newData); newDatas2Display.push(newData);
} }

View File

@ -49,7 +49,7 @@ describe("Tests du script central de FreeDatas2HTML", () =>
expect(converter.parser.datas2Parse).toEqual(""); expect(converter.parser.datas2Parse).toEqual("");
}); });
it("S'il est fourni une chaîne de caractères valide, elle doit être passée au parseur.", () => it("S'il est fourni une chaîne de caractères non vide, elle doit être passée au parseur.", () =>
{ {
converter=new FreeDatas2HTML("CSV", "datas"); converter=new FreeDatas2HTML("CSV", "datas");
expect(converter.parser.datas2Parse).toEqual("datas"); expect(converter.parser.datas2Parse).toEqual("datas");
@ -86,7 +86,7 @@ describe("Tests du script central de FreeDatas2HTML", () =>
it("Doit générer une erreur si le parseur ne retourne aucun résultat.", async () => it("Doit générer une erreur si le parseur ne retourne aucun résultat.", async () =>
{ {
converter=new FreeDatas2HTML("CSV"); converter=new FreeDatas2HTML("CSV");
spyOn(converter.parser, "parse"); // bloque le fonctionnement de parse() spyOn(converter.parser, "parse"); // bloque le fonctionnement de parse() qui sinon bloquerait la suite
await expectAsync(converter.run()).toBeRejectedWith(new Error(errors.parserFail)); await expectAsync(converter.run()).toBeRejectedWith(new Error(errors.parserFail));
}); });
@ -133,7 +133,7 @@ describe("Tests du script central de FreeDatas2HTML", () =>
beforeEach( async () => beforeEach( async () =>
{ {
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" }); converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" });
await converter.run(); await converter.run(); // simple parsage, car aucun élément indiqué pour l'affichage
simpleSort = (a: number, b: number) => simpleSort = (a: number, b: number) =>
{ {
if(a < b) if(a < b)
@ -148,12 +148,11 @@ describe("Tests du script central de FreeDatas2HTML", () =>
it("Le test d'existence d'un champ doit retourner false s'il est lancé avant que les données n'aient été parsées.", () => it("Le test d'existence d'un champ doit retourner false s'il est lancé avant que les données n'aient été parsées.", () =>
{ {
converter=new FreeDatas2HTML("CSV"); converter=new FreeDatas2HTML("CSV");
const check=converter.checkFieldExist(0);
expect(converter.checkFieldExist(0)).toBeFalse(); expect(converter.checkFieldExist(0)).toBeFalse();
// Dans le cas d'un parsage ne retournant rien, c'est le parseur qui doit générer une erreur. // Dans le cas d'un parsage ne retournant rien, c'est le parseur qui doit générer une erreur.
}); });
it("Doit retourner false si le numéro de champ n'est pas trouvé dans les données.", () => it("Doit retourner false si le numéro de champ n'est pas trouvé dans les données parsées.", () =>
{ {
let check=converter.checkFieldExist(-2); let check=converter.checkFieldExist(-2);
expect(check).toBeFalse(); expect(check).toBeFalse();
@ -163,7 +162,7 @@ describe("Tests du script central de FreeDatas2HTML", () =>
expect(check).toBeFalse(); expect(check).toBeFalse();
}); });
it("Doit retourner true si le numéro de champ est bien trouvé dans les données.", () => it("Doit retourner true si le numéro de champ est bien trouvé dans les données parsées.", () =>
{ {
let check=converter.checkFieldExist(0); let check=converter.checkFieldExist(0);
expect(check).toBeTrue(); expect(check).toBeTrue();
@ -171,7 +170,7 @@ describe("Tests du script central de FreeDatas2HTML", () =>
expect(check).toBeTrue(); expect(check).toBeTrue();
}); });
it("Doit générer une erreur si tous les champs devant être affichés ne sont pas présents dans les données reçues.", () => it("Doit générer une erreur si tous les champs devant être affichés ne sont pas présents dans les données parsées.", () =>
{ {
expect(() => { return converter.fields2Rend=[0,2,8]; }).toThrowError(errors.converterFieldNotFound); expect(() => { return converter.fields2Rend=[0,2,8]; }).toThrowError(errors.converterFieldNotFound);
}); });
@ -182,10 +181,60 @@ describe("Tests du script central de FreeDatas2HTML", () =>
expect(converter.fields2Rend.length).toEqual(0); expect(converter.fields2Rend.length).toEqual(0);
}); });
it("Si tous les champs à afficher sont trouvés dans les données, ils doivent être acceptés.", () => it("Si tous les champs devant être affichés sont trouvés dans les données, ils doivent être acceptés.", () =>
{ {
expect(() => { return converter.fields2Rend=[0,1,2]; }).not.toThrowError(); expect(() => { return converter.fields2Rend=[0,1,2]; }).not.toThrowError();
expect(converter.fields2Rend).toEqual([0,1,2]); expect(converter.fields2Rend).toEqual([0,1,2]);
// On peut même changer d'avis :
converter.fields2Rend=[1,2,3];
expect(converter.fields2Rend).toEqual([1,2,3]);
});
it("Doit retourner false si le numéro de champ n'est pas trouvé dans ceux devant être affichés.", () =>
{
let check=converter.checkField2Rend(10);
expect(check).toBeFalse();
converter.fields2Rend=[]; // = tous les champs affichés
check=converter.checkField2Rend(10);
expect(check).toBeFalse();
converter.fields2Rend=[1,3,4];
check=converter.checkField2Rend(2);
expect(check).toBeFalse();
});
it("Doit retourner true si le numéro de champ est bien trouvé dans ceux devant être affichés.", () =>
{
let check=converter.checkField2Rend(2);
expect(check).toBeTrue();
converter.fields2Rend=[]; // = tous les champs affichés
check=converter.checkField2Rend(2);
expect(check).toBeTrue();
converter.fields2Rend=[1,3,4];
check=converter.checkField2Rend(4);
expect(check).toBeTrue();
});
it("Doit retourner le rang d'un champ parmis ceux devant être affichés et -1 s'il n'est pas trouvé.", () =>
{
// Pas de champs sélectionnés, on recherche parmis tous les champs parsés :
expect(converter.getFieldDisplayRank(10)).toEqual(-1);
expect(converter.getFieldDisplayRank(0)).toEqual(0);
expect(converter.getFieldDisplayRank(3)).toEqual(3);
// Seuls certains champs doivent être affichés :
converter.fields2Rend=[1,3,4];
expect(converter.getFieldDisplayRank(2)).toEqual(-1);
expect(converter.getFieldDisplayRank(1)).toEqual(0);
expect(converter.getFieldDisplayRank(3)).toEqual(1);
expect(converter.getFieldDisplayRank(4)).toEqual(2);
});
it("Doit retourner la liste des champs devant être affichés.", () =>
{
// Pas de champs sélectionnés = tous les champs parsés doivent être affichés :
expect(converter.realFields2Rend()).toEqual(converter.fields);
// Seuls certains champs doivent être affichés :
converter.fields2Rend=[1,3,4];
expect(converter.realFields2Rend()).toEqual([converter.fields[1], converter.fields[3], converter.fields[4]]);
}); });
it("Doit générer une erreur si une fonction est associée à un champ n'existant pas dans les données.", () => it("Doit générer une erreur si une fonction est associée à un champ n'existant pas dans les données.", () =>
@ -225,7 +274,20 @@ describe("Tests du script central de FreeDatas2HTML", () =>
expect(() => { return converter.refreshView(); }).toThrowError(errors.converterRefreshFail); expect(() => { return converter.refreshView(); }).toThrowError(errors.converterRefreshFail);
}); });
it("Doit appelé la fonction préparant les données à afficher et transmettre le résultat au moteur de rendu.", () => it("Si les champs à afficher n'ont pas été renseignés, tous ceux trouvés par le parseur doivent tous être transmis au moteur de rendu.", () =>
{
converter.refreshView();
expect(converter.datasRender.fields).toEqual(converter.parser.parseResults.fields);
});
it("Si dans champs à afficher ont été renseignés, ils doivent être transmis au moteur de rendu", () =>
{
converter.fields2Rend=[0,2];
converter.refreshView();
expect(converter.datasRender.fields).toEqual([converter.parser.parseResults.fields[0],converter.parser.parseResults.fields[2]]);
});
it("Doit appeler la fonction préparant les données à afficher et transmettre le résultat au moteur de rendu.", () =>
{ {
spyOn(converter, "datas2HTML").and.callThrough(); spyOn(converter, "datas2HTML").and.callThrough();
converter.refreshView(); converter.refreshView();
@ -233,40 +295,7 @@ describe("Tests du script central de FreeDatas2HTML", () =>
expect(converter.datasRender.datas).toEqual(converter.datas2Rend); expect(converter.datasRender.datas).toEqual(converter.datas2Rend);
}); });
it("Si des champs à afficher n'ont pas été renseignés, tous ceux trouvés par le parserur doivent tous être transmis au moteur de rendu.", () => it("Doit appeler le moteur de rendu et afficher le résultat dans la page.", async () =>
{
converter.refreshView();
expect(converter.datasRender.fields).toEqual(converter.parser.parseResults.fields);
});
it("Si dans champs à afficher ont été renseignés, ils doivent être transmis au moteur rendu", async () =>
{
converter.fields2Rend=[1,2];
await converter.run();
expect(converter.datasRender.fields).toEqual([converter.parser.parseResults.fields[1],converter.parser.parseResults.fields[2]]);
});
it("Doit appelé la fonction actualisant le compteur d'enregistrements.", () =>
{
spyOn(converter, "datasCounter2HTML");
converter.refreshView();
expect(converter.datasCounter2HTML).toHaveBeenCalled();
});
it("Si un élément du DOM est renseigné pour le compteur, il doit afficher le nombre d'enregistrements.", async () =>
{
converter.datasCounterElt={ id:"counter" };
converter.datasCounter2HTML();
converter.refreshView();
expect(document.getElementById("counter").textContent).toEqual("118");
// Y compris quand aucune donnée trouvée :
converter.parser=new ParserForCSV();
converter.parser.datas2Parse="name,firstname,city";
await converter.run();
expect(document.getElementById("counter").textContent).toEqual("0");
});
it("Doit appelé le moteur de rendu et afficher le résultat dans la page.", async () =>
{ {
converter=new FreeDatas2HTML("CSV", "name,firstname,birthday\ndoe,john,2000/12/25"); converter=new FreeDatas2HTML("CSV", "name,firstname,birthday\ndoe,john,2000/12/25");
await converter.run();// parse sans rien afficher await converter.run();// parse sans rien afficher
@ -274,20 +303,31 @@ describe("Tests du script central de FreeDatas2HTML", () =>
spyOn(converter.datasRender, "rend2HTML").and.callThrough(); spyOn(converter.datasRender, "rend2HTML").and.callThrough();
converter.refreshView(); converter.refreshView();
expect(converter.datasRender.rend2HTML).toHaveBeenCalled(); expect(converter.datasRender.rend2HTML).toHaveBeenCalled();
// Les données à afficher doivent être assez simples, car certains caractères peuvent être remplacés par innerHTML (exemples :"<" ou ">") // Pour ce test, les données à afficher doivent être assez simples, car certains caractères peuvent être remplacés par innerHTML (exemples :"<" ou ">")
expect(document.getElementById("datas").innerHTML).toEqual(converter.datasRender.rend2HTML()); expect(document.getElementById("datas").innerHTML).toEqual(converter.datasRender.rend2HTML());
}); });
it("Si un élément HTML devant affiché le nombre de résultats est connu, il doit être actualisé.", () => it("Doit appeler la fonction actualisant le compteur d'enregistrements.", () =>
{
spyOn(converter, "datasCounter2HTML");
converter.refreshView();
expect(converter.datasCounter2HTML).toHaveBeenCalled();
});
it("Si un élément HTML devant affiché le nombre de résultats est connu, il doit être actualisé.", async () =>
{ {
converter.datasCounterElt={ id: "counter" }; converter.datasCounterElt={ id: "counter" };
converter.refreshView(); converter.refreshView();
expect(document.getElementById("counter").innerHTML).toEqual(""+converter.nbDatasValid); expect(document.getElementById("counter").innerHTML).toEqual(""+converter.nbDatasValid);
// Y compris quand aucune donnée trouvée :
converter.parser=new ParserForCSV();
converter.parser.datas2Parse="name,firstname,city";
await converter.run();
expect(document.getElementById("counter").textContent).toEqual("0");
}); });
it("Si des champs de classement existent, leur code HTML doit être actualisé.", () => it("Si des champs de classement existent, leur code HTML doit être actualisé.", () =>
{ {
converter.refreshView(); // nécessaire pour que les champs soit trouvés dans le HTML
const sortingField1=new SortingField(converter, 0); const sortingField1=new SortingField(converter, 0);
const sortingField2=new SortingField(converter, 1); const sortingField2=new SortingField(converter, 1);
converter.datasSortingFields=[sortingField1,sortingField2]; converter.datasSortingFields=[sortingField1,sortingField2];
@ -317,34 +357,15 @@ describe("Tests du script central de FreeDatas2HTML", () =>
await converter.run(); await converter.run();
}); });
it("Si une liste de champs à afficher a été renseignée, elle doit être prise en compte.", async () =>
{
converter=new FreeDatas2HTML("CSV","id,firstname,name,birthday\n1,john,doe,2001/12/25\n2,donald,duck,1934/06/09");
converter.datasViewElt={ id:"datas" };
await converter.run();
converter.fields2Rend=[1,2];
converter.refreshView();
expect(converter.datas2Rend).toEqual([{ firstname:"john", name:"doe" }, { firstname:"donald", name:"duck" }]);
});
it("Par défaut, tous les champs trouvés doivent être affichés.", async () =>
{
converter=new FreeDatas2HTML("CSV","id,firstname,name,birthday\n1,john,doe,2001/12/25\n2,donald,duck,1934/06/09");
converter.datasViewElt={ id:"datas" };
await converter.run();
converter.refreshView();
expect(converter.datas2Rend).toEqual([{ id:"1", firstname:"john", name:"doe", birthday:"2001/12/25" }, { id:"2", firstname:"donald", name:"duck", birthday:"1934/06/09" }]);
});
it("Si un champ de classement est activé par l'utilisateur, les données doivent être classées via ce champ.", () => it("Si un champ de classement est activé par l'utilisateur, les données doivent être classées via ce champ.", () =>
{ {
// Compliqué de tester avec spyOn que sort() a été appelée avec la bonne fonction de classement en paramètre // Semble compliqué de tester que sort() a été appelée avec la bonne fonction de classement en paramètre.
// Donc je compare les résultats à ceux attendus // Donc je compare les résultats à ceux attendus en cliquant sur le 1er champ.
const sortingField=new SortingField(converter, 0); const sortingField=new SortingField(converter, 0);
converter.datasSortingFields=[sortingField]; converter.datasSortingFields=[sortingField];
sortingField.field2HTML(); sortingField.field2HTML();
const fieldName=converter.fields[0];
const getTHLink=document.querySelector("th a") as HTMLElement; const getTHLink=document.querySelector("th a") as HTMLElement;
const fieldName=converter.fields[0];
getTHLink.click(); getTHLink.click();
converter.datas.sort( (a, b) => compare( {order: "asc"} )(a[fieldName], b[fieldName])); converter.datas.sort( (a, b) => compare( {order: "asc"} )(a[fieldName], b[fieldName]));
expect(converter.datas2Rend).toEqual(converter.datas); expect(converter.datas2Rend).toEqual(converter.datas);
@ -356,7 +377,7 @@ describe("Tests du script central de FreeDatas2HTML", () =>
expect(converter.datas2Rend).toEqual(converter.datas); expect(converter.datas2Rend).toEqual(converter.datas);
}); });
it("Si une fonction de classement est définie pour le champ activé par l'utilisateur, elle doit être prise en compte.", () => it("Si une fonction de classement est définie pour le champ cliqué par l'utilisateur, elle doit être prise en compte.", () =>
{ {
const mySort = (a: any, b: any, order: "asc"|"desc" = "asc") => const mySort = (a: any, b: any, order: "asc"|"desc" = "asc") =>
{ {
@ -374,20 +395,29 @@ describe("Tests du script central de FreeDatas2HTML", () =>
const sortingField=new SortingField(converter, 4); const sortingField=new SortingField(converter, 4);
converter.datasSortingFields=[sortingField]; converter.datasSortingFields=[sortingField];
sortingField.field2HTML(); sortingField.field2HTML();
const fieldName=converter.fields[0]; const fieldName=converter.fields[4];
const getTHLink=document.querySelector("th a") as HTMLElement; const getTHLink=document.querySelectorAll("th a") as NodeListOf<HTMLElement>;
getTHLink.click(); getTHLink[0].click();
converter.datas.sort( (a, b) => { return mySort(a[fieldName], b[fieldName], "asc"); }); converter.datas.sort( (a, b) => { return mySort(a[fieldName], b[fieldName], "asc"); });
expect(converter.datas2Rend).toEqual(converter.datas); expect(converter.datas2Rend).toEqual(converter.datas);
getTHLink.click(); getTHLink[0].click();
converter.datas.sort( (a, b) => { return mySort(a[fieldName], b[fieldName], "desc"); }); converter.datas.sort( (a, b) => { return mySort(a[fieldName], b[fieldName], "desc"); });
expect(converter.datas2Rend).toEqual(converter.datas); expect(converter.datas2Rend).toEqual(converter.datas);
getTHLink.click(); getTHLink[0].click();
converter.datas.sort( (a, b) => { return mySort(a[fieldName], b[fieldName], "asc"); }); converter.datas.sort( (a, b) => { return mySort(a[fieldName], b[fieldName], "asc"); });
expect(converter.datas2Rend).toEqual(converter.datas); expect(converter.datas2Rend).toEqual(converter.datas);
}); });
it("Si des options de pagination sont activées par l'utilisateur, seules les données de la page choisie doivent être retournées.", () => it("Par défaut, tous les champs trouvés doivent être affichés.", async () =>
{
converter=new FreeDatas2HTML("CSV","id,firstname,name,birthday\n1,john,doe,2001/12/25\n2,donald,duck,1934/06/09");
converter.datasViewElt={ id:"datas" };
await converter.run();
converter.refreshView();
expect(converter.datas2Rend).toEqual([{ id:"1", firstname:"john", name:"doe", birthday:"2001/12/25" }, { id:"2", firstname:"donald", name:"duck", birthday:"1934/06/09" }]);
});
it("Si des options de pagination sont activées, seules les données de la page choisie doivent être retournées.", () =>
{ {
const pagination=new Pagination(converter, { id:"pages" }, "Page à afficher :"); const pagination=new Pagination(converter, { id:"pages" }, "Page à afficher :");
pagination.options={ displayElement: { id:"paginationOptions" }, values: [10,20,50] , name: "Choix de pagination :" }; pagination.options={ displayElement: { id:"paginationOptions" }, values: [10,20,50] , name: "Choix de pagination :" };
@ -416,7 +446,7 @@ describe("Tests du script central de FreeDatas2HTML", () =>
filter1.filter2HTML(); filter1.filter2HTML();
const filter2=new Selector(converter, 4, { id:"selector2"} ); const filter2=new Selector(converter, 4, { id:"selector2"} );
converter.datasFilters=[filter1,filter2]; converter.datasFilters=[filter1,filter2];
// si le 1er n'est pas réellement lancé, le second est bloqué, car cela retourne un "false" // Nécessaire de vraiment lancer le 1er, sinon le second est bloqué, car cela retourne un "false"
spyOn(filter1, "dataIsOk").and.callThrough(); spyOn(filter1, "dataIsOk").and.callThrough();
spyOn(filter2, "dataIsOk"); spyOn(filter2, "dataIsOk");
converter.refreshView(); converter.refreshView();
@ -439,5 +469,22 @@ describe("Tests du script central de FreeDatas2HTML", () =>
expect(filter1.dataIsOk).toHaveBeenCalledTimes(118); expect(filter1.dataIsOk).toHaveBeenCalledTimes(118);
expect(filter2.dataIsOk).toHaveBeenCalledTimes(4); expect(filter2.dataIsOk).toHaveBeenCalledTimes(4);
}); });
it("Si une liste de champs à afficher a été renseignée, elle doit être prise en compte.", async () =>
{
converter=new FreeDatas2HTML("CSV","id,firstname,name,birthday\n1,john,doe,2001/12/25\n2,donald,duck,1934/06/09");
converter.datasViewElt={ id:"datas" };
await converter.run();
converter.fields2Rend=[1,2];
converter.refreshView();
expect(converter.datas2Rend).toEqual([{ firstname:"john", name:"doe" }, { firstname:"donald", name:"duck" }]);
// Même quand les données sont dans le désordre :
converter=new FreeDatas2HTML("JSON", JSON.stringify([{nom:"dugenoux","prénom":"henri","âge":25},{nom:"michu","âge":58,"prénom":"mariette"}]));
await converter.run();
converter.fields2Rend=[0,1];
converter.datasViewElt={ id:"datas" };
converter.refreshView();
expect(converter.datas2Rend).toEqual([{"nom": "dugenoux", "prénom": "henri"}, { nom:"michu", "prénom":"mariette" }]);
});
}); });
}); });