/** * ๐Ÿงช ํƒ€์ž… ์•ˆ์ „์„ฑ ์ข…ํ•ฉ ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค * * ํ™”๋ฉด๊ด€๋ฆฌ, ์ œ์–ด๊ด€๋ฆฌ, ํ…Œ์ด๋ธ” ํƒ€์ž…๊ด€๋ฆฌ ์‹œ์Šคํ…œ์˜ ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. * ์‹ค์ œ ์‚ฌ์šฉ์ž ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ํƒ€์ž… ์˜ค๋ฅ˜ ์ƒํ™ฉ์„ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค. */ import { ComponentData, WebType, ButtonActionType, WidgetComponent, ContainerComponent, // ํƒ€์ž… ๊ฐ€๋“œ ํ•จ์ˆ˜๋“ค isWidgetComponent, isContainerComponent, isWebType, isButtonActionType, // ์•ˆ์ „ํ•œ ์บ์ŠคํŒ… ํ•จ์ˆ˜๋“ค asWidgetComponent, asContainerComponent, // ๋ณ€ํ™˜ ํ•จ์ˆ˜๋“ค ynToBoolean, booleanToYN, // ํ…Œ์ด๋ธ” ๊ด€๋ จ UnifiedColumnInfo, ColumnTypeInfo, // ์ œ์–ด ๊ด€๋ จ ExtendedButtonTypeConfig, // ํ™”๋ฉด ๊ด€๋ จ ScreenDefinition, GroupState, } from "@/types"; // ===== 1๋‹จ๊ณ„: ๊ธฐ๋ณธ ํƒ€์ž… ๊ฒ€์ฆ ํ…Œ์ŠคํŠธ ===== export class TypeSafetyTestSuite { /** * ๐Ÿงช Test 1: WebType ํƒ€์ž… ์•ˆ์ „์„ฑ ๊ฒ€์ฆ */ static testWebTypeValidation() { console.log("๐Ÿงช Test 1: WebType ํƒ€์ž… ์•ˆ์ „์„ฑ ๊ฒ€์ฆ"); // ์œ ํšจํ•œ WebType๋“ค const validWebTypes = [ "text", "number", "decimal", "date", "datetime", "select", "dropdown", "radio", "checkbox", "boolean", "textarea", "code", "entity", "file", "email", "tel", "url", "button", ]; // ๋ฌดํšจํ•œ ํƒ€์ž…๋“ค (๊ธฐ์กด ์‹œ์Šคํ…œ์—์„œ ๋ฌธ์ œ๊ฐ€ ๋˜์—ˆ๋˜ ๊ฒƒ๋“ค) const invalidWebTypes = [ "text_area", // ๊ธฐ์กด์— ์‚ฌ์šฉ๋˜๋˜ ์ž˜๋ชป๋œ ํƒ€์ž… "VARCHAR", // DB ํƒ€์ž…๊ณผ ํ˜ผ๋™ "submit", // ButtonActionType๊ณผ ํ˜ผ๋™ "container", // ComponentType๊ณผ ํ˜ผ๋™ "", null, undefined, ]; validWebTypes.forEach((type) => { const isValid = isWebType(type); console.assert(isValid, `์œ ํšจํ•œ WebType์ด ๊ฑฐ๋ถ€๋จ: ${type}`); if (isValid) { console.log(`โœ… Valid WebType: ${type}`); } }); invalidWebTypes.forEach((type) => { const isValid = isWebType(type as any); console.assert(!isValid, `๋ฌดํšจํ•œ WebType์ด ํ—ˆ์šฉ๋จ: ${type}`); if (!isValid) { console.log(`โŒ Invalid WebType rejected: ${type}`); } }); } /** * ๐Ÿงช Test 2: ComponentData ํƒ€์ž… ๊ฐ€๋“œ ์•ˆ์ „์„ฑ */ static testComponentTypeGuards() { console.log("\n๐Ÿงช Test 2: ComponentData ํƒ€์ž… ๊ฐ€๋“œ ์•ˆ์ „์„ฑ"); // ์˜ฌ๋ฐ”๋ฅธ ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ const widgetComponent: WidgetComponent = { id: "widget-1", type: "widget", position: { x: 0, y: 0 }, size: { width: 200, height: 40 }, widgetType: "text", label: "ํ…Œ์ŠคํŠธ ํ…์ŠคํŠธ", placeholder: "์ž…๋ ฅํ•˜์„ธ์š”", required: false, readonly: false, webTypeConfig: {}, }; const containerComponent: ContainerComponent = { id: "container-1", type: "container", position: { x: 0, y: 0 }, size: { width: 400, height: 300 }, label: "์ปจํ…Œ์ด๋„ˆ", children: [], layoutDirection: "vertical", }; // ํƒ€์ž… ๊ฐ€๋“œ ํ…Œ์ŠคํŠธ console.assert(isWidgetComponent(widgetComponent), "WidgetComponent ํƒ€์ž… ๊ฐ€๋“œ ์‹คํŒจ"); console.assert(isContainerComponent(containerComponent), "ContainerComponent ํƒ€์ž… ๊ฐ€๋“œ ์‹คํŒจ"); console.assert(!isWidgetComponent(containerComponent), "์ž˜๋ชป๋œ ํƒ€์ž…์ด ํ†ต๊ณผ๋จ"); console.assert(!isContainerComponent(widgetComponent), "์ž˜๋ชป๋œ ํƒ€์ž…์ด ํ†ต๊ณผ๋จ"); // ์•ˆ์ „ํ•œ ์บ์ŠคํŒ… ํ…Œ์ŠคํŠธ const safeWidget = asWidgetComponent(widgetComponent); const safeContainer = asContainerComponent(containerComponent); console.assert(safeWidget !== null, "์•ˆ์ „ํ•œ ์œ„์ ฏ ์บ์ŠคํŒ… ์‹คํŒจ"); console.assert(safeContainer !== null, "์•ˆ์ „ํ•œ ์ปจํ…Œ์ด๋„ˆ ์บ์ŠคํŒ… ์‹คํŒจ"); console.assert(asWidgetComponent(containerComponent) === null, "์ž˜๋ชป๋œ ์บ์ŠคํŒ…์ด ํ—ˆ์šฉ๋จ"); console.log("โœ… Component ํƒ€์ž… ๊ฐ€๋“œ ๋ชจ๋“  ํ…Œ์ŠคํŠธ ํ†ต๊ณผ"); } /** * ๐Ÿงช Test 3: DB ํ˜ธํ™˜์„ฑ (Y/N โ†” boolean) ๋ณ€ํ™˜ ํ…Œ์ŠคํŠธ */ static testYNBooleanConversion() { console.log("\n๐Ÿงช Test 3: DB ํ˜ธํ™˜์„ฑ Y/N โ†” boolean ๋ณ€ํ™˜ ํ…Œ์ŠคํŠธ"); // Y/N โ†’ boolean ๋ณ€ํ™˜ console.assert(ynToBoolean("Y") === true, "Y โ†’ true ๋ณ€ํ™˜ ์‹คํŒจ"); console.assert(ynToBoolean("N") === false, "N โ†’ false ๋ณ€ํ™˜ ์‹คํŒจ"); console.assert(ynToBoolean("") === false, "๋นˆ ๋ฌธ์ž์—ด โ†’ false ๋ณ€ํ™˜ ์‹คํŒจ"); console.assert(ynToBoolean(undefined) === false, "undefined โ†’ false ๋ณ€ํ™˜ ์‹คํŒจ"); // boolean โ†’ Y/N ๋ณ€ํ™˜ console.assert(booleanToYN(true) === "Y", "true โ†’ Y ๋ณ€ํ™˜ ์‹คํŒจ"); console.assert(booleanToYN(false) === "N", "false โ†’ N ๋ณ€ํ™˜ ์‹คํŒจ"); // ์‹ค์ œ DB ์‹œ๋‚˜๋ฆฌ์˜ค ์‹œ๋ฎฌ๋ ˆ์ด์…˜ const dbColumnData = { isActive: "Y", isVisible: "N", isPrimaryKey: "Y", isNullable: "N", }; const convertedData = { isActive: ynToBoolean(dbColumnData.isActive), isVisible: ynToBoolean(dbColumnData.isVisible), isPrimaryKey: ynToBoolean(dbColumnData.isPrimaryKey), isNullable: ynToBoolean(dbColumnData.isNullable), }; console.assert(convertedData.isActive === true, "DB isActive ๋ณ€ํ™˜ ์‹คํŒจ"); console.assert(convertedData.isVisible === false, "DB isVisible ๋ณ€ํ™˜ ์‹คํŒจ"); console.log("โœ… Y/N โ†” boolean ๋ณ€ํ™˜ ๋ชจ๋“  ํ…Œ์ŠคํŠธ ํ†ต๊ณผ"); } /** * ๐Ÿงช Test 4: ์‹ค์ œ ํผ ์ €์žฅ ์‹œ๋‚˜๋ฆฌ์˜ค ์‹œ๋ฎฌ๋ ˆ์ด์…˜ */ static async testFormSaveScenarios() { console.log("\n๐Ÿงช Test 4: ์‹ค์ œ ํผ ์ €์žฅ ์‹œ๋‚˜๋ฆฌ์˜ค ์‹œ๋ฎฌ๋ ˆ์ด์…˜"); // ์‹œ๋‚˜๋ฆฌ์˜ค 1: ํ˜ผํ•ฉ ์›นํƒ€์ž… ํผ ๋ฐ์ดํ„ฐ const formData = { userName: "ํ™๊ธธ๋™", userAge: 25, userEmail: "hong@example.com", isActive: true, birthDate: "1999-01-01", userRole: "admin", description: "ํ…Œ์ŠคํŠธ ์‚ฌ์šฉ์ž์ž…๋‹ˆ๋‹ค.", }; // ์‹œ๋‚˜๋ฆฌ์˜ค 2: ์ปดํฌ๋„ŒํŠธ๋ณ„ ์›นํƒ€์ž… ๋งคํ•‘ const formComponents: ComponentData[] = [ { id: "userName", type: "widget", widgetType: "text", position: { x: 0, y: 0 }, size: { width: 200, height: 40 }, label: "์‚ฌ์šฉ์ž๋ช…", columnName: "user_name", webTypeConfig: {}, } as WidgetComponent, { id: "userAge", type: "widget", widgetType: "number", position: { x: 0, y: 50 }, size: { width: 200, height: 40 }, label: "๋‚˜์ด", columnName: "user_age", webTypeConfig: { min: 0, max: 120 }, } as WidgetComponent, { id: "isActive", type: "widget", widgetType: "checkbox", position: { x: 0, y: 100 }, size: { width: 200, height: 40 }, label: "ํ™œ์„ฑํ™”", columnName: "is_active", webTypeConfig: {}, } as WidgetComponent, ]; // ํƒ€์ž… ์•ˆ์ „ํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ const processedData: Record = {}; for (const component of formComponents) { if (isWidgetComponent(component)) { const { columnName, widgetType } = component; if (columnName && widgetType && formData.hasOwnProperty(component.id)) { const rawValue = formData[component.id as keyof typeof formData]; // ์›นํƒ€์ž…๋ณ„ ์•ˆ์ „ํ•œ ๋ณ€ํ™˜ switch (widgetType) { case "text": case "email": case "textarea": processedData[columnName] = String(rawValue); break; case "number": case "decimal": processedData[columnName] = Number(rawValue); break; case "checkbox": case "boolean": processedData[columnName] = booleanToYN(Boolean(rawValue)); break; case "date": case "datetime": processedData[columnName] = rawValue ? String(rawValue) : null; break; default: console.warn(`์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ์›นํƒ€์ž…: ${widgetType}`); processedData[columnName] = rawValue; } } } } console.log("โœ… ํผ ๋ฐ์ดํ„ฐ ํƒ€์ž… ์•ˆ์ „ ๋ณ€ํ™˜:", processedData); // ๊ฒ€์ฆ: ๋ชจ๋“  ๊ฐ’์ด ์˜ฌ๋ฐ”๋ฅธ ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜๋˜์—ˆ๋Š”์ง€ ํ™•์ธ console.assert(typeof processedData.user_name === "string", "์‚ฌ์šฉ์ž๋ช… ํƒ€์ž… ๋ณ€ํ™˜ ์‹คํŒจ"); console.assert(typeof processedData.user_age === "number", "๋‚˜์ด ํƒ€์ž… ๋ณ€ํ™˜ ์‹คํŒจ"); console.assert(processedData.is_active === "Y" || processedData.is_active === "N", "ํ™œ์„ฑํ™” ์ƒํƒœ ๋ณ€ํ™˜ ์‹คํŒจ"); } /** * ๐Ÿงช Test 5: ๋ฒ„ํŠผ ์ œ์–ด๊ด€๋ฆฌ ํƒ€์ž… ์•ˆ์ „์„ฑ ํ…Œ์ŠคํŠธ */ static testButtonControlTypesSafety() { console.log("\n๐Ÿงช Test 5: ๋ฒ„ํŠผ ์ œ์–ด๊ด€๋ฆฌ ํƒ€์ž… ์•ˆ์ „์„ฑ ํ…Œ์ŠคํŠธ"); // ButtonActionType ์•ˆ์ „์„ฑ ๊ฒ€์ฆ const validActions: ButtonActionType[] = [ "save", "cancel", "delete", "edit", "add", "search", "reset", "submit", "close", "popup", "modal", "navigate", "control", ]; validActions.forEach((action) => { console.assert(isButtonActionType(action), `์œ ํšจํ•œ ButtonActionType ๊ฑฐ๋ถ€: ${action}`); }); // ๋ฌดํšจํ•œ ์•ก์…˜ ํƒ€์ž…๋“ค const invalidActions = ["insert", "update", "remove", ""]; invalidActions.forEach((action) => { console.assert(!isButtonActionType(action), `๋ฌดํšจํ•œ ButtonActionType ํ—ˆ์šฉ: ${action}`); }); console.log("โœ… ๋ฒ„ํŠผ ์ œ์–ด๊ด€๋ฆฌ ํƒ€์ž… ์•ˆ์ „์„ฑ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ"); } /** * ๐Ÿงช Test 6: ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ ์ •๋ณด ํƒ€์ž… ํ˜ธํ™˜์„ฑ ํ…Œ์ŠคํŠธ */ static testTableColumnTypeCompatibility() { console.log("\n๐Ÿงช Test 6: ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ ์ •๋ณด ํƒ€์ž… ํ˜ธํ™˜์„ฑ ํ…Œ์ŠคํŠธ"); // ๋ฐฑ์—”๋“œ์—์„œ ๋ฐ›์€ ์›์‹œ ์ปฌ๋Ÿผ ์ •๋ณด (ColumnTypeInfo) const backendColumnInfo: ColumnTypeInfo = { columnName: "user_name", displayName: "์‚ฌ์šฉ์ž๋ช…", dataType: "varchar", dbType: "character varying(100)", webType: "text", // string ํƒ€์ž… (๋ฐฑ์—”๋“œ) inputType: "direct", detailSettings: JSON.stringify({ maxLength: 100 }), description: "์‚ฌ์šฉ์ž์˜ ์ด๋ฆ„์„ ์ €์žฅํ•˜๋Š” ์ปฌ๋Ÿผ", isNullable: "N", // Y/N ๋ฌธ์ž์—ด isPrimaryKey: false, defaultValue: "", maxLength: 100, }; // ํ”„๋ก ํŠธ์—”๋“œ ํ†ตํ•ฉ ์ปฌ๋Ÿผ ์ •๋ณด๋กœ ๋ณ€ํ™˜ (UnifiedColumnInfo) const unifiedColumnInfo: UnifiedColumnInfo = { columnName: backendColumnInfo.columnName, displayName: backendColumnInfo.displayName, dataType: backendColumnInfo.dataType, dbType: backendColumnInfo.dbType, webType: isWebType(backendColumnInfo.webType) ? (backendColumnInfo.webType as WebType) : "text", // ์•ˆ์ „ํ•œ ํƒ€์ž… ๋ณ€ํ™˜ inputType: backendColumnInfo.inputType, detailSettings: JSON.parse(backendColumnInfo.detailSettings || "{}"), description: backendColumnInfo.description, isNullable: ynToBoolean(backendColumnInfo.isNullable), // Y/N โ†’ boolean isPrimaryKey: backendColumnInfo.isPrimaryKey, defaultValue: backendColumnInfo.defaultValue, maxLength: backendColumnInfo.maxLength, companyCode: backendColumnInfo.companyCode, }; // ๊ฒ€์ฆ console.assert(isWebType(unifiedColumnInfo.webType), "WebType ๋ณ€ํ™˜ ์‹คํŒจ"); console.assert(typeof unifiedColumnInfo.isNullable === "boolean", "isNullable ํƒ€์ž… ๋ณ€ํ™˜ ์‹คํŒจ"); console.assert(typeof unifiedColumnInfo.detailSettings === "object", "detailSettings JSON ํŒŒ์‹ฑ ์‹คํŒจ"); console.log("โœ… ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ ํƒ€์ž… ํ˜ธํ™˜์„ฑ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ"); console.log("๋ณ€ํ™˜๋œ ์ปฌ๋Ÿผ ์ •๋ณด:", unifiedColumnInfo); } /** * ๐Ÿงช Test 7: ๋ณตํ•ฉ ์‹œ๋‚˜๋ฆฌ์˜ค - ํ™”๋ฉด ์„ค๊ณ„ + ๋ฐ์ดํ„ฐ ์ €์žฅ + ์ œ์–ด ์‹คํ–‰ */ static async testComplexScenario() { console.log("\n๐Ÿงช Test 7: ๋ณตํ•ฉ ์‹œ๋‚˜๋ฆฌ์˜ค - ํ™”๋ฉด ์„ค๊ณ„ + ๋ฐ์ดํ„ฐ ์ €์žฅ + ์ œ์–ด ์‹คํ–‰"); try { // Step 1: ํ™”๋ฉด ์ •์˜ ์ƒ์„ฑ (๋‹จ์ˆœํ™”๋œ ๋ฒ„์ „) const screenDefinition: ScreenDefinition = { screenId: 1001, screenName: "์‚ฌ์šฉ์ž ๊ด€๋ฆฌ", screenCode: "USER_MANAGEMENT", tableName: "user_info", tableLabel: "์‚ฌ์šฉ์ž ์ •๋ณด", description: "์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ํ™”๋ฉด", isActive: "Y", }; // ๊ฐœ๋ณ„ ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ const components: ComponentData[] = [ { id: "userName", type: "widget", widgetType: "text", position: { x: 10, y: 10 }, size: { width: 200, height: 40 }, label: "์‚ฌ์šฉ์ž๋ช…", columnName: "user_name", required: true, webTypeConfig: { maxLength: 50 }, } as WidgetComponent, ]; // Step 2: ์ปดํฌ๋„ŒํŠธ ํƒ€์ž… ์•ˆ์ „์„ฑ ๊ฒ€์ฆ components.forEach((component) => { if (isWidgetComponent(component)) { console.assert(isWebType(component.widgetType), `์ž˜๋ชป๋œ ์œ„์ ฏํƒ€์ž…: ${component.widgetType}`); } }); // Step 3: ๊ทธ๋ฃน ์ƒํƒœ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ const groupState: GroupState = { isGrouping: true, selectedComponents: ["userName", "saveButton"], groupTarget: "userForm", groupMode: "create", groupTitle: "์‚ฌ์šฉ์ž ์ž…๋ ฅ ํผ", }; // Step 4: ์‹ค์ œ ์ €์žฅ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ const formData = { userName: "ํ…Œ์ŠคํŠธ ์‚ฌ์šฉ์ž", userEmail: "test@example.com", isActive: true, }; console.log("โœ… ๋ณตํ•ฉ ์‹œ๋‚˜๋ฆฌ์˜ค ๋ชจ๋“  ๋‹จ๊ณ„ ์„ฑ๊ณต"); console.log("- ํ™”๋ฉด ์ •์˜ ์ƒ์„ฑ: โœ“"); console.log("- ์ปดํฌ๋„ŒํŠธ ํƒ€์ž… ๊ฒ€์ฆ: โœ“"); console.log("- ๊ทธ๋ฃน ์ƒํƒœ ๊ด€๋ฆฌ: โœ“"); console.log("- ๋ฐ์ดํ„ฐ ์ €์žฅ ์‹œ๋ฎฌ๋ ˆ์ด์…˜: โœ“"); } catch (error) { console.error("โŒ ๋ณตํ•ฉ ์‹œ๋‚˜๋ฆฌ์˜ค ์‹คํŒจ:", error); throw error; } } /** * ๐ŸŽฏ ๋ชจ๋“  ํ…Œ์ŠคํŠธ ์‹คํ–‰ */ static async runAllTests() { console.log("๐ŸŽฏ ํƒ€์ž… ์•ˆ์ „์„ฑ ์ข…ํ•ฉ ํ…Œ์ŠคํŠธ ์‹œ์ž‘\n"); try { this.testWebTypeValidation(); this.testComponentTypeGuards(); this.testYNBooleanConversion(); await this.testFormSaveScenarios(); this.testButtonControlTypesSafety(); this.testTableColumnTypeCompatibility(); await this.testComplexScenario(); console.log("\n๐ŸŽ‰ ๋ชจ๋“  ํƒ€์ž… ์•ˆ์ „์„ฑ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ!"); console.log("โœ… ํ™”๋ฉด๊ด€๋ฆฌ, ์ œ์–ด๊ด€๋ฆฌ, ํ…Œ์ด๋ธ”ํƒ€์ž…๊ด€๋ฆฌ ์‹œ์Šคํ…œ์˜ ํƒ€์ž… ์•ˆ์ „์„ฑ์ด ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค."); return { success: true, passedTests: 7, failedTests: 0, message: "๋ชจ๋“  ํƒ€์ž… ์•ˆ์ „์„ฑ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ", }; } catch (error) { console.error("โŒ ํƒ€์ž… ์•ˆ์ „์„ฑ ํ…Œ์ŠคํŠธ ์‹คํŒจ:", error); return { success: false, passedTests: 0, failedTests: 1, message: `ํ…Œ์ŠคํŠธ ์‹คํŒจ: ${error}`, }; } } } // ๐Ÿ”ฅ ์ŠคํŠธ๋ ˆ์Šค ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค export class StressTestScenarios { /** * ๐Ÿ”ฅ ๊ทนํ•œ ์ƒํ™ฉ ํ…Œ์ŠคํŠธ: ์ž˜๋ชป๋œ ํƒ€์ž…๋“ค์˜ ํ˜ผ์žฌ */ static testMixedInvalidTypes() { console.log("๐Ÿ”ฅ ๊ทนํ•œ ์ƒํ™ฉ ํ…Œ์ŠคํŠธ: ์ž˜๋ชป๋œ ํƒ€์ž…๋“ค์˜ ํ˜ผ์žฌ"); // API๋กœ๋ถ€ํ„ฐ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ์ž˜๋ชป๋œ ๋ฐ์ดํ„ฐ๋“ค const corruptedData = [ { webType: "text_area", expected: false }, // ๊ธฐ์กด ์ž˜๋ชป๋œ ํƒ€์ž… { webType: "VARCHAR(255)", expected: false }, // DB ํƒ€์ž… ํ˜ผ์ž… { webType: "submit", expected: false }, // ButtonActionType ํ˜ผ์ž… { webType: "", expected: false }, // ๋นˆ ๋ฌธ์ž์—ด { webType: null, expected: false }, // null { webType: undefined, expected: false }, // undefined { webType: 123, expected: false }, // ์ˆซ์ž { webType: {}, expected: false }, // ๊ฐ์ฒด { webType: "text", expected: true }, // ์˜ฌ๋ฐ”๋ฅธ ํƒ€์ž… ]; corruptedData.forEach(({ webType, expected }) => { const result = isWebType(webType as any); console.assert( result === expected, `ํƒ€์ž… ๊ฒ€์ฆ ์‹คํŒจ: ${JSON.stringify(webType)} โ†’ expected: ${expected}, got: ${result}`, ); }); console.log("โœ… ๊ทนํ•œ ์ƒํ™ฉ ํƒ€์ž… ๊ฒ€์ฆ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ"); } /** * ๐Ÿ”ฅ ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์‹œ๋‚˜๋ฆฌ์˜ค */ static testBulkDataProcessing() { console.log("๐Ÿ”ฅ ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์‹œ๋‚˜๋ฆฌ์˜ค"); // 1000๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ ๋ฐ ํƒ€์ž… ๊ฒ€์ฆ const components: ComponentData[] = []; const webTypes: WebType[] = ["text", "number", "date", "select", "checkbox"]; for (let i = 0; i < 1000; i++) { const randomWebType = webTypes[i % webTypes.length]; const component: WidgetComponent = { id: `widget-${i}`, type: "widget", widgetType: randomWebType, position: { x: i % 100, y: Math.floor(i / 100) * 50 }, size: { width: 200, height: 40 }, label: `Component ${i}`, webTypeConfig: {}, }; components.push(component); } // ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ ํƒ€์ž… ๊ฒ€์ฆ let validCount = 0; components.forEach((component) => { if (isWidgetComponent(component) && isWebType(component.widgetType)) { validCount++; } }); console.assert(validCount === 1000, `๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ ์‹คํŒจ: ${validCount}/1000`); console.log(`โœ… ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์„ฑ๊ณต: ${validCount}/1000 ์ปดํฌ๋„ŒํŠธ ๊ฒ€์ฆ ์™„๋ฃŒ`); } } // Export for use in tests export default TypeSafetyTestSuite;