/** * Integration Test Page — browse and test all integration endpoints. * * Fetches the catalog from the API worker, renders typed form fields * from JSON Schema, and shows results. * * data-testid attributes for Playwright: * integration-endpoint, integration-submit, integration-result, * integration-error, integration-loading, integration-catalog, * integration-catalog-error */ import { useState, useMemo } from 'react' import { integration, useAsyncResource } from 'deepspace' import type { IntegrationResponse } from 'deepspace' import { useAuth } from 'deepspace' // ============================================================================ // Types // ============================================================================ interface CatalogEntry { endpoint: string billing: { model: string; baseCost: number; currency: string } inputSchema?: JsonSchema example?: Record } interface JsonSchema { type?: string properties?: Record required?: string[] } interface JsonSchemaProperty { type?: string enum?: unknown[] default?: unknown description?: string minimum?: number maximum?: number minLength?: number maxLength?: number items?: JsonSchemaProperty properties?: Record anyOf?: JsonSchemaProperty[] } type Catalog = Record // ============================================================================ // Example Generation — build a complete example from schema + catalog defaults // ============================================================================ function buildFullExample(schema?: JsonSchema | null, catalogExample?: Record): Record { const example: Record = { ...catalogExample } if (!schema?.properties) return example for (const [key, prop] of Object.entries(schema.properties)) { if (example[key] !== undefined) continue // already has a value from catalog if (prop.default !== undefined) { example[key] = prop.default } else if (prop.type === 'array' && prop.items) { example[key] = [buildExampleItem(prop.items)] } else if (prop.type === 'string' && prop.enum) { example[key] = prop.enum[0] } // Skip optional fields without defaults — user fills them in } return example } function buildExampleItem(items: JsonSchemaProperty): unknown { if (items.type === 'string') return 'example' if (items.type === 'number' || items.type === 'integer') return 0 if (items.type === 'object' && items.properties) { const obj: Record = {} for (const [k, v] of Object.entries(items.properties)) { if (v.default !== undefined) obj[k] = v.default else if (v.enum) obj[k] = v.enum[0] else if (v.type === 'string') obj[k] = k else if (v.type === 'number' || v.type === 'integer') obj[k] = v.minimum ?? 0 else if (v.type === 'boolean') obj[k] = false else if (v.anyOf) { const str = v.anyOf.find((a) => a.type === 'string') obj[k] = str ? k : null } } return obj } return null } // ============================================================================ // Schema Form — auto-generates form fields from JSON Schema // ============================================================================ function SchemaForm({ schema, values, onChange, }: { schema: JsonSchema values: Record onChange: (values: Record) => void }) { const properties = schema.properties ?? {} const required = new Set(schema.required ?? []) const updateField = (key: string, value: unknown) => { onChange({ ...values, [key]: value }) } return (
{Object.entries(properties).map(([key, prop]) => (
updateField(key, v)} />
))}
) } function FieldInput({ prop, value, onChange, }: { prop: JsonSchemaProperty value: unknown onChange: (v: unknown) => void }) { // Enum → select if (prop.enum) { return ( ) } // Boolean → checkbox if (prop.type === 'boolean') { return ( onChange(e.target.checked)} className="rounded border-border" /> ) } // Number → number input if (prop.type === 'number' || prop.type === 'integer') { return ( onChange(e.target.value ? Number(e.target.value) : undefined)} className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground" /> ) } // Array / Object → JSON textarea if (prop.type === 'array' || prop.type === 'object') { // Generate a meaningful placeholder for arrays of objects let defaultValue = prop.default ?? (prop.type === 'array' ? [] : {}) if (prop.type === 'array' && Array.isArray(defaultValue) && defaultValue.length === 0 && prop.items?.properties) { // Build an example object from the items schema const exampleItem: Record = {} for (const [k, v] of Object.entries(prop.items.properties)) { if (v.default !== undefined) exampleItem[k] = v.default else if (v.enum) exampleItem[k] = v.enum[0] else if (v.type === 'string') exampleItem[k] = k else if (v.type === 'number' || v.type === 'integer') exampleItem[k] = v.minimum ?? 0 else if (v.type === 'boolean') exampleItem[k] = false else if (v.anyOf) { // Pick the simplest type from anyOf const stringType = v.anyOf.find((a) => a.type === 'string') if (stringType) exampleItem[k] = k else exampleItem[k] = null } } defaultValue = [exampleItem] } const strValue = typeof value === 'string' ? value : JSON.stringify(value ?? defaultValue, null, 2) return (