@@ -13,6 +13,7 @@ import { pipeline } from 'node:stream/promises'
13
13
import path from 'node:path'
14
14
import FormData from 'form-data'
15
15
import os from 'os'
16
+ import { gunzipSync } from 'node:zlib'
16
17
17
18
async function createUser (
18
19
app : FastifyInstance ,
@@ -28,8 +29,16 @@ async function createTask (app: FastifyInstance, taskData: Partial<Task>) {
28
29
return id
29
30
}
30
31
31
- async function uploadImageForTask ( app : FastifyInstance , taskId : number , filePath : string , uploadDir : string ) {
32
- await app . knex < Task > ( 'tasks' ) . where ( { id : taskId } ) . update ( { filename : `${ taskId } _short-logo.png` } )
32
+ async function uploadImageForTask (
33
+ app : FastifyInstance ,
34
+ taskId : number ,
35
+ filePath : string ,
36
+ uploadDir : string
37
+ ) {
38
+ await app
39
+ . knex < Task > ( 'tasks' )
40
+ . where ( { id : taskId } )
41
+ . update ( { filename : `${ taskId } _short-logo.png` } )
33
42
34
43
const file = fs . createReadStream ( filePath )
35
44
const filename = `${ taskId } _short-logo.png`
@@ -803,4 +812,48 @@ describe('Tasks api (logged user only)', () => {
803
812
} )
804
813
} )
805
814
} )
815
+
816
+ describe ( 'GET /api/tasks/download/csv' , ( ) => {
817
+ before ( async ( ) => {
818
+ const app = await build ( )
819
+ await app . knex ( 'tasks' ) . del ( )
820
+ await app . close ( )
821
+ } )
822
+
823
+ it ( 'should stream a gzipped CSV file' , async ( t ) => {
824
+ const app = await build ( t )
825
+
826
+ const tasks = [ ]
827
+ for ( let i = 0 ; i < 1000 ; i ++ ) {
828
+ tasks . push ( {
829
+ name : `Task ${ i + 1 } ` ,
830
+ author_id : 1 ,
831
+ assigned_user_id : 2 ,
832
+ filename : 'task.png' ,
833
+ status : TaskStatusEnum . InProgress
834
+ } )
835
+ }
836
+
837
+ await app . knex ( 'tasks' ) . insert ( tasks )
838
+
839
+ const res = await app . injectWithLogin ( 'basic' , {
840
+ method : 'GET' ,
841
+ url : '/api/tasks/download/csv'
842
+ } )
843
+
844
+ assert . strictEqual ( res . statusCode , 200 )
845
+ assert . strictEqual ( res . headers [ 'content-type' ] , 'application/gzip' )
846
+ assert . strictEqual (
847
+ res . headers [ 'content-disposition' ] ,
848
+ 'attachment; filename="tasks.csv.gz"'
849
+ )
850
+
851
+ const decompressed = gunzipSync ( res . rawPayload ) . toString ( 'utf-8' )
852
+ const lines = decompressed . split ( '\n' )
853
+ assert . equal ( lines . length - 1 , 1001 )
854
+
855
+ assert . ok ( lines [ 1 ] . includes ( 'Task 1,1,2,task.png,in-progress' ) )
856
+ assert . equal ( lines [ 0 ] , 'id,name,author_id,assigned_user_id,filename,status,created_at,updated_at' )
857
+ } )
858
+ } )
806
859
} )
0 commit comments