FreeDatas2HTML/tests/parserForHTMLSpec.ts

129 lines
8.1 KiB
TypeScript

import { ParserForHTML as Parser } from "../src/ParserForHTML";
const errors=require("../src/errors.js");
const fixtures=require("./fixtures.js");
describe("Tests du parseur HTML", () =>
{
let parser: Parser, datasElt: HTMLElement;
beforeEach( () =>
{
parser=new Parser();
document.body.insertAdjacentHTML('afterbegin', "<div id='datas'></div>");
datasElt=document.getElementById("datas");
});
afterEach( () =>
{
document.body.removeChild(document.getElementById("datas"));
});
it("Doit avoir créé une instance du parseur.", () =>
{
expect(parser).toBeInstanceOf(Parser);
expect(parser.datasRemoteSource.url).toEqual("");
});
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);
expect(() => { return parser.datasSelector=" "; }).toThrowError(errors.parserSelectorsIsEmpty);
});
describe("Accès à des données distantes.", () =>
{
it("Doit générer une erreur, si l'accès aux données distantes ne fonctionne pas.", async () =>
{
parser.setRemoteSource({ url:"http://localhost:9876/datas/datas.htm" }); // une seule lettre vous manque...
await expectAsync(parser.parse()).toBeRejectedWith(new Error(errors.parserRemoteFail));
});
it("Si le parseur est appelé avec une url correcte, le DOM du document distant doit être enregistré.", async () =>
{
parser.setRemoteSource({ url:"http://localhost:9876/datas/datas.html" });
await parser.parse();
const parserDOM=new DOMParser();
const htmlString="<html><head></head><body><table><thead><tr><th>Champ 1</th><th>Champ 2</th></tr></thead></table></body></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
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 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("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>";
parser.fieldsSelector="ul > li";
await expectAsync(parser.parse()).toBeRejectedWith(new Error(errors.parserFieldsNotFound));
});
it("Les espaces entourant les noms de champs doivent être supprimés.", async () =>
{
datasElt.innerHTML=fixtures.htmlParserDatas;
await parser.parse();
expect(parser.parseResults.fields).toEqual(["Z (numéro atomique)","Élément", "Symbole", "Famille", "Mots-clés"]);
});
it("Si des champs en trop sont trouvés dans une ligne de données, ils doivent être ignorés. Idem pour les champs absents. Ces anomalies doivent être reportées.", async () =>
{
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.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>";
await expectAsync(parser.parse()).toBeResolved();
});
it("Une ligne n'ayant aucune donnée sera ignorée et l'erreur reportée. Les valeurs vides sont par contre acceptées.", async () =>
{
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[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 () =>
{
datasElt.innerHTML=fixtures.htmlParserDatas;
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.length).toEqual(0);
});
});
});