Création d'une classe séparée pour gérer la pagination.

This commit is contained in:
Fabrice PENHOËT 2021-09-21 17:46:04 +02:00
parent b811c61286
commit bbcf9918d0
6 changed files with 353 additions and 318 deletions

View File

@ -3,11 +3,13 @@ module.exports =
datasNotFound : "Aucune donnée n'a été trouvée.",
elementNotFound : "Aucun élément HTML n'a été trouvé ayant comme \"id\" : ",
needDatasElt: "Merci de fournir un id valide pour l'élément où afficher les données.",
needNaturalNumber: "Merci de fournir un nombre entier supérieur ou égal à zéro pour désigner chaque colonne.",
needPagesSelectorElt: "Merci de fournir l'id de l'élément où afficher le sélecteur de pages.",
needPaginationByDefaultBeInOptions: "La valeur de pagination par défaut doit faire partie des options proposées.",
needPaginationOptionsValues: "Vous n'avez fourni aucune options possibles pour la pagination.",
needPositiveInteger: "Merci de fournir un nombre entier supérieur à zéro pour désigner chaque option de pagination.",
needUrl: "Merci de fournir une url valide pour le fichier CSV à parser.",
paginationNeedDatas: "Il ne peut y avoir de pagination, si les données n'ont pas été récupérées.",
pagination2HTMLFail : "Toutes les donnée nécessaires à la création des sélecteurs de pagination n'ont pas été fournies.",
parserFail: "La lecture des données du fichier a échoué.",
refreshFail: "Le nom des champs et l'élement du DOM receveur sont nécessaires à l'affichage des données.",
selector2HTMLFail: "Le création d'un filtre dans le DOM nécessite l'initialisation de l'élément HTML et du numéro du champs à filter.",

View File

