yx_generate_api_js/test/generate.test.js

253 lines
6.8 KiB
JavaScript

import assert from 'node:assert/strict'
import fs from 'node:fs/promises'
import http from 'node:http'
import os from 'node:os'
import path from 'node:path'
import test from 'node:test'
import { generateApiFiles } from '../src/core/generate.js'
const createTempDir = async () => {
return fs.mkdtemp(path.join(os.tmpdir(), 'yx-generate-api-'))
}
const writeJson = async (filePath, value) => {
await fs.writeFile(filePath, JSON.stringify(value, null, 2), 'utf8')
}
const readFile = async (filePath) => {
return fs.readFile(filePath, 'utf8')
}
test('full generation cleans stale auto-generated files and keeps manual files', async () => {
const tempDir = await createTempDir()
try {
const initialSwaggerPath = path.join(tempDir, 'swagger-initial.json')
const updatedSwaggerPath = path.join(tempDir, 'swagger-updated.json')
const outputDir = path.join(tempDir, 'generated')
await writeJson(initialSwaggerPath, {
openapi: '3.0.0',
paths: {
'/api/v1/Alpha/GetThing': {
get: {
tags: ['Alpha'],
summary: 'Get alpha thing',
responses: {
200: { description: 'OK' },
},
},
},
'/api/v1/Beta/GetList': {
get: {
tags: ['Beta'],
summary: 'Get beta list',
responses: {
200: { description: 'OK' },
},
},
},
},
})
await writeJson(updatedSwaggerPath, {
openapi: '3.0.0',
paths: {
'/api/v1/Alpha/GetThing': {
get: {
tags: ['Alpha'],
summary: 'Get alpha thing',
responses: {
200: { description: 'OK' },
},
},
},
},
})
await generateApiFiles({
projectRoot: tempDir,
swaggerUrl: initialSwaggerPath,
swaggerTimeoutMs: 1000,
outputDir,
requestImport: '../request',
paramStyle: 'object',
modules: [],
cleanOutput: true,
})
await fs.writeFile(path.join(outputDir, 'manual-helper.js'), 'export const keepMe = true\n', 'utf8')
await generateApiFiles({
projectRoot: tempDir,
swaggerUrl: updatedSwaggerPath,
swaggerTimeoutMs: 1000,
outputDir,
requestImport: '../request',
paramStyle: 'object',
modules: [],
cleanOutput: true,
})
await assert.doesNotReject(fs.access(path.join(outputDir, 'alpha.js')))
await assert.rejects(fs.access(path.join(outputDir, 'beta.js')))
await assert.doesNotReject(fs.access(path.join(outputDir, 'manual-helper.js')))
const sharedFile = await readFile(path.join(outputDir, 'shared.js'))
assert.doesNotMatch(sharedFile, /from 'qs'/)
assert.match(sharedFile, /appendQueryEntries/)
} finally {
await fs.rm(tempDir, { recursive: true, force: true })
}
})
test('partial generation keeps other generated modules even when cleanOutput is enabled', async () => {
const tempDir = await createTempDir()
try {
const swaggerPath = path.join(tempDir, 'swagger.json')
const outputDir = path.join(tempDir, 'generated')
await writeJson(swaggerPath, {
openapi: '3.0.0',
paths: {
'/api/v1/Alpha/GetThing': {
get: {
tags: ['Alpha'],
responses: {
200: { description: 'OK' },
},
},
},
'/api/v1/Beta/GetList': {
get: {
tags: ['Beta'],
responses: {
200: { description: 'OK' },
},
},
},
},
})
await generateApiFiles({
projectRoot: tempDir,
swaggerUrl: swaggerPath,
swaggerTimeoutMs: 1000,
outputDir,
requestImport: '../request',
paramStyle: 'object',
modules: [],
cleanOutput: true,
})
await generateApiFiles({
projectRoot: tempDir,
swaggerUrl: swaggerPath,
swaggerTimeoutMs: 1000,
outputDir,
requestImport: '../request',
paramStyle: 'object',
modules: ['Alpha'],
cleanOutput: true,
})
await assert.doesNotReject(fs.access(path.join(outputDir, 'beta.js')))
} finally {
await fs.rm(tempDir, { recursive: true, force: true })
}
})
test('generated index includes namespace exports and collision-safe named exports', async () => {
const tempDir = await createTempDir()
try {
const swaggerPath = path.join(tempDir, 'swagger.json')
const outputDir = path.join(tempDir, 'generated')
await writeJson(swaggerPath, {
openapi: '3.0.0',
paths: {
'/api/v1/Alpha/GetList': {
get: {
tags: ['Alpha'],
responses: {
200: { description: 'OK' },
},
},
},
'/api/v1/Beta/GetList': {
get: {
tags: ['Beta'],
responses: {
200: { description: 'OK' },
},
},
},
'/api/v1/Beta/GetDetail': {
get: {
tags: ['Beta'],
responses: {
200: { description: 'OK' },
},
},
},
},
})
await generateApiFiles({
projectRoot: tempDir,
swaggerUrl: swaggerPath,
swaggerTimeoutMs: 1000,
outputDir,
requestImport: '../request',
paramStyle: 'object',
modules: [],
cleanOutput: true,
})
const indexContent = await readFile(path.join(outputDir, 'index.js'))
assert.match(indexContent, /export \* as alphaApi from ["']\.\/alpha["']/)
assert.match(indexContent, /export \* as betaApi from ["']\.\/beta["']/)
assert.match(indexContent, /export \{ getListApi as alphaGetListApi \} from ["']\.\/alpha["']/)
assert.match(indexContent, /export \{ getListApi as betaGetListApi \} from ["']\.\/beta["']/)
assert.match(indexContent, /export \{ getDetailApi \} from ["']\.\/beta["']/)
} finally {
await fs.rm(tempDir, { recursive: true, force: true })
}
})
test('swagger timeout surfaces a clear error message', async () => {
const tempDir = await createTempDir()
const server = http.createServer((_, response) => {
setTimeout(() => {
response.writeHead(200, { 'Content-Type': 'application/json' })
response.end(JSON.stringify({ openapi: '3.0.0', paths: {} }))
}, 100)
})
try {
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve))
const { port } = server.address()
await assert.rejects(
generateApiFiles({
projectRoot: tempDir,
swaggerUrl: `http://127.0.0.1:${port}/swagger.json`,
swaggerTimeoutMs: 10,
outputDir: path.join(tempDir, 'generated'),
requestImport: '../request',
paramStyle: 'object',
modules: [],
cleanOutput: true,
}),
/timed out/,
)
} finally {
server.close()
await fs.rm(tempDir, { recursive: true, force: true })
}
})