浏览代码

Merge pull request #8278 from blink1073/modernize-csvviewer-7

Modernize CSVViewer Tests
Steven Silvester 5 年之前
父节点
当前提交
4e7b446066

+ 0 - 1
dev_mode/package.json

@@ -371,7 +371,6 @@
       "@jupyterlab/test-codemirror": "../tests/test-codemirror",
       "@jupyterlab/test-completer": "../tests/test-completer",
       "@jupyterlab/test-coreutils": "../tests/test-coreutils",
-      "@jupyterlab/test-csvviewer": "../tests/test-csvviewer",
       "@jupyterlab/test-docregistry": "../tests/test-docregistry",
       "@jupyterlab/test-fileeditor": "../tests/test-fileeditor",
       "@jupyterlab/test-imageviewer": "../tests/test-imageviewer",

+ 11 - 0
packages/csvviewer/.vscode/launch.json

@@ -0,0 +1,11 @@
+{
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "type": "node",
+            "request": "attach",
+            "name": "Attach",
+            "port": 9229
+        }
+    ]
+}

+ 1 - 0
packages/csvviewer/babel.config.js

@@ -0,0 +1 @@
+module.exports = require('@jupyterlab/testutils/lib/babel.config');

+ 2 - 0
packages/csvviewer/jest.config.js

@@ -0,0 +1,2 @@
+const func = require('@jupyterlab/testutils/lib/jest-config-new');
+module.exports = func(__dirname);

+ 11 - 0
packages/csvviewer/package.json

@@ -29,9 +29,14 @@
   },
   "scripts": {
     "build": "tsc -b",
+    "build:test": "tsc --build tsconfig.test.json",
     "clean": "rimraf lib",
     "docs": "typedoc src",
     "prepublishOnly": "npm run build",
+    "test": "jest",
+    "test:cov": "jest --collect-coverage",
+    "test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
+    "test:debug:watch": "node --inspect-brk node_modules/.bin/jest --runInBand --watch",
     "watch": "tsc -b --watch"
   },
   "dependencies": {
@@ -47,7 +52,13 @@
     "@lumino/widgets": "^1.11.1"
   },
   "devDependencies": {
+    "@jupyterlab/testutils": "^2.1.0",
+    "@types/jest": "^24.0.23",
+    "canvas": "^2.6.1",
+    "csv-spectrum": "^1.0.0",
+    "jest": "^25.2.3",
     "rimraf": "~3.0.0",
+    "ts-jest": "^25.2.1",
     "typedoc": "^0.15.4",
     "typescript": "~3.7.3"
   },

+ 2 - 0
tests/test-csvviewer/src/data.csv.ts → packages/csvviewer/test/data.csv.ts

@@ -1,4 +1,6 @@
 // Copyright (c) Jupyter Development Team.
+
+import 'jest';
 // Distributed under the terms of the Modified BSD License.
 
 /**

+ 106 - 146
tests/test-csvviewer/src/model.spec.ts → packages/csvviewer/test/model.spec.ts

@@ -1,75 +1,81 @@
 // Copyright (c) Jupyter Development Team.
-// Distributed under the terms of the Modified BSD License.
 
-import { expect } from 'chai';
+import 'jest';
 
-import { DSVModel } from '@jupyterlab/csvviewer';
+const fs = require('fs');
+
+import { DSVModel } from '../src';
+
+function readCSV(path: string): any {
+  path = require.resolve(path);
+  return fs.readFileSync(path, 'utf8');
+}
 
 /* tslint:disable:no-var-requires */
 const CSV_TEST_FILES = [
   [
     'comma_in_quotes',
-    require('csv-spectrum/csvs/comma_in_quotes.csv').default,
+    readCSV('csv-spectrum/csvs/comma_in_quotes.csv'),
     require('csv-spectrum/json/comma_in_quotes.json')
   ],
 
   [
     'empty',
-    require('csv-spectrum/csvs/empty.csv').default,
+    readCSV('csv-spectrum/csvs/empty.csv'),
     require('csv-spectrum/json/empty.json')
   ],
 
   [
     'empty_crlf',
-    require('csv-spectrum/csvs/empty_crlf.csv').default,
+    readCSV('csv-spectrum/csvs/empty_crlf.csv'),
     require('csv-spectrum/json/empty_crlf.json')
   ],
 
   [
     'escaped_quotes',
-    require('csv-spectrum/csvs/escaped_quotes.csv').default,
+    readCSV('csv-spectrum/csvs/escaped_quotes.csv'),
     require('csv-spectrum/json/escaped_quotes.json')
   ],
 
   [
     'json',
-    require('csv-spectrum/csvs/json.csv').default,
+    readCSV('csv-spectrum/csvs/json.csv'),
     require('csv-spectrum/json/json.json')
   ],
 
   [
     'newlines',
-    require('csv-spectrum/csvs/newlines.csv').default,
+    readCSV('csv-spectrum/csvs/newlines.csv'),
     require('csv-spectrum/json/newlines.json')
   ],
 
   [
     'newlines_crlf',
-    require('csv-spectrum/csvs/newlines_crlf.csv').default,
+    readCSV('csv-spectrum/csvs/newlines_crlf.csv'),
     require('csv-spectrum/json/newlines_crlf.json')
   ],
 
   [
     'quotes_and_newlines',
-    require('csv-spectrum/csvs/quotes_and_newlines.csv').default,
+    readCSV('csv-spectrum/csvs/quotes_and_newlines.csv'),
     require('csv-spectrum/json/quotes_and_newlines.json')
   ],
 
   [
     'simple',
-    require('csv-spectrum/csvs/simple.csv').default,
+    readCSV('csv-spectrum/csvs/simple.csv'),
     require('csv-spectrum/json/simple.json')
   ],
 
   [
     'simple_crlf',
-    require('csv-spectrum/csvs/simple_crlf.csv').default,
+    readCSV('csv-spectrum/csvs/simple_crlf.csv'),
     require('csv-spectrum/json/simple_crlf.json')
   ],
 
   [
     'utf8',
-    require('csv-spectrum/csvs/utf8.csv').default,
+    readCSV('csv-spectrum/csvs/utf8.csv'),
     require('csv-spectrum/json/utf8.json')
   ]
 ];