@ -2,7 +2,8 @@ const Papa = require("papaparse");
const errors = require("./errors.js");
const { compare }= require('natural-orderby');
import { DOMElement, Pagination, Selectors, SortingFields, SortingFunctions } from "./freeDatas2HTMLInterfaces";
import { DOMElement, Paginations, Selectors, SortingFields, SortingFunctions } from "./freeDatas2HTMLInterfaces";
import { Pagination} from "./freeDatas2HTMLPagination";
import { Selector } from "./freeDatas2HTMLSelector";
import { SortingField } from "./freeDatas2HTMLSortingField";
@ -39,18 +40,7 @@ export class FreeDatas2HTML
datasSortedField: SortingFields|undefined;
// La Pagination :
private _Pagination: Pagination|undefined;
// Fonction utile pour tester les numéros de colonne :
public static isPositiveInteger(nb: number)
{
return (Number.isInteger(nb) === false || nb <= 0) ? false : true;
}
// Fonction utile pour tester les valeurs de Pagination :
public static isNaturalNumber(nb: number)
{
return (Number.isInteger(nb) === false || nb < 0) ? false : true;
}
pagination: Paginations|undefined;
// Vérifie que l'élément devant afficher les données existe dans le DOM :
set datasViewElt(elt: DOMElement)
@ -80,9 +70,9 @@ export class FreeDatas2HTML
this._datasSortingFunctions=[];
for(let i = 0; i < SortingFunctions.length; i++)
{
if(FreeDatas2HTML.isNaturalNumber(SortingFunctions[i].datasFieldNb) === false)
console.error(errors.needNaturalNumber);
else
//if(FreeDatas2HTML.isNaturalNumber(SortingFunctions[i].datasFieldNb) === false) // revoir pour tester l'existence du champ
// console.error(errors.needNaturalNumber); // -> à remplacer par un test d'existence de colonne !
//else
this._datasSortingFunctions.push(SortingFunctions[i]);
}
}
@ -98,73 +88,6 @@ export class FreeDatas2HTML
return undefined;
}
// Vérifie la cohérence de toutes les options de pagination reçues :
set Pagination(config: Pagination)
{
this._Pagination={};
// Si une valeur par défaut est fournie ou des valeurs en option, un id valide doit être aussi fourni pour recueillir le sélecteur de pages :
if(config.selectedValue !== undefined || config.options !== undefined)
{
if(config.pages === undefined)
throw new Error(errors.needPagesSelectorElt);
let checkContainerExist=document.getElementById(config.pages.displayElement.id);
if(checkContainerExist === null)
throw new Error(errors.elementNotFound+config.pages.displayElement.id);
else
{
this.Pagination.pages =
{
displayElement:
{
id:config.pages.displayElement.id,
eltDOM: checkContainerExist
},
name: (config.pages.name) ? config.pages.name : "Pages :", // rendre obligatoire cette option s'il doit y avoir affichage ?
selectedValue:1, // c'est la 1ère page qui est affichée par défaut
}
}
}
// Les options de Pagination proposées à l'utilisateur :
if(config.options !== undefined)
{
// Un élément HTML doit exister pour accueillir les options :
let checkContainerExist=document.getElementById(config.options.displayElement.id);
if(checkContainerExist === null)
throw new Error(errors.elementNotFound+config.options.displayElement.id);
else
{
// Seules des entiers positifs sont possibles
for(let i = 0; i < config.options.values.length; i++)
{
if(FreeDatas2HTML.isPositiveInteger(config.options.values[i]) === false)
throw new Error(errors.needPositiveInteger);
}
this._Pagination.options =
{
displayElement: { id:config.options.displayElement.id, eltDOM:checkContainerExist },
name: (config.options.name) ? config.options.name : "Pagination :", // idem, rendre obligatoire ?
values:config.options.values
};
}
}
// Valeur de Pagination par défaut qui doit faire partie des options proposées si elles existent :
if(config.selectedValue !== undefined)
{
if(config.options !== undefined && (config.options.values.indexOf(config.selectedValue) === -1))
throw new Error(errors.needPaginationByDefaultBeInOptions);
if(FreeDatas2HTML.isPositiveInteger(config.selectedValue))
this._Pagination.selectedValue=config.selectedValue;
else
throw new Error(errors.needPositiveInteger);
}
}
// Retourne les options de Pagination actuelles
get Pagination(): Pagination
{
return <Pagination>this._Pagination;
}
// Parse des données distantes (url) fournies en CSV :
public async parse(): Promise<any>
{
@ -221,36 +144,6 @@ export class FreeDatas2HTML
console.error(this.parseErrors);
else
{
let converter=this;
// Si demandé, création d'une liste de valeurs de Pagination possibles
if(converter.Pagination !==undefined && converter.Pagination.options !==undefined && converter.Pagination.options.values.length > 0)
{
const values=converter.Pagination.options.values;
let selectorsHTML="<label for='freeDatas2HTMLPaginationSelector'>"+converter.Pagination.options.name+" </label><select name='freeDatas2HTMLPaginationSelector' id='freeDatas2HTMLPaginationSelector'><option value='0'>----</option>";
for(let j in values)
selectorsHTML+="<option value='"+(Number(j)+1)+"'>"+values[j]+"</option>";
selectorsHTML+="</select>";
converter.Pagination.options.displayElement.eltDOM!.innerHTML=selectorsHTML;
let selectElement = document.getElementById("freeDatas2HTMLPaginationSelector") as HTMLInputElement;
// Si une Pagination par défaut existe, on la sélectionne :
if(converter.Pagination.selectedValue !== undefined)
{
let indexSelectedValue=converter.Pagination.options.values.indexOf(converter.Pagination.selectedValue)+1;
selectElement.value=""+indexSelectedValue;
}
selectElement.addEventListener('change', function(e)
{
if(selectElement.value === "0")
converter.Pagination.selectedValue=undefined; // = pas de Pagination
else
converter.Pagination.selectedValue=values[Number(selectElement.value)-1];
// on regénère le HTML :
converter.datasHTML=converter.createDatasHTML(converter.parseMetas!.fields as string[], converter.parseDatas);
converter.refreshView();
});
}
// Si tout est ok, affichage initial de toutes les données du fichier
this.refreshView();
return true;
@ -288,11 +181,11 @@ export class FreeDatas2HTML
datas.sort( (a, b) => compare( {order: fieldOrder} )(a[field], b[field]));
}
// Dois-je prendre en compte une Pagination ?
// Dois-je prendre en compte une pagination ?
let firstData=0;
if (this.Pagination !== undefined && this.Pagination.selectedValue !== undefined && this.Pagination.pages !== undefined && this.Pagination.pages.selectedValue !== undefined)
firstData=this.Pagination.selectedValue*(this.Pagination.pages.selectedValue-1);
let maxData = (this.Pagination !== undefined && this.Pagination.selectedValue !== undefined) ? this.Pagination.selectedValue : datas.length+1;
if (this.pagination !== undefined && this.pagination.selectedValue !== undefined && this.pagination.pages !== undefined && this.pagination.pages.selectedValue !== undefined)
firstData=this.pagination.selectedValue*(this.pagination.pages.selectedValue-1);
let maxData = (this.pagination !== undefined && this.pagination.selectedValue !== undefined) ? this.pagination.selectedValue : datas.length+1;
// Création du tableau de données :
let datasHTML="<table><thead>";
@ -308,7 +201,7 @@ export class FreeDatas2HTML
let i=0;
while(this.datasSelectors[i] !== undefined && visible===true)
{
visible=this.datasSelectors[i].dataIsOk(datas[row]); // à revoir car cette fonction est nécessaire !
visible=this.datasSelectors[i].dataIsOk(datas[row]);
i++;
}
}
@ -329,39 +222,14 @@ export class FreeDatas2HTML
nbTotal++;
}
datasHTML+="</tbody></table>";
// Si Pagination définie et tous les enregistrements n'ont pas été affichés, alors création d'un sélecteur de pages
if (this.Pagination !== undefined && this.Pagination.selectedValue !== undefined && this.Pagination.pages !== undefined && nbTotal > this.Pagination.selectedValue)
{
let nbPages=Math.ceil(nbTotal/this.Pagination.selectedValue);
let selectorsHTML="<label for='freeDatas2HTMLPagesSelector'>"+this.Pagination.pages.name+" </label><select name='freeDatas2HTMLPagesSelector' id='freeDatas2HTMLPagesSelector'><option value='1'>1</option>";
this.Pagination.pages.values=[1];
for(let j=2; j <= nbPages; j++)
{
selectorsHTML+="<option value='"+j+"'>"+j+"</option>";
this.Pagination.pages.values.push(j);
}
selectorsHTML+="</select>";
this.Pagination.pages.displayElement.eltDOM!.innerHTML=selectorsHTML;
let selectElement = document.getElementById("freeDatas2HTMLPagesSelector") as HTMLInputElement;
if(this.Pagination.pages.selectedValue !== undefined)
selectElement.value=""+this.Pagination.pages.selectedValue;
let converter=this;
this.Pagination.pages.selectedValue=1;
selectElement.addEventListener('change', function(e)
{
converter.Pagination.pages!.selectedValue=Number(selectElement.value);
converter.datasHTML=converter.createDatasHTML(converter.parseMetas!.fields as string[], converter.parseDatas);
converter.refreshView();
});
}
else if(this.Pagination !== undefined && this.Pagination.pages !== undefined)
this.Pagination.pages.displayElement.eltDOM!.innerHTML="";
// Tout réaffichage peut entraîner une modification du nombre de pages (évolution filtres, etc.)
if(this.pagination !== undefined)
this.pagination.creaPageSelector(nbTotal);
return datasHTML;
}
}
// Permet l'appel des dépendances via un seul script
export { Pagination } from "./freeDatas2HTMLPagination";
export { Selector } from "./freeDatas2HTMLSelector";
export { SortingField } from "./freeDatas2HTMLSortingField";

