]> git.ardis.lu - csvio/commitdiff
Refactor to delete redundant code
authorArdis Lu <ardisglu@gmail.com>
Fri, 3 Jan 2025 04:32:41 +0000 (20:32 -0800)
committerArdis Lu <ardisglu@gmail.com>
Fri, 3 Jan 2025 04:32:41 +0000 (20:32 -0800)
test/core.test.js

index 22f51b2c0369f7f9d4b61f21a4efc280f17466a5..b0699a03184bc61d48cb253a26965e75b9ea8196 100644 (file)
@@ -2,7 +2,7 @@ import { suite, test } from 'node:test';
 import { deepStrictEqual } from 'node:assert/strict';
 import { unlink } from 'node:fs/promises';
 
-import { csvStreamEqual, csvStreamEqualWritable, createCSVMockStream, createTempFile } from './utils.js';
+import { csvStreamEqualWritable, createCSVMockStream, createTempFile } from './utils.js';
 import { arrayToCSVString, createCSVReadableStream, createCSVTransformStream, createCSVWritableStream } from '../src/core.js';
 
 suite('arrayToCSVString', { concurrency: true }, () => {
@@ -24,119 +24,136 @@ suite('arrayToCSVString', { concurrency: true }, () => {
 });
 
 suite('createCSVReadableStream', { concurrency: true }, () => {
-  test('parses simple CSV', { concurrency: true }, async () => {
-    const stream = createCSVReadableStream('./test/data/simple.csv');
-    await csvStreamEqual(stream, [
-      ['column1', 'column2', 'column3'],
-      ['abc', 'def', 'ghi'],
-      ['123', '456', '789'],
-      ['aaa', 'bbb', 'ccc']
-    ]);
-  });
-  test('parses escaping CSV', { concurrency: true }, async () => {
-    const stream = createCSVReadableStream('./test/data/escaping.csv');
-    await csvStreamEqual(stream, [
-      ['name', 'value'],
-      ['Three spaces', '   '],
-      ['Three commas', ',,,'],
-      ['Three newlines', '\r\n\r\n\r\n'],
-      ['Three unescaped double quotes', 'a"""'],
-      ['Three escaped double quotes', '"""'],
-      ['Unescaped double quotes around delimiter 1 "', 'a'],
-      ['Unescaped double quotes around delimiter 2 ""', 'a'],
-      ['Unescaped double quotes around delimiter 3 """', 'a'],
-      ['Unescaped double quotes around delimiter 4', ' "'],
-      ['Unescaped double quotes around delimiter 5', ' ""'],
-      ['Unescaped double quotes around delimiter 6', ' """'],
-      ['Spaces before and after a value', '   abc   '],
-      ['Spaces before and after three unescaped double quotes', '   """   '],
-      ['Spaces trailing escaped double quotes', 'abc   '],
-      ['Characters trailing escaped double quotes', 'abc def'],
-      ['Unescaped double quotes trailing escaped double quotes', 'abc " def 123 """ 456'],
-      ['Unescaped "double quotes" trailing escaped double quotes', 'abc """ def 123 """ 456'],
-      ['Unicode test 1', 'ไฝ ๅฅฝ'],
-      ['Unicode test 2', '๐Ÿ˜‚๐Ÿ‘Œ๐Ÿ‘'],
-      ['Unicode test 3', '๐Ÿดโ€โ˜ ๏ธ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ'],
-      ['Mixed', ',\r\n",\r\n",\r\n"']
-    ]);
-  });
-  test('parses escaping edges CSV', { concurrency: true }, async () => {
-    const stream = createCSVReadableStream('./test/data/escaping-edges.csv');
-    await csvStreamEqual(stream, [
-      [',,,', '"""'],
-      ['"""', ',,,'],
-      ['a"b""', 'a"b""'],
-      ['a"b""', 'a"b""']
-    ]);
-  });
-  test('parses sparse CSV', { concurrency: true }, async () => {
-    const stream = createCSVReadableStream('./test/data/sparse.csv');
-    await csvStreamEqual(stream, [
-      ['column1', 'column2', 'column3'],
-      [''],
-      ['', ''],
-      ['', '', ''],
-      ['', '', '', ''],
-      ['', '', '', '', ''],
-      ['aaa', 'bbb', 'ccc'],
-      ['111', '222', '333', '444', '555', '666', '777', '888'],
-      ['', 'hhh', 'iii'],
-      ['ggg', '', 'iii'],
-      ['ggg', 'hhh', ''],
-      ['', 'hhh', ''],
-      ['ggg', '', ''],
-      ['', '', 'iii'],
-      ['', '', ''],
-      ['', '', ''],
-      ['', '', ''],
-      [''],
-      ['']
-    ]);
-  });
-  test('parses line feed end-of-line CSV', { concurrency: true }, async () => {
-    const stream = createCSVReadableStream('./test/data/lf-eol.csv');
-    await csvStreamEqual(stream, [
-      ['column1', 'column2'],
-      ['a', 'b'],
-      ['c', 'd'],
-      ['1', '2'],
-      ['3', '4']
-    ]);
-  });
-  test('parses byte order mark CSV', { concurrency: true }, async () => {
-    const stream = createCSVReadableStream('./test/data/bom.csv');
-    await csvStreamEqual(stream, [
-      ['column1', 'column2'],
-      ['ab', 'cd'],
-      ['12', '34']
-    ]);
-  });
-  test('parses single value (no commas or newlines) CSV', { concurrency: true }, async () => {
-    const stream = createCSVReadableStream('./test/data/single-value.csv');
-    await csvStreamEqual(stream, [
-      ['abc']
-    ]);
-  });
-  test('parses single column (no commas) CSV', { concurrency: true }, async () => {
-    const stream = createCSVReadableStream('./test/data/single-column.csv');
-    await csvStreamEqual(stream, [
-      ['abc'],
-      ['def'],
-      ['ghi']
-    ]);
-  });
-  test('parses single row (no newlines) CSV', { concurrency: true }, async () => {
-    const stream = createCSVReadableStream('./test/data/single-row.csv');
-    await csvStreamEqual(stream, [
-      ['abc', 'def', 'ghi']
-    ]);
-  });
-  test('parses blank CSV', { concurrency: true }, async () => {
-    const stream = createCSVReadableStream('./test/data/blank.csv');
-    await csvStreamEqual(stream, [
-      ['']
-    ]);
-  });
+  const vectors = [
+    {
+      name: 'parses simple CSV',
+      input: './test/data/simple.csv',
+      output: [
+        ['column1', 'column2', 'column3'],
+        ['abc', 'def', 'ghi'],
+        ['123', '456', '789'],
+        ['aaa', 'bbb', 'ccc']
+      ]
+    },
+    {
+      name: 'parses escaping CSV',
+      input: './test/data/escaping.csv',
+      output: [
+        ['name', 'value'],
+        ['Three spaces', '   '],
+        ['Three commas', ',,,'],
+        ['Three newlines', '\r\n\r\n\r\n'],
+        ['Three unescaped double quotes', 'a"""'],
+        ['Three escaped double quotes', '"""'],
+        ['Unescaped double quotes around delimiter 1 "', 'a'],
+        ['Unescaped double quotes around delimiter 2 ""', 'a'],
+        ['Unescaped double quotes around delimiter 3 """', 'a'],
+        ['Unescaped double quotes around delimiter 4', ' "'],
+        ['Unescaped double quotes around delimiter 5', ' ""'],
+        ['Unescaped double quotes around delimiter 6', ' """'],
+        ['Spaces before and after a value', '   abc   '],
+        ['Spaces before and after three unescaped double quotes', '   """   '],
+        ['Spaces trailing escaped double quotes', 'abc   '],
+        ['Characters trailing escaped double quotes', 'abc def'],
+        ['Unescaped double quotes trailing escaped double quotes', 'abc " def 123 """ 456'],
+        ['Unescaped "double quotes" trailing escaped double quotes', 'abc """ def 123 """ 456'],
+        ['Unicode test 1', 'ไฝ ๅฅฝ'],
+        ['Unicode test 2', '๐Ÿ˜‚๐Ÿ‘Œ๐Ÿ‘'],
+        ['Unicode test 3', '๐Ÿดโ€โ˜ ๏ธ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ'],
+        ['Mixed', ',\r\n",\r\n",\r\n"']
+      ]
+    },
+    {
+      name: 'parses escaping edges CSV',
+      input: './test/data/escaping-edges.csv',
+      output: [
+        [',,,', '"""'],
+        ['"""', ',,,'],
+        ['a"b""', 'a"b""'],
+        ['a"b""', 'a"b""']
+      ]
+    },
+    {
+      name: 'parses sparse CSV',
+      input: './test/data/sparse.csv',
+      output: [
+        ['column1', 'column2', 'column3'],
+        [''],
+        ['', ''],
+        ['', '', ''],
+        ['', '', '', ''],
+        ['', '', '', '', ''],
+        ['aaa', 'bbb', 'ccc'],
+        ['111', '222', '333', '444', '555', '666', '777', '888'],
+        ['', 'hhh', 'iii'],
+        ['ggg', '', 'iii'],
+        ['ggg', 'hhh', ''],
+        ['', 'hhh', ''],
+        ['ggg', '', ''],
+        ['', '', 'iii'],
+        ['', '', ''],
+        ['', '', ''],
+        ['', '', ''],
+        [''],
+        ['']
+      ]
+    },
+    {
+      name: 'parses line feed end-of-line CSV',
+      input: './test/data/lf-eol.csv',
+      output: [
+        ['column1', 'column2'],
+        ['a', 'b'],
+        ['c', 'd'],
+        ['1', '2'],
+        ['3', '4']
+      ]
+    },
+    {
+      name: 'parses byte order mark CSV',
+      input: './test/data/bom.csv',
+      output: [
+        ['column1', 'column2'],
+        ['ab', 'cd'],
+        ['12', '34']
+      ]
+    },
+    {
+      name: 'parses single value (no commas or newlines) CSV',
+      input: './test/data/single-value.csv',
+      output: [
+        ['abc']
+      ]
+    },
+    {
+      name: 'parses single column (no commas) CSV',
+      input: './test/data/single-column.csv',
+      output: [
+        ['abc'],
+        ['def'],
+        ['ghi']
+      ]
+    },
+    {
+      name: 'parses single row (no newlines) CSV',
+      input: './test/data/single-row.csv',
+      output: [
+        ['abc', 'def', 'ghi']
+      ]
+    },
+    {
+      name: 'parses blank CSV',
+      input: './test/data/blank.csv',
+      output: [
+        ['']
+      ]
+    }
+  ];
+  for (const { name, input, output } of vectors) {
+    test(name, { concurrency: true }, async () => {
+      await createCSVReadableStream(input).pipeTo(csvStreamEqualWritable(output));
+    });
+  }
 });
 
 suite('createCSVTransformStream', { concurrency: true }, () => {
@@ -144,22 +161,23 @@ suite('createCSVTransformStream', { concurrency: true }, () => {
     function timesTwo(row) {
       return [Number(row[0]) * 2, Number(row[1]) * 2];
     }
-    const stream = createCSVMockStream([
+    await createCSVMockStream([
       ['columnA', 'columnB'],
       ['1', '1'],
       ['100', '100'],
       ['223423', '455947'],
       ['348553', '692708'],
       ['536368', '676147']
-    ]).pipeThrough(createCSVTransformStream(timesTwo));
-    await csvStreamEqual(stream, [
-      ['columnA', 'columnB'],
-      [2, 2],
-      [200, 200],
-      [446846, 911894],
-      [697106, 1385416],
-      [1072736, 1352294]
-    ]);
+    ])
+      .pipeThrough(createCSVTransformStream(timesTwo))
+      .pipeTo(csvStreamEqualWritable([
+        ['columnA', 'columnB'],
+        [2, 2],
+        [200, 200],
+        [446846, 911894],
+        [697106, 1385416],
+        [1072736, 1352294]
+      ]));
   });
   test('can add new column', { concurrency: true }, async () => {
     let firstRow = true;
@@ -170,132 +188,130 @@ suite('createCSVTransformStream', { concurrency: true }, () => {
       }
       return [...row, Number(row[0]) + Number(row[1])];
     }
-    const stream = createCSVMockStream([
+    await createCSVMockStream([
       ['columnA', 'columnB'],
       ['1', '1'],
       ['100', '100'],
       ['223423', '455947'],
       ['348553', '692708'],
       ['536368', '676147']
-    ]).pipeThrough(createCSVTransformStream(sum, { includeHeaders: true }));
-    await csvStreamEqual(stream, [
-      ['columnA', 'columnB', 'sum'],
-      ['1', '1', 2],
-      ['100', '100', 200],
-      ['223423', '455947', 679370],
-      ['348553', '692708', 1041261],
-      ['536368', '676147', 1212515]
-    ]);
+    ])
+      .pipeThrough(createCSVTransformStream(sum, { includeHeaders: true }))
+      .pipeTo(csvStreamEqualWritable([
+        ['columnA', 'columnB', 'sum'],
+        ['1', '1', 2],
+        ['100', '100', 200],
+        ['223423', '455947', 679370],
+        ['348553', '692708', 1041261],
+        ['536368', '676147', 1212515]
+      ]));
   });
 });
 
 suite('createCSVWritableStream', { concurrency: true }, () => {
-  test('writes simple CSV', { concurrency: true }, async (t) => {
-    const temp = await createTempFile();
-    t.after(async () => await unlink(temp));
-    const csv = [
-      ['column1', 'column2', 'column3'],
-      ['abc', 'def', 'ghi'],
-      ['123', '456', '789'],
-      ['aaa', 'bbb', 'ccc']
-    ];
-    await createCSVMockStream(csv).pipeTo(createCSVWritableStream(temp));
-    await createCSVReadableStream(temp).pipeTo(csvStreamEqualWritable(csv));
-  });
-  test('writes escaping CSV', { concurrency: true }, async (t) => {
-    const temp = await createTempFile();
-    t.after(async () => await unlink(temp));
-    const csv = [
-      ['name', 'value'],
-      ['Three spaces', '   '],
-      ['Three commas', ',,,'],
-      ['Three newlines', '\r\n\r\n\r\n'],
-      ['Three unescaped double quotes', 'a"""'],
-      ['Three escaped double quotes', '"""'],
-      ['Unescaped double quotes around delimiter 1 "', 'a'],
-      ['Unescaped double quotes around delimiter 2 ""', 'a'],
-      ['Unescaped double quotes around delimiter 3 """', 'a'],
-      ['Unescaped double quotes around delimiter 4', ' "'],
-      ['Unescaped double quotes around delimiter 5', ' ""'],
-      ['Unescaped double quotes around delimiter 6', ' """'],
-      ['Spaces before and after a value', '   abc   '],
-      ['Spaces before and after three unescaped double quotes', '   """   '],
-      ['Spaces trailing escaped double quotes', 'abc   '],
-      ['Characters trailing escaped double quotes', 'abc def'],
-      ['Unescaped double quotes trailing escaped double quotes', 'abc " def 123 """ 456'],
-      ['Unescaped "double quotes" trailing escaped double quotes', 'abc """ def 123 """ 456'],
-      ['Unicode test 1', 'ไฝ ๅฅฝ'],
-      ['Unicode test 2', '๐Ÿ˜‚๐Ÿ‘Œ๐Ÿ‘'],
-      ['Unicode test 3', '๐Ÿดโ€โ˜ ๏ธ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ'],
-      ['Mixed', ',\r\n",\r\n",\r\n"']
-    ];
-    await createCSVMockStream(csv).pipeTo(createCSVWritableStream(temp));
-    await createCSVReadableStream(temp).pipeTo(csvStreamEqualWritable(csv));
-  });
-  test('writes escaping edges CSV', { concurrency: true }, async (t) => {
-    const temp = await createTempFile();
-    t.after(async () => await unlink(temp));
-    const csv = [
-      [',,,', '"""'],
-      ['"""', ',,,'],
-      ['a"b""', 'a"b""'],
-      ['a"b""', 'a"b""']
-    ];
-    await createCSVMockStream(csv).pipeTo(createCSVWritableStream(temp));
-    await createCSVReadableStream(temp).pipeTo(csvStreamEqualWritable(csv));
-  });
-  test('writes sparse CSV', { concurrency: true }, async (t) => {
-    const temp = await createTempFile();
-    t.after(async () => await unlink(temp));
-    const csv = [
-      ['column1', 'column2', 'column3'],
-      [''],
-      ['', ''],
-      ['', '', ''],
-      ['', '', '', ''],
-      ['', '', '', '', ''],
-      ['aaa', 'bbb', 'ccc'],
-      ['111', '222', '333', '444', '555', '666', '777', '888'],
-      ['', 'hhh', 'iii'],
-      ['ggg', '', 'iii'],
-      ['ggg', 'hhh', ''],
-      ['', 'hhh', ''],
-      ['ggg', '', ''],
-      ['', '', 'iii'],
-      ['', '', ''],
-      ['', '', ''],
-      ['', '', ''],
-      [''],
-      ['']
-    ];
-    await createCSVMockStream(csv).pipeTo(createCSVWritableStream(temp));
-    await createCSVReadableStream(temp).pipeTo(csvStreamEqualWritable(csv));
-  });
-  test('writes single value (no commas or newlines)', { concurrency: true }, async (t) => {
-    const temp = await createTempFile();
-    t.after(async () => await unlink(temp));
-    const csv = [
-      ['abc']
-    ];
-    await createCSVMockStream(csv).pipeTo(createCSVWritableStream(temp));
-    await createCSVReadableStream(temp).pipeTo(csvStreamEqualWritable(csv));
-  });
-  test('writes single row (no newlines) CSV', { concurrency: true }, async (t) => {
-    const temp = await createTempFile();
-    t.after(async () => await unlink(temp));
-    const csv = [
-      ['abc', 'def', 'ghi']
-    ];
-    await createCSVMockStream(csv).pipeTo(createCSVWritableStream(temp));
-    await createCSVReadableStream(temp).pipeTo(csvStreamEqualWritable(csv));
-  });
-  test('writes blank CSV', { concurrency: true }, async (t) => {
-    const temp = await createTempFile();
-    t.after(async () => await unlink(temp));
-    const csv = [
-      ['']
-    ];
-    await createCSVMockStream(csv).pipeTo(createCSVWritableStream(temp));
-    await createCSVReadableStream(temp).pipeTo(csvStreamEqualWritable(csv));
-  });
+  const vectors = [
+    {
+      name: 'writes simple CSV',
+      csv: [
+        ['column1', 'column2', 'column3'],
+        ['abc', 'def', 'ghi'],
+        ['123', '456', '789'],
+        ['aaa', 'bbb', 'ccc']
+      ]
+    },
+    {
+      name: 'writes escaping CSV',
+      csv: [
+        ['name', 'value'],
+        ['Three spaces', '   '],
+        ['Three commas', ',,,'],
+        ['Three newlines', '\r\n\r\n\r\n'],
+        ['Three unescaped double quotes', 'a"""'],
+        ['Three escaped double quotes', '"""'],
+        ['Unescaped double quotes around delimiter 1 "', 'a'],
+        ['Unescaped double quotes around delimiter 2 ""', 'a'],
+        ['Unescaped double quotes around delimiter 3 """', 'a'],
+        ['Unescaped double quotes around delimiter 4', ' "'],
+        ['Unescaped double quotes around delimiter 5', ' ""'],
+        ['Unescaped double quotes around delimiter 6', ' """'],
+        ['Spaces before and after a value', '   abc   '],
+        ['Spaces before and after three unescaped double quotes', '   """   '],
+        ['Spaces trailing escaped double quotes', 'abc   '],
+        ['Characters trailing escaped double quotes', 'abc def'],
+        ['Unescaped double quotes trailing escaped double quotes', 'abc " def 123 """ 456'],
+        ['Unescaped "double quotes" trailing escaped double quotes', 'abc """ def 123 """ 456'],
+        ['Unicode test 1', 'ไฝ ๅฅฝ'],
+        ['Unicode test 2', '๐Ÿ˜‚๐Ÿ‘Œ๐Ÿ‘'],
+        ['Unicode test 3', '๐Ÿดโ€โ˜ ๏ธ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ'],
+        ['Mixed', ',\r\n",\r\n",\r\n"']
+      ]
+    },
+    {
+      name: 'writes escaping edges CSV',
+      csv: [
+        [',,,', '"""'],
+        ['"""', ',,,'],
+        ['a"b""', 'a"b""'],
+        ['a"b""', 'a"b""']
+      ]
+    },
+    {
+      name: 'writes sparse CSV',
+      csv: [
+        ['column1', 'column2', 'column3'],
+        [''],
+        ['', ''],
+        ['', '', ''],
+        ['', '', '', ''],
+        ['', '', '', '', ''],
+        ['aaa', 'bbb', 'ccc'],
+        ['111', '222', '333', '444', '555', '666', '777', '888'],
+        ['', 'hhh', 'iii'],
+        ['ggg', '', 'iii'],
+        ['ggg', 'hhh', ''],
+        ['', 'hhh', ''],
+        ['ggg', '', ''],
+        ['', '', 'iii'],
+        ['', '', ''],
+        ['', '', ''],
+        ['', '', ''],
+        [''],
+        ['']
+      ]
+    },
+    {
+      name: 'writes single value (no commas or newlines) CSV',
+      csv: [
+        ['abc']
+      ]
+    },
+    {
+      name: 'writes single column (no commas) CSV',
+      csv: [
+        ['abc'],
+        ['def'],
+        ['ghi']
+      ]
+    },
+    {
+      name: 'writes single row (no newlines) CSV',
+      csv: [
+        ['abc', 'def', 'ghi']
+      ]
+    },
+    {
+      name: 'writes blank CSV',
+      csv: [
+        ['']
+      ]
+    }
+  ];
+  for (const { name, csv } of vectors) {
+    test(name, { concurrency: true }, async (t) => {
+      const temp = await createTempFile();
+      t.after(async () => await unlink(temp));
+      await createCSVMockStream(csv).pipeTo(createCSVWritableStream(temp));
+      await createCSVReadableStream(temp).pipeTo(csvStreamEqualWritable(csv));
+    });
+  }
 });
\ No newline at end of file
This page took 0.049802 seconds and 4 git commands to generate.