@@ -80,14 +86,16 @@ describe('csvviewer/model', () => {
     describe('#constructor()', () => {
       it('should instantiate a `DSVModel`', () => {
         const d = new DSVModel({ data: 'a,b,c\nd,e,f\n', delimiter: ',' });
-        expect(d.rowCount('column-header')).to.equal(1);
-        expect(d.rowCount('body')).to.equal(1);
-        expect(d.columnCount('row-header')).to.equal(1);
-        expect(d.columnCount('body')).to.equal(3);
-        expect(
-          [0, 1, 2].map(i => d.data('column-header', 0, i))
-        ).to.deep.equal(['a', 'b', 'c']);
-        expect([0, 1, 2].map(i => d.data('body', 0, i))).to.deep.equal([
+        expect(d.rowCount('column-header')).toBe(1);
+        expect(d.rowCount('body')).toBe(1);
+        expect(d.columnCount('row-header')).toBe(1);
+        expect(d.columnCount('body')).toBe(3);
+        expect([0, 1, 2].map(i => d.data('column-header', 0, i))).toEqual([
+          'a',
+          'b',
+          'c'
+        ]);
+        expect([0, 1, 2].map(i => d.data('body', 0, i))).toEqual([
           'd',
           'e',
           'f'
@@ -110,26 +118,22 @@ describe('csvviewer/model', () => {
           }
           values.push(row);
         }
-        expect(values).to.deep.equal(answer);
+        expect(values).toEqual(answer);
       }
     });
 
     it('handles tab-separated data', () => {
       const d = new DSVModel({ data: 'a\tb\tc\nd\te\tf\n', delimiter: '\t' });
-      expect(d.rowCount('column-header')).to.equal(1);
-      expect(d.rowCount('body')).to.equal(1);
-      expect(d.columnCount('row-header')).to.equal(1);
-      expect(d.columnCount('body')).to.equal(3);
-      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).to.deep.equal([
+      expect(d.rowCount('column-header')).toBe(1);
+      expect(d.rowCount('body')).toBe(1);
+      expect(d.columnCount('row-header')).toBe(1);
+      expect(d.columnCount('body')).toBe(3);
+      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).toEqual([
         'a',
         'b',
         'c'
       ]);
-      expect([0, 1, 2].map(i => d.data('body', 0, i))).to.deep.equal([
-        'd',
-        'e',
-        'f'
-      ]);
+      expect([0, 1, 2].map(i => d.data('body', 0, i))).toEqual(['d', 'e', 'f']);
     });
 
     it('handles not having a header', () => {
@@ -138,34 +142,26 @@ describe('csvviewer/model', () => {
         delimiter: ',',
         header: false
       });
-      expect(d.rowCount('column-header')).to.equal(1);
-      expect(d.rowCount('body')).to.equal(2);
-      expect(d.columnCount('row-header')).to.equal(1);
-      expect(d.columnCount('body')).to.equal(3);
-      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).to.deep.equal([
+      expect(d.rowCount('column-header')).toBe(1);
+      expect(d.rowCount('body')).toBe(2);
+      expect(d.columnCount('row-header')).toBe(1);
+      expect(d.columnCount('body')).toBe(3);
+      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).toEqual([
         '1',
         '2',
         '3'
       ]);
-      expect([0, 1, 2].map(i => d.data('body', 0, i))).to.deep.equal([
-        'a',
-        'b',
-        'c'
-      ]);
-      expect([0, 1, 2].map(i => d.data('body', 1, i))).to.deep.equal([
-        'd',
-        'e',
-        'f'
-      ]);
+      expect([0, 1, 2].map(i => d.data('body', 0, i))).toEqual(['a', 'b', 'c']);
+      expect([0, 1, 2].map(i => d.data('body', 1, i))).toEqual(['d', 'e', 'f']);
     });
 
     it('handles having only a header', () => {
       const d = new DSVModel({ data: 'a,b,c\n', delimiter: ',', header: true });
-      expect(d.rowCount('column-header')).to.equal(1);
-      expect(d.rowCount('body')).to.equal(0);
-      expect(d.columnCount('row-header')).to.equal(1);
-      expect(d.columnCount('body')).to.equal(3);
-      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).to.deep.equal([
+      expect(d.rowCount('column-header')).toBe(1);
+      expect(d.rowCount('body')).toBe(0);
+      expect(d.columnCount('row-header')).toBe(1);
+      expect(d.columnCount('body')).toBe(3);
+      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).toEqual([
         'a',
         'b',
         'c'
@@ -178,20 +174,16 @@ describe('csvviewer/model', () => {
         delimiter: ',',
         header: false
       });
-      expect(d.rowCount('column-header')).to.equal(1);
-      expect(d.rowCount('body')).to.equal(1);
-      expect(d.columnCount('row-header')).to.equal(1);
-      expect(d.columnCount('body')).to.equal(3);
-      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).to.deep.equal([
+      expect(d.rowCount('column-header')).toBe(1);
+      expect(d.rowCount('body')).toBe(1);
+      expect(d.columnCount('row-header')).toBe(1);
+      expect(d.columnCount('body')).toBe(3);
+      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).toEqual([
         '1',
         '2',
         '3'
       ]);
-      expect([0, 1, 2].map(i => d.data('body', 0, i))).to.deep.equal([
-        'a',
-        'b',
-        'c'
-      ]);
+      expect([0, 1, 2].map(i => d.data('body', 0, i))).toEqual(['a', 'b', 'c']);
     });
 
     it('handles CRLF row delimiter', () => {
@@ -200,20 +192,16 @@ describe('csvviewer/model', () => {
         delimiter: ',',
         rowDelimiter: '\r\n'
       });
-      expect(d.rowCount('column-header')).to.equal(1);
-      expect(d.rowCount('body')).to.equal(1);
-      expect(d.columnCount('row-header')).to.equal(1);
-      expect(d.columnCount('body')).to.equal(3);
-      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).to.deep.equal([
+      expect(d.rowCount('column-header')).toBe(1);
+      expect(d.rowCount('body')).toBe(1);
+      expect(d.columnCount('row-header')).toBe(1);
+      expect(d.columnCount('body')).toBe(3);
+      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).toEqual([
         'a',
         'b',
         'c'
       ]);
-      expect([0, 1, 2].map(i => d.data('body', 0, i))).to.deep.equal([
-        'd',
-        'e',
-        'f'
-      ]);
+      expect([0, 1, 2].map(i => d.data('body', 0, i))).toEqual(['d', 'e', 'f']);
     });
 
     it('handles CR row delimiter', () => {
@@ -222,38 +210,30 @@ describe('csvviewer/model', () => {
         delimiter: ',',
         rowDelimiter: '\r'
       });
-      expect(d.rowCount('column-header')).to.equal(1);
-      expect(d.rowCount('body')).to.equal(1);
-      expect(d.columnCount('row-header')).to.equal(1);
-      expect(d.columnCount('body')).to.equal(3);
-      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).to.deep.equal([
+      expect(d.rowCount('column-header')).toBe(1);
+      expect(d.rowCount('body')).toBe(1);
+      expect(d.columnCount('row-header')).toBe(1);
+      expect(d.columnCount('body')).toBe(3);
+      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).toEqual([
         'a',
         'b',
         'c'
       ]);
-      expect([0, 1, 2].map(i => d.data('body', 0, i))).to.deep.equal([
-        'd',
-        'e',
-        'f'
-      ]);
+      expect([0, 1, 2].map(i => d.data('body', 0, i))).toEqual(['d', 'e', 'f']);
     });
 
     it('can guess the row delimiter', () => {
       const d = new DSVModel({ data: 'a,b,c\rd,e,f\r', delimiter: ',' });
-      expect(d.rowCount('column-header')).to.equal(1);
-      expect(d.rowCount('body')).to.equal(1);
-      expect(d.columnCount('row-header')).to.equal(1);
-      expect(d.columnCount('body')).to.equal(3);
-      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).to.deep.equal([
+      expect(d.rowCount('column-header')).toBe(1);
+      expect(d.rowCount('body')).toBe(1);
+      expect(d.columnCount('row-header')).toBe(1);
+      expect(d.columnCount('body')).toBe(3);
+      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).toEqual([
         'a',
         'b',
         'c'
       ]);
-      expect([0, 1, 2].map(i => d.data('body', 0, i))).to.deep.equal([
-        'd',
-        'e',
-        'f'
-      ]);
+      expect([0, 1, 2].map(i => d.data('body', 0, i))).toEqual(['d', 'e', 'f']);
     });
 
     it('handles a given quote character', () => {
@@ -262,20 +242,16 @@ describe('csvviewer/model', () => {
         delimiter: ',',
         quote: `'`
       });
-      expect(d.rowCount('column-header')).to.equal(1);
-      expect(d.rowCount('body')).to.equal(1);
-      expect(d.columnCount('row-header')).to.equal(1);
-      expect(d.columnCount('body')).to.equal(3);
-      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).to.deep.equal([
+      expect(d.rowCount('column-header')).toBe(1);
+      expect(d.rowCount('body')).toBe(1);
+      expect(d.columnCount('row-header')).toBe(1);
+      expect(d.columnCount('body')).toBe(3);
+      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).toEqual([
         'a',
         'b',
         'c'
       ]);
-      expect([0, 1, 2].map(i => d.data('body', 0, i))).to.deep.equal([
-        'd',
-        'e',
-        'f'
-      ]);
+      expect([0, 1, 2].map(i => d.data('body', 0, i))).toEqual(['d', 'e', 'f']);
     });
 
     it('handles delimiters and quotes inside quotes', () => {
@@ -285,16 +261,16 @@ describe('csvviewer/model', () => {
         quote: `'`,
         rowDelimiter: '\r'
       });
-      expect(d.rowCount('column-header')).to.equal(1);
-      expect(d.rowCount('body')).to.equal(1);
-      expect(d.columnCount('row-header')).to.equal(1);
-      expect(d.columnCount('body')).to.equal(3);
-      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).to.deep.equal([
+      expect(d.rowCount('column-header')).toBe(1);
+      expect(d.rowCount('body')).toBe(1);
+      expect(d.columnCount('row-header')).toBe(1);
+      expect(d.columnCount('body')).toBe(3);
+      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).toEqual([
         'a\rx',
         'b',
         `c'x`
       ]);
-      expect([0, 1, 2].map(i => d.data('body', 0, i))).to.deep.equal([
+      expect([0, 1, 2].map(i => d.data('body', 0, i))).toEqual([
         'd,x',
         'e',
         'f'
@@ -303,25 +279,21 @@ describe('csvviewer/model', () => {
 
     it('handles rows that are too short or too long', () => {
       const d = new DSVModel({ data: `a,b,c\n,c,d,e,f\ng,h`, delimiter: ',' });
-      expect(d.rowCount('column-header')).to.equal(1);
-      expect(d.rowCount('body')).to.equal(2);
-      expect(d.columnCount('row-header')).to.equal(1);
-      expect(d.columnCount('body')).to.equal(3);
-      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).to.deep.equal([
+      expect(d.rowCount('column-header')).toBe(1);
+      expect(d.rowCount('body')).toBe(2);
+      expect(d.columnCount('row-header')).toBe(1);
+      expect(d.columnCount('body')).toBe(3);
+      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).toEqual([
         'a',
         'b',
         'c'
       ]);
-      expect([0, 1, 2].map(i => d.data('body', 0, i))).to.deep.equal([
+      expect([0, 1, 2].map(i => d.data('body', 0, i))).toEqual([
         '',
         'c',
         'd,e,f'
       ]);
-      expect([0, 1, 2].map(i => d.data('body', 1, i))).to.deep.equal([
-        'g',
-        'h',
-        ''
-      ]);
+      expect([0, 1, 2].map(i => d.data('body', 1, i))).toEqual(['g', 'h', '']);
     });
 
     it('handles delayed parsing of rows past the initial rows', async () => {
@@ -330,18 +302,18 @@ describe('csvviewer/model', () => {
         delimiter: ',',
         initialRows: 2
       });
-      expect(d.rowCount('column-header')).to.equal(1);
-      expect(d.rowCount('body')).to.equal(1);
-      expect(d.columnCount('row-header')).to.equal(1);
-      expect(d.columnCount('body')).to.equal(3);
-      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).to.deep.equal([
+      expect(d.rowCount('column-header')).toBe(1);
+      expect(d.rowCount('body')).toBe(1);
+      expect(d.columnCount('row-header')).toBe(1);
+      expect(d.columnCount('body')).toBe(3);
+      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).toEqual([
         'a',
         'b',
         'c'
       ]);
 
       // Expected behavior is that all unparsed data is lumped into the final field.
-      expect([0, 1, 2].map(i => d.data('body', 0, i))).to.deep.equal([
+      expect([0, 1, 2].map(i => d.data('body', 0, i))).toEqual([
         'c',
         'd',
         'e\nf,g,h\ni,j,k'
@@ -349,30 +321,18 @@ describe('csvviewer/model', () => {
 
       // Check everything is in order after all the data has been parsed asynchronously.
       await d.ready;
-      expect(d.rowCount('column-header')).to.equal(1);
-      expect(d.rowCount('body')).to.equal(3);
-      expect(d.columnCount('row-header')).to.equal(1);
-      expect(d.columnCount('body')).to.equal(3);
-      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).to.deep.equal([
+      expect(d.rowCount('column-header')).toBe(1);
+      expect(d.rowCount('body')).toBe(3);
+      expect(d.columnCount('row-header')).toBe(1);
+      expect(d.columnCount('body')).toBe(3);
+      expect([0, 1, 2].map(i => d.data('column-header', 0, i))).toEqual([
         'a',
         'b',
         'c'
       ]);
-      expect([0, 1, 2].map(i => d.data('body', 0, i))).to.deep.equal([
-        'c',
-        'd',
-        'e'
-      ]);
-      expect([0, 1, 2].map(i => d.data('body', 1, i))).to.deep.equal([
-        'f',
-        'g',
-        'h'
-      ]);
-      expect([0, 1, 2].map(i => d.data('body', 2, i))).to.deep.equal([
-        'i',
-        'j',
-        'k'
-      ]);
+      expect([0, 1, 2].map(i => d.data('body', 0, i))).toEqual(['c', 'd', 'e']);
+      expect([0, 1, 2].map(i => d.data('body', 1, i))).toEqual(['f', 'g', 'h']);
+      expect([0, 1, 2].map(i => d.data('body', 2, i))).toEqual(['i', 'j', 'k']);
     });
   });
 });

+ 78 - 79
tests/test-csvviewer/src/parse-noquotes.spec.ts → packages/csvviewer/test/parse-noquotes.spec.ts

@@ -1,9 +1,8 @@
 // Copyright (c) Jupyter Development Team.
-// Distributed under the terms of the Modified BSD License.
 
-import { expect } from 'chai';
+import 'jest';
 
-import { parseDSVNoQuotes as parser } from '@jupyterlab/csvviewer';
+import { parseDSVNoQuotes as parser } from '../src';
 
 describe('csvviewer/parsenoquotes', () => {
   describe('parseDSVNoQuotes', () => {
@@ -13,14 +12,14 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(0);
-      expect(results.offsets).to.deep.equal([0, 9, 18]);
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(0);
+      expect(results.offsets).toEqual([0, 9, 18]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([
         0,
         2,
         4,
@@ -44,13 +43,13 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 8, 16]);
+      expect(results.nrows).toEqual(3);
+      expect(results.offsets).toEqual([0, 8, 16]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([
         0,
         2,
         4,
@@ -72,13 +71,13 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([0]);
+      expect(results.nrows).toEqual(1);
+      expect(results.offsets).toEqual([0]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([0, 2, 4, 6]);
+      expect(results.nrows).toEqual(1);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([0, 2, 4, 6]);
     });
 
     it('handles changing the field delimiter', () => {
@@ -87,13 +86,13 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 8, 16]);
+      expect(results.nrows).toEqual(3);
+      expect(results.offsets).toEqual([0, 8, 16]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([
         0,
         2,
         4,
@@ -115,13 +114,13 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.offsets).to.deep.equal([8, 16]);
+      expect(results.nrows).toEqual(2);
+      expect(results.offsets).toEqual([8, 16]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([8, 10, 12, 14, 16, 18, 20, 22]);
+      expect(results.nrows).toEqual(2);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([8, 10, 12, 14, 16, 18, 20, 22]);
     });
 
     it('handles a max row argument', () => {
@@ -130,13 +129,13 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.offsets).to.deep.equal([0, 8]);
+      expect(results.nrows).toEqual(2);
+      expect(results.offsets).toEqual([0, 8]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([0, 2, 4, 6, 8, 10, 12, 14]);
+      expect(results.nrows).toEqual(2);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([0, 2, 4, 6, 8, 10, 12, 14]);
     });
 
     it('handles a start index and max row argument', () => {
@@ -145,13 +144,13 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([8]);
+      expect(results.nrows).toEqual(1);
+      expect(results.offsets).toEqual([8]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([8, 10, 12, 14]);
+      expect(results.nrows).toEqual(1);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([8, 10, 12, 14]);
     });
 
     it('adjusts columns to match first row by default', () => {
@@ -160,13 +159,13 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 8, 11]);
+      expect(results.nrows).toEqual(3);
+      expect(results.offsets).toEqual([0, 8, 11]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([
         0,
         2,
         4,
@@ -188,13 +187,13 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 9, 13]);
+      expect(results.nrows).toEqual(3);
+      expect(results.offsets).toEqual([0, 9, 13]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([
         0,
         2,
         4,
@@ -216,13 +215,13 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 8, 11]);
+      expect(results.nrows).toEqual(3);
+      expect(results.offsets).toEqual([0, 8, 11]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(5);
-      expect(results.offsets).to.deep.equal([
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(5);
+      expect(results.offsets).toEqual([
         0,
         2,
         4,
@@ -247,13 +246,13 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 9, 13]);
+      expect(results.nrows).toEqual(3);
+      expect(results.offsets).toEqual([0, 9, 13]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(5);
-      expect(results.offsets).to.deep.equal([
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(5);
+      expect(results.offsets).toEqual([
         0,
         2,
         4,
@@ -278,13 +277,13 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([0]);
+      expect(results.nrows).toEqual(1);
+      expect(results.offsets).toEqual([0]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.ncols).to.deep.equal(7);
-      expect(results.offsets).to.deep.equal([0, 2, 4, 6, 7, 7, 7]);
+      expect(results.nrows).toEqual(1);
+      expect(results.ncols).toEqual(7);
+      expect(results.offsets).toEqual([0, 2, 4, 6, 7, 7, 7]);
     });
 
     it('adjusts columns to match ncols with one row and trailing delimiter', () => {
@@ -293,13 +292,13 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([0]);
+      expect(results.nrows).toEqual(1);
+      expect(results.offsets).toEqual([0]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.ncols).to.deep.equal(7);
-      expect(results.offsets).to.deep.equal([0, 2, 4, 6, 7, 7, 7]);
+      expect(results.nrows).toEqual(1);
+      expect(results.ncols).toEqual(7);
+      expect(results.offsets).toEqual([0, 2, 4, 6, 7, 7, 7]);
     });
 
     it('handles a single row delimiter', () => {
@@ -308,13 +307,13 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([0]);
+      expect(results.nrows).toEqual(1);
+      expect(results.offsets).toEqual([0]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.ncols).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([0]);
+      expect(results.nrows).toEqual(1);
+      expect(results.ncols).toEqual(1);
+      expect(results.offsets).toEqual([0]);
     });
 
     it('handles adding columns or merging columns as necessary', () => {
@@ -323,13 +322,13 @@ describe('csvviewer/parsenoquotes', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 6, 15]);
+      expect(results.nrows).toEqual(3);
+      expect(results.offsets).toEqual([0, 6, 15]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 2, 4, 6, 7, 9, 15, 17, 18]);
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(3);
+      expect(results.offsets).toEqual([0, 2, 4, 6, 7, 9, 15, 17, 18]);
     });
   });
 });

+ 113 - 114
tests/test-csvviewer/src/parse.spec.ts → packages/csvviewer/test/parse.spec.ts

@@ -1,9 +1,8 @@
 // Copyright (c) Jupyter Development Team.
-// Distributed under the terms of the Modified BSD License.
 
-import { expect } from 'chai';
+import 'jest';
 
-import { parseDSV as parser } from '@jupyterlab/csvviewer';
+import { parseDSV as parser } from '../src';
 
 describe('csvviewer/parse', () => {
   describe('parseDSV', () => {
@@ -13,14 +12,14 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(0);
-      expect(results.offsets).to.deep.equal([0, 9, 18]);
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(0);
+      expect(results.offsets).toEqual([0, 9, 18]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([
         0,
         2,
         4,
@@ -44,13 +43,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 8, 16]);
+      expect(results.nrows).toEqual(3);
+      expect(results.offsets).toEqual([0, 8, 16]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([
         0,
         2,
         4,
@@ -72,13 +71,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([0]);
+      expect(results.nrows).toEqual(1);
+      expect(results.offsets).toEqual([0]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([0, 2, 4, 6]);
+      expect(results.nrows).toEqual(1);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([0, 2, 4, 6]);
     });
 
     it('handles changing the field delimiter', () => {
@@ -87,13 +86,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 8, 16]);
+      expect(results.nrows).toEqual(3);
+      expect(results.offsets).toEqual([0, 8, 16]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([
         0,
         2,
         4,
@@ -115,13 +114,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.offsets).to.deep.equal([8, 16]);
+      expect(results.nrows).toEqual(2);
+      expect(results.offsets).toEqual([8, 16]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([8, 10, 12, 14, 16, 18, 20, 22]);
+      expect(results.nrows).toEqual(2);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([8, 10, 12, 14, 16, 18, 20, 22]);
     });
 
     it('handles a max row argument', () => {
@@ -130,13 +129,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.offsets).to.deep.equal([0, 8]);
+      expect(results.nrows).toEqual(2);
+      expect(results.offsets).toEqual([0, 8]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([0, 2, 4, 6, 8, 10, 12, 14]);
+      expect(results.nrows).toEqual(2);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([0, 2, 4, 6, 8, 10, 12, 14]);
     });
 
     it('handles a start index and max row argument', () => {
@@ -145,13 +144,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([8]);
+      expect(results.nrows).toEqual(1);
+      expect(results.offsets).toEqual([8]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([8, 10, 12, 14]);
+      expect(results.nrows).toEqual(1);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([8, 10, 12, 14]);
     });
 
     it('adjusts columns to match first row by default', () => {
@@ -160,13 +159,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 8, 11]);
+      expect(results.nrows).toEqual(3);
+      expect(results.offsets).toEqual([0, 8, 11]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([
         0,
         2,
         4,
@@ -188,13 +187,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 9, 13]);
+      expect(results.nrows).toEqual(3);
+      expect(results.offsets).toEqual([0, 9, 13]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(4);
-      expect(results.offsets).to.deep.equal([
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(4);
+      expect(results.offsets).toEqual([
         0,
         2,
         4,
@@ -216,13 +215,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 8, 11]);
+      expect(results.nrows).toEqual(3);
+      expect(results.offsets).toEqual([0, 8, 11]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(5);
-      expect(results.offsets).to.deep.equal([
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(5);
+      expect(results.offsets).toEqual([
         0,
         2,
         4,
@@ -247,13 +246,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 9, 13]);
+      expect(results.nrows).toEqual(3);
+      expect(results.offsets).toEqual([0, 9, 13]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(5);
-      expect(results.offsets).to.deep.equal([
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(5);
+      expect(results.offsets).toEqual([
         0,
         2,
         4,
@@ -278,13 +277,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([0]);
+      expect(results.nrows).toEqual(1);
+      expect(results.offsets).toEqual([0]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.ncols).to.deep.equal(7);
-      expect(results.offsets).to.deep.equal([0, 2, 4, 6, 7, 7, 7]);
+      expect(results.nrows).toEqual(1);
+      expect(results.ncols).toEqual(7);
+      expect(results.offsets).toEqual([0, 2, 4, 6, 7, 7, 7]);
     });
 
     it('adjusts columns to match ncols with one row and trailing delimiter', () => {
@@ -293,13 +292,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([0]);
+      expect(results.nrows).toEqual(1);
+      expect(results.offsets).toEqual([0]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.ncols).to.deep.equal(7);
-      expect(results.offsets).to.deep.equal([0, 2, 4, 6, 7, 7, 7]);
+      expect(results.nrows).toEqual(1);
+      expect(results.ncols).toEqual(7);
+      expect(results.offsets).toEqual([0, 2, 4, 6, 7, 7, 7]);
     });
 
     it('handles a single row delimiter', () => {
@@ -308,13 +307,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([0]);
+      expect(results.nrows).toEqual(1);
+      expect(results.offsets).toEqual([0]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.ncols).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([0]);
+      expect(results.nrows).toEqual(1);
+      expect(results.ncols).toEqual(1);
+      expect(results.offsets).toEqual([0]);
     });
 
     it('handles adding columns or merging columns as necessary', () => {
@@ -323,13 +322,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 6, 15]);
+      expect(results.nrows).toEqual(3);
+      expect(results.offsets).toEqual([0, 6, 15]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(3);
-      expect(results.ncols).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 2, 4, 6, 7, 9, 15, 17, 18]);
+      expect(results.nrows).toEqual(3);
+      expect(results.ncols).toEqual(3);
+      expect(results.offsets).toEqual([0, 2, 4, 6, 7, 9, 15, 17, 18]);
     });
   });
 
@@ -340,13 +339,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([0]);
+      expect(results.nrows).toEqual(1);
+      expect(results.offsets).toEqual([0]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.ncols).to.deep.equal(5);
-      expect(results.offsets).to.deep.equal([0, 6, 13, 21, 26]);
+      expect(results.nrows).toEqual(1);
+      expect(results.ncols).toEqual(5);
+      expect(results.offsets).toEqual([0, 6, 13, 21, 26]);
     });
 
     it('handles quotes with field delimiters', () => {
@@ -355,13 +354,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.offsets).to.deep.equal([0, 10]);
+      expect(results.nrows).toEqual(2);
+      expect(results.offsets).toEqual([0, 10]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.ncols).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 2, 8, 10, 14, 17]);
+      expect(results.nrows).toEqual(2);
+      expect(results.ncols).toEqual(3);
+      expect(results.offsets).toEqual([0, 2, 8, 10, 14, 17]);
     });
 
     it('handles quotes with row delimiters', () => {
@@ -370,13 +369,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.offsets).to.deep.equal([0, 10]);
+      expect(results.nrows).toEqual(2);
+      expect(results.offsets).toEqual([0, 10]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.ncols).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 2, 8, 10, 12, 13]);
+      expect(results.nrows).toEqual(2);
+      expect(results.ncols).toEqual(3);
+      expect(results.offsets).toEqual([0, 2, 8, 10, 12, 13]);
     });
 
     it('handles quotes with escaped quotes', () => {
@@ -385,13 +384,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.offsets).to.deep.equal([0, 11]);
+      expect(results.nrows).toEqual(2);
+      expect(results.offsets).toEqual([0, 11]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.ncols).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 2, 9, 11, 13, 14]);
+      expect(results.nrows).toEqual(2);
+      expect(results.ncols).toEqual(3);
+      expect(results.offsets).toEqual([0, 2, 9, 11, 13, 14]);
     });
 
     it('handles setting the quote character', () => {
@@ -400,13 +399,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.offsets).to.deep.equal([0, 13]);
+      expect(results.nrows).toEqual(2);
+      expect(results.offsets).toEqual([0, 13]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(2);
-      expect(results.ncols).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 2, 11, 13, 15, 16]);
+      expect(results.nrows).toEqual(2);
+      expect(results.ncols).toEqual(3);
+      expect(results.offsets).toEqual([0, 2, 11, 13, 15, 16]);
     });
 
     it('handles single quoted field', () => {
@@ -415,13 +414,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([0]);
+      expect(results.nrows).toEqual(1);
+      expect(results.offsets).toEqual([0]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.ncols).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([0]);
+      expect(results.nrows).toEqual(1);
+      expect(results.ncols).toEqual(1);
+      expect(results.offsets).toEqual([0]);
     });
 
     it('handles empty quoted field', () => {
@@ -430,13 +429,13 @@ describe('csvviewer/parse', () => {
       let results;
 
       results = parser({ ...options, columnOffsets: false });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.offsets).to.deep.equal([0]);
+      expect(results.nrows).toEqual(1);
+      expect(results.offsets).toEqual([0]);
 
       results = parser({ ...options, columnOffsets: true });
-      expect(results.nrows).to.deep.equal(1);
-      expect(results.ncols).to.deep.equal(3);
-      expect(results.offsets).to.deep.equal([0, 2, 5]);
+      expect(results.nrows).toEqual(1);
+      expect(results.ncols).toEqual(3);
+      expect(results.offsets).toEqual([0, 2, 5]);
     });
   });
 });

+ 13 - 12
tests/test-csvviewer/src/toolbar.spec.ts → packages/csvviewer/test/toolbar.spec.ts

@@ -1,13 +1,12 @@
 // Copyright (c) Jupyter Development Team.
-// Distributed under the terms of the Modified BSD License.
 
-import { expect } from 'chai';
+import 'jest';
 
 import { Widget } from '@lumino/widgets';
 
 import { simulate } from 'simulate-event';
 
-import { CSVDelimiter } from '@jupyterlab/csvviewer';
+import { CSVDelimiter } from '../src';
 
 const DELIMITERS = [',', ';', '\t'];
 
@@ -16,15 +15,17 @@ describe('csvviewer/toolbar', () => {
     describe('#constructor()', () => {
       it('should instantiate a `CSVDelimiter` toolbar widget', () => {
         const widget = new CSVDelimiter({ selected: ',' });
-        expect(widget).to.be.an.instanceof(CSVDelimiter);
-        expect(Array.from(widget.node.classList)).to.contain('jp-CSVDelimiter');
+        expect(widget).toBeInstanceOf(CSVDelimiter);
+        expect(Array.from(widget.node.classList)).toEqual(
+          expect.arrayContaining(['jp-CSVDelimiter'])
+        );
         widget.dispose();
       });
 
       it('should allow pre-selecting the delimiter', () => {
         const wanted = DELIMITERS[DELIMITERS.length - 1];
         const widget = new CSVDelimiter({ selected: wanted });
-        expect(widget.selectNode.value).to.equal(wanted);
+        expect(widget.selectNode.value).toBe(wanted);
         widget.dispose();
       });
     });
@@ -41,7 +42,7 @@ describe('csvviewer/toolbar', () => {
         Widget.attach(widget, document.body);
         widget.selectNode.selectedIndex = index;
         simulate(widget.selectNode, 'change');
-        expect(delimiter).to.equal(wanted);
+        expect(delimiter).toBe(wanted);
         widget.dispose();
       });
     });
@@ -49,7 +50,7 @@ describe('csvviewer/toolbar', () => {
     describe('#selectNode', () => {
       it('should return the delimiter dropdown select tag', () => {
         const widget = new CSVDelimiter({ selected: ',' });
-        expect(widget.selectNode.tagName.toLowerCase()).to.equal('select');
+        expect(widget.selectNode.tagName.toLowerCase()).toBe('select');
         widget.dispose();
       });
     });
@@ -57,17 +58,17 @@ describe('csvviewer/toolbar', () => {
     describe('#dispose()', () => {
       it('should dispose of the resources held by the widget', () => {
         const widget = new CSVDelimiter({ selected: ',' });
-        expect(widget.isDisposed).to.equal(false);
+        expect(widget.isDisposed).toBe(false);
         widget.dispose();
-        expect(widget.isDisposed).to.equal(true);
+        expect(widget.isDisposed).toBe(true);
       });
 
       it('should be safe to call multiple times', () => {
         const widget = new CSVDelimiter({ selected: ',' });
-        expect(widget.isDisposed).to.equal(false);
+        expect(widget.isDisposed).toBe(false);
         widget.dispose();
         widget.dispose();
-        expect(widget.isDisposed).to.equal(true);
+        expect(widget.isDisposed).toBe(true);
       });
     });
   });

+ 15 - 16
tests/test-csvviewer/src/widget.spec.ts → packages/csvviewer/test/widget.spec.ts

@@ -1,13 +1,12 @@
 // Copyright (c) Jupyter Development Team.
-// Distributed under the terms of the Modified BSD License.
 
-import { expect } from 'chai';
+import 'jest';
 
 import { UUID } from '@lumino/coreutils';
 
-import { ServiceManager } from '@jupyterlab/services';
+import * as Mock from '@jupyterlab/testutils/lib/mock';
 
-import { CSVViewer, GridSearchService } from '@jupyterlab/csvviewer';
+import { CSVViewer, GridSearchService } from '../src';
 
 import {
   Context,
@@ -18,7 +17,7 @@ import { JSONModel, DataGrid, CellRenderer } from '@lumino/datagrid';
 
 function createContext(): Context<DocumentRegistry.IModel> {
   const factory = new TextModelFactory();
-  const manager = new ServiceManager({ standby: 'never' });
+  const manager = new Mock.ServiceManagerMock();
   const path = UUID.uuid4() + '.csv';
   return new Context({ factory, manager, path });
 }
@@ -30,7 +29,7 @@ describe('csvviewer/widget', () => {
     describe('#constructor()', () => {
       it('should instantiate a `CSVViewer`', () => {
         const widget = new CSVViewer({ context });
-        expect(widget).to.be.an.instanceof(CSVViewer);
+        expect(widget).toBeInstanceOf(CSVViewer);
         widget.dispose();
       });
     });
@@ -38,24 +37,24 @@ describe('csvviewer/widget', () => {
     describe('#context', () => {
       it('should be the context for the file', () => {
         const widget = new CSVViewer({ context });
-        expect(widget.context).to.equal(context);
+        expect(widget.context).toBe(context);
       });
     });
 
     describe('#dispose()', () => {
       it('should dispose of the resources held by the widget', () => {
         const widget = new CSVViewer({ context });
-        expect(widget.isDisposed).to.equal(false);
+        expect(widget.isDisposed).toBe(false);
         widget.dispose();
-        expect(widget.isDisposed).to.equal(true);
+        expect(widget.isDisposed).toBe(true);
       });
 
       it('should be safe to call multiple times', () => {
         const widget = new CSVViewer({ context });
-        expect(widget.isDisposed).to.equal(false);
+        expect(widget.isDisposed).toBe(false);
         widget.dispose();
         widget.dispose();
-        expect(widget.isDisposed).to.equal(true);
+        expect(widget.isDisposed).toBe(true);
       });
     });
   });
@@ -111,14 +110,14 @@ describe('csvviewer/widget', () => {
       // (0,1) is the current match
       const query = /match/;
       searchService.find(query);
-      expect(fakeRenderCell(0, 1)).to.equal('currentMatch');
-      expect(fakeRenderCell(1, 1)).to.equal('anotherMatch');
-      expect(fakeRenderCell(0, 0)).to.equal('');
+      expect(fakeRenderCell(0, 1)).toBe('currentMatch');
+      expect(fakeRenderCell(1, 1)).toBe('anotherMatch');
+      expect(fakeRenderCell(0, 0)).toBe('');
 
       // search again, the current match "moves" to be (1,1)
       searchService.find(query);
-      expect(fakeRenderCell(0, 1)).to.equal('anotherMatch');
-      expect(fakeRenderCell(1, 1)).to.equal('currentMatch');
+      expect(fakeRenderCell(0, 1)).toBe('anotherMatch');
+      expect(fakeRenderCell(1, 1)).toBe('currentMatch');
     });
   });
 });

+ 18 - 0
packages/csvviewer/tsconfig.test.json

@@ -0,0 +1,18 @@
+{
+  "extends": "../../tsconfigbase.test",
+  "include": ["src/*", "test/*"],
+  "references": [
+    {
+      "path": "../apputils"
+    },
+    {
+      "path": "../coreutils"
+    },
+    {
+      "path": "../docregistry"
+    },
+    {
+      "path": "../../testutils"
+    }
+  ]
+}

+ 12 - 16
tests/modernize.js

@@ -63,19 +63,20 @@ const tsData = utils.readJSONFile(path.join(testSrc, 'tsconfig.json'));
 delete tsData['compilerOptions']['skipLibCheck'];
 utils.writeJSONFile(path.join(testSrc, 'tsconfig.json'), tsData);
 
-// Update the test files to use imports from `../src`
+// Update the test files to use imports from `../src` and import "jest"
 glob.sync(path.join(testSrc, 'src', '**', '*.ts*')).forEach(function(filePath) {
   console.debug(filePath);
   let src = fs.readFileSync(filePath, 'utf8');
   src = src.split(`'@jupyterlab/${name}/src';`).join(`'../src';`);
-  fs.writeFileSync(filePath, src, 'utf8');
+  let lines = src.split('\n');
+  let i = 0;
+  while (!lines[i++].startsWith('//')) {
+    // no-op
+  }
+  lines.splice(i, 0, ["\nimport 'jest';"]);
+  fs.writeFileSync(filePath, lines.join('\n'), 'utf8');
 });
 
-// Commit changes (needed for jlpm jest-codemods)
-utils.run(
-  `git add test-${name}; git add ../packages/${name}; git commit -m "wip modernize ${name} tests"; true`
-);
-
 // Run jest-codemods to convert from chai to jest.
 console.debug('------------------------------------');
 console.debug('Select the following options');
@@ -85,7 +86,7 @@ console.debug("Yes, and I'm not afraid of false positive transformations");
 console.debug('Yes, use the globals provided by Jest(recommended)');
 console.debug('.');
 console.debug('------------------------------------');
-utils.run('jlpm jest-codemods', { cwd: testSrc });
+utils.run('jlpm jest-codemods --force', { cwd: testSrc });
 
 // Move the test files to `/packages/{name}/test`
 utils.run(`git mv ${testSrc}/src ${pkgPath}/${name}/test`);
@@ -100,16 +101,11 @@ utils.run(
 );
 utils.run(`git add -f ${pkgPath}/${name}/.vscode/launch.json`);
 
+// Remove local folder
+utils.run(`git rm -rf ${testSrc} && rm -rf ${testSrc}`);
+
 // Run integrity
 const rootDir = path.resolve('..');
 utils.run(`jlpm integrity`, {
   cwd: rootDir
 });
-
-// Remove local folder
-utils.run(`git rm -rf ${testSrc}`);
-
-// Commit the changes
-utils.run(
-  `git add ${pkgPath}/${name} && git commit --no-verify -m "wip modernize ${name} tests`
-);

+ 0 - 1
tests/test-csvviewer/karma-cov.conf.js

@@ -1 +0,0 @@
-module.exports = require('../karma-cov.conf');

+ 0 - 1
tests/test-csvviewer/karma.conf.js

@@ -1 +0,0 @@
-module.exports = require('../karma.conf');

+ 0 - 40
tests/test-csvviewer/package.json

@@ -1,40 +0,0 @@
-{
-  "name": "@jupyterlab/test-csvviewer",
-  "version": "2.1.0",
-  "private": true,
-  "scripts": {
-    "build": "tsc -b",
-    "clean": "rimraf build && rimraf coverage",
-    "coverage": "python run-test.py --browsers=ChromeHeadless karma-cov.conf.js",
-    "test": "jlpm run test:firefox-headless",
-    "test:chrome": "python run-test.py --browsers=Chrome karma.conf.js",
-    "test:chrome-headless": "python run-test.py --browsers=ChromeHeadless karma.conf.js",
-    "test:debug": "python run-test.py  --browsers=Chrome --singleRun=false --debug=true --browserNoActivityTimeout=10000000 karma.conf.js",
-    "test:firefox": "python run-test.py --browsers=Firefox karma.conf.js",
-    "test:firefox-headless": "python run-test.py --browsers=FirefoxHeadless karma.conf.js",
-    "test:ie": "python run-test.py  --browsers=IE karma.conf.js",
-    "watch": "tsc -b --watch",
-    "watch:src": "tsc -p src --watch"
-  },
-  "dependencies": {
-    "@jupyterlab/csvviewer": "^2.1.0",
-    "@jupyterlab/docregistry": "^2.1.0",
-    "@jupyterlab/services": "^5.1.0",
-    "@jupyterlab/testutils": "^2.1.0",
-    "@lumino/coreutils": "^1.4.2",
-    "@lumino/datagrid": "^0.6.0",
-    "@lumino/widgets": "^1.11.1",
-    "chai": "^4.2.0",
-    "csv-spectrum": "~1.0.0",
-    "simulate-event": "~1.4.0"
-  },
-  "devDependencies": {
-    "@types/chai": "^4.2.7",
-    "@types/mocha": "^7.0.2",
-    "karma": "^4.4.1",
-    "karma-chrome-launcher": "~3.1.0",
-    "puppeteer": "~2.0.0",
-    "rimraf": "~3.0.0",
-    "typescript": "~3.7.3"
-  }
-}

+ 0 - 10
tests/test-csvviewer/run-test.py

@@ -1,10 +0,0 @@
-# Copyright (c) Jupyter Development Team.
-# Distributed under the terms of the Modified BSD License.
-
-import os
-from jupyterlab.tests.test_app import run_karma
-
-HERE = os.path.realpath(os.path.dirname(__file__))
-
-if __name__ == '__main__':
-    run_karma(HERE)

+ 0 - 24
tests/test-csvviewer/tsconfig.json

@@ -1,24 +0,0 @@
-{
-  "extends": "../../tsconfigbase",
-  "compilerOptions": {
-    "outDir": "build",
-    "types": ["mocha", "node"],
-    "composite": false,
-    "rootDir": "src"
-  },
-  "include": ["src/*"],
-  "references": [
-    {
-      "path": "../../packages/csvviewer"
-    },
-    {
-      "path": "../../packages/docregistry"
-    },
-    {
-      "path": "../../packages/services"
-    },
-    {
-      "path": "../../testutils"
-    }
-  ]
-}

+ 85 - 6
yarn.lock

@@ -5614,6 +5614,15 @@ canonicalize@^1.0.1:
   resolved "https://registry.yarnpkg.com/canonicalize/-/canonicalize-1.0.1.tgz#657b4f3fa38a6ecb97a9e5b7b26d7a19cc6e0da9"
   integrity sha512-N3cmB3QLhS5TJ5smKFf1w42rJXWe6C1qP01z4dxJiI5v269buii4fLHWETDyf7yEd0azGLNC63VxNMiPd2u0Cg==
 
+canvas@^2.6.1:
+  version "2.6.1"
+  resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.6.1.tgz#0d087dd4d60f5a5a9efa202757270abea8bef89e"
+  integrity sha512-S98rKsPcuhfTcYbtF53UIJhcbgIAK533d1kJKMwsMwAIFgfd58MOyxRud3kktlzWiEkFliaJtvyZCBtud/XVEA==
+  dependencies:
+    nan "^2.14.0"
+    node-pre-gyp "^0.11.0"
+    simple-get "^3.0.3"
+
 capture-exit@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4"
@@ -6634,7 +6643,7 @@ csstype@^2.2.0, csstype@^2.4.0, csstype@^2.5.7, csstype@~2.6.9:
   resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.9.tgz#05141d0cd557a56b8891394c1911c40c8a98d098"
   integrity sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==
 
-csv-spectrum@~1.0.0:
+csv-spectrum@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/csv-spectrum/-/csv-spectrum-1.0.0.tgz#591ac9ff48ad4f3eb4338457bc9801b349e3d628"
   integrity sha1-WRrJ/0itTz60M4RXvJgBs0nj1ig=
@@ -6892,6 +6901,13 @@ decompress-response@^3.3.0:
   dependencies:
     mimic-response "^1.0.0"
 
+decompress-response@^4.2.0:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986"
+  integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==
+  dependencies:
+    mimic-response "^2.0.0"
+
 dedent@^0.7.0:
   version "0.7.0"
   resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
@@ -7073,6 +7089,11 @@ detect-indent@^6.0.0:
   resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd"
   integrity sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==
 
+detect-libc@^1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
+  integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
+
 detect-newline@3.1.0, detect-newline@^3.0.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
@@ -9390,7 +9411,7 @@ husky@^3.1.0:
     run-node "^1.0.0"
     slash "^3.0.0"
 
-iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@~0.4.13:
+iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
   version "0.4.24"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
   integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -12025,6 +12046,11 @@ mimic-response@^1.0.0, mimic-response@^1.0.1:
   resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
   integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
 
+mimic-response@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43"
+  integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==
+
 min-document@^2.19.0:
   version "2.19.0"
   resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
@@ -12294,6 +12320,11 @@ nan@^2.12.1:
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
   integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
 
+nan@^2.14.0:
+  version "2.14.1"
+  resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
+  integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
+
 nanomatch@^1.2.9:
   version "1.2.13"
   resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@@ -12316,6 +12347,15 @@ natural-compare@^1.4.0:
   resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
   integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
 
+needle@^2.2.1:
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.1.tgz#14af48732463d7475696f937626b1b993247a56a"
+  integrity sha512-x/gi6ijr4B7fwl6WYL9FwlCvRQKGlUNvnceho8wxkwXqN8jvVmmmATTmZPRRG7b/yC1eode26C2HO9jl78Du9g==
+  dependencies:
+    debug "^3.2.6"
+    iconv-lite "^0.4.4"
+    sax "^1.2.4"
+
 negotiator@0.6.2:
   version "0.6.2"
   resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
@@ -12452,6 +12492,22 @@ node-notifier@^6.0.0:
     shellwords "^0.1.1"
     which "^1.3.1"
 
+node-pre-gyp@^0.11.0:
+  version "0.11.0"
+  resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz#db1f33215272f692cd38f03238e3e9b47c5dd054"
+  integrity sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==
+  dependencies:
+    detect-libc "^1.0.2"
+    mkdirp "^0.5.1"
+    needle "^2.2.1"
+    nopt "^4.0.1"
+    npm-packlist "^1.1.6"
+    npmlog "^4.0.2"
+    rc "^1.2.7"
+    rimraf "^2.6.1"
+    semver "^5.3.0"
+    tar "^4"
+
 node-releases@^1.1.29, node-releases@^1.1.42:
   version "1.1.43"
   resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.43.tgz#2c6ca237f88ce11d49631f11190bb01f8d0549f2"
@@ -12567,6 +12623,15 @@ npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1:
     semver "^5.6.0"
     validate-npm-package-name "^3.0.0"
 
+npm-packlist@^1.1.6:
+  version "1.4.8"
+  resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e"
+  integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==
+  dependencies:
+    ignore-walk "^3.0.1"
+    npm-bundled "^1.0.1"
+    npm-normalize-package-bin "^1.0.1"
+
 npm-packlist@^1.4.4:
   version "1.4.7"
   resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.7.tgz#9e954365a06b80b18111ea900945af4f88ed4848"
@@ -12612,7 +12677,7 @@ npm-run-path@^4.0.0:
   dependencies:
     path-key "^3.0.0"
 
-npmlog@^4.1.2:
+npmlog@^4.0.2, npmlog@^4.1.2:
   version "4.1.2"
   resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
   integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
@@ -13837,7 +13902,7 @@ raw-loader@~4.0.0:
     loader-utils "^1.2.3"
     schema-utils "^2.5.0"
 
-rc@^1.0.1, rc@^1.1.6, rc@^1.2.8:
+rc@^1.0.1, rc@^1.1.6, rc@^1.2.7, rc@^1.2.8:
   version "1.2.8"
   resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
   integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
@@ -14813,7 +14878,7 @@ sanitize-html@~1.20.1:
     srcset "^1.0.0"
     xtend "^4.0.1"
 
-sax@~1.2.4:
+sax@^1.2.4, sax@~1.2.4:
   version "1.2.4"
   resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
   integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
@@ -15050,6 +15115,20 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
   integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
 
+simple-concat@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6"
+  integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=
+
+simple-get@^3.0.3:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3"
+  integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==
+  dependencies:
+    decompress-response "^4.2.0"
+    once "^1.3.1"
+    simple-concat "^1.0.0"
+
 simplebar-react@^1.0.0-alpha.6:
   version "1.2.3"
   resolved "https://registry.yarnpkg.com/simplebar-react/-/simplebar-react-1.2.3.tgz#bd81fa9827628470e9470d06caef6ece15e1c882"
@@ -15826,7 +15905,7 @@ tapable@^1.0.0, tapable@^1.1.3:
   resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
   integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
 
-tar@^4.4.10, tar@^4.4.12, tar@^4.4.8:
+tar@^4, tar@^4.4.10, tar@^4.4.12, tar@^4.4.8:
   version "4.4.13"
   resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
   integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==