@hrforte/react-pivottable 2.2.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,8 @@
2
2
 
3
3
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
4
4
 
5
+ function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
6
+
5
7
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6
8
 
7
9
  /* eslint-disable no-magic-numbers */
@@ -140,19 +142,447 @@ describe(' PivotDataWorker', function () {
140
142
  });
141
143
  });
142
144
 
143
- it('logs the fallback to a synchronous computation', function () {
145
+ it('surfaces worker failures without a synchronous fallback', _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
146
+ var client, promise;
147
+ return regeneratorRuntime.wrap(function _callee$(_context) {
148
+ while (1) {
149
+ switch (_context.prev = _context.next) {
150
+ case 0:
151
+ client = loadClient();
152
+
153
+ client.setWorkerDebug(true);
154
+
155
+ promise = client.computePivotWithFallback(records, 'data-2', config);
156
+
157
+ // Simulate a worker that fails to load before producing any result.
158
+
159
+ instances[0].onerror(new Error('404'));
160
+
161
+ _context.next = 6;
162
+ return promise.then(function () {
163
+ throw new Error('Worker request unexpectedly succeeded');
164
+ }, function (error) {
165
+ expect(error.message).toBe('Pivot worker failed to load');
166
+ });
167
+
168
+ case 6:
169
+ expect(loggedText()).toEqual(expect.arrayContaining([expect.stringContaining('worker error event'), expect.stringContaining('synchronous fallback disabled')]));
170
+ expect(loggedText()).not.toEqual(expect.arrayContaining([expect.stringContaining('running synchronous computation')]));
171
+
172
+ case 8:
173
+ case 'end':
174
+ return _context.stop();
175
+ }
176
+ }
177
+ }, _callee, this);
178
+ })));
179
+
180
+ it('stages large datasets in chunks before computing', function () {
144
181
  var client = loadClient();
145
- client.setWorkerDebug(true);
182
+ var largeRecords = new Array(1200).fill(null).map(function (_, index) {
183
+ return {
184
+ name: 'Employee ' + index
185
+ };
186
+ });
187
+ var promise = client.computePivotInWorker(largeRecords, 'large-data', config);
188
+ var worker = instances[0];
146
189
 
147
- var promise = client.computePivotWithFallback(records, 'data-2', config);
190
+ expect(worker.posted.map(function (message) {
191
+ return message.type;
192
+ })).toEqual(['pivot:setDataStart', 'pivot:setDataChunk']);
148
193
 
149
- // Simulate a worker that fails to load before producing any result.
150
- instances[0].onerror(new Error('404'));
194
+ return new Promise(function (resolve) {
195
+ return setTimeout(resolve, 20);
196
+ }).then(function () {
197
+ var types = worker.posted.map(function (message) {
198
+ return message.type;
199
+ });
200
+ expect(types.filter(function (type) {
201
+ return type === 'pivot:setDataChunk';
202
+ })).toHaveLength(3);
203
+ expect(types.slice(-2)).toEqual(['pivot:setDataEnd', 'pivot:compute']);
204
+ worker.onmessage({
205
+ data: {
206
+ type: 'pivot:result',
207
+ id: 1,
208
+ result: { rowKeys: [], colKeys: [] }
209
+ }
210
+ });
211
+ return promise;
212
+ }).then(function (result) {
213
+ expect(result.rowKeys).toEqual([]);
214
+ });
215
+ });
151
216
 
