UNPKG

@platformos/pos-cli

Version:
127 lines (112 loc) 4.24 kB
// platformos.tests.run-async-result - check result of an async test run via /_tests/results/:id import log from '../log.js'; import { resolveAuth, maskToken } from '../auth.js'; async function makeRequest(options) { const { uri, method = 'GET', headers = {} } = options; const response = await fetch(uri, { method, headers }); const body = await response.text(); return { statusCode: response.status, body }; } function normalizeResult(result) { const status = result.status; const data = { id: result.id, status, test_name: result.test_name, total_assertions: parseInt(result.total_assertions, 10) || 0, total_errors: parseInt(result.total_errors, 10) || 0, total_duration: parseInt(result.total_duration, 10) || 0, error_message: result.error_message || '', tests: result.tests || [], pending: status === 'pending', passed: status === 'success', done: status !== 'pending' }; return data; } const testsRunAsyncResultTool = { description: 'Check the result of an async test run by ID via /_tests/results/:id. Returns current status: pending (still running), success (all passed), failed (assertion failures), or error (runner crashed). Poll until done=true.', inputSchema: { type: 'object', additionalProperties: false, properties: { env: { type: 'string', description: 'Environment name from .pos config' }, url: { type: 'string', description: 'Instance URL (alternative to env)' }, email: { type: 'string', description: 'Account email (alternative to env)' }, token: { type: 'string', description: 'API token (alternative to env)' }, id: { type: 'string', description: 'Test run ID returned by tests-run-async' } }, required: ['id'] }, handler: async (params, ctx = {}) => { const startedAt = new Date().toISOString(); log.debug('tool:tests-run-async-result invoked', { id: params?.id, env: params?.env }); try { const auth = await resolveAuth(params, ctx); const requestFn = ctx.request || makeRequest; const authHeaders = { 'Authorization': `Token ${auth.token}`, 'UserTemporaryToken': auth.token }; const runId = params.id; const resultsUrl = `${auth.url}/_tests/results/${runId}`; log.debug('Fetching test results', { url: resultsUrl }); const response = await requestFn({ method: 'GET', uri: resultsUrl, headers: authHeaders }); const authMeta = { url: auth.url, email: auth.email, token: maskToken(auth.token), source: auth.source }; if (response.statusCode >= 400) { return { ok: false, error: { code: 'HTTP_ERROR', message: `Results request failed with status ${response.statusCode}`, statusCode: response.statusCode, body: response.body }, meta: { url: resultsUrl, startedAt, finishedAt: new Date().toISOString(), auth: authMeta } }; } let result; try { result = JSON.parse(response.body); } catch { return { ok: false, error: { code: 'INVALID_RESPONSE', message: 'Failed to parse results response as JSON', body: response.body }, meta: { url: resultsUrl, startedAt, finishedAt: new Date().toISOString(), auth: authMeta } }; } if (result.error === 'not_found') { return { ok: false, error: { code: 'NOT_FOUND', message: `Test result ${runId} not found`, data: result }, meta: { url: resultsUrl, startedAt, finishedAt: new Date().toISOString(), auth: authMeta } }; } const data = normalizeResult(result); return { ok: true, data, meta: { url: resultsUrl, startedAt, finishedAt: new Date().toISOString(), auth: authMeta } }; } catch (e) { log.error('tool:tests-run-async-result error', { error: String(e) }); return { ok: false, error: { code: 'TESTS_RESULT_ERROR', message: String(e.message || e) } }; } } }; export default testsRunAsyncResultTool;