diff --git a/src/api/viya/spec/uploadTables.spec.ts b/src/api/viya/spec/uploadTables.spec.ts new file mode 100644 index 0000000..529c6e2 --- /dev/null +++ b/src/api/viya/spec/uploadTables.spec.ts @@ -0,0 +1,67 @@ +import { RequestClient } from '../../../request/RequestClient' +import * as convertToCsvModule from '../../../utils/convertToCsv' +import { uploadTables } from '../uploadTables' + +const requestClient = new (>RequestClient)() + +describe('uploadTables', () => { + beforeEach(() => { + setupMocks() + }) + + it('should return a list of uploaded files', async () => { + const data = { foo: 'bar' } + + const files = await uploadTables(requestClient, data, 't0k3n') + + expect(files).toEqual([{ tableName: 'foo', file: 'test-file' }]) + expect(requestClient.uploadFile).toHaveBeenCalledTimes(1) + expect(requestClient.uploadFile).toHaveBeenCalledWith( + '/files/files#rawUpload', + 'Test CSV', + 't0k3n' + ) + }) + + it('should throw an error when the CSV exceeds the maximum length', async () => { + const data = { foo: 'bar' } + jest + .spyOn(convertToCsvModule, 'convertToCSV') + .mockImplementation(() => 'ERROR: LARGE STRING LENGTH') + + const error = await uploadTables(requestClient, data, 't0k3n').catch( + (e) => e + ) + + expect(requestClient.uploadFile).not.toHaveBeenCalled() + expect(error.message).toEqual( + 'The max length of a string value in SASjs is 32765 characters.' + ) + }) + + it('should throw an error when the file upload fails', async () => { + const data = { foo: 'bar' } + jest + .spyOn(requestClient, 'uploadFile') + .mockImplementation(() => Promise.reject('Upload Error')) + + const error = await uploadTables(requestClient, data, 't0k3n').catch( + (e) => e + ) + + expect(error).toContain('Error while uploading file.') + }) +}) + +const setupMocks = () => { + jest.restoreAllMocks() + jest.mock('../../../utils/convertToCsv') + jest + .spyOn(convertToCsvModule, 'convertToCSV') + .mockImplementation(() => 'Test CSV') + jest + .spyOn(requestClient, 'uploadFile') + .mockImplementation(() => + Promise.resolve({ result: 'test-file', etag: '' }) + ) +} diff --git a/src/api/viya/uploadTables.ts b/src/api/viya/uploadTables.ts index 13bf7b8..e7f5b66 100644 --- a/src/api/viya/uploadTables.ts +++ b/src/api/viya/uploadTables.ts @@ -8,12 +8,6 @@ export async function uploadTables( accessToken?: string ) { const uploadedFiles = [] - const headers: any = { - 'Content-Type': 'application/json' - } - if (accessToken) { - headers.Authorization = `Bearer ${accessToken}` - } for (const tableName in data) { const csv = convertToCSV(data[tableName]) diff --git a/src/auth/getAccessToken.ts b/src/auth/getAccessToken.ts index 0b11340..d51833e 100644 --- a/src/auth/getAccessToken.ts +++ b/src/auth/getAccessToken.ts @@ -1,4 +1,5 @@ -import { SasAuthResponse } from '@sasjs/utils' +import { SasAuthResponse } from '@sasjs/utils/types' +import { prefixMessage } from '@sasjs/utils/error' import * as NodeFormData from 'form-data' import { RequestClient } from '../request/RequestClient' @@ -44,6 +45,9 @@ export async function getAccessToken( headers ) .then((res) => res.result as SasAuthResponse) + .catch((err) => { + throw prefixMessage(err, 'Error while getting access token') + }) return authResponse } diff --git a/src/auth/spec/getAccessToken.spec.ts b/src/auth/spec/getAccessToken.spec.ts new file mode 100644 index 0000000..e4fa00f --- /dev/null +++ b/src/auth/spec/getAccessToken.spec.ts @@ -0,0 +1,75 @@ +import { AuthConfig } from '@sasjs/utils' +import * as NodeFormData from 'form-data' +import { generateToken, mockAuthResponse } from './mockResponses' +import { RequestClient } from '../../request/RequestClient' +import { getAccessToken } from '../getAccessToken' + +const requestClient = new (>RequestClient)() + +describe('getAccessToken', () => { + it('should attempt to refresh tokens', async () => { + setupMocks() + const access_token = generateToken(30) + const refresh_token = generateToken(30) + const authConfig: AuthConfig = { + access_token, + refresh_token, + client: 'cl13nt', + secret: 's3cr3t' + } + jest + .spyOn(requestClient, 'post') + .mockImplementation(() => + Promise.resolve({ result: mockAuthResponse, etag: '' }) + ) + const token = Buffer.from( + authConfig.client + ':' + authConfig.secret + ).toString('base64') + + await getAccessToken( + requestClient, + authConfig.client, + authConfig.secret, + authConfig.refresh_token + ) + + expect(requestClient.post).toHaveBeenCalledWith( + '/SASLogon/oauth/token', + expect.any(NodeFormData), + undefined, + expect.stringContaining('multipart/form-data; boundary='), + { + Authorization: 'Basic ' + token + } + ) + }) + + it('should handle errors while refreshing tokens', async () => { + setupMocks() + const access_token = generateToken(30) + const refresh_token = generateToken(30) + const authConfig: AuthConfig = { + access_token, + refresh_token, + client: 'cl13nt', + secret: 's3cr3t' + } + jest + .spyOn(requestClient, 'post') + .mockImplementation(() => Promise.reject('Token Error')) + + const error = await getAccessToken( + requestClient, + authConfig.client, + authConfig.secret, + authConfig.refresh_token + ).catch((e) => e) + + expect(error).toContain('Error while getting access token') + }) +}) + +const setupMocks = () => { + jest.restoreAllMocks() + jest.mock('../../request/RequestClient') +}