217
+ it('requests a viewport without sending the dataset again', function () {
218
+ var client = loadClient();
219
+ var promise = client.computePivotViewportInWorker(42, 64, 128, false, 16, 48);
220
+ var worker = instances[0];
221
+ expect(worker.posted).toEqual([{
222
+ type: 'pivot:viewport',
223
+ id: 1,
224
+ viewportKey: 42,
225
+ start: 64,
226
+ end: 128,
227
+ columnMode: false,
228
+ columnStart: 16,
229
+ columnEnd: 48
230
+ }]);
231
+ worker.onmessage({
232
+ data: {
233
+ type: 'pivot:viewportResult',
234
+ id: 1,
235
+ result: { start: 64, end: 128, rows: [{ displayKey: ['A'] }] }
236
+ }
237
+ });
152
238
  return promise.then(function (result) {
153
- expect(result.totalRecords).toBe(2);
154
- expect(loggedText()).toEqual(expect.arrayContaining([expect.stringContaining('worker error event'), expect.stringContaining('falling back to the main thread'), expect.stringContaining('running synchronous computation'), expect.stringContaining('synchronous computation finished in')]));
239
+ expect(result.rows).toEqual([{ displayKey: ['A'] }]);
240
+ });
241
+ });
242
+
243
+ it('releases a replaced viewport request immediately', _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() {
244
+ var client, firstPromise, secondPromise, worker, firstError;
245
+ return regeneratorRuntime.wrap(function _callee2$(_context2) {
246
+ while (1) {
247
+ switch (_context2.prev = _context2.next) {
248
+ case 0:
249
+ client = loadClient();
250
+ firstPromise = client.computePivotViewportInWorker(42, 0, 64, false).catch(function (error) {
251
+ return error;
252
+ });
253
+ secondPromise = client.computePivotViewportInWorker(42, 64, 128, false);
254
+ worker = instances[0];
255
+ _context2.next = 6;
256
+ return firstPromise;
257
+
258
+ case 6:
259
+ firstError = _context2.sent;
260
+
261
+ expect(firstError.code).toBe('PIVOT_VIEWPORT_CANCELLED');
262
+ expect(worker.posted.filter(function (message) {
263
+ return message.type === 'pivot:viewport';
264
+ })).toHaveLength(2);
265
+
266
+ worker.onmessage({
267
+ data: {
268
+ type: 'pivot:viewportResult',
269
+ id: 2,
270
+ result: { start: 64, end: 128, rows: [] }
271
+ }
272
+ });
273
+ _context2.next = 12;
274
+ return expect(secondPromise).resolves.toEqual({
275
+ start: 64,
276
+ end: 128,
277
+ rows: []
278
+ });
279
+
280
+ case 12:
281
+ case 'end':
282
+ return _context2.stop();
283
+ }
284
+ }
285
+ }, _callee2, this);
286
+ })));
287
+
288
+ it('releases the staged dataset and stages it again for the next compute', _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3() {
289
+ var client, firstPromise, worker, secondPromise;
290
+ return regeneratorRuntime.wrap(function _callee3$(_context3) {
291
+ while (1) {
292
+ switch (_context3.prev = _context3.next) {
293
+ case 0:
294
+ client = loadClient();
295
+ firstPromise = client.computePivotInWorker(records, 'reusable-data', config);
296
+ worker = instances[0];
297
+
298
+ worker.onmessage({
299
+ data: {
300
+ type: 'pivot:result',
301
+ id: 1,
302
+ result: { rowKeys: [], colKeys: [], attrValues: { name: { Nick: 1 } } }
303
+ }
304
+ });
305
+ _context3.next = 6;
306
+ return firstPromise;
307
+
308
+ case 6:
309
+
310
+ client.releaseDatasetInWorker('reusable-data');
311
+ secondPromise = client.computePivotInWorker(records, 'reusable-data', config);
312
+
313
+ expect(worker.posted.map(function (message) {
314
+ return message.type;
315
+ })).toEqual(['pivot:setData', 'pivot:compute', 'pivot:releaseData', 'pivot:setData', 'pivot:compute']);
316
+ worker.onmessage({
317
+ data: {
318
+ type: 'pivot:result',
319
+ id: 2,
320
+ result: { rowKeys: [], colKeys: [] }
321
+ }
322
+ });
323
+ _context3.next = 12;
324
+ return secondPromise;
325
+
326
+ case 12:
327
+ case 'end':
328
+ return _context3.stop();
329
+ }
330
+ }
331
+ }, _callee3, this);
332
+ })));
333
+
334
+ it('terminates the shared worker after the last table owner unmounts', _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4() {
335
+ var client, promise, worker;
336
+ return regeneratorRuntime.wrap(function _callee4$(_context4) {
337
+ while (1) {
338
+ switch (_context4.prev = _context4.next) {
339
+ case 0:
340
+ client = loadClient();
341
+
342
+ client.retainPivotWorker('table-a');
343
+ client.retainPivotWorker('table-b');
344
+ promise = client.computePivotInWorker(records, 'owned-data', config, 'table-a');
345
+ worker = instances[0];
346
+
347
+ worker.onmessage({
348
+ data: {
349
+ type: 'pivot:result',
350
+ id: 1,
351
+ result: { rowKeys: [], colKeys: [] }
352
+ }
353
+ });
354
+ _context4.next = 8;
355
+ return promise;
356
+
357
+ case 8:
358
+
359
+ client.releasePivotWorker('table-a');
360
+ expect(worker.terminated).not.toBe(true);
361
+ client.releasePivotWorker('table-b');
362
+ expect(worker.terminated).toBe(true);
363
+ expect(worker.posted.slice(-2)).toEqual([{ type: 'pivot:releaseOwner', ownerKey: 'table-a' }, { type: 'pivot:releaseOwner', ownerKey: 'table-b' }]);
364
+
365
+ case 13:
366
+ case 'end':
367
+ return _context4.stop();
368
+ }
369
+ }
370
+ }, _callee4, this);
371
+ })));
372
+
373
+ it('caches a computed pivot and returns only requested rows', function () {
374
+ var originalAddEventListener = self.addEventListener;
375
+ var originalPostMessage = self.postMessage;
376
+ var posted = [];
377
+ var onMessage = void 0;
378
+ self.addEventListener = function (type, listener) {
379
+ if (type === 'message') {
380
+ onMessage = listener;
381
+ }
382
+ };
383
+ self.postMessage = function (message) {
384
+ return posted.push(message);
385
+ };
386
+
387
+ try {
388
+ jest.resetModules();
389
+ require('../pivotWorker');
390
+ onMessage({
391
+ data: { type: 'pivot:setData', id: 1, dataKey: 'x', data: records }
392
+ });
393
+ onMessage({ data: { type: 'pivot:compute', id: 1, dataKey: 'x', config: config } });
394
+ var computed = posted.find(function (message) {
395
+ return message.type === 'pivot:result';
396
+ });
397
+ expect(computed.result.viewportKey).toBe(1);
398
+
399
+ onMessage({
400
+ data: {
401
+ type: 'pivot:viewport',
402
+ id: 2,
403
+ viewportKey: 1,
404
+ start: 1,
405
+ end: 2,
406
+ columnMode: false
407
+ }
408
+ });
409
+ var viewport = posted.find(function (message) {
410
+ return message.type === 'pivot:viewportResult';
411
+ });
412
+ expect(viewport.result.rows).toHaveLength(1);
413
+ expect(viewport.result.rows[0].displayKey).toEqual(['Nick']);
414
+ expect(viewport.result.totalRows).toBe(2);
415
+ } finally {
416
+ self.addEventListener = originalAddEventListener;
417
+ self.postMessage = originalPostMessage;
418
+ }
419
+ });
420
+
421
+ it('returns a compact result and viewport cell values for virtual tables', function () {
422
+ var originalAddEventListener = self.addEventListener;
423
+ var originalPostMessage = self.postMessage;
424
+ var posted = [];
425
+ var onMessage = void 0;
426
+ self.addEventListener = function (type, listener) {
427
+ if (type === 'message') {
428
+ onMessage = listener;
429
+ }
430
+ };
431
+ self.postMessage = function (message) {
432
+ return posted.push(message);
433
+ };
434
+ var largeRecords = new Array(400).fill(null).map(function (_, index) {
435
+ return {
436
+ name: 'Employee ' + index,
437
+ department: 'Department ' + index % 3
438
+ };
439
+ });
440
+
441
+ try {
442
+ jest.resetModules();
443
+ require('../pivotWorker');
444
+ onMessage({
445
+ data: {
446
+ type: 'pivot:setData',
447
+ id: 1,
448
+ dataKey: 'virtual-data',
449
+ data: largeRecords
450
+ }
451
+ });
452
+ onMessage({
453
+ data: {
454
+ type: 'pivot:compute',
455
+ id: 1,
456
+ dataKey: 'virtual-data',
457
+ config: Object.assign({}, config, {
458
+ cols: ['department'],
459
+ virtualizeRows: true,
460
+ rendererName: 'Table'
461
+ })
462
+ }
463
+ });
464
+ var computed = posted.find(function (message) {
465
+ return message.type === 'pivot:result';
466
+ });
467
+ expect(computed.result.virtualized).toBe(true);
468
+ expect(computed.result.totalRows).toBe(400);
469
+ expect(computed.result.rowKeys).toEqual([]);
470
+ expect(computed.result.tree).toEqual({});
471
+
472
+ onMessage({
473
+ data: { type: 'pivot:releaseData', dataKey: 'virtual-data' }
474
+ });
475
+
476
+ onMessage({
477
+ data: {
478
+ type: 'pivot:viewport',
479
+ id: 2,
480
+ viewportKey: 1,
481
+ start: 32,
482
+ end: 64,
483
+ columnMode: false
484
+ }
485
+ });
486
+ var viewport = posted.find(function (message) {
487
+ return message.type === 'pivot:viewportResult';
488
+ });
489
+ expect(viewport.result.rows).toHaveLength(32);
490
+ expect(viewport.result.rows[0].cells).toBeDefined();
491
+ expect(viewport.result.rows[0].rowTotal[0]).toBe(1);
492
+
493
+ onMessage({
494
+ data: {
495
+ type: 'pivot:compute',
496
+ id: 3,
497
+ dataKey: 'virtual-data',
498
+ config: config
499
+ }
500
+ });
501
+ var releasedDatasetError = posted.find(function (message) {
502
+ return message.type === 'pivot:error' && message.id === 3;
503
+ });
504
+ expect(releasedDatasetError.message).toContain('no dataset staged');
505
+ } finally {
506
+ self.addEventListener = originalAddEventListener;
507
+ self.postMessage = originalPostMessage;
508
+ }
509
+ });
510
+
511
+ it('uses a compact result when columns are wide but rows are short', function () {
512
+ var originalAddEventListener = self.addEventListener;
513
+ var originalPostMessage = self.postMessage;
514
+ var posted = [];
515
+ var onMessage = void 0;
516
+ self.addEventListener = function (type, listener) {
517
+ if (type === 'message') {
518
+ onMessage = listener;
519
+ }
520
+ };
521
+ self.postMessage = function (message) {
522
+ return posted.push(message);
523
+ };
524
+ var wideRecords = new Array(150).fill(null).map(function (_, index) {
525
+ return {
526
+ employee: 'Employee ' + String(index).padStart(3, '0'),
527
+ gender: index % 2 === 0 ? 'female' : 'male'
528
+ };
155
529
  });
530
+
531
+ try {
532
+ jest.resetModules();
533
+ require('../pivotWorker');
534
+ onMessage({
535
+ data: {
536
+ type: 'pivot:setData',
537
+ id: 1,
538
+ dataKey: 'wide-data',
539
+ data: wideRecords
540
+ }
541
+ });
542
+ onMessage({
543
+ data: {
544
+ type: 'pivot:compute',
545
+ id: 1,
546
+ dataKey: 'wide-data',
547
+ config: Object.assign({}, config, {
548
+ rows: ['gender'],
549
+ cols: ['employee'],
550
+ virtualizeRows: true,
551
+ rendererName: 'Table'
552
+ })
553
+ }
554
+ });
555
+ var computed = posted.find(function (message) {
556
+ return message.type === 'pivot:result';
557
+ });
558
+ expect(computed.result.virtualized).toBe(true);
559
+ expect(computed.result.totalRows).toBe(2);
560
+ expect(computed.result.totalColumns).toBe(150);
561
+ expect(computed.result.tree).toEqual({});
562
+ expect(computed.result.colTotals).toEqual({});
563
+
564
+ onMessage({
565
+ data: {
566
+ type: 'pivot:viewport',
567
+ id: 2,
568
+ viewportKey: 1,
569
+ start: 0,
570
+ end: 2,
571
+ columnMode: false,
572
+ columnStart: 32,
573
+ columnEnd: 48
574
+ }
575
+ });
576
+ var viewport = posted.find(function (message) {
577
+ return message.type === 'pivot:viewportResult';
578
+ });
579
+ expect(viewport.result.rows).toHaveLength(2);
580
+ expect(Object.keys(viewport.result.rows[0].cells).length).toBeLessThanOrEqual(16);
581
+ expect(Object.keys(viewport.result.colTotals)).toHaveLength(16);
582
+ } finally {
583
+ self.addEventListener = originalAddEventListener;
584
+ self.postMessage = originalPostMessage;
585
+ }
156
586
  });
