11import { expect } from 'chai' ;
22import * as path from 'path' ;
3+ import * as fs from 'fs-extra' ;
34import * as sinon from 'sinon' ;
45import { Uri } from 'vscode' ;
56
67import { QueryEvaluationInfo } from '../../run-queries' ;
78import { Severity , compileQuery } from '../../pure/messages' ;
89import * as config from '../../config' ;
10+ import { tmpDir } from '../../helpers' ;
11+ import { QueryServerClient } from '../../queryserver-client' ;
12+ import { CodeQLCliServer } from '../../cli' ;
13+ import { SELECT_QUERY_NAME } from '../../contextual/locationFinder' ;
914
1015describe ( 'run-queries' , ( ) => {
1116 let sandbox : sinon . SinonSandbox ;
@@ -53,6 +58,51 @@ describe('run-queries', () => {
5358 expect ( info . canHaveInterpretedResults ( ) ) . to . eq ( true ) ;
5459 } ) ;
5560
61+ [ SELECT_QUERY_NAME , 'other' ] . forEach ( resultSetName => {
62+ it ( `should export csv results for result set ${ resultSetName } ` , async ( ) => {
63+ const csvLocation = path . join ( tmpDir . name , 'test.csv' ) ;
64+ const qs = createMockQueryServerClient (
65+ createMockCliServer ( {
66+ bqrsInfo : [ { 'result-sets' : [ { name : resultSetName } , { name : 'hucairz' } ] } ] ,
67+ bqrsDecode : [ {
68+ columns : [ { kind : 'NotString' } , { kind : 'String' } ] ,
69+ tuples : [ [ 'a' , 'b' ] , [ 'c' , 'd' ] ] ,
70+ next : 1
71+ } , {
72+ // just for fun, give a different set of columns here
73+ // this won't happen with the real CLI, but it's a good test
74+ columns : [ { kind : 'String' } , { kind : 'NotString' } , { kind : 'StillNotString' } ] ,
75+ tuples : [ [ 'a' , 'b' , 'c' ] ]
76+ } ]
77+ } )
78+ ) ;
79+ const info = createMockQueryInfo ( ) ;
80+ const promise = info . exportCsvResults ( qs , csvLocation ) ;
81+
82+ const result = await promise ;
83+ expect ( result ) . to . eq ( true ) ;
84+
85+ const csv = fs . readFileSync ( csvLocation , 'utf8' ) ;
86+ expect ( csv ) . to . eq ( 'a,"b"\nc,"d"\n"a",b,c\n' ) ;
87+
88+ // now verify that we are using the expected result set
89+ expect ( ( qs . cliServer . bqrsDecode as sinon . SinonStub ) . callCount ) . to . eq ( 2 ) ;
90+ expect ( ( qs . cliServer . bqrsDecode as sinon . SinonStub ) . getCall ( 0 ) . args [ 1 ] ) . to . eq ( resultSetName ) ;
91+ } ) ;
92+ } ) ;
93+
94+ it ( 'should handle csv exports for a query with no result sets' , async ( ) => {
95+ const csvLocation = path . join ( tmpDir . name , 'test.csv' ) ;
96+ const qs = createMockQueryServerClient (
97+ createMockCliServer ( {
98+ bqrsInfo : [ { 'result-sets' : [ ] } ]
99+ } )
100+ ) ;
101+ const info = createMockQueryInfo ( ) ;
102+ const result = await info . exportCsvResults ( qs , csvLocation ) ;
103+ expect ( result ) . to . eq ( false ) ;
104+ } ) ;
105+
56106 describe ( 'compile' , ( ) => {
57107 it ( 'should compile' , async ( ) => {
58108 const info = createMockQueryInfo ( ) ;
@@ -116,7 +166,7 @@ describe('run-queries', () => {
116166 ) ;
117167 }
118168
119- function createMockQueryServerClient ( ) {
169+ function createMockQueryServerClient ( cliServer ?: CodeQLCliServer ) : QueryServerClient {
120170 return {
121171 config : {
122172 timeoutSecs : 5
@@ -131,7 +181,20 @@ describe('run-queries', () => {
131181 } ) ) ,
132182 logger : {
133183 log : sandbox . spy ( )
134- }
135- } ;
184+ } ,
185+ cliServer
186+ } as unknown as QueryServerClient ;
187+ }
188+
189+ function createMockCliServer ( mockOperations : Record < string , any [ ] > ) : CodeQLCliServer {
190+ const mockServer : Record < string , any > = { } ;
191+ for ( const [ operation , returns ] of Object . entries ( mockOperations ) ) {
192+ mockServer [ operation ] = sandbox . stub ( ) ;
193+ returns . forEach ( ( returnValue , i ) => {
194+ mockServer [ operation ] . onCall ( i ) . resolves ( returnValue ) ;
195+ } ) ;
196+ }
197+
198+ return mockServer as unknown as CodeQLCliServer ;
136199 }
137200} ) ;
0 commit comments