Compare commits

...

3 Commits

8 changed files with 107 additions and 97 deletions

View File

@ -1,6 +1,6 @@
{
"name": "freedatas2html",
"version": "0.5.0",
"version": "0.5.2",
"description": "Visualization of data from various sources (CSV, API, HTML...) with filters, classification, pagination, etc.",
"main": "index.js",
"scripts": {

View File

@ -11,7 +11,7 @@ export class Render implements DatasRenders
allBegining:"<table>",
allEnding:"</table>",
fieldsBegining:"<thead><tr>",
fieldsEnding:"</tr><thead>",
fieldsEnding:"</tr></thead>",
fieldDisplaying:"<th>#FIELDNAME</th>",
linesBegining:"<tbody>",
linesEnding:"</tbody>",
@ -40,7 +40,7 @@ export class Render implements DatasRenders
if(this.settings.fieldsBegining !== undefined && this.settings.fieldDisplaying !== undefined && this.settings.fieldsEnding !== undefined )
{
datasHTML+=this.settings.fieldsBegining;
for (let i in this._converter.parseMetas!.fields)
for (let i in this._converter.parseMetas.fields)
datasHTML+=this.settings.fieldDisplaying.replace("#FIELDNAME", this._converter.parseMetas.fields[Number(i)]);
datasHTML+=this.settings.fieldsEnding;
}

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
import { FreeDatas2HTML, Selector } from "../src/freeDatas2HTML";
import { FreeDatas2HTML, Render} from "../src/freeDatas2HTML";
const errors=require("../src/errors.js");
const fixtures=require("./fixtures.js");
@ -134,10 +134,8 @@ describe("Test du script central de FreeDatas2HTML", () =>
expect(converter.parseErrors.length).toEqual(0);
});
it("Doit générer une erreur si au moins un des deux paramètres nécessaires au fonctionnement n'est pas fourni.", async () =>
it("Doit générer une erreur si lancé sur url fournie pour le fichier de données.", async () =>
{
await expectAsync(converter.run()).toBeRejectedWith(new Error(errors.converterNeedDatasElt));
converter.datasViewElt={ id:"datas" };
await expectAsync(converter.run()).toBeRejectedWith(new Error(errors.parserNeedUrl));
});
@ -181,8 +179,17 @@ describe("Test du script central de FreeDatas2HTML", () =>
converter.datasViewElt={ id:"datas" };
converter.datasSourceUrl="http://localhost:9876/datas/datas1.csv";
await converter.run();
let txtDatasViewsElt=document.getElementById("datas").innerHTML;
expect(txtDatasViewsElt).toEqual(fixtures.datasHTML);
const render=new Render(converter);
const htmlForDatas=render.rend2HTML(converter.parseDatas);
// On ne peut comparer directement au contenu du DOM,
// car le navigateur change certains caractères (exemple : ">" devient "&gt;")
expect(converter.datasHTML).toEqual(htmlForDatas);
// Mais le code commence tout de même par <table> :
const txtDatasViewsElt=document.getElementById("datas").innerHTML;
expect(txtDatasViewsElt.indexOf("<table>")).toEqual(0);
// Et on doit retrouver le bon nombre de lignes :
const getTR=document.getElementsByTagName("tr");
expect(getTR.length).toEqual(119);
});
it("Si demandé, doit afficher le nombre de lignes de données du fichier.", async () =>
@ -194,7 +201,5 @@ describe("Test du script central de FreeDatas2HTML", () =>
let txtDatasViewsElt=document.getElementById("counter").innerHTML;
expect(txtDatasViewsElt).toEqual("118");
});
});
});

View File

