mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 13:44:54 +00:00
Add identifier-safe Flask blueprint tests
This commit is contained in:
73
src/lib/generators/__tests__/generateFlaskBlueprint.test.ts
Normal file
73
src/lib/generators/__tests__/generateFlaskBlueprint.test.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import type { FlaskBlueprint } from '@/types/project'
|
||||
|
||||
import { generateFlaskBlueprint } from '../generateFlaskBlueprint'
|
||||
|
||||
const isValidIdentifier = (name: string): boolean => /^[A-Za-z_][A-Za-z0-9_]*$/.test(name)
|
||||
|
||||
const extractBlueprintVariable = (code: string): { variable: string; name: string } => {
|
||||
const match = code.match(/^([A-Za-z_][A-Za-z0-9_]*)_bp = Blueprint\('([^']+)'/m)
|
||||
if (!match) {
|
||||
throw new Error('Blueprint definition not found.')
|
||||
}
|
||||
return { variable: `${match[1]}_bp`, name: match[2] }
|
||||
}
|
||||
|
||||
const extractFunctionNames = (code: string): string[] => {
|
||||
return Array.from(code.matchAll(/^def ([A-Za-z_][A-Za-z0-9_]*)\(\):/gm)).map(match => match[1])
|
||||
}
|
||||
|
||||
const extractDecoratorBlueprints = (code: string): string[] => {
|
||||
return Array.from(code.matchAll(/^@([A-Za-z_][A-Za-z0-9_]*)\.route/gm)).map(match => match[1])
|
||||
}
|
||||
|
||||
describe('generateFlaskBlueprint identifier sanitization', () => {
|
||||
it('creates valid, consistent identifiers for tricky endpoint names', () => {
|
||||
const blueprint: FlaskBlueprint = {
|
||||
id: 'bp-1',
|
||||
name: 'User Auth',
|
||||
urlPrefix: '/auth',
|
||||
description: 'Auth endpoints',
|
||||
endpoints: [
|
||||
{
|
||||
id: 'ep-1',
|
||||
name: 'get-user',
|
||||
description: 'Fetch a user',
|
||||
method: 'GET',
|
||||
path: '/user'
|
||||
},
|
||||
{
|
||||
id: 'ep-2',
|
||||
name: '2fa',
|
||||
description: 'Two factor auth',
|
||||
method: 'POST',
|
||||
path: '/2fa'
|
||||
},
|
||||
{
|
||||
id: 'ep-3',
|
||||
name: 'user.v1',
|
||||
description: 'User v1 endpoint',
|
||||
method: 'GET',
|
||||
path: '/user/v1'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const code = generateFlaskBlueprint(blueprint)
|
||||
const blueprintDefinition = extractBlueprintVariable(code)
|
||||
const functionNames = extractFunctionNames(code)
|
||||
const decoratorBlueprints = extractDecoratorBlueprints(code)
|
||||
|
||||
expect(isValidIdentifier(blueprintDefinition.name)).toBe(true)
|
||||
expect(isValidIdentifier(blueprintDefinition.variable)).toBe(true)
|
||||
expect(blueprintDefinition.variable).toBe('user_auth_bp')
|
||||
expect(blueprintDefinition.name).toBe('user_auth')
|
||||
expect(new Set(decoratorBlueprints)).toEqual(new Set([blueprintDefinition.variable]))
|
||||
|
||||
expect(functionNames).toEqual(['get_user', '_2fa', 'user_v1'])
|
||||
functionNames.forEach(name => {
|
||||
expect(isValidIdentifier(name)).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,14 +1,27 @@
|
||||
import { FlaskBlueprint } from '@/types/project'
|
||||
|
||||
function toPythonIdentifier(value: string, fallback: string): string {
|
||||
const normalized = value
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9_]/g, '_')
|
||||
.replace(/_+/g, '_')
|
||||
.replace(/^_+|_+$/g, '')
|
||||
let safe = normalized || fallback
|
||||
if (/^[0-9]/.test(safe)) {
|
||||
safe = `_${safe}`
|
||||
}
|
||||
return safe
|
||||
}
|
||||
|
||||
export function generateFlaskBlueprint(blueprint: FlaskBlueprint): string {
|
||||
let code = `from flask import Blueprint, request, jsonify\n`
|
||||
code += `from typing import Dict, Any\n\n`
|
||||
|
||||
const blueprintVarName = blueprint.name.toLowerCase().replace(/\s+/g, '_')
|
||||
const blueprintVarName = toPythonIdentifier(blueprint.name, 'blueprint')
|
||||
code += `${blueprintVarName}_bp = Blueprint('${blueprintVarName}', __name__, url_prefix='${blueprint.urlPrefix}')\n\n`
|
||||
|
||||
blueprint.endpoints.forEach(endpoint => {
|
||||
const functionName = endpoint.name.toLowerCase().replace(/\s+/g, '_')
|
||||
const functionName = toPythonIdentifier(endpoint.name, 'endpoint')
|
||||
code += `@${blueprintVarName}_bp.route('${endpoint.path}', methods=['${endpoint.method}'])\n`
|
||||
code += `def ${functionName}():\n`
|
||||
code += ` """\n`
|
||||
|
||||
Reference in New Issue
Block a user