1 module fluentasserts.vibe.json; 2 3 version(Have_vibe_d_data): 4 5 import std.exception, std.conv, std.traits; 6 import std.array, std.algorithm, std.typecons; 7 import std.uni, std.string, std.math; 8 9 import vibe.data.json; 10 import fluentasserts.core.base; 11 import fluentasserts.core.results; 12 13 import fluentasserts.core.serializers; 14 import fluentasserts.core.operations.equal; 15 import fluentasserts.core.operations.arrayEqual; 16 import fluentasserts.core.operations.contain; 17 import fluentasserts.core.operations.startWith; 18 import fluentasserts.core.operations.endWith; 19 import fluentasserts.core.operations.registry; 20 import fluentasserts.core.operations.lessThan; 21 import fluentasserts.core.operations.greaterThan; 22 import fluentasserts.core.operations.between; 23 import fluentasserts.core.operations.approximately; 24 25 static this() { 26 SerializerRegistry.instance.register(&jsonToString); 27 Registry.instance.register!(Json, Json[])("equal", &fluentasserts.core.operations.equal.equal); 28 Registry.instance.register!(Json[], Json)("equal", &fluentasserts.core.operations.equal.equal); 29 Registry.instance.register!(Json[], Json[])("equal", &fluentasserts.core.operations.arrayEqual.arrayEqual); 30 Registry.instance.register!(Json[][], Json[][])("equal", &fluentasserts.core.operations.arrayEqual.arrayEqual); 31 Registry.instance.register!(Json, Json[][])("equal", &fluentasserts.core.operations.arrayEqual.arrayEqual); 32 33 static foreach(Type; BasicNumericTypes) { 34 Registry.instance.register!(Json, Type[])("equal", &fluentasserts.core.operations.equal.equal); 35 Registry.instance.register!(Json, Type)("lessThan", &fluentasserts.core.operations.lessThan.lessThan!Type); 36 Registry.instance.register!(Json, Type)("greaterThan", &fluentasserts.core.operations.greaterThan.greaterThan!Type); 37 Registry.instance.register!(Json, Type)("between", &fluentasserts.core.operations.between.between!Type); 38 Registry.instance.register!(Json, Type)("approximately", &fluentasserts.core.operations.approximately.approximately); 39 } 40 41 static foreach(Type; StringTypes) { 42 Registry.instance.register(extractTypes!(Json[])[0], "void[]", "equal", &arrayEqual); 43 44 Registry.instance.register!(Type[], Json[])("equal", &arrayEqual); 45 46 Registry.instance.register!(Type, Json[])("contain", &contain); 47 Registry.instance.register!(Type, Json)("contain", &contain); 48 Registry.instance.register!(Type[], Json[])("contain", &arrayContain); 49 Registry.instance.register!(Type[], Json[])("containOnly", &arrayContainOnly); 50 51 Registry.instance.register!(Type, Json)("startWith", &startWith); 52 Registry.instance.register!(Type, Json)("endWith", &endWith); 53 } 54 } 55 56 string jsonToString(Json value) { 57 return jsonToString(value, 0); 58 } 59 60 string jsonToString(Json value, size_t level) { 61 62 if(value.type == Json.Type.array) { 63 string prefix = rightJustifier(``, level * 2, ' ').array; 64 return `[` ~ value.byValue.map!(a => jsonToString(a, level)).join(", ") ~ `]`; 65 } 66 67 if(value.type == Json.Type.object) { 68 auto keys = value.keys 69 .sort 70 .filter!(key => value[key].type != Json.Type.null_ && value[key].type != Json.Type.undefined); 71 72 if(keys.empty) { 73 return `{}`; 74 } 75 76 string prefix = rightJustifier(``, 2 + level * 2, ' ').array; 77 string endPrefix = rightJustifier(``, level * 2, ' ').array; 78 79 return "{\n" ~ keys.map!(key => prefix ~ `"` ~ key ~ `": ` ~ value[key].jsonToString(level + 1)).join(",\n") ~ "\n" ~ endPrefix ~ "}"; 80 } 81 82 if(value.type == Json.Type.null_) { 83 return "null"; 84 } 85 86 if(value.type == Json.Type.undefined) { 87 return "undefined"; 88 } 89 90 if(value.type == Json.Type..string) { 91 return `"` ~ value.to!string ~ `"`; 92 } 93 94 if(value.type == Json.Type.float_) { 95 return format("%.10f", value.to!double).strip("0").strip("."); 96 } 97 98 return value.to!string; 99 } 100 101 102 /// it should convert a double to a string 103 unittest { 104 Json(2.3).jsonToString.should.equal("2.3"); 105 Json(59.0 / 15.0).jsonToString.should.equal("3.9333333333"); 106 } 107 108 /// Get all the keys from your Json object 109 string[] keys(Json obj, const string file = __FILE__, const size_t line = __LINE__) @trusted { 110 string[] list; 111 112 if(obj.type != Json.Type.object) { 113 IResult[] results = [ cast(IResult) new MessageResult("Invalid Json type."), 114 cast(IResult) new ExpectedActualResult("object", obj.type.to!string), 115 cast(IResult) new SourceResult(file, line) ]; 116 117 throw new TestException(results, file, line); 118 } 119 120 static if(typeof(obj.byKeyValue).stringof == "Rng") { 121 foreach(string key, Json value; obj.byKeyValue) { 122 list ~= key; 123 } 124 125 list = list.sort.array; 126 127 return list; 128 } else { 129 pragma(msg, "Json.keys is not compatible with your vibe.d version"); 130 assert(false, "Json.keys is not compatible with your vibe.d version"); 131 } 132 } 133 134 /// Empty Json object keys 135 unittest { 136 Json.emptyObject.keys.length.should.equal(0); 137 } 138 139 /// Json object keys 140 unittest { 141 auto obj = Json.emptyObject; 142 obj["key1"] = 1; 143 obj["key2"] = 3; 144 145 obj.keys.should.containOnly(["key1", "key2"]); 146 } 147 148 /// Json array keys 149 unittest { 150 auto obj = Json.emptyArray; 151 152 ({ 153 obj.keys.should.contain(["key1", "key2"]); 154 }).should.throwAnyException.msg.should.startWith("Invalid Json type."); 155 } 156 157 /// Get all the keys from your Json object. The levels will be separated by `.` or `[]` 158 string[] nestedKeys(Json obj) @trusted { 159 return obj.flatten.byKeyValue.map!"a.key".array; 160 } 161 162 /// Empty Json object keys 163 unittest { 164 Json.emptyObject.nestedKeys.length.should.equal(0); 165 } 166 167 /// Get all keys from nested object 168 unittest { 169 auto obj = Json.emptyObject; 170 obj["key1"] = 1; 171 obj["key2"] = 2; 172 obj["key3"] = Json.emptyObject; 173 obj["key3"]["item1"] = "3"; 174 obj["key3"]["item2"] = Json.emptyObject; 175 obj["key3"]["item2"]["item4"] = Json.emptyObject; 176 obj["key3"]["item2"]["item5"] = Json.emptyObject; 177 obj["key3"]["item2"]["item5"]["item6"] = Json.emptyObject; 178 179 obj.nestedKeys.should.containOnly(["key1", "key2", "key3.item1", "key3.item2.item4", "key3.item2.item5.item6"]); 180 } 181 182 /// Get all keys from nested objects inside an array 183 unittest { 184 auto obj = Json.emptyObject; 185 Json elm = Json.emptyObject; 186 elm["item5"] = Json.emptyObject; 187 elm["item5"]["item6"] = Json.emptyObject; 188 189 obj["key2"] = Json.emptyArray; 190 obj["key3"] = Json.emptyArray; 191 obj["key3"] ~= Json("3"); 192 obj["key3"] ~= Json.emptyObject; 193 obj["key3"] ~= elm; 194 obj["key3"] ~= [ Json.emptyArray ]; 195 196 obj.nestedKeys.should.containOnly(["key2", "key3[0]", "key3[1]", "key3[2].item5.item6", "key3[3]"]); 197 } 198 199 /// Takes a nested Json object and moves the values to a Json assoc array where the key 200 /// is the path from the original object to that value 201 Json[string] flatten(Json object) @trusted { 202 Json[string] elements; 203 204 auto root = tuple("", object); 205 Tuple!(string, Json)[] queue = [ root ]; 206 207 while(queue.length > 0) { 208 auto element = queue[0]; 209 210 if(element[0] != "") { 211 if(element[1].type != Json.Type.object && element[1].type != Json.Type.array) { 212 elements[element[0]] = element[1]; 213 } 214 215 if(element[1].type == Json.Type.object && element[1].length == 0) { 216 elements[element[0]] = element[1]; 217 } 218 219 if(element[1].type == Json.Type.array && element[1].length == 0) { 220 elements[element[0]] = element[1]; 221 } 222 } 223 224 if(element[1].type == Json.Type.object) { 225 foreach(string key, value; element[1].byKeyValue) { 226 string nextKey = key; 227 228 if(element[0] != "") { 229 nextKey = element[0] ~ "." ~ nextKey; 230 } 231 232 queue ~= tuple(nextKey, value); 233 } 234 } 235 236 if(element[1].type == Json.Type.array) { 237 size_t index; 238 239 foreach(value; element[1].byValue) { 240 string nextKey = element[0] ~ "[" ~ index.to!string ~ "]"; 241 242 queue ~= tuple(nextKey, value); 243 index++; 244 } 245 } 246 247 queue = queue[1..$]; 248 } 249 250 return elements; 251 } 252 253 /// Get a flatten object 254 unittest { 255 auto obj = Json.emptyObject; 256 obj["key1"] = 1; 257 obj["key2"] = 2; 258 obj["key3"] = Json.emptyObject; 259 obj["key3"]["item1"] = "3"; 260 obj["key3"]["item2"] = Json.emptyObject; 261 obj["key3"]["item2"]["item4"] = Json.emptyObject; 262 obj["key3"]["item2"]["item5"] = Json.emptyObject; 263 obj["key3"]["item2"]["item5"]["item6"] = Json.emptyObject; 264 265 auto result = obj.flatten; 266 result.byKeyValue.map!(a => a.key).should.containOnly(["key1", "key2", "key3.item1", "key3.item2.item4", "key3.item2.item5.item6"]); 267 result["key1"].should.equal(1); 268 result["key2"].should.equal(2); 269 result["key3.item1"].should.equal("3"); 270 result["key3.item2.item4"].should.equal(Json.emptyObject); 271 result["key3.item2.item5.item6"].should.equal(Json.emptyObject); 272 } 273 274 auto unpackJsonArray(T : U[], U)(Json data) if(!isArray!U && isBasicType!U) { 275 return data.byValue.map!(a => a.to!U).array.dup; 276 } 277 278 auto unpackJsonArray(T : U[], U)(Json data) if(!isArray!U && is(Unqual!U == Json)) { 279 U[] result; 280 281 foreach(element; data.byValue) { 282 result ~= element; 283 } 284 285 return result; 286 } 287 288 auto unpackJsonArray(T : U[], U)(Json data) if(isArray!(U) && !isSomeString!(U[])) { 289 U[] result; 290 291 foreach(element; data.byValue) { 292 result ~= unpackJsonArray!(U)(element); 293 } 294 295 return result; 296 } 297 298 version(unittest) { 299 import std.string; 300 } 301 302 /// Two sepparate json objects are equal 303 unittest { 304 Json.emptyObject.should.equal(Json.emptyObject); 305 } 306 307 /// An json object with an undefined value is iqual to an empty object json with no values 308 unittest { 309 auto value = Json.emptyObject; 310 value["key"] = Json(); 311 312 value.should.equal(Json.emptyObject); 313 } 314 315 /// It should be able to compare an empty object with an empty array 316 unittest { 317 auto msg = ({ 318 Json.emptyObject.should.equal(Json.emptyArray); 319 }).should.throwException!TestException.msg; 320 321 msg.split("\n")[0].strip.should.equal(`Json.emptyObject should equal []. {} is not equal to [].`); 322 msg.split("\n")[2].strip.should.equal(`[-[]][+{}]`); 323 msg.split("\n")[4].strip.should.equal("Expected:[]"); 324 msg.split("\n")[5].strip.should.equal("Actual:{}"); 325 326 ({ 327 Json.emptyObject.should.not.equal(Json.emptyArray); 328 }).should.not.throwException!TestException; 329 } 330 331 /// It should be able to compare two strings 332 unittest { 333 ({ 334 Json("test string").should.equal("test string"); 335 Json("other string").should.not.equal("test"); 336 }).should.not.throwAnyException; 337 338 ({ 339 Json("test string").should.equal(Json("test string")); 340 Json("other string").should.not.equal(Json("test")); 341 }).should.not.throwAnyException; 342 343 auto msg = ({ 344 Json("test string").should.equal("test"); 345 }).should.throwException!TestException.msg; 346 347 msg.split("\n")[0].should.equal(`Json("test string") should equal "test". "test string" is not equal to "test".`); 348 } 349 350 /// It throw on comparing a Json number with a string 351 unittest { 352 auto msg = ({ 353 Json(4).should.equal("some string"); 354 }).should.throwException!TestException.msg; 355 356 msg.split("\n")[0].strip.should.equal(`Json(4) should equal "some string". 4 is not equal to "some string".`); 357 msg.split("\n")[2].strip.should.equal(`[-"some string"][+4]`); 358 msg.split("\n")[4].strip.should.equal(`Expected:"some string"`); 359 msg.split("\n")[5].strip.should.equal(`Actual:4`); 360 } 361 362 /// It throws when you compare a Json string with integer values 363 unittest { 364 auto msg = ({ 365 byte val = 4; 366 Json("some string").should.equal(val); 367 }).should.throwException!TestException.msg; 368 369 msg.split("\n")[0].strip.should.equal(`Json("some string") should equal 4. "some string" is not equal to 4.`); 370 msg.split("\n")[2].strip.should.equal(`[-4][+"some string"]`); 371 msg.split("\n")[4].strip.should.equal("Expected:4"); 372 msg.split("\n")[5].strip.should.equal(`Actual:"some string"`); 373 374 msg = ({ 375 short val = 4; 376 Json("some string").should.equal(val); 377 }).should.throwException!TestException.msg; 378 379 msg.split("\n")[0].strip.should.equal(`Json("some string") should equal 4. "some string" is not equal to 4.`); 380 381 msg = ({ 382 int val = 4; 383 Json("some string").should.equal(val); 384 }).should.throwException!TestException.msg; 385 386 msg.split("\n")[0].strip.should.equal(`Json("some string") should equal 4. "some string" is not equal to 4.`); 387 388 msg = ({ 389 long val = 4; 390 Json("some string").should.equal(val); 391 }).should.throwException!TestException.msg; 392 393 msg.split("\n")[0].strip.should.equal(`Json("some string") should equal 4. "some string" is not equal to 4.`); 394 } 395 396 /// It throws when you compare a Json string with unsigned integer values 397 unittest { 398 auto msg = ({ 399 ubyte val = 4; 400 Json("some string").should.equal(val); 401 }).should.throwException!TestException.msg; 402 403 msg.split("\n")[0].strip.should.equal(`Json("some string") should equal 4. "some string" is not equal to 4.`); 404 405 msg = ({ 406 ushort val = 4; 407 Json("some string").should.equal(val); 408 }).should.throwException!TestException.msg; 409 410 msg.split("\n")[0].strip.should.equal(`Json("some string") should equal 4. "some string" is not equal to 4.`); 411 412 msg = ({ 413 uint val = 4; 414 Json("some string").should.equal(val); 415 }).should.throwException!TestException.msg; 416 417 msg.split("\n")[0].strip.should.equal(`Json("some string") should equal 4. "some string" is not equal to 4.`); 418 419 msg = ({ 420 ulong val = 4; 421 Json("some string").should.equal(val); 422 }).should.throwException!TestException.msg; 423 424 msg.split("\n")[0].strip.should.equal(`Json("some string") should equal 4. "some string" is not equal to 4.`); 425 } 426 427 /// It throws when you compare a Json string with floating point values 428 unittest { 429 auto msg = ({ 430 float val = 3.14; 431 Json("some string").should.equal(val); 432 }).should.throwException!TestException.msg; 433 434 msg.split("\n")[0].strip.should.equal(`Json("some string") should equal 3.14. "some string" is not equal to 3.14.`); 435 msg.split("\n")[2].strip.should.equal(`[-3.14][+"some string"]`); 436 msg.split("\n")[4].strip.should.equal("Expected:3.14"); 437 msg.split("\n")[5].strip.should.equal(`Actual:"some string"`); 438 439 msg = ({ 440 double val = 3.14; 441 Json("some string").should.equal(val); 442 }).should.throwException!TestException.msg; 443 444 msg.split("\n")[0].strip.should.equal(`Json("some string") should equal 3.14. "some string" is not equal to 3.14.`); 445 } 446 447 /// It throws when you compare a Json string with bool values 448 unittest { 449 auto msg = ({ 450 Json("some string").should.equal(false); 451 }).should.throwException!TestException.msg; 452 453 msg.split("\n")[0].strip.should.equal(`Json("some string") should equal false. "some string" is not equal to false.`); 454 } 455 456 /// It should be able to compare two integers 457 unittest { 458 Json(4L).should.equal(4f); 459 Json(4).should.equal(4); 460 Json(4).should.not.equal(5); 461 462 Json(4).should.equal(Json(4)); 463 Json(4).should.not.equal(Json(5)); 464 Json(4L).should.not.equal(Json(5f)); 465 466 auto msg = ({ 467 Json(4).should.equal(5); 468 }).should.throwException!TestException.msg; 469 470 msg.split("\n")[0].should.equal(`Json(4) should equal 5. 4 is not equal to 5.`); 471 472 msg = ({ 473 Json(4).should.equal(Json(5)); 474 }).should.throwException!TestException.msg; 475 476 msg.split("\n")[0].should.equal(`Json(4) should equal 5. 4 is not equal to 5.`); 477 } 478 479 /// It throws on comparing an integer Json with a string 480 unittest { 481 auto msg = ({ 482 Json(4).should.equal("5"); 483 }).should.throwException!TestException.msg; 484 485 msg.split("\n")[0].should.equal(`Json(4) should equal "5". 4 is not equal to "5".`); 486 487 msg = ({ 488 Json(4).should.equal(Json("5")); 489 }).should.throwException!TestException.msg; 490 491 msg.split("\n")[0].should.equal(`Json(4) should equal "5". 4 is not equal to "5".`); 492 } 493 494 /// It should be able to compare two floating point numbers 495 unittest { 496 Json(4f).should.equal(4L); 497 Json(4.3).should.equal(4.3); 498 Json(4.3).should.not.equal(5.3); 499 500 Json(4.3).should.equal(Json(4.3)); 501 Json(4.3).should.not.equal(Json(5.3)); 502 503 auto msg = ({ 504 Json(4.3).should.equal(5.3); 505 }).should.throwException!TestException.msg; 506 507 msg.split("\n")[0].should.equal("Json(4.3) should equal 5.3. 4.3 is not equal to 5.3."); 508 509 msg = ({ 510 Json(4.3).should.equal(Json(5.3)); 511 }).should.throwException!TestException.msg; 512 513 msg.split("\n")[0].should.equal("Json(4.3) should equal 5.3. 4.3 is not equal to 5.3."); 514 } 515 516 /// It throws on comparing an floating point Json with a string 517 unittest { 518 auto msg = ({ 519 Json(4f).should.equal("5"); 520 }).should.throwException!TestException.msg; 521 522 msg.split("\n")[0].should.equal(`Json(4f) should equal "5". 4 is not equal to "5".`); 523 524 msg = ({ 525 Json(4f).should.equal(Json("5")); 526 }).should.throwException!TestException.msg; 527 528 msg.split("\n")[0].should.equal(`Json(4f) should equal "5". 4 is not equal to "5".`); 529 } 530 531 /// It should be able to compare two booleans 532 unittest { 533 Json(true).should.equal(true); 534 Json(true).should.not.equal(false); 535 536 Json(true).should.equal(Json(true)); 537 Json(true).should.not.equal(Json(false)); 538 539 auto msg = ({ 540 Json(true).should.equal(false); 541 }).should.throwException!TestException.msg; 542 543 msg.split("\n")[0].should.equal("Json(true) should equal false. true is not equal to false."); 544 545 msg = ({ 546 Json(true).should.equal(Json(false)); 547 }).should.throwException!TestException.msg; 548 549 msg.split("\n")[0].should.equal("Json(true) should equal false. true is not equal to false."); 550 } 551 552 /// It throws on comparing a bool Json with a string 553 unittest { 554 auto msg = ({ 555 Json(true).should.equal("5"); 556 }).should.throwException!TestException.msg; 557 558 msg.split("\n")[0].should.equal(`Json(true) should equal "5". true is not equal to "5".`); 559 560 msg = ({ 561 Json(true).should.equal(Json("5")); 562 }).should.throwException!TestException.msg; 563 564 msg.split("\n")[0].should.equal(`Json(true) should equal "5". true is not equal to "5".`); 565 msg.split("\n")[2].should.equal(`[-"5"][+true]`); 566 msg.split("\n")[4].should.equal(` Expected:"5"`); 567 msg.split("\n")[5].should.equal(` Actual:true`); 568 } 569 570 /// It should be able to compare two arrays 571 unittest { 572 Json[] elements = [Json(1), Json(2)]; 573 Json[] otherElements = [Json(1), Json(2), Json(3)]; 574 575 Json(elements).should.equal([1, 2]); 576 Json(elements).should.not.equal([1, 2, 3]); 577 578 Json(elements).should.equal(Json(elements)); 579 Json(elements).should.not.equal(Json(otherElements)); 580 581 auto msg = ({ 582 Json(elements).should.equal(otherElements); 583 }).should.throwException!TestException.msg; 584 585 msg.split("\n")[0].should.equal("Json(elements) should equal [1, 2, 3]. [1, 2] is not equal to [1, 2, 3]."); 586 587 msg = ({ 588 Json(elements).should.equal(otherElements); 589 }).should.throwException!TestException.msg; 590 591 msg.split("\n")[0].should.equal("Json(elements) should equal [1, 2, 3]. [1, 2] is not equal to [1, 2, 3]."); 592 } 593 594 /// It throws on comparing a Json array with a string 595 unittest { 596 Json[] elements = [Json(1), Json(2)]; 597 auto msg = ({ 598 Json(elements).should.equal("5"); 599 }).should.throwException!TestException.msg; 600 601 msg.split("\n")[0].should.equal(`Json(elements) should equal "5". [1, 2] is not equal to "5".`); 602 603 msg = ({ 604 Json(elements).should.equal(Json("5")); 605 }).should.throwException!TestException.msg; 606 607 msg.split("\n")[0].should.equal(`Json(elements) should equal "5". [1, 2] is not equal to "5".`); 608 } 609 610 /// It should be able to compare two nested arrays 611 unittest { 612 Json[] element1 = [Json(1), Json(2)]; 613 Json[] element2 = [Json(10), Json(20)]; 614 615 Json[] elements = [Json(element1), Json(element2)]; 616 Json[] otherElements = [Json(element1), Json(element2), Json(element1)]; 617 618 Json(elements).should.equal([element1, element2]); 619 Json(elements).should.not.equal([element1, element2, element1]); 620 621 Json(elements).should.equal(Json(elements)); 622 Json(elements).should.not.equal(Json(otherElements)); 623 624 auto msg = ({ 625 Json(elements).should.equal(otherElements); 626 }).should.throwException!TestException.msg; 627 628 msg.split("\n")[0].should.equal("Json(elements) should equal [[1, 2], [10, 20], [1, 2]]. [[1, 2], [10, 20]] is not equal to [[1, 2], [10, 20], [1, 2]]."); 629 630 msg = ({ 631 Json(elements).should.equal(Json(otherElements)); 632 }).should.throwException!TestException.msg; 633 634 msg.split("\n")[0].should.equal("Json(elements) should equal [[1, 2], [10, 20], [1, 2]]. [[1, 2], [10, 20]] is not equal to [[1, 2], [10, 20], [1, 2]]."); 635 } 636 637 /// It should be able to compare two nested arrays with different levels 638 unittest { 639 Json nestedElement = Json([Json(1), Json(2)]); 640 641 Json[] elements = [nestedElement, Json(1)]; 642 Json[] otherElements = [nestedElement, Json(1), nestedElement]; 643 644 Json(elements).should.equal([nestedElement, Json(1)]); 645 Json(elements).should.not.equal([nestedElement, Json(1), nestedElement]); 646 647 Json(elements).should.equal(Json(elements)); 648 Json(elements).should.not.equal(Json(otherElements)); 649 650 auto msg = ({ 651 Json(elements).should.equal(otherElements); 652 }).should.throwException!TestException.msg; 653 654 msg.split("\n")[0].should.equal("Json(elements) should equal [[1, 2], 1, [1, 2]]. [[1, 2], 1] is not equal to [[1, 2], 1, [1, 2]]."); 655 656 msg = ({ 657 Json(elements).should.equal(Json(otherElements)); 658 }).should.throwException!TestException.msg; 659 660 msg.split("\n")[0].should.equal("Json(elements) should equal [[1, 2], 1, [1, 2]]. [[1, 2], 1] is not equal to [[1, 2], 1, [1, 2]]."); 661 } 662 663 /// It should find the key differences inside a Json object 664 unittest { 665 Json expectedObject = Json.emptyObject; 666 Json testObject = Json.emptyObject; 667 testObject["key"] = "some value"; 668 testObject["nested"] = Json.emptyObject; 669 testObject["nested"]["item1"] = "hello"; 670 testObject["nested"]["item2"] = Json.emptyObject; 671 testObject["nested"]["item2"]["value"] = "world"; 672 673 expectedObject["other"] = "other value"; 674 675 auto msg = ({ 676 testObject.should.equal(expectedObject); 677 }).should.throwException!TestException.msg; 678 679 msg.should.startWith(`testObject should equal {`); 680 } 681 682 /// It should find the value differences inside a Json object 683 unittest { 684 Json expectedObject = Json.emptyObject; 685 Json testObject = Json.emptyObject; 686 testObject["key1"] = "some value"; 687 testObject["key2"] = 1; 688 689 expectedObject["key1"] = "other value"; 690 expectedObject["key2"] = 2; 691 692 auto msg = ({ 693 testObject.should.equal(expectedObject); 694 }).should.throwException!TestException.msg; 695 696 msg.should.startWith("testObject should equal {"); 697 } 698 699 /// greaterThan support for Json Objects 700 unittest { 701 Json(5).should.be.greaterThan(4); 702 Json(4).should.not.be.greaterThan(5); 703 704 Json(5f).should.be.greaterThan(4f); 705 Json(4f).should.not.be.greaterThan(5f); 706 707 auto msg = ({ 708 Json("").should.greaterThan(3); 709 }).should.throwException!TestException.msg; 710 711 msg.split("\n")[0].should.equal(`Json("") should greater than 3.`); 712 msg.split("\n")[1].should.equal("Can't convert the values to int"); 713 714 msg = ({ 715 Json(false).should.greaterThan(3f); 716 }).should.throwException!TestException.msg; 717 718 msg.split("\n")[0].should.equal(`Json(false) should greater than 3.`); 719 msg.split("\n")[1].should.equal("Can't convert the values to float"); 720 } 721 722 /// lessThan support for Json Objects 723 unittest { 724 Json(4).should.be.lessThan(5); 725 Json(5).should.not.be.lessThan(4); 726 727 Json(4f).should.be.lessThan(5f); 728 Json(5f).should.not.be.lessThan(4f); 729 730 auto msg = ({ 731 Json("").should.lessThan(3); 732 }).should.throwException!TestException.msg; 733 734 msg.split("\n")[0].should.equal(`Json("") should less than 3.`); 735 msg.split("\n")[1].should.equal(`Can't convert the values to int`); 736 737 msg = ({ 738 Json(false).should.lessThan(3f); 739 }).should.throwException!TestException.msg; 740 741 msg.split("\n")[0].should.equal(`Json(false) should less than 3.`); 742 msg.split("\n")[1].should.equal(`Can't convert the values to float`); 743 } 744 745 /// between support for Json Objects 746 unittest { 747 Json(5).should.be.between(6, 4); 748 Json(5).should.not.be.between(5, 6); 749 750 Json(5f).should.be.between(6f, 4f); 751 Json(5f).should.not.be.between(5f, 6f); 752 753 auto msg = ({ 754 Json(true).should.be.between(6f, 4f); 755 }).should.throwException!TestException.msg; 756 757 msg.split("\n")[0].should.equal("Json(true) should be between 6 and 4. "); 758 msg.split("\n")[1].should.equal("Can't convert the values to float"); 759 } 760 761 /// should be able to use approximately for jsons 762 unittest { 763 Json(10f/3f).should.be.approximately(3, 0.34); 764 Json(10f/3f).should.not.be.approximately(3, 0.24); 765 766 auto msg = ({ 767 Json("").should.be.approximately(3, 0.34); 768 }).should.throwException!TestException.msg; 769 770 msg.should.contain(`Can't parse the provided arguments!`); 771 }