import { ContextManager } from '../ContextManager' import { RequestClient } from '../request/RequestClient' import * as dotenv from 'dotenv' import axios from 'axios' jest.mock('axios') const mockedAxios = axios as jest.Mocked describe('ContextManager', () => { dotenv.config() const contextManager = new ContextManager( process.env.SERVER_URL as string, new RequestClient(process.env.SERVER_URL as string) ) const defaultComputeContexts = contextManager.getDefaultComputeContexts const defaultLauncherContexts = contextManager.getDefaultLauncherContexts const getRandomDefaultComputeContext = () => defaultComputeContexts[ Math.floor(Math.random() * defaultComputeContexts.length) ] const getRandomDefaultLauncherContext = () => defaultLauncherContexts[ Math.floor(Math.random() * defaultLauncherContexts.length) ] describe('getComputeContexts', () => { it('should fetch compute contexts', async () => { const sampleComputeContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: 'Fake Compute Context', attributes: {} } const sampleResponse = { items: [sampleComputeContext] } mockedAxios.get.mockImplementation(() => Promise.resolve({ data: sampleResponse }) ) await expect(contextManager.getComputeContexts()).resolves.toEqual([ sampleComputeContext ]) }) }) describe('getLauncherContexts', () => { it('should fetch launcher contexts', async () => { const sampleComputeContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: 'Fake Launcher Context', attributes: {} } const sampleResponse = { items: [sampleComputeContext] } mockedAxios.get.mockImplementation(() => Promise.resolve({ data: sampleResponse }) ) await expect(contextManager.getLauncherContexts()).resolves.toEqual([ sampleComputeContext ]) }) }) describe('createComputeContext', () => { it('should throw an error if context name was not provided', async () => { await expect( contextManager.createComputeContext( '', 'Test Launcher Context', 'fakeAccountId', [] ) ).rejects.toEqual(new Error('Context name is required.')) }) it('should throw an error when attempt to create context with reserved name', async () => { const contextName = getRandomDefaultComputeContext() await expect( contextManager.createComputeContext( contextName, 'Test Launcher Context', 'fakeAccountId', [] ) ).rejects.toEqual( new Error(`Compute context '${contextName}' already exists.`) ) }) it('should throw an error if context already exists', async () => { const contextName = 'Existing Compute Context' const sampleComputeContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: contextName, attributes: {} } const sampleResponse = { items: [sampleComputeContext] } mockedAxios.get.mockImplementation(() => Promise.resolve({ data: sampleResponse }) ) await expect( contextManager.createComputeContext( contextName, 'Test Launcher Context', 'fakeAccountId', [] ) ).rejects.toEqual( new Error(`Compute context '${contextName}' already exists.`) ) }) it('should create compute context without launcher context', async () => { const contextName = 'New Compute Context' const sampleExistingComputeContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: 'Existing Compute Context', attributes: {} } const sampleNewComputeContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: contextName, attributes: {} } const sampleResponseExistingComputeContexts = { items: [sampleExistingComputeContext] } const sampleResponseCreatedComputeContext = { items: [sampleNewComputeContext] } mockedAxios.get.mockImplementation(() => Promise.resolve({ data: sampleResponseExistingComputeContexts }) ) mockedAxios.post.mockImplementation(() => Promise.resolve({ data: sampleResponseCreatedComputeContext }) ) await expect( contextManager.createComputeContext( contextName, '', 'fakeAccountId', [] ) ).resolves.toEqual({ items: [ { attributes: {}, createdBy: 'fake creator', id: 'fakeId', name: contextName, version: 2 } ] }) }) it('should create compute context with default launcher context', async () => { const contextName = 'New Compute Context' const sampleExistingComputeContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: 'Existing Compute Context', attributes: {} } const sampleNewComputeContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: contextName, attributes: {} } const sampleResponseExistingComputeContexts = { items: [sampleExistingComputeContext] } const sampleResponseCreatedComputeContext = { items: [sampleNewComputeContext] } mockedAxios.get.mockImplementation(() => Promise.resolve({ data: sampleResponseExistingComputeContexts }) ) mockedAxios.post.mockImplementation(() => Promise.resolve({ data: sampleResponseCreatedComputeContext }) ) await expect( contextManager.createComputeContext( contextName, getRandomDefaultLauncherContext(), 'fakeAccountId', [] ) ).resolves.toEqual({ items: [ { attributes: {}, createdBy: 'fake creator', id: 'fakeId', name: contextName, version: 2 } ] }) }) it('should create compute context with not existing launcher context', async () => { const computeContextName = 'New Compute Context' const launcherContextName = 'New Launcher Context' const sampleExistingComputeContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: 'Existing Compute Context', attributes: {} } const sampleNewComputeContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: computeContextName, attributes: {} } const sampleNewLauncherContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: launcherContextName, attributes: {} } const sampleResponseExistingComputeContexts = { items: [sampleExistingComputeContext] } const sampleResponseCreatedLauncherContext = { items: [sampleNewLauncherContext] } const sampleResponseCreatedComputeContext = { items: [sampleNewComputeContext] } mockedAxios.get .mockImplementationOnce(() => Promise.resolve({ data: sampleResponseExistingComputeContexts }) ) .mockImplementationOnce(() => Promise.resolve({ data: sampleResponseCreatedLauncherContext }) ) mockedAxios.post.mockImplementation(() => Promise.resolve({ data: sampleResponseCreatedComputeContext }) ) await expect( contextManager.createComputeContext( computeContextName, launcherContextName, 'fakeAccountId', [] ) ).resolves.toEqual({ items: [ { attributes: {}, createdBy: 'fake creator', id: 'fakeId', name: computeContextName, version: 2 } ] }) }) }) describe('createLauncherContext', () => { it('should throw an error if context name was not provided', async () => { await expect( contextManager.createLauncherContext('', 'Test Description') ).rejects.toEqual(new Error('Context name is required.')) }) it('should throw an error when attempt to create context with reserved name', async () => { const contextName = getRandomDefaultLauncherContext() await expect( contextManager.createLauncherContext(contextName, 'Test Description') ).rejects.toEqual( new Error(`Launcher context '${contextName}' already exists.`) ) }) it('should throw an error if context already exists', async () => { const contextName = 'Existing Launcher Context' const sampleLauncherContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: contextName, attributes: {} } const sampleResponse = { items: [sampleLauncherContext] } mockedAxios.get.mockImplementation(() => Promise.resolve({ data: sampleResponse }) ) await expect( contextManager.createLauncherContext(contextName, 'Test Description') ).rejects.toEqual( new Error(`Launcher context '${contextName}' already exists.`) ) }) it('should create launcher context', async () => { const contextName = 'New Launcher Context' const sampleExistingLauncherContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: 'Existing Launcher Context', attributes: {} } const sampleNewLauncherContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: contextName, attributes: {} } const sampleResponseExistingLauncherContext = { items: [sampleExistingLauncherContext] } const sampleResponseCreatedLauncherContext = { items: [sampleNewLauncherContext] } mockedAxios.get.mockImplementation(() => Promise.resolve({ data: sampleResponseExistingLauncherContext }) ) mockedAxios.post.mockImplementation(() => Promise.resolve({ data: sampleResponseCreatedLauncherContext }) ) await expect( contextManager.createLauncherContext(contextName, 'Test Description') ).resolves.toEqual({ items: [ { attributes: {}, createdBy: 'fake creator', id: 'fakeId', name: contextName, version: 2 } ] }) }) }) describe('editComputeContext', () => { const editedContext = { name: 'updated name', description: 'updated description', id: 'someId' } it('should throw an error if context name was not provided', async () => { await expect( contextManager.editComputeContext('', editedContext) ).rejects.toEqual(new Error('Context name is required.')) }) it('should throw an error when attempt to edit context with reserved name', async () => { const contextName = getRandomDefaultComputeContext() let editError: Error = { name: '', message: '' } try { contextManager.isDefaultContext( contextName, defaultComputeContexts, 'Editing default SAS compute contexts is not allowed.', true ) } catch (error) { editError = error } await expect( contextManager.editComputeContext(contextName, editedContext) ).rejects.toEqual(editError) }) it('should edit context if founded by name', async () => { const sampleComputeContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: editedContext.name, attributes: {} } const sampleResponseGetComputeContextByName = { items: [sampleComputeContext] } mockedAxios.put.mockImplementation(() => Promise.resolve({ data: sampleResponseGetComputeContextByName }) ) const expectedResponse = { etag: '', result: sampleResponseGetComputeContextByName } await expect( contextManager.editComputeContext(editedContext.name, editedContext) ).resolves.toEqual(expectedResponse) }) }) describe('getExecutableContexts', () => { it('should return executable contexts', async () => { const sampleComputeContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: 'Executable Compute Context', attributes: {} } const sampleResponse = { items: [sampleComputeContext] } mockedAxios.get.mockImplementation(() => Promise.resolve({ data: sampleResponse }) ) const user = 'testUser' const fakedExecuteScript = async () => { return Promise.resolve({ log: `SYSUSERID=${user}` }) } const expectedResponse = [ { ...sampleComputeContext, attributes: { sysUserId: user } } ] await expect( contextManager.getExecutableContexts(fakedExecuteScript) ).resolves.toEqual(expectedResponse) }) it('should not return executable contexts', async () => { const sampleComputeContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: 'Not Executable Compute Context', attributes: {} } const sampleResponse = { items: [sampleComputeContext] } mockedAxios.get.mockImplementation(() => Promise.resolve({ data: sampleResponse }) ) const fakedExecuteScript = async () => { return Promise.resolve({ log: '' }) } await expect( contextManager.getExecutableContexts(fakedExecuteScript) ).resolves.toEqual([]) }) }) describe('deleteComputeContext', () => { it('should throw an error if context name was not provided', async () => { await expect(contextManager.deleteComputeContext('')).rejects.toEqual( new Error('Context name is required.') ) }) it('should throw an error when attempt to delete context with reserved name', async () => { const contextName = getRandomDefaultComputeContext() let deleteError: Error = { name: '', message: '' } try { contextManager.isDefaultContext( contextName, defaultComputeContexts, 'Deleting default SAS compute contexts is not allowed.', true ) } catch (error) { deleteError = error } await expect( contextManager.deleteComputeContext(contextName) ).rejects.toEqual(deleteError) }) it('should delete context', async () => { const contextName = 'Compute Context To Delete' const sampleComputeContext = { createdBy: 'fake creator', id: 'fakeId', version: 2, name: contextName, attributes: {} } const sampleResponseGetComputeContextByName = { items: [sampleComputeContext] } const sampleResponseDeletedContext = { items: [sampleComputeContext] } mockedAxios.get.mockImplementation(() => Promise.resolve({ data: sampleResponseGetComputeContextByName }) ) mockedAxios.delete.mockImplementation(() => Promise.resolve({ data: sampleResponseDeletedContext }) ) const expectedResponse = { etag: '', result: sampleResponseDeletedContext } await expect( contextManager.deleteComputeContext(contextName) ).resolves.toEqual(expectedResponse) }) }) })