From 425d6b913804bf46590684d2b841de389fd218b0 Mon Sep 17 00:00:00 2001 From: Andreas Heissenberger Date: Thu, 10 Oct 2019 23:24:45 +0200 Subject: [PATCH 1/5] fix: strict false - broken header keys --- test/fixtures/strict-false-broken.csv | 5 +++++ test/strictNo.test.js | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 test/fixtures/strict-false-broken.csv create mode 100644 test/strictNo.test.js diff --git a/test/fixtures/strict-false-broken.csv b/test/fixtures/strict-false-broken.csv new file mode 100644 index 0000000..d3a70a6 --- /dev/null +++ b/test/fixtures/strict-false-broken.csv @@ -0,0 +1,5 @@ +a,b,c +1,2,3 +4,5,6,7 +8,9,10 + diff --git a/test/strictNo.test.js b/test/strictNo.test.js new file mode 100644 index 0000000..4367e89 --- /dev/null +++ b/test/strictNo.test.js @@ -0,0 +1,19 @@ +const test = require('ava') + +const { collect } = require('./helpers/helper') + +test.cb('strictNo', (t) => { + const verify = (err, lines) => { + const headersFirstLine = Object.keys(lines[0]) + const headersLastLine = Object.keys(lines[2]) + t.deepEqual(headersFirstLine, headersLastLine) + t.false(err, 'no err') + t.snapshot(lines[0], 'first row') + t.snapshot(lines[1], 'broken row') + t.snapshot(lines[2], 'last row') + t.is(lines.length, 3, '3 rows') + t.end() + } + + collect('strict-false-broken', { strict: false }, verify) +}) From ac675ac0830843330b66d716883aa6025b02940f Mon Sep 17 00:00:00 2001 From: Andreas Heissenberger Date: Fri, 11 Oct 2019 00:21:00 +0200 Subject: [PATCH 2/5] fix: do not replace global headers --- index.js | 6 +- test/fixtures/strict-false-less-columns.csv | 4 ++ ...oken.csv => strict-false-more-columns.csv} | 1 - test/snapshots/strictNo.test.js.md | 57 ++++++++++++++++++ test/snapshots/strictNo.test.js.snap | Bin 0 -> 270 bytes test/strictNo.test.js | 26 +++++++- 6 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 test/fixtures/strict-false-less-columns.csv rename test/fixtures/{strict-false-broken.csv => strict-false-more-columns.csv} (96%) create mode 100644 test/snapshots/strictNo.test.js.md create mode 100644 test/snapshots/strictNo.test.js.snap diff --git a/index.js b/index.js index 99f6f09..70983dd 100644 --- a/index.js +++ b/index.js @@ -178,12 +178,10 @@ class CsvParser extends Transform { } writeRow (cells) { - if (this.headers === false || cells.length > this.headers.length) { - this.headers = cells.map((value, index) => index) - } + const headers = (this.headers === false || cells.length !== this.headers.length) ? cells.map((value, index) => index) : this.headers const row = cells.reduce((o, cell, index) => { - const header = this.headers[index] + const header = headers[index] if (header !== null) { o[header] = cell } diff --git a/test/fixtures/strict-false-less-columns.csv b/test/fixtures/strict-false-less-columns.csv new file mode 100644 index 0000000..2b4a252 --- /dev/null +++ b/test/fixtures/strict-false-less-columns.csv @@ -0,0 +1,4 @@ +a,b,c +1,2,3 +4,5 +6,7,8 diff --git a/test/fixtures/strict-false-broken.csv b/test/fixtures/strict-false-more-columns.csv similarity index 96% rename from test/fixtures/strict-false-broken.csv rename to test/fixtures/strict-false-more-columns.csv index d3a70a6..0faec1b 100644 --- a/test/fixtures/strict-false-broken.csv +++ b/test/fixtures/strict-false-more-columns.csv @@ -2,4 +2,3 @@ a,b,c 1,2,3 4,5,6,7 8,9,10 - diff --git a/test/snapshots/strictNo.test.js.md b/test/snapshots/strictNo.test.js.md new file mode 100644 index 0000000..f7f4bc4 --- /dev/null +++ b/test/snapshots/strictNo.test.js.md @@ -0,0 +1,57 @@ +# Snapshot report for `test/strictNo.test.js` + +The actual snapshot is saved in `strictNo.test.js.snap`. + +Generated by [AVA](https://ava.li). + +## strict: false - less columns + +> first row + + { + a: '1', + b: '2', + c: '3', + } + +> broken row + + { + 0: '4', + 1: '5', + } + +> last row + + { + a: '6', + b: '7', + c: '8', + } + +## strict: false - more columns + +> first row + + { + a: '1', + b: '2', + c: '3', + } + +> broken row + + { + 0: '4', + 1: '5', + 2: '6', + 3: '7', + } + +> last row + + { + a: '8', + b: '9', + c: '10', + } diff --git a/test/snapshots/strictNo.test.js.snap b/test/snapshots/strictNo.test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..a07fc72a61edecc133e16df6c2deabd75fe6e25c GIT binary patch literal 270 zcmV+p0rCDpRzVJl?rZ93avX}vB8z2q`;vygxW@Hm&Wb;qTN=+_dWP~#X1Oylu zc^Md)85sG2YM4YoELK5A#zZ*F5M3$>&N4!mN`|wHksQNp1f(s1IGC_Qn9z+hfU``{ zr3~RLQ`&gl47b { +test.cb('strict: false - more columns', (t) => { const verify = (err, lines) => { const headersFirstLine = Object.keys(lines[0]) + const headersBrokenLine = Object.keys(lines[1]) const headersLastLine = Object.keys(lines[2]) + t.false(err, 'no err') + t.is(headersBrokenLine[0], '0', 'first column name is 0') t.deepEqual(headersFirstLine, headersLastLine) + t.snapshot(lines[0], 'first row') + t.snapshot(lines[1], 'broken row') + t.snapshot(lines[2], 'last row') + t.is(lines.length, 3, '3 rows') + t.is(headersBrokenLine.length, 4, '4 columns') + t.end() + } + + collect('strict-false-more-columns', { strict: false }, verify) +}) + +test.cb('strict: false - less columns', (t) => { + const verify = (err, lines) => { + const headersFirstLine = Object.keys(lines[0]) + const headersBrokenLine = Object.keys(lines[1]) + const headersLastLine = Object.keys(lines[2]) t.false(err, 'no err') + t.is(headersBrokenLine[0], '0', 'first column name is "0"') + t.deepEqual(headersFirstLine, headersLastLine) t.snapshot(lines[0], 'first row') t.snapshot(lines[1], 'broken row') t.snapshot(lines[2], 'last row') t.is(lines.length, 3, '3 rows') + t.is(headersBrokenLine.length, 2, '2 columns') t.end() } - collect('strict-false-broken', { strict: false }, verify) + collect('strict-false-less-columns', { strict: false }, verify) }) From 3ad4de9d1ae770d2bdd4dff2184b221b153667cc Mon Sep 17 00:00:00 2001 From: Andreas Heissenberger Date: Sun, 13 Oct 2019 21:41:48 +0200 Subject: [PATCH 3/5] fix: if header exists object properties are set --- index.js | 7 +++++-- test/snapshots/strictNo.test.js.md | 10 +++++----- test/snapshots/strictNo.test.js.snap | Bin 270 -> 265 bytes test/strictNo.test.js | 4 ++-- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/index.js b/index.js index 70983dd..c84d18d 100644 --- a/index.js +++ b/index.js @@ -178,12 +178,15 @@ class CsvParser extends Transform { } writeRow (cells) { - const headers = (this.headers === false || cells.length !== this.headers.length) ? cells.map((value, index) => index) : this.headers + const headers = (this.headers === false) ? cells.map((value, index) => index) : this.headers const row = cells.reduce((o, cell, index) => { const header = headers[index] - if (header !== null) { + if (header === null) return o // skip columns + if (header !== undefined) { o[header] = cell + } else { + o[index] = cell } return o }, {}) diff --git a/test/snapshots/strictNo.test.js.md b/test/snapshots/strictNo.test.js.md index f7f4bc4..093acd0 100644 --- a/test/snapshots/strictNo.test.js.md +++ b/test/snapshots/strictNo.test.js.md @@ -17,8 +17,8 @@ Generated by [AVA](https://ava.li). > broken row { - 0: '4', - 1: '5', + a: '4', + b: '5', } > last row @@ -42,10 +42,10 @@ Generated by [AVA](https://ava.li). > broken row { - 0: '4', - 1: '5', - 2: '6', 3: '7', + a: '4', + b: '5', + c: '6', } > last row diff --git a/test/snapshots/strictNo.test.js.snap b/test/snapshots/strictNo.test.js.snap index a07fc72a61edecc133e16df6c2deabd75fe6e25c..bd21a989c89446207d8de398dde500a9d33959fa 100644 GIT binary patch delta 114 zcmV-&0FD2S0*L}5K~_N^Q*L2!b7*gLAa*he0sv=?^ZBmCX_;G%XHID-umq7Jphs{! z#00lPOljkFGu$?sDg}0?q=r UV=QqxhRM(X0R7z6im3wt07J1aKL7v# delta 119 zcmV--0EqvI0*(SAK~_N^Q*L2!b7*gLAa*he0sw~CQftceCQQtyo}#}}P+yTEpiIz> zG=Q^A(4`FFEK}Ne-3+(a&2f9(Vz9;os}+!T0ODvME(79;gdM~}UVNZS8Q~67V?>zJ ZCg3b^2b?9&fMYT=005@NBs{4D006x%F@695 diff --git a/test/strictNo.test.js b/test/strictNo.test.js index 97e49fd..a370e00 100644 --- a/test/strictNo.test.js +++ b/test/strictNo.test.js @@ -8,8 +8,8 @@ test.cb('strict: false - more columns', (t) => { const headersBrokenLine = Object.keys(lines[1]) const headersLastLine = Object.keys(lines[2]) t.false(err, 'no err') - t.is(headersBrokenLine[0], '0', 'first column name is 0') t.deepEqual(headersFirstLine, headersLastLine) + t.deepEqual(headersBrokenLine, ['3', 'a', 'b', 'c']) t.snapshot(lines[0], 'first row') t.snapshot(lines[1], 'broken row') t.snapshot(lines[2], 'last row') @@ -27,8 +27,8 @@ test.cb('strict: false - less columns', (t) => { const headersBrokenLine = Object.keys(lines[1]) const headersLastLine = Object.keys(lines[2]) t.false(err, 'no err') - t.is(headersBrokenLine[0], '0', 'first column name is "0"') t.deepEqual(headersFirstLine, headersLastLine) + t.deepEqual(headersBrokenLine, ['a', 'b']) t.snapshot(lines[0], 'first row') t.snapshot(lines[1], 'broken row') t.snapshot(lines[2], 'last row') From 5077069bf04745e00ba95e3dcec3bcd268da7c7b Mon Sep 17 00:00:00 2001 From: Andreas Heissenberger Date: Sun, 13 Oct 2019 22:46:43 +0200 Subject: [PATCH 4/5] fix: move added properties to end --- index.js | 2 +- test/snapshots/strictNo.test.js.md | 2 +- test/snapshots/strictNo.test.js.snap | Bin 265 -> 268 bytes test/strictNo.test.js | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index c84d18d..3690774 100644 --- a/index.js +++ b/index.js @@ -186,7 +186,7 @@ class CsvParser extends Transform { if (header !== undefined) { o[header] = cell } else { - o[index] = cell + o[`_${index}`] = cell } return o }, {}) diff --git a/test/snapshots/strictNo.test.js.md b/test/snapshots/strictNo.test.js.md index 093acd0..1f7aa5e 100644 --- a/test/snapshots/strictNo.test.js.md +++ b/test/snapshots/strictNo.test.js.md @@ -42,7 +42,7 @@ Generated by [AVA](https://ava.li). > broken row { - 3: '7', + _3: '7', a: '4', b: '5', c: '6', diff --git a/test/snapshots/strictNo.test.js.snap b/test/snapshots/strictNo.test.js.snap index bd21a989c89446207d8de398dde500a9d33959fa..266e6f41e7096e38ca0a331b3d046873a4362ca7 100644 GIT binary patch literal 268 zcmV+n0rUPrRzVFP#g5bkY8~`+cnSmW_3L^(2iy4r%0pf5VE&^gO>sNcj5Z->f!i^bI32@eXfRmgk=Y1HTL5t|VTUl07e}=5x*2X8 SG13yk>lOgj03dX#0{{T(t#85r literal 265 zcmV+k0rvhuRzVJl?rZ93avX}vB8z2q`;vygxW@Hm&Wb;qTN=+_dWP~#X1Oylu zc^Md)85sG2YM4YoELK5A#zZ*F5M3$>&N4!mN`|wHksQNp1f(s1IGC_Qm~cD91h+#> zY2$S>+%}ry_PWJjjR#gMAngFe(Lh`V#1jcShy~qfW86VNTvXw9s~K$q&H}e%EO9!9 P$ { const headersLastLine = Object.keys(lines[2]) t.false(err, 'no err') t.deepEqual(headersFirstLine, headersLastLine) - t.deepEqual(headersBrokenLine, ['3', 'a', 'b', 'c']) + t.deepEqual(headersBrokenLine, ['a', 'b', 'c', '_3']) t.snapshot(lines[0], 'first row') t.snapshot(lines[1], 'broken row') t.snapshot(lines[2], 'last row') From 240d075dc9ec7fd102eb75bf72a876251f853ffc Mon Sep 17 00:00:00 2001 From: Andreas Heissenberger Date: Sun, 13 Oct 2019 22:47:04 +0200 Subject: [PATCH 5/5] fix: add missing informations --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e66762..af5293a 100644 --- a/README.md +++ b/README.md @@ -251,9 +251,13 @@ Maximum number of bytes per row. An error is thrown if a line exeeds this value. #### strict Type: `Boolean`
+Default: `false` If `true`, instructs the parser that the number of columns in each row must match -the number of `headers` specified. +the number of `headers` specified or throws an exception. +if `false`: the headers are mapped to the column index + less columns: any missing column in the middle will result in a wrong property mapping! + more columns: the aditional columns will create a "_"+index properties - eg. "_10":"value" ## Events