import Testing import Foundation @testable import CalcPad @Suite("FFI JSON Model Decoding Tests") struct FFIModelTests { // MARK: - Single Line Response @Test("Decode number result") func decodeNumberResult() throws { let json = """ { "schema_version": "1.0", "result": { "value": { "kind": "Number", "value": 42.0 }, "metadata": { "span": { "start": 0, "end": 5 }, "result_type": "Number", "display": "42", "raw_value": 42.0 } } } """ let response = try JSONDecoder().decode(FFIResponse.self, from: Data(json.utf8)) #expect(response.schemaVersion == "1.0") #expect(response.result.metadata.display == "42") #expect(response.result.metadata.resultType == "Number") #expect(response.result.metadata.rawValue == 42.0) if case .number(let value) = response.result.value { #expect(value == 42.0) } else { Issue.record("Expected .number variant") } } @Test("Decode unit value result") func decodeUnitValueResult() throws { let json = """ { "schema_version": "1.0", "result": { "value": { "kind": "UnitValue", "value": 5.0, "unit": "kg" }, "metadata": { "span": { "start": 0, "end": 4 }, "result_type": "UnitValue", "display": "5 kg", "raw_value": 5.0 } } } """ let response = try JSONDecoder().decode(FFIResponse.self, from: Data(json.utf8)) if case .unitValue(let value, let unit) = response.result.value { #expect(value == 5.0) #expect(unit == "kg") } else { Issue.record("Expected .unitValue variant") } } @Test("Decode currency value result") func decodeCurrencyValueResult() throws { let json = """ { "schema_version": "1.0", "result": { "value": { "kind": "CurrencyValue", "amount": 19.99, "currency": "USD" }, "metadata": { "span": { "start": 0, "end": 6 }, "result_type": "CurrencyValue", "display": "$19.99", "raw_value": 19.99 } } } """ let response = try JSONDecoder().decode(FFIResponse.self, from: Data(json.utf8)) if case .currencyValue(let amount, let currency) = response.result.value { #expect(amount == 19.99) #expect(currency == "USD") } else { Issue.record("Expected .currencyValue variant") } } @Test("Decode datetime result") func decodeDateTimeResult() throws { let json = """ { "schema_version": "1.0", "result": { "value": { "kind": "DateTime", "date": "2024-03-17" }, "metadata": { "span": { "start": 0, "end": 10 }, "result_type": "DateTime", "display": "2024-03-17", "raw_value": null } } } """ let response = try JSONDecoder().decode(FFIResponse.self, from: Data(json.utf8)) if case .dateTime(let date) = response.result.value { #expect(date == "2024-03-17") } else { Issue.record("Expected .dateTime variant") } #expect(response.result.metadata.rawValue == nil) } @Test("Decode time delta result") func decodeTimeDeltaResult() throws { let json = """ { "schema_version": "1.0", "result": { "value": { "kind": "TimeDelta", "days": 30, "description": "30 days" }, "metadata": { "span": { "start": 0, "end": 8 }, "result_type": "TimeDelta", "display": "30 days", "raw_value": 30.0 } } } """ let response = try JSONDecoder().decode(FFIResponse.self, from: Data(json.utf8)) if case .timeDelta(let days, let desc) = response.result.value { #expect(days == 30) #expect(desc == "30 days") } else { Issue.record("Expected .timeDelta variant") } } @Test("Decode boolean result") func decodeBooleanResult() throws { let json = """ { "schema_version": "1.0", "result": { "value": { "kind": "Boolean", "value": true }, "metadata": { "span": { "start": 0, "end": 5 }, "result_type": "Boolean", "display": "true", "raw_value": null } } } """ let response = try JSONDecoder().decode(FFIResponse.self, from: Data(json.utf8)) if case .boolean(let value) = response.result.value { #expect(value == true) } else { Issue.record("Expected .boolean variant") } } @Test("Decode error result") func decodeErrorResult() throws { let json = """ { "schema_version": "1.0", "result": { "value": { "kind": "Error", "message": "unexpected token", "span": { "start": 0, "end": 3 } }, "metadata": { "span": { "start": 0, "end": 3 }, "result_type": "Error", "display": "Error: unexpected token", "raw_value": null } } } """ let response = try JSONDecoder().decode(FFIResponse.self, from: Data(json.utf8)) #expect(response.result.value.isError) if case .error(let message) = response.result.value { #expect(message == "unexpected token") } else { Issue.record("Expected .error variant") } } // MARK: - Sheet Response @Test("Decode sheet response with multiple results") func decodeSheetResponse() throws { let json = """ { "schema_version": "1.0", "results": [ { "value": { "kind": "Number", "value": 4.0 }, "metadata": { "span": { "start": 0, "end": 5 }, "result_type": "Number", "display": "4", "raw_value": 4.0 } }, { "value": { "kind": "Error", "message": "empty expression", "span": { "start": 0, "end": 0 } }, "metadata": { "span": { "start": 0, "end": 0 }, "result_type": "Error", "display": "Error: empty expression", "raw_value": null } }, { "value": { "kind": "Number", "value": 30.0 }, "metadata": { "span": { "start": 0, "end": 6 }, "result_type": "Number", "display": "30", "raw_value": 30.0 } } ] } """ let response = try JSONDecoder().decode(FFISheetResponse.self, from: Data(json.utf8)) #expect(response.results.count == 3) #expect(response.results[0].metadata.display == "4") #expect(response.results[1].value.isError) #expect(response.results[2].metadata.display == "30") } // MARK: - FFICalcValue.isError @Test("isError returns false for non-error values") func isErrorFalseForNonError() throws { let json = """ { "kind": "Number", "value": 42.0 } """ let value = try JSONDecoder().decode(FFICalcValue.self, from: Data(json.utf8)) #expect(value.isError == false) } }