123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- // Copyright (c) Jupyter Development Team.
- // Distributed under the terms of the Modified BSD License.
- 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',
- readCSV('csv-spectrum/csvs/comma_in_quotes.csv'),
- require('csv-spectrum/json/comma_in_quotes.json')
- ],
- [
- 'empty_values',
- readCSV('csv-spectrum/csvs/empty.csv'),
- require('csv-spectrum/json/empty.json')
- ],
- [
- 'empty_crlf',
- readCSV('csv-spectrum/csvs/empty_crlf.csv'),
- require('csv-spectrum/json/empty_crlf.json')
- ],
- ['empty_file', '', []],
- [
- 'escaped_quotes',
- readCSV('csv-spectrum/csvs/escaped_quotes.csv'),
- require('csv-spectrum/json/escaped_quotes.json')
- ],
- [
- 'json',
- readCSV('csv-spectrum/csvs/json.csv'),
- require('csv-spectrum/json/json.json')
- ],
- [
- 'newlines',
- readCSV('csv-spectrum/csvs/newlines.csv'),
- require('csv-spectrum/json/newlines.json')
- ],
- [
- 'newlines_crlf',
- readCSV('csv-spectrum/csvs/newlines_crlf.csv'),
- require('csv-spectrum/json/newlines_crlf.json')
- ],
- [
- 'quotes_and_newlines',
- readCSV('csv-spectrum/csvs/quotes_and_newlines.csv'),
- require('csv-spectrum/json/quotes_and_newlines.json')
- ],
- [
- 'simple',
- readCSV('csv-spectrum/csvs/simple.csv'),
- require('csv-spectrum/json/simple.json')
- ],
- [
- 'simple_crlf',
- readCSV('csv-spectrum/csvs/simple_crlf.csv'),
- require('csv-spectrum/json/simple_crlf.json')
- ],
- [
- 'utf8',
- readCSV('csv-spectrum/csvs/utf8.csv'),
- require('csv-spectrum/json/utf8.json')
- ]
- ];
- /* tslint:enable:no-var-requires */
- describe('csvviewer/model', () => {
- describe('DSVModel', () => {
- 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')).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'
- ]);
- });
- });
- it('parses a number of test files correctly', () => {
- for (const [, csv, answer] of CSV_TEST_FILES) {
- const d = new DSVModel({ data: csv, delimiter: ',' });
- const labels = [];
- for (let i = 0; i < d.columnCount('body'); i++) {
- labels.push(d.data('column-header', 0, i));
- }
- const values = [];
- for (let r = 0; r < d.rowCount('body'); r++) {
- const row: { [key: string]: string } = {};
- for (let c = 0; c < d.columnCount('body'); c++) {
- row[labels[c]] = d.data('body', r, c);
- }
- values.push(row);
- }
- 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')).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']);
- });
- it('handles not having a header', () => {
- const d = new DSVModel({
- data: 'a,b,c\nd,e,f\n',
- delimiter: ',',
- header: false
- });
- 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))).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')).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'
- ]);
- });
- it('handles single non-header line', () => {
- const d = new DSVModel({
- data: 'a,b,c\n',
- delimiter: ',',
- header: false
- });
- 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))).toEqual(['a', 'b', 'c']);
- });
- it('handles CRLF row delimiter', () => {
- const d = new DSVModel({
- data: 'a,b,c\r\nd,e,f\r\n',
- delimiter: ',',
- rowDelimiter: '\r\n'
- });
- 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']);
- });
- it('handles CR row delimiter', () => {
- const d = new DSVModel({
- data: 'a,b,c\rd,e,f\r',
- delimiter: ',',
- rowDelimiter: '\r'
- });
- 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']);
- });
- it('can guess the row delimiter', () => {
- const d = new DSVModel({ data: 'a,b,c\rd,e,f\r', delimiter: ',' });
- 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']);
- });
- it('handles a given quote character', () => {
- const d = new DSVModel({
- data: `a,'b','c'\r'd',e,'f'\r`,
- delimiter: ',',
- quote: `'`
- });
- 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']);
- });
- it('handles delimiters and quotes inside quotes', () => {
- const d = new DSVModel({
- data: `'a\rx',b,'c''x'\r'd,x',e,'f'\r`,
- delimiter: ',',
- quote: `'`,
- rowDelimiter: '\r'
- });
- 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))).toEqual([
- 'd,x',
- 'e',
- 'f'
- ]);
- });
- 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')).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))).toEqual([
- '',
- 'c',
- 'd,e,f'
- ]);
- 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 () => {
- const d = new DSVModel({
- data: `a,b,c\nc,d,e\nf,g,h\ni,j,k`,
- delimiter: ',',
- initialRows: 2
- });
- 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))).toEqual([
- 'c',
- 'd',
- 'e\nf,g,h\ni,j,k'
- ]);
- // Check everything is in order after all the data has been parsed asynchronously.
- await d.ready;
- 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))).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']);
- });
- });
- });
|