1 | "use strict";
|
2 |
|
3 | var fs = require('fs')
|
4 | , when = require('when')
|
5 | , rowStreamer = require('../src/rowStreamer')
|
6 | , loaders = require('../src/loaders')
|
7 | , transformers = require('../src/transformers')
|
8 | , defines = require('../src/defines')
|
9 | , chai = require('chai')
|
10 | , chaiAsPromised = require('chai-as-promised');
|
11 |
|
12 | chai.Should();
|
13 | chai.use(chaiAsPromised);
|
14 | require("mocha-as-promised")();
|
15 |
|
16 |
|
17 | describe('rowStreamer', function() {
|
18 |
|
19 | var options
|
20 |
|
21 | , tsvSimple, tsvSimple1100, tsvMissingHeaders, tsvTwoSheets, tsvEmptyRow
|
22 | , tsvContinue, tsvDecimalInt
|
23 |
|
24 | , xlsTwoSheets, xlsSimple, xlsInvalid
|
25 |
|
26 | , tsvLoader, datasetTransformer;
|
27 |
|
28 | beforeEach(function() {
|
29 | options = {};
|
30 |
|
31 | tsvSimple = __dirname + '/convert/tsv/files/tsvSimple.tsv';
|
32 | tsvSimple1100 = __dirname + '/convert/tsv/files/tsvSimple1100.tsv';
|
33 | tsvMissingHeaders = __dirname + '/convert/tsv/files/tsvMissingHeaders.tsv';
|
34 | tsvTwoSheets = __dirname + '/convert/tsv/files/tsvTwoSheets.tsv';
|
35 | tsvEmptyRow = __dirname + '/convert/tsv/files/tsvEmptyRow.tsv';
|
36 | tsvContinue = __dirname + '/convert/tsv/files/tsvContinue.tsv';
|
37 | tsvDecimalInt = __dirname + '/convert/tsv/files/tsvDecimalInt.tsv';
|
38 |
|
39 | xlsTwoSheets = __dirname + '/convert/xls/files/xlsTwoSheets.xls';
|
40 | xlsSimple = __dirname + '/convert/xls/files/xlsSimple.xls';
|
41 | xlsInvalid = __dirname + '/convert/xls/files/xlsInvalid.xls';
|
42 |
|
43 | tsvLoader = loaders.getTsvLoader();
|
44 | datasetTransformer = transformers.getDataSetTransformer();
|
45 | });
|
46 |
|
47 | describe('#isDataRowEmpty()', function() {
|
48 |
|
49 | it('should detect that the data row is empty', function() {
|
50 | var dataRow = [' ', '#REF!:emptyRange', '', ' #REF!:emptyRange '];
|
51 | rowStreamer.isDataRowEmpty(datasetTransformer, dataRow).should.be.true;
|
52 | });
|
53 |
|
54 | it('should not detect that the data row is empty', function() {
|
55 | var dataRow = [' ', '', '', 'not empty after all!'];
|
56 | rowStreamer.isDataRowEmpty(datasetTransformer, dataRow).should.be.false;
|
57 | });
|
58 |
|
59 | });
|
60 |
|
61 | describe('#toRows()', function() {
|
62 |
|
63 | it('take a tsv file path and get the rows it contains', function() {
|
64 | var headerCount = 0, dataRowCount = 0;
|
65 | return rowStreamer.toRows(fs.createReadStream(tsvSimple)
|
66 | , tsvLoader, options
|
67 | , function headerRowCallback(dataRow) {
|
68 | dataRow.should.be.instanceOf(Array);
|
69 | dataRow.length.should.equal(8);
|
70 | ++headerCount;
|
71 | }
|
72 | , function dataRowCallback(dataRow) {
|
73 | dataRow.should.be.instanceOf(Array);
|
74 | dataRow.length.should.equal(8);
|
75 | ++dataRowCount;
|
76 | }).then(function() {
|
77 | headerCount.should.equal(1);
|
78 | dataRowCount.should.equal(4);
|
79 | });
|
80 | });
|
81 |
|
82 | it('should find no header rows', function() {
|
83 | options = {
|
84 | headerRow: -1
|
85 | };
|
86 | var headerCount = 0, dataRowCount = 0;
|
87 | return rowStreamer.toRows(fs.createReadStream(tsvSimple)
|
88 | , tsvLoader, options
|
89 | , function headerRowCallback(dataRow) { ++headerCount; }
|
90 | , function dataRowCallback(dataRow) { ++dataRowCount; }
|
91 | ).then(function() {
|
92 | headerCount.should.equal(0);
|
93 | dataRowCount.should.equal(5);
|
94 | });
|
95 | });
|
96 |
|
97 | it('should use the provided headers', function() {
|
98 | options = {
|
99 | headerRow: -1,
|
100 | useHeaders: ['one', 'two', 'three', 'four', 'five'],
|
101 | };
|
102 |
|
103 | var headerRow, headerCount = 0, dataRowCount = 0;
|
104 |
|
105 | return rowStreamer.toRows(fs.createReadStream(tsvMissingHeaders)
|
106 | , tsvLoader, options
|
107 | , function headerRowCallback(dataRow) {
|
108 | headerRow = dataRow;
|
109 | ++headerCount;
|
110 | }
|
111 | , function dataRowCallback(dataRow) {
|
112 | ++dataRowCount;
|
113 | })
|
114 | .then(function() {
|
115 | headerCount.should.equal(1);
|
116 | dataRowCount.should.equal(4);
|
117 | headerRow.should.eql(['one', 'two', 'three', 'four', 'five']);
|
118 | });
|
119 | });
|
120 |
|
121 | it('should provided headers and ignore current header', function() {
|
122 | options = {
|
123 | useHeaders: ['one', 'two', 'three', 'four', 'five'],
|
124 | };
|
125 |
|
126 | var headerRow, headerCount = 0, dataRowCount = 0;
|
127 |
|
128 | return rowStreamer.toRows(fs.createReadStream(tsvSimple)
|
129 | , tsvLoader, options,
|
130 | function headerRowCallback(dataRow) {
|
131 | headerRow = dataRow;
|
132 | ++headerCount;
|
133 | },
|
134 | function dataRowCallback(dataRow) {
|
135 | ++dataRowCount;
|
136 | }
|
137 | ).then(function() {
|
138 | headerCount.should.equal(1);
|
139 | dataRowCount.should.equal(4);
|
140 | headerRow.should.eql(['one', 'two', 'three', 'four', 'five']);
|
141 | });
|
142 | });
|
143 |
|
144 | it('should be able to continue / join lines', function() {
|
145 |
|
146 | var headerRow, data = [], headerCount = 0;
|
147 |
|
148 | return rowStreamer.toRows(fs.createReadStream(tsvContinue)
|
149 | , tsvLoader, options,
|
150 | function headerRowCallback(dataRow) {
|
151 | headerRow = dataRow;
|
152 | ++headerCount;
|
153 | },
|
154 | function dataRowCallback(dataRow) {
|
155 | data.push(dataRow);
|
156 | }
|
157 | ).then(function() {
|
158 | headerCount.should.equal(1);
|
159 | data.should.eql([
|
160 | [ 'Dave Bob James' ],
|
161 | [ 'Madison Sally\nSmith' ],
|
162 | [ 'One\nTwo\nThree' ],
|
163 | [ 'One\n\nTwo\nThree' ],
|
164 | [ '\nOne' ],
|
165 | [ 'One\n' ],
|
166 | [ '\n' ],
|
167 | [ '\n\n\n' ]
|
168 | ]);
|
169 | });
|
170 | });
|
171 |
|
172 | });
|
173 |
|
174 | describe('#getAttributes()', function() {
|
175 |
|
176 | it('get the proper headers & data types back', function() {
|
177 | options = {
|
178 | headerRow: 0
|
179 | };
|
180 | return rowStreamer.getAttributes(fs.createReadStream(tsvSimple)
|
181 | , tsvLoader, datasetTransformer, options
|
182 | ).then(function(fileAttributes) {
|
183 | fileAttributes.headers.should.eql([
|
184 | 'Simple_Text', 'Simple_Int', 'Simple_Numeric',
|
185 | 'Simple_Boolean', 'Simple_LAT', 'Simple_Lng',
|
186 | 'Simple_Primary', 'Simple_Zip'
|
187 | ]);
|
188 | fileAttributes.dataTypes.should.eql([
|
189 | defines.TEXT, defines.INTEGER, defines.NUMERIC,
|
190 | defines.BOOLEAN, defines.LAT, defines.LONG,
|
191 | defines.PRIMARY_INTEGER, defines.ZIP
|
192 | ]);
|
193 | fileAttributes.ignoreColumns.length.should.equal(0);
|
194 | });
|
195 | });
|
196 |
|
197 | it('get the proper headers & data types back (decimal integers)', function() {
|
198 | options = {
|
199 | headerRow: 0
|
200 | };
|
201 | return rowStreamer.getAttributes(
|
202 | fs.createReadStream(tsvDecimalInt)
|
203 | , tsvLoader, datasetTransformer, options
|
204 | ).then(function(fileAttributes) {
|
205 | fileAttributes.headers.should.eql(['int', 'text']);
|
206 | fileAttributes.dataTypes.should.eql([
|
207 | defines.INTEGER, defines.TEXT
|
208 | ]);
|
209 | fileAttributes.ignoreColumns.length.should.equal(0);
|
210 | });
|
211 | });
|
212 |
|
213 | it('should force a particular data type', function() {
|
214 | options = {
|
215 | headerRow: 0,
|
216 | forceTypes: {
|
217 | 'Simple_Int': defines.TEXT
|
218 | }
|
219 | };
|
220 | return rowStreamer.getAttributes(
|
221 | fs.createReadStream(tsvSimple)
|
222 | , tsvLoader, datasetTransformer, options
|
223 | ).then(function(fileAttributes) {
|
224 | fileAttributes.headers.should.eql([
|
225 | 'Simple_Text', 'Simple_Int', 'Simple_Numeric',
|
226 | 'Simple_Boolean', 'Simple_LAT', 'Simple_Lng',
|
227 | 'Simple_Primary', 'Simple_Zip'
|
228 | ]);
|
229 | fileAttributes.dataTypes.should.eql([
|
230 | defines.TEXT, defines.TEXT, defines.NUMERIC,
|
231 | defines.BOOLEAN, defines.LAT, defines.LONG,
|
232 | defines.PRIMARY_INTEGER, defines.ZIP
|
233 | ]);
|
234 | fileAttributes.ignoreColumns.length.should.equal(0);
|
235 | });
|
236 | });
|
237 |
|
238 | it('should ignore empty headers', function(done) {
|
239 | options = {
|
240 | headerRow: 0,
|
241 | ignoreEmptyHeaders: true
|
242 | };
|
243 | return rowStreamer.getAttributes(
|
244 | fs.createReadStream(tsvMissingHeaders)
|
245 | , tsvLoader, datasetTransformer, options
|
246 | ).then(function(fileAttributes) {
|
247 | fileAttributes.headers.should.eql([ 'test_1', 'test_3' ]);
|
248 | fileAttributes.dataTypes.should.eql([
|
249 | defines.TEXT, defines.NUMERIC
|
250 | ]);
|
251 | fileAttributes.ignoreColumns.length.should.equal(1);
|
252 | fileAttributes.ignoreColumns.should.eql([ 1 ]);
|
253 | });
|
254 | });
|
255 |
|
256 | it('should not ignore empty headers', function(done) {
|
257 | options = {
|
258 | headerRow: 0
|
259 | };
|
260 | return rowStreamer.getAttributes(
|
261 | fs.createReadStream(tsvMissingHeaders)
|
262 | , tsvLoader, datasetTransformer, options
|
263 | ).then(function(fileAttributes) {
|
264 | fileAttributes.headers.should.eql([
|
265 | 'test_1', 'column_2', 'test_3'
|
266 | ]);
|
267 | fileAttributes.dataTypes.should.eql([
|
268 | defines.TEXT, defines.PRIMARY_INTEGER, defines.NUMERIC
|
269 | ]);
|
270 | fileAttributes.ignoreColumns.length.should.equal(0);
|
271 | });
|
272 | });
|
273 |
|
274 | });
|
275 |
|
276 | describe('#getData()', function() {
|
277 |
|
278 | it('should loop through the dataset entirely and not skip anything', function(done) {
|
279 | options = {
|
280 | headerRow: 0
|
281 | };
|
282 | var dataRowCount = 0;
|
283 |
|
284 | return rowStreamer.getData(
|
285 | fs.createReadStream(tsvSimple)
|
286 | , tsvLoader, datasetTransformer, options, false,
|
287 | function dataRowCallback(dataRow) { ++dataRowCount; }
|
288 | ).then(function() {
|
289 | dataRowCount.should.equal(4);
|
290 | });
|
291 | });
|
292 |
|
293 | it('should skip empty data rows', function(done) {
|
294 | options = {
|
295 | headerRow: 0
|
296 | };
|
297 | var dataRowCount = 0;
|
298 |
|
299 | return rowStreamer.getData(
|
300 | fs.createReadStream(tsvEmptyRow)
|
301 | , tsvLoader, datasetTransformer, options, false,
|
302 | function dataRowCallback(dataRow) { ++dataRowCount; }
|
303 | ).then(function() {
|
304 | dataRowCount.should.equal(2);
|
305 | });
|
306 | });
|
307 |
|
308 | it('should skip over ignored headers', function(done) {
|
309 | options = { headerRow: 0 };
|
310 | var dataRowCount = 0;
|
311 |
|
312 | return rowStreamer.getData(
|
313 | fs.createReadStream(tsvSimple)
|
314 | , tsvLoader, datasetTransformer, options,
|
315 | [0, 1, 2, 3, 4, 5, 6],
|
316 | function dataRowCallback(dataRow) {
|
317 | dataRow.length.should.equal(1);
|
318 | ++dataRowCount;
|
319 | }
|
320 | ).then(function() {
|
321 | dataRowCount.should.equal(4);
|
322 | });
|
323 | });
|
324 |
|
325 | });
|
326 |
|
327 | describe('#removeIndexes()', function() {
|
328 | it('should remove the indexes provided from the array (first section)', function() {
|
329 | rowStreamer.removeIndexes([0, 1, 2], ['0', '1', '2', '3'])
|
330 | .should.eql(['3']);
|
331 | });
|
332 | it('should remove the indexes provided from the array (end section)', function() {
|
333 | rowStreamer.removeIndexes([1, 2, 3], ['0', '1', '2', '3'])
|
334 | .should.eql(['0']);
|
335 | });
|
336 | it('should remove the indexes provided from the array (mid section)', function() {
|
337 | rowStreamer.removeIndexes([1, 2], ['0', '1', '2', '3'])
|
338 | .should.eql(['0', '3']);
|
339 | });
|
340 | it('should remove the indexes provided from the array (mixed)', function() {
|
341 | rowStreamer.removeIndexes([1, 0, 3], ['0', '1', '2', '3'])
|
342 | .should.eql(['2']);
|
343 | });
|
344 | it('should not remove any indexes', function() {
|
345 | rowStreamer.removeIndexes([], ['0', '1', '2', '3'])
|
346 | .should.eql(['0', '1', '2', '3']);
|
347 | (function() {
|
348 | rowStreamer.removeIndexes(undefined, ['0', '1', '2', '3'])
|
349 | .should.eql(['0', '1', '2', '3']);
|
350 | }).should.throw;
|
351 | });
|
352 | });
|
353 |
|
354 | });
|