mirror of
https://github.com/foss42/apidash.git
synced 2025-07-02 22:16:44 +08:00
fix: explainAPI button glitch in response_pan
This commit is contained in:
@ -55,8 +55,6 @@ class ResponseDetails extends ConsumerWidget {
|
|||||||
final responseModel = ref.watch(selectedRequestModelProvider
|
final responseModel = ref.watch(selectedRequestModelProvider
|
||||||
.select((value) => value?.httpResponseModel));
|
.select((value) => value?.httpResponseModel));
|
||||||
|
|
||||||
final requestModel = ref.watch(selectedRequestModelProvider);
|
|
||||||
final ollamaService = ref.watch(ollamaServiceProvider);
|
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
@ -71,42 +69,6 @@ class ResponseDetails extends ConsumerWidget {
|
|||||||
const Expanded(
|
const Expanded(
|
||||||
child: ResponseTabs(),
|
child: ResponseTabs(),
|
||||||
),
|
),
|
||||||
if (requestModel != null && responseModel != null)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: ElevatedButton(
|
|
||||||
onPressed: () async {
|
|
||||||
try {
|
|
||||||
final explanation = await ollamaService.explainLatestApi(
|
|
||||||
requestModel: requestModel,
|
|
||||||
responseModel: responseModel,
|
|
||||||
);
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => AlertDialog(
|
|
||||||
title: const Text('Explanation'),
|
|
||||||
content: SingleChildScrollView(
|
|
||||||
child: Text(explanation),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.pop(context),
|
|
||||||
child: const Text('Close'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(
|
|
||||||
content: Text("Error explaining response."),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: const Text('Explain API'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -100,53 +100,6 @@ Analysis: [structured analysis]''';
|
|||||||
return generateResponse(prompt);
|
return generateResponse(prompt);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> generateTestCases({required dynamic requestModel, required dynamic responseModel}) async {
|
|
||||||
|
|
||||||
final method = requestModel.httpRequestModel?.method
|
|
||||||
.toString()
|
|
||||||
.split('.')
|
|
||||||
.last
|
|
||||||
.toUpperCase()
|
|
||||||
?? "GET";
|
|
||||||
final endpoint = requestModel.httpRequestModel?.url ?? "Unknown endpoint";
|
|
||||||
final headers = requestModel.httpRequestModel?.enabledHeadersMap ?? {};
|
|
||||||
final parameters = requestModel.httpRequestModel?.enabledParamsMap ?? {};
|
|
||||||
final body = requestModel.httpRequestModel?.body;
|
|
||||||
final exampleParams = await generateExampleParams(
|
|
||||||
requestModel: requestModel,
|
|
||||||
responseModel: responseModel,
|
|
||||||
);
|
|
||||||
final prompt = '''
|
|
||||||
Generate test cases for the following API:
|
|
||||||
|
|
||||||
**API Request:**
|
|
||||||
- **Endpoint:** `$endpoint`
|
|
||||||
- **Method:** `$method`
|
|
||||||
- **Headers:** ${headers.isNotEmpty ? jsonEncode(headers) : "None"}
|
|
||||||
- **Parameters:** ${parameters.isNotEmpty ? jsonEncode(parameters) : "None"}
|
|
||||||
|
|
||||||
**Test Case Requirements:**
|
|
||||||
1. Normal case (valid input, expected success)
|
|
||||||
2. Edge case (unexpected or boundary values)
|
|
||||||
3. Missing required parameters
|
|
||||||
4. Invalid authentication (if applicable)
|
|
||||||
5. Error handling for different status codes
|
|
||||||
|
|
||||||
**Example Test Case Format:**
|
|
||||||
@Test
|
|
||||||
void testValidRequest() {
|
|
||||||
final response = sendRequest("$endpoint", method: "$method", params: $exampleParams);
|
|
||||||
assert(response.status == 200);
|
|
||||||
}
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
Generate test cases covering all scenarios.
|
|
||||||
''';
|
|
||||||
|
|
||||||
return generateResponse(prompt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate example parameter values based on parameter names
|
|
||||||
Future<Map<String, dynamic>> generateExampleParams({required dynamic requestModel, required dynamic responseModel,}) async {
|
Future<Map<String, dynamic>> generateExampleParams({required dynamic requestModel, required dynamic responseModel,}) async {
|
||||||
final ollamaService = OllamaService();
|
final ollamaService = OllamaService();
|
||||||
|
|
||||||
@ -198,4 +151,118 @@ Analyze the following API request and generate structured example parameters.
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Future<String> generateTestCases({required dynamic requestModel, required dynamic responseModel}) async {
|
||||||
|
final method = requestModel.httpRequestModel?.method
|
||||||
|
.toString()
|
||||||
|
.split('.')
|
||||||
|
.last
|
||||||
|
.toUpperCase()
|
||||||
|
?? "GET";
|
||||||
|
final endpoint = requestModel.httpRequestModel?.url ?? "Unknown endpoint";
|
||||||
|
final headers = requestModel.httpRequestModel?.enabledHeadersMap ?? {};
|
||||||
|
final parameters = requestModel.httpRequestModel?.enabledParamsMap ?? {};
|
||||||
|
final body = requestModel.httpRequestModel?.body;
|
||||||
|
final statusCode = responseModel.statusCode ?? 200;
|
||||||
|
|
||||||
|
// Extract example values from successful response
|
||||||
|
final responseBody = responseModel.body is String
|
||||||
|
? jsonDecode(responseModel.body)
|
||||||
|
: responseModel.body;
|
||||||
|
final exampleValues = _extractExampleValues(parameters, responseBody);
|
||||||
|
|
||||||
|
final prompt = '''
|
||||||
|
Generate comprehensive test cases in JSON format for this API endpoint:
|
||||||
|
|
||||||
|
API Details:
|
||||||
|
- Endpoint: $endpoint
|
||||||
|
- Method: $method
|
||||||
|
- Headers: ${headers.isNotEmpty ? jsonEncode(headers) : "None"}
|
||||||
|
- Parameters: ${parameters.isNotEmpty ? jsonEncode(parameters) : "None"}
|
||||||
|
- Successful Response Example (${statusCode}): ${jsonEncode(responseBody)}
|
||||||
|
|
||||||
|
Test Case Requirements:
|
||||||
|
1. Structure tests in JSON format with arrays for different categories
|
||||||
|
2. Include valid parameter combinations from the actual request
|
||||||
|
3. Create edge cases using min/max values and boundary conditions
|
||||||
|
4. Generate invalid parameter combinations that trigger error responses
|
||||||
|
5. Include authentication failure scenarios if applicable
|
||||||
|
6. Mirror successful response structure in test expectations
|
||||||
|
|
||||||
|
JSON Template:
|
||||||
|
{
|
||||||
|
"test_cases": {
|
||||||
|
"valid": [
|
||||||
|
{
|
||||||
|
"name": "Test valid request with typical parameters",
|
||||||
|
"parameters": { /* mirror actual parameter structure */ },
|
||||||
|
"expected": {
|
||||||
|
"status_code": ${statusCode},
|
||||||
|
"body_patterns": { /* key fields to validate */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"edge_cases": [
|
||||||
|
{
|
||||||
|
"name": "Test maximum limit boundary",
|
||||||
|
"parameters": { /* edge values */ },
|
||||||
|
"expected": { /* status and response patterns */ }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"invalid": [
|
||||||
|
{
|
||||||
|
"name": "Test missing required parameter",
|
||||||
|
"parameters": { /* incomplete params */ },
|
||||||
|
"expected": {
|
||||||
|
"status_code": 400,
|
||||||
|
"error_patterns": [ "missing field", "required" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Example Values from Current Implementation:
|
||||||
|
${jsonEncode(exampleValues)}
|
||||||
|
|
||||||
|
Generation Guidelines:
|
||||||
|
- Use parameter names and structure from the actual request
|
||||||
|
- Base valid values on successful response patterns
|
||||||
|
- Derive edge cases from parameter types (e.g., string length, number ranges)
|
||||||
|
- Match error responses to observed API behavior
|
||||||
|
- Include authentication headers if present in original request
|
||||||
|
- Prioritize testing critical business logic endpoints
|
||||||
|
|
||||||
|
Generate the JSON test suite following this structure and guidelines.
|
||||||
|
''';
|
||||||
|
|
||||||
|
return generateResponse(prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> _extractExampleValues( Map<String, String> parameters, dynamic responseBody) {
|
||||||
|
final examples = <String, dynamic>{};
|
||||||
|
|
||||||
|
// Extract parameter examples
|
||||||
|
examples['parameters'] = parameters.map((k, v) =>
|
||||||
|
MapEntry(k, _deriveValuePattern(v)));
|
||||||
|
|
||||||
|
// Extract response body patterns
|
||||||
|
if (responseBody is Map) {
|
||||||
|
examples['response_patterns'] = responseBody.map((k, v) =>
|
||||||
|
MapEntry(k, _deriveValuePattern(v)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return examples;
|
||||||
|
}
|
||||||
|
|
||||||
|
String _deriveValuePattern(dynamic value) {
|
||||||
|
if (value is num) return "{number}";
|
||||||
|
if (value is String) {
|
||||||
|
if (DateTime.tryParse(value) != null) return "{datetime}";
|
||||||
|
if (value.contains('@')) return "{email}";
|
||||||
|
return "{string}";
|
||||||
|
}
|
||||||
|
return "{value}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user