|
1 | 1 | // SPDX-License-Identifier: MPL-2.0 |
2 | | -// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell |
3 | | -// Ported via Harvard Engine bulk-processor |
| 2 | +// Ported via Harvard Engine (Semantic pass) |
4 | 3 |
|
5 | 4 | module Bunsenite_test; |
6 | 5 |
|
7 | | -// TODO: Complete semantic implementation |
| 6 | +// SPDX-License-Identifier: MPL-2.0 |
| 7 | +// Bunsenite ReScript Bindings Test Suite |
| 8 | + |
| 9 | +open Bunsenite |
| 10 | + |
| 11 | +// Test helpers |
| 12 | +fn assertEqual = (actual, expected, testName) => { |
| 13 | + if actual == expected { |
| 14 | + Console.log(`✓ ${testName}`) |
| 15 | + } else { |
| 16 | + Console.error(`✗ ${testName}`) |
| 17 | + Console.error(` Expected: ${expected->Js.Json.stringify}`) |
| 18 | + Console.error(` Actual: ${actual->Js.Json.stringify}`) |
| 19 | + } |
| 20 | +} |
| 21 | + |
| 22 | +fn assertOk = (result, testName) => { |
| 23 | + switch result { |
| 24 | + | Ok(_) => Console.log(`✓ ${testName}`) |
| 25 | + | Error(err) => { |
| 26 | + Console.error(`✗ ${testName}`) |
| 27 | + Console.error(` Error: ${errorToString(err)}`) |
| 28 | + } |
| 29 | + } |
| 30 | +} |
| 31 | + |
| 32 | +fn assertError = (result, testName) => { |
| 33 | + switch result { |
| 34 | + | Error(_) => Console.log(`✓ ${testName}`) |
| 35 | + | Ok(_) => Console.error(`✗ ${testName}: Expected error but got Ok`) |
| 36 | + } |
| 37 | +} |
| 38 | + |
| 39 | +// Test suite |
| 40 | +fn runTests = () => { |
| 41 | + Console.log("\n🧪 Bunsenite ReScript Bindings Test Suite\n") |
| 42 | + |
| 43 | + // Test 1: Parse simple Nickel configuration |
| 44 | + Console.log("Parse Tests:") |
| 45 | + fn simpleConfig = parseNickel("{foo = 42}", "test.ncl") |
| 46 | + assertOk(simpleConfig, "Parse simple number configuration") |
| 47 | + |
| 48 | + // Test 2: Parse object configuration |
| 49 | + fn objectConfig = parseNickel("{name = \"test\", value = 100}", "object.ncl") |
| 50 | + assertOk(objectConfig, "Parse object configuration") |
| 51 | + |
| 52 | + // Test 3: Parse nested configuration |
| 53 | + fn nestedConfig = parseNickel("{server = {port = 8080, host = \"localhost\"}}", "nested.ncl") |
| 54 | + assertOk(nestedConfig, "Parse nested configuration") |
| 55 | + |
| 56 | + // Test 4: Parse array configuration |
| 57 | + fn arrayConfig = parseNickel("{items = [1, 2, 3, 4, 5]}", "array.ncl") |
| 58 | + assertOk(arrayConfig, "Parse array configuration") |
| 59 | + |
| 60 | + // Test 5: Parse invalid syntax (should error) |
| 61 | + fn invalidConfig = parseNickel("{foo = }", "invalid.ncl") |
| 62 | + assertError(invalidConfig, "Parse invalid syntax returns error") |
| 63 | + |
| 64 | + // Test 6: Parse empty configuration |
| 65 | + fn emptyConfig = parseNickel("{}", "empty.ncl") |
| 66 | + assertOk(emptyConfig, "Parse empty configuration") |
| 67 | + |
| 68 | + // Validation Tests |
| 69 | + Console.log("\nValidation Tests:") |
| 70 | + |
| 71 | + fn validConfig = validateNickel("{foo = 42}", "valid.ncl") |
| 72 | + assertOk(validConfig, "Validate correct configuration") |
| 73 | + |
| 74 | + fn invalidValidation = validateNickel("{foo = }", "invalid-validate.ncl") |
| 75 | + assertError(invalidValidation, "Validate incorrect configuration returns error") |
| 76 | + |
| 77 | + // Test 7: Validate complex configuration |
| 78 | + fn complexValid = validateNickel( |
| 79 | + "{ |
| 80 | + app = { |
| 81 | + name = \"example\", |
| 82 | + version = \"1.0.0\", |
| 83 | + config = { |
| 84 | + debug = true, |
| 85 | + port = 3000 |
| 86 | + } |
| 87 | + } |
| 88 | + }", |
| 89 | + "complex.ncl", |
| 90 | + ) |
| 91 | + assertOk(complexValid, "Validate complex nested configuration") |
| 92 | + |
| 93 | + // Library Info Tests |
| 94 | + Console.log("\nLibrary Info Tests:") |
| 95 | + |
| 96 | + fn version = getVersion() |
| 97 | + Console.log(`✓ Got version: ${version}`) |
| 98 | + |
| 99 | + fn tier = getRSRTier() |
| 100 | + Console.log(`✓ Got RSR tier: ${tier}`) |
| 101 | + |
| 102 | + fn perimeter = getTPCFPerimeter() |
| 103 | + Console.log(`✓ Got TPCF perimeter: ${perimeter->Int.toString}`) |
| 104 | + |
| 105 | + // Config Value Tests |
| 106 | + Console.log("\nConfig Value Extraction Tests:") |
| 107 | + |
| 108 | + switch objectConfig { |
| 109 | + | Ok(json) => { |
| 110 | + // Test extracting top-level value |
| 111 | + fn nameValue = getConfigValue(json, list{"name"}) |
| 112 | + switch nameValue { |
| 113 | + | Some(_) => Console.log("✓ Extract top-level value") |
| 114 | + | None => Console.error("✗ Failed to extract top-level value") |
| 115 | + } |
| 116 | + |
| 117 | + // Test extracting non-existent value |
| 118 | + fn missingValue = getConfigValue(json, list{"missing"}) |
| 119 | + switch missingValue { |
| 120 | + | None => Console.log("✓ Non-existent value returns None") |
| 121 | + | Some(_) => Console.error("✗ Non-existent value should return None") |
| 122 | + } |
| 123 | + } |
| 124 | + | Error(_) => Console.error("✗ Could not test config value extraction") |
| 125 | + } |
| 126 | + |
| 127 | + switch nestedConfig { |
| 128 | + | Ok(json) => { |
| 129 | + // Test extracting nested value |
| 130 | + fn portValue = getConfigValue(json, list{"server", "port"}) |
| 131 | + switch portValue { |
| 132 | + | Some(_) => Console.log("✓ Extract nested value") |
| 133 | + | None => Console.error("✗ Failed to extract nested value") |
| 134 | + } |
| 135 | + |
| 136 | + // Test extracting with invalid path |
| 137 | + fn invalidPath = getConfigValue(json, list{"server", "nonexistent", "deep"}) |
| 138 | + switch invalidPath { |
| 139 | + | None => Console.log("✓ Invalid nested path returns None") |
| 140 | + | Some(_) => Console.error("✗ Invalid path should return None") |
| 141 | + } |
| 142 | + } |
| 143 | + | Error(_) => Console.error("✗ Could not test nested value extraction") |
| 144 | + } |
| 145 | + |
| 146 | + // Error handling tests |
| 147 | + Console.log("\nError Handling Tests:") |
| 148 | + |
| 149 | + fn parseErr = parseNickel("{invalid syntax here}", "error-test.ncl") |
| 150 | + switch parseErr { |
| 151 | + | Error(err) => { |
| 152 | + fn errStr = errorToString(err) |
| 153 | + Console.log(`✓ Error converted to string: ${errStr}`) |
| 154 | + } |
| 155 | + | Ok(_) => Console.error("✗ Expected parse error") |
| 156 | + } |
| 157 | + |
| 158 | + // Result struct tests |
| 159 | + Console.log("\nResult Type Tests:") |
| 160 | + |
| 161 | + fn successResult: parseResult = Ok(Js.Json.null) |
| 162 | + switch successResult { |
| 163 | + | Ok(_) => Console.log("✓ parseResult Ok variant works") |
| 164 | + | Error(_) => Console.error("✗ parseResult Ok variant failed") |
| 165 | + } |
| 166 | + |
| 167 | + fn errorResult: parseResult = Error(ParseError("test")) |
| 168 | + switch errorResult { |
| 169 | + | Error(_) => Console.log("✓ parseResult Error variant works") |
| 170 | + | Ok(_) => Console.error("✗ parseResult Error variant failed") |
| 171 | + } |
| 172 | + |
| 173 | + fn validateSuccess: validateResult = Ok() |
| 174 | + switch validateSuccess { |
| 175 | + | Ok() => Console.log("✓ validateResult Ok variant works") |
| 176 | + | Error(_) => Console.error("✗ validateResult Ok variant failed") |
| 177 | + } |
| 178 | + |
| 179 | + Console.log("\n✅ Test suite complete\n") |
| 180 | +} |
| 181 | + |
| 182 | +// Run tests |
| 183 | +runTests() |
| 184 | + |
0 commit comments