@ -85,7 +85,7 @@ describe("Test de la pagination.", () =>
beforeEach( async () =>
{
pagination.options={ displayElement: { id:"paginationOptions" }, values: [10,20,50,500] , name: "Choix de pagination :" };
pagination.selectedValue=10; // revoir car n'est pas testé si déclaré avant les options
pagination.selectedValue=10;
pagination.rend2HTML();
converter.pagination=pagination;
await converter.run();
@ -102,6 +102,18 @@ describe("Test de la pagination.", () =>
expect(getTR.length).toEqual(pagination.selectedValue+1); // 1er TR sert aux titres
});
it("La manipulation du sélecteur de pagination doit appeler la fonction actualisant l'affichage.", () =>
{
spyOn(converter, "refreshView");
let selectElement=document.getElementById("freeDatas2HTMLPaginationSelector") as HTMLInputElement;
selectElement.value="2";
selectElement.dispatchEvent(new Event('change'));
expect(converter.refreshView).toHaveBeenCalledTimes(1);
selectElement.value="0";
selectElement.dispatchEvent(new Event('change'));
expect(converter.refreshView).toHaveBeenCalledTimes(2);
});
it("Si une des options de pagination fournies est sélectionnée, doit afficher le nombre de résultats correspondants.", () =>
{
let selectElement=document.getElementById("freeDatas2HTMLPaginationSelector") as HTMLInputElement;
@ -124,6 +136,18 @@ describe("Test de la pagination.", () =>
let selectElement=document.getElementById("pages").innerHTML;
expect(selectElement).toEqual(fixtures.selectorForPages);
});
it("La manipulation du sélecteur de pages doit appeler la fonction actualisant l'affichage.", () =>
{
spyOn(converter, "refreshView");
let selectElement=document.getElementById("freeDatas2HTMLPagesSelector") as HTMLInputElement;
selectElement.value="2";
selectElement.dispatchEvent(new Event('change'));
expect(converter.refreshView).toHaveBeenCalledTimes(1);
selectElement.value="0";
selectElement.dispatchEvent(new Event('change'));
expect(converter.refreshView).toHaveBeenCalledTimes(2);
});
it("Si l'utilisateur sélectionne une des pages proposées, l'affichage des résultats doit s'adapter en prenant en compte la pagination sélectionnée.", () =>
{
@ -143,7 +167,5 @@ describe("Test de la pagination.", () =>
expect(getTR[18].innerHTML).toEqual(fixtures.lastLineForPageSelection2);
expect(getTR[50]).toBeUndefined();
});
});
});

61
tests/renderSpec.ts Normal file
View File

