diff --git a/src/api/viya/spec/getFileStream.spec.ts b/src/api/viya/spec/getFileStream.spec.ts new file mode 100644 index 0000000..0722e37 --- /dev/null +++ b/src/api/viya/spec/getFileStream.spec.ts @@ -0,0 +1,41 @@ +import { Logger, LogLevel } from '@sasjs/utils/logger' +import * as path from 'path' +import * as fileModule from '@sasjs/utils/file' +import { getFileStream } from '../getFileStream' +import { mockJob } from './mockResponses' +import { WriteStream } from '../../../types' + +describe('getFileStream', () => { + beforeEach(() => { + ;(process as any).logger = new Logger(LogLevel.Off) + setupMocks() + }) + it('should use the given log path if it points to a file', async () => { + const { createWriteStream } = require('@sasjs/utils/file') + + await getFileStream(mockJob, path.join(__dirname, 'test.log')) + + expect(createWriteStream).toHaveBeenCalledWith( + path.join(__dirname, 'test.log') + ) + }) + + it('should generate a log file path with a timestamp if it points to a folder', async () => { + const { createWriteStream } = require('@sasjs/utils/file') + + await getFileStream(mockJob, __dirname) + + expect(createWriteStream).not.toHaveBeenCalledWith(__dirname) + expect(createWriteStream).toHaveBeenCalledWith( + expect.stringContaining(__dirname + '/test job-20') + ) + }) +}) + +const setupMocks = () => { + jest.restoreAllMocks() + jest.mock('@sasjs/utils/file/file') + jest + .spyOn(fileModule, 'createWriteStream') + .mockImplementation(() => Promise.resolve({} as unknown as WriteStream)) +} diff --git a/src/api/viya/spec/pollJobState.spec.ts b/src/api/viya/spec/pollJobState.spec.ts index 7855f57..aba468c 100644 --- a/src/api/viya/spec/pollJobState.spec.ts +++ b/src/api/viya/spec/pollJobState.spec.ts @@ -1,11 +1,11 @@ import { Logger, LogLevel } from '@sasjs/utils' -import * as path from 'path' -import * as fileModule from '@sasjs/utils/file' import { RequestClient } from '../../../request/RequestClient' import { mockAuthConfig, mockJob } from './mockResponses' import { pollJobState } from '../pollJobState' import * as getTokensModule from '../../../auth/getTokens' import * as saveLogModule from '../saveLog' +import * as getFileStreamModule from '../getFileStream' +import * as isNodeModule from '../../../utils/isNode' import { PollOptions } from '../../../types' import { WriteStream } from 'fs' @@ -77,42 +77,43 @@ describe('pollJobState', () => { it('should attempt to fetch and save the log after each poll when streamLog is true', async () => { mockSimplePoll() + const { saveLog } = require('../saveLog') await pollJobState(requestClient, mockJob, false, mockAuthConfig, { ...defaultPollOptions, streamLog: true }) - expect(saveLogModule.saveLog).toHaveBeenCalledTimes(2) + expect(saveLog).toHaveBeenCalledTimes(2) }) - it('should use the given log path if it points to a file', async () => { + it('should create a write stream in Node.js environment when streamLog is true', async () => { mockSimplePoll() + const { getFileStream } = require('../getFileStream') + const { saveLog } = require('../saveLog') await pollJobState(requestClient, mockJob, false, mockAuthConfig, { ...defaultPollOptions, - streamLog: true, - logFolderPath: path.join(__dirname, 'test.log') + streamLog: true }) - expect(fileModule.createWriteStream).toHaveBeenCalledWith( - path.join(__dirname, 'test.log') - ) + expect(getFileStream).toHaveBeenCalled() + expect(saveLog).toHaveBeenCalledTimes(2) }) - it('should generate a log file path with a timestamp if it points to a folder', async () => { + it('should not create a write stream in a non-Node.js environment', async () => { mockSimplePoll() + jest.spyOn(isNodeModule, 'isNode').mockImplementation(() => false) + const { saveLog } = require('../saveLog') + const { getFileStream } = require('../getFileStream') await pollJobState(requestClient, mockJob, false, mockAuthConfig, { ...defaultPollOptions, - streamLog: true, - logFolderPath: path.join(__dirname) + streamLog: true }) - expect(fileModule.createWriteStream).not.toHaveBeenCalledWith(__dirname) - expect(fileModule.createWriteStream).toHaveBeenCalledWith( - expect.stringContaining(__dirname + '/test job-20') - ) + expect(getFileStream).not.toHaveBeenCalled() + expect(saveLog).not.toHaveBeenCalled() }) it('should not attempt to fetch and save the log after each poll when streamLog is false', async () => { @@ -247,7 +248,8 @@ const setupMocks = () => { jest.mock('../../../request/RequestClient') jest.mock('../../../auth/getTokens') jest.mock('../saveLog') - jest.mock('@sasjs/utils/file') + jest.mock('../getFileStream') + jest.mock('../../../utils/isNode') jest .spyOn(requestClient, 'get') @@ -261,8 +263,9 @@ const setupMocks = () => { .spyOn(saveLogModule, 'saveLog') .mockImplementation(() => Promise.resolve()) jest - .spyOn(fileModule, 'createWriteStream') + .spyOn(getFileStreamModule, 'getFileStream') .mockImplementation(() => Promise.resolve({} as unknown as WriteStream)) + jest.spyOn(isNodeModule, 'isNode').mockImplementation(() => true) } const mockSimplePoll = (runningCount = 2) => { diff --git a/src/api/viya/spec/saveLog.spec.ts b/src/api/viya/spec/saveLog.spec.ts index a6c662b..261438e 100644 --- a/src/api/viya/spec/saveLog.spec.ts +++ b/src/api/viya/spec/saveLog.spec.ts @@ -4,7 +4,7 @@ import * as fetchLogsModule from '../../../utils/fetchLogByChunks' import * as writeStreamModule from '../writeStream' import { saveLog } from '../saveLog' import { mockJob } from './mockResponses' -import { WriteStream } from 'fs' +import { WriteStream } from '../../../types' const requestClient = new (>RequestClient)() const stream = {} as unknown as WriteStream diff --git a/src/api/viya/spec/writeStream.spec.ts b/src/api/viya/spec/writeStream.spec.ts new file mode 100644 index 0000000..358c82a --- /dev/null +++ b/src/api/viya/spec/writeStream.spec.ts @@ -0,0 +1,25 @@ +import { WriteStream } from '../../../types' +import { writeStream } from '../writeStream' +import 'jest-extended' + +describe('writeStream', () => { + const stream: WriteStream = { + write: jest.fn(), + path: 'test' + } + + it('should resolve when the stream is written successfully', async () => { + expect(writeStream(stream, 'test')).toResolve() + + expect(stream.write).toHaveBeenCalledWith('test\n', expect.anything()) + }) + + it('should reject when the write errors out', async () => { + jest + .spyOn(stream, 'write') + .mockImplementation((_, callback) => callback(new Error('Test Error'))) + const error = await writeStream(stream, 'test').catch((e) => e) + + expect(error.message).toEqual('Test Error') + }) +})