I'm using PapaParse to parse a CSV file passed by the user. Here is my code:
this.fileToUpload = files.item(0);
this.status = Status.Loading;
let batch = [];
this.papa.parse(this.fileToUpload, {
worker: true,
step: (row) => {
if (batch.length === this.pageSize) {
this.addBatch(batch, this.offset);
this.offset += this.pageSize;
batch = [];
}
batch.push({
id: row.data[0],
name: row.data[1],
address: row.data[2]
});
},
complete: (result) => {
if (batch.length > 0) {
this.addBatch(batch, this.offset);
batch = [];
}
}
});
The worker field indicates that the file should be streamed using web workers, but I think if you implement the step method, you are forcing that anyway. It works perfectly find and parses the uploaded CSV.
My problem lies with testing this using Jasmine. I setup my test with fakeAsync, I call everything that needs to be called, I have even flushed and ticked in the test to let asynchronous code continue, but when I expect a result it always says that the method called with the step method of Papa was not called. I'm checking to see if the addBatch method is being called, but according to Karma it isn't.
it('should upload a valid csv file', fakeAsync(() => {
// given
component.ngOnInit();
spyOn(component, 'addBatch');
const blob = new Blob(['12345,Example,FakeStreet\n54321,Example,FakeStreet'], { type: 'text/csv' });
blob['lastModified'] = '';
blob['name'] = 'filename.csv';
const file = <File>blob;
const fileList = {
0: file,
1: file,
length: 2,
item: (index: number) => file
};
// when
component.addMerchants(fileList);
flush();
// then
expect(component.addBatch).toHaveBeenCalled();
}));
Even when I console.log in the step method, it prints that anyway, which means it is working.
From looking at the threads in Chrome, when the test runs, for a slight couple of milliseconds a thread is created and then deleted, so I'd imagine that's papa.
I don't know if web workers have a separate context? Perhaps because it's being executed there and not in the current Karma window, it's not picking up the call.
Any thoughts on how this can be solved, or any other approaches for testing this?
There is no async work going on, at least not on the main thread, so the NgZone is not 'unstable'. So for all intents and purposes, the test thinks it can just call the expect
method.
You are not really doing a unit test here, but more an integration test. If you want to make a unit test, you should mock the papa.parse
and have your mock handle the complete call based on whatever input you give from your unit test. You can make that async by using setTimeout
if you really want.