Skip to content
← Public packages

@kody/api-research

Research third-party APIs: registry search, provider discovery, OpenAPI summarize, and client scaffold.

tests/api-research.test.ts

99 lines · 3.1 KB · TypeScript
import assert from 'node:assert/strict'
import { test } from 'node:test'
import { assertOpenApiBoundAuth } from '../src/auth.ts'
import { normalizeProviderDomain } from '../src/discover.ts'
import { parseOpenApiSpec, deriveOperationSlug } from '../src/parse-spec-lib.ts'
import { scaffoldOpenApiClient } from '../src/scaffold-client-lib.ts'
import { buildRegistrySearchUrl } from '../src/search-registry.ts'
import { summarizeOpenApiSpec } from '../src/summarize-spec-lib.ts'

const minimalSpec = {
	openapi: '3.0.3',
	info: {
		title: 'Widgets API',
		version: '1.2.3',
		description: 'A'.repeat(400),
	},
	servers: [
		{
			url: 'https://{env}.widgets.example/v1',
			description: 'Env-scoped API',
			variables: {
				env: { default: 'api', enum: ['api', 'staging'] },
			},
		},
	],
	paths: {
		'/widgets': {
			get: {
				operationId: 'listWidgets',
				summary: 'List widgets',
				tags: ['widgets'],
				responses: { '200': { description: 'ok' } },
			},
		},
		'/me': {
			get: {
				operationId: 'getMe',
				summary: 'Current user',
				responses: { '200': { description: 'ok' } },
			},
		},
	},
}

test('parseOpenApiSpec accepts OpenAPI 3 JSON and YAML', () => {
	const parsed = parseOpenApiSpec(JSON.stringify(minimalSpec))
	assert.equal(parsed.openapiVersion, '3.0.3')
	assert.equal(parsed.title, 'Widgets API')
	assert.equal(parsed.servers[0]?.url, 'https://api.widgets.example/v1')
	assert.ok((parsed.description ?? '').endsWith('…'))
	assert.equal(deriveOperationSlug('List Widgets!', 'get', '/widgets'), 'list_widgets')

	const yamlParsed = parseOpenApiSpec(`
openapi: 3.1.0
info:
  title: YAML API
  version: "0.1"
paths:
  /ping:
    get:
      operationId: ping
      responses:
        "200":
          description: ok
`)
	assert.equal(yamlParsed.openapiVersion, '3.1.0')
	assert.equal(yamlParsed.operations[0]?.slug, 'ping')
})

test('summarizeOpenApiSpec picks identity smoke tests and suggested hosts', () => {
	const summary = summarizeOpenApiSpec(parseOpenApiSpec(JSON.stringify(minimalSpec)))
	assert.equal(summary.suggestedApiBaseUrl, 'https://api.widgets.example/v1')
	assert.deepEqual(summary.suggestedHosts, ['api.widgets.example'])
	assert.equal(summary.suggestedSmokeTestOperations[0]?.slug, 'getme')
})

test('scaffoldOpenApiClient emits a named export for the selected slug', () => {
	const parsed = parseOpenApiSpec(JSON.stringify(minimalSpec))
	const scaffold = scaffoldOpenApiClient({
		spec: parsed,
		operationSlugs: ['listwidgets'],
		auth: { kind: 'none' },
		apiBaseUrl: 'https://api.widgets.example/v1',
	})
	assert.match(scaffold.moduleSource, /export async function listwidgets/)
	assert.match(scaffold.moduleSource, /@kody\/api-research/)
	assert.equal(scaffold.operations[0]?.method, 'get')
})

test('search and discover helpers validate inputs', () => {
	assert.equal(
		buildRegistrySearchUrl('github'),
		'https://integrations.sh/api/search?q=github',
	)
	assert.equal(normalizeProviderDomain('GitHub.com'), 'github.com')
	assert.throws(() => normalizeProviderDomain('https://github.com'), /path|scheme/)
	assert.deepEqual(assertOpenApiBoundAuth({ kind: 'none' }), { kind: 'none' })
	assert.throws(() => assertOpenApiBoundAuth({ kind: 'integration' }), /provider/)
})