View File

@ -3,6 +3,27 @@ export interface DOMElement
id: string;
eltDOM?: HTMLElement;
}
export interface Paginations
{
options?: PaginationsOptions;
selectedValue?: number; // on peut utiliser une Pagination sans proposer d'options à l'utilisateur.
pages: PaginationsPages;
rend2HTML(): void;
creaPageSelector(nbTotal:number) : void;
}
export interface PaginationsOptions
{
displayElement: DOMElement;
name?: string;
values: number[];
};
export interface PaginationsPages
{
displayElement: DOMElement;
name: string;
values?: number[];
selectedValue?: number;
}
export interface Selectors
{
datasViewElt: DOMElement;
@ -24,20 +45,3 @@ export interface SortingFunctions
datasFieldNb: number;
sort(a: any,b: any, order?: "asc"|"desc"): number; // cf. https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
}
export interface Pagination
{
options?:
{
displayElement: DOMElement;
name?: string; // rendre obligatoire ?
values: number[];
};
selectedValue?: number; // on peut utiliser une Pagination sans proposer d'options à l'utilisateur.
pages?:
{
displayElement: DOMElement;
name?: string; // rendre obligatoire ?
values?: number[];
selectedValue?: number;
}
}

View File

@ -0,0 +1,150 @@
const errors = require("./errors.js");
import { DOMElement, Paginations, PaginationsOptions, PaginationsPages } from "./freeDatas2HTMLInterfaces";
import { FreeDatas2HTML } from "./freeDatas2HTML";
export class Pagination implements Paginations
{
private _converter: FreeDatas2HTML;
// la pagination en cours, qui peut être modifiée/initialisée par l'utilisateur, si des options lui sont proposées :
private _selectedValue: number|undefined;
// les éventuelles options de pagination :
private _options: PaginationsOptions | undefined;
// les pages proposées, si le nombre d'enregistrement est > à la pagination en cours.
private _pages: PaginationsPages;
public static isPositiveInteger(nb: number)
{
return (Number.isInteger(nb) === false || nb <= 0) ? false : true;
}
// Injection de la classe principale, mais uniquement si les données ont été importées
// De plus l'élément du DOM devant recevoir la liste des pages doit exister
constructor(converter: FreeDatas2HTML, pagesElt: DOMElement, pagesName: string="Pages")
{
if(converter.parseMetas === undefined || converter.parseMetas.fields === undefined)
throw new Error(errors.paginationNeedDatas);
else
{
let checkContainerExist=document.getElementById(pagesElt.id);
if(checkContainerExist === null)
throw new Error(errors.elementNotFound+pagesElt.id);
else
{
this._converter=converter;
this._pages={ displayElement: { id:pagesElt.id, eltDOM:checkContainerExist }, name: pagesName };
}
}
}
set selectedValue(value : number|undefined)
{
if(value === undefined || !Pagination.isPositiveInteger(value))
throw new Error(errors.needPositiveInteger);
if(this.options !== undefined && this.options.values.indexOf(value) === -1)
throw new Error(errors.needPaginationByDefaultBeInOptions);
this._selectedValue=value;
}
get selectedValue() : number|undefined
{
return this._selectedValue;
}
set options(options : PaginationsOptions|undefined)
{
if(options !== undefined)
{
let checkContainerExist=document.getElementById(options.displayElement.id);
if(checkContainerExist === null)
throw new Error(errors.elementNotFound+options.displayElement.id);
else
options.displayElement.eltDOM=checkContainerExist;
if(options.values.length === 0)
throw new Error(errors.needPaginationOptionsValues);
for(let i in options.values)
{
if(!Pagination.isPositiveInteger(options.values[i]))
throw new Error(errors.needPositiveInteger);
}
options.name= (options.name===undefined) ? "Pagination" : options.name ; // on garde la possibilité d'une chaîne vide, si souhaité
this._options=options;
}
}
get options() : PaginationsOptions|undefined
{
return this._options;
}
get pages() : PaginationsPages
{
return this._pages;
}
// Création du <select> correspondant aux choix de valeurs de pagination.
public rend2HTML() : void
{
if(this._converter === undefined || this._options === undefined)
throw new Error(errors.pagination2HTMLFail);
else
{
let selectorsHTML="<label for='freeDatas2HTMLPaginationSelector'>"+this._options.name+" </label><select name='freeDatas2HTMLPaginationSelector' id='freeDatas2HTMLPaginationSelector'><option value='0'>----</option>";
for(let j in this._options.values)
selectorsHTML+="<option value='"+(Number(j)+1)+"'>"+this._options.values[j]+"</option>";
selectorsHTML+="</select>";
this._options.displayElement.eltDOM!.innerHTML=selectorsHTML; // initialiser dans le setter
let selectElement=document.getElementById("freeDatas2HTMLPaginationSelector") as HTMLInputElement;
// Si une Pagination par défaut existe, on la sélectionne :
if(this._selectedValue !== undefined)
{
let indexSelectedValue=this._options.values.indexOf(this._selectedValue)+1;
selectElement.value=""+indexSelectedValue;
}
const pagination=this;
selectElement.addEventListener("change", function(e)
{
if(selectElement.value === "0")
pagination._selectedValue=undefined; // = pas de Pagination
else
pagination._selectedValue=pagination._options!.values[Number(selectElement.value)-1];
// on regénère le HTML :
pagination._converter.refreshView();
});
}
}
// Création du <select> permettant de changer de page
creaPageSelector(nbTotal:number) : void
{
if (this.selectedValue !== undefined)
{
if( nbTotal > this.selectedValue)
{
let nbPages=Math.ceil(nbTotal/this.selectedValue);
let selectorsHTML="<label for='freeDatas2HTMLPagesSelector'>"+this.pages.name+" </label><select name='freeDatas2HTMLPagesSelector' id='freeDatas2HTMLPagesSelector'><option value='1'>1</option>";
this.pages.values=[1];
for(let j=2; j <= nbPages; j++)
{
selectorsHTML+="<option value='"+j+"'>"+j+"</option>";
this.pages.values.push(j);
}
selectorsHTML+="</select>";
this.pages.displayElement.eltDOM!.innerHTML=selectorsHTML;
let selectElement=document.getElementById("freeDatas2HTMLPagesSelector") as HTMLInputElement;
if(this.pages.selectedValue !== undefined)
selectElement.value=""+this.pages.selectedValue;
this.pages.selectedValue=1;
let pagination=this;
selectElement.addEventListener('change', function(e)
{
pagination.pages.selectedValue=Number(selectElement.value);
pagination._converter.refreshView();
});
}
else
this.pages.displayElement.eltDOM!.innerHTML="";
}
else
this.pages.displayElement.eltDOM!.innerHTML="";
}
}

