You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am having an issue trying to mock a http response stream. I am trying to write a fetch request to download an excel file, but for whatever reason I am not able to write a unit test. I get the following error:
FAIL __tests__/excel.test.js > getReadableStream > should return a readable stream for an HTTP URL
Error: Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html ❯ ZipEntries.readEndOfCentral node_modules/jszip/lib/zipEntries.js:167:23 ❯ ZipEntries.load node_modules/jszip/lib/zipEntries.js:255:14 ❯ node_modules/jszip/lib/load.js:48:24 ❯ XLSX.load node_modules/exceljs/lib/xlsx/xlsx.js:279:17 ❯ Module.readExcel helpers/excel.js:51:5 49| 50| const workbook = new ExcelJS.Workbook() 51| await workbook.xlsx.read(stream) | ^ 52| 53| return workbook ❯ __tests__/excel.test.js:95:19
excel.test.js
import{PassThrough}from'node:stream'importExcelJSfrom'exceljs'import{describe,it,expect,beforeAll,afterAll,afterEach}from'vitest'import{setupServer}from'msw/node'import{http,HttpResponse}from'msw'import{readExcel,getReadableStream}from'../excel.js'importdatafrom'./__fixtures__/data.json'constsheetName='Sheet1'// Create a mock serverconstserver=setupServer()// Start the server before all testsbeforeAll(()=>server.listen())// Close the server after all testsafterAll(()=>server.close())// Reset handlers after each testafterEach(()=>server.resetHandlers())exportasyncfunctiongenerateReadableStreamFromJson(jsonData){constworkbook=newExcelJS.Workbook()constworksheet=workbook.addWorksheet(sheetName)if(jsonData.length>0){// Add header rowconstheader=Object.keys(jsonData[0])worksheet.addRow(header)// Add data rowsjsonData.forEach((data)=>{constrowValues=Object.values(data).map(value=>value===null ? '' : value)worksheet.addRow(rowValues)})}else{// Add header row with empty dataworksheet.addRow([])}// Create a PassThrough streamconststream=newPassThrough()try{// Write the workbook to the streamawaitworkbook.xlsx.write(stream)stream.end()}catch(error){stream.emit('error',error)}returnstream}functionvalidateExcelDataAgainstJson(excelData,jsonData){const[headerRow, ...dataRows]=excelData[0].data// Transform Excel data into key-value objectsconstexcelObjects=dataRows.map((row)=>{constobj={}headerRow.slice(1).forEach((header,colIndex)=>{obj[header]=row[colIndex+1]})returnobj})// Compare the transformed Excel data against the JSON dataexpect(excelObjects).toHaveLength(jsonData.length)jsonData.forEach((jsonObj,index)=>{constexcelObj=excelObjects[index]Object.keys(jsonObj).forEach((key)=>{expect(excelObj[key]).toEqual(jsonObj[key]??'')})})}describe('getReadableStream',()=>{it('should return a readable stream for an HTTP URL',async()=>{consturl='http://example.com/data.xlsx'constreadableStream=awaitgenerateReadableStreamFromJson(data)server.use(http.get(url,()=>{returnnewHttpResponse(readableStream,{headers: {'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',},})}))conststream=awaitgetReadableStream(url)constexcel=awaitreadExcel(stream)validateExcelDataAgainstJson(excel,data)})})
excel.js
import{URL}from'node:url'import{createReadStream}from'node:fs'importpathfrom'node:path'import{Readable}from'node:stream'importExcelJSfrom'exceljs'exportasyncfunctiongetReadableStream(input){if(typeofinput!=='string'||input.trim()===''){thrownewError('Invalid input: Must be a non-empty string or a readable stream')}try{constparsedUrl=newURL(input)switch(parsedUrl.protocol){case'http:':
case'https:': {constresponse=awaitfetch(input)if(!response.ok){thrownewError(`Network request failed for ${input} with status code ${response.status}`)}if(!response.body||typeofresponse.body.pipe!=='function'){thrownewError(`Response body is not a readable stream for ${input}`)}returnresponse.body}case'file:':
returncreateReadStream(parsedUrl.pathname)default:
thrownewError(`Unsupported protocol for URL: ${input}. Must use HTTP, HTTPS, or file protocol`)}}catch(e){// If the URL constructor throws an error or the protocol is unsupported, assume it's a local file pathconsole.warn(`Failed to parse URL: ${e.message}. Assuming local file path: ${input}`)returncreateReadStream(path.resolve(input))}}exportasyncfunctionreadExcel(input){try{letstreamif(typeofinput==='string'){stream=awaitgetReadableStream(input)}elseif(inputinstanceofReadable){stream=input}else{thrownewError('Invalid input: Must be a URL, file path, or readable stream')}constworkbook=newExcelJS.Workbook()awaitworkbook.xlsx.read(stream)returnworkbook}catch(e){console.error(`Failed to read Excel file from ${input}`,e)throwe}}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I am having an issue trying to mock a http response stream. I am trying to write a fetch request to download an excel file, but for whatever reason I am not able to write a unit test. I get the following error:
excel.test.js
excel.js
package.json
data.json
I am able to read the excel stream if I don't make an http request, but I get an error about a zip file if I mock the http response to the stream.
Beta Was this translation helpful? Give feedback.
All reactions