Création d'une classe spécifique aux ressources distantes (url, headers...)

This commit is contained in:
Fabrice PENHOËT 2021-10-11 16:44:20 +02:00
parent 776c9a8f40
commit e829b881e8
17 changed files with 228 additions and 96 deletions

View File

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

View File

@ -3,7 +3,6 @@ module.exports =
converterElementNotFound : "Aucun élément HTML n'a été trouvé ayant comme \"id\" : ", converterElementNotFound : "Aucun élément HTML n'a été trouvé ayant comme \"id\" : ",
converterFieldNotFound : "Le champ n'existe pas dans les données ou les données n'ont pas encore été chargées.", converterFieldNotFound : "Le champ n'existe pas dans les données ou les données n'ont pas encore été chargées.",
converterNeedDatasElt: "Merci de fournir un id valide pour l'élément où afficher les données.", converterNeedDatasElt: "Merci de fournir un id valide pour l'élément où afficher les données.",
converterNeedDatas: "Merci de fournir les données à traiter.",
converterRefreshFail: "Le nom des champs et l'élement du DOM receveur sont nécessaires à l'affichage des données.", converterRefreshFail: "Le nom des champs et l'élement du DOM receveur sont nécessaires à l'affichage des données.",
pagination2HTMLFail : "Toutes les donnée nécessaires à la création des sélecteurs de pagination n'ont pas été fournies.", pagination2HTMLFail : "Toutes les donnée nécessaires à la création des sélecteurs de pagination n'ont pas été fournies.",
paginationNeedByfaultValueBeInOptions: "La valeur de pagination par défaut doit faire partie des options proposées.", paginationNeedByfaultValueBeInOptions: "La valeur de pagination par défaut doit faire partie des options proposées.",
@ -15,9 +14,11 @@ module.exports =
parserMeetErrors : "Au moins une erreur a été rencontrée durant le traitement des données.", parserMeetErrors : "Au moins une erreur a été rencontrée durant le traitement des données.",
parserNeedDatas: "Merci de fournir une chaîne de caractères valide à parser.", parserNeedDatas: "Merci de fournir une chaîne de caractères valide à parser.",
parserNeedSource: "Merci de fournir une chaîne de caractères où une url pour les données à parser.", parserNeedSource: "Merci de fournir une chaîne de caractères où une url pour les données à parser.",
parserNeedUrl: "Merci de fournir une url valide pour la source distante de données.",
parserRemoteFail: "Erreur rencontrée durant l'accès aux données distantes.", parserRemoteFail: "Erreur rencontrée durant l'accès aux données distantes.",
parserTypeError: "Une donnée a été trouvée avec un type imprévu : ", parserTypeError: "Une donnée a été trouvée avec un type imprévu : ",
remoteSourceHeaderUnallowed: "Le nom d'une des entêtes passées n'est pas autorisé.",
remoteSourceNeedUrl: "Merci de fournir une url valide pour la source distante de données.",
remoteSourceUrlFail: "L'url fournie ne semble pas valide.",
renderNeedDatas: "Il ne peut y avoir de pagination, si les données n'ont pas été récupérées.", renderNeedDatas: "Il ne peut y avoir de pagination, si les données n'ont pas été récupéré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.", 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.",
selectorCheckIsOkFail: "Le test est lancé sur un filtre incorrectement initialisé ou sur un attribut absent de la donnée à tester.", selectorCheckIsOkFail: "Le test est lancé sur un filtre incorrectement initialisé ou sur un attribut absent de la donnée à tester.",

View File

@ -19,7 +19,8 @@ const initialise = async () =>
}; };
// Création d'un convertisseur parsant les données d'un fichier CSV "distant" // Création d'un convertisseur parsant les données d'un fichier CSV "distant"
let converter=new FreeDatas2HTML("CSV","", { url:"http://localhost:8080/datas/elements-chimiques.csv" }); let converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:8080/datas/elements-chimiques.csv" });
converter.datasViewElt={ id:"datas" }; converter.datasViewElt={ id:"datas" };
await converter.run(); await converter.run();
// Adaptation du rendu suivant la taille de l'écran // Adaptation du rendu suivant la taille de l'écran

View File