View File

@ -2,7 +2,7 @@ import { FreeDatas2HTML, Selector } from "../src/freeDatas2HTML";
const errors=require("../src/errors.js");
const fixtures=require("./fixtures.js");
xdescribe("Test du script central de FreeDatas2HTML", () =>
describe("Test du script central de FreeDatas2HTML", () =>
{
let converter: FreeDatas2HTML;
@ -39,23 +39,7 @@ xdescribe("Test du script central de FreeDatas2HTML", () =>
expect(() => { return converter.datasSourceUrl=" "; }).toThrowError(errors.needUrl);
});
it("Doit retourner un booléen indiquant si un nombre est naturel ou non.", () =>
{
expect(FreeDatas2HTML.isNaturalNumber(-1)).toBeFalse();
expect(FreeDatas2HTML.isNaturalNumber(1.25)).toBeFalse();
expect(FreeDatas2HTML.isNaturalNumber(0)).toBeTrue();
expect(FreeDatas2HTML.isNaturalNumber(1)).toBeTrue();
});
it("Doit retourner un booléen indiquant si un nombre est un entier positif ou non.", () =>
{
expect(FreeDatas2HTML.isPositiveInteger(-1)).toBeFalse();
expect(FreeDatas2HTML.isPositiveInteger(1.25)).toBeFalse();
expect(FreeDatas2HTML.isPositiveInteger(0)).toBeFalse();
expect(FreeDatas2HTML.isPositiveInteger(1)).toBeTrue();
});
// Classement des données :
// Fonction spécfique de classement des données :
it("Doit me retourner la fonction associée à une colonne, de manière à ce qu'elle soit utilisable pour comparer deux valeurs.", () =>
{
// Fonction volontairement basique, car ce n'est pas la fonction que l'on teste ici, mais le fait que l'on puisse l'utiliser !
@ -72,58 +56,6 @@ xdescribe("Test du script central de FreeDatas2HTML", () =>
expect(converter.getSortingFunctionForField(0)).toBeDefined();
expect([7,9,3,5].sort(converter.getSortingFunctionForField(0).sort)).toEqual([9,7,5,3]);
});
// Pagination :
it("Doit générer une erreur quand aucun élément n'est fourni pour recevoir le sélecteur de pages, alors que cela est nécessaire.", () =>
{
expect(() => { return converter.Pagination={ selectedValue:10 }; }).toThrowError(errors.needPagesSelectorElt);
expect(() => { return converter.Pagination={ options: { displayElement: { id:"paginationOptions" }, values: [10,20] }}; }).toThrowError(errors.needPagesSelectorElt);
});
it("Doit générer une erreur si l'élément fourni pour recevoir le sélecteur de pages n'existe pas dans le DOM.", () =>
{
expect(() => { return converter.Pagination={ selectedValue:10, pages: { displayElement: { id:"dontExist" }} }; }).toThrowError(errors.elementNotFound+"dontExist");
});
it("Doit générer une erreur si l'élément fourni pour recevoir le sélecteur de Pagination n'existe pas dans le DOM.", () =>
{
expect(() => { return converter.Pagination={ options: { displayElement: { id:"dontExist" }, values: [10,20] }, pages: { displayElement: { id:"pages" }}}; }).toThrowError(errors.elementNotFound+"dontExist");
});
it("Doit générer une erreur si au moins une des options de Pagination proposée n'est pas un entier positif.", () =>
{
expect(() => { return converter.Pagination={ options: { displayElement: { id:"paginationOptions" }, values:[0,10,20] }, pages: { displayElement: { id:"pages" }}}; }).toThrowError(errors.needPositiveInteger);
});
it("Doit générer une erreur si la Pagination par défaut n'est pas un entier positif.", () =>
{
expect(() => { return converter.Pagination={ selectedValue:0, pages: { displayElement: { id:"pages" }} }; }).toThrowError(errors.needPositiveInteger);
});
it("Doit générer une erreur si la Pagination par défaut ne fait pas partie des valeurs proposées en option.", () =>
{
expect(() => { return converter.Pagination={ selectedValue:15, options: { displayElement: { id:"paginationOptions" }, values:[10,20,50] }, pages: { displayElement: { id:"pages" }}}; }).toThrowError(errors.needPaginationByDefaultBeInOptions);
});
it("Doit accepter une configuration correcte pour la Pagination.", () =>
{
let PaginationOk =
{
selectedValue:10,
options:
{
displayElement : { id:"paginationOptions" },
values: [10,20,50],
name: "Choix de Pagination :"
},
pages:
{
displayElement : { id:"pages" },
name: "Page à afficher :"
}
};
expect(() => { return converter.Pagination=PaginationOk; }).not.toThrowError();
});
});
describe("Parsage du fichier et création du tableau de données", () =>
@ -211,84 +143,4 @@ xdescribe("Test du script central de FreeDatas2HTML", () =>
});
});
describe("Création et action des options permettant de paginer les données affichées.", () =>
{
beforeEach( () =>
{
converter.datasViewElt={ id:"datas" };
converter.datasSourceUrl="http://localhost:9876/datas/datas1.csv";
converter.Pagination=
{
selectedValue:10,
options:
{
displayElement : { id:"paginationOptions" },
values: [10,20,50,500],
name: "Choix de pagination :"
},
pages:
{
displayElement : { id:"pages" },
name: "Page à afficher :"
}
}
});
it("Si des options de pagination sont fournies, doit générer un élement <select> listant les valeurs possibles.", async () =>
{
await converter.run();
expect(document.getElementById("paginationOptions").innerHTML).toEqual(fixtures.selectorForPagination);
});
it("Si une valeur de pagination par défaut fournie, ne doit pas afficher plus de données.", async () =>
{
await converter.run();
let getTableTr=document.querySelectorAll("tr");// attention, un tr sert aux titres
expect(getTableTr.length).toEqual(converter.Pagination.selectedValue+1);
});
it("Si une des options de pagination fournies est sélectionnée, doit afficher la première page de résultats correspondants.", async () =>
{
await converter.run();
let selectElement = document.getElementById("freeDatas2HTMLPaginationSelector") as HTMLInputElement;
selectElement.value="2"; // = 20 éléments / page
selectElement.dispatchEvent(new Event('change'));
let getTableTr=document.querySelectorAll("tr");
expect(getTableTr.length).toEqual(21);
selectElement.value="3"; // = 50 éléments / page
selectElement.dispatchEvent(new Event('change'));
getTableTr=document.querySelectorAll("tr");
expect(getTableTr.length).toEqual(51);
selectElement.value="0"; // = pas de Pagination, on affiche les 118 lignes du fichier
selectElement.dispatchEvent(new Event('change'));
getTableTr=document.querySelectorAll("tr");
expect(getTableTr.length).toEqual(119);
});
it("Si il y a plus de données que le nombre de lignes autorisées par page, un <select> listant les pages doit être affichés.", async () =>
{
await converter.run();
let btnPaginationElt=document.getElementById("pages").innerHTML;
expect(btnPaginationElt).toEqual(fixtures.selectorForPages);
});
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.", async () =>
{
await converter.run();
let selectElement = document.getElementById("freeDatas2HTMLPaginationSelector") as HTMLInputElement;
selectElement.value="3"; // = 50 éléments / page
selectElement.dispatchEvent(new Event('change'));
selectElement=document.getElementById("freeDatas2HTMLPagesSelector") as HTMLInputElement;
selectElement.value="2";
selectElement.dispatchEvent(new Event('change'));
let getTableTr=document.getElementsByTagName("tr");
expect(getTableTr[1].innerHTML).toEqual(fixtures.firstLineForPageSelection1);
expect(getTableTr[50].innerHTML).toEqual(fixtures.lastLineForPageSelection1);
selectElement.value="3"; // troisième page = incomplèet (18 enregistrements)
selectElement.dispatchEvent(new Event('change'));
getTableTr=document.getElementsByTagName("tr");
expect(getTableTr[1].innerHTML).toEqual(fixtures.firstLineForPageSelection2);
expect(getTableTr[18].innerHTML).toEqual(fixtures.lastLineForPageSelection2);
});
});
});

