Relecture code et tests du parseur HTML.
This commit is contained in:
parent
df2658686d
commit
036c3b3400
@ -11,7 +11,6 @@ export class ParserForHTML implements Parsers
|
||||
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,
|
||||
|
@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user