UNPKG

@future-agi/sdk

Version:

We help GenAI teams maintain high-accuracy for their Models in production.

625 lines 26.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const dataset_1 = require("../dataset"); const types_1 = require("../types"); const errors_1 = require("../../utils/errors"); const fs = __importStar(require("fs")); const stream_1 = require("stream"); // Mock built-in modules jest.mock('axios'); jest.mock('fs', () => (Object.assign(Object.assign({}, jest.requireActual('fs')), { existsSync: jest.fn(), createReadStream: jest.fn() }))); // Mock the APIKeyAuth base class jest.mock('../../api/auth', () => ({ APIKeyAuth: class MockAPIKeyAuth { constructor(config) { this._baseUrl = 'https://api.futureagi.com'; // Mock constructor } request(config, responseHandler) { return __awaiter(this, void 0, void 0, function* () { // Mock request method - will be overridden in tests return {}; }); } }, ResponseHandler: class MockResponseHandler { static parse(response, handlerClass) { return handlerClass._parseSuccess(response); } static _parseSuccess(response) { if (response.data) { return response.data; } throw new Error("Mock _parseSuccess error: response.data is undefined"); } static _handleError(response) { throw new Error('Mock error'); } }, })); describe('DatasetResponseHandler', () => { describe('_parseSuccess', () => { test('should parse dataset names response', () => { const mockResponse = { data: { result: { datasets: [ { datasetId: 'dataset-123', name: 'test-dataset', }, ], }, }, config: { url: 'https://api.futureagi.com/model-hub/develops/get-datasets-names/', headers: {}, }, }; const result = dataset_1.DatasetResponseHandler._parseSuccess(mockResponse); expect(result).toEqual({ id: 'dataset-123', name: 'test-dataset', }); }); test('should throw error for empty datasets list', () => { const mockResponse = { data: { result: { datasets: [], }, }, config: { url: 'https://api.futureagi.com/model-hub/develops/get-datasets-names/', headers: {}, }, }; expect(() => { dataset_1.DatasetResponseHandler._parseSuccess(mockResponse); }).toThrow(errors_1.DatasetNotFoundError); }); test('should throw error for multiple datasets', () => { const mockResponse = { data: { result: { datasets: [ { datasetId: '1', name: 'dataset1', }, { datasetId: '2', name: 'dataset2', }, ], }, }, config: { url: 'https://api.futureagi.com/model-hub/develops/get-datasets-names/', headers: {}, }, }; expect(() => { dataset_1.DatasetResponseHandler._parseSuccess(mockResponse); }).toThrow('Multiple datasets found'); }); test('should parse dataset table response', () => { const mockResponse = { data: { result: { columnConfig: [ { id: 'col-1', name: 'name', dataType: types_1.DataTypeChoices.TEXT, originType: types_1.SourceChoices.OTHERS, sourceId: null, isFrozen: { isFrozen: false }, isVisible: true, evalTag: [], averageScore: null, orderIndex: 0, }, ], table: [ { rowId: 'row-1', order: 0, 'col-1': { cellValue: 'John', valueInfos: null, metadata: null, status: 'completed', failureReason: null, }, }, ], metadata: {}, }, }, config: { url: 'https://api.futureagi.com/model-hub/develops/dataset-123/get-dataset-table/', headers: {}, }, }; const result = dataset_1.DatasetResponseHandler._parseSuccess(mockResponse); expect(result.id).toBe('dataset-123'); expect(result.columns).toHaveLength(1); expect(result.rows).toHaveLength(1); expect(result.columns[0].name).toBe('name'); expect(result.rows[0].cells).toHaveLength(1); }); test('should parse dataset creation response', () => { const mockResponse = { data: { result: { datasetId: 'dataset-123', datasetName: 'test-dataset', }, }, config: { url: 'https://api.futureagi.com/model-hub/develops/create-empty-dataset/', headers: {}, }, }; const result = dataset_1.DatasetResponseHandler._parseSuccess(mockResponse); expect(result).toEqual({ id: 'dataset-123', name: 'test-dataset', }); }); }); describe('_handleError', () => { test('should handle different error status codes', () => { const mockResponse = { status: 404, data: { message: 'Dataset not found' }, statusText: 'Not Found', }; expect(() => { dataset_1.DatasetResponseHandler._handleError(mockResponse); }).toThrow(errors_1.DatasetNotFoundError); }); test('should handle server errors', () => { const mockResponse = { status: 500, data: { message: 'Internal server error' }, statusText: 'Internal Server Error', }; expect(() => { dataset_1.DatasetResponseHandler._handleError(mockResponse); }).toThrow('Internal server error'); }); }); }); describe('Dataset', () => { let dataset; let mockRequest; beforeEach(() => { mockRequest = jest.fn(); dataset = new dataset_1.Dataset({ fiApiKey: 'test-key', fiSecretKey: 'test-secret', }); dataset.request = mockRequest; }); describe('constructor', () => { test('should create dataset instance', () => { expect(dataset).toBeInstanceOf(dataset_1.Dataset); }); test('should create dataset with config', () => { const config = { id: 'dataset-123', name: 'test-dataset', }; const datasetWithConfig = new dataset_1.Dataset({ fiApiKey: 'test-key', fiSecretKey: 'test-secret', datasetConfig: config, }); expect(datasetWithConfig.getConfig()).toEqual(config); }); }); describe('getConfig', () => { test('should return dataset config', () => { const config = { id: 'dataset-123', name: 'test-dataset', }; dataset._datasetConfig = config; expect(dataset.getConfig()).toEqual(config); }); test('should throw error when no config is set', () => { expect(() => { dataset.getConfig(); }).toThrow(errors_1.DatasetError); }); }); describe('create', () => { test('should create empty dataset', () => __awaiter(void 0, void 0, void 0, function* () { const config = { name: 'test-dataset', }; dataset._datasetConfig = config; mockRequest.mockResolvedValue({ id: 'dataset-123', name: 'test-dataset', }); const result = yield dataset.create(); expect(result).toBe(dataset); expect(mockRequest).toHaveBeenCalledWith(expect.objectContaining({ method: 'POST', json: expect.objectContaining({ new_dataset_name: 'test-dataset', }), }), dataset_1.DatasetResponseHandler); })); test('should create dataset from file', () => __awaiter(void 0, void 0, void 0, function* () { const config = { name: 'test-dataset', }; dataset._datasetConfig = config; mockRequest.mockResolvedValue({ id: 'dataset-123', name: 'test-dataset', }); // Mock fs.existsSync to avoid file system check fs.existsSync.mockReturnValue(true); fs.createReadStream.mockReturnValue(new stream_1.Readable()); const result = yield dataset.create('path/to/file.csv'); expect(result).toBe(dataset); expect(mockRequest).toHaveBeenCalledWith(expect.objectContaining({ method: 'POST', // Data is now a FormData object, which is harder to inspect directly }), dataset_1.DatasetResponseHandler); })); test('should create dataset from Hugging Face', () => __awaiter(void 0, void 0, void 0, function* () { const config = { name: 'test-dataset', }; const hfConfig = { name: 'squad', subset: 'plain_text', split: 'train', numRows: 1000, }; dataset._datasetConfig = config; mockRequest.mockResolvedValue({ id: 'dataset-123', name: 'test-dataset', }); const result = yield dataset.create(hfConfig); expect(result).toBe(dataset); expect(mockRequest).toHaveBeenCalledWith(expect.objectContaining({ method: 'POST', json: expect.objectContaining({ new_dataset_name: 'test-dataset', huggingface_dataset_name: 'squad', huggingface_dataset_config: 'plain_text', huggingface_dataset_split: 'train', num_rows: 1000, }), }), dataset_1.DatasetResponseHandler); })); test('should throw error when dataset config is not set', () => __awaiter(void 0, void 0, void 0, function* () { yield expect(dataset.create()).rejects.toThrow(errors_1.DatasetError); })); test('should throw error when dataset already exists', () => __awaiter(void 0, void 0, void 0, function* () { const config = { id: 'dataset-123', name: 'test-dataset', }; dataset._datasetConfig = config; yield expect(dataset.create()).rejects.toThrow(errors_1.DatasetError); })); }); describe('download', () => { test('should download dataset', () => __awaiter(void 0, void 0, void 0, function* () { const config = { id: 'dataset-123', name: 'test-dataset', }; dataset._datasetConfig = config; mockRequest.mockResolvedValue({ id: 'dataset-123', columns: [], rows: [], metadata: {}, }); const result = yield dataset.download(); expect(result).toBe(dataset); expect(mockRequest).toHaveBeenCalled(); })); test('should download dataset to memory', () => __awaiter(void 0, void 0, void 0, function* () { const config = { id: 'dataset-123', name: 'test-dataset', }; const mockTable = { id: 'dataset-123', columns: [], rows: [], metadata: {}, }; dataset._datasetConfig = config; mockRequest.mockResolvedValue(mockTable); const result = yield dataset.download(undefined, true); expect(result).toEqual(mockTable); })); test('should throw error when dataset name is not set', () => __awaiter(void 0, void 0, void 0, function* () { yield expect(dataset.download()).rejects.toThrow(errors_1.DatasetError); })); test('should throw error when dataset ID is not set', () => __awaiter(void 0, void 0, void 0, function* () { const config = { name: 'test-dataset', }; dataset._datasetConfig = config; yield expect(dataset.download()).rejects.toThrow(errors_1.DatasetError); })); }); describe('delete', () => { test('should delete dataset', () => __awaiter(void 0, void 0, void 0, function* () { const config = { id: 'dataset-123', name: 'test-dataset', }; dataset._datasetConfig = config; mockRequest.mockResolvedValue({}); yield dataset.delete(); expect(dataset._datasetConfig).toBeNull(); expect(mockRequest).toHaveBeenCalledWith(expect.objectContaining({ method: 'DELETE', json: { dataset_ids: ['dataset-123'] }, }), dataset_1.DatasetResponseHandler); })); test('should throw error when dataset ID is not set', () => __awaiter(void 0, void 0, void 0, function* () { yield expect(dataset.delete()).rejects.toThrow(errors_1.DatasetError); })); }); describe('addColumns', () => { test('should add columns to dataset', () => __awaiter(void 0, void 0, void 0, function* () { const config = { id: 'dataset-123', name: 'test-dataset', }; const columns = [ (0, types_1.createColumn)({ name: 'col1', dataType: types_1.DataTypeChoices.TEXT }), (0, types_1.createColumn)({ name: 'col2', dataType: types_1.DataTypeChoices.INTEGER }), ]; dataset._datasetConfig = config; mockRequest.mockResolvedValue({}); const result = yield dataset.addColumns(columns); expect(result).toBe(dataset); expect(mockRequest).toHaveBeenCalledWith(expect.objectContaining({ method: 'POST', json: { new_columns_data: expect.any(Array) }, }), dataset_1.DatasetResponseHandler); })); test('should throw error when dataset ID is not set', () => __awaiter(void 0, void 0, void 0, function* () { const columns = [ (0, types_1.createColumn)({ name: 'col1', dataType: types_1.DataTypeChoices.TEXT }), ]; yield expect(dataset.addColumns(columns)).rejects.toThrow(errors_1.DatasetError); })); test('should throw error for empty columns array', () => __awaiter(void 0, void 0, void 0, function* () { const config = { id: 'dataset-123', name: 'test-dataset', }; dataset._datasetConfig = config; yield expect(dataset.addColumns([])).rejects.toThrow(errors_1.DatasetValidationError); })); }); describe('addRows', () => { test('should add rows to dataset', () => __awaiter(void 0, void 0, void 0, function* () { const config = { id: 'dataset-123', name: 'test-dataset', }; const rows = [ (0, types_1.createRow)({ cells: [ (0, types_1.createCell)({ columnId: 'col-1', rowId: 'row-1', value: 'test' }), ], }), ]; dataset._datasetConfig = config; mockRequest.mockResolvedValue({}); const result = yield dataset.addRows(rows); expect(result).toBe(dataset); expect(mockRequest).toHaveBeenCalledWith(expect.objectContaining({ method: 'POST', json: { rows: expect.any(Array) }, }), dataset_1.DatasetResponseHandler); })); test('should throw error when dataset ID is not set', () => __awaiter(void 0, void 0, void 0, function* () { const rows = [ (0, types_1.createRow)({ cells: [ (0, types_1.createCell)({ columnId: 'col-1', rowId: 'row-1', value: 'test' }), ], }), ]; yield expect(dataset.addRows(rows)).rejects.toThrow(errors_1.DatasetError); })); test('should throw error for empty rows array', () => __awaiter(void 0, void 0, void 0, function* () { const config = { id: 'dataset-123', name: 'test-dataset', }; dataset._datasetConfig = config; yield expect(dataset.addRows([])).rejects.toThrow(errors_1.DatasetValidationError); })); }); describe('addRunPrompt', () => { test('should add a run prompt with correct payload', () => __awaiter(void 0, void 0, void 0, function* () { const config = { id: 'dataset-123', name: 'test-dataset', }; dataset._datasetConfig = config; mockRequest.mockResolvedValue({}); const options = { name: 'my_prompt', model: 'gpt-3.5-turbo', messages: [{ role: 'user', content: 'Hello' }], }; const result = yield dataset.addRunPrompt(options); expect(result).toBe(dataset); expect(mockRequest).toHaveBeenCalledWith(expect.objectContaining({ method: 'POST', json: expect.objectContaining({ dataset_id: 'dataset-123', name: 'my_prompt', config: expect.objectContaining({ model: 'gpt-3.5-turbo', messages: options.messages, }), }), }), dataset_1.DatasetResponseHandler); })); test('should throw error when dataset ID is not set', () => __awaiter(void 0, void 0, void 0, function* () { const options = { name: 'my_prompt', model: 'gpt-3.5-turbo', messages: [{ role: 'user', content: 'Hello' }], }; yield expect(dataset.addRunPrompt(options)).rejects.toThrow(errors_1.DatasetError); })); }); describe('getColumnId', () => { test('should get column ID by name', () => __awaiter(void 0, void 0, void 0, function* () { const config = { id: 'dataset-123', name: 'test-dataset', }; const mockTable = { id: 'dataset-123', columns: [ { id: 'col-1', name: 'test_column', dataType: types_1.DataTypeChoices.TEXT, source: types_1.SourceChoices.OTHERS, metadata: {}, isFrozen: false, isVisible: true, evalTags: [], orderIndex: 0, }, ], rows: [], metadata: {}, }; dataset._datasetConfig = config; mockRequest.mockResolvedValue(mockTable); const result = yield dataset.getColumnId('test_column'); expect(result).toBe('col-1'); })); test('should return null for non-existent column', () => __awaiter(void 0, void 0, void 0, function* () { const config = { id: 'dataset-123', name: 'test-dataset', }; const mockTable = { id: 'dataset-123', columns: [], rows: [], metadata: {}, }; dataset._datasetConfig = config; mockRequest.mockResolvedValue(mockTable); const result = yield dataset.getColumnId('non_existent_column'); expect(result).toBeNull(); })); test('should throw error when dataset ID is not set', () => __awaiter(void 0, void 0, void 0, function* () { yield expect(dataset.getColumnId('test_column')).rejects.toThrow(errors_1.DatasetError); })); test('should throw error for empty column name', () => __awaiter(void 0, void 0, void 0, function* () { const config = { id: 'dataset-123', name: 'test-dataset', }; dataset._datasetConfig = config; yield expect(dataset.getColumnId('')).rejects.toThrow(errors_1.DatasetValidationError); })); }); describe('static methods', () => { test('should create dataset using static method', () => __awaiter(void 0, void 0, void 0, function* () { const config = { name: 'test-dataset', }; const mockDatasetInstance = new dataset_1.Dataset(); const mockCreate = jest.fn().mockResolvedValue(mockDatasetInstance); jest.spyOn(dataset_1.Dataset.prototype, 'create').mockImplementation(mockCreate); const result = yield dataset_1.Dataset.createDataset(config, undefined, { fiApiKey: 'test-key', fiSecretKey: 'test-secret', }); expect(result).toBeInstanceOf(dataset_1.Dataset); // This assertion is tricky because create is called on a new instance // A better test would be to mock the constructor })); test('should download dataset using static method', () => __awaiter(void 0, void 0, void 0, function* () { const mockDownload = jest.fn().mockResolvedValue('csv content'); const mockFetchConfig = jest.fn().mockResolvedValue({ id: 'dataset-123', name: 'test-dataset', }); // Mock the internal methods on the prototype jest.spyOn(dataset_1.Dataset.prototype, '_fetchDatasetConfig').mockImplementation(mockFetchConfig); jest.spyOn(dataset_1.Dataset.prototype, 'download').mockImplementation(mockDownload); const result = yield dataset_1.Dataset.downloadDataset('test-dataset'); expect(result).toBe('csv content'); expect(mockDownload).toHaveBeenCalled(); })); test('should delete dataset using static method', () => __awaiter(void 0, void 0, void 0, function* () { const mockDelete = jest.fn().mockResolvedValue(undefined); const mockFetchConfig = jest.fn().mockResolvedValue({ id: 'dataset-123', name: 'test-dataset', }); jest.spyOn(dataset_1.Dataset.prototype, '_fetchDatasetConfig').mockImplementation(mockFetchConfig); jest.spyOn(dataset_1.Dataset.prototype, 'delete').mockImplementation(mockDelete); yield dataset_1.Dataset.deleteDataset('test-dataset'); expect(mockDelete).toHaveBeenCalled(); })); }); }); //# sourceMappingURL=dataset.test.js.map