From 972ac5e244c3730d293db13664ed9d6fb039e5ac Mon Sep 17 00:00:00 2001 From: Alex Anderson <191496+alxndrsn@users.noreply.github.com> Date: Thu, 5 Dec 2024 12:21:04 +0300 Subject: [PATCH] test/util/zip: processZipFile(): prevent filename clashes (#1310) Separating file data and meta data prevents clashes for files with names including: * `filenames` * `toString` * etc. --- test/integration/api/submissions.js | 86 ++++++++++---------- test/integration/other/encryption.js | 44 +++++----- test/integration/other/submission-purging.js | 2 +- test/unit/data/attachments.js | 6 +- test/unit/data/briefcase.js | 60 +++++++------- test/unit/util/zip.js | 41 ++++++++-- test/util/zip.js | 12 +-- 7 files changed, 137 insertions(+), 114 deletions(-) diff --git a/test/integration/api/submissions.js b/test/integration/api/submissions.js index fe7794b69..21679c99e 100644 --- a/test/integration/api/submissions.js +++ b/test/integration/api/submissions.js @@ -1567,7 +1567,7 @@ describe('api: /forms/:id/submissions', () => { service.login('alice', (asAlice) => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/simple/submissions.csv.zip')) .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - result['simple.csv'].should.equal('SubmissionDate,meta-instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion\n'); + result.files.get('simple.csv').should.equal('SubmissionDate,meta-instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion\n'); })))); it('should return a zipfile with the relevant data', testService((service) => @@ -1587,7 +1587,7 @@ describe('api: /forms/:id/submissions', () => { .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/simple/submissions.csv.zip')) .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - result['simple.csv'].should.be.a.SimpleCsv(); + result.files.get('simple.csv').should.be.a.SimpleCsv(); }))))); it('should include all repeat rows @slow', testService(async (service) => { @@ -1616,8 +1616,8 @@ describe('api: /forms/:id/submissions', () => { } const result = await httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/single-repeat-1-instance-10qs/submissions.csv.zip')); result.filenames.should.eql([ 'single-repeat-1-instance-10qs.csv', 'single-repeat-1-instance-10qs-repeat.csv' ]); - result['single-repeat-1-instance-10qs.csv'].split('\n').length.should.equal(52); - result['single-repeat-1-instance-10qs-repeat.csv'].split('\n').length.should.equal(52); + result.files.get('single-repeat-1-instance-10qs.csv').split('\n').length.should.equal(52); + result.files.get('single-repeat-1-instance-10qs-repeat.csv').split('\n').length.should.equal(52); })); it('should not include data from other forms', testService((service) => @@ -1642,7 +1642,7 @@ describe('api: /forms/:id/submissions', () => { .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/simple/submissions.csv.zip')) .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - const csv = result['simple.csv'].split('\n').map((row) => row.split(',')); + const csv = result.files.get('simple.csv').split('\n').map((row) => row.split(',')); csv.length.should.equal(4); // header + 2 data rows + newline csv[0].should.eql([ 'SubmissionDate', 'meta-instanceID', 'name', 'age', 'KEY', 'SubmitterID', 'SubmitterName', 'AttachmentsPresent', 'AttachmentsExpected', 'Status', 'ReviewState', 'DeviceID', 'Edits', 'FormVersion' ]); csv[1].shift().should.be.an.recentIsoDate(); @@ -1675,7 +1675,7 @@ describe('api: /forms/:id/submissions', () => { await asAlice.delete('/v1/projects/1/forms/simple/submissions/two'); const result = await httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/simple/submissions.csv.zip')); - const csv = result['simple.csv'].split('\n').map((row) => row.split(',')); + const csv = result.files.get('simple.csv').split('\n').map((row) => row.split(',')); csv.length.should.equal(4); // header + 2 data rows + newline csv[0].should.eql([ 'SubmissionDate', 'meta-instanceID', 'name', 'age', 'KEY', 'SubmitterID', 'SubmitterName', 'AttachmentsPresent', 'AttachmentsExpected', 'Status', 'ReviewState', 'DeviceID', 'Edits', 'FormVersion' ]); csv[1].shift().should.be.an.recentIsoDate(); @@ -1705,7 +1705,7 @@ describe('api: /forms/:id/submissions', () => { .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/simple/submissions.csv.zip?$filter=__system/submitterId eq 5')) .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - const lines = result['simple.csv'].split('\n'); + const lines = result.files.get('simple.csv').split('\n'); lines.length.should.equal(4); lines[1].endsWith(',three,Chelsea,38,three,5,Alice,0,0,,,,0,').should.equal(true); lines[2].endsWith(',one,Alice,30,one,5,Alice,0,0,,,,0,').should.equal(true); @@ -1731,7 +1731,7 @@ describe('api: /forms/:id/submissions', () => { .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/simple/submissions.csv.zip?$filter=__system/reviewState eq null')) .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - const lines = result['simple.csv'].split('\n'); + const lines = result.files.get('simple.csv').split('\n'); lines.length.should.equal(4); lines[1].endsWith(',three,Chelsea,38,three,5,Alice,0,0,,,,0,').should.equal(true); lines[2].endsWith(',one,Alice,30,one,5,Alice,0,0,,,,0,').should.equal(true); @@ -1752,7 +1752,7 @@ describe('api: /forms/:id/submissions', () => { .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/simple/submissions.csv.zip?$filter=year(__system/submissionDate) eq 2010')) .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - const lines = result['simple.csv'].split('\n'); + const lines = result.files.get('simple.csv').split('\n'); lines.length.should.equal(3); lines[1].endsWith(',one,Alice,30,one,5,Alice,0,0,,,,0,').should.equal(true); })))))); @@ -1773,7 +1773,7 @@ describe('api: /forms/:id/submissions', () => { .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/simple/submissions.csv.zip?$filter=__system/updatedAt eq null')) .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - const lines = result['simple.csv'].split('\n'); + const lines = result.files.get('simple.csv').split('\n'); lines.length.should.equal(3); lines[1].endsWith(',one,Alice,30,one,5,Alice,0,0,,,,0,').should.equal(true); }))))); @@ -1802,11 +1802,11 @@ describe('api: /forms/:id/submissions', () => { 'media/here_is_file2.jpg' ]); - result['media/my_file1.mp4'].should.equal('this is test file one'); - result['media/here_is_file2.jpg'].should.equal('this is test file two'); + result.files.get('media/my_file1.mp4').should.equal('this is test file one'); + result.files.get('media/here_is_file2.jpg').should.equal('this is test file two'); // we also check the csv for the sake of verifying the attachments counts. - const csv = result['binaryType.csv'].split('\n'); + const csv = result.files.get('binaryType.csv').split('\n'); csv[0].should.equal('SubmissionDate,meta-instanceID,file1,file2,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); csv[1].should.endWith(',both,my_file1.mp4,here_is_file2.jpg,both,5,Alice,2,2,,,,0,'); csv.length.should.equal(3); // newline at end @@ -1838,11 +1838,11 @@ describe('api: /forms/:id/submissions', () => { 'media/here_is_file2.jpg' ]); - result['media/my_file1.mp4'].should.equal('this is test file one'); - result['media/here_is_file2.jpg'].should.equal('this is test file two'); + result.files.get('media/my_file1.mp4').should.equal('this is test file one'); + result.files.get('media/here_is_file2.jpg').should.equal('this is test file two'); // we also check the csv for the sake of verifying the attachments counts. - const csv = result['binaryType.csv'].split('\n'); + const csv = result.files.get('binaryType.csv').split('\n'); csv[0].should.equal('SubmissionDate,meta-instanceID,file1,file2,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); csv[1].should.endWith(',both,my_file1.mp4,here_is_file2.jpg,both,5,Alice,2,2,,,,0,'); csv.length.should.equal(3); // newline at end @@ -1928,7 +1928,7 @@ describe('api: /forms/:id/submissions', () => { .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/simple/submissions.csv.zip')) .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - const lines = result['simple.csv'].split('\n'); + const lines = result.files.get('simple.csv').split('\n'); lines[1].endsWith('0,updated').should.equal(true); lines[2].endsWith('0,').should.equal(true); lines[3].endsWith('1,').should.equal(true); @@ -1949,7 +1949,7 @@ describe('api: /forms/:id/submissions', () => { .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/selectMultiple/submissions.csv.zip?splitSelectMultiples=true')) .then((result) => { result.filenames.should.containDeep([ 'selectMultiple.csv' ]); - const lines = result['selectMultiple.csv'].split('\n'); + const lines = result.files.get('selectMultiple.csv').split('\n'); lines[0].should.equal('SubmissionDate,meta-instanceID,q1,q1/a,q1/b,g1-q2,g1-q2/m,g1-q2/x,g1-q2/y,g1-q2/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); lines[1].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) .should.equal(',two,b,0,1,m x,1,1,0,0,two,5,Alice,0,0,,,,0,'); @@ -1971,7 +1971,7 @@ describe('api: /forms/:id/submissions', () => { .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/selectMultiple/submissions.csv.zip?splitSelectMultiples=true')) .then((result) => { result.filenames.should.containDeep([ 'selectMultiple.csv' ]); - const lines = result['selectMultiple.csv'].split('\n'); + const lines = result.files.get('selectMultiple.csv').split('\n'); lines[0].should.equal('SubmissionDate,meta-instanceID,q1,g1-q2,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); lines[1].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) .should.equal(',two,b,m x,two,5,Alice,0,0,,,,0,'); @@ -1995,7 +1995,7 @@ describe('api: /forms/:id/submissions', () => { .then(() => exhaust(container)) .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/selectMultiple/submissions.csv.zip?splitSelectMultiples=true&$filter=__system/reviewState eq null')) .then((result) => { - const lines = result['selectMultiple.csv'].split('\n'); + const lines = result.files.get('selectMultiple.csv').split('\n'); lines.length.should.equal(3); lines[1].should.containEql(',one,'); lines[1].should.not.containEql('two'); @@ -2036,7 +2036,7 @@ describe('api: /forms/:id/submissions', () => { .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/simple/submissions.csv.zip?deletedFields=true')) .then((result) => { result.filenames.should.containDeep([ 'simple.csv' ]); - const lines = result['simple.csv'].split('\n'); + const lines = result.files.get('simple.csv').split('\n'); lines[0].should.equal('SubmissionDate,meta-instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); lines[1].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) .should.equal(',three,Chelsea,38,three,5,Alice,0,0,,,,0,2'); @@ -2066,8 +2066,8 @@ describe('api: /forms/:id/submissions', () => { .then((result) => { result.filenames.should.containDeep([ 'binaryType.csv' ]); - should.not.exist(result['media/my_file1.mp4']); - should.not.exist(result['media/here_is_file2.jpg']); + should.not.exist(result.files.get('media/my_file1.mp4')); + should.not.exist(result.files.get('media/here_is_file2.jpg')); })))))); @@ -2096,7 +2096,7 @@ describe('api: /forms/:id/submissions', () => { .expect(201) .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/simple/submissions.csv.zip?groupPaths=false')) .then((result) => { - const csv = result['simple.csv'].split('\n'); + const csv = result.files.get('simple.csv').split('\n'); csv[0].should.equal('SubmissionDate,instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); }))))); @@ -2115,7 +2115,7 @@ describe('api: /forms/:id/submissions', () => { .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/selectMultiple/submissions.csv.zip?splitSelectMultiples=true&groupPaths=false')) .then((result) => { result.filenames.should.containDeep([ 'selectMultiple.csv' ]); - const lines = result['selectMultiple.csv'].split('\n'); + const lines = result.files.get('selectMultiple.csv').split('\n'); lines[0].should.equal('SubmissionDate,instanceID,q1,q1/a,q1/b,q2,q2/m,q2/x,q2/y,q2/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); lines[1].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) .should.equal(',two,b,0,1,m x,1,1,0,0,two,5,Alice,0,0,,,,0,'); @@ -2142,7 +2142,7 @@ describe('api: /forms/:id/submissions', () => { ]); // we also check the csv for the sake of verifying the attachments counts. - const csv = result['binaryType.csv'].split('\n'); + const csv = result.files.get('binaryType.csv').split('\n'); csv[0].should.equal('SubmissionDate,meta-instanceID,file1,file2,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); csv[1].should.endWith(',both,my_file1.mp4,here_is_file2.jpg,both,5,Alice,1,2,,,,0,'); csv.length.should.equal(3); // newline at end @@ -2173,7 +2173,7 @@ describe('api: /forms/:id/submissions', () => { 'audits - audit.csv' ]); - result['audits - audit.csv'].should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value + result.files.get('audits - audit.csv').should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value one,a,/data/a,2000-01-01T00:01,2000-01-01T00:02,1,2,3,aa,bb one,b,/data/b,2000-01-01T00:02,2000-01-01T00:03,4,5,6,cc,dd one,c,/data/c,2000-01-01T00:03,2000-01-01T00:04,7,8,9,ee,ff @@ -2210,7 +2210,7 @@ two,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff 'audits - audit.csv' ]); - result['audits - audit.csv'].should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value + result.files.get('audits - audit.csv').should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value one,a,/data/a,2000-01-01T00:01,2000-01-01T00:02,1,2,3,aa,bb one,b,/data/b,2000-01-01T00:02,2000-01-01T00:03,4,5,6,cc,dd one,c,/data/c,2000-01-01T00:03,2000-01-01T00:04,7,8,9,ee,ff @@ -2251,7 +2251,7 @@ two,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff 'audits - audit.csv' ]); - result['audits - audit.csv'].should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value + result.files.get('audits - audit.csv').should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value one,a,/data/a,2000-01-01T00:01,2000-01-01T00:02,1,2,3,aa,bb one,b,/data/b,2000-01-01T00:02,2000-01-01T00:03,4,5,6,cc,dd one,c,/data/c,2000-01-01T00:03,2000-01-01T00:04,7,8,9,ee,ff @@ -2316,7 +2316,7 @@ two,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff 'audits - audit.csv' ]); - result['audits - audit.csv'].should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value + result.files.get('audits - audit.csv').should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value one,a,/data/a,2000-01-01T00:01,2000-01-01T00:02,1,2,3,aa,bb one,b,/data/b,2000-01-01T00:02,2000-01-01T00:03,4,5,6,cc,dd one,c,/data/c,2000-01-01T00:03,2000-01-01T00:04,7,8,9,ee,ff @@ -2352,7 +2352,7 @@ one,e,/data/e,2000-01-01T00:11,,,,,hh,ii 'audits - audit.csv' ]); - result['audits - audit.csv'].should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value + result.files.get('audits - audit.csv').should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value one,a,/data/a,2000-01-01T00:01,2000-01-01T00:02,1,2,3,aa,bb one,b,/data/b,2000-01-01T00:02,2000-01-01T00:03,4,5,6,cc,dd one,c,/data/c,2000-01-01T00:03,2000-01-01T00:04,7,8,9,ee,ff @@ -2387,7 +2387,7 @@ one,e,/data/e,2000-01-01T00:11,,,,,hh,ii 'audits - audit.csv' ]); - result['audits - audit.csv'].should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value + result.files.get('audits - audit.csv').should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value one,f,/data/f,2000-01-01T00:04,2000-01-01T00:05,-1,-2,,aa,bb one,g,/data/g,2000-01-01T00:05,2000-01-01T00:06,-3,-4,,cc,dd one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff @@ -2419,7 +2419,7 @@ one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff 'audits - audit.csv' ]); - result['audits - audit.csv'].should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value + result.files.get('audits - audit.csv').should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value one,f,/data/f,2000-01-01T00:04,2000-01-01T00:05,-1,-2,,aa,bb one,g,/data/g,2000-01-01T00:05,2000-01-01T00:06,-3,-4,,cc,dd one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff @@ -2447,7 +2447,7 @@ one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff 'audits - audit.csv' ]); - result['audits - audit.csv'].should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value + result.files.get('audits - audit.csv').should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value one,a,/data/a,2000-01-01T00:01,2000-01-01T00:02,1,2,3,aa,bb one,b,/data/b,2000-01-01T00:02,2000-01-01T00:03,4,5,6,cc,dd one,c,/data/c,2000-01-01T00:03,2000-01-01T00:04,7,8,9,ee,ff @@ -2476,7 +2476,7 @@ one,e,/data/e,2000-01-01T00:11,,,,,hh,ii 'audits - audit.csv' ]); - result['audits - audit.csv'].should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value + result.files.get('audits - audit.csv').should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value one,a,/data/a,2000-01-01T00:01,2000-01-01T00:02,1,2,3,aa,bb one,b,/data/b,2000-01-01T00:02,2000-01-01T00:03,4,5,6,cc,dd one,c,/data/c,2000-01-01T00:03,2000-01-01T00:04,7,8,9,ee,ff @@ -2514,7 +2514,7 @@ one,e,/data/e,2000-01-01T00:11,,,,,hh,ii 'audits - audit.csv' ]); - result['audits - audit.csv'].should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value + result.files.get('audits - audit.csv').should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value one,f,/data/f,2000-01-01T00:04,2000-01-01T00:05,-1,-2,,aa,bb one,g,/data/g,2000-01-01T00:05,2000-01-01T00:06,-3,-4,,cc,dd one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff @@ -2687,7 +2687,7 @@ one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/simple/submissions.csv.zip?deletedFields=true')) .then((result) => { result.filenames.should.containDeep([ 'simple.csv' ]); - const lines = result['simple.csv'].split('\n'); + const lines = result.files.get('simple.csv').split('\n'); lines[0].should.equal('SubmissionDate,meta-instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); lines[1].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) .should.equal(',three,Chelsea,38,three,5,Alice,0,0,,,,0,3'); @@ -2790,7 +2790,7 @@ one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff .then((result) => { result.filenames.should.containDeep([ 'simple.csv' ]); - const csv = result['simple.csv'].split('\n').map((row) => row.split(',')); + const csv = result.files.get('simple.csv').split('\n').map((row) => row.split(',')); csv.length.should.equal(3); // header + data row + newline csv[0].should.eql([ 'SubmissionDate', 'meta-instanceID', 'name', 'age', 'KEY', 'SubmitterID', 'SubmitterName', 'AttachmentsPresent', 'AttachmentsExpected', 'Status', 'ReviewState', 'DeviceID', 'Edits', 'FormVersion' ]); csv[1].shift().should.be.an.recentIsoDate(); @@ -2812,7 +2812,7 @@ one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff .then((result) => { result.filenames.should.containDeep([ 'simple.csv' ]); - result['simple.csv'].should.equal('SubmissionDate,meta-instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion\n'); + result.files.get('simple.csv').should.equal('SubmissionDate,meta-instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion\n'); })))))); it('should not carry draft submissions forward to the published version upon publish', testService((service) => @@ -2831,7 +2831,7 @@ one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff .then((result) => { result.filenames.should.containDeep([ 'simple.csv' ]); - result['simple.csv'].should.equal('SubmissionDate,meta-instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion\n'); + result.files.get('simple.csv').should.equal('SubmissionDate,meta-instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion\n'); })))))); it('should not carry over drafts when a draft is replaced', testService((service) => @@ -2850,7 +2850,7 @@ one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff .then((result) => { result.filenames.should.containDeep([ 'simple.csv' ]); - result['simple.csv'].should.equal('SubmissionDate,meta-instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion\n'); + result.files.get('simple.csv').should.equal('SubmissionDate,meta-instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion\n'); })))))); it('should not resurface drafts when a draft is recreated', testService((service) => @@ -2871,7 +2871,7 @@ one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff .then((result) => { result.filenames.should.containDeep([ 'simple.csv' ]); - result['simple.csv'].should.equal('SubmissionDate,meta-instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion\n'); + result.files.get('simple.csv').should.equal('SubmissionDate,meta-instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion\n'); })))))); it('should not log the action in the audit log', testService((service) => @@ -2906,7 +2906,7 @@ one,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff .then(() => httpZipResponseToFiles(asAlice.get('/v1/projects/1/forms/selectMultiple/draft/submissions.csv.zip?splitSelectMultiples=true')) .then((result) => { result.filenames.should.containDeep([ 'selectMultiple.csv' ]); - const lines = result['selectMultiple.csv'].split('\n'); + const lines = result.files.get('selectMultiple.csv').split('\n'); lines[0].should.equal('SubmissionDate,meta-instanceID,q1,q1/a,q1/b,g1-q2,g1-q2/m,g1-q2/x,g1-q2/y,g1-q2/z,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion'); lines[1].slice('yyyy-mm-ddThh:mm:ss._msZ'.length) .should.equal(',two,b,0,1,m x,1,1,0,0,two,,,0,0,,,,0,'); diff --git a/test/integration/other/encryption.js b/test/integration/other/encryption.js index 3da709ee2..0b5cbfb1f 100644 --- a/test/integration/other/encryption.js +++ b/test/integration/other/encryption.js @@ -223,7 +223,7 @@ describe('managed encryption', () => { .then((keyId) => httpZipResponseToFiles(asAlice.get(`/v1/projects/1/forms/simple/submissions.csv.zip?${keyId}=supersecret`)) .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - result['simple.csv'].should.be.an.EncryptedSimpleCsv(); + result.files.get('simple.csv').should.be.an.EncryptedSimpleCsv(); }))))); it('should decrypt to CSV successfully if submissions uploaded to S3', testService((service, { Blobs }) => { @@ -249,7 +249,7 @@ describe('managed encryption', () => { .then((keyId) => httpZipResponseToFiles(asAlice.get(`/v1/projects/1/forms/simple/submissions.csv.zip?${keyId}=supersecret`)) .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - result['simple.csv'].should.be.an.EncryptedSimpleCsv(); + result.files.get('simple.csv').should.be.an.EncryptedSimpleCsv(); })) .then(() => { global.s3.downloads.attempted.should.equal(3); @@ -294,7 +294,7 @@ describe('managed encryption', () => { .set('Content-Type', 'application/x-www-form-urlencoded')) .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - result['simple.csv'].should.be.an.EncryptedSimpleCsv(); + result.files.get('simple.csv').should.be.an.EncryptedSimpleCsv(); }))))); it('should decrypt over cookie auth with passphrases provided via url-encoded POST body', testService((service) => @@ -321,7 +321,7 @@ describe('managed encryption', () => { .set('Content-Type', 'application/x-www-form-urlencoded')) .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - result['simple.csv'].should.be.an.EncryptedSimpleCsv(); + result.files.get('simple.csv').should.be.an.EncryptedSimpleCsv(); }))))); it('should decrypt with passphrases provide via JSON POST body', testService((service) => @@ -342,7 +342,7 @@ describe('managed encryption', () => { .send({ [keyId]: 'supersecret' })) .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - result['simple.csv'].should.be.an.EncryptedSimpleCsv(); + result.files.get('simple.csv').should.be.an.EncryptedSimpleCsv(); }))))); it('should decrypt attached files successfully', testService((service) => @@ -363,9 +363,9 @@ describe('managed encryption', () => { result.filenames.length.should.equal(4); result.filenames.should.containDeep([ 'simple.csv', 'media/alpha', 'media/beta', 'media/charlie' ]); - result['media/alpha'].should.equal('hello this is file alpha'); - result['media/beta'].should.equal('and beta'); - result['media/charlie'].should.equal('file charlie is right here'); + result.files.get('media/alpha').should.equal('hello this is file alpha'); + result.files.get('media/beta').should.equal('and beta'); + result.files.get('media/charlie').should.equal('file charlie is right here'); }))))); it('should decrypt attached files successfully when s3 enabled', testService((service, { Blobs }) => { @@ -388,9 +388,9 @@ describe('managed encryption', () => { result.filenames.length.should.equal(4); result.filenames.should.containDeep([ 'simple.csv', 'media/alpha', 'media/beta', 'media/charlie' ]); - result['media/alpha'].should.equal('hello this is file alpha'); - result['media/beta'].should.equal('and beta'); - result['media/charlie'].should.equal('file charlie is right here'); + result.files.get('media/alpha').should.equal('hello this is file alpha'); + result.files.get('media/beta').should.equal('and beta'); + result.files.get('media/charlie').should.equal('file charlie is right here'); }))); })); @@ -432,7 +432,7 @@ describe('managed encryption', () => { result.filenames.length.should.equal(2); result.filenames.should.containDeep([ 'simple.csv', 'media/testfile.jpg' ]); - result['media/testfile.jpg'].should.equal('hello this is a suffixed file'); + result.files.get('media/testfile.jpg').should.equal('hello this is a suffixed file'); })))))); it('should skip encrypted client audit log attachments and mark them as processed', testService((service, container) => @@ -480,7 +480,7 @@ describe('managed encryption', () => { 'audits - audit.csv' ]); - result['audits - audit.csv'].should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value + result.files.get('audits - audit.csv').should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value one,a,/data/a,2000-01-01T00:01,2000-01-01T00:02,1,2,3,aa,bb one,b,/data/b,2000-01-01T00:02,2000-01-01T00:03,4,5,6,cc,dd one,c,/data/c,2000-01-01T00:03,2000-01-01T00:04,7,8,9,ee,ff @@ -522,7 +522,7 @@ two,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff 'audits - audit.csv' ]); - result['audits - audit.csv'].should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value + result.files.get('audits - audit.csv').should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value one,a,/data/a,2000-01-01T00:01,2000-01-01T00:02,1,2,3,aa,bb one,b,/data/b,2000-01-01T00:02,2000-01-01T00:03,4,5,6,cc,dd one,c,/data/c,2000-01-01T00:03,2000-01-01T00:04,7,8,9,ee,ff @@ -560,7 +560,7 @@ two,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff result.filenames.length.should.equal(2); result.filenames.should.containDeep([ 'binaryType.csv', 'media/my_file1.mp4' ]); - result['media/my_file1.mp4'].should.equal('this is file one'); + result.files.get('media/my_file1.mp4').should.equal('this is file one'); }))))); it('should handle mixed [plaintext/encrypted] attachments (decrypting)', testService((service) => @@ -591,8 +591,8 @@ two,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff result.filenames.length.should.equal(3); result.filenames.should.containDeep([ 'binaryType.csv', 'media/my_file1.mp4', 'media/here_is_file2.jpg' ]); - result['media/my_file1.mp4'].should.equal('this is file one'); - result['media/here_is_file2.jpg'].should.equal('file two you can see'); + result.files.get('media/my_file1.mp4').should.equal('this is file one'); + result.files.get('media/here_is_file2.jpg').should.equal('file two you can see'); }))))); it('should handle mixed[plaintext/encrypted] formdata (decrypting)', testService((service) => @@ -615,7 +615,7 @@ two,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff .then((keyId) => httpZipResponseToFiles(asAlice.get(`/v1/projects/1/forms/simple/submissions.csv.zip?${keyId}=supersecret`)) .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - const csv = result['simple.csv'].split('\n').map((row) => row.split(',')); + const csv = result.files.get('simple.csv').split('\n').map((row) => row.split(',')); csv.length.should.equal(5); // header + 3 data rows + newline csv[0].should.eql([ 'SubmissionDate', 'meta-instanceID', 'name', 'age', 'KEY', 'SubmitterID', 'SubmitterName', 'AttachmentsPresent', 'AttachmentsExpected', 'Status', 'ReviewState', 'DeviceID', 'Edits', 'FormVersion' ]); csv[1].shift().should.be.an.recentIsoDate(); @@ -650,7 +650,7 @@ two,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - const csv = result['simple.csv'].split('\n').map((row) => row.split(',')); + const csv = result.files.get('simple.csv').split('\n').map((row) => row.split(',')); csv.length.should.equal(5); // header + 3 data rows + newline csv[0].should.eql([ 'SubmissionDate', 'meta-instanceID', 'name', 'age', 'KEY', 'SubmitterID', 'SubmitterName', 'AttachmentsPresent', 'AttachmentsExpected', 'Status', 'ReviewState', 'DeviceID', 'Edits', 'FormVersion' ]); csv[1].shift().should.be.an.recentIsoDate(); @@ -709,7 +709,7 @@ two,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff .then(({ body }) => body.map((key) => key.id))) .then((keyIds) => httpZipResponseToFiles(asAlice.get(`/v1/projects/1/forms/simple/submissions.csv.zip?${keyIds[1]}=supersecret&${keyIds[0]}=superdupersecret`)) .then((result) => { - const csv = result['simple.csv'].split('\n').map((row) => row.split(',')); + const csv = result.files.get('simple.csv').split('\n').map((row) => row.split(',')); csv.length.should.equal(5); // header + 3 data rows + newline csv[0].should.eql([ 'SubmissionDate', 'meta-instanceID', 'name', 'age', 'KEY', 'SubmitterID', 'SubmitterName', 'AttachmentsPresent', 'AttachmentsExpected', 'Status', 'ReviewState', 'DeviceID', 'Edits', 'FormVersion' ]); csv[1].shift().should.be.an.recentIsoDate(); @@ -750,7 +750,7 @@ two,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - const csv = result['simple.csv'].split('\n').map((row) => row.split(',')); + const csv = result.files.get('simple.csv').split('\n').map((row) => row.split(',')); csv.length.should.equal(4); // header + 2 data rows + newline csv[0].should.eql([ 'SubmissionDate', 'meta-instanceID', 'name', 'age', 'KEY', 'SubmitterID', 'SubmitterName', 'AttachmentsPresent', 'AttachmentsExpected', 'Status', 'ReviewState', 'DeviceID', 'Edits', 'FormVersion' ]); csv[1].shift().should.be.an.recentIsoDate(); @@ -783,7 +783,7 @@ two,h,/data/h,2000-01-01T00:06,2000-01-01T00:07,-5,-6,,ee,ff .then((result) => { result.filenames.should.eql([ 'simple.csv' ]); - const csv = result['simple.csv'].split('\n').map((row) => row.split(',')); + const csv = result.files.get('simple.csv').split('\n').map((row) => row.split(',')); csv.length.should.equal(4); // header + 2 data rows + newline csv[0].should.eql([ 'SubmissionDate', 'meta-instanceID', 'name', 'age', 'KEY', 'SubmitterID', 'SubmitterName', 'AttachmentsPresent', 'AttachmentsExpected', 'Status', 'ReviewState', 'DeviceID', 'Edits', 'FormVersion' ]); csv[1].shift().should.be.an.recentIsoDate(); diff --git a/test/integration/other/submission-purging.js b/test/integration/other/submission-purging.js index 46e05dacd..2b6cab2a7 100644 --- a/test/integration/other/submission-purging.js +++ b/test/integration/other/submission-purging.js @@ -455,7 +455,7 @@ describe('query module submission purge', () => { 'audits - audit.csv' ]); - result['audits - audit.csv'].should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value + result.files.get('audits - audit.csv').should.equal(`instance ID,event,node,start,end,latitude,longitude,accuracy,old-value,new-value one,a,/data/a,2000-01-01T00:01,2000-01-01T00:02,1,2,3,aa,bb one,b,/data/b,2000-01-01T00:02,2000-01-01T00:03,4,5,6,cc,dd one,c,/data/c,2000-01-01T00:03,2000-01-01T00:04,7,8,9,ee,ff diff --git a/test/unit/data/attachments.js b/test/unit/data/attachments.js index c0cb54876..df76fcceb 100644 --- a/test/unit/data/attachments.js +++ b/test/unit/data/attachments.js @@ -21,9 +21,9 @@ describe('.zip attachments streaming', () => { 'media/thirdfile.ext' ]); - result['media/firstfile.ext'].should.equal('this is my first file'); - result['media/secondfile.ext'].should.equal('this is my second file'); - result['media/thirdfile.ext'].should.equal('this is my third file'); + result.files.get('media/firstfile.ext').should.equal('this is my first file'); + result.files.get('media/secondfile.ext').should.equal('this is my second file'); + result.files.get('media/thirdfile.ext').should.equal('this is my third file'); done(); }); diff --git a/test/unit/data/briefcase.js b/test/unit/data/briefcase.js index 7c9bcbc7e..3b2e7351d 100644 --- a/test/unit/data/briefcase.js +++ b/test/unit/data/briefcase.js @@ -62,7 +62,7 @@ describe('.csv.zip briefcase output @slow', () => { if (err) return done(err); result.filenames.should.eql([ 'mytestform.csv' ]); - result['mytestform.csv'].should.equal( + result.files.get('mytestform.csv').should.equal( `SubmissionDate,name,age,hometown,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,Alice,30,"Seattle, WA",one,,,0,0,,,,0,version 2018-01-01T00:00:00.000Z,Bob,34,"Portland, OR",two,,,0,0,,,,0,version @@ -115,7 +115,7 @@ describe('.csv.zip briefcase output @slow', () => { if (err) return done(err); result.filenames.should.eql([ 'mytestform.csv' ]); - result['mytestform.csv'].should.equal( + result.files.get('mytestform.csv').should.equal( `SubmissionDate,name,age,hometown,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,Alice,30,"Seattle, WA",one,4,daniela,0,0,,,,0,version 2018-01-01T00:00:00.000Z,Bob,34,"Portland, OR",two,8,hernando,0,0,,,,0,version @@ -155,7 +155,7 @@ describe('.csv.zip briefcase output @slow', () => { if (err) return done(err); result.filenames.should.eql([ 'mytestform.csv' ]); - result['mytestform.csv'].should.equal( + result.files.get('mytestform.csv').should.equal( `SubmissionDate,name,age,hometown,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,Alice,30,"Seattle, WA",one,,,2,4,,,,0,version 2018-01-01T00:00:00.000Z,Bob,34,"Portland, OR",two,,,1,4,,,,0,version @@ -194,7 +194,7 @@ describe('.csv.zip briefcase output @slow', () => { if (err) return done(err); result.filenames.should.eql([ 'mytestform.csv' ]); - result['mytestform.csv'].should.equal( + result.files.get('mytestform.csv').should.equal( `SubmissionDate,name,age,hometown,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,,,,one,,,0,0,missing encrypted form data,,,0,version 2018-01-01T00:00:00.000Z,Bob,34,"Portland, OR",two,,,0,0,,rejected,,0,version @@ -231,7 +231,7 @@ describe('.csv.zip briefcase output @slow', () => { if (err) return done(err); result.filenames.should.eql([ 'mytestform.csv' ]); - result['mytestform.csv'].should.equal( + result.files.get('mytestform.csv').should.equal( `SubmissionDate,name,age,hometown,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,,,,one,,,0,0,missing encrypted form data,,test device,0,version `); // eslint-disable-line function-paren-newline @@ -267,7 +267,7 @@ describe('.csv.zip briefcase output @slow', () => { if (err) return done(err); result.filenames.should.eql([ 'mytestform.csv' ]); - result['mytestform.csv'].should.equal( + result.files.get('mytestform.csv').should.equal( `SubmissionDate,name,age,hometown,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,,,,one,,,0,0,,,,3,version `); // eslint-disable-line function-paren-newline @@ -305,7 +305,7 @@ describe('.csv.zip briefcase output @slow', () => { if (err) return done(err); result.filenames.should.eql([ 'mytestform.csv' ]); - result['mytestform.csv'].should.equal( + result.files.get('mytestform.csv').should.equal( `SubmissionDate,name,age,hometown,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,,,,one,,,0,0,,,,0,original 2018-01-01T00:00:00.000Z,,,,two,,,0,0,,,,0,updated @@ -342,7 +342,7 @@ describe('.csv.zip briefcase output @slow', () => { if (err) return done(err); result.filenames.should.eql([ 'mytestform.csv' ]); - result['mytestform.csv'].should.equal( + result.files.get('mytestform.csv').should.equal( `SubmissionDate,name,age,hometown,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,\xABAlice\xBB,30,"Seattle, WA",one,,,0,0,,,,0,version `); // eslint-disable-line function-paren-newline @@ -380,7 +380,7 @@ describe('.csv.zip briefcase output @slow', () => { if (err) return done(err); result.filenames.should.eql([ 'mytestform.csv' ]); - result['mytestform.csv'].should.equal( + result.files.get('mytestform.csv').should.equal( `SubmissionDate,name,age,location-Latitude,location-Longitude,location-Altitude,location-Accuracy,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,Alice,30,47.649434,-122.347737,26.8,3.14,one,,,0,0,,,,0,version 2018-01-01T00:00:00.000Z,Bob,34,47.599115,-122.331753,10,,two,,,0,0,,,,0,version @@ -401,7 +401,7 @@ describe('.csv.zip briefcase output @slow', () => { if (err) return done(err); result.filenames.should.eql([ 'selectMultiple.csv' ]); - result['selectMultiple.csv'].should.equal( + result.files.get('selectMultiple.csv').should.equal( `SubmissionDate,meta-instanceID,q1,q1/x,q1/y,q1/z,g1-q2,g1-q2/m,g1-q2/n,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,one,a b,0,0,0,x y z,0,0,one,,,0,0,,,,0,version 2018-01-01T00:00:00.000Z,two,b,0,0,0,m x,1,0,two,,,0,0,,,,0,version @@ -451,7 +451,7 @@ describe('.csv.zip briefcase output @slow', () => { if (err) return done(err); result.filenames.should.eql([ 'structuredform.csv' ]); - result['structuredform.csv'].should.equal( + result.files.get('structuredform.csv').should.equal( `SubmissionDate,meta-instanceID,name,home-type,home-address-street,home-address-city,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,one,Alice,Apartment,101 Pike St,"Seattle, WA",one,,,0,0,,,,0,version 2018-01-01T00:00:00.000Z,two,Bob,Condo,20 Broadway,"Portland, OR",two,,,0,0,,,,0,version @@ -502,7 +502,7 @@ describe('.csv.zip briefcase output @slow', () => { if (err) return done(err); result.filenames.should.eql([ 'structuredform.csv' ]); - result['structuredform.csv'].should.equal( + result.files.get('structuredform.csv').should.equal( `SubmissionDate,instanceID,name,type,street,city,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,one,Alice,Apartment,101 Pike St,"Seattle, WA",one,,,0,0,,,,0,version 2018-01-01T00:00:00.000Z,two,Bob,Condo,20 Broadway,"Portland, OR",two,,,0,0,,,,0,version @@ -524,7 +524,7 @@ describe('.csv.zip briefcase output @slow', () => { if (err) return done(err); result.filenames.should.eql([ 'selectMultiple.csv' ]); - result['selectMultiple.csv'].should.equal( + result.files.get('selectMultiple.csv').should.equal( `SubmissionDate,instanceID,q1,q1/x,q1/y,q1/z,q2,q2/m,q2/n,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,one,a b,0,0,0,x y z,0,0,one,,,0,0,,,,0,version 2018-01-01T00:00:00.000Z,two,b,0,0,0,m x,1,0,two,,,0,0,,,,0,version @@ -593,13 +593,13 @@ describe('.csv.zip briefcase output @slow', () => { if (err) return done(err); result.filenames.should.containDeep([ 'singlerepeat.csv', 'singlerepeat-child.csv' ]); - result['singlerepeat.csv'].should.equal( + result.files.get('singlerepeat.csv').should.equal( `SubmissionDate,meta-instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,one,Alice,30,one,,,0,0,,,,0,version 2018-01-01T00:00:00.000Z,two,Bob,34,two,,,0,0,,,,0,version 2018-01-01T00:00:00.000Z,three,Chelsea,38,three,,,0,0,,,,0,version `); // eslint-disable-line function-paren-newline - result['singlerepeat-child.csv'].should.equal( + result.files.get('singlerepeat-child.csv').should.equal( `name,age,PARENT_KEY,KEY Billy,4,two,two/children/child[1] Blaine,6,two,two/children/child[2] @@ -657,8 +657,8 @@ Candace,2,three,three/children/child[1] if (err) return done(err); result.filenames.should.containDeep([ 'singlerepeat.csv', 'singlerepeat-child.csv' ]); - result['singlerepeat.csv'].split('\n').length.should.equal(129); - result['singlerepeat-child.csv'].split('\n').length.should.equal(129); + result.files.get('singlerepeat.csv').split('\n').length.should.equal(129); + result.files.get('singlerepeat-child.csv').split('\n').length.should.equal(129); done(); }); }); @@ -734,20 +734,20 @@ Candace,2,three,three/children/child[1] if (err) return done(err); result.filenames.should.containDeep([ 'multirepeat.csv', 'multirepeat-child.csv', 'multirepeat-toy.csv' ]); - result['multirepeat.csv'].should.equal( + result.files.get('multirepeat.csv').should.equal( `SubmissionDate,meta-instanceID,name,age,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,one,Alice,30,one,,,0,0,,,,0,version 2018-01-01T00:00:00.000Z,two,Bob,34,two,,,0,0,,,,0,version 2018-01-01T00:00:00.000Z,three,Chelsea,38,three,,,0,0,,,,0,version `); // eslint-disable-line function-paren-newline - result['multirepeat-child.csv'].should.equal( + result.files.get('multirepeat-child.csv').should.equal( `name,age,PARENT_KEY,KEY Billy,4,two,two/children/child[1] Blaine,6,two,two/children/child[2] Baker,7,two,two/children/child[3] Candace,2,three,three/children/child[1] `); // eslint-disable-line function-paren-newline - result['multirepeat-toy.csv'].should.equal( + result.files.get('multirepeat-toy.csv').should.equal( `name,PARENT_KEY,KEY R2-D2,two/children/child[1],two/children/child[1]/toy[1] BB-8,two/children/child[2],two/children/child[2]/toy[1] @@ -796,11 +796,11 @@ Pod racer,three/children/child[1],three/children/child[1]/toy[3] if (err) return done(err); result.filenames.should.containDeep([ 'pathprefix.csv', 'pathprefix-children.csv' ]); - result['pathprefix.csv'].should.equal( + result.files.get('pathprefix.csv').should.equal( `SubmissionDate,name,children-status,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,Alice,Living at home,one,,,0,0,,,,0,version `); // eslint-disable-line function-paren-newline - result['pathprefix-children.csv'].should.equal( + result.files.get('pathprefix-children.csv').should.equal( `name,PARENT_KEY,KEY Bob,one,one/children[1] Chelsea,one,one/children[2] @@ -887,7 +887,7 @@ Chelsea,one,one/children[2] if (err) return done(err); result.filenames.should.containDeep([ 'all-data-types.csv' ]); - result['all-data-types.csv'].should.equal( + result.files.get('all-data-types.csv').should.equal( `SubmissionDate,some_string,some_int,some_decimal,some_date,some_time,some_date_time,some_geopoint-Latitude,some_geopoint-Longitude,some_geopoint-Altitude,some_geopoint-Accuracy,some_geotrace,some_geoshape,some_barcode,meta-instanceID,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-04-26T08:58:20.525Z,Hola,123,123.456,2018-04-26,08:56:00.000Z,2018-04-26T08:56:00.000Z,43.3149254,-1.9869671,71.80000305175781,15.478,43.314926 -1.9869713 71.80000305175781 10.0;43.3149258 -1.9869694 71.80000305175781 10.0;43.3149258 -1.9869694 71.80000305175781 10.0;,43.31513313655808 -1.9863833114504814 0.0 0.0;43.31552832470026 -1.987161487340927 0.0 0.0;43.315044828733015 -1.9877894595265388 0.0 0.0;43.31459255404834 -1.9869402050971987 0.0 0.0;43.31513313655808 -1.9863833114504814 0.0 0.0;,000049499094,uuid:39f3dd36-161e-45cb-a1a4-395831d253a7,uuid:39f3dd36-161e-45cb-a1a4-395831d253a7,,,0,0,,,,0, `); // eslint-disable-line function-paren-newline @@ -1016,24 +1016,24 @@ Chelsea,one,one/children[2] if (err) return done(err); result.filenames.should.containDeep([ 'nested-repeats.csv', 'nested-repeats-g1.csv', 'nested-repeats-g2.csv', 'nested-repeats-g3.csv' ]); - result['nested-repeats.csv'].should.equal( + result.files.get('nested-repeats.csv').should.equal( `SubmissionDate,meta-instanceID,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-02-01T11:35:19.178Z,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b,,,0,0,,,,0, `); // eslint-disable-line function-paren-newline - result['nested-repeats-g1.csv'].should.equal( + result.files.get('nested-repeats-g1.csv').should.equal( `t1,PARENT_KEY,KEY some text 1,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[1] some text 2,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[2] some text 3,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[3] `); // eslint-disable-line function-paren-newline - result['nested-repeats-g2.csv'].should.equal( + result.files.get('nested-repeats-g2.csv').should.equal( `t2,PARENT_KEY,KEY some text 1.1,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[1],uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[1]/g2[1] some text 1.2,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[1],uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[1]/g2[2] some text 2.1,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[2],uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[2]/g2[1] some text 3.1,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[3],uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[3]/g2[1] `); // eslint-disable-line function-paren-newline - result['nested-repeats-g3.csv'].should.equal( + result.files.get('nested-repeats-g3.csv').should.equal( `t3,PARENT_KEY,KEY some text 1.1.1,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[1]/g2[1],uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[1]/g2[1]/g3[1] some text 3.1.1,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[3]/g2[1],uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[3]/g2[1]/g3[1] @@ -1104,19 +1104,19 @@ some text 3.1.4,uuid:0a1b861f-a5fd-4f49-846a-78dcf06cfc1b/g1[3]/g2[1],uuid:0a1b8 if (err) return done(err); result.filenames.should.containDeep([ 'ambiguous.csv', 'ambiguous-entry~1.csv', 'ambiguous-entry~2.csv' ]); - result['ambiguous.csv'].should.equal( + result.files.get('ambiguous.csv').should.equal( `SubmissionDate,meta-instanceID,name,KEY,SubmitterID,SubmitterName,AttachmentsPresent,AttachmentsExpected,Status,ReviewState,DeviceID,Edits,FormVersion 2018-01-01T00:00:00.000Z,one,Alice,one,,,0,0,,,,0,version 2018-01-01T00:00:00.000Z,two,Bob,two,,,0,0,,,,0,version 2018-01-01T00:00:00.000Z,three,Chelsea,three,,,0,0,,,,0,version `); // eslint-disable-line function-paren-newline - result['ambiguous-entry~1.csv'].should.equal( + result.files.get('ambiguous-entry~1.csv').should.equal( `name,PARENT_KEY,KEY Bobs Hardware,two,two/jobs/entry[1] Local Coffee,two,two/jobs/entry[2] Instantaneous Food,three,three/jobs/entry[1] `); // eslint-disable-line function-paren-newline - result['ambiguous-entry~2.csv'].should.equal( + result.files.get('ambiguous-entry~2.csv').should.equal( `name,PARENT_KEY,KEY Nasrin,two,two/friends/entry[1] Ferrence,three,three/friends/entry[1] diff --git a/test/unit/util/zip.js b/test/unit/util/zip.js index d1e1932e2..c00559f4a 100644 --- a/test/unit/util/zip.js +++ b/test/unit/util/zip.js @@ -104,10 +104,10 @@ describe('zipPart streamer', () => { 'y/test4.file' ]); - result['x/test1.file'].should.equal('test 1'); - result['x/test2.file'].should.equal('test 2'); - result['x/test3.file'].should.equal('test 3'); - result['y/test4.file'].should.equal('test 4'); + result.files.get('x/test1.file').should.equal('test 1'); + result.files.get('x/test2.file').should.equal('test 2'); + result.files.get('x/test3.file').should.equal('test 3'); + result.files.get('y/test4.file').should.equal('test 4'); done(); }); @@ -129,8 +129,8 @@ describe('zipPart streamer', () => { if (err) return done(err); result.filenames.should.containDeep([ 'test1.file', 'test2.file' ]); - result['test1.file'].should.equal('test static'); - result['test2.file'].should.equal('a!test!stream!'); + result.files.get('test1.file').should.equal('test static'); + result.files.get('test2.file').should.equal('a!test!stream!'); done(); }); @@ -205,3 +205,32 @@ describe('zipPart streamer', () => { }); }); +describe('zipStreamToFiles()', () => { + it('should not conflate metadata & file data', (done) => { + const part = zipPart(); + + zipStreamToFiles(zipStreamFromParts(part), (err, result) => { + if (err) return done(err); + + result.filenames.should.eqlInAnyOrder([ + 'test1.file', + 'filenames', + 'toString', + '__proto__' + ]); + + result.files.get('test1.file').should.equal('test 1'); + result.files.get('filenames').should.equal('i should be an array'); + result.files.get('toString').should.equal('i should be a function'); + result.files.get('__proto__').should.equal('i should be an object'); + + done(); + }); + + part.append('test 1', { name: 'test1.file' }); + part.append('i should be an array', { name: 'filenames' }); + part.append('i should be a function', { name: 'toString' }); + part.append('i should be an object', { name: '__proto__' }); + part.finalize(); + }); +}); diff --git a/test/util/zip.js b/test/util/zip.js index 107e2f82e..4a5640640 100644 --- a/test/util/zip.js +++ b/test/util/zip.js @@ -5,15 +5,9 @@ const streamTest = require('streamtest').v2; // unzip and detangle zipfiles. // also, hooraaaayy callback hell. -// calls the callback with an object as follows: -// { -// filenames: [ names of files in zip ], -// {filename}: "contents", -// {filename}: "contents", -// … -// } +// calls the callback with an object { filenames:[], files:Map(name -> contents) } const processZipFile = (zipfile, callback) => { - const result = { filenames: [] }; + const result = { filenames: [], files: new Map() }; const entries = []; let completed = 0; @@ -34,7 +28,7 @@ const processZipFile = (zipfile, callback) => { resultStream.pipe(streamTest.toText((err, contents) => { if (err) return callback(err); - result[entry.fileName] = contents; + result.files.set(entry.fileName, contents); completed += 1; if (completed === entries.length) { callback(null, result);