159
tests/paginationSpec.ts Normal file
View File

@ -0,0 +1,159 @@
import { FreeDatas2HTML, Pagination } from "../src/freeDatas2HTML";
const errors=require("../src/errors.js");
const fixtures=require("./fixtures.js");
describe("Test de la pagination.", () =>
{
let converter: FreeDatas2HTML;
let pagination: Pagination;
beforeEach( async () =>
{
document.body.insertAdjacentHTML("afterbegin", fixtures.datasViewEltHTML);
converter=new FreeDatas2HTML();
converter.datasViewElt={ id:"datas" };
converter.datasSourceUrl="http://localhost:9876/datas/datas1.csv";
await converter.parse();
pagination=new Pagination(converter, { id:"pages" }, "Page à afficher :");
});
afterEach( () =>
{
document.body.removeChild(document.getElementById("fixture"));
});
describe("Test des options de pagination.", () =>
{
it("Doit retourner un booléen indiquant si un nombre est un entier positif ou non.", () =>
{
expect(Pagination.isPositiveInteger(-1)).toBeFalse();
expect(Pagination.isPositiveInteger(1.25)).toBeFalse();
expect(Pagination.isPositiveInteger(0)).toBeFalse();
expect(Pagination.isPositiveInteger(1)).toBeTrue();
});
it("Doit générer une erreur si la pagination est initialisée sans données à traiter.", () =>
{
converter=new FreeDatas2HTML();
expect(() => { return new Pagination(converter, { id:"pages" }); }).toThrowError(errors.paginationNeedDatas);
});
it("Doit générer une erreur si initialisé en fournissant l'id d'un élément n'existant pas pour recevoir la liste des pages.", () =>
{
expect(() => { return new Pagination(converter, { id:"dontExist" }); }).toThrowError(errors.elementNotFound+"dontExist");
});
it("Ne doit pas générer d'erreur si initialisé correctement", () =>
{
expect(() => { return new Pagination(converter, { id:"pages" }); }).not.toThrowError();
});
it("Doit générer une erreur si l'id fourni pour l'élément devant recevoir le sélecteur de pagination n'existe pas dans le DOM.", () =>
{
expect(() => { return pagination.options={ displayElement: { id:"dontExist" }, values: [10,20] }; }).toThrowError(errors.elementNotFound+"dontExist");
});
it("Doit générer une erreur si les options de pagination sont initialisées avec un tableau de valeurs vide.", () =>
{
expect(() => { return pagination.options={ displayElement: { id:"paginationOptions" }, values: [] }; }).toThrowError(errors.needPaginationOptionsValues);
});
it("Doit générer une erreur si au moins une des options de pagination fournies n'est pas un entier positif.", () =>
{
expect(() => { return pagination.options={ displayElement: { id:"paginationOptions" }, values: [0,10,20] }; }).toThrowError(errors.needPositiveInteger);
});
it("Ne doit pas générer d'erreur si les options de pagination fournies sont correctes.", () =>
{
const test={ displayElement: { id:"paginationOptions" }, values: [10,20,50], name: "La pagination" };
expect(() => { return pagination.options=test}).not.toThrowError();
expect(pagination.options).toEqual(test);
});
it("Doit générer une erreur si la pagination par défaut n'est pas un entier positif.", () =>
{
expect(() => { return pagination.selectedValue=0; }).toThrowError(errors.needPositiveInteger);
});
it("Doit générer une erreur si la Pagination par défaut ne fait pas partie des valeurs proposées en option.", () =>
{
pagination.options={ displayElement: { id:"paginationOptions" }, values: [10,20,50] };
expect(() => { return pagination.selectedValue=15; }).toThrowError(errors.needPaginationByDefaultBeInOptions);
});
it("Doit accepter une pagination par défaut correcte, avec ou sans options proposées.", () =>
{
expect(() => { return pagination.selectedValue=10; }).not.toThrowError();
pagination.options={ displayElement: { id:"paginationOptions" }, values: [10,20,50] };
expect(() => { return pagination.selectedValue=10; }).not.toThrowError();
});
});
describe("Création et action des sélecteurs liés à la pagination des données.", () =>
{
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.rend2HTML();
converter.pagination=pagination;
await converter.run();
});
it("Si des options de pagination sont fournies, doit générer un élement <select> listant les valeurs possibles.", () =>
{
expect(document.getElementById("paginationOptions").innerHTML).toEqual(fixtures.selectorForPagination);
});
it("Si une valeur de pagination par défaut fournie, ne doit pas afficher plus de données.", () =>
{
let getTR=document.getElementsByTagName("tr");
expect(getTR.length).toEqual(pagination.selectedValue+1); // 1er TR sert aux titres
});
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;
selectElement.value="2"; // = 20 éléments / page
selectElement.dispatchEvent(new Event('change'));
let getTR=document.getElementsByTagName("tr");
expect(getTR.length).toEqual(21);
selectElement.value="3"; // = 50 éléments / page
selectElement.dispatchEvent(new Event('change'));
getTR=document.getElementsByTagName("tr");
expect(getTR.length).toEqual(51);
selectElement.value="0"; // = pas de Pagination, on affiche les 118 lignes du fichier
selectElement.dispatchEvent(new Event('change'));
getTR=document.getElementsByTagName("tr");
expect(getTR.length).toEqual(119);
});
it("Si il y a plus de données que le nombre de lignes autorisées par page, un <select> listant les pages doit être affiché.", () =>
{
let selectElement=document.getElementById("pages").innerHTML;
expect(selectElement).toEqual(fixtures.selectorForPages);
});
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.", () =>
{
let selectElement=document.getElementById("freeDatas2HTMLPaginationSelector") as HTMLInputElement;
selectElement.value="3"; // = 50 éléments / page
selectElement.dispatchEvent(new Event('change'));
selectElement=document.getElementById("freeDatas2HTMLPagesSelector") as HTMLInputElement;
selectElement.value="2";
selectElement.dispatchEvent(new Event('change'));
let getTR=document.getElementsByTagName("tr");
expect(getTR[1].innerHTML).toEqual(fixtures.firstLineForPageSelection1);
expect(getTR[50].innerHTML).toEqual(fixtures.lastLineForPageSelection1);
selectElement.value="3"; // troisième page = incomplète (18 enregistrements)
selectElement.dispatchEvent(new Event('change'));
getTR=document.getElementsByTagName("tr");
expect(getTR[1].innerHTML).toEqual(fixtures.firstLineForPageSelection2);
expect(getTR[18].innerHTML).toEqual(fixtures.lastLineForPageSelection2);
expect(getTR[50]).toBeUndefined();
});
});
});