From 88f08e8864bf25a2a609b1d6c0a4daacff25558b Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Fri, 7 May 2021 05:26:08 +0500 Subject: [PATCH] fix: removed extra slash + added tests --- src/utils/convertToCsv.spec.ts | 93 ++++++++++++++++++++++++++++++++++ src/utils/convertToCsv.ts | 16 +++--- 2 files changed, 103 insertions(+), 6 deletions(-) diff --git a/src/utils/convertToCsv.spec.ts b/src/utils/convertToCsv.spec.ts index aad5146..b6e48bd 100644 --- a/src/utils/convertToCsv.spec.ts +++ b/src/utils/convertToCsv.spec.ts @@ -72,4 +72,97 @@ describe('convertToCsv', () => { expect(convertToCSV(data)).toEqual(expectedOutput) }) + + it('should convert values with number cases 1', () => { + const data = [ + { col1: 42, col2: null, col3: 'x', col4: null }, + { col1: 42, col2: null, col3: 'x', col4: null }, + { col1: 42, col2: null, col3: 'x', col4: null }, + { col1: 42, col2: null, col3: 'x', col4: '' }, + { col1: 42, col2: null, col3: 'x', col4: '' } + ] + + const expectedOutput = `col1:best. col2:best. col3:$1. col4:$1.\r\n42,.,x,\r\n42,.,x,\r\n42,.,x,\r\n42,.,x,\r\n42,.,x,` + + expect(convertToCSV(data)).toEqual(expectedOutput) + }) + + it('should convert values with number cases 2', () => { + const data = [ + { col1: 42, col2: null, col3: 'x', col4: '' }, + { col1: 42, col2: null, col3: 'x', col4: '' }, + { col1: 42, col2: null, col3: 'x', col4: '' }, + { col1: 42, col2: 1.62, col3: 'x', col4: 'x' }, + { col1: 42, col2: 1.62, col3: 'x', col4: 'x' } + ] + + const expectedOutput = `col1:best. col2:best. col3:$1. col4:$1.\r\n42,.,x,\r\n42,.,x,\r\n42,.,x,\r\n42,1.62,x,x\r\n42,1.62,x,x` + + expect(convertToCSV(data)).toEqual(expectedOutput) + }) + + it('should convert values with common special characters', () => { + expect(convertToCSV([{ tab: '\t' }])).toEqual(`tab:$1.\r\n\"\t\"`) + expect(convertToCSV([{ lf: '\n' }])).toEqual(`lf:$1.\r\n\"\n\"`) + expect(convertToCSV([{ semicolon: ';semi' }])).toEqual( + `semicolon:$5.\r\n;semi` + ) + expect(convertToCSV([{ percent: '%' }])).toEqual(`percent:$1.\r\n%`) + expect(convertToCSV([{ singleQuote: "'" }])).toEqual( + `singleQuote:$1.\r\n\"'\"` + ) + expect(convertToCSV([{ doubleQuote: '"' }])).toEqual( + `doubleQuote:$1.\r\n""""` + ) + expect(convertToCSV([{ crlf: '\r\n' }])).toEqual(`crlf:$2.\r\n\"\n\"`) + expect(convertToCSV([{ euro: '€euro' }])).toEqual(`euro:$7.\r\n€euro`) + expect(convertToCSV([{ banghash: '!#banghash' }])).toEqual( + `banghash:$10.\r\n!#banghash` + ) + }) + + it('should convert values with other special characters', () => { + const data = [ + { + speech0: '"speech', + pct: '%percent', + speech: '"speech', + slash: '\\slash', + slashWithSpecial: '\\\tslash', + macvar: '&sysuserid', + chinese: '传/傳chinese', + sigma: 'Σsigma', + at: '@at', + serbian: 'Српски', + dollar: '$' + } + ] + + const expectedOutput = `speech0:$7. pct:$8. speech:$7. slash:$6. slashWithSpecial:$7. macvar:$10. chinese:$14. sigma:$7. at:$3. serbian:$12. dollar:$1.\r\n"""speech",%percent,"""speech",\\slash,\"\\\tslash\",&sysuserid,传/傳chinese,Σsigma,@at,Српски,$` + + expect(convertToCSV(data)).toEqual(expectedOutput) + + expect(convertToCSV([{ speech: 'menext' }])).toEqual(`speech:$6.\r\nmenext`) + expect(convertToCSV([{ speech: 'me\nnext' }])).toEqual( + `speech:$7.\r\n\"me\nnext\"` + ) + expect(convertToCSV([{ speech: `me'next` }])).toEqual( + `speech:$7.\r\n\"me'next\"` + ) + expect(convertToCSV([{ speech: `me"next` }])).toEqual( + `speech:$7.\r\n\"me""next\"` + ) + expect(convertToCSV([{ speech: `me""next` }])).toEqual( + `speech:$8.\r\n\"me""""next\"` + ) + expect(convertToCSV([{ slashWithSpecial: '\\\tslash' }])).toEqual( + `slashWithSpecial:$7.\r\n\"\\\tslash\"` + ) + expect(convertToCSV([{ slashWithSpecial: '\\ \tslash' }])).toEqual( + `slashWithSpecial:$8.\r\n\"\\ \tslash\"` + ) + expect( + convertToCSV([{ slashWithSpecialExtra: '\\\ts\tl\ta\ts\t\th\t' }]) + ).toEqual(`slashWithSpecialExtra:$13.\r\n\"\\\ts\tl\ta\ts\t\th\t\"`) + }) }) diff --git a/src/utils/convertToCsv.ts b/src/utils/convertToCsv.ts index d6d0841..8260a93 100644 --- a/src/utils/convertToCsv.ts +++ b/src/utils/convertToCsv.ts @@ -71,15 +71,19 @@ export const convertToCSV = (data: any) => { let value const currentCell = row[fieldName] - // stringify with replacer converts null values to empty strings - // also wraps the value in double quotes - value = JSON.stringify(currentCell, replacer).replace(/\\\"/g, `""`) + if (typeof currentCell === 'number') return currentCell - value = value.replace(/\\\\/gm, '\\') + // stringify with replacer converts null values to empty strings + value = currentCell === null ? '' : currentCell + + // if there any present, it should have preceding (") for escaping + value = value.replace(/"/g, `""`) + + // also wraps the value in double quotes + value = `"${value}"` if ( - value.substring(1, value.length - 1).search(/(\\t|\\n|\\r|,|\'|\")/gm) < - 0 + value.substring(1, value.length - 1).search(/(\t|\n|\r|,|\'|\")/gm) < 0 ) { // Remove wrapping quotes for values that don't contain special characters value = value.substring(1, value.length - 1)