@ -5,7 +5,8 @@ const initialise = async () =>
try try
{ {
// Création d'un convertisseur parsant des données transmises en JSON // Création d'un convertisseur parsant des données transmises en JSON
let converter=new FreeDatas2HTML("JSON", "", { url: "http://localhost:8080/datas/posts.json", withCredentials:true, headers: [{ key:"Authorization", value:"Token YWxhZGRpbjpvcGVuc2VzYW1l" }] }); let converter=new FreeDatas2HTML("JSON");
converter.parser.setRemoteSource({ url: "http://localhost:8080/datas/posts.json", withCredentials:true, headers: [{ key:"Authorization", value:"Token YWxhZGRpbjpvcGVuc2VzYW1l" }] });
converter.datasViewElt={ id:"datas" }; converter.datasViewElt={ id:"datas" };
await converter.run(); await converter.run();
// Adaptation du rendu suivant la taille de l'écran // Adaptation du rendu suivant la taille de l'écran

View File

@ -50,28 +50,26 @@ export class FreeDatas2HTML
private _datasCounter: Counter = {}; private _datasCounter: Counter = {};
// J'initialiser avec des valeurs par défaut pouvant être surchargées par les setters // J'initialiser avec des valeurs par défaut pouvant être surchargées par les setters
// Attention, si je transmets datasRemoteSource ici, il ne passera pas par un new RemoteSources()
// Il doit donc déjà avoir été testé
constructor(datasType:"CSV"|"HTML"|"JSON", datas2Parse="", datasRemoteSource?:RemoteSource) constructor(datasType:"CSV"|"HTML"|"JSON", datas2Parse="", datasRemoteSource?:RemoteSource)
{ {
this.datasRender=new Render(this); this.datasRender=new Render(this);
switch (datasType) switch (datasType)
{ {
case "CSV": case "CSV":
this.parser=new ParserForCSV(); this.parser=new ParserForCSV(datasRemoteSource);
break; break;
case "HTML": case "HTML":
this.parser=new ParserForCSV(); this.parser=new ParserForCSV(datasRemoteSource);
console.error("Appeler le parseur HTML"); console.error("Appeler le parseur HTML");
break; break;
case "JSON": case "JSON":
this.parser=new ParserForJSON(); this.parser=new ParserForJSON(datasRemoteSource);
break; break;
} }
if(datas2Parse !== "") if(datas2Parse !== "")
this.parser.datas2Parse=datas2Parse; this.parser.datas2Parse=datas2Parse;
else if(datasRemoteSource !== undefined)
this.parser.datasRemoteSource=datasRemoteSource;
else
throw new Error(errors.converterNeedDatas);
} }
// 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
@ -145,7 +143,7 @@ export class FreeDatas2HTML
// Traite les données fournies via le parseur adhoc // Traite les données fournies via le parseur adhoc
// Si un élément du DOM est fourni, appelle la fonction affichant les données // Si un élément du DOM est fourni, appelle la fonction affichant les données
public async run(): Promise<any> public async run(): Promise<any>
{ {
await this.parser.parse(); await this.parser.parse();
if(this.parser.parseResults === undefined) if(this.parser.parseResults === undefined)
throw new Error(errors.parserFail); throw new Error(errors.parserFail);

View File

@ -66,15 +66,20 @@ export interface ParseResults
export interface Parsers export interface Parsers
{ {
datasRemoteSource: RemoteSource; datasRemoteSource: RemoteSource;
setRemoteSource(settings : RemoteSourceSettings): void;
datas2Parse: string; datas2Parse: string;
parseResults: ParseResults|undefined; parseResults: ParseResults|undefined;
parse(): Promise<void>; parse(): Promise<void>;
} }
export interface RemoteSource export interface RemoteSourceSettings
{ {
url: string; url: string;
headers?: { key:string, value:string }[] ; headers?: { key:string, value:string }[];
withCredentials?:boolean; withCredentials?: boolean;
}
export interface RemoteSource extends RemoteSourceSettings
{
getFetchSettings() : {};
} }
export interface Selectors export interface Selectors
{ {

View File

@ -1,7 +1,8 @@
const Papa = require("papaparse"); const Papa = require("papaparse");
const errors = require("./errors.js"); const errors = require("./errors.js");
import { RemoteSources } from "./freeDatas2HTMLRemoteSources";
import { ParseResults, Parsers, RemoteSource } from "./freeDatas2HTMLInterfaces"; import { ParseResults, Parsers, RemoteSource, RemoteSourceSettings } from "./freeDatas2HTMLInterfaces";
interface PapaParseOptions interface PapaParseOptions
{ {
delimiter: string; delimiter: string;
@ -25,7 +26,7 @@ interface PrivatePapaParseOptions
export class ParserForCSV implements Parsers export class ParserForCSV implements Parsers
{ {
private _datasRemoteSource: RemoteSource={ url:"" }; private _datasRemoteSource: RemoteSource;
private _datas2Parse:string=""; private _datas2Parse:string="";
private _parseResults:ParseResults|undefined=undefined; private _parseResults:ParseResults|undefined=undefined;
@ -52,17 +53,19 @@ export class ParserForCSV implements Parsers
skipEmptyLines:"greedy", skipEmptyLines:"greedy",
withCredentials: undefined withCredentials: undefined
} }
// Revoir tous les protocoles possibles pour une source distante (http(s)://.. , ftp..) // L'instance d'une autre classe que RemoteSource peut être passée au constructeur
set datasRemoteSource(source: RemoteSource) constructor(datasRemoteSource?: RemoteSource)
{ {
if(source.url.trim().length === 0) if(datasRemoteSource !== undefined)
throw new Error(errors.parserNeedUrl); this._datasRemoteSource=datasRemoteSource;
else else
{ this._datasRemoteSource=new RemoteSources({ url:"" });
source.url=source.url.trim(); }
this._datasRemoteSource=source;
} public setRemoteSource(source: RemoteSourceSettings)
{
this._datasRemoteSource=new RemoteSources(source);
} }
get datasRemoteSource() : RemoteSource get datasRemoteSource() : RemoteSource

View File

@ -1,23 +1,26 @@
const errors = require("./errors.js"); const errors = require("./errors.js");
import { RemoteSources } from "./freeDatas2HTMLRemoteSources";
import { ParseErrors, ParseResults, Parsers, RemoteSource } from "./freeDatas2HTMLInterfaces"; import { ParseErrors, ParseResults, Parsers, RemoteSource, RemoteSourceSettings } from "./freeDatas2HTMLInterfaces";
export class ParserForJSON implements Parsers export class ParserForJSON implements Parsers
{ {
private _datasRemoteSource: RemoteSource={ url:"" }; private _datasRemoteSource: RemoteSource;
private _datas2Parse: string=""; private _datas2Parse: string="";
private _parseResults: ParseResults|undefined=undefined; private _parseResults: ParseResults|undefined=undefined;
// Revoir tous les protocoles possibles pour une source distante (http(s)://.. , ftp..) // L'instance d'une autre classe que RemoteSource peut être passée au constructeur
set datasRemoteSource(source: RemoteSource) constructor(datasRemoteSource?: RemoteSource)
{ {
if(source.url.trim().length === 0) if(datasRemoteSource !== undefined)
throw new Error(errors.parserNeedUrl); this._datasRemoteSource=datasRemoteSource;
else else
{ this._datasRemoteSource=new RemoteSources({ url:"" });
source.url=source.url.trim(); }
this._datasRemoteSource=source;
} public setRemoteSource(source: RemoteSourceSettings)
{
this._datasRemoteSource=new RemoteSources(source);
} }
get datasRemoteSource() : RemoteSource get datasRemoteSource() : RemoteSource
@ -63,6 +66,8 @@ export class ParserForJSON implements Parsers
let parseContent=""; let parseContent="";
if(parser._datasRemoteSource.url !== "") if(parser._datasRemoteSource.url !== "")
{ {
const settings: {}=parser._datasRemoteSource.getFetchSettings();
/*
const headers=new Headers(); const headers=new Headers();
if(parser._datasRemoteSource.headers !== undefined) if(parser._datasRemoteSource.headers !== undefined)
{ {
@ -71,6 +76,7 @@ export class ParserForJSON implements Parsers
} }
const credentials : RequestCredentials|undefined=(parser._datasRemoteSource.withCredentials) ? "include" : "omit"; const credentials : RequestCredentials|undefined=(parser._datasRemoteSource.withCredentials) ? "include" : "omit";
const settings={ method: "GET", headers: headers, credentials: credentials }; const settings={ method: "GET", headers: headers, credentials: credentials };
*/
const response=await fetch(parser._datasRemoteSource.url, settings); const response=await fetch(parser._datasRemoteSource.url, settings);
if (! response.ok) if (! response.ok)
throw new Error(errors.parserRemoteFail); throw new Error(errors.parserRemoteFail);

View File

@ -0,0 +1,85 @@
const errors = require("./errors.js");
import { RemoteSource, RemoteSourceSettings } from "./freeDatas2HTMLInterfaces";
export class RemoteSources implements RemoteSource
{
public allowedUrlProtocol: string[]=["https:","http:"];
private _url: string;
private _headers: { key:string, value:string }[]=[];
private _withCredentials: boolean=false;
constructor(RemoteSettings: RemoteSourceSettings)
{
this._url=RemoteSettings.url;
if(RemoteSettings.headers !== undefined)
this.headers=RemoteSettings.headers;
if(RemoteSettings.withCredentials !== undefined)
this.withCredentials=RemoteSettings.withCredentials;
}
set url(url: string)
{
if(url.trim().length === 0)
throw new Error(errors.remoteSourceNeedUrl);
else
{
try
{
const checkUrl=new URL(url);// peut déjà générer une erreur si url bidon
if(this.allowedUrlProtocol.indexOf(checkUrl.protocol) === -1)
throw new Error();
}
catch(e)
{
throw new Error(errors.remoteSourceUrlFail);
}
this._url=url.trim();
}
}
get url() : string
{
return this._url;
}
set headers(headers: { key:string, value:string }[])
{
const forbiddenHeadersNames: string[]=["Accept-Charset","Accept-Encoding","Access-Control-Request-Headers","Access-Control-Request-Method","Connection","Content-Length","Cookie","Cookie2","Date","DNT","Expect","Host","Keep-Alive","Origin","Referer","TE","Trailer","Transfer-Encoding","Upgrade","Via"]; // cf. https://developer.mozilla.org/fr/docs/Glossary/Forbidden_header_name
for(let header of headers)
{
header.key=header.key.trim();
if(header.key.startsWith("Sec-") || header.key.startsWith("Proxy-") || forbiddenHeadersNames.indexOf(header.key) !== -1)
console.error(errors.remoteSourceHeaderIsUnallowed);
else
this._headers.push({ key:header.key, value:header.value.trim() });
}
}
get headers() : { key:string, value:string }[]
{
return this._headers;
}
set withCredentials(credentials: boolean)
{
this._withCredentials=credentials;
}
get withCredentials() : boolean
{
return this._withCredentials;
}
public getFetchSettings() : {}
{
const headers=new Headers();
if(this._headers !== undefined)
{
for(let header of this._headers)
headers.append(header.key, header.value);
}
const credentials : RequestCredentials|undefined=(this._withCredentials) ? "include" : "omit";
return { method: "GET", headers: headers, credentials: credentials };
}
}

View File

@ -10,7 +10,8 @@ describe("Test du script central de FreeDatas2HTML", () =>
beforeEach( () => beforeEach( () =>
{ {
converter=new FreeDatas2HTML("CSV","", { url:"http://localhost:9876/datas/datas1.csv"}); converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" });
document.body.insertAdjacentHTML('afterbegin', fixtures.datasViewEltHTML); document.body.insertAdjacentHTML('afterbegin', fixtures.datasViewEltHTML);
}); });
@ -72,7 +73,8 @@ describe("Test du script central de FreeDatas2HTML", () =>
return 0; return 0;
}; };
expect(() => { return converter.datasSortingFunctions=[{ datasFieldNb:0, sort:simpleSort }]; }).toThrowError(errors.converterFieldNotFound); // données non chargées expect(() => { return converter.datasSortingFunctions=[{ datasFieldNb:0, sort:simpleSort }]; }).toThrowError(errors.converterFieldNotFound); // données non chargées
converter=new FreeDatas2HTML("CSV","", { url:"http://localhost:9876/datas/datas1.csv"}); converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" });
await converter.run(); await converter.run();
expect(() => { return converter.datasSortingFunctions=[{ datasFieldNb:10, sort:simpleSort }]; }).toThrowError(errors.converterFieldNotFound); expect(() => { return converter.datasSortingFunctions=[{ datasFieldNb:10, sort:simpleSort }]; }).toThrowError(errors.converterFieldNotFound);
}); });
@ -122,7 +124,8 @@ describe("Test du script central de FreeDatas2HTML", () =>
it("Doit générer une erreur, si la moindre erreur est rencontrée durant la parsage et que cela n'est pas accepté.", async () => it("Doit générer une erreur, si la moindre erreur est rencontrée durant la parsage et que cela n'est pas accepté.", async () =>
{ {
converter=new FreeDatas2HTML("CSV","", { url:"http://localhost:9876/datas/datas-errors1.csv"}); converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas-errors1.csv" });
converter.stopIfParseErrors=true; converter.stopIfParseErrors=true;
await expectAsync(converter.run()).toBeRejectedWith(new Error(errors.parserMeetErrors)); await expectAsync(converter.run()).toBeRejectedWith(new Error(errors.parserMeetErrors));
}); });
@ -130,7 +133,8 @@ describe("Test du script central de FreeDatas2HTML", () =>
it("Si cela n'est pas demandé, le script ne sera pas bloqué, même si des erreurs sont rencontrées durant le parsage.", async () => it("Si cela n'est pas demandé, le script ne sera pas bloqué, même si des erreurs sont rencontrées durant le parsage.", async () =>
{ {
converter.datasViewElt={ id:"datas" }; converter.datasViewElt={ id:"datas" };
converter=new FreeDatas2HTML("CSV","", { url:"http://localhost:9876/datas/datas-errors1.csv"}); converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas-errors1.csv" });
await expectAsync(converter.run()).toBeResolved(); await expectAsync(converter.run()).toBeResolved();
}); });

View File

@ -11,7 +11,8 @@ describe("Test de la pagination.", () =>
beforeEach( async () => beforeEach( async () =>
{ {
document.body.insertAdjacentHTML("afterbegin", fixtures.datasViewEltHTML); document.body.insertAdjacentHTML("afterbegin", fixtures.datasViewEltHTML);
converter=new FreeDatas2HTML("CSV","", { url:"http://localhost:9876/datas/datas1.csv"}); converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" });
converter.datasViewElt={ id:"datas" }; converter.datasViewElt={ id:"datas" };
await converter.run(); await converter.run();
pagination=new Pagination(converter, { id:"pages" }, "Page à afficher :"); pagination=new Pagination(converter, { id:"pages" }, "Page à afficher :");
@ -34,7 +35,8 @@ describe("Test de la pagination.", () =>
it("Doit générer une erreur si la pagination est initialisée sans données à traiter.", () => it("Doit générer une erreur si la pagination est initialisée sans données à traiter.", () =>
{ {
converter=new FreeDatas2HTML("CSV","", { url:"http://localhost:9876/datas/datas1.csv"}); converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" });
expect(() => { return new Pagination(converter, { id:"pages" }); }).toThrowError(errors.paginationNeedDatas); expect(() => { return new Pagination(converter, { id:"pages" }); }).toThrowError(errors.paginationNeedDatas);
}); });

View File

@ -1,5 +1,5 @@
const Papa = require("papaparse"); const Papa = require("papaparse");
import { RemoteSource } from "../src/freeDatas2HTMLInterfaces"; import { RemoteSource, RemoteSourceSettings } from "../src/freeDatas2HTMLInterfaces";
import { ParserForCSV as Parser } from "../src/freeDatas2HTMLParserForCSV"; import { ParserForCSV as Parser } from "../src/freeDatas2HTMLParserForCSV";
const errors=require("../src/errors.js"); const errors=require("../src/errors.js");
@ -19,22 +19,6 @@ describe("Tests du parseur de CSV", () =>
expect(parser).toBeInstanceOf(Parser); expect(parser).toBeInstanceOf(Parser);
}); });
it("Doit générer une erreur si l'url fournie pour importer les données est une chaîne vide.", () =>
{
expect(() => { return parser.datasRemoteSource= { url:"" } }).toThrowError(errors.parserNeedUrl);
expect(() => { return parser.datasRemoteSource= { url:" " } }).toThrowError(errors.parserNeedUrl);
});
it("Doit accepter des paramètres valides pour la source de données distante.", () =>
{
let myRemoteSource: RemoteSource={ url:"zz" };
parser.datasRemoteSource=myRemoteSource;
expect(parser.datasRemoteSource).toEqual(myRemoteSource);
myRemoteSource={ url:"zz", headers:[ { key:"test", value:"coucou"}, { key:"test2", value:"coucou2"}], withCredentials:true };
parser.datasRemoteSource=myRemoteSource;
expect(parser.datasRemoteSource).toEqual(myRemoteSource);
});
it("Doit générer une erreur si la chaîne de données à parser est vide.", () => it("Doit générer une erreur si la chaîne de données à parser est vide.", () =>
{ {
expect(() => { return parser.datas2Parse="" }).toThrowError(errors.parserNeedDatas); expect(() => { return parser.datas2Parse="" }).toThrowError(errors.parserNeedDatas);
@ -73,19 +57,19 @@ describe("Tests du parseur de CSV", () =>
{ {
// Même remarque, test précédent // Même remarque, test précédent
spyOn(Papa, "parse"); spyOn(Papa, "parse");
let myRemoteSource: RemoteSource={ url:"http://localhost:9876/datas/datas1.csv", withCredentials:true }; let myRemoteSource: RemoteSourceSettings={ url:"http://localhost:9876/datas/datas1.csv", withCredentials:true };
parser.datasRemoteSource=myRemoteSource; parser.setRemoteSource(myRemoteSource);
parser.parse(); parser.parse();
expect(parser.privateOptions).toEqual( expect(parser.privateOptions).toEqual(
{ {
header:true, header:true,
download:true, download:true,
downloadRequestHeaders:undefined, downloadRequestHeaders:{},// on passe une liste de headers, même vide
skipEmptyLines:"greedy", skipEmptyLines:"greedy",
withCredentials:true withCredentials:true
}); });
myRemoteSource={ url:"http://localhost:9876/datas/datas1.csv", headers:[ { key:"test", value:"coucou"}, { key:"test2", value:"coucou2"}] , withCredentials:false }; myRemoteSource={ url:"http://localhost:9876/datas/datas1.csv", headers:[ { key:"test", value:"coucou"}, { key:"test2", value:"coucou2"}] , withCredentials:false };
parser.datasRemoteSource=myRemoteSource; parser.setRemoteSource(myRemoteSource);;
parser.parse(); parser.parse();
expect(parser.privateOptions).toEqual( expect(parser.privateOptions).toEqual(
{ {
@ -100,7 +84,7 @@ describe("Tests du parseur de CSV", () =>
it("Si le parseur a été appelé avec les données nécessaires, des résultats doivent être enregistrés.", async () => it("Si le parseur a été appelé avec les données nécessaires, des résultats doivent être enregistrés.", async () =>
{ {
parser.datasRemoteSource={ url:"http://localhost:9876/datas/datas1.csv" }; parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" });
await parser.parse(); await parser.parse();
expect(parser.parseResults).not.toBeUndefined(); expect(parser.parseResults).not.toBeUndefined();
// Y compris si les données fournies sont bidon : // Y compris si les données fournies sont bidon :

View File

@ -18,8 +18,8 @@ describe("Tests du parseur de JSON", () =>
it("Doit générer une erreur si la chaîne de données à parser est vide.", () => it("Doit générer une erreur si la chaîne de données à parser est vide.", () =>
{ {
expect(() => { return parser.datas2Parse= "" }).toThrowError(errors.parserNeedDatas); expect(() => { return parser.datas2Parse="" }).toThrowError(errors.parserNeedDatas);
expect(() => { return parser.datas2Parse= " " }).toThrowError(errors.parserNeedDatas); expect(() => { return parser.datas2Parse=" " }).toThrowError(errors.parserNeedDatas);
}); });
it("Doit accepter toute chaîne de caractères non vide pour les données à parser.", () => it("Doit accepter toute chaîne de caractères non vide pour les données à parser.", () =>
@ -41,24 +41,8 @@ describe("Tests du parseur de JSON", () =>
}); });
describe("Accès à des données distantes.", () => describe("Accès à des données distantes.", () =>
{ {
it("Doit générer une erreur si l'url fournie pour importer les données est une chaîne vide.", () => /*it("Si des options sont fournies pour appeler une ressource distante, elles doivent être prises en compte.", async () =>
{
expect(() => { return parser.datasRemoteSource= { url:"" } }).toThrowError(errors.parserNeedUrl);
expect(() => { return parser.datasRemoteSource= { url:" " } }).toThrowError(errors.parserNeedUrl);
});
it("Doit accepter des paramètres valides pour la source de données distante.", () =>
{
let myRemoteSource: RemoteSource={ url:"zz" };
parser.datasRemoteSource=myRemoteSource;
expect(parser.datasRemoteSource).toEqual(myRemoteSource);
myRemoteSource={ url:"zz", headers: [ { key:"test", value: "coucou"}, { key:"test2", value:"coucou2"}], withCredentials:true };
parser.datasRemoteSource=myRemoteSource;
expect(parser.datasRemoteSource).toEqual(myRemoteSource);
});
it("Si des options sont fournies pour appeler une ressource distante, elles doivent être prises en compte.", async () =>
{ {
spyOn(window,"fetch").and.callThrough(); spyOn(window,"fetch").and.callThrough();
parser.datasRemoteSource={ url: "http://localhost:9876/datas/posts.json", withCredentials:true, headers: [{ key:"Authorization", value:"Token YWxhZGRpbjpvcGVuc2VzYW1l" }]}; parser.datasRemoteSource={ url: "http://localhost:9876/datas/posts.json", withCredentials:true, headers: [{ key:"Authorization", value:"Token YWxhZGRpbjpvcGVuc2VzYW1l" }]};
@ -73,17 +57,17 @@ describe("Tests du parseur de JSON", () =>
credentials: credentials, credentials: credentials,
}; };
expect(fetch).toHaveBeenCalledWith("http://localhost:9876/datas/posts.json", settings); expect(fetch).toHaveBeenCalledWith("http://localhost:9876/datas/posts.json", settings);
}); });*/
it("Doit générer une erreur, si l'accès aux données distantes est défaillant.", async () => it("Doit générer une erreur, si l'accès aux données distantes est défaillant.", async () =>
{ {
parser.datasRemoteSource={ url:"http://localhost:9876/datas/posts.jso" }; // une seule lettre vous manque... parser.setRemoteSource({ url:"http://localhost:9876/datas/posts.jso" }); // une seule lettre vous manque...
await expectAsync(parser.parse()).toBeRejectedWith(new Error(errors.parserRemoteFail)); await expectAsync(parser.parse()).toBeRejectedWith(new Error(errors.parserRemoteFail));
}); });
it("Si le parseur a été appelé avec une url fournissant des données correctes, des résultats doivent être enregistrés.", async () => it("Si le parseur a été appelé avec une url fournissant des données correctes, des résultats doivent être enregistrés.", async () =>
{ {
parser.datasRemoteSource={ url:"http://localhost:9876/datas/posts.json" }; parser.setRemoteSource({ url:"http://localhost:9876/datas/posts.json" });
await parser.parse(); await parser.parse();
expect(parser.parseResults).not.toBeUndefined(); expect(parser.parseResults).not.toBeUndefined();
}); });

51
tests/remoteSourceSpec.ts Normal file
View File

@ -0,0 +1,51 @@
import { RemoteSources } from "../src/freeDatas2HTMLRemoteSources";
const errors=require("../src/errors.js");
describe("Tests des urls distantes", () =>
{
let source: RemoteSources;
beforeEach( () =>
{
source=new RemoteSources({ url:"http://localhost:8080/" });
});
it("Doit générer une erreur si l'url fournie est une chaîne vide.", () =>
{
expect(() => { return source.url=""; }).toThrowError(errors.remoteSourceNeedUrl);
expect(() => { return source.url=" "; }).toThrowError(errors.remoteSourceNeedUrl);
});
it("Doit générer une erreur si l'url fournie n'utilise pas un des protocoles autorisés.", () =>
{
expect(() => { return source.url="htp://localhost:8080/"; }).toThrowError(errors.remoteSourceUrlFail);
expect(() => { return source.url="ftp://localhost:8080/"; }).toThrowError(errors.remoteSourceUrlFail);
});
it("Doit accepter une url valide", () =>
{
expect(() => { return source.url="http://localhost:8080/"; }).not.toThrowError();
source.allowedUrlProtocol.push("ftp:");
expect(() => { return source.url="ftp://localhost:8080/"; }).not.toThrowError();
});
it("Seuls les headers conformes doivent être retenus", () =>
{
source.headers=[ { key:"token", value:"1234" }, { key:"vide", value:"" }, { key:"Sec-id", value:"666" }, { key:"Proxy-name", value:"myProxy" }, { key:"Content-Length", value:"255" }, { key:"userName", value:"Toto" }];
expect(source.headers).toEqual([ { key:"token", value:"1234" }, { key:"vide", value:"" }, { key:"userName", value:"Toto" }]);
});
it("Doit retourner la configuration correcte pour fetch.", () =>
{
let headers=new Headers();
expect(source.getFetchSettings()).toEqual({ method: "GET", headers: headers, credentials: "omit" });
source.headers=[ { key:"token", value:"1234" }, { key:"userName", value:"Toto" }];
source.withCredentials=true;
headers=new Headers();
headers.append("token", "1234");
headers.append("userName", "Toto");
expect(source.getFetchSettings()).toEqual({ method: "GET", headers: headers, credentials: "include" });
});
});

View File

@ -9,7 +9,8 @@ describe("Test du moteur de rendu HTML.", () =>
beforeEach(() => beforeEach(() =>
{ {
converter=new FreeDatas2HTML("CSV","", { url:"http://localhost:8080/datas/datas1.csv"}); converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" });
render=new Render(converter); render=new Render(converter);
converter.fields=[ "Z", "Élément", "Symbole", "Famille" ] ; converter.fields=[ "Z", "Élément", "Symbole", "Famille" ] ;
// Les champs des différentes lignes ne sont pas forcément dans le même ordre, dans les champs peuvent être vide ou encore en trop... // Les champs des différentes lignes ne sont pas forcément dans le même ordre, dans les champs peuvent être vide ou encore en trop...

View File

@ -11,7 +11,8 @@ describe("Test des filtres de données", () =>
beforeEach( async () => beforeEach( async () =>
{ {
document.body.insertAdjacentHTML("afterbegin", fixtures.datasViewEltHTML); document.body.insertAdjacentHTML("afterbegin", fixtures.datasViewEltHTML);
converter=new FreeDatas2HTML("CSV","", { url:"http://localhost:9876/datas/datas1.csv"}); converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" });
converter.datasViewElt={ id:"datas" }; converter.datasViewElt={ id:"datas" };
await converter.run(); await converter.run();
}); });
@ -25,7 +26,8 @@ describe("Test des filtres de données", () =>
{ {
it("Doit générer une erreur, si initialisé sans fournir la liste des champs servant à classer les données.", () => it("Doit générer une erreur, si initialisé sans fournir la liste des champs servant à classer les données.", () =>
{ {
converter=new FreeDatas2HTML("CSV","", { url:"http://localhost:9876/datas/datas1.csv"}); converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" });
expect(() => { return new Selector(converter, 0, { id:"selector1" }); }).toThrowError(errors.selectorNeedDatas); expect(() => { return new Selector(converter, 0, { id:"selector1" }); }).toThrowError(errors.selectorNeedDatas);
}); });
@ -73,7 +75,8 @@ describe("Test des filtres de données", () =>
it("Si des valeurs vides sont présentes dans une champ utilisé pour un sélecteur, elles doivent être ignorées.", async () => it("Si des valeurs vides sont présentes dans une champ utilisé pour un sélecteur, elles doivent être ignorées.", async () =>
{ {
converter=new FreeDatas2HTML("CSV","", { url:"http://localhost:9876/datas/datas1-emtyinfield.csv"}); converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1-emtyinfield.csv" });
await converter.run(); await converter.run();
selector.selector2HTML(); selector.selector2HTML();
expect(document.getElementById("selector1").innerHTML).toEqual(fixtures.selector1HTML); expect(document.getElementById("selector1").innerHTML).toEqual(fixtures.selector1HTML);
@ -81,7 +84,8 @@ describe("Test des filtres de données", () =>
it("Si un séparateur est fourni, les valeurs distinctes extraites de ce champ doivent le prendre en compte.", async () => it("Si un séparateur est fourni, les valeurs distinctes extraites de ce champ doivent le prendre en compte.", async () =>
{ {
converter=new FreeDatas2HTML("CSV","", { url:"http://localhost:9876/datas/datas1+tagsfield.csv"}); converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1+tagsfield.csv" });
await converter.run(); await converter.run();
selector=new Selector(converter, 5, { id:"selector1" }); selector=new Selector(converter, 5, { id:"selector1" });
selector.separator="|"; selector.separator="|";

View File

@ -11,7 +11,8 @@ describe("Test des champs de classement.", () =>
beforeEach( async () => beforeEach( async () =>
{ {
document.body.insertAdjacentHTML("afterbegin", fixtures.datasViewEltHTML); document.body.insertAdjacentHTML("afterbegin", fixtures.datasViewEltHTML);
converter=new FreeDatas2HTML("CSV","", { url:"http://localhost:9876/datas/datas1.csv"}); converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" });
converter.datasViewElt={ id:"datas" }; converter.datasViewElt={ id:"datas" };
await converter.run(); await converter.run();
const fields=document.querySelectorAll("th"); const fields=document.querySelectorAll("th");
@ -26,7 +27,8 @@ 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.", () => it("Doit générer une erreur, si initialisé sans fournir la liste des champs servant à classer les données.", () =>
{ {
converter=new FreeDatas2HTML("CSV","", { url:"http://localhost:9876/datas/datas1.csv"}); converter=new FreeDatas2HTML("CSV");
converter.parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" });
expect(() => { return new SortingField(converter, 0); }).toThrowError(errors.sortingFieldNeedDatas); expect(() => { return new SortingField(converter, 0); }).toThrowError(errors.sortingFieldNeedDatas);
}); });