From 18be9e8806bd606b8e0e4953f8ff27a68075fd98 Mon Sep 17 00:00:00 2001 From: Mihajlo Medjedovic Date: Mon, 3 Mar 2025 17:52:53 +0100 Subject: [PATCH] fix: jest tests RequestClient.spec.ts --- jest.config.js | 2 +- package-lock.json | 36 +++++++++++++++++++++++++++ package.json | 2 ++ src/api/viya/spec/saveLog.spec.ts | 2 +- src/api/viya/spec/writeStream.spec.ts | 31 ++++++++++++++++++++++- src/api/viya/writeStream.ts | 15 +++++++---- src/request/RequestClient.ts | 1 - src/test/RequestClient.spec.ts | 31 ++++++++++++++--------- src/test/SAS_server_app.ts | 12 +++++++-- src/types/WriteStream.ts | 12 ++++++--- 10 files changed, 118 insertions(+), 26 deletions(-) diff --git a/jest.config.js b/jest.config.js index 300b73b..32734d7 100644 --- a/jest.config.js +++ b/jest.config.js @@ -142,7 +142,7 @@ module.exports = { // Options that will be passed to the testEnvironment // testEnvironmentOptions: {}, - testEnvironment: 'jest-environment-jsdom', + testEnvironment: 'node', // Adds a location field to test results // testLocationInResults: false, diff --git a/package-lock.json b/package-lock.json index 6eab022..7151d4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,12 +17,14 @@ }, "devDependencies": { "@cypress/webpack-preprocessor": "5.9.1", + "@types/cors": "^2.8.17", "@types/express": "4.17.13", "@types/jest": "29.5.14", "@types/mime": "2.0.3", "@types/pem": "1.9.6", "@types/tough-cookie": "4.0.2", "copyfiles": "2.4.1", + "cors": "^2.8.5", "cp": "0.2.0", "cypress": "7.7.0", "dotenv": "16.0.0", @@ -2740,6 +2742,16 @@ "@types/node": "*" } }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/eslint": { "version": "9.6.1", "dev": true, @@ -4614,6 +4626,20 @@ "dev": true, "license": "MIT" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/cosmiconfig": { "version": "7.1.0", "dev": true, @@ -11640,6 +11666,16 @@ "dev": true, "license": "MIT" }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "dev": true, diff --git a/package.json b/package.json index 1367699..cddc86a 100644 --- a/package.json +++ b/package.json @@ -45,12 +45,14 @@ "license": "ISC", "devDependencies": { "@cypress/webpack-preprocessor": "5.9.1", + "@types/cors": "^2.8.17", "@types/express": "4.17.13", "@types/jest": "29.5.14", "@types/mime": "2.0.3", "@types/pem": "1.9.6", "@types/tough-cookie": "4.0.2", "copyfiles": "2.4.1", + "cors": "^2.8.5", "cp": "0.2.0", "cypress": "7.7.0", "dotenv": "16.0.0", diff --git a/src/api/viya/spec/saveLog.spec.ts b/src/api/viya/spec/saveLog.spec.ts index bd89306..400448b 100644 --- a/src/api/viya/spec/saveLog.spec.ts +++ b/src/api/viya/spec/saveLog.spec.ts @@ -69,5 +69,5 @@ const setupMocks = () => { .mockImplementation(() => Promise.resolve('Test Log')) jest .spyOn(writeStreamModule, 'writeStream') - .mockImplementation(() => Promise.resolve()) + .mockImplementation(() => Promise.resolve(true)) } diff --git a/src/api/viya/spec/writeStream.spec.ts b/src/api/viya/spec/writeStream.spec.ts index 95c817e..6343f16 100644 --- a/src/api/viya/spec/writeStream.spec.ts +++ b/src/api/viya/spec/writeStream.spec.ts @@ -10,12 +10,22 @@ import { describe('writeStream', () => { const filename = 'test.txt' const content = 'test' + let stream: WriteStream beforeAll(async () => { stream = await createWriteStream(filename) }) + beforeEach(async () => { + await deleteFile(filename).catch(() => {}) // Ignore errors if the file doesn't exist + stream = await createWriteStream(filename) + }) + + afterEach(async () => { + await deleteFile(filename).catch(() => {}) // Ensure cleanup after test + }) + it('should resolve when the stream is written successfully', async () => { await expect(writeStream(stream, content)).toResolve() await expect(fileExists(filename)).resolves.toEqual(true) @@ -25,11 +35,30 @@ describe('writeStream', () => { }) it('should reject when the write errors out', async () => { + // Mock implementation of the write method jest .spyOn(stream, 'write') - .mockImplementation((_, callback) => callback(new Error('Test Error'))) + .mockImplementation( + ( + chunk: any, + encodingOrCb?: + | BufferEncoding + | ((error: Error | null | undefined) => void), + cb?: (error: Error | null | undefined) => void + ) => { + const callback = + typeof encodingOrCb === 'function' ? encodingOrCb : cb + if (callback) { + callback(new Error('Test Error')) // Simulate an error + } + return true // Simulate that the write operation was called + } + ) + + // Call the writeStream function and catch the error const error = await writeStream(stream, content).catch((e: any) => e) + // Assert that the error is correctly handled expect(error.message).toEqual('Test Error') }) }) diff --git a/src/api/viya/writeStream.ts b/src/api/viya/writeStream.ts index 59f1210..3fcd64c 100644 --- a/src/api/viya/writeStream.ts +++ b/src/api/viya/writeStream.ts @@ -3,9 +3,14 @@ import { WriteStream } from '../../types' export const writeStream = async ( stream: WriteStream, content: string -): Promise => - stream.write(content + '\n', (e: any) => { - if (e) return Promise.reject(e) - - return Promise.resolve() +): Promise => { + return new Promise((resolve, reject) => { + stream.write(content + '\n', (err: Error | null | undefined) => { + if (err) { + reject(err) // Reject on write error + } else { + resolve(true) // Resolve on successful write + } + }) }) +} diff --git a/src/request/RequestClient.ts b/src/request/RequestClient.ts index 48a0bc7..49d01b7 100644 --- a/src/request/RequestClient.ts +++ b/src/request/RequestClient.ts @@ -5,7 +5,6 @@ import { AxiosRequestHeaders, AxiosResponse } from 'axios' -import axios from 'axios' import * as https from 'https' import { CsrfToken } from '..' import { isAuthorizeFormRequired, isLogInRequired } from '../auth' diff --git a/src/test/RequestClient.spec.ts b/src/test/RequestClient.spec.ts index 7f42c0b..6c30214 100644 --- a/src/test/RequestClient.spec.ts +++ b/src/test/RequestClient.spec.ts @@ -24,9 +24,17 @@ const axiosActual = jest.requireActual('axios') jest .spyOn(axiosModules, 'createAxiosInstance') .mockImplementation((baseURL: string, httpsAgent?: https.Agent) => - axiosActual.create({ baseURL, httpsAgent }) + axiosActual.create({ baseURL, httpsAgent, withCredentials: true }) ) +jest.mock('util', () => { + const actualUtil = jest.requireActual('util') + return { + ...actualUtil, + inspect: jest.fn(actualUtil.inspect) + } +}) + const PORT = 8000 const SERVER_URL = `https://localhost:${PORT}/` @@ -432,15 +440,18 @@ ${resHeaders[0]}: ${resHeaders[1]}${ }) describe('prettifyString', () => { + const inspectMock = UtilsModule.inspect as unknown as jest.Mock + + beforeEach(() => { + // Reset the mock before each test to ensure a clean slate + inspectMock.mockClear() + }) + it(`should call inspect without colors when verbose mode is set to 'bleached'`, () => { const requestClient = new RequestClient('') - let verbose: VerboseMode = 'bleached' - requestClient.setVerboseMode(verbose) - - jest.spyOn(UtilsModule, 'inspect') + requestClient.setVerboseMode('bleached') const testStr = JSON.stringify({ test: 'test' }) - requestClient['prettifyString'](testStr) expect(UtilsModule.inspect).toHaveBeenCalledWith(testStr, { @@ -448,15 +459,11 @@ ${resHeaders[0]}: ${resHeaders[1]}${ }) }) - it(`should call inspect with colors when verbose mode is set to 'true'`, () => { + it(`should call inspect with colors when verbose mode is set to true`, () => { const requestClient = new RequestClient('') - let verbose: VerboseMode = true - requestClient.setVerboseMode(verbose) - - jest.spyOn(UtilsModule, 'inspect') + requestClient.setVerboseMode(true) const testStr = JSON.stringify({ test: 'test' }) - requestClient['prettifyString'](testStr) expect(UtilsModule.inspect).toHaveBeenCalledWith(testStr, { diff --git a/src/test/SAS_server_app.ts b/src/test/SAS_server_app.ts index aa8aa2c..e8e976c 100644 --- a/src/test/SAS_server_app.ts +++ b/src/test/SAS_server_app.ts @@ -1,7 +1,15 @@ import express = require('express') +import cors from 'cors' export const app = express() +app.use( + cors({ + origin: 'http://localhost', // Allow requests only from this origin + credentials: true // Allow credentials (cookies, auth headers, etc.) + }) +) + export const mockedAuthResponse = { access_token: 'access_token', token_type: 'bearer', @@ -12,11 +20,11 @@ export const mockedAuthResponse = { jti: 'jti' } -app.get('/', function (req: any, res: any) { +app.get('/', (req: any, res: any) => { res.send('Hello World') }) -app.post('/SASLogon/oauth/token', function (req: any, res: any) { +app.post('/SASLogon/oauth/token', (req: any, res: any) => { let valid = true // capture the encoded form data diff --git a/src/types/WriteStream.ts b/src/types/WriteStream.ts index 83a1d13..e21d760 100644 --- a/src/types/WriteStream.ts +++ b/src/types/WriteStream.ts @@ -1,4 +1,10 @@ -export interface WriteStream { - write: (content: string, callback: (err?: Error) => any) => void - path: string +import { WriteStream as FsWriteStream } from 'fs' + +export interface WriteStream extends FsWriteStream { + write( + chunk: any, + encoding?: BufferEncoding | ((error: Error | null | undefined) => void), + cb?: (error: Error | null | undefined) => void + ): boolean + path: string | Buffer }