ERP-node/frontend/test-scenarios/api-integration-tests.ts

421 lines
13 KiB
TypeScript
Raw Normal View History

/**
* 🌐 API
*
* API와 .
*/
import { apiClient } from "@/lib/api/client";
import {
ComponentData,
WidgetComponent,
ScreenDefinition,
LayoutData,
TableInfo,
UnifiedColumnInfo,
ColumnTypeInfo,
ButtonActionType,
WebType,
isWebType,
isButtonActionType,
ynToBoolean,
booleanToYN,
} from "@/types";
export class APIIntegrationTestSuite {
/**
* 🧪 Test 1: 테이블 API
*/
static async testTableInfoAPI() {
console.log("🧪 API Test 1: 테이블 정보 API 타입 안전성");
try {
// 실제 API 호출
const response = await apiClient.get("/api/admin/table-management/tables", {
params: { companyCode: "COMPANY_1" },
});
if (response.data && Array.isArray(response.data)) {
const tables = response.data as TableInfo[];
tables.forEach((table, index) => {
// 필수 필드 검증
console.assert(typeof table.tableName === "string", `테이블 ${index}: tableName이 문자열이 아님`);
console.assert(typeof table.tableLabel === "string", `테이블 ${index}: tableLabel이 문자열이 아님`);
if (table.columns && Array.isArray(table.columns)) {
table.columns.forEach((column, colIndex) => {
// 컬럼 타입 검증
console.assert(
typeof column.columnName === "string",
`테이블 ${index}, 컬럼 ${colIndex}: columnName이 문자열이 아님`,
);
// WebType 안전성 검증
if (column.webType) {
const isValidWebType = isWebType(column.webType);
if (!isValidWebType) {
console.warn(
`테이블 ${table.tableName}, 컬럼 ${column.columnName}: 유효하지 않은 webType: ${column.webType}`,
);
}
}
});
}
});
console.log(`✅ 테이블 정보 API: ${tables.length}개 테이블 검증 완료`);
return true;
}
} catch (error) {
console.error("❌ 테이블 정보 API 테스트 실패:", error);
return false;
}
}
/**
* 🧪 Test 2: 컬럼 API
*/
static async testColumnTypeAPI() {
console.log("🧪 API Test 2: 컬럼 타입 정보 API 호환성");
try {
const response = await apiClient.get("/api/admin/table-management/columns", {
params: {
tableName: "user_info",
companyCode: "COMPANY_1",
},
});
if (response.data && Array.isArray(response.data)) {
const columns = response.data as ColumnTypeInfo[];
// 백엔드 타입을 프론트엔드 통합 타입으로 변환 테스트
const unifiedColumns: UnifiedColumnInfo[] = columns.map((col) => ({
columnName: col.columnName,
displayName: col.displayName,
dataType: col.dataType,
dbType: col.dbType,
webType: isWebType(col.webType) ? (col.webType as WebType) : "text",
inputType: col.inputType || "direct",
detailSettings: col.detailSettings ? JSON.parse(col.detailSettings) : {},
description: col.description || "",
isNullable: ynToBoolean(col.isNullable),
isPrimaryKey: col.isPrimaryKey,
defaultValue: col.defaultValue,
maxLength: col.maxLength,
companyCode: col.companyCode,
}));
// 변환 검증
unifiedColumns.forEach((unifiedCol, index) => {
const originalCol = columns[index];
// WebType 변환 검증
console.assert(isWebType(unifiedCol.webType), `컬럼 ${unifiedCol.columnName}: WebType 변환 실패`);
// Y/N → boolean 변환 검증
console.assert(
typeof unifiedCol.isNullable === "boolean",
`컬럼 ${unifiedCol.columnName}: isNullable boolean 변환 실패`,
);
// JSON 파싱 검증
console.assert(
typeof unifiedCol.detailSettings === "object",
`컬럼 ${unifiedCol.columnName}: detailSettings 객체 변환 실패`,
);
});
console.log(`✅ 컬럼 타입 API: ${unifiedColumns.length}개 컬럼 변환 완료`);
return true;
}
} catch (error) {
console.error("❌ 컬럼 타입 API 테스트 실패:", error);
return false;
}
}
/**
* 🧪 Test 3: 화면 / API
*/
static async testScreenDefinitionAPI() {
console.log("🧪 API Test 3: 화면 정의 저장/불러오기 API");
try {
// 테스트용 화면 정의 생성
const testScreenDefinition: ScreenDefinition = {
screenId: 9999, // 테스트용 임시 ID
screenName: "API 테스트 화면",
screenCode: "API_TEST_SCREEN",
tableName: "test_table",
tableLabel: "테스트 테이블",
description: "API 타입 안전성 테스트용 화면",
isActive: "Y",
layoutData: {
screenId: 9999,
components: [
{
id: "testWidget",
type: "widget",
widgetType: "text",
position: { x: 10, y: 10 },
size: { width: 200, height: 40 },
label: "테스트 입력",
columnName: "test_column",
required: true,
webTypeConfig: { maxLength: 100 },
} as WidgetComponent,
],
gridSettings: {
enabled: true,
size: 10,
snapToGrid: true,
showGrid: true,
color: "#e0e0e0",
opacity: 0.5,
},
},
};
// 화면 정의 저장 시도
const saveResponse = await apiClient.post("/api/admin/screen-management/screens", testScreenDefinition);
if (saveResponse.status === 200 || saveResponse.status === 201) {
console.log("✅ 화면 정의 저장 성공");
// 저장된 화면 불러오기 시도
const loadResponse = await apiClient.get(
`/api/admin/screen-management/screens/${testScreenDefinition.screenId}`,
);
if (loadResponse.data) {
const loadedScreen = loadResponse.data as ScreenDefinition;
// 데이터 무결성 검증
console.assert(loadedScreen.screenName === testScreenDefinition.screenName, "화면명 불일치");
console.assert(loadedScreen.layoutData.components.length > 0, "컴포넌트 데이터 손실");
// 컴포넌트 타입 안전성 검증
loadedScreen.layoutData.components.forEach((component) => {
if (component.type === "widget") {
const widget = component as WidgetComponent;
console.assert(isWebType(widget.widgetType), `위젯 타입 검증 실패: ${widget.widgetType}`);
}
});
console.log("✅ 화면 정의 불러오기 및 검증 완료");
}
// 테스트 데이터 정리
try {
await apiClient.delete(`/api/admin/screen-management/screens/${testScreenDefinition.screenId}`);
console.log("✅ 테스트 데이터 정리 완료");
} catch (cleanupError) {
console.warn("⚠️ 테스트 데이터 정리 실패 (정상적일 수 있음):", cleanupError);
}
return true;
}
} catch (error) {
console.error("❌ 화면 정의 API 테스트 실패:", error);
return false;
}
}
/**
* 🧪 Test 4: API
*/
static async testFormDataSaveAPI() {
console.log("🧪 API Test 4: 폼 데이터 저장 API 타입 안전성");
try {
// 다양한 웹타입의 폼 데이터 준비
const formData = {
textField: "테스트 텍스트",
numberField: 123,
booleanField: true,
dateField: "2024-01-01",
selectField: "option1",
emailField: "test@example.com",
};
// 컴포넌트 정의 (폼 구조)
const formComponents: WidgetComponent[] = [
{
id: "textField",
type: "widget",
widgetType: "text",
position: { x: 0, y: 0 },
size: { width: 200, height: 40 },
label: "텍스트",
columnName: "text_column",
webTypeConfig: {},
},
{
id: "numberField",
type: "widget",
widgetType: "number",
position: { x: 0, y: 50 },
size: { width: 200, height: 40 },
label: "숫자",
columnName: "number_column",
webTypeConfig: {},
},
{
id: "booleanField",
type: "widget",
widgetType: "checkbox",
position: { x: 0, y: 100 },
size: { width: 200, height: 40 },
label: "체크박스",
columnName: "boolean_column",
webTypeConfig: {},
},
];
// 타입 안전한 데이터 변환
const processedData: Record<string, any> = {};
formComponents.forEach((component) => {
const fieldValue = formData[component.id as keyof typeof formData];
if (fieldValue !== undefined && component.columnName) {
switch (component.widgetType) {
case "text":
case "email":
processedData[component.columnName] = String(fieldValue);
break;
case "number":
processedData[component.columnName] = Number(fieldValue);
break;
case "checkbox":
case "boolean":
processedData[component.columnName] = booleanToYN(Boolean(fieldValue));
break;
case "date":
processedData[component.columnName] = fieldValue ? String(fieldValue) : null;
break;
default:
processedData[component.columnName] = fieldValue;
}
}
});
// 실제 API 호출 시뮬레이션 (일반적인 폼 저장 엔드포인트)
console.log("📤 처리된 폼 데이터:", processedData);
// 타입 검증
console.assert(typeof processedData.text_column === "string", "텍스트 필드 타입 오류");
console.assert(typeof processedData.number_column === "number", "숫자 필드 타입 오류");
console.assert(
processedData.boolean_column === "Y" || processedData.boolean_column === "N",
"불린 필드 Y/N 변환 오류",
);
console.log("✅ 폼 데이터 저장 타입 안전성 검증 완료");
return true;
} catch (error) {
console.error("❌ 폼 데이터 저장 API 테스트 실패:", error);
return false;
}
}
/**
* 🧪 Test 5: 버튼 API
*/
static async testButtonActionAPI() {
console.log("🧪 API Test 5: 버튼 액션 실행 API 타입 안전성");
try {
const buttonActions: ButtonActionType[] = [
"save",
"cancel",
"delete",
"edit",
"add",
"search",
"reset",
"submit",
"close",
"popup",
"modal",
"navigate",
"control",
];
// 각 버튼 액션 타입 검증
buttonActions.forEach((action) => {
console.assert(isButtonActionType(action), `유효하지 않은 버튼 액션: ${action}`);
});
// 잘못된 액션 타입들 검증
const invalidActions = ["insert", "update", "remove", ""];
invalidActions.forEach((action) => {
console.assert(!isButtonActionType(action), `잘못된 액션이 허용됨: ${action}`);
});
console.log("✅ 버튼 액션 타입 안전성 검증 완료");
return true;
} catch (error) {
console.error("❌ 버튼 액션 API 테스트 실패:", error);
return false;
}
}
/**
* 🎯 API
*/
static async runAllAPITests() {
console.log("🎯 API 연동 타입 안전성 테스트 시작\n");
const results = {
tableInfoAPI: false,
columnTypeAPI: false,
screenDefinitionAPI: false,
formDataSaveAPI: false,
buttonActionAPI: false,
};
try {
results.tableInfoAPI = await this.testTableInfoAPI();
results.columnTypeAPI = await this.testColumnTypeAPI();
results.screenDefinitionAPI = await this.testScreenDefinitionAPI();
results.formDataSaveAPI = await this.testFormDataSaveAPI();
results.buttonActionAPI = await this.testButtonActionAPI();
const passedTests = Object.values(results).filter(Boolean).length;
const totalTests = Object.keys(results).length;
console.log(`\n🎉 API 연동 테스트 완료: ${passedTests}/${totalTests} 통과`);
if (passedTests === totalTests) {
console.log("✅ 모든 API 연동 타입 안전성 테스트 통과!");
} else {
console.log("⚠️ 일부 API 연동 테스트 실패");
}
return {
success: passedTests === totalTests,
passedTests,
totalTests,
results,
};
} catch (error) {
console.error("❌ API 연동 테스트 실행 실패:", error);
return {
success: false,
passedTests: 0,
totalTests: Object.keys(results).length,
results,
error: String(error),
};
}
}
}
export default APIIntegrationTestSuite;