import XCTest @testable import SwiftBricks final class SwiftBricksTests: XCTestCase { // MARK: - Schema解析 func testParseSimpleSchema() throws { let json = """ { "widgettype": "Text", "options": { "text": "Hello World", "i18n": false } } """ let data = json.data(using: .utf8)! let schema = try JSONDecoder().decode(ControlSchema.self, from: data) XCTAssertEqual(schema.widgettype, "Text") XCTAssertEqual(schema.options.text, "Hello World") XCTAssertEqual(schema.options.i18n, false) } func testParseVBoxWithSubwidgets() throws { let json = """ { "widgettype": "VBox", "options": { "spacing": 10, "css": "card" }, "subwidgets": [ { "widgettype": "Title2", "options": { "text": "标题" } }, { "widgettype": "Text", "options": { "otext": "描述文本" } }, { "widgettype": "Button", "id": "btn1", "options": { "label": "点击" }, "binds": [{ "wid": "self", "event": "click", "actiontype": "urlwidget", "target": "content", "options": { "url": "/api/page.ui" } }] } ] } """ let data = json.data(using: .utf8)! let schema = try JSONDecoder().decode(ControlSchema.self, from: data) XCTAssertEqual(schema.widgettype, "VBox") XCTAssertEqual(schema.options.spacing, 10) XCTAssertEqual(schema.subwidgets?.count, 3) XCTAssertEqual(schema.subwidgets?[0].widgettype, "Title2") XCTAssertEqual(schema.subwidgets?[2].binds?.count, 1) XCTAssertEqual(schema.subwidgets?[2].binds?[0].actiontype, "urlwidget") } func testParseFormSchema() throws { let json = """ { "widgettype": "Form", "options": { "title": "用户信息", "submit_url": "/api/submit.dspy", "fields": [ { "name": "username", "label": "用户名", "uitype": "str", "required": true, "rules": [{ "type": "required", "message": "不能为空" }] }, { "name": "role", "label": "角色", "uitype": "code", "codes": [{"value": "admin", "text": "管理员"}, {"value": "user", "text": "普通用户"}] } ] } } """ let data = json.data(using: .utf8)! let schema = try JSONDecoder().decode(ControlSchema.self, from: data) XCTAssertEqual(schema.widgettype, "Form") XCTAssertEqual(schema.options.fields?.count, 2) XCTAssertEqual(schema.options.fields?[0].rules?.count, 1) XCTAssertEqual(schema.options.fields?[1].codes?.count, 2) } func testParseTabularSchema() throws { let json = """ { "widgettype": "Tabular", "options": { "data_url": "/api/list.dspy", "page_rows": 10, "row_options": { "fields": [ { "name": "id", "label": "ID", "uitype": "str" }, { "name": "name", "label": "名称", "uitype": "str" } ], "browserfields": { "exclouded": ["id"] } } } } """ let data = json.data(using: .utf8)! let schema = try JSONDecoder().decode(ControlSchema.self, from: data) XCTAssertEqual(schema.widgettype, "Tabular") XCTAssertEqual(schema.options.page_rows, 10) XCTAssertEqual(schema.options.row_options?.fields?.count, 2) XCTAssertEqual(schema.options.row_options?.browserfields?.exclouded, ["id"]) } // MARK: - ActionType验证 func testValidActionTypes() { XCTAssertEqual(ActionType.allCases.count, 9) XCTAssertNotNil(ActionType(rawValue: "urlwidget")) XCTAssertNotNil(ActionType(rawValue: "urldata")) XCTAssertNotNil(ActionType(rawValue: "method")) XCTAssertNotNil(ActionType(rawValue: "event")) XCTAssertNil(ActionType(rawValue: "fetch")) // 无效 XCTAssertNil(ActionType(rawValue: "ajax")) // 无效 } // MARK: - WidgetType验证 func testWidgetTypeCategories() { XCTAssertTrue(WidgetType.vbox.isLayout) XCTAssertTrue(WidgetType.hbox.isLayout) XCTAssertTrue(WidgetType.text.isText) XCTAssertTrue(WidgetType.title2.isText) XCTAssertTrue(WidgetType.input.isInput) XCTAssertFalse(WidgetType.button.isLayout) } // MARK: - Store @MainActor func testStoreFormValues() { let store = BricksStore() store.setFormField(formId: "form1", field: "name", value: "Alice") store.setFormField(formId: "form1", field: "email", value: "alice@test.com") XCTAssertEqual(store.getFormField(formId: "form1", field: "name"), "Alice") XCTAssertEqual(store.getFormField(formId: "form1", field: "email"), "alice@test.com") let all = store.getFormValues(formId: "form1") XCTAssertEqual(all.count, 2) store.clearForm(formId: "form1") XCTAssertEqual(store.getFormField(formId: "form1", field: "name"), "") } @MainActor func testStoreTableData() { let store = BricksStore() let rows: [[String: Any]] = [ ["id": "1", "name": "Alice"], ["id": "2", "name": "Bob"] ] store.setTableData(id: "tbl1", rows: rows) store.selectRow(tabularId: "tbl1", index: 1) XCTAssertEqual(store.getTableData(id: "tbl1").count, 2) XCTAssertEqual(store.getSelectedRow(tabularId: "tbl1"), 1) let selected = store.getSelectedRowData(tabularId: "tbl1") XCTAssertEqual(selected?["name"] as? String, "Bob") } // MARK: - I18n @MainActor func testI18nTranslation() { let i18n = BricksI18n(locale: "en") i18n.loadMessages([ "你好": "Hello", "提交": "Submit" ]) XCTAssertEqual(i18n.t("你好"), "Hello") XCTAssertEqual(i18n.t("提交"), "Submit") XCTAssertEqual(i18n.t("未知"), "未知") // 未翻译返回原文 } // MARK: - EventBus @MainActor func testEventBus() async { let bus = BricksEventBus() var received = false bus.on("test.click") { _ in received = true } await bus.dispatch("test.click") XCTAssertTrue(received) } // MARK: - Engine模板替换 @MainActor func testTemplateResolve() { let engine = BricksEngine() let result = engine.resolveTemplate("/api/detail.dspy?id=${id}$", params: ["id": "12345"]) XCTAssertEqual(result, "/api/detail.dspy?id=12345") } }