From c3c0206c643cea62c0837782389997fe344527c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20PENHO=C3=8BT?= Date: Wed, 13 Oct 2021 18:20:53 +0200 Subject: [PATCH] =?UTF-8?q?Fichier=20parseur=20CSV=20renomm=C3=A9.=20Relec?= =?UTF-8?q?ture=20code=20+=20ajout=20tests.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...as2HTMLParserForCSV.ts => ParserForCSV.ts} | 50 +++++++++---------- src/freeDatas2HTML.ts | 4 +- tests/parserForCSVSpec.ts | 28 ++++++++--- 3 files changed, 48 insertions(+), 34 deletions(-) rename src/{freeDatas2HTMLParserForCSV.ts => ParserForCSV.ts} (79%) diff --git a/src/freeDatas2HTMLParserForCSV.ts b/src/ParserForCSV.ts similarity index 79% rename from src/freeDatas2HTMLParserForCSV.ts rename to src/ParserForCSV.ts index 0ecf215..7bf48c2 100644 --- a/src/freeDatas2HTMLParserForCSV.ts +++ b/src/ParserForCSV.ts @@ -34,24 +34,23 @@ export class ParserForCSV implements Parsers private _parseResults:ParseResults|undefined=undefined; public options: PublicPapaParseOptions = { - delimiter: "", - newline: "", - quoteChar: '"', - escapeChar: '"', - transformHeader: function(field: string, index: number): string { return field.trim() }, - preview: 0, - comments: "", - fastMode: undefined, - transform: undefined + delimiter:"", + newline:"", + quoteChar:'"', + escapeChar:'"', + transformHeader:function(field: string, index: number): string { return field.trim() }, + preview:0, + comments:"", + fastMode:undefined, + transform:undefined } - // Options de Papa Parse ne pouvant être modifées de l'extérieur private _privateOptions: PrivatePapaParseOptions = { - header: true, // nécessaire pour obtenir le nom des champs - download: false, - downloadRequestHeaders: undefined, + header:true, + download:false, + downloadRequestHeaders:undefined, skipEmptyLines:"greedy", - withCredentials: undefined + withCredentials:undefined } // L'instance d'une autre classe que RemoteSource peut être passée au constructeur @@ -96,8 +95,6 @@ export class ParserForCSV implements Parsers return this._privateOptions; } - // async dans le cas d'une source distante - // Et création d'une Promise car PapaParse utilise des fonctions callback. public async parse(): Promise { const parser=this, options=this.options; @@ -110,8 +107,8 @@ export class ParserForCSV implements Parsers if(parser._datasRemoteSource.headers !== undefined) { this._privateOptions.downloadRequestHeaders={}; - for(let i=0; i< parser._datasRemoteSource.headers.length; i++) - this._privateOptions.downloadRequestHeaders[parser._datasRemoteSource.headers[i].key]=parser._datasRemoteSource.headers[i].value; + for(let header of parser._datasRemoteSource.headers) + this._privateOptions.downloadRequestHeaders[header.key]=header.value; } } else if(parser._datas2Parse !== "") @@ -133,18 +130,22 @@ export class ParserForCSV implements Parsers comments: options.comments, complete: function(results :any) { - // Attention, Papa Parse peut accepter un nom de champ vide + // Attention, Papa Parse peut accepter un nom de champ vide ou en doublon ! let realFields: string[]=[]; for(let field of results.meta.fields) { - if(field.trim() !== "") - realFields.push(field); + let checkField=field.trim(); + if(checkField !== "" && realFields.indexOf(checkField) === -1) + realFields.push(checkField); + else + console.error(errors.parserFieldNameFail); } if(realFields.length === 0) - reject(new Error(errors.parserFail)); + reject(new Error(errors.parserFieldsNotFound)); else { - parser._parseResults={ + parser._parseResults= + { datas: results.data, errors: results.errors, fields: realFields, @@ -157,9 +158,8 @@ export class ParserForCSV implements Parsers skipEmptyLines:"greedy", fastMode: options.fastMode, withCredentials: this._privateOptions.withCredentials, - transform: options.transform + transform: options.transform }); }); } - } \ No newline at end of file diff --git a/src/freeDatas2HTML.ts b/src/freeDatas2HTML.ts index 3dbd1a1..66ba5f7 100644 --- a/src/freeDatas2HTML.ts +++ b/src/freeDatas2HTML.ts @@ -3,7 +3,7 @@ const errors=require("./errors.js"); import { Counter, Datas, DatasRenders, DOMElement, Paginations, Parsers, ParseErrors, RemoteSources, Selectors, SortingFields, SortingFunctions } from "./freeDatas2HTMLInterfaces"; import { Pagination} from "./freeDatas2HTMLPagination"; -import { ParserForCSV} from "./freeDatas2HTMLParserForCSV"; +import { ParserForCSV} from "./ParserForCSV"; import { ParserForHTML} from "./freeDatas2HTMLParserForHTML"; import { ParserForJSON} from "./freeDatas2HTMLParserForJSON"; import { Render} from "./freeDatas2HTMLRender"; @@ -24,7 +24,7 @@ export class FreeDatas2HTML public datasType: "CSV"|"HTML"|"JSON"|undefined; // Le nom des champs trouvés dans les données : - public fields: string[]|undefined=undefined; + public fields: string[]|undefined=undefined; // Les données à proprement parler : public datas: {[index: string]:any}[]=[]; // Les erreurs rencontrées durant le traitement des données reçues : diff --git a/tests/parserForCSVSpec.ts b/tests/parserForCSVSpec.ts index 712d46a..b41e3ee 100644 --- a/tests/parserForCSVSpec.ts +++ b/tests/parserForCSVSpec.ts @@ -1,10 +1,8 @@ -const Papa = require("papaparse"); +const Papa=require("papaparse"); import { RemoteSourceSettings } from "../src/freeDatas2HTMLInterfaces"; -import { ParserForCSV as Parser } from "../src/freeDatas2HTMLParserForCSV"; +import { ParserForCSV as Parser } from "../src/ParserForCSV"; const errors=require("../src/errors.js"); -// Pas de test de Papa Parse lui-même, car il s'agit d'un module externe. -// Mais tests de la classe l'utilisant. describe("Tests du parseur de CSV", () => { let parser: Parser; @@ -14,9 +12,10 @@ describe("Tests du parseur de CSV", () => parser=new Parser(); }); - it("Doit avoir créé une instance du Parser", () => + it("Doit avoir créé une instance du Parser et initialiser la ressource distante avec une url vide.", () => { expect(parser).toBeInstanceOf(Parser); + expect(parser.datasRemoteSource.url).toEqual(""); }); it("Doit générer une erreur si la chaîne de données à parser est vide.", () => @@ -39,7 +38,7 @@ describe("Tests du parseur de CSV", () => it("Si les données sont directement fournies, cela doit être pris en compte dans les options passées à Papa Parse.", () => { // Idéalement il faudrait tester les paramètres passés à PapaParse - // Mais semble impossible à cause des fonctions callback ?! + // Mais semble impossible à cause des fonctions callback ? spyOn(Papa, "parse"); parser.datas2Parse="datas"; parser.parse(); @@ -51,6 +50,7 @@ describe("Tests du parseur de CSV", () => skipEmptyLines:"greedy", withCredentials:undefined }); + expect(Papa.parse).toHaveBeenCalledTimes(1); }); it("Si une ressource distante est fournie, cela doit être pris en compte dans les options passées à Papa Parse.", () => @@ -64,7 +64,7 @@ describe("Tests du parseur de CSV", () => { header:true, download:true, - downloadRequestHeaders:{},// on passe une liste de headers, même vide + downloadRequestHeaders:{},// passe une liste de headers, même vide skipEmptyLines:"greedy", withCredentials:true }); @@ -82,6 +82,20 @@ describe("Tests du parseur de CSV", () => expect(Papa.parse).toHaveBeenCalledTimes(2); }); + it("Si les données à parser contiennent des noms de champ vide ou en doublon, ils doivent être ignorés.", async () => + { + parser.datas2Parse="field1;field2;field3;field3; ;"; + await parser.parse(); + expect(parser.parseResults.fields).toEqual(["field1","field2","field3"]); + }); + + it("Doit générer une erreur si aucun nom de champ trouvé.", async () => + { + parser.setRemoteSource({ url:"http://localhost:9876/datas/nodatas.csv" }); + await expectAsync(parser.parse()).toBeRejectedWith(new Error(errors.parserFieldsNotFound)); + }); + + // Pas de test du fonctionnement de "Papa Parse" lui-même, car il s'agit d'un module externe. it("Si le parseur a été appelé avec les données nécessaires, des résultats doivent être enregistrés.", async () => { parser.setRemoteSource({ url:"http://localhost:9876/datas/datas1.csv" });