737 lines
22 KiB
TypeScript
737 lines
22 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { Toolkits } from '../../src/models/Toolkits';
|
|
import ComposioClient from '@composio/client';
|
|
import { telemetry } from '../../src/telemetry/Telemetry';
|
|
import { ComposioAuthConfigNotFoundError } from '../../src/errors/AuthConfigErrors';
|
|
import { AuthSchemeTypes } from '../../src/types/authConfigs.types';
|
|
import { APIError } from '@composio/client';
|
|
|
|
// Mock dependencies
|
|
vi.mock('../../src/telemetry/Telemetry', () => ({
|
|
telemetry: {
|
|
instrument: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
// Create mock client with toolkit-related methods
|
|
const createMockClient = () => ({
|
|
baseURL: 'https://api.composio.dev',
|
|
apiKey: 'test-api-key',
|
|
toolkits: {
|
|
list: vi.fn(),
|
|
retrieve: vi.fn(),
|
|
retrieveCategories: vi.fn(),
|
|
listCategories: vi.fn(),
|
|
authorize: vi.fn(),
|
|
get: vi.fn(),
|
|
},
|
|
authConfigs: {
|
|
list: vi.fn(),
|
|
create: vi.fn(),
|
|
},
|
|
connectedAccounts: {
|
|
initiate: vi.fn(),
|
|
create: vi.fn(),
|
|
list: vi.fn(),
|
|
},
|
|
});
|
|
|
|
// Mock response data
|
|
const mockToolkitListResponse = {
|
|
items: [
|
|
{
|
|
name: 'GitHub',
|
|
slug: 'github',
|
|
meta: {
|
|
created_at: '2024-01-01',
|
|
updated_at: '2024-01-02',
|
|
tools_count: 10,
|
|
triggers_count: 5,
|
|
},
|
|
is_local_toolkit: false,
|
|
auth_schemes: ['oauth2'],
|
|
composio_managed_auth_schemes: ['oauth2'],
|
|
no_auth: false,
|
|
},
|
|
],
|
|
};
|
|
|
|
const mockToolkitRetrieveResponse = {
|
|
name: 'GitHub',
|
|
slug: 'github',
|
|
meta: {
|
|
created_at: '2024-01-01',
|
|
updated_at: '2024-01-02',
|
|
tools_count: 10,
|
|
triggers_count: 5,
|
|
},
|
|
is_local_toolkit: false,
|
|
composio_managed_auth_schemes: ['oauth2'],
|
|
auth_config_details: [
|
|
{
|
|
name: 'oauth2',
|
|
mode: 'oauth2',
|
|
fields: {
|
|
auth_config_creation: {
|
|
optional: [],
|
|
required: [],
|
|
},
|
|
connected_account_initiation: {
|
|
optional: [],
|
|
required: [],
|
|
},
|
|
},
|
|
proxy: {
|
|
base_url: 'https://api.github.com',
|
|
},
|
|
},
|
|
],
|
|
get_current_user_endpoint: '/user',
|
|
get_current_user_endpoint_method: 'GET',
|
|
};
|
|
|
|
describe('Toolkits', () => {
|
|
let toolkits: Toolkits;
|
|
let mockClient: ReturnType<typeof createMockClient>;
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
mockClient = createMockClient();
|
|
toolkits = new Toolkits(mockClient as unknown as ComposioClient);
|
|
});
|
|
|
|
describe('constructor', () => {
|
|
it('should create an instance successfully', () => {
|
|
expect(toolkits).toBeInstanceOf(Toolkits);
|
|
expect(telemetry.instrument).toHaveBeenCalledWith(toolkits, 'Toolkits');
|
|
});
|
|
|
|
it('should store the client reference', () => {
|
|
expect(toolkits['client']).toBe(mockClient);
|
|
});
|
|
});
|
|
|
|
describe('get', () => {
|
|
it('should get a list of toolkits', async () => {
|
|
mockClient.toolkits.list.mockResolvedValue(mockToolkitListResponse);
|
|
|
|
const result = await toolkits.get({});
|
|
|
|
expect(result).toEqual([
|
|
{
|
|
name: 'GitHub',
|
|
slug: 'github',
|
|
meta: {
|
|
createdAt: '2024-01-01',
|
|
updatedAt: '2024-01-02',
|
|
toolsCount: 10,
|
|
triggersCount: 5,
|
|
},
|
|
isLocalToolkit: false,
|
|
authSchemes: ['oauth2'],
|
|
composioManagedAuthSchemes: ['oauth2'],
|
|
noAuth: false,
|
|
},
|
|
]);
|
|
expect(mockClient.toolkits.list).toHaveBeenCalledWith({}, undefined);
|
|
});
|
|
|
|
it('should get a single toolkit by slug', async () => {
|
|
mockClient.toolkits.retrieve.mockResolvedValue(mockToolkitRetrieveResponse);
|
|
|
|
const result = await toolkits.get('github');
|
|
|
|
expect(result).toEqual({
|
|
name: 'GitHub',
|
|
slug: 'github',
|
|
meta: {
|
|
createdAt: '2024-01-01',
|
|
updatedAt: '2024-01-02',
|
|
toolsCount: 10,
|
|
triggersCount: 5,
|
|
},
|
|
isLocalToolkit: false,
|
|
composioManagedAuthSchemes: ['oauth2'],
|
|
authConfigDetails: [
|
|
{
|
|
name: 'oauth2',
|
|
mode: 'oauth2',
|
|
fields: {
|
|
authConfigCreation: {
|
|
optional: [],
|
|
required: [],
|
|
},
|
|
connectedAccountInitiation: {
|
|
optional: [],
|
|
required: [],
|
|
},
|
|
},
|
|
proxy: {
|
|
baseUrl: 'https://api.github.com',
|
|
},
|
|
},
|
|
],
|
|
getCurrentUserEndpoint: '/user',
|
|
getCurrentUserEndpointMethod: 'GET',
|
|
});
|
|
expect(mockClient.toolkits.retrieve).toHaveBeenCalledWith('github', undefined, undefined);
|
|
});
|
|
|
|
it('should handle toolkit without getCurrentUserEndpointMethod', async () => {
|
|
const responseWithoutMethod = {
|
|
...mockToolkitRetrieveResponse,
|
|
get_current_user_endpoint_method: undefined,
|
|
};
|
|
mockClient.toolkits.retrieve.mockResolvedValue(responseWithoutMethod);
|
|
|
|
const result = await toolkits.get('github');
|
|
|
|
expect(result).toEqual({
|
|
name: 'GitHub',
|
|
slug: 'github',
|
|
meta: {
|
|
createdAt: '2024-01-01',
|
|
updatedAt: '2024-01-02',
|
|
toolsCount: 10,
|
|
triggersCount: 5,
|
|
},
|
|
isLocalToolkit: false,
|
|
composioManagedAuthSchemes: ['oauth2'],
|
|
authConfigDetails: [
|
|
{
|
|
name: 'oauth2',
|
|
mode: 'oauth2',
|
|
fields: {
|
|
authConfigCreation: {
|
|
optional: [],
|
|
required: [],
|
|
},
|
|
connectedAccountInitiation: {
|
|
optional: [],
|
|
required: [],
|
|
},
|
|
},
|
|
proxy: {
|
|
baseUrl: 'https://api.github.com',
|
|
},
|
|
},
|
|
],
|
|
getCurrentUserEndpoint: '/user',
|
|
getCurrentUserEndpointMethod: undefined,
|
|
});
|
|
});
|
|
|
|
it('should throw ValidationError for invalid list query', async () => {
|
|
const promise = toolkits.get({ category: 123 } as any);
|
|
await expect(promise).rejects.toThrowError('Failed to fetch toolkits');
|
|
});
|
|
|
|
it('should throw ComposioToolkitNotFoundError when toolkit not found', async () => {
|
|
mockClient.toolkits.retrieve.mockRejectedValue(
|
|
new Error('Toolkit with slug non-existent not found')
|
|
);
|
|
|
|
const promise = toolkits.get('non-existent');
|
|
await expect(promise).rejects.toThrowError("Couldn't fetch Toolkit with slug: non-existent");
|
|
});
|
|
|
|
it('should throw ComposioToolkitFetchError for other errors', async () => {
|
|
mockClient.toolkits.list.mockRejectedValue(new Error('Network error'));
|
|
|
|
const promise = toolkits.get({});
|
|
await expect(promise).rejects.toThrowError('Failed to fetch toolkits');
|
|
});
|
|
});
|
|
|
|
describe('listCategories', () => {
|
|
it('should list toolkit categories', async () => {
|
|
const mockResponse = {
|
|
items: [
|
|
{
|
|
id: 'cat-1',
|
|
name: 'Category 1',
|
|
},
|
|
],
|
|
next_cursor: null,
|
|
total_pages: 1,
|
|
};
|
|
|
|
mockClient.toolkits.retrieveCategories.mockResolvedValue(mockResponse);
|
|
|
|
const result = await toolkits.listCategories();
|
|
|
|
expect(result).toEqual({
|
|
items: mockResponse.items,
|
|
nextCursor: mockResponse.next_cursor,
|
|
totalPages: mockResponse.total_pages,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('authorize', () => {
|
|
const userId = 'user_123';
|
|
const toolkitSlug = 'test-toolkit';
|
|
const mockToolkitResponse = {
|
|
slug: toolkitSlug,
|
|
name: 'Test Toolkit',
|
|
meta: {
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
tools_count: 1,
|
|
triggers_count: 0,
|
|
},
|
|
is_local_toolkit: false,
|
|
auth_config_details: [
|
|
{
|
|
name: 'OAUTH2',
|
|
mode: 'OAUTH2',
|
|
fields: {
|
|
auth_config_creation: {
|
|
optional: [],
|
|
required: [],
|
|
},
|
|
connected_account_initiation: {
|
|
optional: [],
|
|
required: [],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
};
|
|
|
|
it('should create auth config and initiate connection when no auth config exists', async () => {
|
|
// Mock toolkit retrieval
|
|
mockClient.toolkits.retrieve.mockResolvedValueOnce(mockToolkitResponse);
|
|
|
|
// Mock empty auth config list
|
|
mockClient.authConfigs.list.mockResolvedValueOnce({
|
|
items: [],
|
|
next_cursor: null,
|
|
total_pages: 1,
|
|
});
|
|
|
|
// Mock auth config creation
|
|
mockClient.authConfigs.create.mockResolvedValueOnce({
|
|
auth_config: {
|
|
id: 'auth_config_123',
|
|
auth_scheme: 'OAUTH2',
|
|
is_composio_managed: true,
|
|
is_disabled: false,
|
|
name: 'Test Toolkit Auth Config',
|
|
tool_access_config: {
|
|
tools_for_connected_account_creation: undefined,
|
|
},
|
|
no_of_connections: 0,
|
|
status: 'ENABLED',
|
|
uuid: 'uuid-1',
|
|
},
|
|
toolkit: {
|
|
logo: 'https://example.com/logo.png',
|
|
slug: toolkitSlug,
|
|
},
|
|
});
|
|
|
|
// Mock connected accounts list
|
|
mockClient.connectedAccounts.list.mockResolvedValueOnce({
|
|
items: [],
|
|
next_cursor: null,
|
|
total_pages: 1,
|
|
});
|
|
|
|
// Mock connection initiation
|
|
mockClient.connectedAccounts.create.mockResolvedValueOnce({
|
|
id: 'conn_123',
|
|
connectionData: {
|
|
type: 'OAUTH2',
|
|
val: {
|
|
status: 'INITIALIZING',
|
|
redirectUrl: 'https://auth.example.com/connect',
|
|
authScheme: 'OAUTH2',
|
|
},
|
|
},
|
|
});
|
|
|
|
const connectionRequest = await toolkits.authorize(userId, toolkitSlug);
|
|
|
|
// Verify the flow
|
|
expect(mockClient.toolkits.retrieve).toHaveBeenCalledWith(toolkitSlug, undefined, undefined);
|
|
expect(mockClient.authConfigs.list).toHaveBeenCalledWith(
|
|
{
|
|
toolkit_slug: toolkitSlug,
|
|
},
|
|
undefined
|
|
);
|
|
expect(mockClient.authConfigs.create).toHaveBeenCalledWith(
|
|
{
|
|
toolkit: {
|
|
slug: toolkitSlug,
|
|
},
|
|
auth_config: {
|
|
type: 'use_composio_managed_auth',
|
|
credentials: undefined,
|
|
name: 'Test Toolkit Auth Config',
|
|
tool_access_config: undefined,
|
|
},
|
|
},
|
|
undefined
|
|
);
|
|
expect(mockClient.connectedAccounts.create).toHaveBeenCalledWith(
|
|
{
|
|
auth_config: {
|
|
id: 'auth_config_123',
|
|
},
|
|
connection: {
|
|
user_id: userId,
|
|
},
|
|
},
|
|
undefined
|
|
);
|
|
expect(connectionRequest).toHaveProperty('id', 'conn_123');
|
|
expect(connectionRequest).toHaveProperty('waitForConnection');
|
|
expect(typeof connectionRequest.waitForConnection).toBe('function');
|
|
expect(connectionRequest.redirectUrl).toBe('https://auth.example.com/connect');
|
|
});
|
|
|
|
it('should use existing auth config to initiate connection', async () => {
|
|
// Mock toolkit retrieval
|
|
mockClient.toolkits.retrieve.mockResolvedValueOnce(mockToolkitResponse);
|
|
|
|
// Mock existing auth config
|
|
mockClient.authConfigs.list.mockResolvedValueOnce({
|
|
items: [
|
|
{
|
|
id: 'existing_auth_123',
|
|
auth_scheme: 'OAUTH2',
|
|
is_composio_managed: true,
|
|
is_disabled: false,
|
|
name: 'Existing Auth Config',
|
|
no_of_connections: 1,
|
|
status: 'ENABLED',
|
|
uuid: 'uuid-1',
|
|
toolkit: {
|
|
logo: 'https://example.com/logo.png',
|
|
slug: toolkitSlug,
|
|
},
|
|
},
|
|
],
|
|
next_cursor: null,
|
|
total_pages: 1,
|
|
});
|
|
|
|
// Mock connected accounts list
|
|
mockClient.connectedAccounts.list.mockResolvedValueOnce({
|
|
items: [],
|
|
next_cursor: null,
|
|
total_pages: 1,
|
|
});
|
|
|
|
// Mock connection initiation
|
|
mockClient.connectedAccounts.create.mockResolvedValueOnce({
|
|
id: 'conn_123',
|
|
connectionData: {
|
|
val: {
|
|
status: 'INITIALIZING',
|
|
redirectUrl: 'https://auth.example.com/connect',
|
|
authScheme: 'OAUTH2',
|
|
},
|
|
},
|
|
});
|
|
|
|
const connectionRequest = await toolkits.authorize(userId, toolkitSlug);
|
|
|
|
// Verify the flow
|
|
expect(mockClient.toolkits.retrieve).toHaveBeenCalledWith(toolkitSlug, undefined, undefined);
|
|
expect(mockClient.authConfigs.list).toHaveBeenCalledWith(
|
|
{
|
|
toolkit_slug: toolkitSlug,
|
|
},
|
|
undefined
|
|
);
|
|
expect(mockClient.authConfigs.create).not.toHaveBeenCalled();
|
|
expect(mockClient.connectedAccounts.create).toHaveBeenCalledWith(
|
|
{
|
|
auth_config: {
|
|
id: 'existing_auth_123',
|
|
},
|
|
connection: {
|
|
user_id: userId,
|
|
},
|
|
},
|
|
undefined
|
|
);
|
|
expect(connectionRequest).toHaveProperty('id', 'conn_123');
|
|
expect(connectionRequest).toHaveProperty('waitForConnection');
|
|
expect(typeof connectionRequest.waitForConnection).toBe('function');
|
|
expect(connectionRequest.redirectUrl).toBe('https://auth.example.com/connect');
|
|
});
|
|
|
|
it('should throw ComposioAuthConfigNotFoundError when toolkit has no auth config details', async () => {
|
|
// Mock toolkit retrieval with no auth config details
|
|
mockClient.toolkits.retrieve.mockResolvedValueOnce({
|
|
...mockToolkitResponse,
|
|
auth_config_details: [], // Empty auth config details
|
|
});
|
|
|
|
// Mock empty auth config list
|
|
mockClient.authConfigs.list.mockResolvedValueOnce({
|
|
items: [],
|
|
next_cursor: null,
|
|
total_pages: 1,
|
|
});
|
|
|
|
const promise = toolkits.authorize(userId, toolkitSlug);
|
|
|
|
await expect(promise).rejects.toThrow(ComposioAuthConfigNotFoundError);
|
|
await expect(promise).rejects.toThrow(`No auth configs found for toolkit ${toolkitSlug}`);
|
|
expect(mockClient.authConfigs.create).not.toHaveBeenCalled();
|
|
expect(mockClient.connectedAccounts.create).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should throw ComposioAuthConfigNotFoundError when auth config creation fails', async () => {
|
|
// Mock toolkit retrieval
|
|
mockClient.toolkits.retrieve.mockResolvedValueOnce(mockToolkitResponse);
|
|
|
|
// Mock empty auth config list
|
|
mockClient.authConfigs.list.mockResolvedValueOnce({
|
|
items: [],
|
|
next_cursor: null,
|
|
total_pages: 1,
|
|
});
|
|
|
|
// Mock auth config creation failure with ComposioClient.APIError
|
|
const apiError = new ComposioClient.APIError(
|
|
400,
|
|
'Bad Request',
|
|
'Bad Request',
|
|
new Headers()
|
|
);
|
|
mockClient.authConfigs.create.mockRejectedValueOnce(apiError);
|
|
|
|
const promise = toolkits.authorize(userId, toolkitSlug);
|
|
|
|
await expect(promise).rejects.toThrow(ComposioAuthConfigNotFoundError);
|
|
await expect(promise).rejects.toThrow(
|
|
`No Default auth config found for toolkit ${toolkitSlug}`
|
|
);
|
|
expect(mockClient.connectedAccounts.create).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should throw ComposioToolkitNotFoundError when toolkit does not exist', async () => {
|
|
mockClient.toolkits.retrieve.mockRejectedValue(
|
|
new APIError(400, 'Toolkit not found', 'Toolkit not found', new Headers())
|
|
);
|
|
|
|
const promise = toolkits.authorize('user-123', 'non-existent');
|
|
|
|
await expect(promise).rejects.toThrow("Couldn't fetch Toolkit with slug: non-existent");
|
|
expect(mockClient.authConfigs.list).not.toHaveBeenCalled();
|
|
expect(mockClient.authConfigs.create).not.toHaveBeenCalled();
|
|
expect(mockClient.connectedAccounts.create).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('getAuthConfigCreationFields', () => {
|
|
const toolkitSlug = 'test-toolkit';
|
|
const mockToolkit = {
|
|
authConfigDetails: [
|
|
{
|
|
name: 'oauth2',
|
|
mode: 'OAUTH2',
|
|
fields: {
|
|
authConfigCreation: {
|
|
required: [{ name: 'client_id' }, { name: 'client_secret' }],
|
|
optional: [{ name: 'redirect_uri' }],
|
|
},
|
|
connectedAccountInitiation: {
|
|
required: [{ name: 'code' }],
|
|
optional: [{ name: 'state' }],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
};
|
|
|
|
beforeEach(() => {
|
|
vi.spyOn(Toolkits.prototype as any, 'getToolkitBySlug').mockResolvedValue(mockToolkit as any);
|
|
});
|
|
|
|
it('returns all fields when requiredOnly is false', async () => {
|
|
const result = await toolkits.getAuthConfigCreationFields(
|
|
toolkitSlug,
|
|
AuthSchemeTypes.OAUTH2,
|
|
{
|
|
requiredOnly: false,
|
|
}
|
|
);
|
|
expect(result).toEqual([
|
|
{ name: 'client_id', required: true },
|
|
{ name: 'client_secret', required: true },
|
|
{ name: 'redirect_uri', required: false },
|
|
]);
|
|
});
|
|
|
|
it('returns only required fields when requiredOnly is true', async () => {
|
|
const result = await toolkits.getAuthConfigCreationFields(
|
|
toolkitSlug,
|
|
AuthSchemeTypes.OAUTH2,
|
|
{
|
|
requiredOnly: true,
|
|
}
|
|
);
|
|
expect(result).toEqual([
|
|
{ name: 'client_id', required: true },
|
|
{ name: 'client_secret', required: true },
|
|
]);
|
|
});
|
|
|
|
it('selects the correct auth config by authScheme', async () => {
|
|
const multiToolkit = {
|
|
authConfigDetails: [
|
|
{
|
|
name: 'oauth2',
|
|
mode: 'OAUTH2',
|
|
fields: {
|
|
authConfigCreation: {
|
|
required: [{ name: 'client_id' }],
|
|
optional: [],
|
|
},
|
|
connectedAccountInitiation: {
|
|
required: [],
|
|
optional: [],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: 'api_key',
|
|
mode: 'API_KEY',
|
|
fields: {
|
|
authConfigCreation: {
|
|
required: [{ name: 'api_key' }],
|
|
optional: [],
|
|
},
|
|
connectedAccountInitiation: {
|
|
required: [],
|
|
optional: [],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
};
|
|
(Toolkits.prototype as any).getToolkitBySlug = vi.fn().mockResolvedValueOnce(multiToolkit);
|
|
const result = await toolkits.getAuthConfigCreationFields(
|
|
toolkitSlug,
|
|
AuthSchemeTypes.API_KEY,
|
|
{
|
|
requiredOnly: true,
|
|
}
|
|
);
|
|
expect(result).toEqual([{ name: 'api_key', required: true }]);
|
|
});
|
|
|
|
it('throws if no authConfigDetails', async () => {
|
|
(Toolkits.prototype as any).getToolkitBySlug = vi.fn().mockResolvedValueOnce({});
|
|
await expect(
|
|
toolkits.getAuthConfigCreationFields(toolkitSlug, AuthSchemeTypes.API_KEY, {
|
|
requiredOnly: true,
|
|
})
|
|
).rejects.toThrow(ComposioAuthConfigNotFoundError);
|
|
});
|
|
});
|
|
|
|
describe('getConnectedAccountInitiationFields', () => {
|
|
const toolkitSlug = 'test-toolkit';
|
|
const mockToolkit = {
|
|
authConfigDetails: [
|
|
{
|
|
name: 'oauth2',
|
|
mode: 'OAUTH2',
|
|
fields: {
|
|
authConfigCreation: {
|
|
required: [],
|
|
optional: [],
|
|
},
|
|
connectedAccountInitiation: {
|
|
required: [{ name: 'code' }],
|
|
optional: [{ name: 'state' }],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
};
|
|
|
|
beforeEach(() => {
|
|
vi.spyOn(Toolkits.prototype as any, 'getToolkitBySlug').mockResolvedValue(mockToolkit as any);
|
|
});
|
|
|
|
it('returns all fields when requiredOnly is false', async () => {
|
|
const result = await toolkits.getConnectedAccountInitiationFields(toolkitSlug, 'OAUTH2', {
|
|
requiredOnly: false,
|
|
});
|
|
expect(result).toEqual([
|
|
{ name: 'code', required: true },
|
|
{ name: 'state', required: false },
|
|
]);
|
|
});
|
|
|
|
it('returns only required fields when requiredOnly is true', async () => {
|
|
const result = await toolkits.getConnectedAccountInitiationFields(toolkitSlug, 'OAUTH2', {
|
|
requiredOnly: true,
|
|
});
|
|
expect(result).toEqual([{ name: 'code', required: true }]);
|
|
});
|
|
|
|
it('selects the correct auth config by authScheme', async () => {
|
|
const multiToolkit = {
|
|
authConfigDetails: [
|
|
{
|
|
name: 'oauth2',
|
|
mode: 'OAUTH2',
|
|
fields: {
|
|
authConfigCreation: {
|
|
required: [],
|
|
optional: [],
|
|
},
|
|
connectedAccountInitiation: {
|
|
required: [{ name: 'code' }],
|
|
optional: [],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: 'api_key',
|
|
mode: 'API_KEY',
|
|
fields: {
|
|
authConfigCreation: {
|
|
required: [],
|
|
optional: [],
|
|
},
|
|
connectedAccountInitiation: {
|
|
required: [{ name: 'api_key_code' }],
|
|
optional: [],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
};
|
|
(Toolkits.prototype as any).getToolkitBySlug = vi.fn().mockResolvedValueOnce(multiToolkit);
|
|
const result = await toolkits.getConnectedAccountInitiationFields(
|
|
toolkitSlug,
|
|
AuthSchemeTypes.API_KEY,
|
|
{
|
|
requiredOnly: true,
|
|
}
|
|
);
|
|
expect(result).toEqual([{ name: 'api_key_code', required: true }]);
|
|
});
|
|
|
|
it('throws if no authConfigDetails', async () => {
|
|
(Toolkits.prototype as any).getToolkitBySlug = vi.fn().mockResolvedValueOnce({});
|
|
await expect(
|
|
toolkits.getConnectedAccountInitiationFields(toolkitSlug, AuthSchemeTypes.API_KEY, {
|
|
requiredOnly: true,
|
|
})
|
|
).rejects.toThrow(ComposioAuthConfigNotFoundError);
|
|
});
|
|
});
|
|
});
|