157
587
 
158
588
  it('stops logging when debug is switched off again', function () {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/__tests__/PivotDataWorker-test.js"],"names":["describe","records","name","gender","config","rows","cols","aggregations","key","aggregatorName","vals","instances","logSpy","FakeWorker","url","posted","onmessage","onerror","push","message","terminated","loggedText","mock","calls","map","call","filter","String","arg","startsWith","join","loadClient","jest","resetModules","require","beforeEach","global","Worker","spyOn","console","mockImplementation","afterEach","mockRestore","it","client","promise","computePivotInWorker","expect","not","toHaveBeenCalled","data","type","id","result","rowKeys","colKeys","setWorkerDebug","toEqual","arrayContaining","stringContaining","types","staged","find","m","toBe","dataKey","worker","processed","total","phase","totalRecords","then","computePivotWithFallback","Error","mockClear"],"mappings":"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","file":"PivotDataWorker-test.js","sourcesContent":["/* eslint-disable no-magic-numbers */\n/*\n * Tests the main-thread worker client, including the debug logging that the\n * `workerDebug` prop of PivotTableUI switches on.\n */\ndescribe(' PivotDataWorker', function() {\n const records = [\n {name: 'Nick', gender: 'male'},\n {name: 'Jane', gender: 'female'},\n ];\n const config = {\n rows: ['name'],\n cols: [],\n aggregations: [{key: 'count', aggregatorName: 'Count', vals: []}],\n };\n\n let instances;\n let logSpy;\n\n class FakeWorker {\n constructor(url) {\n this.url = url;\n this.posted = [];\n this.onmessage = null;\n this.onerror = null;\n instances.push(this);\n }\n\n postMessage(message) {\n this.posted.push(message);\n }\n\n terminate() {\n this.terminated = true;\n }\n }\n\n // console.log('%c[pivottable worker]', 'style', ...) -> strip the format\n // directive and its style argument to assert on the message itself.\n const loggedText = () =>\n logSpy.mock.calls.map(call =>\n call\n .filter(\n arg =>\n !String(arg).startsWith('%c') && !String(arg).startsWith('color:')\n )\n .join(' ')\n );\n\n const loadClient = () => {\n jest.resetModules();\n return require('../PivotDataWorker');\n };\n\n beforeEach(function() {\n instances = [];\n global.Worker = FakeWorker;\n logSpy = jest.spyOn(console, 'log').mockImplementation(() => {});\n });\n\n afterEach(function() {\n logSpy.mockRestore();\n });\n\n it('is silent by default', function() {\n const client = loadClient();\n const promise = client.computePivotInWorker(records, 'data-1', config);\n expect(logSpy).not.toHaveBeenCalled();\n // Resolve the request so nothing stays pending.\n instances[0].onmessage({\n data: {type: 'pivot:result', id: 1, result: {rowKeys: [], colKeys: []}},\n });\n return promise;\n });\n\n it('logs the whole worker pipeline when debug is enabled', function() {\n const client = loadClient();\n client.setWorkerDebug(true);\n\n const promise = client.computePivotInWorker(records, 'data-1', config);\n\n expect(loggedText()).toEqual(\n expect.arrayContaining([\n expect.stringContaining('debug logging enabled'),\n expect.stringContaining('worker created: pivot-worker.js'),\n expect.stringContaining('#1 dispatching to worker'),\n expect.stringContaining('staging 2 records'),\n ])\n );\n\n // Staging + compute messages are sent (staging only once per dataKey).\n const types = instances[0].posted.map(message => message.type);\n expect(types).toEqual(['pivot:debug', 'pivot:setData', 'pivot:compute']);\n const staged = instances[0].posted.find(m => m.type === 'pivot:setData');\n expect(staged.data).toBe(records);\n expect(staged.dataKey).toBe('data-1');\n\n const worker = instances[0];\n // Progress percentages were removed: legacy `pivot:progress` messages\n // from an older worker bundle must be ignored without corrupting the\n // request (the result still resolves afterwards).\n worker.onmessage({\n data: {\n type: 'pivot:progress',\n id: 1,\n processed: 2,\n total: 2,\n phase: 'materialize',\n },\n });\n expect(loggedText()).not.toEqual(\n expect.arrayContaining([expect.stringContaining('progress')])\n );\n\n // Debug logs forwarded from inside the worker thread.\n worker.onmessage({data: {type: 'pivot:log', message: 'computed in 5ms'}});\n expect(loggedText()).toEqual(\n expect.arrayContaining([\n expect.stringContaining('(in worker) computed in 5ms'),\n ])\n );\n\n worker.onmessage({\n data: {\n type: 'pivot:result',\n id: 1,\n result: {\n totalRecords: 2,\n rowKeys: [['Nick']],\n colKeys: [],\n aggregations: [],\n },\n },\n });\n return promise.then(result => {\n expect(result.totalRecords).toBe(2);\n expect(loggedText()).toEqual(\n expect.arrayContaining([\n expect.stringContaining('#1 result received in'),\n ])\n );\n });\n });\n\n it('logs the fallback to a synchronous computation', function() {\n const client = loadClient();\n client.setWorkerDebug(true);\n\n const promise = client.computePivotWithFallback(records, 'data-2', config);\n\n // Simulate a worker that fails to load before producing any result.\n instances[0].onerror(new Error('404'));\n\n return promise.then(result => {\n expect(result.totalRecords).toBe(2);\n expect(loggedText()).toEqual(\n expect.arrayContaining([\n expect.stringContaining('worker error event'),\n expect.stringContaining('falling back to the main thread'),\n expect.stringContaining('running synchronous computation'),\n expect.stringContaining('synchronous computation finished in'),\n ])\n );\n });\n });\n\n it('stops logging when debug is switched off again', function() {\n const client = loadClient();\n client.setWorkerDebug(true);\n logSpy.mockClear();\n client.setWorkerDebug(false);\n expect(loggedText()).toEqual(\n expect.arrayContaining([\n expect.stringContaining('debug logging disabled'),\n ])\n );\n logSpy.mockClear();\n client.setWorkerDebug(false);\n expect(logSpy).not.toHaveBeenCalled();\n });\n});\n"]}
1
+ {"version":3,"sources":["../../src/__tests__/PivotDataWorker-test.js"],"names":["describe","records","name","gender","config","rows","cols","aggregations","key","aggregatorName","vals","instances","logSpy","FakeWorker","url","posted","onmessage","onerror","push","message","terminated","loggedText","mock","calls","map","call","filter","String","arg","startsWith","join","loadClient","jest","resetModules","require","beforeEach","global","Worker","spyOn","console","mockImplementation","afterEach","mockRestore","it","client","promise","computePivotInWorker","expect","not","toHaveBeenCalled","data","type","id","result","rowKeys","colKeys","setWorkerDebug","toEqual","arrayContaining","stringContaining","types","staged","find","m","toBe","dataKey","worker","processed","total","phase","totalRecords","then","computePivotWithFallback","Error","error","largeRecords","Array","fill","_","index","Promise","setTimeout","resolve","toHaveLength","slice","computePivotViewportInWorker","viewportKey","start","end","columnMode","columnStart","columnEnd","displayKey","firstPromise","catch","secondPromise","firstError","code","resolves","attrValues","Nick","releaseDatasetInWorker","retainPivotWorker","releasePivotWorker","ownerKey","originalAddEventListener","self","addEventListener","originalPostMessage","postMessage","onMessage","listener","computed","viewport","totalRows","department","Object","assign","virtualizeRows","rendererName","virtualized","tree","cells","toBeDefined","rowTotal","releasedDatasetError","toContain","wideRecords","employee","padStart","totalColumns","colTotals","keys","length","toBeLessThanOrEqual","mockClear"],"mappings":"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","file":"PivotDataWorker-test.js","sourcesContent":["/* eslint-disable no-magic-numbers */\n/*\n * Tests the main-thread worker client, including the debug logging that the\n * `workerDebug` prop of PivotTableUI switches on.\n */\ndescribe(' PivotDataWorker', function() {\n const records = [\n {name: 'Nick', gender: 'male'},\n {name: 'Jane', gender: 'female'},\n ];\n const config = {\n rows: ['name'],\n cols: [],\n aggregations: [{key: 'count', aggregatorName: 'Count', vals: []}],\n };\n\n let instances;\n let logSpy;\n\n class FakeWorker {\n constructor(url) {\n this.url = url;\n this.posted = [];\n this.onmessage = null;\n this.onerror = null;\n instances.push(this);\n }\n\n postMessage(message) {\n this.posted.push(message);\n }\n\n terminate() {\n this.terminated = true;\n }\n }\n\n // console.log('%c[pivottable worker]', 'style', ...) -> strip the format\n // directive and its style argument to assert on the message itself.\n const loggedText = () =>\n logSpy.mock.calls.map(call =>\n call\n .filter(\n arg =>\n !String(arg).startsWith('%c') && !String(arg).startsWith('color:')\n )\n .join(' ')\n );\n\n const loadClient = () => {\n jest.resetModules();\n return require('../PivotDataWorker');\n };\n\n beforeEach(function() {\n instances = [];\n global.Worker = FakeWorker;\n logSpy = jest.spyOn(console, 'log').mockImplementation(() => {});\n });\n\n afterEach(function() {\n logSpy.mockRestore();\n });\n\n it('is silent by default', function() {\n const client = loadClient();\n const promise = client.computePivotInWorker(records, 'data-1', config);\n expect(logSpy).not.toHaveBeenCalled();\n // Resolve the request so nothing stays pending.\n instances[0].onmessage({\n data: {type: 'pivot:result', id: 1, result: {rowKeys: [], colKeys: []}},\n });\n return promise;\n });\n\n it('logs the whole worker pipeline when debug is enabled', function() {\n const client = loadClient();\n client.setWorkerDebug(true);\n\n const promise = client.computePivotInWorker(records, 'data-1', config);\n\n expect(loggedText()).toEqual(\n expect.arrayContaining([\n expect.stringContaining('debug logging enabled'),\n expect.stringContaining('worker created: pivot-worker.js'),\n expect.stringContaining('#1 dispatching to worker'),\n expect.stringContaining('staging 2 records'),\n ])\n );\n\n // Staging + compute messages are sent (staging only once per dataKey).\n const types = instances[0].posted.map(message => message.type);\n expect(types).toEqual(['pivot:debug', 'pivot:setData', 'pivot:compute']);\n const staged = instances[0].posted.find(m => m.type === 'pivot:setData');\n expect(staged.data).toBe(records);\n expect(staged.dataKey).toBe('data-1');\n\n const worker = instances[0];\n // Progress percentages were removed: legacy `pivot:progress` messages\n // from an older worker bundle must be ignored without corrupting the\n // request (the result still resolves afterwards).\n worker.onmessage({\n data: {\n type: 'pivot:progress',\n id: 1,\n processed: 2,\n total: 2,\n phase: 'materialize',\n },\n });\n expect(loggedText()).not.toEqual(\n expect.arrayContaining([expect.stringContaining('progress')])\n );\n\n // Debug logs forwarded from inside the worker thread.\n worker.onmessage({data: {type: 'pivot:log', message: 'computed in 5ms'}});\n expect(loggedText()).toEqual(\n expect.arrayContaining([\n expect.stringContaining('(in worker) computed in 5ms'),\n ])\n );\n\n worker.onmessage({\n data: {\n type: 'pivot:result',\n id: 1,\n result: {\n totalRecords: 2,\n rowKeys: [['Nick']],\n colKeys: [],\n aggregations: [],\n },\n },\n });\n return promise.then(result => {\n expect(result.totalRecords).toBe(2);\n expect(loggedText()).toEqual(\n expect.arrayContaining([\n expect.stringContaining('#1 result received in'),\n ])\n );\n });\n });\n\n it('surfaces worker failures without a synchronous fallback', async function() {\n const client = loadClient();\n client.setWorkerDebug(true);\n\n const promise = client.computePivotWithFallback(records, 'data-2', config);\n\n // Simulate a worker that fails to load before producing any result.\n instances[0].onerror(new Error('404'));\n\n await promise.then(\n () => {\n throw new Error('Worker request unexpectedly succeeded');\n },\n error => {\n expect(error.message).toBe('Pivot worker failed to load');\n }\n );\n expect(loggedText()).toEqual(\n expect.arrayContaining([\n expect.stringContaining('worker error event'),\n expect.stringContaining('synchronous fallback disabled'),\n ])\n );\n expect(loggedText()).not.toEqual(\n expect.arrayContaining([\n expect.stringContaining('running synchronous computation'),\n ])\n );\n });\n\n it('stages large datasets in chunks before computing', function() {\n const client = loadClient();\n const largeRecords = new Array(1200).fill(null).map((_, index) => ({\n name: `Employee ${index}`,\n }));\n const promise = client.computePivotInWorker(\n largeRecords,\n 'large-data',\n config\n );\n const worker = instances[0];\n\n expect(worker.posted.map(message => message.type)).toEqual([\n 'pivot:setDataStart',\n 'pivot:setDataChunk',\n ]);\n\n return new Promise(resolve => setTimeout(resolve, 20))\n .then(() => {\n const types = worker.posted.map(message => message.type);\n expect(\n types.filter(type => type === 'pivot:setDataChunk')\n ).toHaveLength(3);\n expect(types.slice(-2)).toEqual(['pivot:setDataEnd', 'pivot:compute']);\n worker.onmessage({\n data: {\n type: 'pivot:result',\n id: 1,\n result: {rowKeys: [], colKeys: []},\n },\n });\n return promise;\n })\n .then(result => {\n expect(result.rowKeys).toEqual([]);\n });\n });\n\n it('requests a viewport without sending the dataset again', function() {\n const client = loadClient();\n const promise = client.computePivotViewportInWorker(\n 42,\n 64,\n 128,\n false,\n 16,\n 48\n );\n const worker = instances[0];\n expect(worker.posted).toEqual([\n {\n type: 'pivot:viewport',\n id: 1,\n viewportKey: 42,\n start: 64,\n end: 128,\n columnMode: false,\n columnStart: 16,\n columnEnd: 48,\n },\n ]);\n worker.onmessage({\n data: {\n type: 'pivot:viewportResult',\n id: 1,\n result: {start: 64, end: 128, rows: [{displayKey: ['A']}]},\n },\n });\n return promise.then(result => {\n expect(result.rows).toEqual([{displayKey: ['A']}]);\n });\n });\n\n it('releases a replaced viewport request immediately', async function() {\n const client = loadClient();\n const firstPromise = client\n .computePivotViewportInWorker(42, 0, 64, false)\n .catch(error => error);\n const secondPromise = client.computePivotViewportInWorker(\n 42,\n 64,\n 128,\n false\n );\n const worker = instances[0];\n\n const firstError = await firstPromise;\n expect(firstError.code).toBe('PIVOT_VIEWPORT_CANCELLED');\n expect(\n worker.posted.filter(message => message.type === 'pivot:viewport')\n ).toHaveLength(2);\n\n worker.onmessage({\n data: {\n type: 'pivot:viewportResult',\n id: 2,\n result: {start: 64, end: 128, rows: []},\n },\n });\n await expect(secondPromise).resolves.toEqual({\n start: 64,\n end: 128,\n rows: [],\n });\n });\n\n it('releases the staged dataset and stages it again for the next compute', async function() {\n const client = loadClient();\n const firstPromise = client.computePivotInWorker(\n records,\n 'reusable-data',\n config\n );\n const worker = instances[0];\n worker.onmessage({\n data: {\n type: 'pivot:result',\n id: 1,\n result: {rowKeys: [], colKeys: [], attrValues: {name: {Nick: 1}}},\n },\n });\n await firstPromise;\n\n client.releaseDatasetInWorker('reusable-data');\n const secondPromise = client.computePivotInWorker(\n records,\n 'reusable-data',\n config\n );\n expect(worker.posted.map(message => message.type)).toEqual([\n 'pivot:setData',\n 'pivot:compute',\n 'pivot:releaseData',\n 'pivot:setData',\n 'pivot:compute',\n ]);\n worker.onmessage({\n data: {\n type: 'pivot:result',\n id: 2,\n result: {rowKeys: [], colKeys: []},\n },\n });\n await secondPromise;\n });\n\n it('terminates the shared worker after the last table owner unmounts', async function() {\n const client = loadClient();\n client.retainPivotWorker('table-a');\n client.retainPivotWorker('table-b');\n const promise = client.computePivotInWorker(\n records,\n 'owned-data',\n config,\n 'table-a'\n );\n const worker = instances[0];\n worker.onmessage({\n data: {\n type: 'pivot:result',\n id: 1,\n result: {rowKeys: [], colKeys: []},\n },\n });\n await promise;\n\n client.releasePivotWorker('table-a');\n expect(worker.terminated).not.toBe(true);\n client.releasePivotWorker('table-b');\n expect(worker.terminated).toBe(true);\n expect(worker.posted.slice(-2)).toEqual([\n {type: 'pivot:releaseOwner', ownerKey: 'table-a'},\n {type: 'pivot:releaseOwner', ownerKey: 'table-b'},\n ]);\n });\n\n it('caches a computed pivot and returns only requested rows', function() {\n const originalAddEventListener = self.addEventListener;\n const originalPostMessage = self.postMessage;\n const posted = [];\n let onMessage;\n self.addEventListener = (type, listener) => {\n if (type === 'message') {\n onMessage = listener;\n }\n };\n self.postMessage = message => posted.push(message);\n\n try {\n jest.resetModules();\n require('../pivotWorker');\n onMessage({\n data: {type: 'pivot:setData', id: 1, dataKey: 'x', data: records},\n });\n onMessage({data: {type: 'pivot:compute', id: 1, dataKey: 'x', config}});\n const computed = posted.find(message => message.type === 'pivot:result');\n expect(computed.result.viewportKey).toBe(1);\n\n onMessage({\n data: {\n type: 'pivot:viewport',\n id: 2,\n viewportKey: 1,\n start: 1,\n end: 2,\n columnMode: false,\n },\n });\n const viewport = posted.find(\n message => message.type === 'pivot:viewportResult'\n );\n expect(viewport.result.rows).toHaveLength(1);\n expect(viewport.result.rows[0].displayKey).toEqual(['Nick']);\n expect(viewport.result.totalRows).toBe(2);\n } finally {\n self.addEventListener = originalAddEventListener;\n self.postMessage = originalPostMessage;\n }\n });\n\n it('returns a compact result and viewport cell values for virtual tables', function() {\n const originalAddEventListener = self.addEventListener;\n const originalPostMessage = self.postMessage;\n const posted = [];\n let onMessage;\n self.addEventListener = (type, listener) => {\n if (type === 'message') {\n onMessage = listener;\n }\n };\n self.postMessage = message => posted.push(message);\n const largeRecords = new Array(400).fill(null).map((_, index) => ({\n name: `Employee ${index}`,\n department: `Department ${index % 3}`,\n }));\n\n try {\n jest.resetModules();\n require('../pivotWorker');\n onMessage({\n data: {\n type: 'pivot:setData',\n id: 1,\n dataKey: 'virtual-data',\n data: largeRecords,\n },\n });\n onMessage({\n data: {\n type: 'pivot:compute',\n id: 1,\n dataKey: 'virtual-data',\n config: Object.assign({}, config, {\n cols: ['department'],\n virtualizeRows: true,\n rendererName: 'Table',\n }),\n },\n });\n const computed = posted.find(message => message.type === 'pivot:result');\n expect(computed.result.virtualized).toBe(true);\n expect(computed.result.totalRows).toBe(400);\n expect(computed.result.rowKeys).toEqual([]);\n expect(computed.result.tree).toEqual({});\n\n onMessage({\n data: {type: 'pivot:releaseData', dataKey: 'virtual-data'},\n });\n\n onMessage({\n data: {\n type: 'pivot:viewport',\n id: 2,\n viewportKey: 1,\n start: 32,\n end: 64,\n columnMode: false,\n },\n });\n const viewport = posted.find(\n message => message.type === 'pivot:viewportResult'\n );\n expect(viewport.result.rows).toHaveLength(32);\n expect(viewport.result.rows[0].cells).toBeDefined();\n expect(viewport.result.rows[0].rowTotal[0]).toBe(1);\n\n onMessage({\n data: {\n type: 'pivot:compute',\n id: 3,\n dataKey: 'virtual-data',\n config,\n },\n });\n const releasedDatasetError = posted.find(\n message => message.type === 'pivot:error' && message.id === 3\n );\n expect(releasedDatasetError.message).toContain('no dataset staged');\n } finally {\n self.addEventListener = originalAddEventListener;\n self.postMessage = originalPostMessage;\n }\n });\n\n it('uses a compact result when columns are wide but rows are short', function() {\n const originalAddEventListener = self.addEventListener;\n const originalPostMessage = self.postMessage;\n const posted = [];\n let onMessage;\n self.addEventListener = (type, listener) => {\n if (type === 'message') {\n onMessage = listener;\n }\n };\n self.postMessage = message => posted.push(message);\n const wideRecords = new Array(150).fill(null).map((_, index) => ({\n employee: `Employee ${String(index).padStart(3, '0')}`,\n gender: index % 2 === 0 ? 'female' : 'male',\n }));\n\n try {\n jest.resetModules();\n require('../pivotWorker');\n onMessage({\n data: {\n type: 'pivot:setData',\n id: 1,\n dataKey: 'wide-data',\n data: wideRecords,\n },\n });\n onMessage({\n data: {\n type: 'pivot:compute',\n id: 1,\n dataKey: 'wide-data',\n config: Object.assign({}, config, {\n rows: ['gender'],\n cols: ['employee'],\n virtualizeRows: true,\n rendererName: 'Table',\n }),\n },\n });\n const computed = posted.find(message => message.type === 'pivot:result');\n expect(computed.result.virtualized).toBe(true);\n expect(computed.result.totalRows).toBe(2);\n expect(computed.result.totalColumns).toBe(150);\n expect(computed.result.tree).toEqual({});\n expect(computed.result.colTotals).toEqual({});\n\n onMessage({\n data: {\n type: 'pivot:viewport',\n id: 2,\n viewportKey: 1,\n start: 0,\n end: 2,\n columnMode: false,\n columnStart: 32,\n columnEnd: 48,\n },\n });\n const viewport = posted.find(\n message => message.type === 'pivot:viewportResult'\n );\n expect(viewport.result.rows).toHaveLength(2);\n expect(\n Object.keys(viewport.result.rows[0].cells).length\n ).toBeLessThanOrEqual(16);\n expect(Object.keys(viewport.result.colTotals)).toHaveLength(16);\n } finally {\n self.addEventListener = originalAddEventListener;\n self.postMessage = originalPostMessage;\n }\n });\n\n it('stops logging when debug is switched off again', function() {\n const client = loadClient();\n client.setWorkerDebug(true);\n logSpy.mockClear();\n client.setWorkerDebug(false);\n expect(loggedText()).toEqual(\n expect.arrayContaining([\n expect.stringContaining('debug logging disabled'),\n ])\n );\n logSpy.mockClear();\n client.setWorkerDebug(false);\n expect(logSpy).not.toHaveBeenCalled();\n });\n});\n"]}
@@ -79,6 +79,44 @@ describe(' PivotTableUI showProcessing', function () {
79
79
  expect(node.querySelector('.pvtTable')).not.toBeNull();
80
80
  });
81
81
 
82
+ it('does not pass undefined attrValues while the worker is pending', function () {
83
+ var originalWorker = global.Worker;
84
+ var errorSpy = jest.spyOn(console, 'error').mockImplementation(function () {});
85
+ global.Worker = function () {
86
+ function PendingWorker() {
87
+ _classCallCheck(this, PendingWorker);
88
+ }
89
+
90
+ _createClass(PendingWorker, [{
91
+ key: 'postMessage',
92
+ value: function postMessage() {}
93
+ }, {
94
+ key: 'terminate',
95
+ value: function terminate() {}
96
+ }]);
97
+
98
+ return PendingWorker;
99
+ }();
100
+ try {
101
+ mount(Object.assign({}, baseProps, {
102
+ data: new Array(201).fill(null).map(function (_, index) {
103
+ return {
104
+ name: 'Employee ' + index
105
+ };
106
+ })
107
+ }));
108
+ var warnings = errorSpy.mock.calls.map(function (call) {
109
+ return call.join(' ');
110
+ }).filter(function (message) {
111
+ return message.includes('attrValues');
112
+ });
113
+ expect(warnings).toEqual([]);
114
+ } finally {
115
+ global.Worker = originalWorker;
116
+ errorSpy.mockRestore();
117
+ }
118
+ });
119
+
82
120
  it('renders the overlay on top of the table when showProcessing is true', function () {
83
121
  var _mount2 = mount(baseProps),
84
122
  node = _mount2.node,
@@ -93,12 +131,13 @@ describe(' PivotTableUI showProcessing', function () {
93
131
 
94
132
  var overlay = node.querySelector('.pvtLoadingOverlay');
95
133
  expect(overlay).not.toBeNull();
134
+ expect(overlay.parentElement.classList.contains('pvtOutput')).toBe(true);
96
135
  // The overlay is layered on top of the table: the table must survive.
97
136
  expect(node.querySelector('.pvtTable')).not.toBeNull();
98
137
  // Only a spinner and a label: progress percentages were removed, the
99
138
  // overlay simply stays until the worker posts its result event.
100
139
  expect(overlay.querySelector('.pvtLoadingSpinner')).not.toBeNull();
101
- expect(overlay.querySelector('.pvtLoadingText').textContent).toBe('Processing…');
140
+ expect(overlay.querySelector('.pvtLoadingText').textContent).toBe('Processing');
102
141
  expect(overlay.querySelector('.pvtLoadingBar')).toBeNull();
103
142
  expect(overlay.querySelector('.pvtLoadingPercent')).toBeNull();
104
143
 
@@ -116,7 +155,7 @@ describe(' PivotTableUI showProcessing', function () {
116
155
  expect(node.querySelector('.pvtLoadingSpinner')).not.toBeNull();
117
156
  expect(node.querySelector('.pvtLoadingBarWrap')).toBeNull();
118
157
  expect(node.querySelector('.pvtLoadingPercent')).toBeNull();
119
- expect(node.querySelector('.pvtLoadingText').textContent).toBe('Processing…');
158
+ expect(node.querySelector('.pvtLoadingText').textContent).toBe('Processing');
120
159
  });
121
160
 
122
161
  it('hides the overlay only after the worker responds and the table renders', function () {