@ -0,0 +1,61 @@
import { FreeDatas2HTML, Render } from "../src/freeDatas2HTML";
const errors=require("../src/errors.js");
const fixtures=require("./fixtures.js");
describe("Test du moteur de rendu HTML.", () =>
{
let converter: FreeDatas2HTML;
let render: Render;
let datas: any[];
beforeEach(() =>
{
converter=new FreeDatas2HTML();
render=new Render(converter);
converter.parseMetas={ fields : [ "Z", "Élément", "Symbole", "Famille" ] };
datas=[{"Z":"1","Élément":"Hydrogène","Symbole":"H","Famille":"Non-métal"},{"Z":"2","Élément":"Hélium","Symbole":"He","Famille":"Gaz noble"},{"Z":"3","Élément":"Lithium","Symbole":"Li","Famille":"Métal alcalin"},{"Z":"4","Élément":"Béryllium","Symbole":"Be","Famille":"","Champ ignoré":"Je me sens ignoré !"}] ;// Famille volontairement vide et champ à ignoré pour le dernier
});
it("Doit générer une erreur, si lancé sans fournir une liste des champs de données.", () =>
{
converter.parseMetas=undefined;
expect(() => { return render.rend2HTML(datas) }).toThrowError(errors.renderNeedDatas);
converter.parseMetas={ delimiter: " "};
expect(() => { return render.rend2HTML(datas) }).toThrowError(errors.renderNeedDatas);
});
it("Ne doit pas générer d'erreur, si lancé avec une liste des champs de données, même s'il n'y a aucune donnée à afficher.", () =>
{
expect(() => { return render.rend2HTML([])}).not.toThrowError();
});
it("Doit retourner le code HTML créé en se basant sur la configuration par défaut, avec ou sans données à afficher.", () =>
{
// La configuration par défaut affiche le nom des champs, même quand il n'y a pas de données :
let html=render.rend2HTML([]);
expect(html).toEqual("<table><thead><tr><th>Z</th><th>Élément</th><th>Symbole</th><th>Famille</th></tr></thead><tbody></tbody></table>");
// Avec des données :
html=render.rend2HTML(datas);
expect(html).toEqual("<table><thead><tr><th>Z</th><th>Élément</th><th>Symbole</th><th>Famille</th></tr></thead><tbody><tr><td>1</td><td>Hydrogène</td><td>H</td><td>Non-métal</td></tr><tr><td>2</td><td>Hélium</td><td>He</td><td>Gaz noble</td></tr><tr><td>3</td><td>Lithium</td><td>Li</td><td>Métal alcalin</td></tr><tr><td>4</td><td>Béryllium</td><td>Be</td><td></td></tr></tbody></table>");
});
it("Doit retourner un code HTML correspondant à la configuration fournie, avec ou sans données à afficher.", () =>
{
render.settings=
{
allBegining:"<div id=\"test\"><h4>Pas de noms de champs !</h4>",
allEnding:"</div>",
linesBegining:"<div id=\"myDatas\">",
linesEnding:"</div>",
lineBegining:"<ul>",
lineEnding:"</ul>",
dataDisplaying:"<li><b>#FIELDNAME :</b> #VALUE</li>",
};
let html=render.rend2HTML([]);
expect(html).toEqual("<div id=\"test\"><h4>Pas de noms de champs !</h4><div id=\"myDatas\"></div></div>");
// Avec des données :
html=render.rend2HTML(datas);
expect(html).toEqual("<div id=\"test\"><h4>Pas de noms de champs !</h4><div id=\"myDatas\"><ul><li><b>Z :</b> 1</li><li><b>Élément :</b> Hydrogène</li><li><b>Symbole :</b> H</li><li><b>Famille :</b> Non-métal</li></ul><ul><li><b>Z :</b> 2</li><li><b>Élément :</b> Hélium</li><li><b>Symbole :</b> He</li><li><b>Famille :</b> Gaz noble</li></ul><ul><li><b>Z :</b> 3</li><li><b>Élément :</b> Lithium</li><li><b>Symbole :</b> Li</li><li><b>Famille :</b> Métal alcalin</li></ul><ul><li><b>Z :</b> 4</li><li><b>Élément :</b> Béryllium</li><li><b>Symbole :</b> Be</li><li><b>Famille :</b> </li></ul></div></div>");
});
});

View File

