diff --git a/src/job-execution/FileUploader.ts b/src/job-execution/FileUploader.ts index ee3f2c2..868ae98 100644 --- a/src/job-execution/FileUploader.ts +++ b/src/job-execution/FileUploader.ts @@ -1,8 +1,7 @@ import { getValidJson, parseSasViyaDebugResponse, - parseWeboutResponse, - SASJS_LOGS_SEPARATOR + parseWeboutResponse } from '../utils' import { UploadFile } from '../types/UploadFile' import { diff --git a/src/request/SasjsRequestClient.ts b/src/request/SasjsRequestClient.ts index 30a4f2d..760c5c8 100644 --- a/src/request/SasjsRequestClient.ts +++ b/src/request/SasjsRequestClient.ts @@ -1,8 +1,7 @@ import { RequestClient } from './RequestClient' import { AxiosResponse } from 'axios' -import { SASJS_LOGS_SEPARATOR } from '../utils' -interface SasjsParsedResponse { +export interface SasjsParsedResponse { result: T log: string etag: string @@ -45,13 +44,30 @@ export class SasjsRequestClient extends RequestClient { } } catch { if (response.data.includes(SASJS_LOGS_SEPARATOR)) { - const splittedResponse = response.data.split(SASJS_LOGS_SEPARATOR) + const { data } = response + const splittedResponse: string[] = data.split(SASJS_LOGS_SEPARATOR) - webout = splittedResponse[0] + webout = splittedResponse.splice(0, 1)[0] if (webout !== undefined) parsedResponse = webout - log = splittedResponse[1] - printOutput = splittedResponse[2] + // log can contain nested logs + const logs = splittedResponse.splice(0, splittedResponse.length - 1) + + // tests if string ends with SASJS_LOGS_SEPARATOR + const endingWithLogSepRegExp = new RegExp(`${SASJS_LOGS_SEPARATOR}$`) + + // at this point splittedResponse can contain only one item + const lastChunk = splittedResponse[0] + + if (lastChunk) { + // if the last chunk doesn't end with SASJS_LOGS_SEPARATOR, then it is a printOutput + // else the last chunk is part of the log and has to be joined + if (!endingWithLogSepRegExp.test(data)) printOutput = lastChunk + else if (logs.length > 1) logs.push(lastChunk) + } + + // join logs into single log with SASJS_LOGS_SEPARATOR + log = logs.join(SASJS_LOGS_SEPARATOR) } else { parsedResponse = response.data } @@ -59,7 +75,7 @@ export class SasjsRequestClient extends RequestClient { const returnResult: SasjsParsedResponse = { result: parsedResponse as T, - log, + log: log || '', etag, status: response.status } @@ -69,3 +85,6 @@ export class SasjsRequestClient extends RequestClient { return returnResult } } + +export const SASJS_LOGS_SEPARATOR = + 'SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784' diff --git a/src/request/spec/SasjsRequestClient.spec.ts b/src/request/spec/SasjsRequestClient.spec.ts new file mode 100644 index 0000000..b70007b --- /dev/null +++ b/src/request/spec/SasjsRequestClient.spec.ts @@ -0,0 +1,172 @@ +import { + SASJS_LOGS_SEPARATOR, + SasjsRequestClient, + SasjsParsedResponse +} from '../SasjsRequestClient' +import { AxiosResponse } from 'axios' + +describe('SasjsRequestClient', () => { + const requestClient = new SasjsRequestClient('') + const etag = 'etag' + const status = 200 + + const webout = `hello` + const log = `1 The SAS System Tuesday, 25 July 2023 12:51:00 + + +PROC MIGRATE will preserve current SAS file attributes and is +recommended for converting all your SAS libraries from any +SAS 8 release to SAS 9. For details and examples, please see +http://support.sas.com/rnd/migration/index.html + + + +NOTE: SAS initialization used: + real time 0.01 seconds + cpu time 0.02 seconds + + +` + const printOutput = 'printOutPut' + + describe('parseResponse', () => {}) + + it('should parse response with 1 log', () => { + const response: AxiosResponse = { + data: `${webout} +${SASJS_LOGS_SEPARATOR} +${log} +${SASJS_LOGS_SEPARATOR}`, + status, + statusText: 'ok', + headers: { etag }, + config: {} + } + + const expectedParsedResponse: SasjsParsedResponse = { + result: `${webout} +`, + log: ` +${log} +`, + etag, + status + } + + expect(requestClient['parseResponse'](response)).toEqual( + expectedParsedResponse + ) + }) + + it('should parse response with 1 log and printOutput', () => { + const response: AxiosResponse = { + data: `${webout} +${SASJS_LOGS_SEPARATOR} +${log} +${SASJS_LOGS_SEPARATOR} +${printOutput}`, + status, + statusText: 'ok', + headers: { etag }, + config: {} + } + + const expectedParsedResponse: SasjsParsedResponse = { + result: `${webout} +`, + log: ` +${log} +`, + etag, + status, + printOutput: ` +${printOutput}` + } + + expect(requestClient['parseResponse'](response)).toEqual( + expectedParsedResponse + ) + }) + + it('should parse response with nested logs', () => { + const logWithNestedLog = `root log start +${SASJS_LOGS_SEPARATOR} +${log} +${SASJS_LOGS_SEPARATOR} +root log end` + + const response: AxiosResponse = { + data: `${webout} +${SASJS_LOGS_SEPARATOR} +${logWithNestedLog} +${SASJS_LOGS_SEPARATOR}`, + status, + statusText: 'ok', + headers: { etag }, + config: {} + } + + const expectedParsedResponse: SasjsParsedResponse = { + result: `${webout} +`, + log: ` +${logWithNestedLog} +`, + etag, + status + } + + expect(requestClient['parseResponse'](response)).toEqual( + expectedParsedResponse + ) + }) + + it('should parse response with nested logs and printOutput', () => { + const logWithNestedLog = `root log start +${SASJS_LOGS_SEPARATOR} +${log} +${SASJS_LOGS_SEPARATOR} +log with indentation + ${SASJS_LOGS_SEPARATOR} + ${log} + ${SASJS_LOGS_SEPARATOR} +some SAS code containing ${SASJS_LOGS_SEPARATOR} +root log end` + + const response: AxiosResponse = { + data: `${webout} +${SASJS_LOGS_SEPARATOR} +${logWithNestedLog} +${SASJS_LOGS_SEPARATOR} +${printOutput}`, + status, + statusText: 'ok', + headers: { etag }, + config: {} + } + + const expectedParsedResponse: SasjsParsedResponse = { + result: `${webout} +`, + log: ` +${logWithNestedLog} +`, + etag, + status, + printOutput: ` +${printOutput}` + } + + expect(requestClient['parseResponse'](response)).toEqual( + expectedParsedResponse + ) + }) +}) + +describe('SASJS_LOGS_SEPARATOR', () => { + it('SASJS_LOGS_SEPARATOR should be hardcoded', () => { + expect(SASJS_LOGS_SEPARATOR).toEqual( + 'SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784' + ) + }) +}) diff --git a/src/utils/constants.ts b/src/utils/constants.ts deleted file mode 100644 index 943e05a..0000000 --- a/src/utils/constants.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const SASJS_LOGS_SEPARATOR = - 'SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784' diff --git a/src/utils/index.ts b/src/utils/index.ts index 68def1a..cbc166a 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -2,7 +2,6 @@ export * from './appendExtraResponseAttributes' export * from './asyncForEach' export * from './compareTimestamps' export * from './convertToCsv' -export * from './constants' export * from './createAxiosInstance' export * from './delay' export * from './fetchLogByChunks'