Yimaru-BackEnd/postman/Dynamic-Question-Type-Builder.postman_collection.json

419 lines
13 KiB
JSON

{
"info": {
"name": "Yimaru Dynamic Question Type Builder API",
"_postman_id": "f0f9c795-09aa-4f5a-9cc0-1f2fcb0f1b01",
"description": "Complete Postman collection for the dynamic question type builder feature, including catalog, validation, reusable type-definition CRUD, and question create/update using question_type_definition_id.",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"variable": [
{
"key": "baseUrl",
"value": "http://localhost:8080"
},
{
"key": "apiPrefix",
"value": "/api/v1"
},
{
"key": "token",
"value": ""
},
{
"key": "questionTypeDefinitionId",
"value": ""
},
{
"key": "questionId",
"value": ""
}
],
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{token}}",
"type": "string"
}
]
},
"item": [
{
"name": "01 - Builder Component Catalog",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}{{apiPrefix}}/questions/component-catalog",
"host": [
"{{baseUrl}}"
],
"path": [
"{{apiPrefix}}",
"questions",
"component-catalog"
]
},
"description": "Returns supported stimulus and response component kinds for dynamic type definitions."
},
"response": []
},
{
"name": "02 - Validate Dynamic Type Definition",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"stimulus_component_kinds\": [\"INSTRUCTION\", \"TEXT_PASSAGE\"],\n \"response_component_kinds\": [\"MULTIPLE_CHOICE\"]\n}"
},
"url": {
"raw": "{{baseUrl}}{{apiPrefix}}/questions/validate-question-type-definition",
"host": [
"{{baseUrl}}"
],
"path": [
"{{apiPrefix}}",
"questions",
"validate-question-type-definition"
]
},
"description": "Validates a candidate dynamic question-type definition before saving."
},
"response": []
},
{
"name": "03 - Create Question Type Definition (MCQ Dynamic)",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"key\": \"mcq_dynamic_vocab\",\n \"display_name\": \"MCQ Dynamic Vocabulary\",\n \"description\": \"Dynamic multiple-choice template for vocabulary checks.\",\n \"stimulus_component_kinds\": [\"INSTRUCTION\", \"TEXT_PASSAGE\"],\n \"response_component_kinds\": [\"MULTIPLE_CHOICE\"],\n \"status\": \"ACTIVE\"\n}"
},
"url": {
"raw": "{{baseUrl}}{{apiPrefix}}/questions/type-definitions",
"host": [
"{{baseUrl}}"
],
"path": [
"{{apiPrefix}}",
"questions",
"type-definitions"
]
},
"description": "Creates a reusable dynamic question-type definition."
},
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test('Status is 201', function () { pm.response.to.have.status(201); });",
"var json = pm.response.json();",
"if (json && json.data && json.data.id) {",
" pm.collectionVariables.set('questionTypeDefinitionId', json.data.id);",
"}"
],
"type": "text/javascript"
}
}
],
"response": []
},
{
"name": "04 - List Question Type Definitions (Include System)",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}{{apiPrefix}}/questions/type-definitions?include_system=true&status=ACTIVE",
"host": [
"{{baseUrl}}"
],
"path": [
"{{apiPrefix}}",
"questions",
"type-definitions"
],
"query": [
{
"key": "include_system",
"value": "true"
},
{
"key": "status",
"value": "ACTIVE"
}
]
},
"description": "Lists reusable dynamic definitions (system + custom)."
},
"response": []
},
{
"name": "05 - Get Question Type Definition By ID",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}{{apiPrefix}}/questions/type-definitions/{{questionTypeDefinitionId}}",
"host": [
"{{baseUrl}}"
],
"path": [
"{{apiPrefix}}",
"questions",
"type-definitions",
"{{questionTypeDefinitionId}}"
]
},
"description": "Fetches one dynamic type-definition by ID."
},
"response": []
},
{
"name": "06 - Update Question Type Definition",
"request": {
"method": "PUT",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"display_name\": \"MCQ Dynamic Vocabulary (Updated)\",\n \"description\": \"Updated dynamic MCQ template.\",\n \"stimulus_component_kinds\": [\"INSTRUCTION\", \"TEXT_PASSAGE\", \"IMAGE\"],\n \"response_component_kinds\": [\"MULTIPLE_CHOICE\", \"ANSWER_TIMER\"],\n \"status\": \"ACTIVE\"\n}"
},
"url": {
"raw": "{{baseUrl}}{{apiPrefix}}/questions/type-definitions/{{questionTypeDefinitionId}}",
"host": [
"{{baseUrl}}"
],
"path": [
"{{apiPrefix}}",
"questions",
"type-definitions",
"{{questionTypeDefinitionId}}"
]
},
"description": "Updates dynamic definition (except key/system flag)."
},
"response": []
},
{
"name": "07 - Create Question Using question_type_definition_id",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"question_text\": \"Choose the correct synonym for 'rapid'.\",\n \"question_type_definition_id\": {{questionTypeDefinitionId}},\n \"difficulty_level\": \"EASY\",\n \"points\": 1,\n \"status\": \"PUBLISHED\",\n \"options\": [\n { \"option_text\": \"Slow\", \"option_order\": 1, \"is_correct\": false },\n { \"option_text\": \"Quick\", \"option_order\": 2, \"is_correct\": true },\n { \"option_text\": \"Heavy\", \"option_order\": 3, \"is_correct\": false },\n { \"option_text\": \"Late\", \"option_order\": 4, \"is_correct\": false }\n ]\n}"
},
"url": {
"raw": "{{baseUrl}}{{apiPrefix}}/questions",
"host": [
"{{baseUrl}}"
],
"path": [
"{{apiPrefix}}",
"questions"
]
},
"description": "Creates a question by binding to a dynamic definition. Backend infers runtime question_type from the definition."
},
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test('Status is 201', function () { pm.response.to.have.status(201); });",
"var json = pm.response.json();",
"if (json && json.data && json.data.id) {",
" pm.collectionVariables.set('questionId', json.data.id);",
"}"
],
"type": "text/javascript"
}
}
],
"response": []
},
{
"name": "08 - Create Question (Explicit question_type + Definition)",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"question_text\": \"Pick the antonym of 'expand'.\",\n \"question_type\": \"MCQ\",\n \"question_type_definition_id\": {{questionTypeDefinitionId}},\n \"difficulty_level\": \"MEDIUM\",\n \"points\": 2,\n \"options\": [\n { \"option_text\": \"Increase\", \"option_order\": 1, \"is_correct\": false },\n { \"option_text\": \"Contract\", \"option_order\": 2, \"is_correct\": true },\n { \"option_text\": \"Stretch\", \"option_order\": 3, \"is_correct\": false },\n { \"option_text\": \"Grow\", \"option_order\": 4, \"is_correct\": false }\n ]\n}"
},
"url": {
"raw": "{{baseUrl}}{{apiPrefix}}/questions",
"host": [
"{{baseUrl}}"
],
"path": [
"{{apiPrefix}}",
"questions"
]
},
"description": "Valid combination: explicit question_type must match the type inferred from the selected definition."
},
"response": []
},
{
"name": "09 - Update Question (Switch/Attach Definition)",
"request": {
"method": "PUT",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"question_type_definition_id\": {{questionTypeDefinitionId}},\n \"question_type\": \"MCQ\",\n \"question_text\": \"Choose the best definition of 'meticulous'.\",\n \"options\": [\n { \"option_text\": \"Careless\", \"option_order\": 1, \"is_correct\": false },\n { \"option_text\": \"Very careful and precise\", \"option_order\": 2, \"is_correct\": true },\n { \"option_text\": \"Quickly done\", \"option_order\": 3, \"is_correct\": false }\n ],\n \"status\": \"PUBLISHED\"\n}"
},
"url": {
"raw": "{{baseUrl}}{{apiPrefix}}/questions/{{questionId}}",
"host": [
"{{baseUrl}}"
],
"path": [
"{{apiPrefix}}",
"questions",
"{{questionId}}"
]
},
"description": "Updates a question and links (or re-links) it to a dynamic definition."
},
"response": []
},
{
"name": "10 - Get Question By ID",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}{{apiPrefix}}/questions/{{questionId}}",
"host": [
"{{baseUrl}}"
],
"path": [
"{{apiPrefix}}",
"questions",
"{{questionId}}"
]
},
"description": "Returns question details (options/short_answers/audio fields as applicable)."
},
"response": []
},
{
"name": "11 - List Questions",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}{{apiPrefix}}/questions?question_type=MCQ&limit=10&offset=0",
"host": [
"{{baseUrl}}"
],
"path": [
"{{apiPrefix}}",
"questions"
],
"query": [
{
"key": "question_type",
"value": "MCQ"
},
{
"key": "limit",
"value": "10"
},
{
"key": "offset",
"value": "0"
}
]
},
"description": "Lists questions filtered by runtime question_type."
},
"response": []
},
{
"name": "12 - Negative Test: Mismatched Type and Definition",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"question_text\": \"This should fail.\",\n \"question_type\": \"AUDIO\",\n \"question_type_definition_id\": {{questionTypeDefinitionId}},\n \"options\": [\n { \"option_text\": \"A\", \"option_order\": 1, \"is_correct\": true }\n ]\n}"
},
"url": {
"raw": "{{baseUrl}}{{apiPrefix}}/questions",
"host": [
"{{baseUrl}}"
],
"path": [
"{{apiPrefix}}",
"questions"
]
},
"description": "Expected 400 because explicit question_type does not match inferred type from definition."
},
"response": []
},
{
"name": "13 - Delete Custom Question Type Definition",
"request": {
"method": "DELETE",
"header": [],
"url": {
"raw": "{{baseUrl}}{{apiPrefix}}/questions/type-definitions/{{questionTypeDefinitionId}}",
"host": [
"{{baseUrl}}"
],
"path": [
"{{apiPrefix}}",
"questions",
"type-definitions",
"{{questionTypeDefinitionId}}"
]
},
"description": "Deletes a custom definition. System definitions cannot be deleted."
},
"response": []
}
]
}