Compare commits

...

3 Commits

7 changed files with 147 additions and 168 deletions

View File

@ -5,13 +5,12 @@ import { RemoteSource } from "./RemoteSource";
export class ParserForHTML implements Parsers
{
private _datasRemoteSource: RemoteSources;
private _document2Parse: HTMLDocument=document;
private _document2Parse: HTMLDocument=document;
private _parseResults: ParseResults|undefined=undefined;
private _fieldsSelector: string="table > thead > tr > th";
private _rowsSelector: string="table > tbody > tr";
private _datasSelector: string="tr > td";
// L'instance d'une autre classe que RemoteSource peut être passée au constructeur
constructor(datasRemoteSource?: RemoteSources)
{
if(datasRemoteSource !== undefined)
@ -81,14 +80,13 @@ export class ParserForHTML implements Parsers
public async parse(): Promise<any>
{
const parser=this;
const realFields: string[]=[], datas: {[index: string]:string}[]=[], parseErrors: ParseErrors[]=[];
// Document HTML distant ?
if(parser._datasRemoteSource.url !== "")
if(this._datasRemoteSource.url !== "")
{
const settings: {}=parser._datasRemoteSource.getFetchSettings();
const response=await fetch(parser._datasRemoteSource.url, settings);
const settings: {}=this._datasRemoteSource.getFetchSettings();
const response=await fetch(this._datasRemoteSource.url, settings);
if (! response.ok)
throw new Error(errors.parserRemoteFail);
const responseHTML=await response.text();
@ -96,8 +94,7 @@ export class ParserForHTML implements Parsers
this._document2Parse=parserDOM.parseFromString(responseHTML, "text/html");
}
// Récupérer les noms des champs qui doivent avoir été fournis
// Ils ne peuvent être une chaîne vide ou en doublon
// Récupération du noms de champs
const fields=this._document2Parse.querySelectorAll(this._fieldsSelector);
if(fields.length === 0)
throw new Error(errors.parserElementsNotFound+this._fieldsSelector);
@ -107,13 +104,12 @@ export class ParserForHTML implements Parsers
if(checkField !== "" && realFields.indexOf(checkField) === -1)
realFields.push(checkField);
else
console.error(errors.parserFieldNameFail); // lancer une exception, car risque de bugs par la suite ???
parseErrors.push({ row:-1, message: errors.parserFieldNameFail});
}
if(realFields.length === 0)
throw new Error(errors.parserFieldsNotFound);
// Puis récupération des données.
// Il peut n'y avoir aucune ligne si aucune donnée trouvée.
// Puis récupération des éventuelles données.
const rows=this._document2Parse.querySelectorAll(this._rowsSelector);
let datasElts;
for(let i=0; i < rows.length; i++)
@ -121,7 +117,7 @@ export class ParserForHTML implements Parsers
// Les nombre de données par ligne ne devrait pas être différent du nombre de champs.
datasElts=rows[i].querySelectorAll(this._datasSelector);
if(datasElts.length !== realFields.length)
parseErrors.push({ row:i, message:errors.parserMeetErrors});
parseErrors.push({ row:i, message:errors.parserNumberOfFieldsFail});
// Les chaînes vides sont par contre acceptées ici.
let dataObject: {[index: string]: string} = {}
for(let j=0; j < datasElts.length && j < realFields.length; j++)
@ -130,9 +126,9 @@ export class ParserForHTML implements Parsers
if(Object.keys(dataObject).length !== 0)
datas.push(dataObject)
else
parseErrors.push({ row:i, message:errors.parserMeetErrors});
parseErrors.push({ row:i, message: errors.parserLineWithoutDatas});
}
parser._parseResults =
this._parseResults =
{
datas: datas,
errors: parseErrors,

75
src/SortingField.ts Normal file
View File

@ -0,0 +1,75 @@
const { compare }=require('natural-orderby');
const errors=require("./errors.js");
import { SortingFields } from "./interfaces";
import { FreeDatas2HTML } from "./freeDatas2HTML";
export class SortingField implements SortingFields
{
_converter: FreeDatas2HTML;
_fieldsDOMSelector: string;
_datasFieldNb: number;
_order: "asc"|"desc"|undefined=undefined;
// Injection de la classe principale, mais uniquement si les noms des champs ont été importés et affichés correctement
constructor(converter: FreeDatas2HTML, datasFieldNb: number, fieldsDOMSelector: string="th")
{
if(converter.fields === undefined)
throw new Error(errors.sortingFieldNeedDatas);
else if(! converter.checkFieldExist(datasFieldNb))
throw new Error(errors.sortingFieldNotFound);
else
{
const fields=document.querySelectorAll(fieldsDOMSelector);
if(fields === undefined)
throw new Error(errors.sortingFieldsNotInHTML);
else if(fields.length !== converter.fields.length)
throw new Error(errors.sortingFieldsNbFail);
else
{
this._converter=converter;
this._datasFieldNb=datasFieldNb;
this._fieldsDOMSelector=fieldsDOMSelector;
}
}
}
get converter() : FreeDatas2HTML
{
return this._converter;
}
get fieldsDOMSelector() : string
{
return this._fieldsDOMSelector;
}
get datasFieldNb() : number
{
return this._datasFieldNb;
}
get order() : "asc"|"desc"|undefined
{
return this._order;
}
public field2HTML() : void
{
const fields=document.querySelectorAll(this._fieldsDOMSelector);
let htmlContent=fields[this._datasFieldNb].innerHTML;
htmlContent="<a href='#freeDatas2HTMLSorting"+this._datasFieldNb+"' id='freeDatas2HTMLSorting"+this._datasFieldNb+"'>"+htmlContent+"</a>";
fields[this._datasFieldNb].innerHTML=htmlContent;
const sortingElement=document.getElementById("freeDatas2HTMLSorting"+this._datasFieldNb), field=this;
sortingElement!.addEventListener("click", function(e) // "!" car je sais que sortingElement existe, puisque je viens de le créer !
{
e.preventDefault();
let order=field._order ;
if(order === undefined || order === "desc")
field._order="asc";
else
field._order="desc";
field._converter.datasSortedField=field;
field._converter.refreshView();
});
}
}

View File

@ -33,7 +33,7 @@ module.exports =
selectorSelectedIndexNotFound: "La valeur sélectionnée n'a pas été trouvée dans la liste des champs.",
sortingField2HTMLFail: "Toutes les donnée nécessaires à la création du lien de classement n'ont pas été fournies.",
sortingFieldNeedDatas: "Le création d'un champ de classement nécessite la transmission de la liste des champs.",
sortingFieldFieldNotFound: "Au moins un des champs devant permettre de classer les données n'existe pas dans le fichier.",
sortingFieldNotFound: "Au moins un des champs devant permettre de classer les données n'existe pas dans le fichier.",
sortingFieldsNbFail: "Le nombre de champs trouvés dans le DOM ne correspond pas à celui des données à classer.",
sortingFieldsNotInHTML: "Les champs pouvant servir à classer les données n'ont pas été trouvés dans le DOM.",
};

View File

@ -8,7 +8,7 @@ import { ParserForHTML} from "./ParserForHTML";
import { ParserForJSON} from "./ParserForJSON";
import { Render} from "./freeDatas2HTMLRender";
import { Selector } from "./freeDatas2HTMLSelector";
import { SortingField } from "./freeDatas2HTMLSortingField";
import { SortingField } from "./SortingField";
export class FreeDatas2HTML
{
@ -238,4 +238,4 @@ export class FreeDatas2HTML
export { Pagination } from "./freeDatas2HTMLPagination";
export { Render} from "./freeDatas2HTMLRender";
export { Selector } from "./freeDatas2HTMLSelector";
export { SortingField } from "./freeDatas2HTMLSortingField";
export { SortingField } from "./SortingField";

View File

@ -1,77 +0,0 @@
const { compare }=require('natural-orderby');
const errors=require("./errors.js");
import { SortingFields } from "./interfaces";
import { FreeDatas2HTML } from "./freeDatas2HTML";
export class SortingField implements SortingFields
{
_converter: FreeDatas2HTML;
_fieldsDOMSelector: string;
_datasFieldNb: number;
_order: "asc"|"desc"|undefined=undefined;
// Injection de la classe principale, mais uniquement si le nom des champs ont été importés et affichés correctement
constructor(converter: FreeDatas2HTML, datasFieldNb: number, fieldsDOMSelector: string="th")
{
if(converter.fields === undefined)
throw new Error(errors.sortingFieldNeedDatas);
else if(! converter.checkFieldExist(Number(datasFieldNb)))
throw new Error(errors.sortingFieldFieldNotFound);
else
{
const fields=document.querySelectorAll(fieldsDOMSelector);
if(fields === undefined)
throw new Error(errors.sortingFieldsNotInHTML);
else if(fields.length !== converter.fields.length)
throw new Error(errors.sortingFieldsNbFail);
else
{
this._converter=converter;
this._datasFieldNb=datasFieldNb;
this._fieldsDOMSelector=fieldsDOMSelector;
}
}
}
get fieldsDOMSelector() : string
{
return this._fieldsDOMSelector;
}
get datasFieldNb() : number
{
return this._datasFieldNb;
}
get order() : "asc"|"desc"|undefined
{
return this._order;
}
// Création du lien dans le HTML correspondant au champ de classement
public field2HTML() : void
{
if(this._converter === undefined || this._fieldsDOMSelector === "" || this._datasFieldNb === undefined)
throw new Error(errors.sortingField2HTMLFail);
else
{
const fields=document.querySelectorAll(this._fieldsDOMSelector);
let htmlContent=fields[this._datasFieldNb].innerHTML;
htmlContent="<a href='#freeDatas2HTMLSorting"+this._datasFieldNb+"' id='freeDatas2HTMLSorting"+this._datasFieldNb+"'>"+htmlContent+"</a>";
fields[this._datasFieldNb].innerHTML=htmlContent;
const sortingElement=document.getElementById("freeDatas2HTMLSorting"+this._datasFieldNb), field=this;
sortingElement!.addEventListener("click", function(e) // je sais que sortingElement existe, car je viens de le créer !
{
e.preventDefault();
let order=field._order ;
if(order === undefined || order === "desc")
field._order="asc";
else
field._order="desc";
field._converter.datasSortedField=field;
field._converter.refreshView();
});
}
}
}

View File

@ -21,9 +21,10 @@ describe("Tests du parseur HTML", () =>
it("Doit avoir créé une instance du parseur.", () =>
{
expect(parser).toBeInstanceOf(Parser);
expect(parser.datasRemoteSource.url).toEqual("");
});
it("Ne doit pas accepter des valeurs vides pour les sélecteurs CSS.", () =>
it("Ne doit pas accepter de valeurs vides pour les sélecteurs CSS.", () =>
{
expect(() => { return parser.fieldsSelector=""; }).toThrowError(errors.parserSelectorsIsEmpty);
expect(() => { return parser.rowsSelector=" "; }).toThrowError(errors.parserSelectorsIsEmpty);
@ -47,30 +48,42 @@ describe("Tests du parseur HTML", () =>
const doc=parserDOM.parseFromString(htmlString, "text/html");
expect(parser.document2Parse).toEqual(doc);
});
it("Si des options de connexion distante sont fournies, elles doivent être utilisées.", async () =>
{
spyOn(window, "fetch").and.callThrough();
parser.setRemoteSource({ url:"http://localhost:9876/datas/datas.html", headers: [{ key:"token", value:"1234" }, { key:"userName", value:"Toto" }], withCredentials:true });
await parser.parse();
const headers=new Headers();
headers.append("token", "1234");
headers.append("userName", "Toto");
expect(window.fetch).toHaveBeenCalledWith("http://localhost:9876/datas/datas.html", { method: "GET", headers: headers, credentials: "include" });
});
});
describe("Extraction des données du document.", () =>
{
it("Doit générer une erreur si aucun élément n'est trouvé dans le document pour les sélecteurs CSS fournis pour les noms de champs.", async () =>
{
await expectAsync(parser.parse()).toBeRejectedWith(new Error(errors.parserElementsNotFound+"table > thead > tr > th")); // valeurs par défaut, mais rien dans le DOM
await expectAsync(parser.parse()).toBeRejectedWith(new Error(errors.parserElementsNotFound+"table > thead > tr > th")); // = valeurs par défaut, mais rien dans le DOM
datasElt.innerHTML=fixtures.htmlParserDatas;
await expectAsync(parser.parse()).not.toBeRejectedWith(new Error(errors.parserElementsNotFound+"table > thead > tr > th"));
parser.fieldsSelector="ul#dontExist > li"; // n'existe pas dans ce qui a été injecté
await expectAsync(parser.parse()).toBeRejectedWith(new Error(errors.parserElementsNotFound+"ul#dontExist > li"));
});
it("Les noms de champ vides ou en doublon doivent être ignorés.", async () =>
it("Les noms de champ vides ou en doublon doivent être ignorés et les erreurs reportées.", async () =>
{
datasElt.innerHTML="<ul><li>Champ1</li><li> </li><li>Champ2</li><li>Champ2</li></ul>";
parser.fieldsSelector="ul > li";
await parser.parse();
expect(parser.parseResults.fields).toEqual(["Champ1","Champ2"]);
expect(parser.parseResults.errors).toEqual([{ row:-1, message: errors.parserFieldNameFail}, { row:-1, message: errors.parserFieldNameFail}]);
});
it("Au moins un nom de champ valide doit avoir été trouvé.", async () =>
it("Doit générer une erreur, si aucun nom de champ valide n'est trouvé dans le document.", async () =>
{
datasElt.innerHTML="<ul><li></li><li> </li></ul>";
datasElt.innerHTML="<ul><li> </li><li> </li></ul>";
parser.fieldsSelector="ul > li";
await expectAsync(parser.parse()).toBeRejectedWith(new Error(errors.parserFieldsNotFound));
});
@ -87,13 +100,13 @@ describe("Tests du parseur HTML", () =>
datasElt.innerHTML=fixtures.htmlParserDatasBadFields; // un "td" manquant en ligne 0 et un en trop en ligne 1
await parser.parse();
expect(parser.parseResults.datas).toEqual([{"Z (numéro atomique)":"1","Élément":"Hydrogène", Symbole:"H", Famille:"Non-métal" }, {"Z (numéro atomique)":"2","Élément":"Hélium", Symbole:"He", Famille:"Gaz noble", "Mots-clés":"Mot-clé2" }, {"Z (numéro atomique)":"3","Élément":"Lithium", Symbole:"Li", Famille:"Métal alcalin", "Mots-clés":"Mot-clé2,Mot-clé1" }, {"Z (numéro atomique)":"4","Élément":"Béryllium", Symbole:"Be", Famille:"Métal alcalino-terreux", "Mots-clés":"Mot-clé3" }]);
expect(parser.parseResults.errors[0]).toEqual({row:0,message:errors.parserMeetErrors});
expect(parser.parseResults.errors[1]).toEqual({row:1,message:errors.parserMeetErrors});
expect(parser.parseResults.errors[0]).toEqual({row:0,message:errors.parserNumberOfFieldsFail});
expect(parser.parseResults.errors[1]).toEqual({row:1,message:errors.parserNumberOfFieldsFail});
});
it("Le fait qu'aucune donnée ne soit trouvée ne doit pas générer une erreur.", async () =>
{
datasElt.innerHTML="<table><thead><tr><th>Champ1</th><th>Champ2</th></tr></thead></table>"
datasElt.innerHTML="<table><thead><tr><th>Champ1</th><th>Champ2</th></tr></thead></table>";
await expectAsync(parser.parse()).toBeResolved();
});
@ -102,7 +115,7 @@ describe("Tests du parseur HTML", () =>
datasElt.innerHTML=fixtures.htmlParserDatasEmptyLine; // avant dernière ligne sans "td", "Mots-clé" vide pour la 1ière ligne.
await parser.parse();
expect(parser.parseResults.datas).toEqual([{"Z (numéro atomique)":"1","Élément":"Hydrogène", Symbole:"H", Famille:"Non-métal", "Mots-clés":"" }, {"Z (numéro atomique)":"2","Élément":"Hélium", Symbole:"He", Famille:"Gaz noble", "Mots-clés":"Mot-clé2" }, {"Z (numéro atomique)":"3","Élément":"Lithium", Symbole:"Li", Famille:"Métal alcalin", "Mots-clés":"Mot-clé2,Mot-clé1" }, {"Z (numéro atomique)":"4","Élément":"Béryllium", Symbole:"Be", Famille:"Métal alcalino-terreux", "Mots-clés":"Mot-clé3" }]);
expect(parser.parseResults.errors[0]).toEqual({row:3,message:errors.parserMeetErrors});
expect(parser.parseResults.errors[1]).toEqual({row:3,message:errors.parserLineWithoutDatas});// errors[0] = erreur nombre de champs 1ère ligne
});
it("Si le code HTML fourni est ok, aucune erreur de lecture ne doit être reportée.", async () =>
@ -112,6 +125,5 @@ describe("Tests du parseur HTML", () =>
expect(parser.parseResults.datas).toEqual([{"Z (numéro atomique)":"1","Élément":"Hydrogène", Symbole:"H", Famille:"Non-métal", "Mots-clés":"" }, {"Z (numéro atomique)":"2","Élément":"Hélium", Symbole:"He", Famille:"Gaz noble", "Mots-clés":"Mot-clé2" }, {"Z (numéro atomique)":"3","Élément":"Lithium", Symbole:"Li", Famille:"Métal alcalin", "Mots-clés":"Mot-clé2,Mot-clé1" }, {"Z (numéro atomique)":"4","Élément":"Béryllium", Symbole:"Be", Famille:"Métal alcalino-terreux", "Mots-clés":"Mot-clé3" }]);
expect(parser.parseResults.errors.length).toEqual(0);
});
});
});

View File

@ -1,5 +1,4 @@
import { FreeDatas2HTML, Selector, SortingField } from "../src/freeDatas2HTML";
import { FreeDatas2HTML, SortingField } from "../src/freeDatas2HTML";
const errors=require("../src/errors.js");
const fixtures=require("./fixtures.js");
@ -28,15 +27,15 @@ describe("Test des champs de classement.", () =>
it("Doit générer une erreur, si initialisé sans fournir la liste des champs servant à classer les données.", () =>
{
converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" });
// Pas lancé converter.run() donc les données n'ont pas été parsées :
expect(() => { return new SortingField(converter, 0); }).toThrowError(errors.sortingFieldNeedDatas);
});
it("Doit générer une erreur, si initialisé avec un numéro du champ de classement n'existant pas dans les données.", () =>
{
expect(() => { return new SortingField(converter, 9); }).toThrowError(errors.sortingFieldFieldNotFound);
expect(() => { return new SortingField(converter, -1); }).toThrowError(errors.sortingFieldFieldNotFound);
expect(() => { return new SortingField(converter, 1.1); }).toThrowError(errors.sortingFieldFieldNotFound);
expect(() => { return new SortingField(converter, 9); }).toThrowError(errors.sortingFieldNotFound);
expect(() => { return new SortingField(converter, -1); }).toThrowError(errors.sortingFieldNotFound);
expect(() => { return new SortingField(converter, 1.1); }).toThrowError(errors.sortingFieldNotFound);
});
it("Doit générer une erreur, si initialisé sans élements HTML textuels dans la page servant d'entêtes aux données.", () =>
@ -44,7 +43,7 @@ describe("Test des champs de classement.", () =>
expect(() => { return new SortingField(converter, 0, "th.cols"); }).toThrowError(errors.sortingsFieldNotInHTML);
});
it("Doit générer une erreur, si le nombre d'éléments du DOM devant servir d'entêtes est différent du nombre de champs des données.", () =>
it("Doit générer une erreur, si le nombre d'éléments trouvés dans le DOM pour les entêtes est différent du nombre de champs des données.", () =>
{
expect(() => { return new SortingField(converter, 0, "td"); }).toThrowError(errors.sortingFieldsNbFail);
});
@ -57,8 +56,8 @@ describe("Test des champs de classement.", () =>
});
});
describe("Création des liens permettant de classer les données affichées.", () =>
{
describe("Création et action des liens permettant de classer les données affichées.", () =>
{
it("Doit générer un élement lien <a> avec comme ancre l'élément HTML correspondant au nom de la colonne.", () =>
{
let sortingField=new SortingField(converter, 0);
@ -69,62 +68,36 @@ describe("Test des champs de classement.", () =>
expect(getTH[0].innerHTML).toEqual(fixtures.sortingColumn1HTML);
expect(getTH[2].innerHTML).toEqual(fixtures.sortingColumn2HTML);
});
});
describe("Action des colonnes de classement en corrélation avec le convertiseur.", () =>
{
it("Le 1er clic sur l'entête d'une des colonnes doit classer les données dans le sens ascendant, puis descendant et ainsi de suite.", async () =>
it("Lorsqu'ils sont cliqués, doivent transmettre l'information au convertisseur + lui demander d'actualiser l'affichage.", () =>
{
let sortingField=new SortingField(converter, 2);
sortingField.field2HTML();
converter.datasSortingFields=[sortingField];
let getTHLink=document.querySelector("th a") as HTMLElement;
getTHLink.click();// tri ascendant
let getTR=document.querySelectorAll("tr");
let txtDatasViewsElt=getTR[1].innerHTML;
expect(txtDatasViewsElt).toEqual("<td>89</td><td>Actinium</td><td>Ac</td><td>Actinide</td><td>≤ 1</td>");
getTHLink.click();// tri descendant
getTR=document.querySelectorAll("tr");
txtDatasViewsElt=getTR[1].innerHTML;
expect(txtDatasViewsElt).toEqual("<td>40</td><td>Zirconium</td><td>Zr</td><td>Métal de transition</td><td>&gt; 100000</td>");
getTHLink.click();// de nouveau ascendant
getTR=document.querySelectorAll("tr");
txtDatasViewsElt=getTR[1].innerHTML;
expect(txtDatasViewsElt).toEqual("<td>89</td><td>Actinium</td><td>Ac</td><td>Actinide</td><td>≤ 1</td>");
const sortingField1=new SortingField(converter, 2);
sortingField1.field2HTML();
const sortingField2=new SortingField(converter, 3);
sortingField2.field2HTML();
converter.datasSortingFields=[sortingField1, sortingField2];
let getTHLinks=document.querySelectorAll("th a") as NodeListOf<HTMLElement>;
spyOn(converter, "refreshView");
getTHLinks[0].click();// tri ascendant 1er champ
expect(sortingField1.converter.datasSortedField).toEqual(sortingField1);
expect(sortingField1.converter.datasSortedField.order).toEqual("asc");
expect(converter.refreshView).toHaveBeenCalledTimes(1);
getTHLinks[1].click();// tri ascendant mais sur le second champ
expect(sortingField2.converter.datasSortedField).toEqual(sortingField2);
expect(sortingField2.converter.datasSortedField.order).toEqual("asc");
expect(converter.refreshView).toHaveBeenCalledTimes(2);
getTHLinks[0].click();// tri descendant sur le 1er champ
expect(sortingField1.converter.datasSortedField).toEqual(sortingField1);
expect(sortingField1.converter.datasSortedField.order).toEqual("desc");
expect(converter.refreshView).toHaveBeenCalledTimes(3);
getTHLinks[0].click();// de nouveau ascendant
expect(sortingField1.converter.datasSortedField).toEqual(sortingField1);
expect(sortingField1.converter.datasSortedField.order).toEqual("asc");
expect(converter.refreshView).toHaveBeenCalledTimes(4);
});
it("Prise en compte d'une fonction spécifique associée au champ de classement.", async () =>
{
const mySort=(a: any, b: any, order: "asc"|"desc"="asc") =>
{
const values=[ "> 100000", "> 1 et < 100 000", "≤ 1", "Traces", "Inexistant"];
if(order === "desc")
values.reverse();
if(values.indexOf(a) > values.indexOf(b))
return -1;
else if(values.indexOf(a) < values.indexOf(b))
return 1;
else
return 0;
};
converter.datasSortingFunctions=[{ datasFieldNb: 4, sort:mySort }];
let sortingField=new SortingField(converter, 4);
sortingField.field2HTML();
converter.datasSortingFields=[sortingField];
let getTHLink=document.querySelector("th a") as HTMLElement;
getTHLink.click();// tri ascendant
let getTR=document.querySelectorAll("tr");
let txtDatasViewsElt=getTR[1].innerHTML;
expect(txtDatasViewsElt).toEqual("<td>95</td><td>Américium</td><td>Am</td><td>Actinide</td><td>Inexistant</td>");
getTHLink.click();// tri descendant
getTR=document.querySelectorAll("tr");
txtDatasViewsElt=getTR[1].innerHTML;
expect(txtDatasViewsElt).toEqual("<td>1</td><td>Hydrogène</td><td>H</td><td>Non-métal</td><td>&gt; 100000</td>");
getTHLink.click();// de nouveau ascendant
getTR=document.querySelectorAll("tr");
txtDatasViewsElt=getTR[1].innerHTML;
expect(txtDatasViewsElt).toEqual("<td>95</td><td>Américium</td><td>Am</td><td>Actinide</td><td>Inexistant</td>");
});
});
});
});