mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Drop examples; popping into a separate repo
This commit is contained in:
+42
-58
@@ -15,25 +15,25 @@ pnpm add @galaxyproject/client-api
|
||||
## Usage
|
||||
|
||||
```typescript
|
||||
import { createGalaxyApi } from '@galaxyproject/client-api';
|
||||
import { createGalaxyApi } from "@galaxyproject/client-api";
|
||||
|
||||
// Create an instance of the Galaxy API client with a specific base URL
|
||||
const api = createGalaxyApi('https://usegalaxy.org');
|
||||
const api = createGalaxyApi("https://usegalaxy.org");
|
||||
|
||||
// Alternatively, use the default (current origin)
|
||||
// const api = createGalaxyApi();
|
||||
|
||||
// Example: Get a list of histories
|
||||
const { data, error } = await api.GET('/api/histories');
|
||||
const { data, error } = await api.GET("/api/histories");
|
||||
|
||||
if (error) {
|
||||
console.error('Error fetching histories:', error);
|
||||
console.error("Error fetching histories:", error);
|
||||
} else {
|
||||
console.log('Histories:', data);
|
||||
console.log("Histories:", data);
|
||||
}
|
||||
|
||||
// For backward compatibility
|
||||
import { GalaxyApi } from '@galaxyproject/client-api';
|
||||
import { GalaxyApi } from "@galaxyproject/client-api";
|
||||
const legacyApi = GalaxyApi(); // Uses current origin
|
||||
```
|
||||
|
||||
@@ -42,67 +42,48 @@ const legacyApi = GalaxyApi(); // Uses current origin
|
||||
This package provides TypeScript types for all Galaxy API endpoints and models:
|
||||
|
||||
```typescript
|
||||
import {
|
||||
createGalaxyApi,
|
||||
type HistorySummary,
|
||||
type DatasetEntry
|
||||
} from '@galaxyproject/client-api';
|
||||
import { createGalaxyApi, type HistorySummary, type DatasetEntry } from "@galaxyproject/client-api";
|
||||
|
||||
const api = createGalaxyApi();
|
||||
|
||||
// Type-safe API calls
|
||||
const { data: histories } = await api.GET('/api/histories');
|
||||
const { data: histories } = await api.GET("/api/histories");
|
||||
// histories is typed as HistorySummary[] | undefined
|
||||
|
||||
// You can use the types for your variables
|
||||
const myHistory: HistorySummary = {
|
||||
id: '123',
|
||||
name: 'My History',
|
||||
// ...other required properties
|
||||
id: "123",
|
||||
name: "My History",
|
||||
// ...other required properties
|
||||
};
|
||||
```
|
||||
|
||||
## Comprehensive Examples
|
||||
## Example
|
||||
|
||||
The package includes several comprehensive examples in the `src/examples` directory that demonstrate common use cases:
|
||||
|
||||
### List Tools Example
|
||||
The package includes a simple example in the `src/example.ts` file that demonstrates how to use the client:
|
||||
|
||||
```typescript
|
||||
import { createGalaxyApi } from '@galaxyproject/client-api';
|
||||
import { createGalaxyApi } from "@galaxyproject/client-api";
|
||||
|
||||
// Default to localhost:8080 if no URL is provided
|
||||
const api = createGalaxyApi('http://localhost:8080');
|
||||
// Create a client with a specific Galaxy instance
|
||||
const api = createGalaxyApi("https://usegalaxy.org");
|
||||
|
||||
// Fetch all available tools
|
||||
const { data, error } = await api.GET('/api/tools');
|
||||
// Example: Get a list of tools
|
||||
async function getTools() {
|
||||
const { data, error } = await api.GET("/api/tools");
|
||||
|
||||
if (error) {
|
||||
console.error('Error fetching tools:', error);
|
||||
} else {
|
||||
console.log(`Found ${data.length} tools`);
|
||||
|
||||
// Group tools by section
|
||||
const sections = {};
|
||||
for (const tool of data) {
|
||||
const section = tool.panel_section_name || 'Ungrouped';
|
||||
if (!sections[section]) sections[section] = [];
|
||||
sections[section].push(tool);
|
||||
}
|
||||
|
||||
// Print summary
|
||||
Object.keys(sections).forEach(section => {
|
||||
console.log(`${section}: ${sections[section].length} tools`);
|
||||
});
|
||||
if (error) {
|
||||
console.error("Error fetching tools:", error);
|
||||
return [];
|
||||
}
|
||||
|
||||
// Log tool count
|
||||
console.log(`Found ${data.length} tools`);
|
||||
|
||||
return data;
|
||||
}
|
||||
```
|
||||
|
||||
See all examples in the `src/examples` directory for:
|
||||
- Working with histories and datasets
|
||||
- Authentication with API keys
|
||||
- Comprehensive error handling
|
||||
- And more!
|
||||
|
||||
## Design Notes
|
||||
|
||||
This package uses symlinks to reference API type definitions from the main Galaxy client while providing a standalone client implementation. This approach was chosen to:
|
||||
@@ -112,8 +93,9 @@ This package uses symlinks to reference API type definitions from the main Galax
|
||||
3. Allow the client to work independently of Galaxy's internal utilities
|
||||
|
||||
Key symlinks:
|
||||
|
||||
- `src/api` → `../../client/src/api` (for type definitions)
|
||||
- `src/utils/simple-error.ts` → `../../../client/src/utils/simple-error.ts`
|
||||
- `src/utils/error.ts` - Custom error handling utilities
|
||||
|
||||
## Development
|
||||
|
||||
@@ -122,16 +104,17 @@ To work on this package:
|
||||
1. Make changes to the API type definitions in the main Galaxy client
|
||||
2. The type changes will automatically be available in this package via symlinks
|
||||
3. Build the library for distribution:
|
||||
```bash
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Build the library
|
||||
npm run build
|
||||
|
||||
# Watch mode for development
|
||||
npm run dev
|
||||
```
|
||||
```bash
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Build the library
|
||||
npm run build
|
||||
|
||||
# Watch mode for development
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
@@ -152,7 +135,8 @@ npm run test:coverage
|
||||
```
|
||||
|
||||
The tests verify:
|
||||
|
||||
- Client creation with default and custom base URLs
|
||||
- Basic API interaction with proper typing
|
||||
- Error handling
|
||||
- Backward compatibility with the original API
|
||||
- Backward compatibility with the original API
|
||||
|
||||
@@ -24,10 +24,7 @@
|
||||
"prepublishOnly": "npm run clean && npm run build",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"examples:tools": "node src/examples/listTools.mjs",
|
||||
"examples:histories": "node src/examples/historyOperations.mjs",
|
||||
"examples:auth": "node src/examples/authentication.mjs"
|
||||
"test:coverage": "vitest run --coverage"
|
||||
},
|
||||
"keywords": [
|
||||
"galaxy",
|
||||
|
||||
+22
-22
@@ -40,35 +40,35 @@ export type AsyncTaskResultSummary = components["schemas"]["AsyncTaskResultSumma
|
||||
export type HistorySortByLiteral = "create_time" | "name" | "update_time" | "username" | undefined;
|
||||
|
||||
export interface HistoryContentsStats {
|
||||
id: string;
|
||||
update_time: string;
|
||||
size: number;
|
||||
contents_active: components["schemas"]["HistoryActiveContentCounts"];
|
||||
id: string;
|
||||
update_time: string;
|
||||
size: number;
|
||||
contents_active: components["schemas"]["HistoryActiveContentCounts"];
|
||||
}
|
||||
|
||||
export interface HistorySummaryExtended extends HistorySummary, HistoryContentsStats {
|
||||
user_id: string | null;
|
||||
user_id: string | null;
|
||||
}
|
||||
|
||||
export interface SelectableObjectStore extends ConcreteObjectStoreModel {
|
||||
object_store_id: string;
|
||||
object_store_id: string;
|
||||
}
|
||||
|
||||
export type DatasetEntry = HDASummary | HDADetailed | HDAInaccessible;
|
||||
|
||||
export interface DCECollection extends DCESummary {
|
||||
element_type: "dataset_collection";
|
||||
object: DCObject;
|
||||
element_type: "dataset_collection";
|
||||
object: DCObject;
|
||||
}
|
||||
|
||||
export interface DCEDataset extends DCESummary {
|
||||
element_type: "hda";
|
||||
object: HDAObject;
|
||||
element_type: "hda";
|
||||
object: HDAObject;
|
||||
}
|
||||
|
||||
export interface SubCollection extends DCObject {
|
||||
name: string;
|
||||
hdca_id: string;
|
||||
name: string;
|
||||
hdca_id: string;
|
||||
}
|
||||
|
||||
export type CollectionEntry = HDCASummary | SubCollection;
|
||||
@@ -76,31 +76,31 @@ export type HistoryItemSummary = HDASummary | HDCASummary;
|
||||
|
||||
// Utility functions
|
||||
export function isHDA(entry?: HistoryItemSummary): entry is HDASummary {
|
||||
return entry !== undefined && "history_content_type" in entry && entry.history_content_type === "dataset";
|
||||
return entry !== undefined && "history_content_type" in entry && entry.history_content_type === "dataset";
|
||||
}
|
||||
|
||||
export function isHDCA(entry?: HistoryItemSummary | CollectionEntry): entry is HDCASummary {
|
||||
return (
|
||||
entry !== undefined && "history_content_type" in entry && entry.history_content_type === "dataset_collection"
|
||||
);
|
||||
return (
|
||||
entry !== undefined && "history_content_type" in entry && entry.history_content_type === "dataset_collection"
|
||||
);
|
||||
}
|
||||
|
||||
export function isDCE(item: object): item is DCESummary {
|
||||
return item && "element_type" in item;
|
||||
return item && "element_type" in item;
|
||||
}
|
||||
|
||||
export function isCollectionElement(element: DCESummary): element is DCECollection {
|
||||
return element.element_type === "dataset_collection";
|
||||
return element.element_type === "dataset_collection";
|
||||
}
|
||||
|
||||
export function isDatasetElement(element: DCESummary): element is DCEDataset {
|
||||
return element.element_type === "hda";
|
||||
return element.element_type === "hda";
|
||||
}
|
||||
|
||||
export function hasDetails(entry: DatasetEntry): entry is HDADetailed {
|
||||
return "peek" in entry;
|
||||
return "peek" in entry;
|
||||
}
|
||||
|
||||
export function isInaccessible(entry: DatasetEntry): entry is HDAInaccessible {
|
||||
return "accessible" in entry && !entry.accessible;
|
||||
}
|
||||
return "accessible" in entry && !entry.accessible;
|
||||
}
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { createGalaxyApi } from './client';
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { createGalaxyApi } from "./client";
|
||||
|
||||
// Create a mock API client for testing
|
||||
const mockApiClient = {
|
||||
GET: vi.fn(),
|
||||
POST: vi.fn(),
|
||||
PUT: vi.fn(),
|
||||
DELETE: vi.fn(),
|
||||
PATCH: vi.fn(),
|
||||
GET: vi.fn(),
|
||||
POST: vi.fn(),
|
||||
PUT: vi.fn(),
|
||||
DELETE: vi.fn(),
|
||||
PATCH: vi.fn(),
|
||||
};
|
||||
|
||||
// Mock createClient before importing
|
||||
vi.mock('openapi-fetch', () => {
|
||||
return {
|
||||
default: vi.fn().mockImplementation(() => mockApiClient)
|
||||
};
|
||||
vi.mock("openapi-fetch", () => {
|
||||
return {
|
||||
default: vi.fn().mockImplementation(() => mockApiClient),
|
||||
};
|
||||
});
|
||||
|
||||
import createClient from 'openapi-fetch';
|
||||
import createClient from "openapi-fetch";
|
||||
|
||||
describe('Galaxy API Client', () => {
|
||||
beforeEach(() => {
|
||||
// Reset mock function calls before each test
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
describe("Galaxy API Client", () => {
|
||||
beforeEach(() => {
|
||||
// Reset mock function calls before each test
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('creates a client with the default base URL', () => {
|
||||
// Set up window.location.origin for testing
|
||||
const originalLocation = window.location;
|
||||
delete (window as any).location;
|
||||
window.location = { ...originalLocation, origin: 'https://test-galaxy.org' } as any;
|
||||
it("creates a client with the default base URL", () => {
|
||||
// Set up window.location.origin for testing
|
||||
const originalLocation = window.location;
|
||||
delete (window as any).location;
|
||||
window.location = { ...originalLocation, origin: "https://test-galaxy.org" } as any;
|
||||
|
||||
const api = createGalaxyApi();
|
||||
|
||||
expect(createClient).toHaveBeenCalledWith({ baseUrl: 'https://test-galaxy.org' });
|
||||
|
||||
// Restore window.location
|
||||
window.location = originalLocation;
|
||||
});
|
||||
const api = createGalaxyApi();
|
||||
|
||||
it('creates a client with a custom base URL', () => {
|
||||
const customUrl = 'https://usegalaxy.org';
|
||||
const api = createGalaxyApi(customUrl);
|
||||
|
||||
expect(createClient).toHaveBeenCalledWith({ baseUrl: customUrl });
|
||||
});
|
||||
expect(createClient).toHaveBeenCalledWith({ baseUrl: "https://test-galaxy.org" });
|
||||
|
||||
it('strips trailing slash from base URL', () => {
|
||||
const customUrl = 'https://usegalaxy.org/';
|
||||
const expectedUrl = 'https://usegalaxy.org';
|
||||
const api = createGalaxyApi(customUrl);
|
||||
|
||||
expect(createClient).toHaveBeenCalledWith({ baseUrl: expectedUrl });
|
||||
});
|
||||
// Restore window.location
|
||||
window.location = originalLocation;
|
||||
});
|
||||
|
||||
it('returns the configured client', () => {
|
||||
const api = createGalaxyApi();
|
||||
|
||||
// Should have all the HTTP methods
|
||||
expect(api).toEqual(mockApiClient);
|
||||
expect(api).toHaveProperty('GET');
|
||||
expect(api).toHaveProperty('POST');
|
||||
expect(api).toHaveProperty('PUT');
|
||||
expect(api).toHaveProperty('DELETE');
|
||||
expect(api).toHaveProperty('PATCH');
|
||||
});
|
||||
});
|
||||
it("creates a client with a custom base URL", () => {
|
||||
const customUrl = "https://usegalaxy.org";
|
||||
const api = createGalaxyApi(customUrl);
|
||||
|
||||
expect(createClient).toHaveBeenCalledWith({ baseUrl: customUrl });
|
||||
});
|
||||
|
||||
it("strips trailing slash from base URL", () => {
|
||||
const customUrl = "https://usegalaxy.org/";
|
||||
const expectedUrl = "https://usegalaxy.org";
|
||||
const api = createGalaxyApi(customUrl);
|
||||
|
||||
expect(createClient).toHaveBeenCalledWith({ baseUrl: expectedUrl });
|
||||
});
|
||||
|
||||
it("returns the configured client", () => {
|
||||
const api = createGalaxyApi();
|
||||
|
||||
// Should have all the HTTP methods
|
||||
expect(api).toEqual(mockApiClient);
|
||||
expect(api).toHaveProperty("GET");
|
||||
expect(api).toHaveProperty("POST");
|
||||
expect(api).toHaveProperty("PUT");
|
||||
expect(api).toHaveProperty("DELETE");
|
||||
expect(api).toHaveProperty("PATCH");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,9 +7,9 @@ import { type GalaxyApiPaths } from "./api-types";
|
||||
* @returns The Galaxy API client
|
||||
*/
|
||||
export function createGalaxyApi(baseUrl: string = window.location.origin) {
|
||||
return createClient<GalaxyApiPaths>({
|
||||
baseUrl: baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl
|
||||
});
|
||||
return createClient<GalaxyApiPaths>({
|
||||
baseUrl: baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl,
|
||||
});
|
||||
}
|
||||
|
||||
export type GalaxyApiClient = ReturnType<typeof createGalaxyApi>;
|
||||
export type GalaxyApiClient = ReturnType<typeof createGalaxyApi>;
|
||||
|
||||
+44
-28
@@ -1,37 +1,53 @@
|
||||
// Example usage of the Galaxy API client
|
||||
import { createGalaxyApi, type HistorySummary } from "./index";
|
||||
import { createGalaxyApi } from "./index";
|
||||
|
||||
// Create a client
|
||||
const api = createGalaxyApi("https://usegalaxy.org");
|
||||
|
||||
// Example function to get histories
|
||||
async function getHistories() {
|
||||
const { data, error } = await api.GET("/api/histories");
|
||||
|
||||
if (error) {
|
||||
console.error("Error fetching histories:", error);
|
||||
return [];
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
// Example function to get a list of tools
|
||||
async function getTools() {
|
||||
const { data, error } = await api.GET("/api/tools");
|
||||
|
||||
// Example function with type safety
|
||||
async function getHistoryById(id: string): Promise<HistorySummary | null> {
|
||||
const { data, error } = await api.GET("/api/histories/{history_id}", {
|
||||
params: {
|
||||
path: {
|
||||
history_id: id
|
||||
}
|
||||
if (error) {
|
||||
console.error("Error fetching tools:", error);
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
if (error || !data) {
|
||||
console.error("Error fetching history:", error);
|
||||
return null;
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
// Log tool count
|
||||
console.log(`Found ${data.length} tools`);
|
||||
|
||||
// Group tools by section
|
||||
const sections: Record<string, any[]> = {};
|
||||
for (const tool of data) {
|
||||
const section = tool.panel_section_name || "Ungrouped";
|
||||
if (!sections[section]) sections[section] = [];
|
||||
sections[section].push(tool);
|
||||
}
|
||||
|
||||
// Print summary
|
||||
Object.keys(sections).forEach((section) => {
|
||||
console.log(`${section}: ${sections[section].length} tools`);
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export { getHistories, getHistoryById };
|
||||
// Example function to get a specific tool by ID
|
||||
async function getToolById(id: string) {
|
||||
const { data, error } = await api.GET("/api/tools/{tool_id}", {
|
||||
params: {
|
||||
path: {
|
||||
tool_id: id,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (error || !data) {
|
||||
console.error("Error fetching tool:", error);
|
||||
return null;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export { getTools, getToolById };
|
||||
|
||||
+8
-11
@@ -11,24 +11,21 @@ export * from "./api-types";
|
||||
|
||||
// SimpleError class for error handling
|
||||
export class SimpleError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = "GalaxyApiError";
|
||||
}
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = "GalaxyApiError";
|
||||
}
|
||||
}
|
||||
|
||||
// Re-export the client functions
|
||||
export {
|
||||
createGalaxyApi,
|
||||
type GalaxyApiClient
|
||||
};
|
||||
export { createGalaxyApi, type GalaxyApiClient };
|
||||
|
||||
// For backward compatibility - creates a client with default settings
|
||||
export function GalaxyApi() {
|
||||
return createGalaxyApi();
|
||||
return createGalaxyApi();
|
||||
}
|
||||
|
||||
// Utility function to format error messages
|
||||
export function formatErrorMessage(error: any): string {
|
||||
return errorMessageAsString(error);
|
||||
}
|
||||
return errorMessageAsString(error);
|
||||
}
|
||||
|
||||
+102
-103
@@ -1,119 +1,118 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { type HistorySummary } from './api-types';
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { type HistorySummary } from "./api-types";
|
||||
|
||||
// Set up mock responses
|
||||
const mockHistories: HistorySummary[] = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'Test History 1',
|
||||
deleted: false,
|
||||
purged: false,
|
||||
archived: false,
|
||||
tags: [],
|
||||
model_class: 'History',
|
||||
url: '/api/histories/1',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Test History 2',
|
||||
deleted: false,
|
||||
purged: false,
|
||||
archived: false,
|
||||
tags: ['test'],
|
||||
model_class: 'History',
|
||||
url: '/api/histories/2',
|
||||
},
|
||||
{
|
||||
id: "1",
|
||||
name: "Test History 1",
|
||||
deleted: false,
|
||||
purged: false,
|
||||
archived: false,
|
||||
tags: [],
|
||||
model_class: "History",
|
||||
url: "/api/histories/1",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "Test History 2",
|
||||
deleted: false,
|
||||
purged: false,
|
||||
archived: false,
|
||||
tags: ["test"],
|
||||
model_class: "History",
|
||||
url: "/api/histories/2",
|
||||
},
|
||||
];
|
||||
|
||||
// Create a mock API client with typed responses
|
||||
const mockApiClient = {
|
||||
GET: vi.fn().mockImplementation((path, options) => {
|
||||
if (path === '/api/histories') {
|
||||
return Promise.resolve({
|
||||
data: mockHistories,
|
||||
error: null,
|
||||
response: new Response(),
|
||||
});
|
||||
}
|
||||
if (path === '/api/histories/{history_id}' &&
|
||||
options?.params?.path?.history_id === '1') {
|
||||
return Promise.resolve({
|
||||
data: mockHistories[0],
|
||||
error: null,
|
||||
response: new Response(),
|
||||
});
|
||||
}
|
||||
return Promise.resolve({
|
||||
data: null,
|
||||
error: { status: 404, message: 'Not found' },
|
||||
response: new Response(),
|
||||
});
|
||||
}),
|
||||
POST: vi.fn(),
|
||||
PUT: vi.fn(),
|
||||
DELETE: vi.fn(),
|
||||
PATCH: vi.fn(),
|
||||
GET: vi.fn().mockImplementation((path, options) => {
|
||||
if (path === "/api/histories") {
|
||||
return Promise.resolve({
|
||||
data: mockHistories,
|
||||
error: null,
|
||||
response: new Response(),
|
||||
});
|
||||
}
|
||||
if (path === "/api/histories/{history_id}" && options?.params?.path?.history_id === "1") {
|
||||
return Promise.resolve({
|
||||
data: mockHistories[0],
|
||||
error: null,
|
||||
response: new Response(),
|
||||
});
|
||||
}
|
||||
return Promise.resolve({
|
||||
data: null,
|
||||
error: { status: 404, message: "Not found" },
|
||||
response: new Response(),
|
||||
});
|
||||
}),
|
||||
POST: vi.fn(),
|
||||
PUT: vi.fn(),
|
||||
DELETE: vi.fn(),
|
||||
PATCH: vi.fn(),
|
||||
};
|
||||
|
||||
// Setup mocks before importing the modules that use them
|
||||
vi.mock('openapi-fetch', () => {
|
||||
return {
|
||||
default: vi.fn().mockImplementation(() => mockApiClient)
|
||||
};
|
||||
vi.mock("openapi-fetch", () => {
|
||||
return {
|
||||
default: vi.fn().mockImplementation(() => mockApiClient),
|
||||
};
|
||||
});
|
||||
|
||||
// Import the modules after setting up mocks
|
||||
import { createGalaxyApi, GalaxyApi } from './index';
|
||||
import { createGalaxyApi, GalaxyApi } from "./index";
|
||||
|
||||
describe('Galaxy API Integration', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('exports the createGalaxyApi function', () => {
|
||||
expect(typeof createGalaxyApi).toBe('function');
|
||||
});
|
||||
|
||||
it('exports the backward-compatible GalaxyApi function', () => {
|
||||
expect(typeof GalaxyApi).toBe('function');
|
||||
expect(GalaxyApi()).toEqual(mockApiClient);
|
||||
});
|
||||
|
||||
it('retrieves histories with proper typing', async () => {
|
||||
const api = createGalaxyApi();
|
||||
const { data, error } = await api.GET('/api/histories');
|
||||
|
||||
expect(error).toBeNull();
|
||||
expect(data).toEqual(mockHistories);
|
||||
|
||||
if (data) {
|
||||
// This is a type check - if TypeScript can compile this,
|
||||
// it means the types are working correctly
|
||||
const firstHistory = data[0];
|
||||
expect(firstHistory.id).toBe('1');
|
||||
expect(firstHistory.name).toBe('Test History 1');
|
||||
}
|
||||
});
|
||||
|
||||
it('retrieves a single history by ID', async () => {
|
||||
const api = createGalaxyApi();
|
||||
const { data, error } = await api.GET('/api/histories/{history_id}', {
|
||||
params: {
|
||||
path: {
|
||||
history_id: '1'
|
||||
}
|
||||
}
|
||||
describe("Galaxy API Integration", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
expect(error).toBeNull();
|
||||
expect(data).toEqual(mockHistories[0]);
|
||||
});
|
||||
|
||||
it('handles errors properly', async () => {
|
||||
const api = createGalaxyApi();
|
||||
const { data, error } = await api.GET('/api/nonexistent');
|
||||
|
||||
expect(data).toBeNull();
|
||||
expect(error).toEqual({ status: 404, message: 'Not found' });
|
||||
});
|
||||
});
|
||||
it("exports the createGalaxyApi function", () => {
|
||||
expect(typeof createGalaxyApi).toBe("function");
|
||||
});
|
||||
|
||||
it("exports the backward-compatible GalaxyApi function", () => {
|
||||
expect(typeof GalaxyApi).toBe("function");
|
||||
expect(GalaxyApi()).toEqual(mockApiClient);
|
||||
});
|
||||
|
||||
it("retrieves histories with proper typing", async () => {
|
||||
const api = createGalaxyApi();
|
||||
const { data, error } = await api.GET("/api/histories");
|
||||
|
||||
expect(error).toBeNull();
|
||||
expect(data).toEqual(mockHistories);
|
||||
|
||||
if (data) {
|
||||
// This is a type check - if TypeScript can compile this,
|
||||
// it means the types are working correctly
|
||||
const firstHistory = data[0];
|
||||
expect(firstHistory.id).toBe("1");
|
||||
expect(firstHistory.name).toBe("Test History 1");
|
||||
}
|
||||
});
|
||||
|
||||
it("retrieves a single history by ID", async () => {
|
||||
const api = createGalaxyApi();
|
||||
const { data, error } = await api.GET("/api/histories/{history_id}", {
|
||||
params: {
|
||||
path: {
|
||||
history_id: "1",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(error).toBeNull();
|
||||
expect(data).toEqual(mockHistories[0]);
|
||||
});
|
||||
|
||||
it("handles errors properly", async () => {
|
||||
const api = createGalaxyApi();
|
||||
const { data, error } = await api.GET("/api/nonexistent");
|
||||
|
||||
expect(data).toBeNull();
|
||||
expect(error).toEqual({ status: 404, message: "Not found" });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,33 +6,33 @@
|
||||
* Convert various error formats to a readable string message
|
||||
*/
|
||||
export function errorMessageAsString(error: any): string {
|
||||
if (typeof error === 'string') {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (error instanceof Error) {
|
||||
return error.message;
|
||||
}
|
||||
|
||||
if (error && typeof error === 'object') {
|
||||
// Handle API response errors
|
||||
if (error.status && error.error) {
|
||||
return `API Error (${error.status}): ${error.error}`;
|
||||
if (typeof error === "string") {
|
||||
return error;
|
||||
}
|
||||
|
||||
// Handle response objects with error message
|
||||
if (error.message) {
|
||||
return error.message;
|
||||
|
||||
if (error instanceof Error) {
|
||||
return error.message;
|
||||
}
|
||||
|
||||
// Try to stringify the error object
|
||||
try {
|
||||
return JSON.stringify(error);
|
||||
} catch (e) {
|
||||
// Fall back to object inspection
|
||||
return String(error);
|
||||
|
||||
if (error && typeof error === "object") {
|
||||
// Handle API response errors
|
||||
if (error.status && error.error) {
|
||||
return `API Error (${error.status}): ${error.error}`;
|
||||
}
|
||||
|
||||
// Handle response objects with error message
|
||||
if (error.message) {
|
||||
return error.message;
|
||||
}
|
||||
|
||||
// Try to stringify the error object
|
||||
try {
|
||||
return JSON.stringify(error);
|
||||
} catch (e) {
|
||||
// Fall back to object inspection
|
||||
return String(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 'Unknown error';
|
||||
}
|
||||
|
||||
return "Unknown error";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user