@ -184,91 +184,20 @@ describe("Test des filtres de données", () =>
};
expect(selector.dataIsOk(data2Test)).toBeTrue();
});
});
describe("Action des sélecteurs en corrélation avec le convertisseur.", () =>
{
beforeEach( async () =>
it("La manipulation d'un sélecteur doit appeler la fonction actualisant l'affichage, y compris pour supprimer ce filtre (0).", () =>
{
document.body.insertAdjacentHTML("afterbegin", fixtures.datasViewEltHTML);
converter=new FreeDatas2HTML();
converter.datasViewElt={ id:"datas" };
converter.datasSourceUrl="http://localhost:9876/datas/datas1.csv";
await converter.parse();
selector=new Selector(converter, 3, { id:"selector1" });
selector.selector2HTML();
});
it("Le choix d'une option dans un des sélecteurs doit modifier le contenu du tableau pour ne garder que les données correspondantes et les afficher toutes si sélection 0.", () =>
{
converter.datasSelectors=[selector];
spyOn(converter, "refreshView");
let selectElement=document.getElementById("freeDatas2HTML_selector1") as HTMLInputElement;
selectElement.value="4";
selectElement.dispatchEvent(new Event('change'));
let txtDatasViewsElt=document.getElementById("datas").innerHTML;
expect(txtDatasViewsElt).toEqual(fixtures.datasHTMLFor1Select);
expect(converter.refreshView).toHaveBeenCalledTimes(1);
selectElement.value="0";
selectElement.dispatchEvent(new Event('change'));
txtDatasViewsElt=document.getElementById("datas").innerHTML;
expect(txtDatasViewsElt).toEqual(fixtures.datasHTML);
});
it("Si plusieurs sélecteurs sont utilisés, seules les données correspondant à tous ces choix doivent être affichées. Il peut n'y avoir aucun résultat.", () =>
{
let selector2=new Selector(converter, 4, { id:"selector2" });
selector2.selector2HTML();
converter.datasSelectors=[selector, selector2];
let selectElement=document.getElementById("freeDatas2HTML_selector1") as HTMLInputElement;
selectElement.value="2";
selectElement=document.getElementById("freeDatas2HTML_selector2") as HTMLInputElement;
selectElement.value="1";
selectElement.dispatchEvent(new Event('change'));
let txtDatasViewsElt=document.getElementById("datas").innerHTML;
expect(txtDatasViewsElt).toEqual(fixtures.datasHTMLFor2Select);
selectElement.value="4";
selectElement.dispatchEvent(new Event('change'));
txtDatasViewsElt=document.getElementById("datas").innerHTML;
expect(txtDatasViewsElt).toEqual(fixtures.datasHTMLFor2SelectNone);
});
it("Si un séparateur est fourni pour un sélecteur, lorsque qu'une valeur y est sélectionnée, toutes les lignes de données la contenant doivent être affichées.", async () =>
{
converter.datasSourceUrl="http://localhost:9876/datas/datas1+tagsfield.csv";
await converter.parse();
selector=new Selector(converter, 5, { id:"selector1" });
selector.separator="|";
selector.selector2HTML();
converter.datasSelectors=[selector];
let selectElement=document.getElementById("freeDatas2HTML_selector1") as HTMLInputElement;
selectElement.value="11"; //="Exemple10" retournant une seule ligne
selectElement.dispatchEvent(new Event('change'));
let txtDatasViewsElt=document.getElementById("datas").innerHTML;
expect(txtDatasViewsElt).toEqual(fixtures.datasHTMLForSelectTagsField);
});
it("Les filtres basés sur un séparateur peuvent fonctionner avec un autre filtre.", async () =>
{
converter.datasSourceUrl="http://localhost:9876/datas/datas1+tagsfield.csv";
await converter.parse();
selector=new Selector(converter, 4, { id:"selector1" });
selector.selector2HTML();
let selector2=new Selector(converter, 5, { id:"selector2" });
selector2.separator="|";
selector2.selector2HTML();
converter.datasSelectors=[selector, selector2];
let selectElement=document.getElementById("freeDatas2HTML_selector2") as HTMLInputElement;
selectElement.value="11"; //="Exemple10" retournant une seule ligne
selectElement.dispatchEvent(new Event('change'));
let txtDatasViewsElt=document.getElementById("datas").innerHTML;
expect(txtDatasViewsElt).toEqual(fixtures.datasHTMLForSelectTagsField);
selectElement=document.getElementById("freeDatas2HTML_selector1") as HTMLInputElement;
selectElement.value="1"; // doit garder la ligne
selectElement.dispatchEvent(new Event('change'));
expect(txtDatasViewsElt).toEqual(fixtures.datasHTMLForSelectTagsField);
selectElement.value="3"; // doit supprimer la ligne restant
selectElement.dispatchEvent(new Event('change'));
txtDatasViewsElt=document.getElementById("datas").innerHTML;
expect(txtDatasViewsElt).toEqual("<table><thead><tr><th>Z (numéro atomique)</th><th>Élément</th><th>Symbole</th><th>Famille</th><th>Abondance des éléments dans la croûte terrestre (μg/k)</th><th>Étiquettes</th></tr></thead><tbody></tbody></table>");
expect(converter.refreshView).toHaveBeenCalledTimes(2);
});
});
});

View File

@ -3,7 +3,7 @@ import { FreeDatas2HTML, Selector, SortingField } from "../src/freeDatas2HTML";
const errors=require("../src/errors.js");
const fixtures=require("./fixtures.js");
describe("Test des champs de classement.", () =>
xdescribe("Test des champs de classement.", () =>
{
let converter: FreeDatas2HTML;
let sortingField: SortingField;