diff --git a/src/ParserForHTML.ts b/src/ParserForHTML.ts
index d69428f..5ecc1ab 100644
--- a/src/ParserForHTML.ts
+++ b/src/ParserForHTML.ts
@@ -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
{
- 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,
diff --git a/tests/parserForHTMLSpec.ts b/tests/parserForHTMLSpec.ts
index 4ad9a8e..ef686b1 100644
--- a/tests/parserForHTMLSpec.ts
+++ b/tests/parserForHTMLSpec.ts
@@ -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="";
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="";
+ datasElt.innerHTML="";
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=""
+ datasElt.innerHTML="";
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);
});
-
});
});
\ No newline at end of file